knife-essentials 0.9.2 → 0.9.3
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.
- data/lib/chef/knife/raw_essentials.rb +3 -61
- data/lib/chef_fs/data_handler/data_handler_base.rb +2 -1
- data/lib/chef_fs/file_system/base_fs_object.rb +75 -1
- data/lib/chef_fs/file_system/chef_repository_file_system_entry.rb +23 -0
- data/lib/chef_fs/file_system/cookbook_dir.rb +27 -13
- data/lib/chef_fs/file_system/cookbooks_dir.rb +89 -30
- data/lib/chef_fs/file_system/data_bags_dir.rb +5 -1
- data/lib/chef_fs/file_system/nodes_dir.rb +8 -14
- data/lib/chef_fs/file_system/rest_list_dir.rb +6 -2
- data/lib/chef_fs/file_system/rest_list_entry.rb +15 -3
- data/lib/chef_fs/knife.rb +28 -17
- data/lib/chef_fs/version.rb +1 -1
- data/spec/chef_fs/file_system/chef_server_root_dir_spec.rb +26 -12
- data/spec/chef_fs/file_system/cookbook_dir_spec.rb +582 -0
- data/spec/chef_fs/file_system/cookbooks_dir_spec.rb +81 -489
- data/spec/chef_fs/file_system/data_bags_dir_spec.rb +63 -49
- data/spec/integration/deps_spec.rb +32 -32
- data/spec/integration/diff_spec.rb +425 -133
- data/spec/integration/download_spec.rb +743 -211
- data/spec/integration/upload_spec.rb +814 -244
- data/spec/support/integration_helper.rb +33 -6
- data/spec/support/knife_support.rb +4 -2
- metadata +19 -2
@@ -6,27 +6,28 @@ describe 'knife upload' do
|
|
6
6
|
extend IntegrationSupport
|
7
7
|
include KnifeSupport
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
knife
|
29
|
-
|
9
|
+
context 'without versioned cookbooks' do
|
10
|
+
when_the_chef_server "has one of each thing" do
|
11
|
+
client 'x', '{}'
|
12
|
+
cookbook 'x', '1.0.0', { 'metadata.rb' => 'version "1.0.0"' }
|
13
|
+
data_bag 'x', { 'y' => '{}' }
|
14
|
+
environment 'x', '{}'
|
15
|
+
node 'x', '{}'
|
16
|
+
role 'x', '{}'
|
17
|
+
user 'x', '{}'
|
18
|
+
|
19
|
+
when_the_repository 'has only top-level directories' do
|
20
|
+
directory 'clients'
|
21
|
+
directory 'cookbooks'
|
22
|
+
directory 'data_bags'
|
23
|
+
directory 'environments'
|
24
|
+
directory 'nodes'
|
25
|
+
directory 'roles'
|
26
|
+
directory 'users'
|
27
|
+
|
28
|
+
it 'knife upload does nothing' do
|
29
|
+
knife('upload /').should_succeed ''
|
30
|
+
knife('diff --name-status /').should_succeed <<EOM
|
30
31
|
D\t/cookbooks/x
|
31
32
|
D\t/data_bags/x
|
32
33
|
D\t/environments/_default.json
|
@@ -46,19 +47,19 @@ EOM
|
|
46
47
|
D\t/environments/_default.json
|
47
48
|
EOM
|
48
49
|
end
|
49
|
-
|
50
|
+
end
|
50
51
|
|
51
|
-
|
52
|
-
|
52
|
+
when_the_repository 'has an identical copy of each thing' do
|
53
|
+
file 'clients/x.json', <<EOM
|
53
54
|
{}
|
54
55
|
EOM
|
55
|
-
|
56
|
-
|
56
|
+
file 'cookbooks/x/metadata.rb', 'version "1.0.0"'
|
57
|
+
file 'data_bags/x/y.json', <<EOM
|
57
58
|
{
|
58
59
|
"id": "y"
|
59
60
|
}
|
60
61
|
EOM
|
61
|
-
|
62
|
+
file 'environments/_default.json', <<EOM
|
62
63
|
{
|
63
64
|
"name": "_default",
|
64
65
|
"description": "The default Chef environment",
|
@@ -72,7 +73,7 @@ EOM
|
|
72
73
|
}
|
73
74
|
}
|
74
75
|
EOM
|
75
|
-
|
76
|
+
file 'environments/x.json', <<EOM
|
76
77
|
{
|
77
78
|
"chef_type": "environment",
|
78
79
|
"cookbook_versions": {
|
@@ -86,10 +87,10 @@ EOM
|
|
86
87
|
}
|
87
88
|
}
|
88
89
|
EOM
|
89
|
-
|
90
|
+
file 'nodes/x.json', <<EOM
|
90
91
|
{}
|
91
92
|
EOM
|
92
|
-
|
93
|
+
file 'roles/x.json', <<EOM
|
93
94
|
{
|
94
95
|
"chef_type": "role",
|
95
96
|
"default_attributes": {
|
@@ -106,22 +107,22 @@ EOM
|
|
106
107
|
]
|
107
108
|
}
|
108
109
|
EOM
|
109
|
-
|
110
|
+
file 'users/x.json', <<EOM
|
110
111
|
{}
|
111
112
|
EOM
|
112
113
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
114
|
+
it 'knife upload makes no changes' do
|
115
|
+
knife('upload /cookbooks/x').should_succeed ''
|
116
|
+
knife('diff --name-status /').should_succeed ''
|
117
|
+
end
|
117
118
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
119
|
+
it 'knife upload --purge makes no changes' do
|
120
|
+
knife('upload --purge /').should_succeed ''
|
121
|
+
knife('diff --name-status /').should_succeed ''
|
122
|
+
end
|
122
123
|
|
123
|
-
|
124
|
-
|
124
|
+
context 'except the role file' do
|
125
|
+
file 'roles/x.json', <<EOM
|
125
126
|
{
|
126
127
|
"chef_type": "role",
|
127
128
|
"default_attributes": {
|
@@ -138,14 +139,14 @@ EOM
|
|
138
139
|
]
|
139
140
|
}
|
140
141
|
EOM
|
141
|
-
|
142
|
-
|
143
|
-
|
142
|
+
it 'knife upload changes the role' do
|
143
|
+
knife('upload /').should_succeed "Updated /roles/x.json\n"
|
144
|
+
knife('diff --name-status /').should_succeed ''
|
145
|
+
end
|
144
146
|
end
|
145
|
-
end
|
146
147
|
|
147
|
-
|
148
|
-
|
148
|
+
context 'except the role file is textually different, but not ACTUALLY different' do
|
149
|
+
file 'roles/x.json', <<EOM
|
149
150
|
{
|
150
151
|
"chef_type": "role",
|
151
152
|
"default_attributes": {
|
@@ -162,27 +163,27 @@ EOM
|
|
162
163
|
]
|
163
164
|
}
|
164
165
|
EOM
|
165
|
-
|
166
|
-
|
167
|
-
|
166
|
+
it 'knife upload / does not change anything' do
|
167
|
+
knife('upload /').should_succeed ''
|
168
|
+
knife('diff --name-status /').should_succeed ''
|
169
|
+
end
|
168
170
|
end
|
169
|
-
end
|
170
171
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
172
|
+
context 'as well as one extra copy of each thing' do
|
173
|
+
file 'clients/y.json', { 'name' => 'y' }
|
174
|
+
file 'cookbooks/x/blah.rb', ''
|
175
|
+
file 'cookbooks/y/metadata.rb', 'version "1.0.0"'
|
176
|
+
file 'data_bags/x/z.json', <<EOM
|
176
177
|
{
|
177
178
|
"id": "z"
|
178
179
|
}
|
179
180
|
EOM
|
180
|
-
|
181
|
+
file 'data_bags/y/zz.json', <<EOM
|
181
182
|
{
|
182
183
|
"id": "zz"
|
183
184
|
}
|
184
185
|
EOM
|
185
|
-
|
186
|
+
file 'environments/y.json', <<EOM
|
186
187
|
{
|
187
188
|
"chef_type": "environment",
|
188
189
|
"cookbook_versions": {
|
@@ -196,8 +197,8 @@ EOM
|
|
196
197
|
}
|
197
198
|
}
|
198
199
|
EOM
|
199
|
-
|
200
|
-
|
200
|
+
file 'nodes/y.json', { 'name' => 'y' }
|
201
|
+
file 'roles/y.json', <<EOM
|
201
202
|
{
|
202
203
|
"chef_type": "role",
|
203
204
|
"default_attributes": {
|
@@ -214,10 +215,10 @@ EOM
|
|
214
215
|
]
|
215
216
|
}
|
216
217
|
EOM
|
217
|
-
|
218
|
+
file 'users/y.json', { 'name' => 'y' }
|
218
219
|
|
219
|
-
|
220
|
-
|
220
|
+
it 'knife upload adds the new files' do
|
221
|
+
knife('upload /').should_succeed <<EOM
|
221
222
|
Updated /cookbooks/x
|
222
223
|
Created /cookbooks/y
|
223
224
|
Created /data_bags/x/z.json
|
@@ -226,352 +227,921 @@ Created /data_bags/y/zz.json
|
|
226
227
|
Created /environments/y.json
|
227
228
|
Created /roles/y.json
|
228
229
|
EOM
|
229
|
-
|
230
|
+
knife('diff --name-status /').should_succeed ''
|
231
|
+
end
|
230
232
|
end
|
231
233
|
end
|
232
|
-
end
|
233
234
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
235
|
+
when_the_repository 'is empty' do
|
236
|
+
it 'knife upload does nothing' do
|
237
|
+
knife('upload /').should_succeed ''
|
238
|
+
knife('diff --name-status /').should_succeed <<EOM
|
238
239
|
D\t/cookbooks
|
239
240
|
D\t/data_bags
|
240
241
|
D\t/environments
|
241
242
|
D\t/roles
|
242
243
|
EOM
|
243
|
-
|
244
|
+
end
|
244
245
|
|
245
|
-
|
246
|
-
|
246
|
+
it 'knife upload --purge deletes nothing' do
|
247
|
+
knife('upload --purge /').should_fail <<EOM
|
247
248
|
ERROR: /cookbooks cannot be deleted.
|
248
249
|
ERROR: /data_bags cannot be deleted.
|
249
250
|
ERROR: /environments cannot be deleted.
|
250
251
|
ERROR: /roles cannot be deleted.
|
251
252
|
EOM
|
252
|
-
|
253
|
+
knife('diff --name-status /').should_succeed <<EOM
|
253
254
|
D\t/cookbooks
|
254
255
|
D\t/data_bags
|
255
256
|
D\t/environments
|
256
257
|
D\t/roles
|
257
258
|
EOM
|
258
|
-
|
259
|
+
end
|
259
260
|
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
261
|
+
context 'when current directory is top level' do
|
262
|
+
cwd '.'
|
263
|
+
it 'knife upload with no parameters reports an error' do
|
264
|
+
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/
|
265
|
+
end
|
264
266
|
end
|
265
267
|
end
|
266
268
|
end
|
267
|
-
end
|
268
269
|
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
270
|
+
# Test upload of an item when the other end doesn't even have the container
|
271
|
+
when_the_chef_server 'is empty' do
|
272
|
+
when_the_repository 'has two data bag items' do
|
273
|
+
file 'data_bags/x/y.json', <<EOM
|
273
274
|
{
|
274
275
|
"id": "y"
|
275
276
|
}
|
276
277
|
EOM
|
277
|
-
|
278
|
+
file 'data_bags/x/z.json', <<EOM
|
278
279
|
{
|
279
280
|
"id": "z"
|
280
281
|
}
|
281
282
|
EOM
|
282
|
-
|
283
|
-
|
283
|
+
it 'knife upload of one data bag item itself succeeds' do
|
284
|
+
knife('upload /data_bags/x/y.json').should_succeed <<EOM
|
284
285
|
Created /data_bags/x
|
285
286
|
Created /data_bags/x/y.json
|
286
287
|
EOM
|
287
|
-
|
288
|
+
knife('diff --name-status /data_bags').should_succeed <<EOM
|
288
289
|
A\t/data_bags/x/z.json
|
289
290
|
EOM
|
291
|
+
end
|
290
292
|
end
|
291
293
|
end
|
292
|
-
end
|
293
294
|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
295
|
+
when_the_chef_server 'has three data bag items' do
|
296
|
+
data_bag 'x', { 'deleted' => {}, 'modified' => {}, 'unmodified' => {} }
|
297
|
+
when_the_repository 'has a modified, unmodified, added and deleted data bag item' do
|
298
|
+
file 'data_bags/x/added.json', <<EOM
|
298
299
|
{
|
299
300
|
"id": "added"
|
300
301
|
}
|
301
302
|
EOM
|
302
|
-
|
303
|
+
file 'data_bags/x/modified.json', <<EOM
|
303
304
|
{
|
304
305
|
"id": "modified",
|
305
306
|
"foo": "bar"
|
306
307
|
}
|
307
308
|
EOM
|
308
|
-
|
309
|
+
file 'data_bags/x/unmodified.json', <<EOM
|
309
310
|
{
|
310
311
|
"id": "unmodified"
|
311
312
|
}
|
312
313
|
EOM
|
313
|
-
|
314
|
-
|
314
|
+
it 'knife upload of the modified file succeeds' do
|
315
|
+
knife('upload /data_bags/x/modified.json').should_succeed <<EOM
|
315
316
|
Updated /data_bags/x/modified.json
|
316
317
|
EOM
|
317
|
-
|
318
|
+
knife('diff --name-status /data_bags').should_succeed <<EOM
|
318
319
|
D\t/data_bags/x/deleted.json
|
319
320
|
A\t/data_bags/x/added.json
|
320
321
|
EOM
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
322
|
+
end
|
323
|
+
it 'knife upload of the unmodified file does nothing' do
|
324
|
+
knife('upload /data_bags/x/unmodified.json').should_succeed ''
|
325
|
+
knife('diff --name-status /data_bags').should_succeed <<EOM
|
325
326
|
D\t/data_bags/x/deleted.json
|
326
327
|
M\t/data_bags/x/modified.json
|
327
328
|
A\t/data_bags/x/added.json
|
328
329
|
EOM
|
329
|
-
|
330
|
-
|
331
|
-
|
330
|
+
end
|
331
|
+
it 'knife upload of the added file succeeds' do
|
332
|
+
knife('upload /data_bags/x/added.json').should_succeed <<EOM
|
332
333
|
Created /data_bags/x/added.json
|
333
334
|
EOM
|
334
|
-
|
335
|
+
knife('diff --name-status /data_bags').should_succeed <<EOM
|
335
336
|
D\t/data_bags/x/deleted.json
|
336
337
|
M\t/data_bags/x/modified.json
|
337
338
|
EOM
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
339
|
+
end
|
340
|
+
it 'knife upload of the deleted file does nothing' do
|
341
|
+
knife('upload /data_bags/x/deleted.json').should_succeed ''
|
342
|
+
knife('diff --name-status /data_bags').should_succeed <<EOM
|
342
343
|
D\t/data_bags/x/deleted.json
|
343
344
|
M\t/data_bags/x/modified.json
|
344
345
|
A\t/data_bags/x/added.json
|
345
346
|
EOM
|
346
|
-
|
347
|
-
|
348
|
-
|
347
|
+
end
|
348
|
+
it 'knife upload --purge of the deleted file deletes it' do
|
349
|
+
knife('upload --purge /data_bags/x/deleted.json').should_succeed <<EOM
|
349
350
|
Deleted extra entry /data_bags/x/deleted.json (purge is on)
|
350
351
|
EOM
|
351
|
-
|
352
|
+
knife('diff --name-status /data_bags').should_succeed <<EOM
|
352
353
|
M\t/data_bags/x/modified.json
|
353
354
|
A\t/data_bags/x/added.json
|
354
355
|
EOM
|
355
|
-
|
356
|
-
|
357
|
-
|
356
|
+
end
|
357
|
+
it 'knife upload of the entire data bag uploads everything' do
|
358
|
+
knife('upload /data_bags/x').should_succeed <<EOM
|
358
359
|
Created /data_bags/x/added.json
|
359
360
|
Updated /data_bags/x/modified.json
|
360
361
|
EOM
|
361
|
-
|
362
|
+
knife('diff --name-status /data_bags').should_succeed <<EOM
|
362
363
|
D\t/data_bags/x/deleted.json
|
363
364
|
EOM
|
364
|
-
|
365
|
-
|
366
|
-
|
365
|
+
end
|
366
|
+
it 'knife upload --purge of the entire data bag uploads everything' do
|
367
|
+
knife('upload --purge /data_bags/x').should_succeed <<EOM
|
367
368
|
Created /data_bags/x/added.json
|
368
369
|
Updated /data_bags/x/modified.json
|
369
370
|
Deleted extra entry /data_bags/x/deleted.json (purge is on)
|
370
371
|
EOM
|
371
|
-
|
372
|
-
end
|
373
|
-
context 'when cwd is the /data_bags directory' do
|
374
|
-
cwd 'data_bags'
|
375
|
-
it 'knife upload fails' do
|
376
|
-
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/
|
372
|
+
knife('diff --name-status /data_bags').should_succeed ''
|
377
373
|
end
|
378
|
-
|
379
|
-
|
374
|
+
context 'when cwd is the /data_bags directory' do
|
375
|
+
cwd 'data_bags'
|
376
|
+
it 'knife upload fails' do
|
377
|
+
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/
|
378
|
+
end
|
379
|
+
it 'knife upload --purge . uploads everything' do
|
380
|
+
knife('upload --purge .').should_succeed <<EOM
|
380
381
|
Created x/added.json
|
381
382
|
Updated x/modified.json
|
382
383
|
Deleted extra entry x/deleted.json (purge is on)
|
383
384
|
EOM
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
385
|
+
knife('diff --name-status /data_bags').should_succeed ''
|
386
|
+
end
|
387
|
+
it 'knife upload --purge * uploads everything' do
|
388
|
+
knife('upload --purge *').should_succeed <<EOM
|
388
389
|
Created x/added.json
|
389
390
|
Updated x/modified.json
|
390
391
|
Deleted extra entry x/deleted.json (purge is on)
|
391
392
|
EOM
|
392
|
-
|
393
|
+
knife('diff --name-status /data_bags').should_succeed ''
|
394
|
+
end
|
393
395
|
end
|
394
396
|
end
|
395
397
|
end
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
knife('upload /cookbooks/x').should_succeed <<EOM
|
398
|
+
|
399
|
+
# Cookbook upload is a funny thing ... direct cookbook upload works, but
|
400
|
+
# upload of a file is designed not to work at present. Make sure that is the
|
401
|
+
# case.
|
402
|
+
when_the_chef_server 'has a cookbook' do
|
403
|
+
cookbook 'x', '1.0.0', { 'metadata.rb' => 'version "1.0.0"', 'z.rb' => '' }
|
404
|
+
when_the_repository 'has a modified, extra and missing file for the cookbook' do
|
405
|
+
file 'cookbooks/x/metadata.rb', 'version "1.0.0"'
|
406
|
+
file 'cookbooks/x/y.rb', 'hi'
|
407
|
+
it 'knife upload of any individual file fails' do
|
408
|
+
knife('upload /cookbooks/x/metadata.rb').should_fail "ERROR: /cookbooks/x/metadata.rb cannot be updated.\n"
|
409
|
+
knife('upload /cookbooks/x/y.rb').should_fail "ERROR: /cookbooks/x cannot have a child created under it.\n"
|
410
|
+
knife('upload --purge /cookbooks/x/z.rb').should_fail "ERROR: /cookbooks/x/z.rb cannot be deleted.\n"
|
411
|
+
end
|
412
|
+
# TODO this is a bit of an inconsistency: if we didn't specify --purge,
|
413
|
+
# technically we shouldn't have deleted missing files. But ... cookbooks
|
414
|
+
# are a special case.
|
415
|
+
it 'knife upload of the cookbook itself succeeds' do
|
416
|
+
knife('upload /cookbooks/x').should_succeed <<EOM
|
416
417
|
Updated /cookbooks/x
|
417
418
|
EOM
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
419
|
+
knife('diff --name-status /cookbooks').should_succeed ''
|
420
|
+
end
|
421
|
+
it 'knife upload --purge of the cookbook itself succeeds' do
|
422
|
+
knife('upload /cookbooks/x').should_succeed <<EOM
|
422
423
|
Updated /cookbooks/x
|
423
424
|
EOM
|
424
|
-
|
425
|
+
knife('diff --name-status /cookbooks').should_succeed ''
|
426
|
+
end
|
425
427
|
end
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
knife('upload /cookbooks/x').should_succeed <<EOM
|
428
|
+
when_the_repository 'has a missing file for the cookbook' do
|
429
|
+
file 'cookbooks/x/metadata.rb', 'version "1.0.0"'
|
430
|
+
it 'knife upload of the cookbook succeeds' do
|
431
|
+
knife('upload /cookbooks/x').should_succeed <<EOM
|
431
432
|
Updated /cookbooks/x
|
432
433
|
EOM
|
433
|
-
|
434
|
+
knife('diff --name-status /cookbooks').should_succeed ''
|
435
|
+
end
|
434
436
|
end
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
knife('upload /cookbooks/x').should_succeed <<EOM
|
437
|
+
when_the_repository 'has an extra file for the cookbook' do
|
438
|
+
file 'cookbooks/x/metadata.rb', 'version "1.0.0"'
|
439
|
+
file 'cookbooks/x/z.rb', ''
|
440
|
+
file 'cookbooks/x/blah.rb', ''
|
441
|
+
it 'knife upload of the cookbook succeeds' do
|
442
|
+
knife('upload /cookbooks/x').should_succeed <<EOM
|
442
443
|
Updated /cookbooks/x
|
443
444
|
EOM
|
444
|
-
|
445
|
+
knife('diff --name-status /cookbooks').should_succeed ''
|
446
|
+
end
|
445
447
|
end
|
446
448
|
end
|
447
|
-
end
|
448
449
|
|
449
|
-
|
450
|
-
|
451
|
-
|
450
|
+
when_the_repository 'has a cookbook' do
|
451
|
+
file 'cookbooks/x/metadata.rb', 'version "1.0.0"'
|
452
|
+
file 'cookbooks/x/onlyin1.0.0.rb', 'old_text'
|
452
453
|
|
453
|
-
|
454
|
-
|
455
|
-
|
454
|
+
when_the_chef_server 'has a later version for the cookbook' do
|
455
|
+
cookbook 'x', '1.0.0', { 'metadata.rb' => 'version "1.0.0"', 'onlyin1.0.0.rb' => '' }
|
456
|
+
cookbook 'x', '1.0.1', { 'metadata.rb' => 'version "1.0.1"', 'onlyin1.0.1.rb' => 'hi' }
|
456
457
|
|
457
|
-
|
458
|
-
|
458
|
+
it 'knife upload /cookbooks/x uploads the local version' do
|
459
|
+
knife('diff --name-status /cookbooks').should_succeed <<EOM
|
459
460
|
M\t/cookbooks/x/metadata.rb
|
460
461
|
D\t/cookbooks/x/onlyin1.0.1.rb
|
461
462
|
A\t/cookbooks/x/onlyin1.0.0.rb
|
462
463
|
EOM
|
463
|
-
|
464
|
+
knife('upload --purge /cookbooks/x').should_succeed <<EOM
|
464
465
|
Updated /cookbooks/x
|
465
466
|
EOM
|
466
|
-
|
467
|
+
knife('diff --name-status /cookbooks').should_succeed <<EOM
|
467
468
|
M\t/cookbooks/x/metadata.rb
|
468
469
|
D\t/cookbooks/x/onlyin1.0.1.rb
|
469
470
|
A\t/cookbooks/x/onlyin1.0.0.rb
|
470
471
|
EOM
|
472
|
+
end
|
471
473
|
end
|
472
|
-
end
|
473
474
|
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
475
|
+
when_the_chef_server 'has an earlier version for the cookbook' do
|
476
|
+
cookbook 'x', '1.0.0', { 'metadata.rb' => 'version "1.0.0"', 'onlyin1.0.0.rb' => ''}
|
477
|
+
cookbook 'x', '0.9.9', { 'metadata.rb' => 'version "0.9.9"', 'onlyin0.9.9.rb' => 'hi' }
|
478
|
+
it 'knife upload /cookbooks/x uploads the local version' do
|
479
|
+
knife('upload --purge /cookbooks/x').should_succeed <<EOM
|
479
480
|
Updated /cookbooks/x
|
480
481
|
EOM
|
481
|
-
|
482
|
+
knife('diff --name-status /cookbooks').should_succeed ''
|
483
|
+
end
|
482
484
|
end
|
483
|
-
end
|
484
485
|
|
485
|
-
|
486
|
-
|
486
|
+
when_the_chef_server 'has a later version for the cookbook, and no current version' do
|
487
|
+
cookbook 'x', '1.0.1', { 'metadata.rb' => 'version "1.0.1"', 'onlyin1.0.1.rb' => 'hi' }
|
487
488
|
|
488
|
-
|
489
|
-
|
489
|
+
it 'knife upload /cookbooks/x uploads the local version' do
|
490
|
+
knife('diff --name-status /cookbooks').should_succeed <<EOM
|
490
491
|
M\t/cookbooks/x/metadata.rb
|
491
492
|
D\t/cookbooks/x/onlyin1.0.1.rb
|
492
493
|
A\t/cookbooks/x/onlyin1.0.0.rb
|
493
494
|
EOM
|
494
|
-
|
495
|
+
knife('upload --purge /cookbooks/x').should_succeed <<EOM
|
495
496
|
Updated /cookbooks/x
|
496
497
|
EOM
|
497
|
-
|
498
|
+
knife('diff --name-status /cookbooks').should_succeed <<EOM
|
498
499
|
M\t/cookbooks/x/metadata.rb
|
499
500
|
D\t/cookbooks/x/onlyin1.0.1.rb
|
500
501
|
A\t/cookbooks/x/onlyin1.0.0.rb
|
501
502
|
EOM
|
503
|
+
end
|
502
504
|
end
|
503
|
-
end
|
504
505
|
|
505
|
-
|
506
|
-
|
506
|
+
when_the_chef_server 'has an earlier version for the cookbook, and no current version' do
|
507
|
+
cookbook 'x', '0.9.9', { 'metadata.rb' => 'version "0.9.9"', 'onlyin0.9.9.rb' => 'hi' }
|
507
508
|
|
508
|
-
|
509
|
-
|
509
|
+
it 'knife upload /cookbooks/x uploads the new version' do
|
510
|
+
knife('upload --purge /cookbooks/x').should_succeed <<EOM
|
510
511
|
Updated /cookbooks/x
|
511
512
|
EOM
|
512
|
-
|
513
|
+
knife('diff --name-status /cookbooks').should_succeed ''
|
514
|
+
end
|
513
515
|
end
|
514
516
|
end
|
515
|
-
end
|
516
517
|
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
518
|
+
when_the_chef_server 'has an environment' do
|
519
|
+
environment 'x', {}
|
520
|
+
when_the_repository 'has an environment with bad JSON' do
|
521
|
+
file 'environments/x.json', '{'
|
522
|
+
it 'knife upload tries and fails' do
|
523
|
+
knife('upload /environments/x.json').should_fail "WARN: Parse error reading #{path_to('environments/x.json')} as JSON: A JSON text must at least contain two octets!\nERROR: /environments/x.json failed to write: Parse error reading JSON: A JSON text must at least contain two octets!\n"
|
524
|
+
knife('diff --name-status /environments/x.json').should_succeed "M\t/environments/x.json\n", :stderr => "WARN: Parse error reading #{path_to('environments/x.json')} as JSON: A JSON text must at least contain two octets!\n"
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
when_the_repository 'has the same environment with the wrong name in the file' do
|
529
|
+
file 'environments/x.json', { 'name' => 'y' }
|
530
|
+
it 'knife upload fails' do
|
531
|
+
knife('upload /environments/x.json').should_fail "ERROR: /environments/x.json failed to write: Name in remote/environments/x.json/x.json must be 'x' (is 'y')\n"
|
532
|
+
knife('diff --name-status /environments/x.json').should_succeed "M\t/environments/x.json\n"
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
when_the_repository 'has the same environment with no name in the file' do
|
537
|
+
file 'environments/x.json', { 'description' => 'hi' }
|
538
|
+
it 'knife upload succeeds' do
|
539
|
+
knife('upload /environments/x.json').should_succeed "Updated /environments/x.json\n"
|
540
|
+
knife('diff --name-status /environments/x.json').should_succeed ''
|
541
|
+
end
|
524
542
|
end
|
525
543
|
end
|
526
544
|
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
545
|
+
when_the_chef_server 'is empty' do
|
546
|
+
when_the_repository 'has an environment with bad JSON' do
|
547
|
+
file 'environments/x.json', '{'
|
548
|
+
it 'knife upload tries and fails' do
|
549
|
+
knife('upload /environments/x.json').should_fail "ERROR: /environments failed to create_child: Parse error reading JSON creating child 'x.json': A JSON text must at least contain two octets!\n"
|
550
|
+
knife('diff --name-status /environments/x.json').should_succeed "A\t/environments/x.json\n"
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
when_the_repository 'has an environment with the wrong name in the file' do
|
555
|
+
file 'environments/x.json', { 'name' => 'y' }
|
556
|
+
it 'knife upload fails' do
|
557
|
+
knife('upload /environments/x.json').should_fail "ERROR: /environments failed to create_child: Name in remote/environments/x.json must be 'x' (is 'y')\n"
|
558
|
+
knife('diff --name-status /environments/x.json').should_succeed "A\t/environments/x.json\n"
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
when_the_repository 'has an environment with no name in the file' do
|
563
|
+
file 'environments/x.json', { 'description' => 'hi' }
|
564
|
+
it 'knife upload succeeds' do
|
565
|
+
knife('upload /environments/x.json').should_succeed "Created /environments/x.json\n"
|
566
|
+
knife('diff --name-status /environments/x.json').should_succeed ''
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
when_the_repository 'has a data bag with no id in the file' do
|
571
|
+
file 'data_bags/bag/x.json', { 'foo' => 'bar' }
|
572
|
+
it 'knife upload succeeds' do
|
573
|
+
knife('upload /data_bags/bag/x.json').should_succeed "Created /data_bags/bag\nCreated /data_bags/bag/x.json\n"
|
574
|
+
knife('diff --name-status /data_bags/bag/x.json').should_succeed ''
|
575
|
+
end
|
532
576
|
end
|
533
577
|
end
|
578
|
+
end # without versioned cookbooks
|
534
579
|
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
580
|
+
with_versioned_cookbooks do
|
581
|
+
when_the_chef_server "has one of each thing" do
|
582
|
+
client 'x', '{}'
|
583
|
+
cookbook 'x', '1.0.0', { 'metadata.rb' => 'version "1.0.0"' }
|
584
|
+
data_bag 'x', { 'y' => '{}' }
|
585
|
+
environment 'x', '{}'
|
586
|
+
node 'x', '{}'
|
587
|
+
role 'x', '{}'
|
588
|
+
user 'x', '{}'
|
589
|
+
|
590
|
+
when_the_repository 'has only top-level directories' do
|
591
|
+
directory 'clients'
|
592
|
+
directory 'cookbooks'
|
593
|
+
directory 'data_bags'
|
594
|
+
directory 'environments'
|
595
|
+
directory 'nodes'
|
596
|
+
directory 'roles'
|
597
|
+
directory 'users'
|
598
|
+
|
599
|
+
it 'knife upload does nothing' do
|
600
|
+
knife('upload /').should_succeed ''
|
601
|
+
knife('diff --name-status /').should_succeed <<EOM
|
602
|
+
D\t/cookbooks/x-1.0.0
|
603
|
+
D\t/data_bags/x
|
604
|
+
D\t/environments/_default.json
|
605
|
+
D\t/environments/x.json
|
606
|
+
D\t/roles/x.json
|
607
|
+
EOM
|
608
|
+
end
|
609
|
+
|
610
|
+
it 'knife upload --purge deletes everything' do
|
611
|
+
knife('upload --purge /').should_succeed(<<EOM, :stderr => "WARNING: /environments/_default.json cannot be deleted (default environment cannot be modified).\n")
|
612
|
+
Deleted extra entry /cookbooks/x-1.0.0 (purge is on)
|
613
|
+
Deleted extra entry /data_bags/x (purge is on)
|
614
|
+
Deleted extra entry /environments/x.json (purge is on)
|
615
|
+
Deleted extra entry /roles/x.json (purge is on)
|
616
|
+
EOM
|
617
|
+
knife('diff --name-status /').should_succeed <<EOM
|
618
|
+
D\t/environments/_default.json
|
619
|
+
EOM
|
620
|
+
end
|
621
|
+
end
|
622
|
+
|
623
|
+
when_the_repository 'has an identical copy of each thing' do
|
624
|
+
file 'clients/x.json', <<EOM
|
625
|
+
{}
|
626
|
+
EOM
|
627
|
+
file 'cookbooks/x-1.0.0/metadata.rb', 'version "1.0.0"'
|
628
|
+
file 'data_bags/x/y.json', <<EOM
|
629
|
+
{
|
630
|
+
"id": "y"
|
631
|
+
}
|
632
|
+
EOM
|
633
|
+
file 'environments/_default.json', <<EOM
|
634
|
+
{
|
635
|
+
"name": "_default",
|
636
|
+
"description": "The default Chef environment",
|
637
|
+
"cookbook_versions": {
|
638
|
+
},
|
639
|
+
"json_class": "Chef::Environment",
|
640
|
+
"chef_type": "environment",
|
641
|
+
"default_attributes": {
|
642
|
+
},
|
643
|
+
"override_attributes": {
|
644
|
+
}
|
645
|
+
}
|
646
|
+
EOM
|
647
|
+
file 'environments/x.json', <<EOM
|
648
|
+
{
|
649
|
+
"chef_type": "environment",
|
650
|
+
"cookbook_versions": {
|
651
|
+
},
|
652
|
+
"default_attributes": {
|
653
|
+
},
|
654
|
+
"description": "",
|
655
|
+
"json_class": "Chef::Environment",
|
656
|
+
"name": "x",
|
657
|
+
"override_attributes": {
|
658
|
+
}
|
659
|
+
}
|
660
|
+
EOM
|
661
|
+
file 'nodes/x.json', <<EOM
|
662
|
+
{}
|
663
|
+
EOM
|
664
|
+
file 'roles/x.json', <<EOM
|
665
|
+
{
|
666
|
+
"chef_type": "role",
|
667
|
+
"default_attributes": {
|
668
|
+
},
|
669
|
+
"description": "",
|
670
|
+
"env_run_lists": {
|
671
|
+
},
|
672
|
+
"json_class": "Chef::Role",
|
673
|
+
"name": "x",
|
674
|
+
"override_attributes": {
|
675
|
+
},
|
676
|
+
"run_list": [
|
677
|
+
|
678
|
+
]
|
679
|
+
}
|
680
|
+
EOM
|
681
|
+
file 'users/x.json', <<EOM
|
682
|
+
{}
|
683
|
+
EOM
|
684
|
+
|
685
|
+
it 'knife upload makes no changes' do
|
686
|
+
knife('upload /cookbooks/x-1.0.0').should_succeed ''
|
687
|
+
knife('diff --name-status /').should_succeed ''
|
688
|
+
end
|
689
|
+
|
690
|
+
it 'knife upload --purge makes no changes' do
|
691
|
+
knife('upload --purge /').should_succeed ''
|
692
|
+
knife('diff --name-status /').should_succeed ''
|
693
|
+
end
|
694
|
+
|
695
|
+
context 'except the role file' do
|
696
|
+
file 'roles/x.json', <<EOM
|
697
|
+
{
|
698
|
+
"chef_type": "role",
|
699
|
+
"default_attributes": {
|
700
|
+
},
|
701
|
+
"description": "blarghle",
|
702
|
+
"env_run_lists": {
|
703
|
+
},
|
704
|
+
"json_class": "Chef::Role",
|
705
|
+
"name": "x",
|
706
|
+
"override_attributes": {
|
707
|
+
},
|
708
|
+
"run_list": [
|
709
|
+
|
710
|
+
]
|
711
|
+
}
|
712
|
+
EOM
|
713
|
+
it 'knife upload changes the role' do
|
714
|
+
knife('upload /').should_succeed "Updated /roles/x.json\n"
|
715
|
+
knife('diff --name-status /').should_succeed ''
|
716
|
+
end
|
717
|
+
end
|
718
|
+
|
719
|
+
context 'except the role file is textually different, but not ACTUALLY different' do
|
720
|
+
file 'roles/x.json', <<EOM
|
721
|
+
{
|
722
|
+
"chef_type": "role",
|
723
|
+
"default_attributes": {
|
724
|
+
},
|
725
|
+
"env_run_lists": {
|
726
|
+
},
|
727
|
+
"json_class": "Chef::Role",
|
728
|
+
"name": "x",
|
729
|
+
"description": "",
|
730
|
+
"override_attributes": {
|
731
|
+
},
|
732
|
+
"run_list": [
|
733
|
+
|
734
|
+
]
|
735
|
+
}
|
736
|
+
EOM
|
737
|
+
it 'knife upload / does not change anything' do
|
738
|
+
knife('upload /').should_succeed ''
|
739
|
+
knife('diff --name-status /').should_succeed ''
|
740
|
+
end
|
741
|
+
end
|
742
|
+
|
743
|
+
context 'as well as one extra copy of each thing' do
|
744
|
+
file 'clients/y.json', { 'name' => 'y' }
|
745
|
+
file 'cookbooks/x-1.0.0/blah.rb', ''
|
746
|
+
file 'cookbooks/x-2.0.0/metadata.rb', 'version "2.0.0"'
|
747
|
+
file 'cookbooks/y-1.0.0/metadata.rb', 'version "1.0.0"'
|
748
|
+
file 'data_bags/x/z.json', <<EOM
|
749
|
+
{
|
750
|
+
"id": "z"
|
751
|
+
}
|
752
|
+
EOM
|
753
|
+
file 'data_bags/y/zz.json', <<EOM
|
754
|
+
{
|
755
|
+
"id": "zz"
|
756
|
+
}
|
757
|
+
EOM
|
758
|
+
file 'environments/y.json', <<EOM
|
759
|
+
{
|
760
|
+
"chef_type": "environment",
|
761
|
+
"cookbook_versions": {
|
762
|
+
},
|
763
|
+
"default_attributes": {
|
764
|
+
},
|
765
|
+
"description": "",
|
766
|
+
"json_class": "Chef::Environment",
|
767
|
+
"name": "y",
|
768
|
+
"override_attributes": {
|
769
|
+
}
|
770
|
+
}
|
771
|
+
EOM
|
772
|
+
file 'nodes/y.json', { 'name' => 'y' }
|
773
|
+
file 'roles/y.json', <<EOM
|
774
|
+
{
|
775
|
+
"chef_type": "role",
|
776
|
+
"default_attributes": {
|
777
|
+
},
|
778
|
+
"description": "",
|
779
|
+
"env_run_lists": {
|
780
|
+
},
|
781
|
+
"json_class": "Chef::Role",
|
782
|
+
"name": "y",
|
783
|
+
"override_attributes": {
|
784
|
+
},
|
785
|
+
"run_list": [
|
786
|
+
|
787
|
+
]
|
788
|
+
}
|
789
|
+
EOM
|
790
|
+
file 'users/y.json', { 'name' => 'y' }
|
791
|
+
|
792
|
+
it 'knife upload adds the new files' do
|
793
|
+
knife('upload /').should_succeed <<EOM
|
794
|
+
Updated /cookbooks/x-1.0.0
|
795
|
+
Created /cookbooks/x-2.0.0
|
796
|
+
Created /cookbooks/y-1.0.0
|
797
|
+
Created /data_bags/x/z.json
|
798
|
+
Created /data_bags/y
|
799
|
+
Created /data_bags/y/zz.json
|
800
|
+
Created /environments/y.json
|
801
|
+
Created /roles/y.json
|
802
|
+
EOM
|
803
|
+
knife('diff --name-status /').should_succeed ''
|
804
|
+
end
|
805
|
+
end
|
806
|
+
end
|
807
|
+
|
808
|
+
when_the_repository 'is empty' do
|
809
|
+
it 'knife upload does nothing' do
|
810
|
+
knife('upload /').should_succeed ''
|
811
|
+
knife('diff --name-status /').should_succeed <<EOM
|
812
|
+
D\t/cookbooks
|
813
|
+
D\t/data_bags
|
814
|
+
D\t/environments
|
815
|
+
D\t/roles
|
816
|
+
EOM
|
817
|
+
end
|
818
|
+
|
819
|
+
it 'knife upload --purge deletes nothing' do
|
820
|
+
knife('upload --purge /').should_fail <<EOM
|
821
|
+
ERROR: /cookbooks cannot be deleted.
|
822
|
+
ERROR: /data_bags cannot be deleted.
|
823
|
+
ERROR: /environments cannot be deleted.
|
824
|
+
ERROR: /roles cannot be deleted.
|
825
|
+
EOM
|
826
|
+
knife('diff --name-status /').should_succeed <<EOM
|
827
|
+
D\t/cookbooks
|
828
|
+
D\t/data_bags
|
829
|
+
D\t/environments
|
830
|
+
D\t/roles
|
831
|
+
EOM
|
832
|
+
end
|
833
|
+
|
834
|
+
context 'when current directory is top level' do
|
835
|
+
cwd '.'
|
836
|
+
it 'knife upload with no parameters reports an error' do
|
837
|
+
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/
|
838
|
+
end
|
839
|
+
end
|
540
840
|
end
|
541
841
|
end
|
542
|
-
end
|
543
842
|
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
843
|
+
# Test upload of an item when the other end doesn't even have the container
|
844
|
+
when_the_chef_server 'is empty' do
|
845
|
+
when_the_repository 'has two data bag items' do
|
846
|
+
file 'data_bags/x/y.json', <<EOM
|
847
|
+
{
|
848
|
+
"id": "y"
|
849
|
+
}
|
850
|
+
EOM
|
851
|
+
file 'data_bags/x/z.json', <<EOM
|
852
|
+
{
|
853
|
+
"id": "z"
|
854
|
+
}
|
855
|
+
EOM
|
856
|
+
it 'knife upload of one data bag item itself succeeds' do
|
857
|
+
knife('upload /data_bags/x/y.json').should_succeed <<EOM
|
858
|
+
Created /data_bags/x
|
859
|
+
Created /data_bags/x/y.json
|
860
|
+
EOM
|
861
|
+
knife('diff --name-status /data_bags').should_succeed <<EOM
|
862
|
+
A\t/data_bags/x/z.json
|
863
|
+
EOM
|
864
|
+
end
|
550
865
|
end
|
551
866
|
end
|
552
867
|
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
868
|
+
when_the_chef_server 'has three data bag items' do
|
869
|
+
data_bag 'x', { 'deleted' => {}, 'modified' => {}, 'unmodified' => {} }
|
870
|
+
when_the_repository 'has a modified, unmodified, added and deleted data bag item' do
|
871
|
+
file 'data_bags/x/added.json', <<EOM
|
872
|
+
{
|
873
|
+
"id": "added"
|
874
|
+
}
|
875
|
+
EOM
|
876
|
+
file 'data_bags/x/modified.json', <<EOM
|
877
|
+
{
|
878
|
+
"id": "modified",
|
879
|
+
"foo": "bar"
|
880
|
+
}
|
881
|
+
EOM
|
882
|
+
file 'data_bags/x/unmodified.json', <<EOM
|
883
|
+
{
|
884
|
+
"id": "unmodified"
|
885
|
+
}
|
886
|
+
EOM
|
887
|
+
it 'knife upload of the modified file succeeds' do
|
888
|
+
knife('upload /data_bags/x/modified.json').should_succeed <<EOM
|
889
|
+
Updated /data_bags/x/modified.json
|
890
|
+
EOM
|
891
|
+
knife('diff --name-status /data_bags').should_succeed <<EOM
|
892
|
+
D\t/data_bags/x/deleted.json
|
893
|
+
A\t/data_bags/x/added.json
|
894
|
+
EOM
|
895
|
+
end
|
896
|
+
it 'knife upload of the unmodified file does nothing' do
|
897
|
+
knife('upload /data_bags/x/unmodified.json').should_succeed ''
|
898
|
+
knife('diff --name-status /data_bags').should_succeed <<EOM
|
899
|
+
D\t/data_bags/x/deleted.json
|
900
|
+
M\t/data_bags/x/modified.json
|
901
|
+
A\t/data_bags/x/added.json
|
902
|
+
EOM
|
903
|
+
end
|
904
|
+
it 'knife upload of the added file succeeds' do
|
905
|
+
knife('upload /data_bags/x/added.json').should_succeed <<EOM
|
906
|
+
Created /data_bags/x/added.json
|
907
|
+
EOM
|
908
|
+
knife('diff --name-status /data_bags').should_succeed <<EOM
|
909
|
+
D\t/data_bags/x/deleted.json
|
910
|
+
M\t/data_bags/x/modified.json
|
911
|
+
EOM
|
912
|
+
end
|
913
|
+
it 'knife upload of the deleted file does nothing' do
|
914
|
+
knife('upload /data_bags/x/deleted.json').should_succeed ''
|
915
|
+
knife('diff --name-status /data_bags').should_succeed <<EOM
|
916
|
+
D\t/data_bags/x/deleted.json
|
917
|
+
M\t/data_bags/x/modified.json
|
918
|
+
A\t/data_bags/x/added.json
|
919
|
+
EOM
|
920
|
+
end
|
921
|
+
it 'knife upload --purge of the deleted file deletes it' do
|
922
|
+
knife('upload --purge /data_bags/x/deleted.json').should_succeed <<EOM
|
923
|
+
Deleted extra entry /data_bags/x/deleted.json (purge is on)
|
924
|
+
EOM
|
925
|
+
knife('diff --name-status /data_bags').should_succeed <<EOM
|
926
|
+
M\t/data_bags/x/modified.json
|
927
|
+
A\t/data_bags/x/added.json
|
928
|
+
EOM
|
929
|
+
end
|
930
|
+
it 'knife upload of the entire data bag uploads everything' do
|
931
|
+
knife('upload /data_bags/x').should_succeed <<EOM
|
932
|
+
Created /data_bags/x/added.json
|
933
|
+
Updated /data_bags/x/modified.json
|
934
|
+
EOM
|
935
|
+
knife('diff --name-status /data_bags').should_succeed <<EOM
|
936
|
+
D\t/data_bags/x/deleted.json
|
937
|
+
EOM
|
938
|
+
end
|
939
|
+
it 'knife upload --purge of the entire data bag uploads everything' do
|
940
|
+
knife('upload --purge /data_bags/x').should_succeed <<EOM
|
941
|
+
Created /data_bags/x/added.json
|
942
|
+
Updated /data_bags/x/modified.json
|
943
|
+
Deleted extra entry /data_bags/x/deleted.json (purge is on)
|
944
|
+
EOM
|
945
|
+
knife('diff --name-status /data_bags').should_succeed ''
|
946
|
+
end
|
947
|
+
context 'when cwd is the /data_bags directory' do
|
948
|
+
cwd 'data_bags'
|
949
|
+
it 'knife upload fails' do
|
950
|
+
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/
|
951
|
+
end
|
952
|
+
it 'knife upload --purge . uploads everything' do
|
953
|
+
knife('upload --purge .').should_succeed <<EOM
|
954
|
+
Created x/added.json
|
955
|
+
Updated x/modified.json
|
956
|
+
Deleted extra entry x/deleted.json (purge is on)
|
957
|
+
EOM
|
958
|
+
knife('diff --name-status /data_bags').should_succeed ''
|
959
|
+
end
|
960
|
+
it 'knife upload --purge * uploads everything' do
|
961
|
+
knife('upload --purge *').should_succeed <<EOM
|
962
|
+
Created x/added.json
|
963
|
+
Updated x/modified.json
|
964
|
+
Deleted extra entry x/deleted.json (purge is on)
|
965
|
+
EOM
|
966
|
+
knife('diff --name-status /data_bags').should_succeed ''
|
967
|
+
end
|
968
|
+
end
|
969
|
+
end
|
970
|
+
end
|
971
|
+
|
972
|
+
# Cookbook upload is a funny thing ... direct cookbook upload works, but
|
973
|
+
# upload of a file is designed not to work at present. Make sure that is the
|
974
|
+
# case.
|
975
|
+
when_the_chef_server 'has a cookbook' do
|
976
|
+
cookbook 'x', '1.0.0', { 'metadata.rb' => 'version "1.0.0"', 'z.rb' => '' }
|
977
|
+
when_the_repository 'has a modified, extra and missing file for the cookbook' do
|
978
|
+
file 'cookbooks/x-1.0.0/metadata.rb', 'version "1.0.0"'
|
979
|
+
file 'cookbooks/x-1.0.0/y.rb', 'hi'
|
980
|
+
it 'knife upload of any individual file fails' do
|
981
|
+
knife('upload /cookbooks/x-1.0.0/metadata.rb').should_fail "ERROR: /cookbooks/x-1.0.0/metadata.rb cannot be updated.\n"
|
982
|
+
knife('upload /cookbooks/x-1.0.0/y.rb').should_fail "ERROR: /cookbooks/x-1.0.0 cannot have a child created under it.\n"
|
983
|
+
knife('upload --purge /cookbooks/x-1.0.0/z.rb').should_fail "ERROR: /cookbooks/x-1.0.0/z.rb cannot be deleted.\n"
|
984
|
+
end
|
985
|
+
# TODO this is a bit of an inconsistency: if we didn't specify --purge,
|
986
|
+
# technically we shouldn't have deleted missing files. But ... cookbooks
|
987
|
+
# are a special case.
|
988
|
+
it 'knife upload of the cookbook itself succeeds' do
|
989
|
+
knife('upload /cookbooks/x-1.0.0').should_succeed <<EOM
|
990
|
+
Updated /cookbooks/x-1.0.0
|
991
|
+
EOM
|
992
|
+
knife('diff --name-status /cookbooks').should_succeed ''
|
993
|
+
end
|
994
|
+
it 'knife upload --purge of the cookbook itself succeeds' do
|
995
|
+
knife('upload /cookbooks/x-1.0.0').should_succeed <<EOM
|
996
|
+
Updated /cookbooks/x-1.0.0
|
997
|
+
EOM
|
998
|
+
knife('diff --name-status /cookbooks').should_succeed ''
|
999
|
+
end
|
1000
|
+
end
|
1001
|
+
when_the_repository 'has a missing file for the cookbook' do
|
1002
|
+
file 'cookbooks/x-1.0.0/metadata.rb', 'version "1.0.0"'
|
1003
|
+
it 'knife upload of the cookbook succeeds' do
|
1004
|
+
knife('upload /cookbooks/x-1.0.0').should_succeed <<EOM
|
1005
|
+
Updated /cookbooks/x-1.0.0
|
1006
|
+
EOM
|
1007
|
+
knife('diff --name-status /cookbooks').should_succeed ''
|
1008
|
+
end
|
1009
|
+
end
|
1010
|
+
when_the_repository 'has an extra file for the cookbook' do
|
1011
|
+
file 'cookbooks/x-1.0.0/metadata.rb', 'version "1.0.0"'
|
1012
|
+
file 'cookbooks/x-1.0.0/z.rb', ''
|
1013
|
+
file 'cookbooks/x-1.0.0/blah.rb', ''
|
1014
|
+
it 'knife upload of the cookbook succeeds' do
|
1015
|
+
knife('upload /cookbooks/x-1.0.0').should_succeed <<EOM
|
1016
|
+
Updated /cookbooks/x-1.0.0
|
1017
|
+
EOM
|
1018
|
+
knife('diff --name-status /cookbooks').should_succeed ''
|
1019
|
+
end
|
558
1020
|
end
|
559
1021
|
end
|
560
1022
|
|
561
|
-
when_the_repository 'has
|
562
|
-
file '
|
563
|
-
|
564
|
-
|
565
|
-
|
1023
|
+
when_the_repository 'has a cookbook' do
|
1024
|
+
file 'cookbooks/x-1.0.0/metadata.rb', 'version "1.0.0"'
|
1025
|
+
file 'cookbooks/x-1.0.0/onlyin1.0.0.rb', 'old_text'
|
1026
|
+
|
1027
|
+
when_the_chef_server 'has a later version for the cookbook' do
|
1028
|
+
cookbook 'x', '1.0.0', { 'metadata.rb' => 'version "1.0.0"', 'onlyin1.0.0.rb' => '' }
|
1029
|
+
cookbook 'x', '1.0.1', { 'metadata.rb' => 'version "1.0.1"', 'onlyin1.0.1.rb' => 'hi' }
|
1030
|
+
|
1031
|
+
it 'knife upload /cookbooks uploads the local version' do
|
1032
|
+
knife('diff --name-status /cookbooks').should_succeed <<EOM
|
1033
|
+
M\t/cookbooks/x-1.0.0/onlyin1.0.0.rb
|
1034
|
+
D\t/cookbooks/x-1.0.1
|
1035
|
+
EOM
|
1036
|
+
knife('upload --purge /cookbooks').should_succeed <<EOM
|
1037
|
+
Updated /cookbooks/x-1.0.0
|
1038
|
+
Deleted extra entry /cookbooks/x-1.0.1 (purge is on)
|
1039
|
+
EOM
|
1040
|
+
knife('diff --name-status /cookbooks').should_succeed ''
|
1041
|
+
end
|
1042
|
+
end
|
1043
|
+
|
1044
|
+
when_the_chef_server 'has an earlier version for the cookbook' do
|
1045
|
+
cookbook 'x', '1.0.0', { 'metadata.rb' => 'version "1.0.0"', 'onlyin1.0.0.rb' => ''}
|
1046
|
+
cookbook 'x', '0.9.9', { 'metadata.rb' => 'version "0.9.9"', 'onlyin0.9.9.rb' => 'hi' }
|
1047
|
+
it 'knife upload /cookbooks uploads the local version' do
|
1048
|
+
knife('upload --purge /cookbooks').should_succeed <<EOM
|
1049
|
+
Updated /cookbooks/x-1.0.0
|
1050
|
+
Deleted extra entry /cookbooks/x-0.9.9 (purge is on)
|
1051
|
+
EOM
|
1052
|
+
knife('diff --name-status /cookbooks').should_succeed ''
|
1053
|
+
end
|
1054
|
+
end
|
1055
|
+
|
1056
|
+
when_the_chef_server 'has a later version for the cookbook, and no current version' do
|
1057
|
+
cookbook 'x', '1.0.1', { 'metadata.rb' => 'version "1.0.1"', 'onlyin1.0.1.rb' => 'hi' }
|
1058
|
+
|
1059
|
+
it 'knife upload /cookbooks/x uploads the local version' do
|
1060
|
+
knife('diff --name-status /cookbooks').should_succeed <<EOM
|
1061
|
+
D\t/cookbooks/x-1.0.1
|
1062
|
+
A\t/cookbooks/x-1.0.0
|
1063
|
+
EOM
|
1064
|
+
knife('upload --purge /cookbooks').should_succeed <<EOM
|
1065
|
+
Created /cookbooks/x-1.0.0
|
1066
|
+
Deleted extra entry /cookbooks/x-1.0.1 (purge is on)
|
1067
|
+
EOM
|
1068
|
+
knife('diff --name-status /cookbooks').should_succeed ''
|
1069
|
+
end
|
1070
|
+
end
|
1071
|
+
|
1072
|
+
when_the_chef_server 'has an earlier version for the cookbook, and no current version' do
|
1073
|
+
cookbook 'x', '0.9.9', { 'metadata.rb' => 'version "0.9.9"', 'onlyin0.9.9.rb' => 'hi' }
|
1074
|
+
|
1075
|
+
it 'knife upload /cookbooks/x uploads the new version' do
|
1076
|
+
knife('upload --purge /cookbooks').should_succeed <<EOM
|
1077
|
+
Created /cookbooks/x-1.0.0
|
1078
|
+
Deleted extra entry /cookbooks/x-0.9.9 (purge is on)
|
1079
|
+
EOM
|
1080
|
+
knife('diff --name-status /cookbooks').should_succeed ''
|
1081
|
+
end
|
566
1082
|
end
|
567
1083
|
end
|
568
1084
|
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
knife
|
1085
|
+
when_the_chef_server 'has an environment' do
|
1086
|
+
environment 'x', {}
|
1087
|
+
when_the_repository 'has an environment with bad JSON' do
|
1088
|
+
file 'environments/x.json', '{'
|
1089
|
+
it 'knife upload tries and fails' do
|
1090
|
+
knife('upload /environments/x.json').should_fail "WARN: Parse error reading #{path_to('environments/x.json')} as JSON: A JSON text must at least contain two octets!\nERROR: /environments/x.json failed to write: Parse error reading JSON: A JSON text must at least contain two octets!\n"
|
1091
|
+
knife('diff --name-status /environments/x.json').should_succeed "M\t/environments/x.json\n", :stderr => "WARN: Parse error reading #{path_to('environments/x.json')} as JSON: A JSON text must at least contain two octets!\n"
|
1092
|
+
end
|
1093
|
+
end
|
1094
|
+
|
1095
|
+
when_the_repository 'has the same environment with the wrong name in the file' do
|
1096
|
+
file 'environments/x.json', { 'name' => 'y' }
|
1097
|
+
it 'knife upload fails' do
|
1098
|
+
knife('upload /environments/x.json').should_fail "ERROR: /environments/x.json failed to write: Name in remote/environments/x.json/x.json must be 'x' (is 'y')\n"
|
1099
|
+
knife('diff --name-status /environments/x.json').should_succeed "M\t/environments/x.json\n"
|
1100
|
+
end
|
1101
|
+
end
|
1102
|
+
|
1103
|
+
when_the_repository 'has the same environment with no name in the file' do
|
1104
|
+
file 'environments/x.json', { 'description' => 'hi' }
|
1105
|
+
it 'knife upload succeeds' do
|
1106
|
+
knife('upload /environments/x.json').should_succeed "Updated /environments/x.json\n"
|
1107
|
+
knife('diff --name-status /environments/x.json').should_succeed ''
|
1108
|
+
end
|
574
1109
|
end
|
575
1110
|
end
|
576
|
-
|
1111
|
+
|
1112
|
+
when_the_chef_server 'is empty' do
|
1113
|
+
when_the_repository 'has an environment with bad JSON' do
|
1114
|
+
file 'environments/x.json', '{'
|
1115
|
+
it 'knife upload tries and fails' do
|
1116
|
+
knife('upload /environments/x.json').should_fail "ERROR: /environments failed to create_child: Parse error reading JSON creating child 'x.json': A JSON text must at least contain two octets!\n"
|
1117
|
+
knife('diff --name-status /environments/x.json').should_succeed "A\t/environments/x.json\n"
|
1118
|
+
end
|
1119
|
+
end
|
1120
|
+
|
1121
|
+
when_the_repository 'has an environment with the wrong name in the file' do
|
1122
|
+
file 'environments/x.json', { 'name' => 'y' }
|
1123
|
+
it 'knife upload fails' do
|
1124
|
+
knife('upload /environments/x.json').should_fail "ERROR: /environments failed to create_child: Name in remote/environments/x.json must be 'x' (is 'y')\n"
|
1125
|
+
knife('diff --name-status /environments/x.json').should_succeed "A\t/environments/x.json\n"
|
1126
|
+
end
|
1127
|
+
end
|
1128
|
+
|
1129
|
+
when_the_repository 'has an environment with no name in the file' do
|
1130
|
+
file 'environments/x.json', { 'description' => 'hi' }
|
1131
|
+
it 'knife upload succeeds' do
|
1132
|
+
knife('upload /environments/x.json').should_succeed "Created /environments/x.json\n"
|
1133
|
+
knife('diff --name-status /environments/x.json').should_succeed ''
|
1134
|
+
end
|
1135
|
+
end
|
1136
|
+
|
1137
|
+
when_the_repository 'has a data bag with no id in the file' do
|
1138
|
+
file 'data_bags/bag/x.json', { 'foo' => 'bar' }
|
1139
|
+
it 'knife upload succeeds' do
|
1140
|
+
knife('upload /data_bags/bag/x.json').should_succeed "Created /data_bags/bag\nCreated /data_bags/bag/x.json\n"
|
1141
|
+
knife('diff --name-status /data_bags/bag/x.json').should_succeed ''
|
1142
|
+
end
|
1143
|
+
end
|
1144
|
+
end
|
1145
|
+
end # with versioned cookbooks
|
1146
|
+
|
577
1147
|
end
|