knife-essentials 0.8.3 → 0.8.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. data/lib/chef/knife/diff_essentials.rb +2 -2
  2. data/lib/chef/knife/download_essentials.rb +5 -1
  3. data/lib/chef/knife/list_essentials.rb +2 -1
  4. data/lib/chef/knife/upload_essentials.rb +5 -1
  5. data/lib/chef_fs/command_line.rb +94 -63
  6. data/lib/chef_fs/file_system.rb +113 -93
  7. data/lib/chef_fs/file_system/base_fs_object.rb +91 -37
  8. data/lib/chef_fs/file_system/chef_repository_file_system_cookbooks_dir.rb +14 -1
  9. data/lib/chef_fs/file_system/chef_server_root_dir.rb +2 -1
  10. data/lib/chef_fs/file_system/cookbook_file.rb +7 -1
  11. data/lib/chef_fs/file_system/cookbooks_dir.rb +13 -6
  12. data/lib/chef_fs/file_system/environments_dir.rb +59 -0
  13. data/lib/chef_fs/file_system/multiplexed_dir.rb +1 -1
  14. data/lib/chef_fs/file_system/nodes_dir.rb +1 -0
  15. data/lib/chef_fs/file_system/operation_not_allowed_error.rb +29 -0
  16. data/lib/chef_fs/file_system/operation_skipped_error.rb +29 -0
  17. data/lib/chef_fs/knife.rb +29 -21
  18. data/lib/chef_fs/version.rb +1 -1
  19. data/spec/chef_fs/diff_spec.rb +30 -30
  20. data/spec/chef_fs/file_system/cookbooks_dir_spec.rb +5 -1
  21. data/spec/integration/chef_repo_path_spec.rb +705 -0
  22. data/spec/integration/chef_repository_file_system_spec.rb +82 -713
  23. data/spec/integration/chefignore_spec.rb +258 -0
  24. data/spec/integration/diff_spec.rb +151 -0
  25. data/spec/integration/download_spec.rb +403 -0
  26. data/spec/integration/list_spec.rb +21 -21
  27. data/spec/integration/upload_spec.rb +407 -0
  28. data/spec/support/integration_helper.rb +9 -4
  29. data/spec/support/knife_support.rb +14 -2
  30. metadata +12 -3
@@ -131,8 +131,8 @@ EOM
131
131
  EOM
132
132
  end
133
133
 
134
- it "knife list -Rp --flat / returns everything" do
135
- knife('list -Rp --flat /').should_succeed <<EOM
134
+ it "knife list -Rfp / returns everything" do
135
+ knife('list -Rfp /').should_succeed <<EOM
136
136
  /cookbooks/
137
137
  /cookbooks/cookbook1/
138
138
  /cookbooks/cookbook1/metadata.rb
@@ -230,8 +230,8 @@ EOM
230
230
  context 'when cwd is at the top of the repository' do
231
231
  cwd '.'
232
232
 
233
- it "knife list -Rp --flat returns everything" do
234
- knife('list -Rp --flat').should_succeed <<EOM
233
+ it "knife list -Rfp returns everything" do
234
+ knife('list -Rfp').should_succeed <<EOM
235
235
  cookbooks/
236
236
  cookbooks/cookbook1/
237
237
  cookbooks/cookbook1/metadata.rb
@@ -263,8 +263,8 @@ EOM
263
263
  context 'when cwd is in cookbooks/' do
264
264
  cwd 'cookbooks'
265
265
 
266
- it "knife list -Rp --flat / returns everything" do
267
- knife('list -Rp --flat /').should_succeed <<EOM
266
+ it "knife list -Rfp / returns everything" do
267
+ knife('list -Rfp /').should_succeed <<EOM
268
268
  ./
269
269
  cookbook1/
270
270
  cookbook1/metadata.rb
@@ -289,8 +289,8 @@ cookbook2/recipes/default.rb
289
289
  EOM
290
290
  end
291
291
 
292
- it "knife list -Rp --flat .. returns everything" do
293
- knife('list -Rp --flat ..').should_succeed <<EOM
292
+ it "knife list -Rfp .. returns everything" do
293
+ knife('list -Rfp ..').should_succeed <<EOM
294
294
  ./
295
295
  cookbook1/
296
296
  cookbook1/metadata.rb
@@ -315,8 +315,8 @@ cookbook2/recipes/default.rb
315
315
  EOM
316
316
  end
317
317
 
318
- it "knife list -Rp --flat returns cookbooks" do
319
- knife('list -Rp --flat').should_succeed <<EOM
318
+ it "knife list -Rfp returns cookbooks" do
319
+ knife('list -Rfp').should_succeed <<EOM
320
320
  cookbook1/
321
321
  cookbook1/metadata.rb
322
322
  cookbook2/
@@ -334,8 +334,8 @@ EOM
334
334
  context 'when cwd is in cookbooks/cookbook2' do
335
335
  cwd 'cookbooks/cookbook2'
336
336
 
337
- it "knife list -Rp --flat returns cookbooks" do
338
- knife('list -Rp --flat').should_succeed <<EOM
337
+ it "knife list -Rfp returns cookbooks" do
338
+ knife('list -Rfp').should_succeed <<EOM
339
339
  metadata.rb
340
340
  recipes/
341
341
  recipes/default.rb
@@ -351,8 +351,8 @@ EOM
351
351
  context 'when cwd is in cookbooks/' do
352
352
  cwd 'cookbooks'
353
353
 
354
- it "knife list -Rp --flat returns cookbooks" do
355
- knife('list -Rp --flat').should_succeed <<EOM
354
+ it "knife list -Rfp returns cookbooks" do
355
+ knife('list -Rfp').should_succeed <<EOM
356
356
  cookbook1/
357
357
  cookbook1/metadata.rb
358
358
  cookbook2/
@@ -366,8 +366,8 @@ EOM
366
366
  context 'when cwd is in symlinked/' do
367
367
  cwd 'symlinked'
368
368
 
369
- it "knife list -Rp --flat returns cookbooks" do
370
- knife('list -Rp --flat').should_succeed <<EOM
369
+ it "knife list -Rfp returns cookbooks" do
370
+ knife('list -Rfp').should_succeed <<EOM
371
371
  cookbook1/
372
372
  cookbook1/metadata.rb
373
373
  cookbook2/
@@ -386,8 +386,8 @@ EOM
386
386
  context 'when cwd is in real_cookbooks/' do
387
387
  cwd 'real_cookbooks'
388
388
 
389
- it "knife list -Rp --flat returns cookbooks" do
390
- knife('list -Rp --flat').should_succeed <<EOM
389
+ it "knife list -Rfp returns cookbooks" do
390
+ knife('list -Rfp').should_succeed <<EOM
391
391
  cookbook1/
392
392
  cookbook1/metadata.rb
393
393
  cookbook2/
@@ -401,8 +401,8 @@ EOM
401
401
  context 'when cwd is in cookbooks/' do
402
402
  cwd 'cookbooks'
403
403
 
404
- it "knife list -Rp --flat returns cookbooks" do
405
- knife('list -Rp --flat').should_succeed <<EOM
404
+ it "knife list -Rfp returns cookbooks" do
405
+ knife('list -Rfp').should_succeed <<EOM
406
406
  cookbook1/
407
407
  cookbook1/metadata.rb
408
408
  cookbook2/
@@ -459,7 +459,7 @@ EOM
459
459
  file 'users/user1.json', {}
460
460
  file 'users/user2.json', {}
461
461
 
462
- it "knife list -Rp --flat / returns everything" do
462
+ it "knife list -Rfp / returns everything" do
463
463
  knife('list -Rp --local --flat /').should_succeed <<EOM
464
464
  /cookbooks/
465
465
  /cookbooks/cookbook1/
@@ -0,0 +1,407 @@
1
+ require 'support/integration_helper'
2
+ require 'chef/knife/upload_essentials'
3
+ require 'chef/knife/diff_essentials'
4
+
5
+ describe 'knife upload' do
6
+ extend IntegrationSupport
7
+ include KnifeSupport
8
+
9
+ when_the_chef_server "has one of each thing" do
10
+ client 'x', '{}'
11
+ cookbook 'x', '1.0.0', { 'metadata.rb' => 'version "1.0.0"' }
12
+ data_bag 'x', { 'y' => '{}' }
13
+ environment 'x', '{}'
14
+ node 'x', '{}'
15
+ role 'x', '{}'
16
+ user 'x', '{}'
17
+
18
+ when_the_repository 'has only top-level directories' do
19
+ directory 'clients'
20
+ directory 'cookbooks'
21
+ directory 'data_bags'
22
+ directory 'environments'
23
+ directory 'nodes'
24
+ directory 'roles'
25
+ directory 'users'
26
+
27
+ it 'knife upload does nothing' do
28
+ knife('upload /').should_succeed ''
29
+ knife('diff --name-status /').should_succeed <<EOM
30
+ D\t/cookbooks/x
31
+ D\t/data_bags/x
32
+ D\t/environments/_default.json
33
+ D\t/environments/x.json
34
+ D\t/roles/x.json
35
+ EOM
36
+ end
37
+
38
+ it 'knife upload --purge deletes everything' do
39
+ knife('upload --purge /').should_succeed(<<EOM, :stderr => "WARN: The default environment (_default.json) cannot be deleted. Skipping.\n")
40
+ Deleted extra entry /cookbooks/x (purge is on)
41
+ Deleted extra entry /data_bags/x (purge is on)
42
+ Deleted extra entry /environments/x.json (purge is on)
43
+ Deleted extra entry /roles/x.json (purge is on)
44
+ EOM
45
+ knife('diff --name-status /').should_succeed <<EOM
46
+ D\t/environments/_default.json
47
+ EOM
48
+ end
49
+ end
50
+
51
+ when_the_repository 'has an identical copy of each thing' do
52
+ file 'clients/x.json', <<EOM
53
+ {}
54
+ EOM
55
+ file 'cookbooks/x/metadata.rb', 'version "1.0.0"'
56
+ file 'data_bags/x/y.json', <<EOM
57
+ {
58
+ "id": "y"
59
+ }
60
+ EOM
61
+ file 'environments/_default.json', <<EOM
62
+ {
63
+ "name": "_default",
64
+ "description": "The default Chef environment",
65
+ "cookbook_versions": {
66
+ },
67
+ "json_class": "Chef::Environment",
68
+ "chef_type": "environment",
69
+ "default_attributes": {
70
+ },
71
+ "override_attributes": {
72
+ }
73
+ }
74
+ EOM
75
+ file 'environments/x.json', <<EOM
76
+ {
77
+ "chef_type": "environment",
78
+ "cookbook_versions": {
79
+ },
80
+ "default_attributes": {
81
+ },
82
+ "description": "",
83
+ "json_class": "Chef::Environment",
84
+ "name": "x",
85
+ "override_attributes": {
86
+ }
87
+ }
88
+ EOM
89
+ file 'nodes/x.json', <<EOM
90
+ {}
91
+ EOM
92
+ file 'roles/x.json', <<EOM
93
+ {
94
+ "chef_type": "role",
95
+ "default_attributes": {
96
+ },
97
+ "description": "",
98
+ "env_run_lists": {
99
+ },
100
+ "json_class": "Chef::Role",
101
+ "name": "x",
102
+ "override_attributes": {
103
+ },
104
+ "run_list": [
105
+
106
+ ]
107
+ }
108
+ EOM
109
+ file 'users/x.json', <<EOM
110
+ {}
111
+ EOM
112
+
113
+ it 'knife upload makes no changes' do
114
+ knife('upload /').should_succeed ''
115
+ knife('diff --name-status /').should_succeed ''
116
+ end
117
+
118
+ it 'knife upload --purge makes no changes' do
119
+ knife('upload --purge /').should_succeed ''
120
+ knife('diff --name-status /').should_succeed ''
121
+ end
122
+
123
+ context 'except the role file' do
124
+ file 'roles/x.json', <<EOM
125
+ {
126
+ "chef_type": "role",
127
+ "default_attributes": {
128
+ },
129
+ "description": "blarghle",
130
+ "env_run_lists": {
131
+ },
132
+ "json_class": "Chef::Role",
133
+ "name": "x",
134
+ "override_attributes": {
135
+ },
136
+ "run_list": [
137
+
138
+ ]
139
+ }
140
+ EOM
141
+ it 'knife upload changes the role' do
142
+ knife('upload /').should_succeed "Updated /roles/x.json\n"
143
+ knife('diff --name-status /').should_succeed ''
144
+ end
145
+ end
146
+
147
+ context 'as well as one extra copy of each thing' do
148
+ file 'clients/y.json', { 'name' => 'y' }
149
+ file 'cookbooks/x/blah.rb', ''
150
+ file 'cookbooks/y/metadata.rb', 'version "1.0.0"'
151
+ file 'data_bags/x/z.json', <<EOM
152
+ {
153
+ "id": "z"
154
+ }
155
+ EOM
156
+ file 'data_bags/y/zz.json', <<EOM
157
+ {
158
+ "id": "zz"
159
+ }
160
+ EOM
161
+ file 'environments/y.json', <<EOM
162
+ {
163
+ "chef_type": "environment",
164
+ "cookbook_versions": {
165
+ },
166
+ "default_attributes": {
167
+ },
168
+ "description": "",
169
+ "json_class": "Chef::Environment",
170
+ "name": "y",
171
+ "override_attributes": {
172
+ }
173
+ }
174
+ EOM
175
+ file 'nodes/y.json', { 'name' => 'y' }
176
+ file 'roles/y.json', <<EOM
177
+ {
178
+ "chef_type": "role",
179
+ "default_attributes": {
180
+ },
181
+ "description": "",
182
+ "env_run_lists": {
183
+ },
184
+ "json_class": "Chef::Role",
185
+ "name": "y",
186
+ "override_attributes": {
187
+ },
188
+ "run_list": [
189
+
190
+ ]
191
+ }
192
+ EOM
193
+ file 'users/y.json', { 'name' => 'y' }
194
+
195
+ it 'knife upload adds the new files' do
196
+ knife('upload /').should_succeed <<EOM
197
+ Updated /cookbooks/x
198
+ Created /cookbooks/y
199
+ Created /data_bags/x/z.json
200
+ Created /data_bags/y
201
+ Created /data_bags/y/zz.json
202
+ Created /environments/y.json
203
+ Created /roles/y.json
204
+ EOM
205
+ knife('diff --name-status /').should_succeed ''
206
+ end
207
+ end
208
+ end
209
+
210
+ when_the_repository 'is empty' do
211
+ it 'knife upload does nothing' do
212
+ knife('upload /').should_succeed ''
213
+ knife('diff --name-status /').should_succeed <<EOM
214
+ D\t/cookbooks
215
+ D\t/data_bags
216
+ D\t/environments
217
+ D\t/roles
218
+ EOM
219
+ end
220
+
221
+ it 'knife upload --purge deletes nothing' do
222
+ knife('upload --purge /').should_fail <<EOM
223
+ ERROR: remote/cookbooks cannot be deleted.
224
+ ERROR: remote/data_bags cannot be deleted.
225
+ ERROR: remote/environments cannot be deleted.
226
+ ERROR: remote/roles cannot be deleted.
227
+ EOM
228
+ knife('diff --name-status /').should_succeed <<EOM
229
+ D\t/cookbooks
230
+ D\t/data_bags
231
+ D\t/environments
232
+ D\t/roles
233
+ EOM
234
+ end
235
+
236
+ context 'when current directory is top level' do
237
+ cwd '.'
238
+ it 'knife upload with no parameters reports an error' do
239
+ knife('upload').should_fail "FATAL: Must specify at least one argument. If you want to upload everything in this directory, type \"knife upload .\"\n", :stdout => /USAGE/
240
+ end
241
+ end
242
+ end
243
+ end
244
+
245
+ # Test upload of an item when the other end doesn't even have the container
246
+ when_the_chef_server 'is empty' do
247
+ when_the_repository 'has two data bag items' do
248
+ file 'data_bags/x/y.json', <<EOM
249
+ {
250
+ "id": "y"
251
+ }
252
+ EOM
253
+ file 'data_bags/x/z.json', <<EOM
254
+ {
255
+ "id": "z"
256
+ }
257
+ EOM
258
+ it 'knife upload of one data bag item itself succeeds' do
259
+ knife('upload /data_bags/x/y.json').should_succeed <<EOM
260
+ Created /data_bags/x
261
+ Created /data_bags/x/y.json
262
+ EOM
263
+ knife('diff --name-status /data_bags').should_succeed <<EOM
264
+ A\t/data_bags/x/z.json
265
+ EOM
266
+ end
267
+ end
268
+ end
269
+
270
+ when_the_chef_server 'has three data bag items' do
271
+ data_bag 'x', { 'deleted' => {}, 'modified' => {}, 'unmodified' => {} }
272
+ when_the_repository 'has a modified, unmodified, added and deleted data bag item' do
273
+ file 'data_bags/x/added.json', <<EOM
274
+ {
275
+ "id": "added"
276
+ }
277
+ EOM
278
+ file 'data_bags/x/modified.json', <<EOM
279
+ {
280
+ "id": "modified",
281
+ "foo": "bar"
282
+ }
283
+ EOM
284
+ file 'data_bags/x/unmodified.json', <<EOM
285
+ {
286
+ "id": "unmodified"
287
+ }
288
+ EOM
289
+ it 'knife upload of the modified file succeeds' do
290
+ knife('upload /data_bags/x/modified.json').should_succeed <<EOM
291
+ Updated /data_bags/x/modified.json
292
+ EOM
293
+ knife('diff --name-status /data_bags').should_succeed <<EOM
294
+ D\t/data_bags/x/deleted.json
295
+ A\t/data_bags/x/added.json
296
+ EOM
297
+ end
298
+ it 'knife upload of the unmodified file does nothing' do
299
+ knife('upload /data_bags/x/unmodified.json').should_succeed ''
300
+ knife('diff --name-status /data_bags').should_succeed <<EOM
301
+ D\t/data_bags/x/deleted.json
302
+ M\t/data_bags/x/modified.json
303
+ A\t/data_bags/x/added.json
304
+ EOM
305
+ end
306
+ it 'knife upload of the added file succeeds' do
307
+ knife('upload /data_bags/x/added.json').should_succeed <<EOM
308
+ Created /data_bags/x/added.json
309
+ EOM
310
+ knife('diff --name-status /data_bags').should_succeed <<EOM
311
+ D\t/data_bags/x/deleted.json
312
+ M\t/data_bags/x/modified.json
313
+ EOM
314
+ end
315
+ it 'knife upload of the deleted file does nothing' do
316
+ knife('upload /data_bags/x/deleted.json').should_succeed ''
317
+ knife('diff --name-status /data_bags').should_succeed <<EOM
318
+ D\t/data_bags/x/deleted.json
319
+ M\t/data_bags/x/modified.json
320
+ A\t/data_bags/x/added.json
321
+ EOM
322
+ end
323
+ it 'knife upload --purge of the deleted file deletes it' do
324
+ knife('upload --purge /data_bags/x/deleted.json').should_succeed <<EOM
325
+ Deleted extra entry /data_bags/x/deleted.json (purge is on)
326
+ EOM
327
+ knife('diff --name-status /data_bags').should_succeed <<EOM
328
+ M\t/data_bags/x/modified.json
329
+ A\t/data_bags/x/added.json
330
+ EOM
331
+ end
332
+ it 'knife upload of the entire data bag uploads everything' do
333
+ knife('upload /data_bags/x').should_succeed <<EOM
334
+ Created /data_bags/x/added.json
335
+ Updated /data_bags/x/modified.json
336
+ EOM
337
+ knife('diff --name-status /data_bags').should_succeed <<EOM
338
+ D\t/data_bags/x/deleted.json
339
+ EOM
340
+ end
341
+ it 'knife upload --purge of the entire data bag uploads everything' do
342
+ knife('upload --purge /data_bags/x').should_succeed <<EOM
343
+ Created /data_bags/x/added.json
344
+ Updated /data_bags/x/modified.json
345
+ Deleted extra entry /data_bags/x/deleted.json (purge is on)
346
+ EOM
347
+ knife('diff --name-status /data_bags').should_succeed ''
348
+ end
349
+ end
350
+ end
351
+
352
+ # Cookbook upload is a funny thing ... direct cookbook upload works, but
353
+ # upload of a file is designed not to work at present. Make sure that is the
354
+ # case.
355
+ when_the_chef_server 'has a cookbook' do
356
+ cookbook 'x', '1.0.0', { 'metadata.rb' => 'version "1.0.0"', 'z.rb' => '' }
357
+ when_the_repository 'has a modified, extra and missing file for the cookbook' do
358
+ file 'cookbooks/x/metadata.rb', 'version "1.0.0"'
359
+ file 'cookbooks/x/y.rb', 'hi'
360
+ it 'knife upload of any individual file fails' do
361
+ knife('upload /cookbooks/x/metadata.rb').should_fail "ERROR: remote/cookbooks/x/metadata.rb cannot be updated.\n"
362
+ knife('upload /cookbooks/x/y.rb').should_fail "ERROR: remote/cookbooks/x cannot have a child created under it.\n"
363
+ knife('upload --purge /cookbooks/x/z.rb').should_fail "ERROR: remote/cookbooks/x/z.rb cannot be deleted.\n"
364
+ end
365
+ # TODO this is a bit of an inconsistency: if we didn't specify --purge,
366
+ # technically we shouldn't have deleted missing files. But ... cookbooks
367
+ # are a special case.
368
+ it 'knife upload of the cookbook itself succeeds' do
369
+ knife('upload /cookbooks/x').should_succeed <<EOM
370
+ Updated /cookbooks/x
371
+ EOM
372
+ knife('diff --name-status /cookbooks').should_succeed ''
373
+ end
374
+ it 'knife upload --purge of the cookbook itself succeeds' do
375
+ knife('upload /cookbooks/x').should_succeed <<EOM
376
+ Updated /cookbooks/x
377
+ EOM
378
+ knife('diff --name-status /cookbooks').should_succeed ''
379
+ end
380
+ end
381
+ when_the_repository 'has a missing file for the cookbook' do
382
+ file 'cookbooks/x/metadata.rb', 'version "1.0.0"'
383
+ it 'knife upload of the cookbook succeeds' do
384
+ knife('upload /cookbooks/x').should_succeed <<EOM
385
+ Updated /cookbooks/x
386
+ EOM
387
+ knife('diff --name-status /cookbooks').should_succeed ''
388
+ end
389
+ end
390
+ when_the_repository 'has an extra file for the cookbook' do
391
+ file 'cookbooks/x/metadata.rb', 'version "1.0.0"'
392
+ file 'cookbooks/x/z.rb', ''
393
+ file 'cookbooks/x/blah.rb', ''
394
+ it 'knife upload of the cookbook succeeds' do
395
+ knife('upload /cookbooks/x').should_succeed <<EOM
396
+ Updated /cookbooks/x
397
+ EOM
398
+ knife('diff --name-status /cookbooks').should_succeed ''
399
+ end
400
+ end
401
+ end
402
+
403
+ # Upload from a cwd
404
+ # Upload with *'s
405
+ # Upload with JSON that isn't *really* modified
406
+ # Multiple cookbook versions!!!!
407
+ end