foreman_host_reports 0.0.3

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.
Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +619 -0
  3. data/README.md +545 -0
  4. data/app/controllers/api/v2/host_reports_controller.rb +98 -0
  5. data/app/controllers/concerns/foreman_host_reports/controller/parameters/host_report.rb +25 -0
  6. data/app/controllers/host_reports_controller.rb +46 -0
  7. data/app/models/concerns/foreman_host_reports/host_extensions.rb +9 -0
  8. data/app/models/concerns/foreman_host_reports/smart_proxy_extensions.rb +9 -0
  9. data/app/models/host_report.rb +85 -0
  10. data/app/models/report_keyword.rb +11 -0
  11. data/app/views/api/v2/host_reports/base.json.rabl +5 -0
  12. data/app/views/api/v2/host_reports/create.json.rabl +5 -0
  13. data/app/views/api/v2/host_reports/index.json.rabl +5 -0
  14. data/app/views/api/v2/host_reports/main.json.rabl +15 -0
  15. data/app/views/api/v2/host_reports/show.json.rabl +11 -0
  16. data/config/routes.rb +33 -0
  17. data/db/migrate/20210112183526_add_host_reports.rb +36 -0
  18. data/db/migrate/20210616133601_create_report_keywords.rb +12 -0
  19. data/lib/foreman_host_reports/engine.rb +68 -0
  20. data/lib/foreman_host_reports/version.rb +3 -0
  21. data/lib/foreman_host_reports.rb +4 -0
  22. data/lib/tasks/foreman_host_reports_tasks.rake +50 -0
  23. data/locale/Makefile +60 -0
  24. data/locale/en/foreman_host_reports.po +19 -0
  25. data/locale/foreman_host_reports.pot +19 -0
  26. data/locale/gemspec.rb +2 -0
  27. data/package.json +45 -0
  28. data/test/controllers/api/v2/host_reports_controller_test.rb +278 -0
  29. data/test/factories/foreman_host_reports_factories.rb +21 -0
  30. data/test/snapshots/foreman-web.json +918 -0
  31. data/test/test_plugin_helper.rb +11 -0
  32. data/test/unit/foreman_host_reports_test.rb +9 -0
  33. data/webpack/global_index.js +4 -0
  34. data/webpack/global_test_setup.js +11 -0
  35. data/webpack/index.js +0 -0
  36. data/webpack/src/Router/HostReports/Components/HostReportDeleteModal.js +50 -0
  37. data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/Components/FormatCell.js +53 -0
  38. data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/Components/FormatCell.scss +4 -0
  39. data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/Components/Formatters/formatCellFormatter.js +6 -0
  40. data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/Components/Formatters/hostReportsToShowFormatter.js +13 -0
  41. data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/Components/Formatters/index.js +4 -0
  42. data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/Components/Formatters/reportToShowFormatter.js +13 -0
  43. data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/Components/Formatters/statusFormatter.js +9 -0
  44. data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/Components/HostReportsToShowCell.js +32 -0
  45. data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/Components/ReportToShowCell.js +27 -0
  46. data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/Components/StatusCell.js +77 -0
  47. data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/Components/StatusCell.scss +9 -0
  48. data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/Components/formatImages.js +7 -0
  49. data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/Components/images/ansible.png +0 -0
  50. data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/Components/images/puppet.png +0 -0
  51. data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/HostReportsTable.js +85 -0
  52. data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/HostReportsTableSchema.js +65 -0
  53. data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/index.js +28 -0
  54. data/webpack/src/Router/HostReports/IndexPage/IndexPage.js +88 -0
  55. data/webpack/src/Router/HostReports/IndexPage/IndexPageActions.js +55 -0
  56. data/webpack/src/Router/HostReports/IndexPage/IndexPageHelpers.js +50 -0
  57. data/webpack/src/Router/HostReports/IndexPage/IndexPageSelectors.js +86 -0
  58. data/webpack/src/Router/HostReports/IndexPage/constants.js +14 -0
  59. data/webpack/src/Router/HostReports/IndexPage/index.js +98 -0
  60. data/webpack/src/Router/HostReports/ShowPage/Components/HostReportMetrics/HostReportMetrics.scss +3 -0
  61. data/webpack/src/Router/HostReports/ShowPage/Components/HostReportMetrics/index.js +100 -0
  62. data/webpack/src/Router/HostReports/ShowPage/Components/ReportLogs/Ansible.js +77 -0
  63. data/webpack/src/Router/HostReports/ShowPage/Components/ReportLogs/Puppet.js +79 -0
  64. data/webpack/src/Router/HostReports/ShowPage/Components/ReportLogs/helpers.js +17 -0
  65. data/webpack/src/Router/HostReports/ShowPage/Components/ReportLogs/index.js +29 -0
  66. data/webpack/src/Router/HostReports/ShowPage/Components/ReportLogsFilter/index.js +109 -0
  67. data/webpack/src/Router/HostReports/ShowPage/ShowPage.js +160 -0
  68. data/webpack/src/Router/HostReports/ShowPage/ShowPageSelectors.js +51 -0
  69. data/webpack/src/Router/HostReports/ShowPage/index.js +75 -0
  70. data/webpack/src/Router/HostReports/constants.js +15 -0
  71. data/webpack/src/Router/routes.js +23 -0
  72. data/webpack/test_setup.js +17 -0
  73. metadata +133 -0
@@ -0,0 +1,278 @@
1
+ require 'test_plugin_helper'
2
+
3
+ class Api::V2::HostReportsControllerTest < ActionController::TestCase
4
+ context 'when user does not have permission to view hosts' do
5
+ let :host_report do
6
+ as_admin { FactoryBot.create(:host_report) }
7
+ end
8
+
9
+ setup { setup_user('view', 'host_reports') }
10
+
11
+ test 'cannot view any reports' do
12
+ get :show, params: { id: host_report.id }, session: set_session_user.merge(user: User.current.id)
13
+ assert_response :not_found
14
+ end
15
+
16
+ test 'cannot delete host reports' do
17
+ setup_user 'destroy', 'host_reports'
18
+ delete :destroy, params: { id: host_report.id }, session: set_session_user.merge(user: User.current.id)
19
+ assert_response :not_found
20
+ end
21
+ end
22
+
23
+ describe 'Non Admin User' do
24
+ def setup
25
+ User.current = users(:one) # use an unprivileged user, not apiadmin
26
+ end
27
+
28
+ def report_body
29
+ @report_body ||= read_report('foreman-web.json')
30
+ end
31
+
32
+ let :host do
33
+ as_admin { FactoryBot.create(:host) }
34
+ end
35
+
36
+ def test_create_valid
37
+ User.current = nil
38
+ post :create, params: {
39
+ host_report: {
40
+ host: host.name, body: report_body, reported_at: Time.current,
41
+ status: 0
42
+ },
43
+ }, session: set_session_user
44
+ assert_response :success
45
+ end
46
+
47
+ def test_create_invalid
48
+ User.current = nil
49
+ post :create, params: { host_report: { body: report_body } }, session: set_session_user
50
+ assert_response :unprocessable_entity
51
+ end
52
+
53
+ test 'assign keywords' do
54
+ User.current = nil
55
+ post :create, params: {
56
+ host_report: {
57
+ host: host.name, body: report_body, reported_at: Time.current,
58
+ status: 0, keywords: %w[HasError HasFailedResource]
59
+ },
60
+ }, session: set_session_user
61
+ report = ActiveSupport::JSON.decode(@response.body)
62
+ assert_response :created
63
+ refute_empty report['keywords']
64
+ end
65
+
66
+ test 're-use existing keywords' do
67
+ User.current = nil
68
+ assert_difference('ReportKeyword.count', 2) do
69
+ post :create, params: {
70
+ host_report: {
71
+ host: host.name, body: report_body, reported_at: Time.current,
72
+ status: 0, keywords: %w[HasError HasFailedResource]
73
+ },
74
+ }, session: set_session_user
75
+
76
+ post :create, params: {
77
+ host_report: {
78
+ host: host.name, body: report_body, reported_at: Time.current,
79
+ status: 0, keywords: %w[HasError HasFailedResource]
80
+ },
81
+ }, session: set_session_user
82
+ end
83
+ end
84
+
85
+ test 'when ":restrict_registered_smart_proxies" is false, HTTP requests should be able to create a report' do
86
+ Setting[:restrict_registered_smart_proxies] = false
87
+ SETTINGS[:require_ssl] = false
88
+
89
+ Resolv.any_instance.stubs(:getnames).returns(['else.where'])
90
+ post :create, params: {
91
+ host_report: {
92
+ host: host.name, body: report_body, reported_at: Time.current,
93
+ status: 0
94
+ },
95
+ }
96
+ assert_nil @controller.detected_proxy
97
+ assert_response :created
98
+ end
99
+
100
+ test 'hosts with a registered smart proxy on should create a report successfully' do
101
+ Setting[:restrict_registered_smart_proxies] = true
102
+ Setting[:require_ssl_smart_proxies] = false
103
+
104
+ stub_smart_proxy_v2_features
105
+ proxy = smart_proxies(:puppetmaster)
106
+ as_admin { proxy.update_attribute(:url, 'http://configreports.foreman') }
107
+ proxy_host = URI.parse(proxy.url).host
108
+ Resolv.any_instance.stubs(:getnames).returns([proxy_host])
109
+ post :create, params: {
110
+ host_report: {
111
+ host: host.name, body: report_body, reported_at: Time.current,
112
+ status: 0
113
+ },
114
+ }
115
+ assert_equal proxy, @controller.detected_proxy
116
+ assert_response :created
117
+ end
118
+
119
+ test 'hosts without a registered smart proxy on should not be able to create a report' do
120
+ Setting[:restrict_registered_smart_proxies] = true
121
+ Setting[:require_ssl_smart_proxies] = false
122
+
123
+ Resolv.any_instance.stubs(:getnames).returns(['another.host'])
124
+ post :create, params: {
125
+ host_report: {
126
+ host: host.name, body: report_body, reported_at: Time.current,
127
+ status: 0
128
+ },
129
+ }
130
+ assert_response :forbidden
131
+ end
132
+
133
+ test 'hosts with a registered smart proxy and SSL cert should create a report successfully' do
134
+ Setting[:restrict_registered_smart_proxies] = true
135
+ Setting[:require_ssl_smart_proxies] = true
136
+
137
+ @request.env['HTTPS'] = 'on'
138
+ @request.env['SSL_CLIENT_S_DN'] = 'CN=else.where'
139
+ @request.env['SSL_CLIENT_VERIFY'] = 'SUCCESS'
140
+ post :create, params: {
141
+ host_report: {
142
+ host: host.name, body: report_body, reported_at: Time.current,
143
+ status: 0
144
+ },
145
+ }
146
+ assert_response :created
147
+ end
148
+
149
+ test 'hosts without a registered smart proxy but with an SSL cert should not be able to create a report' do
150
+ Setting[:restrict_registered_smart_proxies] = true
151
+ Setting[:require_ssl_smart_proxies] = true
152
+
153
+ @request.env['HTTPS'] = 'on'
154
+ @request.env['SSL_CLIENT_S_DN'] = 'CN=another.host'
155
+ @request.env['SSL_CLIENT_VERIFY'] = 'SUCCESS'
156
+ post :create, params: {
157
+ host_report: {
158
+ host: host.name, body: report_body, reported_at: Time.current,
159
+ status: 0
160
+ },
161
+ }
162
+ assert_response :forbidden
163
+ end
164
+
165
+ test 'hosts with an unverified SSL cert should not be able to create a report' do
166
+ Setting[:restrict_registered_smart_proxies] = true
167
+ Setting[:require_ssl_smart_proxies] = true
168
+
169
+ @request.env['HTTPS'] = 'on'
170
+ @request.env['SSL_CLIENT_S_DN'] = 'CN=else.where'
171
+ @request.env['SSL_CLIENT_VERIFY'] = 'FAILED'
172
+ post :create, params: {
173
+ host_report: {
174
+ host: host.name, body: report_body, reported_at: Time.current,
175
+ status: 0
176
+ },
177
+ }
178
+ assert_response :forbidden
179
+ end
180
+
181
+ test 'when "require_ssl_smart_proxies" and "require_ssl" are true, HTTP requests should not be able to create a report' do
182
+ Setting[:restrict_registered_smart_proxies] = true
183
+ Setting[:require_ssl_smart_proxies] = true
184
+ SETTINGS[:require_ssl] = true
185
+
186
+ Resolv.any_instance.stubs(:getnames).returns(['else.where'])
187
+ post :create, params: {
188
+ host_report: {
189
+ host: host.name, body: report_body, reported_at: Time.current,
190
+ status: 0
191
+ },
192
+ }
193
+ assert_response :forbidden
194
+ end
195
+
196
+ test 'when "require_ssl_smart_proxies" is true and "require_ssl" is false, HTTP requests should be able to create reports' do
197
+ # since require_ssl_smart_proxies is only applicable to HTTPS connections, both should be set
198
+ Setting[:restrict_registered_smart_proxies] = true
199
+ Setting[:require_ssl_smart_proxies] = true
200
+ SETTINGS[:require_ssl] = false
201
+
202
+ Resolv.any_instance.stubs(:getnames).returns(['else.where'])
203
+ post :create, params: {
204
+ host_report: {
205
+ host: host.name, body: report_body, reported_at: Time.current,
206
+ status: 0
207
+ },
208
+ }
209
+ assert_response :created
210
+ end
211
+ end
212
+
213
+ test 'should get index' do
214
+ FactoryBot.create(:host_report)
215
+ get :index
216
+ assert_response :success
217
+ refute_nil assigns(:host_reports)
218
+ reports = ActiveSupport::JSON.decode(@response.body)
219
+ refute_empty reports['results']
220
+ end
221
+
222
+ context 'with organization given' do
223
+ let(:host_report_org) { Organization.first }
224
+ let(:host_report_loc) { Location.first }
225
+ let(:reporting_host) do
226
+ FactoryBot.create(:host, location: host_report_loc, organization: host_report_org)
227
+ end
228
+ let(:host_report) do
229
+ FactoryBot.create(:host_report, host: reporting_host)
230
+ end
231
+
232
+ test 'should get host reports in organization' do
233
+ host_report.save!
234
+ get :index, params: { organization_id: host_report_org.id }
235
+ assert_response :success
236
+ refute_nil assigns(:host_reports)
237
+ reports = ActiveSupport::JSON.decode(@response.body)
238
+ refute_empty reports['results']
239
+ end
240
+ end
241
+
242
+ test 'should show individual record' do
243
+ report = FactoryBot.create(:host_report)
244
+ get :show, params: { id: report.to_param }
245
+ assert_response :success
246
+ show_response = ActiveSupport::JSON.decode(@response.body)
247
+ refute_empty show_response
248
+ end
249
+
250
+ test 'should destroy report' do
251
+ report = FactoryBot.create(:host_report)
252
+ assert_difference('HostReport.count', -1) do
253
+ delete :destroy, params: { id: report.to_param }
254
+ end
255
+ assert_response :success
256
+ refute HostReport.unscoped.find_by(id: report.id)
257
+ end
258
+
259
+ test 'should get reports for given host only' do
260
+ report = FactoryBot.create(:host_report)
261
+ get :index, params: { host_id: report.host.id }
262
+ assert_response :success
263
+ refute_nil assigns(:host_reports)
264
+ reports = ActiveSupport::JSON.decode(@response.body)
265
+ refute_empty reports['results']
266
+ assert_equal 1, reports['results'].count
267
+ end
268
+
269
+ test 'should return empty result for host with no reports' do
270
+ host = FactoryBot.create(:host)
271
+ get :index, params: { host_id: host.to_param }
272
+ assert_response :success
273
+ refute_nil assigns(:host_reports)
274
+ reports = ActiveSupport::JSON.decode(@response.body)
275
+ assert_empty reports['results']
276
+ assert_equal 0, reports['results'].count
277
+ end
278
+ end
@@ -0,0 +1,21 @@
1
+ FactoryBot.define do
2
+ factory :host_report do
3
+ host
4
+ reported_at { Time.now.utc }
5
+ status { 0 }
6
+ body { 'report data' }
7
+ end
8
+
9
+ trait :with_keyword do
10
+ transient do
11
+ name { 'HasError' }
12
+ end
13
+ after(:build) do |report, evaluator|
14
+ report.report_keyword_ids = [FactoryBot.create(:report_keyword, name: evaluator.name).id]
15
+ end
16
+ end
17
+
18
+ factory :report_keyword do
19
+ sequence(:name) { |n| "Keyword-#{n}" }
20
+ end
21
+ end