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
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'puppetlabs-onceover/controlrepo'
|
|
3
|
+
require 'puppetlabs-onceover/vendored_modules'
|
|
4
|
+
require 'puppetlabs-onceover/deploy'
|
|
5
|
+
require 'tmpdir'
|
|
6
|
+
require 'fileutils'
|
|
7
|
+
|
|
8
|
+
describe PuppetlabsOnceover::Deploy do
|
|
9
|
+
subject(:deploy) { described_class.new }
|
|
10
|
+
|
|
11
|
+
# Every test gets its own scratch tempdir standing in for
|
|
12
|
+
# repo.tempdir/.onceover, cleaned up afterwards so nothing leaks into the
|
|
13
|
+
# real repo tree.
|
|
14
|
+
let(:tempdir) { Dir.mktmpdir('deploy-spec-tempdir') }
|
|
15
|
+
|
|
16
|
+
after do
|
|
17
|
+
FileUtils.rm_rf(tempdir)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def build_repo(fixture, tempdir_override: tempdir)
|
|
21
|
+
repo = PuppetlabsOnceover::Controlrepo.new(path: "spec/fixtures/controlrepos/#{fixture}")
|
|
22
|
+
repo.tempdir = tempdir_override
|
|
23
|
+
repo
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe '#deploy_local' do
|
|
27
|
+
context 'when the controlrepo has no Puppetfile' do
|
|
28
|
+
it 'defaults to skipping r10k entirely and still copies the tree' do
|
|
29
|
+
repo = build_repo('minimal')
|
|
30
|
+
|
|
31
|
+
expect(deploy).not_to receive(:system)
|
|
32
|
+
|
|
33
|
+
result = deploy.deploy_local(repo, {})
|
|
34
|
+
|
|
35
|
+
expect(result).to eq(tempdir)
|
|
36
|
+
production_dir = "#{tempdir}/#{repo.environmentpath}/production"
|
|
37
|
+
expect(File.exist?("#{production_dir}/environment.conf")).to be true
|
|
38
|
+
expect(File.exist?("#{production_dir}/.onceover_manifest.json")).to be true
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context 'when skip_r10k is explicitly requested' do
|
|
43
|
+
it 'copies the tree (including the untouched Puppetfile) but never shells out' do
|
|
44
|
+
repo = build_repo('basic')
|
|
45
|
+
|
|
46
|
+
expect(deploy).not_to receive(:system)
|
|
47
|
+
|
|
48
|
+
deploy.deploy_local(repo, { skip_r10k: true })
|
|
49
|
+
|
|
50
|
+
production_dir = "#{tempdir}/#{repo.environmentpath}/production"
|
|
51
|
+
original_puppetfile = File.read('spec/fixtures/controlrepos/basic/Puppetfile')
|
|
52
|
+
expect(File.read("#{production_dir}/Puppetfile")).to eq(original_puppetfile)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context 'symlinks, directories, and plain files in the controlrepo' do
|
|
57
|
+
it 'recreates symlinks, directories, and files in the copied tree' do
|
|
58
|
+
repo = build_repo('deploy_test')
|
|
59
|
+
|
|
60
|
+
deploy.deploy_local(repo, { skip_r10k: true })
|
|
61
|
+
|
|
62
|
+
production_dir = "#{tempdir}/#{repo.environmentpath}/production"
|
|
63
|
+
expect(File.symlink?("#{production_dir}/a_symlink")).to be true
|
|
64
|
+
expect(File.directory?("#{production_dir}/a_dir")).to be true
|
|
65
|
+
expect(File.read("#{production_dir}/a_dir/nested_file.txt")).to eq("nested\n")
|
|
66
|
+
expect(File.read("#{production_dir}/regular_file.txt")).to eq("hello\n")
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context 'when a modules directory exists in the current working directory' do
|
|
71
|
+
it 'logs a warning' do
|
|
72
|
+
repo = build_repo('deploy_test')
|
|
73
|
+
|
|
74
|
+
allow(File).to receive(:directory?).and_call_original
|
|
75
|
+
allow(File).to receive(:directory?).with('modules').and_return(true)
|
|
76
|
+
|
|
77
|
+
expect(logger).to receive(:warn).with(/modules directory/)
|
|
78
|
+
|
|
79
|
+
deploy.deploy_local(repo, { skip_r10k: true })
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context 'when a previous run left an onceover manifest behind' do
|
|
84
|
+
it 'removes the files listed in the old manifest before copying the new tree' do
|
|
85
|
+
repo = build_repo('deploy_test')
|
|
86
|
+
production_dir = "#{tempdir}/#{repo.environmentpath}/production"
|
|
87
|
+
FileUtils.mkdir_p(production_dir)
|
|
88
|
+
stale_file = File.join(production_dir, 'stale_leftover.txt')
|
|
89
|
+
File.write(stale_file, 'leftover')
|
|
90
|
+
File.write(
|
|
91
|
+
File.join(production_dir, '.onceover_manifest.json'),
|
|
92
|
+
['stale_leftover.txt'].to_json
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
deploy.deploy_local(repo, { skip_r10k: true })
|
|
96
|
+
|
|
97
|
+
expect(File.exist?(stale_file)).to be false
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
context 'when the Puppetfile references :control_branch' do
|
|
102
|
+
it 'substitutes the current git branch in for :control_branch' do
|
|
103
|
+
repo = build_repo('control_branch')
|
|
104
|
+
|
|
105
|
+
allow(deploy).to receive(:system) do |_cmd|
|
|
106
|
+
Kernel.system('true')
|
|
107
|
+
true
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
deploy.deploy_local(repo, { skip_r10k: false })
|
|
111
|
+
|
|
112
|
+
production_dir = "#{tempdir}/#{repo.environmentpath}/production"
|
|
113
|
+
puppetfile_contents = File.read("#{production_dir}/Puppetfile")
|
|
114
|
+
expect(puppetfile_contents).not_to include(':control_branch')
|
|
115
|
+
current_branch = `git rev-parse --abbrev-ref HEAD`.chomp
|
|
116
|
+
expect(puppetfile_contents).to include("'#{current_branch}'")
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
context 'when auto_vendored is requested' do
|
|
121
|
+
it 'asks VendoredModules for missing modules and appends them to the Puppetfile' do
|
|
122
|
+
repo = build_repo('basic')
|
|
123
|
+
|
|
124
|
+
vendored_modules_double = instance_double(
|
|
125
|
+
'PuppetlabsOnceover::VendoredModules',
|
|
126
|
+
missing_vendored: [{ 'puppetlabs-mymodule' => { git: 'https://example.com/mymodule.git', ref: 'main' } }]
|
|
127
|
+
)
|
|
128
|
+
allow(vendored_modules_double).to receive(:puppetfile_missing_vendored)
|
|
129
|
+
allow(PuppetlabsOnceover::VendoredModules).to receive(:new).and_return(vendored_modules_double)
|
|
130
|
+
|
|
131
|
+
allow(deploy).to receive(:system) do |_cmd|
|
|
132
|
+
Kernel.system('true')
|
|
133
|
+
true
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
deploy.deploy_local(repo, { skip_r10k: false, auto_vendored: true })
|
|
137
|
+
|
|
138
|
+
production_dir = "#{tempdir}/#{repo.environmentpath}/production"
|
|
139
|
+
puppetfile_contents = File.read("#{production_dir}/Puppetfile")
|
|
140
|
+
expect(puppetfile_contents).to include('puppetlabs-mymodule')
|
|
141
|
+
expect(puppetfile_contents).to include('PuppetlabsOnceover Managed Vendored Modules')
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it 'leaves the Puppetfile untouched when there are no missing vendored modules' do
|
|
145
|
+
repo = build_repo('basic')
|
|
146
|
+
|
|
147
|
+
vendored_modules_double = instance_double(
|
|
148
|
+
'PuppetlabsOnceover::VendoredModules',
|
|
149
|
+
missing_vendored: []
|
|
150
|
+
)
|
|
151
|
+
allow(vendored_modules_double).to receive(:puppetfile_missing_vendored)
|
|
152
|
+
allow(PuppetlabsOnceover::VendoredModules).to receive(:new).and_return(vendored_modules_double)
|
|
153
|
+
|
|
154
|
+
allow(deploy).to receive(:system) do |_cmd|
|
|
155
|
+
Kernel.system('true')
|
|
156
|
+
true
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
deploy.deploy_local(repo, { skip_r10k: false, auto_vendored: true })
|
|
160
|
+
|
|
161
|
+
production_dir = "#{tempdir}/#{repo.environmentpath}/production"
|
|
162
|
+
puppetfile_contents = File.read("#{production_dir}/Puppetfile")
|
|
163
|
+
expect(puppetfile_contents).not_to include('PuppetlabsOnceover Managed Vendored Modules')
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
context 'when r10k succeeds' do
|
|
168
|
+
it 'runs r10k puppetfile install and returns the tempdir, honoring force/config/trace/debug opts' do
|
|
169
|
+
repo = build_repo('basic')
|
|
170
|
+
allow(repo).to receive(:r10k_config_file).and_return('/tmp/some-r10k.yaml')
|
|
171
|
+
logger.level = :debug
|
|
172
|
+
|
|
173
|
+
seen_cmd = nil
|
|
174
|
+
allow(deploy).to receive(:system) do |cmd|
|
|
175
|
+
seen_cmd = cmd
|
|
176
|
+
Kernel.system('true')
|
|
177
|
+
true
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
result = deploy.deploy_local(repo, { skip_r10k: false, force: true, trace: true })
|
|
181
|
+
|
|
182
|
+
expect(result).to eq(tempdir)
|
|
183
|
+
expect(seen_cmd).to include('r10k puppetfile install --color')
|
|
184
|
+
expect(seen_cmd).to include('--force')
|
|
185
|
+
expect(seen_cmd).to include('--config /tmp/some-r10k.yaml')
|
|
186
|
+
expect(seen_cmd).to include('--trace')
|
|
187
|
+
expect(seen_cmd).to include('--verbose debug')
|
|
188
|
+
|
|
189
|
+
logger.level = :info
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it 'passes plain --verbose (not --verbose debug) when the logger is above debug level' do
|
|
193
|
+
repo = build_repo('basic')
|
|
194
|
+
logger.level = :info
|
|
195
|
+
|
|
196
|
+
seen_cmd = nil
|
|
197
|
+
allow(deploy).to receive(:system) do |cmd|
|
|
198
|
+
seen_cmd = cmd
|
|
199
|
+
Kernel.system('true')
|
|
200
|
+
true
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
deploy.deploy_local(repo, { skip_r10k: false })
|
|
204
|
+
|
|
205
|
+
expect(seen_cmd).to match(/--verbose(?! debug)/)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
context 'when r10k fails' do
|
|
210
|
+
it 'raises an error' do
|
|
211
|
+
repo = build_repo('basic')
|
|
212
|
+
|
|
213
|
+
allow(deploy).to receive(:system) do |_cmd|
|
|
214
|
+
Kernel.system('false')
|
|
215
|
+
false
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
expect { deploy.deploy_local(repo, { skip_r10k: false }) }.to raise_error(
|
|
219
|
+
'r10k could not install all required modules'
|
|
220
|
+
)
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
context 'when repo.tempdir is nil' do
|
|
225
|
+
it 'creates a fresh tempdir via Dir.mktmpdir' do
|
|
226
|
+
repo = build_repo('minimal', tempdir_override: nil)
|
|
227
|
+
|
|
228
|
+
result = deploy.deploy_local(repo, {})
|
|
229
|
+
|
|
230
|
+
expect(result).not_to be_nil
|
|
231
|
+
expect(File.directory?(result)).to be true
|
|
232
|
+
FileUtils.rm_rf(result)
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# NOTE: the `else raise "#{repo.tempdir} is not a directory"` branch
|
|
237
|
+
# (deploy.rb, just after `if File.directory?(repo.tempdir)`) is left
|
|
238
|
+
# uncovered. Reaching it legitimately requires repo.tempdir to vanish
|
|
239
|
+
# between the copy step a few lines above and this check, and stubbing
|
|
240
|
+
# File.directory?(repo.tempdir) to force it false also fools FileUtils'
|
|
241
|
+
# own internal use of File.directory? earlier in the method (it calls
|
|
242
|
+
# mkdir_p on a path it now believes doesn't exist, which raises
|
|
243
|
+
# Errno::EEXIST instead of reaching the intended branch). Not worth
|
|
244
|
+
# fighting with a source change out of scope for this test pass.
|
|
245
|
+
end
|
|
246
|
+
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'puppetlabs-onceover/group'
|
|
3
|
+
require 'puppetlabs-onceover/class'
|
|
4
|
+
require 'puppetlabs-onceover/node'
|
|
5
|
+
require 'puppetlabs-onceover/testconfig'
|
|
6
|
+
require 'puppetlabs-onceover/controlrepo'
|
|
7
|
+
|
|
8
|
+
describe "PuppetlabsOnceover::Group" do
|
|
9
|
+
before(:each) do
|
|
10
|
+
PuppetlabsOnceover::Class.class_variable_set(:@@all, [])
|
|
11
|
+
PuppetlabsOnceover::Node.class_variable_set(:@@all, [])
|
|
12
|
+
PuppetlabsOnceover::Group.class_variable_set(:@@all, [])
|
|
13
|
+
PuppetlabsOnceover::Test.class_variable_set(:@@all, [])
|
|
14
|
+
logger.level = :fatal
|
|
15
|
+
PuppetlabsOnceover::Controlrepo.new(path: 'spec/fixtures/controlrepos/factsets')
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe "#initialize" do
|
|
19
|
+
it "accepts a ready-made list of Class objects as-is" do
|
|
20
|
+
a = PuppetlabsOnceover::Class.new('role::a')
|
|
21
|
+
b = PuppetlabsOnceover::Class.new('role::b')
|
|
22
|
+
group = PuppetlabsOnceover::Group.new('my_classes', [a, b])
|
|
23
|
+
expect(group.name).to eq('my_classes')
|
|
24
|
+
expect(group.members).to eq([a, b])
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "accepts a ready-made list of Node objects as-is" do
|
|
28
|
+
a = PuppetlabsOnceover::Node.new('node_a')
|
|
29
|
+
b = PuppetlabsOnceover::Node.new('node_b')
|
|
30
|
+
group = PuppetlabsOnceover::Group.new('my_nodes', [a, b])
|
|
31
|
+
expect(group.members).to eq([a, b])
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "defaults to an empty member list when members is nil" do
|
|
35
|
+
group = PuppetlabsOnceover::Group.new('empty_group', nil)
|
|
36
|
+
expect(group.members).to eq([])
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "resolves a hash into a subtractive include/exclude list via TestConfig.subtractive_to_list" do
|
|
40
|
+
a = PuppetlabsOnceover::Node.new('node_a')
|
|
41
|
+
b = PuppetlabsOnceover::Node.new('node_b')
|
|
42
|
+
PuppetlabsOnceover::Group.new('all_nodes', [a, b])
|
|
43
|
+
PuppetlabsOnceover::Group.new('excluded', [b])
|
|
44
|
+
|
|
45
|
+
group = PuppetlabsOnceover::Group.new('subtractive', { 'include' => 'all_nodes', 'exclude' => 'excluded' })
|
|
46
|
+
expect(group.members).to eq([a])
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "resolves a list of names/groups into member objects, flattening nested groups" do
|
|
50
|
+
a = PuppetlabsOnceover::Node.new('node_a')
|
|
51
|
+
b = PuppetlabsOnceover::Node.new('node_b')
|
|
52
|
+
PuppetlabsOnceover::Group.new('inner', [a])
|
|
53
|
+
|
|
54
|
+
group = PuppetlabsOnceover::Group.new('outer', %w[inner node_b])
|
|
55
|
+
expect(group.members).to eq([a, b])
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "raises when a resolved member list mixes classes and nodes" do
|
|
59
|
+
PuppetlabsOnceover::Class.new('role::a')
|
|
60
|
+
PuppetlabsOnceover::Node.new('node_a')
|
|
61
|
+
|
|
62
|
+
expect do
|
|
63
|
+
PuppetlabsOnceover::Group.new('mixed', ['role::a', 'node_a'])
|
|
64
|
+
end.to raise_error(RuntimeError, /must contain either all nodes or all classes/)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "adds itself to .all" do
|
|
68
|
+
group = PuppetlabsOnceover::Group.new('g', nil)
|
|
69
|
+
expect(PuppetlabsOnceover::Group.all).to eq([group])
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
describe ".find" do
|
|
74
|
+
it "finds a group by name" do
|
|
75
|
+
group = PuppetlabsOnceover::Group.new('g', nil)
|
|
76
|
+
expect(PuppetlabsOnceover::Group.find('g')).to eq(group)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "returns nil when no group matches" do
|
|
80
|
+
expect(PuppetlabsOnceover::Group.find('nope')).to be_nil
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
describe ".all" do
|
|
85
|
+
it "returns every group created so far" do
|
|
86
|
+
a = PuppetlabsOnceover::Group.new('a', nil)
|
|
87
|
+
b = PuppetlabsOnceover::Group.new('b', nil)
|
|
88
|
+
expect(PuppetlabsOnceover::Group.all).to eq([a, b])
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
describe ".valid_members?" do
|
|
93
|
+
it "is true for an all-Class list" do
|
|
94
|
+
a = PuppetlabsOnceover::Class.new('role::a')
|
|
95
|
+
expect(PuppetlabsOnceover::Group.valid_members?([a])).to eq(true)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "is true for an all-Node list" do
|
|
99
|
+
a = PuppetlabsOnceover::Node.new('node_a')
|
|
100
|
+
expect(PuppetlabsOnceover::Group.valid_members?([a])).to eq(true)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "is false for a mixed list" do
|
|
104
|
+
a = PuppetlabsOnceover::Class.new('role::a')
|
|
105
|
+
b = PuppetlabsOnceover::Node.new('node_a')
|
|
106
|
+
expect(PuppetlabsOnceover::Group.valid_members?([a, b])).to eq(false)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "is false for an empty list (all? on empty is true for the Class check, so this actually documents current behavior)" do
|
|
110
|
+
expect(PuppetlabsOnceover::Group.valid_members?([])).to eq(true)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "rescues any StandardError raised while checking and returns false" do
|
|
114
|
+
exploding = Object.new
|
|
115
|
+
def exploding.is_a?(*)
|
|
116
|
+
raise StandardError, 'boom'
|
|
117
|
+
end
|
|
118
|
+
expect(PuppetlabsOnceover::Group.valid_members?([exploding])).to eq(false)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'puppetlabs-onceover/logger'
|
|
3
|
+
|
|
4
|
+
describe PuppetlabsOnceover::Logger do
|
|
5
|
+
let(:includer) do
|
|
6
|
+
Class.new do
|
|
7
|
+
include PuppetlabsOnceover::Logger
|
|
8
|
+
end.new
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
before(:each) do
|
|
12
|
+
$logger = nil
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
after(:each) do
|
|
16
|
+
$logger = nil
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'lazily builds a Logging logger with a stdout appender on first call' do
|
|
20
|
+
logger = includer.logger
|
|
21
|
+
expect(logger).to eq(Logging.logger['Colors'])
|
|
22
|
+
expect(Logging::LNAMES[logger.level]).to eq('INFO')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'memoizes the logger across calls' do
|
|
26
|
+
first = includer.logger
|
|
27
|
+
second = includer.logger
|
|
28
|
+
expect(first).to equal(second)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'puppetlabs-onceover/node'
|
|
3
|
+
require 'puppetlabs-onceover/controlrepo'
|
|
4
|
+
|
|
5
|
+
describe "PuppetlabsOnceover::Node" do
|
|
6
|
+
before(:each) do
|
|
7
|
+
PuppetlabsOnceover::Node.class_variable_set(:@@all, [])
|
|
8
|
+
logger.level = :fatal
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe "#initialize" do
|
|
12
|
+
context "when the controlrepo's factsets can be found" do
|
|
13
|
+
before(:each) do
|
|
14
|
+
PuppetlabsOnceover::Controlrepo.new(path: 'spec/fixtures/controlrepos/factsets')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "sets the name and a nil beaker_node" do
|
|
18
|
+
node = PuppetlabsOnceover::Node.new('centos7_notrusted')
|
|
19
|
+
expect(node.name).to eq('centos7_notrusted')
|
|
20
|
+
expect(node.beaker_node).to be_nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "loads the fact_set from the matching factset file" do
|
|
24
|
+
node = PuppetlabsOnceover::Node.new('centos7_notrusted')
|
|
25
|
+
expect(node.fact_set).to be_a(Hash)
|
|
26
|
+
expect(node.fact_set['operatingsystem']).to eq('CentOS')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "strips the 'environment' key out of the fact_set via clean_facts" do
|
|
30
|
+
node = PuppetlabsOnceover::Node.new('centos_with_env')
|
|
31
|
+
expect(node.fact_set).not_to have_key('environment')
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "finds a top-level 'trusted' hash for trusted_set" do
|
|
35
|
+
node = PuppetlabsOnceover::Node.new('centos7_trusted_extensions_top')
|
|
36
|
+
expect(node.trusted_set).to eq({ 'pp_datacenter' => 'PDX' })
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "falls back to a nested trusted.extensions hash for trusted_set when no top-level trusted hash exists" do
|
|
40
|
+
node = PuppetlabsOnceover::Node.new('centos7_trusted_extensions_nested')
|
|
41
|
+
expect(node.trusted_set).to be_a(Hash)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "falls back to an empty hash for trusted_set when neither is present" do
|
|
45
|
+
node = PuppetlabsOnceover::Node.new('centos7_notrusted')
|
|
46
|
+
expect(node.trusted_set).to eq({})
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "falls back to a nested trusted.external hash for trusted_external_set when no top-level trusted_external hash exists" do
|
|
50
|
+
node = PuppetlabsOnceover::Node.new('centos7_trusted_external_nested')
|
|
51
|
+
expect(node.trusted_external_set).to be_a(Hash)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "falls back to an empty hash for trusted_external_set when neither is present" do
|
|
55
|
+
node = PuppetlabsOnceover::Node.new('centos7_notrusted')
|
|
56
|
+
expect(node.trusted_external_set).to eq({})
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "adds itself to .all" do
|
|
60
|
+
node = PuppetlabsOnceover::Node.new('centos7_notrusted')
|
|
61
|
+
expect(PuppetlabsOnceover::Node.all).to eq([node])
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
context "when no factset matches the given name" do
|
|
66
|
+
before(:each) do
|
|
67
|
+
PuppetlabsOnceover::Controlrepo.new(path: 'spec/fixtures/controlrepos/factsets')
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# facts_file_index comes back nil, so PuppetlabsOnceover::Controlrepo.facts[nil]
|
|
71
|
+
# raises TypeError -- this is the rescue branch that defaults everything to {}
|
|
72
|
+
it "rescues the TypeError and defaults fact_set/trusted_set/trusted_external_set to {}" do
|
|
73
|
+
node = PuppetlabsOnceover::Node.new('no_such_factset_anywhere')
|
|
74
|
+
expect(node.fact_set).to eq({})
|
|
75
|
+
expect(node.trusted_set).to eq({})
|
|
76
|
+
expect(node.trusted_external_set).to eq({})
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
describe ".find" do
|
|
82
|
+
before(:each) do
|
|
83
|
+
PuppetlabsOnceover::Controlrepo.new(path: 'spec/fixtures/controlrepos/factsets')
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "finds a node by name" do
|
|
87
|
+
node = PuppetlabsOnceover::Node.new('centos7_notrusted')
|
|
88
|
+
expect(PuppetlabsOnceover::Node.find('centos7_notrusted')).to eq(node)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "returns the same node object when passed a Node instance" do
|
|
92
|
+
node = PuppetlabsOnceover::Node.new('centos7_notrusted')
|
|
93
|
+
expect(PuppetlabsOnceover::Node.find(node)).to eq(node)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it "returns nil (and warns) when nothing matches" do
|
|
97
|
+
expect(PuppetlabsOnceover::Node.find('nonexistent')).to be_nil
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
describe ".all" do
|
|
102
|
+
before(:each) do
|
|
103
|
+
PuppetlabsOnceover::Controlrepo.new(path: 'spec/fixtures/controlrepos/factsets')
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "returns every node created so far" do
|
|
107
|
+
a = PuppetlabsOnceover::Node.new('centos7_notrusted')
|
|
108
|
+
b = PuppetlabsOnceover::Node.new('centos_with_env')
|
|
109
|
+
expect(PuppetlabsOnceover::Node.all).to eq([a, b])
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
describe ".clean_facts" do
|
|
114
|
+
it "deletes the 'environment' key and returns the factset" do
|
|
115
|
+
factset = { 'environment' => 'production', 'foo' => 'bar' }
|
|
116
|
+
expect(PuppetlabsOnceover::Node.clean_facts(factset)).to eq({ 'foo' => 'bar' })
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "is a no-op when there is no 'environment' key" do
|
|
120
|
+
factset = { 'foo' => 'bar' }
|
|
121
|
+
expect(PuppetlabsOnceover::Node.clean_facts(factset)).to eq({ 'foo' => 'bar' })
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|