cheffish 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +10 -0
  3. data/LICENSE +201 -201
  4. data/README.md +120 -120
  5. data/Rakefile +23 -23
  6. data/cheffish.gemspec +26 -0
  7. data/lib/chef/provider/chef_acl.rb +446 -439
  8. data/lib/chef/provider/chef_client.rb +53 -53
  9. data/lib/chef/provider/chef_container.rb +55 -55
  10. data/lib/chef/provider/chef_data_bag.rb +55 -55
  11. data/lib/chef/provider/chef_data_bag_item.rb +278 -278
  12. data/lib/chef/provider/chef_environment.rb +83 -83
  13. data/lib/chef/provider/chef_group.rb +83 -83
  14. data/lib/chef/provider/chef_mirror.rb +169 -169
  15. data/lib/chef/provider/chef_node.rb +87 -87
  16. data/lib/chef/provider/chef_organization.rb +155 -155
  17. data/lib/chef/provider/chef_resolved_cookbooks.rb +46 -46
  18. data/lib/chef/provider/chef_role.rb +84 -84
  19. data/lib/chef/provider/chef_user.rb +59 -59
  20. data/lib/chef/provider/private_key.rb +225 -225
  21. data/lib/chef/provider/public_key.rb +88 -88
  22. data/lib/chef/resource/chef_acl.rb +69 -69
  23. data/lib/chef/resource/chef_client.rb +48 -48
  24. data/lib/chef/resource/chef_container.rb +22 -22
  25. data/lib/chef/resource/chef_data_bag.rb +22 -22
  26. data/lib/chef/resource/chef_data_bag_item.rb +121 -121
  27. data/lib/chef/resource/chef_environment.rb +77 -77
  28. data/lib/chef/resource/chef_group.rb +53 -53
  29. data/lib/chef/resource/chef_mirror.rb +52 -52
  30. data/lib/chef/resource/chef_node.rb +22 -22
  31. data/lib/chef/resource/chef_organization.rb +69 -69
  32. data/lib/chef/resource/chef_resolved_cookbooks.rb +35 -35
  33. data/lib/chef/resource/chef_role.rb +110 -110
  34. data/lib/chef/resource/chef_user.rb +56 -56
  35. data/lib/chef/resource/private_key.rb +48 -48
  36. data/lib/chef/resource/public_key.rb +25 -25
  37. data/lib/cheffish.rb +235 -235
  38. data/lib/cheffish/actor_provider_base.rb +131 -131
  39. data/lib/cheffish/basic_chef_client.rb +184 -184
  40. data/lib/cheffish/chef_provider_base.rb +246 -246
  41. data/lib/cheffish/chef_run.rb +162 -162
  42. data/lib/cheffish/chef_run_data.rb +19 -19
  43. data/lib/cheffish/chef_run_listener.rb +30 -30
  44. data/lib/cheffish/key_formatter.rb +113 -113
  45. data/lib/cheffish/merged_config.rb +98 -94
  46. data/lib/cheffish/recipe_dsl.rb +157 -157
  47. data/lib/cheffish/rspec.rb +8 -8
  48. data/lib/cheffish/rspec/chef_run_support.rb +83 -83
  49. data/lib/cheffish/rspec/matchers.rb +4 -4
  50. data/lib/cheffish/rspec/matchers/be_idempotent.rb +16 -16
  51. data/lib/cheffish/rspec/matchers/emit_no_warnings_or_errors.rb +15 -15
  52. data/lib/cheffish/rspec/matchers/have_updated.rb +37 -37
  53. data/lib/cheffish/rspec/matchers/partially_match.rb +63 -63
  54. data/lib/cheffish/rspec/recipe_run_wrapper.rb +78 -78
  55. data/lib/cheffish/rspec/repository_support.rb +108 -108
  56. data/lib/cheffish/server_api.rb +52 -52
  57. data/lib/cheffish/version.rb +3 -3
  58. data/lib/cheffish/with_pattern.rb +21 -21
  59. data/spec/functional/fingerprint_spec.rb +64 -64
  60. data/spec/functional/merged_config_spec.rb +19 -19
  61. data/spec/functional/server_api_spec.rb +13 -13
  62. data/spec/integration/chef_acl_spec.rb +892 -879
  63. data/spec/integration/chef_client_spec.rb +105 -105
  64. data/spec/integration/chef_container_spec.rb +33 -33
  65. data/spec/integration/chef_group_spec.rb +309 -309
  66. data/spec/integration/chef_mirror_spec.rb +491 -491
  67. data/spec/integration/chef_node_spec.rb +786 -786
  68. data/spec/integration/chef_organization_spec.rb +226 -226
  69. data/spec/integration/chef_role_spec.rb +78 -78
  70. data/spec/integration/chef_user_spec.rb +85 -85
  71. data/spec/integration/private_key_spec.rb +399 -399
  72. data/spec/integration/recipe_dsl_spec.rb +28 -28
  73. data/spec/integration/rspec/converge_spec.rb +183 -183
  74. data/spec/support/key_support.rb +29 -29
  75. data/spec/support/spec_support.rb +15 -15
  76. data/spec/unit/get_private_key_spec.rb +131 -131
  77. data/spec/unit/recipe_run_wrapper_spec.rb +37 -37
  78. metadata +7 -5
@@ -1,491 +1,491 @@
1
- require 'support/spec_support'
2
- require 'cheffish/rspec/chef_run_support'
3
- require 'chef/resource/chef_mirror'
4
- require 'chef/provider/chef_mirror'
5
-
6
- describe Chef::Resource::ChefMirror do
7
- extend Cheffish::RSpec::ChefRunSupport
8
-
9
- when_the_chef_12_server 'is in multi-org mode' do
10
- organization 'foo'
11
-
12
- before :each do
13
- Chef::Config.chef_server_url = URI.join(Chef::Config.chef_server_url, '/organizations/foo').to_s
14
- end
15
-
16
- describe 'basic download and upload' do
17
- when_the_repository 'is full of stuff' do
18
- file 'nodes/x.json', {}
19
- file 'roles/x.json', {}
20
- directory 'cookbooks/x' do
21
- file 'metadata.rb', 'name "x"; version "2.0.0"'
22
- end
23
-
24
- it "Download grabs defaults" do
25
- expect_recipe {
26
- chef_mirror '' do
27
- action :download
28
- end
29
- }.to have_updated('chef_mirror[]', :download)
30
- expect(File.exist?(path_to('groups/admins.json'))).to be true
31
- expect(File.exist?(path_to('environments/_default.json'))).to be true
32
- end
33
-
34
- it "Upload uploads everything" do
35
- expect_recipe {
36
- chef_mirror '' do
37
- action :upload
38
- end
39
- }.to have_updated('chef_mirror[]', :upload)
40
- expect { get('nodes/x') }.not_to raise_error
41
- expect { get('roles/x') }.not_to raise_error
42
- expect { get('cookbooks/x/2.0.0') }.not_to raise_error
43
- end
44
-
45
- it 'chef_mirror with concurrency 0 fails with a reasonable message' do
46
- expect {
47
- converge {
48
- chef_mirror '' do
49
- concurrency 0
50
- action :download
51
- end
52
- }
53
- }.to raise_error /chef_mirror.concurrency must be above 0/
54
- end
55
- end
56
- end
57
-
58
- context 'and the Chef server has a node and role in it' do
59
- node 'x', {}
60
- role 'x', {}
61
-
62
- when_the_repository 'is empty' do
63
- it "Download grabs the node and role" do
64
- expect_recipe {
65
- chef_mirror '' do
66
- action :download
67
- end
68
- }.to have_updated('chef_mirror[]', :download)
69
- expect(File.exist?(path_to('nodes/x.json'))).to be true
70
- expect(File.exist?(path_to('roles/x.json'))).to be true
71
- end
72
-
73
- it "Upload uploads nothing" do
74
- expect_recipe {
75
- chef_mirror '' do
76
- action :upload
77
- end
78
- }.not_to have_updated('chef_mirror[]', :upload)
79
- end
80
- end
81
- end
82
-
83
- context 'and the Chef server has nodes and roles named x' do
84
- node 'x', {}
85
- role 'x', {}
86
-
87
- when_the_repository 'has nodes and roles named y' do
88
- file 'nodes/y.json', {}
89
- file 'roles/y.json', {}
90
-
91
- it "Download grabs the x's" do
92
- expect_recipe {
93
- chef_mirror '' do
94
- action :download
95
- end
96
- }.to have_updated('chef_mirror[]', :download)
97
- expect(File.exist?(path_to('nodes/x.json'))).to be true
98
- expect(File.exist?(path_to('roles/x.json'))).to be true
99
- expect(File.exist?(path_to('nodes/y.json'))).to be true
100
- expect(File.exist?(path_to('roles/y.json'))).to be true
101
- end
102
-
103
- it "Upload uploads the y's" do
104
- expect_recipe {
105
- chef_mirror '' do
106
- action :upload
107
- end
108
- }.to have_updated('chef_mirror[]', :upload)
109
- expect { get('nodes/x') }.not_to raise_error
110
- expect { get('roles/x') }.not_to raise_error
111
- expect { get('nodes/y') }.not_to raise_error
112
- expect { get('roles/y') }.not_to raise_error
113
- end
114
-
115
- it "Download with purge grabs the x's and deletes the y's" do
116
- expect_recipe {
117
- chef_mirror '' do
118
- purge true
119
- action :download
120
- end
121
- }.to have_updated('chef_mirror[]', :download)
122
- expect(File.exist?(path_to('nodes/x.json'))).to be true
123
- expect(File.exist?(path_to('roles/x.json'))).to be true
124
- end
125
-
126
- it "Upload with :purge uploads the y's and deletes the x's" do
127
- expect_recipe {
128
- chef_mirror '*/*.json' do
129
- purge true
130
- action :upload
131
- end
132
- }.to have_updated('chef_mirror[*/*.json]', :upload)
133
- expect { get('nodes/y') }.not_to raise_error
134
- expect { get('roles/y') }.not_to raise_error
135
- end
136
- end
137
- end
138
-
139
- describe "chef_repo_path" do
140
- when_the_repository 'has stuff but no chef_repo_path' do
141
- file 'repo/nodes/x.json', {}
142
- file 'repo/roles/x.json', {}
143
- file 'repo2/nodes/y.json', {}
144
- file 'repo2/roles/y.json', {}
145
-
146
- before do
147
- Chef::Config.delete(:chef_repo_path)
148
- Chef::Config.delete(:node_path)
149
- Chef::Config.delete(:cookbook_path)
150
- Chef::Config.delete(:role_path)
151
- end
152
-
153
- it "Upload with chef_repo_path('repo') uploads everything" do
154
- repo_path = path_to('repo')
155
- expect_recipe {
156
- chef_mirror '' do
157
- chef_repo_path repo_path
158
- action :upload
159
- end
160
- }.to have_updated('chef_mirror[]', :upload)
161
- expect { get('nodes/x') }.not_to raise_error
162
- expect { get('roles/x') }.not_to raise_error
163
- expect { get('nodes/y') }.to raise_error /404/
164
- expect { get('roles/y') }.to raise_error /404/
165
- end
166
-
167
- it "Upload with chef_repo_path(:chef_repo_path) with multiple paths uploads everything" do
168
- repo_path = path_to('repo')
169
- repo2_path = path_to('repo2')
170
- expect_recipe {
171
- chef_mirror '' do
172
- chef_repo_path :chef_repo_path => [ repo_path, repo2_path ]
173
- action :upload
174
- end
175
- }.to have_updated('chef_mirror[]', :upload)
176
- expect { get('nodes/x') }.not_to raise_error
177
- expect { get('roles/x') }.not_to raise_error
178
- expect { get('nodes/y') }.not_to raise_error
179
- expect { get('roles/y') }.not_to raise_error
180
- end
181
-
182
- it "Upload with chef_repo_path(:node_path, :role_path) uploads everything" do
183
- repo_path = path_to('repo')
184
- repo2_path = path_to('repo2')
185
-
186
- expect_recipe {
187
- chef_mirror '' do
188
- chef_repo_path :chef_repo_path => '/blahblah',
189
- :node_path => "#{repo_path}/nodes",
190
- :role_path => "#{repo2_path}/roles"
191
- action :upload
192
- end
193
- }.to have_updated('chef_mirror[]', :upload)
194
- expect { get('nodes/x') }.not_to raise_error
195
- expect { get('roles/x') }.to raise_error /404/
196
- expect { get('nodes/y') }.to raise_error /404/
197
- expect { get('roles/y') }.not_to raise_error
198
- end
199
-
200
- it "Upload with chef_repo_path(:chef_repo_path, :role_path) uploads everything" do
201
- repo_path = path_to('repo')
202
- repo2_path = path_to('repo2')
203
-
204
- expect_recipe {
205
- chef_mirror '' do
206
- chef_repo_path :chef_repo_path => repo_path,
207
- :role_path => "#{repo2_path}/roles"
208
- action :upload
209
- end
210
- }.to have_updated('chef_mirror[]', :upload)
211
- expect { get('nodes/x') }.not_to raise_error
212
- expect { get('roles/x') }.to raise_error /404/
213
- expect { get('nodes/y') }.to raise_error /404/
214
- expect { get('roles/y') }.not_to raise_error
215
- end
216
-
217
- it "Upload with chef_repo_path(:node_path, :role_path) with multiple paths uploads everything" do
218
- repo_path = path_to('repo')
219
- repo2_path = path_to('repo2')
220
-
221
- expect_recipe {
222
- chef_mirror '' do
223
- chef_repo_path :chef_repo_path => [ 'foo', 'bar' ],
224
- :node_path => [ "#{repo_path}/nodes", "#{repo2_path}/nodes" ],
225
- :role_path => [ "#{repo_path}/roles", "#{repo2_path}/roles" ]
226
- action :upload
227
- end
228
- }.to have_updated('chef_mirror[]', :upload)
229
- expect { get('nodes/x') }.not_to raise_error
230
- expect { get('roles/x') }.not_to raise_error
231
- expect { get('nodes/y') }.not_to raise_error
232
- expect { get('roles/y') }.not_to raise_error
233
- end
234
- end
235
- end
236
-
237
- describe "cookbook upload, chef_repo_path and versioned_cookbooks" do
238
- when_the_repository 'has cookbooks in non-versioned format' do
239
- file 'cookbooks/x-1.0.0/metadata.rb', 'name "x-1.0.0"; version "2.0.0"'
240
- file 'cookbooks/y-1.0.0/metadata.rb', 'name "y-3.0.0"; version "4.0.0"'
241
-
242
- it "chef_mirror :upload uploads everything" do
243
- expect_recipe {
244
- chef_mirror '' do
245
- action :upload
246
- end
247
- }.to have_updated('chef_mirror[]', :upload)
248
- expect { get('cookbooks/x-1.0.0/2.0.0') }.not_to raise_error
249
- expect { get('cookbooks/y-3.0.0/4.0.0') }.not_to raise_error
250
- end
251
-
252
- context 'and Chef::Config.versioned_cookbooks is false' do
253
- before do
254
- Chef::Config.versioned_cookbooks false
255
- end
256
- it "chef_mirror :upload uploads everything" do
257
- expect_recipe {
258
- chef_mirror '' do
259
- action :upload
260
- end
261
- }.to have_updated('chef_mirror[]', :upload)
262
- expect { get('cookbooks/x-1.0.0/2.0.0') }.not_to raise_error
263
- expect { get('cookbooks/y-3.0.0/4.0.0') }.not_to raise_error
264
- end
265
- end
266
-
267
- context 'and Chef::Config.chef_repo_path is not set but versioned_cookbooks is false' do
268
- before do
269
- Chef::Config.delete(:chef_repo_path)
270
- Chef::Config.versioned_cookbooks false
271
- end
272
-
273
- it "chef_mirror :upload with chef_repo_path and versioned_cookbooks false uploads cookbooks with name including version" do
274
- repository_dir = @repository_dir
275
- expect_recipe {
276
- chef_mirror '' do
277
- chef_repo_path repository_dir
278
- versioned_cookbooks false
279
- action :upload
280
- end
281
- }.to have_updated('chef_mirror[]', :upload)
282
- expect { get('cookbooks/x-1.0.0/2.0.0') }.not_to raise_error
283
- expect { get('cookbooks/y-3.0.0/4.0.0') }.not_to raise_error
284
- end
285
- end
286
- end
287
-
288
- when_the_repository 'has cookbooks in versioned_cookbook format' do
289
- file 'cookbooks/x-1.0.0/metadata.rb', 'name "x"; version "1.0.0"'
290
- file 'cookbooks/x-2.0.0/metadata.rb', 'name "x"; version "2.0.0"'
291
-
292
- context 'and Chef::Config.versioned_cookbooks is true' do
293
- before do
294
- Chef::Config.versioned_cookbooks true
295
- end
296
- it "chef_mirror :upload uploads everything" do
297
- expect_recipe {
298
- chef_mirror '' do
299
- action :upload
300
- end
301
- }.to have_updated('chef_mirror[]', :upload)
302
- expect { get('cookbooks/x/1.0.0') }.not_to raise_error
303
- expect { get('cookbooks/x/2.0.0') }.not_to raise_error
304
- end
305
- end
306
-
307
- context 'and Chef::Config.chef_repo_path set somewhere else' do
308
- before do
309
- Chef::Config.chef_repo_path = '/x/y/z'
310
- end
311
- it "chef_mirror :upload with chef_repo_path uploads cookbooks" do
312
- repository_dir = @repository_dir
313
- expect_recipe {
314
- chef_mirror '' do
315
- chef_repo_path repository_dir
316
- action :upload
317
- end
318
- }.to have_updated('chef_mirror[]', :upload)
319
- expect { get('cookbooks/x/1.0.0') }.not_to raise_error
320
- expect { get('cookbooks/x/2.0.0') }.not_to raise_error
321
- end
322
- end
323
-
324
- context 'and Chef::Config.chef_repo_path is not set but versioned_cookbooks is false' do
325
- before do
326
- Chef::Config.delete(:chef_repo_path)
327
- Chef::Config.versioned_cookbooks false
328
- end
329
-
330
- it "chef_mirror :upload with chef_repo_path uploads cookbooks with name split from version" do
331
- repository_dir = @repository_dir
332
- expect_recipe {
333
- chef_mirror '' do
334
- chef_repo_path repository_dir
335
- action :upload
336
- end
337
- }.to have_updated('chef_mirror[]', :upload)
338
- expect { get('cookbooks/x/1.0.0') }.not_to raise_error
339
- expect { get('cookbooks/x/2.0.0') }.not_to raise_error
340
- end
341
-
342
- it "chef_mirror :upload with chef_repo_path and versioned_cookbooks uploads cookbooks with name split from version" do
343
- repository_dir = @repository_dir
344
- expect_recipe {
345
- chef_mirror '' do
346
- chef_repo_path repository_dir
347
- versioned_cookbooks true
348
- action :upload
349
- end
350
- }.to have_updated('chef_mirror[]', :upload)
351
- expect { get('cookbooks/x/1.0.0') }.not_to raise_error
352
- expect { get('cookbooks/x/2.0.0') }.not_to raise_error
353
- end
354
- end
355
-
356
- context 'and Chef::Config.chef_repo_path is not set but versioned_cookbooks is true' do
357
- before do
358
- Chef::Config.delete(:chef_repo_path)
359
- Chef::Config.versioned_cookbooks true
360
- end
361
- it "chef_mirror :upload with chef_repo_path uploads cookbooks with name split from version" do
362
- repository_dir = @repository_dir
363
- expect_recipe {
364
- chef_mirror '' do
365
- chef_repo_path repository_dir
366
- action :upload
367
- end
368
- }.to have_updated('chef_mirror[]', :upload)
369
- expect { get('cookbooks/x/1.0.0') }.not_to raise_error
370
- expect { get('cookbooks/x/2.0.0') }.not_to raise_error
371
- end
372
- end
373
- end
374
- end
375
-
376
- describe 'cookbook download, chef_repo_path, and versioned_cookbooks' do
377
- context 'when the Chef server has a cookbook with multiple versions' do
378
- cookbook 'x', '1.0.0', 'metadata.rb' => 'name "x"; version "1.0.0"'
379
- cookbook 'x', '2.0.0', 'metadata.rb' => 'name "x"; version "2.0.0"'
380
-
381
- when_the_repository 'is empty' do
382
- it 'chef_mirror :download downloads the latest version of the cookbook' do
383
- expect_recipe {
384
- chef_mirror '' do
385
- action :download
386
- end
387
- }.to have_updated('chef_mirror[]', :download)
388
- expect(File.read(path_to('cookbooks/x/metadata.rb'))).to eq('name "x"; version "2.0.0"')
389
- end
390
-
391
- it 'chef_mirror :download with versioned_cookbooks = true downloads all versions of the cookbook' do
392
- expect_recipe {
393
- chef_mirror '' do
394
- versioned_cookbooks true
395
- action :download
396
- end
397
- }.to have_updated('chef_mirror[]', :download)
398
- expect(File.read(path_to('cookbooks/x-1.0.0/metadata.rb'))).to eq('name "x"; version "1.0.0"')
399
- expect(File.read(path_to('cookbooks/x-2.0.0/metadata.rb'))).to eq('name "x"; version "2.0.0"')
400
- end
401
-
402
- context 'and Chef::Config.chef_repo_path is set elsewhere' do
403
- before do
404
- Chef::Config.chef_repo_path = '/x/y/z'
405
- end
406
-
407
- it 'chef_mirror :download with chef_repo_path downloads all versions of the cookbook' do
408
- repository_dir = @repository_dir
409
- expect_recipe {
410
- chef_mirror '' do
411
- chef_repo_path repository_dir
412
- action :download
413
- end
414
- }.to have_updated('chef_mirror[]', :download)
415
- expect(File.read(path_to('cookbooks/x-1.0.0/metadata.rb'))).to eq('name "x"; version "1.0.0"')
416
- expect(File.read(path_to('cookbooks/x-2.0.0/metadata.rb'))).to eq('name "x"; version "2.0.0"')
417
- end
418
-
419
- it 'chef_mirror :download with chef_repo_path and versioned_cookbooks = false downloads the latest version of the cookbook' do
420
- repository_dir = @repository_dir
421
- expect_recipe {
422
- chef_mirror '' do
423
- chef_repo_path repository_dir
424
- versioned_cookbooks false
425
- action :download
426
- end
427
- }.to have_updated('chef_mirror[]', :download)
428
- expect(File.read(path_to('cookbooks/x/metadata.rb'))).to eq('name "x"; version "2.0.0"')
429
- end
430
- end
431
-
432
- context 'and Chef::Config.versioned_cookbooks is true' do
433
- before do
434
- Chef::Config.versioned_cookbooks = true
435
- end
436
-
437
- it 'chef_mirror :download downloads all versions of the cookbook' do
438
- expect_recipe {
439
- chef_mirror '' do
440
- action :download
441
- end
442
- }.to have_updated('chef_mirror[]', :download)
443
- expect(File.read(path_to('cookbooks/x-1.0.0/metadata.rb'))).to eq('name "x"; version "1.0.0"')
444
- expect(File.read(path_to('cookbooks/x-2.0.0/metadata.rb'))).to eq('name "x"; version "2.0.0"')
445
- end
446
-
447
- it 'chef_mirror :download with versioned_cookbooks = false downloads the latest version of the cookbook' do
448
- expect_recipe {
449
- chef_mirror '' do
450
- versioned_cookbooks false
451
- action :download
452
- end
453
- }.to have_updated('chef_mirror[]', :download)
454
- expect(File.read(path_to('cookbooks/x/metadata.rb'))).to eq('name "x"; version "2.0.0"')
455
- end
456
-
457
- context 'and Chef::Config.chef_repo_path is set elsewhere' do
458
- before do
459
- Chef::Config.chef_repo_path = '/x/y/z'
460
- end
461
-
462
- it 'chef_mirror :download with chef_repo_path downloads all versions of the cookbook' do
463
- repository_dir = @repository_dir
464
- expect_recipe {
465
- chef_mirror '' do
466
- chef_repo_path repository_dir
467
- action :download
468
- end
469
- }.to have_updated('chef_mirror[]', :download)
470
- expect(File.read(path_to('cookbooks/x-1.0.0/metadata.rb'))).to eq('name "x"; version "1.0.0"')
471
- expect(File.read(path_to('cookbooks/x-2.0.0/metadata.rb'))).to eq('name "x"; version "2.0.0"')
472
- end
473
-
474
- it 'chef_mirror :download with chef_repo_path and versioned_cookbooks = false downloads the latest version of the cookbook' do
475
- repository_dir = @repository_dir
476
- expect_recipe {
477
- chef_mirror '' do
478
- chef_repo_path repository_dir
479
- versioned_cookbooks false
480
- action :download
481
- end
482
- }.to have_updated('chef_mirror[]', :download)
483
- expect(File.read(path_to('cookbooks/x/metadata.rb'))).to eq('name "x"; version "2.0.0"')
484
- end
485
- end
486
- end
487
- end
488
- end
489
- end
490
- end
491
- end
1
+ require 'support/spec_support'
2
+ require 'cheffish/rspec/chef_run_support'
3
+ require 'chef/resource/chef_mirror'
4
+ require 'chef/provider/chef_mirror'
5
+
6
+ describe Chef::Resource::ChefMirror do
7
+ extend Cheffish::RSpec::ChefRunSupport
8
+
9
+ when_the_chef_12_server 'is in multi-org mode' do
10
+ organization 'foo'
11
+
12
+ before :each do
13
+ Chef::Config.chef_server_url = URI.join(Chef::Config.chef_server_url, '/organizations/foo').to_s
14
+ end
15
+
16
+ describe 'basic download and upload' do
17
+ when_the_repository 'is full of stuff' do
18
+ file 'nodes/x.json', {}
19
+ file 'roles/x.json', {}
20
+ directory 'cookbooks/x' do
21
+ file 'metadata.rb', 'name "x"; version "2.0.0"'
22
+ end
23
+
24
+ it "Download grabs defaults" do
25
+ expect_recipe {
26
+ chef_mirror '' do
27
+ action :download
28
+ end
29
+ }.to have_updated('chef_mirror[]', :download)
30
+ expect(File.exist?(path_to('groups/admins.json'))).to be true
31
+ expect(File.exist?(path_to('environments/_default.json'))).to be true
32
+ end
33
+
34
+ it "Upload uploads everything" do
35
+ expect_recipe {
36
+ chef_mirror '' do
37
+ action :upload
38
+ end
39
+ }.to have_updated('chef_mirror[]', :upload)
40
+ expect { get('nodes/x') }.not_to raise_error
41
+ expect { get('roles/x') }.not_to raise_error
42
+ expect { get('cookbooks/x/2.0.0') }.not_to raise_error
43
+ end
44
+
45
+ it 'chef_mirror with concurrency 0 fails with a reasonable message' do
46
+ expect {
47
+ converge {
48
+ chef_mirror '' do
49
+ concurrency 0
50
+ action :download
51
+ end
52
+ }
53
+ }.to raise_error /chef_mirror.concurrency must be above 0/
54
+ end
55
+ end
56
+ end
57
+
58
+ context 'and the Chef server has a node and role in it' do
59
+ node 'x', {}
60
+ role 'x', {}
61
+
62
+ when_the_repository 'is empty' do
63
+ it "Download grabs the node and role" do
64
+ expect_recipe {
65
+ chef_mirror '' do
66
+ action :download
67
+ end
68
+ }.to have_updated('chef_mirror[]', :download)
69
+ expect(File.exist?(path_to('nodes/x.json'))).to be true
70
+ expect(File.exist?(path_to('roles/x.json'))).to be true
71
+ end
72
+
73
+ it "Upload uploads nothing" do
74
+ expect_recipe {
75
+ chef_mirror '' do
76
+ action :upload
77
+ end
78
+ }.not_to have_updated('chef_mirror[]', :upload)
79
+ end
80
+ end
81
+ end
82
+
83
+ context 'and the Chef server has nodes and roles named x' do
84
+ node 'x', {}
85
+ role 'x', {}
86
+
87
+ when_the_repository 'has nodes and roles named y' do
88
+ file 'nodes/y.json', {}
89
+ file 'roles/y.json', {}
90
+
91
+ it "Download grabs the x's" do
92
+ expect_recipe {
93
+ chef_mirror '' do
94
+ action :download
95
+ end
96
+ }.to have_updated('chef_mirror[]', :download)
97
+ expect(File.exist?(path_to('nodes/x.json'))).to be true
98
+ expect(File.exist?(path_to('roles/x.json'))).to be true
99
+ expect(File.exist?(path_to('nodes/y.json'))).to be true
100
+ expect(File.exist?(path_to('roles/y.json'))).to be true
101
+ end
102
+
103
+ it "Upload uploads the y's" do
104
+ expect_recipe {
105
+ chef_mirror '' do
106
+ action :upload
107
+ end
108
+ }.to have_updated('chef_mirror[]', :upload)
109
+ expect { get('nodes/x') }.not_to raise_error
110
+ expect { get('roles/x') }.not_to raise_error
111
+ expect { get('nodes/y') }.not_to raise_error
112
+ expect { get('roles/y') }.not_to raise_error
113
+ end
114
+
115
+ it "Download with purge grabs the x's and deletes the y's" do
116
+ expect_recipe {
117
+ chef_mirror '' do
118
+ purge true
119
+ action :download
120
+ end
121
+ }.to have_updated('chef_mirror[]', :download)
122
+ expect(File.exist?(path_to('nodes/x.json'))).to be true
123
+ expect(File.exist?(path_to('roles/x.json'))).to be true
124
+ end
125
+
126
+ it "Upload with :purge uploads the y's and deletes the x's" do
127
+ expect_recipe {
128
+ chef_mirror '*/*.json' do
129
+ purge true
130
+ action :upload
131
+ end
132
+ }.to have_updated('chef_mirror[*/*.json]', :upload)
133
+ expect { get('nodes/y') }.not_to raise_error
134
+ expect { get('roles/y') }.not_to raise_error
135
+ end
136
+ end
137
+ end
138
+
139
+ describe "chef_repo_path" do
140
+ when_the_repository 'has stuff but no chef_repo_path' do
141
+ file 'repo/nodes/x.json', {}
142
+ file 'repo/roles/x.json', {}
143
+ file 'repo2/nodes/y.json', {}
144
+ file 'repo2/roles/y.json', {}
145
+
146
+ before do
147
+ Chef::Config.delete(:chef_repo_path)
148
+ Chef::Config.delete(:node_path)
149
+ Chef::Config.delete(:cookbook_path)
150
+ Chef::Config.delete(:role_path)
151
+ end
152
+
153
+ it "Upload with chef_repo_path('repo') uploads everything" do
154
+ repo_path = path_to('repo')
155
+ expect_recipe {
156
+ chef_mirror '' do
157
+ chef_repo_path repo_path
158
+ action :upload
159
+ end
160
+ }.to have_updated('chef_mirror[]', :upload)
161
+ expect { get('nodes/x') }.not_to raise_error
162
+ expect { get('roles/x') }.not_to raise_error
163
+ expect { get('nodes/y') }.to raise_error /404/
164
+ expect { get('roles/y') }.to raise_error /404/
165
+ end
166
+
167
+ it "Upload with chef_repo_path(:chef_repo_path) with multiple paths uploads everything" do
168
+ repo_path = path_to('repo')
169
+ repo2_path = path_to('repo2')
170
+ expect_recipe {
171
+ chef_mirror '' do
172
+ chef_repo_path :chef_repo_path => [ repo_path, repo2_path ]
173
+ action :upload
174
+ end
175
+ }.to have_updated('chef_mirror[]', :upload)
176
+ expect { get('nodes/x') }.not_to raise_error
177
+ expect { get('roles/x') }.not_to raise_error
178
+ expect { get('nodes/y') }.not_to raise_error
179
+ expect { get('roles/y') }.not_to raise_error
180
+ end
181
+
182
+ it "Upload with chef_repo_path(:node_path, :role_path) uploads everything" do
183
+ repo_path = path_to('repo')
184
+ repo2_path = path_to('repo2')
185
+
186
+ expect_recipe {
187
+ chef_mirror '' do
188
+ chef_repo_path :chef_repo_path => '/blahblah',
189
+ :node_path => "#{repo_path}/nodes",
190
+ :role_path => "#{repo2_path}/roles"
191
+ action :upload
192
+ end
193
+ }.to have_updated('chef_mirror[]', :upload)
194
+ expect { get('nodes/x') }.not_to raise_error
195
+ expect { get('roles/x') }.to raise_error /404/
196
+ expect { get('nodes/y') }.to raise_error /404/
197
+ expect { get('roles/y') }.not_to raise_error
198
+ end
199
+
200
+ it "Upload with chef_repo_path(:chef_repo_path, :role_path) uploads everything" do
201
+ repo_path = path_to('repo')
202
+ repo2_path = path_to('repo2')
203
+
204
+ expect_recipe {
205
+ chef_mirror '' do
206
+ chef_repo_path :chef_repo_path => repo_path,
207
+ :role_path => "#{repo2_path}/roles"
208
+ action :upload
209
+ end
210
+ }.to have_updated('chef_mirror[]', :upload)
211
+ expect { get('nodes/x') }.not_to raise_error
212
+ expect { get('roles/x') }.to raise_error /404/
213
+ expect { get('nodes/y') }.to raise_error /404/
214
+ expect { get('roles/y') }.not_to raise_error
215
+ end
216
+
217
+ it "Upload with chef_repo_path(:node_path, :role_path) with multiple paths uploads everything" do
218
+ repo_path = path_to('repo')
219
+ repo2_path = path_to('repo2')
220
+
221
+ expect_recipe {
222
+ chef_mirror '' do
223
+ chef_repo_path :chef_repo_path => [ 'foo', 'bar' ],
224
+ :node_path => [ "#{repo_path}/nodes", "#{repo2_path}/nodes" ],
225
+ :role_path => [ "#{repo_path}/roles", "#{repo2_path}/roles" ]
226
+ action :upload
227
+ end
228
+ }.to have_updated('chef_mirror[]', :upload)
229
+ expect { get('nodes/x') }.not_to raise_error
230
+ expect { get('roles/x') }.not_to raise_error
231
+ expect { get('nodes/y') }.not_to raise_error
232
+ expect { get('roles/y') }.not_to raise_error
233
+ end
234
+ end
235
+ end
236
+
237
+ describe "cookbook upload, chef_repo_path and versioned_cookbooks" do
238
+ when_the_repository 'has cookbooks in non-versioned format' do
239
+ file 'cookbooks/x-1.0.0/metadata.rb', 'name "x-1.0.0"; version "2.0.0"'
240
+ file 'cookbooks/y-1.0.0/metadata.rb', 'name "y-3.0.0"; version "4.0.0"'
241
+
242
+ it "chef_mirror :upload uploads everything" do
243
+ expect_recipe {
244
+ chef_mirror '' do
245
+ action :upload
246
+ end
247
+ }.to have_updated('chef_mirror[]', :upload)
248
+ expect { get('cookbooks/x-1.0.0/2.0.0') }.not_to raise_error
249
+ expect { get('cookbooks/y-3.0.0/4.0.0') }.not_to raise_error
250
+ end
251
+
252
+ context 'and Chef::Config.versioned_cookbooks is false' do
253
+ before do
254
+ Chef::Config.versioned_cookbooks false
255
+ end
256
+ it "chef_mirror :upload uploads everything" do
257
+ expect_recipe {
258
+ chef_mirror '' do
259
+ action :upload
260
+ end
261
+ }.to have_updated('chef_mirror[]', :upload)
262
+ expect { get('cookbooks/x-1.0.0/2.0.0') }.not_to raise_error
263
+ expect { get('cookbooks/y-3.0.0/4.0.0') }.not_to raise_error
264
+ end
265
+ end
266
+
267
+ context 'and Chef::Config.chef_repo_path is not set but versioned_cookbooks is false' do
268
+ before do
269
+ Chef::Config.delete(:chef_repo_path)
270
+ Chef::Config.versioned_cookbooks false
271
+ end
272
+
273
+ it "chef_mirror :upload with chef_repo_path and versioned_cookbooks false uploads cookbooks with name including version" do
274
+ repository_dir = @repository_dir
275
+ expect_recipe {
276
+ chef_mirror '' do
277
+ chef_repo_path repository_dir
278
+ versioned_cookbooks false
279
+ action :upload
280
+ end
281
+ }.to have_updated('chef_mirror[]', :upload)
282
+ expect { get('cookbooks/x-1.0.0/2.0.0') }.not_to raise_error
283
+ expect { get('cookbooks/y-3.0.0/4.0.0') }.not_to raise_error
284
+ end
285
+ end
286
+ end
287
+
288
+ when_the_repository 'has cookbooks in versioned_cookbook format' do
289
+ file 'cookbooks/x-1.0.0/metadata.rb', 'name "x"; version "1.0.0"'
290
+ file 'cookbooks/x-2.0.0/metadata.rb', 'name "x"; version "2.0.0"'
291
+
292
+ context 'and Chef::Config.versioned_cookbooks is true' do
293
+ before do
294
+ Chef::Config.versioned_cookbooks true
295
+ end
296
+ it "chef_mirror :upload uploads everything" do
297
+ expect_recipe {
298
+ chef_mirror '' do
299
+ action :upload
300
+ end
301
+ }.to have_updated('chef_mirror[]', :upload)
302
+ expect { get('cookbooks/x/1.0.0') }.not_to raise_error
303
+ expect { get('cookbooks/x/2.0.0') }.not_to raise_error
304
+ end
305
+ end
306
+
307
+ context 'and Chef::Config.chef_repo_path set somewhere else' do
308
+ before do
309
+ Chef::Config.chef_repo_path = '/x/y/z'
310
+ end
311
+ it "chef_mirror :upload with chef_repo_path uploads cookbooks" do
312
+ repository_dir = @repository_dir
313
+ expect_recipe {
314
+ chef_mirror '' do
315
+ chef_repo_path repository_dir
316
+ action :upload
317
+ end
318
+ }.to have_updated('chef_mirror[]', :upload)
319
+ expect { get('cookbooks/x/1.0.0') }.not_to raise_error
320
+ expect { get('cookbooks/x/2.0.0') }.not_to raise_error
321
+ end
322
+ end
323
+
324
+ context 'and Chef::Config.chef_repo_path is not set but versioned_cookbooks is false' do
325
+ before do
326
+ Chef::Config.delete(:chef_repo_path)
327
+ Chef::Config.versioned_cookbooks false
328
+ end
329
+
330
+ it "chef_mirror :upload with chef_repo_path uploads cookbooks with name split from version" do
331
+ repository_dir = @repository_dir
332
+ expect_recipe {
333
+ chef_mirror '' do
334
+ chef_repo_path repository_dir
335
+ action :upload
336
+ end
337
+ }.to have_updated('chef_mirror[]', :upload)
338
+ expect { get('cookbooks/x/1.0.0') }.not_to raise_error
339
+ expect { get('cookbooks/x/2.0.0') }.not_to raise_error
340
+ end
341
+
342
+ it "chef_mirror :upload with chef_repo_path and versioned_cookbooks uploads cookbooks with name split from version" do
343
+ repository_dir = @repository_dir
344
+ expect_recipe {
345
+ chef_mirror '' do
346
+ chef_repo_path repository_dir
347
+ versioned_cookbooks true
348
+ action :upload
349
+ end
350
+ }.to have_updated('chef_mirror[]', :upload)
351
+ expect { get('cookbooks/x/1.0.0') }.not_to raise_error
352
+ expect { get('cookbooks/x/2.0.0') }.not_to raise_error
353
+ end
354
+ end
355
+
356
+ context 'and Chef::Config.chef_repo_path is not set but versioned_cookbooks is true' do
357
+ before do
358
+ Chef::Config.delete(:chef_repo_path)
359
+ Chef::Config.versioned_cookbooks true
360
+ end
361
+ it "chef_mirror :upload with chef_repo_path uploads cookbooks with name split from version" do
362
+ repository_dir = @repository_dir
363
+ expect_recipe {
364
+ chef_mirror '' do
365
+ chef_repo_path repository_dir
366
+ action :upload
367
+ end
368
+ }.to have_updated('chef_mirror[]', :upload)
369
+ expect { get('cookbooks/x/1.0.0') }.not_to raise_error
370
+ expect { get('cookbooks/x/2.0.0') }.not_to raise_error
371
+ end
372
+ end
373
+ end
374
+ end
375
+
376
+ describe 'cookbook download, chef_repo_path, and versioned_cookbooks' do
377
+ context 'when the Chef server has a cookbook with multiple versions' do
378
+ cookbook 'x', '1.0.0', 'metadata.rb' => 'name "x"; version "1.0.0"'
379
+ cookbook 'x', '2.0.0', 'metadata.rb' => 'name "x"; version "2.0.0"'
380
+
381
+ when_the_repository 'is empty' do
382
+ it 'chef_mirror :download downloads the latest version of the cookbook' do
383
+ expect_recipe {
384
+ chef_mirror '' do
385
+ action :download
386
+ end
387
+ }.to have_updated('chef_mirror[]', :download)
388
+ expect(File.read(path_to('cookbooks/x/metadata.rb'))).to eq('name "x"; version "2.0.0"')
389
+ end
390
+
391
+ it 'chef_mirror :download with versioned_cookbooks = true downloads all versions of the cookbook' do
392
+ expect_recipe {
393
+ chef_mirror '' do
394
+ versioned_cookbooks true
395
+ action :download
396
+ end
397
+ }.to have_updated('chef_mirror[]', :download)
398
+ expect(File.read(path_to('cookbooks/x-1.0.0/metadata.rb'))).to eq('name "x"; version "1.0.0"')
399
+ expect(File.read(path_to('cookbooks/x-2.0.0/metadata.rb'))).to eq('name "x"; version "2.0.0"')
400
+ end
401
+
402
+ context 'and Chef::Config.chef_repo_path is set elsewhere' do
403
+ before do
404
+ Chef::Config.chef_repo_path = '/x/y/z'
405
+ end
406
+
407
+ it 'chef_mirror :download with chef_repo_path downloads all versions of the cookbook' do
408
+ repository_dir = @repository_dir
409
+ expect_recipe {
410
+ chef_mirror '' do
411
+ chef_repo_path repository_dir
412
+ action :download
413
+ end
414
+ }.to have_updated('chef_mirror[]', :download)
415
+ expect(File.read(path_to('cookbooks/x-1.0.0/metadata.rb'))).to eq('name "x"; version "1.0.0"')
416
+ expect(File.read(path_to('cookbooks/x-2.0.0/metadata.rb'))).to eq('name "x"; version "2.0.0"')
417
+ end
418
+
419
+ it 'chef_mirror :download with chef_repo_path and versioned_cookbooks = false downloads the latest version of the cookbook' do
420
+ repository_dir = @repository_dir
421
+ expect_recipe {
422
+ chef_mirror '' do
423
+ chef_repo_path repository_dir
424
+ versioned_cookbooks false
425
+ action :download
426
+ end
427
+ }.to have_updated('chef_mirror[]', :download)
428
+ expect(File.read(path_to('cookbooks/x/metadata.rb'))).to eq('name "x"; version "2.0.0"')
429
+ end
430
+ end
431
+
432
+ context 'and Chef::Config.versioned_cookbooks is true' do
433
+ before do
434
+ Chef::Config.versioned_cookbooks = true
435
+ end
436
+
437
+ it 'chef_mirror :download downloads all versions of the cookbook' do
438
+ expect_recipe {
439
+ chef_mirror '' do
440
+ action :download
441
+ end
442
+ }.to have_updated('chef_mirror[]', :download)
443
+ expect(File.read(path_to('cookbooks/x-1.0.0/metadata.rb'))).to eq('name "x"; version "1.0.0"')
444
+ expect(File.read(path_to('cookbooks/x-2.0.0/metadata.rb'))).to eq('name "x"; version "2.0.0"')
445
+ end
446
+
447
+ it 'chef_mirror :download with versioned_cookbooks = false downloads the latest version of the cookbook' do
448
+ expect_recipe {
449
+ chef_mirror '' do
450
+ versioned_cookbooks false
451
+ action :download
452
+ end
453
+ }.to have_updated('chef_mirror[]', :download)
454
+ expect(File.read(path_to('cookbooks/x/metadata.rb'))).to eq('name "x"; version "2.0.0"')
455
+ end
456
+
457
+ context 'and Chef::Config.chef_repo_path is set elsewhere' do
458
+ before do
459
+ Chef::Config.chef_repo_path = '/x/y/z'
460
+ end
461
+
462
+ it 'chef_mirror :download with chef_repo_path downloads all versions of the cookbook' do
463
+ repository_dir = @repository_dir
464
+ expect_recipe {
465
+ chef_mirror '' do
466
+ chef_repo_path repository_dir
467
+ action :download
468
+ end
469
+ }.to have_updated('chef_mirror[]', :download)
470
+ expect(File.read(path_to('cookbooks/x-1.0.0/metadata.rb'))).to eq('name "x"; version "1.0.0"')
471
+ expect(File.read(path_to('cookbooks/x-2.0.0/metadata.rb'))).to eq('name "x"; version "2.0.0"')
472
+ end
473
+
474
+ it 'chef_mirror :download with chef_repo_path and versioned_cookbooks = false downloads the latest version of the cookbook' do
475
+ repository_dir = @repository_dir
476
+ expect_recipe {
477
+ chef_mirror '' do
478
+ chef_repo_path repository_dir
479
+ versioned_cookbooks false
480
+ action :download
481
+ end
482
+ }.to have_updated('chef_mirror[]', :download)
483
+ expect(File.read(path_to('cookbooks/x/metadata.rb'))).to eq('name "x"; version "2.0.0"')
484
+ end
485
+ end
486
+ end
487
+ end
488
+ end
489
+ end
490
+ end
491
+ end