foreman_expire_hosts 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rubocop.yml +54 -0
  4. data/.rubocop_todo.yml +74 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE +674 -0
  7. data/README.md +124 -0
  8. data/app/assets/javascripts/foreman_expire_hosts/application.js +3 -0
  9. data/app/assets/javascripts/foreman_expire_hosts/datepicker_for_host_expired_on_field.js +27 -0
  10. data/app/assets/stylesheets/foreman_expire_hosts/application.scss +4 -0
  11. data/app/controllers/concerns/foreman_expire_hosts/host_controller_extensions.rb +73 -0
  12. data/app/helpers/concerns/foreman_expire_hosts/hosts_helper_extensions.rb +41 -0
  13. data/app/helpers/expire_hosts_mailer_helper.rb +15 -0
  14. data/app/mailers/expire_hosts_mailer.rb +37 -0
  15. data/app/models/concerns/foreman_expire_hosts/host_ext.rb +86 -0
  16. data/app/models/host_status/expiration_status.rb +57 -0
  17. data/app/models/setting/expire_hosts.rb +21 -0
  18. data/app/overrides/add_expired_on_field_to_host_form.rb +6 -0
  19. data/app/overrides/add_expired_on_field_to_host_show.rb +6 -0
  20. data/app/overrides/add_js_to_host_index.rb +6 -0
  21. data/app/overrides/deleted_expired_host_comment_in_audits.rb +13 -0
  22. data/app/views/expire_hosts_mailer/_hosts_table.html.erb +40 -0
  23. data/app/views/expire_hosts_mailer/deleted_hosts_notification.html.erb +3 -0
  24. data/app/views/expire_hosts_mailer/expiry_warning_notification.html.erb +4 -0
  25. data/app/views/expire_hosts_mailer/failed_to_delete_hosts_notification.html.erb +4 -0
  26. data/app/views/expire_hosts_mailer/failed_to_stop_hosts_notification.html.erb +4 -0
  27. data/app/views/expire_hosts_mailer/stopped_hosts_notification.html.erb +4 -0
  28. data/app/views/hosts/_expired_message.html.erb +4 -0
  29. data/app/views/hosts/_expired_on_field.html.erb +20 -0
  30. data/app/views/hosts/select_multiple_expiration.html.erb +23 -0
  31. data/config/routes.rb +4 -0
  32. data/db/migrate/20150427101516_add_expiry_on_to_hosts.rb +5 -0
  33. data/foreman_expire_hosts.gemspec +26 -0
  34. data/lib/expire_hosts_notifications.rb +121 -0
  35. data/lib/foreman_expire_hosts/engine.rb +61 -0
  36. data/lib/foreman_expire_hosts/version.rb +3 -0
  37. data/lib/foreman_expire_hosts.rb +3 -0
  38. data/lib/tasks/expired_hosts.rake +46 -0
  39. data/test/factories/foreman_expire_hosts_factories.rb +15 -0
  40. data/test/functional/concerns/hosts_controller_extensions_test.rb +45 -0
  41. data/test/test_plugin_helper.rb +10 -0
  42. data/test/unit/concerns/host_extensions_test.rb +136 -0
  43. data/test/unit/host_status/expiration_status_test.rb +28 -0
  44. metadata +153 -0
data/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # foreman\_expire\_hosts
2
+
3
+ # Context
4
+
5
+ Foreman makes host creation extremely simple for a sysadmin or a user. However this simplicity lead to wasteful usage of compute resources. foreman_expiry plugin allows to specify an expiry date for the host. On this date the host will be deleted.
6
+
7
+ This plugin add expired on(date) field to host form under Additional Information section. If we create any host with expiry date, then that host will be stopped on given date and then deleted. If host has null/blank for expired on field then that host will be live forever (until it deleted manually).
8
+
9
+ This plugin will send two warning notification before host expiry (see settings.yaml). It also sends notifications when the host stopped on its expiry date and when host is deleted after few days (configured in settings).
10
+
11
+ # Screenshots
12
+ ![Expiry date field in host form](https://raw.githubusercontent.com/ingenico-group/screenshots/master/foreman_host_expiry/expiry-date-field-in-host-form.png)
13
+
14
+ ![Expiry date field in host show page](https://raw.githubusercontent.com/ingenico-group/screenshots/master/foreman_host_expiry/expiry-date-in-host-show-page.png)
15
+
16
+ ![Plugin Settings](https://raw.githubusercontent.com/ingenico-group/screenshots/master/foreman_host_expiry/settings.png)
17
+
18
+
19
+ # Installation
20
+ Please see the Foreman manual for appropriate instructions:
21
+
22
+ * [Foreman: How to Install a Plugin](http://theforeman.org/manuals/latest/index.html#6.Plugins)
23
+
24
+ Example installation from source.
25
+ Require foreman_expire_hosts gem installation (edit `~foreman/bundler.d/Gemfile.local.rb`):
26
+
27
+ ```yaml
28
+ gem 'foreman_expire_hosts', :git => "https://github.com/ingenico-group/foreman_expire_hosts.git"
29
+ ```
30
+
31
+ Update Foreman with the new gems:
32
+
33
+ bundle update foreman_expire_hosts
34
+
35
+ # Dependency
36
+
37
+ This gem required uglifier, execjs and therubyracer gems to load assets. If you install this plugin through RPM package, please install ruby193-rubygem-uglifier, ruby193-rubygem-execjs and ruby193-rubygem-therubyracer rpm package before installing this plugin RPM package
38
+
39
+ # Post installation
40
+
41
+ This plugin needs additional column in hosts table. Please run migration with below command
42
+
43
+ ```yaml
44
+ VERSION=20150427101516 RAILS_ENV=production rake db:migrate:up
45
+ ```
46
+
47
+ Add below line to crontab under root user to take appropriate action on expiring/expired hosts and notify user about those hosts. This cronjob will run at 11:30 PM(Midnight)
48
+
49
+
50
+ ```
51
+ 30 23 * * * /usr/sbin/foreman-rake expired_hosts:deliver_notifications >> /var/log/foreman/expired_hosts.log 2>&1
52
+ ```
53
+
54
+ # Pre remove
55
+
56
+ If we want to remove this feature and remove expired_on column from hosts table, please run below rake task and remove this gem from the Gemfile
57
+
58
+ ```yaml
59
+ VERSION=20150427101516 RAILS_ENV=production rake db:migrate:down
60
+ ```
61
+
62
+ # Configuration
63
+
64
+ This plugin will add configurations to settings table and are editable from settings page
65
+
66
+ ![Plugin Settings](https://raw.githubusercontent.com/ingenico-group/screenshots/master/foreman_host_expiry/settings.png)
67
+
68
+ NOTE: After installing this plugin, please update administrator email in Foreman Web UI (More -> Settings -> General) with valid email. This can be used to send notification when plugin failed to deliver notifications to its owner.
69
+
70
+
71
+ # Foreman API to add expiry date to host
72
+
73
+ Existing foreman host create/edit API can be used to add/update host's expiry date. For example
74
+
75
+ Create host with expiry date
76
+
77
+ ```yaml
78
+ POST /api/hosts
79
+ {
80
+ "host": {
81
+ "name": "testhost11",
82
+ "environment_id": "334344675",
83
+ "domain_id": "22495316",
84
+ "ip": "10.0.0.20",
85
+ "mac": "52:53:00:1e:85:93",
86
+ "ptable_id": "980190962",
87
+ "medium_id": "980190962",
88
+ "architecture_id": "501905019",
89
+ "operatingsystem_id": "1073012828",
90
+ "puppet_proxy_id": "980190962",
91
+ "compute_resource_id": "980190962",
92
+ "root_pass": "xybxa6JUkz63w",
93
+ "location_id": "255093256",
94
+ "organization_id": "447626438",
95
+ "expired_on": "30/12/2014" # dd/mm/yyyy format
96
+ }
97
+ }
98
+ ```
99
+
100
+ curl command example
101
+
102
+ ```yaml
103
+ curl -u admin:changeme 'https://your-foreman-url.com/api/hosts' -d 'host[name]=testhost11&host[expired_on]=30/12/2014&......' -X POST
104
+ ```
105
+ Update host expiry date
106
+
107
+ ```yaml
108
+ POST /api/hosts/testhost11
109
+ {
110
+ "host": {
111
+ "expired_on": "30/12/2014" # dd/mm/yyyy format
112
+ }
113
+ }
114
+ ```
115
+
116
+ curl command example
117
+
118
+ ```yaml
119
+ curl -u admin:changeme 'https://your-foreman-url.com/api/hosts/testhost11' -d 'host[expired_on]=30/12/2014' -X PUT
120
+ ```
121
+
122
+ ## License
123
+
124
+ GPLv3
@@ -0,0 +1,3 @@
1
+ //= require bootstrap-datepicker
2
+ //= require foreman_expire_hosts/datepicker_for_host_expired_on_field
3
+
@@ -0,0 +1,27 @@
1
+ var shortcuts = {"1 day": 1, "1 week": 7, "1 month": 30, "1 year": 365, "3 days": 3, "3 weeks": 21, "3 months": 90};
2
+ function append_shortcuts() {
3
+ if ($(".datepicker-days #datepicker_shortcuts").length == 0) {
4
+ var shortcuts_html = "<div id='datepicker_shortcuts'><div>";
5
+ var shortcut_item = 1;
6
+ $.each(shortcuts, function (lable, days) {
7
+ var today = new Date();
8
+ today.setDate(today.getDate() + days);
9
+ if (shortcut_item == 5) {
10
+ shortcuts_html += "</div><div style='padding-top: 3px'>"
11
+ }
12
+ shortcuts_html += "<a style='width: 65px;' class='btn btn-default btn-xs' role='button' title='" + $.fn.datepicker.dates.en.monthsShort[today.getMonth()] + " " + today.getDate() + " " + today.getFullYear() + "' onclick='populate_date_from_days(" + days + ")'>" + lable + "</a>&nbsp;";
13
+ shortcut_item += 1
14
+ });
15
+ shortcuts_html += "</div></div>";
16
+ $(".datepicker-days table").before(shortcuts_html)
17
+ }
18
+ }
19
+
20
+ function populate_date_from_days(shortcut_days) {
21
+ var today = new Date();
22
+ today.setDate(today.getDate() + shortcut_days);
23
+ $('#host_expired_on').datepicker('setDate', today);
24
+ $('#host_expired_on').datepicker('remove');
25
+ //$('#host_expired_on').val(today.getDate()+'/'+(today.getMonth()+1)+'/'+today.getFullYear())
26
+ //$('#host_expired_on').datepicker('hide')
27
+ }
@@ -0,0 +1,4 @@
1
+ /*
2
+ *= require_self
3
+ *= require bootstrap-datepicker3
4
+ */
@@ -0,0 +1,73 @@
1
+ module ForemanExpireHosts
2
+ module HostControllerExtensions
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ before_filter :validate_multiple_expiration, :only => :update_multiple_expiration
7
+ before_filter :find_multiple, :only => [:select_multiple_expiration, :update_multiple_expiration]
8
+ alias_method_chain :action_permission, :expire_hosts
9
+ end
10
+
11
+ def select_multiple_expiration
12
+ end
13
+
14
+ def update_multiple_expiration
15
+ expiration_date = params[:host][:expired_on]
16
+ expiration_date = Date.parse(expiration_date) if expiration_date.present?
17
+
18
+ failed_hosts = {}
19
+
20
+ @hosts.each do |host|
21
+ begin
22
+ host.expired_on = expiration_date
23
+ host.save!
24
+ rescue => error
25
+ failed_hosts[host.name] = error
26
+ message = if expiration_date.present?
27
+ _('Failed to set expiration date for %{host} to %{expiration_date}.') % {:host => host, :expiration_date => l(expiration_date)}
28
+ else
29
+ _('Failed to clear expiration date for %s.') % host
30
+ end
31
+ Foreman::Logging.exception(message, error)
32
+ end
33
+ end
34
+
35
+ if failed_hosts.empty?
36
+ if expiration_date.present?
37
+ notice _('The expiration date of the selected hosts was set to %s.') % l(expiration_date)
38
+ else
39
+ notice _('The expiration date of the selected hosts was cleared.')
40
+ end
41
+ else
42
+ error n_('The expiration date could not be set for host: %s.',
43
+ 'The expiration date could not be set for hosts: %s.',
44
+ failed_hosts.count) % failed_hosts.map { |h, err| "#{h} (#{err})" }.to_sentence
45
+ end
46
+ redirect_back_or_to hosts_path
47
+ end
48
+
49
+ private
50
+
51
+ def validate_multiple_expiration
52
+ if params[:host].nil? || (expiration_date = params[:host][:expired_on]).nil?
53
+ error _('No expiration date selected!')
54
+ redirect_to(select_multiple_expiration_hosts_path) && (return false)
55
+ end
56
+ begin
57
+ Date.parse(expiration_date) if expiration_date.present?
58
+ rescue ArgumentError
59
+ error _('Invalid expiration date!')
60
+ redirect_to(select_multiple_expiration_hosts_path) && (return false)
61
+ end
62
+ end
63
+
64
+ def action_permission_with_expire_hosts
65
+ case params[:action]
66
+ when 'select_multiple_expiration', 'update_multiple_expiration'
67
+ :edit
68
+ else
69
+ action_permission_without_expire_hosts
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,41 @@
1
+ module ForemanExpireHosts
2
+ module HostsHelperExtensions
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ alias_method_chain :multiple_actions, :expire_hosts
7
+ end
8
+
9
+ def multiple_actions_with_expire_hosts
10
+ multiple_actions_without_expire_hosts + [[_('Change Expiration'), select_multiple_expiration_hosts_path]]
11
+ end
12
+
13
+ def host_expiry_warning_message(host)
14
+ return nil unless host.expires?
15
+ if host.expired_past_grace_period?
16
+ message = _('This host has expired %s ago and needs to be deleted manually.') % time_ago_in_words(host.expired_on)
17
+ elsif host.expired?
18
+ message = _('This host has expired %{time_ago} ago and will be deleted on %{delete_date}.') % {:delete_date => l(host.expiration_grace_period_end_date), :time_ago => time_ago_in_words(host.expired_on)}
19
+ elsif host.expires_today?
20
+ message = _('This host will expire today.')
21
+ elsif host.pending_expiration?
22
+ message = _('This host will expire in %{distance_of_time} (on %{expire_date}).') % {:expire_date => l(host.expired_on), :distance_of_time => future_time_in_words(host.expired_on)}
23
+ end
24
+ message
25
+ end
26
+
27
+ def destroyed_expired_host_audit_comment_in_list(audit)
28
+ return unless audit.auditable_type.to_s == 'Host' && audit.action == 'destroy' && !audit.comment.blank?
29
+ "<div style='color: #737373;font-size: 14px'>Comment: #{audit.comment}</div>".html_safe
30
+ end
31
+
32
+ def destroyed_expired_host_audit_comment_in_show(audit)
33
+ return unless audit.auditable_type.to_s == 'Host' && audit.action == 'destroy' && !audit.comment.blank?
34
+ "<tr><td>Comment</td><td>#{audit.comment}</td></tr>".html_safe
35
+ end
36
+
37
+ def future_time_in_words(to_time, options = {})
38
+ distance_of_time_in_words(to_time, Time.current, options)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,15 @@
1
+ module ExpireHostsMailerHelper
2
+ def relative_date(date, opts = {})
3
+ return _('N/A') if date.blank?
4
+ opts[:tense] ||= :future if Date.today < date
5
+ opts[:tense] ||= :past if Date.today > date
6
+
7
+ if opts[:tense] == :future
8
+ _('in %s') % (time_ago_in_words date)
9
+ elsif opts[:tense] == :past
10
+ _('%s ago') % (time_ago_in_words date)
11
+ else
12
+ _('today')
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,37 @@
1
+ class ExpireHostsMailer < ApplicationMailer
2
+
3
+ default :content_type => 'text/html', :from => Setting[:email_reply_address] || 'noreply@your-foreman.com'
4
+
5
+ def deleted_hosts_notification(emails, hosts)
6
+ @hosts = hosts
7
+ mail(:to => emails, :subject => 'Deleted expired hosts in Foreman', :importance => 'High')
8
+ end
9
+
10
+ def failed_to_delete_hosts_notification(emails, hosts)
11
+ @hosts = hosts
12
+ mail(:to => emails, :subject => 'Failed to delete expired hosts in Foreman', :importance => 'High')
13
+ end
14
+
15
+ def stopped_hosts_notification(emails, delete_date, hosts)
16
+ @hosts = hosts
17
+ @delete_date = delete_date
18
+ mail(:to => emails, :subject => 'Stopped expired hosts in Foreman', :importance => 'High') do |format|
19
+ format.html { render :layout => 'application_mailer' }
20
+ end
21
+ end
22
+
23
+ def failed_to_stop_hosts_notification(emails, hosts)
24
+ @hosts = hosts
25
+ mail(:to => emails, :subject => 'Failed to stop expired hosts in Foreman', :importance => 'High') do |format|
26
+ format.html { render :layout => 'application_mailer' }
27
+ end
28
+ end
29
+
30
+ def expiry_warning_notification(emails, expiry_date, hosts)
31
+ @hosts = hosts
32
+ @expiry_date = expiry_date
33
+ mail(:to => emails, :subject => 'Expiring hosts in foreman', :importance => 'High') do |format|
34
+ format.html { render :layout => 'application_mailer' }
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,86 @@
1
+ module ForemanExpireHosts
2
+ module HostExt
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ after_validation :validate_expired_on
7
+ attr_accessible :expired_on
8
+
9
+ validates :expired_on, :presence => true, :if => -> { Setting[:is_host_expiry_date_mandatory] }
10
+
11
+ has_one :expiration_status_object, :class_name => 'HostStatus::ExpirationStatus', :foreign_key => 'host_id'
12
+
13
+ before_validation :refresh_expiration_status
14
+
15
+ scope :expiring, -> { where('expired_on IS NOT NULL') }
16
+ scope :with_expire_date, ->(date) { expiring.where('expired_on = ?', date) }
17
+ scope :expired, -> { expiring.where('expired_on < ?', Date.today) }
18
+ scope :expiring_today, -> { expiring.with_expire_date(Date.today) }
19
+ scope :expired_past_grace_period, -> { expiring.where('expired_on < ?', Date.today + Setting[:days_to_delete_after_host_expiration].to_i) }
20
+
21
+ scoped_search :on => :expired_on, :complete_value => :true, :rename => :expires
22
+ end
23
+
24
+ def validate_expired_on
25
+ if self.expires?
26
+ begin
27
+ unless expired_on.to_s.to_date > Date.today
28
+ errors.add(:expired_on, _('must be in the future'))
29
+ end
30
+ rescue => e
31
+ errors.add(:expired_on, _('is invalid'))
32
+ end
33
+ end
34
+ if self.changed.include?('expired_on')
35
+ unless can_modify_expiry_date?
36
+ errors.add(:expired_on, _('no permission to edit'))
37
+ end
38
+ end
39
+ errors[:expired_on].empty?
40
+ end
41
+
42
+ def expires?
43
+ expired_on.present?
44
+ end
45
+
46
+ def expires_today?
47
+ return false unless expires?
48
+ expired_on.to_date == Date.today
49
+ end
50
+
51
+ def expired?
52
+ return false unless expires?
53
+ expired_on.to_date < Date.today
54
+ end
55
+
56
+ def expiration_grace_period_end_date
57
+ return nil unless expires?
58
+ expired_on + Setting[:days_to_delete_after_host_expiration].to_i
59
+ end
60
+
61
+ def expired_past_grace_period?
62
+ return false unless expires?
63
+ expiration_grace_period_end_date < Date.today
64
+ end
65
+
66
+ def pending_expiration_start_date
67
+ Date.today - Setting['notify1_days_before_host_expiry'].to_i
68
+ end
69
+
70
+ def pending_expiration?
71
+ return false unless expires?
72
+ return false if expired?
73
+ pending_expiration_start_date <= expired_on
74
+ end
75
+
76
+ def can_modify_expiry_date?
77
+ (new_record? || (defined?(Rails::Console) || (User.current && (User.current.admin || (Setting[:can_owner_modify_host_expiry_date] || ((owner_type == 'User' && owner.id == User.current.id) || (owner_type == 'Usergroup' && owner.users.map(&:id).include?(User.current.id))))))))
78
+ end
79
+
80
+ private
81
+
82
+ def refresh_expiration_status
83
+ self.get_status(HostStatus::ExpirationStatus).refresh
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,57 @@
1
+ module HostStatus
2
+ class ExpirationStatus < HostStatus::Status
3
+ OK = 0
4
+ EXPIRED = 1
5
+ IN_GRACE_PERIOD = 2
6
+ EXPIRES_TODAY = 3
7
+ PENDING = 4
8
+
9
+ def self.status_name
10
+ N_('Expiration Status')
11
+ end
12
+
13
+ def to_status(_options = {})
14
+ return EXPIRED if host.expired_past_grace_period?
15
+ return IN_GRACE_PERIOD if host.expired?
16
+ return EXPIRES_TODAY if host.expires_today?
17
+ return PENDING if host.pending_expiration?
18
+ OK
19
+ end
20
+
21
+ def to_global(_options = {})
22
+ case to_status
23
+ when OK
24
+ HostStatus::Global::OK
25
+ when EXPIRES_TODAY
26
+ HostStatus::Global::WARN
27
+ when IN_GRACE_PERIOD
28
+ HostStatus::Global::ERROR
29
+ when EXPIRED
30
+ HostStatus::Global::ERROR
31
+ when PENDING
32
+ HostStatus::Global::ERROR
33
+ else
34
+ HostStatus::Global::OK
35
+ end
36
+ end
37
+
38
+ def to_label(_options = {})
39
+ case to_status
40
+ when OK
41
+ N_('Expires on %s') % I18n.l(host.expired_on)
42
+ when EXPIRES_TODAY
43
+ N_('Expires today')
44
+ when IN_GRACE_PERIOD
45
+ N_('Expired on %s, in grace period') % I18n.l(host.expired_on)
46
+ when EXPIRED
47
+ N_('Expired on %s') % I18n.l(host.expired_on)
48
+ else
49
+ N_('Pending expiration on %s') % I18n.l(host.expired_on)
50
+ end
51
+ end
52
+
53
+ def relevant?(options = {})
54
+ host.expires?
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,21 @@
1
+ class Setting::ExpireHosts < Setting
2
+
3
+ def self.load_defaults
4
+ # Check the table exists
5
+ return unless super
6
+
7
+ self.transaction do
8
+ [
9
+ self.set('is_host_expiry_date_mandatory', N_('Make expiry date field mandatory on host creation/update'), false, N_('Require host expiry date')),
10
+ self.set('can_owner_modify_host_expiry_date', N_('Allow host owner to modify host expiry date field. If the field is false then admin only can edit expiry field'), false, N_('Host owner can modify host expiry date')),
11
+ self.set('notify1_days_before_host_expiry', N_('Send first notification to owner of hosts about his hosts expiring in given days. Must be integer only'), 7, N_('First expiry notification')),
12
+ self.set('notify2_days_before_host_expiry', N_('Send second notification to owner of hosts about his hosts expiring in given days. Must be integer only'), 1, N_('Second expiry notification')),
13
+ self.set('days_to_delete_after_host_expiration', N_('Delete expired hosts after given days of hosts expiry date. Must be integer only'), 3, N_('Expiry grace period in days')),
14
+ self.set('host_expiry_email_recipients', N_('All notifications will be delivered to its owner. If any other users/admins need to receive those expiry wanting notifications then those emails can be configured here. This must be string and multiple emails can give with coma(,) separated'), 'foreman-admin@your_foreman.com', N_('Expiry e-mail recipients'))
15
+ ].each { |s| self.create! s.update(:category => 'Setting::ExpireHosts') }
16
+ end
17
+
18
+ true
19
+ end
20
+
21
+ end
@@ -0,0 +1,6 @@
1
+ Deface::Override.new(
2
+ :virtual_path => 'hosts/_form',
3
+ :name => 'host_form_expired_on_field',
4
+ :insert_after => 'div#model_name',
5
+ :partial => 'hosts/expired_on_field'
6
+ )
@@ -0,0 +1,6 @@
1
+ Deface::Override.new(
2
+ :virtual_path => 'hosts/show',
3
+ :name => 'host_expiry_waring_in_show',
4
+ :insert_before => '#host-show',
5
+ :partial => 'hosts/expired_message.html.erb'
6
+ )
@@ -0,0 +1,6 @@
1
+ Deface::Override.new(
2
+ :virtual_path => 'hosts/_list',
3
+ :name => 'host_list_expiration_js',
4
+ :insert_before => '#confirmation-modal',
5
+ :text => "<%= stylesheet 'foreman_expire_hosts/application' %><%= javascript 'foreman_expire_hosts/application' %>"
6
+ )
@@ -0,0 +1,13 @@
1
+ Deface::Override.new(
2
+ :virtual_path => 'audits/_list',
3
+ :name => 'deleted_expired_host_audit_comment_in_list',
4
+ :insert_bottom => 'div.row div.audit-content',
5
+ :text => "\n <%= destroyed_expired_host_audit_comment_in_list(audit) %>"
6
+ )
7
+
8
+ Deface::Override.new(
9
+ :virtual_path => 'audits/show',
10
+ :name => 'deleted_expired_host_audit_comment_in_show',
11
+ :insert_bottom => 'div#tab1 table',
12
+ :text => "\n <%= destroyed_expired_host_audit_comment_in_show(@audit) %>"
13
+ )
@@ -0,0 +1,40 @@
1
+ <table>
2
+ <thead>
3
+ <tr>
4
+ <th>
5
+ <%= _('Hostname') %>
6
+ </th>
7
+ <th>
8
+ <%= _('Host group') %>
9
+ </th>
10
+ <th>
11
+ <%= _('Environment') %>
12
+ </th>
13
+ <th>
14
+ <%= _('Expiration Date') %>
15
+ </th>
16
+ </tr>
17
+ </thead>
18
+ <tbody>
19
+ <% hosts.each do |host| %>
20
+ <tr>
21
+ <td class="hosts-rows">
22
+ <% if link_to_hosts %>
23
+ <%= link_to host, host_url(:id => host, :only_path => true) %>
24
+ <% else %>
25
+ <%= host %>
26
+ <% end %>
27
+ </td>
28
+ <td class="hosts-rows">
29
+ <%= host.hostgroup %>
30
+ </td>
31
+ <td class="hosts-rows">
32
+ <%= host.environment %>
33
+ </td>
34
+ <td class="hosts-rows">
35
+ <%= "#{l(host.expired_on)} (#{relative_date(host.expired_on)})" if host.expires? %>
36
+ </td>
37
+ </tr>
38
+ <% end %>
39
+ </tbody>
40
+ </table>
@@ -0,0 +1,3 @@
1
+ <%= _("The following hosts have been deleted from Foreman:") %> <br/><br/>
2
+
3
+ <%= render 'hosts_table', :hosts => @hosts, :link_to_hosts => false %>
@@ -0,0 +1,4 @@
1
+ <%= _('The following hosts will be expired on %s. Please change expiry date if you want to keep these hosts alive.') % @expiry_date %>
2
+ <br/><br/>
3
+
4
+ <%= render 'hosts_table', :hosts => @hosts, :link_to_hosts => true %>
@@ -0,0 +1,4 @@
1
+ <%= _('Failed to delete the following expired hosts in Foreman. Please delete them manually.') %>
2
+ <br/><br/>
3
+
4
+ <%= render 'hosts_table', :hosts => @hosts, :link_to_hosts => true %>
@@ -0,0 +1,4 @@
1
+ <%= _('Failed to stop the following expired hosts in Foreman. Please stop them manually.') %>
2
+ <br/><br/>
3
+
4
+ <%= render 'hosts_table', :hosts => @hosts, :link_to_hosts => true %>
@@ -0,0 +1,4 @@
1
+ <%= _('The following hosts have been expired in Foreman and will be stopped for now. These hosts will be destroyed on %s. Please change their expiry date and power them on if you want to keep the hosts.') % l @delete_date %>
2
+ <br/><br/>
3
+
4
+ <%= render 'hosts_table', :hosts => @hosts, :link_to_hosts => true %>
@@ -0,0 +1,4 @@
1
+ <% expiry_message = host_expiry_warning_message(@host) %>
2
+ <% if expiry_message.present? %>
3
+ <%= alert(:text => expiry_message, :class => 'alert-warning') %>
4
+ <% end %>
@@ -0,0 +1,20 @@
1
+ <% if @host.can_modify_expiry_date? %>
2
+ <%= stylesheet 'foreman_expire_hosts/application' %>
3
+ <%= javascript 'foreman_expire_hosts/application' %>
4
+ <% end %>
5
+ <%= text_f f, :expired_on,
6
+ :value => @host.expired_on.try(:strftime, '%d/%m/%Y'),
7
+ :data => { provide: @host.can_modify_expiry_date? ? 'datepicker' : 'readonly',
8
+ orientation: 'top left',
9
+ date_autoclose: true,
10
+ date_clear_btn: true,
11
+ date_format: 'dd/mm/yyyy',
12
+ date_start_date: Date.tomorrow.strftime('%d/%m/%Y'),
13
+ date_today_highlight: true
14
+ },
15
+ :autocomplete => false,
16
+ :placeholder => 'dd/mm/yyyy',
17
+ :help_inline => popover('Auto Expiry', 'Host will be deleted automatically on given expired date.
18
+ <br> Leave blank to keep the host until deleted manually'),
19
+ :onfocus => 'append_shortcuts()'
20
+ %>
@@ -0,0 +1,23 @@
1
+ <%= stylesheet 'foreman_expire_hosts/application' %>
2
+ <%= javascript 'foreman_expire_hosts/application' %>
3
+ <%= render 'selected_hosts', :hosts => @hosts %>
4
+
5
+ <%= form_for :host, :url => update_multiple_expiration_hosts_path(:host_ids => params[:host_ids]) do |f| %>
6
+
7
+ <%= _('Host will be deleted automatically on given expired date. Leave blank to clear expiration date.') %>
8
+
9
+ <%= text_f f, :expired_on,
10
+ :value => (Date.today + 14).strftime('%d/%m/%Y'),
11
+ :data => { provide: 'datepicker',
12
+ orientation: 'top left',
13
+ date_autoclose: true,
14
+ date_clear_btn: true,
15
+ date_format: 'dd/mm/yyyy',
16
+ date_start_date: Date.tomorrow.strftime('%d/%m/%Y'),
17
+ date_today_highlight: true
18
+ },
19
+ :autocomplete => false,
20
+ :placeholder => 'dd/mm/yyyy',
21
+ :onfocus => 'append_shortcuts()'
22
+ %>
23
+ <% end %>
data/config/routes.rb ADDED
@@ -0,0 +1,4 @@
1
+ Foreman::Application.routes.draw do
2
+ get 'expired_hosts/select_multiple_expiration' => 'hosts#select_multiple_expiration', as: 'select_multiple_expiration_hosts'
3
+ post 'expired_hosts/update_multiple_expiration' => 'hosts#update_multiple_expiration', as: 'update_multiple_expiration_hosts'
4
+ end