foreman_maintain 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +107 -25
  3. data/bin/foreman-maintain +1 -0
  4. data/definitions/checks/disk_speed_minimal.rb +31 -19
  5. data/definitions/checks/foreman_tasks/invalid/check_old.rb +20 -0
  6. data/definitions/checks/foreman_tasks/invalid/check_pending_state.rb +20 -0
  7. data/definitions/checks/foreman_tasks/invalid/check_planning_state.rb +20 -0
  8. data/definitions/checks/foreman_tasks/not_paused.rb +29 -0
  9. data/definitions/checks/foreman_tasks/not_running.rb +14 -0
  10. data/definitions/checks/sync_plans/with_disabled_status.rb +18 -0
  11. data/definitions/checks/sync_plans/with_enabled_status.rb +18 -0
  12. data/definitions/checks/system_registration.rb +31 -0
  13. data/definitions/features/downstream.rb +5 -3
  14. data/definitions/features/foreman_1_11_x.rb +4 -2
  15. data/definitions/features/foreman_1_7_x.rb +5 -3
  16. data/definitions/features/foreman_database.rb +11 -5
  17. data/definitions/features/foreman_tasks.rb +118 -9
  18. data/definitions/features/sync_plans.rb +75 -0
  19. data/definitions/features/upstream.rb +5 -3
  20. data/definitions/procedures/foreman_tasks/delete.rb +33 -0
  21. data/definitions/procedures/foreman_tasks/resume.rb +14 -0
  22. data/definitions/procedures/foreman_tasks/ui_investigate.rb +19 -0
  23. data/definitions/procedures/hammer_setup.rb +50 -0
  24. data/definitions/procedures/install_package.rb +17 -0
  25. data/definitions/procedures/sync_plans/disable.rb +22 -0
  26. data/definitions/procedures/sync_plans/enable.rb +21 -0
  27. data/definitions/scenarios/pre_upgrade_check_foreman_1_14.rb +7 -6
  28. data/definitions/scenarios/pre_upgrade_check_satellite_6_0_z.rb +8 -6
  29. data/definitions/scenarios/pre_upgrade_check_satellite_6_1.rb +8 -6
  30. data/definitions/scenarios/pre_upgrade_check_satellite_6_1_z.rb +8 -6
  31. data/definitions/scenarios/pre_upgrade_check_satellite_6_2.rb +8 -6
  32. data/definitions/scenarios/pre_upgrade_check_satellite_6_2_z.rb +8 -6
  33. data/definitions/scenarios/pre_upgrade_check_satellite_6_3.rb +8 -6
  34. data/lib/foreman_maintain.rb +52 -5
  35. data/lib/foreman_maintain/check.rb +18 -12
  36. data/lib/foreman_maintain/cli/base.rb +9 -2
  37. data/lib/foreman_maintain/cli/health_command.rb +2 -1
  38. data/lib/foreman_maintain/cli/upgrade_command.rb +2 -0
  39. data/lib/foreman_maintain/concerns/hammer.rb +20 -0
  40. data/lib/foreman_maintain/concerns/logger.rb +1 -5
  41. data/lib/foreman_maintain/concerns/metadata.rb +138 -31
  42. data/lib/foreman_maintain/concerns/system_helpers.rb +36 -32
  43. data/lib/foreman_maintain/config.rb +40 -5
  44. data/lib/foreman_maintain/core_ext.rb +24 -0
  45. data/lib/foreman_maintain/detector.rb +12 -13
  46. data/lib/foreman_maintain/error.rb +28 -0
  47. data/lib/foreman_maintain/executable.rb +86 -11
  48. data/lib/foreman_maintain/feature.rb +1 -0
  49. data/lib/foreman_maintain/param.rb +47 -0
  50. data/lib/foreman_maintain/reporter.rb +20 -3
  51. data/lib/foreman_maintain/reporter/cli_reporter.rb +166 -66
  52. data/lib/foreman_maintain/runner.rb +56 -13
  53. data/lib/foreman_maintain/runner/execution.rb +8 -0
  54. data/lib/foreman_maintain/scenario.rb +46 -2
  55. data/lib/foreman_maintain/top_level_modules.rb +3 -0
  56. data/lib/foreman_maintain/utils.rb +2 -0
  57. data/lib/foreman_maintain/utils/command_runner.rb +101 -0
  58. data/lib/foreman_maintain/utils/disk/device.rb +5 -9
  59. data/lib/foreman_maintain/utils/hammer.rb +78 -0
  60. data/lib/foreman_maintain/version.rb +1 -1
  61. data/lib/foreman_maintain/yaml_storage.rb +48 -0
  62. metadata +27 -9
  63. data/definitions/checks/foreman_tasks_not_paused.rb +0 -14
  64. data/definitions/checks/foreman_tasks_not_running.rb +0 -10
  65. data/definitions/procedures/foreman_tasks_resume.rb +0 -13
  66. data/lib/foreman_maintain/logger.rb +0 -11
@@ -3,6 +3,8 @@ module ForemanMaintain
3
3
  # Class representing an execution of a single step in scenario
4
4
  class Execution
5
5
  include Concerns::Logger
6
+ extend Forwardable
7
+ def_delegators :@reporter, :with_spinner, :puts, :print, :ask, :assumeyes?
6
8
 
7
9
  # Step performed as part of the execution
8
10
  attr_reader :step
@@ -16,6 +18,8 @@ module ForemanMaintain
16
18
  # Output of the execution, to be filled by execution step
17
19
  attr_accessor :output
18
20
 
21
+ attr_reader :reporter
22
+
19
23
  def initialize(step, reporter)
20
24
  @step = step
21
25
  @reporter = reporter
@@ -35,6 +39,10 @@ module ForemanMaintain
35
39
  @status == :fail
36
40
  end
37
41
 
42
+ def warning?
43
+ @status == :warning
44
+ end
45
+
38
46
  def run
39
47
  @status = :running
40
48
  @reporter.before_execution_starts(self)
@@ -8,13 +8,14 @@ module ForemanMaintain
8
8
  attr_reader :steps
9
9
 
10
10
  class FilteredScenario < Scenario
11
- manual_detection
11
+ metadata { manual_detection }
12
+
12
13
  attr_reader :filter_label, :filter_tags
13
14
 
14
15
  def initialize(filter)
15
16
  @filter_tags = filter[:tags]
16
17
  @filter_label = filter[:label]
17
- @steps = ForemanMaintain.available_checks(filter)
18
+ @steps = ForemanMaintain.available_checks(filter).map(&:ensure_instance)
18
19
  end
19
20
 
20
21
  def description
@@ -36,6 +37,23 @@ module ForemanMaintain
36
37
  end
37
38
  end
38
39
 
40
+ class PreparationScenario < Scenario
41
+ metadata do
42
+ manual_detection
43
+ description 'preparation steps required to run the next scenarios'
44
+ end
45
+
46
+ attr_reader :main_scenario
47
+
48
+ def initialize(main_scenario)
49
+ @main_scenario = main_scenario
50
+ end
51
+
52
+ def steps
53
+ @steps ||= main_scenario.preparation_steps.find_all(&:necessary?)
54
+ end
55
+ end
56
+
39
57
  def initialize
40
58
  @steps = []
41
59
  compose
@@ -44,6 +62,32 @@ module ForemanMaintain
44
62
  # Override to compose steps for the scenario
45
63
  def compose; end
46
64
 
65
+ def preparation_steps
66
+ # we first take the preparation steps defined for the scenario + collect
67
+ # preparation steps for the steps inside the scenario
68
+ steps.inject(super.dup) do |results, step|
69
+ results.concat(step.preparation_steps)
70
+ end.uniq
71
+ end
72
+
73
+ # scenarios to be run before this scenario
74
+ def before_scenarios
75
+ scenarios = []
76
+ preparation_scenario = PreparationScenario.new(self)
77
+ scenarios << [preparation_scenario] unless preparation_scenario.steps.empty?
78
+ scenarios
79
+ end
80
+
81
+ def add_steps(steps)
82
+ steps.each do |step|
83
+ self.steps << step.ensure_instance
84
+ end
85
+ end
86
+
87
+ def add_step(step)
88
+ add_steps([step])
89
+ end
90
+
47
91
  def self.inspect
48
92
  "Scenario Class #{metadata[:description]}<#{name}>"
49
93
  end
@@ -11,3 +11,6 @@ end
11
11
 
12
12
  module Scenarios
13
13
  end
14
+
15
+ # do not include this names in autogenerated labels
16
+ ForemanMaintain::Concerns::Metadata.top_level_modules = [Features, Checks, Procedures, Scenarios]
@@ -1 +1,3 @@
1
+ require 'foreman_maintain/utils/command_runner'
1
2
  require 'foreman_maintain/utils/disk'
3
+ require 'foreman_maintain/utils/hammer'
@@ -0,0 +1,101 @@
1
+ require 'English'
2
+ require 'tempfile'
3
+
4
+ module ForemanMaintain
5
+ module Utils
6
+ # Wrapper around running a command
7
+ class CommandRunner
8
+ attr_reader :logger, :command
9
+
10
+ def initialize(logger, command, options)
11
+ options.validate_options!(:stdin, :hidden_patterns, :interactive)
12
+ @logger = logger
13
+ @command = command
14
+ @stdin = options[:stdin]
15
+ @hidden_patterns = Array(options[:hidden_patterns])
16
+ @interactive = options[:interactive]
17
+ @options = options
18
+ raise ArgumentError, 'Can not pass stdin for interactive command' if @interactive && @stdin
19
+ end
20
+
21
+ def run
22
+ logger.debug(hide_strings("Running command #{@command} with stdin #{@stdin.inspect}"))
23
+ if @interactive
24
+ run_interactively
25
+ else
26
+ run_non_interactively
27
+ end
28
+ logger.debug("output of the command:\n #{hide_strings(output)}")
29
+ end
30
+
31
+ def interactive?
32
+ @interactive
33
+ end
34
+
35
+ def output
36
+ raise 'Command not yet executed' unless defined? @output
37
+ @output
38
+ end
39
+
40
+ def exit_status
41
+ raise 'Command not yet executed' unless defined? @exit_status
42
+ @exit_status
43
+ end
44
+
45
+ def success?
46
+ exit_status == 0
47
+ end
48
+
49
+ def execution_error
50
+ raise Error::ExecutionError.new(hide_strings(@command),
51
+ exit_status,
52
+ hide_strings(@stdin),
53
+ @interactive ? nil : hide_strings(@output))
54
+ end
55
+
56
+ private
57
+
58
+ # rubocop:disable Metrics/AbcSize
59
+ def run_interactively
60
+ # use tmp files to capture output and exit status of the command when
61
+ # running interactively
62
+ log_file = Tempfile.open('captured-output')
63
+ exit_file = Tempfile.open('captured-exit-code')
64
+ Kernel.system("script -qc '#{full_command}; echo $? > #{exit_file.path}' #{log_file.path}")
65
+ File.open(log_file.path) { |f| @output = f.read }
66
+ File.open(exit_file.path) do |f|
67
+ exit_status = f.read.strip
68
+ @exit_status = if exit_status.empty?
69
+ 256
70
+ else
71
+ exit_status.to_i
72
+ end
73
+ end
74
+ ensure
75
+ log_file.close
76
+ exit_file.close
77
+ end
78
+
79
+ def run_non_interactively
80
+ IO.popen(full_command, 'r+') do |f|
81
+ if @stdin
82
+ f.puts(@stdin)
83
+ f.close_write
84
+ end
85
+ @output = f.read.strip
86
+ end
87
+ @exit_status = $CHILD_STATUS.exitstatus
88
+ end
89
+
90
+ def full_command
91
+ "#{@command} 2>&1"
92
+ end
93
+
94
+ def hide_strings(string)
95
+ @hidden_patterns.reduce(string) do |result, hidden_pattern|
96
+ result.gsub(hidden_pattern, '[FILTERED]')
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -2,28 +2,24 @@ module ForemanMaintain
2
2
  module Utils
3
3
  module Disk
4
4
  class Device
5
+ extend Forwardable
6
+
5
7
  include ForemanMaintain::Concerns::SystemHelpers
6
8
 
7
- EXTERNAL_MOUNT_TYPE = %w(fuseblk nfs).freeze
9
+ EXTERNAL_MOUNT_TYPE = %w[fuseblk nfs].freeze
8
10
 
9
11
  attr_accessor :dir, :name, :unit, :read_speed
10
12
 
11
13
  attr_reader :io_device
12
14
 
15
+ def_delegators :io_device, :unit, :read_speed
16
+
13
17
  def initialize(dir)
14
18
  @dir = dir
15
19
  @name = find_device
16
20
  @io_device = init_io_device
17
21
  end
18
22
 
19
- def unit
20
- @unit ||= io_device.unit
21
- end
22
-
23
- def read_speed
24
- @read_speed ||= io_device.read_speed
25
- end
26
-
27
23
  def slow_disk_error_msg
28
24
  "Slow disk detected #{dir} mounted on #{name}.
29
25
  Actual disk speed: #{read_speed} #{default_unit}
@@ -0,0 +1,78 @@
1
+ module ForemanMaintain
2
+ module Utils
3
+ class Hammer
4
+ class CredentialsError < RuntimeError
5
+ end
6
+ include Concerns::SystemHelpers
7
+
8
+ attr_reader :settings
9
+
10
+ def self.instance
11
+ @instance ||= new
12
+ end
13
+
14
+ def config_file
15
+ config_dir = File.dirname(ForemanMaintain.config_file)
16
+ File.join(config_dir, 'foreman-maintain-hammer.yml')
17
+ end
18
+
19
+ # tries to setup hammer based on default configuration and returns true
20
+ # if it succeeds
21
+ # rubocop:disable Metrics/AbcSize
22
+ def setup_from_default
23
+ return unless File.exist?(default_config_file)
24
+ hammer_config = YAML.load_file(default_config_file)
25
+ foreman_config = hammer_config.fetch(:foreman, {})
26
+ if !foreman_config[:username].to_s.empty? && !foreman_config[:password].to_s.empty?
27
+ save_config(hammer_config)
28
+ ready? && default_config_file
29
+ end
30
+ end
31
+
32
+ def setup_from_answers(username = nil, password = nil)
33
+ save_config(:foreman => { :username => username, :password => password })
34
+ ready?
35
+ end
36
+
37
+ # Run a hammer command, examples:
38
+ # run_command('host list')
39
+ def run_command(args)
40
+ output = execute("#{command_base} #{args}")
41
+ if output =~ /Invalid username or password/
42
+ raise CredentialsError, 'Invalid hammer credentials: '\
43
+ 'we expect the hammer username/password to be stored'\
44
+ "in #{config_file}"
45
+ end
46
+ output
47
+ end
48
+
49
+ def configured?
50
+ File.exist?(config_file)
51
+ end
52
+
53
+ def ready?
54
+ return @ready if defined? @ready
55
+ return false unless configured?
56
+ run_command('architecture list')
57
+ @ready = true
58
+ rescue CredentialsError
59
+ @ready = false
60
+ end
61
+
62
+ private
63
+
64
+ def default_config_file
65
+ @default_config_file ||= File.expand_path('~/.hammer/cli.modules.d/foreman.yml')
66
+ end
67
+
68
+ def command_base
69
+ %(LANG=en_US.utf-8 hammer -c "#{config_file}" --interactive=no)
70
+ end
71
+
72
+ def save_config(config)
73
+ remove_instance_variable '@ready' if defined? @ready
74
+ File.open(config_file, 'w', 0o600) { |f| f.puts YAML.dump(config) }
75
+ end
76
+ end
77
+ end
78
+ end
@@ -1,3 +1,3 @@
1
1
  module ForemanMaintain
2
- VERSION = '0.0.2'.freeze
2
+ VERSION = '0.0.3'.freeze
3
3
  end
@@ -0,0 +1,48 @@
1
+ module ForemanMaintain
2
+ class YamlStorage
3
+ extend Forwardable
4
+ attr_reader :sub_key, :data
5
+ def_delegators :data, :[], :[]=
6
+
7
+ def initialize(sub_key, data = {})
8
+ @sub_key = sub_key
9
+ @data = data
10
+ end
11
+
12
+ def save
13
+ self.class.save_sub_key(sub_key, data)
14
+ end
15
+
16
+ class << self
17
+ def load_file
18
+ if File.exist?(storage_file_path)
19
+ YAML.load_file(storage_file_path) || {}
20
+ else
21
+ {}
22
+ end
23
+ end
24
+
25
+ def storage_file_path
26
+ File.expand_path(ForemanMaintain.config.storage_file)
27
+ end
28
+
29
+ def storage_register
30
+ @storage_register ||= {}
31
+ end
32
+
33
+ def load(sub_key)
34
+ storage_register[sub_key] ||= load_file.fetch(sub_key, {})
35
+ YamlStorage.new(sub_key, storage_register[sub_key])
36
+ end
37
+
38
+ def save_sub_key(sub_key, data_val)
39
+ new_data = load_file.merge(sub_key => data_val)
40
+ File.open(storage_file_path, 'w') { |f| f.write new_data.to_yaml }
41
+ end
42
+
43
+ def save_all
44
+ storage_register.values.each(&:save)
45
+ end
46
+ end
47
+ end
48
+ end
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.0.2
4
+ version: 0.0.3
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: 2017-03-16 00:00:00.000000000 Z
11
+ date: 2017-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clamp
@@ -94,9 +94,8 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
- description: |
98
- Provides various features that helps keeping the Foreman/Satellite up and
99
- running.
97
+ description: Provides various features that helps keeping the Foreman/Satellite up
98
+ and running.
100
99
  email: inecas@redhat.com
101
100
  executables:
102
101
  - foreman-maintain
@@ -109,15 +108,28 @@ files:
109
108
  - README.md
110
109
  - bin/foreman-maintain
111
110
  - definitions/checks/disk_speed_minimal.rb
112
- - definitions/checks/foreman_tasks_not_paused.rb
113
- - definitions/checks/foreman_tasks_not_running.rb
111
+ - definitions/checks/foreman_tasks/invalid/check_old.rb
112
+ - definitions/checks/foreman_tasks/invalid/check_pending_state.rb
113
+ - definitions/checks/foreman_tasks/invalid/check_planning_state.rb
114
+ - definitions/checks/foreman_tasks/not_paused.rb
115
+ - definitions/checks/foreman_tasks/not_running.rb
116
+ - definitions/checks/sync_plans/with_disabled_status.rb
117
+ - definitions/checks/sync_plans/with_enabled_status.rb
118
+ - definitions/checks/system_registration.rb
114
119
  - definitions/features/downstream.rb
115
120
  - definitions/features/foreman_1_11_x.rb
116
121
  - definitions/features/foreman_1_7_x.rb
117
122
  - definitions/features/foreman_database.rb
118
123
  - definitions/features/foreman_tasks.rb
124
+ - definitions/features/sync_plans.rb
119
125
  - definitions/features/upstream.rb
120
- - definitions/procedures/foreman_tasks_resume.rb
126
+ - definitions/procedures/foreman_tasks/delete.rb
127
+ - definitions/procedures/foreman_tasks/resume.rb
128
+ - definitions/procedures/foreman_tasks/ui_investigate.rb
129
+ - definitions/procedures/hammer_setup.rb
130
+ - definitions/procedures/install_package.rb
131
+ - definitions/procedures/sync_plans/disable.rb
132
+ - definitions/procedures/sync_plans/enable.rb
121
133
  - definitions/scenarios/pre_upgrade_check_foreman_1_14.rb
122
134
  - definitions/scenarios/pre_upgrade_check_satellite_6_0_z.rb
123
135
  - definitions/scenarios/pre_upgrade_check_satellite_6_1.rb
@@ -132,14 +144,17 @@ files:
132
144
  - lib/foreman_maintain/cli/health_command.rb
133
145
  - lib/foreman_maintain/cli/upgrade_command.rb
134
146
  - lib/foreman_maintain/concerns/finders.rb
147
+ - lib/foreman_maintain/concerns/hammer.rb
135
148
  - lib/foreman_maintain/concerns/logger.rb
136
149
  - lib/foreman_maintain/concerns/metadata.rb
137
150
  - lib/foreman_maintain/concerns/system_helpers.rb
138
151
  - lib/foreman_maintain/config.rb
152
+ - lib/foreman_maintain/core_ext.rb
139
153
  - lib/foreman_maintain/detector.rb
154
+ - lib/foreman_maintain/error.rb
140
155
  - lib/foreman_maintain/executable.rb
141
156
  - lib/foreman_maintain/feature.rb
142
- - lib/foreman_maintain/logger.rb
157
+ - lib/foreman_maintain/param.rb
143
158
  - lib/foreman_maintain/procedure.rb
144
159
  - lib/foreman_maintain/reporter.rb
145
160
  - lib/foreman_maintain/reporter/cli_reporter.rb
@@ -148,13 +163,16 @@ files:
148
163
  - lib/foreman_maintain/scenario.rb
149
164
  - lib/foreman_maintain/top_level_modules.rb
150
165
  - lib/foreman_maintain/utils.rb
166
+ - lib/foreman_maintain/utils/command_runner.rb
151
167
  - lib/foreman_maintain/utils/disk.rb
152
168
  - lib/foreman_maintain/utils/disk/device.rb
153
169
  - lib/foreman_maintain/utils/disk/io.rb
154
170
  - lib/foreman_maintain/utils/disk/io/block_device.rb
155
171
  - lib/foreman_maintain/utils/disk/io/file_system.rb
156
172
  - lib/foreman_maintain/utils/disk/nil_device.rb
173
+ - lib/foreman_maintain/utils/hammer.rb
157
174
  - lib/foreman_maintain/version.rb
175
+ - lib/foreman_maintain/yaml_storage.rb
158
176
  homepage: https://github.com/theforeman/foreman_maintain
159
177
  licenses:
160
178
  - GPL-3.0