knife-essentials 0.8.3 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. data/lib/chef/knife/diff_essentials.rb +2 -2
  2. data/lib/chef/knife/download_essentials.rb +5 -1
  3. data/lib/chef/knife/list_essentials.rb +2 -1
  4. data/lib/chef/knife/upload_essentials.rb +5 -1
  5. data/lib/chef_fs/command_line.rb +94 -63
  6. data/lib/chef_fs/file_system.rb +113 -93
  7. data/lib/chef_fs/file_system/base_fs_object.rb +91 -37
  8. data/lib/chef_fs/file_system/chef_repository_file_system_cookbooks_dir.rb +14 -1
  9. data/lib/chef_fs/file_system/chef_server_root_dir.rb +2 -1
  10. data/lib/chef_fs/file_system/cookbook_file.rb +7 -1
  11. data/lib/chef_fs/file_system/cookbooks_dir.rb +13 -6
  12. data/lib/chef_fs/file_system/environments_dir.rb +59 -0
  13. data/lib/chef_fs/file_system/multiplexed_dir.rb +1 -1
  14. data/lib/chef_fs/file_system/nodes_dir.rb +1 -0
  15. data/lib/chef_fs/file_system/operation_not_allowed_error.rb +29 -0
  16. data/lib/chef_fs/file_system/operation_skipped_error.rb +29 -0
  17. data/lib/chef_fs/knife.rb +29 -21
  18. data/lib/chef_fs/version.rb +1 -1
  19. data/spec/chef_fs/diff_spec.rb +30 -30
  20. data/spec/chef_fs/file_system/cookbooks_dir_spec.rb +5 -1
  21. data/spec/integration/chef_repo_path_spec.rb +705 -0
  22. data/spec/integration/chef_repository_file_system_spec.rb +82 -713
  23. data/spec/integration/chefignore_spec.rb +258 -0
  24. data/spec/integration/diff_spec.rb +151 -0
  25. data/spec/integration/download_spec.rb +403 -0
  26. data/spec/integration/list_spec.rb +21 -21
  27. data/spec/integration/upload_spec.rb +407 -0
  28. data/spec/support/integration_helper.rb +9 -4
  29. data/spec/support/knife_support.rb +14 -2
  30. metadata +12 -3
@@ -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