foreman_maintain 0.6.13 → 0.7.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 +4 -4
- data/README.md +2 -2
- data/definitions/checks/disk/available_space_candlepin.rb +27 -0
- data/definitions/checks/foreman/check_checkpoint_segments.rb +30 -22
- data/definitions/checks/foreman_tasks/not_paused.rb +10 -13
- data/definitions/checks/package_manager/yum/validate_yum_config.rb +51 -0
- data/definitions/features/candlepin.rb +4 -0
- data/definitions/features/dynflow_sidekiq.rb +7 -4
- data/definitions/features/foreman_cockpit.rb +15 -0
- data/definitions/features/foreman_tasks.rb +12 -2
- data/definitions/features/pulpcore.rb +20 -5
- data/definitions/procedures/backup/accessibility_confirmation.rb +1 -1
- data/definitions/procedures/backup/online/safety_confirmation.rb +11 -6
- data/definitions/procedures/backup/snapshot/logical_volume_confirmation.rb +1 -1
- data/definitions/procedures/content/migration_stats.rb +12 -0
- data/definitions/procedures/content/prepare.rb +2 -6
- data/definitions/procedures/content/prepare_abort.rb +12 -0
- data/definitions/procedures/content/switchover.rb +1 -1
- data/definitions/procedures/foreman_tasks/delete.rb +3 -4
- data/definitions/procedures/foreman_tasks/resume.rb +5 -0
- data/definitions/procedures/packages/installer_confirmation.rb +1 -1
- data/definitions/procedures/packages/update_all_confirmation.rb +1 -1
- data/definitions/procedures/prep_6_10_upgrade.rb +29 -0
- data/definitions/procedures/restore/confirmation.rb +1 -1
- data/definitions/procedures/restore/installer_reset.rb +10 -1
- data/definitions/procedures/service/list.rb +12 -2
- data/definitions/scenarios/backup.rb +2 -0
- data/definitions/scenarios/content.rb +50 -3
- data/definitions/scenarios/prep_6_10_upgrade.rb +13 -0
- data/definitions/scenarios/upgrade_to_capsule_6_9.rb +88 -0
- data/definitions/scenarios/upgrade_to_capsule_6_9_z.rb +88 -0
- data/definitions/scenarios/upgrade_to_satellite_6_9.rb +90 -0
- data/definitions/scenarios/upgrade_to_satellite_6_9_z.rb +89 -0
- data/lib/foreman_maintain.rb +3 -1
- data/lib/foreman_maintain/cli.rb +8 -0
- data/lib/foreman_maintain/cli/content_command.rb +17 -2
- data/lib/foreman_maintain/cli/upgrade_command.rb +2 -0
- data/lib/foreman_maintain/concerns/downstream.rb +4 -0
- data/lib/foreman_maintain/concerns/primary_checks.rb +23 -0
- data/lib/foreman_maintain/package_manager/dnf.rb +1 -0
- data/lib/foreman_maintain/reporter.rb +18 -13
- data/lib/foreman_maintain/reporter/cli_reporter.rb +24 -11
- data/lib/foreman_maintain/runner.rb +13 -8
- data/lib/foreman_maintain/scenario.rb +4 -0
- data/lib/foreman_maintain/utils/backup.rb +1 -1
- data/lib/foreman_maintain/utils/disk/io_device.rb +4 -0
- data/lib/foreman_maintain/utils/service/systemd.rb +13 -2
- data/lib/foreman_maintain/version.rb +1 -1
- metadata +14 -3
- data/definitions/checks/yum_exclude.rb +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b7bee1fb68980f7f9358b61a13c7d0a5eba0c78d308ebcfeb717e31cb6c71942
|
4
|
+
data.tar.gz: 808fb2970b786aec29df42004b22ecf82b52e8bd31666410136842c6621d2b67
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b5cba26dc0b3011336003c542e7d051b48a1a8896d5b36865d21b25e4a9367b1d1b3929d409ef6bb00fc2947c4f27141e0433a4e14c536291a269c0b334c1f5
|
7
|
+
data.tar.gz: a9e794c196a502b2307506863f0e75e1a4a1a803793986040d118f679f0bd921b0f8a5a95f76516844e97c71f831be5b2cdd9bd7052bb2fc6409dd4089e09f75
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Foreman
|
1
|
+
# Foreman Maintain [](https://github.com/theforeman/foreman_maintain/workflows/Ruby%20Tests/badge.svg?event=pull_request) <a href="https://codeclimate.com/github/theforeman/foreman_maintain"><img src="https://codeclimate.com/github/theforeman/foreman_maintain/badges/gpa.svg" /></a>
|
2
2
|
|
3
3
|
The `foreman_maintain` aims to provide various features that helps keep the
|
4
4
|
Foreman/Satellite up and running. It supports multiple versions and subparts
|
@@ -52,7 +52,7 @@ Subcommands:
|
|
52
52
|
is-enabled Get maintenance-mode status code
|
53
53
|
|
54
54
|
content Content related commands
|
55
|
-
prepare Prepare content for Pulp 3
|
55
|
+
prepare Prepare content for Pulp 3
|
56
56
|
switchover Switch support for certain content from Pulp 2 to Pulp 3
|
57
57
|
```
|
58
58
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Checks
|
2
|
+
module Disk
|
3
|
+
class AvailableSpaceCandlepin < ForemanMaintain::Check
|
4
|
+
metadata do
|
5
|
+
label :available_space_cp
|
6
|
+
description 'Check to make sure /var/lib/candlepin has enough space'
|
7
|
+
tags :pre_upgrade
|
8
|
+
confine do
|
9
|
+
feature(:candlepin) && check_min_version('candlepin', '3.1')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
MAX_USAGE_IN_PERCENT = 90
|
14
|
+
|
15
|
+
def run
|
16
|
+
assert(enough_space?, "System has more than #{MAX_USAGE_IN_PERCENT}% space used"\
|
17
|
+
" on #{feature(:candlepin).work_dir}.\n"\
|
18
|
+
'See https://bugzilla.redhat.com/show_bug.cgi?id=1898605')
|
19
|
+
end
|
20
|
+
|
21
|
+
def enough_space?
|
22
|
+
io_obj = ForemanMaintain::Utils::Disk::IODevice.new(feature(:candlepin).work_dir)
|
23
|
+
io_obj.space_used_in_percent < MAX_USAGE_IN_PERCENT
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -18,31 +18,39 @@ module Checks
|
|
18
18
|
# rubocop:disable Metrics/MethodLength
|
19
19
|
def check_custom_hiera
|
20
20
|
hiera_file = feature(:installer).custom_hiera_file
|
21
|
-
|
22
|
-
|
23
|
-
if config
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
elsif config['postgresql::server::config_entries'].key?('checkpoint_segments')
|
30
|
-
message = <<-MESSAGE.strip_heredoc
|
31
|
-
ERROR: Tuning option 'checkpoint_segments' found.
|
32
|
-
This option is no longer valid for PostgreSQL 9.5 or newer.
|
33
|
-
Please remove it from following file and re-run the command.
|
34
|
-
- #{hiera_file}
|
35
|
-
MESSAGE
|
36
|
-
if feature(:katello)
|
37
|
-
message += <<-MESSAGE.strip_heredoc
|
38
|
-
The presence of checkpoint_segments in #{hiera_file} indicates manual tuning.
|
39
|
-
Manual tuning can override values provided by the --tuning parameter.
|
40
|
-
Review #{hiera_file} for values that are already provided by the built in tuning profiles.
|
41
|
-
Built in tuning profiles also provide a supported upgrade path.
|
21
|
+
begin
|
22
|
+
config = YAML.load_file(hiera_file)
|
23
|
+
if config.is_a?(Hash) && config.key?('postgresql::server::config_entries')
|
24
|
+
if config['postgresql::server::config_entries'].nil?
|
25
|
+
return <<-MESSAGE.strip_heredoc
|
26
|
+
ERROR: 'postgresql::server::config_entries' cannot be null.
|
27
|
+
Please remove it from following file and re-run the command.
|
28
|
+
- #{hiera_file}
|
42
29
|
MESSAGE
|
30
|
+
elsif config['postgresql::server::config_entries'].key?('checkpoint_segments')
|
31
|
+
message = <<-MESSAGE.strip_heredoc
|
32
|
+
ERROR: Tuning option 'checkpoint_segments' found.
|
33
|
+
This option is no longer valid for PostgreSQL 9.5 or newer.
|
34
|
+
Please remove it from following file and re-run the command.
|
35
|
+
- #{hiera_file}
|
36
|
+
MESSAGE
|
37
|
+
if feature(:katello)
|
38
|
+
message += <<-MESSAGE.strip_heredoc
|
39
|
+
The presence of checkpoint_segments in #{hiera_file} indicates manual tuning.
|
40
|
+
Manual tuning can override values provided by the --tuning parameter.
|
41
|
+
Review #{hiera_file} for values that are already provided by the built in tuning profiles.
|
42
|
+
Built in tuning profiles also provide a supported upgrade path.
|
43
|
+
MESSAGE
|
44
|
+
end
|
45
|
+
return message
|
43
46
|
end
|
44
|
-
|
47
|
+
elsif config.is_a?(String)
|
48
|
+
fail! "Error: File #{hiera_file} is not a yaml file."
|
49
|
+
exit 1
|
45
50
|
end
|
51
|
+
rescue Psych::SyntaxError
|
52
|
+
fail! "Found syntax error in file: #{hiera_file}"
|
53
|
+
exit 1
|
46
54
|
end
|
47
55
|
end
|
48
56
|
# rubocop:enable Metrics/MethodLength
|
@@ -9,23 +9,20 @@ module Checks::ForemanTasks
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def run
|
12
|
-
paused_tasks_count = feature(:foreman_tasks).paused_tasks_count(
|
12
|
+
paused_tasks_count = feature(:foreman_tasks).paused_tasks_count()
|
13
13
|
assert(paused_tasks_count == 0,
|
14
14
|
"There are currently #{paused_tasks_count} paused tasks in the system",
|
15
|
-
:next_steps =>
|
16
|
-
[Procedures::ForemanTasks::Resume.new,
|
17
|
-
Procedures::ForemanTasks::UiInvestigate.new('search_query' => scoped_search_query)])
|
15
|
+
:next_steps => next_procedures)
|
18
16
|
end
|
19
17
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
Actions::Katello::EventQueue::Monitor]
|
18
|
+
def next_procedures
|
19
|
+
if assumeyes?
|
20
|
+
return [Procedures::ForemanTasks::Resume.new,
|
21
|
+
Procedures::ForemanTasks::Delete.new(:state => :paused)]
|
22
|
+
end
|
23
|
+
[Procedures::ForemanTasks::Resume.new,
|
24
|
+
Procedures::ForemanTasks::Delete.new(:state => :paused),
|
25
|
+
Procedures::ForemanTasks::UiInvestigate.new('search_query' => 'state = paused')]
|
29
26
|
end
|
30
27
|
end
|
31
28
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Checks::PackageManager
|
2
|
+
module Yum
|
3
|
+
class ValidateYumConfig < ForemanMaintain::Check
|
4
|
+
metadata do
|
5
|
+
label :validate_yum_config
|
6
|
+
description 'Check to validate yum configuration before upgrade'
|
7
|
+
tags :pre_upgrade
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
final_result = verify_config_options
|
12
|
+
assert(
|
13
|
+
final_result[:matched_keys].empty?,
|
14
|
+
failure_message(final_result)
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def failure_message(final_result)
|
21
|
+
verb_string = final_result[:matched_keys].length > 1 ? 'are' : 'is'
|
22
|
+
|
23
|
+
"#{final_result[:matched_keys].join(',')} #{verb_string} set in /etc/yum.conf as below:"\
|
24
|
+
"\n#{final_result[:grep_output]}"\
|
25
|
+
"\nUnset this configuration as it is risky while yum update or upgrade!"
|
26
|
+
end
|
27
|
+
|
28
|
+
def verify_config_options
|
29
|
+
result = {}
|
30
|
+
combined_regex = yum_config_options.values.join('|')
|
31
|
+
result[:grep_output] = execute_grep_cmd(combined_regex)
|
32
|
+
result[:matched_keys] = yum_config_options.keys.select do |key|
|
33
|
+
result[:grep_output].include?(key)
|
34
|
+
end
|
35
|
+
result
|
36
|
+
end
|
37
|
+
|
38
|
+
def execute_grep_cmd(regex_string)
|
39
|
+
execute_with_status("grep -iE '#{regex_string}' /etc/yum.conf")[1]
|
40
|
+
end
|
41
|
+
|
42
|
+
def yum_config_options
|
43
|
+
@yum_config_options ||= {
|
44
|
+
'exclude' => '^exclude\s*=\s*\S+.*$',
|
45
|
+
'clean_requirements_on_remove' =>
|
46
|
+
'^clean_requirements_on_remove\s*=\S*(1|yes|true)$'
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -7,10 +7,6 @@ class Features::DynflowSidekiq < ForemanMaintain::Feature
|
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
def services
|
11
|
-
service_names.map { |service| system_service service, instance_priority(service) }
|
12
|
-
end
|
13
|
-
|
14
10
|
def config_files
|
15
11
|
# Workaround until foreman-installer can deploy scaled workers
|
16
12
|
service_symlinks = configured_instances.map do |service|
|
@@ -22,6 +18,13 @@ class Features::DynflowSidekiq < ForemanMaintain::Feature
|
|
22
18
|
].flatten
|
23
19
|
end
|
24
20
|
|
21
|
+
def services
|
22
|
+
service_names.map do |service|
|
23
|
+
system_service service, instance_priority(service),
|
24
|
+
:instance_parent_unit => 'dynflow-sidekiq@'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
25
28
|
private
|
26
29
|
|
27
30
|
def instance_priority(instance)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Features::ForemanCockpit < ForemanMaintain::Feature
|
2
|
+
metadata do
|
3
|
+
label :foreman_cockpit
|
4
|
+
|
5
|
+
confine do
|
6
|
+
server? && find_package('tfm-rubygem-foreman_remote_execution-cockpit')
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def services
|
11
|
+
[
|
12
|
+
system_service('foreman-cockpit')
|
13
|
+
]
|
14
|
+
end
|
15
|
+
end
|
@@ -89,13 +89,19 @@ class Features::ForemanTasks < ForemanMaintain::Feature
|
|
89
89
|
|
90
90
|
if state == :old
|
91
91
|
old_tasks_condition
|
92
|
+
elsif state == :paused
|
93
|
+
paused_tasks_condition
|
92
94
|
else
|
93
95
|
tasks_condition(state)
|
94
96
|
end
|
95
97
|
end
|
96
98
|
|
97
99
|
def resume_task_using_hammer
|
98
|
-
|
100
|
+
if check_min_version('satellite', '6.8')
|
101
|
+
feature(:hammer).run('task resume --search ""')
|
102
|
+
else
|
103
|
+
feature(:hammer).run('task resume')
|
104
|
+
end
|
99
105
|
end
|
100
106
|
|
101
107
|
def fetch_tasks_status(state, spinner)
|
@@ -176,6 +182,10 @@ class Features::ForemanTasks < ForemanMaintain::Feature
|
|
176
182
|
"foreman_tasks_tasks.started_at < CURRENT_DATE - INTERVAL '#{MIN_AGE} days'"
|
177
183
|
end
|
178
184
|
|
185
|
+
def paused_tasks_condition(state = "'paused'")
|
186
|
+
"foreman_tasks_tasks.state IN (#{state})"
|
187
|
+
end
|
188
|
+
|
179
189
|
def prepare_for_backup(state)
|
180
190
|
dir = backup_dir(state)
|
181
191
|
execute("mkdir -p #{dir}")
|
@@ -193,6 +203,6 @@ class Features::ForemanTasks < ForemanMaintain::Feature
|
|
193
203
|
end
|
194
204
|
|
195
205
|
def valid(state)
|
196
|
-
%w[old planning pending].include?(state.to_s)
|
206
|
+
%w[old planning pending paused].include?(state.to_s)
|
197
207
|
end
|
198
208
|
end
|
@@ -5,24 +5,39 @@ class Features::Pulpcore < ForemanMaintain::Feature
|
|
5
5
|
label :pulpcore
|
6
6
|
|
7
7
|
confine do
|
8
|
-
ForemanMaintain::Utils::Service::Systemd.new('pulpcore-api', 0).exist?
|
8
|
+
ForemanMaintain::Utils::Service::Systemd.new('pulpcore-api', 0).exist? &&
|
9
|
+
ForemanMaintain::Utils::Service::Systemd.new('pulpcore-api', 0).enabled?
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
12
13
|
def services
|
13
|
-
[
|
14
|
+
self.class.pulpcore_common_services + [
|
14
15
|
system_service('rh-redis5-redis', 5),
|
15
|
-
system_service('pulpcore-api', 10),
|
16
|
-
system_service('pulpcore-content', 10),
|
17
|
-
system_service('pulpcore-resource-manager', 10),
|
18
16
|
system_service('pulpcore-worker@*', 20, :all => true, :skip_enablement => true),
|
19
17
|
system_service('httpd', 30)
|
20
18
|
]
|
21
19
|
end
|
22
20
|
|
21
|
+
def self.pulpcore_migration_services
|
22
|
+
pulpcore_common_services + [
|
23
|
+
ForemanMaintain::Utils.system_service('pulpcore-worker@1', 20),
|
24
|
+
ForemanMaintain::Utils.system_service('pulpcore-worker@2', 20),
|
25
|
+
ForemanMaintain::Utils.system_service('pulpcore-worker@3', 20),
|
26
|
+
ForemanMaintain::Utils.system_service('pulpcore-worker@4', 20)
|
27
|
+
]
|
28
|
+
end
|
29
|
+
|
23
30
|
def config_files
|
24
31
|
[
|
25
32
|
'/etc/pulp/settings.py'
|
26
33
|
]
|
27
34
|
end
|
35
|
+
|
36
|
+
def self.pulpcore_common_services
|
37
|
+
[
|
38
|
+
ForemanMaintain::Utils.system_service('pulpcore-api', 10, :socket => 'pulpcore-api'),
|
39
|
+
ForemanMaintain::Utils.system_service('pulpcore-content', 10, :socket => 'pulpcore-content'),
|
40
|
+
ForemanMaintain::Utils.system_service('pulpcore-resource-manager', 10)
|
41
|
+
]
|
42
|
+
end
|
28
43
|
end
|
@@ -7,7 +7,7 @@ module Procedures::Backup
|
|
7
7
|
|
8
8
|
def run
|
9
9
|
answer = ask_decision("WARNING: This script will stop your services.\n\n" \
|
10
|
-
'Do you want to proceed?', 'y(yes), q(quit)')
|
10
|
+
'Do you want to proceed?', actions_msg: 'y(yes), q(quit)')
|
11
11
|
abort! unless answer == :yes
|
12
12
|
end
|
13
13
|
end
|
@@ -4,21 +4,26 @@ module Procedures::Backup
|
|
4
4
|
metadata do
|
5
5
|
description 'Data consistency warning'
|
6
6
|
tags :backup
|
7
|
+
param :include_db_dumps, 'Are database dumps included in backup', :flag => true,
|
8
|
+
:default => false
|
7
9
|
end
|
8
10
|
|
9
11
|
def run
|
10
|
-
answer = ask_decision(
|
11
|
-
|
12
|
+
answer = ask_decision(warning_message(@include_db_dumps), actions_msg: 'y(yes), q(quit)')
|
13
|
+
abort! unless answer == :yes
|
14
|
+
end
|
15
|
+
|
16
|
+
def warning_message(include_db_dumps)
|
17
|
+
substr = include_db_dumps ? 'database dump' : 'online backup'
|
18
|
+
"*** WARNING: The #{substr} is intended for making a copy of the data\n" \
|
12
19
|
'*** for debugging purposes only.' \
|
13
20
|
" The backup routine can not ensure 100% consistency while the\n" \
|
14
21
|
"*** backup is taking place as there is a chance there may be data mismatch between\n" \
|
15
22
|
'*** Mongo and Postgres databases while the services are live.' \
|
16
|
-
" If you wish to utilize the
|
23
|
+
" If you wish to utilize the #{substr}\n" \
|
17
24
|
'*** for production use you need to ensure that there are' \
|
18
25
|
" no modifications occurring during\n" \
|
19
|
-
"*** your backup run.\n\nDo you want to proceed?"
|
20
|
-
)
|
21
|
-
abort! unless answer == :yes
|
26
|
+
"*** your backup run.\n\nDo you want to proceed?"
|
22
27
|
end
|
23
28
|
end
|
24
29
|
end
|
@@ -40,7 +40,7 @@ module Procedures::Backup
|
|
40
40
|
'*** If you would like to continue, the snapshot size will be required to be at least' \
|
41
41
|
" the size of the actual #{shared_lv.join(', ')} database.\n" \
|
42
42
|
"*** You can skip this confirmation with the '-y' flag.\n\n" \
|
43
|
-
'Do you want to proceed?', 'y(yes), q(quit)')
|
43
|
+
'Do you want to proceed?', actions_msg: 'y(yes), q(quit)')
|
44
44
|
abort! unless answer == :yes
|
45
45
|
end
|
46
46
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Procedures::Content
|
2
|
+
class MigrationStats < ForemanMaintain::Procedure
|
3
|
+
metadata do
|
4
|
+
description 'Retrieve Pulp 2 to Pulp 3 migration statistics'
|
5
|
+
for_feature :pulpcore
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
puts execute!('foreman-rake katello:pulp3_migration_stats')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -3,15 +3,11 @@ module Procedures::Content
|
|
3
3
|
metadata do
|
4
4
|
description 'Prepare content for Pulp 3'
|
5
5
|
for_feature :pulpcore
|
6
|
-
|
7
|
-
confine do
|
8
|
-
# FIXME: remove this condition on next downstream upgrade scenario
|
9
|
-
!feature(:instance).downstream
|
10
|
-
end
|
11
6
|
end
|
12
7
|
|
13
8
|
def run
|
14
|
-
|
9
|
+
# use interactive to get realtime output
|
10
|
+
puts execute!('foreman-rake katello:pulp3_migration', :interactive => true)
|
15
11
|
end
|
16
12
|
end
|
17
13
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Procedures::Content
|
2
|
+
class PrepareAbort < ForemanMaintain::Procedure
|
3
|
+
metadata do
|
4
|
+
description 'Abort all running Pulp 2 to Pulp 3 migration tasks'
|
5
|
+
for_feature :pulpcore
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
puts execute!('foreman-rake katello:pulp3_migration_abort')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|