foreman_host_reports 0.0.4 → 1.0.0
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 +67 -447
- data/app/controllers/api/v2/host_reports_controller.rb +39 -20
- data/app/controllers/concerns/foreman_host_reports/controller/hosts_controller_extensions.rb +18 -0
- data/app/controllers/concerns/foreman_host_reports/controller/parameters/host_report.rb +1 -1
- data/app/controllers/host_reports_controller.rb +32 -2
- data/app/helpers/concerns/foreman_host_reports/hosts_helper_extensions.rb +25 -0
- data/app/models/concerns/foreman_host_reports/host_extensions.rb +6 -0
- data/app/models/host_report.rb +15 -0
- data/app/models/host_status/host_report_status.rb +185 -0
- data/app/views/api/v2/host_reports/main.json.rabl +1 -2
- data/config/routes.rb +2 -4
- data/db/migrate/20220113064436_rename_status_summaries.rb +12 -0
- data/lib/foreman_host_reports/engine.rb +11 -5
- data/lib/foreman_host_reports/version.rb +1 -1
- data/test/controllers/api/v2/host_reports_controller_test.rb +30 -67
- data/test/factories/foreman_host_reports_factories.rb +13 -5
- data/test/model/host_report_status_test.rb +204 -0
- data/test/test_plugin_helper.rb +4 -2
- data/webpack/__mocks__/foremanReact/components/Pagination/index.js +2 -0
- data/webpack/fills.js +23 -0
- data/webpack/global_index.js +2 -0
- data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/Components/Formatters/statusFormatter.js +3 -4
- data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/Components/StatusCell.js +1 -1
- data/webpack/src/Router/HostReports/IndexPage/Components/HostReportsTable/HostReportsTable.js +2 -10
- data/webpack/src/Router/HostReports/IndexPage/IndexPage.js +0 -1
- data/webpack/src/Router/HostReports/IndexPage/IndexPageActions.js +5 -4
- data/webpack/src/Router/HostReports/IndexPage/IndexPageHelpers.js +1 -1
- data/webpack/src/Router/HostReports/IndexPage/__tests__/HostReportsIndexPage.test.js +3 -4
- data/webpack/src/Router/HostReports/IndexPage/__tests__/__snapshots__/HostReportsIndexPage.test.js.snap +4 -6
- data/webpack/src/Router/HostReports/IndexPage/constants.js +4 -3
- data/webpack/src/Router/HostReports/ShowPage/Components/ReportLogs/Ansible.js +62 -27
- data/webpack/src/Router/HostReports/ShowPage/Components/ReportLogs/Components/EmptyLogsRow.js +27 -0
- data/webpack/src/Router/HostReports/ShowPage/Components/ReportLogs/Components/RawMsgModal.js +41 -0
- data/webpack/src/Router/HostReports/ShowPage/Components/ReportLogs/Puppet.js +38 -37
- data/webpack/src/Router/HostReports/ShowPage/Components/ReportLogs/index.js +10 -3
- data/webpack/src/Router/HostReports/ShowPage/Components/ReportLogsFilter/index.js +56 -65
- data/webpack/src/Router/HostReports/ShowPage/ShowPage.js +34 -8
- data/webpack/src/Router/HostReports/constants.js +2 -0
- data/webpack/src/components/ReportsTab/ReportsTable.js +117 -0
- data/webpack/src/components/ReportsTab/helpers.js +155 -0
- data/webpack/src/components/ReportsTab/index.js +132 -0
- metadata +18 -19
- data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +0 -4
@@ -3,6 +3,7 @@
|
|
3
3
|
module Api
|
4
4
|
module V2
|
5
5
|
class HostReportsController < V2::BaseController
|
6
|
+
include Foreman::TelemetryHelper
|
6
7
|
include Api::Version2
|
7
8
|
include Foreman::Controller::CsvResponder
|
8
9
|
include Foreman::Controller::SmartProxyAuth
|
@@ -23,7 +24,7 @@ module Api
|
|
23
24
|
@host_reports = resource_scope_for_index(options)
|
24
25
|
end
|
25
26
|
|
26
|
-
api :GET, '/
|
27
|
+
api :GET, '/host_reports/:id', N_('Show host report details')
|
27
28
|
param :id, :identifier, required: true
|
28
29
|
def show
|
29
30
|
@host_report = resource_scope.find(params[:id])
|
@@ -34,38 +35,55 @@ module Api
|
|
34
35
|
param :host, String, required: true, desc: N_("Hostname of the report's host origin")
|
35
36
|
param :format, HostReport.formats.keys, required: false, desc: N_('Format of the report, e.g. Ansible')
|
36
37
|
param :reported_at, String, required: true, desc: N_('UTC time of the report')
|
37
|
-
param :
|
38
|
-
param :
|
39
|
-
param :
|
40
|
-
param :other, Integer, required: false, desc: N_('Number of other resources or tasks')
|
38
|
+
param :change, Integer, required: false, desc: N_('Summary count of actions with change (semantics is different for each report type)')
|
39
|
+
param :nochange, Integer, required: false, desc: N_('Summary count of actions without change (semantics is different for each report type)')
|
40
|
+
param :failure, Integer, required: false, desc: N_('Summary count of actions with failure (semantics is different for each report type)')
|
41
41
|
param :body, String, required: true, desc: N_('String with JSON formatted body of the report')
|
42
|
-
param :proxy, String, required: false, desc: N_('Hostname of the proxy processed the report')
|
42
|
+
param :proxy, String, required: false, desc: N_('Hostname of the proxy processed the report (will be detected from SSL cert for HTTPS requests)')
|
43
43
|
param :keywords, Array, of: String, required: false, desc: N_('A list of keywords to associate with the report for better searching')
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
api :POST, '/
|
47
|
+
api :POST, '/host_reports/', N_('Create a host report')
|
48
48
|
param_group :host_report, as: :create
|
49
|
-
|
50
49
|
def create
|
50
|
+
result = nil
|
51
|
+
# version is unused at the moment (version = 1)
|
51
52
|
params[:host_report].delete(:version)
|
53
|
+
# check existing host and proxy
|
54
|
+
raise("Unknown host: #{@hostname}") unless params[:host_report][:host_id]
|
55
|
+
# fetch the body
|
52
56
|
the_body = params[:host_report].delete(:body)
|
53
57
|
if the_body && !the_body.is_a?(String)
|
54
58
|
logger.warn "Report body not as a string, serializing JSON"
|
55
59
|
the_body = JSON.pretty_generate(the_body)
|
56
60
|
end
|
61
|
+
# process keywords
|
57
62
|
keywords = params[:host_report].delete(:keywords)
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
63
|
+
report_keyword_ids = []
|
64
|
+
telemetry_duration_histogram(:host_report_create_keywords, :ms) do
|
65
|
+
if keywords.present?
|
66
|
+
keywords_to_insert = keywords.each_with_object([]) do |n, ks|
|
67
|
+
ks << { name: n }
|
68
|
+
end
|
69
|
+
ReportKeyword.upsert_all(keywords_to_insert, unique_by: :name)
|
70
|
+
report_keyword_ids = ReportKeyword.where(name: keywords).distinct.pluck(:id)
|
62
71
|
end
|
63
|
-
ReportKeyword.upsert_all(keywords_to_insert, unique_by: :name)
|
64
|
-
@host_report.report_keyword_ids = ReportKeyword.where(name: keywords).distinct.pluck(:id)
|
65
72
|
end
|
66
|
-
|
67
|
-
@host_report.body
|
73
|
+
# create new record
|
74
|
+
@host_report = HostReport.new(host_report_params.merge(body: the_body, report_keyword_ids: report_keyword_ids))
|
75
|
+
telemetry_duration_histogram(:host_report_create, :ms) do
|
76
|
+
result = @host_report.save
|
77
|
+
end
|
78
|
+
# refresh status and last_report flag
|
79
|
+
telemetry_duration_histogram(:host_report_create_refresh, :ms) do
|
80
|
+
time = Time.parse(params[:host_report][:reported_at]).utc
|
81
|
+
@host.update_attribute(:last_report, time) if @host.last_report.nil? || @host.last_report.utc < time
|
82
|
+
@host.refresh_statuses([HostStatus::HostReportStatus])
|
83
|
+
end
|
68
84
|
process_response result
|
85
|
+
rescue StandardError => e
|
86
|
+
render_exception(e, :status => :unprocessable_entity)
|
69
87
|
end
|
70
88
|
|
71
89
|
api :DELETE, '/host_reports/:id', N_('Delete a host report')
|
@@ -86,10 +104,11 @@ module Api
|
|
86
104
|
private
|
87
105
|
|
88
106
|
def resolve_ids
|
89
|
-
hostname = params[:host_report].delete(:host)
|
90
|
-
proxyname = params[:host_report].delete(:proxy)
|
91
|
-
|
92
|
-
params[:host_report][:
|
107
|
+
@hostname = params[:host_report].delete(:host)
|
108
|
+
@proxyname = params[:host_report].delete(:proxy)
|
109
|
+
@host = Host.find_by(name: @hostname)
|
110
|
+
params[:host_report][:host_id] ||= @host&.id
|
111
|
+
params[:host_report][:proxy_id] = detected_proxy&.id # provided by SmartProxyAuth concern
|
93
112
|
end
|
94
113
|
|
95
114
|
def resource_scope(options = {})
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ForemanHostReports
|
2
|
+
module Controller
|
3
|
+
module HostsControllerExtensions
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module Overrides
|
7
|
+
def preload_reports
|
8
|
+
@last_report_ids = HostReport.where(:host_id => @hosts.map(&:id)).reorder('').group(:host_id).maximum(:id)
|
9
|
+
@last_reports = HostReport.where(:id => @last_report_ids.values)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
included do
|
14
|
+
prepend Overrides
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -11,7 +11,7 @@ module ForemanHostReports
|
|
11
11
|
Foreman::ParameterFilter.new(::HostReport).tap do |filter|
|
12
12
|
# body is permitted in controller
|
13
13
|
filter.permit :format, :version, :host, :proxy, :reported_at,
|
14
|
-
:proxy_id, :host_id, :
|
14
|
+
:proxy_id, :host_id, :change, :nochange, :failure
|
15
15
|
filter.permit :keywords => []
|
16
16
|
end
|
17
17
|
end
|
@@ -2,6 +2,28 @@
|
|
2
2
|
|
3
3
|
class HostReportsController < ::ApplicationController
|
4
4
|
include Foreman::Controller::AutoCompleteSearch
|
5
|
+
def index
|
6
|
+
respond_to do |format|
|
7
|
+
format.html do
|
8
|
+
render '/react/index'
|
9
|
+
end
|
10
|
+
|
11
|
+
format.json do
|
12
|
+
reports = resource_base_search_and_page
|
13
|
+
render json: {
|
14
|
+
itemCount: reports.count,
|
15
|
+
reports: reports.map do |r|
|
16
|
+
r.attributes.except('body').merge(
|
17
|
+
keywords: r.report_keywords.map(&:name),
|
18
|
+
can_delete: can_delete?(r),
|
19
|
+
can_view: can_view?(r),
|
20
|
+
status: r.status
|
21
|
+
)
|
22
|
+
end,
|
23
|
+
}, status: :ok
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
5
27
|
|
6
28
|
def show
|
7
29
|
@host_report = resource_scope.find(params[:id])
|
@@ -29,8 +51,8 @@ class HostReportsController < ::ApplicationController
|
|
29
51
|
reported_at: @host_report.reported_at,
|
30
52
|
},
|
31
53
|
permissions: {
|
32
|
-
can_delete:
|
33
|
-
can_view:
|
54
|
+
can_delete: can_delete?(@host_report),
|
55
|
+
can_view: can_view?(@host_report),
|
34
56
|
},
|
35
57
|
}, status: :ok
|
36
58
|
end
|
@@ -43,4 +65,12 @@ class HostReportsController < ::ApplicationController
|
|
43
65
|
options[:permission] = :view_host_reports
|
44
66
|
super(options).my_reports
|
45
67
|
end
|
68
|
+
|
69
|
+
def can_delete?(report)
|
70
|
+
authorized_for(auth_object: report, authorizer: authorizer, permission: "destroy_#{controller_permission}")
|
71
|
+
end
|
72
|
+
|
73
|
+
def can_view?(report)
|
74
|
+
authorized_for(auth_object: report, authorizer: authorizer, permission: "view_#{controller_permission}")
|
75
|
+
end
|
46
76
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ForemanHostReports
|
2
|
+
module HostsHelperExtensions
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module Overrides
|
6
|
+
def last_report_column(record)
|
7
|
+
opts = { :rel => "twipsy" }
|
8
|
+
date = record.last_report.nil? ? '' : "#{date_time_absolute_value(record.last_report)}, "
|
9
|
+
time = record.last_report? ? date_time_relative_value(record.last_report) : ""
|
10
|
+
if @last_report_ids[record.id]
|
11
|
+
opts["data-original-title"] = date + _("view last report details")
|
12
|
+
link_to_if_authorized(time, hash_for_host_report_path(:id => record.last_host_report_object_any_format&.id), opts)
|
13
|
+
else
|
14
|
+
opts.merge!(:disabled => true, :class => "disabled", :onclick => 'return false')
|
15
|
+
opts["data-original-title"] = date + _("report already deleted") unless record.last_report.nil?
|
16
|
+
link_to_if_authorized(time, hash_for_host_reports_path, opts)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
included do
|
22
|
+
prepend Overrides
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -4,6 +4,12 @@ module ForemanHostReports
|
|
4
4
|
|
5
5
|
included do
|
6
6
|
has_many :host_reports, foreign_key: :host_id, class_name: 'HostReport', inverse_of: :host, dependent: :destroy
|
7
|
+
has_one :last_host_report_object_any_format, -> { order("#{HostReport.table_name}.reported_at DESC, #{HostReport.table_name}.id").limit(1) }, foreign_key: :host_id, class_name: 'HostReport', inverse_of: :host, dependent: :delete
|
8
|
+
has_one :host_report_status_object, class_name: 'HostStatus::HostReportStatus', foreign_key: :host_id, inverse_of: :host, dependent: :delete
|
9
|
+
|
10
|
+
scoped_search relation: :host_reports, on: :change, rename: :report_changes, only_explicit: true
|
11
|
+
scoped_search relation: :host_reports, on: :nochange, rename: :report_nochanges, only_explicit: true
|
12
|
+
scoped_search relation: :host_reports, on: :failure, rename: :report_failures, only_explicit: true
|
7
13
|
end
|
8
14
|
end
|
9
15
|
end
|
data/app/models/host_report.rb
CHANGED
@@ -24,6 +24,9 @@ class HostReport < ApplicationRecord
|
|
24
24
|
scoped_search relation: :proxy, on: :name, complete_value: true, rename: :proxy
|
25
25
|
scoped_search relation: :organization, on: :name, complete_value: true, rename: :organization
|
26
26
|
scoped_search relation: :location, on: :name, complete_value: true, rename: :location
|
27
|
+
scoped_search on: :change, aliases: %i[changed changes]
|
28
|
+
scoped_search on: :nochange, aliases: %i[unchanged nochanges]
|
29
|
+
scoped_search on: :failure, aliases: %i[failed failures]
|
27
30
|
scoped_search on: :reported_at, complete_value: true, default_order: :desc, rename: :reported, only_explicit: true, aliases: %i[last_report reported_at]
|
28
31
|
scoped_search on: :format, complete_value: { plain: 0, puppet: 1, ansible: 2 }
|
29
32
|
# This is to simulate has_many :report_keywords relation for scoped_search library to work
|
@@ -52,4 +55,16 @@ class HostReport < ApplicationRecord
|
|
52
55
|
conditions: sanitize_sql_for_conditions(["host_reports.report_keyword_ids @> ?", "{#{keyword_ids.join(',')}}"]),
|
53
56
|
}
|
54
57
|
end
|
58
|
+
|
59
|
+
def status
|
60
|
+
if failure&.positive?
|
61
|
+
:failure
|
62
|
+
elsif change&.positive?
|
63
|
+
:change
|
64
|
+
elsif nochange&.positive?
|
65
|
+
:nochange
|
66
|
+
else
|
67
|
+
:empty
|
68
|
+
end
|
69
|
+
end
|
55
70
|
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
module HostStatus
|
2
|
+
# rubocop:disable Style/GuardClause
|
3
|
+
class HostReportStatus < Status
|
4
|
+
def last_report
|
5
|
+
self.last_report = host.last_host_report_object_any_format unless @last_report_set
|
6
|
+
@last_report
|
7
|
+
end
|
8
|
+
|
9
|
+
def last_report=(report)
|
10
|
+
@last_report_set = true
|
11
|
+
@last_report = report
|
12
|
+
end
|
13
|
+
|
14
|
+
# <host report fields>
|
15
|
+
def change
|
16
|
+
last_report&.change || 0
|
17
|
+
end
|
18
|
+
|
19
|
+
def nochange
|
20
|
+
last_report&.nochange || 0
|
21
|
+
end
|
22
|
+
|
23
|
+
def failure
|
24
|
+
last_report&.failure || 0
|
25
|
+
end
|
26
|
+
|
27
|
+
def change?
|
28
|
+
change.positive?
|
29
|
+
end
|
30
|
+
|
31
|
+
def nochange?
|
32
|
+
nochange.positive?
|
33
|
+
end
|
34
|
+
|
35
|
+
def failure?
|
36
|
+
failure.positive?
|
37
|
+
end
|
38
|
+
# </host report fields>
|
39
|
+
|
40
|
+
# <legacy report compatibility fields>
|
41
|
+
def restarted
|
42
|
+
0
|
43
|
+
end
|
44
|
+
|
45
|
+
def failed_restarts
|
46
|
+
0
|
47
|
+
end
|
48
|
+
|
49
|
+
def skipped
|
50
|
+
0
|
51
|
+
end
|
52
|
+
# </legacy report compatibility fields>
|
53
|
+
|
54
|
+
def expected_report_interval
|
55
|
+
(reported_format_interval.presence || default_report_interval).to_i.minutes
|
56
|
+
end
|
57
|
+
|
58
|
+
def reported_format_interval
|
59
|
+
if host.params.key? "#{last_report.format.downcase}_interval"
|
60
|
+
host.params["#{last_report.format.downcase}_interval"]
|
61
|
+
else
|
62
|
+
Setting[:"#{last_report.format.downcase}_interval"]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def out_of_sync?
|
67
|
+
if (host && !host.enabled?) || no_reports? || out_of_sync_disabled?
|
68
|
+
false
|
69
|
+
else
|
70
|
+
!reported_at.nil? && reported_at < (Time.now.utc - expected_report_interval)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def no_reports?
|
75
|
+
host && last_report.nil?
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.status_name
|
79
|
+
N_("Configuration")
|
80
|
+
end
|
81
|
+
|
82
|
+
# Constants are bit-mask friendly in case we want to query them in the DB
|
83
|
+
UNKNOWN = -0b000000000000010000000000000000 # -65536
|
84
|
+
FAILURES = -0b000000000000000000000000000001 # -1
|
85
|
+
EMPTY = 0b000000000000000000000000000000 # 0
|
86
|
+
NO_CHANGES = 0b000000000000000000000100000000 # 256
|
87
|
+
CHANGES = 0b000000000000010000000000000000 # 65536
|
88
|
+
|
89
|
+
LABELS = {
|
90
|
+
FAILURES => N_("Failure(s)"),
|
91
|
+
EMPTY => N_("Empty"),
|
92
|
+
NO_CHANGES => N_("No changes"),
|
93
|
+
CHANGES => N_("Changes applied"),
|
94
|
+
}.freeze
|
95
|
+
|
96
|
+
def to_label(_options = {})
|
97
|
+
if host && !host.enabled
|
98
|
+
return N_("Alerts disabled")
|
99
|
+
elsif out_of_sync?
|
100
|
+
return N_("Out of sync")
|
101
|
+
end
|
102
|
+
|
103
|
+
LABELS.fetch(to_status, N_("Unknown config status"))
|
104
|
+
end
|
105
|
+
|
106
|
+
def to_global(options = {})
|
107
|
+
handle_options(options)
|
108
|
+
|
109
|
+
if failure?
|
110
|
+
HostStatus::Global::ERROR
|
111
|
+
elsif out_of_sync?
|
112
|
+
HostStatus::Global::WARN
|
113
|
+
elsif no_reports? && (host.configuration? || Setting[:always_show_configuration_status])
|
114
|
+
HostStatus::Global::WARN
|
115
|
+
else
|
116
|
+
HostStatus::Global::OK
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def to_status(options = {})
|
121
|
+
handle_options(options)
|
122
|
+
|
123
|
+
if host&.enabled && last_report.present?
|
124
|
+
if last_report.failure.positive?
|
125
|
+
FAILURES
|
126
|
+
elsif last_report.change.positive?
|
127
|
+
CHANGES
|
128
|
+
elsif last_report.nochange.positive?
|
129
|
+
NO_CHANGES
|
130
|
+
else
|
131
|
+
EMPTY
|
132
|
+
end
|
133
|
+
else
|
134
|
+
UNKNOWN
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def relevant?(options = {})
|
139
|
+
handle_options(options)
|
140
|
+
|
141
|
+
host.configuration? || last_report.present? || Setting[:always_show_configuration_status]
|
142
|
+
end
|
143
|
+
|
144
|
+
def status_link
|
145
|
+
return @status_link if defined?(@status_link)
|
146
|
+
return @status_link = nil if last_report.nil?
|
147
|
+
return @status_link = nil unless User.current.can?(:view_host_reports, last_report, false)
|
148
|
+
|
149
|
+
@status_link = last_report && Rails.application.routes.url_helpers.host_report_path(last_report)
|
150
|
+
end
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
# Configuration status can be calculated from database state, but also reports can be
|
155
|
+
# passed in via options. In that case, report is matched with the host and set.
|
156
|
+
# Don't ask me why this is implemented this way, this is copy-paste from the original
|
157
|
+
# ConfigurationStatus in Foreman core.
|
158
|
+
def handle_options(options)
|
159
|
+
if options.key?(:last_reports) && !options[:last_reports].nil?
|
160
|
+
cached_report = options[:last_reports].find { |r| r.host_id == host_id }
|
161
|
+
self.last_report = cached_report
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def update_timestamp
|
166
|
+
self.reported_at = last_report.try(:reported_at) || Time.now.utc
|
167
|
+
end
|
168
|
+
|
169
|
+
def default_report_interval
|
170
|
+
if host.params.key? 'outofsync_interval'
|
171
|
+
host.params['outofsync_interval']
|
172
|
+
else
|
173
|
+
Setting[:outofsync_interval]
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def out_of_sync_disabled?
|
178
|
+
Setting[:"#{last_report.format.downcase}_out_of_sync_disabled"]
|
179
|
+
end
|
180
|
+
end
|
181
|
+
# rubocop:enable Style/GuardClause
|
182
|
+
end
|
183
|
+
|
184
|
+
HostStatus.status_registry.delete(HostStatus::ConfigurationStatus)
|
185
|
+
HostStatus.status_registry.add(HostStatus::HostReportStatus)
|
@@ -5,8 +5,7 @@ object @host_report
|
|
5
5
|
extends 'api/v2/host_reports/base'
|
6
6
|
extends 'api/v2/layouts/permissions'
|
7
7
|
|
8
|
-
attributes :format, :host_id, :proxy_id, :reported_at, :
|
9
|
-
:pending, :other
|
8
|
+
attributes :format, :host_id, :proxy_id, :reported_at, :change, :nochange, :failure
|
10
9
|
|
11
10
|
node(:host_name) do |report|
|
12
11
|
report.host.name
|
data/config/routes.rb
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
Rails.application.routes.draw do
|
2
|
-
match '/host_reports' => 'react#index', via: :get
|
3
|
-
|
4
2
|
resources :hosts do
|
5
3
|
member do
|
6
4
|
match 'host_reports', to: 'react#index', via: :get
|
7
5
|
end
|
8
6
|
end
|
9
7
|
|
10
|
-
resources :host_reports, only: %i[show] do
|
8
|
+
resources :host_reports, only: %i[index show] do
|
11
9
|
collection do
|
12
10
|
get 'auto_complete_search'
|
13
11
|
end
|
@@ -15,7 +13,7 @@ Rails.application.routes.draw do
|
|
15
13
|
|
16
14
|
namespace :api, defaults: { format: 'json' } do
|
17
15
|
scope '(:apiv)', module: :v2, defaults: { apiv: 'v2' }, apiv: /v2/,
|
18
|
-
|
16
|
+
constraints: ApiConstraints.new(version: 2, default: true) do
|
19
17
|
resources :host_reports, only: %i[index show create destroy] do
|
20
18
|
collection do
|
21
19
|
get 'export'
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class RenameStatusSummaries < ActiveRecord::Migration[6.0]
|
2
|
+
def change
|
3
|
+
remove_column :host_reports, :applied, :integer
|
4
|
+
remove_column :host_reports, :pending, :integer
|
5
|
+
remove_column :host_reports, :other, :integer
|
6
|
+
remove_column :host_reports, :failed, :integer
|
7
|
+
|
8
|
+
add_column :host_reports, :change, :integer, default: 0
|
9
|
+
add_column :host_reports, :nochange, :integer, default: 0
|
10
|
+
add_column :host_reports, :failure, :integer, default: 0
|
11
|
+
end
|
12
|
+
end
|
@@ -18,7 +18,7 @@ module ForemanHostReports
|
|
18
18
|
|
19
19
|
initializer 'foreman_host_reports.register_plugin', :before => :finisher_hook do |_app|
|
20
20
|
Foreman::Plugin.register :foreman_host_reports do
|
21
|
-
requires_foreman '>= 3.
|
21
|
+
requires_foreman '>= 3.2.0'
|
22
22
|
|
23
23
|
apipie_documented_controllers ["#{ForemanHostReports::Engine.root}/app/controllers/api/v2/*.rb"]
|
24
24
|
# Add Global files for extending foreman-core components and routes
|
@@ -36,10 +36,14 @@ module ForemanHostReports
|
|
36
36
|
|
37
37
|
# add menu entry
|
38
38
|
menu :top_menu, :host_reports, url: '/host_reports',
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
url_hash: { controller: :host_reports, action: :index },
|
40
|
+
caption: N_('Host Reports'),
|
41
|
+
parent: :monitor_menu,
|
42
|
+
before: :reports
|
43
|
+
|
44
|
+
add_histogram_telemetry(:host_report_create_keywords, 'Time spent processing keywords (ms)')
|
45
|
+
add_histogram_telemetry(:host_report_create_refresh, 'Time spent processing status refresh (ms)')
|
46
|
+
add_histogram_telemetry(:host_report_create, 'Time spent saving record (ms)')
|
43
47
|
end
|
44
48
|
end
|
45
49
|
|
@@ -48,6 +52,8 @@ module ForemanHostReports
|
|
48
52
|
config.to_prepare do
|
49
53
|
Host::Managed.include ForemanHostReports::HostExtensions
|
50
54
|
SmartProxy.include ForemanHostReports::HostExtensions
|
55
|
+
::HostsController.include ForemanHostReports::Controller::HostsControllerExtensions
|
56
|
+
::HostsHelper.include ForemanHostReports::HostsHelperExtensions
|
51
57
|
rescue => e
|
52
58
|
Rails.logger.warn "ForemanHostReports: skipping engine hook (#{e})"
|
53
59
|
end
|