puppet_litmus 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 418acded5bb7ca19c9a011892b89b805aaedd642be7e94d004f038640d144c28
4
- data.tar.gz: 20082a2cba1921b73cfb1a0324709253b6f74318916c8c302c8eb917cf7ad2f3
2
+ SHA1:
3
+ metadata.gz: 9caf40c0204bbf7ee96cd7972dc94d1d08fe3789
4
+ data.tar.gz: f08c3e7468e1fc0c17a4ec66dd4df044cb7b21b4
5
5
  SHA512:
6
- metadata.gz: d55ceaa23d4df5e1aed93363f2d3ecd725817064003630728887fb5f10262f079e89e60dc69b86e05f22e560d98f9b9ea1dcf5cad4fc419ad2d56766b538e499
7
- data.tar.gz: d27be055768592ccdbc603b374787a2f4ce555f6c8649bcee071a5beaece65e699bd4cc2b7b22ece8706cb1ecc3ffa26752afd6d61477b9dd443866d20c50e68
6
+ metadata.gz: 630d0081008784dd6d8a0b822a2e69eea7e36c7eafec4263844c70bbed503936f804e2f3cac591d479ae7ccdc7fea7c0b00037a7e7da16063f80d86bdfb37506
7
+ data.tar.gz: 8362adbc00c895e436d1b587a3c4e9f8f66d5b9105fe1fab5d0c2c43a5c84a14db97fa6c9e08d5069a56a3c70ca5de9da57f6b3c9695aaa029b7507690b2a2d3
data/README.md CHANGED
@@ -1,7 +1,14 @@
1
1
  # Litmus
2
2
 
3
+ <div name="logo">
4
+ <img src="resources/litmus-dark-RGB.png"
5
+ style="display: block; margin-left: auto; margin-right: auto;"
6
+ width="50%"
7
+ alt="litmus logo">
8
+ </div>
9
+
3
10
  ## Overview
4
- 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```.
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```.
5
12
 
6
13
  Litmus allows Puppet module developers to:
7
14
  * provision targets to test against,
@@ -20,25 +27,9 @@ All our documentation is currently available in the [Wiki](https://github.com/pu
20
27
  * [Architecture](https://github.com/puppetlabs/puppet_litmus/wiki/Architecture-of-puppet-litmus) with an explanation of what's going on under the hood
21
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).
22
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
23
-
30
+ * [Helper functions](https://github.com/puppetlabs/puppet_litmus/wiki/Helper-Functions-for-Litmus) a guide to the various helper functions within Litmus.
24
31
  ## Known issues
25
32
 
26
- ### PDK and Bolt dependencies infers support on Ruby and Puppet versions
27
-
28
- We are actively working towards the point that where we declare our gem dependencies for PDK and Bolt gems in the puppet_litmus gemspec file [here](https://github.com/puppetlabs/puppet_litmus/blame/master/puppet_litmus.gemspec#L23)
29
-
30
- Bolt has a hard dependency on Puppet 6, and CRI 2.15.1 which is ruby version specific
31
-
32
- PDK depends on CRI 2.10.0 which is ruby version specific
33
-
34
- We have work in progress to create a pathway through this. A fix is up for PDK, which allows CRI 2.15 and 2.10 to be used (here)[https://github.com/puppetlabs/pdk/pull/638]. This also allows the use of multiple ruby versions.
35
-
36
- A PR (here)[https://github.com/puppetlabs/puppetlabs-motd/pull/200] shows what needs to happen within a module, to use litmus for puppet 5 unit tests, and puppet 6 unit tests. Also for running acceptance tests against puppet 5 and puppet 6 with litmus.
37
-
38
- (Gem changes for a module)[https://github.com/puppetlabs/puppetlabs-motd/blob/29d8c9b0ceceb4b0114a66077ce0f473a49481a5/Gemfile#L34-L39] it only installs litmus if your are running puppet 6 and system tests. Also to use a version of the pdk that has the CRI fixes. You can still test against puppet 5 targets in acceptance tests. IF you want to run unit tests against the puppet 5 gem you will have to run something like (this)[https://github.com/puppetlabs/puppetlabs-motd/blob/29d8c9b0ceceb4b0114a66077ce0f473a49481a5/.travis.yml#L107]
39
-
40
- Thank you for your patience.
41
-
42
33
  ## Other Resources
43
34
 
44
35
  * [Is it Worth the Time?](https://xkcd.com/1205/)
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ # helper functions for manipulating and reading a bolt inventory file
4
+ module PuppetLitmus::InventoryManipulation
5
+ def inventory_hash_from_inventory_file(inventory_full_path = nil)
6
+ inventory_full_path = if inventory_full_path.nil?
7
+ 'inventory.yaml'
8
+ else
9
+ inventory_full_path
10
+ end
11
+ raise "There is no inventory file at '#{inventory_full_path}'" unless File.exist?(inventory_full_path)
12
+
13
+ inventory_hash = YAML.load_file(inventory_full_path)
14
+ inventory_hash
15
+ end
16
+
17
+ def find_targets(inventory_hash, targets)
18
+ if targets.nil?
19
+ inventory = Bolt::Inventory.new(inventory_hash, nil)
20
+ targets = inventory.node_names.to_a
21
+ else
22
+ targets = [targets]
23
+ end
24
+ targets
25
+ end
26
+
27
+ def target_in_group(inventory_hash, node_name, group_name)
28
+ exists = false
29
+ inventory_hash['groups'].each do |group|
30
+ next unless group['name'] == group_name
31
+
32
+ group['nodes'].each do |node|
33
+ exists = true if node['name'] == node_name
34
+ end
35
+ end
36
+ exists
37
+ end
38
+
39
+ def config_from_node(inventory_hash, node_name)
40
+ inventory_hash['groups'].each do |group|
41
+ group['nodes'].each do |node|
42
+ if node['name'] == node_name
43
+ return node['config']
44
+ end
45
+ end
46
+ end
47
+ raise "No config was found for #{node_name}"
48
+ end
49
+
50
+ def facts_from_node(inventory_hash, node_name)
51
+ inventory_hash['groups'].each do |group|
52
+ group['nodes'].each do |node|
53
+ if node['name'] == node_name
54
+ return node['facts']
55
+ end
56
+ end
57
+ end
58
+ raise "No config was found for #{node_name}"
59
+ end
60
+
61
+ def add_node_to_group(inventory_hash, node_name, group_name)
62
+ inventory_hash['groups'].each do |group|
63
+ if group['name'] == group_name
64
+ group['nodes'].push node_name
65
+ end
66
+ end
67
+ inventory_hash
68
+ end
69
+
70
+ def remove_node(inventory_hash, node_name)
71
+ inventory_hash['groups'].each do |group|
72
+ group['nodes'].delete_if { |i| i['name'] == node_name }
73
+ end
74
+ inventory_hash
75
+ end
76
+ end
@@ -66,7 +66,7 @@ namespace :litmus do
66
66
  metadata = JSON.parse(File.read('metadata.json'))
67
67
  get_metadata_operating_systems(metadata) do |os_and_version|
68
68
  puts os_and_version
69
- include PuppetLitmus
69
+ include BoltSpec::Run
70
70
  Rake::Task['spec_prep'].invoke
71
71
  config_data = { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') }
72
72
  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'))
@@ -87,15 +87,25 @@ namespace :litmus do
87
87
  task :provision_list, [:key] do |_task, args|
88
88
  provision_hash = YAML.load_file('./provision.yaml')
89
89
  provisioner = provision_hash[args[:key]]['provisioner']
90
+ failed_image_message = ''
90
91
  provision_hash[args[:key]]['images'].each do |image|
92
+ # this is the only way to capture the stdout from the rake task, it will affect pry
93
+ capture_rake_output = StringIO.new
94
+ $stdout = capture_rake_output
91
95
  Rake::Task['litmus:provision'].invoke(provisioner, image)
96
+ if $stdout.string =~ %r{.status.=>.failure}
97
+ failed_image_message += "=====\n#{image}\n#{$stdout.string}\n"
98
+ else
99
+ STDOUT.puts $stdout.string
100
+ end
92
101
  Rake::Task['litmus:provision'].reenable
93
102
  end
103
+ raise "Failed to provision with '#{provisioner}'\n #{failed_image_message}" unless failed_image_message.empty?
94
104
  end
95
105
 
96
106
  desc "provision container/VM - abs/docker/vmpooler eg 'bundle exec rake 'litmus:provision[vmpooler, ubuntu-1604-x86_64]'"
97
107
  task :provision, [:provisioner, :platform] do |_task, args|
98
- include PuppetLitmus
108
+ include BoltSpec::Run
99
109
  Rake::Task['spec_prep'].invoke
100
110
  config_data = { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') }
101
111
  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'))
@@ -197,6 +207,7 @@ namespace :litmus do
197
207
 
198
208
  desc 'tear-down - decommission machines'
199
209
  task :tear_down, [:target] do |_task, args|
210
+ include BoltSpec::Run
200
211
  Rake::Task['spec_prep'].invoke
201
212
  config_data = { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') }
202
213
  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'))
@@ -226,7 +237,7 @@ namespace :litmus do
226
237
  end
227
238
 
228
239
  namespace :acceptance do
229
- include PuppetLitmus
240
+ include PuppetLitmus::InventoryManipulation
230
241
  if File.file?('inventory.yaml')
231
242
  inventory_hash = inventory_hash_from_inventory_file
232
243
  hosts = find_targets(inventory_hash, nil)
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ # helper functions for running puppet commands, and helpers
4
+ module PuppetLitmus::Serverspec
5
+ def idempotent_apply(manifest)
6
+ manifest_file_location = create_manifest_file(manifest)
7
+ apply_manifest(nil, catch_failures: true, manifest_file_location: manifest_file_location)
8
+ apply_manifest(nil, catch_changes: true, manifest_file_location: manifest_file_location)
9
+ end
10
+
11
+ def apply_manifest(manifest, opts = {})
12
+ target_node_name = ENV['TARGET_HOST']
13
+ raise 'manifest and manifest_file_location in the opts hash are mutually exclusive arguments, pick one' if !manifest.nil? && !opts[:manifest_file_location].nil?
14
+ raise 'please pass a manifest or the manifest_file_location in the opts hash' if (manifest.nil? || manifest == '') && opts[:manifest_file_location].nil?
15
+
16
+ manifest_file_location = opts[:manifest_file_location] || create_manifest_file(manifest)
17
+ inventory_hash = if target_node_name.nil? || target_node_name == 'localhost'
18
+ nil
19
+ else
20
+ inventory_hash_from_inventory_file
21
+ end
22
+ command_to_run = "puppet apply #{manifest_file_location}"
23
+ command_to_run += " --modulepath #{Dir.pwd}/spec/fixtures/modules" if target_node_name.nil? || target_node_name == 'localhost'
24
+ command_to_run += ' --detailed-exitcodes' if !opts[:catch_changes].nil? && (opts[:catch_changes] == true)
25
+ # BOLT-608
26
+ if Gem.win_platform?
27
+ stdout, stderr, status = Open3.capture3(command_to_run)
28
+ status_text = if status.to_i.zero?
29
+ 'success'
30
+ else
31
+ 'failure'
32
+ end
33
+ result = [{ 'node' => 'localhost', 'status' => status_text, 'result' => { 'exit_code' => status.to_i, 'stderr' => stderr, 'stdout' => stdout } }]
34
+ else
35
+ result = run_command(command_to_run, target_node_name, config: nil, inventory: inventory_hash)
36
+ end
37
+
38
+ raise "apply mainfest failed\n`#{command_to_run}`\n======\n#{result}" if result.first['result']['exit_code'] != 0 && opts[:expect_failures] != true
39
+
40
+ result.first
41
+ end
42
+
43
+ # creates a temp manifest file locally & remote depending on target
44
+ def create_manifest_file(manifest)
45
+ target_node_name = ENV['TARGET_HOST']
46
+ manifest_file = Tempfile.new(['manifest_', '.pp'])
47
+ manifest_file.write(manifest)
48
+ manifest_file.close
49
+ if target_node_name.nil? || target_node_name == 'localhost'
50
+ # no need to transfer
51
+ manifest_file_location = manifest_file.path
52
+ else
53
+ # transfer to TARGET_HOST
54
+ inventory_hash = inventory_hash_from_inventory_file
55
+ manifest_file_location = "/tmp/#{File.basename(manifest_file)}"
56
+ result = upload_file(manifest_file.path, manifest_file_location, target_node_name, options: {}, config: nil, inventory: inventory_hash)
57
+ raise result.first['result'].to_s unless result.first['status'] == 'success'
58
+ end
59
+ manifest_file_location
60
+ end
61
+
62
+ def run_shell(command_to_run, opts = {})
63
+ inventory_hash = inventory_hash_from_inventory_file
64
+ target_node_name = ENV['TARGET_HOST']
65
+ result = run_command(command_to_run, target_node_name, config: nil, inventory: inventory_hash)
66
+
67
+ raise "shell failed\n`#{command_to_run}`\n======\n#{result}" if result.first['result']['exit_code'] != 0 && opts[:expect_failures] != true
68
+
69
+ result
70
+ end
71
+
72
+ # Runs a selected task against the target host. Parameters should be passed in with a hash format.
73
+ def run_bolt_task(task_name, params = {})
74
+ config_data = { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') }
75
+ inventory_hash = inventory_hash_from_inventory_file
76
+ target_node_name = ENV['TARGET_HOST'] if target_node_name.nil?
77
+
78
+ result = run_task(task_name, target_node_name, params, config: config_data, inventory: inventory_hash)
79
+
80
+ raise "task failed\n`#{task_name}`\n======\n#{result}" if result.first['status'] != 'success'
81
+
82
+ result
83
+ end
84
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
  # version of this gem
4
4
  module PuppetLitmus
5
- VERSION ||= '0.0.1'
5
+ VERSION ||= '0.1.0'
6
6
  end
data/lib/puppet_litmus.rb CHANGED
@@ -1,161 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bolt_spec/run'
4
+ require 'puppet_litmus/inventory_manipulation'
5
+ require 'puppet_litmus/serverspec'
4
6
 
5
7
  # Helper methods for testing puppet content
6
8
  module PuppetLitmus
7
9
  include BoltSpec::Run
8
- def apply_manifest(manifest, opts = {})
9
- target_node_name = ENV['TARGET_HOST']
10
- raise 'manifest and manifest_file_location in the opts hash are mutually exclusive arguments, pick one' if !manifest.nil? && !opts[:manifest_file_location].nil?
11
- raise 'please pass a manifest or the manifest_file_location in the opts hash' if (manifest.nil? || manifest == '') && opts[:manifest_file_location].nil?
12
-
13
- manifest_file_location = opts[:manifest_file_location] || create_manifest_file(manifest)
14
- inventory_hash = if target_node_name.nil? || target_node_name == 'localhost'
15
- nil
16
- else
17
- inventory_hash_from_inventory_file
18
- end
19
- command_to_run = "puppet apply #{manifest_file_location}"
20
- command_to_run += " --modulepath #{Dir.pwd}/spec/fixtures/modules" if target_node_name.nil? || target_node_name == 'localhost'
21
- command_to_run += ' --detailed-exitcodes' if !opts[:catch_changes].nil? && (opts[:catch_changes] == true)
22
- # BOLT-608
23
- if Gem.win_platform?
24
- stdout, stderr, status = Open3.capture3(command_to_run)
25
- status_text = if status.to_i.zero?
26
- 'success'
27
- else
28
- 'failure'
29
- end
30
- result = [{ 'node' => 'localhost', 'status' => status_text, 'result' => { 'exit_code' => status.to_i, 'stderr' => stderr, 'stdout' => stdout } }]
31
- else
32
- result = run_command(command_to_run, target_node_name, config: nil, inventory: inventory_hash)
33
- end
34
-
35
- raise "apply mainfest failed\n`#{command_to_run}`\n======\n#{result}" if result.first['result']['exit_code'] != 0 && opts[:expect_failures] != true
36
-
37
- result
38
- end
39
-
40
- # creates a temp manifest file locally & remote depending on target
41
- def create_manifest_file(manifest)
42
- target_node_name = ENV['TARGET_HOST']
43
- manifest_file = Tempfile.new(['manifest_', '.pp'])
44
- manifest_file.write(manifest)
45
- manifest_file.close
46
- if target_node_name.nil? || target_node_name == 'localhost'
47
- # no need to transfer
48
- manifest_file_location = manifest_file.path
49
- else
50
- # transfer to TARGET_HOST
51
- command = "bundle exec bolt file upload #{manifest_file.path} /tmp/#{File.basename(manifest_file)} --nodes #{target_node_name} --inventoryfile inventory.yaml"
52
- stdout, stderr, status = Open3.capture3(command)
53
- error_message = "Attempted to run\ncommand:'#{command}'\nstdout:#{stdout}\nstderr:#{stderr}"
54
- raise error_message unless status.to_i.zero?
55
-
56
- manifest_file_location = "/tmp/#{File.basename(manifest_file)}"
57
- end
58
- manifest_file_location
59
- end
60
-
61
- def apply_manifest_and_idempotent(manifest)
62
- manifest_file_location = create_manifest_file(manifest)
63
- apply_manifest(nil, catch_failures: true, manifest_file_location: manifest_file_location)
64
- apply_manifest(nil, catch_changes: true, manifest_file_location: manifest_file_location)
65
- end
66
-
67
- def run_shell(command_to_run, opts = {})
68
- inventory_hash = inventory_hash_from_inventory_file
69
- target_node_name = ENV['TARGET_HOST']
70
- result = run_command(command_to_run, target_node_name, config: nil, inventory: inventory_hash)
71
-
72
- raise "shell failed\n`#{command_to_run}`\n======\n#{result}" if result.first['result']['exit_code'] != 0 && opts[:expect_failures] != true
73
-
74
- result
75
- end
76
-
77
- def inventory_hash_from_inventory_file(inventory_full_path = nil)
78
- inventory_full_path = if inventory_full_path.nil?
79
- 'inventory.yaml'
80
- else
81
- inventory_full_path
82
- end
83
- raise "There is no inventory file at '#{inventory_full_path}'" unless File.exist?(inventory_full_path)
84
-
85
- inventory_hash = YAML.load_file(inventory_full_path)
86
- inventory_hash
87
- end
88
-
89
- def find_targets(inventory_hash, targets)
90
- if targets.nil?
91
- inventory = Bolt::Inventory.new(inventory_hash, nil)
92
- targets = inventory.node_names.to_a
93
- else
94
- targets = [targets]
95
- end
96
- targets
97
- end
98
-
99
- def target_in_group(inventory_hash, node_name, group_name)
100
- exists = false
101
- inventory_hash['groups'].each do |group|
102
- next unless group['name'] == group_name
103
-
104
- group['nodes'].each do |node|
105
- exists = true if node['name'] == node_name
106
- end
107
- end
108
- exists
109
- end
110
-
111
- def config_from_node(inventory_hash, node_name)
112
- inventory_hash['groups'].each do |group|
113
- group['nodes'].each do |node|
114
- if node['name'] == node_name
115
- return node['config']
116
- end
117
- end
118
- end
119
- raise "No config was found for #{node_name}"
120
- end
121
-
122
- def facts_from_node(inventory_hash, node_name)
123
- inventory_hash['groups'].each do |group|
124
- group['nodes'].each do |node|
125
- if node['name'] == node_name
126
- return node['facts']
127
- end
128
- end
129
- end
130
- raise "No config was found for #{node_name}"
131
- end
132
-
133
- def add_node_to_group(inventory_hash, node_name, group_name)
134
- inventory_hash['groups'].each do |group|
135
- if group['name'] == group_name
136
- group['nodes'].push node_name
137
- end
138
- end
139
- inventory_hash
140
- end
141
-
142
- def remove_node(inventory_hash, node_name)
143
- inventory_hash['groups'].each do |group|
144
- group['nodes'].delete_if { |i| i['name'] == node_name }
145
- end
146
- inventory_hash
147
- end
148
-
149
- # Runs a selected task against the target host. Parameters should be passed in with a hash format.
150
- def task_run(task_name, params)
151
- config_data = { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') }
152
- inventory_hash = inventory_hash_from_inventory_file
153
- target_node_name = ENV['TARGET_HOST'] if target_node_name.nil?
154
-
155
- result = run_task(task_name, target_node_name, params, config: config_data, inventory: inventory_hash)
156
-
157
- raise "task failed\n`#{task_name}`\n======\n#{result}" if result.first['status'] != 'success'
158
-
159
- result
160
- end
10
+ include PuppetLitmus::InventoryManipulation
11
+ include PuppetLitmus::Serverspec
161
12
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe PuppetLitmus do
6
+ it 'has a version number' do
7
+ expect(described_class::VERSION).not_to be nil
8
+ expect(described_class::VERSION).to be_a_kind_of(String)
9
+ end
10
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec'
4
+ require 'puppet_litmus'
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.0.1
4
+ version: 0.1.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-04-03 00:00:00.000000000 Z
11
+ date: 2019-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bolt
@@ -61,8 +61,12 @@ files:
61
61
  - LICENSE
62
62
  - README.md
63
63
  - lib/puppet_litmus.rb
64
+ - lib/puppet_litmus/inventory_manipulation.rb
64
65
  - lib/puppet_litmus/rake_tasks.rb
66
+ - lib/puppet_litmus/serverspec.rb
65
67
  - lib/puppet_litmus/version.rb
68
+ - spec/lib/puppet_litmus_spec.rb
69
+ - spec/spec_helper.rb
66
70
  homepage: https://github.com/puppetlabs/puppet_litmus
67
71
  licenses:
68
72
  - Apache-2.0
@@ -83,9 +87,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
87
  version: '0'
84
88
  requirements: []
85
89
  rubyforge_project:
86
- rubygems_version: 2.7.6
90
+ rubygems_version: 2.6.14.1
87
91
  signing_key:
88
92
  specification_version: 4
89
93
  summary: Providing a simple command line tool for puppet content creators, to enable
90
94
  simple and complex test deployments.
91
- test_files: []
95
+ test_files:
96
+ - spec/spec_helper.rb
97
+ - spec/lib/puppet_litmus_spec.rb