knife-essentials 0.8.3 → 0.8.4

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