foreman_rh_cloud 3.0.19 → 3.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +17 -2
- data/app/controllers/insights_cloud/hits_controller.rb +37 -0
- data/app/controllers/insights_cloud/settings_controller.rb +1 -1
- data/app/controllers/insights_cloud/tasks_controller.rb +1 -2
- data/app/models/inventory_sync/inventory_status.rb +6 -0
- data/app/models/setting/rh_cloud.rb +5 -5
- data/app/services/foreman_rh_cloud/remediations_retriever.rb +78 -0
- data/app/services/foreman_rh_cloud/template_renderer_helper.rb +22 -0
- data/app/views/job_templates/rh_cloud_remediations.erb +14 -0
- data/config/routes.rb +1 -0
- data/db/migrate/20210404000001_change_resolutions.foreman_rh_cloud.rb +10 -0
- data/db/seeds.d/50_job_templates.rb +14 -0
- data/lib/foreman_rh_cloud/engine.rb +13 -1
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/insights_cloud.rb +12 -0
- data/lib/insights_cloud/async/insights_full_sync.rb +16 -6
- data/lib/insights_cloud/async/insights_resolutions_sync.rb +69 -0
- data/lib/insights_cloud/async/insights_rules_sync.rb +13 -17
- data/lib/insights_cloud/async/insights_scheduled_sync.rb +1 -1
- data/lib/tasks/rh_cloud_inventory.rake +1 -1
- data/package.json +1 -1
- data/test/factories/insights_factories.rb +22 -0
- data/test/jobs/insights_full_sync_test.rb +12 -8
- data/test/jobs/insights_resolutions_sync_test.rb +74 -0
- data/test/jobs/insights_rules_sync_test.rb +5 -3
- data/test/jobs/inventory_full_sync_test.rb +1 -1
- data/test/unit/services/foreman_rh_cloud/remediations_retriever_test.rb +49 -0
- data/test/unit/services/foreman_rh_cloud/template_renderer_helper_test.rb +28 -0
- data/webpack/ForemanInventoryUpload/Components/InventorySettings/AdvancedSetting/AdvancedSettingsConstants.js +5 -3
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/PageDescription.js +15 -2
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/__tests__/__snapshots__/PageDescription.test.js.snap +13 -2
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +1 -1
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableSelectors.js +3 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediateButton.js +59 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationActions.js +12 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationHelpers.js +43 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.js +101 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.scss +9 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModalFooter.js +43 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationTableConstants.js +38 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/Resolutions.js +55 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/index.js +34 -0
- data/webpack/InsightsCloudSync/InsightsCloudSync.js +8 -3
- data/webpack/InsightsCloudSync/InsightsCloudSync.scss +5 -0
- data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +9 -6
- data/webpack/{InsightsCloudSync/Components/InsightsTable/components → common/table}/EmptyState.js +0 -0
- data/webpack/common/table/helpers.js +7 -0
- metadata +33 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1a6bf66d7fd1c5302e88b9cd6f28f36c36d9ba8ecfcba3f32e4076c5ba856a05
|
|
4
|
+
data.tar.gz: d9d67e5ec55ac92e3101544c9e2d7f8f3d8e40112927c70efc23ddb117e8f96b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c241a52fe6d3f028777c0c70cea3cc68a2008cf2392d4dd9608b5332614638dce68baade016fddd46985ddcf6cddfa9638d28a86c6f645147ed52a304063a4a4
|
|
7
|
+
data.tar.gz: f32f203c82ddc7d4964155ac0afcfa18fc6cd6501df8a9bff9197e6fc03590cd5c71720fb8c512c64c920b503ed01d7a6118f2633e64f36f5a05ffd222af4197
|
data/README.md
CHANGED
|
@@ -52,7 +52,7 @@ From command-line:
|
|
|
52
52
|
|
|
53
53
|
# all organizations
|
|
54
54
|
/usr/sbin/foreman-rake rh_cloud_insights:sync
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
# specific organization with id 1
|
|
57
57
|
export organization_id=1
|
|
58
58
|
/usr/sbin/foreman-rake rh_cloud_insights:sync
|
|
@@ -61,6 +61,22 @@ From command-line:
|
|
|
61
61
|
|
|
62
62
|
*Todo list here*
|
|
63
63
|
|
|
64
|
+
## Design
|
|
65
|
+
|
|
66
|
+
### Endpoints
|
|
67
|
+
|
|
68
|
+
| purpose | url | ENV setting for the **bold** part
|
|
69
|
+
| ------------------------------| -------| -----------
|
|
70
|
+
| Inventory uploads | **https://cert.cloud.redhat.com/api/ingress/v1/upload** | SATELLITE_INVENTORY_UPLOAD_URL
|
|
71
|
+
| Query inventory hosts list | **https://cloud.redhat.com** /api/inventory/v1/hosts?tags= | SATELLITE_RH_CLOUD_URL
|
|
72
|
+
| Query insights hits | **https://cloud.redhat.com** /api/insights/v1/export/hits/ | SATELLITE_RH_CLOUD_URL
|
|
73
|
+
| Query insights rules | **https://cloud.redhat.com** /api/insights/v1/rule/?impacting=true&rule_status=enabled&has_playbook=true&limit=&offset= | SATELLITE_RH_CLOUD_URL
|
|
74
|
+
| Query insights resolutions | **https://cloud.redhat.com** /api/remediations/v1/resolutions| SATELLITE_RH_CLOUD_URL
|
|
75
|
+
| Forward insights-client `/static` requests | **https://cloud.redhat.com** /api/static | SATELLITE_RH_CLOUD_URL
|
|
76
|
+
| Forward insights-client legacy `/platform` requests | **https://cert.cloud.redhat.com** /api | SATELLITE_CERT_RH_CLOUD_URL
|
|
77
|
+
| Forward insights-client legacy `/redhat_access/r/insights` requests | **https://cert-api.access.redhat.com** /r/insights | SATELLITE_LEGACY_INSIGHTS_URL
|
|
78
|
+
|
|
79
|
+
|
|
64
80
|
## Contributing
|
|
65
81
|
|
|
66
82
|
Fork and send a Pull Request. Thanks!
|
|
@@ -81,4 +97,3 @@ GNU General Public License for more details.
|
|
|
81
97
|
|
|
82
98
|
You should have received a copy of the GNU General Public License
|
|
83
99
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
84
|
-
|
|
@@ -9,6 +9,7 @@ module InsightsCloud
|
|
|
9
9
|
hasToken: !Setting[:rh_cloud_token].empty?,
|
|
10
10
|
hits: hits.map { |hit| hit.attributes.merge(hostname: hit.host&.name, has_playbook: hit.has_playbook?) },
|
|
11
11
|
itemCount: hits.count,
|
|
12
|
+
isExperimentalMode: Setting[:lab_features],
|
|
12
13
|
}, status: :ok
|
|
13
14
|
end
|
|
14
15
|
|
|
@@ -20,6 +21,21 @@ module InsightsCloud
|
|
|
20
21
|
}, status: :ok
|
|
21
22
|
end
|
|
22
23
|
|
|
24
|
+
def resolutions
|
|
25
|
+
if remediation_all_selected_param
|
|
26
|
+
hits = InsightsHit.with_playbook.search_for(params[:query])
|
|
27
|
+
else
|
|
28
|
+
hits = resource_base_search_and_page.where(id: remediation_ids_param)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
hits.preload(:host, rule: :resolutions)
|
|
32
|
+
|
|
33
|
+
render json: {
|
|
34
|
+
hits: hits.map { |hit| hit.attributes.merge(hostname: hit.host&.name, resolutions: hit.rule.resolutions.map(&:attributes), reboot: hit.rule.reboot_required) },
|
|
35
|
+
itemCount: hits.count,
|
|
36
|
+
}, status: :ok
|
|
37
|
+
end
|
|
38
|
+
|
|
23
39
|
def model_of_controller
|
|
24
40
|
::InsightsHit
|
|
25
41
|
end
|
|
@@ -32,10 +48,31 @@ module InsightsCloud
|
|
|
32
48
|
:insights_hits
|
|
33
49
|
end
|
|
34
50
|
|
|
51
|
+
def action_permission
|
|
52
|
+
case params[:action]
|
|
53
|
+
when 'resolutions'
|
|
54
|
+
'view'
|
|
55
|
+
else
|
|
56
|
+
super
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
35
60
|
private
|
|
36
61
|
|
|
37
62
|
def host_id_param
|
|
38
63
|
params.require(:host_id)
|
|
39
64
|
end
|
|
65
|
+
|
|
66
|
+
def remediation_request_params
|
|
67
|
+
params.permit(remediations: [:hit_id, :remediation_id]).require(:remediations)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def remediation_ids_param
|
|
71
|
+
params.require(:ids).map(&:to_i)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def remediation_all_selected_param
|
|
75
|
+
ActiveModel::Type::Boolean.new.cast(params[:isAllSelected])
|
|
76
|
+
end
|
|
40
77
|
end
|
|
41
78
|
end
|
|
@@ -13,7 +13,7 @@ module InsightsCloud
|
|
|
13
13
|
token = Setting::RhCloud.find_by_name("rh_cloud_token")
|
|
14
14
|
token.value = params.require(:value)
|
|
15
15
|
token.save!
|
|
16
|
-
InsightsCloud::Async::InsightsFullSync
|
|
16
|
+
ForemanTasks.sync_task(InsightsCloud::Async::InsightsFullSync)
|
|
17
17
|
redirect_to(:controller => "hits", :action => 'index')
|
|
18
18
|
end
|
|
19
19
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
module InsightsCloud
|
|
2
2
|
class TasksController < ::ApplicationController
|
|
3
3
|
def create
|
|
4
|
-
|
|
5
|
-
task = ForemanTasks::Task.find_by(external_id: job.provider_job_id)
|
|
4
|
+
task = ForemanTasks.async_task(InsightsCloud::Async::InsightsFullSync)
|
|
6
5
|
|
|
7
6
|
render json: {
|
|
8
7
|
task: task,
|
|
@@ -26,5 +26,11 @@ module InventorySync
|
|
|
26
26
|
N_('Successfully uploaded to your RH cloud inventory')
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
|
+
|
|
30
|
+
def to_status(options = {})
|
|
31
|
+
# this method used to calculate status.
|
|
32
|
+
# Since the calculation is done externally we should return the previously calculated status
|
|
33
|
+
status
|
|
34
|
+
end
|
|
29
35
|
end
|
|
30
36
|
end
|
|
@@ -14,12 +14,12 @@ class Setting::RhCloud < Setting
|
|
|
14
14
|
def self.default_settings
|
|
15
15
|
return unless ActiveRecord::Base.connection.table_exists?('settings')
|
|
16
16
|
[
|
|
17
|
-
set('allow_auto_inventory_upload', N_('
|
|
18
|
-
set('allow_auto_insights_sync', N_('
|
|
19
|
-
set('obfuscate_inventory_hostnames', N_('Obfuscate host names sent to Red Hat cloud'), false, N_('Obfuscate host names')),
|
|
20
|
-
set('obfuscate_inventory_ips', N_('Obfuscate
|
|
17
|
+
set('allow_auto_inventory_upload', N_('Enable automatic upload of your host inventory to the Red Hat cloud'), true, N_('Automatic inventory upload')),
|
|
18
|
+
set('allow_auto_insights_sync', N_('Enable automatic synchronization of Insights recommendations from the Red Hat cloud'), false, N_('Synchronize recommendations Automatically')),
|
|
19
|
+
set('obfuscate_inventory_hostnames', N_('Obfuscate host names sent to the Red Hat cloud'), false, N_('Obfuscate host names')),
|
|
20
|
+
set('obfuscate_inventory_ips', N_('Obfuscate ipv4 addresses sent to the Red Hat cloud'), false, N_('Obfuscate host ipv4 addresses')),
|
|
21
21
|
set('rh_cloud_token', N_('Authentication token to Red Hat cloud services. Used to authenticate requests to cloud APIs'), nil, N_('Red Hat Cloud token'), nil, encrypted: true),
|
|
22
|
-
set('exclude_installed_packages', N_('Exclude installed packages from Red Hat cloud
|
|
22
|
+
set('exclude_installed_packages', N_('Exclude installed packages from being uploaded to the Red Hat cloud'), false, N_("Exclude installed Packages")),
|
|
23
23
|
set('include_parameter_tags', N_('Should import include parameter tags from Foreman?'), false, N_('Include parameters in insights-client reports')),
|
|
24
24
|
]
|
|
25
25
|
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
module ForemanRhCloud
|
|
2
|
+
class RemediationsRetriever
|
|
3
|
+
include CloudAuth
|
|
4
|
+
|
|
5
|
+
attr_reader :logger
|
|
6
|
+
|
|
7
|
+
def initialize(hit_remediation_pairs, logger: Logger.new(IO::NULL))
|
|
8
|
+
@hit_remediation_pairs = hit_remediation_pairs
|
|
9
|
+
@logger = logger
|
|
10
|
+
|
|
11
|
+
logger.debug("Querying playbook for #{hit_remediation_pairs}")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def create_playbook
|
|
15
|
+
response = query_playbook
|
|
16
|
+
|
|
17
|
+
logger.debug("Got playbook response: #{response.body}")
|
|
18
|
+
|
|
19
|
+
response.body
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def hit_ids
|
|
25
|
+
@hit_remediation_pairs.map { |pair| pair["hit_id"] }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def remediation_ids
|
|
29
|
+
@hit_remediation_pairs.map { |pair| pair["resolution_id"] }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def hits
|
|
33
|
+
@hits ||= Hash[
|
|
34
|
+
InsightsHit.joins(:insights_facet).where(id: hit_ids).pluck(:id, 'insights_facets.uuid')
|
|
35
|
+
]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def pairs_by_remediation_id
|
|
39
|
+
@hit_remediation_pairs.group_by { |pair| pair["resolution_id"] }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def remediations
|
|
43
|
+
@remediations ||= Hash[
|
|
44
|
+
InsightsResolution.where(id: remediation_ids).pluck(:id, :resolution_type, :rule_id).map do |id, resolution_type, rule_id|
|
|
45
|
+
[id, {resolution_type: resolution_type, rule_id: rule_id}]
|
|
46
|
+
end
|
|
47
|
+
]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def playbook_request
|
|
51
|
+
{
|
|
52
|
+
issues: pairs_by_remediation_id.map do |remediation_id, pairs|
|
|
53
|
+
{
|
|
54
|
+
resolution: remediations[remediation_id][:resolution_type],
|
|
55
|
+
id: InsightsCloud.remediation_rule_id(remediations[remediation_id][:rule_id]),
|
|
56
|
+
systems: pairs.map do |pair|
|
|
57
|
+
hits[pair["hit_id"]]
|
|
58
|
+
end,
|
|
59
|
+
}
|
|
60
|
+
end,
|
|
61
|
+
}
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def query_playbook
|
|
65
|
+
RestClient::Request.execute(
|
|
66
|
+
method: :post,
|
|
67
|
+
url: InsightsCloud.playbook_url,
|
|
68
|
+
verify_ssl: ForemanRhCloud.verify_ssl_method,
|
|
69
|
+
proxy: ForemanRhCloud.transformed_http_proxy_string(logger: logger),
|
|
70
|
+
headers: {
|
|
71
|
+
content_type: :json,
|
|
72
|
+
Authorization: "Bearer #{rh_credentials}",
|
|
73
|
+
},
|
|
74
|
+
payload: playbook_request.to_json
|
|
75
|
+
)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module ForemanRhCloud
|
|
2
|
+
# Macro to fetch remediation playbook from cloud.redhat.com
|
|
3
|
+
module TemplateRendererHelper
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
extend ApipieDSL::Module
|
|
6
|
+
|
|
7
|
+
apipie :class, 'Macros related to Red Hat cloud interface' do
|
|
8
|
+
name 'RHCloud'
|
|
9
|
+
sections only: %w[all jobs]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
apipie :method, 'Returns a playbook generated from Red Hat cloud recommendations' do
|
|
13
|
+
required :hit_remediation_pairs, String, desc: 'JSON-encoded array of hashes in the form of [{hit_id: 1, remediation_id: 2}, ...]'
|
|
14
|
+
returns String, desc: 'Playbook generated for the specific recommendations and hosts'
|
|
15
|
+
end
|
|
16
|
+
def remediations_playbook(hit_remediation_pairs)
|
|
17
|
+
hit_remediation_pairs = JSON.parse(hit_remediation_pairs)
|
|
18
|
+
retriever = ForemanRhCloud::RemediationsRetriever.new(hit_remediation_pairs, logger: template_logger)
|
|
19
|
+
retriever.create_playbook
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<%#
|
|
2
|
+
kind: job_template
|
|
3
|
+
name: Run remediations based on Insights recommendations
|
|
4
|
+
job_category: Red Hat Insights
|
|
5
|
+
description_format: 'Insights remediations for selected issues'
|
|
6
|
+
feature: rh_cloud_remediate_hosts
|
|
7
|
+
template_inputs:
|
|
8
|
+
- name: hit_remediation_pairs
|
|
9
|
+
description: Pairs of issues and selected remediation
|
|
10
|
+
input_type: user
|
|
11
|
+
required: true
|
|
12
|
+
provider_type: Ansible
|
|
13
|
+
%>
|
|
14
|
+
<%= remediations_playbook(input('hit_remediation_pairs')) %>
|
data/config/routes.rb
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class ChangeResolutions < ActiveRecord::Migration[5.2]
|
|
2
|
+
def change
|
|
3
|
+
remove_column :insights_resolutions, :system_type, :integer
|
|
4
|
+
remove_column :insights_resolutions, :has_playbook, :boolean
|
|
5
|
+
rename_column :insights_resolutions, :resolution, :description
|
|
6
|
+
add_column :insights_resolutions, :needs_reboot, :boolean
|
|
7
|
+
add_column :insights_resolutions, :resolution_risk, :integer
|
|
8
|
+
add_column :insights_resolutions, :resolution_type, :string
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
organizations = Organization.unscoped.all
|
|
2
|
+
locations = Location.unscoped.all
|
|
3
|
+
User.as_anonymous_admin do
|
|
4
|
+
JobTemplate.without_auditing do
|
|
5
|
+
Dir[File.join("#{ForemanRhCloud::Engine.root}/app/views/job_templates/**/*.erb")].each do |template|
|
|
6
|
+
template = JobTemplate.import_raw!(File.read(template),
|
|
7
|
+
:default => true,
|
|
8
|
+
:lock => true,
|
|
9
|
+
:update => true)
|
|
10
|
+
template.organizations = organizations if template.present?
|
|
11
|
+
template.locations = locations if template.present?
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -48,7 +48,7 @@ module ForemanRhCloud
|
|
|
48
48
|
:view_insights_hits,
|
|
49
49
|
{
|
|
50
50
|
'/foreman_rh_cloud/insights_cloud': [:index], # for bookmarks and later for showing the page
|
|
51
|
-
'insights_cloud/hits': [:index, :show, :auto_complete_search],
|
|
51
|
+
'insights_cloud/hits': [:index, :show, :auto_complete_search, :resolutions],
|
|
52
52
|
'insights_cloud/settings': [:index, :show],
|
|
53
53
|
'react': [:index],
|
|
54
54
|
},
|
|
@@ -87,6 +87,9 @@ module ForemanRhCloud
|
|
|
87
87
|
id: 'insights',
|
|
88
88
|
onlyif: proc { |host| host.insights }
|
|
89
89
|
end
|
|
90
|
+
|
|
91
|
+
extend_template_helpers ForemanRhCloud::TemplateRendererHelper
|
|
92
|
+
allowed_template_helpers :remediations_playbook
|
|
90
93
|
end
|
|
91
94
|
|
|
92
95
|
::Katello::UINotifications::Subscriptions::ManifestImportSuccess.include ForemanInventoryUpload::Notifications::ManifestImportSuccessNotificationOverride if defined?(Katello)
|
|
@@ -114,5 +117,14 @@ module ForemanRhCloud
|
|
|
114
117
|
locale_domain = 'foreman_rh_cloud'
|
|
115
118
|
Foreman::Gettext::Support.add_text_domain locale_domain, locale_dir
|
|
116
119
|
end
|
|
120
|
+
|
|
121
|
+
config.to_prepare do
|
|
122
|
+
RemoteExecutionFeature.register(
|
|
123
|
+
:rh_cloud_remediate_hosts,
|
|
124
|
+
N_('Apply Insights recommendations'),
|
|
125
|
+
description: N_('Run remediation playbook generated by Insights'),
|
|
126
|
+
host_action_button: false
|
|
127
|
+
)
|
|
128
|
+
end
|
|
117
129
|
end
|
|
118
130
|
end
|
data/lib/insights_cloud.rb
CHANGED
|
@@ -16,4 +16,16 @@ module InsightsCloud
|
|
|
16
16
|
def self.rules_url(limit: ForemanRhCloud.query_limit, offset: 0)
|
|
17
17
|
ForemanRhCloud.base_url + "/api/insights/v1/rule/?impacting=true&rule_status=enabled&has_playbook=true&limit=#{limit}&offset=#{offset}"
|
|
18
18
|
end
|
|
19
|
+
|
|
20
|
+
def self.resolutions_url
|
|
21
|
+
ForemanRhCloud.base_url + '/api/remediations/v1/resolutions'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.playbook_url
|
|
25
|
+
ForemanRhCloud.base_url + '/api/remediations/v1/playbook'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.remediation_rule_id(rule_id)
|
|
29
|
+
"advisor:#{rule_id}"
|
|
30
|
+
end
|
|
19
31
|
end
|
|
@@ -2,17 +2,19 @@ require 'rest-client'
|
|
|
2
2
|
|
|
3
3
|
module InsightsCloud
|
|
4
4
|
module Async
|
|
5
|
-
class InsightsFullSync < ::
|
|
5
|
+
class InsightsFullSync < ::Actions::EntryAction
|
|
6
6
|
include ::ForemanRhCloud::CloudAuth
|
|
7
7
|
|
|
8
|
-
def
|
|
8
|
+
def plan
|
|
9
9
|
# This can be turned off when we enable automatic status syncs
|
|
10
10
|
# This step will query cloud inventory to retrieve inventory uuids for each host
|
|
11
|
-
|
|
11
|
+
plan_hosts_sync
|
|
12
|
+
plan_self
|
|
13
|
+
plan_rules_sync
|
|
14
|
+
end
|
|
12
15
|
|
|
16
|
+
def run
|
|
13
17
|
perform_hits_sync
|
|
14
|
-
|
|
15
|
-
InsightsRulesSync.perform_later
|
|
16
18
|
end
|
|
17
19
|
|
|
18
20
|
def perform_hits_sync
|
|
@@ -25,11 +27,19 @@ module InsightsCloud
|
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
def logger
|
|
28
|
-
|
|
30
|
+
action_logger
|
|
29
31
|
end
|
|
30
32
|
|
|
31
33
|
private
|
|
32
34
|
|
|
35
|
+
def plan_hosts_sync
|
|
36
|
+
plan_action InventorySync::Async::InventoryHostsSync
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def plan_rules_sync
|
|
40
|
+
plan_action InsightsRulesSync
|
|
41
|
+
end
|
|
42
|
+
|
|
33
43
|
def query_insights_hits
|
|
34
44
|
hits_response = RestClient::Request.execute(
|
|
35
45
|
method: :get,
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require 'rest-client'
|
|
2
|
+
|
|
3
|
+
module InsightsCloud
|
|
4
|
+
module Async
|
|
5
|
+
class InsightsResolutionsSync < ::Actions::EntryAction
|
|
6
|
+
include ::ForemanRhCloud::CloudAuth
|
|
7
|
+
|
|
8
|
+
RULE_ID_REGEX = /[^:]*:(?<id>.*)/
|
|
9
|
+
|
|
10
|
+
def run
|
|
11
|
+
InsightsResolution.transaction do
|
|
12
|
+
InsightsResolution.delete_all
|
|
13
|
+
api_response = query_insights_resolutions(relevant_rules)
|
|
14
|
+
write_resolutions(api_response)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def logger
|
|
19
|
+
action_logger
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def query_insights_resolutions(rule_ids)
|
|
25
|
+
resolutions_response = RestClient::Request.execute(
|
|
26
|
+
method: :post,
|
|
27
|
+
url: InsightsCloud.resolutions_url,
|
|
28
|
+
verify_ssl: ForemanRhCloud.verify_ssl_method,
|
|
29
|
+
proxy: ForemanRhCloud.transformed_http_proxy_string(logger: logger),
|
|
30
|
+
headers: {
|
|
31
|
+
content_type: :json,
|
|
32
|
+
Authorization: "Bearer #{rh_credentials}",
|
|
33
|
+
},
|
|
34
|
+
payload: {
|
|
35
|
+
issues: rule_ids,
|
|
36
|
+
}.to_json
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
JSON.parse(resolutions_response)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def relevant_rules
|
|
43
|
+
InsightsRule.all.pluck(:rule_id).map { |id| InsightsCloud.remediation_rule_id(id) }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def to_resolution_hash(rule_id, resolution_hash)
|
|
47
|
+
{
|
|
48
|
+
rule_id: rule_id,
|
|
49
|
+
description: resolution_hash['description'],
|
|
50
|
+
resolution_type: resolution_hash['id'],
|
|
51
|
+
needs_reboot: resolution_hash['needs_reboot'],
|
|
52
|
+
resolution_risk: resolution_hash['resolution_risk'],
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def write_resolutions(response)
|
|
57
|
+
all_resolutions = response.map do |rule_id, rule_details|
|
|
58
|
+
rule_details['resolutions'].map { |resolution| to_resolution_hash(to_rule_id(rule_id), resolution) }
|
|
59
|
+
end.flatten
|
|
60
|
+
|
|
61
|
+
InsightsResolution.create(all_resolutions)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def to_rule_id(resolution_rule_id)
|
|
65
|
+
RULE_ID_REGEX.match(resolution_rule_id).named_captures.fetch('id', resolution_rule_id)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|