cheffish 0.7.1 → 0.8

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/chef/provider/chef_acl.rb +434 -0
  3. data/lib/chef/provider/chef_client.rb +5 -1
  4. data/lib/chef/provider/chef_container.rb +50 -0
  5. data/lib/chef/provider/chef_group.rb +78 -0
  6. data/lib/chef/provider/chef_mirror.rb +138 -0
  7. data/lib/chef/provider/chef_organization.rb +150 -0
  8. data/lib/chef/provider/chef_user.rb +6 -1
  9. data/lib/chef/provider/public_key.rb +0 -1
  10. data/lib/chef/resource/chef_acl.rb +38 -44
  11. data/lib/chef/resource/chef_container.rb +18 -0
  12. data/lib/chef/resource/chef_group.rb +49 -0
  13. data/lib/chef/resource/chef_mirror.rb +47 -0
  14. data/lib/chef/resource/chef_organization.rb +64 -0
  15. data/lib/chef/resource/private_key.rb +6 -1
  16. data/lib/chef/resource/public_key.rb +5 -0
  17. data/lib/cheffish/actor_provider_base.rb +14 -9
  18. data/lib/cheffish/basic_chef_client.rb +18 -2
  19. data/lib/cheffish/chef_provider_base.rb +7 -0
  20. data/lib/cheffish/merged_config.rb +10 -2
  21. data/lib/cheffish/recipe_dsl.rb +34 -8
  22. data/lib/cheffish/server_api.rb +12 -2
  23. data/lib/cheffish/version.rb +1 -1
  24. data/lib/cheffish.rb +2 -2
  25. data/spec/functional/merged_config_spec.rb +20 -0
  26. data/spec/integration/chef_acl_spec.rb +914 -0
  27. data/spec/integration/chef_client_spec.rb +78 -44
  28. data/spec/integration/chef_container_spec.rb +34 -0
  29. data/spec/integration/chef_group_spec.rb +324 -0
  30. data/spec/integration/chef_mirror_spec.rb +244 -0
  31. data/spec/integration/chef_node_spec.rb +115 -93
  32. data/spec/integration/chef_organization_spec.rb +244 -0
  33. data/spec/integration/chef_user_spec.rb +51 -9
  34. data/spec/support/repository_support.rb +103 -0
  35. data/spec/support/spec_support.rb +55 -2
  36. metadata +23 -9
  37. data/lib/chef/resource/in_parallel.rb +0 -6
@@ -0,0 +1,244 @@
1
+ require 'support/spec_support'
2
+ require 'chef/resource/chef_mirror'
3
+ require 'chef/provider/chef_mirror'
4
+
5
+ describe Chef::Resource::ChefMirror do
6
+ extend SpecSupport
7
+
8
+ when_the_chef_server 'is in multi-org mode', :osc_compat => false, :single_org => false do
9
+ organization 'foo'
10
+
11
+ before :each do
12
+ Chef::Config.chef_server_url = URI.join(Chef::Config.chef_server_url, '/organizations/foo').to_s
13
+ end
14
+
15
+ context 'and is empty' do
16
+ when_the_repository 'is full of stuff' do
17
+ file 'nodes/x.json', {}
18
+ file 'roles/x.json', {}
19
+
20
+ it "Download grabs defaults" do
21
+ run_recipe do
22
+ chef_mirror '' do
23
+ action :download
24
+ end
25
+ end
26
+ expect(chef_run).to have_updated('chef_mirror[]', :download)
27
+ expect(File.exist?(path_to('groups/admins.json'))).to be true
28
+ expect(File.exist?(path_to('environments/_default.json'))).to be true
29
+ end
30
+
31
+ it "Upload uploads everything" do
32
+ run_recipe do
33
+ chef_mirror '' do
34
+ action :upload
35
+ end
36
+ end
37
+ expect(chef_run).to have_updated('chef_mirror[]', :upload)
38
+ expect { get('nodes/x') }.not_to raise_error
39
+ expect { get('roles/x') }.not_to raise_error
40
+ end
41
+
42
+ it 'chef_mirror with concurrency 0 fails with a reasonable message' do
43
+ expect {
44
+ run_recipe do
45
+ chef_mirror '' do
46
+ concurrency 0
47
+ action :download
48
+ end
49
+ end
50
+ }.to raise_error /chef_mirror.concurrency must be above 0/
51
+ end
52
+ end
53
+
54
+ when_the_repository 'has stuff but no chef_repo_path' do
55
+ file 'repo/nodes/x.json', {}
56
+ file 'repo/roles/x.json', {}
57
+ file 'repo2/nodes/y.json', {}
58
+ file 'repo2/roles/y.json', {}
59
+
60
+ before do
61
+ Chef::Config.delete(:chef_repo_path)
62
+ Chef::Config.delete(:node_path)
63
+ Chef::Config.delete(:cookbook_path)
64
+ Chef::Config.delete(:role_path)
65
+ end
66
+
67
+ it "Upload with chef_repo_path('repo') uploads everything" do
68
+ repo_path = path_to('repo')
69
+ run_recipe do
70
+ chef_mirror '' do
71
+ chef_repo_path repo_path
72
+ action :upload
73
+ end
74
+ end
75
+ expect(chef_run).to have_updated('chef_mirror[]', :upload)
76
+ expect { get('nodes/x') }.not_to raise_error
77
+ expect { get('roles/x') }.not_to raise_error
78
+ expect { get('nodes/y') }.to raise_error
79
+ expect { get('roles/y') }.to raise_error
80
+ end
81
+
82
+ it "Upload with chef_repo_path(:chef_repo_path) with multiple paths uploads everything" do
83
+ repo_path = path_to('repo')
84
+ repo2_path = path_to('repo2')
85
+ run_recipe do
86
+ chef_mirror '' do
87
+ chef_repo_path :chef_repo_path => [ repo_path, repo2_path ]
88
+ action :upload
89
+ end
90
+ end
91
+ expect(chef_run).to have_updated('chef_mirror[]', :upload)
92
+ expect { get('nodes/x') }.not_to raise_error
93
+ expect { get('roles/x') }.not_to raise_error
94
+ expect { get('nodes/y') }.not_to raise_error
95
+ expect { get('roles/y') }.not_to raise_error
96
+ end
97
+
98
+ it "Upload with chef_repo_path(:node_path, :role_path) uploads everything" do
99
+ repo_path = path_to('repo')
100
+ repo2_path = path_to('repo2')
101
+
102
+ run_recipe do
103
+ chef_mirror '' do
104
+ chef_repo_path :chef_repo_path => '/blahblah',
105
+ :node_path => "#{repo_path}/nodes",
106
+ :role_path => "#{repo2_path}/roles"
107
+ action :upload
108
+ end
109
+ end
110
+ expect(chef_run).to have_updated('chef_mirror[]', :upload)
111
+ expect { get('nodes/x') }.not_to raise_error
112
+ expect { get('roles/x') }.to raise_error
113
+ expect { get('nodes/y') }.to raise_error
114
+ expect { get('roles/y') }.not_to raise_error
115
+ end
116
+
117
+ it "Upload with chef_repo_path(:chef_repo_path, :role_path) uploads everything" do
118
+ repo_path = path_to('repo')
119
+ repo2_path = path_to('repo2')
120
+
121
+ run_recipe do
122
+ chef_mirror '' do
123
+ chef_repo_path :chef_repo_path => repo_path,
124
+ :role_path => "#{repo2_path}/roles"
125
+ action :upload
126
+ end
127
+ end
128
+ expect(chef_run).to have_updated('chef_mirror[]', :upload)
129
+ expect { get('nodes/x') }.not_to raise_error
130
+ expect { get('roles/x') }.to raise_error
131
+ expect { get('nodes/y') }.to raise_error
132
+ expect { get('roles/y') }.not_to raise_error
133
+ end
134
+
135
+ it "Upload with chef_repo_path(:node_path, :role_path) with multiple paths uploads everything" do
136
+ repo_path = path_to('repo')
137
+ repo2_path = path_to('repo2')
138
+
139
+ run_recipe do
140
+ chef_mirror '' do
141
+ chef_repo_path :chef_repo_path => [ 'foo', 'bar' ],
142
+ :node_path => [ "#{repo_path}/nodes", "#{repo2_path}/nodes" ],
143
+ :role_path => [ "#{repo_path}/roles", "#{repo2_path}/roles" ]
144
+ action :upload
145
+ end
146
+ end
147
+ expect(chef_run).to have_updated('chef_mirror[]', :upload)
148
+ expect { get('nodes/x') }.not_to raise_error
149
+ expect { get('roles/x') }.not_to raise_error
150
+ expect { get('nodes/y') }.not_to raise_error
151
+ expect { get('roles/y') }.not_to raise_error
152
+ end
153
+ end
154
+ end
155
+
156
+ context 'and has stuff' do
157
+ node 'x', {}
158
+ role 'x', {}
159
+
160
+ when_the_repository 'is empty' do
161
+ it "Download grabs stuff" do
162
+ run_recipe do
163
+ chef_mirror '' do
164
+ action :download
165
+ end
166
+ end
167
+ expect(chef_run).to have_updated('chef_mirror[]', :download)
168
+ expect(File.exist?(path_to('nodes/x.json'))).to be true
169
+ expect(File.exist?(path_to('roles/x.json'))).to be true
170
+ end
171
+
172
+ it "Upload uploads nothing" do
173
+ run_recipe do
174
+ chef_mirror '' do
175
+ action :upload
176
+ end
177
+ end
178
+ expect(chef_run).not_to have_updated('chef_mirror[]', :upload)
179
+ end
180
+ end
181
+ end
182
+
183
+ context 'and has nodes and roles named x' do
184
+ node 'x', {}
185
+ role 'x', {}
186
+
187
+ when_the_repository 'has nodes and roles named y' do
188
+ file 'nodes/y.json', {}
189
+ file 'roles/y.json', {}
190
+
191
+ it "Download grabs the x's" do
192
+ run_recipe do
193
+ chef_mirror '' do
194
+ action :download
195
+ end
196
+ end
197
+ expect(chef_run).to have_updated('chef_mirror[]', :download)
198
+ expect(File.exist?(path_to('nodes/x.json'))).to be true
199
+ expect(File.exist?(path_to('roles/x.json'))).to be true
200
+ expect(File.exist?(path_to('nodes/y.json'))).to be true
201
+ expect(File.exist?(path_to('roles/y.json'))).to be true
202
+ end
203
+
204
+ it "Upload uploads the y's" do
205
+ run_recipe do
206
+ chef_mirror '' do
207
+ action :upload
208
+ end
209
+ end
210
+ expect(chef_run).to have_updated('chef_mirror[]', :upload)
211
+ expect { get('nodes/x') }.not_to raise_error
212
+ expect { get('roles/x') }.not_to raise_error
213
+ expect { get('nodes/y') }.not_to raise_error
214
+ expect { get('roles/y') }.not_to raise_error
215
+ end
216
+
217
+ it "Download with purge grabs the x's and deletes the y's" do
218
+ run_recipe do
219
+ chef_mirror '' do
220
+ purge true
221
+ action :download
222
+ end
223
+ end
224
+ expect(chef_run).to have_updated('chef_mirror[]', :download)
225
+ expect(File.exist?(path_to('nodes/x.json'))).to be true
226
+ expect(File.exist?(path_to('roles/x.json'))).to be true
227
+ end
228
+
229
+ it "Upload with :purge uploads the y's and deletes the x's" do
230
+ run_recipe do
231
+ chef_mirror '*/*.json' do
232
+ purge true
233
+ action :upload
234
+ end
235
+ end
236
+ expect(chef_run).to have_updated('chef_mirror[*/*.json]', :upload)
237
+ expect { get('nodes/y') }.not_to raise_error
238
+ expect { get('roles/y') }.not_to raise_error
239
+ end
240
+ end
241
+ end
242
+
243
+ end
244
+ end
@@ -5,140 +5,162 @@ require 'chef/provider/chef_node'
5
5
  describe Chef::Resource::ChefNode do
6
6
  extend SpecSupport
7
7
 
8
- when_the_chef_server 'is empty' do
9
- context 'and we run a recipe that creates node "blah"' do
10
- with_converge do
11
- chef_node 'blah'
12
- end
8
+ when_the_chef_server 'is in multi-org mode', :osc_compat => false, :single_org => false do
9
+ organization 'foo'
13
10
 
14
- it 'the node gets created' do
15
- expect(chef_run).to have_updated 'chef_node[blah]', :create
16
- expect(get('/nodes/blah')['name']).to eq('blah')
17
- end
11
+ before :each do
12
+ Chef::Config.chef_server_url = URI.join(Chef::Config.chef_server_url, '/organizations/foo').to_s
18
13
  end
19
14
 
20
- # TODO why-run mode
21
-
22
- context 'and another chef server is running on port 8899' do
23
- before :each do
24
- @server = ChefZero::Server.new(:port => 8899)
25
- @server.start_background
26
- end
27
-
28
- after :each do
29
- @server.stop
30
- end
31
-
32
- context 'and a recipe is run that creates node "blah" on the second chef server using with_chef_server' do
33
-
15
+ context 'and is empty' do
16
+ context 'and we run a recipe that creates node "blah"' do
34
17
  with_converge do
35
- with_chef_server 'http://127.0.0.1:8899'
36
18
  chef_node 'blah'
37
19
  end
38
20
 
39
- it 'the node is created on the second chef server but not the first' do
21
+ it 'the node gets created' do
40
22
  expect(chef_run).to have_updated 'chef_node[blah]', :create
41
- expect { get('/nodes/blah') }.to raise_error(Net::HTTPServerException)
42
- expect(get('http://127.0.0.1:8899/nodes/blah')['name']).to eq('blah')
23
+ expect(get('nodes/blah')['name']).to eq('blah')
43
24
  end
44
25
  end
45
26
 
46
- context 'and a recipe is run that creates node "blah" on the second chef server using chef_server' do
27
+ # TODO why-run mode
47
28
 
48
- with_converge do
49
- chef_node 'blah' do
50
- chef_server({ :chef_server_url => 'http://127.0.0.1:8899' })
51
- end
29
+ context 'and another chef server is running on port 8899' do
30
+ before :each do
31
+ @server = ChefZero::Server.new(:port => 8899)
32
+ @server.start_background
52
33
  end
53
34
 
54
- it 'the node is created on the second chef server but not the first' do
55
- expect(chef_run).to have_updated 'chef_node[blah]', :create
56
- expect { get('/nodes/blah') }.to raise_error(Net::HTTPServerException)
57
- expect(get('http://127.0.0.1:8899/nodes/blah')['name']).to eq('blah')
35
+ after :each do
36
+ @server.stop
58
37
  end
59
- end
60
38
 
61
- end
62
- end
39
+ context 'and a recipe is run that creates node "blah" on the second chef server using with_chef_server' do
63
40
 
64
- when_the_chef_server 'has a node named "blah"' do
65
- node 'blah', {}
41
+ with_converge do
42
+ with_chef_server 'http://127.0.0.1:8899'
43
+ chef_node 'blah'
44
+ end
66
45
 
67
- with_converge do
68
- chef_node 'blah'
69
- end
46
+ it 'the node is created on the second chef server but not the first' do
47
+ expect(chef_run).to have_updated 'chef_node[blah]', :create
48
+ expect { get('nodes/blah') }.to raise_error(Net::HTTPServerException)
49
+ expect(get('http://127.0.0.1:8899/nodes/blah')['name']).to eq('blah')
50
+ end
51
+ end
52
+
53
+ context 'and a recipe is run that creates node "blah" on the second chef server using chef_server' do
70
54
 
71
- it 'chef_node "blah" does not get created or updated' do
72
- expect(chef_run).not_to have_updated 'chef_node[blah]', :create
55
+ with_converge do
56
+ chef_node 'blah' do
57
+ chef_server({ :chef_server_url => 'http://127.0.0.1:8899' })
58
+ end
59
+ end
60
+
61
+ it 'the node is created on the second chef server but not the first' do
62
+ expect(chef_run).to have_updated 'chef_node[blah]', :create
63
+ expect { get('nodes/blah') }.to raise_error(Net::HTTPServerException)
64
+ expect(get('http://127.0.0.1:8899/nodes/blah')['name']).to eq('blah')
65
+ end
66
+ end
67
+ end
73
68
  end
74
- end
75
69
 
76
- when_the_chef_server 'has a node named "blah" with tags' do
77
- node 'blah', {
78
- 'normal' => { 'tags' => [ 'a', 'b' ] }
79
- }
70
+ context 'and has a node named "blah"' do
71
+ node 'blah', {}
80
72
 
81
- context 'with chef_node "blah" that sets attributes' do
82
73
  with_converge do
83
- chef_node 'blah' do
84
- attributes({})
85
- end
74
+ chef_node 'blah'
86
75
  end
87
76
 
88
- it 'the tags in attributes are used' do
89
- expect(get('/nodes/blah')['normal']['tags']).to eq([ 'a', 'b' ])
77
+ it 'chef_node "blah" does not get created or updated' do
78
+ expect(chef_run).not_to have_updated 'chef_node[blah]', :create
90
79
  end
91
80
  end
92
81
 
93
- context 'with chef_node "blah" that sets attributes with tags in them' do
94
- with_converge do
95
- chef_node 'blah' do
96
- attributes 'tags' => [ 'c', 'd' ]
82
+ context 'and has a node named "blah" with tags' do
83
+ node 'blah', {
84
+ 'normal' => { 'tags' => [ 'a', 'b' ] }
85
+ }
86
+
87
+ context 'with chef_node "blah" that sets attributes' do
88
+ with_converge do
89
+ chef_node 'blah' do
90
+ attributes({})
91
+ end
92
+ end
93
+
94
+ it 'the tags in attributes are used' do
95
+ expect(get('nodes/blah')['normal']['tags']).to eq([ 'a', 'b' ])
97
96
  end
98
97
  end
99
98
 
100
- it 'the tags in attributes are used' do
101
- expect(get('/nodes/blah')['normal']['tags']).to eq([ 'c', 'd' ])
99
+ context 'with chef_node "blah" that sets attributes with tags in them' do
100
+ with_converge do
101
+ chef_node 'blah' do
102
+ attributes 'tags' => [ 'c', 'd' ]
103
+ end
104
+ end
105
+
106
+ it 'the tags in attributes are used' do
107
+ expect(get('nodes/blah')['normal']['tags']).to eq([ 'c', 'd' ])
108
+ end
102
109
  end
103
110
  end
104
- end
105
111
 
106
- when_the_chef_server 'has a node named "blah" with everything in it' do
107
- node 'blah', {
108
- 'chef_environment' => 'blah',
109
- 'run_list' => [ 'recipe[bjork]' ],
110
- 'normal' => { 'foo' => 'bar', 'tags' => [ 'a', 'b' ] },
111
- 'default' => { 'foo2' => 'bar2' },
112
- 'automatic' => { 'foo3' => 'bar3' },
113
- 'override' => { 'foo4' => 'bar4' }
114
- }
115
-
116
- context 'with chef_node "blah"' do
117
- with_converge do
118
- chef_node 'blah'
112
+ context 'has a node named "blah" with everything in it' do
113
+ node 'blah', {
114
+ 'chef_environment' => 'blah',
115
+ 'run_list' => [ 'recipe[bjork]' ],
116
+ 'normal' => { 'foo' => 'bar', 'tags' => [ 'a', 'b' ] },
117
+ 'default' => { 'foo2' => 'bar2' },
118
+ 'automatic' => { 'foo3' => 'bar3' },
119
+ 'override' => { 'foo4' => 'bar4' }
120
+ }
121
+
122
+ context 'with chef_node "blah"' do
123
+ with_converge do
124
+ chef_node 'blah'
125
+ end
126
+
127
+ it 'nothing gets updated' do
128
+ expect(chef_run).not_to have_updated 'chef_node[blah]', :create
129
+ end
119
130
  end
120
131
 
121
- it 'nothing gets updated' do
122
- expect(chef_run).not_to have_updated 'chef_node[blah]', :create
132
+ context 'with chef_node "blah" with complete true' do
133
+ with_converge do
134
+ chef_node 'blah' do
135
+ complete true
136
+ end
137
+ end
138
+
139
+ it 'default, automatic and override attributes are left alone' do
140
+ expect(chef_run).to have_updated 'chef_node[blah]', :create
141
+ node = get('nodes/blah')
142
+ expect(node['chef_environment']).to eq('_default')
143
+ expect(node['run_list']).to eq([])
144
+ expect(node['normal']).to eq({ 'tags' => [ 'a', 'b' ] })
145
+ expect(node['default']).to eq({ 'foo2' => 'bar2' })
146
+ expect(node['automatic']).to eq({ 'foo3' => 'bar3' })
147
+ expect(node['override']).to eq({ 'foo4' => 'bar4' })
148
+ end
123
149
  end
124
150
  end
151
+ end
125
152
 
126
- context 'with chef_node "blah" with complete true' do
127
- with_converge do
128
- chef_node 'blah' do
129
- complete true
153
+ when_the_chef_server 'is in OSC mode' do
154
+ context 'and is empty' do
155
+ context 'and we run a recipe that creates node "blah"' do
156
+ with_converge do
157
+ chef_node 'blah'
130
158
  end
131
- end
132
159
 
133
- it 'default, automatic and override attributes are left alone' do
134
- expect(chef_run).to have_updated 'chef_node[blah]', :create
135
- node = get('/nodes/blah')
136
- expect(node['chef_environment']).to eq('_default')
137
- expect(node['run_list']).to eq([])
138
- expect(node['normal']).to eq({ 'tags' => [ 'a', 'b' ] })
139
- expect(node['default']).to eq({ 'foo2' => 'bar2' })
140
- expect(node['automatic']).to eq({ 'foo3' => 'bar3' })
141
- expect(node['override']).to eq({ 'foo4' => 'bar4' })
160
+ it 'the node gets created' do
161
+ expect(chef_run).to have_updated 'chef_node[blah]', :create
162
+ expect(get('nodes/blah')['name']).to eq('blah')
163
+ end
142
164
  end
143
165
  end
144
166
  end