foreman_maintain 1.12.2 → 1.12.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 841269b0b17944b3a732b728e7c51ba5c11bdec27b47c45ce6b13fb61ec8be06
4
- data.tar.gz: 966dd22a328585cb68ecb248341b8b566787f7efa6f590eb8dc1877203fdc895
3
+ metadata.gz: a99136516325dc9d13b83ddca246f197ecc63199d74cd950a582946a503fc2eb
4
+ data.tar.gz: c59533ff3ae35ffdece203759eef0d16b3bc67fc9bd5146b32a0988c00821770
5
5
  SHA512:
6
- metadata.gz: f996ba857e7ad9598f6b4e26811710387d8592c2841bb26dbf63660d44774c388312ab217d795dbd24c258767b3c276b048f13ced797927703dd6c85dbde106f
7
- data.tar.gz: 72cc8e83ee3ff2fb76fdcaa226695c05b90fe70ed63bb82b7d65e8307d82cbab6b6141b51a8f5ceaac410648d41f9308744998b255a9ab2e9f8bf43b0d50d8fa
6
+ metadata.gz: d2f883dfe1a9959d2790d856be260073a57a874d3d3e0fadd2c54b4eef1dbaf4979fe20070ffde6699dd2ff86dcb8733426f1eaa4a7213f1c1493a419678bc58
7
+ data.tar.gz: 00a9ee5352ef84dd5b36451e862eedb070806e2b6233042cc35b72a1cd43c6c483b163246f301f833f4c2f3f6edf8bfbd1379463c9cf0060adef2e3ec6fb7258
@@ -5,7 +5,7 @@ module Checks::Container
5
5
  confine do
6
6
  feature(:satellite)&.connected? && feature(:containers)
7
7
  end
8
- description 'Check whether podman is logged in to registry'
8
+ description 'Check whether podman needs to be logged in to the registry'
9
9
  tags :pre_upgrade
10
10
  end
11
11
 
@@ -8,6 +8,22 @@ class Features::Iop < ForemanMaintain::Feature
8
8
  end
9
9
  end
10
10
 
11
+ CONTAINER_NAMES =
12
+ [
13
+ 'insights-engine',
14
+ 'gateway',
15
+ 'host-inventory',
16
+ 'ingress',
17
+ 'puptoo',
18
+ 'yuptoo',
19
+ 'advisor-backend',
20
+ 'advisor-frontend',
21
+ 'remediations',
22
+ 'vmaas',
23
+ 'vulnerability-engine',
24
+ 'vulnerability-frontend',
25
+ ].freeze
26
+
11
27
  def config_files
12
28
  [
13
29
  '/var/lib/containers/storage/volumes/iop-core-kafka-data',
@@ -42,4 +58,32 @@ class Features::Iop < ForemanMaintain::Feature
42
58
  ]
43
59
  end
44
60
  # rubocop:enable Metrics/MethodLength
61
+
62
+ def timers
63
+ [
64
+ system_service('iop-service-vuln-vmaas-sync.timer', 20),
65
+ ]
66
+ end
67
+
68
+ def container_base
69
+ if feature(:instance).downstream
70
+ 'registry.redhat.io/satellite'
71
+ else
72
+ 'quay.io/iop'
73
+ end
74
+ end
75
+
76
+ def container_names
77
+ if feature(:instance).downstream
78
+ CONTAINER_NAMES.map { |container_name| "#{container_name}-rhel9" }
79
+ else
80
+ CONTAINER_NAMES
81
+ end
82
+ end
83
+
84
+ def container_images(container_version)
85
+ container_names.map do |container_name|
86
+ "#{container_base}/#{container_name}:#{container_version}"
87
+ end
88
+ end
45
89
  end
@@ -1,4 +1,7 @@
1
+ require 'foreman_maintain/concerns/systemd'
2
+
1
3
  class Features::Service < ForemanMaintain::Feature
4
+ include ForemanMaintain::Concerns::Systemd
2
5
  metadata do
3
6
  label :service
4
7
  end
@@ -13,10 +16,7 @@ class Features::Service < ForemanMaintain::Feature
13
16
 
14
17
  def existing_services
15
18
  ForemanMaintain.available_features.flat_map(&:services).
16
- sort.
17
- inject([]) do |pool, service| # uniq(&:to_s) for ruby 1.8.7
18
- (pool.last.nil? || !pool.last.matches?(service)) ? pool << service : pool
19
- end.
19
+ sort.uniq(&:to_s).
20
20
  select(&:exist?)
21
21
  end
22
22
 
@@ -30,14 +30,6 @@ class Features::Service < ForemanMaintain::Feature
30
30
  Hash[services.sort_by { |k, _| k.to_i }.reverse]
31
31
  end
32
32
 
33
- def action_noun(action)
34
- action_word_modified(action) + 'ing'
35
- end
36
-
37
- def action_past_tense(action)
38
- action_word_modified(action) + 'ed'
39
- end
40
-
41
33
  def filter_disabled_services!(action, service_list)
42
34
  if %w[start stop restart status].include?(action)
43
35
  service_list.select! { |service| !service.respond_to?(:enabled?) || service.enabled? }
@@ -45,13 +37,6 @@ class Features::Service < ForemanMaintain::Feature
45
37
  service_list
46
38
  end
47
39
 
48
- def unit_file_available?(name)
49
- cmd = "systemctl --no-legend --no-pager list-unit-files --type=service #{name} |\
50
- grep --word-regexp --quiet #{name}"
51
- exit_status, = execute_with_status(cmd)
52
- exit_status == 0
53
- end
54
-
55
40
  private
56
41
 
57
42
  def use_system_service(action, options, spinner)
@@ -96,28 +81,6 @@ class Features::Service < ForemanMaintain::Feature
96
81
  services_and_statuses.map! { |service, status| [service, status.value] }
97
82
  end
98
83
 
99
- def format_status(output, exit_code, options)
100
- status = ''
101
- if !options[:failing] || exit_code > 0
102
- if options[:brief]
103
- status += format_brief_status(exit_code)
104
- elsif !(output.nil? || output.empty?)
105
- status += "\n" + output
106
- end
107
- end
108
- status
109
- end
110
-
111
- def format_brief_status(exit_code)
112
- result = (exit_code == 0) ? reporter.status_label(:success) : reporter.status_label(:fail)
113
- padding = reporter.max_length - reporter.last_line.to_s.length - 30
114
- "#{' ' * padding} #{result}"
115
- end
116
-
117
- def allowed_action?(action)
118
- %w[start stop restart status enable disable].include?(action)
119
- end
120
-
121
84
  def extend_service_list_with_sockets(service_list, options)
122
85
  return service_list unless options[:include_sockets]
123
86
 
@@ -162,21 +125,4 @@ class Features::Service < ForemanMaintain::Feature
162
125
  service_list.concat(unregistered_service_list)
163
126
  service_list
164
127
  end
165
-
166
- def action_word_modified(action)
167
- case action
168
- when 'status'
169
- 'display'
170
- when 'enable', 'disable'
171
- action.chomp('e')
172
- when 'stop'
173
- action + 'p'
174
- else
175
- action
176
- end
177
- end
178
-
179
- def exclude_services_only(options)
180
- existing_services - filtered_services(options)
181
- end
182
128
  end
@@ -0,0 +1,96 @@
1
+ require 'foreman_maintain/concerns/systemd'
2
+
3
+ class Features::Timer < ForemanMaintain::Feature
4
+ include ForemanMaintain::Concerns::Systemd
5
+ metadata do
6
+ label :timer
7
+ end
8
+
9
+ def handle_timers(spinner, action, options = {})
10
+ # options is used to handle "exclude" and "only" i.e.
11
+ # { :only => ["httpd"] }
12
+ # { :exclude => ["pulp-workers", "tomcat"] }
13
+ use_system_timer(action, options, spinner)
14
+ end
15
+
16
+ def existing_timers
17
+ ForemanMaintain.available_features.flat_map(&:timers).
18
+ sort.uniq(&:to_s).
19
+ select(&:exist?)
20
+ end
21
+
22
+ def filtered_timers(options, action = '')
23
+ timers = filter_timers(existing_timers, options, action)
24
+
25
+ raise 'No timers found matching your parameters' unless timers.any?
26
+ return timers unless options[:reverse]
27
+
28
+ Hash[timers.sort_by { |k, _| k.to_i }.reverse]
29
+ end
30
+
31
+ def filter_disabled_timers!(action, timer_list)
32
+ if %w[start stop restart status].include?(action)
33
+ timer_list.select! { |timer| !timer.respond_to?(:enabled?) || timer.enabled? }
34
+ end
35
+ timer_list
36
+ end
37
+
38
+ private
39
+
40
+ def use_system_timer(action, options, spinner)
41
+ options[:reverse] = action == 'stop'
42
+ raise 'Unsupported action detected' unless allowed_action?(action)
43
+
44
+ status, failed_timers = run_action_on_timers(action, options, spinner)
45
+
46
+ spinner.update("All timers #{action_past_tense(action)}")
47
+ if action == 'status'
48
+ raise "Some timers are not running (#{failed_timers.join(', ')})" if status > 0
49
+
50
+ spinner.update('All timers are running')
51
+ end
52
+ end
53
+
54
+ def run_action_on_timers(action, options, spinner)
55
+ status = 0
56
+ failed_timers = []
57
+ filtered_timers(options, action).each_value do |group|
58
+ fork_threads_for_timers(action, group, spinner).each do |timer, status_and_output|
59
+ spinner.update("#{action_noun(action)} #{timer}") if action == 'status'
60
+ item_status, output = status_and_output
61
+ formatted = format_status(output, item_status, options)
62
+ puts formatted unless formatted.empty?
63
+
64
+ if item_status > 0
65
+ status = item_status
66
+ failed_timers << timer
67
+ end
68
+ end
69
+ end
70
+ [status, failed_timers]
71
+ end
72
+
73
+ def fork_threads_for_timers(action, timers, spinner)
74
+ timers_and_statuses = []
75
+ timers.each do |timer|
76
+ spinner.update("#{action_noun(action)} #{timer}") if action != 'status'
77
+ timers_and_statuses << [timer, Thread.new { timer.send(action.to_sym) }]
78
+ end
79
+ timers_and_statuses.map! { |timer, status| [timer, status.value] }
80
+ end
81
+
82
+ def filter_timers(timer_list, options, action)
83
+ if options[:only]&.any?
84
+ timer_list = timer_list.select do |timer|
85
+ options[:only].any? { |opt| timer.matches?(opt) }
86
+ end
87
+ end
88
+
89
+ if options[:exclude]&.any?
90
+ timer_list = timer_list.reject { |timer| options[:exclude].include?(timer.name) }
91
+ end
92
+
93
+ timer_list = filter_disabled_timers!(action, timer_list)
94
+ timer_list.group_by(&:priority).to_h
95
+ end
96
+ end
@@ -0,0 +1,19 @@
1
+ module Procedures::Iop
2
+ class ImagePrune < ForemanMaintain::Procedure
3
+ metadata do
4
+ description 'Prune unused IoP container images'
5
+
6
+ confine do
7
+ feature(:iop)
8
+ end
9
+ end
10
+
11
+ def run
12
+ prune_images
13
+ end
14
+
15
+ def prune_images
16
+ execute!("podman image prune --force")
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ module Procedures::Iop
2
+ class Update < ForemanMaintain::Procedure
3
+ metadata do
4
+ description 'Update IoP containers'
5
+
6
+ confine do
7
+ feature(:iop) && (feature(:satellite)&.connected? || !feature(:satellite))
8
+ end
9
+
10
+ param :version,
11
+ 'Version of the containers to pull',
12
+ :required => true
13
+ end
14
+
15
+ def run
16
+ pull_images
17
+ end
18
+
19
+ def pull_images
20
+ feature(:iop).container_images(@version).each do |container_image|
21
+ execute!("podman pull #{container_image}")
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ module Procedures::Timer
2
+ class Start < ForemanMaintain::Procedure
3
+ metadata do
4
+ description 'Start systemd timers'
5
+
6
+ for_feature :timer
7
+ confine do
8
+ feature(:timer)&.existing_timers&.any?
9
+ end
10
+
11
+ tags :post_migrations
12
+ end
13
+
14
+ def run
15
+ with_spinner('Starting systemd timers') do |spinner|
16
+ feature(:timer).handle_timers(spinner, 'start')
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ module Procedures::Timer
2
+ class Stop < ForemanMaintain::Procedure
3
+ metadata do
4
+ description 'Stop systemd timers'
5
+
6
+ for_feature :timer
7
+ confine do
8
+ feature(:timer)&.existing_timers&.any?
9
+ end
10
+
11
+ tags :pre_migrations
12
+ end
13
+
14
+ def run
15
+ with_spinner('Stopping systemd timers') do |spinner|
16
+ feature(:timer).handle_timers(spinner, 'stop')
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reports
4
+ class Bookmarks < ForemanMaintain::Report
5
+ metadata do
6
+ description 'Report about bookmark usage'
7
+ end
8
+
9
+ def run
10
+ public_count = bookmarks_custom_public_count
11
+ private_count = bookmarks_custom_private_count
12
+
13
+ data_field('bookmarks_custom_public_count') { public_count }
14
+ data_field('bookmarks_custom_private_count') { private_count }
15
+ data_field('bookmarks_custom_count') { public_count + private_count }
16
+ end
17
+
18
+ private
19
+
20
+ def bookmarks_custom_public_count
21
+ # Count public bookmarks that are NOT owned by internal users
22
+ bookmarks_not_owned_by_internal_users(public: true)
23
+ end
24
+
25
+ def bookmarks_custom_private_count
26
+ # Count private bookmarks that are NOT owned by internal users
27
+ bookmarks_not_owned_by_internal_users(public: false)
28
+ end
29
+
30
+ def bookmarks_not_owned_by_internal_users(public:)
31
+ # Helper method to count bookmarks not owned by internal users with optional public filter
32
+ public_condition = public ? 'AND b.public = true' : 'AND b.public = false'
33
+
34
+ sql_count(
35
+ <<~SQL
36
+ bookmarks b
37
+ WHERE (
38
+ b.owner_type = 'User'
39
+ #{public_condition}
40
+ AND b.owner_id NOT IN (
41
+ SELECT u.id
42
+ FROM users u
43
+ INNER JOIN auth_sources a ON u.auth_source_id = a.id
44
+ WHERE a.type = 'AuthSourceHidden'
45
+ )
46
+ )
47
+ SQL
48
+ )
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reports
4
+ class DisconnectedEnvironment < ForemanMaintain::Report
5
+ metadata do
6
+ description 'Checks if the instance is in a disconnected environment'
7
+ end
8
+
9
+ def run
10
+ data_field('disconnected_environment') do
11
+ subscription_connection_setting = sql_setting('subscription_connection_enabled')
12
+
13
+ # If setting doesn't exist, assume connected (not disconnected)
14
+ if subscription_connection_setting.nil?
15
+ false
16
+ else
17
+ # disconnected when subscription_connection_enabled is false
18
+ YAML.safe_load(subscription_connection_setting) == false
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -4,6 +4,7 @@ module Reports
4
4
  description 'Check how resources are grouped'
5
5
  end
6
6
 
7
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
7
8
  def run
8
9
  self.data = {}
9
10
  data_field('host_collections_count') { sql_count('katello_host_collections') }
@@ -26,6 +27,63 @@ module Reports
26
27
  if table_exists('config_groups')
27
28
  data_field('config_group_count') { sql_count('config_groups') }
28
29
  end
30
+
31
+ data_field('usergroup_max_nesting_level') { usergroup_max_nesting_level }
32
+
33
+ usergroup_roles_stats = usergroup_roles_statistics
34
+ data['user_group_roles_max_count'] = usergroup_roles_stats[:max_count]
35
+ data['user_group_roles_min_count'] = usergroup_roles_stats[:min_count]
36
+ end
37
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
38
+
39
+ private
40
+
41
+ def usergroup_max_nesting_level
42
+ # Use recursive CTE to find maximum nesting level of usergroups
43
+ cte_sql = <<~SQL
44
+ WITH RECURSIVE usergroup_hierarchy AS (
45
+ -- Base case: root usergroups (not members of any other usergroup)
46
+ SELECT id, 1 as level
47
+ FROM usergroups
48
+ WHERE id NOT IN (
49
+ SELECT member_id
50
+ FROM usergroup_members
51
+ WHERE member_type = 'Usergroup'
52
+ )
53
+ UNION ALL
54
+ -- Recursive case: usergroups that are members of other usergroups
55
+ SELECT ug.id, uh.level + 1
56
+ FROM usergroups ug
57
+ INNER JOIN usergroup_members ugm ON ug.id = ugm.member_id
58
+ INNER JOIN usergroup_hierarchy uh ON ugm.usergroup_id = uh.id
59
+ WHERE ugm.member_type = 'Usergroup'
60
+ )
61
+ SQL
62
+
63
+ sql_as_count('COALESCE(MAX(level) - 1, 0)', 'usergroup_hierarchy', cte: cte_sql)
64
+ end
65
+
66
+ def usergroup_roles_statistics
67
+ # Query to get role counts per usergroup, including usergroups with 0 roles
68
+ roles_per_usergroup = query(
69
+ <<~SQL
70
+ SELECT ug.id, COALESCE(ur.role_count, 0) as role_count
71
+ FROM usergroups ug
72
+ LEFT JOIN (
73
+ SELECT owner_id, COUNT(*) as role_count
74
+ FROM user_roles
75
+ WHERE owner_type = 'Usergroup'
76
+ GROUP BY owner_id
77
+ ) ur ON ug.id = ur.owner_id
78
+ SQL
79
+ )
80
+
81
+ if roles_per_usergroup.empty?
82
+ { max_count: 0, min_count: 0 }
83
+ else
84
+ role_counts = roles_per_usergroup.map { |row| row['role_count'].to_i }
85
+ { max_count: role_counts.max, min_count: role_counts.min }
86
+ end
29
87
  end
30
88
  end
31
89
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reports
4
+ class LabFeatures < ForemanMaintain::Report
5
+ metadata do
6
+ description 'Checks if lab features are enabled'
7
+ end
8
+
9
+ def run
10
+ data_field('lab_features_enabled') do
11
+ lab_features_setting = sql_setting('lab_features')
12
+ return false if lab_features_setting.nil?
13
+
14
+ # Parse the YAML setting value and convert to boolean
15
+ YAML.safe_load(lab_features_setting) == true
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reports
4
+ class PersonalAccessToken < ForemanMaintain::Report
5
+ metadata do
6
+ description 'Report about Personal Access Token usage'
7
+ end
8
+
9
+ def run
10
+ # Total count of non-revoked personal access tokens
11
+ data_field('pat_counts') do
12
+ sql_count('personal_access_tokens WHERE revoked = false')
13
+ end
14
+
15
+ # Count of tokens that were used recently (updated in last 2 months)
16
+ data_field('pat_recently_used_count') do
17
+ sql_count("personal_access_tokens WHERE updated_at >= NOW() - INTERVAL '2 months'")
18
+ end
19
+
20
+ # Count of revoked personal access tokens
21
+ data_field('revoked_pats_count') do
22
+ sql_count('personal_access_tokens WHERE revoked = true')
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reports
4
+ class Selinux < ForemanMaintain::Report
5
+ metadata do
6
+ description 'Report about SELinux enforcement status'
7
+ end
8
+
9
+ def run
10
+ data_field('selinux_enforced') { selinux_enforced? }
11
+ end
12
+
13
+ private
14
+
15
+ def selinux_enforced?
16
+ # Check if getenforce command exists and SELinux is installed
17
+ return false unless command_present?('getenforce')
18
+
19
+ # Execute getenforce command and check if SELinux is enforcing
20
+ status = execute('getenforce').strip.downcase
21
+ status == 'enforcing'
22
+ rescue StandardError
23
+ # If any error occurs, assume SELinux is not enforced
24
+ false
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reports
4
+ class Webhooks < ForemanMaintain::Report
5
+ metadata do
6
+ description 'Report about webhook usage'
7
+ end
8
+
9
+ def run
10
+ data_field('webhooks_enabled_count') { sql_count('webhooks WHERE enabled = true') }
11
+ data_field('webhooks_subscribed_events') { webhooks_subscribed_events }
12
+ data_field('shell_hooks_count') { sql_count('webhooks WHERE proxy_authorization = true') }
13
+ end
14
+
15
+ private
16
+
17
+ def webhooks_subscribed_events
18
+ # Extract all events from webhooks table and join into comma-separated string
19
+ events_data = query('SELECT events FROM webhooks')
20
+
21
+ all_events = []
22
+ events_data.each do |row|
23
+ events_value = row['events']
24
+ next if events_value.nil? || events_value.empty?
25
+
26
+ # Parse the array-like string - handle both JSON array format and simple arrays
27
+ # Remove outer brackets/braces, quotes, and split by comma
28
+ cleaned_value = events_value.gsub(/^[\[{]|[\]}]$/, '').gsub(/["']/, '')
29
+ parsed_events = cleaned_value.split(',').map(&:strip)
30
+ all_events.concat(parsed_events)
31
+ end
32
+
33
+ # Remove duplicates and join with commas
34
+ all_events.uniq.reject(&:empty?).join(',')
35
+ end
36
+ end
37
+ end
@@ -72,6 +72,7 @@ module Scenarios::Foreman
72
72
  add_steps(
73
73
  Procedures::MaintenanceMode::EnableMaintenanceMode,
74
74
  Procedures::Crond::Stop,
75
+ Procedures::Timer::Stop,
75
76
  Procedures::SyncPlans::Disable
76
77
  )
77
78
  end
@@ -113,6 +114,7 @@ module Scenarios::Foreman
113
114
  Procedures::RefreshFeatures,
114
115
  Procedures::Service::Start,
115
116
  Procedures::Crond::Start,
117
+ Procedures::Timer::Start,
116
118
  Procedures::SyncPlans::Enable,
117
119
  Procedures::MaintenanceMode::DisableMaintenanceMode
118
120
  )
@@ -10,6 +10,7 @@ module ForemanMaintain::Scenarios
10
10
  def compose
11
11
  add_step(Procedures::MaintenanceMode::EnableMaintenanceMode)
12
12
  add_step(Procedures::Crond::Stop)
13
+ add_step(Procedures::Timer::Stop)
13
14
  add_step(Procedures::SyncPlans::Disable)
14
15
  end
15
16
  end
@@ -25,6 +26,7 @@ module ForemanMaintain::Scenarios
25
26
  def compose
26
27
  add_step(Procedures::SyncPlans::Enable)
27
28
  add_step(Procedures::Crond::Start)
29
+ add_step(Procedures::Timer::Start)
28
30
  add_step(Procedures::MaintenanceMode::DisableMaintenanceMode)
29
31
  end
30
32
  end
@@ -29,6 +29,7 @@ module ForemanMaintain::Scenarios
29
29
  Procedures::Restore::RequiredPackages,
30
30
  Procedures::Restore::Configs)
31
31
  add_step_with_context(Procedures::Crond::Stop)
32
+ add_step_with_context(Procedures::Timer::Stop)
32
33
  unless backup.incremental?
33
34
  add_steps_with_context(Procedures::Restore::InstallerReset)
34
35
  end
@@ -49,6 +50,7 @@ module ForemanMaintain::Scenarios
49
50
  add_step(Procedures::Installer::Run.new(:assumeyes => true))
50
51
  add_step_with_context(Procedures::Installer::UpgradeRakeTask)
51
52
  add_step_with_context(Procedures::Crond::Start)
53
+ add_step_with_context(Procedures::Timer::Start)
52
54
  end
53
55
  # rubocop:enable Metrics/MethodLength,Metrics/AbcSize
54
56
 
@@ -119,6 +121,7 @@ module ForemanMaintain::Scenarios
119
121
 
120
122
  def compose
121
123
  add_step_with_context(Procedures::Crond::Stop)
124
+ add_step_with_context(Procedures::Timer::Stop)
122
125
  end
123
126
  end
124
127
  end
@@ -74,6 +74,7 @@ module Scenarios::Satellite
74
74
  add_steps(
75
75
  Procedures::MaintenanceMode::EnableMaintenanceMode,
76
76
  Procedures::Crond::Stop,
77
+ Procedures::Timer::Stop,
77
78
  Procedures::SyncPlans::Disable,
78
79
  )
79
80
  end
@@ -97,6 +98,7 @@ module Scenarios::Satellite
97
98
  :assumeyes => true,
98
99
  :download_only => true
99
100
  ),
101
+ Procedures::Iop::Update.new(:version => target_version),
100
102
  Procedures::Service::Stop,
101
103
  Procedures::Packages::Update.new(:assumeyes => true, :clean_cache => false),
102
104
  )
@@ -116,8 +118,10 @@ module Scenarios::Satellite
116
118
  Procedures::RefreshFeatures,
117
119
  Procedures::Service::Start,
118
120
  Procedures::Crond::Start,
121
+ Procedures::Timer::Start,
119
122
  Procedures::SyncPlans::Enable,
120
123
  Procedures::MaintenanceMode::DisableMaintenanceMode,
124
+ Procedures::Iop::ImagePrune,
121
125
  )
122
126
  end
123
127
  end
@@ -69,8 +69,10 @@ module Scenarios::Update
69
69
  :assumeyes => true,
70
70
  :download_only => true
71
71
  ),
72
+ Procedures::Iop::Update.new(:version => feature(:instance).current_major_version),
72
73
  Procedures::MaintenanceMode::EnableMaintenanceMode,
73
74
  Procedures::Crond::Stop,
75
+ Procedures::Timer::Stop,
74
76
  Procedures::SyncPlans::Disable
75
77
  )
76
78
  end
@@ -104,8 +106,10 @@ module Scenarios::Update
104
106
  Procedures::RefreshFeatures,
105
107
  Procedures::Service::Start,
106
108
  Procedures::Crond::Start,
109
+ Procedures::Timer::Start,
107
110
  Procedures::SyncPlans::Enable,
108
- Procedures::MaintenanceMode::DisableMaintenanceMode
111
+ Procedures::MaintenanceMode::DisableMaintenanceMode,
112
+ Procedures::Iop::ImagePrune,
109
113
  )
110
114
  end
111
115
  end
@@ -137,7 +137,7 @@ module ForemanMaintain
137
137
  option '--label', 'label',
138
138
  'Run only a specific check with a label. ' \
139
139
  '(Use "list" command to see available labels)' do |label|
140
- raise ArgumentError, 'value not specified' if label.nil? || label.empty?
140
+ raise ArgumentError, 'no value provided' if label.nil? || label.empty?
141
141
  underscorize(label).to_sym
142
142
  end
143
143
  end
@@ -147,7 +147,7 @@ module ForemanMaintain
147
147
  'Run only those with all specific set of tags. ' \
148
148
  '(Use list-tags command to see available tags)',
149
149
  :multivalued => true) do |tags|
150
- raise ArgumentError, 'value not specified' if tags.nil? || tags.empty?
150
+ raise ArgumentError, 'no value provided' if tags.nil? || tags.empty?
151
151
  tags.map { |tag| underscorize(tag).to_sym }
152
152
  end
153
153
  end
@@ -166,7 +166,7 @@ module ForemanMaintain
166
166
  if opts.include?('whitelist')
167
167
  option(['-w', '--whitelist'], 'whitelist',
168
168
  'Comma-separated list of labels of steps to be skipped') do |whitelist|
169
- raise ArgumentError, 'value not specified' if whitelist.nil? || whitelist.empty?
169
+ raise ArgumentError, 'no value provided' if whitelist.nil? || whitelist.empty?
170
170
  whitelist.split(',').map(&:strip)
171
171
  end
172
172
  end
@@ -0,0 +1,50 @@
1
+ module ForemanMaintain
2
+ module Concerns
3
+ module Systemd
4
+ def action_noun(action)
5
+ action_word_modified(action) + 'ing'
6
+ end
7
+
8
+ def action_past_tense(action)
9
+ action_word_modified(action) + 'ed'
10
+ end
11
+
12
+ private
13
+
14
+ def format_status(output, exit_code, options)
15
+ status = ''
16
+ if !options[:failing] || exit_code > 0
17
+ if options[:brief]
18
+ status += format_brief_status(exit_code)
19
+ elsif !(output.nil? || output.empty?)
20
+ status += "\n" + output
21
+ end
22
+ end
23
+ status
24
+ end
25
+
26
+ def format_brief_status(exit_code)
27
+ result = (exit_code == 0) ? reporter.status_label(:success) : reporter.status_label(:fail)
28
+ padding = reporter.max_length - reporter.last_line.to_s.length - 30
29
+ "#{' ' * padding} #{result}"
30
+ end
31
+
32
+ def allowed_action?(action)
33
+ %w[start stop restart status enable disable].include?(action)
34
+ end
35
+
36
+ def action_word_modified(action)
37
+ case action
38
+ when 'status'
39
+ 'display'
40
+ when 'enable', 'disable'
41
+ action.chomp('e')
42
+ when 'stop'
43
+ action + 'p'
44
+ else
45
+ action
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -25,6 +25,15 @@ module ForemanMaintain
25
25
  []
26
26
  end
27
27
 
28
+ # Override method with list of applicable timers for feature.
29
+ # Services have a number for priority in order to ensure
30
+ # they are started and stopped in the correct order.
31
+ # example:
32
+ # [ system_service('foo', 10), system_service('bar', 20) ]
33
+ def timers
34
+ []
35
+ end
36
+
28
37
  # Override to generate additional feature instances that can't be
29
38
  # autodetected directly
30
39
  def additional_features
@@ -12,8 +12,9 @@ module ForemanMaintain::Utils
12
12
  def command(action)
13
13
  all = @options.fetch(:all, false)
14
14
  skip_enablement = @options.fetch(:skip_enablement, false)
15
- if skip_enablement && %w[enable disable].include?(action)
16
- return skip_enablement_message(action, @name)
15
+ if %w[enable disable].include?(action)
16
+ return skip_enablement_message(action, @name) if skip_enablement
17
+ return if generated?
17
18
  end
18
19
 
19
20
  cmd = "systemctl #{action} #{@name}"
@@ -59,6 +60,10 @@ module ForemanMaintain::Utils
59
60
  end
60
61
  end
61
62
 
63
+ def generated?
64
+ service_enabled_status == 'generated'
65
+ end
66
+
62
67
  def matches?(service)
63
68
  if service.is_a? String
64
69
  service == @name || File.fnmatch(service, @name)
@@ -1,3 +1,3 @@
1
1
  module ForemanMaintain
2
- VERSION = '1.12.2'.freeze
2
+ VERSION = '1.12.4'.freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_maintain
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.12.2
4
+ version: 1.12.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Nečas
@@ -245,6 +245,7 @@ files:
245
245
  - definitions/features/service.rb
246
246
  - definitions/features/sync_plans.rb
247
247
  - definitions/features/tar.rb
248
+ - definitions/features/timer.rb
248
249
  - definitions/procedures/backup/accessibility_confirmation.rb
249
250
  - definitions/procedures/backup/clean.rb
250
251
  - definitions/procedures/backup/compress_data.rb
@@ -275,6 +276,8 @@ files:
275
276
  - definitions/procedures/hammer_setup.rb
276
277
  - definitions/procedures/installer/run.rb
277
278
  - definitions/procedures/installer/upgrade_rake_task.rb
279
+ - definitions/procedures/iop/image_prune.rb
280
+ - definitions/procedures/iop/update.rb
278
281
  - definitions/procedures/knowledge_base_article.rb
279
282
  - definitions/procedures/maintenance_mode/disable_maintenance_mode.rb
280
283
  - definitions/procedures/maintenance_mode/enable_maintenance_mode.rb
@@ -329,26 +332,34 @@ files:
329
332
  - definitions/procedures/service/stop.rb
330
333
  - definitions/procedures/sync_plans/disable.rb
331
334
  - definitions/procedures/sync_plans/enable.rb
335
+ - definitions/procedures/timer/start.rb
336
+ - definitions/procedures/timer/stop.rb
332
337
  - definitions/reports/advisor_on_prem_remediations.rb
333
338
  - definitions/reports/alternate_content_sources.rb
339
+ - definitions/reports/bookmarks.rb
334
340
  - definitions/reports/compliance.rb
335
341
  - definitions/reports/content.rb
342
+ - definitions/reports/disconnected_environment.rb
336
343
  - definitions/reports/external_auth_source.rb
337
344
  - definitions/reports/grouping.rb
338
345
  - definitions/reports/image_mode_hosts.rb
339
346
  - definitions/reports/instance.rb
340
347
  - definitions/reports/inventory.rb
341
348
  - definitions/reports/kerberos.rb
349
+ - definitions/reports/lab_features.rb
342
350
  - definitions/reports/ldap_auth_source.rb
343
351
  - definitions/reports/networking.rb
344
352
  - definitions/reports/oidc_usage.rb
353
+ - definitions/reports/personal_access_token.rb
345
354
  - definitions/reports/platform.rb
346
355
  - definitions/reports/provisioning.rb
347
356
  - definitions/reports/rbac.rb
348
357
  - definitions/reports/recurring_logics.rb
358
+ - definitions/reports/selinux.rb
349
359
  - definitions/reports/template
350
360
  - definitions/reports/virt_who.rb
351
361
  - definitions/reports/vmware.rb
362
+ - definitions/reports/webhooks.rb
352
363
  - definitions/scenarios/backup.rb
353
364
  - definitions/scenarios/foreman_upgrade.rb
354
365
  - definitions/scenarios/maintenance_mode.rb
@@ -405,6 +416,7 @@ files:
405
416
  - lib/foreman_maintain/concerns/scenario_metadata.rb
406
417
  - lib/foreman_maintain/concerns/system_helpers.rb
407
418
  - lib/foreman_maintain/concerns/system_service.rb
419
+ - lib/foreman_maintain/concerns/systemd.rb
408
420
  - lib/foreman_maintain/concerns/upstream.rb
409
421
  - lib/foreman_maintain/concerns/versions.rb
410
422
  - lib/foreman_maintain/config.rb