foreman_monitoring 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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