puppet_litmus 0.7.3 → 0.8.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 +5 -5
- data/LICENSE +201 -201
- data/README.md +35 -35
- data/lib/puppet_litmus.rb +15 -15
- data/lib/puppet_litmus/inventory_manipulation.rb +203 -159
- data/lib/puppet_litmus/rake_tasks.rb +460 -445
- data/lib/puppet_litmus/serverspec.rb +224 -214
- data/lib/puppet_litmus/version.rb +6 -6
- data/spec/data/inventory.yaml +16 -16
- data/spec/lib/puppet_litmus/inventory_manipulation_spec.rb +138 -102
- data/spec/lib/puppet_litmus/rake_tasks_spec.rb +55 -55
- data/spec/lib/puppet_litmus/serverspec_spec.rb +194 -196
- data/spec/lib/puppet_litmus/version_spec.rb +10 -10
- data/spec/spec_helper.rb +29 -29
- metadata +7 -7
@@ -1,214 +1,224 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# helper functions for running puppet commands. They execute a target system specified by ENV['TARGET_HOST']
|
4
|
-
# heavily uses functions from here https://github.com/puppetlabs/bolt/blob/master/developer-docs/bolt_spec-run.md
|
5
|
-
module PuppetLitmus::Serverspec
|
6
|
-
# Applies a manifest twice. First checking for errors. Secondly to make sure no changes occur.
|
7
|
-
#
|
8
|
-
# @param manifest [String] puppet manifest code to be applied.
|
9
|
-
# @return [Boolean] The result of the 2 apply manifests.
|
10
|
-
def idempotent_apply(manifest)
|
11
|
-
manifest_file_location = create_manifest_file(manifest)
|
12
|
-
apply_manifest(nil, catch_failures: true, manifest_file_location: manifest_file_location)
|
13
|
-
apply_manifest(nil, catch_changes: true, manifest_file_location: manifest_file_location)
|
14
|
-
end
|
15
|
-
|
16
|
-
# rubocop:disable Layout/TrailingWhitespace
|
17
|
-
|
18
|
-
# Applies a manifest. returning the result of that apply. Mimics the apply_manifest from beaker
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
# :
|
28
|
-
#
|
29
|
-
#
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
result_obj[:
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# helper functions for running puppet commands. They execute a target system specified by ENV['TARGET_HOST']
|
4
|
+
# heavily uses functions from here https://github.com/puppetlabs/bolt/blob/master/developer-docs/bolt_spec-run.md
|
5
|
+
module PuppetLitmus::Serverspec
|
6
|
+
# Applies a manifest twice. First checking for errors. Secondly to make sure no changes occur.
|
7
|
+
#
|
8
|
+
# @param manifest [String] puppet manifest code to be applied.
|
9
|
+
# @return [Boolean] The result of the 2 apply manifests.
|
10
|
+
def idempotent_apply(manifest)
|
11
|
+
manifest_file_location = create_manifest_file(manifest)
|
12
|
+
apply_manifest(nil, catch_failures: true, manifest_file_location: manifest_file_location)
|
13
|
+
apply_manifest(nil, catch_changes: true, manifest_file_location: manifest_file_location)
|
14
|
+
end
|
15
|
+
|
16
|
+
# rubocop:disable Layout/TrailingWhitespace
|
17
|
+
|
18
|
+
# Applies a manifest. returning the result of that apply. Mimics the apply_manifest from beaker
|
19
|
+
#
|
20
|
+
# When you set the environment variable RSPEC_DEBUG, the output of your
|
21
|
+
# puppet run will be displayed. If you have set the :debug flag, you will see the
|
22
|
+
# full debug log. If you have **not** set the :debug flag, it will display the regular
|
23
|
+
# output.
|
24
|
+
#
|
25
|
+
# @param manifest [String] puppet manifest code to be applied.
|
26
|
+
# @param opts [Hash] Alters the behaviour of the command. Valid options are:
|
27
|
+
# :catch_changes [Boolean] exit status of 1 if there were changes.
|
28
|
+
# :expect_failures [Boolean] doesnt return an exit code of non-zero if the apply failed.
|
29
|
+
# :manifest_file_location [Path] The place on the target system.
|
30
|
+
# :prefix_command [String] prefixes the puppet apply command; eg "export LANGUAGE='ja'".
|
31
|
+
# :debug [Boolean] run puppet apply with the debug flag.
|
32
|
+
# :noop [Boolean] run puppet apply with the noop flag.
|
33
|
+
# @yieldreturn [Block] this method will yield to a block of code passed by the caller; this can be used for additional validation, etc.
|
34
|
+
# @return [Object] A result object from the apply.
|
35
|
+
def apply_manifest(manifest, opts = {})
|
36
|
+
# rubocop:enable Layout/TrailingWhitespace
|
37
|
+
target_node_name = ENV['TARGET_HOST']
|
38
|
+
raise 'manifest and manifest_file_location in the opts hash are mutually exclusive arguments, pick one' if !manifest.nil? && !opts[:manifest_file_location].nil?
|
39
|
+
raise 'please pass a manifest or the manifest_file_location in the opts hash' if (manifest.nil? || manifest == '') && opts[:manifest_file_location].nil?
|
40
|
+
|
41
|
+
manifest_file_location = opts[:manifest_file_location] || create_manifest_file(manifest)
|
42
|
+
inventory_hash = if target_node_name.nil? || target_node_name == 'localhost'
|
43
|
+
nil
|
44
|
+
else
|
45
|
+
inventory_hash_from_inventory_file
|
46
|
+
end
|
47
|
+
command_to_run = "#{opts[:prefix_command]} puppet apply #{manifest_file_location}"
|
48
|
+
command_to_run += " --modulepath #{Dir.pwd}/spec/fixtures/modules" if target_node_name.nil? || target_node_name == 'localhost'
|
49
|
+
command_to_run += ' --detailed-exitcodes' if !opts[:catch_changes].nil? && (opts[:catch_changes] == true)
|
50
|
+
command_to_run += ' --debug' if !opts[:debug].nil? && (opts[:debug] == true)
|
51
|
+
command_to_run += ' --noop' if !opts[:noop].nil? && (opts[:noop] == true)
|
52
|
+
result = run_command(command_to_run, target_node_name, config: nil, inventory: inventory_hash)
|
53
|
+
|
54
|
+
raise "apply manifest failed\n`#{command_to_run}`\n======\n#{result}" if result.first['result']['exit_code'] != 0 && opts[:expect_failures] != true
|
55
|
+
|
56
|
+
result = OpenStruct.new(exit_code: result.first['result']['exit_code'],
|
57
|
+
stdout: result.first['result']['stdout'],
|
58
|
+
stderr: result.first['result']['stderr'])
|
59
|
+
yield result if block_given?
|
60
|
+
if ENV['RSPEC_DEBUG']
|
61
|
+
puts "apply manifest succeded\n #{command_to_run}\n======\nwith status #{result.exit_code}"
|
62
|
+
puts result.stderr
|
63
|
+
puts result.stdout
|
64
|
+
end
|
65
|
+
result
|
66
|
+
end
|
67
|
+
|
68
|
+
# Creates a manifest file locally in a temp location, if its a remote target copy it to there.
|
69
|
+
#
|
70
|
+
# @param manifest [String] puppet manifest code.
|
71
|
+
# @return [String] The path to the location of the manifest.
|
72
|
+
def create_manifest_file(manifest)
|
73
|
+
require 'tmpdir'
|
74
|
+
target_node_name = ENV['TARGET_HOST']
|
75
|
+
tmp_filename = File.join(Dir.tmpdir, "manifest_#{Time.now.strftime('%Y%m%d')}_#{Process.pid}_#{rand(0x100000000).to_s(36)}.pp")
|
76
|
+
manifest_file = File.open(tmp_filename, 'w')
|
77
|
+
manifest_file.write(manifest)
|
78
|
+
manifest_file.close
|
79
|
+
if target_node_name.nil? || target_node_name == 'localhost'
|
80
|
+
# no need to transfer
|
81
|
+
manifest_file_location = manifest_file.path
|
82
|
+
else
|
83
|
+
# transfer to TARGET_HOST
|
84
|
+
inventory_hash = inventory_hash_from_inventory_file
|
85
|
+
manifest_file_location = "/tmp/#{File.basename(manifest_file)}"
|
86
|
+
result = upload_file(manifest_file.path, manifest_file_location, target_node_name, options: {}, config: nil, inventory: inventory_hash)
|
87
|
+
raise result.first['result'].to_s unless result.first['status'] == 'success'
|
88
|
+
end
|
89
|
+
manifest_file_location
|
90
|
+
end
|
91
|
+
|
92
|
+
# Runs a command against the target system
|
93
|
+
#
|
94
|
+
# @param command_to_run [String] The command to execute.
|
95
|
+
# @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.
|
96
|
+
# @yieldreturn [Block] this method will yield to a block of code passed by the caller; this can be used for additional validation, etc.
|
97
|
+
# @return [Object] A result object from the command.
|
98
|
+
def run_shell(command_to_run, opts = {})
|
99
|
+
target_node_name = ENV['TARGET_HOST']
|
100
|
+
inventory_hash = if target_node_name.nil? || target_node_name == 'localhost'
|
101
|
+
nil
|
102
|
+
else
|
103
|
+
inventory_hash_from_inventory_file
|
104
|
+
end
|
105
|
+
result = run_command(command_to_run, target_node_name, config: nil, inventory: inventory_hash)
|
106
|
+
raise "shell failed\n`#{command_to_run}`\n======\n#{result}" if result.first['result']['exit_code'] != 0 && opts[:expect_failures] != true
|
107
|
+
|
108
|
+
result = OpenStruct.new(exit_code: result.first['result']['exit_code'],
|
109
|
+
stdout: result.first['result']['stdout'],
|
110
|
+
stderr: result.first['result']['stderr'])
|
111
|
+
yield result if block_given?
|
112
|
+
result
|
113
|
+
end
|
114
|
+
|
115
|
+
# Copies file to the target, using its respective transport
|
116
|
+
#
|
117
|
+
# @param source [String] place locally, to copy from.
|
118
|
+
# @param destination [String] place on the target, to copy to.
|
119
|
+
# @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.
|
120
|
+
# @yieldreturn [Block] this method will yield to a block of code passed by the caller; this can be used for additional validation, etc.
|
121
|
+
# @return [Object] A result object from the command.
|
122
|
+
def bolt_upload_file(source, destination, opts = {}, options = {})
|
123
|
+
target_node_name = ENV['TARGET_HOST'] if target_node_name.nil?
|
124
|
+
inventory_hash = if target_node_name.nil? || target_node_name == 'localhost'
|
125
|
+
nil
|
126
|
+
else
|
127
|
+
inventory_hash_from_inventory_file
|
128
|
+
end
|
129
|
+
|
130
|
+
result = upload_file(source, destination, target_node_name, options: options, config: nil, inventory: inventory_hash)
|
131
|
+
|
132
|
+
result_obj = {
|
133
|
+
exit_code: 0,
|
134
|
+
stdout: result.first['result']['_output'],
|
135
|
+
stderr: nil,
|
136
|
+
result: result.first['result'],
|
137
|
+
}
|
138
|
+
|
139
|
+
if result.first['status'] != 'success'
|
140
|
+
raise "upload file failed\n======\n#{result}" if opts[:expect_failures] != true
|
141
|
+
|
142
|
+
result_obj[:exit_code] = 255
|
143
|
+
result_obj[:stderr] = result.first['result']['_error']['msg']
|
144
|
+
end
|
145
|
+
|
146
|
+
result = OpenStruct.new(exit_code: result_obj[:exit_code],
|
147
|
+
stdout: result_obj[:stdout],
|
148
|
+
stderr: result_obj[:stderr])
|
149
|
+
yield result if block_given?
|
150
|
+
result
|
151
|
+
end
|
152
|
+
|
153
|
+
# Runs a task against the target system.
|
154
|
+
#
|
155
|
+
# @param task_name [String] The name of the task to run.
|
156
|
+
# @param params [Hash] key : value pairs to be passed to the task.
|
157
|
+
# @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.
|
158
|
+
# @return [Object] A result object from the task.The values available are stdout, stderr and result.
|
159
|
+
def run_bolt_task(task_name, params = {}, opts = {})
|
160
|
+
config_data = { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') }
|
161
|
+
target_node_name = ENV['TARGET_HOST'] if target_node_name.nil?
|
162
|
+
inventory_hash = if target_node_name.nil? || target_node_name == 'localhost'
|
163
|
+
nil
|
164
|
+
else
|
165
|
+
inventory_hash_from_inventory_file
|
166
|
+
end
|
167
|
+
|
168
|
+
result = run_task(task_name, target_node_name, params, config: config_data, inventory: inventory_hash)
|
169
|
+
result_obj = {
|
170
|
+
exit_code: 0,
|
171
|
+
stdout: nil,
|
172
|
+
stderr: nil,
|
173
|
+
result: result.first['result'],
|
174
|
+
}
|
175
|
+
|
176
|
+
if result.first['status'] == 'success'
|
177
|
+
# stdout returns unstructured data if structured data is not available
|
178
|
+
result_obj[:stdout] = if result.first['result']['_output'].nil?
|
179
|
+
result.first['result'].to_s
|
180
|
+
else
|
181
|
+
result.first['result']['_output']
|
182
|
+
end
|
183
|
+
|
184
|
+
else
|
185
|
+
raise "task failed\n`#{task_name}`\n======\n#{result}" if opts[:expect_failures] != true
|
186
|
+
|
187
|
+
result_obj[:exit_code] = result.first['result']['_error']['details'].fetch('exitcode', 255)
|
188
|
+
result_obj[:stderr] = result.first['result']['_error']['msg']
|
189
|
+
end
|
190
|
+
|
191
|
+
result = OpenStruct.new(exit_code: result_obj[:exit_code],
|
192
|
+
stdout: result_obj[:stdout],
|
193
|
+
stderr: result_obj[:stderr],
|
194
|
+
result: result_obj[:result])
|
195
|
+
yield result if block_given?
|
196
|
+
result
|
197
|
+
end
|
198
|
+
|
199
|
+
# Runs a script against the target system.
|
200
|
+
#
|
201
|
+
# @param script [String] The path to the script on the source machine
|
202
|
+
# @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.
|
203
|
+
# @param arguments [Array] Array of arguments to pass to script on runtime
|
204
|
+
# @yieldreturn [Block] this method will yield to a block of code passed by the caller; this can be used for additional validation, etc.
|
205
|
+
# @return [Object] A result object from the script run.
|
206
|
+
def bolt_run_script(script, opts = {}, arguments: [])
|
207
|
+
target_node_name = ENV['TARGET_HOST'] if target_node_name.nil?
|
208
|
+
inventory_hash = if target_node_name.nil? || target_node_name == 'localhost'
|
209
|
+
nil
|
210
|
+
else
|
211
|
+
inventory_hash_from_inventory_file
|
212
|
+
end
|
213
|
+
|
214
|
+
result = run_script(script, target_node_name, arguments, options: opts, config: nil, inventory: inventory_hash)
|
215
|
+
|
216
|
+
raise "script run failed\n`#{script}`\n======\n#{result}" if result.first['result']['exit_code'] != 0 && opts[:expect_failures] != true
|
217
|
+
|
218
|
+
result = OpenStruct.new(exit_code: result.first['result']['exit_code'],
|
219
|
+
stdout: result.first['result']['stdout'],
|
220
|
+
stderr: result.first['result']['stderr'])
|
221
|
+
yield result if block_given?
|
222
|
+
result
|
223
|
+
end
|
224
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# version of this gem
|
4
|
-
module PuppetLitmus
|
5
|
-
VERSION ||= '0.
|
6
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# version of this gem
|
4
|
+
module PuppetLitmus
|
5
|
+
VERSION ||= '0.8.0'
|
6
|
+
end
|