test-kitchen 1.2.1 → 1.3.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 +4 -4
- data/.cane +1 -1
- data/.rubocop.yml +3 -0
- data/.travis.yml +20 -9
- data/CHANGELOG.md +219 -108
- data/Gemfile +10 -6
- data/Guardfile +38 -9
- data/README.md +11 -1
- data/Rakefile +21 -37
- data/bin/kitchen +4 -4
- data/features/kitchen_action_commands.feature +161 -0
- data/features/kitchen_console_command.feature +34 -0
- data/features/kitchen_diagnose_command.feature +64 -0
- data/features/kitchen_init_command.feature +29 -17
- data/features/kitchen_list_command.feature +2 -2
- data/features/kitchen_login_command.feature +56 -0
- data/features/{sink_command.feature → kitchen_sink_command.feature} +0 -0
- data/features/kitchen_test_command.feature +88 -0
- data/features/step_definitions/gem_steps.rb +8 -6
- data/features/step_definitions/git_steps.rb +4 -2
- data/features/step_definitions/output_steps.rb +5 -0
- data/features/support/env.rb +12 -9
- data/lib/kitchen.rb +60 -38
- data/lib/kitchen/base64_stream.rb +55 -0
- data/lib/kitchen/busser.rb +124 -58
- data/lib/kitchen/cli.rb +121 -38
- data/lib/kitchen/collection.rb +3 -3
- data/lib/kitchen/color.rb +4 -4
- data/lib/kitchen/command.rb +78 -11
- data/lib/kitchen/command/action.rb +3 -2
- data/lib/kitchen/command/console.rb +12 -5
- data/lib/kitchen/command/diagnose.rb +17 -3
- data/lib/kitchen/command/driver_discover.rb +26 -7
- data/lib/kitchen/command/exec.rb +41 -0
- data/lib/kitchen/command/list.rb +44 -14
- data/lib/kitchen/command/login.rb +2 -1
- data/lib/kitchen/command/sink.rb +2 -1
- data/lib/kitchen/command/test.rb +5 -4
- data/lib/kitchen/config.rb +146 -14
- data/lib/kitchen/configurable.rb +314 -0
- data/lib/kitchen/data_munger.rb +522 -18
- data/lib/kitchen/diagnostic.rb +43 -4
- data/lib/kitchen/driver.rb +4 -4
- data/lib/kitchen/driver/base.rb +80 -115
- data/lib/kitchen/driver/dummy.rb +34 -6
- data/lib/kitchen/driver/proxy.rb +14 -3
- data/lib/kitchen/driver/ssh_base.rb +61 -7
- data/lib/kitchen/errors.rb +109 -9
- data/lib/kitchen/generator/driver_create.rb +39 -5
- data/lib/kitchen/generator/init.rb +130 -45
- data/lib/kitchen/instance.rb +162 -28
- data/lib/kitchen/lazy_hash.rb +79 -7
- data/lib/kitchen/loader/yaml.rb +159 -27
- data/lib/kitchen/logger.rb +267 -21
- data/lib/kitchen/logging.rb +30 -3
- data/lib/kitchen/login_command.rb +11 -2
- data/lib/kitchen/metadata_chopper.rb +2 -2
- data/lib/kitchen/provisioner.rb +4 -4
- data/lib/kitchen/provisioner/base.rb +107 -103
- data/lib/kitchen/provisioner/chef/berkshelf.rb +36 -8
- data/lib/kitchen/provisioner/chef/librarian.rb +40 -11
- data/lib/kitchen/provisioner/chef_base.rb +206 -167
- data/lib/kitchen/provisioner/chef_solo.rb +25 -7
- data/lib/kitchen/provisioner/chef_zero.rb +105 -29
- data/lib/kitchen/provisioner/dummy.rb +1 -1
- data/lib/kitchen/provisioner/shell.rb +21 -6
- data/lib/kitchen/rake_tasks.rb +8 -3
- data/lib/kitchen/shell_out.rb +15 -18
- data/lib/kitchen/ssh.rb +122 -27
- data/lib/kitchen/state_file.rb +24 -7
- data/lib/kitchen/thor_tasks.rb +9 -4
- data/lib/kitchen/util.rb +43 -118
- data/lib/kitchen/version.rb +1 -1
- data/lib/vendor/hash_recursive_merge.rb +10 -2
- data/spec/kitchen/base64_stream_spec.rb +77 -0
- data/spec/kitchen/busser_spec.rb +490 -0
- data/spec/kitchen/collection_spec.rb +10 -10
- data/spec/kitchen/color_spec.rb +2 -2
- data/spec/kitchen/config_spec.rb +234 -62
- data/spec/kitchen/configurable_spec.rb +490 -0
- data/spec/kitchen/data_munger_spec.rb +1070 -862
- data/spec/kitchen/diagnostic_spec.rb +79 -0
- data/spec/kitchen/driver/base_spec.rb +80 -85
- data/spec/kitchen/driver/dummy_spec.rb +43 -14
- data/spec/kitchen/driver/proxy_spec.rb +134 -0
- data/spec/kitchen/driver/ssh_base_spec.rb +644 -0
- data/spec/kitchen/driver_spec.rb +15 -15
- data/spec/kitchen/errors_spec.rb +309 -0
- data/spec/kitchen/instance_spec.rb +143 -46
- data/spec/kitchen/lazy_hash_spec.rb +36 -9
- data/spec/kitchen/loader/yaml_spec.rb +237 -226
- data/spec/kitchen/logger_spec.rb +419 -0
- data/spec/kitchen/logging_spec.rb +59 -0
- data/spec/kitchen/login_command_spec.rb +49 -0
- data/spec/kitchen/metadata_chopper_spec.rb +82 -0
- data/spec/kitchen/platform_spec.rb +4 -4
- data/spec/kitchen/provisioner/base_spec.rb +65 -125
- data/spec/kitchen/provisioner/chef_base_spec.rb +798 -0
- data/spec/kitchen/provisioner/chef_solo_spec.rb +316 -0
- data/spec/kitchen/provisioner/chef_zero_spec.rb +624 -0
- data/spec/kitchen/provisioner/shell_spec.rb +269 -0
- data/spec/kitchen/provisioner_spec.rb +6 -6
- data/spec/kitchen/shell_out_spec.rb +143 -0
- data/spec/kitchen/ssh_spec.rb +683 -0
- data/spec/kitchen/state_file_spec.rb +28 -21
- data/spec/kitchen/suite_spec.rb +7 -7
- data/spec/kitchen/util_spec.rb +68 -10
- data/spec/kitchen_spec.rb +107 -0
- data/spec/spec_helper.rb +18 -13
- data/support/chef-client-zero.rb +10 -9
- data/support/chef_helpers.sh +16 -0
- data/support/download_helpers.sh +109 -0
- data/test-kitchen.gemspec +42 -33
- metadata +107 -33
@@ -0,0 +1,316 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2014, Fletcher Nichol
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require_relative "../../spec_helper"
|
20
|
+
|
21
|
+
require "kitchen"
|
22
|
+
require "kitchen/provisioner/chef_solo"
|
23
|
+
|
24
|
+
describe Kitchen::Provisioner::ChefSolo do
|
25
|
+
|
26
|
+
let(:logged_output) { StringIO.new }
|
27
|
+
let(:logger) { Logger.new(logged_output) }
|
28
|
+
|
29
|
+
let(:config) do
|
30
|
+
{ :test_base_path => "/b", :kitchen_root => "/r", :log_level => :info }
|
31
|
+
end
|
32
|
+
|
33
|
+
let(:suite) do
|
34
|
+
stub(:name => "fries")
|
35
|
+
end
|
36
|
+
|
37
|
+
let(:instance) do
|
38
|
+
stub(:name => "coolbeans", :logger => logger, :suite => suite)
|
39
|
+
end
|
40
|
+
|
41
|
+
let(:provisioner) do
|
42
|
+
Kitchen::Provisioner::ChefSolo.new(config).finalize_config!(instance)
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "default config" do
|
46
|
+
|
47
|
+
it "sets :solo_rb to an empty Hash" do
|
48
|
+
provisioner[:solo_rb].must_equal Hash.new
|
49
|
+
end
|
50
|
+
|
51
|
+
it "sets :chef_solo_path to a path using :chef_omnibus_root" do
|
52
|
+
config[:chef_omnibus_root] = "/nice/place"
|
53
|
+
|
54
|
+
provisioner[:chef_solo_path].must_equal "/nice/place/bin/chef-solo"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#create_sandbox" do
|
59
|
+
|
60
|
+
before do
|
61
|
+
@root = Dir.mktmpdir
|
62
|
+
config[:kitchen_root] = @root
|
63
|
+
end
|
64
|
+
|
65
|
+
after do
|
66
|
+
FileUtils.remove_entry(@root)
|
67
|
+
begin
|
68
|
+
provisioner.cleanup_sandbox
|
69
|
+
rescue # rubocop:disable Lint/HandleExceptions
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "solo.rb file" do
|
74
|
+
|
75
|
+
let(:file) do
|
76
|
+
IO.read(sandbox_path("solo.rb")).lines.map(&:chomp)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "creates a solo.rb" do
|
80
|
+
provisioner.create_sandbox
|
81
|
+
|
82
|
+
sandbox_path("solo.rb").file?.must_equal true
|
83
|
+
end
|
84
|
+
|
85
|
+
it "logs a message on info" do
|
86
|
+
provisioner.create_sandbox
|
87
|
+
|
88
|
+
logged_output.string.must_match info_line("Preparing solo.rb")
|
89
|
+
end
|
90
|
+
|
91
|
+
it "logs a message on debug" do
|
92
|
+
provisioner.create_sandbox
|
93
|
+
|
94
|
+
logged_output.string.
|
95
|
+
must_match debug_line_starting_with("Creating solo.rb from {")
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "defaults" do
|
99
|
+
|
100
|
+
before { provisioner.create_sandbox }
|
101
|
+
|
102
|
+
it "sets node_name to the instance name" do
|
103
|
+
file.must_include %{node_name "#{instance.name}"}
|
104
|
+
end
|
105
|
+
|
106
|
+
it "sets checksum_path" do
|
107
|
+
file.must_include %{checksum_path "/tmp/kitchen/checksums"}
|
108
|
+
end
|
109
|
+
|
110
|
+
it "sets file_backup_path" do
|
111
|
+
file.must_include %{file_backup_path "/tmp/kitchen/backup"}
|
112
|
+
end
|
113
|
+
|
114
|
+
it "sets cookbook_path" do
|
115
|
+
file.must_include %{cookbook_path } +
|
116
|
+
%{["/tmp/kitchen/cookbooks", "/tmp/kitchen/site-cookbooks"]}
|
117
|
+
end
|
118
|
+
|
119
|
+
it "sets data_bag_path" do
|
120
|
+
file.must_include %{data_bag_path "/tmp/kitchen/data_bags"}
|
121
|
+
end
|
122
|
+
|
123
|
+
it "sets environment_path" do
|
124
|
+
file.must_include %{environment_path "/tmp/kitchen/environments"}
|
125
|
+
end
|
126
|
+
|
127
|
+
it "sets node_path" do
|
128
|
+
file.must_include %{node_path "/tmp/kitchen/nodes"}
|
129
|
+
end
|
130
|
+
|
131
|
+
it "sets role_path" do
|
132
|
+
file.must_include %{role_path "/tmp/kitchen/roles"}
|
133
|
+
end
|
134
|
+
|
135
|
+
it "sets client_path" do
|
136
|
+
file.must_include %{client_path "/tmp/kitchen/clients"}
|
137
|
+
end
|
138
|
+
|
139
|
+
it "sets user_path" do
|
140
|
+
file.must_include %{user_path "/tmp/kitchen/users"}
|
141
|
+
end
|
142
|
+
|
143
|
+
it "sets validation_key" do
|
144
|
+
file.must_include %{validation_key "/tmp/kitchen/validation.pem"}
|
145
|
+
end
|
146
|
+
|
147
|
+
it "sets client_key" do
|
148
|
+
file.must_include %{client_key "/tmp/kitchen/client.pem"}
|
149
|
+
end
|
150
|
+
|
151
|
+
it "sets chef_server_url" do
|
152
|
+
file.must_include %{chef_server_url "http://127.0.0.1:8889"}
|
153
|
+
end
|
154
|
+
|
155
|
+
it "sets encrypted_data_bag_secret" do
|
156
|
+
file.must_include %{encrypted_data_bag_secret } +
|
157
|
+
%{"/tmp/kitchen/encrypted_data_bag_secret"}
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
it "supports overwriting defaults" do
|
162
|
+
config[:solo_rb] = {
|
163
|
+
:node_name => "eagles",
|
164
|
+
:user_path => "/a/b/c/u",
|
165
|
+
:client_key => "lol"
|
166
|
+
}
|
167
|
+
provisioner.create_sandbox
|
168
|
+
|
169
|
+
file.must_include %{node_name "eagles"}
|
170
|
+
file.must_include %{user_path "/a/b/c/u"}
|
171
|
+
file.must_include %{client_key "lol"}
|
172
|
+
end
|
173
|
+
|
174
|
+
it " supports adding new configuration" do
|
175
|
+
config[:solo_rb] = {
|
176
|
+
:dark_secret => "golang"
|
177
|
+
}
|
178
|
+
provisioner.create_sandbox
|
179
|
+
|
180
|
+
file.must_include %{dark_secret "golang"}
|
181
|
+
end
|
182
|
+
|
183
|
+
it "formats array values correctly" do
|
184
|
+
config[:solo_rb] = {
|
185
|
+
:foos => %w[foo1 foo2]
|
186
|
+
}
|
187
|
+
provisioner.create_sandbox
|
188
|
+
|
189
|
+
file.must_include %{foos ["foo1", "foo2"]}
|
190
|
+
end
|
191
|
+
|
192
|
+
it "formats integer values correctly" do
|
193
|
+
config[:solo_rb] = {
|
194
|
+
:foo => 7
|
195
|
+
}
|
196
|
+
provisioner.create_sandbox
|
197
|
+
|
198
|
+
file.must_include %{foo 7}
|
199
|
+
end
|
200
|
+
|
201
|
+
it "formats symbol values correctly" do
|
202
|
+
config[:solo_rb] = {
|
203
|
+
:foo => :bar
|
204
|
+
}
|
205
|
+
provisioner.create_sandbox
|
206
|
+
|
207
|
+
file.must_include %{foo :bar}
|
208
|
+
end
|
209
|
+
|
210
|
+
it "formats boolean values correctly" do
|
211
|
+
config[:solo_rb] = {
|
212
|
+
:foo => false,
|
213
|
+
:bar => true
|
214
|
+
}
|
215
|
+
provisioner.create_sandbox
|
216
|
+
|
217
|
+
file.must_include %{foo false}
|
218
|
+
file.must_include %{bar true}
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def sandbox_path(path)
|
223
|
+
Pathname.new(provisioner.sandbox_path).join(path)
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
describe "#run_command" do
|
229
|
+
|
230
|
+
let(:cmd) { provisioner.run_command }
|
231
|
+
|
232
|
+
it "uses bourne shell" do
|
233
|
+
cmd.must_match(/\Ash -c '$/)
|
234
|
+
cmd.must_match(/'\Z/)
|
235
|
+
end
|
236
|
+
|
237
|
+
it "uses sudo for chef-solo when configured" do
|
238
|
+
config[:chef_omnibus_root] = "/c"
|
239
|
+
config[:sudo] = true
|
240
|
+
|
241
|
+
cmd.must_match regexify("sudo -E /c/bin/chef-solo ", :partial_line)
|
242
|
+
end
|
243
|
+
|
244
|
+
it "does not use sudo for chef-solo when configured" do
|
245
|
+
config[:chef_omnibus_root] = "/c"
|
246
|
+
config[:sudo] = false
|
247
|
+
|
248
|
+
cmd.must_match regexify("chef-solo ", :partial_line)
|
249
|
+
cmd.wont_match regexify("sudo -E /c/bin/chef-solo ", :partial_line)
|
250
|
+
end
|
251
|
+
|
252
|
+
it "sets config flag on chef-solo" do
|
253
|
+
cmd.must_match regexify(" --config /tmp/kitchen/solo.rb", :partial_line)
|
254
|
+
end
|
255
|
+
|
256
|
+
it "sets config flag for custom root_path" do
|
257
|
+
config[:root_path] = "/a/b"
|
258
|
+
|
259
|
+
cmd.must_match regexify(" --config /a/b/solo.rb", :partial_line)
|
260
|
+
end
|
261
|
+
|
262
|
+
it "sets json attributes flag on chef-solo" do
|
263
|
+
cmd.must_match regexify(
|
264
|
+
" --json-attributes /tmp/kitchen/dna.json", :partial_line)
|
265
|
+
end
|
266
|
+
|
267
|
+
it "sets json attribtes flag for custom root_path" do
|
268
|
+
config[:root_path] = "/booyah"
|
269
|
+
|
270
|
+
cmd.must_match regexify(
|
271
|
+
" --json-attributes /booyah/dna.json", :partial_line)
|
272
|
+
end
|
273
|
+
|
274
|
+
it "sets log level flag on chef-solo to auto by default" do
|
275
|
+
cmd.must_match regexify(" --log_level auto", :partial_line)
|
276
|
+
end
|
277
|
+
|
278
|
+
it "set log level flag for custom level" do
|
279
|
+
config[:log_level] = :extreme
|
280
|
+
|
281
|
+
cmd.must_match regexify(" --log_level extreme", :partial_line)
|
282
|
+
end
|
283
|
+
|
284
|
+
it "sets force formatter flag on chef-solo" do
|
285
|
+
cmd.must_match regexify(" --force-formatter", :partial_line)
|
286
|
+
end
|
287
|
+
|
288
|
+
it "sets no color flag on chef-solo" do
|
289
|
+
cmd.must_match regexify(" --no-color", :partial_line)
|
290
|
+
end
|
291
|
+
|
292
|
+
it "does not set logfile flag by default" do
|
293
|
+
cmd.wont_match regexify(" --logfile ", :partial_line)
|
294
|
+
end
|
295
|
+
|
296
|
+
it "sets logfile flag for custom value" do
|
297
|
+
config[:log_file] = "/a/out.log"
|
298
|
+
|
299
|
+
cmd.must_match regexify(" --logfile /a/out.log", :partial_line)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
def info_line(msg)
|
304
|
+
%r{^I, .* : #{Regexp.escape(msg)}$}
|
305
|
+
end
|
306
|
+
|
307
|
+
def debug_line_starting_with(msg)
|
308
|
+
%r{^D, .* : #{Regexp.escape(msg)}}
|
309
|
+
end
|
310
|
+
|
311
|
+
def regexify(str, line = :whole_line)
|
312
|
+
r = Regexp.escape(str)
|
313
|
+
r = "^\s*#{r}$" if line == :whole_line
|
314
|
+
Regexp.new(r)
|
315
|
+
end
|
316
|
+
end
|
@@ -0,0 +1,624 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2014, Fletcher Nichol
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require_relative "../../spec_helper"
|
20
|
+
|
21
|
+
require "kitchen"
|
22
|
+
require "kitchen/provisioner/chef_zero"
|
23
|
+
|
24
|
+
describe Kitchen::Provisioner::ChefZero do
|
25
|
+
|
26
|
+
let(:logged_output) { StringIO.new }
|
27
|
+
let(:logger) { Logger.new(logged_output) }
|
28
|
+
|
29
|
+
let(:config) do
|
30
|
+
{ :test_base_path => "/b", :kitchen_root => "/r", :log_level => :info }
|
31
|
+
end
|
32
|
+
|
33
|
+
let(:suite) do
|
34
|
+
stub(:name => "fries")
|
35
|
+
end
|
36
|
+
|
37
|
+
let(:instance) do
|
38
|
+
stub(:name => "coolbeans", :logger => logger, :suite => suite)
|
39
|
+
end
|
40
|
+
|
41
|
+
let(:provisioner) do
|
42
|
+
Kitchen::Provisioner::ChefZero.new(config).finalize_config!(instance)
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "default config" do
|
46
|
+
|
47
|
+
it "sets :client_rb to an empty Hash" do
|
48
|
+
provisioner[:client_rb].must_equal Hash.new
|
49
|
+
end
|
50
|
+
|
51
|
+
it "sets :chef_client_path to a path using :chef_omnibus_root" do
|
52
|
+
config[:chef_omnibus_root] = "/nice/place"
|
53
|
+
|
54
|
+
provisioner[:chef_client_path].must_equal "/nice/place/bin/chef-client"
|
55
|
+
end
|
56
|
+
|
57
|
+
it "sets :ruby_bindir to use an Omnibus Ruby" do
|
58
|
+
provisioner[:ruby_bindir].must_equal "/opt/chef/embedded/bin"
|
59
|
+
end
|
60
|
+
|
61
|
+
it "sets :json_attributes to true" do
|
62
|
+
provisioner[:json_attributes].must_equal true
|
63
|
+
end
|
64
|
+
|
65
|
+
it "does not set :chef_zero_host" do
|
66
|
+
provisioner[:chef_zero_host].must_equal nil
|
67
|
+
end
|
68
|
+
|
69
|
+
it "sets :chef_zero_port to 8889" do
|
70
|
+
provisioner[:chef_zero_port].must_equal 8889
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#create_sandbox" do
|
75
|
+
|
76
|
+
before do
|
77
|
+
@root = Dir.mktmpdir
|
78
|
+
config[:kitchen_root] = @root
|
79
|
+
end
|
80
|
+
|
81
|
+
after do
|
82
|
+
FileUtils.remove_entry(@root)
|
83
|
+
begin
|
84
|
+
provisioner.cleanup_sandbox
|
85
|
+
rescue # rubocop:disable Lint/HandleExceptions
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "client.rb file" do
|
90
|
+
|
91
|
+
let(:file) do
|
92
|
+
IO.read(sandbox_path("client.rb")).lines.map(&:chomp)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "creates a client.rb" do
|
96
|
+
provisioner.create_sandbox
|
97
|
+
|
98
|
+
sandbox_path("client.rb").file?.must_equal true
|
99
|
+
end
|
100
|
+
|
101
|
+
it "logs a message on info" do
|
102
|
+
provisioner.create_sandbox
|
103
|
+
|
104
|
+
logged_output.string.must_match info_line("Preparing client.rb")
|
105
|
+
end
|
106
|
+
|
107
|
+
it "logs a message on debug" do
|
108
|
+
provisioner.create_sandbox
|
109
|
+
|
110
|
+
logged_output.string.
|
111
|
+
must_match debug_line_starting_with("Creating client.rb from {")
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "defaults" do
|
115
|
+
|
116
|
+
before { provisioner.create_sandbox }
|
117
|
+
|
118
|
+
it "sets node_name to the instance name" do
|
119
|
+
file.must_include %{node_name "#{instance.name}"}
|
120
|
+
end
|
121
|
+
|
122
|
+
it "sets checksum_path" do
|
123
|
+
file.must_include %{checksum_path "/tmp/kitchen/checksums"}
|
124
|
+
end
|
125
|
+
|
126
|
+
it "sets file_backup_path" do
|
127
|
+
file.must_include %{file_backup_path "/tmp/kitchen/backup"}
|
128
|
+
end
|
129
|
+
|
130
|
+
it "sets cookbook_path" do
|
131
|
+
file.must_include %{cookbook_path } +
|
132
|
+
%{["/tmp/kitchen/cookbooks", "/tmp/kitchen/site-cookbooks"]}
|
133
|
+
end
|
134
|
+
|
135
|
+
it "sets data_bag_path" do
|
136
|
+
file.must_include %{data_bag_path "/tmp/kitchen/data_bags"}
|
137
|
+
end
|
138
|
+
|
139
|
+
it "sets environment_path" do
|
140
|
+
file.must_include %{environment_path "/tmp/kitchen/environments"}
|
141
|
+
end
|
142
|
+
|
143
|
+
it "sets node_path" do
|
144
|
+
file.must_include %{node_path "/tmp/kitchen/nodes"}
|
145
|
+
end
|
146
|
+
|
147
|
+
it "sets role_path" do
|
148
|
+
file.must_include %{role_path "/tmp/kitchen/roles"}
|
149
|
+
end
|
150
|
+
|
151
|
+
it "sets client_path" do
|
152
|
+
file.must_include %{client_path "/tmp/kitchen/clients"}
|
153
|
+
end
|
154
|
+
|
155
|
+
it "sets user_path" do
|
156
|
+
file.must_include %{user_path "/tmp/kitchen/users"}
|
157
|
+
end
|
158
|
+
|
159
|
+
it "sets validation_key" do
|
160
|
+
file.must_include %{validation_key "/tmp/kitchen/validation.pem"}
|
161
|
+
end
|
162
|
+
|
163
|
+
it "sets client_key" do
|
164
|
+
file.must_include %{client_key "/tmp/kitchen/client.pem"}
|
165
|
+
end
|
166
|
+
|
167
|
+
it "sets chef_server_url" do
|
168
|
+
file.must_include %{chef_server_url "http://127.0.0.1:8889"}
|
169
|
+
end
|
170
|
+
|
171
|
+
it "sets encrypted_data_bag_secret" do
|
172
|
+
file.must_include %{encrypted_data_bag_secret } +
|
173
|
+
%{"/tmp/kitchen/encrypted_data_bag_secret"}
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
it "supports overwriting defaults" do
|
178
|
+
config[:client_rb] = {
|
179
|
+
:node_name => "eagles",
|
180
|
+
:user_path => "/a/b/c/u",
|
181
|
+
:client_key => "lol"
|
182
|
+
}
|
183
|
+
provisioner.create_sandbox
|
184
|
+
|
185
|
+
file.must_include %{node_name "eagles"}
|
186
|
+
file.must_include %{user_path "/a/b/c/u"}
|
187
|
+
file.must_include %{client_key "lol"}
|
188
|
+
end
|
189
|
+
|
190
|
+
it " supports adding new configuration" do
|
191
|
+
config[:client_rb] = {
|
192
|
+
:dark_secret => "golang"
|
193
|
+
}
|
194
|
+
provisioner.create_sandbox
|
195
|
+
|
196
|
+
file.must_include %{dark_secret "golang"}
|
197
|
+
end
|
198
|
+
|
199
|
+
it "formats array values correctly" do
|
200
|
+
config[:client_rb] = {
|
201
|
+
:foos => %w[foo1 foo2]
|
202
|
+
}
|
203
|
+
provisioner.create_sandbox
|
204
|
+
|
205
|
+
file.must_include %{foos ["foo1", "foo2"]}
|
206
|
+
end
|
207
|
+
|
208
|
+
it "formats integer values correctly" do
|
209
|
+
config[:client_rb] = {
|
210
|
+
:foo => 7
|
211
|
+
}
|
212
|
+
provisioner.create_sandbox
|
213
|
+
|
214
|
+
file.must_include %{foo 7}
|
215
|
+
end
|
216
|
+
|
217
|
+
it "formats symbol values correctly" do
|
218
|
+
config[:client_rb] = {
|
219
|
+
:foo => :bar
|
220
|
+
}
|
221
|
+
provisioner.create_sandbox
|
222
|
+
|
223
|
+
file.must_include %{foo :bar}
|
224
|
+
end
|
225
|
+
|
226
|
+
it "formats boolean values correctly" do
|
227
|
+
config[:client_rb] = {
|
228
|
+
:foo => false,
|
229
|
+
:bar => true
|
230
|
+
}
|
231
|
+
provisioner.create_sandbox
|
232
|
+
|
233
|
+
file.must_include %{foo false}
|
234
|
+
file.must_include %{bar true}
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
describe "validation.pem file" do
|
239
|
+
|
240
|
+
it "creates file" do
|
241
|
+
provisioner.create_sandbox
|
242
|
+
|
243
|
+
sandbox_path("validation.pem").file?.must_equal true
|
244
|
+
end
|
245
|
+
|
246
|
+
it "logs a message on info" do
|
247
|
+
provisioner.create_sandbox
|
248
|
+
|
249
|
+
logged_output.string.must_match info_line("Preparing validation.pem")
|
250
|
+
end
|
251
|
+
|
252
|
+
it "logs a message on debug" do
|
253
|
+
provisioner.create_sandbox
|
254
|
+
|
255
|
+
logged_output.string.
|
256
|
+
must_match debug_line_starting_with("Using a dummy validation.pem")
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
describe "chef-client-zero.rb file" do
|
261
|
+
|
262
|
+
describe "for modern Chef versions" do
|
263
|
+
|
264
|
+
before { config[:require_chef_omnibus] = "11.10" }
|
265
|
+
|
266
|
+
it "does not create the file" do
|
267
|
+
provisioner.create_sandbox
|
268
|
+
|
269
|
+
sandbox_path("chef-client-zero.rb").file?.must_equal false
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
describe "for old Chef versions" do
|
274
|
+
|
275
|
+
before { config[:require_chef_omnibus] = "10.20" }
|
276
|
+
|
277
|
+
it "creates the file when using an old Chef version" do
|
278
|
+
provisioner.create_sandbox
|
279
|
+
|
280
|
+
sandbox_path("chef-client-zero.rb").file?.must_equal true
|
281
|
+
end
|
282
|
+
|
283
|
+
it "logs a message on info" do
|
284
|
+
provisioner.create_sandbox
|
285
|
+
|
286
|
+
logged_output.string.
|
287
|
+
must_match info_line("Preparing chef-client-zero.rb")
|
288
|
+
end
|
289
|
+
|
290
|
+
it "logs a message on debug" do
|
291
|
+
provisioner.create_sandbox
|
292
|
+
|
293
|
+
logged_output.string.must_match debug_line_starting_with(
|
294
|
+
"Using a vendored chef-client-zero.rb")
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
def sandbox_path(path)
|
300
|
+
Pathname.new(provisioner.sandbox_path).join(path)
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
describe "#prepare_command" do
|
305
|
+
|
306
|
+
let(:cmd) { provisioner.prepare_command }
|
307
|
+
|
308
|
+
describe "for modern Chef versions" do
|
309
|
+
|
310
|
+
before { config[:require_chef_omnibus] = "11.10" }
|
311
|
+
|
312
|
+
it "returns nil" do
|
313
|
+
cmd.must_equal nil
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
describe "for old Chef versions" do
|
318
|
+
|
319
|
+
before do
|
320
|
+
config[:require_chef_omnibus] = "10.20"
|
321
|
+
config[:ruby_bindir] = "/rbd"
|
322
|
+
end
|
323
|
+
|
324
|
+
it "uses bourne shell" do
|
325
|
+
cmd.must_match(/\Ash -c '$/)
|
326
|
+
cmd.must_match(/'\Z/)
|
327
|
+
end
|
328
|
+
|
329
|
+
it "sets the CHEF_REPO_PATH environment variable" do
|
330
|
+
config[:root_path] = "/r"
|
331
|
+
|
332
|
+
cmd.must_match regexify(%{CHEF_REPO_PATH="/r" }, :partial_line)
|
333
|
+
end
|
334
|
+
|
335
|
+
it "sets the GEM_HOME environment variable" do
|
336
|
+
config[:root_path] = "/r"
|
337
|
+
|
338
|
+
cmd.must_match regexify(
|
339
|
+
%{GEM_HOME="/r/chef-client-zero-gems" }, :partial_line)
|
340
|
+
end
|
341
|
+
|
342
|
+
it "sets the GEM_PATH environment variable" do
|
343
|
+
config[:root_path] = "/r"
|
344
|
+
|
345
|
+
cmd.must_match regexify(
|
346
|
+
%{GEM_PATH="/r/chef-client-zero-gems" }, :partial_line)
|
347
|
+
end
|
348
|
+
|
349
|
+
it "sets the GEM_CACHE environment variable" do
|
350
|
+
config[:root_path] = "/r"
|
351
|
+
|
352
|
+
cmd.must_match regexify(
|
353
|
+
%{GEM_CACHE="/r/chef-client-zero-gems/cache" }, :partial_line)
|
354
|
+
end
|
355
|
+
|
356
|
+
it "exports all the environment variables" do
|
357
|
+
cmd.must_match regexify(
|
358
|
+
"export CHEF_REPO_PATH GEM_HOME GEM_PATH GEM_CACHE;", :partial_line)
|
359
|
+
end
|
360
|
+
|
361
|
+
it "checks if chef-zero is installed" do
|
362
|
+
cmd.must_match regexify(
|
363
|
+
%{if ! sudo -E /rbd/gem list chef-zero -i >/dev/null; then})
|
364
|
+
end
|
365
|
+
|
366
|
+
it "installs the chef gem" do
|
367
|
+
cmd.must_match regexify(
|
368
|
+
%{sudo -E /rbd/gem install chef --no-ri --no-rdoc --conservative})
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
describe "#run_command" do
|
374
|
+
|
375
|
+
let(:cmd) { provisioner.run_command }
|
376
|
+
|
377
|
+
describe "for modern Chef versions" do
|
378
|
+
|
379
|
+
before { config[:require_chef_omnibus] = "11.10" }
|
380
|
+
|
381
|
+
it "uses bourne shell" do
|
382
|
+
cmd.must_match(/\Ash -c '$/)
|
383
|
+
cmd.must_match(/'\Z/)
|
384
|
+
end
|
385
|
+
|
386
|
+
it "uses sudo for chef-client when configured" do
|
387
|
+
config[:chef_omnibus_root] = "/c"
|
388
|
+
config[:sudo] = true
|
389
|
+
|
390
|
+
cmd.must_match regexify("sudo -E /c/bin/chef-client ", :partial_line)
|
391
|
+
end
|
392
|
+
|
393
|
+
it "does not use sudo for chef-client when configured" do
|
394
|
+
config[:chef_omnibus_root] = "/c"
|
395
|
+
config[:sudo] = false
|
396
|
+
|
397
|
+
cmd.must_match regexify("/c/bin/chef-client ", :partial_line)
|
398
|
+
cmd.wont_match regexify("sudo -E /c/bin/chef-client ", :partial_line)
|
399
|
+
end
|
400
|
+
|
401
|
+
it "sets local mode flag on chef-client" do
|
402
|
+
cmd.must_match regexify(" --local-mode", :partial_line)
|
403
|
+
end
|
404
|
+
|
405
|
+
it "sets config flag on chef-client" do
|
406
|
+
cmd.must_match regexify(
|
407
|
+
" --config /tmp/kitchen/client.rb", :partial_line)
|
408
|
+
end
|
409
|
+
|
410
|
+
it "sets config flag for custom root_path" do
|
411
|
+
config[:root_path] = "/a/b"
|
412
|
+
|
413
|
+
cmd.must_match regexify(" --config /a/b/client.rb", :partial_line)
|
414
|
+
end
|
415
|
+
|
416
|
+
it "sets log level flag on chef-client to auto by default" do
|
417
|
+
cmd.must_match regexify(" --log_level auto", :partial_line)
|
418
|
+
end
|
419
|
+
|
420
|
+
it "set log level flag for custom level" do
|
421
|
+
config[:log_level] = :extreme
|
422
|
+
|
423
|
+
cmd.must_match regexify(" --log_level extreme", :partial_line)
|
424
|
+
end
|
425
|
+
|
426
|
+
it "sets force formatter flag on chef-solo" do
|
427
|
+
cmd.must_match regexify(" --force-formatter", :partial_line)
|
428
|
+
end
|
429
|
+
|
430
|
+
it "sets no color flag on chef-solo" do
|
431
|
+
cmd.must_match regexify(" --no-color", :partial_line)
|
432
|
+
end
|
433
|
+
|
434
|
+
it "sets chef zero port flag on chef-client" do
|
435
|
+
cmd.must_match regexify(" --chef-zero-port 8889", :partial_line)
|
436
|
+
end
|
437
|
+
|
438
|
+
it "sets chef zero host flag for custom host" do
|
439
|
+
config[:chef_zero_host] = "192.168.0.1"
|
440
|
+
|
441
|
+
cmd.must_match regexify(" --chef-zero-host 192.168.0.1", :partial_line)
|
442
|
+
end
|
443
|
+
|
444
|
+
it "sets chef zero port flag for custom port" do
|
445
|
+
config[:chef_zero_port] = 123
|
446
|
+
|
447
|
+
cmd.must_match regexify(" --chef-zero-port 123", :partial_line)
|
448
|
+
end
|
449
|
+
|
450
|
+
it "does not set chef zero host flag when value is falsey" do
|
451
|
+
config[:chef_zero_host] = nil
|
452
|
+
|
453
|
+
cmd.wont_match regexify(" --chef-zero-host ", :partial_line)
|
454
|
+
end
|
455
|
+
|
456
|
+
it "does not set chef zero port flag when value is falsey" do
|
457
|
+
config[:chef_zero_port] = nil
|
458
|
+
|
459
|
+
cmd.wont_match regexify(" --chef-zero-port ", :partial_line)
|
460
|
+
end
|
461
|
+
|
462
|
+
it "sets json attributes flag on chef-client" do
|
463
|
+
cmd.must_match regexify(
|
464
|
+
" --json-attributes /tmp/kitchen/dna.json", :partial_line)
|
465
|
+
end
|
466
|
+
|
467
|
+
it "sets json attribtes flag for custom root_path" do
|
468
|
+
config[:root_path] = "/booyah"
|
469
|
+
|
470
|
+
cmd.must_match regexify(
|
471
|
+
" --json-attributes /booyah/dna.json", :partial_line)
|
472
|
+
end
|
473
|
+
|
474
|
+
it "does not set json attributes flag if config is falsey" do
|
475
|
+
config[:json_attributes] = false
|
476
|
+
|
477
|
+
cmd.wont_match regexify(" --json-attributes ", :partial_line)
|
478
|
+
end
|
479
|
+
|
480
|
+
it "does not set logfile flag by default" do
|
481
|
+
cmd.wont_match regexify(" --logfile ", :partial_line)
|
482
|
+
end
|
483
|
+
|
484
|
+
it "sets logfile flag for custom value" do
|
485
|
+
config[:log_file] = "/a/out.log"
|
486
|
+
|
487
|
+
cmd.must_match regexify(" --logfile /a/out.log", :partial_line)
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
describe "for old Chef versions" do
|
492
|
+
|
493
|
+
before do
|
494
|
+
config[:require_chef_omnibus] = "10.20"
|
495
|
+
config[:ruby_bindir] = "/r/bin"
|
496
|
+
end
|
497
|
+
|
498
|
+
it "uses bourne shell" do
|
499
|
+
cmd.must_match(/\Ash -c '$/)
|
500
|
+
cmd.must_match(/'\Z/)
|
501
|
+
end
|
502
|
+
|
503
|
+
it "uses sudo for ruby when configured" do
|
504
|
+
config[:root_path] = "/x"
|
505
|
+
config[:sudo] = true
|
506
|
+
|
507
|
+
cmd.must_match regexify(
|
508
|
+
"sudo -E /r/bin/ruby /x/chef-client-zero.rb ", :partial_line)
|
509
|
+
end
|
510
|
+
|
511
|
+
it "does not use sudo for ruby when configured" do
|
512
|
+
config[:root_path] = "/x"
|
513
|
+
config[:sudo] = false
|
514
|
+
|
515
|
+
cmd.must_match regexify(
|
516
|
+
"/r/bin/ruby /x/chef-client-zero.rb ", :partial_line)
|
517
|
+
cmd.wont_match regexify(
|
518
|
+
"sudo -E /r/bin/ruby /x/chef-client-zero.rb ", :partial_line)
|
519
|
+
end
|
520
|
+
|
521
|
+
it "does not set local mode flag" do
|
522
|
+
cmd.wont_match regexify(" --local-mode", :partial_line)
|
523
|
+
end
|
524
|
+
|
525
|
+
it "sets config flag on chef-client" do
|
526
|
+
cmd.must_match regexify(
|
527
|
+
" --config /tmp/kitchen/client.rb", :partial_line)
|
528
|
+
end
|
529
|
+
|
530
|
+
it "sets config flag for custom root_path" do
|
531
|
+
config[:root_path] = "/a/b"
|
532
|
+
|
533
|
+
cmd.must_match regexify(" --config /a/b/client.rb", :partial_line)
|
534
|
+
end
|
535
|
+
|
536
|
+
it "sets log level flag on chef-client to auto by default" do
|
537
|
+
cmd.must_match regexify(" --log_level auto", :partial_line)
|
538
|
+
end
|
539
|
+
|
540
|
+
it "set log level flag for custom level" do
|
541
|
+
config[:log_level] = :extreme
|
542
|
+
|
543
|
+
cmd.must_match regexify(" --log_level extreme", :partial_line)
|
544
|
+
end
|
545
|
+
|
546
|
+
it "sets force formatter flag on chef-solo" do
|
547
|
+
cmd.must_match regexify(" --force-formatter", :partial_line)
|
548
|
+
end
|
549
|
+
|
550
|
+
it "sets no color flag on chef-solo" do
|
551
|
+
cmd.must_match regexify(" --no-color", :partial_line)
|
552
|
+
end
|
553
|
+
|
554
|
+
it "sets json attributes flag on chef-client" do
|
555
|
+
cmd.must_match regexify(
|
556
|
+
" --json-attributes /tmp/kitchen/dna.json", :partial_line)
|
557
|
+
end
|
558
|
+
|
559
|
+
it "sets json attribtes flag for custom root_path" do
|
560
|
+
config[:root_path] = "/booyah"
|
561
|
+
|
562
|
+
cmd.must_match regexify(
|
563
|
+
" --json-attributes /booyah/dna.json", :partial_line)
|
564
|
+
end
|
565
|
+
|
566
|
+
it "does not set json attributes flag if config is falsey" do
|
567
|
+
config[:json_attributes] = false
|
568
|
+
|
569
|
+
cmd.wont_match regexify(" --json-attributes ", :partial_line)
|
570
|
+
end
|
571
|
+
|
572
|
+
it "does not set logfile flag by default" do
|
573
|
+
cmd.wont_match regexify(" --logfile ", :partial_line)
|
574
|
+
end
|
575
|
+
|
576
|
+
it "sets logfile flag for custom value" do
|
577
|
+
config[:log_file] = "/a/out.log"
|
578
|
+
|
579
|
+
cmd.must_match regexify(" --logfile /a/out.log", :partial_line)
|
580
|
+
end
|
581
|
+
|
582
|
+
it "sets the CHEF_REPO_PATH environment variable" do
|
583
|
+
config[:root_path] = "/r"
|
584
|
+
|
585
|
+
cmd.must_match regexify(%{CHEF_REPO_PATH="/r" }, :partial_line)
|
586
|
+
end
|
587
|
+
|
588
|
+
it "sets the GEM_HOME environment variable" do
|
589
|
+
config[:root_path] = "/r"
|
590
|
+
|
591
|
+
cmd.must_match regexify(
|
592
|
+
%{GEM_HOME="/r/chef-client-zero-gems" }, :partial_line)
|
593
|
+
end
|
594
|
+
|
595
|
+
it "sets the GEM_PATH environment variable" do
|
596
|
+
config[:root_path] = "/r"
|
597
|
+
|
598
|
+
cmd.must_match regexify(
|
599
|
+
%{GEM_PATH="/r/chef-client-zero-gems" }, :partial_line)
|
600
|
+
end
|
601
|
+
|
602
|
+
it "sets the GEM_CACHE environment variable" do
|
603
|
+
config[:root_path] = "/r"
|
604
|
+
|
605
|
+
cmd.must_match regexify(
|
606
|
+
%{GEM_CACHE="/r/chef-client-zero-gems/cache" }, :partial_line)
|
607
|
+
end
|
608
|
+
end
|
609
|
+
end
|
610
|
+
|
611
|
+
def info_line(msg)
|
612
|
+
%r{^I, .* : #{Regexp.escape(msg)}$}
|
613
|
+
end
|
614
|
+
|
615
|
+
def debug_line_starting_with(msg)
|
616
|
+
%r{^D, .* : #{Regexp.escape(msg)}}
|
617
|
+
end
|
618
|
+
|
619
|
+
def regexify(str, line = :whole_line)
|
620
|
+
r = Regexp.escape(str)
|
621
|
+
r = "^\s*#{r}$" if line == :whole_line
|
622
|
+
Regexp.new(r)
|
623
|
+
end
|
624
|
+
end
|