Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Foreman RH Cloud API Bindings to upload hits #933

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
module Api
module V2
module InsightsAdvisor
class InsightsAdvisorController < ::Api::V2::BaseController
include ::Api::Version2
include Foreman::Controller::SmartProxyAuth
add_smart_proxy_filters [:upload_hits]

api :PATCH, "/insights_advisor/upload_hits", N_("Upload from insights advisor")
param :host_name, String, required: true
param :host_uuid, String, required: true
Comment on lines +10 to +11
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need both?


param :payload, Hash, :desc => N_("On prem payload including resolutions, rules, hits") do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we configure that one not to be logged? it's massive

param :resolutions, Array, :desc => N_("upload resolutions related to the hits") do
param :rule_id, String, :desc => N_("rule id"), :required => true
param :description, String, :desc => N_("resolution description")
param :needs_reboot, :bool, :desc => N_("need reboot")
param :resolution_risk, String, :desc => N_("resolution risk")
param :resolution_type, String, :desc => N_("type")
end

param :rules, Array, :desc => N_("upload rules related to the hits") do
param :rule_id, String, :desc => N_("rule id"), :required => true
param :description, String, :desc => N_("rule description")
param :category_name, String, :desc => N_("category name")
param :impact_name, String, :desc => N_("impact name")
param :summary, String, :desc => N_("summary")
param :generic, String, :desc => N_("generic")
param :reason, String, :desc => N_("reason")
param :total_risk, :number, :desc => N_("total risk")
param :reboot_required, :bool, :desc => N_("reboot required")
param :more_info, String, :desc => N_("more info")
param :rating, :number, :desc => N_("rating")
end

param :hits, Array, :desc => N_("upload hits information") do
param :rule_id, String, :desc => N_("rule id"), :required => true
param :title, String, :desc => N_("rule title")
param :solution_url, String, :desc => N_("solution url")
param :total_risk, :number, :desc => N_("total risk")
param :likelihood, :number, :desc => N_("likelihood number")
param :publish_date, String, :desc => N_("publish date (YYYY-MM-DD)")
param :results_url, String, :desc => N_("result url")
end
param :details, String, :desc => N_("upload hits details json")
end

def upload_hits
host = Host.find_by(name: params.require(:host_name))
payload = payload_params.to_h
task = ForemanTasks.async_task(ForemanHits::Async::Upload, host, params.require(:host_uuid), payload)

render json: {
task: task,
}, status: :ok
end

def payload_params
params.require(:payload).permit(
:details,
{
resolutions: [
:rule_id, :description, :needs_reboot, :resolution_risk, :resolution_type
],
rules: [
:rule_id, :description, :category_name, :impact_name, :summary, :generic,
:reason, :total_risk, :reboot_required, :more_info, :rating
],
hits: [
:rule_id, :title, :solution_url, :total_risk, :likelihood, :publish_date, :results_url
],
}
)
end
end
end
end
end
2 changes: 2 additions & 0 deletions app/models/concerns/rh_cloud_host.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,7 @@ module RhCloudHost
scoped_search :relation => :inventory_sync_status_object, :on => :status, :rename => :insights_inventory_sync_status,
:complete_value => { :disconnect => ::InventorySync::InventoryStatus::DISCONNECT,
:sync => ::InventorySync::InventoryStatus::SYNC }

scoped_search :relation => :insights, :on => :uuid, :only_explicit => true, :rename => :insights_uuid
end
end
5 changes: 4 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,12 @@
end
end

namespace 'insights_advisor' do
patch 'upload_hits', to: 'insights_advisor#upload_hits'
end

namespace 'rh_cloud' do
post 'enable_connector', to: 'inventory#enable_cloud_connector'

post 'cloud_request', to: 'cloud_request#update'
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddUniqueIndexToRuleIdAndHostIdInInsightsHits < ActiveRecord::Migration[7.0]
def change
add_index :insights_hits, [:rule_id, :host_id], unique: true, name: 'index_insight_hits_on_rule_id_and_host_id'
end
end
54 changes: 54 additions & 0 deletions lib/foreman_hits/async/upload.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
module ForemanHits
module Async
class Upload < ::Actions::EntryAction
def plan(host, uuid, payload = {})
plan_self(host_id: host.id, uuid: uuid, payload: payload)
end

def run
host = Host.find(input[:host_id])
payload = input[:payload]
update_facets(host, input[:uuid])
update_hits(host, payload)
update_rules_and_resolutions(payload)
update_details(host, payload)
end

def update_facets(host, uuid)
InsightsFacet.find_or_create_by(host_id: host.id) do |facet|
facet.uuid = uuid
end
host.reload
end

def update_hits(host, payload)
facet = host.insights
facet.hits.delete_all
hits = payload[:hits]
# rubocop:disable Rails/SkipsModelValidations
facet.hits.insert_all(hits)
facet.update(hits_count: facet.hits.count)
# rubocop:enable Rails/SkipsModelValidations
end

def update_rules_and_resolutions(payload)
# rubocop:disable Rails/SkipsModelValidations
::InsightsRule.upsert_all(payload[:rules], unique_by: :rule_id)
rules = payload[:rules].map { |rule| rule[:rule_id] }
::InsightsResolution.where(rule_id: rules).delete_all
::InsightsResolution.insert_all(payload[:resolutions])
# rubocop:enable Rails/SkipsModelValidations
end

def update_details(host, payload)
fact_name = FactName.where(name: "insights::hit_details", short_name: 'insights_details').first_or_create
fact_value = host.fact_values.where(fact_name: fact_name).first_or_create
fact_value.update(value: payload[:details])
end

def rescue_strategy_for_self
Dynflow::Action::Rescue::Fail
end
end
end
end
Loading