puppet_litmus 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/puppet_litmus/inventory_manipulation.rb +47 -0
- data/lib/puppet_litmus/rake_tasks.rb +17 -6
- data/lib/puppet_litmus/serverspec.rb +31 -0
- data/lib/puppet_litmus/version.rb +1 -1
- data/spec/data/inventory.yaml +16 -0
- data/spec/lib/puppet_litmus/inventory_manipulation_spec.rb +55 -0
- data/spec/lib/puppet_litmus/serverspec_spec.rb +29 -0
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9a8186fb041ca1c958fb32f75389eceb29cbe6c107c0510b725fdc2bba18b900
|
4
|
+
data.tar.gz: 7ffe43266b6c14f59f1c306f86c018f44b312d9ee02e9253e3b3cbd38932f26e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 =
|
365
|
+
test = 'bundle exec bundle exec rspec ./spec/acceptance --format progress'
|
363
366
|
title = "#{target}, #{facts_from_node(inventory_hash, target)['platform']}"
|
364
|
-
|
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
|
-
|
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.
|
@@ -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.
|
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-
|
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
|
-
|
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/
|
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
|