foreman_maintain 0.8.21 → 0.8.24
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/definitions/checks/pulpcore/group_ownership_check.rb +18 -0
- data/definitions/features/foreman_tasks.rb +3 -0
- data/definitions/features/system_repos.rb +8 -0
- data/definitions/procedures/pulp/remove.rb +12 -0
- data/definitions/procedures/repositories/backup_enabled_repos.rb +16 -0
- data/definitions/procedures/repositories/enable.rb +13 -0
- data/definitions/scenarios/self_upgrade.rb +102 -0
- data/definitions/scenarios/upgrade_to_satellite_6_10.rb +1 -8
- data/lib/foreman_maintain/cli/self_upgrade_command.rb +39 -0
- data/lib/foreman_maintain/cli.rb +2 -0
- data/lib/foreman_maintain/version.rb +1 -1
- metadata +7 -6
- data/lib/foreman_maintain/concerns/el_repos_manager_common.rb +0 -20
- data/lib/foreman_maintain/repos_manager/dnf_config_manager.rb +0 -13
- data/lib/foreman_maintain/repos_manager/el_common.rb +0 -0
- data/lib/foreman_maintain/repos_manager/yum_config_manager.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 164031605ab91a858e8051175df3cfa485cb8d7641495649b56fc369c8f86901
|
4
|
+
data.tar.gz: 34bff6ed46469b2de1f936c4b9fb9a292e56f3fbef6084c0f2d9f84d7d5a8389
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bcce432d5b166c898ecfa33e2a215c8dde59011c72a9f356a877c16caad70da945e06742b4bf867f70963d095ca5520f0fd7aea38893c8ea28a183f08f45ba3f
|
7
|
+
data.tar.gz: b88af64fe1462a21f0f53c42ae8d67fd940208ccb2234af5ad043fd0ac0121726aec6b215d6b5fbe7dd3c747f1b8aa5f797953cab1b757dd69c7c2c51656a084
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Checks
|
2
|
+
module Pulpcore
|
3
|
+
class GroupOwnershipCheck < ForemanMaintain::Check
|
4
|
+
metadata do
|
5
|
+
description 'Check the group owner of /var/lib/pulp directory'
|
6
|
+
label :group_ownership_check_of_pulp_content
|
7
|
+
manual_detection
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
group_id = File.stat('/var/lib/pulp/').gid
|
12
|
+
if Etc.getgrgid(group_id).name != 'pulp'
|
13
|
+
fail! "Please run 'foreman-maintain prep-6.10-upgrade' prior to upgrading."
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -88,6 +88,9 @@ class Features::ForemanTasks < ForemanMaintain::Feature
|
|
88
88
|
DELETE FROM dynflow_actions USING foreman_tasks_tasks WHERE (foreman_tasks_tasks.external_id = dynflow_actions.execution_plan_uuid::varchar) AND #{tasks_condition};
|
89
89
|
DELETE FROM dynflow_execution_plans USING foreman_tasks_tasks WHERE (foreman_tasks_tasks.external_id = dynflow_execution_plans.uuid::varchar) AND #{tasks_condition};
|
90
90
|
DELETE FROM foreman_tasks_tasks WHERE #{tasks_condition};
|
91
|
+
-- Delete locks and links which may now be orphaned
|
92
|
+
DELETE FROM foreman_tasks_locks as ftl where ftl.id NOT IN (SELECT id FROM foreman_tasks_tasks);
|
93
|
+
DELETE FROM foreman_tasks_links as ftl where ftl.id NOT IN (SELECT id FROM foreman_tasks_tasks);
|
91
94
|
COMMIT;
|
92
95
|
SQL
|
93
96
|
|
@@ -21,6 +21,10 @@ class Features::SystemRepos < ForemanMaintain::Feature
|
|
21
21
|
Hash[*repos.delete!(' ').split("\n")]
|
22
22
|
end
|
23
23
|
|
24
|
+
def enabled_repos_ids
|
25
|
+
trim_repoids(enabled_repos_hash.keys)
|
26
|
+
end
|
27
|
+
|
24
28
|
def upstream_repos_ids
|
25
29
|
trim_repoids(upstream_repos.keys)
|
26
30
|
end
|
@@ -29,6 +33,10 @@ class Features::SystemRepos < ForemanMaintain::Feature
|
|
29
33
|
execute!("yum-config-manager --disable #{repo_ids.join(',')}")
|
30
34
|
end
|
31
35
|
|
36
|
+
def enable_repos(repo_ids)
|
37
|
+
execute!("yum-config-manager --enable #{repo_ids.join(',')}")
|
38
|
+
end
|
39
|
+
|
32
40
|
private
|
33
41
|
|
34
42
|
def trim_repoids(repos)
|
@@ -86,6 +86,8 @@ module Procedures::Pulp
|
|
86
86
|
drop_migrations
|
87
87
|
|
88
88
|
delete_pulp_data(rm_cmds) if rm_cmds.any?
|
89
|
+
|
90
|
+
restart_pulpcore_services
|
89
91
|
end
|
90
92
|
|
91
93
|
def remove_pulp
|
@@ -168,5 +170,15 @@ module Procedures::Pulp
|
|
168
170
|
spinner.update('Done deleting pulp2 data directories')
|
169
171
|
end
|
170
172
|
end
|
173
|
+
|
174
|
+
def restart_pulpcore_services
|
175
|
+
with_spinner('Restarting pulpcore services') do |spinner|
|
176
|
+
pulp_services = feature(:pulpcore).services
|
177
|
+
|
178
|
+
feature(:service).handle_services(spinner, 'stop', :only => pulp_services)
|
179
|
+
feature(:service).handle_services(spinner, 'start', :only => pulp_services)
|
180
|
+
spinner.update('Done restarting pulpcore services')
|
181
|
+
end
|
182
|
+
end
|
171
183
|
end
|
172
184
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Procedures::Repositories
|
2
|
+
class BackupEnabledRepos < ForemanMaintain::Procedure
|
3
|
+
metadata do
|
4
|
+
label :backup_enabled_repos
|
5
|
+
description 'Stores enabled repositories in yaml file'
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
enabled_repos_ids = feature(:system_repos).enabled_repos_ids
|
10
|
+
unless enabled_repos_ids.empty?
|
11
|
+
backup_dir = File.expand_path(ForemanMaintain.config.backup_dir)
|
12
|
+
File.write(File.join(backup_dir, 'enabled_repos.yml'), enabled_repos_ids.to_yaml)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Procedures::Repositories
|
2
|
+
class Enable < ForemanMaintain::Procedure
|
3
|
+
metadata do
|
4
|
+
param :repos, 'List of repositories to enable'
|
5
|
+
description 'Enable repositories'
|
6
|
+
end
|
7
|
+
def run
|
8
|
+
with_spinner('Enabling repositories') do
|
9
|
+
feature(:system_repos).enable_repos(@repos)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module ForemanMaintain::Scenarios
|
2
|
+
class SelfUpgradeBase < ForemanMaintain::Scenario
|
3
|
+
def enabled_system_repos_id
|
4
|
+
feature(:system_repos).enabled_repos_ids
|
5
|
+
end
|
6
|
+
|
7
|
+
def enable_repos(repo_ids = stored_enabled_repos_ids)
|
8
|
+
add_step(Procedures::Repositories::Enable.new(repos: repo_ids))
|
9
|
+
end
|
10
|
+
|
11
|
+
def disable_repos(repo_ids = stored_enabled_repos_ids)
|
12
|
+
add_step(Procedures::Repositories::Disable.new(repos: repo_ids))
|
13
|
+
end
|
14
|
+
|
15
|
+
def target_version
|
16
|
+
@target_version ||= context.get(:target_version)
|
17
|
+
end
|
18
|
+
|
19
|
+
def current_version
|
20
|
+
feature(:instance).downstream.current_minor_version
|
21
|
+
end
|
22
|
+
|
23
|
+
def maintenance_repo_id(version)
|
24
|
+
if (repo = ENV['maintenance_repo'])
|
25
|
+
return repo unless repo.empty?
|
26
|
+
end
|
27
|
+
|
28
|
+
maintenance_repo(version)
|
29
|
+
end
|
30
|
+
|
31
|
+
def maintenance_repo(version)
|
32
|
+
if el7?
|
33
|
+
"rhel-#{el_major_version}-server-satellite-maintenance-#{version}-rpms"
|
34
|
+
else
|
35
|
+
"satellite-maintenance-#{version}-for-rhel-#{el_major_version}-x86_64-rpms"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def maintenance_repo_version
|
40
|
+
return '6' if current_version == '6.10'
|
41
|
+
|
42
|
+
current_version
|
43
|
+
end
|
44
|
+
|
45
|
+
def stored_enabled_repos_ids
|
46
|
+
@stored_enabled_repos_ids ||= begin
|
47
|
+
path = File.expand_path('enabled_repos.yml', ForemanMaintain.config.backup_dir)
|
48
|
+
@stored_enabled_repos_ids = File.file?(path) ? YAML.load(File.read(path)) : []
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def all_maintenance_repos
|
53
|
+
repo_regex = if el7?
|
54
|
+
/rhel-\d-server-satellite-maintenance-\d.\d-rpms/
|
55
|
+
else
|
56
|
+
/satellite-maintenance-\d.\d-for-rhel-\d-x86_64-rpms/
|
57
|
+
end
|
58
|
+
stored_enabled_repos_ids.select { |id| !id.match(repo_regex).nil? }
|
59
|
+
end
|
60
|
+
|
61
|
+
def repos_ids_to_reenable
|
62
|
+
repos_ids_to_reenable = stored_enabled_repos_ids - all_maintenance_repos
|
63
|
+
repos_ids_to_reenable << maintenance_repo(maintenance_repo_version)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class SelfUpgrade < SelfUpgradeBase
|
68
|
+
metadata do
|
69
|
+
label :self_upgrade_foreman_maintain
|
70
|
+
description "Enables the specified version's maintenance repository and,"\
|
71
|
+
"\nupdates the satellite-maintain packages"
|
72
|
+
manual_detection
|
73
|
+
end
|
74
|
+
|
75
|
+
def compose
|
76
|
+
if check_min_version('foreman', '2.5') || check_min_version('foreman-proxy', '2.5')
|
77
|
+
pkgs_to_update = %w[satellite-maintain rubygem-foreman_maintain]
|
78
|
+
add_step(Procedures::Repositories::BackupEnabledRepos.new)
|
79
|
+
disable_repos
|
80
|
+
add_step(Procedures::Repositories::Enable.new(repos: [maintenance_repo_id(target_version)]))
|
81
|
+
add_step(Procedures::Packages::Update.new(packages: pkgs_to_update, assumeyes: true))
|
82
|
+
enable_repos(repos_ids_to_reenable)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class SelfUpgradeRescue < SelfUpgradeBase
|
88
|
+
metadata do
|
89
|
+
label :rescue_self_upgrade
|
90
|
+
description 'Disables all version specific maintenance repositories and,'\
|
91
|
+
"\nenables the repositories which were configured prior to self upgrade"
|
92
|
+
manual_detection
|
93
|
+
run_strategy :fail_slow
|
94
|
+
end
|
95
|
+
|
96
|
+
def compose
|
97
|
+
if check_min_version('foreman', '2.5') || check_min_version('foreman-proxy', '2.5')
|
98
|
+
enable_repos(repos_ids_to_reenable)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -25,6 +25,7 @@ module Scenarios::Satellite_6_10
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def compose
|
28
|
+
add_step(Checks::Pulpcore::GroupOwnershipCheck)
|
28
29
|
add_step(Checks::Puppet::WarnAboutPuppetRemoval)
|
29
30
|
add_step(Checks::CheckForNewerPackages.new(:packages => [foreman_plugin_name('katello'),
|
30
31
|
'python3-pulp-2to3-migration'],
|
@@ -61,13 +62,6 @@ module Scenarios::Satellite_6_10
|
|
61
62
|
context.map(:assumeyes, Procedures::Installer::Upgrade => :assumeyes)
|
62
63
|
end
|
63
64
|
|
64
|
-
def check_var_lib_pulp
|
65
|
-
group_id = File.stat('/var/lib/pulp/').gid
|
66
|
-
if Etc.getgrgid(group_id).name != 'pulp'
|
67
|
-
raise "Please run 'foreman-maintain prep-6.10-upgrade' prior to upgrading."
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
65
|
def pulp3_switchover_steps
|
72
66
|
add_step(Procedures::Service::Enable.
|
73
67
|
new(:only => Features::Pulpcore.pulpcore_migration_services))
|
@@ -79,7 +73,6 @@ module Scenarios::Satellite_6_10
|
|
79
73
|
end
|
80
74
|
|
81
75
|
def compose
|
82
|
-
check_var_lib_pulp
|
83
76
|
unless check_min_version(foreman_plugin_name('katello'), '4.0')
|
84
77
|
pulp3_switchover_steps
|
85
78
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module ForemanMaintain
|
2
|
+
module Cli
|
3
|
+
class SelfUpgradeCommand < Base
|
4
|
+
option ['--target-version'], 'TARGET_VERSION',\
|
5
|
+
'Major version of the Satellite or Capsule'\
|
6
|
+
', e.g 7.0', :required => true
|
7
|
+
def execute
|
8
|
+
allow_major_version_upgrade_only
|
9
|
+
run_scenario(upgrade_scenario, upgrade_rescue_scenario)
|
10
|
+
end
|
11
|
+
|
12
|
+
def upgrade_scenario
|
13
|
+
Scenarios::SelfUpgrade.new(target_version: target_version)
|
14
|
+
end
|
15
|
+
|
16
|
+
def upgrade_rescue_scenario
|
17
|
+
Scenarios::SelfUpgradeRescue.new(target_version: target_version)
|
18
|
+
end
|
19
|
+
|
20
|
+
def current_downstream_version
|
21
|
+
ForemanMaintain.detector.feature(:instance).downstream.current_version
|
22
|
+
end
|
23
|
+
|
24
|
+
def allow_major_version_upgrade_only
|
25
|
+
begin
|
26
|
+
next_version = Gem::Version.new(target_version)
|
27
|
+
rescue ArgumentError => err
|
28
|
+
raise Error::UsageError, "Invalid version! #{err}"
|
29
|
+
end
|
30
|
+
if current_downstream_version >= next_version
|
31
|
+
message = "The target-version #{target_version} should be "\
|
32
|
+
"greater than existing version #{current_downstream_version},"\
|
33
|
+
"\nand self-upgrade should be used for major version upgrades only!"
|
34
|
+
raise Error::UsageError, message
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/foreman_maintain/cli.rb
CHANGED
@@ -11,6 +11,7 @@ require 'foreman_maintain/cli/restore_command'
|
|
11
11
|
require 'foreman_maintain/cli/maintenance_mode_command'
|
12
12
|
require 'foreman_maintain/cli/packages_command'
|
13
13
|
require 'foreman_maintain/cli/content_command'
|
14
|
+
require 'foreman_maintain/cli/self_upgrade_command'
|
14
15
|
|
15
16
|
module ForemanMaintain
|
16
17
|
module Cli
|
@@ -25,6 +26,7 @@ module ForemanMaintain
|
|
25
26
|
subcommand 'packages', 'Lock/Unlock package protection, install, update', PackagesCommand
|
26
27
|
subcommand 'advanced', 'Advanced tools for server maintenance', AdvancedCommand
|
27
28
|
subcommand 'content', 'Content related commands', ContentCommand
|
29
|
+
subcommand 'self-upgrade', 'Perform major version self upgrade', SelfUpgradeCommand
|
28
30
|
subcommand 'maintenance-mode', 'Control maintenance-mode for application',
|
29
31
|
MaintenanceModeCommand
|
30
32
|
if ForemanMaintain.detector.feature(:satellite) &&
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman_maintain
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.24
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Nečas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-03-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: clamp
|
@@ -154,6 +154,7 @@ files:
|
|
154
154
|
- definitions/checks/original_assets.rb
|
155
155
|
- definitions/checks/package_manager/yum/validate_yum_config.rb
|
156
156
|
- definitions/checks/pulpcore/db_up.rb
|
157
|
+
- definitions/checks/pulpcore/group_ownership_check.rb
|
157
158
|
- definitions/checks/puppet/provide_upgrade_guide.rb
|
158
159
|
- definitions/checks/puppet/verify_no_empty_cacert_requests.rb
|
159
160
|
- definitions/checks/puppet/warn_about_puppet_removal.rb
|
@@ -273,7 +274,9 @@ files:
|
|
273
274
|
- definitions/procedures/puppet/delete_empty_ca_cert_request_files.rb
|
274
275
|
- definitions/procedures/refresh_features.rb
|
275
276
|
- definitions/procedures/remote_execution/remove_existing_settingsd.rb
|
277
|
+
- definitions/procedures/repositories/backup_enabled_repos.rb
|
276
278
|
- definitions/procedures/repositories/disable.rb
|
279
|
+
- definitions/procedures/repositories/enable.rb
|
277
280
|
- definitions/procedures/repositories/setup.rb
|
278
281
|
- definitions/procedures/restore/candlepin_dump.rb
|
279
282
|
- definitions/procedures/restore/configs.rb
|
@@ -306,6 +309,7 @@ files:
|
|
306
309
|
- definitions/scenarios/packages.rb
|
307
310
|
- definitions/scenarios/prep_6_10_upgrade.rb
|
308
311
|
- definitions/scenarios/restore.rb
|
312
|
+
- definitions/scenarios/self_upgrade.rb
|
309
313
|
- definitions/scenarios/services.rb
|
310
314
|
- definitions/scenarios/upgrade_to_capsule_6_10.rb
|
311
315
|
- definitions/scenarios/upgrade_to_capsule_6_10_z.rb
|
@@ -353,13 +357,13 @@ files:
|
|
353
357
|
- lib/foreman_maintain/cli/maintenance_mode_command.rb
|
354
358
|
- lib/foreman_maintain/cli/packages_command.rb
|
355
359
|
- lib/foreman_maintain/cli/restore_command.rb
|
360
|
+
- lib/foreman_maintain/cli/self_upgrade_command.rb
|
356
361
|
- lib/foreman_maintain/cli/service_command.rb
|
357
362
|
- lib/foreman_maintain/cli/transform_clamp_options.rb
|
358
363
|
- lib/foreman_maintain/cli/upgrade_command.rb
|
359
364
|
- lib/foreman_maintain/concerns/base_database.rb
|
360
365
|
- lib/foreman_maintain/concerns/directory_marker.rb
|
361
366
|
- lib/foreman_maintain/concerns/downstream.rb
|
362
|
-
- lib/foreman_maintain/concerns/el_repos_manager_common.rb
|
363
367
|
- lib/foreman_maintain/concerns/finders.rb
|
364
368
|
- lib/foreman_maintain/concerns/hammer.rb
|
365
369
|
- lib/foreman_maintain/concerns/logger.rb
|
@@ -387,9 +391,6 @@ files:
|
|
387
391
|
- lib/foreman_maintain/procedure.rb
|
388
392
|
- lib/foreman_maintain/reporter.rb
|
389
393
|
- lib/foreman_maintain/reporter/cli_reporter.rb
|
390
|
-
- lib/foreman_maintain/repos_manager/dnf_config_manager.rb
|
391
|
-
- lib/foreman_maintain/repos_manager/el_common.rb
|
392
|
-
- lib/foreman_maintain/repos_manager/yum_config_manager.rb
|
393
394
|
- lib/foreman_maintain/runner.rb
|
394
395
|
- lib/foreman_maintain/runner/execution.rb
|
395
396
|
- lib/foreman_maintain/runner/stored_execution.rb
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module ForemanMaintain
|
2
|
-
module Concerns
|
3
|
-
module ElReposManagerCommon
|
4
|
-
include ForemanMaintain::Concerns::OsFacts
|
5
|
-
|
6
|
-
def package_manager
|
7
|
-
return 'dnf' if el8?
|
8
|
-
|
9
|
-
'yum'
|
10
|
-
end
|
11
|
-
|
12
|
-
def enabled_repos_hash
|
13
|
-
repos = execute("#{package_manager} repolist enabled -d 6 -e 0 2> /dev/null | grep -E 'Repo-id|Repo-baseurl'")
|
14
|
-
return {} if repos.empty?
|
15
|
-
|
16
|
-
Hash[*repos.delete!(' ').split("\n")]
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
module ForemanMaintain::ReposManager
|
2
|
-
class DnfConfigManager
|
3
|
-
include ForemanMaintain::Concerns::ElReposManagerCommon
|
4
|
-
|
5
|
-
def disable_repos(repo_ids)
|
6
|
-
execute!("dnf config-manager --set-disabled #{repo_ids.join(',')}")
|
7
|
-
end
|
8
|
-
|
9
|
-
def enable_repos(repo_ids)
|
10
|
-
execute!("dnf config-manager --set-enabled #{repo_ids.join(',')}")
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
File without changes
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module ForemanMaintain::ReposManager
|
2
|
-
class YumConfigManager
|
3
|
-
include ForemanMaintain::Concerns::ElReposManagerCommon
|
4
|
-
|
5
|
-
def disable_repos(repo_ids)
|
6
|
-
execute!("yum-config-manager --disable #{repo_ids.join(',')}")
|
7
|
-
end
|
8
|
-
|
9
|
-
def enable_repos(repo_ids)
|
10
|
-
execute!("yum-config-manager --enable #{repo_ids.join(',')}")
|
11
|
-
end
|
12
|
-
|
13
|
-
def enabled_repos_hash
|
14
|
-
repos = execute("yum repolist enabled -d 6 -e 0 2> /dev/null | grep -E 'Repo-id|Repo-baseurl'")
|
15
|
-
return {} if repos.empty?
|
16
|
-
|
17
|
-
Hash[*repos.delete!(' ').split("\n")]
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|