puppetlabs-onceover 5.0.3 → 5.0.4
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/.gitignore +4 -0
- data/.rubocop_todo.yml +35 -15
- data/CHANGELOG.md +387 -3
- data/Gemfile +1 -0
- data/lib/puppetlabs-onceover/cli/plugins.rb +3 -3
- data/lib/puppetlabs-onceover/controlrepo.rb +8 -7
- data/lib/puppetlabs-onceover/version.rb +1 -1
- data/spec/fixtures/controlrepos/deploy_test/Puppetfile +3 -0
- data/spec/fixtures/controlrepos/deploy_test/a_dir/nested_file.txt +1 -0
- data/spec/fixtures/controlrepos/deploy_test/a_symlink +1 -0
- data/spec/fixtures/controlrepos/deploy_test/environment.conf +1 -0
- data/spec/fixtures/controlrepos/deploy_test/regular_file.txt +1 -0
- data/spec/puppetlabs-onceover/beaker_spec.rb +293 -0
- data/spec/puppetlabs-onceover/class_spec.rb +89 -0
- data/spec/puppetlabs-onceover/cli/run_spec.rb +80 -0
- data/spec/puppetlabs-onceover/cli/show_spec.rb +67 -0
- data/spec/puppetlabs-onceover/cli_spec.rb +79 -0
- data/spec/puppetlabs-onceover/controlrepo_spec.rb +787 -5
- data/spec/puppetlabs-onceover/deploy_spec.rb +246 -0
- data/spec/puppetlabs-onceover/group_spec.rb +121 -0
- data/spec/puppetlabs-onceover/logger_spec.rb +30 -0
- data/spec/puppetlabs-onceover/node_spec.rb +124 -0
- data/spec/puppetlabs-onceover/rake_tasks_spec.rb +173 -0
- data/spec/puppetlabs-onceover/rspec/formatters_spec.rb +361 -0
- data/spec/puppetlabs-onceover/runner_spec.rb +307 -0
- data/spec/puppetlabs-onceover/test_spec.rb +177 -0
- data/spec/puppetlabs-onceover/testconfig_spec.rb +451 -0
- data/spec/puppetlabs-onceover/vendored_modules_spec.rb +302 -0
- data/spec/puppetlabs-onceover/version_spec.rb +10 -0
- data/spec/spec_helper.rb +8 -0
- metadata +22 -1
|
@@ -1,18 +1,800 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
require 'puppetlabs-onceover/controlrepo'
|
|
3
|
+
require 'r10k/puppetfile'
|
|
4
|
+
require 'tmpdir'
|
|
5
|
+
require 'fileutils'
|
|
6
|
+
require 'yaml'
|
|
3
7
|
|
|
4
8
|
describe "PuppetlabsOnceover::Controlrepo" do
|
|
9
|
+
# TestConfig.new (used by #spec_tests) instantiates PuppetlabsOnceover::Class/Node/Group/Test,
|
|
10
|
+
# each of which keep a process-global @@all array. Reset them around every example here too,
|
|
11
|
+
# so this file doesn't leak state into (or pick up state from) other spec files' examples.
|
|
12
|
+
before(:each) do
|
|
13
|
+
PuppetlabsOnceover::Class.class_variable_set(:@@all, []) if defined?(PuppetlabsOnceover::Class)
|
|
14
|
+
PuppetlabsOnceover::Node.class_variable_set(:@@all, []) if defined?(PuppetlabsOnceover::Node)
|
|
15
|
+
PuppetlabsOnceover::Group.class_variable_set(:@@all, []) if defined?(PuppetlabsOnceover::Group)
|
|
16
|
+
PuppetlabsOnceover::Test.class_variable_set(:@@all, []) if defined?(PuppetlabsOnceover::Test)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
let(:basic_path) { File.expand_path('spec/fixtures/controlrepos/basic') }
|
|
20
|
+
let(:minimal_path) { File.expand_path('spec/fixtures/controlrepos/minimal') }
|
|
21
|
+
let(:factsets_path) { File.expand_path('spec/fixtures/controlrepos/factsets') }
|
|
22
|
+
|
|
5
23
|
context "in a barebones controlrepo" do
|
|
6
24
|
before do
|
|
7
|
-
@repo = PuppetlabsOnceover::Controlrepo.new(
|
|
8
|
-
{
|
|
9
|
-
path: 'spec/fixtures/controlrepos/minimal'
|
|
10
|
-
}
|
|
11
|
-
)
|
|
25
|
+
@repo = PuppetlabsOnceover::Controlrepo.new(path: minimal_path)
|
|
12
26
|
end
|
|
13
27
|
|
|
14
28
|
context "without hiera.yaml" do
|
|
15
29
|
it { expect(@repo.hiera_config_file_relative_path).to be_nil }
|
|
30
|
+
it { expect(@repo.hiera_config_file).to be_nil }
|
|
31
|
+
it { expect(@repo.hiera_config).to be_nil }
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe "#initialize" do
|
|
36
|
+
it "uses the given :path directly" do
|
|
37
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
38
|
+
expect(repo.root).to eq(basic_path)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "traverses upward from Dir.pwd looking for environment.conf when no :path is given" do
|
|
42
|
+
nested = File.join(basic_path, 'site', 'role', 'manifests')
|
|
43
|
+
Dir.chdir(nested) do
|
|
44
|
+
repo = PuppetlabsOnceover::Controlrepo.new
|
|
45
|
+
expect(repo.root).to eq(basic_path)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "throws if it can never find an environment.conf above the cwd" do
|
|
50
|
+
Dir.mktmpdir do |tmp|
|
|
51
|
+
Dir.chdir(tmp) do
|
|
52
|
+
# `throw "..."` with a String label (not caught anywhere) surfaces as an
|
|
53
|
+
# UncaughtThrowError -- this is the real behavior of Controlrepo#initialize,
|
|
54
|
+
# not a mistake in this spec.
|
|
55
|
+
expect { PuppetlabsOnceover::Controlrepo.new }.to raise_error(UncaughtThrowError)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "merges options found in an onceover.yaml when present" do
|
|
61
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: File.expand_path('spec/fixtures/controlrepos/function_mocking'))
|
|
62
|
+
expect(repo.opts[:debug]).to eq(true)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "sets the logger level to debug when :debug option is truthy" do
|
|
66
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path, debug: true)
|
|
67
|
+
expect(repo.opts[:debug]).to eq(true)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "expands a relative :manifest option against root" do
|
|
71
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path, manifest: 'site/role/manifests/example.pp')
|
|
72
|
+
expect(repo.manifest).to eq(File.expand_path('site/role/manifests/example.pp', basic_path))
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "leaves manifest nil when not set anywhere" do
|
|
76
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: minimal_path)
|
|
77
|
+
expect(repo.manifest).to be_nil
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "respects the ONCEOVER_YAML env var" do
|
|
81
|
+
custom_yaml = File.expand_path('spec/fixtures/controlrepos/function_mocking/spec/onceover.yaml')
|
|
82
|
+
begin
|
|
83
|
+
ENV['ONCEOVER_YAML'] = custom_yaml
|
|
84
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
85
|
+
expect(repo.onceover_yaml).to eq(custom_yaml)
|
|
86
|
+
ensure
|
|
87
|
+
ENV.delete('ONCEOVER_YAML')
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "accepts explicit :facts_files" do
|
|
92
|
+
f = File.expand_path('spec/fixtures/controlrepos/factsets/spec/factsets/centos_with_env.json')
|
|
93
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: factsets_path, facts_files: [f])
|
|
94
|
+
expect(repo.facts_files).to eq([f])
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "accepts a custom :role_regex and :profile_regex" do
|
|
98
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path, role_regex: '^role::', profile_regex: '^profile::')
|
|
99
|
+
expect(repo.role_regex).to eq(/^role::/)
|
|
100
|
+
expect(repo.profile_regex).to eq(/^profile::/)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
describe "class-level delegation methods" do
|
|
105
|
+
before do
|
|
106
|
+
@repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "delegates .root" do
|
|
110
|
+
expect(PuppetlabsOnceover::Controlrepo.root).to eq(@repo.root)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "delegates .puppetfile" do
|
|
114
|
+
expect(PuppetlabsOnceover::Controlrepo.puppetfile).to eq(@repo.puppetfile)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "delegates .facts_files" do
|
|
118
|
+
expect(PuppetlabsOnceover::Controlrepo.facts_files).to eq(@repo.facts_files)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "delegates .classes" do
|
|
122
|
+
expect(PuppetlabsOnceover::Controlrepo.classes).to eq(@repo.classes)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "delegates .roles" do
|
|
126
|
+
expect(PuppetlabsOnceover::Controlrepo.roles).to eq(@repo.roles)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it "delegates .profiles" do
|
|
130
|
+
expect(PuppetlabsOnceover::Controlrepo.profiles).to eq(@repo.profiles)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "delegates .config" do
|
|
134
|
+
expect(PuppetlabsOnceover::Controlrepo.config).to eq(@repo.config)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it "delegates .facts" do
|
|
138
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: factsets_path)
|
|
139
|
+
expect(PuppetlabsOnceover::Controlrepo.facts).to eq(repo.facts(nil, 'values'))
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "delegates .trusted_facts" do
|
|
143
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: factsets_path)
|
|
144
|
+
expect(PuppetlabsOnceover::Controlrepo.trusted_facts).to eq(repo.facts(nil, 'trusted'))
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it "delegates .trusted_external_facts" do
|
|
148
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: factsets_path)
|
|
149
|
+
expect(PuppetlabsOnceover::Controlrepo.trusted_external_facts).to eq(repo.facts(nil, 'trusted_external'))
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it "delegates .hiera_config_file" do
|
|
153
|
+
expect(PuppetlabsOnceover::Controlrepo.hiera_config_file).to eq(@repo.hiera_config_file)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
describe "#to_s" do
|
|
158
|
+
it "renders a human readable summary" do
|
|
159
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
160
|
+
output = repo.to_s
|
|
161
|
+
expect(output).to include('puppetfile')
|
|
162
|
+
expect(output).to include('roles')
|
|
163
|
+
expect(output).to include('profiles')
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
describe "#roles and #profiles" do
|
|
168
|
+
it "finds roles matching the default role_regex" do
|
|
169
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
170
|
+
expect(repo.roles).to include('role::webserver', 'role::database_server', 'role::example')
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
it "finds profiles matching the default profile_regex" do
|
|
174
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
175
|
+
expect(repo.profiles).to include('profile::example', 'profile::base')
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
describe "#classes / private #get_classes / #find_classname" do
|
|
180
|
+
it "removes interpolated ($) modulepath entries before scanning" do
|
|
181
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
182
|
+
classes = repo.classes
|
|
183
|
+
expect(classes).not_to be_empty
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it "#find_classname returns nil for a file with no class definition" do
|
|
187
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
188
|
+
Dir.mktmpdir do |dir|
|
|
189
|
+
file = File.join(dir, 'nope.pp')
|
|
190
|
+
File.write(file, "# just a comment\n")
|
|
191
|
+
expect(repo.send(:find_classname, file)).to be_nil
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
it "#find_classname rescues ArgumentError from an invalid byte sequence and keeps scanning" do
|
|
196
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
197
|
+
Dir.mktmpdir do |dir|
|
|
198
|
+
file = File.join(dir, 'bad_encoding.pp')
|
|
199
|
+
# An invalid UTF-8 byte sequence makes `line =~ regex` raise ArgumentError.
|
|
200
|
+
File.binwrite(file, "# \xFF\xFE bad line\n")
|
|
201
|
+
expect { repo.send(:find_classname, file) }.not_to raise_error
|
|
202
|
+
expect(repo.send(:find_classname, file)).to be_nil
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
it "#find_classname supports namespaced classes" do
|
|
207
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
208
|
+
Dir.mktmpdir do |dir|
|
|
209
|
+
file = File.join(dir, 'ns.pp')
|
|
210
|
+
File.write(file, "class role::deep::nested {\n}\n")
|
|
211
|
+
expect(repo.send(:find_classname, file)).to eq('role::deep::nested')
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it "#get_classes finds classes recursively under a directory" do
|
|
216
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
217
|
+
classes = repo.send(:get_classes, File.join(basic_path, 'site'))
|
|
218
|
+
expect(classes).to include('role::webserver')
|
|
16
219
|
end
|
|
17
220
|
end
|
|
221
|
+
|
|
222
|
+
describe "#facts" do
|
|
223
|
+
let(:repo) { PuppetlabsOnceover::Controlrepo.new(path: factsets_path) }
|
|
224
|
+
|
|
225
|
+
it "returns an array of fact hashes" do
|
|
226
|
+
expect(repo.facts).to be_an(Array)
|
|
227
|
+
expect(repo.facts).not_to be_empty
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
it "raises if filter is not a Hash" do
|
|
231
|
+
expect { repo.facts('not-a-hash') }.to raise_error(RuntimeError, /Filter param must be a hash/)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
it "filters facts by a matching top-level key/value" do
|
|
235
|
+
all = repo.facts
|
|
236
|
+
sample = all.first
|
|
237
|
+
key, value = sample.first
|
|
238
|
+
filtered = repo.facts({ key => value })
|
|
239
|
+
expect(filtered).not_to be_empty
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
it "returns an empty array when the filter matches nothing" do
|
|
243
|
+
filtered = repo.facts({ 'this_key_does_not_exist_anywhere' => 'nope' })
|
|
244
|
+
expect(filtered).to eq([])
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
it "supports nested hash filters via #keypair_is_in_hash" do
|
|
248
|
+
expect(repo.send(:keypair_is_in_hash, { 'a' => { 'b' => 'c' } }, 'a', { 'b' => 'c' })).to eq(true)
|
|
249
|
+
expect(repo.send(:keypair_is_in_hash, { 'a' => { 'b' => 'c' } }, 'a', { 'b' => 'nope' })).to eq(false)
|
|
250
|
+
expect(repo.send(:keypair_is_in_hash, {}, 'missing', 'value')).to eq(false)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
it "falls back to trusted/trusted_external top level keys when 'values' key is absent" do
|
|
254
|
+
repo2 = PuppetlabsOnceover::Controlrepo.new(path: factsets_path)
|
|
255
|
+
expect { repo2.facts(nil, 'trusted') }.not_to raise_error
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
describe "#read_facts (private)" do
|
|
260
|
+
let(:repo) { PuppetlabsOnceover::Controlrepo.new(path: factsets_path) }
|
|
261
|
+
|
|
262
|
+
it "parses valid JSON" do
|
|
263
|
+
f = Dir[File.join(factsets_path, 'spec', 'factsets', '*.json')].first
|
|
264
|
+
expect(repo.send(:read_facts, f)).to be_a(Hash)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
it "raises a friendly error for invalid JSON" do
|
|
268
|
+
Dir.mktmpdir do |dir|
|
|
269
|
+
bad = File.join(dir, 'bad.json')
|
|
270
|
+
File.write(bad, "{not json")
|
|
271
|
+
expect { repo.send(:read_facts, bad) }.to raise_error(RuntimeError, /Could not parse/)
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
describe "#config" do
|
|
277
|
+
it "parses modulepath, strips comments, and handles values containing '='" do
|
|
278
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
279
|
+
config = repo.config
|
|
280
|
+
expect(config['modulepath']).to eq(['site', 'modules', '$basemodulepath'])
|
|
281
|
+
expect(config['value_with_equals']).to eq("'foo=bar'")
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
it "raises a friendly error when modulepath is missing from environment.conf" do
|
|
285
|
+
Dir.mktmpdir do |dir|
|
|
286
|
+
File.write(File.join(dir, 'environment.conf'), "config_version = 'x'\n")
|
|
287
|
+
expect { PuppetlabsOnceover::Controlrepo.new(path: dir) }.to raise_error(RuntimeError, /modulepath was not found/)
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
describe "#hiera_config_file / #hiera_config_file_relative_path / #hiera_config / #hiera_config=" do
|
|
293
|
+
it "prefers hiera.yaml in spec_dir over root" do
|
|
294
|
+
Dir.mktmpdir do |dir|
|
|
295
|
+
FileUtils.mkdir_p(File.join(dir, 'spec'))
|
|
296
|
+
File.write(File.join(dir, 'environment.conf'), "modulepath = site:modules\n")
|
|
297
|
+
File.write(File.join(dir, 'spec', 'hiera.yaml'), "---\nversion: 5\n")
|
|
298
|
+
File.write(File.join(dir, 'hiera.yaml'), "---\nversion: 3\n")
|
|
299
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: dir)
|
|
300
|
+
expect(repo.hiera_config_file).to eq(File.expand_path('spec/hiera.yaml', dir))
|
|
301
|
+
expect(repo.hiera_config['version']).to eq(5)
|
|
302
|
+
expect(repo.hiera_config_file_relative_path).to eq('spec/hiera.yaml')
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
it "falls back to hiera.yaml at root when not present in spec_dir" do
|
|
307
|
+
Dir.mktmpdir do |dir|
|
|
308
|
+
FileUtils.mkdir_p(File.join(dir, 'spec'))
|
|
309
|
+
File.write(File.join(dir, 'environment.conf'), "modulepath = site:modules\n")
|
|
310
|
+
File.write(File.join(dir, 'hiera.yaml'), "---\nversion: 3\n")
|
|
311
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: dir)
|
|
312
|
+
expect(repo.hiera_config_file).to eq(File.expand_path('hiera.yaml', dir))
|
|
313
|
+
expect(repo.hiera_config['version']).to eq(3)
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
it "returns nil from #hiera_config and prints a warning when no hiera.yaml exists anywhere" do
|
|
318
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: minimal_path)
|
|
319
|
+
expect { expect(repo.hiera_config).to be_nil }.to output(/WARNING: Could not find hiera config file/).to_stdout
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
it "#hiera_config= writes the given data back to hiera_config_file" do
|
|
323
|
+
Dir.mktmpdir do |dir|
|
|
324
|
+
FileUtils.mkdir_p(File.join(dir, 'spec'))
|
|
325
|
+
File.write(File.join(dir, 'environment.conf'), "modulepath = site:modules\n")
|
|
326
|
+
File.write(File.join(dir, 'spec', 'hiera.yaml'), "---\nversion: 5\n")
|
|
327
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: dir)
|
|
328
|
+
repo.hiera_config = { 'version' => 5, 'defaults' => { 'datadir' => 'newdata' } }
|
|
329
|
+
expect(YAML.load_file(repo.hiera_config_file)['defaults']['datadir']).to eq('newdata')
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
describe "#hiera_data" do
|
|
335
|
+
it "finds a single hiera-ish data directory" do
|
|
336
|
+
Dir.mktmpdir do |dir|
|
|
337
|
+
File.write(File.join(dir, 'environment.conf'), "modulepath = site:modules\n")
|
|
338
|
+
FileUtils.mkdir_p(File.join(dir, 'hieradata'))
|
|
339
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: dir)
|
|
340
|
+
expect(repo.hiera_data).to eq(File.expand_path('hieradata', dir))
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
it "raises when there is more than one candidate hiera data directory" do
|
|
345
|
+
Dir.mktmpdir do |dir|
|
|
346
|
+
File.write(File.join(dir, 'environment.conf'), "modulepath = site:modules\n")
|
|
347
|
+
FileUtils.mkdir_p(File.join(dir, 'hieradata'))
|
|
348
|
+
FileUtils.mkdir_p(File.join(dir, 'hiera_data_2'))
|
|
349
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: dir)
|
|
350
|
+
expect { repo.hiera_data }.to raise_error(RuntimeError, /too many directories/)
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
describe "#r10k_config_file / #r10k_config / #r10k_config=" do
|
|
356
|
+
it "prefers r10k.yaml in spec_dir over root" do
|
|
357
|
+
Dir.mktmpdir do |dir|
|
|
358
|
+
FileUtils.mkdir_p(File.join(dir, 'spec'))
|
|
359
|
+
File.write(File.join(dir, 'environment.conf'), "modulepath = site:modules\n")
|
|
360
|
+
File.write(File.join(dir, 'spec', 'r10k.yaml'), "---\ncachedir: /tmp/spec-cache\n")
|
|
361
|
+
File.write(File.join(dir, 'r10k.yaml'), "---\ncachedir: /tmp/root-cache\n")
|
|
362
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: dir)
|
|
363
|
+
expect(repo.r10k_config_file).to eq(File.expand_path('spec/r10k.yaml', dir))
|
|
364
|
+
expect(repo.r10k_config['cachedir']).to eq('/tmp/spec-cache')
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
it "falls back to r10k.yaml at root" do
|
|
369
|
+
Dir.mktmpdir do |dir|
|
|
370
|
+
FileUtils.mkdir_p(File.join(dir, 'spec'))
|
|
371
|
+
File.write(File.join(dir, 'environment.conf'), "modulepath = site:modules\n")
|
|
372
|
+
File.write(File.join(dir, 'r10k.yaml'), "---\ncachedir: /tmp/root-cache\n")
|
|
373
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: dir)
|
|
374
|
+
expect(repo.r10k_config_file).to eq(File.expand_path('r10k.yaml', dir))
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
it "returns nil when neither exists" do
|
|
379
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: minimal_path)
|
|
380
|
+
expect(repo.r10k_config_file).to be_nil
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
it "#r10k_config= writes data back out" do
|
|
384
|
+
Dir.mktmpdir do |dir|
|
|
385
|
+
FileUtils.mkdir_p(File.join(dir, 'spec'))
|
|
386
|
+
File.write(File.join(dir, 'environment.conf'), "modulepath = site:modules\n")
|
|
387
|
+
File.write(File.join(dir, 'spec', 'r10k.yaml'), "---\ncachedir: /tmp/a\n")
|
|
388
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: dir)
|
|
389
|
+
repo.r10k_config = { 'cachedir' => '/tmp/b' }
|
|
390
|
+
expect(YAML.load_file(repo.r10k_config_file)['cachedir']).to eq('/tmp/b')
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
describe "#temp_manifest" do
|
|
396
|
+
it "returns whatever @manifest currently is" do
|
|
397
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path, manifest: 'site/role/manifests/example.pp')
|
|
398
|
+
expect(repo.temp_manifest).to eq(repo.manifest)
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
describe "#print_puppetfile_table" do
|
|
403
|
+
it "prints a table for both forge and git modules, out-of-date and up-to-date" do
|
|
404
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
405
|
+
|
|
406
|
+
puppetfile = R10K::Puppetfile.new(basic_path)
|
|
407
|
+
puppetfile.load!
|
|
408
|
+
forge_mod = puppetfile.modules.find { |m| m.is_a?(R10K::Module::Forge) }
|
|
409
|
+
puppetfile.modules.find { |m| m.is_a?(R10K::Module::Git) }
|
|
410
|
+
|
|
411
|
+
current_release = double('release', version: '9.9.9')
|
|
412
|
+
v3_module = double('v3_module', current_release: current_release, endorsement: 'supported', superseded_by: nil)
|
|
413
|
+
allow(forge_mod).to receive(:v3_module).and_return(v3_module)
|
|
414
|
+
|
|
415
|
+
allow(R10K::Puppetfile).to receive(:new).and_return(puppetfile)
|
|
416
|
+
allow(puppetfile).to receive(:load!)
|
|
417
|
+
|
|
418
|
+
expect { repo.print_puppetfile_table }.to output(/Full Name/).to_stdout
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
it "captures a RuntimeError raised while assessing a module and reports it in the error table" do
|
|
422
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
423
|
+
|
|
424
|
+
puppetfile = R10K::Puppetfile.new(basic_path)
|
|
425
|
+
puppetfile.load!
|
|
426
|
+
forge_mod = puppetfile.modules.find { |m| m.is_a?(R10K::Module::Forge) }
|
|
427
|
+
|
|
428
|
+
call_count = 0
|
|
429
|
+
allow(forge_mod).to receive(:v3_module) do
|
|
430
|
+
call_count += 1
|
|
431
|
+
raise 'boom' if call_count == 1
|
|
432
|
+
|
|
433
|
+
double('v3_module', current_release: double('release', version: '4.11.0'))
|
|
434
|
+
end
|
|
435
|
+
allow(forge_mod).to receive(:expected_version).and_return('4.11.0')
|
|
436
|
+
|
|
437
|
+
allow(R10K::Puppetfile).to receive(:new).and_return(puppetfile)
|
|
438
|
+
allow(puppetfile).to receive(:load!)
|
|
439
|
+
allow(puppetfile).to receive(:modules).and_return([forge_mod])
|
|
440
|
+
|
|
441
|
+
expect { repo.print_puppetfile_table }.to output(/Issue assessing module/).to_stdout
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
it "marks major/minor/tiny/patchlevel version differences appropriately" do
|
|
445
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
446
|
+
puppetfile = R10K::Puppetfile.new(basic_path)
|
|
447
|
+
puppetfile.load!
|
|
448
|
+
forge_mod = puppetfile.modules.find { |m| m.is_a?(R10K::Module::Forge) }
|
|
449
|
+
allow(forge_mod).to receive(:expected_version).and_return('1.0.0')
|
|
450
|
+
current_release = double('release', version: '2.0.0')
|
|
451
|
+
v3_module = double('v3_module', current_release: current_release, endorsement: 'supported', superseded_by: { slug: 'newmod' })
|
|
452
|
+
allow(forge_mod).to receive(:v3_module).and_return(v3_module)
|
|
453
|
+
|
|
454
|
+
allow(R10K::Puppetfile).to receive(:new).and_return(puppetfile)
|
|
455
|
+
allow(puppetfile).to receive(:load!)
|
|
456
|
+
allow(puppetfile).to receive(:modules).and_return([forge_mod])
|
|
457
|
+
|
|
458
|
+
expect { repo.print_puppetfile_table }.to output(/Major/).to_stdout
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
it "marks a minor version difference" do
|
|
462
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
463
|
+
puppetfile = R10K::Puppetfile.new(basic_path)
|
|
464
|
+
puppetfile.load!
|
|
465
|
+
forge_mod = puppetfile.modules.find { |m| m.is_a?(R10K::Module::Forge) }
|
|
466
|
+
allow(forge_mod).to receive(:expected_version).and_return('1.0.0')
|
|
467
|
+
v3_module = double('v3_module', current_release: double('release', version: '1.1.0'), endorsement: 'supported', superseded_by: nil)
|
|
468
|
+
allow(forge_mod).to receive(:v3_module).and_return(v3_module)
|
|
469
|
+
allow(R10K::Puppetfile).to receive(:new).and_return(puppetfile)
|
|
470
|
+
allow(puppetfile).to receive(:load!)
|
|
471
|
+
allow(puppetfile).to receive(:modules).and_return([forge_mod])
|
|
472
|
+
expect { repo.print_puppetfile_table }.to output(/Minor/).to_stdout
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
it "marks a tiny version difference" do
|
|
476
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
477
|
+
puppetfile = R10K::Puppetfile.new(basic_path)
|
|
478
|
+
puppetfile.load!
|
|
479
|
+
forge_mod = puppetfile.modules.find { |m| m.is_a?(R10K::Module::Forge) }
|
|
480
|
+
allow(forge_mod).to receive(:expected_version).and_return('1.0.0')
|
|
481
|
+
v3_module = double('v3_module', current_release: double('release', version: '1.0.1'), endorsement: 'supported', superseded_by: nil)
|
|
482
|
+
allow(forge_mod).to receive(:v3_module).and_return(v3_module)
|
|
483
|
+
allow(R10K::Puppetfile).to receive(:new).and_return(puppetfile)
|
|
484
|
+
allow(puppetfile).to receive(:load!)
|
|
485
|
+
allow(puppetfile).to receive(:modules).and_return([forge_mod])
|
|
486
|
+
expect { repo.print_puppetfile_table }.to output(/Tiny/).to_stdout
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
it "marks a patchlevel version difference" do
|
|
490
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
491
|
+
puppetfile = R10K::Puppetfile.new(basic_path)
|
|
492
|
+
puppetfile.load!
|
|
493
|
+
forge_mod = puppetfile.modules.find { |m| m.is_a?(R10K::Module::Forge) }
|
|
494
|
+
allow(forge_mod).to receive(:expected_version).and_return('1.0.0-0')
|
|
495
|
+
v3_module = double('v3_module', current_release: double('release', version: '1.0.0-1'), endorsement: 'supported', superseded_by: nil)
|
|
496
|
+
allow(forge_mod).to receive(:v3_module).and_return(v3_module)
|
|
497
|
+
allow(R10K::Puppetfile).to receive(:new).and_return(puppetfile)
|
|
498
|
+
allow(puppetfile).to receive(:load!)
|
|
499
|
+
allow(puppetfile).to receive(:modules).and_return([forge_mod])
|
|
500
|
+
expect { repo.print_puppetfile_table }.to output(/PatchLevel/).to_stdout
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
it "marks a patchlevel_minor version difference" do
|
|
504
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
505
|
+
puppetfile = R10K::Puppetfile.new(basic_path)
|
|
506
|
+
puppetfile.load!
|
|
507
|
+
forge_mod = puppetfile.modules.find { |m| m.is_a?(R10K::Module::Forge) }
|
|
508
|
+
allow(forge_mod).to receive(:expected_version).and_return('1.0.0-0-0')
|
|
509
|
+
v3_module = double('v3_module', current_release: double('release', version: '1.0.0-0-1'), endorsement: 'supported', superseded_by: nil)
|
|
510
|
+
allow(forge_mod).to receive(:v3_module).and_return(v3_module)
|
|
511
|
+
allow(R10K::Puppetfile).to receive(:new).and_return(puppetfile)
|
|
512
|
+
allow(puppetfile).to receive(:load!)
|
|
513
|
+
allow(puppetfile).to receive(:modules).and_return([forge_mod])
|
|
514
|
+
expect { repo.print_puppetfile_table }.to output(/PatchLevel_minor/).to_stdout
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
it "marks 'No' when versions are identical" do
|
|
518
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
519
|
+
puppetfile = R10K::Puppetfile.new(basic_path)
|
|
520
|
+
puppetfile.load!
|
|
521
|
+
forge_mod = puppetfile.modules.find { |m| m.is_a?(R10K::Module::Forge) }
|
|
522
|
+
allow(forge_mod).to receive(:expected_version).and_return('1.0.0')
|
|
523
|
+
v3_module = double('v3_module', current_release: double('release', version: '1.0.0'), endorsement: 'supported', superseded_by: nil)
|
|
524
|
+
allow(forge_mod).to receive(:v3_module).and_return(v3_module)
|
|
525
|
+
allow(R10K::Puppetfile).to receive(:new).and_return(puppetfile)
|
|
526
|
+
allow(puppetfile).to receive(:load!)
|
|
527
|
+
allow(puppetfile).to receive(:modules).and_return([forge_mod])
|
|
528
|
+
expect { repo.print_puppetfile_table }.to output(/No/).to_stdout
|
|
529
|
+
end
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
describe "#update_puppetfile" do
|
|
533
|
+
it "rewrites the expected version of forge modules in place" do
|
|
534
|
+
Dir.mktmpdir do |dir|
|
|
535
|
+
FileUtils.cp_r(Dir.glob(File.join(basic_path, '*')), dir)
|
|
536
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: dir)
|
|
537
|
+
|
|
538
|
+
puppetfile = R10K::Puppetfile.new(dir)
|
|
539
|
+
puppetfile.load!
|
|
540
|
+
forge_mod = puppetfile.modules.find { |m| m.is_a?(R10K::Module::Forge) }
|
|
541
|
+
allow(forge_mod).to receive(:owner).and_return('puppetlabs')
|
|
542
|
+
allow(forge_mod).to receive(:name).and_return('stdlib')
|
|
543
|
+
allow(forge_mod).to receive(:expected_version).and_return('4.11.0')
|
|
544
|
+
v3_module = double('v3_module', current_release: double('release', version: '9.9.9'))
|
|
545
|
+
allow(forge_mod).to receive(:v3_module).and_return(v3_module)
|
|
546
|
+
allow(puppetfile).to receive(:modules).and_return([forge_mod])
|
|
547
|
+
|
|
548
|
+
allow(R10K::Puppetfile).to receive(:new).and_return(puppetfile)
|
|
549
|
+
allow(puppetfile).to receive(:load!)
|
|
550
|
+
|
|
551
|
+
expect { repo.update_puppetfile }.to output(/changed/).to_stdout
|
|
552
|
+
expect(File.read(repo.puppetfile)).to include('9.9.9')
|
|
553
|
+
end
|
|
554
|
+
end
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
describe "#fixtures" do
|
|
558
|
+
it "renders a .fixtures.yml with symlinks, forge_modules and repositories" do
|
|
559
|
+
Dir.mktmpdir do |dir|
|
|
560
|
+
FileUtils.cp_r(Dir.glob(File.join(basic_path, '*')), dir)
|
|
561
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: dir)
|
|
562
|
+
|
|
563
|
+
puppetfile = R10K::Puppetfile.new(dir)
|
|
564
|
+
puppetfile.load!
|
|
565
|
+
|
|
566
|
+
allow(R10K::Puppetfile).to receive(:new).and_return(puppetfile)
|
|
567
|
+
allow(puppetfile).to receive(:load).and_return(true)
|
|
568
|
+
|
|
569
|
+
# The `code_dirs.each { |dir| Dir["#{dir}/*"] }` loop in #fixtures uses the
|
|
570
|
+
# modulepath entries as-is (unexpanded, unlike #classes), so it only finds
|
|
571
|
+
# anything when the process cwd is the controlrepo root.
|
|
572
|
+
result = nil
|
|
573
|
+
Dir.chdir(dir) { result = repo.fixtures }
|
|
574
|
+
expect(result).to include('forge_modules')
|
|
575
|
+
expect(result).to include('repositories')
|
|
576
|
+
expect(result).to include('symlinks')
|
|
577
|
+
end
|
|
578
|
+
end
|
|
579
|
+
|
|
580
|
+
it "treats a Hash expected_version (local path) as a symlink" do
|
|
581
|
+
Dir.mktmpdir do |dir|
|
|
582
|
+
File.write(File.join(dir, 'environment.conf'), "modulepath = site:modules:$basemodulepath\n")
|
|
583
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: dir)
|
|
584
|
+
|
|
585
|
+
local_mod = double('mod')
|
|
586
|
+
allow(local_mod).to receive(:is_a?).with(R10K::Module::Forge).and_return(true)
|
|
587
|
+
allow(local_mod).to receive(:is_a?).with(R10K::Module::Git).and_return(false)
|
|
588
|
+
allow(local_mod).to receive(:to_s).and_return('localmod')
|
|
589
|
+
allow(local_mod).to receive(:name).and_return('localmod')
|
|
590
|
+
allow(local_mod).to receive(:expected_version).and_return({ path: '/some/local/path' })
|
|
591
|
+
|
|
592
|
+
puppetfile = double('puppetfile', load: true, modules: [local_mod])
|
|
593
|
+
allow(R10K::Puppetfile).to receive(:new).and_return(puppetfile)
|
|
594
|
+
|
|
595
|
+
result = repo.fixtures
|
|
596
|
+
expect(result).to include('symlinks')
|
|
597
|
+
expect(result).to include('/some/local/path')
|
|
598
|
+
end
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
it "raises if the Puppetfile cannot be loaded" do
|
|
602
|
+
Dir.mktmpdir do |dir|
|
|
603
|
+
File.write(File.join(dir, 'environment.conf'), "modulepath = site:modules:$basemodulepath\n")
|
|
604
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: dir)
|
|
605
|
+
puppetfile = double('puppetfile', load: false)
|
|
606
|
+
allow(R10K::Puppetfile).to receive(:new).and_return(puppetfile)
|
|
607
|
+
expect { repo.fixtures }.to raise_error(RuntimeError, /Could not load Puppetfile/)
|
|
608
|
+
end
|
|
609
|
+
end
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
describe "self.evaluate_template" do
|
|
613
|
+
after(:each) { PuppetlabsOnceover::Controlrepo.instance_variable_set(:@root, nil) }
|
|
614
|
+
|
|
615
|
+
it "renders the gem's default template when no custom one is present" do
|
|
616
|
+
repo = double('repo', roles: [], facts_files: [])
|
|
617
|
+
result = PuppetlabsOnceover::Controlrepo.evaluate_template('controlrepo.yaml.erb', binding)
|
|
618
|
+
expect(result).to include('classes:')
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
it "prefers a custom template under <root>/spec/templates when present" do
|
|
622
|
+
Dir.mktmpdir do |dir|
|
|
623
|
+
FileUtils.mkdir_p(File.join(dir, 'spec', 'templates'))
|
|
624
|
+
File.write(File.join(dir, 'spec', 'templates', 'my_template.erb'), "custom-<%= 1 + 1 %>\n")
|
|
625
|
+
PuppetlabsOnceover::Controlrepo.instance_variable_set(:@root, dir)
|
|
626
|
+
|
|
627
|
+
result = nil
|
|
628
|
+
expect { result = PuppetlabsOnceover::Controlrepo.evaluate_template('my_template.erb', binding) }.to output(/Using Custom/).to_stdout
|
|
629
|
+
expect(result).to include('custom-2')
|
|
630
|
+
end
|
|
631
|
+
end
|
|
632
|
+
end
|
|
633
|
+
|
|
634
|
+
describe "self.create_dirs_and_log" do
|
|
635
|
+
it "creates all missing intermediate directories and logs each one" do
|
|
636
|
+
Dir.mktmpdir do |dir|
|
|
637
|
+
target = File.join(dir, 'a', 'b', 'c')
|
|
638
|
+
Dir.chdir(dir) do
|
|
639
|
+
expect { PuppetlabsOnceover::Controlrepo.create_dirs_and_log(target) }.to output(/created/).to_stdout
|
|
640
|
+
end
|
|
641
|
+
expect(File.directory?(target)).to eq(true)
|
|
642
|
+
end
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
it "does nothing when the directory already exists" do
|
|
646
|
+
Dir.mktmpdir do |dir|
|
|
647
|
+
Dir.chdir(dir) do
|
|
648
|
+
out = capture_stdout { PuppetlabsOnceover::Controlrepo.create_dirs_and_log(dir) }
|
|
649
|
+
expect(out).to eq('')
|
|
650
|
+
end
|
|
651
|
+
end
|
|
652
|
+
end
|
|
653
|
+
end
|
|
654
|
+
|
|
655
|
+
describe "self.init_write_file" do
|
|
656
|
+
it "creates the file (and parent dirs) when it does not exist" do
|
|
657
|
+
Dir.mktmpdir do |dir|
|
|
658
|
+
Dir.chdir(dir) do
|
|
659
|
+
target = File.join(dir, 'nested', 'file.txt')
|
|
660
|
+
expect { PuppetlabsOnceover::Controlrepo.init_write_file('hello', target) }.to output(/created/).to_stdout
|
|
661
|
+
expect(File.read(target)).to eq('hello')
|
|
662
|
+
end
|
|
663
|
+
end
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
it "skips writing when the file already exists" do
|
|
667
|
+
Dir.mktmpdir do |dir|
|
|
668
|
+
Dir.chdir(dir) do
|
|
669
|
+
target = File.join(dir, 'file.txt')
|
|
670
|
+
File.write(target, 'original')
|
|
671
|
+
expect { PuppetlabsOnceover::Controlrepo.init_write_file('new content', target) }.to output(/skipped/).to_stdout
|
|
672
|
+
expect(File.read(target)).to eq('original')
|
|
673
|
+
end
|
|
674
|
+
end
|
|
675
|
+
end
|
|
676
|
+
end
|
|
677
|
+
|
|
678
|
+
describe "self.generate_onceover_yaml" do
|
|
679
|
+
it "renders a controlrepo.yaml.erb driven by the repo's roles and facts_files" do
|
|
680
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: basic_path)
|
|
681
|
+
result = PuppetlabsOnceover::Controlrepo.generate_onceover_yaml(repo)
|
|
682
|
+
expect(result).to include('classes:')
|
|
683
|
+
expect(result).to include('nodes:')
|
|
684
|
+
end
|
|
685
|
+
end
|
|
686
|
+
|
|
687
|
+
describe "self.init" do
|
|
688
|
+
it "writes out the standard set of config files and updates .gitignore" do
|
|
689
|
+
Dir.mktmpdir do |dir|
|
|
690
|
+
FileUtils.mkdir_p(File.join(dir, 'spec'))
|
|
691
|
+
File.write(File.join(dir, 'environment.conf'), "modulepath = site:modules:$basemodulepath\n")
|
|
692
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: dir)
|
|
693
|
+
|
|
694
|
+
allow(Dir).to receive(:pwd).and_call_original
|
|
695
|
+
|
|
696
|
+
Dir.chdir(dir) do
|
|
697
|
+
expect { PuppetlabsOnceover::Controlrepo.init(repo) }.to output(/created/).to_stdout
|
|
698
|
+
end
|
|
699
|
+
|
|
700
|
+
expect(File.exist?(repo.onceover_yaml)).to eq(true)
|
|
701
|
+
expect(File.exist?(File.join(dir, 'Rakefile'))).to eq(true)
|
|
702
|
+
expect(File.exist?(File.join(dir, 'Gemfile'))).to eq(true)
|
|
703
|
+
expect(File.read(File.join(dir, '.gitignore'))).to include('.onceover')
|
|
704
|
+
end
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
it "appends to an existing .gitignore rather than clobbering it" do
|
|
708
|
+
Dir.mktmpdir do |dir|
|
|
709
|
+
FileUtils.mkdir_p(File.join(dir, 'spec'))
|
|
710
|
+
File.write(File.join(dir, 'environment.conf'), "modulepath = site:modules:$basemodulepath\n")
|
|
711
|
+
File.write(File.join(dir, '.gitignore'), "vendor/\n")
|
|
712
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: dir)
|
|
713
|
+
|
|
714
|
+
Dir.chdir(dir) do
|
|
715
|
+
PuppetlabsOnceover::Controlrepo.init(repo)
|
|
716
|
+
end
|
|
717
|
+
|
|
718
|
+
content = File.read(File.join(dir, '.gitignore'))
|
|
719
|
+
expect(content).to include('vendor/')
|
|
720
|
+
expect(content).to include('.onceover')
|
|
721
|
+
end
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
it "does not touch .gitignore again if .onceover is already listed" do
|
|
725
|
+
Dir.mktmpdir do |dir|
|
|
726
|
+
FileUtils.mkdir_p(File.join(dir, 'spec'))
|
|
727
|
+
File.write(File.join(dir, 'environment.conf'), "modulepath = site:modules:$basemodulepath\n")
|
|
728
|
+
File.write(File.join(dir, '.gitignore'), ".onceover\n")
|
|
729
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: dir)
|
|
730
|
+
|
|
731
|
+
Dir.chdir(dir) do
|
|
732
|
+
out = capture_stdout { PuppetlabsOnceover::Controlrepo.init(repo) }
|
|
733
|
+
expect(out).not_to match(/changed .gitignore/)
|
|
734
|
+
end
|
|
735
|
+
end
|
|
736
|
+
end
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
describe "self.generate_nodesets (deprecated)" do
|
|
740
|
+
it "comments out hosts for which no vagrant box could be found (404)" do
|
|
741
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: factsets_path)
|
|
742
|
+
|
|
743
|
+
response = double('response', code: '404', body: nil)
|
|
744
|
+
http = double('http')
|
|
745
|
+
allow(http).to receive(:use_ssl=)
|
|
746
|
+
allow(http).to receive(:get).and_return(response)
|
|
747
|
+
allow(Net::HTTP).to receive(:new).and_return(http)
|
|
748
|
+
|
|
749
|
+
result = PuppetlabsOnceover::Controlrepo.generate_nodesets(repo)
|
|
750
|
+
expect(result).to include('HOSTS')
|
|
751
|
+
expect(result).to include('#')
|
|
752
|
+
end
|
|
753
|
+
|
|
754
|
+
it "includes a real box url when the API call succeeds" do
|
|
755
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: factsets_path)
|
|
756
|
+
|
|
757
|
+
box_body = {
|
|
758
|
+
'current_version' => {
|
|
759
|
+
'providers' => [
|
|
760
|
+
{ 'name' => 'virtualbox', 'original_url' => 'https://example.com/box.box' }
|
|
761
|
+
]
|
|
762
|
+
}
|
|
763
|
+
}.to_json
|
|
764
|
+
|
|
765
|
+
response = double('response', code: '200', body: box_body)
|
|
766
|
+
http = double('http')
|
|
767
|
+
allow(http).to receive(:use_ssl=)
|
|
768
|
+
allow(http).to receive(:get).and_return(response)
|
|
769
|
+
allow(Net::HTTP).to receive(:new).and_return(http)
|
|
770
|
+
|
|
771
|
+
result = PuppetlabsOnceover::Controlrepo.generate_nodesets(repo)
|
|
772
|
+
expect(result).to include('box_url')
|
|
773
|
+
expect(result).to include('https://example.com/box.box')
|
|
774
|
+
end
|
|
775
|
+
end
|
|
776
|
+
|
|
777
|
+
describe "#spec_tests" do
|
|
778
|
+
it "yields deduplicated, filtered test tuples built from onceover.yaml" do
|
|
779
|
+
repo_path = File.expand_path('spec/fixtures/controlrepos/function_mocking')
|
|
780
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: repo_path, onceover_yaml: File.join(repo_path, 'spec', 'onceover.yaml'))
|
|
781
|
+
|
|
782
|
+
yielded = []
|
|
783
|
+
repo.spec_tests do |class_name, node_name, _fact_set, _trusted_set, _trusted_external_set, _pre_condition|
|
|
784
|
+
yielded << [class_name, node_name]
|
|
785
|
+
end
|
|
786
|
+
|
|
787
|
+
expect(yielded).not_to be_empty
|
|
788
|
+
expect(yielded.map(&:first)).to all(match(/role::/))
|
|
789
|
+
end
|
|
790
|
+
end
|
|
791
|
+
end
|
|
792
|
+
|
|
793
|
+
def capture_stdout
|
|
794
|
+
old = $stdout
|
|
795
|
+
$stdout = StringIO.new
|
|
796
|
+
yield
|
|
797
|
+
$stdout.string
|
|
798
|
+
ensure
|
|
799
|
+
$stdout = old
|
|
18
800
|
end
|