voxpupuli-acceptance 0.1.1 → 1.0.1

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
2
  SHA256:
3
- metadata.gz: 5703585055ce98b5b167311675cef06877eca43a25d888f24c304f9dd3cc9e48
4
- data.tar.gz: 998637dd8ed80052df9988eba800bd6601fe6b90512b1b29572b1aa8d6546925
3
+ metadata.gz: a4af7213db70ec8ff38b6c3210f221161309ce55aacad5fc2edceda47acad4c8
4
+ data.tar.gz: 9837dce3ad8410384caa6d75d275e2ca8bbbcf706c556cf67c3c19c18314e67e
5
5
  SHA512:
6
- metadata.gz: bc2449b163a0c21a8394242b4ddd6ca920573ebd13b4cad7d2e76a87a379272b8a68ca1f1cab75f53aa2d62335bbccb6b78d1ae5bfaf61eb66e471d14978ab98
7
- data.tar.gz: f7ef10e75b2f31605e8ac942a1c917f0cc86ed080bb6dc0f6d1346013a2e4b05afb64706dc665fc03f4c52bc75f1c038b41bb810f5855a36aefa18e4dbf4e331
6
+ metadata.gz: f3f0acefd724b135d00a073c4587c09467e952e1e147796d50189319639ed5fa4de34afd6f0d7b55e441dbbf575badb9634c539c285492c05ecd791ef376c450
7
+ data.tar.gz: 8b17e3c63d05c963bc37a9d8dac23e105b8d726518f7ffb8898875fc3dff14cce0e861f9170b26aa41901718b0abff45e089230813ca2fd67dfd744664062372
@@ -0,0 +1,21 @@
1
+ shared_examples 'an idempotent resource' do |host|
2
+ host ||= default
3
+
4
+ it 'applies with no errors' do
5
+ apply_manifest_on(host, manifest, catch_failures: true)
6
+ end
7
+
8
+ it 'applies a second time without changes' do
9
+ apply_manifest_on(host, manifest, catch_changes: true)
10
+ end
11
+ end
12
+
13
+ shared_examples 'the example' do |name, host|
14
+ include_examples 'an idempotent resource', host do
15
+ let(:manifest) do
16
+ path = File.join(Dir.pwd, 'examples', name)
17
+ raise Exception, "Example '#{path}' does not exist" unless File.exist?(path)
18
+ File.read(path)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+ module Voxpupuli
2
+ module Acceptance
3
+ class Facts
4
+ ENV_VAR_PREFIX = 'BEAKER_FACTER_'
5
+ FACT_FILE = '/etc/facter/facts.d/voxpupuli-acceptance-env.json'
6
+
7
+ class << self
8
+ def beaker_facts_from_env
9
+ facts = {}
10
+
11
+ ENV.each do |var, value|
12
+ next unless var.start_with?(ENV_VAR_PREFIX)
13
+
14
+ fact = var.sub(ENV_VAR_PREFIX, '').downcase
15
+ facts[fact] = value
16
+ end
17
+
18
+ facts
19
+ end
20
+
21
+ def write_beaker_facts_on(hosts)
22
+ beaker_facts = beaker_facts_from_env
23
+
24
+ if beaker_facts.any?
25
+ require 'json'
26
+ on(hosts, "mkdir -p #{File.dirname(FACT_FILE)} && cat <<VOXPUPULI_BEAKER_ENV_VARS > #{FACT_FILE}\n#{beaker_facts.to_json}\nVOXPUPULI_BEAKER_ENV_VARS")
27
+ else
28
+ on(hosts, "rm -f #{FACT_FILE}")
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,143 @@
1
+ require 'tmpdir'
2
+ require 'puppet/modulebuilder'
3
+
4
+ module Voxpupuli
5
+ module Acceptance
6
+ class Fixtures
7
+ class << self
8
+ # Install fixture modules on the given hosts
9
+ #
10
+ # @param [Host, Array<Host>, String, Symbol] hosts
11
+ # The beaker hosts to run on
12
+ # @param [Array<String>, String] modulepath
13
+ # A modulepath as Puppet uses it. Typically spec/fixtures/modules
14
+ # @param [Logger, nil] logger
15
+ # An optional logger
16
+ def install_fixture_modules_on(hosts, modulepath, logger = nil)
17
+ Dir.mktmpdir do |destination|
18
+ modules = build_modules(modulepath, destination, logger)
19
+
20
+ install_modules_on(hosts, modules, logger)
21
+ end
22
+
23
+ nil
24
+ end
25
+
26
+ # Build modules in the given sources.
27
+ #
28
+ # @param [Array<String>, String] modulepath
29
+ # A modulepath as Puppet uses it
30
+ # @param [String] destination
31
+ # The target directory to build modules into
32
+ # @param [Logger, nil] logger
33
+ # An optional logger
34
+ #
35
+ # @return [Hash<String=>String>]
36
+ # A mapping of module names and the path to their tarball
37
+ def build_modules(modulepath, destination, logger = nil)
38
+ modulepath = [modulepath] if modulepath.is_a?(String)
39
+
40
+ modules = {}
41
+
42
+ modulepath.each do |dir|
43
+ Dir[File.join(dir, '*', 'metadata.json')].each do |metadata|
44
+ path = File.dirname(metadata)
45
+ name = File.basename(path)
46
+ next if modules.include?(name)
47
+
48
+ builder = Puppet::Modulebuilder::Builder.new(File.realpath(path), destination, logger)
49
+
50
+ unless valid_directory_name?(name, builder.metadata['name'])
51
+ warning = "Directory name of #{path} doesn't match metadata name #{builder.metadata['name']}"
52
+ if logger
53
+ logger.warn(warning)
54
+ else
55
+ STDERR.puts(warning)
56
+ end
57
+ end
58
+
59
+ modules[name] = builder.build
60
+ end
61
+ end
62
+
63
+ modules
64
+ end
65
+
66
+ # Install modules on a number of hosts
67
+ #
68
+ # This is done by iterating over every host. On that host a temporary
69
+ # directory is created. Each module is copied there and installed by
70
+ # force.
71
+ #
72
+ # @param [Host, Array<Host>, String, Symbol] hosts
73
+ # The beaker hosts to run on
74
+ # @param [Hash<String=>String>] modules
75
+ # A mapping between module names and their tarball
76
+ # @param [Logger, nil] logger
77
+ # An optional logger
78
+ def install_modules_on(hosts, modules, logger = nil)
79
+ hosts.each do |host|
80
+ logger.debug("Installing modules on #{host}") if logger
81
+
82
+ temp_dir_on(host) do |target_dir|
83
+ modules.each do |name, source_path|
84
+ target_file = File.join(target_dir, File.basename(source_path))
85
+ logger.debug("Copying module #{name} from #{source_path} to #{target_file}") if logger
86
+
87
+ scp_to(host, source_path, target_file)
88
+ on host, puppet("module install --force --ignore-dependencies '#{target_file}'")
89
+ end
90
+ end
91
+ end
92
+
93
+ nil
94
+ end
95
+
96
+ # Create a temporay directory on the host, similar to Dir.mktmpdir but
97
+ # on a remote host.
98
+ #
99
+ # @example
100
+ # temp_dir_on(host) { |dir| puts dir }
101
+ #
102
+ # @param [Host, String, Symbol] host
103
+ # The beaker host to run on
104
+ def temp_dir_on(host, &block)
105
+ result = on host, "mktemp -d"
106
+ raise "Could not create directory" unless result.success?
107
+
108
+ dir = result.stdout.strip
109
+
110
+ begin
111
+ yield dir
112
+ ensure
113
+ on host, "rm -rf #{dir}"
114
+ end
115
+
116
+ nil
117
+ end
118
+
119
+ # Validate a directory name matches its metadata name.
120
+ #
121
+ # This is useful to detect misconfigurations in fixture set ups.
122
+ #
123
+ # @example
124
+ # assert valid_directory_name?('tftp', 'theforeman-tftp')
125
+ # @example
126
+ # refute valid_directory_name?('puppet-tftp', 'theforeman-tftp')
127
+ #
128
+ # @param [String] directory_name
129
+ # Name of the directory. Not the full path
130
+ # @param [String] metadata_name
131
+ # Name as it shows up in the metadata. It is normalized and accepts
132
+ # both / and - as separators.
133
+ #
134
+ # @return [Boolean] Wether the directory name is valid with the given
135
+ # metadata name
136
+ def valid_directory_name?(directory_name, metadata_name)
137
+ normalized = metadata_name.tr('/', '-').split('-').last
138
+ normalized == directory_name
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,7 @@
1
+ begin
2
+ require 'puppetlabs_spec_helper/tasks/beaker'
3
+ # Fixtures can be needed because of spec_prep
4
+ require 'puppetlabs_spec_helper/tasks/fixtures'
5
+ rescue LoadError
6
+ require 'beaker-rspec/rake_task'
7
+ end
@@ -1,14 +1,25 @@
1
- def configure_beaker(&block)
1
+ require_relative 'examples'
2
+
3
+ def configure_beaker(modules: :metadata, &block)
2
4
  ENV['PUPPET_INSTALL_TYPE'] ||= 'agent'
3
5
  ENV['BEAKER_PUPPET_COLLECTION'] ||= 'puppet6'
4
6
  ENV['BEAKER_debug'] ||= 'true'
5
7
  ENV['BEAKER_HYPERVISOR'] ||= 'docker'
6
8
 
9
+ # On Ruby 3 this doesn't appear to matter but on Ruby 2 beaker-hiera must be
10
+ # included before beaker-rspec so Beaker::DSL is final
11
+ require 'beaker-hiera'
7
12
  require 'beaker-rspec'
8
13
  require 'beaker-puppet'
9
14
  require 'beaker/puppet_install_helper'
10
- require 'beaker/module_install_helper'
11
- $module_source_dir = get_module_source_directory caller
15
+
16
+ case modules
17
+ when :metadata
18
+ require 'beaker/module_install_helper'
19
+ $module_source_dir = get_module_source_directory caller
20
+ when :fixtures
21
+ require_relative 'fixtures'
22
+ end
12
23
 
13
24
  run_puppet_install_helper unless ENV['BEAKER_provision'] == 'no'
14
25
 
@@ -18,14 +29,56 @@ def configure_beaker(&block)
18
29
 
19
30
  # Configure all nodes in nodeset
20
31
  c.before :suite do
21
- install_module
22
- install_module_dependencies
32
+ case modules
33
+ when :metadata
34
+ install_module
35
+ install_module_dependencies
36
+ when :fixtures
37
+ fixture_modules = File.join(Dir.pwd, 'spec', 'fixtures', 'modules')
38
+ Voxpupuli::Acceptance::Fixtures.install_fixture_modules_on(hosts, fixture_modules)
39
+ end
23
40
 
24
- if block
25
- hosts.each do |host|
26
- yield host
41
+ if RSpec.configuration.suite_configure_facts_from_env
42
+ require_relative 'facts'
43
+ Voxpupuli::Acceptance::Facts.write_beaker_facts_on(hosts)
44
+ end
45
+
46
+ if RSpec.configuration.suite_hiera?
47
+ hiera_data_dir = RSpec.configuration.suite_hiera_data_dir
48
+
49
+ if Dir.exist?(hiera_data_dir)
50
+ write_hiera_config_on(hosts, RSpec.configuration.suite_hiera_hierachy)
51
+ copy_hiera_data_to(hosts, hiera_data_dir)
52
+ end
53
+ end
54
+
55
+ local_setup = RSpec.configuration.setup_acceptance_node
56
+ hosts.each do |host|
57
+ yield host if block
58
+
59
+ if local_setup && File.exist?(local_setup)
60
+ puts "Configuring #{host} by applying #{local_setup}"
61
+ apply_manifest_on(host, File.read(local_setup), catch_failures: true)
27
62
  end
28
63
  end
29
64
  end
30
65
  end
31
66
  end
67
+
68
+ RSpec.configure do |c|
69
+ # Fact handling
70
+ c.add_setting :suite_configure_facts_from_env, default: true
71
+
72
+ # Hiera settings
73
+ c.add_setting :suite_hiera, default: true
74
+ c.add_setting :suite_hiera_data_dir, default: File.join('spec', 'acceptance', 'hieradata')
75
+ c.add_setting :suite_hiera_hierachy, default: [
76
+ 'fqdn/%{fqdn}.yaml',
77
+ 'os/%{os.family}/%{os.release.major}.yaml',
78
+ 'os/%{os.family}.yaml',
79
+ 'common.yaml',
80
+ ]
81
+
82
+ # Node setup
83
+ c.add_setting :setup_acceptance_node, default: File.join('spec', 'setup_acceptance_node.pp')
84
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: voxpupuli-acceptance
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vox Pupuli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-06 00:00:00.000000000 Z
11
+ date: 2021-07-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bcrypt_pbkdf
@@ -31,6 +31,12 @@ dependencies:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 4.2.0
34
+ - - "!="
35
+ - !ruby/object:Gem::Version
36
+ version: 4.22.0
37
+ - - "!="
38
+ - !ruby/object:Gem::Version
39
+ version: 4.23.0
34
40
  type: :runtime
35
41
  prerelease: false
36
42
  version_requirements: !ruby/object:Gem::Requirement
@@ -38,6 +44,12 @@ dependencies:
38
44
  - - ">="
39
45
  - !ruby/object:Gem::Version
40
46
  version: 4.2.0
47
+ - - "!="
48
+ - !ruby/object:Gem::Version
49
+ version: 4.22.0
50
+ - - "!="
51
+ - !ruby/object:Gem::Version
52
+ version: 4.23.0
41
53
  - !ruby/object:Gem::Dependency
42
54
  name: beaker-docker
43
55
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +64,20 @@ dependencies:
52
64
  - - ">="
53
65
  - !ruby/object:Gem::Version
54
66
  version: '0'
67
+ - !ruby/object:Gem::Dependency
68
+ name: beaker-hiera
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '0.4'
74
+ type: :runtime
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '0.4'
55
81
  - !ruby/object:Gem::Dependency
56
82
  name: beaker-hostgenerator
57
83
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +176,34 @@ dependencies:
150
176
  - - ">="
151
177
  - !ruby/object:Gem::Version
152
178
  version: '0'
179
+ - !ruby/object:Gem::Dependency
180
+ name: puppet-modulebuilder
181
+ requirement: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - "~>"
184
+ - !ruby/object:Gem::Version
185
+ version: '0.1'
186
+ type: :runtime
187
+ prerelease: false
188
+ version_requirements: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - "~>"
191
+ - !ruby/object:Gem::Version
192
+ version: '0.1'
193
+ - !ruby/object:Gem::Dependency
194
+ name: rake
195
+ requirement: !ruby/object:Gem::Requirement
196
+ requirements:
197
+ - - ">="
198
+ - !ruby/object:Gem::Version
199
+ version: '0'
200
+ type: :runtime
201
+ prerelease: false
202
+ version_requirements: !ruby/object:Gem::Requirement
203
+ requirements:
204
+ - - ">="
205
+ - !ruby/object:Gem::Version
206
+ version: '0'
153
207
  - !ruby/object:Gem::Dependency
154
208
  name: rbnacl
155
209
  requirement: !ruby/object:Gem::Requirement
@@ -215,8 +269,12 @@ extensions: []
215
269
  extra_rdoc_files: []
216
270
  files:
217
271
  - lib/voxpupuli/acceptance.rb
272
+ - lib/voxpupuli/acceptance/examples.rb
273
+ - lib/voxpupuli/acceptance/facts.rb
274
+ - lib/voxpupuli/acceptance/fixtures.rb
275
+ - lib/voxpupuli/acceptance/rake.rb
218
276
  - lib/voxpupuli/acceptance/spec_helper_acceptance.rb
219
- homepage: http://github.com/voxpupuli/voxpupuli-acceptance
277
+ homepage: https://github.com/voxpupuli/voxpupuli-acceptance
220
278
  licenses:
221
279
  - Apache-2.0
222
280
  metadata: {}
@@ -228,15 +286,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
228
286
  requirements:
229
287
  - - ">="
230
288
  - !ruby/object:Gem::Version
231
- version: '0'
289
+ version: '2.4'
290
+ - - "<"
291
+ - !ruby/object:Gem::Version
292
+ version: '4'
232
293
  required_rubygems_version: !ruby/object:Gem::Requirement
233
294
  requirements:
234
295
  - - ">="
235
296
  - !ruby/object:Gem::Version
236
297
  version: '0'
237
298
  requirements: []
238
- rubyforge_project:
239
- rubygems_version: 2.7.10
299
+ rubygems_version: 3.1.6
240
300
  signing_key:
241
301
  specification_version: 4
242
302
  summary: Helpers for acceptance testing Vox Pupuli modules