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
@@ -28,46 +28,59 @@ describe ChefFS::FileSystem::DataBagsDir do
|
|
28
28
|
:client_key => 'key'
|
29
29
|
}, 'everything')
|
30
30
|
}
|
31
|
-
let(:data_bags_dir) { root_dir.child('data_bags') }
|
32
|
-
let(:should_list_data_bags) do
|
33
|
-
@rest.should_receive(:get_rest).with('data').once.and_return(
|
34
|
-
{
|
35
|
-
"achild" => "http://opscode.com/achild",
|
36
|
-
"bchild" => "http://opscode.com/bchild"
|
37
|
-
})
|
38
|
-
end
|
39
|
-
before(:each) do
|
40
|
-
@rest = double("rest")
|
41
|
-
Chef::REST.stub(:new).with('url','username','key') { @rest }
|
42
|
-
end
|
43
31
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
data_bags_dir.dir?.should be_true
|
49
|
-
end
|
50
|
-
it 'exists' do
|
51
|
-
data_bags_dir.exists?.should be_true
|
52
|
-
end
|
53
|
-
it 'has name data_bags' do
|
54
|
-
data_bags_dir.name.should == 'data_bags'
|
55
|
-
end
|
56
|
-
it 'has path /data_bags' do
|
57
|
-
data_bags_dir.path.should == '/data_bags'
|
58
|
-
end
|
59
|
-
it 'has path_for_printing remote/data_bags' do
|
60
|
-
data_bags_dir.path_for_printing.should == 'remote/data_bags'
|
32
|
+
let(:data_bags_dir) do
|
33
|
+
root_dir.child('data_bags').tap do |artifact|
|
34
|
+
artifact.stub(:chef_collection).and_return(chef_collection)
|
35
|
+
end
|
61
36
|
end
|
62
|
-
|
63
|
-
|
64
|
-
|
37
|
+
|
38
|
+
let(:should_list_data_bags) { } # noop. Remove before committing
|
39
|
+
|
40
|
+
let(:chef_collection) do
|
41
|
+
{
|
42
|
+
"achild" => "http://opscode.com/achild",
|
43
|
+
"bchild" => "http://opscode.com/bchild"
|
44
|
+
}
|
65
45
|
end
|
66
|
-
|
67
|
-
|
46
|
+
|
47
|
+
let(:item_collection) do
|
48
|
+
{
|
49
|
+
"aitem" => "http://opscode.com/achild",
|
50
|
+
"bitem" => "http://opscode.com/bchild"
|
51
|
+
}
|
68
52
|
end
|
69
|
-
|
70
|
-
|
53
|
+
|
54
|
+
context 'code contract' do
|
55
|
+
|
56
|
+
it 'has / as parent' do
|
57
|
+
data_bags_dir.parent.should == root_dir
|
58
|
+
end
|
59
|
+
it 'is a directory' do
|
60
|
+
data_bags_dir.dir?.should be_true
|
61
|
+
end
|
62
|
+
it 'exists' do
|
63
|
+
data_bags_dir.exists?.should be_true
|
64
|
+
end
|
65
|
+
it 'has name data_bags' do
|
66
|
+
data_bags_dir.name.should == 'data_bags'
|
67
|
+
end
|
68
|
+
it 'has path /data_bags' do
|
69
|
+
data_bags_dir.path.should == '/data_bags'
|
70
|
+
end
|
71
|
+
it 'has path_for_printing remote/data_bags' do
|
72
|
+
data_bags_dir.path_for_printing.should == 'remote/data_bags'
|
73
|
+
end
|
74
|
+
it 'has correct children' do
|
75
|
+
should_list_data_bags
|
76
|
+
data_bags_dir.children.map { |child| child.name }.should =~ %w(achild bchild)
|
77
|
+
end
|
78
|
+
it 'can have directories as children' do
|
79
|
+
data_bags_dir.can_have_child?('blah', true).should be_true
|
80
|
+
end
|
81
|
+
it 'cannot have files as children' do
|
82
|
+
data_bags_dir.can_have_child?('blah', false).should be_false
|
83
|
+
end
|
71
84
|
end
|
72
85
|
|
73
86
|
shared_examples_for 'a data bag item' do
|
@@ -90,11 +103,14 @@ describe ChefFS::FileSystem::DataBagsDir do
|
|
90
103
|
it 'has correct path_for_printing' do
|
91
104
|
data_bag_item.path_for_printing.should == "remote/data_bags/#{data_bag_dir_name}/#{data_bag_item_name}"
|
92
105
|
end
|
106
|
+
|
93
107
|
it 'reads correctly' do
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
108
|
+
data_bag_item.should_receive(:raw_request).
|
109
|
+
with("data/#{data_bag_dir_name}/#{data_bag_item_short_name}").
|
110
|
+
once.and_return({'a' => 'b'}.to_json)
|
111
|
+
|
112
|
+
data_bag_item.read.should ==
|
113
|
+
'{
|
98
114
|
"id": "aitem",
|
99
115
|
"a": "b"
|
100
116
|
}'
|
@@ -102,13 +118,8 @@ describe ChefFS::FileSystem::DataBagsDir do
|
|
102
118
|
end
|
103
119
|
|
104
120
|
shared_examples_for 'a data bag' do
|
105
|
-
let(:should_list_data_bag_items)
|
106
|
-
|
107
|
-
{
|
108
|
-
"aitem" => "http://opscode.com/achild",
|
109
|
-
"bitem" => "http://opscode.com/bchild"
|
110
|
-
})
|
111
|
-
end
|
121
|
+
let(:should_list_data_bag_items) { data_bag_dir.should_receive(:chef_collection).once.and_return(item_collection) }
|
122
|
+
|
112
123
|
it 'has /data as a parent' do
|
113
124
|
data_bag_dir.parent.should == data_bags_dir
|
114
125
|
end
|
@@ -174,7 +185,11 @@ describe ChefFS::FileSystem::DataBagsDir do
|
|
174
185
|
nonexistent_child.dir?.should be_false
|
175
186
|
end
|
176
187
|
it 'read returns NotFoundError' do
|
177
|
-
|
188
|
+
nonexistent_child.should_receive(:raw_request).
|
189
|
+
with("data/#{data_bag_dir_name}/blah").
|
190
|
+
once.
|
191
|
+
and_raise(Net::HTTPServerException.new(nil,Net::HTTPResponse.new(nil,'404',nil)))
|
192
|
+
|
178
193
|
expect { nonexistent_child.read }.to raise_error(ChefFS::FileSystem::NotFoundError)
|
179
194
|
end
|
180
195
|
end
|
@@ -182,7 +197,6 @@ describe ChefFS::FileSystem::DataBagsDir do
|
|
182
197
|
|
183
198
|
context 'achild from data_bags.children' do
|
184
199
|
let(:data_bag_dir) do
|
185
|
-
should_list_data_bags
|
186
200
|
data_bags_dir.children.select { |child| child.name == 'achild' }.first
|
187
201
|
end
|
188
202
|
let(:data_bag_dir_name) { 'achild' }
|
@@ -16,9 +16,9 @@ describe 'knife deps' do
|
|
16
16
|
when_the_repository 'has a role with a default run_list' do
|
17
17
|
file 'roles/starring.json', { 'run_list' => %w(role[minor] recipe[quiche] recipe[soup::chicken]) }
|
18
18
|
file 'roles/minor.json', {}
|
19
|
-
file 'cookbooks/quiche/metadata.rb', ''
|
19
|
+
file 'cookbooks/quiche/metadata.rb', 'name "quiche"'
|
20
20
|
file 'cookbooks/quiche/recipes/default.rb', ''
|
21
|
-
file 'cookbooks/soup/metadata.rb', ''
|
21
|
+
file 'cookbooks/soup/metadata.rb', 'name "soup"'
|
22
22
|
file 'cookbooks/soup/recipes/chicken.rb', ''
|
23
23
|
it 'knife deps reports all dependencies' do
|
24
24
|
knife('deps /roles/starring.json').should_succeed <<EOM
|
@@ -33,9 +33,9 @@ EOM
|
|
33
33
|
when_the_repository 'has a role with an env_run_list' do
|
34
34
|
file 'roles/starring.json', { 'env_run_lists' => { 'desert' => %w(role[minor] recipe[quiche] recipe[soup::chicken]) } }
|
35
35
|
file 'roles/minor.json', {}
|
36
|
-
file 'cookbooks/quiche/metadata.rb', ''
|
36
|
+
file 'cookbooks/quiche/metadata.rb', 'name "quiche"'
|
37
37
|
file 'cookbooks/quiche/recipes/default.rb', ''
|
38
|
-
file 'cookbooks/soup/metadata.rb', ''
|
38
|
+
file 'cookbooks/soup/metadata.rb', 'name "soup"'
|
39
39
|
file 'cookbooks/soup/recipes/chicken.rb', ''
|
40
40
|
it 'knife deps reports all dependencies' do
|
41
41
|
knife('deps /roles/starring.json').should_succeed <<EOM
|
@@ -62,9 +62,9 @@ EOM
|
|
62
62
|
end
|
63
63
|
when_the_repository 'has a node with roles and recipes in its run_list' do
|
64
64
|
file 'roles/minor.json', {}
|
65
|
-
file 'cookbooks/quiche/metadata.rb', ''
|
65
|
+
file 'cookbooks/quiche/metadata.rb', 'name "quiche"'
|
66
66
|
file 'cookbooks/quiche/recipes/default.rb', ''
|
67
|
-
file 'cookbooks/soup/metadata.rb', ''
|
67
|
+
file 'cookbooks/soup/metadata.rb', 'name "soup"'
|
68
68
|
file 'cookbooks/soup/recipes/chicken.rb', ''
|
69
69
|
file 'nodes/mort.json', { 'run_list' => %w(role[minor] recipe[quiche] recipe[soup::chicken]) }
|
70
70
|
it 'knife deps reports just the node' do
|
@@ -77,15 +77,15 @@ EOM
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
when_the_repository 'has a cookbook with no dependencies' do
|
80
|
-
file 'cookbooks/quiche/metadata.rb', ''
|
80
|
+
file 'cookbooks/quiche/metadata.rb', 'name "quiche"'
|
81
81
|
file 'cookbooks/quiche/recipes/default.rb', ''
|
82
82
|
it 'knife deps reports just the cookbook' do
|
83
83
|
knife('deps /cookbooks/quiche').should_succeed "/cookbooks/quiche\n"
|
84
84
|
end
|
85
85
|
end
|
86
86
|
when_the_repository 'has a cookbook with dependencies' do
|
87
|
-
file 'cookbooks/kettle/metadata.rb', ''
|
88
|
-
file 'cookbooks/quiche/metadata.rb', '
|
87
|
+
file 'cookbooks/kettle/metadata.rb', 'name "kettle"'
|
88
|
+
file 'cookbooks/quiche/metadata.rb', "name 'quiche'\ndepends 'kettle'\n"
|
89
89
|
file 'cookbooks/quiche/recipes/default.rb', ''
|
90
90
|
it 'knife deps reports just the cookbook' do
|
91
91
|
knife('deps /cookbooks/quiche').should_succeed "/cookbooks/kettle\n/cookbooks/quiche\n"
|
@@ -106,9 +106,9 @@ EOM
|
|
106
106
|
when_the_repository 'has a deep dependency tree' do
|
107
107
|
file 'roles/starring.json', { 'run_list' => %w(role[minor] recipe[quiche] recipe[soup::chicken]) }
|
108
108
|
file 'roles/minor.json', {}
|
109
|
-
file 'cookbooks/quiche/metadata.rb', ''
|
109
|
+
file 'cookbooks/quiche/metadata.rb', 'name "quiche"'
|
110
110
|
file 'cookbooks/quiche/recipes/default.rb', ''
|
111
|
-
file 'cookbooks/soup/metadata.rb', ''
|
111
|
+
file 'cookbooks/soup/metadata.rb', 'name "soup"'
|
112
112
|
file 'cookbooks/soup/recipes/chicken.rb', ''
|
113
113
|
file 'environments/desert.json', {}
|
114
114
|
file 'nodes/mort.json', { 'chef_environment' => 'desert', 'run_list' => [ 'role[starring]' ] }
|
@@ -171,10 +171,10 @@ EOM
|
|
171
171
|
|
172
172
|
context 'circular dependencies' do
|
173
173
|
when_the_repository 'has cookbooks with circular dependencies' do
|
174
|
-
file 'cookbooks/foo/metadata.rb', '
|
175
|
-
file 'cookbooks/bar/metadata.rb', '
|
176
|
-
file 'cookbooks/baz/metadata.rb', '
|
177
|
-
file 'cookbooks/self/metadata.rb', '
|
174
|
+
file 'cookbooks/foo/metadata.rb', "name 'foo'\ndepends 'bar'\n"
|
175
|
+
file 'cookbooks/bar/metadata.rb', "name 'bar'\ndepends 'baz'\n"
|
176
|
+
file 'cookbooks/baz/metadata.rb', "name 'baz'\ndepends 'foo'\n"
|
177
|
+
file 'cookbooks/self/metadata.rb', "name 'self'\ndepends 'self'\n"
|
178
178
|
it 'knife deps prints each once' do
|
179
179
|
knife('deps /cookbooks/foo /cookbooks/self').should_succeed <<EOM
|
180
180
|
/cookbooks/baz
|
@@ -312,7 +312,7 @@ EOM
|
|
312
312
|
end
|
313
313
|
end
|
314
314
|
when_the_repository 'has a cookbook' do
|
315
|
-
file 'cookbooks/blah/metadata.rb', ''
|
315
|
+
file 'cookbooks/blah/metadata.rb', 'name "blah"'
|
316
316
|
it 'knife deps on a cookbook file shows no dependencies' do
|
317
317
|
knife('deps /cookbooks/blah/metadata.rb').should_succeed(
|
318
318
|
"/cookbooks/blah/metadata.rb\n"
|
@@ -333,8 +333,8 @@ EOM
|
|
333
333
|
when_the_chef_server 'has a role with a default run_list' do
|
334
334
|
role 'starring', { 'run_list' => %w(role[minor] recipe[quiche] recipe[soup::chicken]) }
|
335
335
|
role 'minor', {}
|
336
|
-
cookbook 'quiche', '1.0.0', { 'metadata.rb' => '', 'recipes' => { 'default.rb' => '' } }
|
337
|
-
cookbook 'soup', '1.0.0', { 'metadata.rb' => '', 'recipes' => { 'chicken.rb' => '' } }
|
336
|
+
cookbook 'quiche', '1.0.0', { 'metadata.rb' => "name 'quiche'\nversion '1.0.0'\n", 'recipes' => { 'default.rb' => '' } }
|
337
|
+
cookbook 'soup', '1.0.0', { 'metadata.rb' => "name 'soup'\nversion '1.0.0'\n", 'recipes' => { 'chicken.rb' => '' } }
|
338
338
|
it 'knife deps reports all dependencies' do
|
339
339
|
knife('deps --remote /roles/starring.json').should_succeed <<EOM
|
340
340
|
/roles/minor.json
|
@@ -348,8 +348,8 @@ EOM
|
|
348
348
|
when_the_chef_server 'has a role with an env_run_list' do
|
349
349
|
role 'starring', { 'env_run_lists' => { 'desert' => %w(role[minor] recipe[quiche] recipe[soup::chicken]) } }
|
350
350
|
role 'minor', {}
|
351
|
-
cookbook 'quiche', '1.0.0', { 'metadata.rb' => '', 'recipes' => { 'default.rb' => '' } }
|
352
|
-
cookbook 'soup', '1.0.0', { 'metadata.rb' => '', 'recipes' => { 'chicken.rb' => '' } }
|
351
|
+
cookbook 'quiche', '1.0.0', { 'metadata.rb' => "name 'quiche'\nversion '1.0.0'\n", 'recipes' => { 'default.rb' => '' } }
|
352
|
+
cookbook 'soup', '1.0.0', { 'metadata.rb' => "name 'soup'\nversion '1.0.0'\n", 'recipes' => { 'chicken.rb' => '' } }
|
353
353
|
it 'knife deps reports all dependencies' do
|
354
354
|
knife('deps --remote /roles/starring.json').should_succeed <<EOM
|
355
355
|
/roles/minor.json
|
@@ -375,8 +375,8 @@ EOM
|
|
375
375
|
end
|
376
376
|
when_the_chef_server 'has a node with roles and recipes in its run_list' do
|
377
377
|
role 'minor', {}
|
378
|
-
cookbook 'quiche', '1.0.0', { 'metadata.rb' => '', 'recipes' => { 'default.rb' => '' } }
|
379
|
-
cookbook 'soup', '1.0.0', { 'metadata.rb' => '', 'recipes' => { 'chicken.rb' => '' } }
|
378
|
+
cookbook 'quiche', '1.0.0', { 'metadata.rb' => "name 'quiche'\nversion '1.0.0'\n", 'recipes' => { 'default.rb' => '' } }
|
379
|
+
cookbook 'soup', '1.0.0', { 'metadata.rb' => "name 'soup'\nversion '1.0.0'\n", 'recipes' => { 'chicken.rb' => '' } }
|
380
380
|
node 'mort', { 'run_list' => %w(role[minor] recipe[quiche] recipe[soup::chicken]) }
|
381
381
|
it 'knife deps reports just the node' do
|
382
382
|
knife('deps --remote --repo-mode=everything /nodes/mort.json').should_succeed <<EOM
|
@@ -388,14 +388,14 @@ EOM
|
|
388
388
|
end
|
389
389
|
end
|
390
390
|
when_the_chef_server 'has a cookbook with no dependencies' do
|
391
|
-
cookbook 'quiche', '1.0.0', { 'metadata.rb' => '', 'recipes' => { 'default.rb' => '' } }
|
391
|
+
cookbook 'quiche', '1.0.0', { 'metadata.rb' => "name 'quiche'\nversion '1.0.0'\n", 'recipes' => { 'default.rb' => '' } }
|
392
392
|
it 'knife deps reports just the cookbook' do
|
393
393
|
knife('deps --remote /cookbooks/quiche').should_succeed "/cookbooks/quiche\n"
|
394
394
|
end
|
395
395
|
end
|
396
396
|
when_the_chef_server 'has a cookbook with dependencies' do
|
397
|
-
cookbook 'kettle', '1.0.0', { 'metadata.rb' => '' }
|
398
|
-
cookbook 'quiche', '1.0.0', { 'metadata.rb' => '
|
397
|
+
cookbook 'kettle', '1.0.0', { 'metadata.rb' => "name 'kettle'\nversion '1.0.0'\n" }
|
398
|
+
cookbook 'quiche', '1.0.0', { 'metadata.rb' => "name 'quiche'\ndepends 'kettle'\n", 'recipes' => { 'default.rb' => '' } }
|
399
399
|
it 'knife deps reports just the cookbook' do
|
400
400
|
knife('deps --remote /cookbooks/quiche').should_succeed "/cookbooks/kettle\n/cookbooks/quiche\n"
|
401
401
|
end
|
@@ -415,8 +415,8 @@ EOM
|
|
415
415
|
when_the_chef_server 'has a deep dependency tree' do
|
416
416
|
role 'starring', { 'run_list' => %w(role[minor] recipe[quiche] recipe[soup::chicken]) }
|
417
417
|
role 'minor', {}
|
418
|
-
cookbook 'quiche', '1.0.0', { 'metadata.rb' => '', 'recipes' => { 'default.rb' => '' } }
|
419
|
-
cookbook 'soup', '1.0.0', { 'metadata.rb' => '', 'recipes' => { 'chicken.rb' => '' } }
|
418
|
+
cookbook 'quiche', '1.0.0', { 'metadata.rb' => "name 'quiche'\nversion '1.0.0'\n", 'recipes' => { 'default.rb' => '' } }
|
419
|
+
cookbook 'soup', '1.0.0', { 'metadata.rb' => "name 'soup'\nversion '1.0.0'\n", 'recipes' => { 'chicken.rb' => '' } }
|
420
420
|
environment 'desert', {}
|
421
421
|
node 'mort', { 'chef_environment' => 'desert', 'run_list' => [ 'role[starring]' ] }
|
422
422
|
node 'bart', { 'run_list' => [ 'role[minor]' ] }
|
@@ -478,10 +478,10 @@ EOM
|
|
478
478
|
|
479
479
|
context 'circular dependencies' do
|
480
480
|
when_the_chef_server 'has cookbooks with circular dependencies' do
|
481
|
-
cookbook 'foo', '1.0.0', { 'metadata.rb'
|
482
|
-
cookbook 'bar', '1.0.0', { 'metadata.rb'
|
483
|
-
cookbook 'baz', '1.0.0', { 'metadata.rb'
|
484
|
-
cookbook 'self', '1.0.0', { 'metadata.rb' => '
|
481
|
+
cookbook 'foo', '1.0.0', { 'metadata.rb' => "name 'foo'\ndepends 'bar'\n" }
|
482
|
+
cookbook 'bar', '1.0.0', { 'metadata.rb' => "name 'bar'\ndepends 'baz'\n" }
|
483
|
+
cookbook 'baz', '1.0.0', { 'metadata.rb' => "name 'baz'\ndepends 'foo'\n" }
|
484
|
+
cookbook 'self', '1.0.0', { 'metadata.rb' => "name 'self'\ndepends 'self'\n" }
|
485
485
|
it 'knife deps prints each once' do
|
486
486
|
knife('deps --remote /cookbooks/foo /cookbooks/self').should_succeed <<EOM
|
487
487
|
/cookbooks/baz
|
@@ -615,7 +615,7 @@ EOM
|
|
615
615
|
end
|
616
616
|
end
|
617
617
|
when_the_chef_server 'has a cookbook' do
|
618
|
-
cookbook 'blah', '1.0.0', { 'metadata.rb' => '' }
|
618
|
+
cookbook 'blah', '1.0.0', { 'metadata.rb' => 'name "blah"' }
|
619
619
|
it 'knife deps on a cookbook file shows no dependencies' do
|
620
620
|
knife('deps --remote /cookbooks/blah/metadata.rb').should_succeed(
|
621
621
|
"/cookbooks/blah/metadata.rb\n"
|
@@ -5,26 +5,27 @@ describe 'knife diff' do
|
|
5
5
|
extend IntegrationSupport
|
6
6
|
include KnifeSupport
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
knife
|
8
|
+
context 'without versioned cookbooks' do
|
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 diff reports everything as deleted' do
|
28
|
+
knife('diff --name-status /').should_succeed <<EOM
|
28
29
|
D\t/cookbooks/x
|
29
30
|
D\t/data_bags/x
|
30
31
|
D\t/environments/_default.json
|
@@ -34,17 +35,17 @@ EOM
|
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
37
|
-
|
38
|
-
|
38
|
+
when_the_repository 'has an identical copy of each thing' do
|
39
|
+
file 'clients/x.json', <<EOM
|
39
40
|
{}
|
40
41
|
EOM
|
41
|
-
|
42
|
-
|
42
|
+
file 'cookbooks/x/metadata.rb', 'version "1.0.0"'
|
43
|
+
file 'data_bags/x/y.json', <<EOM
|
43
44
|
{
|
44
45
|
"id": "y"
|
45
46
|
}
|
46
47
|
EOM
|
47
|
-
|
48
|
+
file 'environments/_default.json', <<EOM
|
48
49
|
{
|
49
50
|
"name": "_default",
|
50
51
|
"description": "The default Chef environment",
|
@@ -58,7 +59,7 @@ EOM
|
|
58
59
|
}
|
59
60
|
}
|
60
61
|
EOM
|
61
|
-
|
62
|
+
file 'environments/x.json', <<EOM
|
62
63
|
{
|
63
64
|
"chef_type": "environment",
|
64
65
|
"cookbook_versions": {
|
@@ -72,10 +73,10 @@ EOM
|
|
72
73
|
}
|
73
74
|
}
|
74
75
|
EOM
|
75
|
-
|
76
|
+
file 'nodes/x.json', <<EOM
|
76
77
|
{}
|
77
78
|
EOM
|
78
|
-
|
79
|
+
file 'roles/x.json', <<EOM
|
79
80
|
{
|
80
81
|
"chef_type": "role",
|
81
82
|
"default_attributes": {
|
@@ -92,48 +93,48 @@ EOM
|
|
92
93
|
]
|
93
94
|
}
|
94
95
|
EOM
|
95
|
-
|
96
|
+
file 'users/x.json', <<EOM
|
96
97
|
{}
|
97
98
|
EOM
|
98
99
|
|
99
|
-
|
100
|
-
|
101
|
-
|
100
|
+
it 'knife diff reports no differences' do
|
101
|
+
knife('diff /').should_succeed ''
|
102
|
+
end
|
102
103
|
|
103
|
-
|
104
|
-
|
105
|
-
|
104
|
+
it 'knife diff /environments/nonexistent.json reports an error' do
|
105
|
+
knife('diff /environments/nonexistent.json').should_fail "ERROR: /environments/nonexistent.json: No such file or directory on remote or local\n"
|
106
|
+
end
|
106
107
|
|
107
|
-
|
108
|
-
|
109
|
-
|
108
|
+
it 'knife diff /environments/*.txt reports an error' do
|
109
|
+
knife('diff /environments/*.txt').should_fail "ERROR: /environments/*.txt: No such file or directory on remote or local\n"
|
110
|
+
end
|
110
111
|
|
111
|
-
|
112
|
-
|
112
|
+
context 'except the role file' do
|
113
|
+
file 'roles/x.json', <<EOM
|
113
114
|
{
|
114
115
|
"foo": "bar"
|
115
116
|
}
|
116
117
|
EOM
|
117
|
-
|
118
|
-
|
118
|
+
it 'knife diff reports the role as different' do
|
119
|
+
knife('diff --name-status /').should_succeed <<EOM
|
119
120
|
M\t/roles/x.json
|
120
121
|
EOM
|
122
|
+
end
|
121
123
|
end
|
122
|
-
end
|
123
124
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
125
|
+
context 'as well as one extra copy of each thing' do
|
126
|
+
file 'clients/y.json', {}
|
127
|
+
file 'cookbooks/x/blah.rb', ''
|
128
|
+
file 'cookbooks/y/metadata.rb', 'version "1.0.0"'
|
129
|
+
file 'data_bags/x/z.json', {}
|
130
|
+
file 'data_bags/y/zz.json', {}
|
131
|
+
file 'environments/y.json', {}
|
132
|
+
file 'nodes/y.json', {}
|
133
|
+
file 'roles/y.json', {}
|
134
|
+
file 'users/y.json', {}
|
135
|
+
|
136
|
+
it 'knife diff reports the new files as added' do
|
137
|
+
knife('diff --name-status /').should_succeed <<EOM
|
137
138
|
A\t/cookbooks/x/blah.rb
|
138
139
|
A\t/cookbooks/y
|
139
140
|
A\t/data_bags/x/z.json
|
@@ -141,160 +142,451 @@ A\t/data_bags/y
|
|
141
142
|
A\t/environments/y.json
|
142
143
|
A\t/roles/y.json
|
143
144
|
EOM
|
144
|
-
|
145
|
+
end
|
145
146
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
147
|
+
context 'when cwd is the data_bags directory' do
|
148
|
+
cwd 'data_bags'
|
149
|
+
it 'knife diff reports different data bags' do
|
150
|
+
knife('diff --name-status').should_succeed <<EOM
|
150
151
|
A\tx/z.json
|
151
152
|
A\ty
|
152
153
|
EOM
|
153
|
-
|
154
|
-
|
155
|
-
|
154
|
+
end
|
155
|
+
it 'knife diff * reports different data bags' do
|
156
|
+
knife('diff --name-status *').should_succeed <<EOM
|
156
157
|
A\tx/z.json
|
157
158
|
A\ty
|
158
159
|
EOM
|
160
|
+
end
|
159
161
|
end
|
160
162
|
end
|
161
163
|
end
|
162
|
-
end
|
163
164
|
|
164
|
-
|
165
|
-
|
166
|
-
|
165
|
+
when_the_repository 'is empty' do
|
166
|
+
it 'knife diff reports everything as deleted' do
|
167
|
+
knife('diff --name-status /').should_succeed <<EOM
|
167
168
|
D\t/cookbooks
|
168
169
|
D\t/data_bags
|
169
170
|
D\t/environments
|
170
171
|
D\t/roles
|
171
172
|
EOM
|
173
|
+
end
|
172
174
|
end
|
173
175
|
end
|
174
|
-
end
|
175
176
|
|
176
|
-
|
177
|
-
|
178
|
-
|
177
|
+
when_the_repository 'has a cookbook' do
|
178
|
+
file 'cookbooks/x/metadata.rb', 'version "1.0.0"'
|
179
|
+
file 'cookbooks/x/onlyin1.0.0.rb', ''
|
179
180
|
|
180
|
-
|
181
|
-
|
182
|
-
|
181
|
+
when_the_chef_server 'has a later version for the cookbook' do
|
182
|
+
cookbook 'x', '1.0.0', { 'metadata.rb' => 'version "1.0.0"', 'onlyin1.0.0.rb' => ''}
|
183
|
+
cookbook 'x', '1.0.1', { 'metadata.rb' => 'version "1.0.1"', 'onlyin1.0.1.rb' => '' }
|
183
184
|
|
184
|
-
|
185
|
-
|
185
|
+
it 'knife diff /cookbooks/x shows differences' do
|
186
|
+
knife('diff --name-status /cookbooks/x').should_succeed <<EOM
|
186
187
|
M\t/cookbooks/x/metadata.rb
|
187
188
|
D\t/cookbooks/x/onlyin1.0.1.rb
|
188
189
|
A\t/cookbooks/x/onlyin1.0.0.rb
|
189
190
|
EOM
|
190
|
-
|
191
|
+
end
|
191
192
|
|
192
|
-
|
193
|
-
|
193
|
+
it 'knife diff --diff-filter=MAT does not show deleted files' do
|
194
|
+
knife('diff --diff-filter=MAT --name-status /cookbooks/x').should_succeed <<EOM
|
194
195
|
M\t/cookbooks/x/metadata.rb
|
195
196
|
A\t/cookbooks/x/onlyin1.0.0.rb
|
196
197
|
EOM
|
198
|
+
end
|
197
199
|
end
|
198
|
-
end
|
199
200
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
201
|
+
when_the_chef_server 'has an earlier version for the cookbook' do
|
202
|
+
cookbook 'x', '1.0.0', { 'metadata.rb' => 'version "1.0.0"', 'onlyin1.0.0.rb' => '' }
|
203
|
+
cookbook 'x', '0.9.9', { 'metadata.rb' => 'version "0.9.9"', 'onlyin0.9.9.rb' => '' }
|
204
|
+
it 'knife diff /cookbooks/x shows no differences' do
|
205
|
+
knife('diff --name-status /cookbooks/x').should_succeed ''
|
206
|
+
end
|
205
207
|
end
|
206
|
-
end
|
207
208
|
|
208
|
-
|
209
|
-
|
209
|
+
when_the_chef_server 'has a later version for the cookbook, and no current version' do
|
210
|
+
cookbook 'x', '1.0.1', { 'metadata.rb' => 'version "1.0.1"', 'onlyin1.0.1.rb' => '' }
|
210
211
|
|
211
|
-
|
212
|
-
|
212
|
+
it 'knife diff /cookbooks/x shows the differences' do
|
213
|
+
knife('diff --name-status /cookbooks/x').should_succeed <<EOM
|
213
214
|
M\t/cookbooks/x/metadata.rb
|
214
215
|
D\t/cookbooks/x/onlyin1.0.1.rb
|
215
216
|
A\t/cookbooks/x/onlyin1.0.0.rb
|
216
217
|
EOM
|
218
|
+
end
|
217
219
|
end
|
218
|
-
end
|
219
220
|
|
220
|
-
|
221
|
-
|
221
|
+
when_the_chef_server 'has an earlier version for the cookbook, and no current version' do
|
222
|
+
cookbook 'x', '0.9.9', { 'metadata.rb' => 'version "0.9.9"', 'onlyin0.9.9.rb' => '' }
|
222
223
|
|
223
|
-
|
224
|
-
|
224
|
+
it 'knife diff /cookbooks/x shows the differences' do
|
225
|
+
knife('diff --name-status /cookbooks/x').should_succeed <<EOM
|
225
226
|
M\t/cookbooks/x/metadata.rb
|
226
227
|
D\t/cookbooks/x/onlyin0.9.9.rb
|
227
228
|
A\t/cookbooks/x/onlyin1.0.0.rb
|
228
229
|
EOM
|
230
|
+
end
|
229
231
|
end
|
230
232
|
end
|
231
|
-
end
|
232
233
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
234
|
+
context 'json diff tests' do
|
235
|
+
when_the_repository 'has an empty environment file' do
|
236
|
+
file 'environments/x.json', {}
|
237
|
+
when_the_chef_server 'has an empty environment' do
|
238
|
+
environment 'x', {}
|
239
|
+
it 'knife diff returns no differences' do
|
240
|
+
knife('diff /environments/x.json').should_succeed ''
|
241
|
+
end
|
240
242
|
end
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
knife('diff /environments/x.json').should_succeed(/
|
243
|
+
when_the_chef_server 'has an environment with a different value' do
|
244
|
+
environment 'x', { 'description' => 'hi' }
|
245
|
+
it 'knife diff reports the difference', :pending => (RUBY_VERSION < "1.9") do
|
246
|
+
knife('diff /environments/x.json').should_succeed(/
|
246
247
|
{
|
247
248
|
- "name": "x",
|
248
249
|
- "description": "hi"
|
249
250
|
\+ "name": "x"
|
250
251
|
}
|
251
252
|
/)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
when_the_repository 'has an environment file with a value in it' do
|
258
|
+
file 'environments/x.json', { 'description' => 'hi' }
|
259
|
+
when_the_chef_server 'has an environment with the same value' do
|
260
|
+
environment 'x', { 'description' => 'hi' }
|
261
|
+
it 'knife diff returns no differences' do
|
262
|
+
knife('diff /environments/x.json').should_succeed ''
|
263
|
+
end
|
264
|
+
end
|
265
|
+
when_the_chef_server 'has an environment with no value' do
|
266
|
+
environment 'x', {}
|
267
|
+
it 'knife diff reports the difference', :pending => (RUBY_VERSION < "1.9") do
|
268
|
+
knife('diff /environments/x.json').should_succeed(/
|
269
|
+
{
|
270
|
+
- "name": "x"
|
271
|
+
\+ "name": "x",
|
272
|
+
\+ "description": "hi"
|
273
|
+
}
|
274
|
+
/)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
when_the_chef_server 'has an environment with a different value' do
|
278
|
+
environment 'x', { 'description' => 'lo' }
|
279
|
+
it 'knife diff reports the difference', :pending => (RUBY_VERSION < "1.9") do
|
280
|
+
knife('diff /environments/x.json').should_succeed(/
|
281
|
+
{
|
282
|
+
"name": "x",
|
283
|
+
- "description": "lo"
|
284
|
+
\+ "description": "hi"
|
285
|
+
}
|
286
|
+
/)
|
287
|
+
end
|
252
288
|
end
|
253
289
|
end
|
254
290
|
end
|
255
291
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
it 'knife diff
|
261
|
-
knife('diff /environments/x.json').should_succeed ''
|
292
|
+
when_the_chef_server 'has an environment' do
|
293
|
+
environment 'x', {}
|
294
|
+
when_the_repository 'has an environment with bad JSON' do
|
295
|
+
file 'environments/x.json', '{'
|
296
|
+
it 'knife diff reports an error and does a textual diff' do
|
297
|
+
knife('diff /environments/x.json').should_succeed(/- "name": "x"/, :stderr => "WARN: Parse error reading #{path_to('environments/x.json')} as JSON: A JSON text must at least contain two octets!\n")
|
262
298
|
end
|
263
299
|
end
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
300
|
+
end
|
301
|
+
end # without versioned cookbooks
|
302
|
+
|
303
|
+
with_versioned_cookbooks do
|
304
|
+
when_the_chef_server "has one of each thing" do
|
305
|
+
client 'x', '{}'
|
306
|
+
cookbook 'x', '1.0.0', { 'metadata.rb' => 'version "1.0.0"' }
|
307
|
+
data_bag 'x', { 'y' => '{}' }
|
308
|
+
environment 'x', '{}'
|
309
|
+
node 'x', '{}'
|
310
|
+
role 'x', '{}'
|
311
|
+
user 'x', '{}'
|
312
|
+
|
313
|
+
when_the_repository 'has only top-level directories' do
|
314
|
+
directory 'clients'
|
315
|
+
directory 'cookbooks'
|
316
|
+
directory 'data_bags'
|
317
|
+
directory 'environments'
|
318
|
+
directory 'nodes'
|
319
|
+
directory 'roles'
|
320
|
+
directory 'users'
|
321
|
+
|
322
|
+
it 'knife diff reports everything as deleted' do
|
323
|
+
knife('diff --name-status /').should_succeed <<EOM
|
324
|
+
D\t/cookbooks/x-1.0.0
|
325
|
+
D\t/data_bags/x
|
326
|
+
D\t/environments/_default.json
|
327
|
+
D\t/environments/x.json
|
328
|
+
D\t/roles/x.json
|
329
|
+
EOM
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
when_the_repository 'has an identical copy of each thing' do
|
334
|
+
file 'clients/x.json', <<EOM
|
335
|
+
{}
|
336
|
+
EOM
|
337
|
+
file 'cookbooks/x-1.0.0/metadata.rb', 'version "1.0.0"'
|
338
|
+
file 'data_bags/x/y.json', <<EOM
|
339
|
+
{
|
340
|
+
"id": "y"
|
341
|
+
}
|
342
|
+
EOM
|
343
|
+
file 'environments/_default.json', <<EOM
|
344
|
+
{
|
345
|
+
"name": "_default",
|
346
|
+
"description": "The default Chef environment",
|
347
|
+
"cookbook_versions": {
|
348
|
+
},
|
349
|
+
"json_class": "Chef::Environment",
|
350
|
+
"chef_type": "environment",
|
351
|
+
"default_attributes": {
|
352
|
+
},
|
353
|
+
"override_attributes": {
|
354
|
+
}
|
355
|
+
}
|
356
|
+
EOM
|
357
|
+
file 'environments/x.json', <<EOM
|
358
|
+
{
|
359
|
+
"chef_type": "environment",
|
360
|
+
"cookbook_versions": {
|
361
|
+
},
|
362
|
+
"default_attributes": {
|
363
|
+
},
|
364
|
+
"description": "",
|
365
|
+
"json_class": "Chef::Environment",
|
366
|
+
"name": "x",
|
367
|
+
"override_attributes": {
|
368
|
+
}
|
369
|
+
}
|
370
|
+
EOM
|
371
|
+
file 'nodes/x.json', <<EOM
|
372
|
+
{}
|
373
|
+
EOM
|
374
|
+
file 'roles/x.json', <<EOM
|
375
|
+
{
|
376
|
+
"chef_type": "role",
|
377
|
+
"default_attributes": {
|
378
|
+
},
|
379
|
+
"description": "",
|
380
|
+
"env_run_lists": {
|
381
|
+
},
|
382
|
+
"json_class": "Chef::Role",
|
383
|
+
"name": "x",
|
384
|
+
"override_attributes": {
|
385
|
+
},
|
386
|
+
"run_list": [
|
387
|
+
|
388
|
+
]
|
389
|
+
}
|
390
|
+
EOM
|
391
|
+
file 'users/x.json', <<EOM
|
392
|
+
{}
|
393
|
+
EOM
|
394
|
+
|
395
|
+
it 'knife diff reports no differences' do
|
396
|
+
knife('diff /').should_succeed ''
|
397
|
+
end
|
398
|
+
|
399
|
+
it 'knife diff /environments/nonexistent.json reports an error' do
|
400
|
+
knife('diff /environments/nonexistent.json').should_fail "ERROR: /environments/nonexistent.json: No such file or directory on remote or local\n"
|
401
|
+
end
|
402
|
+
|
403
|
+
it 'knife diff /environments/*.txt reports an error' do
|
404
|
+
knife('diff /environments/*.txt').should_fail "ERROR: /environments/*.txt: No such file or directory on remote or local\n"
|
405
|
+
end
|
406
|
+
|
407
|
+
context 'except the role file' do
|
408
|
+
file 'roles/x.json', <<EOM
|
409
|
+
{
|
410
|
+
"foo": "bar"
|
411
|
+
}
|
412
|
+
EOM
|
413
|
+
it 'knife diff reports the role as different' do
|
414
|
+
knife('diff --name-status /').should_succeed <<EOM
|
415
|
+
M\t/roles/x.json
|
416
|
+
EOM
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
context 'as well as one extra copy of each thing' do
|
421
|
+
file 'clients/y.json', {}
|
422
|
+
file 'cookbooks/x-1.0.0/blah.rb', ''
|
423
|
+
file 'cookbooks/x-2.0.0/metadata.rb', 'version "2.0.0"'
|
424
|
+
file 'cookbooks/y-1.0.0/metadata.rb', 'version "1.0.0"'
|
425
|
+
file 'data_bags/x/z.json', {}
|
426
|
+
file 'data_bags/y/zz.json', {}
|
427
|
+
file 'environments/y.json', {}
|
428
|
+
file 'nodes/y.json', {}
|
429
|
+
file 'roles/y.json', {}
|
430
|
+
file 'users/y.json', {}
|
431
|
+
|
432
|
+
it 'knife diff reports the new files as added' do
|
433
|
+
knife('diff --name-status /').should_succeed <<EOM
|
434
|
+
A\t/cookbooks/x-1.0.0/blah.rb
|
435
|
+
A\t/cookbooks/x-2.0.0
|
436
|
+
A\t/cookbooks/y-1.0.0
|
437
|
+
A\t/data_bags/x/z.json
|
438
|
+
A\t/data_bags/y
|
439
|
+
A\t/environments/y.json
|
440
|
+
A\t/roles/y.json
|
441
|
+
EOM
|
442
|
+
end
|
443
|
+
|
444
|
+
context 'when cwd is the data_bags directory' do
|
445
|
+
cwd 'data_bags'
|
446
|
+
it 'knife diff reports different data bags' do
|
447
|
+
knife('diff --name-status').should_succeed <<EOM
|
448
|
+
A\tx/z.json
|
449
|
+
A\ty
|
450
|
+
EOM
|
451
|
+
end
|
452
|
+
it 'knife diff * reports different data bags' do
|
453
|
+
knife('diff --name-status *').should_succeed <<EOM
|
454
|
+
A\tx/z.json
|
455
|
+
A\ty
|
456
|
+
EOM
|
457
|
+
end
|
458
|
+
end
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|
462
|
+
when_the_repository 'is empty' do
|
463
|
+
it 'knife diff reports everything as deleted' do
|
464
|
+
knife('diff --name-status /').should_succeed <<EOM
|
465
|
+
D\t/cookbooks
|
466
|
+
D\t/data_bags
|
467
|
+
D\t/environments
|
468
|
+
D\t/roles
|
469
|
+
EOM
|
470
|
+
end
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
when_the_repository 'has a cookbook' do
|
475
|
+
file 'cookbooks/x-1.0.0/metadata.rb', 'version "1.0.0"'
|
476
|
+
file 'cookbooks/x-1.0.0/onlyin1.0.0.rb', ''
|
477
|
+
|
478
|
+
when_the_chef_server 'has a later version for the cookbook' do
|
479
|
+
cookbook 'x', '1.0.0', { 'metadata.rb' => 'version "1.0.0"', 'onlyin1.0.0.rb' => ''}
|
480
|
+
cookbook 'x', '1.0.1', { 'metadata.rb' => 'version "1.0.1"', 'onlyin1.0.1.rb' => '' }
|
481
|
+
|
482
|
+
it 'knife diff /cookbooks shows differences' do
|
483
|
+
knife('diff --name-status /cookbooks').should_succeed <<EOM
|
484
|
+
D\t/cookbooks/x-1.0.1
|
485
|
+
EOM
|
486
|
+
end
|
487
|
+
|
488
|
+
it 'knife diff --diff-filter=MAT does not show deleted files' do
|
489
|
+
knife('diff --diff-filter=MAT --name-status /cookbooks').should_succeed ''
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
when_the_chef_server 'has an earlier version for the cookbook' do
|
494
|
+
cookbook 'x', '1.0.0', { 'metadata.rb' => 'version "1.0.0"', 'onlyin1.0.0.rb' => '' }
|
495
|
+
cookbook 'x', '0.9.9', { 'metadata.rb' => 'version "0.9.9"', 'onlyin0.9.9.rb' => '' }
|
496
|
+
it 'knife diff /cookbooks shows the differences' do
|
497
|
+
knife('diff --name-status /cookbooks').should_succeed "D\t/cookbooks/x-0.9.9\n"
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
when_the_chef_server 'has a later version for the cookbook, and no current version' do
|
502
|
+
cookbook 'x', '1.0.1', { 'metadata.rb' => 'version "1.0.1"', 'onlyin1.0.1.rb' => '' }
|
503
|
+
|
504
|
+
it 'knife diff /cookbooks shows the differences' do
|
505
|
+
knife('diff --name-status /cookbooks').should_succeed <<EOM
|
506
|
+
D\t/cookbooks/x-1.0.1
|
507
|
+
A\t/cookbooks/x-1.0.0
|
508
|
+
EOM
|
509
|
+
end
|
510
|
+
end
|
511
|
+
|
512
|
+
when_the_chef_server 'has an earlier version for the cookbook, and no current version' do
|
513
|
+
cookbook 'x', '0.9.9', { 'metadata.rb' => 'version "0.9.9"', 'onlyin0.9.9.rb' => '' }
|
514
|
+
|
515
|
+
it 'knife diff /cookbooks shows the differences' do
|
516
|
+
knife('diff --name-status /cookbooks').should_succeed <<EOM
|
517
|
+
D\t/cookbooks/x-0.9.9
|
518
|
+
A\t/cookbooks/x-1.0.0
|
519
|
+
EOM
|
520
|
+
end
|
521
|
+
end
|
522
|
+
end
|
523
|
+
|
524
|
+
context 'json diff tests' do
|
525
|
+
when_the_repository 'has an empty environment file' do
|
526
|
+
file 'environments/x.json', {}
|
527
|
+
when_the_chef_server 'has an empty environment' do
|
528
|
+
environment 'x', {}
|
529
|
+
it 'knife diff returns no differences' do
|
530
|
+
knife('diff /environments/x.json').should_succeed ''
|
531
|
+
end
|
532
|
+
end
|
533
|
+
when_the_chef_server 'has an environment with a different value' do
|
534
|
+
environment 'x', { 'description' => 'hi' }
|
535
|
+
it 'knife diff reports the difference', :pending => (RUBY_VERSION < "1.9") do
|
536
|
+
knife('diff /environments/x.json').should_succeed(/
|
537
|
+
{
|
538
|
+
- "name": "x",
|
539
|
+
- "description": "hi"
|
540
|
+
\+ "name": "x"
|
541
|
+
}
|
542
|
+
/)
|
543
|
+
end
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
when_the_repository 'has an environment file with a value in it' do
|
548
|
+
file 'environments/x.json', { 'description' => 'hi' }
|
549
|
+
when_the_chef_server 'has an environment with the same value' do
|
550
|
+
environment 'x', { 'description' => 'hi' }
|
551
|
+
it 'knife diff returns no differences' do
|
552
|
+
knife('diff /environments/x.json').should_succeed ''
|
553
|
+
end
|
554
|
+
end
|
555
|
+
when_the_chef_server 'has an environment with no value' do
|
556
|
+
environment 'x', {}
|
557
|
+
it 'knife diff reports the difference', :pending => (RUBY_VERSION < "1.9") do
|
558
|
+
knife('diff /environments/x.json').should_succeed(/
|
268
559
|
{
|
269
560
|
- "name": "x"
|
270
561
|
\+ "name": "x",
|
271
562
|
\+ "description": "hi"
|
272
563
|
}
|
273
564
|
/)
|
565
|
+
end
|
274
566
|
end
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
knife('diff /environments/x.json').should_succeed(/
|
567
|
+
when_the_chef_server 'has an environment with a different value' do
|
568
|
+
environment 'x', { 'description' => 'lo' }
|
569
|
+
it 'knife diff reports the difference', :pending => (RUBY_VERSION < "1.9") do
|
570
|
+
knife('diff /environments/x.json').should_succeed(/
|
280
571
|
{
|
281
572
|
"name": "x",
|
282
573
|
- "description": "lo"
|
283
574
|
\+ "description": "hi"
|
284
575
|
}
|
285
576
|
/)
|
577
|
+
end
|
286
578
|
end
|
287
579
|
end
|
288
580
|
end
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
581
|
+
|
582
|
+
when_the_chef_server 'has an environment' do
|
583
|
+
environment 'x', {}
|
584
|
+
when_the_repository 'has an environment with bad JSON' do
|
585
|
+
file 'environments/x.json', '{'
|
586
|
+
it 'knife diff reports an error and does a textual diff' do
|
587
|
+
knife('diff /environments/x.json').should_succeed(/- "name": "x"/, :stderr => "WARN: Parse error reading #{path_to('environments/x.json')} as JSON: A JSON text must at least contain two octets!\n")
|
588
|
+
end
|
297
589
|
end
|
298
590
|
end
|
299
|
-
end
|
591
|
+
end # without versioned cookbooks
|
300
592
|
end
|