foreman_monitoring 0.1.2 → 2.1.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +16 -7
  3. data/Rakefile +0 -0
  4. data/app/controllers/api/v2/downtime_controller.rb +63 -0
  5. data/app/controllers/api/v2/monitoring_results_controller.rb +5 -4
  6. data/app/controllers/concerns/foreman_monitoring/find_host_by_client_cert.rb +60 -0
  7. data/app/controllers/concerns/foreman_monitoring/hosts_controller_extensions.rb +21 -20
  8. data/app/helpers/concerns/foreman_monitoring/hosts_helper_ext.rb +16 -19
  9. data/app/lib/proxy_api/monitoring.rb +9 -6
  10. data/app/models/concerns/foreman_monitoring/host_extensions.rb +15 -14
  11. data/app/models/concerns/foreman_monitoring/hostgroup_extensions.rb +7 -3
  12. data/app/models/concerns/orchestration/monitoring.rb +22 -15
  13. data/app/models/host_status/monitoring_status.rb +7 -4
  14. data/app/models/monitoring_result.rb +13 -6
  15. data/app/models/setting/monitoring.rb +4 -2
  16. data/app/overrides/add_host_monitoring_result_tab.rb +8 -6
  17. data/app/overrides/add_host_multiple_power_set_downtime_checkbox.rb +5 -3
  18. data/app/overrides/add_host_set_downtime_modal.rb +4 -2
  19. data/app/services/monitoring.rb +3 -0
  20. data/app/views/hosts/_downtime_fields.html.erb +2 -2
  21. data/app/views/monitoring_results/_host_tab_pane.html.erb +2 -2
  22. data/config/routes.rb +3 -0
  23. data/db/migrate/20160817135723_create_monitoring_results.rb +5 -1
  24. data/db/migrate/20161220201510_add_monitoring_proxy_id_to_host_and_hostgroup.rb +3 -1
  25. data/db/migrate/201910180900_rename_downtime_host_permission.rb +15 -0
  26. data/db/seeds.d/60-monitoring_proxy_feature.rb +2 -0
  27. data/lib/foreman_monitoring.rb +2 -0
  28. data/lib/foreman_monitoring/engine.rb +32 -28
  29. data/lib/foreman_monitoring/version.rb +3 -1
  30. data/lib/tasks/foreman_monitoring_tasks.rake +5 -5
  31. data/locale/gemspec.rb +2 -0
  32. data/test/controllers/api/v2/downtime_controller_test.rb +73 -0
  33. data/test/factories/feature.rb +4 -2
  34. data/test/factories/host.rb +6 -4
  35. data/test/factories/monitoring_results.rb +9 -7
  36. data/test/factories/smart_proxy.rb +3 -1
  37. data/test/functional/hosts_controller_test.rb +65 -52
  38. data/test/lib/proxy_api/monitoring_test.rb +16 -14
  39. data/test/test_plugin_helper.rb +5 -3
  40. data/test/unit/host_status/monitoring_status_test.rb +18 -16
  41. data/test/unit/host_test.rb +6 -4
  42. data/test/unit/monitoring_result_test.rb +75 -0
  43. data/test/unit/monitoring_test.rb +5 -3
  44. metadata +62 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f742aa658a66234e28555d6dbba4beca116e6ba3d49db3c02898bd7cc295a5d9
4
- data.tar.gz: f11b41bb8dc37e78431df10c3fc255f7680039293e7e0c9ff0268a4c975d49ef
3
+ metadata.gz: 6bc195afe4c0af30313894eaf37dcf99c36625fe510998783df94932111c9891
4
+ data.tar.gz: 8d37c47d99c8d48163242ce490159c59a6a4e6c2588709daac0bac841a450c5a
5
5
  SHA512:
6
- metadata.gz: f7dbdfc58ea1b7669eefff4b603ccc4f813b87a3aadbb4cd4a48ad86de3899403b440709d1b2a1f9145dc5b4b4487875ad0a33de031142d70e47d139278043d1
7
- data.tar.gz: 39f27d2331c23bd24392d1abcaa47dc4ec9757463a27503518d501581ba2b276acc2528fa58b2e76f632f58ac00cb91801060d09a821a9853e0754ced75342dc
6
+ metadata.gz: cf715511ef2835a64702b2f865c6380c178dd8c70b2038428ea3a0c9a72fefcef4715ec4c2bcca82fbf687c9ea5a463c5e041009fe7e795cb6aab6484020d6f3
7
+ data.tar.gz: 8c4c4cbaad0dffa2f7d338d19e116cc58c05272b262d36d5bf221137391577a414dcd3ba83c34d78c46207bf8298675529a988d42fd736961751687325b615b1
data/README.md CHANGED
@@ -17,7 +17,7 @@ The gem name is `foreman_monitoring`.
17
17
 
18
18
  RPM users can install the `tfm-rubygem-foreman_monitoring` package.
19
19
 
20
- Deb users can install the `ruby-foreman_monitoring` package.
20
+ Deb users can install the `ruby-foreman-monitoring` package.
21
21
 
22
22
  If using the gem as installation source database enhancement and service restart must
23
23
  be done manually.
@@ -28,6 +28,15 @@ foreman-rake db:seed
28
28
  touch ~foreman/tmp/restart.txt
29
29
  ```
30
30
 
31
+ ## Compatibility
32
+
33
+ | Foreman Version | Plugin Version |
34
+ | --------------- | --------------:|
35
+ | >= 1.15 | ~> 0.1 |
36
+ | >= 1.17 | ~> 1.0 |
37
+ | >= 2.0 | ~> 2.0 |
38
+ | >= 2.2 | ~> 2.1 |
39
+
31
40
  # Usage
32
41
 
33
42
  For managing a host in the monitoring solution a Smart Proxy providing
@@ -35,15 +44,15 @@ the `monitoring` feature has to be assigned. This can be done during
35
44
  provisioning or as a bulk action from the host overview.
36
45
 
37
46
  You can configure the default action which will be done during host
38
- provisioning and deprovisioning. Provisioning allows to create a monitoring
39
- object or take no action while deprovisioing allows to delete the monitoring
40
- object, set a downtime or take no action. For rebuild it will by default
47
+ provisioning and de-provisioning. Provisioning allows to create a monitoring
48
+ object or take no action while de-provisoning allows deleting the monitoring
49
+ object, set a downtime or take no action. For rebuild, it will by default
41
50
  set a downtime.
42
51
 
43
52
  The plugin will show you the monitoring status as a sub-status and a detail
44
53
  panel. You can configure if the sub-status should affect the global status.
45
54
 
46
- Furthermore it allows to individually set a downtime at the host detail view
55
+ Furthermore, it allows to individually set a downtime at the host detail view
47
56
  or as a bulk action from the host overview.
48
57
 
49
58
  # Troubleshooting
@@ -51,8 +60,8 @@ or as a bulk action from the host overview.
51
60
  Logging entries relevant to the plug-in will be located in the Foreman's log
52
61
  which is by default `/var/log/foreman/production.log`.
53
62
 
54
- Also check the troubleshooting section of the Smart Proxy plug-in if problems
55
- occure in the underlying communication.
63
+ Also, check the troubleshooting section of the Smart Proxy plug-in if problems
64
+ occur in the underlying communication.
56
65
 
57
66
  ## Contributing
58
67
 
data/Rakefile CHANGED
File without changes
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Api
4
+ module V2
5
+ class DowntimeController < V2::BaseController
6
+ include Api::Version2
7
+ include ::ForemanMonitoring::FindHostByClientCert
8
+
9
+ authorize_host_by_client_cert %i[create]
10
+ before_action :find_host, :only => [:create]
11
+
12
+ api :POST, '/downtime', N_('Schedule host downtime')
13
+ param :duration, :number, :desc => N_('Downtime duration (seconds)'), :required => false
14
+ param :reason, String, :desc => N_('Downtime reason'), :required => false
15
+
16
+ def create
17
+ begin
18
+ options = {
19
+ :comment => downtime_params[:reason] || _('Host requested downtime')
20
+ }
21
+ if downtime_params.key? :duration
22
+ options[:start_time] = Time.now.to_i
23
+ options[:end_time] = Time.now.to_i + downtime_params[:duration].to_i
24
+ end
25
+ @host.downtime_host(options)
26
+ rescue StandardError => e
27
+ Foreman::Logging.exception('Failed to request downtime', e)
28
+ render :json => { 'message' => e.message }, :status => :unprocessable_entity
29
+ return
30
+ end
31
+
32
+ render :json => { 'message' => 'OK' }
33
+ end
34
+
35
+ private
36
+
37
+ def downtime_params
38
+ params.permit(:duration, :reason)
39
+ end
40
+
41
+ def find_host
42
+ @host = detected_host
43
+
44
+ return true if @host
45
+
46
+ logger.info 'Denying access because no host could be detected.'
47
+ if User.current
48
+ render_error 'access_denied',
49
+ :status => :forbidden,
50
+ :locals => {
51
+ :details => 'You need to authenticate with a valid client cert. The DN has to match a known host.'
52
+ }
53
+ else
54
+ render_error 'unauthorized',
55
+ :status => :unauthorized,
56
+ :locals => {
57
+ :user_login => get_client_cert_hostname
58
+ }
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Api
2
4
  module V2
3
5
  class MonitoringResultsController < V2::BaseController
@@ -17,10 +19,9 @@ module Api
17
19
 
18
20
  def create
19
21
  begin
20
- MonitoringResult.import(monitoring_result_params.with_indifferent_access)
21
- rescue => e
22
- logger.error "Failed to import monitoring result: #{e.message}"
23
- logger.debug e.backtrace.join("\n")
22
+ MonitoringResult.import(monitoring_result_params.to_h.with_indifferent_access)
23
+ rescue StandardError => e
24
+ Foreman::Logging.exception('Failed to import monitoring result', e)
24
25
  render :json => { 'message' => e.message }, :status => :unprocessable_entity
25
26
  return
26
27
  end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanMonitoring
4
+ module FindHostByClientCert
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ def authorize_host_by_client_cert(actions, _options = {})
9
+ skip_before_action :require_login, :only => actions, :raise => false
10
+ skip_before_action :check_user_enabled, :only => actions, :raise => false
11
+ skip_before_action :authorize, :only => actions
12
+ skip_before_action :verify_authenticity_token, :only => actions
13
+ skip_before_action :set_taxonomy, :only => actions, :raise => false
14
+ skip_before_action :session_expiry, :update_activity_time, :only => actions
15
+ before_action(:only => actions) { require_client_cert_or_login }
16
+ attr_reader :detected_host
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ # Permits Hosts authorized by their client cert
23
+ # or a user with permission
24
+ def require_client_cert_or_login
25
+ @detected_host = find_host_by_client_cert
26
+
27
+ if detected_host
28
+ set_admin_user
29
+ return true
30
+ end
31
+
32
+ require_login
33
+ unless User.current
34
+ render_error 'unauthorized', :status => :unauthorized unless performed? && api_request?
35
+ return false
36
+ end
37
+ authorize
38
+ end
39
+
40
+ def find_host_by_client_cert
41
+ hostname = get_client_cert_hostname
42
+
43
+ return unless hostname
44
+
45
+ host ||= Host::Base.find_by(certname: hostname) ||
46
+ Host::Base.find_by(name: hostname)
47
+ logger.info { "Found Host #{host} by client cert #{hostname}" } if host
48
+ host
49
+ end
50
+
51
+ def get_client_cert_hostname
52
+ client_certificate = Foreman::ClientCertificate.new(request: request)
53
+ return unless client_certificate.verified?
54
+
55
+ hostname = client_certificate.subject
56
+ logger.debug "Extracted hostname '#{hostname}' from client certificate." if hostname
57
+ hostname
58
+ end
59
+ end
60
+ end
@@ -1,18 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ForemanMonitoring
2
4
  module HostsControllerExtensions
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- before_action :find_resource_with_monitoring, :only => [:downtime]
7
- before_action :find_multiple_with_monitoring, :only => %i[select_multiple_downtime update_multiple_downtime
8
- select_multiple_monitoring_proxy update_multiple_monitoring_proxy]
9
- before_action :validate_host_downtime_params, :only => [:downtime]
10
- before_action :validate_hosts_downtime_params, :only => [:update_multiple_downtime]
11
- before_action :validate_multiple_monitoring_proxy, :only => :update_multiple_monitoring_proxy
12
-
13
- alias_method :find_resource_with_monitoring, :find_resource
14
- alias_method :find_multiple_with_monitoring, :find_multiple
15
- alias_method_chain :update_multiple_power_state, :monitoring
5
+ def self.prepended(base)
6
+ base.class_eval do
7
+ before_action :find_resource_with_monitoring, :only => [:downtime]
8
+ before_action :find_multiple_with_monitoring, :only => %i[select_multiple_downtime update_multiple_downtime
9
+ select_multiple_monitoring_proxy update_multiple_monitoring_proxy]
10
+ before_action :validate_host_downtime_params, :only => [:downtime]
11
+ before_action :validate_hosts_downtime_params, :only => [:update_multiple_downtime]
12
+ before_action :validate_multiple_monitoring_proxy, :only => :update_multiple_monitoring_proxy
13
+
14
+ alias_method :find_resource_with_monitoring, :find_resource
15
+ alias_method :find_multiple_with_monitoring, :find_multiple
16
+ end
16
17
  end
17
18
 
18
19
  def downtime
@@ -39,14 +40,14 @@ module ForemanMonitoring
39
40
  failed_hosts[host.name] = error_message
40
41
  logger.error "Failed to set a host downtime for #{host}: #{error_message}"
41
42
  end
42
- rescue => error
43
- failed_hosts[host.name] = error
44
- Foreman::Logging.exception(_('Failed to set a host downtime for %s.') % host, error)
43
+ rescue StandardError => e
44
+ failed_hosts[host.name] = e
45
+ Foreman::Logging.exception(_('Failed to set a host downtime for %s.') % host, e)
45
46
  end
46
47
  end
47
48
 
48
49
  if failed_hosts.empty?
49
- notice _('A downtime was set for the selected hosts.')
50
+ success _('A downtime was set for the selected hosts.')
50
51
  else
51
52
  error n_('A downtime clould not be set for host: %s.',
52
53
  'A downtime could not be set for hosts: %s.',
@@ -65,7 +66,7 @@ module ForemanMonitoring
65
66
  update_multiple_proxy(_('Monitoring'), :monitoring_proxy=)
66
67
  end
67
68
 
68
- def update_multiple_power_state_with_monitoring
69
+ def update_multiple_power_state
69
70
  options = {
70
71
  :comment => 'Power state changed in Foreman',
71
72
  :author => "Foreman User #{User.current}",
@@ -86,7 +87,7 @@ module ForemanMonitoring
86
87
  end
87
88
  end
88
89
  end
89
- update_multiple_power_state_without_monitoring
90
+ super
90
91
  end
91
92
 
92
93
  private
@@ -129,7 +130,7 @@ module ForemanMonitoring
129
130
  def action_permission
130
131
  case params[:action]
131
132
  when 'downtime', 'select_multiple_downtime', 'update_multiple_downtime'
132
- :downtime
133
+ :manage_downtime
133
134
  when 'select_multiple_monitoring_proxy', 'update_multiple_monitoring_proxy'
134
135
  :edit
135
136
  else
@@ -1,33 +1,30 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ForemanMonitoring
2
4
  module HostsHelperExt
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- alias_method_chain :host_title_actions, :monitoring
7
- alias_method_chain :multiple_actions, :monitoring
8
- end
9
-
10
- def multiple_actions_with_monitoring
11
- return multiple_actions_without_monitoring unless authorized_for(:controller => :hosts, :action => :select_multiple_downtime)
12
- multiple_actions_without_monitoring + [[_('Set downtime'), select_multiple_downtime_hosts_path], [_('Change Monitoring Proxy'), select_multiple_monitoring_proxy_hosts_path]]
5
+ def multiple_actions
6
+ actions = super
7
+ actions << [_('Set downtime'), select_multiple_downtime_hosts_path] if authorized_for(:controller => :hosts, :action => :select_multiple_downtime)
8
+ actions << [_('Change Monitoring Proxy'), select_multiple_monitoring_proxy_hosts_path] if authorized_for(:controller => :hosts, :action => :select_multiple_monitoring_proxy)
9
+ actions
13
10
  end
14
11
 
15
- def host_title_actions_with_monitoring(host)
12
+ def host_title_actions(host)
16
13
  title_actions(
17
14
  button_group(
18
15
  display_link_if_authorized(_('Downtime'),
19
16
  hash_for_host_path(:id => host).merge(:auth_object => host,
20
- :permission => :manage_host_downtimes,
17
+ :permission => :manage_downtime_hosts,
21
18
  :anchor => 'set_host_downtime'),
22
19
  :class => 'btn btn-default',
23
20
  :disabled => !host.monitored?,
24
- :title => _('Set a downtime for this host'),
25
- :id => 'host-downtime',
26
- :data => { :toggle => 'modal',
27
- :target => '#set_host_downtime' })
21
+ :title => _('Set a downtime for this host'),
22
+ :id => 'host-downtime',
23
+ :data => { :toggle => 'modal',
24
+ :target => '#set_host_downtime' })
28
25
  )
29
26
  )
30
- host_title_actions_without_monitoring(host)
27
+ super
31
28
  end
32
29
 
33
30
  def host_monitoring_result_icon_class(result)
@@ -58,10 +55,10 @@ module ForemanMonitoring
58
55
  end
59
56
  end
60
57
 
61
- def datetime_f(f, attr, options = {})
58
+ def monitoring_datetime_f(f, attr, options = {})
62
59
  field(f, attr, options) do
63
60
  addClass options, 'form-control'
64
- f.datetime_local_field attr, options
61
+ f.datetime_field attr, options
65
62
  end
66
63
  end
67
64
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ProxyAPI
2
4
  class Monitoring < ProxyAPI::Resource
3
5
  def initialize(args)
@@ -7,34 +9,35 @@ module ProxyAPI
7
9
 
8
10
  def create_host_downtime(host, args = {})
9
11
  parse(post(args, "downtime/host/#{host}"))
10
- rescue => e
12
+ rescue StandardError => e
11
13
  raise ProxyException.new(url, e, N_('Unable to set downtime for %s') % host)
12
14
  end
13
15
 
14
16
  def remove_host_downtime(host, args = {})
15
17
  parse(delete("downtime/host/#{host}?#{args.to_query}"))
16
- rescue => e
18
+ rescue StandardError => e
17
19
  raise ProxyException.new(url, e, N_('Unable to remove downtime for %s') % host)
18
20
  end
19
21
 
20
22
  def create_host(host, attributes = {})
21
23
  parse(put({ :attributes => attributes }, "host/#{host}"))
22
- rescue => e
24
+ rescue StandardError => e
23
25
  raise ProxyException.new(url, e, N_('Unable to create monitoring host object for %s') % host)
24
26
  end
25
27
 
26
28
  def update_host(host, attributes = {})
27
29
  parse(post({ :attributes => attributes }, "host/#{host}"))
28
- rescue => e
30
+ rescue StandardError => e
29
31
  raise ProxyException.new(url, e, N_('Unable to update monitoring host object for %s') % host)
30
32
  end
31
33
 
32
34
  def delete_host(host)
33
35
  raise Foreman::Exception, 'Missing hostname.' if host.blank?
36
+
34
37
  parse(delete("host/#{host}"))
35
38
  rescue RestClient::ResourceNotFound
36
39
  true
37
- rescue => e
40
+ rescue StandardError => e
38
41
  raise ProxyException.new(url, e, N_('Unable to delete monitoring host object for %s') % host)
39
42
  end
40
43
 
@@ -42,7 +45,7 @@ module ProxyAPI
42
45
  parse(get("host/#{host}"))
43
46
  rescue RestClient::ResourceNotFound
44
47
  nil
45
- rescue => e
48
+ rescue StandardError => e
46
49
  raise ProxyException.new(url, e, N_('Unable to query monitoring host object for %{host}: %{message}') % { :host => host, :message => e.try(:response) || e.try(:message) })
47
50
  end
48
51
  end
@@ -1,15 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ForemanMonitoring
2
4
  module HostExtensions
3
- extend ActiveSupport::Concern
4
- included do
5
- include Orchestration::Monitoring
6
-
7
- after_build :downtime_host_build
5
+ def self.prepended(base)
6
+ base.class_eval do
7
+ include Orchestration::Monitoring
8
8
 
9
- alias_method_chain :smart_proxy_ids, :monitoring_proxy
10
- alias_method_chain :hostgroup_inherited_attributes, :monitoring
9
+ after_build :downtime_host_build
11
10
 
12
- has_many :monitoring_results, :dependent => :destroy, :foreign_key => 'host_id'
11
+ has_many :monitoring_results, :dependent => :destroy, :foreign_key => 'host_id', :inverse_of => :host
12
+ end
13
13
  end
14
14
 
15
15
  def monitoring_status(options = {})
@@ -30,6 +30,7 @@ module ForemanMonitoring
30
30
 
31
31
  def downtime_host(options)
32
32
  return unless monitored?
33
+
33
34
  begin
34
35
  monitoring.set_downtime_host(self, options)
35
36
  rescue ProxyAPI::ProxyException => e
@@ -42,12 +43,12 @@ module ForemanMonitoring
42
43
  monitoring_proxy.present?
43
44
  end
44
45
 
45
- def hostgroup_inherited_attributes_with_monitoring
46
- hostgroup_inherited_attributes_without_monitoring + ['monitoring_proxy_id']
46
+ def hostgroup_inherited_attributes
47
+ super + ['monitoring_proxy_id']
47
48
  end
48
49
 
49
- def smart_proxy_ids_with_monitoring_proxy
50
- ids = smart_proxy_ids_without_monitoring_proxy
50
+ def smart_proxy_ids
51
+ ids = super
51
52
  [monitoring_proxy, hostgroup.try(:monitoring_proxy)].compact.each do |proxy|
52
53
  ids << proxy.id
53
54
  end
@@ -61,12 +62,12 @@ module ForemanMonitoring
61
62
  :architecture => architecture.try(:name),
62
63
  :os => operatingsystem.try(:to_label),
63
64
  :osfamily => operatingsystem.try(:family),
64
- :virtual => provider != 'BareMetal',
65
+ :virtual => virtual.presence || provider != 'BareMetal',
65
66
  :provider => provider,
66
67
  :compute_resource => compute_resource.try(:to_label),
67
68
  :hostgroup => hostgroup.try(:to_label),
68
69
  :organization => organization.try(:name),
69
- :location => organization.try(:name),
70
+ :location => location.try(:name),
70
71
  :comment => comment,
71
72
  :environment => environment.try(:to_s),
72
73
  :owner_name => owner.try(:name)