foreman_rh_cloud 13.0.7 → 13.0.9
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/app/controllers/concerns/foreman_rh_cloud/registration_manager_extensions.rb +39 -0
- data/app/controllers/foreman_inventory_upload/accounts_controller.rb +1 -1
- data/app/controllers/foreman_inventory_upload/uploads_controller.rb +1 -1
- data/lib/foreman_inventory_upload/async/create_missing_insights_facets.rb +3 -2
- data/lib/foreman_inventory_upload/async/queue_for_upload_job.rb +1 -23
- data/lib/foreman_inventory_upload/async/upload_report_direct_job.rb +200 -0
- data/lib/foreman_inventory_upload.rb +6 -6
- data/lib/foreman_rh_cloud/engine.rb +1 -0
- data/lib/foreman_rh_cloud/plugin.rb +4 -0
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/inventory_sync/async/inventory_hosts_sync.rb +0 -2
- data/lib/tasks/rh_cloud_inventory.rake +11 -1
- data/package.json +1 -1
- data/test/controllers/accounts_controller_test.rb +1 -1
- data/test/controllers/uploads_controller_test.rb +1 -1
- data/test/jobs/cloud_connector_announce_task_test.rb +3 -2
- data/test/jobs/connector_playbook_execution_reporter_task_test.rb +32 -20
- data/test/jobs/create_missing_insights_facets_test.rb +151 -0
- data/test/jobs/exponential_backoff_test.rb +9 -8
- data/test/jobs/generate_host_report_test.rb +100 -0
- data/test/jobs/generate_report_job_test.rb +146 -0
- data/test/jobs/host_inventory_report_job_test.rb +244 -0
- data/test/jobs/insights_client_status_aging_test.rb +3 -2
- data/test/jobs/insights_full_sync_test.rb +13 -7
- data/test/jobs/insights_resolutions_sync_test.rb +9 -5
- data/test/jobs/insights_rules_sync_test.rb +5 -3
- data/test/jobs/inventory_full_sync_test.rb +9 -5
- data/test/jobs/inventory_hosts_sync_test.rb +11 -6
- data/test/jobs/inventory_scheduled_sync_test.rb +10 -6
- data/test/jobs/inventory_self_host_sync_test.rb +1 -1
- data/test/jobs/queue_for_upload_job_test.rb +10 -19
- data/test/jobs/remove_insights_hosts_job_test.rb +14 -15
- data/test/jobs/single_host_report_job_test.rb +155 -0
- data/test/jobs/upload_report_direct_job_test.rb +399 -0
- data/test/unit/lib/foreman_rh_cloud/registration_manager_extensions_test.rb +192 -0
- data/webpack/ForemanColumnExtensions/index.js +2 -0
- data/webpack/ForemanInventoryUpload/Components/AccountList/AccountList.js +1 -1
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/ListItem.fixtures.js +4 -5
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/ListItem.js +4 -2
- data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/__tests__/__snapshots__/ListItem.test.js.snap +9 -10
- data/webpack/ForemanInventoryUpload/Components/Dashboard/Dashboard.js +4 -1
- data/webpack/ForemanInventoryUpload/Components/PageHeader/PageHeader.js +24 -17
- data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/PageHeader.test.js +178 -8
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/ToolbarButtons.js +3 -1
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/__tests__/ToolbarButtons.test.js +69 -51
- data/webpack/InsightsCloudSync/Components/InsightsSettings/InsightsSettings.js +3 -3
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +3 -9
- data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/InsightsTable.test.js +12 -7
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.js +2 -2
- data/webpack/InsightsCloudSync/Components/ToolbarDropdown.js +3 -3
- data/webpack/InsightsCloudSync/InsightsCloudSync.js +3 -3
- data/webpack/InsightsCloudSync/InsightsCloudSync.test.js +10 -0
- data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +1 -1
- data/webpack/InsightsHostDetailsTab/NewHostDetailsTab.js +5 -5
- data/webpack/InsightsVulnerabilityHostIndexExtensions/CVECountCell.js +2 -2
- data/webpack/InsightsVulnerabilityHostIndexExtensions/__tests__/CVECountCell.test.js +77 -22
- data/webpack/common/Hooks/ConfigHooks.js +3 -16
- metadata +17 -8
- data/lib/foreman_inventory_upload/async/upload_report_job.rb +0 -97
- data/lib/foreman_inventory_upload/scripts/uploader.sh.erb +0 -55
- data/test/jobs/upload_report_job_test.rb +0 -37
- data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageHeader.test.js.snap +0 -36
- data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTable.test.js.snap +0 -112
- data/webpack/__mocks__/foremanReact/common/hooks/API/APIHooks.js +0 -3
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
require 'test_plugin_helper'
|
|
2
|
+
require 'foreman_tasks/test_helpers'
|
|
3
|
+
|
|
4
|
+
class CreateMissingInsightsFacetsTest < ActiveSupport::TestCase
|
|
5
|
+
include Dynflow::Testing::Factories
|
|
6
|
+
include KatelloCVEHelper
|
|
7
|
+
|
|
8
|
+
setup do
|
|
9
|
+
User.current = User.find_by(login: 'secret_admin')
|
|
10
|
+
@cve = make_cve
|
|
11
|
+
@env = @cve.lifecycle_environment
|
|
12
|
+
@organization = @env.organization
|
|
13
|
+
|
|
14
|
+
# Create a host with subscription facet but no insights facet
|
|
15
|
+
@host_without_facet = FactoryBot.create(
|
|
16
|
+
:host,
|
|
17
|
+
:with_subscription,
|
|
18
|
+
:with_content,
|
|
19
|
+
content_view: @cve.content_view,
|
|
20
|
+
lifecycle_environment: @env,
|
|
21
|
+
organization: @organization
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Create a host with both subscription and insights facets
|
|
25
|
+
@host_with_facet = FactoryBot.create(
|
|
26
|
+
:host,
|
|
27
|
+
:with_subscription,
|
|
28
|
+
:with_content,
|
|
29
|
+
content_view: @cve.content_view,
|
|
30
|
+
lifecycle_environment: @env,
|
|
31
|
+
organization: @organization
|
|
32
|
+
)
|
|
33
|
+
@host_with_facet.build_insights(uuid: @host_with_facet.subscription_facet.uuid)
|
|
34
|
+
@host_with_facet.insights.save!
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
test 'creates insights facets for hosts without them' do
|
|
38
|
+
assert_nil @host_without_facet.insights
|
|
39
|
+
|
|
40
|
+
action = create_and_plan_action(
|
|
41
|
+
ForemanInventoryUpload::Async::CreateMissingInsightsFacets,
|
|
42
|
+
@organization.id
|
|
43
|
+
)
|
|
44
|
+
action = run_action(action)
|
|
45
|
+
|
|
46
|
+
@host_without_facet.reload
|
|
47
|
+
assert_not_nil @host_without_facet.insights
|
|
48
|
+
assert_equal @host_without_facet.subscription_facet.uuid, @host_without_facet.insights.uuid
|
|
49
|
+
assert_match(/Missing Insights facets created: 1/, action.output[:result])
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
test 'does not create duplicate facets for hosts that already have them' do
|
|
53
|
+
original_uuid = @host_with_facet.insights.uuid
|
|
54
|
+
original_id = @host_with_facet.insights.id
|
|
55
|
+
|
|
56
|
+
action = create_and_plan_action(
|
|
57
|
+
ForemanInventoryUpload::Async::CreateMissingInsightsFacets,
|
|
58
|
+
@organization.id
|
|
59
|
+
)
|
|
60
|
+
run_action(action)
|
|
61
|
+
|
|
62
|
+
@host_with_facet.reload
|
|
63
|
+
assert_equal original_id, @host_with_facet.insights.id
|
|
64
|
+
assert_equal original_uuid, @host_with_facet.insights.uuid
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
test 'handles organization with no missing facets' do
|
|
68
|
+
# Create insights facet for the host that was missing one
|
|
69
|
+
@host_without_facet.build_insights(uuid: @host_without_facet.subscription_facet.uuid)
|
|
70
|
+
@host_without_facet.insights.save!
|
|
71
|
+
|
|
72
|
+
action = create_and_plan_action(
|
|
73
|
+
ForemanInventoryUpload::Async::CreateMissingInsightsFacets,
|
|
74
|
+
@organization.id
|
|
75
|
+
)
|
|
76
|
+
action = run_action(action)
|
|
77
|
+
|
|
78
|
+
assert_match(/There were no missing Insights facets/, action.output[:result])
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
test 'creates multiple facets when multiple hosts are missing them' do
|
|
82
|
+
# Remove the insights facet from the host that has one
|
|
83
|
+
@host_with_facet.insights.destroy
|
|
84
|
+
@host_with_facet.reload
|
|
85
|
+
|
|
86
|
+
assert_nil @host_without_facet.insights
|
|
87
|
+
assert_nil @host_with_facet.insights
|
|
88
|
+
|
|
89
|
+
action = create_and_plan_action(
|
|
90
|
+
ForemanInventoryUpload::Async::CreateMissingInsightsFacets,
|
|
91
|
+
@organization.id
|
|
92
|
+
)
|
|
93
|
+
action = run_action(action)
|
|
94
|
+
|
|
95
|
+
@host_without_facet.reload
|
|
96
|
+
@host_with_facet.reload
|
|
97
|
+
assert_not_nil @host_without_facet.insights
|
|
98
|
+
assert_not_nil @host_with_facet.insights
|
|
99
|
+
# After the bug fix, the count should correctly show 2 hosts
|
|
100
|
+
assert_match(/Missing Insights facets created: 2/, action.output[:result])
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
test 'logs result message' do
|
|
104
|
+
Rails.logger.expects(:debug).with(regexp_matches(/Missing Insights facets created/))
|
|
105
|
+
|
|
106
|
+
action = create_and_plan_action(
|
|
107
|
+
ForemanInventoryUpload::Async::CreateMissingInsightsFacets,
|
|
108
|
+
@organization.id
|
|
109
|
+
)
|
|
110
|
+
run_action(action)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
test 'correctly counts facets across multiple batches' do
|
|
114
|
+
# Remove existing insights facet
|
|
115
|
+
@host_with_facet.insights.destroy
|
|
116
|
+
@host_with_facet.reload
|
|
117
|
+
|
|
118
|
+
# Stub the batch size to force multiple batches with just 2 hosts
|
|
119
|
+
ForemanInventoryUpload.stubs(:slice_size).returns(1)
|
|
120
|
+
|
|
121
|
+
assert_nil @host_without_facet.insights
|
|
122
|
+
assert_nil @host_with_facet.insights
|
|
123
|
+
|
|
124
|
+
action = create_and_plan_action(
|
|
125
|
+
ForemanInventoryUpload::Async::CreateMissingInsightsFacets,
|
|
126
|
+
@organization.id
|
|
127
|
+
)
|
|
128
|
+
action = run_action(action)
|
|
129
|
+
|
|
130
|
+
@host_without_facet.reload
|
|
131
|
+
@host_with_facet.reload
|
|
132
|
+
assert_not_nil @host_without_facet.insights
|
|
133
|
+
assert_not_nil @host_with_facet.insights
|
|
134
|
+
# Count should be 2 even though processed in 2 separate batches
|
|
135
|
+
assert_match(/Missing Insights facets created: 2/, action.output[:result])
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
test 'handles error when InsightsFacet.upsert_all fails' do
|
|
139
|
+
# Stub upsert_all to raise an exception
|
|
140
|
+
InsightsFacet.stubs(:upsert_all).raises(StandardError.new('upsert failed'))
|
|
141
|
+
|
|
142
|
+
action = create_and_plan_action(
|
|
143
|
+
ForemanInventoryUpload::Async::CreateMissingInsightsFacets,
|
|
144
|
+
@organization.id
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
assert_raises(StandardError) do
|
|
148
|
+
run_action(action)
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
@@ -2,7 +2,7 @@ require 'test_plugin_helper'
|
|
|
2
2
|
require 'foreman_tasks/test_helpers'
|
|
3
3
|
|
|
4
4
|
class ExponentialBackoffTest < ActiveSupport::TestCase
|
|
5
|
-
include
|
|
5
|
+
include Dynflow::Testing::Factories
|
|
6
6
|
|
|
7
7
|
class TestAction < ::Actions::EntryAction
|
|
8
8
|
include ::ForemanRhCloud::Async::ExponentialBackoff
|
|
@@ -19,28 +19,29 @@ class ExponentialBackoffTest < ActiveSupport::TestCase
|
|
|
19
19
|
test 'executes an action once' do
|
|
20
20
|
TestAction.any_instance.expects(:action_callback).returns(->(instance) { instance.done! })
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
action = create_and_plan_action(TestAction)
|
|
23
|
+
run_action(action)
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
test 'fails after a single excution if done was called' do
|
|
26
27
|
TestAction.any_instance.expects(:action_callback).returns(
|
|
27
28
|
lambda do |instance|
|
|
28
29
|
instance.done!
|
|
29
|
-
raise
|
|
30
|
+
raise StandardError.new('Foo')
|
|
30
31
|
end
|
|
31
32
|
)
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
action = create_and_plan_action(TestAction)
|
|
35
|
+
run_action(action)
|
|
34
36
|
end
|
|
35
37
|
|
|
36
38
|
test 'executes the task three times before failing it' do
|
|
37
39
|
# speed up the execution
|
|
38
40
|
TestAction.any_instance.stubs(:poll_intervals).returns([0, 0, 0])
|
|
39
41
|
|
|
40
|
-
TestAction.any_instance.expects(:action_callback).raises(
|
|
42
|
+
TestAction.any_instance.expects(:action_callback).raises(StandardError.new('Foo')).at_least_once
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
assert ex.aggregated_message =~ /Foo/
|
|
44
|
+
action = create_and_plan_action(TestAction)
|
|
45
|
+
run_action(action)
|
|
45
46
|
end
|
|
46
47
|
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
require 'test_plugin_helper'
|
|
2
|
+
require 'foreman_tasks/test_helpers'
|
|
3
|
+
|
|
4
|
+
class GenerateHostReportTest < ActiveSupport::TestCase
|
|
5
|
+
include Dynflow::Testing::Factories
|
|
6
|
+
include FolderIsolation
|
|
7
|
+
|
|
8
|
+
let(:organization) { FactoryBot.create(:organization) }
|
|
9
|
+
let(:base_folder) { @tmpdir }
|
|
10
|
+
let(:filter) { '' }
|
|
11
|
+
|
|
12
|
+
setup do
|
|
13
|
+
# Stub the ArchivedReport generator
|
|
14
|
+
@mock_generator = mock('archived_report_generator')
|
|
15
|
+
@mock_generator.stubs(:render)
|
|
16
|
+
ForemanInventoryUpload::Generators::ArchivedReport.stubs(:new).returns(@mock_generator)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
test 'plan sets target path correctly' do
|
|
20
|
+
expected_archive_name = ForemanInventoryUpload.facts_archive_name(organization.id, filter)
|
|
21
|
+
expected_target = File.join(base_folder, expected_archive_name)
|
|
22
|
+
|
|
23
|
+
action = create_and_plan_action(
|
|
24
|
+
ForemanInventoryUpload::Async::GenerateHostReport,
|
|
25
|
+
base_folder,
|
|
26
|
+
organization.id,
|
|
27
|
+
filter
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
assert_equal expected_target, action.input[:target]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
test 'run generates report archive' do
|
|
34
|
+
expected_target = File.join(base_folder, ForemanInventoryUpload.facts_archive_name(organization.id, filter))
|
|
35
|
+
|
|
36
|
+
ForemanInventoryUpload::Generators::ArchivedReport.expects(:new).with(expected_target).returns(@mock_generator)
|
|
37
|
+
@mock_generator.expects(:render).with(organization: organization.id, filter: filter)
|
|
38
|
+
|
|
39
|
+
action = create_and_plan_action(
|
|
40
|
+
ForemanInventoryUpload::Async::GenerateHostReport,
|
|
41
|
+
base_folder,
|
|
42
|
+
organization.id,
|
|
43
|
+
filter
|
|
44
|
+
)
|
|
45
|
+
action = run_action(action)
|
|
46
|
+
|
|
47
|
+
assert_match(/Generated #{Regexp.escape(expected_target)} for organization id #{organization.id}/, action.output[:result])
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
test 'generates report with filter' do
|
|
51
|
+
filter_value = 'id=123'
|
|
52
|
+
expected_target = File.join(base_folder, ForemanInventoryUpload.facts_archive_name(organization.id, filter_value))
|
|
53
|
+
|
|
54
|
+
ForemanInventoryUpload::Generators::ArchivedReport.expects(:new).with(expected_target).returns(@mock_generator)
|
|
55
|
+
@mock_generator.expects(:render).with(organization: organization.id, filter: filter_value)
|
|
56
|
+
|
|
57
|
+
action = create_and_plan_action(
|
|
58
|
+
ForemanInventoryUpload::Async::GenerateHostReport,
|
|
59
|
+
base_folder,
|
|
60
|
+
organization.id,
|
|
61
|
+
filter_value
|
|
62
|
+
)
|
|
63
|
+
action = run_action(action)
|
|
64
|
+
|
|
65
|
+
assert_match(/organization id #{organization.id}/, action.output[:result])
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
test 'stores organization_id and filter in input' do
|
|
69
|
+
filter_value = 'name~test'
|
|
70
|
+
|
|
71
|
+
action = create_and_plan_action(
|
|
72
|
+
ForemanInventoryUpload::Async::GenerateHostReport,
|
|
73
|
+
base_folder,
|
|
74
|
+
organization.id,
|
|
75
|
+
filter_value
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
assert_equal organization.id, action.input[:organization_id]
|
|
79
|
+
assert_equal filter_value, action.input[:filter]
|
|
80
|
+
assert_equal base_folder, action.input[:base_folder]
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
test 'handles ArchivedReport generator failure' do
|
|
84
|
+
expected_target = File.join(base_folder, ForemanInventoryUpload.facts_archive_name(organization.id, filter))
|
|
85
|
+
|
|
86
|
+
ForemanInventoryUpload::Generators::ArchivedReport.expects(:new).with(expected_target).returns(@mock_generator)
|
|
87
|
+
@mock_generator.expects(:render).with(organization: organization.id, filter: filter).raises(StandardError.new('Report generation failed'))
|
|
88
|
+
|
|
89
|
+
action = create_and_plan_action(
|
|
90
|
+
ForemanInventoryUpload::Async::GenerateHostReport,
|
|
91
|
+
base_folder,
|
|
92
|
+
organization.id,
|
|
93
|
+
filter
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
assert_raises(StandardError) do
|
|
97
|
+
run_action(action)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
require 'test_plugin_helper'
|
|
2
|
+
require 'foreman_tasks/test_helpers'
|
|
3
|
+
|
|
4
|
+
class GenerateReportJobTest < ActiveSupport::TestCase
|
|
5
|
+
include Dynflow::Testing::Factories
|
|
6
|
+
include Dynflow::Testing::Assertions
|
|
7
|
+
|
|
8
|
+
let(:organization) { FactoryBot.create(:organization) }
|
|
9
|
+
let(:base_folder) { Dir.mktmpdir }
|
|
10
|
+
|
|
11
|
+
setup do
|
|
12
|
+
# Stub settings
|
|
13
|
+
Setting.stubs(:[]).with(:subscription_connection_enabled).returns(true)
|
|
14
|
+
Setting.stubs(:[]).with("foreman_tasks_sync_task_timeout").returns(120)
|
|
15
|
+
Setting.stubs(:[]).with(:content_default_http_proxy).returns(nil)
|
|
16
|
+
Setting.stubs(:[]).with(:http_proxy).returns(nil)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
teardown do
|
|
20
|
+
FileUtils.remove_entry base_folder if Dir.exist?(base_folder)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
test 'disconnected parameter defaults to false' do
|
|
24
|
+
# When disconnected defaults to false and subscription_connection is enabled,
|
|
25
|
+
# QueueForUploadJob should be scheduled
|
|
26
|
+
action = create_and_plan_action(
|
|
27
|
+
ForemanInventoryUpload::Async::GenerateReportJob,
|
|
28
|
+
base_folder,
|
|
29
|
+
organization.id
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
assert_action_planned(action, ForemanInventoryUpload::Async::QueueForUploadJob)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
test 'disconnected parameter can be set to true explicitly' do
|
|
36
|
+
# When disconnected is explicitly true, QueueForUploadJob should NOT be scheduled
|
|
37
|
+
action = create_and_plan_action(
|
|
38
|
+
ForemanInventoryUpload::Async::GenerateReportJob,
|
|
39
|
+
base_folder,
|
|
40
|
+
organization.id,
|
|
41
|
+
true
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
refute_action_planned(action, ForemanInventoryUpload::Async::QueueForUploadJob)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
test 'disconnected parameter can be set to false explicitly' do
|
|
48
|
+
# When disconnected is explicitly false and subscription_connection is enabled,
|
|
49
|
+
# QueueForUploadJob should be scheduled
|
|
50
|
+
action = create_and_plan_action(
|
|
51
|
+
ForemanInventoryUpload::Async::GenerateReportJob,
|
|
52
|
+
base_folder,
|
|
53
|
+
organization.id,
|
|
54
|
+
false
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
assert_action_planned(action, ForemanInventoryUpload::Async::QueueForUploadJob)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
test 'skips upload when subscription_connection_enabled is false' do
|
|
61
|
+
Setting.stubs(:[]).with(:subscription_connection_enabled).returns(false)
|
|
62
|
+
|
|
63
|
+
action = create_and_plan_action(
|
|
64
|
+
ForemanInventoryUpload::Async::GenerateReportJob,
|
|
65
|
+
base_folder,
|
|
66
|
+
organization.id,
|
|
67
|
+
false
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
refute_action_planned(action, ForemanInventoryUpload::Async::QueueForUploadJob)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
test 'schedules upload when disconnected is false and subscription_connection is enabled' do
|
|
74
|
+
Setting.stubs(:[]).with(:subscription_connection_enabled).returns(true)
|
|
75
|
+
|
|
76
|
+
expected_archive_name = ForemanInventoryUpload.facts_archive_name(organization.id, nil)
|
|
77
|
+
action = create_and_plan_action(
|
|
78
|
+
ForemanInventoryUpload::Async::GenerateReportJob,
|
|
79
|
+
base_folder,
|
|
80
|
+
organization.id,
|
|
81
|
+
false
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
assert_action_planned_with(
|
|
85
|
+
action,
|
|
86
|
+
ForemanInventoryUpload::Async::QueueForUploadJob,
|
|
87
|
+
base_folder,
|
|
88
|
+
expected_archive_name,
|
|
89
|
+
organization.id
|
|
90
|
+
)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
test 'handles hosts_filter parameter' do
|
|
94
|
+
hosts_filter = 'name~test'
|
|
95
|
+
expected_archive_name = ForemanInventoryUpload.facts_archive_name(organization.id, hosts_filter)
|
|
96
|
+
|
|
97
|
+
action = create_and_plan_action(
|
|
98
|
+
ForemanInventoryUpload::Async::GenerateReportJob,
|
|
99
|
+
base_folder,
|
|
100
|
+
organization.id,
|
|
101
|
+
false,
|
|
102
|
+
hosts_filter
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
assert_action_planned_with(
|
|
106
|
+
action,
|
|
107
|
+
ForemanInventoryUpload::Async::QueueForUploadJob,
|
|
108
|
+
base_folder,
|
|
109
|
+
expected_archive_name,
|
|
110
|
+
organization.id
|
|
111
|
+
)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
test 'output_label generates correct label' do
|
|
115
|
+
label = ForemanInventoryUpload::Async::GenerateReportJob.output_label('test_org')
|
|
116
|
+
assert_equal 'report_for_test_org', label
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
test 'output_label with filter includes parameterized filter' do
|
|
120
|
+
action = create_and_plan_action(
|
|
121
|
+
ForemanInventoryUpload::Async::GenerateReportJob,
|
|
122
|
+
base_folder,
|
|
123
|
+
organization.id,
|
|
124
|
+
false,
|
|
125
|
+
'name~production'
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# The output label should include organization id and parameterized filter
|
|
129
|
+
expected_label = "report_for_#{organization.id}[name-production]"
|
|
130
|
+
assert_equal expected_label, action.input[:instance_label]
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
test 'output_label without filter includes only organization id' do
|
|
134
|
+
action = create_and_plan_action(
|
|
135
|
+
ForemanInventoryUpload::Async::GenerateReportJob,
|
|
136
|
+
base_folder,
|
|
137
|
+
organization.id,
|
|
138
|
+
false,
|
|
139
|
+
''
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# The output label should include only organization id when filter is empty
|
|
143
|
+
expected_label = "report_for_#{organization.id}"
|
|
144
|
+
assert_equal expected_label, action.input[:instance_label]
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
require 'test_plugin_helper'
|
|
2
|
+
require 'foreman_tasks/test_helpers'
|
|
3
|
+
|
|
4
|
+
class HostInventoryReportJobTest < ActiveSupport::TestCase
|
|
5
|
+
include Dynflow::Testing::Factories
|
|
6
|
+
include Dynflow::Testing::Assertions
|
|
7
|
+
|
|
8
|
+
let(:organization) { FactoryBot.create(:organization) }
|
|
9
|
+
let(:base_folder) { Dir.mktmpdir }
|
|
10
|
+
let(:hosts_filter) { '' }
|
|
11
|
+
let(:upload) { true }
|
|
12
|
+
|
|
13
|
+
teardown do
|
|
14
|
+
FileUtils.remove_entry base_folder if Dir.exist?(base_folder)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
test 'plan schedules GenerateHostReport action' do
|
|
18
|
+
action = create_and_plan_action(
|
|
19
|
+
ForemanInventoryUpload::Async::HostInventoryReportJob,
|
|
20
|
+
base_folder,
|
|
21
|
+
organization.id,
|
|
22
|
+
hosts_filter,
|
|
23
|
+
upload
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
assert_action_planned_with(
|
|
27
|
+
action,
|
|
28
|
+
ForemanInventoryUpload::Async::GenerateHostReport,
|
|
29
|
+
base_folder,
|
|
30
|
+
organization.id,
|
|
31
|
+
hosts_filter
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
test 'plan schedules QueueForUploadJob when upload is true' do
|
|
36
|
+
expected_archive_name = ForemanInventoryUpload.facts_archive_name(organization.id, hosts_filter)
|
|
37
|
+
|
|
38
|
+
action = create_and_plan_action(
|
|
39
|
+
ForemanInventoryUpload::Async::HostInventoryReportJob,
|
|
40
|
+
base_folder,
|
|
41
|
+
organization.id,
|
|
42
|
+
hosts_filter,
|
|
43
|
+
true
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
assert_action_planned_with(
|
|
47
|
+
action,
|
|
48
|
+
ForemanInventoryUpload::Async::QueueForUploadJob,
|
|
49
|
+
base_folder,
|
|
50
|
+
expected_archive_name,
|
|
51
|
+
organization.id
|
|
52
|
+
)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
test 'plan skips QueueForUploadJob when upload is false' do
|
|
56
|
+
action = create_and_plan_action(
|
|
57
|
+
ForemanInventoryUpload::Async::HostInventoryReportJob,
|
|
58
|
+
base_folder,
|
|
59
|
+
organization.id,
|
|
60
|
+
hosts_filter,
|
|
61
|
+
false
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
refute_action_planned(action, ForemanInventoryUpload::Async::QueueForUploadJob)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
test 'plan defaults upload to true when not specified' do
|
|
68
|
+
action = create_and_plan_action(
|
|
69
|
+
ForemanInventoryUpload::Async::HostInventoryReportJob,
|
|
70
|
+
base_folder,
|
|
71
|
+
organization.id,
|
|
72
|
+
hosts_filter
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
assert_action_planned(action, ForemanInventoryUpload::Async::QueueForUploadJob)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
test 'plan schedules CreateMissingInsightsFacets when IoP is enabled' do
|
|
79
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(true)
|
|
80
|
+
|
|
81
|
+
action = create_and_plan_action(
|
|
82
|
+
ForemanInventoryUpload::Async::HostInventoryReportJob,
|
|
83
|
+
base_folder,
|
|
84
|
+
organization.id,
|
|
85
|
+
hosts_filter,
|
|
86
|
+
upload
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
assert_action_planned_with(
|
|
90
|
+
action,
|
|
91
|
+
ForemanInventoryUpload::Async::CreateMissingInsightsFacets,
|
|
92
|
+
organization.id
|
|
93
|
+
)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
test 'plan skips CreateMissingInsightsFacets when IoP is disabled' do
|
|
97
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(false)
|
|
98
|
+
|
|
99
|
+
action = create_and_plan_action(
|
|
100
|
+
ForemanInventoryUpload::Async::HostInventoryReportJob,
|
|
101
|
+
base_folder,
|
|
102
|
+
organization.id,
|
|
103
|
+
hosts_filter,
|
|
104
|
+
upload
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
refute_action_planned(action, ForemanInventoryUpload::Async::CreateMissingInsightsFacets)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
test 'plan schedules all three actions with IoP enabled and upload true' do
|
|
111
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(true)
|
|
112
|
+
|
|
113
|
+
action = create_and_plan_action(
|
|
114
|
+
ForemanInventoryUpload::Async::HostInventoryReportJob,
|
|
115
|
+
base_folder,
|
|
116
|
+
organization.id,
|
|
117
|
+
hosts_filter,
|
|
118
|
+
true
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
assert_action_planned(action, ForemanInventoryUpload::Async::GenerateHostReport)
|
|
122
|
+
assert_action_planned(action, ForemanInventoryUpload::Async::QueueForUploadJob)
|
|
123
|
+
assert_action_planned(action, ForemanInventoryUpload::Async::CreateMissingInsightsFacets)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
test 'plan schedules only generation and facets with IoP enabled and upload false' do
|
|
127
|
+
ForemanRhCloud.stubs(:with_iop_smart_proxy?).returns(true)
|
|
128
|
+
|
|
129
|
+
action = create_and_plan_action(
|
|
130
|
+
ForemanInventoryUpload::Async::HostInventoryReportJob,
|
|
131
|
+
base_folder,
|
|
132
|
+
organization.id,
|
|
133
|
+
hosts_filter,
|
|
134
|
+
false
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
assert_action_planned(action, ForemanInventoryUpload::Async::GenerateHostReport)
|
|
138
|
+
refute_action_planned(action, ForemanInventoryUpload::Async::QueueForUploadJob)
|
|
139
|
+
assert_action_planned(action, ForemanInventoryUpload::Async::CreateMissingInsightsFacets)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
test 'humanized_name returns correct string' do
|
|
143
|
+
action = create_and_plan_action(
|
|
144
|
+
ForemanInventoryUpload::Async::HostInventoryReportJob,
|
|
145
|
+
base_folder,
|
|
146
|
+
organization.id,
|
|
147
|
+
hosts_filter,
|
|
148
|
+
upload
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
assert_equal 'Host inventory report job', action.humanized_name
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
test 'handles empty hosts_filter parameter' do
|
|
155
|
+
action = create_and_plan_action(
|
|
156
|
+
ForemanInventoryUpload::Async::HostInventoryReportJob,
|
|
157
|
+
base_folder,
|
|
158
|
+
organization.id,
|
|
159
|
+
'',
|
|
160
|
+
upload
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
assert_action_planned_with(
|
|
164
|
+
action,
|
|
165
|
+
ForemanInventoryUpload::Async::GenerateHostReport,
|
|
166
|
+
base_folder,
|
|
167
|
+
organization.id,
|
|
168
|
+
''
|
|
169
|
+
)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
test 'handles custom hosts_filter parameter' do
|
|
173
|
+
custom_filter = 'name~production'
|
|
174
|
+
expected_archive_name = ForemanInventoryUpload.facts_archive_name(organization.id, custom_filter)
|
|
175
|
+
|
|
176
|
+
action = create_and_plan_action(
|
|
177
|
+
ForemanInventoryUpload::Async::HostInventoryReportJob,
|
|
178
|
+
base_folder,
|
|
179
|
+
organization.id,
|
|
180
|
+
custom_filter,
|
|
181
|
+
upload
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
assert_action_planned_with(
|
|
185
|
+
action,
|
|
186
|
+
ForemanInventoryUpload::Async::GenerateHostReport,
|
|
187
|
+
base_folder,
|
|
188
|
+
organization.id,
|
|
189
|
+
custom_filter
|
|
190
|
+
)
|
|
191
|
+
assert_action_planned_with(
|
|
192
|
+
action,
|
|
193
|
+
ForemanInventoryUpload::Async::QueueForUploadJob,
|
|
194
|
+
base_folder,
|
|
195
|
+
expected_archive_name,
|
|
196
|
+
organization.id
|
|
197
|
+
)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
test 'handles invalid hosts_filter parameter' do
|
|
201
|
+
invalid_filter = 'name~~'
|
|
202
|
+
|
|
203
|
+
action = create_and_plan_action(
|
|
204
|
+
ForemanInventoryUpload::Async::HostInventoryReportJob,
|
|
205
|
+
base_folder,
|
|
206
|
+
organization.id,
|
|
207
|
+
invalid_filter,
|
|
208
|
+
upload
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
# Job should still plan even with invalid filter syntax
|
|
212
|
+
assert_action_planned(action, ForemanInventoryUpload::Async::GenerateHostReport)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
test 'handles potentially malicious hosts_filter parameter' do
|
|
216
|
+
malicious_filter = "'; DROP TABLE hosts; --"
|
|
217
|
+
|
|
218
|
+
action = create_and_plan_action(
|
|
219
|
+
ForemanInventoryUpload::Async::HostInventoryReportJob,
|
|
220
|
+
base_folder,
|
|
221
|
+
organization.id,
|
|
222
|
+
malicious_filter,
|
|
223
|
+
upload
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
# Job should handle malicious input safely (filter is parameterized)
|
|
227
|
+
assert_action_planned(action, ForemanInventoryUpload::Async::GenerateHostReport)
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
test 'handles non-matching hosts_filter parameter' do
|
|
231
|
+
non_matching_filter = 'name~doesnotexist'
|
|
232
|
+
|
|
233
|
+
action = create_and_plan_action(
|
|
234
|
+
ForemanInventoryUpload::Async::HostInventoryReportJob,
|
|
235
|
+
base_folder,
|
|
236
|
+
organization.id,
|
|
237
|
+
non_matching_filter,
|
|
238
|
+
upload
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
# Job should plan successfully even if filter matches no hosts
|
|
242
|
+
assert_action_planned(action, ForemanInventoryUpload::Async::GenerateHostReport)
|
|
243
|
+
end
|
|
244
|
+
end
|
|
@@ -2,7 +2,7 @@ require 'test_plugin_helper'
|
|
|
2
2
|
require 'foreman_tasks/test_helpers'
|
|
3
3
|
|
|
4
4
|
class InsightsClientStatusAgingTest < ActiveSupport::TestCase
|
|
5
|
-
include
|
|
5
|
+
include Dynflow::Testing::Factories
|
|
6
6
|
|
|
7
7
|
setup do
|
|
8
8
|
User.current = User.find_by(login: 'secret_admin')
|
|
@@ -21,7 +21,8 @@ class InsightsClientStatusAgingTest < ActiveSupport::TestCase
|
|
|
21
21
|
InsightsClientReportStatus.find_or_initialize_by(host_id: @host3.id).update(status: InsightsClientReportStatus::REPORTING, reported_at: Time.now - InsightsClientReportStatus::REPORT_INTERVAL - 1.day)
|
|
22
22
|
InsightsClientReportStatus.find_or_initialize_by(host_id: @host4.id).update(status: InsightsClientReportStatus::NO_REPORT, reported_at: Time.now - InsightsClientReportStatus::REPORT_INTERVAL - 1.day)
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
action = create_and_plan_action(InsightsCloud::Async::InsightsClientStatusAging)
|
|
25
|
+
run_action(action)
|
|
25
26
|
|
|
26
27
|
@hosts.each(&:reload)
|
|
27
28
|
|