puppet_litmus 0.15.0 → 0.18.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5910db3eed130389c917cfb64116897400905e1d66851f57e16be04d1070b95a
4
- data.tar.gz: 01066623755c8b944f4362c0829fd46e3aaa13866a206fe17c74a19da3ed8143
3
+ metadata.gz: c9148f5cf259702d6b12f875555b4cbef8fdbc4ff78081e495ca1b9b8948d082
4
+ data.tar.gz: 3b002919bfff6ce6cb794ed9bd3d8b6b5712ba76d1cceceba1c8d205488f9057
5
5
  SHA512:
6
- metadata.gz: 4ce37bbfc92942ee4a50c4cc0831ccd8deac29ec092001c1c82dc3b7a8c57cd1bdb745bb64e224fc0fbc220c458b990b4ea429908a6548a7d18195a63873b3d3
7
- data.tar.gz: 49b0a06fdf5772a2ed5104108cc4163b96b6eb500f1bf70259052099ab9231ee7d6b7c56bdfdc3af2708229600eda0c9bd41fb53cf5438db8c5f17309e24728a
6
+ metadata.gz: 458f9935cf9148d839f0a2ac3cb3851a85ef18df7a7e99a0b216adafb9d33999a1d672da95f5450c1b371794cd6ecf7d92131778d79cdb47ea0cd0788e1901c4
7
+ data.tar.gz: 4c1c40a1b40865ff788af2f52c6766a5f5d159674ce3f62173da91713dd96f5e1e78f1fb41234e5a7d82aa89c1cb1b2f35a29c841bf2e3307719506c4a130793
data/README.md CHANGED
@@ -8,27 +8,23 @@
8
8
  </div>
9
9
 
10
10
  ## Overview
11
- Litmus provides a simple command line tool for Puppet content creators, to enable both simple and complex test deployments against specifically configured target systems. It is available as a gem, and can be installed by running ```gem install puppet_litmus```.
12
11
 
13
- Litmus allows Puppet module developers to:
14
- * provision targets to test against,
15
- * install the Puppet Agent,
16
- * install a module,
17
- * run tests, and
18
- * tear down the infrastructure.
12
+ Litmus is a command line tool that allows you to run acceptance tests against Puppet modules.
19
13
 
20
- The tool facilitates parallel test runs, running tests in isolation, and each step is standalone, allowing other operations between test runs, such as debugging, or configuration updates on the test targets.
14
+ Litmus allows you to:
15
+ * Provision targets to test against
16
+ * Install a Puppet agent
17
+ * Install a module
18
+ * Run tests
19
+ * Tear down the infrastructure
21
20
 
22
- ## Documentation
21
+ Litmus also facilitates parallel test runs and running tests in isolation. Each step is standalone, allowing other operations between test runs, such as debugging or configuration updates on the test targets.
22
+
23
+ Install Litmus as a gem by running ```gem install puppet_litmus```.
23
24
 
24
- All our documentation is currently available in the [Wiki](https://github.com/puppetlabs/puppet_litmus/wiki).
25
+ ## Documentation
25
26
 
26
- * [Overview](https://github.com/puppetlabs/puppet_litmus/wiki/Overview-of-Litmus) of the main functions
27
- * [Architecture](https://github.com/puppetlabs/puppet_litmus/wiki/Architecture-of-puppet-litmus) with an explanation of what's going on under the hood
28
- * [Step-by-step guide](https://github.com/puppetlabs/puppet_litmus/wiki/Tutorial:-use-Litmus-to-execute-acceptance-tests-with-a-sample-module-(MoTD)) of how to use Litmus with the popular and simple [MoTD Puppet module](https://forge.puppet.com/puppetlabs/motd).
29
- * [How to guide](https://github.com/puppetlabs/puppet_litmus/wiki/Converting-a-module-to-use-Litmus) walking through how to use Litmus in a module
30
- * [Helper functions](https://github.com/puppetlabs/puppet_litmus/wiki/Helper-Functions-for-Litmus) a guide to the various helper functions within Litmus.
31
- ## Known issues
27
+ For documentation, see our [Litmus Wiki](https://github.com/puppetlabs/puppet_litmus/wiki).
32
28
 
33
29
  ## Other Resources
34
30
 
@@ -8,7 +8,6 @@ require 'puppet_litmus/inventory_manipulation'
8
8
  require 'puppet_litmus/puppet_helpers'
9
9
  require 'puppet_litmus/rake_helper'
10
10
  require 'puppet_litmus/spec_helper_acceptance'
11
- require 'honeycomb-beeline'
12
11
 
13
12
  # Helper methods for testing puppet content
14
13
  module PuppetLitmus
@@ -16,23 +15,4 @@ module PuppetLitmus
16
15
  include PuppetLitmus::InventoryManipulation
17
16
  include PuppetLitmus::PuppetHelpers
18
17
  include PuppetLitmus::RakeHelper
19
- Honeycomb.configure do |config|
20
- end
21
- process_span = Honeycomb.start_span(name: 'Litmus Testing')
22
- if ENV['CI'] == 'true' && ENV['TRAVIS'] == 'true'
23
- process_span.add_field('module_name', ENV['TRAVIS_REPO_SLUG'])
24
- process_span.add_field('travis_build_id', ENV['TRAVIS_BUILD_ID'])
25
- process_span.add_field('travis_build_web_url', ENV['TRAVIS_BUILD_WEB_URL'])
26
- process_span.add_field('travis_commit_message', ENV['TRAVIS_COMMIT_MESSAGE'])
27
- process_span.add_field('travis_pull_request_sha', ENV['TRAVIS_PULL_REQUEST_SHA'])
28
- elsif ENV['CI'] == 'True' && ENV['APPVEYOR'] == 'True'
29
- process_span.add_field('module_name', ENV['APPVEYOR_PROJECT_SLUG'])
30
- process_span.add_field('appveyor_build_id', ENV['APPVEYOR_BUILD_ID'])
31
- process_span.add_field('appveyor_url', "https://ci.appveyor.com/project/#{ENV['APPVEYOR_REPO_NAME']}/builds/#{ENV['APPVEYOR_BUILD_ID']}")
32
- process_span.add_field('appveyor_repo_commit_message', ENV['APPVEYOR_REPO_COMMIT_MESSAGE'])
33
- process_span.add_field('appveyor_pull_request_head_commit', ENV['APPVEYOR_PULL_REQUEST_HEAD_COMMIT'])
34
- end
35
- at_exit do
36
- process_span.send
37
- end
38
18
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ module PuppetLitmus; end # rubocop:disable Style/Documentation
4
+
3
5
  # helper functions for manipulating and reading a bolt inventory file
4
6
  module PuppetLitmus::InventoryManipulation
5
7
  # Creates an inventory hash from the inventory.yaml.
@@ -233,7 +235,7 @@ module PuppetLitmus::InventoryManipulation
233
235
  #
234
236
  # @param inventory_hash [Hash] hash of the inventory.yaml file
235
237
  # @param feature_name [String] feature to locate in the node
236
- # node_name [String] node of nodes to limit the search for the node_name in
238
+ # @param node_name [String] node of nodes to limit the search for the node_name in
237
239
  # @return inventory.yaml file with feature removed from the node.
238
240
  # @return [Hash] inventory_hash with feature added to node if node_name exists in inventory hash.
239
241
  def remove_feature_from_node(inventory_hash, feature_name, node_name)
@@ -255,4 +257,13 @@ module PuppetLitmus::InventoryManipulation
255
257
  def write_to_inventory_file(inventory_hash, inventory_full_path)
256
258
  File.open(inventory_full_path, 'wb+') { |f| f.write(inventory_hash.to_yaml) }
257
259
  end
260
+
261
+ # Add the `litmus.platform` with platform information for the target
262
+ #
263
+ # @param inventory_hash [Hash] hash of the inventory.yaml file
264
+ # @param node_name [String] node of nodes to limit the search for the node_name in
265
+ def add_platform_field(inventory_hash, node_name)
266
+ facts = facts_from_node(inventory_hash, node_name)
267
+ Honeycomb.current_span.add_field('litmus.platform', facts&.dig('platform'))
268
+ end
258
269
  end
@@ -8,87 +8,107 @@ module PuppetLitmus::PuppetHelpers
8
8
  # @param manifest [String] puppet manifest code to be applied.
9
9
  # @return [Boolean] The result of the 2 apply manifests.
10
10
  def idempotent_apply(manifest)
11
- manifest_file_location = create_manifest_file(manifest)
12
- apply_manifest(nil, expect_failures: false, manifest_file_location: manifest_file_location)
13
- apply_manifest(nil, catch_changes: true, manifest_file_location: manifest_file_location)
11
+ Honeycomb.start_span(name: 'litmus.idempotent_apply') do |span|
12
+ ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header unless ENV['HTTP_X_HONEYCOMB_TRACE']
13
+ manifest_file_location = create_manifest_file(manifest)
14
+ apply_manifest(nil, expect_failures: false, manifest_file_location: manifest_file_location)
15
+ apply_manifest(nil, catch_changes: true, manifest_file_location: manifest_file_location)
16
+ end
14
17
  end
15
18
 
16
- # rubocop:disable Layout/TrailingWhitespace
17
-
18
19
  # Applies a manifest. returning the result of that apply. Mimics the apply_manifest from beaker
19
- #
20
+ #
20
21
  # When you set the environment variable RSPEC_DEBUG, the output of your
21
22
  # puppet run will be displayed. If you have set the :debug flag, you will see the
22
23
  # full debug log. If you have **not** set the :debug flag, it will display the regular
23
24
  # output.
24
25
  #
25
26
  # @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] (false) We're after idempotency so allow exit code 0 only.
28
- # :expect_changes [Boolean] (false) We're after changes specifically so allow exit code 2 only.
29
- # :catch_failures [Boolean] (false) We're after only complete success so allow exit codes 0 and 2 only.
30
- # :expect_failures [Boolean] (false) We're after failures specifically so allow exit codes 1, 4, and 6 only.
31
- # :manifest_file_location [Path] The place on the target system.
27
+ # @param opts [Hash] Alters the behaviour of the command. Valid options are:
28
+ # :catch_changes [Boolean] (false) We're after idempotency so allow exit code 0 only.
29
+ # :expect_changes [Boolean] (false) We're after changes specifically so allow exit code 2 only.
30
+ # :catch_failures [Boolean] (false) We're after only complete success so allow exit codes 0 and 2 only.
31
+ # :expect_failures [Boolean] (false) We're after failures specifically so allow exit codes 1, 4, and 6 only.
32
+ # :manifest_file_location [Path] The place on the target system.
32
33
  # :hiera_config [Path] The path to the hiera.yaml configuration on the runner.
33
- # :prefix_command [String] prefixes the puppet apply command; eg "export LANGUAGE='ja'".
34
- # :debug [Boolean] run puppet apply with the debug flag.
35
- # :noop [Boolean] run puppet apply with the noop flag.
34
+ # :prefix_command [String] prefixes the puppet apply command; eg "export LANGUAGE='ja'".
35
+ # :trace [Boolean] run puppet apply with the trace flag (defaults to `true`).
36
+ # :debug [Boolean] run puppet apply with the debug flag.
37
+ # :noop [Boolean] run puppet apply with the noop flag.
36
38
  # @yieldreturn [Block] this method will yield to a block of code passed by the caller; this can be used for additional validation, etc.
37
39
  # @return [Object] A result object from the apply.
38
40
  def apply_manifest(manifest, opts = {})
39
- # rubocop:enable Layout/TrailingWhitespace
40
- target_node_name = targeting_localhost? ? 'litmus_localhost' : ENV['TARGET_HOST']
41
- raise 'manifest and manifest_file_location in the opts hash are mutually exclusive arguments, pick one' if !manifest.nil? && !opts[:manifest_file_location].nil?
42
- raise 'please pass a manifest or the manifest_file_location in the opts hash' if (manifest.nil? || manifest == '') && opts[:manifest_file_location].nil?
43
- raise 'please specify only one of `catch_changes`, `expect_changes`, `catch_failures` or `expect_failures`' if
44
- [opts[:catch_changes], opts[:expect_changes], opts[:catch_failures], opts[:expect_failures]].compact.length > 1
45
-
46
- if opts[:catch_changes]
47
- use_detailed_exit_codes = true
48
- acceptable_exit_codes = [0]
49
- elsif opts[:catch_failures]
50
- use_detailed_exit_codes = true
51
- acceptable_exit_codes = [0, 2]
52
- elsif opts[:expect_failures]
53
- use_detailed_exit_codes = true
54
- acceptable_exit_codes = [1, 4, 6]
55
- elsif opts[:expect_changes]
56
- use_detailed_exit_codes = true
57
- acceptable_exit_codes = [2]
58
- else
59
- use_detailed_exit_codes = false
60
- acceptable_exit_codes = [0]
61
- end
41
+ Honeycomb.start_span(name: 'litmus.apply_manifest') do |span|
42
+ ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header unless ENV['HTTP_X_HONEYCOMB_TRACE']
43
+ span.add_field('litmus.manifest', manifest)
44
+ span.add_field('litmus.opts', opts)
62
45
 
63
- manifest_file_location = opts[:manifest_file_location] || create_manifest_file(manifest)
64
- inventory_hash = File.exist?('inventory.yaml') ? inventory_hash_from_inventory_file : localhost_inventory_hash
65
- raise "Target '#{target_node_name}' not found in inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
66
-
67
- command_to_run = "#{opts[:prefix_command]} puppet apply #{manifest_file_location}"
68
- command_to_run += " --modulepath #{Dir.pwd}/spec/fixtures/modules" if target_node_name == 'litmus_localhost'
69
- command_to_run += " --hiera_config='#{opts[:hiera_config]}'" unless opts[:hiera_config].nil?
70
- command_to_run += ' --debug' if !opts[:debug].nil? && (opts[:debug] == true)
71
- command_to_run += ' --noop' if !opts[:noop].nil? && (opts[:noop] == true)
72
- command_to_run += ' --detailed-exitcodes' if use_detailed_exit_codes == true
73
-
74
- result = run_command(command_to_run, target_node_name, config: nil, inventory: inventory_hash)
75
- status = result.first['result']['exit_code']
76
- if opts[:catch_changes] && !acceptable_exit_codes.include?(status)
77
- report_puppet_apply_change(command_to_run, result)
78
- elsif !acceptable_exit_codes.include?(status)
79
- report_puppet_apply_error(command_to_run, result, acceptable_exit_codes)
80
- end
46
+ target_node_name = targeting_localhost? ? 'litmus_localhost' : ENV['TARGET_HOST']
47
+ raise 'manifest and manifest_file_location in the opts hash are mutually exclusive arguments, pick one' if !manifest.nil? && !opts[:manifest_file_location].nil?
48
+ raise 'please pass a manifest or the manifest_file_location in the opts hash' if (manifest.nil? || manifest == '') && opts[:manifest_file_location].nil?
49
+ raise 'please specify only one of `catch_changes`, `expect_changes`, `catch_failures` or `expect_failures`' if
50
+ [opts[:catch_changes], opts[:expect_changes], opts[:catch_failures], opts[:expect_failures]].compact.length > 1
51
+
52
+ opts = { trace: true }.merge(opts)
53
+
54
+ if opts[:catch_changes]
55
+ use_detailed_exit_codes = true
56
+ acceptable_exit_codes = [0]
57
+ elsif opts[:catch_failures]
58
+ use_detailed_exit_codes = true
59
+ acceptable_exit_codes = [0, 2]
60
+ elsif opts[:expect_failures]
61
+ use_detailed_exit_codes = true
62
+ acceptable_exit_codes = [1, 4, 6]
63
+ elsif opts[:expect_changes]
64
+ use_detailed_exit_codes = true
65
+ acceptable_exit_codes = [2]
66
+ else
67
+ use_detailed_exit_codes = false
68
+ acceptable_exit_codes = [0]
69
+ end
81
70
 
82
- result = OpenStruct.new(exit_code: result.first['result']['exit_code'],
83
- stdout: result.first['result']['stdout'],
84
- stderr: result.first['result']['stderr'])
85
- yield result if block_given?
86
- if ENV['RSPEC_DEBUG']
87
- puts "apply manifest succeded\n #{command_to_run}\n======\nwith status #{result.exit_code}"
88
- puts result.stderr
89
- puts result.stdout
71
+ manifest_file_location = opts[:manifest_file_location] || create_manifest_file(manifest)
72
+ inventory_hash = File.exist?('inventory.yaml') ? inventory_hash_from_inventory_file : localhost_inventory_hash
73
+ raise "Target '#{target_node_name}' not found in inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
74
+
75
+ span.add_field('litmus.node_name', target_node_name)
76
+ add_platform_field(inventory_hash, target_node_name)
77
+
78
+ command_to_run = "#{opts[:prefix_command]} puppet apply #{manifest_file_location}"
79
+ command_to_run += ' --trace' if !opts[:trace].nil? && (opts[:trace] == true)
80
+ command_to_run += " --modulepath #{Dir.pwd}/spec/fixtures/modules" if target_node_name == 'litmus_localhost'
81
+ command_to_run += " --hiera_config='#{opts[:hiera_config]}'" unless opts[:hiera_config].nil?
82
+ command_to_run += ' --debug' if !opts[:debug].nil? && (opts[:debug] == true)
83
+ command_to_run += ' --noop' if !opts[:noop].nil? && (opts[:noop] == true)
84
+ command_to_run += ' --detailed-exitcodes' if use_detailed_exit_codes == true
85
+
86
+ span.add_field('litmus.command_to_run', command_to_run)
87
+ span.add_field('litmus.target_node_name', target_node_name)
88
+ bolt_result = run_command(command_to_run, target_node_name, config: nil, inventory: inventory_hash)
89
+ span.add_field('litmus.bolt_result', bolt_result)
90
+
91
+ result = OpenStruct.new(exit_code: bolt_result.first['value']['exit_code'],
92
+ stdout: bolt_result.first['value']['stdout'],
93
+ stderr: bolt_result.first['value']['stderr'])
94
+ span.add_field('litmus.result', result.to_h)
95
+
96
+ status = result.exit_code
97
+ if opts[:catch_changes] && !acceptable_exit_codes.include?(status)
98
+ report_puppet_apply_change(command_to_run, bolt_result)
99
+ elsif !acceptable_exit_codes.include?(status)
100
+ report_puppet_apply_error(command_to_run, bolt_result, acceptable_exit_codes)
101
+ end
102
+
103
+ yield result if block_given?
104
+
105
+ if ENV['RSPEC_DEBUG']
106
+ puts "apply manifest succeded\n #{command_to_run}\n======\nwith status #{result.exit_code}"
107
+ puts result.stderr
108
+ puts result.stdout
109
+ end
110
+ result
90
111
  end
91
- result
92
112
  end
93
113
 
94
114
  # Creates a manifest file locally in a temp location, if its a remote target copy it to there.
@@ -96,23 +116,35 @@ module PuppetLitmus::PuppetHelpers
96
116
  # @param manifest [String] puppet manifest code.
97
117
  # @return [String] The path to the location of the manifest.
98
118
  def create_manifest_file(manifest)
99
- require 'tmpdir'
100
- target_node_name = ENV['TARGET_HOST']
101
- tmp_filename = File.join(Dir.tmpdir, "manifest_#{Time.now.strftime('%Y%m%d')}_#{Process.pid}_#{rand(0x100000000).to_s(36)}.pp")
102
- manifest_file = File.open(tmp_filename, 'w')
103
- manifest_file.write(manifest)
104
- manifest_file.close
105
- if target_node_name.nil? || target_node_name == 'localhost'
106
- # no need to transfer
107
- manifest_file_location = manifest_file.path
108
- else
109
- # transfer to TARGET_HOST
110
- inventory_hash = inventory_hash_from_inventory_file
111
- manifest_file_location = "/tmp/#{File.basename(manifest_file)}"
112
- result = upload_file(manifest_file.path, manifest_file_location, target_node_name, options: {}, config: nil, inventory: inventory_hash)
113
- raise result.first['result'].to_s unless result.first['status'] == 'success'
119
+ Honeycomb.start_span(name: 'litmus.create_manifest_file') do |span|
120
+ ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header unless ENV['HTTP_X_HONEYCOMB_TRACE']
121
+ span.add_field('litmus.manifest', manifest)
122
+
123
+ require 'tmpdir'
124
+ target_node_name = ENV['TARGET_HOST']
125
+ tmp_filename = File.join(Dir.tmpdir, "manifest_#{Time.now.strftime('%Y%m%d')}_#{Process.pid}_#{rand(0x100000000).to_s(36)}.pp")
126
+ manifest_file = File.open(tmp_filename, 'w')
127
+ manifest_file.write(manifest)
128
+ manifest_file.close
129
+ if target_node_name.nil? || target_node_name == 'localhost'
130
+ # no need to transfer
131
+ manifest_file_location = manifest_file.path
132
+ else
133
+ # transfer to TARGET_HOST
134
+ inventory_hash = inventory_hash_from_inventory_file
135
+ span.add_field('litmus.node_name', target_node_name)
136
+ add_platform_field(inventory_hash, target_node_name)
137
+
138
+ manifest_file_location = File.basename(manifest_file)
139
+ bolt_result = upload_file(manifest_file.path, manifest_file_location, target_node_name, options: {}, config: nil, inventory: inventory_hash)
140
+ span.add_field('litmus.bolt_result', bolt_result)
141
+ raise bolt_result.first['value'].to_s unless bolt_result.first['status'] == 'success'
142
+ end
143
+
144
+ span.add_field('litmus.manifest_file_location', manifest_file_location)
145
+
146
+ manifest_file_location
114
147
  end
115
- manifest_file_location
116
148
  end
117
149
 
118
150
  # Runs a command against the target system
@@ -122,23 +154,31 @@ module PuppetLitmus::PuppetHelpers
122
154
  # @yieldreturn [Block] this method will yield to a block of code passed by the caller; this can be used for additional validation, etc.
123
155
  # @return [Object] A result object from the command.
124
156
  def run_shell(command_to_run, opts = {})
125
- Honeycomb.start_span(name: 'litmus_runshell') do |span|
157
+ Honeycomb.start_span(name: 'litmus.run_shell') do |span|
158
+ ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header unless ENV['HTTP_X_HONEYCOMB_TRACE']
159
+ span.add_field('litmus.command_to_run', command_to_run)
160
+ span.add_field('litmus.opts', opts)
161
+
126
162
  target_node_name = targeting_localhost? ? 'litmus_localhost' : ENV['TARGET_HOST']
127
163
  inventory_hash = File.exist?('inventory.yaml') ? inventory_hash_from_inventory_file : localhost_inventory_hash
128
164
  raise "Target '#{target_node_name}' not found in inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
129
165
 
130
- result = run_command(command_to_run, target_node_name, config: nil, inventory: inventory_hash)
131
- if result.first['result']['exit_code'] != 0 && opts[:expect_failures] != true
132
- span.add_field('litmus_runshellfailure', result)
133
- raise "shell failed\n`#{command_to_run}`\n======\n#{result}"
166
+ span.add_field('litmus.node_name', target_node_name)
167
+ add_platform_field(inventory_hash, target_node_name)
168
+
169
+ bolt_result = run_command(command_to_run, target_node_name, config: nil, inventory: inventory_hash)
170
+ span.add_field('litmus.bolt_result', bolt_result)
171
+
172
+ if bolt_result.first['value']['exit_code'] != 0 && opts[:expect_failures] != true
173
+ raise "shell failed\n`#{command_to_run}`\n======\n#{bolt_result}"
134
174
  end
135
175
 
136
- result = OpenStruct.new(exit_code: result.first['result']['exit_code'],
137
- exit_status: result.first['result']['exit_code'],
138
- stdout: result.first['result']['stdout'],
139
- stderr: result.first['result']['stderr'])
176
+ result = OpenStruct.new(exit_code: bolt_result.first['value']['exit_code'],
177
+ exit_status: bolt_result.first['value']['exit_code'],
178
+ stdout: bolt_result.first['value']['stdout'],
179
+ stderr: bolt_result.first['value']['stderr'])
180
+ span.add_field('litmus.result', result.to_h)
140
181
  yield result if block_given?
141
- span.add_field('litmus_runshellsuccess', result)
142
182
  result
143
183
  end
144
184
  end
@@ -151,52 +191,64 @@ module PuppetLitmus::PuppetHelpers
151
191
  # @yieldreturn [Block] this method will yield to a block of code passed by the caller; this can be used for additional validation, etc.
152
192
  # @return [Object] A result object from the command.
153
193
  def bolt_upload_file(source, destination, opts = {}, options = {})
154
- Honeycomb.start_span(name: 'litmus_uploadfile') do |span|
194
+ Honeycomb.start_span(name: 'litmus.bolt_upload_file') do |span|
195
+ ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header unless ENV['HTTP_X_HONEYCOMB_TRACE']
196
+ span.add_field('litmus.source', source)
197
+ span.add_field('litmus.destination', destination)
198
+ span.add_field('litmus.opts', opts)
199
+ span.add_field('litmus.options', options)
200
+
155
201
  target_node_name = targeting_localhost? ? 'litmus_localhost' : ENV['TARGET_HOST']
156
202
  inventory_hash = File.exist?('inventory.yaml') ? inventory_hash_from_inventory_file : localhost_inventory_hash
157
203
  raise "Target '#{target_node_name}' not found in inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
158
204
 
159
- result = upload_file(source, destination, target_node_name, options: options, config: nil, inventory: inventory_hash)
205
+ span.add_field('litmus.node_name', target_node_name)
206
+ add_platform_field(inventory_hash, target_node_name)
207
+
208
+ bolt_result = upload_file(source, destination, target_node_name, options: options, config: nil, inventory: inventory_hash)
209
+ span.add_field('litmus.bolt_result', bolt_result)
160
210
 
161
211
  result_obj = {
162
212
  exit_code: 0,
163
- stdout: result.first['result']['_output'],
213
+ stdout: bolt_result.first['value']['_output'],
164
214
  stderr: nil,
165
- result: result.first['result'],
215
+ result: bolt_result.first['value'],
166
216
  }
167
217
 
168
- if result.first['status'] != 'success'
218
+ if bolt_result.first['status'] != 'success'
169
219
  if opts[:expect_failures] != true
170
- span.add_field('litmus_uploadfilefailure', result)
171
- raise "upload file failed\n======\n#{result}"
220
+ span.add_field('litmus_uploadfilefailure', bolt_result)
221
+ raise "upload file failed\n======\n#{bolt_result}"
172
222
  end
173
223
 
174
224
  result_obj[:exit_code] = 255
175
- result_obj[:stderr] = result.first['result']['_error']['msg']
225
+ result_obj[:stderr] = bolt_result.first['value']['_error']['msg']
176
226
  end
177
227
 
178
228
  result = OpenStruct.new(exit_code: result_obj[:exit_code],
179
229
  stdout: result_obj[:stdout],
180
230
  stderr: result_obj[:stderr])
231
+ span.add_field('litmus.result', result.to_h)
181
232
  yield result if block_given?
182
- span.add_field('litmus_uploadfilesucess', result)
183
233
  result
184
234
  end
185
235
  end
186
236
 
187
- # rubocop:disable Layout/TrailingWhitespace
188
-
189
237
  # Runs a task against the target system.
190
238
  #
191
239
  # @param task_name [String] The name of the task to run.
192
240
  # @param params [Hash] key : value pairs to be passed to the task.
193
- # @param opts [Hash] Alters the behaviour of the command. Valid options are
194
- # :expect_failures [Boolean] doesnt return an exit code of non-zero if the command failed.
241
+ # @param opts [Hash] Alters the behaviour of the command. Valid options are
242
+ # :expect_failures [Boolean] doesnt return an exit code of non-zero if the command failed.
195
243
  # :inventory_file [String] path to the inventory file to use with the task.
196
244
  # @return [Object] A result object from the task.The values available are stdout, stderr and result.
197
- # rubocop:enable Layout/TrailingWhitespace
198
245
  def run_bolt_task(task_name, params = {}, opts = {})
199
- Honeycomb.start_span(name: 'litmus_runtask') do |span|
246
+ Honeycomb.start_span(name: 'litmus.run_task') do |span|
247
+ ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header unless ENV['HTTP_X_HONEYCOMB_TRACE']
248
+ span.add_field('litmus.task_name', task_name)
249
+ span.add_field('litmus.params', params)
250
+ span.add_field('litmus.opts', opts)
251
+
200
252
  config_data = { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') }
201
253
  target_node_name = targeting_localhost? ? 'litmus_localhost' : ENV['TARGET_HOST']
202
254
  inventory_hash = if !opts[:inventory_file].nil? && File.exist?(opts[:inventory_file])
@@ -208,34 +260,37 @@ module PuppetLitmus::PuppetHelpers
208
260
  end
209
261
  raise "Target '#{target_node_name}' not found in inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
210
262
 
211
- result = run_task(task_name, target_node_name, params, config: config_data, inventory: inventory_hash)
263
+ span.add_field('litmus.node_name', target_node_name)
264
+ add_platform_field(inventory_hash, target_node_name)
265
+
266
+ bolt_result = run_task(task_name, target_node_name, params, config: config_data, inventory: inventory_hash)
212
267
  result_obj = {
213
268
  exit_code: 0,
214
269
  stdout: nil,
215
270
  stderr: nil,
216
- result: result.first['result'],
271
+ result: bolt_result.first['value'],
217
272
  }
218
273
 
219
- if result.first['status'] == 'success'
274
+ if bolt_result.first['status'] == 'success'
220
275
  # stdout returns unstructured data if structured data is not available
221
- result_obj[:stdout] = if result.first['result']['_output'].nil?
222
- result.first['result'].to_s
276
+ result_obj[:stdout] = if bolt_result.first['value']['_output'].nil?
277
+ bolt_result.first['value'].to_s
223
278
  else
224
- result.first['result']['_output']
279
+ bolt_result.first['value']['_output']
225
280
  end
226
281
 
227
282
  else
228
283
  if opts[:expect_failures] != true
229
- span.add_field('litmus_runtaskfailure', result)
230
- raise "task failed\n`#{task_name}`\n======\n#{result}"
284
+ span.add_field('litmus_runtaskfailure', bolt_result)
285
+ raise "task failed\n`#{task_name}`\n======\n#{bolt_result}"
231
286
  end
232
287
 
233
- result_obj[:exit_code] = if result.first['result']['_error']['details'].nil?
288
+ result_obj[:exit_code] = if bolt_result.first['value']['_error']['details'].nil?
234
289
  255
235
290
  else
236
- result.first['result']['_error']['details'].fetch('exitcode', 255)
291
+ bolt_result.first['value']['_error']['details'].fetch('exitcode', 255)
237
292
  end
238
- result_obj[:stderr] = result.first['result']['_error']['msg']
293
+ result_obj[:stderr] = bolt_result.first['value']['_error']['msg']
239
294
  end
240
295
 
241
296
  result = OpenStruct.new(exit_code: result_obj[:exit_code],
@@ -243,7 +298,7 @@ module PuppetLitmus::PuppetHelpers
243
298
  stderr: result_obj[:stderr],
244
299
  result: result_obj[:result])
245
300
  yield result if block_given?
246
- span.add_field('litmus_runtasksuccess', result)
301
+ span.add_field('litmus.result', result.to_h)
247
302
  result
248
303
  end
249
304
  end
@@ -256,23 +311,31 @@ module PuppetLitmus::PuppetHelpers
256
311
  # @yieldreturn [Block] this method will yield to a block of code passed by the caller; this can be used for additional validation, etc.
257
312
  # @return [Object] A result object from the script run.
258
313
  def bolt_run_script(script, opts = {}, arguments: [])
259
- Honeycomb.start_span(name: 'litmus_runscript') do |span|
314
+ Honeycomb.start_span(name: 'litmus.bolt_run_script') do |span|
315
+ ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header unless ENV['HTTP_X_HONEYCOMB_TRACE']
316
+ span.add_field('litmus.script', script)
317
+ span.add_field('litmus.opts', opts)
318
+ span.add_field('litmus.arguments', arguments)
319
+
260
320
  target_node_name = targeting_localhost? ? 'litmus_localhost' : ENV['TARGET_HOST']
261
321
  inventory_hash = File.exist?('inventory.yaml') ? inventory_hash_from_inventory_file : localhost_inventory_hash
262
322
  raise "Target '#{target_node_name}' not found in inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
263
323
 
264
- result = run_script(script, target_node_name, arguments, options: opts, config: nil, inventory: inventory_hash)
324
+ span.add_field('litmus.node_name', target_node_name)
325
+ add_platform_field(inventory_hash, target_node_name)
326
+
327
+ bolt_result = run_script(script, target_node_name, arguments, options: opts, config: nil, inventory: inventory_hash)
265
328
 
266
- if result.first['result']['exit_code'] != 0 && opts[:expect_failures] != true
267
- span.add_field('litmus_runscriptfailure', result)
268
- raise "script run failed\n`#{script}`\n======\n#{result}"
329
+ if bolt_result.first['value']['exit_code'] != 0 && opts[:expect_failures] != true
330
+ span.add_field('litmus_runscriptfailure', bolt_result)
331
+ raise "script run failed\n`#{script}`\n======\n#{bolt_result}"
269
332
  end
270
333
 
271
- result = OpenStruct.new(exit_code: result.first['result']['exit_code'],
272
- stdout: result.first['result']['stdout'],
273
- stderr: result.first['result']['stderr'])
334
+ result = OpenStruct.new(exit_code: bolt_result.first['value']['exit_code'],
335
+ stdout: bolt_result.first['value']['stdout'],
336
+ stderr: bolt_result.first['value']['stderr'])
274
337
  yield result if block_given?
275
- span.add_field('litmus_runscriptsuccess', result)
338
+ span.add_field('litmus.result', result.to_h)
276
339
  result
277
340
  end
278
341
  end
@@ -289,14 +352,14 @@ module PuppetLitmus::PuppetHelpers
289
352
  # Report an error in the puppet run
290
353
  #
291
354
  # @param command [String] The puppet command causing the error.
292
- # @param result [Array] The result struct containing the result
293
- def report_puppet_apply_error(command, result, acceptable_exit_codes)
355
+ # @param bolt_result [Array] The result object from bolt
356
+ def report_puppet_apply_error(command, bolt_result, acceptable_exit_codes)
294
357
  puppet_apply_error = <<~ERROR
295
358
  apply manifest failed
296
359
  `#{command}`
297
- with exit code #{result.first['result']['exit_code']} (expected: #{acceptable_exit_codes})
360
+ with exit code #{bolt_result.first['value']['exit_code']} (expected: #{acceptable_exit_codes})
298
361
  ====== Start output of failed Puppet apply ======
299
- #{puppet_output(result)}
362
+ #{puppet_output(bolt_result)}
300
363
  ====== End output of failed Puppet apply ======
301
364
  ERROR
302
365
  raise puppet_apply_error
@@ -305,22 +368,22 @@ module PuppetLitmus::PuppetHelpers
305
368
  # Report an unexpected change in the puppet run
306
369
  #
307
370
  # @param command [String] The puppet command causing the error.
308
- # @param result [Array] The result struct containing the result
309
- def report_puppet_apply_change(command, result)
371
+ # @param bolt_result [Array] The result object from bolt
372
+ def report_puppet_apply_change(command, bolt_result)
310
373
  puppet_apply_changes = <<~ERROR
311
374
  apply manifest expected no changes
312
375
  `#{command}`
313
376
  ====== Start output of Puppet apply with unexpected changes ======
314
- #{puppet_output(result)}
377
+ #{puppet_output(bolt_result)}
315
378
  ====== End output of Puppet apply with unexpected changes ======
316
379
  ERROR
317
380
  raise puppet_apply_changes
318
381
  end
319
382
 
320
383
  # Return the stdout of the puppet run
321
- def puppet_output(result)
322
- result.dig(0, 'result', 'stderr').to_s << \
323
- result.dig(0, 'result', 'stdout').to_s
384
+ def puppet_output(bolt_result)
385
+ bolt_result.dig(0, 'value', 'stderr').to_s << \
386
+ bolt_result.dig(0, 'value', 'stdout').to_s
324
387
  end
325
388
 
326
389
  # Checks a puppet return status and returns true if it both