Module: PuppetLitmus::RakeHelper
- Included in:
- PuppetLitmus
- Defined in:
- lib/puppet_litmus/rake_helper.rb
Overview
helper methods for the litmus rake tasks
Defined Under Namespace
Classes: LitmusTimeoutError
Instance Method Summary collapse
-
#build_module(module_dir = nil, target_dir = nil) ⇒ String
Build the module in ‘module_dir` and put the resulting compressed tarball into `target_dir`.
-
#build_modules_in_dir(source_dir, target_dir = nil) ⇒ Array
Builds all the modules in a specified directory.
-
#build_modules_in_folder(source_folder) ⇒ Object
deprecated
Deprecated.
Use ‘build_modules_in_dir` instead
-
#check_bolt_errors(result_set) ⇒ Hash
Parse out errors messages in result set returned by Bolt command.
- #check_connectivity?(inventory_hash, target_node_name) ⇒ Boolean
- #configure_path(inventory_hash) ⇒ Object
-
#get_metadata_operating_systems(metadata) ⇒ String
Gets a string representing the operating system and version.
- #install_agent(collection, targets, inventory_hash) ⇒ Object
-
#install_module(inventory_hash, target_node_name, module_tar, module_repository = nil, ignore_dependencies = false) ⇒ Object
Install a specific module tarball to the specified target.
- #metadata_module_name ⇒ Object
- #provision(provisioner, platform, inventory_vars) ⇒ Object
- #provision_list(provision_hash, key) ⇒ Object
- #provisioner_task(provisioner) ⇒ Object
-
#raise_bolt_errors(result_set, error_msg) ⇒ Object
Parse out errors messages in result set returned by Bolt command.
-
#run_local_command(command) ⇒ Object
Executes a command on the test runner.
- #start_spinner(message) ⇒ Object
- #stop_spinner(spinner) ⇒ Object
- #tear_down(node_name, inventory_hash) ⇒ Object
- #tear_down_nodes(targets, inventory_hash) ⇒ Object
-
#uninstall_module(inventory_hash, target_node_name, module_to_remove = nil, **opts) ⇒ Object
Uninstall a module from a specified target.
- #with_retries(options: { tries: Float::INFINITY }, max_wait_minutes: 8) ⇒ Object
Instance Method Details
#build_module(module_dir = nil, target_dir = nil) ⇒ String
Build the module in ‘module_dir` and put the resulting compressed tarball into `target_dir`.
251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/puppet_litmus/rake_helper.rb', line 251 def build_module(module_dir = nil, target_dir = nil) require 'puppet/modulebuilder' module_dir ||= Dir.pwd target_dir ||= File.join(source_dir, 'pkg') puts "Building '#{module_dir}' into '#{target_dir}'" builder = Puppet::Modulebuilder::Builder.new(module_dir, target_dir, nil) # Force the metadata to be read. Raises if metadata could not be found = builder. builder.build end |
#build_modules_in_dir(source_dir, target_dir = nil) ⇒ Array
Builds all the modules in a specified directory
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/puppet_litmus/rake_helper.rb', line 271 def build_modules_in_dir(source_dir, target_dir = nil) target_dir ||= File.join(Dir.pwd, 'pkg') # remove old build dir if exists, before we build afresh FileUtils.rm_rf(target_dir) if File.directory?(target_dir) module_tars = Dir.entries(source_dir).map do |entry| next if ['.', '..'].include? entry module_dir = File.join(source_dir, entry) next unless File.directory? module_dir build_module(module_dir, target_dir) end module_tars.compact end |
#build_modules_in_folder(source_folder) ⇒ Object
Use ‘build_modules_in_dir` instead
288 289 290 |
# File 'lib/puppet_litmus/rake_helper.rb', line 288 def build_modules_in_folder(source_folder) build_modules_in_dir(source_folder) end |
#check_bolt_errors(result_set) ⇒ Hash
Parse out errors messages in result set returned by Bolt command.
400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
# File 'lib/puppet_litmus/rake_helper.rb', line 400 def check_bolt_errors(result_set) errors = {} # iterate through each error result_set.each do |target_result| status = target_result['status'] # jump to the next one when there is not fail next if status != 'failure' target = target_result['target'] # get some info from error errors[target] = target_result['value'] end errors end |
#check_connectivity?(inventory_hash, target_node_name) ⇒ Boolean
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 |
# File 'lib/puppet_litmus/rake_helper.rb', line 357 def check_connectivity?(inventory_hash, target_node_name) Honeycomb.start_span(name: 'litmus.check_connectivity') do |span| ENV['HONEYCOMB_TRACE'] = span.to_trace_header # if we're only checking connectivity for a single node if target_node_name span.add_field('litmus.target_node_name', target_node_name) add_platform_field(inventory_hash, target_node_name) end include ::BoltSpec::Run target_nodes = find_targets(inventory_hash, target_node_name) puts "Checking connectivity for #{target_nodes.inspect}" span.add_field('litmus.target_nodes', target_nodes) results = run_command('cd .', target_nodes, config: nil, inventory: inventory_hash) span.add_field('litmus.bolt_result', results) failed = [] results.reject { |r| r['status'] == 'success' }.each do |result| puts "Failure connecting to #{result['target']}:\n#{result.inspect}" failed.push(result['target']) end span.add_field('litmus.connectivity_success', results.select { |r| r['status'] == 'success' }) span.add_field('litmus.connectivity_failure', results.reject { |r| r['status'] == 'success' }) raise "Connectivity has failed on: #{failed}" unless failed.length.zero? puts 'Connectivity check PASSED.' true end end |
#configure_path(inventory_hash) ⇒ Object
231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/puppet_litmus/rake_helper.rb', line 231 def configure_path(inventory_hash) results = [] # fix the path on ssh_nodes unless inventory_hash['groups'].select { |group| group['name'] == 'ssh_nodes' && !group['targets'].empty? }.size.zero? results << run_command('echo PATH="$PATH:/opt/puppetlabs/puppet/bin" > /etc/environment', 'ssh_nodes', config: nil, inventory: inventory_hash) end unless inventory_hash['groups'].select { |group| group['name'] == 'winrm_nodes' && !group['targets'].empty? }.size.zero? results << run_command('[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\Program Files\Puppet Labs\Puppet\bin;C:\Program Files (x86)\Puppet Labs\Puppet\bin", "Machine")', 'winrm_nodes', config: nil, inventory: inventory_hash) end results end |
#get_metadata_operating_systems(metadata) ⇒ String
Gets a string representing the operating system and version.
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/puppet_litmus/rake_helper.rb', line 64 def () return unless .is_a?(Hash) return unless ['operatingsystem_support'].is_a?(Array) ['operatingsystem_support'].each do |os_info| next unless os_info['operatingsystem'] && os_info['operatingsystemrelease'] os_name = case os_info['operatingsystem'] when 'Amazon', 'Archlinux', 'AIX', 'OSX' next when 'OracleLinux' 'oracle' when 'Windows' 'win' else os_info['operatingsystem'].downcase end os_info['operatingsystemrelease'].each do |release| version = case os_name when 'ubuntu', 'osx' release.sub('.', '') when 'sles' release.gsub(%r{ SP[14]}, '') when 'win' release = release.delete('.') if release.include? '8.1' release.sub('Server', '').sub('10', '10-pro') else release end yield "#{os_name}-#{version.downcase}-x86_64".delete(' ') end end end |
#install_agent(collection, targets, inventory_hash) ⇒ Object
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/puppet_litmus/rake_helper.rb', line 209 def install_agent(collection, targets, inventory_hash) Honeycomb.start_span(name: 'litmus.install_agent') do |span| ENV['HONEYCOMB_TRACE'] = span.to_trace_header span.add_field('litmus.collection', collection) span.add_field('litmus.targets', targets) include ::BoltSpec::Run params = if collection.nil? {} else { 'collection' => collection } end raise "puppet_agent was not found in #{DEFAULT_CONFIG_DATA['modulepath']}, please amend the .fixtures.yml file" \ unless File.directory?(File.join(DEFAULT_CONFIG_DATA['modulepath'], 'puppet_agent')) # using boltspec, when the runner is called it changes the inventory_hash dropping the version field. The clone works around this bolt_result = run_task('puppet_agent::install', targets, params, config: DEFAULT_CONFIG_DATA, inventory: inventory_hash.clone) raise_bolt_errors(bolt_result, 'Installation of agent failed.') bolt_result end end |
#install_module(inventory_hash, target_node_name, module_tar, module_repository = nil, ignore_dependencies = false) ⇒ Object
Install a specific module tarball to the specified target. This method installs dependencies using a forge repository.
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'lib/puppet_litmus/rake_helper.rb', line 301 def install_module(inventory_hash, target_node_name, module_tar, module_repository = nil, ignore_dependencies = false) # rubocop:disable Style/OptionalBooleanParameter Honeycomb.start_span(name: 'install_module') do |span| ENV['HONEYCOMB_TRACE'] = span.to_trace_header span.add_field('litmus.target_node_name', target_node_name) span.add_field('litmus.module_tar', module_tar) # make sure the module to install is not installed # otherwise `puppet module install` might silently skip it module_name = File.basename(module_tar, '.tar.gz').split('-', 3)[0..1].join('-') uninstall_module(inventory_hash.clone, target_node_name, module_name, force: true) include ::BoltSpec::Run target_nodes = find_targets(inventory_hash, target_node_name) span.add_field('litmus.target_nodes', target_nodes) bolt_result = upload_file(module_tar, File.basename(module_tar), target_nodes, options: {}, config: nil, inventory: inventory_hash.clone) raise_bolt_errors(bolt_result, 'Failed to upload module.') module_repository_opts = "--module_repository '#{module_repository}'" unless module_repository.nil? install_module_command = "puppet module install #{module_repository_opts} #{File.basename(module_tar)}" install_module_command += ' --ignore-dependencies --force' if ignore_dependencies.to_s.downcase == 'true' span.add_field('litmus.install_module_command', install_module_command) bolt_result = run_command(install_module_command, target_nodes, config: nil, inventory: inventory_hash.clone) raise_bolt_errors(bolt_result, "Installation of package #{File.basename(module_tar)} failed.") bolt_result end end |
#metadata_module_name ⇒ Object
330 331 332 333 334 335 336 337 338 |
# File 'lib/puppet_litmus/rake_helper.rb', line 330 def require 'json' raise 'Could not find metadata.json' unless File.exist?(File.join(Dir.pwd, 'metadata.json')) = JSON.parse(File.read(File.join(Dir.pwd, 'metadata.json'))) raise 'Could not read module name from metadata.json' if ['name'].nil? ['name'] end |
#provision(provisioner, platform, inventory_vars) ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/puppet_litmus/rake_helper.rb', line 119 def provision(provisioner, platform, inventory_vars) include ::BoltSpec::Run raise "the provision module was not found in #{DEFAULT_CONFIG_DATA['modulepath']}, please amend the .fixtures.yml file" unless File.directory?(File.join(DEFAULT_CONFIG_DATA['modulepath'], 'provision')) params = { 'action' => 'provision', 'platform' => platform, 'inventory' => Dir.pwd } params['vars'] = inventory_vars unless inventory_vars.nil? Honeycomb.add_field_to_trace('litmus.provisioner', provisioner) Honeycomb.start_span(name: 'litmus.provision') do |span| ENV['HONEYCOMB_TRACE'] = span.to_trace_header span.add_field('litmus.platform', platform) task_name = provisioner_task(provisioner) span.add_field('litmus.task_name', task_name) span.add_field('litmus.params', params) span.add_field('litmus.config', DEFAULT_CONFIG_DATA) bolt_result = run_task(task_name, 'localhost', params, config: DEFAULT_CONFIG_DATA, inventory: nil) span.add_field('litmus.result', bolt_result) span.add_field('litmus.node_name', bolt_result&.first&.dig('value', 'node_name')) raise_bolt_errors(bolt_result, "provisioning of #{platform} failed.") bolt_result end end |
#provision_list(provision_hash, key) ⇒ Object
147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/puppet_litmus/rake_helper.rb', line 147 def provision_list(provision_hash, key) provisioner = provision_hash[key]['provisioner'] inventory_vars = provision_hash[key]['vars'] # Splat the params into environment variables to pass to the provision task but only in this runspace provision_hash[key]['params']&.each { |k, value| ENV[k.upcase] = value.to_s } results = [] Honeycomb.current_span.add_field('litmus.images', provision_hash[key]['images']) provision_hash[key]['images'].each do |image| results << provision(provisioner, image, inventory_vars) end results end |
#provisioner_task(provisioner) ⇒ Object
387 388 389 390 391 392 393 394 |
# File 'lib/puppet_litmus/rake_helper.rb', line 387 def provisioner_task(provisioner) if SUPPORTED_PROVISIONERS.include?(provisioner) "provision::#{provisioner}" else warn "WARNING: Unsuported provisioner '#{provisioner}', try #{SUPPORTED_PROVISIONERS.join('/')}" provisioner.to_s end end |
#raise_bolt_errors(result_set, error_msg) ⇒ Object
Parse out errors messages in result set returned by Bolt command. If there are errors, raise them.
419 420 421 422 423 424 425 426 427 428 |
# File 'lib/puppet_litmus/rake_helper.rb', line 419 def raise_bolt_errors(result_set, error_msg) errors = check_bolt_errors(result_set) unless errors.empty? formatted_results = errors.map { |k, v| " #{k}: #{v.inspect}" }.join("\n") raise "#{error_msg}\nResults:\n#{formatted_results}}" end nil end |
#run_local_command(command) ⇒ Object
Executes a command on the test runner.
104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/puppet_litmus/rake_helper.rb', line 104 def run_local_command(command) Honeycomb.start_span(name: 'litmus.run_local_command') do |span| ENV['HONEYCOMB_TRACE'] = span.to_trace_header span.add_field('litmus.command', command) require 'open3' stdout, stderr, status = Open3.capture3(command) = "Attempted to run\ncommand:'#{command}'\nstdout:#{stdout}\nstderr:#{stderr}" raise unless status.to_i.zero? stdout end end |
#start_spinner(message) ⇒ Object
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 |
# File 'lib/puppet_litmus/rake_helper.rb', line 430 def start_spinner() if (ENV['CI'] || '').downcase == 'true' puts spinner = Thread.new do # CI systems are strange beasts, we only output a '.' every wee while to keep the terminal alive. loop do printf '.' sleep(10) end end else require 'tty-spinner' spinner = TTY::Spinner.new("[:spinner] #{}") spinner.auto_spin end spinner end |
#stop_spinner(spinner) ⇒ Object
448 449 450 451 452 453 454 |
# File 'lib/puppet_litmus/rake_helper.rb', line 448 def stop_spinner(spinner) if (ENV['CI'] || '').downcase == 'true' Thread.kill(spinner) else spinner.success end end |
#tear_down(node_name, inventory_hash) ⇒ Object
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/puppet_litmus/rake_helper.rb', line 193 def tear_down(node_name, inventory_hash) Honeycomb.start_span(name: 'litmus.tear_down') do |span| ENV['HONEYCOMB_TRACE'] = span.to_trace_header # how do we know what provisioner to use span.add_field('litmus.node_name', node_name) add_platform_field(inventory_hash, node_name) params = { 'action' => 'tear_down', 'node_name' => node_name, 'inventory' => Dir.pwd } node_facts = facts_from_node(inventory_hash, node_name) bolt_result = run_task(provisioner_task(node_facts['provisioner']), 'localhost', params, config: DEFAULT_CONFIG_DATA, inventory: nil) raise_bolt_errors(bolt_result, "tear_down of #{node_name} failed.") bolt_result end end |
#tear_down_nodes(targets, inventory_hash) ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/puppet_litmus/rake_helper.rb', line 161 def tear_down_nodes(targets, inventory_hash) Honeycomb.start_span(name: 'litmus.tear_down_nodes') do |span| ENV['HONEYCOMB_TRACE'] = span.to_trace_header span.add_field('litmus.targets', targets) include ::BoltSpec::Run config_data = { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') } raise "the provision module was not found in #{config_data['modulepath']}, please amend the .fixtures.yml file" unless File.directory?(File.join(config_data['modulepath'], 'provision')) results = {} targets.each do |node_name| next if node_name == 'litmus_localhost' result = tear_down(node_name, inventory_hash) # Some provisioners tear_down targets that were created as a batch job. # These provisioners should return the list of additional targets # removed so that we do not attempt to process them. if result != [] && result[0]['value'].key?('removed') removed_targets = result[0]['value']['removed'] result[0]['value'].delete('removed') removed_targets.each do |removed_target| targets.delete(removed_target) results[removed_target] = result end end results[node_name] = result unless result == [] end results end end |
#uninstall_module(inventory_hash, target_node_name, module_to_remove = nil, **opts) ⇒ Object
Uninstall a module from a specified target
345 346 347 348 349 350 351 352 353 354 355 |
# File 'lib/puppet_litmus/rake_helper.rb', line 345 def uninstall_module(inventory_hash, target_node_name, module_to_remove = nil, **opts) include ::BoltSpec::Run module_name = module_to_remove || target_nodes = find_targets(inventory_hash, target_node_name) install_module_command = "puppet module uninstall #{module_name}" install_module_command += ' --force' if opts[:force] bolt_result = run_command(install_module_command, target_nodes, config: nil, inventory: inventory_hash) # `puppet module uninstall --force` fails if the module is not installed. Ignore errors when force is set raise_bolt_errors(bolt_result, "uninstalling #{module_name} failed.") unless opts[:force] bolt_result end |
#with_retries(options: { tries: Float::INFINITY }, max_wait_minutes: 8) ⇒ Object
467 468 469 470 471 472 473 474 |
# File 'lib/puppet_litmus/rake_helper.rb', line 467 def with_retries(options: { tries: Float::INFINITY }, max_wait_minutes: 8) stop = Time.now + (max_wait_minutes * 60) Retryable.retryable(.merge(not: [LitmusTimeoutError])) do raise LitmusTimeoutError if Time.now > stop yield end end |