foreman_monitoring 1.0.1 → 2.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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/downtime_controller.rb +63 -0
  3. data/app/controllers/api/v2/monitoring_results_controller.rb +2 -0
  4. data/app/controllers/concerns/foreman_monitoring/find_host_by_client_cert.rb +59 -0
  5. data/app/controllers/concerns/foreman_monitoring/hosts_controller_extensions.rb +7 -5
  6. data/app/helpers/concerns/foreman_monitoring/hosts_helper_ext.rb +7 -5
  7. data/app/lib/proxy_api/monitoring.rb +3 -0
  8. data/app/models/concerns/foreman_monitoring/host_extensions.rb +4 -1
  9. data/app/models/concerns/foreman_monitoring/hostgroup_extensions.rb +4 -0
  10. data/app/models/concerns/orchestration/monitoring.rb +13 -4
  11. data/app/models/host_status/monitoring_status.rb +5 -0
  12. data/app/models/monitoring_result.rb +6 -3
  13. data/app/models/setting/monitoring.rb +2 -0
  14. data/app/overrides/add_host_monitoring_result_tab.rb +8 -6
  15. data/app/overrides/add_host_multiple_power_set_downtime_checkbox.rb +5 -3
  16. data/app/overrides/add_host_set_downtime_modal.rb +4 -2
  17. data/app/services/monitoring.rb +3 -0
  18. data/app/views/monitoring_results/_host_tab_pane.html.erb +1 -1
  19. data/config/routes.rb +3 -0
  20. data/db/migrate/20160817135723_create_monitoring_results.rb +2 -0
  21. data/db/migrate/20161220201510_add_monitoring_proxy_id_to_host_and_hostgroup.rb +2 -0
  22. data/db/migrate/201910180900_rename_downtime_host_permission.rb +15 -0
  23. data/db/seeds.d/60-monitoring_proxy_feature.rb +2 -0
  24. data/lib/foreman_monitoring.rb +2 -0
  25. data/lib/foreman_monitoring/engine.rb +26 -22
  26. data/lib/foreman_monitoring/version.rb +3 -1
  27. data/lib/tasks/foreman_monitoring_tasks.rake +3 -1
  28. data/locale/gemspec.rb +2 -0
  29. data/test/controllers/api/v2/downtime_controller_test.rb +73 -0
  30. data/test/factories/feature.rb +3 -1
  31. data/test/factories/host.rb +3 -1
  32. data/test/factories/monitoring_results.rb +8 -6
  33. data/test/factories/smart_proxy.rb +2 -0
  34. data/test/functional/hosts_controller_test.rb +18 -16
  35. data/test/lib/proxy_api/monitoring_test.rb +3 -1
  36. data/test/test_plugin_helper.rb +2 -0
  37. data/test/unit/host_status/monitoring_status_test.rb +6 -4
  38. data/test/unit/host_test.rb +2 -0
  39. data/test/unit/monitoring_result_test.rb +2 -0
  40. data/test/unit/monitoring_test.rb +2 -0
  41. metadata +59 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eca113371402bd1f2251f09d5fd35ef5fce8ef9719299517e37cd56856ee9bbc
4
- data.tar.gz: 1d03b4a53865238e521074bf22f9f247e0b74413b1265790995ca6269be923cf
3
+ metadata.gz: 5e703d5ad965ed3aecba3fee0dc31a7a2c80a84eab893392484555fda8ba8ab1
4
+ data.tar.gz: 6dce2771bea3df536cb244aadfbad6483387d71157c4b70d5cbe0256b27f508c
5
5
  SHA512:
6
- metadata.gz: 9f6bb65a07d9a823f9ebad01708ce60b5a8058b6d86b2d67af1016c5361927de85a7e5ce2868bd4b8ec886236949f755d2a04e8b78698d07ed0de9b208b0e830
7
- data.tar.gz: f1a7ae4199d026bbcf8feb054f783aca7d0eb86096129b3d54d6e051d2be6174648086280ca4b3e1c4c3545cc41d8f4aa921cdd8fa720ea52ef7f1b177e444ac
6
+ metadata.gz: e3c24e7c223b0103333d21717636f338176cb2756028d60943c8e6276ffaa366de039dec2b5afd527b5f50464737194b6cc6d5e357f9696d6b56aff167b7fc6e
7
+ data.tar.gz: ca91aa5af43494a254fbe03bd13cb4e4e30dccfdab8e47befb8252f97b2cce1bd8ab850739993d1675d194f3253a8b5825b248f6d95cc75b6b7c4915252356eb
@@ -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
@@ -0,0 +1,59 @@
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 :authorize, :only => actions
11
+ skip_before_action :verify_authenticity_token, :only => actions
12
+ skip_before_action :set_taxonomy, :only => actions, :raise => false
13
+ skip_before_action :session_expiry, :update_activity_time, :only => actions
14
+ before_action(:only => actions) { require_client_cert_or_login }
15
+ attr_reader :detected_host
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ # Permits Hosts authorized by their client cert
22
+ # or a user with permission
23
+ def require_client_cert_or_login
24
+ @detected_host = find_host_by_client_cert
25
+
26
+ if detected_host
27
+ set_admin_user
28
+ return true
29
+ end
30
+
31
+ require_login
32
+ unless User.current
33
+ render_error 'unauthorized', :status => :unauthorized unless performed? && api_request?
34
+ return false
35
+ end
36
+ authorize
37
+ end
38
+
39
+ def find_host_by_client_cert
40
+ hostname = get_client_cert_hostname
41
+
42
+ return unless hostname
43
+
44
+ host ||= Host::Base.find_by(certname: hostname) ||
45
+ Host::Base.find_by(name: hostname)
46
+ logger.info { "Found Host #{host} by client cert #{hostname}" } if host
47
+ host
48
+ end
49
+
50
+ def get_client_cert_hostname
51
+ client_certificate = Foreman::ClientCertificate.new(request: request)
52
+ return unless client_certificate.verified?
53
+
54
+ hostname = client_certificate.subject
55
+ logger.debug "Extracted hostname '#{hostname}' from client certificate." if hostname
56
+ hostname
57
+ end
58
+ end
59
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ForemanMonitoring
2
4
  module HostsControllerExtensions
3
5
  def self.prepended(base)
@@ -38,14 +40,14 @@ module ForemanMonitoring
38
40
  failed_hosts[host.name] = error_message
39
41
  logger.error "Failed to set a host downtime for #{host}: #{error_message}"
40
42
  end
41
- rescue StandardError => error
42
- failed_hosts[host.name] = error
43
- 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)
44
46
  end
45
47
  end
46
48
 
47
49
  if failed_hosts.empty?
48
- notice _('A downtime was set for the selected hosts.')
50
+ success _('A downtime was set for the selected hosts.')
49
51
  else
50
52
  error n_('A downtime clould not be set for host: %s.',
51
53
  'A downtime could not be set for hosts: %s.',
@@ -128,7 +130,7 @@ module ForemanMonitoring
128
130
  def action_permission
129
131
  case params[:action]
130
132
  when 'downtime', 'select_multiple_downtime', 'update_multiple_downtime'
131
- :downtime
133
+ :manage_downtime
132
134
  when 'select_multiple_monitoring_proxy', 'update_multiple_monitoring_proxy'
133
135
  :edit
134
136
  else
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ForemanMonitoring
2
4
  module HostsHelperExt
3
5
  def multiple_actions
@@ -12,14 +14,14 @@ module ForemanMonitoring
12
14
  button_group(
13
15
  display_link_if_authorized(_('Downtime'),
14
16
  hash_for_host_path(:id => host).merge(:auth_object => host,
15
- :permission => :manage_host_downtimes,
17
+ :permission => :manage_downtime_hosts,
16
18
  :anchor => 'set_host_downtime'),
17
19
  :class => 'btn btn-default',
18
20
  :disabled => !host.monitored?,
19
- :title => _('Set a downtime for this host'),
20
- :id => 'host-downtime',
21
- :data => { :toggle => 'modal',
22
- :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' })
23
25
  )
24
26
  )
25
27
  super
@@ -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)
@@ -31,6 +33,7 @@ module ProxyAPI
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ForemanMonitoring
2
4
  module HostExtensions
3
5
  def self.prepended(base)
@@ -28,6 +30,7 @@ module ForemanMonitoring
28
30
 
29
31
  def downtime_host(options)
30
32
  return unless monitored?
33
+
31
34
  begin
32
35
  monitoring.set_downtime_host(self, options)
33
36
  rescue ProxyAPI::ProxyException => e
@@ -59,7 +62,7 @@ module ForemanMonitoring
59
62
  :architecture => architecture.try(:name),
60
63
  :os => operatingsystem.try(:to_label),
61
64
  :osfamily => operatingsystem.try(:family),
62
- :virtual => provider != 'BareMetal',
65
+ :virtual => virtual.presence || provider != 'BareMetal',
63
66
  :provider => provider,
64
67
  :compute_resource => compute_resource.try(:to_label),
65
68
  :hostgroup => hostgroup.try(:to_label),
@@ -1,14 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ForemanMonitoring
2
4
  module HostgroupExtensions
3
5
  extend ActiveSupport::Concern
4
6
 
5
7
  def monitoring_proxy
6
8
  return super if ancestry.blank?
9
+
7
10
  SmartProxy.find_by(id: inherited_monitoring_proxy_id)
8
11
  end
9
12
 
10
13
  def inherited_monitoring_proxy_id
11
14
  return monitoring_proxy_id if ancestry.blank?
15
+
12
16
  self[:monitoring_proxy_id] || self.class.sort_by_ancestry(ancestors.where('monitoring_proxy_id is not NULL')).last.try(:monitoring_proxy_id)
13
17
  end
14
18
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Orchestration::Monitoring
2
4
  extend ActiveSupport::Concern
3
5
 
@@ -10,32 +12,38 @@ module Orchestration::Monitoring
10
12
 
11
13
  def queue_monitoring
12
14
  return unless monitored? && errors.empty?
15
+
13
16
  clear_monitoring_object
14
17
  !monitoring_object.key?(:attrs) ? queue_monitoring_create : queue_monitoring_update
15
18
  end
16
19
 
17
20
  def queue_monitoring_create
18
21
  return true unless ::Monitoring.create_action?(:create)
19
- queue.create(:name => _('Create monitoring object for %s') % self, :priority => 20,
22
+
23
+ queue.create(:name => _('Create monitoring object for %s') % self, :priority => 20,
20
24
  :action => [self, :setMonitoring])
21
25
  end
22
26
 
23
27
  def queue_monitoring_update
24
28
  return unless monitoring_update_required?(monitoring_object[:attrs], monitoring_attributes)
29
+
25
30
  Rails.logger.debug('Detected a change to the monitoring object is required.')
26
31
  return unless ::Monitoring.create_action?(:create)
27
- queue.create(:name => _('Monitoring update for %s') % old, :priority => 2,
32
+
33
+ queue.create(:name => _('Monitoring update for %s') % old, :priority => 2,
28
34
  :action => [self, :setMonitoringUpdate])
29
35
  end
30
36
 
31
37
  def queue_monitoring_destroy
32
38
  return unless monitored? && errors.empty?
39
+
33
40
  if ::Monitoring.delete_action?(:delete)
34
- queue.create(:name => _('Removing monitoring object for %s') % self, :priority => 2,
41
+ queue.create(:name => _('Removing monitoring object for %s') % self, :priority => 2,
35
42
  :action => [self, :delMonitoring])
36
43
  end
37
44
  return unless ::Monitoring.delete_action?(:downtime)
38
- queue.create(:name => _('Set monitoring downtime for %s') % self, :priority => 2,
45
+
46
+ queue.create(:name => _('Set monitoring downtime for %s') % self, :priority => 2,
39
47
  :action => [self, :setMonitoringDowntime])
40
48
  end
41
49
 
@@ -95,6 +103,7 @@ module Orchestration::Monitoring
95
103
 
96
104
  def monitoring_update_required?(actual_attrs, desired_attrs)
97
105
  return true if actual_attrs.deep_symbolize_keys.keys != desired_attrs.deep_symbolize_keys.keys
106
+
98
107
  actual_attrs.deep_symbolize_keys.merge(desired_attrs.deep_symbolize_keys) do |k, actual_v, desired_v|
99
108
  if actual_v.is_a?(Hash) && desired_v.is_a?(Hash)
100
109
  return true if monitoring_update_required?(actual_v, desired_v)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HostStatus
2
4
  class MonitoringStatus < HostStatus::Status
3
5
  OK = 0
@@ -14,6 +16,7 @@ module HostStatus
14
16
  grouped_results.each_key do |resultset|
15
17
  result, downtime, acknowledged = resultset
16
18
  next if downtime
19
+
17
20
  result = map_result_to_status(result)
18
21
  result = WARNING if acknowledged || result == UNKNOWN
19
22
  state = result if result > state
@@ -23,6 +26,7 @@ module HostStatus
23
26
 
24
27
  def to_global(_options = {})
25
28
  return HostStatus::Global::OK unless should_affect_global_status?
29
+
26
30
  case status
27
31
  when OK
28
32
  HostStatus::Global::OK
@@ -74,6 +78,7 @@ module HostStatus
74
78
 
75
79
  def map_result_to_status(result)
76
80
  return result if Rails::VERSION::MAJOR < 5
81
+
77
82
  case result.to_sym
78
83
  when :ok
79
84
  OK
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class MonitoringResult < ApplicationRecord
2
- enum :result => %i[ok warning critical unknown]
4
+ enum :result => { :ok => 0, :warning => 1, :critical => 2, :unknown => 3 }
3
5
 
4
6
  belongs_to_host
5
7
 
@@ -30,11 +32,11 @@ class MonitoringResult < ApplicationRecord
30
32
  created = MonitoringResult.where(:host => host, :service => result[:service]).first_or_create
31
33
  # rubocop:disable Rails/Date
32
34
  if created.timestamp.blank? || updates[:timestamp].blank? || (created.timestamp.to_time - updates[:timestamp].to_time) < 2
33
- created.update_attributes(updates)
35
+ created.update(updates)
34
36
 
35
37
  if created.persisted?
36
38
  logger.info("Imported monitoring result for #{host} in #{(Time.now.utc - start_time).round(2)} seconds")
37
- host.refresh_statuses
39
+ host.get_status(::HostStatus::MonitoringStatus).refresh!
38
40
  end
39
41
  else
40
42
  logger.debug "Skipping monitoring result import for #{host} as it is older than what we have."
@@ -46,6 +48,7 @@ class MonitoringResult < ApplicationRecord
46
48
  def status
47
49
  return :ok if downtime
48
50
  return :warning if acknowledged
51
+
49
52
  result.to_sym
50
53
  end
51
54
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Setting
2
4
  class Monitoring < ::Setting
3
5
  def self.default_settings
@@ -1,9 +1,11 @@
1
- Deface::Override.new(:virtual_path => 'hosts/show',
2
- :name => 'add_monitoring_result_tab',
1
+ # frozen_string_literal: true
2
+
3
+ Deface::Override.new(:virtual_path => 'hosts/show',
4
+ :name => 'add_monitoring_result_tab',
3
5
  :insert_bottom => 'ul.nav-tabs',
4
- :partial => 'monitoring_results/host_tab')
6
+ :partial => 'monitoring_results/host_tab')
5
7
 
6
- Deface::Override.new(:virtual_path => 'hosts/show',
7
- :name => 'add_monitoring_result_tab_pane',
8
+ Deface::Override.new(:virtual_path => 'hosts/show',
9
+ :name => 'add_monitoring_result_tab_pane',
8
10
  :insert_bottom => 'div.tab-content',
9
- :partial => 'monitoring_results/host_tab_pane')
11
+ :partial => 'monitoring_results/host_tab_pane')
@@ -1,4 +1,6 @@
1
- Deface::Override.new(:virtual_path => 'hosts/select_multiple_power_state',
2
- :name => 'add_host_multiple_power_set_downtime_checkbox',
1
+ # frozen_string_literal: true
2
+
3
+ Deface::Override.new(:virtual_path => 'hosts/select_multiple_power_state',
4
+ :name => 'add_host_multiple_power_set_downtime_checkbox',
3
5
  :insert_before => "erb[silent]:contains('end')",
4
- :partial => 'hosts/host_downtime_checkbox')
6
+ :partial => 'hosts/host_downtime_checkbox')
@@ -1,4 +1,6 @@
1
- Deface::Override.new(:virtual_path => 'hosts/show',
2
- :name => 'add_monitoring_set_downtime_modal',
1
+ # frozen_string_literal: true
2
+
3
+ Deface::Override.new(:virtual_path => 'hosts/show',
4
+ :name => 'add_monitoring_set_downtime_modal',
3
5
  :insert_after => 'div#review_before_build',
4
6
  :partial => 'hosts/set_host_downtime')
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Monitoring
2
4
  CREATE_ACTIONS = {
3
5
  'none' => _('None'),
@@ -49,6 +51,7 @@ class Monitoring
49
51
  def query_host(host)
50
52
  result = proxy_api.query_host(host.name)
51
53
  return {} unless result
54
+
52
55
  {
53
56
  :attrs => result
54
57
  }
@@ -2,7 +2,7 @@
2
2
  <div class="tab-pane" id="monitoring">
3
3
  <% if @host.monitoring_results.any? %>
4
4
  <table class="<%= table_css_classes %>">
5
- <thead
5
+ <thead>
6
6
  <tr>
7
7
  <th colspan="2">Monitoring</th>
8
8
  </tr>
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Rails.application.routes.draw do
2
4
  namespace :api, :defaults => { :format => 'json' } do
3
5
  scope '(:apiv)', :module => :v2,
@@ -5,6 +7,7 @@ Rails.application.routes.draw do
5
7
  :apiv => /v1|v2/,
6
8
  :constraints => ApiConstraints.new(:version => 2) do
7
9
  resources :monitoring_results, :only => [:create]
10
+ resources :downtime, :only => [:create]
8
11
  end
9
12
  end
10
13
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class CreateMonitoringResults < ActiveRecord::Migration[4.2]
2
4
  def change
3
5
  # rubocop:disable Rails/CreateTableWithTimestamps
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class AddMonitoringProxyIdToHostAndHostgroup < ActiveRecord::Migration[4.2]
2
4
  def self.up
3
5
  add_column :hosts, :monitoring_proxy_id, :integer
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RenameDowntimeHostPermission < ActiveRecord::Migration[5.2]
4
+ def up
5
+ # rubocop:disable Rails/SkipsModelValidations
6
+ Permission.where(name: 'manage_host_downtimes').update_all(name: 'manage_downtime_hosts')
7
+ # rubocop:enable Rails/SkipsModelValidations
8
+ end
9
+
10
+ def down
11
+ # rubocop:disable Rails/SkipsModelValidations
12
+ Permission.where(name: 'manage_downtime_hosts').update_all(name: 'manage_host_downtimes')
13
+ # rubocop:enable Rails/SkipsModelValidations
14
+ end
15
+ end
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  f = Feature.where(:name => 'Monitoring').first_or_create
2
4
  raise "Unable to create proxy feature: #{format_errors f}" if f.nil? || f.errors.any?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'foreman_monitoring/engine'
2
4
 
3
5
  module ForemanMonitoring
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'deface'
2
4
 
3
5
  module ForemanMonitoring
@@ -18,18 +20,17 @@ module ForemanMonitoring
18
20
 
19
21
  initializer 'foreman_monitoring.load_default_settings',
20
22
  :before => :load_config_initializers do |_app|
21
- if begin
22
- Setting.table_exists?
23
- rescue StandardError
24
- false
25
- end
26
- require_dependency File.expand_path('../../../app/models/setting/monitoring.rb', __FILE__)
27
- end
23
+ setting_table_exists = begin
24
+ Setting.table_exists?
25
+ rescue StandardError
26
+ false
27
+ end
28
+ require_dependency File.expand_path('../../app/models/setting/monitoring.rb', __dir__) if setting_table_exists
28
29
  end
29
30
 
30
31
  initializer 'foreman_monitoring.register_plugin', :before => :finisher_hook do |_app|
31
32
  Foreman::Plugin.register :foreman_monitoring do
32
- requires_foreman '>= 1.17'
33
+ requires_foreman '>= 2.0'
33
34
 
34
35
  apipie_documented_controllers ["#{ForemanMonitoring::Engine.root}/app/controllers/api/v2/*.rb"]
35
36
 
@@ -37,22 +38,25 @@ module ForemanMonitoring
37
38
  permission :view_monitoring_results,
38
39
  {},
39
40
  :resource_type => 'Host'
40
- permission :manage_host_downtimes,
41
- { :hosts => [:downtime, :select_multiple_downtime, :update_multiple_downtime] },
41
+ permission :manage_downtime_hosts,
42
+ { :hosts => [:downtime, :select_multiple_downtime, :update_multiple_downtime], :'api/v2/downtime' => [:create] },
42
43
  :resource_type => 'Host'
43
44
  permission :upload_monitoring_results,
44
45
  :'api/v2/monitoring_results' => [:create]
45
- permission :edit_hosts,
46
- { :hosts => [:select_multiple_monitoring_proxy, :update_multiple_monitoring_proxy] },
47
- :resource_type => 'Host'
48
46
  end
49
47
 
50
- role 'Monitoring viewer', [:view_monitoring_results]
51
- role 'Monitoring manager', [:view_monitoring_results, :manage_host_downtimes]
48
+ # Extend built in permissions
49
+ Foreman::AccessControl.permission(:edit_hosts).actions.concat [
50
+ 'hosts/select_multiple_monitoring_proxy',
51
+ 'hosts/update_multiple_monitoring_proxy'
52
+ ]
53
+
54
+ role 'Monitoring viewer', [:view_monitoring_results], 'Role granting permissions to view monitor results'
55
+ role 'Monitoring manager', [:view_monitoring_results, :manage_downtime_hosts], 'Role granting permissions to view monitor results and manage downtimes'
52
56
 
53
57
  register_custom_status HostStatus::MonitoringStatus
54
58
 
55
- add_controller_action_scope(HostsController, :index) { |base_scope| base_scope.includes(:monitoring_results) }
59
+ add_controller_action_scope('HostsController', :index) { |base_scope| base_scope.includes(:monitoring_results) }
56
60
 
57
61
  monitoring_proxy_options = {
58
62
  :feature => 'Monitoring',
@@ -65,23 +69,23 @@ module ForemanMonitoring
65
69
  smart_proxy_for Host::Managed, :monitoring_proxy, monitoring_proxy_options
66
70
  smart_proxy_for Hostgroup, :monitoring_proxy, monitoring_proxy_options
67
71
 
68
- add_controller_action_scope(HostsController, :index) { |base_scope| base_scope.includes(:monitoring_proxy) }
72
+ add_controller_action_scope('HostsController', :index) { |base_scope| base_scope.includes(:monitoring_proxy) }
69
73
  end
70
74
  end
71
75
 
72
76
  config.to_prepare do
73
77
  begin
74
- ::Host::Managed.send(:prepend, ForemanMonitoring::HostExtensions)
75
- ::Hostgroup.send(:include, ForemanMonitoring::HostgroupExtensions)
76
- ::HostsHelper.send(:prepend, ForemanMonitoring::HostsHelperExt)
77
- ::HostsController.send(:prepend, ForemanMonitoring::HostsControllerExtensions)
78
+ ::Host::Managed.prepend(ForemanMonitoring::HostExtensions)
79
+ ::Hostgroup.include(ForemanMonitoring::HostgroupExtensions)
80
+ ::HostsHelper.prepend(ForemanMonitoring::HostsHelperExt)
81
+ ::HostsController.prepend(ForemanMonitoring::HostsControllerExtensions)
78
82
  rescue StandardError => e
79
83
  Rails.logger.warn "ForemanMonitoring: skipping engine hook (#{e})"
80
84
  end
81
85
  end
82
86
 
83
87
  initializer 'foreman_monitoring.register_gettext', after: :load_config_initializers do |_app|
84
- locale_dir = File.join(File.expand_path('../../..', __FILE__), 'locale')
88
+ locale_dir = File.join(File.expand_path('../..', __dir__), 'locale')
85
89
  locale_domain = 'foreman_monitoring'
86
90
  Foreman::Gettext::Support.add_text_domain locale_domain, locale_dir
87
91
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ForemanMonitoring
2
- VERSION = '1.0.1'.freeze
4
+ VERSION = '2.0.0'
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Tests
2
4
  namespace :test do
3
5
  desc 'Test ForemanMonitoring'
@@ -11,7 +13,7 @@ namespace :test do
11
13
  end
12
14
 
13
15
  namespace :foreman_monitoring do
14
- task :rubocop do
16
+ task rubocop: :environment do
15
17
  begin
16
18
  require 'rubocop/rake_task'
17
19
  RuboCop::RakeTask.new(:rubocop_foreman_monitoring) do |task|
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Matches foreman_monitoring.gemspec
2
4
  _('Set a downtime for hosts after they are deleted in Foreman.')
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_plugin_helper'
4
+
5
+ class Api::V2::DowntimeControllerTest < ActionController::TestCase
6
+ let(:host1) { as_admin { FactoryBot.create(:host, :managed) } }
7
+
8
+ context 'with user authentication' do
9
+ context '#create' do
10
+ test 'should deny access' do
11
+ put :create
12
+ assert_response :forbidden
13
+ end
14
+ end
15
+ end
16
+
17
+ context 'with client cert' do
18
+ setup do
19
+ User.current = nil
20
+ reset_api_credentials
21
+
22
+ Setting[:ssl_client_dn_env] = 'SSL_CLIENT_S_DN'
23
+ Setting[:ssl_client_verify_env] = 'SSL_CLIENT_VERIFY'
24
+
25
+ @request.env['HTTPS'] = 'on'
26
+ @request.env['SSL_CLIENT_S_DN'] = "CN=#{host1.name},DN=example,DN=com"
27
+ @request.env['SSL_CLIENT_VERIFY'] = 'SUCCESS'
28
+ end
29
+
30
+ context '#create' do
31
+ test 'should create downtime' do
32
+ put :create
33
+ assert_response :success
34
+ end
35
+ end
36
+
37
+ context '#create with duration' do
38
+ test 'should create downtime with given duration' do
39
+ Host::Managed.any_instance.expects(:downtime_host).with { |params| params[:end_time] - params[:start_time] == 3600 }
40
+ put :create, params: { duration: 3600 }
41
+ assert_response :success
42
+ end
43
+
44
+ test 'should create downtime with given duration as string' do
45
+ Host::Managed.any_instance.expects(:downtime_host).with { |params| params[:end_time] - params[:start_time] == 3600 }
46
+ put :create, params: { duration: '3600' }
47
+ assert_response :success
48
+ end
49
+ end
50
+
51
+ context '#create with reason' do
52
+ test 'should create downtime with given reason' do
53
+ Host::Managed.any_instance.expects(:downtime_host).with { |params| params[:comment] == 'In testing' }
54
+ put :create, params: { reason: 'In testing' }
55
+ assert_response :success
56
+ end
57
+ end
58
+ end
59
+
60
+ context 'without any credentials' do
61
+ setup do
62
+ User.current = nil
63
+ reset_api_credentials
64
+ end
65
+
66
+ context '#create' do
67
+ test 'should deny access' do
68
+ post :create
69
+ assert_response :unauthorized
70
+ end
71
+ end
72
+ end
73
+ end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  FactoryBot.modify do
2
4
  factory :feature do
3
5
  trait :monitoring do
4
- name 'Monitoring'
6
+ name { 'Monitoring' }
5
7
  end
6
8
  end
7
9
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  FactoryBot.modify do
2
4
  factory :host do
3
5
  trait :with_monitoring do
@@ -8,7 +10,7 @@ FactoryBot.modify do
8
10
 
9
11
  trait :with_monitoring_results do
10
12
  transient do
11
- monitoring_result_count 20
13
+ monitoring_result_count { 20 }
12
14
  end
13
15
  after(:create) do |host, evaluator|
14
16
  evaluator.monitoring_result_count.times do
@@ -1,30 +1,32 @@
1
+ # frozen_string_literal: true
2
+
1
3
  FactoryBot.define do
2
4
  factory :monitoring_result do
3
5
  sequence(:service) { |n| "Service #{n}" }
4
6
  result { rand(0..3) }
5
7
 
6
8
  trait :ok do
7
- result 0
9
+ result { 0 }
8
10
  end
9
11
 
10
12
  trait :warning do
11
- result 1
13
+ result { 1 }
12
14
  end
13
15
 
14
16
  trait :critical do
15
- result 2
17
+ result { 2 }
16
18
  end
17
19
 
18
20
  trait :unknown do
19
- result 3
21
+ result { 3 }
20
22
  end
21
23
 
22
24
  trait :downtime do
23
- downtime true
25
+ downtime { true }
24
26
  end
25
27
 
26
28
  trait :acknowledged do
27
- acknowledged true
29
+ acknowledged { true }
28
30
  end
29
31
  end
30
32
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  FactoryBot.modify do
2
4
  factory :smart_proxy do
3
5
  trait :monitoring do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_plugin_helper'
2
4
 
3
5
  class HostsControllerExtensionsTest < ActionController::TestCase
@@ -22,17 +24,17 @@ class HostsControllerExtensionsTest < ActionController::TestCase
22
24
  params: {
23
25
  :id => @host.name,
24
26
  :downtime => {
25
- :comment => 'Maintenance work.',
27
+ :comment => 'Maintenance work.',
26
28
  :starttime => Time.current,
27
- :endtime => Time.current.advance(:hours => 2)
29
+ :endtime => Time.current.advance(:hours => 2)
28
30
  }
29
31
  },
30
32
  session: set_session_user
31
33
  assert_response :found
32
34
  assert_redirected_to host_path(:id => @host)
33
35
  assert_nil flash[:error]
34
- assert_not_nil flash[:notice]
35
- assert_equal "Created downtime for #{@host}", flash[:notice]
36
+ assert_not_nil flash[:success]
37
+ assert_equal "Created downtime for #{@host}", flash[:success]
36
38
  end
37
39
 
38
40
  test 'with missing comment param the flash should inform it' do
@@ -58,9 +60,9 @@ class HostsControllerExtensionsTest < ActionController::TestCase
58
60
  params: {
59
61
  :id => @host.name,
60
62
  :downtime => {
61
- :comment => 'Maintenance work.',
63
+ :comment => 'Maintenance work.',
62
64
  :starttime => 'invalid',
63
- :endtime => 'invalid'
65
+ :endtime => 'invalid'
64
66
  }
65
67
  },
66
68
  session: set_session_user
@@ -78,9 +80,9 @@ class HostsControllerExtensionsTest < ActionController::TestCase
78
80
  params: {
79
81
  :id => @host.name,
80
82
  :downtime => {
81
- :comment => 'Maintenance work.',
83
+ :comment => 'Maintenance work.',
82
84
  :starttime => '2017-04-20T10:15',
83
- :endtime => '2017-04-20T12:15'
85
+ :endtime => '2017-04-20T12:15'
84
86
  }
85
87
  },
86
88
  session: set_session_user
@@ -120,8 +122,8 @@ class HostsControllerExtensionsTest < ActionController::TestCase
120
122
  assert_response :found
121
123
  assert_redirected_to hosts_path
122
124
  assert_nil flash[:error]
123
- assert_not_nil flash[:notice]
124
- assert_equal 'A downtime was set for the selected hosts.', flash[:notice]
125
+ assert_not_nil flash[:success]
126
+ assert_equal 'A downtime was set for the selected hosts.', flash[:success]
125
127
  end
126
128
  end
127
129
 
@@ -151,8 +153,8 @@ class HostsControllerExtensionsTest < ActionController::TestCase
151
153
  assert_response :found
152
154
  assert_redirected_to hosts_path
153
155
  assert_nil flash[:error]
154
- assert_not_nil flash[:notice]
155
- assert_equal 'The power state of the selected hosts will be set to poweroff', flash[:notice]
156
+ assert_not_nil flash[:success]
157
+ assert_equal 'The power state of the selected hosts will be set to poweroff', flash[:success]
156
158
  end
157
159
 
158
160
  test 'should not set a downtime if not selected' do
@@ -170,8 +172,8 @@ class HostsControllerExtensionsTest < ActionController::TestCase
170
172
  assert_response :found
171
173
  assert_redirected_to hosts_path
172
174
  assert_nil flash[:error]
173
- assert_not_nil flash[:notice]
174
- assert_equal 'The power state of the selected hosts will be set to poweroff', flash[:notice]
175
+ assert_not_nil flash[:success]
176
+ assert_equal 'The power state of the selected hosts will be set to poweroff', flash[:success]
175
177
  end
176
178
  end
177
179
 
@@ -196,7 +198,7 @@ class HostsControllerExtensionsTest < ActionController::TestCase
196
198
 
197
199
  test 'should change the proxy' do
198
200
  hosts.each do |host|
199
- refute_equal monitoring_proxy, host.monitoring_proxy
201
+ assert_not_equal monitoring_proxy, host.monitoring_proxy
200
202
  end
201
203
 
202
204
  params = {
@@ -209,7 +211,7 @@ class HostsControllerExtensionsTest < ActionController::TestCase
209
211
  assert_response :found
210
212
  assert_redirected_to hosts_path
211
213
  assert_nil flash[:error]
212
- assert_equal "The Monitoring proxy of the selected hosts was set to #{monitoring_proxy.name}", flash[:notice]
214
+ assert_equal "The Monitoring proxy of the selected hosts was set to #{monitoring_proxy.name}", flash[:success]
213
215
 
214
216
  hosts.each do |host|
215
217
  as_admin do
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
- class ProxyApiDhcpTest < ActiveSupport::TestCase
5
+ class ProxyApiMonitoringTest < ActiveSupport::TestCase
4
6
  def setup
5
7
  @url = 'http://localhost:8443'
6
8
  @monitoring = ProxyAPI::Monitoring.new(:url => @url)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This calls the main test_helper in Foreman-core
2
4
  require 'test_helper'
3
5
  require 'database_cleaner'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_plugin_helper'
2
4
 
3
5
  class MonitoringStatusTest < ActiveSupport::TestCase
@@ -61,7 +63,7 @@ class MonitoringStatusTest < ActiveSupport::TestCase
61
63
  assert status.relevant?
62
64
 
63
65
  host.build = true
64
- refute status.relevant?
66
+ assert_not status.relevant?
65
67
  end
66
68
 
67
69
  test '#host_known_in_monitoring? should be true' do
@@ -76,10 +78,10 @@ class MonitoringStatusTest < ActiveSupport::TestCase
76
78
  context 'status with host without monitoring results' do
77
79
  test '#relevant? is always false when build changes' do
78
80
  host.build = false
79
- refute status.relevant?
81
+ assert_not status.relevant?
80
82
 
81
83
  host.build = true
82
- refute status.relevant?
84
+ assert_not status.relevant?
83
85
  end
84
86
 
85
87
  test '#refresh! refreshes the date and persists the record' do
@@ -90,7 +92,7 @@ class MonitoringStatusTest < ActiveSupport::TestCase
90
92
  end
91
93
 
92
94
  test '#host_known_in_monitoring? should be false' do
93
- refute status.host_known_in_monitoring?
95
+ assert_not status.host_known_in_monitoring?
94
96
  end
95
97
  end
96
98
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_plugin_helper'
2
4
 
3
5
  class HostTest < ActiveSupport::TestCase
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_plugin_helper'
2
4
 
3
5
  class MonitoringResultTest < ActiveSupport::TestCase
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_plugin_helper'
2
4
 
3
5
  class MonitoringTest < ActiveSupport::TestCase
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_monitoring
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Timo Goebel
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-28 00:00:00.000000000 Z
11
+ date: 2020-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdoc
@@ -28,16 +28,58 @@ dependencies:
28
28
  name: rubocop
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '='
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.52.0
33
+ version: 0.80.0
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '='
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.52.0
40
+ version: 0.80.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop-minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop-performance
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
41
83
  - !ruby/object:Gem::Dependency
42
84
  name: deface
43
85
  requirement: !ruby/object:Gem::Requirement
@@ -62,7 +104,9 @@ files:
62
104
  - LICENSE
63
105
  - README.md
64
106
  - Rakefile
107
+ - app/controllers/api/v2/downtime_controller.rb
65
108
  - app/controllers/api/v2/monitoring_results_controller.rb
109
+ - app/controllers/concerns/foreman_monitoring/find_host_by_client_cert.rb
66
110
  - app/controllers/concerns/foreman_monitoring/hosts_controller_extensions.rb
67
111
  - app/helpers/concerns/foreman_monitoring/hosts_helper_ext.rb
68
112
  - app/lib/proxy_api/monitoring.rb
@@ -86,6 +130,7 @@ files:
86
130
  - config/routes.rb
87
131
  - db/migrate/20160817135723_create_monitoring_results.rb
88
132
  - db/migrate/20161220201510_add_monitoring_proxy_id_to_host_and_hostgroup.rb
133
+ - db/migrate/201910180900_rename_downtime_host_permission.rb
89
134
  - db/seeds.d/60-monitoring_proxy_feature.rb
90
135
  - lib/foreman_monitoring.rb
91
136
  - lib/foreman_monitoring/engine.rb
@@ -95,6 +140,7 @@ files:
95
140
  - locale/en/foreman_monitoring.po
96
141
  - locale/foreman_monitoring.pot
97
142
  - locale/gemspec.rb
143
+ - test/controllers/api/v2/downtime_controller_test.rb
98
144
  - test/factories/feature.rb
99
145
  - test/factories/host.rb
100
146
  - test/factories/monitoring_results.rb
@@ -106,11 +152,11 @@ files:
106
152
  - test/unit/host_test.rb
107
153
  - test/unit/monitoring_result_test.rb
108
154
  - test/unit/monitoring_test.rb
109
- homepage: http://www.github.com/theforeman/foreman_monitoring
155
+ homepage: https://github.com/theforeman/foreman_monitoring
110
156
  licenses:
111
- - GPLv3
157
+ - GPL-3.0
112
158
  metadata: {}
113
- post_install_message:
159
+ post_install_message:
114
160
  rdoc_options: []
115
161
  require_paths:
116
162
  - lib
@@ -125,9 +171,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
171
  - !ruby/object:Gem::Version
126
172
  version: '0'
127
173
  requirements: []
128
- rubyforge_project:
129
- rubygems_version: 2.7.3
130
- signing_key:
174
+ rubygems_version: 3.1.2
175
+ signing_key:
131
176
  specification_version: 4
132
177
  summary: Foreman plugin for monitoring system integration.
133
178
  test_files:
@@ -141,4 +186,5 @@ test_files:
141
186
  - test/factories/host.rb
142
187
  - test/lib/proxy_api/monitoring_test.rb
143
188
  - test/test_plugin_helper.rb
189
+ - test/controllers/api/v2/downtime_controller_test.rb
144
190
  - test/functional/hosts_controller_test.rb