puppet_litmus 0.4.0 → 0.5.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/lib/puppet_litmus/inventory_manipulation.rb +37 -1
- data/lib/puppet_litmus/rake_tasks.rb +167 -42
- data/lib/puppet_litmus/serverspec.rb +11 -8
- data/lib/puppet_litmus/version.rb +1 -1
- data/spec/lib/puppet_litmus/inventory_manipulation_spec.rb +47 -0
- data/spec/lib/puppet_litmus/rake_tasks_spec.rb +55 -0
- data/spec/lib/puppet_litmus/serverspec_spec.rb +53 -0
- data/spec/lib/{puppet_litmus_spec.rb → puppet_litmus/version_spec.rb} +0 -0
- data/spec/spec_helper.rb +25 -0
- metadata +10 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 33763c6946158b131037d7d28f96b7db4ae5b924
|
|
4
|
+
data.tar.gz: f85aa0cd77c310d4e798f8676189839bb4276d2b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 345cfa379161bccf03db5945499114e6d322161891b66d85aac934e7cd8de8834cc73c465d65a19c482cf8320d22c1ae89b1afb8bcc9794dab2faf3a7460aeec
|
|
7
|
+
data.tar.gz: bc6916ad37c08f73ab2594c9537e14212257583e37437c396ea1f716219edfdda2a9be430c9d55bc8b7b1f777ec27beac7c76f1a97fb6d676f72bb36327a3ccf
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
# helper functions for manipulating and reading a bolt inventory file
|
|
4
4
|
module PuppetLitmus::InventoryManipulation
|
|
5
|
+
# Creates an inventory hash from the inventory.yaml.
|
|
6
|
+
#
|
|
7
|
+
# @param inventory_full_path [String] path to the inventory.yaml file
|
|
8
|
+
# @return [Hash] hash of the inventory.yaml file.
|
|
5
9
|
def inventory_hash_from_inventory_file(inventory_full_path = nil)
|
|
6
10
|
inventory_full_path = if inventory_full_path.nil?
|
|
7
11
|
'inventory.yaml'
|
|
@@ -14,6 +18,11 @@ module PuppetLitmus::InventoryManipulation
|
|
|
14
18
|
inventory_hash
|
|
15
19
|
end
|
|
16
20
|
|
|
21
|
+
# Finds targets to perform operations on from an inventory hash.
|
|
22
|
+
#
|
|
23
|
+
# @param inventory_hash [Hash] hash of the inventory.yaml file
|
|
24
|
+
# @param targets [Array]
|
|
25
|
+
# @return [Array] array of targets.
|
|
17
26
|
def find_targets(inventory_hash, targets)
|
|
18
27
|
if targets.nil?
|
|
19
28
|
inventory = Bolt::Inventory.new(inventory_hash, nil)
|
|
@@ -24,6 +33,12 @@ module PuppetLitmus::InventoryManipulation
|
|
|
24
33
|
targets
|
|
25
34
|
end
|
|
26
35
|
|
|
36
|
+
# Determines if a node_name exists in a group in the inventory_hash.
|
|
37
|
+
#
|
|
38
|
+
# @param inventory_hash [Hash] hash of the inventory.yaml file
|
|
39
|
+
# @param node_name [String] node to locate in the group
|
|
40
|
+
# @param group_name [String] group of nodes to limit the search for the node_name in
|
|
41
|
+
# @return [Boolean] true if node_name exists in group_name.
|
|
27
42
|
def target_in_group(inventory_hash, node_name, group_name)
|
|
28
43
|
exists = false
|
|
29
44
|
inventory_hash['groups'].each do |group|
|
|
@@ -36,6 +51,11 @@ module PuppetLitmus::InventoryManipulation
|
|
|
36
51
|
exists
|
|
37
52
|
end
|
|
38
53
|
|
|
54
|
+
# Finds a config hash in the inventory hash by searching for a node name.
|
|
55
|
+
#
|
|
56
|
+
# @param inventory_hash [Hash] hash of the inventory.yaml file
|
|
57
|
+
# @param node_name [String] node to locate in the group
|
|
58
|
+
# @return [Hash] config for node of name node_name
|
|
39
59
|
def config_from_node(inventory_hash, node_name)
|
|
40
60
|
inventory_hash['groups'].each do |group|
|
|
41
61
|
group['nodes'].each do |node|
|
|
@@ -47,6 +67,11 @@ module PuppetLitmus::InventoryManipulation
|
|
|
47
67
|
raise "No config was found for #{node_name}"
|
|
48
68
|
end
|
|
49
69
|
|
|
70
|
+
# Finds a facts hash in the inventory hash by searching for a node name.
|
|
71
|
+
#
|
|
72
|
+
# @param inventory_hash [Hash] hash of the inventory.yaml file
|
|
73
|
+
# @param node_name [String] node to locate in the group
|
|
74
|
+
# @return [Hash] facts for node of name node_name
|
|
50
75
|
def facts_from_node(inventory_hash, node_name)
|
|
51
76
|
inventory_hash['groups'].each do |group|
|
|
52
77
|
group['nodes'].each do |node|
|
|
@@ -55,9 +80,15 @@ module PuppetLitmus::InventoryManipulation
|
|
|
55
80
|
end
|
|
56
81
|
end
|
|
57
82
|
end
|
|
58
|
-
raise "No
|
|
83
|
+
raise "No facts were found for #{node_name}"
|
|
59
84
|
end
|
|
60
85
|
|
|
86
|
+
# Adds a node to a group specified, if group_name exists in inventory hash.
|
|
87
|
+
#
|
|
88
|
+
# @param inventory_hash [Hash] hash of the inventory.yaml file
|
|
89
|
+
# @param node_name [String] node to locate in the group
|
|
90
|
+
# group_name [String] group of nodes to limit the search for the node_name in
|
|
91
|
+
# @return [Hash] inventory_hash with node added to group if group_name exists in inventory hash.
|
|
61
92
|
def add_node_to_group(inventory_hash, node_name, group_name)
|
|
62
93
|
inventory_hash['groups'].each do |group|
|
|
63
94
|
if group['name'] == group_name
|
|
@@ -67,6 +98,11 @@ module PuppetLitmus::InventoryManipulation
|
|
|
67
98
|
inventory_hash
|
|
68
99
|
end
|
|
69
100
|
|
|
101
|
+
# Removes named node from a group inside an inventory_hash.
|
|
102
|
+
#
|
|
103
|
+
# @param inventory_hash [Hash] hash of the inventory.yaml file
|
|
104
|
+
# @param node_name [String] node to locate in the group
|
|
105
|
+
# @return [Hash] inventory_hash with node of node_name removed.
|
|
70
106
|
def remove_node(inventory_hash, node_name)
|
|
71
107
|
inventory_hash['groups'].each do |group|
|
|
72
108
|
group['nodes'].delete_if { |i| i['name'] == node_name }
|
|
@@ -8,51 +8,64 @@ require 'pdk'
|
|
|
8
8
|
require 'json'
|
|
9
9
|
require 'parallel'
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
metadata[
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
when 'Windows'
|
|
24
|
-
'win'
|
|
25
|
-
else
|
|
26
|
-
os_info['operatingsystem'].downcase
|
|
27
|
-
end
|
|
11
|
+
# helper methods for the litmus rake tasks
|
|
12
|
+
module LitmusRakeHelper
|
|
13
|
+
# Gets a string representing the operating system and version.
|
|
14
|
+
#
|
|
15
|
+
# @param metadata [Hash] metadata to parse for operating system info
|
|
16
|
+
# @return [String] the operating system string with version info for use in provisioning.
|
|
17
|
+
def get_metadata_operating_systems(metadata)
|
|
18
|
+
return unless metadata.is_a?(Hash)
|
|
19
|
+
return unless metadata['operatingsystem_support'].is_a?(Array)
|
|
20
|
+
|
|
21
|
+
metadata['operatingsystem_support'].each do |os_info|
|
|
22
|
+
next unless os_info['operatingsystem'] && os_info['operatingsystemrelease']
|
|
28
23
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
release = release.delete('.') if release.include? '8.1'
|
|
37
|
-
release.sub('Server', '').sub('10', '10-pro')
|
|
24
|
+
os_name = case os_info['operatingsystem']
|
|
25
|
+
when 'Amazon', 'Archlinux', 'AIX', 'OSX'
|
|
26
|
+
next
|
|
27
|
+
when 'OracleLinux'
|
|
28
|
+
'oracle'
|
|
29
|
+
when 'Windows'
|
|
30
|
+
'win'
|
|
38
31
|
else
|
|
39
|
-
|
|
32
|
+
os_info['operatingsystem'].downcase
|
|
40
33
|
end
|
|
41
34
|
|
|
42
|
-
|
|
35
|
+
os_info['operatingsystemrelease'].each do |release|
|
|
36
|
+
version = case os_name
|
|
37
|
+
when 'ubuntu', 'osx'
|
|
38
|
+
release.sub('.', '')
|
|
39
|
+
when 'sles'
|
|
40
|
+
release.gsub(%r{ SP[14]}, '')
|
|
41
|
+
when 'win'
|
|
42
|
+
release = release.delete('.') if release.include? '8.1'
|
|
43
|
+
release.sub('Server', '').sub('10', '10-pro')
|
|
44
|
+
else
|
|
45
|
+
release
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
yield "#{os_name}-#{version.downcase}-x86_64".delete(' ')
|
|
49
|
+
end
|
|
43
50
|
end
|
|
44
51
|
end
|
|
45
|
-
end
|
|
46
52
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
# Executes a command on the test runner.
|
|
54
|
+
#
|
|
55
|
+
# @param command [String] command to execute.
|
|
56
|
+
# @return [Object] the standard out stream.
|
|
57
|
+
def run_local_command(command)
|
|
58
|
+
stdout, stderr, status = Open3.capture3(command)
|
|
59
|
+
error_message = "Attempted to run\ncommand:'#{command}'\nstdout:#{stdout}\nstderr:#{stderr}"
|
|
60
|
+
raise error_message unless status.to_i.zero?
|
|
51
61
|
|
|
52
|
-
|
|
62
|
+
stdout
|
|
63
|
+
end
|
|
53
64
|
end
|
|
54
65
|
|
|
55
66
|
namespace :litmus do
|
|
67
|
+
include LitmusRakeHelper
|
|
68
|
+
# Prints all supported OSes from metadata.json file.
|
|
56
69
|
desc 'print all supported OSes from metadata'
|
|
57
70
|
task :metadata do
|
|
58
71
|
metadata = JSON.parse(File.read('metadata.json'))
|
|
@@ -61,7 +74,11 @@ namespace :litmus do
|
|
|
61
74
|
end
|
|
62
75
|
end
|
|
63
76
|
|
|
64
|
-
|
|
77
|
+
# DEPRECATED - Provisions all supported OSes with provisioner eg 'bundle exec rake litmus:provision_from_metadata['vmpooler']'.
|
|
78
|
+
#
|
|
79
|
+
# @param :provisioner [String] provisioner to use in provisioning all OSes.
|
|
80
|
+
desc "DEPRECATED: provision_from_metadata task is deprecated.
|
|
81
|
+
Provision all supported OSes with provisioner eg 'bundle exec rake 'litmus:provision_from_metadata'"
|
|
65
82
|
task :provision_from_metadata, [:provisioner] do |_task, args|
|
|
66
83
|
metadata = JSON.parse(File.read('metadata.json'))
|
|
67
84
|
get_metadata_operating_systems(metadata) do |os_and_version|
|
|
@@ -83,6 +100,9 @@ namespace :litmus do
|
|
|
83
100
|
end
|
|
84
101
|
end
|
|
85
102
|
|
|
103
|
+
# Provisions a list of OSes from provision.yaml file e.g. 'bundle exec rake litmus:provision_list[default]'.
|
|
104
|
+
#
|
|
105
|
+
# @param :key [String] key that maps to a value for a provisioner and an image to be used for each OS provisioned.
|
|
86
106
|
desc "provision list of machines from provision.yaml file. 'bundle exec rake 'litmus:provision_list[default]'"
|
|
87
107
|
task :provision_list, [:key] do |_task, args|
|
|
88
108
|
provision_hash = YAML.load_file('./provision.yaml')
|
|
@@ -103,9 +123,19 @@ namespace :litmus do
|
|
|
103
123
|
raise "Failed to provision with '#{provisioner}'\n #{failed_image_message}" unless failed_image_message.empty?
|
|
104
124
|
end
|
|
105
125
|
|
|
126
|
+
# Provision a container or VM with a given platform 'bundle exec rake 'litmus:provision[vmpooler, ubuntu-1604-x86_64]'.
|
|
127
|
+
#
|
|
128
|
+
# @param :provisioner [String] provisioner to use in provisioning given platform.
|
|
129
|
+
# @param :platform [String] OS platform for container or VM to use.
|
|
106
130
|
desc "provision container/VM - abs/docker/vagrant/vmpooler eg 'bundle exec rake 'litmus:provision[vmpooler, ubuntu-1604-x86_64]'"
|
|
107
131
|
task :provision, [:provisioner, :platform] do |_task, args|
|
|
108
132
|
include BoltSpec::Run
|
|
133
|
+
spinner = if (ENV['CI'] == 'true') || !ENV['DISTELLI_BUILDNUM'].nil?
|
|
134
|
+
TTY::Spinner.new(':spinner', frames: ['.'], interval: 0.1)
|
|
135
|
+
else
|
|
136
|
+
TTY::Spinner.new("Provisioning #{args[:platform]} using #{args[:provisioner]} provisioner.[:spinner]")
|
|
137
|
+
end
|
|
138
|
+
spinner.auto_spin
|
|
109
139
|
Rake::Task['spec_prep'].invoke
|
|
110
140
|
config_data = { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') }
|
|
111
141
|
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'))
|
|
@@ -116,17 +146,29 @@ namespace :litmus do
|
|
|
116
146
|
|
|
117
147
|
params = { 'action' => 'provision', 'platform' => args[:platform], 'inventory' => Dir.pwd }
|
|
118
148
|
results = run_task("provision::#{args[:provisioner]}", 'localhost', params, config: config_data, inventory: nil)
|
|
119
|
-
|
|
149
|
+
if results.first['status'] != 'success'
|
|
150
|
+
spinner.error
|
|
151
|
+
raise "Failed provisioning #{args[:platform]} using #{args[:provisioner]}\n#{results.first}"
|
|
152
|
+
end
|
|
120
153
|
|
|
154
|
+
spinner.success
|
|
121
155
|
puts "#{results.first['result']['node_name']}, #{args[:platform]}"
|
|
122
156
|
end
|
|
123
157
|
|
|
158
|
+
# Install puppet agent on a collection of nodes
|
|
159
|
+
#
|
|
160
|
+
# @param :collection [String] parameters to pass to the puppet agent install command.
|
|
161
|
+
# @param :target_node_name [Array] nodes on which to install puppet agent.
|
|
124
162
|
desc 'install puppet agent, [:collection, :target_node_name]'
|
|
125
163
|
task :install_agent, [:collection, :target_node_name] do |_task, args|
|
|
126
|
-
puts 'install_agent'
|
|
127
|
-
include BoltSpec::Run
|
|
128
164
|
inventory_hash = inventory_hash_from_inventory_file
|
|
129
165
|
targets = find_targets(inventory_hash, args[:target_node_name])
|
|
166
|
+
if targets.empty?
|
|
167
|
+
puts 'No targets found'
|
|
168
|
+
exit 0
|
|
169
|
+
end
|
|
170
|
+
puts 'install_agent'
|
|
171
|
+
include BoltSpec::Run
|
|
130
172
|
Rake::Task['spec_prep'].invoke
|
|
131
173
|
config_data = { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') }
|
|
132
174
|
params = if args[:collection].nil?
|
|
@@ -153,8 +195,69 @@ namespace :litmus do
|
|
|
153
195
|
end
|
|
154
196
|
end
|
|
155
197
|
|
|
198
|
+
# Install puppet enterprise - for internal puppet employees only - Requires an el7 provisioned machine - experimental feature [:target_node_name]'
|
|
199
|
+
#
|
|
200
|
+
# @param :target_node_name [Array] nodes on which to install puppet agent.
|
|
201
|
+
desc 'install puppet enterprise - for internal puppet employees only - Requires an el7 provisioned machine - experimental feature [:target_node_name]'
|
|
202
|
+
task :install_pe, [:target_node_name] do |_task, args|
|
|
203
|
+
inventory_hash = inventory_hash_from_inventory_file
|
|
204
|
+
target_nodes = find_targets(inventory_hash, args[:target_node_name])
|
|
205
|
+
if target_nodes.empty?
|
|
206
|
+
puts 'No targets found'
|
|
207
|
+
exit 0
|
|
208
|
+
end
|
|
209
|
+
puts 'install_pe'
|
|
210
|
+
include BoltSpec::Run
|
|
211
|
+
Rake::Task['spec_prep'].invoke
|
|
212
|
+
config_data = { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') }
|
|
213
|
+
|
|
214
|
+
puts 'Setting up parameters'
|
|
215
|
+
|
|
216
|
+
PE_RELEASE = 2019.0
|
|
217
|
+
pe_latest_cmd = "curl http://enterprise.delivery.puppetlabs.net/#{PE_RELEASE}/ci-ready/LATEST"
|
|
218
|
+
pe_latest = run_command(pe_latest_cmd, target_nodes, config: config_data, inventory: inventory_hash)
|
|
219
|
+
pe_latest_string = pe_latest[0]['result']['stdout'].delete("\n")
|
|
220
|
+
PE_FILE_NAME = "puppet-enterprise-#{pe_latest_string}-el-7-x86_64"
|
|
221
|
+
TAR_FILE = "#{PE_FILE_NAME}.tar"
|
|
222
|
+
DOWNLOAD_URL = "http://enterprise.delivery.puppetlabs.net/#{PE_RELEASE}/ci-ready/#{TAR_FILE}"
|
|
223
|
+
|
|
224
|
+
puts 'Initiating PE download'
|
|
225
|
+
|
|
226
|
+
# Download PE
|
|
227
|
+
download_pe_cmd = "wget -q #{DOWNLOAD_URL}"
|
|
228
|
+
run_command(download_pe_cmd, target_nodes, config: config_data, inventory: inventory_hash)
|
|
229
|
+
|
|
230
|
+
puts 'PE successfully downloaded, running installer (this may take 5 or so minutes, please be patient)'
|
|
231
|
+
|
|
232
|
+
# Install PE
|
|
233
|
+
untar_cmd = "tar xvf #{TAR_FILE}"
|
|
234
|
+
run_command(untar_cmd, target_nodes, config: config_data, inventory: inventory_hash)
|
|
235
|
+
puts run_command("cd #{PE_FILE_NAME} && 1 | ./puppet-enterprise-installer", target_nodes, config: nil, inventory: inventory_hash)[0]['result']['stdout']
|
|
236
|
+
|
|
237
|
+
puts 'Autosigning Certificates'
|
|
238
|
+
|
|
239
|
+
# Set Autosign
|
|
240
|
+
autosign_cmd = "echo 'autosign = true' >> /etc/puppetlabs/puppet/puppet.conf"
|
|
241
|
+
run_command(autosign_cmd, target_nodes, config: config_data, inventory: inventory_hash)
|
|
242
|
+
|
|
243
|
+
puts 'Finishing installation with a Puppet Agent run'
|
|
244
|
+
|
|
245
|
+
run_command('puppet agent -t', target_nodes, config: config_data, inventory: inventory_hash)
|
|
246
|
+
|
|
247
|
+
puts 'PE Installation is now complete'
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Install the puppet module under test on a collection of nodes
|
|
251
|
+
#
|
|
252
|
+
# @param :target_node_name [Array] nodes on which to install a puppet module for testing.
|
|
156
253
|
desc 'install_module - build and install module'
|
|
157
254
|
task :install_module, [:target_node_name] do |_task, args|
|
|
255
|
+
inventory_hash = inventory_hash_from_inventory_file
|
|
256
|
+
target_nodes = find_targets(inventory_hash, args[:target_node_name])
|
|
257
|
+
if target_nodes.empty?
|
|
258
|
+
puts 'No targets found'
|
|
259
|
+
exit 0
|
|
260
|
+
end
|
|
158
261
|
include BoltSpec::Run
|
|
159
262
|
# old cli_way
|
|
160
263
|
# pdk_build_command = 'bundle exec pdk build --force'
|
|
@@ -167,8 +270,6 @@ namespace :litmus do
|
|
|
167
270
|
module_tar = builder.build
|
|
168
271
|
puts 'Built'
|
|
169
272
|
|
|
170
|
-
inventory_hash = inventory_hash_from_inventory_file
|
|
171
|
-
target_nodes = find_targets(inventory_hash, args[:target_node_name])
|
|
172
273
|
# module_tar = Dir.glob('pkg/*.tar.gz').max_by { |f| File.mtime(f) }
|
|
173
274
|
raise "Unable to find package in 'pkg/*.tar.gz'" if module_tar.nil?
|
|
174
275
|
|
|
@@ -192,15 +293,34 @@ namespace :litmus do
|
|
|
192
293
|
puts 'Installed'
|
|
193
294
|
end
|
|
194
295
|
|
|
296
|
+
# Provision a list of machines, install a puppet agent, and install the puppet module under test on a collection of nodes
|
|
297
|
+
#
|
|
298
|
+
# @param :key [String] key that maps to a value for a provisioner and an image to be used for each OS provisioned.
|
|
299
|
+
# @param :collection [String] parameters to pass to the puppet agent install command.
|
|
300
|
+
desc 'provision_install - provision a list of machines, install an agent, and the module.'
|
|
301
|
+
task :provision_install, [:key, :collection] do |_task, args|
|
|
302
|
+
Rake::Task['spec_prep'].invoke
|
|
303
|
+
Rake::Task['litmus:provision_list'].invoke(args[:key])
|
|
304
|
+
Rake::Task['litmus:install_agent'].invoke(args[:collection])
|
|
305
|
+
Rake::Task['litmus:install_module'].invoke
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# Decommissions test machines.
|
|
309
|
+
#
|
|
310
|
+
# @param :target [Array] nodes to remove from test environemnt and decommission.
|
|
195
311
|
desc 'tear-down - decommission machines'
|
|
196
312
|
task :tear_down, [:target] do |_task, args|
|
|
313
|
+
inventory_hash = inventory_hash_from_inventory_file
|
|
314
|
+
targets = find_targets(inventory_hash, args[:target])
|
|
315
|
+
if targets.empty?
|
|
316
|
+
puts 'No targets found'
|
|
317
|
+
exit 0
|
|
318
|
+
end
|
|
197
319
|
include BoltSpec::Run
|
|
198
320
|
Rake::Task['spec_prep'].invoke
|
|
199
321
|
config_data = { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') }
|
|
200
322
|
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'))
|
|
201
323
|
|
|
202
|
-
inventory_hash = inventory_hash_from_inventory_file
|
|
203
|
-
targets = find_targets(inventory_hash, args[:target])
|
|
204
324
|
bad_results = []
|
|
205
325
|
targets.each do |node_name|
|
|
206
326
|
# how do we know what provisioner to use
|
|
@@ -229,8 +349,13 @@ namespace :litmus do
|
|
|
229
349
|
inventory_hash = inventory_hash_from_inventory_file
|
|
230
350
|
targets = find_targets(inventory_hash, nil)
|
|
231
351
|
|
|
352
|
+
# Run acceptance tests against all machines in the inventory file in parallel.
|
|
232
353
|
desc 'Run tests in parallel against all machines in the inventory file'
|
|
233
354
|
task :parallel do
|
|
355
|
+
if targets.empty?
|
|
356
|
+
puts 'No targets found'
|
|
357
|
+
exit 0
|
|
358
|
+
end
|
|
234
359
|
spinners = TTY::Spinner::Multi.new("Running against #{targets.size} targets.[:spinner]", frames: ['.'], interval: 0.1)
|
|
235
360
|
payloads = []
|
|
236
361
|
targets.each do |target|
|
|
@@ -21,11 +21,11 @@ module PuppetLitmus::Serverspec
|
|
|
21
21
|
# @param opts [Hash] Alters the behaviour of the command. Valid options are:
|
|
22
22
|
# :catch_changes [Boolean] exit status of 1 if there were changes.
|
|
23
23
|
# :expect_failures [Boolean] doesnt return an exit code of non-zero if the apply failed.
|
|
24
|
-
# :manifest_file_location [Path] The place on the target system.
|
|
25
|
-
# :prefix_command [String] prefixes the puppet apply command; eg "export LANGUAGE='ja'".
|
|
26
|
-
# :debug [Boolean] run puppet apply with the debug flag.
|
|
27
|
-
# :noop [Boolean] run puppet apply with the noop flag.
|
|
28
|
-
# @
|
|
24
|
+
# :manifest_file_location [Path] The place on the target system.
|
|
25
|
+
# :prefix_command [String] prefixes the puppet apply command; eg "export LANGUAGE='ja'".
|
|
26
|
+
# :debug [Boolean] run puppet apply with the debug flag.
|
|
27
|
+
# :noop [Boolean] run puppet apply with the noop flag.
|
|
28
|
+
# @yieldreturn [Block] this method will yield to a block of code passed by the caller; this can be used for additional validation, etc.
|
|
29
29
|
# @return [Object] A result object from the apply.
|
|
30
30
|
def apply_manifest(manifest, opts = {})
|
|
31
31
|
# rubocop:enable Layout/TrailingWhitespace
|
|
@@ -83,13 +83,16 @@ module PuppetLitmus::Serverspec
|
|
|
83
83
|
#
|
|
84
84
|
# @param command_to_run [String] The command to execute.
|
|
85
85
|
# @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.
|
|
86
|
-
# @
|
|
86
|
+
# @yieldreturn [Block] this method will yield to a block of code passed by the caller; this can be used for additional validation, etc.
|
|
87
87
|
# @return [Object] A result object from the command.
|
|
88
88
|
def run_shell(command_to_run, opts = {})
|
|
89
|
-
inventory_hash = inventory_hash_from_inventory_file
|
|
90
89
|
target_node_name = ENV['TARGET_HOST']
|
|
90
|
+
inventory_hash = if target_node_name.nil? || target_node_name == 'localhost'
|
|
91
|
+
nil
|
|
92
|
+
else
|
|
93
|
+
inventory_hash_from_inventory_file
|
|
94
|
+
end
|
|
91
95
|
result = run_command(command_to_run, target_node_name, config: nil, inventory: inventory_hash)
|
|
92
|
-
|
|
93
96
|
raise "shell failed\n`#{command_to_run}`\n======\n#{result}" if result.first['result']['exit_code'] != 0 && opts[:expect_failures] != true
|
|
94
97
|
|
|
95
98
|
result = OpenStruct.new(exit_code: result.first['result']['exit_code'],
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe PuppetLitmus::InventoryManipulation do
|
|
6
|
+
class DummyClass
|
|
7
|
+
end
|
|
8
|
+
let(:dummy_class) do
|
|
9
|
+
dummy_class = DummyClass.new
|
|
10
|
+
dummy_class.extend(described_class)
|
|
11
|
+
dummy_class
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context 'with config_from_node' do
|
|
15
|
+
let(:no_config_hash) do
|
|
16
|
+
{ 'groups' =>
|
|
17
|
+
[{ 'name' => 'ssh_nodes',
|
|
18
|
+
'nodes' =>
|
|
19
|
+
[{ 'name' => 'test.delivery.puppetlabs.net',
|
|
20
|
+
'facts' => { 'provisioner' => 'vmpooler', 'platform' => 'centos-5-x86_64' } }] },
|
|
21
|
+
{ 'name' => 'winrm_nodes', 'nodes' => [] }] }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
let(:config_hash) do
|
|
25
|
+
{ 'groups' =>
|
|
26
|
+
[{ 'name' => 'ssh_nodes',
|
|
27
|
+
'nodes' =>
|
|
28
|
+
[{ 'name' => 'test.delivery.puppetlabs.net',
|
|
29
|
+
'config' => { 'transport' => 'ssh', 'ssh' => { 'user' => 'root', 'password' => 'Qu@lity!', 'host-key-check' => false } },
|
|
30
|
+
'facts' => { 'provisioner' => 'vmpooler', 'platform' => 'centos-5-x86_64' } }] },
|
|
31
|
+
{ 'name' => 'winrm_nodes', 'nodes' => [] }] }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'no matching node, raises' do
|
|
35
|
+
expect { dummy_class.config_from_node(config_hash, 'not.here') }.to raise_error('No config was found for not.here')
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'no config section, returns nil' do
|
|
39
|
+
expect(dummy_class.config_from_node(no_config_hash, 'test.delivery.puppetlabs.net')).to eq(nil)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'config exists, and returns' do
|
|
43
|
+
expect(dummy_class.config_from_node(config_hash, 'test.delivery.puppetlabs.net')).to eq('transport' => 'ssh', 'ssh' =>
|
|
44
|
+
{ 'user' => 'root', 'password' => 'Qu@lity!', 'host-key-check' => false })
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'rake'
|
|
5
|
+
|
|
6
|
+
describe 'litmus rake tasks' do
|
|
7
|
+
before(:all) do # rubocop:disable RSpec/BeforeAfterAll
|
|
8
|
+
load File.expand_path('../../../lib/puppet_litmus/rake_tasks.rb', __dir__)
|
|
9
|
+
# the spec_prep task is stubbed, rather than load from another gem.
|
|
10
|
+
Rake::Task.define_task(:spec_prep)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
context 'with litmus:metadata task' do
|
|
14
|
+
it 'happy path' do
|
|
15
|
+
metadata = { 'name' => 'puppetlabs-postgresql',
|
|
16
|
+
'version' => '6.0.0',
|
|
17
|
+
'operatingsystem_support' =>
|
|
18
|
+
[{ 'operatingsystem' => 'RedHat', 'operatingsystemrelease' => ['5'] },
|
|
19
|
+
{ 'operatingsystem' => 'Ubuntu', 'operatingsystemrelease' => ['14.04', '18.04'] }],
|
|
20
|
+
'template-ref' => 'heads/master-0-g7827fc2' }
|
|
21
|
+
expect(File).to receive(:read).with(any_args).once
|
|
22
|
+
expect(JSON).to receive(:parse).with(any_args).and_return(metadata)
|
|
23
|
+
expect(STDOUT).to receive(:puts).with('redhat-5-x86_64')
|
|
24
|
+
expect(STDOUT).to receive(:puts).with('ubuntu-1404-x86_64')
|
|
25
|
+
expect(STDOUT).to receive(:puts).with('ubuntu-1804-x86_64')
|
|
26
|
+
Rake::Task['litmus:metadata'].invoke
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context 'with litmus:provision_install task' do
|
|
31
|
+
it 'happy path' do
|
|
32
|
+
expect(Rake::Task['spec_prep']).to receive(:invoke).and_return('').once
|
|
33
|
+
expect(Rake::Task['litmus:provision_list']).to receive(:invoke).with('default').once
|
|
34
|
+
expect(Rake::Task['litmus:install_agent']).to receive(:invoke).with('puppet6').once
|
|
35
|
+
expect(Rake::Task['litmus:install_module']).to receive(:invoke).once
|
|
36
|
+
Rake::Task['litmus:provision_install'].invoke('default', 'puppet6')
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context 'with litmus:provision task' do
|
|
41
|
+
it 'provisions' do
|
|
42
|
+
results = [{ 'node' => 'localhost',
|
|
43
|
+
'target' => 'localhost',
|
|
44
|
+
'action' => 'task',
|
|
45
|
+
'object' => 'provision::docker',
|
|
46
|
+
'status' => 'success',
|
|
47
|
+
'result' => { 'status' => 'ok', 'node_name' => 'localhost:2222' } }]
|
|
48
|
+
|
|
49
|
+
allow(File).to receive(:directory?).with(any_args).and_return(true)
|
|
50
|
+
allow_any_instance_of(BoltSpec::Run).to receive(:run_task).with(any_args).and_return(results) # rubocop:disable RSpec/AnyInstance
|
|
51
|
+
expect(STDOUT).to receive(:puts).with('localhost:2222, centos:7')
|
|
52
|
+
Rake::Task['litmus:provision'].invoke('docker', 'centos:7')
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe PuppetLitmus::Serverspec do
|
|
6
|
+
class DummyClass
|
|
7
|
+
end
|
|
8
|
+
let(:dummy_class) do
|
|
9
|
+
dummy_class = DummyClass.new
|
|
10
|
+
dummy_class.extend(described_class)
|
|
11
|
+
dummy_class
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context 'with idempotent_apply' do
|
|
15
|
+
let(:manifest) do
|
|
16
|
+
"include '::doot'"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'calls all functions' do
|
|
20
|
+
expect(dummy_class).to receive(:create_manifest_file).with(manifest).and_return('/bla.pp')
|
|
21
|
+
expect(dummy_class).to receive(:apply_manifest).with(nil, catch_failures: true, manifest_file_location: '/bla.pp')
|
|
22
|
+
expect(dummy_class).to receive(:apply_manifest).with(nil, catch_changes: true, manifest_file_location: '/bla.pp')
|
|
23
|
+
dummy_class.idempotent_apply(manifest)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe '.run_shell' do
|
|
28
|
+
let(:command_to_run) { "puts 'doot'" }
|
|
29
|
+
let(:result) { ['result' => { 'exit_code' => 0, 'stdout' => nil, 'stderr' => nil }] }
|
|
30
|
+
let(:inventory_hash) { Hash.new(0) }
|
|
31
|
+
|
|
32
|
+
it 'responds to run_shell' do
|
|
33
|
+
expect(dummy_class).to respond_to(:run_shell).with(1..2).arguments
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context 'when running against localhost and no inventory.yaml file' do
|
|
37
|
+
it 'does run_shell against localhost without error' do
|
|
38
|
+
allow(ENV).to receive(:[]).with('TARGET_HOST').and_return('localhost')
|
|
39
|
+
expect(dummy_class).to receive(:run_command).with(command_to_run, 'localhost', config: nil, inventory: nil).and_return(result)
|
|
40
|
+
expect { dummy_class.run_shell(command_to_run) }.not_to raise_error
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context 'when running against remote host' do
|
|
45
|
+
it 'does run_shell against remote host without error' do
|
|
46
|
+
allow(ENV).to receive(:[]).with('TARGET_HOST').and_return('some.host')
|
|
47
|
+
expect(dummy_class).to receive(:inventory_hash_from_inventory_file).and_return(inventory_hash)
|
|
48
|
+
expect(dummy_class).to receive(:run_command).with(command_to_run, 'some.host', config: nil, inventory: inventory_hash).and_return(result)
|
|
49
|
+
expect { dummy_class.run_shell(command_to_run) }.not_to raise_error
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
File without changes
|
data/spec/spec_helper.rb
CHANGED
|
@@ -2,3 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
require 'rspec'
|
|
4
4
|
require 'puppet_litmus'
|
|
5
|
+
|
|
6
|
+
if ENV['COVERAGE'] == 'yes'
|
|
7
|
+
require 'simplecov'
|
|
8
|
+
|
|
9
|
+
SimpleCov.formatters = [
|
|
10
|
+
SimpleCov::Formatter::HTMLFormatter,
|
|
11
|
+
]
|
|
12
|
+
SimpleCov.start do
|
|
13
|
+
track_files 'lib/**/*.rb'
|
|
14
|
+
|
|
15
|
+
add_filter '/spec'
|
|
16
|
+
|
|
17
|
+
# do not track vendored files
|
|
18
|
+
add_filter '/vendor'
|
|
19
|
+
add_filter '/.vendor'
|
|
20
|
+
|
|
21
|
+
# do not track gitignored files
|
|
22
|
+
# this adds about 4 seconds to the coverage check
|
|
23
|
+
# this could definitely be optimized
|
|
24
|
+
add_filter do |f|
|
|
25
|
+
# system returns true if exit status is 0, which with git-check-ignore means file is ignored
|
|
26
|
+
system("git check-ignore --quiet #{f.filename}")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
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.5.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-
|
|
11
|
+
date: 2019-06-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bolt
|
|
@@ -85,7 +85,10 @@ 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/lib/
|
|
88
|
+
- spec/lib/puppet_litmus/inventory_manipulation_spec.rb
|
|
89
|
+
- spec/lib/puppet_litmus/rake_tasks_spec.rb
|
|
90
|
+
- spec/lib/puppet_litmus/serverspec_spec.rb
|
|
91
|
+
- spec/lib/puppet_litmus/version_spec.rb
|
|
89
92
|
- spec/spec_helper.rb
|
|
90
93
|
homepage: https://github.com/puppetlabs/puppet_litmus
|
|
91
94
|
licenses:
|
|
@@ -114,4 +117,7 @@ summary: Providing a simple command line tool for puppet content creators, to en
|
|
|
114
117
|
simple and complex test deployments.
|
|
115
118
|
test_files:
|
|
116
119
|
- spec/spec_helper.rb
|
|
117
|
-
- spec/lib/
|
|
120
|
+
- spec/lib/puppet_litmus/rake_tasks_spec.rb
|
|
121
|
+
- spec/lib/puppet_litmus/version_spec.rb
|
|
122
|
+
- spec/lib/puppet_litmus/inventory_manipulation_spec.rb
|
|
123
|
+
- spec/lib/puppet_litmus/serverspec_spec.rb
|