puppet_litmus 0.18.4 → 0.19.0
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/exe/matrix_from_metadata +62 -0
- data/lib/puppet_litmus/inventory_manipulation.rb +6 -7
- data/lib/puppet_litmus/puppet_helpers.rb +37 -1
- data/lib/puppet_litmus/rake_helper.rb +12 -6
- data/lib/puppet_litmus/rake_tasks.rb +40 -19
- data/lib/puppet_litmus/spec_helper_acceptance.rb +3 -0
- data/lib/puppet_litmus/version.rb +1 -1
- data/spec/lib/puppet_litmus/puppet_helpers_spec.rb +47 -9
- data/spec/lib/puppet_litmus/rake_tasks_spec.rb +7 -7
- metadata +9 -7
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: ffba803cc6b53c4bdb7084bf11be4fac807f3b3cd237c5ddb297dcf6ca3a403d
         | 
| 4 | 
            +
              data.tar.gz: 5cdb613f2be957e20a63fc1250b10113e468e162817657f0f987675f2ba7c055
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: ea1fd95a69bfac81b56f94f3ee28b91be2587c501bf24729931c128315e41d5eaf937dce013ee0d63ec7a350469ac32ab0d7711e50411a0e5fe00340dabdd803
         | 
| 7 | 
            +
              data.tar.gz: 899ac2b0edb422ccf35c9cdb5f46bec6b2a6a97557dca12ffc994e046ed8cf1e6eec2553865a3c4439b272d1dd29b0111fc24b2e1bb93575cb77fc0bfd7606b1
         | 
| @@ -0,0 +1,62 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
            # frozen_string_literal: true
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            # this script creates a build matrix for github actions from the claimed supported platforms in metadata.json
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            require 'json'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            IMAGE_TABLE = {
         | 
| 9 | 
            +
              'RedHat-6' => 'rhel-6',
         | 
| 10 | 
            +
              'RedHat-7' => 'rhel-7',
         | 
| 11 | 
            +
              'RedHat-8' => 'rhel-8',
         | 
| 12 | 
            +
              'SLES-12' => 'sles-12',
         | 
| 13 | 
            +
              'SLES-15' => 'sles-15',
         | 
| 14 | 
            +
              'Windows-2012 R2' => 'windows-2012-r2-core',
         | 
| 15 | 
            +
              'Windows-2016' => 'windows-2016',
         | 
| 16 | 
            +
              'Windows-2019' => 'windows-2019-core',
         | 
| 17 | 
            +
            }.freeze
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            DOCKER_PLATFORMS = [
         | 
| 20 | 
            +
              'CentOS-6',
         | 
| 21 | 
            +
              'CentOS-7',
         | 
| 22 | 
            +
              'CentOS-8',
         | 
| 23 | 
            +
              'Debian-10',
         | 
| 24 | 
            +
              'Debian-8',
         | 
| 25 | 
            +
              'Debian-9',
         | 
| 26 | 
            +
              'OracleLinux-6',
         | 
| 27 | 
            +
              'OracleLinux-7',
         | 
| 28 | 
            +
              'Scientific-6',
         | 
| 29 | 
            +
              'Scientific-7',
         | 
| 30 | 
            +
              'Ubuntu-14.04',
         | 
| 31 | 
            +
              'Ubuntu-16.04',
         | 
| 32 | 
            +
              'Ubuntu-18.04',
         | 
| 33 | 
            +
              'Ubuntu-20.04',
         | 
| 34 | 
            +
            ].freeze
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            matrix = {
         | 
| 37 | 
            +
              platform: [],
         | 
| 38 | 
            +
              collection: %w[
         | 
| 39 | 
            +
                puppet5
         | 
| 40 | 
            +
                puppet6
         | 
| 41 | 
            +
                puppet7-nightly
         | 
| 42 | 
            +
              ],
         | 
| 43 | 
            +
            }
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            metadata = JSON.parse(File.read('metadata.json'))
         | 
| 46 | 
            +
            metadata['operatingsystem_support'].sort_by { |a| a['operatingsystem'] }.each do |sup|
         | 
| 47 | 
            +
              os = sup['operatingsystem']
         | 
| 48 | 
            +
              sup['operatingsystemrelease'].sort_by { |a| a.to_i }.each do |ver|
         | 
| 49 | 
            +
                image_key = "#{os}-#{ver}"
         | 
| 50 | 
            +
                if IMAGE_TABLE.key? image_key
         | 
| 51 | 
            +
                  matrix[:platform] << IMAGE_TABLE[image_key]
         | 
| 52 | 
            +
                elsif DOCKER_PLATFORMS.include? image_key
         | 
| 53 | 
            +
                  puts "Expecting #{image_key} test using docker on travis"
         | 
| 54 | 
            +
                else
         | 
| 55 | 
            +
                  puts "::warning::Cannot find image for #{image_key}"
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
            end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            puts "::set-output name=matrix::#{JSON.generate(matrix)}"
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            puts "Created matrix with #{matrix[:platform].length * matrix[:collection].length} cells."
         | 
| @@ -18,7 +18,7 @@ module PuppetLitmus::InventoryManipulation | |
| 18 18 | 
             
                raise "There is no inventory file at '#{inventory_full_path}'." unless File.exist?(inventory_full_path)
         | 
| 19 19 |  | 
| 20 20 | 
             
                inventory_hash = YAML.load_file(inventory_full_path)
         | 
| 21 | 
            -
                raise "Inventory file is incompatible (version 2 and up). Try the 'bolt project migrate' command." if inventory_hash | 
| 21 | 
            +
                raise "Inventory file is incompatible (version 2 and up). Try the 'bolt project migrate' command." if inventory_hash['version'].nil? || (inventory_hash['version'] < 2)
         | 
| 22 22 |  | 
| 23 23 | 
             
                inventory_hash
         | 
| 24 24 | 
             
              end
         | 
| @@ -50,12 +50,11 @@ module PuppetLitmus::InventoryManipulation | |
| 50 50 | 
             
              # @param targets [Array]
         | 
| 51 51 | 
             
              # @return [Array] array of targets.
         | 
| 52 52 | 
             
              def find_targets(inventory_hash, targets)
         | 
| 53 | 
            -
                 | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
                targets
         | 
| 53 | 
            +
                if targets.nil?
         | 
| 54 | 
            +
                  inventory_hash.to_s.scan(%r{uri"=>"(\S*)"}).flatten
         | 
| 55 | 
            +
                else
         | 
| 56 | 
            +
                  [targets]
         | 
| 57 | 
            +
                end
         | 
| 59 58 | 
             
              end
         | 
| 60 59 |  | 
| 61 60 | 
             
              # Determines if a node_name exists in a group in the inventory_hash.
         | 
| @@ -147,6 +147,42 @@ module PuppetLitmus::PuppetHelpers | |
| 147 147 | 
             
                end
         | 
| 148 148 | 
             
              end
         | 
| 149 149 |  | 
| 150 | 
            +
              # Writes a string variable to a file on a target node at a specified path.
         | 
| 151 | 
            +
              #
         | 
| 152 | 
            +
              # @param content [String] String data to write to the file.
         | 
| 153 | 
            +
              # @param destination [String] The path on the target node to write the file.
         | 
| 154 | 
            +
              # @return [Bool] Success. The file was succesfully writtne on the target.
         | 
| 155 | 
            +
              def write_file(content, destination)
         | 
| 156 | 
            +
                Honeycomb.start_span(name: 'litmus.write_file') do |span|
         | 
| 157 | 
            +
                  ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
         | 
| 158 | 
            +
                  span.add_field('litmus.destination', destination)
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                  require 'tmpdir'
         | 
| 161 | 
            +
                  target_node_name = ENV['TARGET_HOST']
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                  Tempfile.create('litmus') do |tmp_file|
         | 
| 164 | 
            +
                    tmp_file.write(content)
         | 
| 165 | 
            +
                    tmp_file.flush
         | 
| 166 | 
            +
                    if target_node_name.nil? || target_node_name == 'localhost'
         | 
| 167 | 
            +
                      require 'fileutils'
         | 
| 168 | 
            +
                      # no need to transfer
         | 
| 169 | 
            +
                      FileUtils.cp(tmp_file.path, destination)
         | 
| 170 | 
            +
                    else
         | 
| 171 | 
            +
                      # transfer to TARGET_HOST
         | 
| 172 | 
            +
                      inventory_hash = inventory_hash_from_inventory_file
         | 
| 173 | 
            +
                      span.add_field('litmus.node_name', target_node_name)
         | 
| 174 | 
            +
                      add_platform_field(inventory_hash, target_node_name)
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                      bolt_result = upload_file(tmp_file.path, destination, target_node_name, options: {}, config: nil, inventory: inventory_hash)
         | 
| 177 | 
            +
                      span.add_field('litmus.bolt_result.file_upload', bolt_result)
         | 
| 178 | 
            +
                      raise bolt_result.first['value'].to_s unless bolt_result.first['status'] == 'success'
         | 
| 179 | 
            +
                    end
         | 
| 180 | 
            +
                  end
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                  true
         | 
| 183 | 
            +
                end
         | 
| 184 | 
            +
              end
         | 
| 185 | 
            +
             | 
| 150 186 | 
             
              # Runs a command against the target system
         | 
| 151 187 | 
             
              #
         | 
| 152 188 | 
             
              # @param command_to_run [String] The command to execute.
         | 
| @@ -382,7 +418,7 @@ module PuppetLitmus::PuppetHelpers | |
| 382 418 |  | 
| 383 419 | 
             
              # Return the stdout of the puppet run
         | 
| 384 420 | 
             
              def puppet_output(bolt_result)
         | 
| 385 | 
            -
                bolt_result.dig(0, 'value', 'stderr').to_s  | 
| 421 | 
            +
                bolt_result.dig(0, 'value', 'stderr').to_s + \
         | 
| 386 422 | 
             
                  bolt_result.dig(0, 'value', 'stdout').to_s
         | 
| 387 423 | 
             
              end
         | 
| 388 424 |  | 
| @@ -48,7 +48,7 @@ end | |
| 48 48 | 
             
            module PuppetLitmus::RakeHelper
         | 
| 49 49 | 
             
              # DEFAULT_CONFIG_DATA should be frozen for our safety, but it needs to work around https://github.com/puppetlabs/bolt/pull/1696
         | 
| 50 50 | 
             
              DEFAULT_CONFIG_DATA ||= { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') } # .freeze # rubocop:disable Style/MutableConstant
         | 
| 51 | 
            -
              SUPPORTED_PROVISIONERS ||= %w[abs docker docker_exp vagrant vmpooler].freeze
         | 
| 51 | 
            +
              SUPPORTED_PROVISIONERS ||= %w[abs docker docker_exp provision_service vagrant vmpooler].freeze
         | 
| 52 52 |  | 
| 53 53 | 
             
              # Gets a string representing the operating system and version.
         | 
| 54 54 | 
             
              #
         | 
| @@ -208,9 +208,13 @@ module PuppetLitmus::RakeHelper | |
| 208 208 | 
             
              def configure_path(inventory_hash)
         | 
| 209 209 | 
             
                results = []
         | 
| 210 210 | 
             
                # fix the path on ssh_nodes
         | 
| 211 | 
            -
                unless inventory_hash['groups'].select { |group| group['name'] == 'ssh_nodes' }.size.zero?
         | 
| 212 | 
            -
                  results  | 
| 213 | 
            -
             | 
| 211 | 
            +
                unless inventory_hash['groups'].select { |group| group['name'] == 'ssh_nodes' && !group['targets'].empty? }.size.zero?
         | 
| 212 | 
            +
                  results << run_command('echo PATH="$PATH:/opt/puppetlabs/puppet/bin" > /etc/environment',
         | 
| 213 | 
            +
                                         'ssh_nodes', config: nil, inventory: inventory_hash)
         | 
| 214 | 
            +
                end
         | 
| 215 | 
            +
                unless inventory_hash['groups'].select { |group| group['name'] == 'winrm_nodes' && !group['targets'].empty? }.size.zero?
         | 
| 216 | 
            +
                  results << run_command('[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\Program Files\Puppet Labs\Puppet\bin;C:\Program Files (x86)\Puppet Labs\Puppet\bin", "Machine")',
         | 
| 217 | 
            +
                                         'winrm_nodes', config: nil, inventory: inventory_hash)
         | 
| 214 218 | 
             
                end
         | 
| 215 219 | 
             
                results
         | 
| 216 220 | 
             
              end
         | 
| @@ -227,7 +231,7 @@ module PuppetLitmus::RakeHelper | |
| 227 231 | 
             
                module_dir ||= Dir.pwd
         | 
| 228 232 | 
             
                target_dir ||= File.join(source_dir, 'pkg')
         | 
| 229 233 |  | 
| 230 | 
            -
                puts "Building '#{module_dir}' into '#{target_dir}' | 
| 234 | 
            +
                puts "Building '#{module_dir}' into '#{target_dir}'"
         | 
| 231 235 | 
             
                builder = Puppet::Modulebuilder::Builder.new(module_dir, target_dir, nil)
         | 
| 232 236 |  | 
| 233 237 | 
             
                # Force the metadata to be read. Raises if metadata could not be found
         | 
| @@ -269,8 +273,9 @@ module PuppetLitmus::RakeHelper | |
| 269 273 | 
             
              # @param target_node_name [String] the name of the target where the module should be installed
         | 
| 270 274 | 
             
              # @param module_tar [String] the filename of the module tarball to upload
         | 
| 271 275 | 
             
              # @param module_repository [String] the URL for the forge to use for downloading modules. Defaults to the public Forge API.
         | 
| 276 | 
            +
              # @param ignore_dependencies [Boolean] flag used to ignore module dependencies defaults to false.
         | 
| 272 277 | 
             
              # @return a bolt result
         | 
| 273 | 
            -
              def install_module(inventory_hash, target_node_name, module_tar, module_repository = nil)
         | 
| 278 | 
            +
              def install_module(inventory_hash, target_node_name, module_tar, module_repository = nil, ignore_dependencies = false) # rubocop:disable Style/OptionalBooleanParameter
         | 
| 274 279 | 
             
                Honeycomb.start_span(name: 'install_module') do |span|
         | 
| 275 280 | 
             
                  ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
         | 
| 276 281 | 
             
                  span.add_field('litmus.target_node_name', target_node_name)
         | 
| @@ -290,6 +295,7 @@ module PuppetLitmus::RakeHelper | |
| 290 295 |  | 
| 291 296 | 
             
                  module_repository_opts = "--module_repository '#{module_repository}'" unless module_repository.nil?
         | 
| 292 297 | 
             
                  install_module_command = "puppet module install #{module_repository_opts} #{File.basename(module_tar)}"
         | 
| 298 | 
            +
                  install_module_command += ' --ignore-dependencies --force' if ignore_dependencies.to_s.downcase == 'true'
         | 
| 293 299 | 
             
                  span.add_field('litmus.install_module_command', install_module_command)
         | 
| 294 300 |  | 
| 295 301 | 
             
                  bolt_result = run_command(install_module_command, target_nodes, config: nil, inventory: inventory_hash.clone)
         | 
| @@ -59,7 +59,7 @@ namespace :litmus do | |
| 59 59 | 
             
                  if result.first['status'] != 'success'
         | 
| 60 60 | 
             
                    failed_image_message += "=====\n#{result.first['target']}\n#{result.first['value']['_output']}\n#{result.inspect}"
         | 
| 61 61 | 
             
                  else
         | 
| 62 | 
            -
                     | 
| 62 | 
            +
                    $stdout.puts "#{result.first['value']['node_name']}, #{image}"
         | 
| 63 63 | 
             
                  end
         | 
| 64 64 | 
             
                  results << result
         | 
| 65 65 | 
             
                end
         | 
| @@ -122,21 +122,34 @@ namespace :litmus do | |
| 122 122 | 
             
                    command_to_run = "bolt task run puppet_agent::install --targets #{result['target']} --inventoryfile inventory.yaml --modulepath #{DEFAULT_CONFIG_DATA['modulepath']}"
         | 
| 123 123 | 
             
                    raise "Failed on #{result['target']}\n#{result}\ntry running '#{command_to_run}'"
         | 
| 124 124 | 
             
                  else
         | 
| 125 | 
            +
                    # validate successful install
         | 
| 126 | 
            +
                    puts "Successfull install result: #{result.inspect}" if ENV['DEBUG'] == true
         | 
| 127 | 
            +
                    retries = 0
         | 
| 128 | 
            +
                    begin
         | 
| 129 | 
            +
                      responses = run_command('puppet --version', targets, options: {}, config: DEFAULT_CONFIG_DATA, inventory: inventory_hash.clone)
         | 
| 130 | 
            +
                      responses.each do |response|
         | 
| 131 | 
            +
                        raise "Error checking puppet version on #{response.to_json}" if response['status'] != 'success'
         | 
| 132 | 
            +
                      end
         | 
| 133 | 
            +
                    rescue StandardError => e
         | 
| 134 | 
            +
                      puts "ERROR:#{e}"
         | 
| 135 | 
            +
                      # fix the path
         | 
| 136 | 
            +
                      path_changes = configure_path(inventory_hash)
         | 
| 137 | 
            +
                      path_changes.each do |change|
         | 
| 138 | 
            +
                        puts "Configuring puppet path result: #{change.inspect}"
         | 
| 139 | 
            +
                      end
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                      retries += 1
         | 
| 142 | 
            +
                      sleep 3
         | 
| 143 | 
            +
                      retry if retries <= 300
         | 
| 144 | 
            +
                      raise 'Failed to detect installed puppet version after 5 minutes'
         | 
| 145 | 
            +
                    end
         | 
| 146 | 
            +
             | 
| 125 147 | 
             
                    # add puppet-agent feature to successful nodes
         | 
| 126 148 | 
             
                    inventory_hash = add_feature_to_node(inventory_hash, 'puppet-agent', result['target'])
         | 
| 127 149 | 
             
                  end
         | 
| 128 150 | 
             
                end
         | 
| 129 151 | 
             
                # update the inventory with the puppet-agent feature set per node
         | 
| 130 152 | 
             
                write_to_inventory_file(inventory_hash, 'inventory.yaml')
         | 
| 131 | 
            -
             | 
| 132 | 
            -
                # fix the path on ssh_nodes
         | 
| 133 | 
            -
                results = configure_path(inventory_hash)
         | 
| 134 | 
            -
             | 
| 135 | 
            -
                results.each do |result|
         | 
| 136 | 
            -
                  if result['status'] != 'success'
         | 
| 137 | 
            -
                    puts "Failed on #{result['target']}\n#{result}"
         | 
| 138 | 
            -
                  end
         | 
| 139 | 
            -
                end
         | 
| 140 153 | 
             
              end
         | 
| 141 154 |  | 
| 142 155 | 
             
              # Add a given feature to a selection of nodes
         | 
| @@ -195,8 +208,8 @@ namespace :litmus do | |
| 195 208 | 
             
              # @param :source [String] source directory to look in (ignores symlinks) defaults do './spec/fixtures/modules'.
         | 
| 196 209 | 
             
              # @param :target_node_name [Array] nodes on which to install a puppet module for testing.
         | 
| 197 210 | 
             
              desc 'build and install all modules from a directory'
         | 
| 198 | 
            -
              task :install_modules_from_directory, [:source, :target_node_name, :module_repository] do |_task, args|
         | 
| 199 | 
            -
                args.with_defaults(source: nil, target_node_name: nil, module_repository: nil)
         | 
| 211 | 
            +
              task :install_modules_from_directory, [:source, :target_node_name, :module_repository, :ignore_dependencies] do |_task, args|
         | 
| 212 | 
            +
                args.with_defaults(source: nil, target_node_name: nil, module_repository: nil, ignore_dependencies: false)
         | 
| 200 213 | 
             
                inventory_hash = inventory_hash_from_inventory_file
         | 
| 201 214 | 
             
                target_nodes = find_targets(inventory_hash, args[:target_node_name])
         | 
| 202 215 | 
             
                if target_nodes.empty?
         | 
| @@ -217,7 +230,7 @@ namespace :litmus do | |
| 217 230 | 
             
                module_tars.each do |module_tar|
         | 
| 218 231 | 
             
                  puts "Installing '#{module_tar}'"
         | 
| 219 232 | 
             
                  target_nodes.each do |target_node_name|
         | 
| 220 | 
            -
                    install_module(inventory_hash, target_node_name, module_tar, args[:module_repository])
         | 
| 233 | 
            +
                    install_module(inventory_hash, target_node_name, module_tar, args[:module_repository], args[:ignore_dependencies])
         | 
| 221 234 | 
             
                    puts "Installed '#{module_tar}' on #{target_node_name}"
         | 
| 222 235 | 
             
                  end
         | 
| 223 236 | 
             
                end
         | 
| @@ -321,15 +334,21 @@ namespace :litmus do | |
| 321 334 |  | 
| 322 335 | 
             
                  # Run acceptance tests against all machines in the inventory file in parallel.
         | 
| 323 336 | 
             
                  desc 'Run tests in parallel against all machines in the inventory file'
         | 
| 324 | 
            -
                  task :parallel do
         | 
| 337 | 
            +
                  task :parallel, [:tag] do |_task, args|
         | 
| 338 | 
            +
                    args.with_defaults(tag: nil)
         | 
| 325 339 | 
             
                    if targets.empty?
         | 
| 326 340 | 
             
                      puts 'No targets found'
         | 
| 327 341 | 
             
                      exit 0
         | 
| 328 342 | 
             
                    end
         | 
| 343 | 
            +
                    tag_value = if args[:tag].nil?
         | 
| 344 | 
            +
                                  nil
         | 
| 345 | 
            +
                                else
         | 
| 346 | 
            +
                                  "--tag #{args[:tag]}"
         | 
| 347 | 
            +
                                end
         | 
| 329 348 | 
             
                    payloads = []
         | 
| 330 349 | 
             
                    # Generate list of targets to provision
         | 
| 331 350 | 
             
                    targets.each do |target|
         | 
| 332 | 
            -
                      test =  | 
| 351 | 
            +
                      test = "bundle exec rspec ./spec/acceptance #{tag_value} --format progress --require rspec_honeycomb_formatter --format RSpecHoneycombFormatter"
         | 
| 333 352 | 
             
                      title = "#{target}, #{facts_from_node(inventory_hash, target)['platform']}"
         | 
| 334 353 | 
             
                      options = {
         | 
| 335 354 | 
             
                        env: {
         | 
| @@ -367,9 +386,9 @@ namespace :litmus do | |
| 367 386 | 
             
                      # because we cannot modify variables inside of Parallel
         | 
| 368 387 | 
             
                      results.each do |result|
         | 
| 369 388 | 
             
                        if result.last.to_i.zero?
         | 
| 370 | 
            -
                          success_list.push(result.first.scan(%r{.*})[ | 
| 389 | 
            +
                          success_list.push(result.first.scan(%r{.*})[3])
         | 
| 371 390 | 
             
                        else
         | 
| 372 | 
            -
                          failure_list.push(result.first.scan(%r{.*})[ | 
| 391 | 
            +
                          failure_list.push(result.first.scan(%r{.*})[3])
         | 
| 373 392 | 
             
                        end
         | 
| 374 393 | 
             
                      end
         | 
| 375 394 | 
             
                      Thread.kill(progress)
         | 
| @@ -411,8 +430,9 @@ namespace :litmus do | |
| 411 430 | 
             
                    desc "Run serverspec against #{target}"
         | 
| 412 431 | 
             
                    next if target == 'litmus_localhost'
         | 
| 413 432 |  | 
| 414 | 
            -
                    RSpec::Core::RakeTask.new(target.to_sym) do |t|
         | 
| 433 | 
            +
                    RSpec::Core::RakeTask.new(target.to_sym, :tag) do |t, args|
         | 
| 415 434 | 
             
                      t.pattern = 'spec/acceptance/**{,/*/**}/*_spec.rb'
         | 
| 435 | 
            +
                      t.rspec_opts = "--tag #{args[:tag]}" unless args[:tag].nil?
         | 
| 416 436 | 
             
                      ENV['TARGET_HOST'] = target
         | 
| 417 437 | 
             
                    end
         | 
| 418 438 | 
             
                  end
         | 
| @@ -421,8 +441,9 @@ namespace :litmus do | |
| 421 441 | 
             
                # add localhost separately
         | 
| 422 442 | 
             
                desc 'Run serverspec against localhost, USE WITH CAUTION, this action can be potentially dangerous.'
         | 
| 423 443 | 
             
                host = 'localhost'
         | 
| 424 | 
            -
                RSpec::Core::RakeTask.new(host.to_sym) do |t|
         | 
| 444 | 
            +
                RSpec::Core::RakeTask.new(host.to_sym, :tag) do |t, args|
         | 
| 425 445 | 
             
                  t.pattern = 'spec/acceptance/**{,/*/**}/*_spec.rb'
         | 
| 446 | 
            +
                  t.rspec_opts = "--tag #{args[:tag]}" unless args[:tag].nil?
         | 
| 426 447 | 
             
                  Rake::Task['spec_prep'].invoke
         | 
| 427 448 | 
             
                  ENV['TARGET_HOST'] = host
         | 
| 428 449 | 
             
                end
         | 
| @@ -35,6 +35,7 @@ module PuppetLitmus | |
| 35 35 | 
             
                    options[:port] = node_config.dig('ssh', 'port') unless node_config.dig('ssh', 'port').nil?
         | 
| 36 36 | 
             
                    options[:keys] = node_config.dig('ssh', 'private-key') unless node_config.dig('ssh', 'private-key').nil?
         | 
| 37 37 | 
             
                    options[:password] = node_config.dig('ssh', 'password') unless node_config.dig('ssh', 'password').nil?
         | 
| 38 | 
            +
                    run_as = node_config.dig('ssh', 'run-as') unless node_config.dig('ssh', 'run-as').nil?
         | 
| 38 39 | 
             
                    # Support both net-ssh 4 and 5.
         | 
| 39 40 | 
             
                    # rubocop:disable Metrics/BlockNesting
         | 
| 40 41 | 
             
                    options[:verify_host_key] = if node_config.dig('ssh', 'host-key-check').nil?
         | 
| @@ -67,6 +68,8 @@ module PuppetLitmus | |
| 67 68 | 
             
                    set :host,        options[:host_name] || host
         | 
| 68 69 | 
             
                    set :ssh_options, options
         | 
| 69 70 | 
             
                    set :request_pty, false
         | 
| 71 | 
            +
                    set :sudo_password, options[:password] if run_as
         | 
| 72 | 
            +
                    puts "Running tests as #{run_as}" if run_as
         | 
| 70 73 | 
             
                  elsif target_in_group(inventory_hash, ENV['TARGET_HOST'], 'winrm_nodes')
         | 
| 71 74 | 
             
                    require 'winrm'
         | 
| 72 75 |  | 
| @@ -113,10 +113,10 @@ RSpec.describe PuppetLitmus::PuppetHelpers do | |
| 113 113 | 
             
                let(:local) { '/tmp' }
         | 
| 114 114 | 
             
                let(:remote) { '/remote_tmp' }
         | 
| 115 115 | 
             
                # Ignore rubocop because these hashes are representative of output from an external method and editing them leads to test failures.
         | 
| 116 | 
            -
                # rubocop:disable Layout/ | 
| 117 | 
            -
                let(:result_success) {[{'target'=>'some.host','action'=>'upload','object'=>'C:\foo\bar.ps1','status'=>'success','value'=>{'_output'=>'Uploaded \'C:\foo\bar.ps1\' to \'some.host:C:\bar\''}}]}
         | 
| 118 | 
            -
                let(:result_failure) {[{'target'=>'some.host','action'=>nil,'object'=>nil,'status'=>'failure','value'=>{'_error'=>{'kind'=>'puppetlabs.tasks/task_file_error','msg'=>'No such file or directory @ rb_sysopen - /nonexistant/file/path','details'=>{},'issue_code'=>'WRITE_ERROR'}}}]}
         | 
| 119 | 
            -
                # rubocop:enable | 
| 116 | 
            +
                # rubocop:disable Layout/SpaceAroundOperators, Layout/LineLength, Layout/SpaceAfterComma
         | 
| 117 | 
            +
                let(:result_success) { [{ 'target'=>'some.host','action'=>'upload','object'=>'C:\foo\bar.ps1','status'=>'success','value'=>{ '_output'=>'Uploaded \'C:\foo\bar.ps1\' to \'some.host:C:\bar\'' } }] }
         | 
| 118 | 
            +
                let(:result_failure) { [{ 'target'=>'some.host','action'=>nil,'object'=>nil,'status'=>'failure','value'=>{ '_error'=>{ 'kind'=>'puppetlabs.tasks/task_file_error','msg'=>'No such file or directory @ rb_sysopen - /nonexistant/file/path','details'=>{},'issue_code'=>'WRITE_ERROR' } } }] }
         | 
| 119 | 
            +
                # rubocop:enable, Layout/SpaceAroundOperators, Layout/LineLength, Layout/SpaceAfterComma
         | 
| 120 120 |  | 
| 121 121 | 
             
                it 'responds to run_shell' do
         | 
| 122 122 | 
             
                  expect(self).to respond_to(:bolt_upload_file).with(2..3).arguments
         | 
| @@ -212,11 +212,11 @@ RSpec.describe PuppetLitmus::PuppetHelpers do | |
| 212 212 | 
             
                let(:params) { { 'action' => 'install', 'name' => 'foo' } }
         | 
| 213 213 | 
             
                let(:config_data) { { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') } }
         | 
| 214 214 | 
             
                # Ignore rubocop because these hashes are representative of output from an external method and editing them leads to test failures.
         | 
| 215 | 
            -
                # rubocop:disable Layout/ | 
| 216 | 
            -
                let(:result_unstructured_task_success){ [{'target'=>'some.host','action'=>'task','object'=>'testtask::unstructured','status'=>'success','value'=>{'_output'=>'SUCCESS!'}}]}
         | 
| 217 | 
            -
                let(:result_structured_task_success){ [{'target'=>'some.host','action'=>'task','object'=>'testtask::structured','status'=>'success','value'=>{'key1'=>'foo','key2'=>'bar'}}]}
         | 
| 218 | 
            -
                let(:result_failure) {[{'target'=>'some.host','action'=>'task','object'=>'testtask::unstructured','status'=>'failure','value'=>{'_error'=>{'msg'=>'FAILURE!','kind'=>'puppetlabs.tasks/task-error','details'=>{'exitcode'=>123}}}}]}
         | 
| 219 | 
            -
                # rubocop:enable Layout/ | 
| 215 | 
            +
                # rubocop:disable Layout/SpaceBeforeBlockBraces
         | 
| 216 | 
            +
                let(:result_unstructured_task_success){ [{ 'target'=>'some.host','action'=>'task','object'=>'testtask::unstructured','status'=>'success','value'=>{ '_output'=>'SUCCESS!' } }] }
         | 
| 217 | 
            +
                let(:result_structured_task_success){ [{ 'target'=>'some.host','action'=>'task','object'=>'testtask::structured','status'=>'success','value'=>{ 'key1'=>'foo','key2'=>'bar' } }] }
         | 
| 218 | 
            +
                let(:result_failure) { [{ 'target'=>'some.host','action'=>'task','object'=>'testtask::unstructured','status'=>'failure','value'=>{ '_error'=>{ 'msg'=>'FAILURE!','kind'=>'puppetlabs.tasks/task-error','details'=>{ 'exitcode'=>123 } } } }] }
         | 
| 219 | 
            +
                # rubocop:enable Layout/SpaceBeforeBlockBraces, Layout/SpaceAroundOperators, Layout/LineLength, Layout/SpaceAfterComma
         | 
| 220 220 |  | 
| 221 221 | 
             
                it 'responds to bolt_run_task' do
         | 
| 222 222 | 
             
                  expect(self).to respond_to(:run_bolt_task).with(2..3).arguments
         | 
| @@ -286,4 +286,42 @@ RSpec.describe PuppetLitmus::PuppetHelpers do | |
| 286 286 | 
             
                  end
         | 
| 287 287 | 
             
                end
         | 
| 288 288 | 
             
              end
         | 
| 289 | 
            +
             | 
| 290 | 
            +
              describe '.write_file' do
         | 
| 291 | 
            +
                let(:content) { 'foo' }
         | 
| 292 | 
            +
                let(:destination) { '/tmp/foo' }
         | 
| 293 | 
            +
                let(:owner) { 'foo:foo' }
         | 
| 294 | 
            +
                let(:local_path) { '/tmp/local_foo' }
         | 
| 295 | 
            +
             | 
| 296 | 
            +
                before(:each) do
         | 
| 297 | 
            +
                  allow_any_instance_of(File).to receive(:path).and_return(local_path)
         | 
| 298 | 
            +
                end
         | 
| 299 | 
            +
             | 
| 300 | 
            +
                it 'responds to write_file' do
         | 
| 301 | 
            +
                  expect(self).to respond_to(:write_file).with(2).arguments
         | 
| 302 | 
            +
                end
         | 
| 303 | 
            +
             | 
| 304 | 
            +
                context 'without setting owner' do
         | 
| 305 | 
            +
                  it 'call upload file with the correct params' do
         | 
| 306 | 
            +
                    stub_const('ENV', ENV.to_hash.merge('TARGET_HOST' => 'some.host'))
         | 
| 307 | 
            +
                    expect(self).to receive(:inventory_hash_from_inventory_file).and_return(inventory_hash)
         | 
| 308 | 
            +
                    result = instance_double('result')
         | 
| 309 | 
            +
                    allow(result).to receive(:first).and_return({ 'status' => 'success' })
         | 
| 310 | 
            +
                    expect(self).to receive(:upload_file).with(local_path, destination, 'some.host', options: {}, config: nil, inventory: inventory_hash).and_return(result)
         | 
| 311 | 
            +
                    result = write_file(content, destination)
         | 
| 312 | 
            +
                    expect(result).to be true
         | 
| 313 | 
            +
                  end
         | 
| 314 | 
            +
                end
         | 
| 315 | 
            +
             | 
| 316 | 
            +
                context 'when upload encounters an error' do
         | 
| 317 | 
            +
                  it 'call upload file with the correct params' do
         | 
| 318 | 
            +
                    stub_const('ENV', ENV.to_hash.merge('TARGET_HOST' => 'some.host'))
         | 
| 319 | 
            +
                    expect(self).to receive(:inventory_hash_from_inventory_file).and_return(inventory_hash)
         | 
| 320 | 
            +
                    result = instance_double('result')
         | 
| 321 | 
            +
                    allow(result).to receive(:first).and_return({ 'status' => 'failure', 'value' => 'foo error' })
         | 
| 322 | 
            +
                    expect(self).to receive(:upload_file).with(local_path, destination, 'some.host', options: {}, config: nil, inventory: inventory_hash).and_return(result)
         | 
| 323 | 
            +
                    expect { write_file(content, destination) }.to raise_error 'foo error'
         | 
| 324 | 
            +
                  end
         | 
| 325 | 
            +
                end
         | 
| 326 | 
            +
              end
         | 
| 289 327 | 
             
            end
         | 
| @@ -19,9 +19,9 @@ describe 'litmus rake tasks' do | |
| 19 19 | 
             
                               'template-ref' => 'heads/master-0-g7827fc2' }
         | 
| 20 20 | 
             
                  expect(File).to receive(:read).with(any_args).once
         | 
| 21 21 | 
             
                  expect(JSON).to receive(:parse).with(any_args).and_return(metadata)
         | 
| 22 | 
            -
                  expect( | 
| 23 | 
            -
                  expect( | 
| 24 | 
            -
                  expect( | 
| 22 | 
            +
                  expect($stdout).to receive(:puts).with('redhat-5-x86_64')
         | 
| 23 | 
            +
                  expect($stdout).to receive(:puts).with('ubuntu-1404-x86_64')
         | 
| 24 | 
            +
                  expect($stdout).to receive(:puts).with('ubuntu-1804-x86_64')
         | 
| 25 25 | 
             
                  Rake::Task['litmus:metadata'].invoke
         | 
| 26 26 | 
             
                end
         | 
| 27 27 | 
             
              end
         | 
| @@ -39,11 +39,11 @@ describe 'litmus rake tasks' do | |
| 39 39 | 
             
                  expect_any_instance_of(PuppetLitmus::InventoryManipulation).to receive(:inventory_hash_from_inventory_file).and_return(inventory_hash)
         | 
| 40 40 | 
             
                  expect(File).to receive(:directory?).with(target_dir).and_return(true)
         | 
| 41 41 | 
             
                  expect_any_instance_of(Object).to receive(:build_modules_in_dir).with(target_dir).and_return([dummy_tar])
         | 
| 42 | 
            -
                  expect( | 
| 42 | 
            +
                  expect($stdout).to receive(:puts).with(start_with('Building all modules in'))
         | 
| 43 43 | 
             
                  expect_any_instance_of(Object).to receive(:upload_file).once.and_return([])
         | 
| 44 | 
            -
                  expect( | 
| 44 | 
            +
                  expect($stdout).to receive(:puts).with(start_with('Installing \'spec/data/doot.tar.gz\''))
         | 
| 45 45 | 
             
                  expect_any_instance_of(Object).to receive(:run_command).twice.and_return([])
         | 
| 46 | 
            -
                  expect( | 
| 46 | 
            +
                  expect($stdout).to receive(:puts).with(start_with('Installed \'spec/data/doot.tar.gz\''))
         | 
| 47 47 | 
             
                  Rake::Task['litmus:install_modules_from_directory'].invoke('./spec/fixtures/modules')
         | 
| 48 48 | 
             
                end
         | 
| 49 49 | 
             
              end
         | 
| @@ -68,7 +68,7 @@ describe 'litmus rake tasks' do | |
| 68 68 |  | 
| 69 69 | 
             
                  allow(File).to receive(:directory?).with(any_args).and_return(true)
         | 
| 70 70 | 
             
                  allow_any_instance_of(BoltSpec::Run).to receive(:run_task).with(any_args).and_return(results)
         | 
| 71 | 
            -
                  expect( | 
| 71 | 
            +
                  expect($stdout).to receive(:puts).with('localhost:2222, centos:7')
         | 
| 72 72 | 
             
                  Rake::Task['litmus:provision'].invoke('docker', 'centos:7')
         | 
| 73 73 | 
             
                end
         | 
| 74 74 | 
             
              end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: puppet_litmus
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.19.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Puppet, Inc.
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 | 
            -
            bindir:  | 
| 9 | 
            +
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2020- | 
| 11 | 
            +
            date: 2020-11-23 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bolt
         | 
| @@ -79,7 +79,7 @@ dependencies: | |
| 79 79 | 
             
                    version: '1.34'
         | 
| 80 80 | 
             
                - - "<"
         | 
| 81 81 | 
             
                  - !ruby/object:Gem::Version
         | 
| 82 | 
            -
                    version:  | 
| 82 | 
            +
                    version: 3.0.0
         | 
| 83 83 | 
             
              type: :runtime
         | 
| 84 84 | 
             
              prerelease: false
         | 
| 85 85 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| @@ -89,7 +89,7 @@ dependencies: | |
| 89 89 | 
             
                    version: '1.34'
         | 
| 90 90 | 
             
                - - "<"
         | 
| 91 91 | 
             
                  - !ruby/object:Gem::Version
         | 
| 92 | 
            -
                    version:  | 
| 92 | 
            +
                    version: 3.0.0
         | 
| 93 93 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 94 94 | 
             
              name: parallel
         | 
| 95 95 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -150,12 +150,14 @@ description: "    Providing a simple command line tool for puppet content creato | |
| 150 150 | 
             
              to enable simple and complex test deployments.\n"
         | 
| 151 151 | 
             
            email:
         | 
| 152 152 | 
             
            - info@puppet.com
         | 
| 153 | 
            -
            executables: | 
| 153 | 
            +
            executables:
         | 
| 154 | 
            +
            - matrix_from_metadata
         | 
| 154 155 | 
             
            extensions: []
         | 
| 155 156 | 
             
            extra_rdoc_files: []
         | 
| 156 157 | 
             
            files:
         | 
| 157 158 | 
             
            - LICENSE
         | 
| 158 159 | 
             
            - README.md
         | 
| 160 | 
            +
            - exe/matrix_from_metadata
         | 
| 159 161 | 
             
            - lib/puppet_litmus.rb
         | 
| 160 162 | 
             
            - lib/puppet_litmus/inventory_manipulation.rb
         | 
| 161 163 | 
             
            - lib/puppet_litmus/puppet_helpers.rb
         | 
| @@ -193,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 193 195 | 
             
                - !ruby/object:Gem::Version
         | 
| 194 196 | 
             
                  version: '0'
         | 
| 195 197 | 
             
            requirements: []
         | 
| 196 | 
            -
            rubygems_version: 3.1. | 
| 198 | 
            +
            rubygems_version: 3.1.4
         | 
| 197 199 | 
             
            signing_key:
         | 
| 198 200 | 
             
            specification_version: 4
         | 
| 199 201 | 
             
            summary: Providing a simple command line tool for puppet content creators, to enable
         |