puppet_litmus 0.5.0 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 33763c6946158b131037d7d28f96b7db4ae5b924
4
- data.tar.gz: f85aa0cd77c310d4e798f8676189839bb4276d2b
2
+ SHA256:
3
+ metadata.gz: 9a8186fb041ca1c958fb32f75389eceb29cbe6c107c0510b725fdc2bba18b900
4
+ data.tar.gz: 7ffe43266b6c14f59f1c306f86c018f44b312d9ee02e9253e3b3cbd38932f26e
5
5
  SHA512:
6
- metadata.gz: 345cfa379161bccf03db5945499114e6d322161891b66d85aac934e7cd8de8834cc73c465d65a19c482cf8320d22c1ae89b1afb8bcc9794dab2faf3a7460aeec
7
- data.tar.gz: bc6916ad37c08f73ab2594c9537e14212257583e37437c396ea1f716219edfdda2a9be430c9d55bc8b7b1f777ec27beac7c76f1a97fb6d676f72bb36327a3ccf
6
+ metadata.gz: 12e95c5b22a998f54833adf7edd459ace61a85cceabc1463c5d572110aa2241c7642c96ab943ff6c9a6b8e5be4e42ff925fbaa19a6b4752f14ca5b9b0f050cda
7
+ data.tar.gz: 0b7570f08589b2603390f89920cf689a4e4f5491ed279e0dc7498aa3b182b9aa586c96a81be13cb16297d5ab7f6e92ec7eb82e0c31a1eebb4c88552471a2ce74
@@ -109,4 +109,51 @@ module PuppetLitmus::InventoryManipulation
109
109
  end
110
110
  inventory_hash
111
111
  end
112
+
113
+ # Adds a feature to the group specified/
114
+ #
115
+ # @param inventory_hash [Hash] hash of the inventory.yaml file
116
+ # @param feature_name [String] feature to locate in the group
117
+ # group_name [String] group of nodes to limit the search for the group_name in
118
+ # @return inventory.yaml file with feature added to group.
119
+ # @return [Hash] inventory_hash with feature added to group if group_name exists in inventory hash.
120
+ def add_feature_to_group(inventory_hash, feature_name, group_name)
121
+ i = 0
122
+ inventory_hash['groups'].each do |group|
123
+ if group['name'] == group_name
124
+ if group['features'].nil? == true
125
+ group = group.merge('features' => [])
126
+ end
127
+ group['features'].push feature_name
128
+ inventory_hash['groups'][i] = group
129
+ end
130
+ i += 1
131
+ end
132
+ inventory_hash
133
+ end
134
+
135
+ # Removes a feature from the group specified/
136
+ #
137
+ # @param inventory_hash [Hash] hash of the inventory.yaml file
138
+ # @param feature_name [String] feature to locate in the group
139
+ # group_name [String] group of nodes to limit the search for the group_name in
140
+ # @return inventory.yaml file with feature removed from the group.
141
+ # @return [Hash] inventory_hash with feature added to group if group_name exists in inventory hash.
142
+ def remove_feature_from_group(inventory_hash, feature_name, group_name)
143
+ inventory_hash['groups'].each do |group|
144
+ if group['name'] == group_name && group['features'].nil? != true
145
+ group['features'].delete(feature_name)
146
+ end
147
+ end
148
+ inventory_hash
149
+ end
150
+
151
+ # Write inventory_hash to inventory_yaml file/
152
+ #
153
+ # @param inventory_full_path [String] path to the inventory.yaml file
154
+ # @param inventory_hash [Hash] hash of the inventory.yaml file
155
+ # @return inventory.yaml file with feature added to group.
156
+ def write_to_inventory_file(inventory_hash, inventory_full_path)
157
+ File.open(inventory_full_path, 'w+') { |f| f.write(inventory_hash.to_yaml) }
158
+ end
112
159
  end
@@ -107,6 +107,8 @@ namespace :litmus do
107
107
  task :provision_list, [:key] do |_task, args|
108
108
  provision_hash = YAML.load_file('./provision.yaml')
109
109
  provisioner = provision_hash[args[:key]]['provisioner']
110
+ # Splat the params into environment variables to pass to the provision task but only in this runspace
111
+ provision_hash[args[:key]]['params']&.each { |key, value| ENV["LITMUS_#{key.upcase}"] = value }
110
112
  failed_image_message = ''
111
113
  provision_hash[args[:key]]['images'].each do |image|
112
114
  # this is the only way to capture the stdout from the rake task, it will affect pry
@@ -358,22 +360,30 @@ namespace :litmus do
358
360
  end
359
361
  spinners = TTY::Spinner::Multi.new("Running against #{targets.size} targets.[:spinner]", frames: ['.'], interval: 0.1)
360
362
  payloads = []
363
+ # Generate list of targets to provision
361
364
  targets.each do |target|
362
- test = "TARGET_HOST=#{target} bundle exec rspec ./spec/acceptance --format progress"
365
+ test = 'bundle exec bundle exec rspec ./spec/acceptance --format progress'
363
366
  title = "#{target}, #{facts_from_node(inventory_hash, target)['platform']}"
364
- payloads << [title, test]
367
+ options = {
368
+ env: {
369
+ 'TARGET_HOST' => target,
370
+ },
371
+ }
372
+ payloads << [title, test, options]
365
373
  end
366
374
 
367
375
  results = []
368
376
  success_list = []
369
377
  failure_list = []
378
+ # Provision targets depending on what environment we're in
370
379
  if (ENV['CI'] == 'true') || !ENV['DISTELLI_BUILDNUM'].nil?
371
380
  # CI systems are strange beasts, we only output a '.' every wee while to keep the terminal alive.
372
381
  puts "Running against #{targets.size} targets.\n"
373
382
  spinner = TTY::Spinner.new(':spinner', frames: ['.'], interval: 0.1)
374
383
  spinner.auto_spin
375
- results = Parallel.map(payloads) do |title, test|
376
- stdout, stderr, status = Open3.capture3(test)
384
+ results = Parallel.map(payloads) do |title, test, options|
385
+ env = options[:env].nil? ? {} : options[:env]
386
+ stdout, stderr, status = Open3.capture3(env, test)
377
387
  ["================\n#{title}\n", stdout, stderr, status]
378
388
  end
379
389
  # because we cannot modify variables inside of Parallel
@@ -387,9 +397,10 @@ namespace :litmus do
387
397
  spinner.success
388
398
  else
389
399
  spinners = TTY::Spinner::Multi.new("[:spinner] Running against #{targets.size} targets.")
390
- payloads.each do |title, test|
400
+ payloads.each do |title, test, options|
401
+ env = options[:env].nil? ? {} : options[:env]
391
402
  spinners.register("[:spinner] #{title}") do |sp|
392
- stdout, stderr, status = Open3.capture3(test)
403
+ stdout, stderr, status = Open3.capture3(env, test)
393
404
  if status.to_i.zero?
394
405
  sp.success
395
406
  success_list.push(title)
@@ -102,6 +102,37 @@ module PuppetLitmus::Serverspec
102
102
  result
103
103
  end
104
104
 
105
+ # Copies file to the target, using its respective transport
106
+ #
107
+ # @param source [String] place locally, to copy from.
108
+ # @param destination [String] place on the target, to copy to.
109
+ # @param opts [Hash] Alters the behaviour of the command. Valid options are :expect_failures [Boolean] doesnt return an exit code of non-zero if the command failed.
110
+ # @yieldreturn [Block] this method will yield to a block of code passed by the caller; this can be used for additional validation, etc.
111
+ # @return [Object] A result object from the command.
112
+ def bolt_upload_file(source, destination, options = {})
113
+ target_node_name = ENV['TARGET_HOST'] if target_node_name.nil?
114
+ inventory_hash = if target_node_name.nil? || target_node_name == 'localhost'
115
+ nil
116
+ else
117
+ inventory_hash_from_inventory_file
118
+ end
119
+
120
+ result = upload_file(source, destination, target_node_name, options: options, config: nil, inventory: inventory_hash)
121
+
122
+ raise "upload file failed\n======\n#{result}" if result.first['status'] != 'success'
123
+
124
+ exit_code = if result.first['status'] == 'success'
125
+ 0
126
+ else
127
+ 255
128
+ end
129
+ result = OpenStruct.new(exit_code: exit_code,
130
+ stdout: result.first['result']['status'],
131
+ stderr: result.first['result']['status'])
132
+ yield result if block_given?
133
+ result
134
+ end
135
+
105
136
  # Runs a task against the target system.
106
137
  #
107
138
  # @param task_name [String] The name of the task to run.
@@ -2,5 +2,5 @@
2
2
 
3
3
  # version of this gem
4
4
  module PuppetLitmus
5
- VERSION ||= '0.5.0'
5
+ VERSION ||= '0.6.0'
6
6
  end
@@ -0,0 +1,16 @@
1
+ ---
2
+ groups:
3
+ - name: ssh_nodes
4
+ nodes:
5
+ - name: test.delivery.puppetlabs.net
6
+ config:
7
+ transport: ssh
8
+ ssh:
9
+ user: root
10
+ password: Qu@lity!
11
+ host-key-check: false
12
+ facts:
13
+ provisioner: vmpooler
14
+ platform: centos-5-x86_64
15
+ - name: winrm_nodes
16
+ nodes: []
@@ -31,6 +31,40 @@ RSpec.describe PuppetLitmus::InventoryManipulation do
31
31
  { 'name' => 'winrm_nodes', 'nodes' => [] }] }
32
32
  end
33
33
 
34
+ let(:inventory_full_path) { 'spec/data/inventory.yaml' }
35
+
36
+ let(:no_feature_hash) do
37
+ { 'groups' =>
38
+ [{ 'name' => 'ssh_nodes',
39
+ 'nodes' =>
40
+ [{ 'name' => 'test.delivery.puppetlabs.net',
41
+ 'config' => { 'transport' => 'ssh', 'ssh' => { 'user' => 'root', 'password' => 'Qu@lity!', 'host-key-check' => false } },
42
+ 'facts' => { 'provisioner' => 'vmpooler', 'platform' => 'centos-5-x86_64' } }] },
43
+ { 'name' => 'winrm_nodes', 'nodes' => [] }] }
44
+ end
45
+
46
+ let(:feature_hash) do
47
+ { 'groups' =>
48
+ [{ 'name' => 'ssh_nodes',
49
+ 'nodes' =>
50
+ [{ 'name' => 'test.delivery.puppetlabs.net',
51
+ 'config' => { 'transport' => 'ssh', 'ssh' => { 'user' => 'root', 'password' => 'Qu@lity!', 'host-key-check' => false } },
52
+ 'facts' => { 'provisioner' => 'vmpooler', 'platform' => 'centos-5-x86_64' } }],
53
+ 'features' => ['puppet-agent'] },
54
+ { 'name' => 'winrm_nodes', 'nodes' => [] }] }
55
+ end
56
+
57
+ let(:empty_feature_hash) do
58
+ { 'groups' =>
59
+ [{ 'name' => 'ssh_nodes',
60
+ 'nodes' =>
61
+ [{ 'name' => 'test.delivery.puppetlabs.net',
62
+ 'config' => { 'transport' => 'ssh', 'ssh' => { 'user' => 'root', 'password' => 'Qu@lity!', 'host-key-check' => false } },
63
+ 'facts' => { 'provisioner' => 'vmpooler', 'platform' => 'centos-5-x86_64' } }],
64
+ 'features' => [] },
65
+ { 'name' => 'winrm_nodes', 'nodes' => [] }] }
66
+ end
67
+
34
68
  it 'no matching node, raises' do
35
69
  expect { dummy_class.config_from_node(config_hash, 'not.here') }.to raise_error('No config was found for not.here')
36
70
  end
@@ -43,5 +77,26 @@ RSpec.describe PuppetLitmus::InventoryManipulation do
43
77
  expect(dummy_class.config_from_node(config_hash, 'test.delivery.puppetlabs.net')).to eq('transport' => 'ssh', 'ssh' =>
44
78
  { 'user' => 'root', 'password' => 'Qu@lity!', 'host-key-check' => false })
45
79
  end
80
+
81
+ it 'no feature exists, and returns hash with feature added' do
82
+ expect(dummy_class.add_feature_to_group(no_feature_hash, 'puppet-agent', 'ssh_nodes')).to eq('groups' => [{ 'features' => ['puppet-agent'], 'name' => 'ssh_nodes', 'nodes' => [{ 'config' => { 'ssh' => { 'host-key-check' => false, 'password' => 'Qu@lity!', 'user' => 'root' }, 'transport' => 'ssh' }, 'facts' => { 'platform' => 'centos-5-x86_64', 'provisioner' => 'vmpooler' }, 'name' => 'test.delivery.puppetlabs.net' }] }, { 'name' => 'winrm_nodes', 'nodes' => [] }]) # rubocop:disable Metrics/LineLength: Line is too long
83
+ end
84
+
85
+ it 'feature exists, and returns hash with feature removed' do
86
+ expect(dummy_class.remove_feature_from_group(feature_hash, 'puppet-agent', 'ssh_nodes')).to eq('groups' => [{ 'features' => [], 'name' => 'ssh_nodes', 'nodes' => [{ 'config' => { 'ssh' => { 'host-key-check' => false, 'password' => 'Qu@lity!', 'user' => 'root' }, 'transport' => 'ssh' }, 'facts' => { 'platform' => 'centos-5-x86_64', 'provisioner' => 'vmpooler' }, 'name' => 'test.delivery.puppetlabs.net' }] }, { 'name' => 'winrm_nodes', 'nodes' => [] }]) # rubocop:disable Metrics/LineLength: Line is too long
87
+ end
88
+
89
+ it 'write from inventory_hash to inventory_yaml file feature_hash' do
90
+ expect { dummy_class.write_to_inventory_file(feature_hash, inventory_full_path) }.not_to raise_error
91
+ end
92
+
93
+ it 'empty feature exists, and returns hash with feature added' do
94
+ expect(dummy_class.add_feature_to_group(empty_feature_hash, 'puppet-agent', 'ssh_nodes')).to eq('groups' => [{ 'features' => ['puppet-agent'], 'name' => 'ssh_nodes', 'nodes' => [{ 'config' => { 'ssh' => { 'host-key-check' => false, 'password' => 'Qu@lity!', 'user' => 'root' }, 'transport' => 'ssh' }, 'facts' => { 'platform' => 'centos-5-x86_64', 'provisioner' => 'vmpooler' }, 'name' => 'test.delivery.puppetlabs.net' }] }, { 'name' => 'winrm_nodes', 'nodes' => [] }]) # rubocop:disable Metrics/LineLength: Line is too long
95
+ end
96
+
97
+ it 'write from inventory_hash to inventory_yaml file no feature_hash' do
98
+ expect(File).to exist(inventory_full_path)
99
+ expect { dummy_class.write_to_inventory_file(no_feature_hash, inventory_full_path) }.not_to raise_error
100
+ end
46
101
  end
47
102
  end
@@ -50,4 +50,33 @@ RSpec.describe PuppetLitmus::Serverspec do
50
50
  end
51
51
  end
52
52
  end
53
+
54
+ describe '.bolt_upload_file' do
55
+ let(:local) { '/tmp' }
56
+ let(:remote) { '/remote_tmp' }
57
+ let(:result) { ['status' => 'success', 'result' => { 'exit_code' => 0, 'stdout' => nil, 'stderr' => nil }] }
58
+ let(:inventory_hash) { Hash.new(0) }
59
+
60
+ it 'responds to run_shell' do
61
+ expect(dummy_class).to respond_to(:bolt_upload_file).with(2..3).arguments
62
+ end
63
+
64
+ context 'when running against remote host' do
65
+ it 'does upload_file against remote host without error' do
66
+ allow(ENV).to receive(:[]).with('TARGET_HOST').and_return('some.host')
67
+ expect(dummy_class).to receive(:inventory_hash_from_inventory_file).and_return(inventory_hash)
68
+ expect(dummy_class).to receive(:upload_file).with(local, remote, 'some.host', options: {}, config: nil, inventory: inventory_hash).and_return(result)
69
+ expect { dummy_class.bolt_upload_file(local, remote) }.not_to raise_error
70
+ end
71
+ end
72
+
73
+ context 'when running against remote host' do
74
+ it 'does upload_file against localhost without error' do
75
+ allow(ENV).to receive(:[]).with('TARGET_HOST').and_return('localhost')
76
+ expect(dummy_class).not_to receive(:inventory_hash_from_inventory_file)
77
+ expect(dummy_class).to receive(:upload_file).with(local, remote, 'localhost', options: {}, config: nil, inventory: nil).and_return(result)
78
+ expect { dummy_class.bolt_upload_file(local, remote) }.not_to raise_error
79
+ end
80
+ end
81
+ end
53
82
  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.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-13 00:00:00.000000000 Z
11
+ date: 2019-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bolt
@@ -85,6 +85,7 @@ files:
85
85
  - lib/puppet_litmus/rake_tasks.rb
86
86
  - lib/puppet_litmus/serverspec.rb
87
87
  - lib/puppet_litmus/version.rb
88
+ - spec/data/inventory.yaml
88
89
  - spec/lib/puppet_litmus/inventory_manipulation_spec.rb
89
90
  - spec/lib/puppet_litmus/rake_tasks_spec.rb
90
91
  - spec/lib/puppet_litmus/serverspec_spec.rb
@@ -109,15 +110,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
110
  - !ruby/object:Gem::Version
110
111
  version: '0'
111
112
  requirements: []
112
- rubyforge_project:
113
- rubygems_version: 2.6.14.1
113
+ rubygems_version: 3.0.4
114
114
  signing_key:
115
115
  specification_version: 4
116
116
  summary: Providing a simple command line tool for puppet content creators, to enable
117
117
  simple and complex test deployments.
118
118
  test_files:
119
- - spec/spec_helper.rb
120
- - spec/lib/puppet_litmus/rake_tasks_spec.rb
121
- - spec/lib/puppet_litmus/version_spec.rb
119
+ - spec/data/inventory.yaml
122
120
  - spec/lib/puppet_litmus/inventory_manipulation_spec.rb
121
+ - spec/lib/puppet_litmus/rake_tasks_spec.rb
123
122
  - spec/lib/puppet_litmus/serverspec_spec.rb
123
+ - spec/lib/puppet_litmus/version_spec.rb
124
+ - spec/spec_helper.rb