foreman_maintain 0.0.2 → 0.0.3
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 +107 -25
- data/bin/foreman-maintain +1 -0
- data/definitions/checks/disk_speed_minimal.rb +31 -19
- data/definitions/checks/foreman_tasks/invalid/check_old.rb +20 -0
- data/definitions/checks/foreman_tasks/invalid/check_pending_state.rb +20 -0
- data/definitions/checks/foreman_tasks/invalid/check_planning_state.rb +20 -0
- data/definitions/checks/foreman_tasks/not_paused.rb +29 -0
- data/definitions/checks/foreman_tasks/not_running.rb +14 -0
- data/definitions/checks/sync_plans/with_disabled_status.rb +18 -0
- data/definitions/checks/sync_plans/with_enabled_status.rb +18 -0
- data/definitions/checks/system_registration.rb +31 -0
- data/definitions/features/downstream.rb +5 -3
- data/definitions/features/foreman_1_11_x.rb +4 -2
- data/definitions/features/foreman_1_7_x.rb +5 -3
- data/definitions/features/foreman_database.rb +11 -5
- data/definitions/features/foreman_tasks.rb +118 -9
- data/definitions/features/sync_plans.rb +75 -0
- data/definitions/features/upstream.rb +5 -3
- data/definitions/procedures/foreman_tasks/delete.rb +33 -0
- data/definitions/procedures/foreman_tasks/resume.rb +14 -0
- data/definitions/procedures/foreman_tasks/ui_investigate.rb +19 -0
- data/definitions/procedures/hammer_setup.rb +50 -0
- data/definitions/procedures/install_package.rb +17 -0
- data/definitions/procedures/sync_plans/disable.rb +22 -0
- data/definitions/procedures/sync_plans/enable.rb +21 -0
- data/definitions/scenarios/pre_upgrade_check_foreman_1_14.rb +7 -6
- data/definitions/scenarios/pre_upgrade_check_satellite_6_0_z.rb +8 -6
- data/definitions/scenarios/pre_upgrade_check_satellite_6_1.rb +8 -6
- data/definitions/scenarios/pre_upgrade_check_satellite_6_1_z.rb +8 -6
- data/definitions/scenarios/pre_upgrade_check_satellite_6_2.rb +8 -6
- data/definitions/scenarios/pre_upgrade_check_satellite_6_2_z.rb +8 -6
- data/definitions/scenarios/pre_upgrade_check_satellite_6_3.rb +8 -6
- data/lib/foreman_maintain.rb +52 -5
- data/lib/foreman_maintain/check.rb +18 -12
- data/lib/foreman_maintain/cli/base.rb +9 -2
- data/lib/foreman_maintain/cli/health_command.rb +2 -1
- data/lib/foreman_maintain/cli/upgrade_command.rb +2 -0
- data/lib/foreman_maintain/concerns/hammer.rb +20 -0
- data/lib/foreman_maintain/concerns/logger.rb +1 -5
- data/lib/foreman_maintain/concerns/metadata.rb +138 -31
- data/lib/foreman_maintain/concerns/system_helpers.rb +36 -32
- data/lib/foreman_maintain/config.rb +40 -5
- data/lib/foreman_maintain/core_ext.rb +24 -0
- data/lib/foreman_maintain/detector.rb +12 -13
- data/lib/foreman_maintain/error.rb +28 -0
- data/lib/foreman_maintain/executable.rb +86 -11
- data/lib/foreman_maintain/feature.rb +1 -0
- data/lib/foreman_maintain/param.rb +47 -0
- data/lib/foreman_maintain/reporter.rb +20 -3
- data/lib/foreman_maintain/reporter/cli_reporter.rb +166 -66
- data/lib/foreman_maintain/runner.rb +56 -13
- data/lib/foreman_maintain/runner/execution.rb +8 -0
- data/lib/foreman_maintain/scenario.rb +46 -2
- data/lib/foreman_maintain/top_level_modules.rb +3 -0
- data/lib/foreman_maintain/utils.rb +2 -0
- data/lib/foreman_maintain/utils/command_runner.rb +101 -0
- data/lib/foreman_maintain/utils/disk/device.rb +5 -9
- data/lib/foreman_maintain/utils/hammer.rb +78 -0
- data/lib/foreman_maintain/version.rb +1 -1
- data/lib/foreman_maintain/yaml_storage.rb +48 -0
- metadata +27 -9
- data/definitions/checks/foreman_tasks_not_paused.rb +0 -14
- data/definitions/checks/foreman_tasks_not_running.rb +0 -10
- data/definitions/procedures/foreman_tasks_resume.rb +0 -13
- data/lib/foreman_maintain/logger.rb +0 -11
@@ -0,0 +1,21 @@
|
|
1
|
+
module Procedures::SyncPlans
|
2
|
+
class Enable < ForemanMaintain::Procedure
|
3
|
+
metadata do
|
4
|
+
for_feature :sync_plans
|
5
|
+
description 're-enable sync plans'
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
enabled_sync_plans
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def enabled_sync_plans
|
15
|
+
with_spinner('re-enabling sync plans') do |spinner|
|
16
|
+
record_ids = feature(:sync_plans).make_enable
|
17
|
+
spinner.update "Total #{record_ids.length} sync plans are now enabled."
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,12 +1,13 @@
|
|
1
1
|
class Scenarios::PreUpgradeCheckForeman_1_14 < ForemanMaintain::Scenario
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
metadata do
|
3
|
+
description 'checks before upgrading to Foreman 1.14'
|
4
|
+
tags :pre_upgrade_check
|
5
|
+
confine do
|
6
|
+
feature(:upstream)
|
7
|
+
end
|
5
8
|
end
|
6
9
|
|
7
|
-
tags :pre_upgrade_check
|
8
|
-
|
9
10
|
def compose
|
10
|
-
|
11
|
+
add_steps(find_checks(:default))
|
11
12
|
end
|
12
13
|
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
class Scenarios::PreUpgradeCheckSatellite_6_0_z < ForemanMaintain::Scenario
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
metadata do
|
3
|
+
tags :pre_upgrade_check, :satellite_6_0_z
|
4
|
+
description 'checks before upgrading to Satellite 6.0'
|
5
|
+
confine do
|
6
|
+
feature(:downstream) && feature(:downstream).current_version.to_s.start_with?('6.0.')
|
7
|
+
end
|
6
8
|
end
|
7
9
|
|
8
10
|
def compose
|
9
|
-
|
10
|
-
|
11
|
+
add_steps(find_checks(:default))
|
12
|
+
add_steps(find_checks(:pre_upgrade))
|
11
13
|
end
|
12
14
|
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
class Scenarios::PreUpgradeCheckSatellite_6_1 < ForemanMaintain::Scenario
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
metadata do
|
3
|
+
description 'checks before upgrading to Satellite 6.1'
|
4
|
+
tags :pre_upgrade_check, :satellite_6_1
|
5
|
+
confine do
|
6
|
+
feature(:downstream) && feature(:downstream).current_version.to_s.start_with?('6.0.')
|
7
|
+
end
|
6
8
|
end
|
7
9
|
|
8
10
|
def compose
|
9
|
-
|
10
|
-
|
11
|
+
add_steps(find_checks(:default))
|
12
|
+
add_steps(find_checks(:pre_upgrade))
|
11
13
|
end
|
12
14
|
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
class Scenarios::PreUpgradeCheckSatellite_6_1_z < ForemanMaintain::Scenario
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
metadata do
|
3
|
+
description 'checks before upgrading to Satellite 6.1.z'
|
4
|
+
tags :pre_upgrade_check, :satellite_6_1_z
|
5
|
+
confine do
|
6
|
+
feature(:downstream) && feature(:downstream).current_version.to_s.start_with?('6.1.')
|
7
|
+
end
|
6
8
|
end
|
7
9
|
|
8
10
|
def compose
|
9
|
-
|
10
|
-
|
11
|
+
add_steps(find_checks(:default))
|
12
|
+
add_steps(find_checks(:pre_upgrade))
|
11
13
|
end
|
12
14
|
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
class Scenarios::PreUpgradeCheckSatellite_6_2 < ForemanMaintain::Scenario
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
metadata do
|
3
|
+
description 'checks before upgrading to Satellite 6.2'
|
4
|
+
tags :pre_upgrade_check, :satellite_6_2
|
5
|
+
confine do
|
6
|
+
feature(:downstream) && feature(:downstream).current_version.to_s.start_with?('6.1.')
|
7
|
+
end
|
6
8
|
end
|
7
9
|
|
8
10
|
def compose
|
9
|
-
|
10
|
-
|
11
|
+
add_steps(find_checks(:default))
|
12
|
+
add_steps(find_checks(:pre_upgrade))
|
11
13
|
end
|
12
14
|
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
class Scenarios::PreUpgradeCheckSatellite_6_2_z < ForemanMaintain::Scenario
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
metadata do
|
3
|
+
description 'checks before upgrading to Satellite 6.2.z'
|
4
|
+
tags :pre_upgrade_check, :satellite_6_2_z
|
5
|
+
confine do
|
6
|
+
feature(:downstream) && feature(:downstream).current_version.to_s.start_with?('6.2.')
|
7
|
+
end
|
6
8
|
end
|
7
9
|
|
8
10
|
def compose
|
9
|
-
|
10
|
-
|
11
|
+
add_steps(find_checks(:default))
|
12
|
+
add_steps(find_checks(:pre_upgrade))
|
11
13
|
end
|
12
14
|
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
class Scenarios::PreUpgradeCheckSatellite_6_3 < ForemanMaintain::Scenario
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
metadata do
|
3
|
+
description 'checks before upgrading to Satellite 6.3'
|
4
|
+
tags :pre_upgrade_check, :satellite_6_3
|
5
|
+
confine do
|
6
|
+
feature(:downstream) && feature(:downstream).current_version.to_s.start_with?('6.2.')
|
7
|
+
end
|
6
8
|
end
|
7
9
|
|
8
10
|
def compose
|
9
|
-
|
10
|
-
|
11
|
+
add_steps(find_checks(:default))
|
12
|
+
add_steps(find_checks(:pre_upgrade))
|
11
13
|
end
|
12
14
|
end
|
data/lib/foreman_maintain.rb
CHANGED
@@ -2,16 +2,23 @@ if RUBY_VERSION <= '1.8.7'
|
|
2
2
|
require 'rubygems'
|
3
3
|
end
|
4
4
|
|
5
|
+
require 'forwardable'
|
5
6
|
require 'json'
|
7
|
+
require 'logger'
|
8
|
+
require 'yaml'
|
6
9
|
|
7
10
|
module ForemanMaintain
|
11
|
+
require 'foreman_maintain/core_ext'
|
8
12
|
require 'foreman_maintain/concerns/logger'
|
13
|
+
require 'foreman_maintain/concerns/finders'
|
9
14
|
require 'foreman_maintain/concerns/metadata'
|
10
15
|
require 'foreman_maintain/concerns/system_helpers'
|
11
|
-
require 'foreman_maintain/concerns/
|
16
|
+
require 'foreman_maintain/concerns/hammer'
|
12
17
|
require 'foreman_maintain/top_level_modules'
|
18
|
+
require 'foreman_maintain/yaml_storage'
|
13
19
|
require 'foreman_maintain/config'
|
14
20
|
require 'foreman_maintain/detector'
|
21
|
+
require 'foreman_maintain/param'
|
15
22
|
require 'foreman_maintain/feature'
|
16
23
|
require 'foreman_maintain/executable'
|
17
24
|
require 'foreman_maintain/check'
|
@@ -20,13 +27,29 @@ module ForemanMaintain
|
|
20
27
|
require 'foreman_maintain/runner'
|
21
28
|
require 'foreman_maintain/reporter'
|
22
29
|
require 'foreman_maintain/utils'
|
30
|
+
require 'foreman_maintain/error'
|
23
31
|
|
24
32
|
class << self
|
25
|
-
attr_accessor :config
|
33
|
+
attr_accessor :config, :logger
|
34
|
+
|
35
|
+
LOGGER_LEVEL_MAPPING = {
|
36
|
+
'debug' => ::Logger::DEBUG,
|
37
|
+
'info' => ::Logger::INFO,
|
38
|
+
'warn' => ::Logger::WARN,
|
39
|
+
'error' => ::Logger::ERROR,
|
40
|
+
'fatal' => ::Logger::FATAL,
|
41
|
+
'unknown' => ::Logger::UNKNOWN
|
42
|
+
}.freeze
|
26
43
|
|
27
|
-
def setup(
|
28
|
-
|
44
|
+
def setup(options = {})
|
45
|
+
# using a queue, we can log the messages which are generated before initializing logger
|
46
|
+
self.config = Config.new(options)
|
29
47
|
load_definitions
|
48
|
+
init_logger
|
49
|
+
end
|
50
|
+
|
51
|
+
def config_file
|
52
|
+
config.config_file
|
30
53
|
end
|
31
54
|
|
32
55
|
def load_definitions
|
@@ -34,7 +57,8 @@ module ForemanMaintain
|
|
34
57
|
# between the definitions directories
|
35
58
|
$LOAD_PATH.concat(config.definitions_dirs)
|
36
59
|
config.definitions_dirs.each do |definitions_dir|
|
37
|
-
|
60
|
+
file_paths = File.expand_path(File.join(definitions_dir, '**', '*.rb'))
|
61
|
+
Dir.glob(file_paths).each { |f| require f }
|
38
62
|
end
|
39
63
|
end
|
40
64
|
|
@@ -57,5 +81,28 @@ module ForemanMaintain
|
|
57
81
|
def available_procedures(*args)
|
58
82
|
detector.available_procedures(*args)
|
59
83
|
end
|
84
|
+
|
85
|
+
def init_logger
|
86
|
+
# Note - If timestamp added to filename then number of log files i.e second
|
87
|
+
# argument to Logger.new will not work as expected
|
88
|
+
filename = File.expand_path("#{config.log_dir}/foreman-maintain.log")
|
89
|
+
@logger = Logger.new(filename, 10, 10_240_000).tap do |logger|
|
90
|
+
logger.level = LOGGER_LEVEL_MAPPING[config.log_level] || Logger::DEBUG
|
91
|
+
logger.datetime_format = '%Y-%m-%d %H:%M:%S%z '
|
92
|
+
end
|
93
|
+
pickup_log_messages
|
94
|
+
end
|
95
|
+
|
96
|
+
def pickup_log_messages
|
97
|
+
return if config.pre_setup_log_messages.empty?
|
98
|
+
config.pre_setup_log_messages.each { |msg| logger.info msg }
|
99
|
+
config.pre_setup_log_messages.clear
|
100
|
+
end
|
101
|
+
|
102
|
+
def storage(label)
|
103
|
+
ForemanMaintain::YamlStorage.load(label)
|
104
|
+
rescue => e
|
105
|
+
logger.error "Invalid Storage label i.e #{label}. Error - #{e.message}"
|
106
|
+
end
|
60
107
|
end
|
61
108
|
end
|
@@ -7,15 +7,20 @@ module ForemanMaintain
|
|
7
7
|
|
8
8
|
attr_accessor :associated_feature
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
def assert(condition, error_message)
|
18
|
-
|
10
|
+
# run condition and mark the check as failed when not passing
|
11
|
+
#
|
12
|
+
# ==== Options
|
13
|
+
#
|
14
|
+
# * +:next_steps* - one or more procedures that can be followed to address
|
15
|
+
# the failure, will be offered to the user when running
|
16
|
+
# in interactive mode
|
17
|
+
def assert(condition, error_message, options = {})
|
18
|
+
options = options.validate_options!(:next_steps)
|
19
|
+
unless condition
|
20
|
+
next_steps = Array(options.fetch(:next_steps, []))
|
21
|
+
self.next_steps.concat(next_steps)
|
22
|
+
raise Error::Fail, error_message
|
23
|
+
end
|
19
24
|
end
|
20
25
|
|
21
26
|
# public method to be overriden
|
@@ -26,9 +31,10 @@ module ForemanMaintain
|
|
26
31
|
# internal method called by executor
|
27
32
|
def __run__(execution)
|
28
33
|
super
|
29
|
-
rescue Fail => e
|
30
|
-
|
31
|
-
|
34
|
+
rescue Error::Fail => e
|
35
|
+
fail!(e.message)
|
36
|
+
rescue Error::Warn => e
|
37
|
+
warn!(e.message)
|
32
38
|
end
|
33
39
|
end
|
34
40
|
end
|
@@ -20,11 +20,13 @@ module ForemanMaintain
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def reporter
|
23
|
-
@reporter ||= ForemanMaintain::Reporter::CLIReporter.new
|
23
|
+
@reporter ||= ForemanMaintain::Reporter::CLIReporter.new(STDOUT,
|
24
|
+
STDIN,
|
25
|
+
:assumeyes => assumeyes?)
|
24
26
|
end
|
25
27
|
|
26
28
|
def run_scenario(scenario)
|
27
|
-
ForemanMaintain::Runner.new(reporter, scenario).run
|
29
|
+
ForemanMaintain::Runner.new(reporter, scenario, :assumeyes => assumeyes?).run
|
28
30
|
end
|
29
31
|
|
30
32
|
def available_checks
|
@@ -54,6 +56,11 @@ module ForemanMaintain
|
|
54
56
|
tags.split(',').map(&:strip).map { |tag| underscorize(tag).to_sym }
|
55
57
|
end
|
56
58
|
end
|
59
|
+
|
60
|
+
def self.interactive_option
|
61
|
+
option ['-y', '--assumeyes'], :flag,
|
62
|
+
'Automatically answer yes for all questions'
|
63
|
+
end
|
57
64
|
end
|
58
65
|
end
|
59
66
|
end
|
@@ -30,6 +30,7 @@ module ForemanMaintain
|
|
30
30
|
subcommand 'check', 'Run the health checks against the system' do
|
31
31
|
label_option
|
32
32
|
tags_option
|
33
|
+
interactive_option
|
33
34
|
|
34
35
|
def execute
|
35
36
|
scenario = Scenario::FilteredScenario.new(filter)
|
@@ -45,7 +46,7 @@ module ForemanMaintain
|
|
45
46
|
if label
|
46
47
|
{ :label => label }
|
47
48
|
else
|
48
|
-
{ :tags => tags || [:
|
49
|
+
{ :tags => tags || [:default] }
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
@@ -40,6 +40,8 @@ module ForemanMaintain
|
|
40
40
|
|
41
41
|
subcommand 'check', 'Run pre-upgrade checks for upgradeing to specified version' do
|
42
42
|
parameter 'TARGET_VERSION', 'Target version of the upgrade', :required => false
|
43
|
+
interactive_option
|
44
|
+
|
43
45
|
def execute
|
44
46
|
versions_to_scenarios = available_target_versions(:pre_upgrade_check)
|
45
47
|
scenario = versions_to_scenarios[target_version]
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ForemanMaintain
|
2
|
+
module Concerns
|
3
|
+
module Hammer
|
4
|
+
def self.included(base)
|
5
|
+
base.metadata do
|
6
|
+
preparation_steps { Procedures::HammerSetup.new }
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# Run a hammer command, examples:
|
11
|
+
# hammer('host list')
|
12
|
+
def hammer(args)
|
13
|
+
Utils::Hammer.instance.run_command(args)
|
14
|
+
end
|
15
|
+
|
16
|
+
# TODO: method for specifying that the check that includes this method
|
17
|
+
# requires hammer to be setup
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,12 +1,8 @@
|
|
1
|
-
require 'logger'
|
2
|
-
|
3
1
|
module ForemanMaintain
|
4
2
|
module Concerns
|
5
3
|
module Logger
|
6
4
|
def logger
|
7
|
-
@logger ||=
|
8
|
-
logger.level = ForemanMaintain.config.log_level
|
9
|
-
end
|
5
|
+
@logger ||= ForemanMaintain.logger
|
10
6
|
end
|
11
7
|
end
|
12
8
|
end
|
@@ -1,21 +1,61 @@
|
|
1
1
|
module ForemanMaintain
|
2
2
|
module Concerns
|
3
3
|
module Metadata
|
4
|
-
|
4
|
+
# limit of steps dependent on each other, to avoid endless recursion
|
5
|
+
MAX_PREPARATION_STEPS_DEPTH = 20
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# modules not to be included in autogenerated labels
|
9
|
+
attr_accessor :top_level_modules
|
10
|
+
end
|
11
|
+
|
12
|
+
class DSL
|
13
|
+
attr_reader :data
|
14
|
+
|
15
|
+
def initialize(data = {})
|
16
|
+
@data = data
|
17
|
+
end
|
18
|
+
|
5
19
|
def label(label)
|
6
|
-
|
20
|
+
@data[:label] = label
|
7
21
|
end
|
8
22
|
|
9
23
|
def tags(*tags)
|
10
|
-
|
24
|
+
@data[:tags].concat(tags)
|
11
25
|
end
|
12
26
|
|
13
27
|
def description(description)
|
14
|
-
|
28
|
+
@data[:description] = description
|
15
29
|
end
|
16
30
|
|
17
31
|
def confine(&block)
|
18
|
-
|
32
|
+
@data[:confine_blocks] << block
|
33
|
+
end
|
34
|
+
|
35
|
+
# Parametrize the definition.
|
36
|
+
#
|
37
|
+
# == Arguments
|
38
|
+
#
|
39
|
+
# +name+: Name (Symbol) of the attribute
|
40
|
+
# +description_or_options+: Description string or a Hash with options
|
41
|
+
# +options+: Hash with options (unless specified in +descriptions_or_options+)
|
42
|
+
# +&block+: block to be called when processing the data: can be used for validation
|
43
|
+
# and type-casing of the value: expected to return the value to be used
|
44
|
+
#
|
45
|
+
# == Options
|
46
|
+
#
|
47
|
+
# +:description+: String describing the parameter
|
48
|
+
# +:required+: true if required
|
49
|
+
# +:flag+: param is just a true/false value: not expecting other values
|
50
|
+
#
|
51
|
+
def param(name, descripiton_or_options = {}, options = {}, &block)
|
52
|
+
case descripiton_or_options
|
53
|
+
when String
|
54
|
+
description = descripiton_or_options
|
55
|
+
when Hash
|
56
|
+
options = options.merge(descripiton_or_options) if descripiton_or_options.is_a?(Hash)
|
57
|
+
end
|
58
|
+
@data[:params][name] = Param.new(name, description, options, &block)
|
19
59
|
end
|
20
60
|
|
21
61
|
# Mark the class as manual: this means the instance
|
@@ -24,23 +64,33 @@ module ForemanMaintain
|
|
24
64
|
# The classes marked for manual detect need to be initialized
|
25
65
|
# in from other places (such as `additional_features` in Feature)
|
26
66
|
def manual_detection
|
27
|
-
@autodetect = false
|
67
|
+
@data[:autodetect] = false
|
28
68
|
end
|
29
69
|
|
30
|
-
|
31
|
-
|
70
|
+
# in the block, define one or more preparation steps needed
|
71
|
+
# before executing this definition
|
72
|
+
def preparation_steps(&block)
|
73
|
+
@data[:preparation_steps_blocks] << block
|
32
74
|
end
|
33
75
|
|
34
76
|
# Specify what feature the definition related to.
|
35
77
|
def for_feature(feature_label)
|
36
|
-
|
78
|
+
@data[:for_feature] = feature_label
|
37
79
|
confine do
|
38
80
|
feature(feature_label)
|
39
81
|
end
|
40
82
|
end
|
83
|
+
|
84
|
+
def self.eval_dsl(metadata, &block)
|
85
|
+
new(metadata).tap do |dsl|
|
86
|
+
dsl.instance_eval(&block)
|
87
|
+
end.data
|
88
|
+
end
|
41
89
|
end
|
42
90
|
|
43
91
|
module ClassMethods
|
92
|
+
include Finders
|
93
|
+
|
44
94
|
def inherited(klass)
|
45
95
|
sub_classes << klass
|
46
96
|
end
|
@@ -56,6 +106,10 @@ module ForemanMaintain
|
|
56
106
|
@sub_classes ||= []
|
57
107
|
end
|
58
108
|
|
109
|
+
def autodetect?
|
110
|
+
metadata.fetch(:autodetect, true)
|
111
|
+
end
|
112
|
+
|
59
113
|
def all_sub_classes(ignore_abstract_classes = true)
|
60
114
|
ret = []
|
61
115
|
ret << self if !ignore_abstract_classes || !abstract_class
|
@@ -65,22 +119,87 @@ module ForemanMaintain
|
|
65
119
|
ret
|
66
120
|
end
|
67
121
|
|
68
|
-
def metadata
|
122
|
+
def metadata(&block)
|
69
123
|
@metadata ||= initialize_metadata
|
124
|
+
if block
|
125
|
+
DSL.eval_dsl(@metadata, &block)
|
126
|
+
end
|
127
|
+
@metadata
|
128
|
+
end
|
129
|
+
|
130
|
+
def label
|
131
|
+
metadata[:label] || generate_label
|
132
|
+
end
|
133
|
+
|
134
|
+
def description
|
135
|
+
metadata[:description] || to_s
|
136
|
+
end
|
137
|
+
|
138
|
+
def tags
|
139
|
+
metadata[:tags]
|
140
|
+
end
|
141
|
+
|
142
|
+
def params
|
143
|
+
metadata[:params] || []
|
70
144
|
end
|
71
145
|
|
72
146
|
def initialize_metadata
|
73
147
|
{ :tags => [],
|
74
|
-
:confine_blocks => []
|
148
|
+
:confine_blocks => [],
|
149
|
+
:params => {},
|
150
|
+
:preparation_steps_blocks => [] }.tap do |metadata|
|
75
151
|
if superclass.respond_to?(:metadata)
|
76
152
|
metadata[:label] = superclass.metadata[:label]
|
77
153
|
end
|
78
154
|
end
|
79
155
|
end
|
156
|
+
|
157
|
+
def present?
|
158
|
+
evaluate_confines
|
159
|
+
end
|
160
|
+
|
161
|
+
def preparation_steps(recursion_depth = 0, trace = [])
|
162
|
+
raise "Too many dependent steps #{trace}" if recursion_depth > MAX_PREPARATION_STEPS_DEPTH
|
163
|
+
return @preparation_steps if defined?(@preparation_steps)
|
164
|
+
preparation_steps = metadata[:preparation_steps_blocks].map(&:call)
|
165
|
+
preparation_steps.each { |step| raise ArgumentError unless step.is_a?(Executable) }
|
166
|
+
all_preparation_steps = []
|
167
|
+
preparation_steps.each do |step|
|
168
|
+
all_preparation_steps.concat(
|
169
|
+
step.preparation_steps(recursion_depth + 1, trace + [step])
|
170
|
+
)
|
171
|
+
all_preparation_steps << step
|
172
|
+
end
|
173
|
+
@preparation_steps = all_preparation_steps
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
def evaluate_confines
|
179
|
+
raise 'Recursive confine block call detected' if @confines_evaluation_in_progress
|
180
|
+
@confines_evaluation_in_progress = true
|
181
|
+
metadata[:confine_blocks].all? do |block|
|
182
|
+
instance_exec(&block)
|
183
|
+
end
|
184
|
+
ensure
|
185
|
+
@confines_evaluation_in_progress = false
|
186
|
+
end
|
187
|
+
|
188
|
+
def generate_label
|
189
|
+
label_parts = []
|
190
|
+
name.split('::').reduce(Object) do |parent_constant, name|
|
191
|
+
constant = parent_constant.const_get(name)
|
192
|
+
unless Metadata.top_level_modules.include?(constant)
|
193
|
+
# CamelCase -> camel_case
|
194
|
+
label_parts << name.split(/(?=[A-Z])/).map(&:downcase)
|
195
|
+
end
|
196
|
+
constant
|
197
|
+
end
|
198
|
+
label_parts.join('_').to_sym
|
199
|
+
end
|
80
200
|
end
|
81
201
|
|
82
202
|
def self.included(klass)
|
83
|
-
klass.extend(DSL)
|
84
203
|
klass.extend(ClassMethods)
|
85
204
|
end
|
86
205
|
|
@@ -89,35 +208,23 @@ module ForemanMaintain
|
|
89
208
|
end
|
90
209
|
|
91
210
|
def label
|
92
|
-
|
211
|
+
self.class.label
|
93
212
|
end
|
94
213
|
|
95
214
|
def description
|
96
|
-
|
215
|
+
self.class.description
|
97
216
|
end
|
98
217
|
|
99
218
|
def tags
|
100
|
-
|
101
|
-
end
|
102
|
-
|
103
|
-
def present?
|
104
|
-
@_present ||= evaluate_confines
|
219
|
+
self.class.tags
|
105
220
|
end
|
106
221
|
|
107
|
-
|
108
|
-
|
109
|
-
def evaluate_confines
|
110
|
-
raise 'Recursive dependency in confine blocks detected' if @confines_evaluation_in_progress
|
111
|
-
@confines_evaluation_in_progress = true
|
112
|
-
metadata[:confine_blocks].all? do |block|
|
113
|
-
instance_exec(&block)
|
114
|
-
end
|
115
|
-
ensure
|
116
|
-
@confines_evaluation_in_progress = false
|
222
|
+
def params
|
223
|
+
self.class.params
|
117
224
|
end
|
118
225
|
|
119
|
-
def
|
120
|
-
self.class.
|
226
|
+
def preparation_steps(*args)
|
227
|
+
self.class.preparation_steps(*args)
|
121
228
|
end
|
122
229
|
end
|
123
230
|
end
|