chef 17.4.38-universal-mingw32 → 17.5.22-universal-mingw32
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/chef.gemspec +2 -0
- data/lib/chef/application/base.rb +11 -1
- data/lib/chef/client.rb +1 -2
- data/lib/chef/compliance/input.rb +115 -0
- data/lib/chef/compliance/input_collection.rb +139 -0
- data/lib/chef/compliance/profile.rb +122 -0
- data/lib/chef/compliance/profile_collection.rb +109 -0
- data/lib/chef/compliance/runner.rb +47 -5
- data/lib/chef/compliance/waiver.rb +115 -0
- data/lib/chef/compliance/waiver_collection.rb +143 -0
- data/lib/chef/dsl/compliance.rb +38 -0
- data/lib/chef/dsl/reader_helpers.rb +51 -0
- data/lib/chef/dsl/recipe.rb +4 -2
- data/lib/chef/dsl/secret.rb +2 -4
- data/lib/chef/dsl/universal.rb +2 -0
- data/lib/chef/event_dispatch/base.rb +44 -2
- data/lib/chef/formatters/doc.rb +46 -0
- data/lib/chef/http/basic_client.rb +15 -7
- data/lib/chef/http.rb +7 -3
- data/lib/chef/provider/file.rb +2 -0
- data/lib/chef/provider/link.rb +2 -2
- data/lib/chef/provider/registry_key.rb +3 -2
- data/lib/chef/provider/remote_file/http.rb +1 -1
- data/lib/chef/provider/template.rb +1 -1
- data/lib/chef/resource/archive_file.rb +17 -14
- data/lib/chef/resource/chef_client_scheduled_task.rb +45 -2
- data/lib/chef/resource/chocolatey_config.rb +13 -13
- data/lib/chef/resource/file/verification/json.rb +50 -0
- data/lib/chef/resource/file/verification/yaml.rb +52 -0
- data/lib/chef/resource/inspec_input.rb +128 -0
- data/lib/chef/resource/inspec_waiver.rb +185 -0
- data/lib/chef/resource/mount.rb +1 -1
- data/lib/chef/resource/registry_key.rb +36 -48
- data/lib/chef/resource/remote_file.rb +98 -2
- data/lib/chef/resource/timezone.rb +2 -2
- data/lib/chef/resource/user_ulimit.rb +1 -0
- data/lib/chef/resource/windows_printer.rb +1 -1
- data/lib/chef/resource/windows_uac.rb +3 -1
- data/lib/chef/resource/windows_user_privilege.rb +1 -1
- data/lib/chef/resources.rb +2 -0
- data/lib/chef/run_context/cookbook_compiler.rb +112 -28
- data/lib/chef/run_context.rb +31 -1
- data/lib/chef/secret_fetcher/akeyless_vault.rb +57 -0
- data/lib/chef/secret_fetcher/aws_secrets_manager.rb +1 -1
- data/lib/chef/secret_fetcher/azure_key_vault.rb +1 -1
- data/lib/chef/secret_fetcher/base.rb +1 -1
- data/lib/chef/secret_fetcher/hashi_vault.rb +100 -0
- data/lib/chef/secret_fetcher.rb +8 -2
- data/lib/chef/version.rb +1 -1
- data/spec/data/archive_file/test_archive.tar.gz +0 -0
- data/spec/functional/resource/archive_file_spec.rb +87 -0
- data/spec/functional/resource/group_spec.rb +5 -1
- data/spec/functional/resource/link_spec.rb +8 -0
- data/spec/integration/compliance/compliance_spec.rb +60 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/platform_helpers.rb +4 -0
- data/spec/support/ruby_installer.rb +51 -0
- data/spec/unit/compliance/input_spec.rb +104 -0
- data/spec/unit/compliance/profile_spec.rb +120 -0
- data/spec/unit/compliance/waiver_spec.rb +104 -0
- data/spec/unit/http/basic_client_spec.rb +30 -0
- data/spec/unit/http_spec.rb +8 -2
- data/spec/unit/provider/link_spec.rb +13 -7
- data/spec/unit/provider/remote_file/http_spec.rb +10 -0
- data/spec/unit/provider/template_spec.rb +2 -2
- data/spec/unit/resource/archive_file_spec.rb +414 -3
- data/spec/unit/resource/chef_client_scheduled_task_spec.rb +69 -0
- data/spec/unit/resource/file/verification/json_spec.rb +72 -0
- data/spec/unit/resource/file/verification/yaml_spec.rb +67 -0
- data/spec/unit/resource/inspec_input_spec.rb +300 -0
- data/spec/unit/resource/inspec_waiver_spec.rb +312 -0
- data/spec/unit/resource/mount_spec.rb +10 -0
- data/spec/unit/resource/user_ulimit_spec.rb +14 -1
- data/spec/unit/secret_fetcher/akeyless_vault_spec.rb +37 -0
- data/spec/unit/secret_fetcher/hashi_vault_spec.rb +80 -0
- data/tasks/rspec.rb +2 -1
- metadata +60 -6
@@ -17,19 +17,60 @@
|
|
17
17
|
|
18
18
|
require "spec_helper"
|
19
19
|
|
20
|
-
|
20
|
+
begin
|
21
|
+
require "ffi-libarchive"
|
22
|
+
rescue LoadError
|
23
|
+
module Archive
|
24
|
+
class Reader
|
25
|
+
def close; end
|
26
|
+
def each_entry; end
|
27
|
+
def extract(entry, flags = 0, destination: nil); end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Exclude this test on platforms where ffi-libarchive loading is broken
|
33
|
+
describe Chef::Resource::ArchiveFile, :libarchive_loading_broken do
|
21
34
|
let(:node) { Chef::Node.new }
|
22
35
|
let(:events) { Chef::EventDispatch::Dispatcher.new }
|
23
36
|
let(:run_context) { Chef::RunContext.new(node, {}, events) }
|
24
|
-
let(:
|
37
|
+
let(:destination) { Dir.mktmpdir }
|
38
|
+
let(:path) { File.expand_path("/tmp/foo.zip") }
|
39
|
+
let(:resource) do
|
40
|
+
r = Chef::Resource::ArchiveFile.new(path, run_context)
|
41
|
+
r.destination = destination
|
42
|
+
r
|
43
|
+
end
|
25
44
|
let(:provider) { resource.provider_for_action(:extract) }
|
45
|
+
let(:entry_time) { Time.new(2021, 5, 25, 2, 2, 0, "-05:00") }
|
46
|
+
let(:older_time) { entry_time - 100 }
|
47
|
+
let(:newer_time) { entry_time + 100 }
|
48
|
+
|
49
|
+
let(:archive_reader) { instance_double("Archive::Reader", close: nil) }
|
50
|
+
let(:archive_entry_1) { instance_double("Archive::Entry", pathname: "folder-1/", mtime: entry_time) }
|
51
|
+
let(:archive_entry_2) { instance_double("Archive::Entry", pathname: "folder-1/file-1.txt", mtime: entry_time) }
|
52
|
+
let(:archive_entry_3) { instance_double("Archive::Entry", pathname: "folder-1/folder-2/", mtime: entry_time) }
|
53
|
+
let(:archive_entry_4) { instance_double("Archive::Entry", pathname: "folder-1/folder-2/file-2.txt", mtime: entry_time) }
|
54
|
+
|
55
|
+
let(:archive_reader_with_strip_components_1) { instance_double("Archive::Reader", close: nil) }
|
56
|
+
let(:archive_entry_2_s1) { instance_double("Archive::Entry", pathname: "file-1.txt", mtime: entry_time) }
|
57
|
+
let(:archive_entry_3_s1) { instance_double("Archive::Entry", pathname: "folder-2/", mtime: entry_time) }
|
58
|
+
let(:archive_entry_4_s1) { instance_double("Archive::Entry", pathname: "folder-2/file-2.txt", mtime: entry_time) }
|
59
|
+
|
60
|
+
let(:archive_reader_with_strip_components_2) { instance_double("Archive::Reader", close: nil) }
|
61
|
+
let(:archive_entry_4_s2) { instance_double("Archive::Entry", pathname: "file-2.txt", mtime: entry_time) }
|
62
|
+
|
63
|
+
before do
|
64
|
+
allow(resource).to receive(:provider_for_action).with(:extract).and_return(provider)
|
65
|
+
end
|
26
66
|
|
27
67
|
it "has a resource name of :archive_file" do
|
28
68
|
expect(resource.resource_name).to eql(:archive_file)
|
29
69
|
end
|
30
70
|
|
31
71
|
it "has a name property of path" do
|
32
|
-
|
72
|
+
r = Chef::Resource::ArchiveFile.new("my-name", run_context)
|
73
|
+
expect(r.path).to match("my-name")
|
33
74
|
end
|
34
75
|
|
35
76
|
it "sets the default action as :extract" do
|
@@ -44,6 +85,376 @@ describe Chef::Resource::ArchiveFile do
|
|
44
85
|
expect(resource.mode).to eql("755")
|
45
86
|
end
|
46
87
|
|
88
|
+
it "strip_components property defaults to 0" do
|
89
|
+
expect(resource.strip_components).to eql(0)
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "#action_extract" do
|
93
|
+
before do
|
94
|
+
allow(FileUtils).to receive(:mkdir_p)
|
95
|
+
allow(File).to receive(:exist?).and_call_original
|
96
|
+
allow(File).to receive(:exist?).with(path).and_return(true)
|
97
|
+
allow(File).to receive(:exist?).with(destination).and_return(true)
|
98
|
+
|
99
|
+
allow(Archive::Reader).to receive(:open_filename).with(path, nil, strip_components: 0).and_return(archive_reader)
|
100
|
+
allow(archive_reader).to receive(:each_entry)
|
101
|
+
.and_yield(archive_entry_1)
|
102
|
+
.and_yield(archive_entry_2)
|
103
|
+
.and_yield(archive_entry_3)
|
104
|
+
.and_yield(archive_entry_4)
|
105
|
+
allow(archive_reader).to receive(:extract).with(archive_entry_1, any_args)
|
106
|
+
allow(archive_reader).to receive(:extract).with(archive_entry_2, any_args)
|
107
|
+
allow(archive_reader).to receive(:extract).with(archive_entry_3, any_args)
|
108
|
+
allow(archive_reader).to receive(:extract).with(archive_entry_4, any_args)
|
109
|
+
|
110
|
+
allow(Archive::Reader).to receive(:open_filename).with(path, nil, strip_components: 1).and_return(archive_reader_with_strip_components_1)
|
111
|
+
allow(archive_reader_with_strip_components_1).to receive(:each_entry)
|
112
|
+
.and_yield(archive_entry_2_s1)
|
113
|
+
.and_yield(archive_entry_3_s1)
|
114
|
+
.and_yield(archive_entry_4_s1)
|
115
|
+
allow(archive_reader_with_strip_components_1).to receive(:extract).with(archive_entry_2_s1, any_args)
|
116
|
+
allow(archive_reader_with_strip_components_1).to receive(:extract).with(archive_entry_3_s1, any_args)
|
117
|
+
allow(archive_reader_with_strip_components_1).to receive(:extract).with(archive_entry_4_s1, any_args)
|
118
|
+
|
119
|
+
allow(Archive::Reader).to receive(:open_filename).with(path, nil, strip_components: 2).and_return(archive_reader_with_strip_components_2)
|
120
|
+
allow(archive_reader_with_strip_components_2).to receive(:each_entry)
|
121
|
+
.and_yield(archive_entry_4_s2)
|
122
|
+
allow(archive_reader_with_strip_components_2).to receive(:extract).with(archive_entry_4_s2, any_args)
|
123
|
+
|
124
|
+
allow(File).to receive(:exist?).with("#{destination}/folder-1").and_return(true)
|
125
|
+
allow(File).to receive(:exist?).with("#{destination}/folder-1/file-1.txt").and_return(true)
|
126
|
+
allow(File).to receive(:exist?).with("#{destination}/folder-1/folder-2").and_return(true)
|
127
|
+
allow(File).to receive(:exist?).with("#{destination}/folder-1/folder-2/file-2.txt").and_return(true)
|
128
|
+
|
129
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1").and_return(entry_time)
|
130
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/file-1.txt").and_return(entry_time)
|
131
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2").and_return(entry_time)
|
132
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2/file-2.txt").and_return(entry_time)
|
133
|
+
|
134
|
+
resource.overwrite(true) # Force it to converge
|
135
|
+
end
|
136
|
+
|
137
|
+
context "when destination directory does not exist" do
|
138
|
+
before do
|
139
|
+
allow(File).to receive(:exist?).with(destination).and_return(false)
|
140
|
+
end
|
141
|
+
|
142
|
+
it "creates destination directory" do
|
143
|
+
expect(FileUtils).to receive(:mkdir_p).with(destination, { mode: 493 })
|
144
|
+
resource.run_action(:extract)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context "when destination directory exists" do
|
149
|
+
before do
|
150
|
+
allow(File).to receive(:exist?).with(destination).and_return(true)
|
151
|
+
end
|
152
|
+
|
153
|
+
it "does not create destination directory" do
|
154
|
+
expect(FileUtils).not_to receive(:mkdir_p)
|
155
|
+
resource.run_action(:extract)
|
156
|
+
end
|
157
|
+
|
158
|
+
context "when overwrite is set to false" do
|
159
|
+
before do
|
160
|
+
resource.overwrite(false)
|
161
|
+
end
|
162
|
+
|
163
|
+
context "when files on disk have identical modified times than what is in the archive" do
|
164
|
+
before do
|
165
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1").and_return(entry_time)
|
166
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/file-1.txt").and_return(entry_time)
|
167
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2").and_return(entry_time)
|
168
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2/file-2.txt").and_return(entry_time)
|
169
|
+
end
|
170
|
+
|
171
|
+
it "does not extract archive" do
|
172
|
+
expect(provider).not_to receive(:extract)
|
173
|
+
resource.run_action(:extract)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context "when files on disk have newer modified times than what is in the archive" do
|
178
|
+
before do
|
179
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1").and_return(newer_time)
|
180
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/file-1.txt").and_return(newer_time)
|
181
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2").and_return(newer_time)
|
182
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2/file-2.txt").and_return(newer_time)
|
183
|
+
end
|
184
|
+
|
185
|
+
it "does not extract archive" do
|
186
|
+
expect(provider).not_to receive(:extract)
|
187
|
+
resource.run_action(:extract)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
context "when files on disk have older modified times than what is in the archive" do
|
192
|
+
before do
|
193
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1").and_return(older_time)
|
194
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/file-1.txt").and_return(older_time)
|
195
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2").and_return(older_time)
|
196
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2/file-2.txt").and_return(older_time)
|
197
|
+
end
|
198
|
+
|
199
|
+
it "does not extract archive" do
|
200
|
+
expect(provider).not_to receive(:extract)
|
201
|
+
resource.run_action(:extract)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
context "when overwrite is set to true" do
|
207
|
+
before do
|
208
|
+
resource.overwrite(true)
|
209
|
+
end
|
210
|
+
|
211
|
+
context "when files on disk have identical modified times than what is in the archive" do
|
212
|
+
before do
|
213
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1").and_return(entry_time)
|
214
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/file-1.txt").and_return(entry_time)
|
215
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2").and_return(entry_time)
|
216
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2/file-2.txt").and_return(entry_time)
|
217
|
+
end
|
218
|
+
|
219
|
+
it "extracts archive" do
|
220
|
+
expect(provider).to receive(:extract)
|
221
|
+
resource.run_action(:extract)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
context "when files on disk have newer modified times than what is in the archive" do
|
226
|
+
before do
|
227
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1").and_return(newer_time)
|
228
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/file-1.txt").and_return(newer_time)
|
229
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2").and_return(newer_time)
|
230
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2/file-2.txt").and_return(newer_time)
|
231
|
+
end
|
232
|
+
|
233
|
+
it "extracts archive" do
|
234
|
+
expect(provider).to receive(:extract)
|
235
|
+
resource.run_action(:extract)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
context "when files on disk have older modified times than what is in the archive" do
|
240
|
+
before do
|
241
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1").and_return(older_time)
|
242
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/file-1.txt").and_return(older_time)
|
243
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2").and_return(older_time)
|
244
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2/file-2.txt").and_return(older_time)
|
245
|
+
end
|
246
|
+
|
247
|
+
it "extracts archive" do
|
248
|
+
expect(provider).to receive(:extract)
|
249
|
+
resource.run_action(:extract)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
context "when overwrite is set to :auto" do
|
255
|
+
before do
|
256
|
+
resource.overwrite(:auto)
|
257
|
+
end
|
258
|
+
|
259
|
+
context "when strip_components is set to 0" do
|
260
|
+
before do
|
261
|
+
resource.strip_components(0)
|
262
|
+
end
|
263
|
+
|
264
|
+
context "when files on disk have identical modified times than what is in the archive" do
|
265
|
+
before do
|
266
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1").and_return(entry_time)
|
267
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/file-1.txt").and_return(entry_time)
|
268
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2").and_return(entry_time)
|
269
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2/file-2.txt").and_return(entry_time)
|
270
|
+
end
|
271
|
+
|
272
|
+
context "when there is at least one missing files on disk" do
|
273
|
+
before do
|
274
|
+
expect(File).to receive(:exist?).with("#{destination}/folder-1").and_return(false)
|
275
|
+
expect(File).to receive(:exist?).with("#{destination}/folder-1/file-1.txt").and_return(true)
|
276
|
+
expect(File).to receive(:exist?).with("#{destination}/folder-1/folder-2").and_return(true)
|
277
|
+
expect(File).to receive(:exist?).with("#{destination}/folder-1/folder-2/file-2.txt").and_return(true)
|
278
|
+
end
|
279
|
+
|
280
|
+
it "extracts archive" do
|
281
|
+
expect(provider).to receive(:extract)
|
282
|
+
resource.run_action(:extract)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
context "when there are no missing files on disk" do
|
287
|
+
before do
|
288
|
+
expect(File).to receive(:exist?).with("#{destination}/folder-1").and_return(true)
|
289
|
+
expect(File).to receive(:exist?).with("#{destination}/folder-1/file-1.txt").and_return(true)
|
290
|
+
expect(File).to receive(:exist?).with("#{destination}/folder-1/folder-2").and_return(true)
|
291
|
+
expect(File).to receive(:exist?).with("#{destination}/folder-1/folder-2/file-2.txt").and_return(true)
|
292
|
+
end
|
293
|
+
|
294
|
+
it "does not extract archive" do
|
295
|
+
expect(provider).not_to receive(:extract)
|
296
|
+
resource.run_action(:extract)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
context "when strip_components is set to 1" do
|
303
|
+
before do
|
304
|
+
resource.strip_components(1)
|
305
|
+
end
|
306
|
+
|
307
|
+
context "when files on disk have identical modified times than what is in the archive" do
|
308
|
+
before do
|
309
|
+
allow(File).to receive(:mtime).with("#{destination}/file-1.txt").and_return(entry_time)
|
310
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-2").and_return(entry_time)
|
311
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-2/file-2.txt").and_return(entry_time)
|
312
|
+
end
|
313
|
+
|
314
|
+
context "when there is at least one missing files on disk" do
|
315
|
+
before do
|
316
|
+
expect(File).not_to receive(:exist?).with("#{destination}/folder-1")
|
317
|
+
expect(File).not_to receive(:exist?).with("#{destination}/folder-1/file-1.txt")
|
318
|
+
expect(File).not_to receive(:exist?).with("#{destination}/folder-1/folder-2")
|
319
|
+
expect(File).not_to receive(:exist?).with("#{destination}/folder-1/folder-2/file-2.txt")
|
320
|
+
expect(File).to receive(:exist?).with("#{destination}/file-1.txt").and_return(false)
|
321
|
+
expect(File).to receive(:exist?).with("#{destination}/folder-2").and_return(true)
|
322
|
+
expect(File).to receive(:exist?).with("#{destination}/folder-2/file-2.txt").and_return(true)
|
323
|
+
end
|
324
|
+
|
325
|
+
it "extracts archive" do
|
326
|
+
expect(provider).to receive(:extract)
|
327
|
+
resource.run_action(:extract)
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
context "when there are no missing files on disk" do
|
332
|
+
before do
|
333
|
+
expect(File).not_to receive(:exist?).with("#{destination}/folder-1")
|
334
|
+
expect(File).not_to receive(:exist?).with("#{destination}/folder-1/file-1.txt")
|
335
|
+
expect(File).not_to receive(:exist?).with("#{destination}/folder-1/folder-2")
|
336
|
+
expect(File).not_to receive(:exist?).with("#{destination}/folder-1/folder-2/file-2.txt")
|
337
|
+
expect(File).to receive(:exist?).with("#{destination}/file-1.txt").and_return(true)
|
338
|
+
expect(File).to receive(:exist?).with("#{destination}/folder-2").and_return(true)
|
339
|
+
expect(File).to receive(:exist?).with("#{destination}/folder-2/file-2.txt").and_return(true)
|
340
|
+
end
|
341
|
+
|
342
|
+
it "does not extract archive" do
|
343
|
+
expect(provider).not_to receive(:extract)
|
344
|
+
resource.run_action(:extract)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
context "when files on disk have newer modified times than what is in the archive" do
|
351
|
+
before do
|
352
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1").and_return(newer_time)
|
353
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/file-1.txt").and_return(newer_time)
|
354
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2").and_return(newer_time)
|
355
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2/file-2.txt").and_return(newer_time)
|
356
|
+
end
|
357
|
+
|
358
|
+
it "extracts archive" do
|
359
|
+
expect(provider).to receive(:extract)
|
360
|
+
resource.run_action(:extract)
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
context "when files on disk have older modified times than what is in the archive" do
|
365
|
+
before do
|
366
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1").and_return(older_time)
|
367
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/file-1.txt").and_return(older_time)
|
368
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2").and_return(older_time)
|
369
|
+
allow(File).to receive(:mtime).with("#{destination}/folder-1/folder-2/file-2.txt").and_return(older_time)
|
370
|
+
end
|
371
|
+
|
372
|
+
it "extracts archive" do
|
373
|
+
expect(provider).to receive(:extract)
|
374
|
+
resource.run_action(:extract)
|
375
|
+
end
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
context "when strip_components is set to 0" do
|
381
|
+
before do
|
382
|
+
resource.strip_components(0)
|
383
|
+
end
|
384
|
+
|
385
|
+
it "does not strip any paths" do
|
386
|
+
expect(archive_reader).to receive(:extract).with(archive_entry_1, 4)
|
387
|
+
expect(archive_reader).to receive(:extract).with(archive_entry_2, 4)
|
388
|
+
expect(archive_reader).to receive(:extract).with(archive_entry_3, 4)
|
389
|
+
expect(archive_reader).to receive(:extract).with(archive_entry_4, 4)
|
390
|
+
resource.run_action(:extract)
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
context "when strip_components is set to 1" do
|
395
|
+
before do
|
396
|
+
resource.strip_components(1)
|
397
|
+
end
|
398
|
+
|
399
|
+
it "strips leading number of paths specified in strip_components" do
|
400
|
+
expect(archive_reader_with_strip_components_1).to receive(:extract).with(archive_entry_2_s1, 4)
|
401
|
+
expect(archive_reader_with_strip_components_1).to receive(:extract).with(archive_entry_3_s1, 4)
|
402
|
+
expect(archive_reader_with_strip_components_1).to receive(:extract).with(archive_entry_4_s1, 4)
|
403
|
+
resource.run_action(:extract)
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
context "when strip_components is set to 2" do
|
408
|
+
before do
|
409
|
+
resource.strip_components(2)
|
410
|
+
end
|
411
|
+
|
412
|
+
it "strips leading number of paths specified in strip_components" do
|
413
|
+
expect(archive_reader_with_strip_components_2).to receive(:extract).with(archive_entry_4_s2, 4)
|
414
|
+
resource.run_action(:extract)
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
context "when owner property is set" do
|
419
|
+
before { resource.owner "root" }
|
420
|
+
|
421
|
+
it "chowns all archive file/directory paths" do
|
422
|
+
expect(FileUtils).to receive(:chown).with("root", nil, "#{destination}/folder-1/")
|
423
|
+
expect(FileUtils).to receive(:chown).with("root", nil, "#{destination}/folder-1/file-1.txt")
|
424
|
+
expect(FileUtils).to receive(:chown).with("root", nil, "#{destination}/folder-1/folder-2/")
|
425
|
+
expect(FileUtils).to receive(:chown).with("root", nil, "#{destination}/folder-1/folder-2/file-2.txt")
|
426
|
+
resource.run_action(:extract)
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
context "when group property is set" do
|
431
|
+
before { resource.group "root" }
|
432
|
+
|
433
|
+
it "chowns all archive file/directory paths" do
|
434
|
+
expect(FileUtils).to receive(:chown).with(nil, "root", "#{destination}/folder-1/")
|
435
|
+
expect(FileUtils).to receive(:chown).with(nil, "root", "#{destination}/folder-1/file-1.txt")
|
436
|
+
expect(FileUtils).to receive(:chown).with(nil, "root", "#{destination}/folder-1/folder-2/")
|
437
|
+
expect(FileUtils).to receive(:chown).with(nil, "root", "#{destination}/folder-1/folder-2/file-2.txt")
|
438
|
+
resource.run_action(:extract)
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
context "when owner and group properties are set" do
|
443
|
+
before do
|
444
|
+
resource.owner "root"
|
445
|
+
resource.group "root"
|
446
|
+
end
|
447
|
+
|
448
|
+
it "chowns all archive file/directory paths" do
|
449
|
+
expect(FileUtils).to receive(:chown).with("root", "root", "#{destination}/folder-1/")
|
450
|
+
expect(FileUtils).to receive(:chown).with("root", "root", "#{destination}/folder-1/file-1.txt")
|
451
|
+
expect(FileUtils).to receive(:chown).with("root", "root", "#{destination}/folder-1/folder-2/")
|
452
|
+
expect(FileUtils).to receive(:chown).with("root", "root", "#{destination}/folder-1/folder-2/file-2.txt")
|
453
|
+
resource.run_action(:extract)
|
454
|
+
end
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
47
458
|
it "mode property throws a deprecation warning if Integers are passed" do
|
48
459
|
expect(Chef::Log).to receive(:deprecation)
|
49
460
|
resource.mode 755
|
@@ -25,6 +25,11 @@ describe Chef::Resource::ChefClientScheduledTask do
|
|
25
25
|
let(:resource) { Chef::Resource::ChefClientScheduledTask.new("fakey_fakerton", run_context) }
|
26
26
|
let(:provider) { resource.provider_for_action(:add) }
|
27
27
|
|
28
|
+
before do
|
29
|
+
allow(ENV).to receive(:[]).and_call_original
|
30
|
+
allow(ENV).to receive(:[]).with("COMSPEC").and_return("C:\\Windows\\System32\\cmd.exe")
|
31
|
+
end
|
32
|
+
|
28
33
|
it "sets the default action as :add" do
|
29
34
|
expect(resource.action).to eql([:add])
|
30
35
|
end
|
@@ -73,11 +78,75 @@ describe Chef::Resource::ChefClientScheduledTask do
|
|
73
78
|
expect(resource.chef_binary_path).to eql("C:/opscode/chef/bin/chef-client")
|
74
79
|
end
|
75
80
|
|
81
|
+
context "priority" do
|
82
|
+
it "default value is 7" do
|
83
|
+
expect(resource.priority).to eq(7)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "raise error when priority value less than 0" do
|
87
|
+
expect { resource.priority(-1) }.to raise_error(Chef::Exceptions::ValidationFailed, "Option priority's value -1 should be in range of 0 to 10!")
|
88
|
+
end
|
89
|
+
|
90
|
+
it "raise error when priority values is greater than 10" do
|
91
|
+
expect { resource.priority 11 }.to raise_error(Chef::Exceptions::ValidationFailed, "Option priority's value 11 should be in range of 0 to 10!")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
76
95
|
it "supports :add and :remove actions" do
|
77
96
|
expect { resource.action :add }.not_to raise_error
|
78
97
|
expect { resource.action :remove }.not_to raise_error
|
79
98
|
end
|
80
99
|
|
100
|
+
it "expects use_consistent_splay to be true when set" do
|
101
|
+
resource.use_consistent_splay = true
|
102
|
+
expect(resource.use_consistent_splay).to eql(true)
|
103
|
+
end
|
104
|
+
|
105
|
+
context "when configured to use a consistent splay" do
|
106
|
+
before do
|
107
|
+
node.automatic_attrs[:shard_seed] = nil
|
108
|
+
allow(node).to receive(:name).and_return("test_node")
|
109
|
+
resource.config_directory = "C:/chef" # Allows local unit testing on nix flavors
|
110
|
+
resource.use_consistent_splay = true
|
111
|
+
end
|
112
|
+
|
113
|
+
it "sleeps the same amount each time based on splay before running the task" do
|
114
|
+
expect(provider.full_command).to eql("C:\\Windows\\System32\\cmd.exe /c \"C:/windows/system32/windowspowershell/v1.0/powershell.exe Start-Sleep -s 272 && C:/opscode/chef/bin/chef-client -L C:/chef/log/client.log -c C:/chef/client.rb\"")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "#consistent_splay_command" do
|
119
|
+
context "when use_consistent_splay is false" do
|
120
|
+
it "returns nil" do
|
121
|
+
expect(provider.consistent_splay_command).to eql(nil)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "when use_consistent_splay is true" do
|
126
|
+
before do
|
127
|
+
resource.use_consistent_splay true
|
128
|
+
allow(provider).to receive(:splay_sleep_time).and_return(222)
|
129
|
+
end
|
130
|
+
|
131
|
+
it "returns a powershell sleep command to be appended to the chef client run command" do
|
132
|
+
expect(provider.consistent_splay_command).to eql("C:/windows/system32/windowspowershell/v1.0/powershell.exe Start-Sleep -s 222 && ")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "#splay_sleep_time" do
|
138
|
+
it "uses shard_seed attribute if present" do
|
139
|
+
node.automatic_attrs[:shard_seed] = "73399073"
|
140
|
+
expect(provider.splay_sleep_time(300)).to satisfy { |v| v >= 0 && v <= 300 }
|
141
|
+
end
|
142
|
+
|
143
|
+
it "uses a hex conversion of a md5 hash of the splay if present" do
|
144
|
+
node.automatic_attrs[:shard_seed] = nil
|
145
|
+
allow(node).to receive(:name).and_return("test_node")
|
146
|
+
expect(provider.splay_sleep_time(300)).to satisfy { |v| v >= 0 && v <= 300 }
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
81
150
|
describe "#client_cmd" do
|
82
151
|
it "creates a valid command if using all default properties" do
|
83
152
|
expect(provider.client_cmd).to eql("C:/opscode/chef/bin/chef-client -L /etc/chef/log/client.log -c /etc/chef/client.rb") | eql("C:/opscode/chef/bin/chef-client -L C:\\chef/log/client.log -c C:\\chef/client.rb")
|
@@ -0,0 +1,72 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Antony Thomas (<antonydeepak@gmail.com>)
|
3
|
+
# Copyright:: Copyright (c) Facebook, Inc. and its affiliates.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require "spec_helper"
|
20
|
+
|
21
|
+
describe Chef::Resource::File::Verification::Json do
|
22
|
+
let(:parent_resource) { Chef::Resource.new("llama") }
|
23
|
+
|
24
|
+
before(:all) do
|
25
|
+
@valid_json = "valid-#{Time.now.to_i}.json"
|
26
|
+
f = File.new(@valid_json, "w")
|
27
|
+
f.write('{
|
28
|
+
"foo": "bar"
|
29
|
+
}')
|
30
|
+
f.close
|
31
|
+
|
32
|
+
@invalid_json = "invalid-#{Time.now.to_i}.json"
|
33
|
+
f = File.new(@invalid_json, "w")
|
34
|
+
f.write("{
|
35
|
+
'foo': 'bar'
|
36
|
+
}")
|
37
|
+
f.close
|
38
|
+
|
39
|
+
@empty_json = "empty-#{Time.now.to_i}.json"
|
40
|
+
File.new(@empty_json, "w").close
|
41
|
+
end
|
42
|
+
|
43
|
+
context "verify" do
|
44
|
+
it "returns true for valid json" do
|
45
|
+
v = Chef::Resource::File::Verification::Json.new(parent_resource, :json, {})
|
46
|
+
expect(v.verify(@valid_json)).to eq(true)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "returns false for invalid json" do
|
50
|
+
v = Chef::Resource::File::Verification::Json.new(parent_resource, :json, {})
|
51
|
+
expect(v.verify(@invalid_json)).to eq(false)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "returns true for empty file" do
|
55
|
+
# Expectation here is different from that of default JSON parser included in ruby 2.4+.
|
56
|
+
# The default parser considers empty string as invalid JSON
|
57
|
+
# https://stackoverflow.com/questions/30621802/why-does-json-parse-fail-with-the-empty-string,
|
58
|
+
# however JSONCompat parses an empty string to `nil`.
|
59
|
+
# We are retaining the behavior of JSONCompat for two reasons
|
60
|
+
# - It is universal inside Chef codebase
|
61
|
+
# - It can be helpful to not throw an error when a `file` or `template` is empty
|
62
|
+
v = Chef::Resource::File::Verification::Json.new(parent_resource, :json, {})
|
63
|
+
expect(v.verify(@empty_json)).to eq(true)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
after(:all) do
|
68
|
+
File.delete(@valid_json)
|
69
|
+
File.delete(@invalid_json)
|
70
|
+
File.delete(@empty_json)
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Antony Thomas (<antonydeepak@gmail.com>)
|
3
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require "spec_helper"
|
20
|
+
|
21
|
+
describe Chef::Resource::File::Verification::Yaml do
|
22
|
+
let(:parent_resource) { Chef::Resource.new("llama") }
|
23
|
+
|
24
|
+
before(:all) do
|
25
|
+
@valid_yaml = "valid-#{Time.now.to_i}.yaml"
|
26
|
+
f = File.new(@valid_yaml, "w")
|
27
|
+
f.write("# comment
|
28
|
+
svc:
|
29
|
+
mysqlPassword: sepppasswd
|
30
|
+
")
|
31
|
+
f.close
|
32
|
+
|
33
|
+
@invalid_yaml = "invalid-#{Time.now.to_i}.yaml"
|
34
|
+
f = File.new(@invalid_yaml, "w")
|
35
|
+
f.write("# comment
|
36
|
+
svc:
|
37
|
+
mysqlPassword: 'sepppasswd
|
38
|
+
")
|
39
|
+
f.close
|
40
|
+
|
41
|
+
@empty_yaml = "empty-#{Time.now.to_i}.yaml"
|
42
|
+
File.new(@empty_yaml, "w").close
|
43
|
+
end
|
44
|
+
|
45
|
+
context "verify" do
|
46
|
+
it "returns true for valid yaml" do
|
47
|
+
v = Chef::Resource::File::Verification::Yaml.new(parent_resource, :yaml, {})
|
48
|
+
expect(v.verify(@valid_yaml)).to eq(true)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "returns false for invalid yaml" do
|
52
|
+
v = Chef::Resource::File::Verification::Yaml.new(parent_resource, :yaml, {})
|
53
|
+
expect(v.verify(@invalid_yaml)).to eq(false)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "returns true for empty file" do
|
57
|
+
v = Chef::Resource::File::Verification::Yaml.new(parent_resource, :yaml, {})
|
58
|
+
expect(v.verify(@empty_yaml)).to eq(true)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
after(:all) do
|
63
|
+
File.delete(@valid_yaml)
|
64
|
+
File.delete(@invalid_yaml)
|
65
|
+
File.delete(@empty_yaml)
|
66
|
+
end
|
67
|
+
end
|