foreman_expire_hosts 6.0.0 → 7.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +78 -0
- data/.rubocop.yml +18 -13
- data/.rubocop_todo.yml +11 -31
- data/Gemfile +2 -0
- data/README.md +1 -0
- data/app/controllers/concerns/foreman_expire_hosts/api/v2/hosts_controller_extensions.rb +2 -0
- data/app/controllers/concerns/foreman_expire_hosts/host_controller_extensions.rb +20 -15
- data/app/helpers/concerns/foreman_expire_hosts/audits_helper_extensions.rb +4 -0
- data/app/helpers/concerns/foreman_expire_hosts/hosts_helper_extensions.rb +5 -22
- data/app/helpers/expire_hosts_mailer_helper.rb +3 -0
- data/app/helpers/foreman_expire_hosts/hosts_helper.rb +16 -0
- data/app/mailers/expire_hosts_mailer.rb +3 -0
- data/app/models/concerns/foreman_expire_hosts/host_ext.rb +9 -1
- data/app/models/host_status/expiration_status.rb +3 -0
- data/app/models/setting/expire_hosts.rb +2 -0
- data/app/overrides/add_expired_on_field_to_host_form.rb +4 -2
- data/app/overrides/add_expired_on_field_to_host_show.rb +5 -3
- data/app/overrides/deleted_expired_host_comment_in_audits.rb +8 -6
- data/app/services/foreman_expire_hosts/action/base.rb +9 -2
- data/app/services/foreman_expire_hosts/action/delete_expired_hosts.rb +3 -0
- data/app/services/foreman_expire_hosts/action/stop_expired_hosts.rb +6 -2
- data/app/services/foreman_expire_hosts/expiry_edit_authorizer.rb +2 -0
- data/app/services/foreman_expire_hosts/notification/base.rb +12 -3
- data/app/services/foreman_expire_hosts/notification/deleted_hosts.rb +2 -0
- data/app/services/foreman_expire_hosts/notification/expiry_warning.rb +2 -0
- data/app/services/foreman_expire_hosts/notification/failed_deleted_hosts.rb +2 -0
- data/app/services/foreman_expire_hosts/notification/failed_stopped_hosts.rb +2 -0
- data/app/services/foreman_expire_hosts/notification/stopped_hosts.rb +2 -0
- data/app/services/foreman_expire_hosts/safe_destroy.rb +7 -5
- data/app/services/foreman_expire_hosts/ui_notifications/hosts/base.rb +4 -1
- data/app/services/foreman_expire_hosts/ui_notifications/hosts/expiry_warning.rb +2 -0
- data/app/services/foreman_expire_hosts/ui_notifications/hosts/stopped_host.rb +2 -0
- data/app/views/api/v2/hosts/expiration.json.rabl +2 -0
- data/app/views/hosts/_expired_on_field.html.erb +11 -20
- data/app/views/hosts/select_multiple_expiration.html.erb +10 -15
- data/config/routes.rb +2 -0
- data/db/migrate/20150427101516_add_expiry_on_to_hosts.rb +2 -0
- data/db/seeds.d/80_expire_hosts_ui_notification.rb +2 -0
- data/extra/foreman_expire_hosts.cron +8 -0
- data/foreman_expire_hosts.gemspec +10 -3
- data/lib/expire_hosts_notifications.rb +3 -0
- data/lib/foreman_expire_hosts.rb +2 -0
- data/lib/foreman_expire_hosts/engine.rb +22 -10
- data/lib/foreman_expire_hosts/version.rb +3 -1
- data/lib/tasks/expired_hosts.rake +3 -1
- data/test/factories/foreman_expire_hosts_factories.rb +7 -5
- data/test/functional/api/v2/hosts_controller_test.rb +3 -1
- data/test/functional/concerns/hosts_controller_extensions_test.rb +3 -1
- data/test/helpers/hosts_helper_test.rb +5 -0
- data/test/lib/expire_hosts_notifications_test.rb +91 -45
- data/test/test_plugin_helper.rb +2 -0
- data/test/unit/concerns/host_extensions_test.rb +21 -19
- data/test/unit/expire_hosts_mailer_test.rb +6 -0
- data/test/unit/expiry_edit_authorizer_test.rb +2 -0
- data/test/unit/host_status/expiration_status_test.rb +3 -1
- data/test/unit/safe_destroy_test.rb +3 -1
- metadata +53 -26
- data/app/assets/javascripts/foreman_expire_hosts/application.js +0 -3
- data/app/assets/javascripts/foreman_expire_hosts/datepicker_for_host_expired_on_field.js +0 -27
- data/app/assets/stylesheets/foreman_expire_hosts/application.scss +0 -4
- data/app/overrides/add_js_to_host_index.rb +0 -6
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module HostStatus
|
2
4
|
class ExpirationStatus < HostStatus::Status
|
3
5
|
OK = 0
|
@@ -15,6 +17,7 @@ module HostStatus
|
|
15
17
|
return EXPIRED if host.expired_past_grace_period?
|
16
18
|
return IN_GRACE_PERIOD if host.expired?
|
17
19
|
return PENDING if host.pending_expiration?
|
20
|
+
|
18
21
|
OK
|
19
22
|
end
|
20
23
|
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
Deface::Override.new(
|
2
4
|
:virtual_path => 'hosts/_form',
|
3
|
-
:name
|
5
|
+
:name => 'host_form_expired_on_field',
|
4
6
|
:insert_after => 'div#model_name',
|
5
|
-
:partial
|
7
|
+
:partial => 'hosts/expired_on_field'
|
6
8
|
)
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
Deface::Override.new(
|
2
|
-
:virtual_path
|
3
|
-
:name
|
4
|
+
:virtual_path => 'hosts/show',
|
5
|
+
:name => 'host_expiry_waring_in_show',
|
4
6
|
:insert_before => '#host-show',
|
5
|
-
:partial
|
7
|
+
:partial => 'hosts/expired_message.html.erb'
|
6
8
|
)
|
@@ -1,13 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
Deface::Override.new(
|
2
|
-
:virtual_path
|
3
|
-
:name
|
4
|
+
:virtual_path => 'audits/_list',
|
5
|
+
:name => 'deleted_expired_host_audit_comment_in_list',
|
4
6
|
:insert_bottom => 'div.row div.audit-content',
|
5
|
-
:text
|
7
|
+
:text => "\n <%= destroyed_expired_host_audit_comment_in_list(audit) %>"
|
6
8
|
)
|
7
9
|
|
8
10
|
Deface::Override.new(
|
9
|
-
:virtual_path
|
10
|
-
:name
|
11
|
+
:virtual_path => 'audits/show',
|
12
|
+
:name => 'deleted_expired_host_audit_comment_in_show',
|
11
13
|
:insert_bottom => 'div#tab1 table',
|
12
|
-
:text
|
14
|
+
:text => "\n <%= destroyed_expired_host_audit_comment_in_show(@audit) %>"
|
13
15
|
)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ForemanExpireHosts
|
2
4
|
module Action
|
3
5
|
class Base
|
@@ -17,9 +19,14 @@ module ForemanExpireHosts
|
|
17
19
|
|
18
20
|
def process
|
19
21
|
hosts.each do |host|
|
20
|
-
|
22
|
+
result = action(host)
|
23
|
+
next if result.nil?
|
24
|
+
|
25
|
+
if result
|
26
|
+
logger.info "Action #{self.class.name} for host #{host.name} was successful."
|
21
27
|
self.successful_hosts << host
|
22
28
|
else
|
29
|
+
logger.info "Action #{self.class.name} for host #{host.name} failed."
|
23
30
|
self.failed_hosts << host
|
24
31
|
end
|
25
32
|
end
|
@@ -51,7 +58,7 @@ module ForemanExpireHosts
|
|
51
58
|
}
|
52
59
|
end
|
53
60
|
|
54
|
-
delegate :logger, :to => :
|
61
|
+
delegate :logger, :to => :ForemanExpireHosts
|
55
62
|
end
|
56
63
|
end
|
57
64
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ForemanExpireHosts
|
2
4
|
module Action
|
3
5
|
class DeleteExpiredHosts < Base
|
@@ -8,6 +10,7 @@ module ForemanExpireHosts
|
|
8
10
|
end
|
9
11
|
|
10
12
|
def action(host)
|
13
|
+
logger.info "Destroying expired host #{host}."
|
11
14
|
SafeDestroy.new(host).destroy!
|
12
15
|
end
|
13
16
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ForemanExpireHosts
|
2
4
|
module Action
|
3
5
|
class StopExpiredHosts < Base
|
@@ -8,8 +10,10 @@ module ForemanExpireHosts
|
|
8
10
|
end
|
9
11
|
|
10
12
|
def action(host)
|
11
|
-
return
|
12
|
-
|
13
|
+
return false unless host.supports_power?
|
14
|
+
return unless host.power.ready?
|
15
|
+
|
16
|
+
logger.info "Powering down expired host in grace period #{host}."
|
13
17
|
host.power.stop
|
14
18
|
rescue StandardError
|
15
19
|
false
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ForemanExpireHosts
|
2
4
|
module Notification
|
3
5
|
class Base
|
@@ -24,22 +26,27 @@ module ForemanExpireHosts
|
|
24
26
|
end
|
25
27
|
|
26
28
|
def deliver_mail_notification(recipient, hosts)
|
29
|
+
return true if hosts.empty?
|
30
|
+
|
31
|
+
logger.info "Deliving mail notification '#{humanized_name}' for hosts #{hosts.to_sentence} to #{recipient}."
|
32
|
+
|
27
33
|
build_mail_notification(recipient, hosts).deliver_now
|
28
|
-
rescue SocketError, Net::SMTPError =>
|
34
|
+
rescue SocketError, Net::SMTPError => e
|
29
35
|
message = _('Failed to deliver %{notification_name} for Hosts %{hosts}') % {
|
30
36
|
:notification_name => humanized_name,
|
31
37
|
:hosts => hosts.map(&:name).to_sentence
|
32
38
|
}
|
33
|
-
Foreman::Logging.exception(message,
|
39
|
+
Foreman::Logging.exception(message, e)
|
34
40
|
end
|
35
41
|
|
36
42
|
def deliver_ui_notifications
|
37
43
|
all_hosts.each do |host|
|
44
|
+
logger.info "Deliving UI notification '#{humanized_name}' for host '#{host}'."
|
38
45
|
build_ui_notification(host).deliver!
|
39
46
|
end
|
40
47
|
end
|
41
48
|
|
42
|
-
delegate :logger, :to => :
|
49
|
+
delegate :logger, :to => :ForemanExpireHosts
|
43
50
|
|
44
51
|
def humanized_name
|
45
52
|
_('Notification')
|
@@ -59,11 +66,13 @@ module ForemanExpireHosts
|
|
59
66
|
return global_recipients if global_recipients.present?
|
60
67
|
return [User.anonymous_admin] if host.owner.blank?
|
61
68
|
return [host.owner] if host.owner_type == 'User'
|
69
|
+
|
62
70
|
host.owner.all_users
|
63
71
|
end
|
64
72
|
|
65
73
|
def additional_recipients
|
66
74
|
return [] if Setting[:host_expiry_email_recipients].nil?
|
75
|
+
|
67
76
|
Setting[:host_expiry_email_recipients].split(',').compact.map(&:strip)
|
68
77
|
end
|
69
78
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ForemanExpireHosts
|
2
4
|
class SafeDestroy
|
3
5
|
# See http://projects.theforeman.org/issues/14702 for reasoning.
|
@@ -13,18 +15,18 @@ module ForemanExpireHosts
|
|
13
15
|
# See https://community.theforeman.org/t/how-to-properly-destroy-a-content-host/8621
|
14
16
|
# for reasoning.
|
15
17
|
if subject.is_a?(Host::Base) && with_katello?
|
16
|
-
Katello::RegistrationManager.unregister_host(
|
18
|
+
Katello::RegistrationManager.unregister_host(subject)
|
17
19
|
else
|
18
20
|
subject.destroy!
|
19
21
|
end
|
20
|
-
rescue ActiveRecord::RecordNotDestroyed =>
|
22
|
+
rescue ActiveRecord::RecordNotDestroyed => e
|
21
23
|
message = _('Failed to delete %{class_name} %{subject}: %{message} - Errors: %{errors}') % {
|
22
24
|
:class_name => subject.class.name,
|
23
25
|
:subject => subject,
|
24
|
-
:message =>
|
25
|
-
:errors =>
|
26
|
+
:message => e.message,
|
27
|
+
:errors => e.record.errors.full_messages.to_sentence
|
26
28
|
}
|
27
|
-
Foreman::Logging.exception(message,
|
29
|
+
Foreman::Logging.exception(message, e)
|
28
30
|
false
|
29
31
|
end
|
30
32
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ForemanExpireHosts
|
2
4
|
module UINotifications
|
3
5
|
module Hosts
|
@@ -6,6 +8,7 @@ module ForemanExpireHosts
|
|
6
8
|
|
7
9
|
def create
|
8
10
|
return add_notification unless find_notification
|
11
|
+
|
9
12
|
redeliver! if redeliver?
|
10
13
|
find_notification
|
11
14
|
end
|
@@ -45,7 +48,7 @@ module ForemanExpireHosts
|
|
45
48
|
|
46
49
|
def redeliver!
|
47
50
|
recipients = find_notification.notification_recipients
|
48
|
-
recipients.update_all(seen: false)
|
51
|
+
recipients.update_all(seen: false)
|
49
52
|
recipients.pluck(:user_id).each do |user_id|
|
50
53
|
::UINotifications::CacheHandler.new(user_id).clear
|
51
54
|
end
|
@@ -1,22 +1,13 @@
|
|
1
|
-
<% if @host.can_modify_expiry_date? %>
|
2
|
-
<%= stylesheet 'foreman_expire_hosts/application' %>
|
3
|
-
<%= javascript 'foreman_expire_hosts/application' %>
|
4
|
-
<% end %>
|
5
1
|
<%= datepicker_f f, :expired_on,
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
:help_block => ('<span class="pficon-warning-triangle-o"></span> '.html_safe + _('You are not allowed to change the expiry date of this host.') unless @host.can_modify_expiry_date?),
|
18
|
-
:readonly => !@host.can_modify_expiry_date?,
|
19
|
-
:help_inline => popover('Auto Expiry', _('Host will be deleted automatically on given expiry date.') + '<br>'.html_safe +
|
20
|
-
_('Leave blank to keep the host until deleted manually')),
|
21
|
-
:onfocus => 'append_shortcuts()'
|
2
|
+
{
|
3
|
+
:label => _('Expires on'),
|
4
|
+
:autocomplete => false,
|
5
|
+
:include_blank => true,
|
6
|
+
:use_month_numbers => false,
|
7
|
+
:start_year => Date.today.year,
|
8
|
+
:help_block => ('<span class="pficon-warning-triangle-o"></span> '.html_safe + _('You are not allowed to change the expiry date of this host.') unless @host.can_modify_expiry_date?),
|
9
|
+
:disabled => !@host.can_modify_expiry_date?,
|
10
|
+
:help_inline => popover('Auto Expiry', _('Expired hosts will be deleted automatically after the grace period has passed.') + '<br>'.html_safe +
|
11
|
+
_('If you do not want this host to expire and do not want it to be deleted automatically, do not specify an expiry date.'))
|
12
|
+
}
|
22
13
|
%>
|
@@ -1,23 +1,18 @@
|
|
1
|
-
<%= stylesheet 'foreman_expire_hosts/application' %>
|
2
|
-
<%= javascript 'foreman_expire_hosts/application' %>
|
3
1
|
<%= render 'selected_hosts', :hosts => @hosts %>
|
4
2
|
|
5
3
|
<%= form_for :host, :url => update_multiple_expiration_hosts_path(:host_ids => params[:host_ids]) do |f| %>
|
6
4
|
|
7
|
-
<%= _('
|
5
|
+
<%= _('Hosts will be deleted automatically on the given expiry date. Leave blank to clear expiration date.') %>
|
8
6
|
|
9
7
|
<%= datepicker_f f, :expired_on,
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
:autocomplete => false,
|
20
|
-
:placeholder => 'dd/mm/yyyy',
|
21
|
-
:onfocus => 'append_shortcuts()'
|
8
|
+
{
|
9
|
+
:autocomplete => false,
|
10
|
+
:include_blank => true,
|
11
|
+
:use_month_numbers => false,
|
12
|
+
:start_year => Date.today.year
|
13
|
+
},
|
14
|
+
{
|
15
|
+
:onchange => 'tfm.hosts.table.toggleMultipleOkButton(this);'
|
16
|
+
}
|
22
17
|
%>
|
23
18
|
<% end %>
|
data/config/routes.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
Foreman::Application.routes.draw do
|
2
4
|
post 'expired_hosts/select_multiple_expiration' => 'hosts#select_multiple_expiration', as: 'select_multiple_expiration_hosts'
|
3
5
|
post 'expired_hosts/update_multiple_expiration' => 'hosts#update_multiple_expiration', as: 'update_multiple_expiration_hosts'
|
@@ -0,0 +1,8 @@
|
|
1
|
+
SHELL=/bin/sh
|
2
|
+
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
3
|
+
|
4
|
+
RAILS_ENV=production
|
5
|
+
FOREMAN_HOME=/usr/share/foreman
|
6
|
+
|
7
|
+
# Send out notifications about expired hosts
|
8
|
+
45 7 * * * foreman /usr/sbin/foreman-rake expired_hosts:deliver_notifications >>/var/log/foreman/expired_hosts.log 2>&1
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require File.expand_path('lib/foreman_expire_hosts/version', __dir__)
|
2
4
|
require 'date'
|
3
5
|
|
@@ -8,7 +10,10 @@ Gem::Specification.new do |s|
|
|
8
10
|
s.authors = ['Nagarjuna Rachaneni', 'Timo Goebel']
|
9
11
|
s.email = ['nn.nagarjuna@gmail.com', 'mail@timogoebel.name']
|
10
12
|
s.summary = 'Foreman plugin for limiting host lifetime'
|
11
|
-
s.description =
|
13
|
+
s.description = <<~DESC
|
14
|
+
A Foreman plugin that allows hosts to expire at a configurable date.
|
15
|
+
Hosts will be shut down and automatically deleted after a grace period.
|
16
|
+
DESC
|
12
17
|
s.homepage = 'https://github.com/theforeman/foreman_expire_hosts'
|
13
18
|
s.licenses = ['GPL-3.0']
|
14
19
|
|
@@ -18,9 +23,11 @@ Gem::Specification.new do |s|
|
|
18
23
|
|
19
24
|
s.require_paths = ['lib']
|
20
25
|
|
21
|
-
s.add_dependency 'bootstrap-datepicker-rails'
|
22
26
|
s.add_dependency 'deface'
|
23
27
|
|
24
28
|
s.add_development_dependency 'rdoc'
|
25
|
-
s.add_development_dependency 'rubocop', '0.
|
29
|
+
s.add_development_dependency 'rubocop', '~> 0.80.0'
|
30
|
+
s.add_development_dependency 'rubocop-minitest', '~> 0.7.0'
|
31
|
+
s.add_development_dependency 'rubocop-performance', '~> 1.5.2'
|
32
|
+
s.add_development_dependency 'rubocop-rails', '~> 2.4.2'
|
26
33
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ExpireHostsNotifications
|
2
4
|
class << self
|
3
5
|
def delete_expired_hosts
|
@@ -10,6 +12,7 @@ module ExpireHostsNotifications
|
|
10
12
|
|
11
13
|
def deliver_expiry_warning_notification(num = 1) # notify1_days_before_expiry
|
12
14
|
return unless [1, 2].include?(num)
|
15
|
+
|
13
16
|
days_before_expiry = Setting["notify#{num}_days_before_host_expiry"].to_i
|
14
17
|
expiry_date = (Date.today + days_before_expiry)
|
15
18
|
notifiable_hosts = Host.with_expire_date(expiry_date).preload(:owner)
|