knife-essentials 0.8.3 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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