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.
- checksums.yaml +4 -4
- data/lib/chef/provider/chef_acl.rb +434 -0
- data/lib/chef/provider/chef_client.rb +5 -1
- data/lib/chef/provider/chef_container.rb +50 -0
- data/lib/chef/provider/chef_group.rb +78 -0
- data/lib/chef/provider/chef_mirror.rb +138 -0
- data/lib/chef/provider/chef_organization.rb +150 -0
- data/lib/chef/provider/chef_user.rb +6 -1
- data/lib/chef/provider/public_key.rb +0 -1
- data/lib/chef/resource/chef_acl.rb +38 -44
- data/lib/chef/resource/chef_container.rb +18 -0
- data/lib/chef/resource/chef_group.rb +49 -0
- data/lib/chef/resource/chef_mirror.rb +47 -0
- data/lib/chef/resource/chef_organization.rb +64 -0
- data/lib/chef/resource/private_key.rb +6 -1
- data/lib/chef/resource/public_key.rb +5 -0
- data/lib/cheffish/actor_provider_base.rb +14 -9
- data/lib/cheffish/basic_chef_client.rb +18 -2
- data/lib/cheffish/chef_provider_base.rb +7 -0
- data/lib/cheffish/merged_config.rb +10 -2
- data/lib/cheffish/recipe_dsl.rb +34 -8
- data/lib/cheffish/server_api.rb +12 -2
- data/lib/cheffish/version.rb +1 -1
- data/lib/cheffish.rb +2 -2
- data/spec/functional/merged_config_spec.rb +20 -0
- data/spec/integration/chef_acl_spec.rb +914 -0
- data/spec/integration/chef_client_spec.rb +78 -44
- data/spec/integration/chef_container_spec.rb +34 -0
- data/spec/integration/chef_group_spec.rb +324 -0
- data/spec/integration/chef_mirror_spec.rb +244 -0
- data/spec/integration/chef_node_spec.rb +115 -93
- data/spec/integration/chef_organization_spec.rb +244 -0
- data/spec/integration/chef_user_spec.rb +51 -9
- data/spec/support/repository_support.rb +103 -0
- data/spec/support/spec_support.rb +55 -2
- metadata +23 -9
- 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
|
9
|
-
|
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
|
-
|
15
|
-
|
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
|
-
|
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
|
21
|
+
it 'the node gets created' do
|
40
22
|
expect(chef_run).to have_updated 'chef_node[blah]', :create
|
41
|
-
expect
|
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
|
-
|
27
|
+
# TODO why-run mode
|
47
28
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
55
|
-
|
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
|
-
|
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
|
-
|
65
|
-
|
41
|
+
with_converge do
|
42
|
+
with_chef_server 'http://127.0.0.1:8899'
|
43
|
+
chef_node 'blah'
|
44
|
+
end
|
66
45
|
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
72
|
-
|
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
|
-
|
77
|
-
|
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'
|
84
|
-
attributes({})
|
85
|
-
end
|
74
|
+
chef_node 'blah'
|
86
75
|
end
|
87
76
|
|
88
|
-
it '
|
89
|
-
expect(
|
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 '
|
94
|
-
|
95
|
-
|
96
|
-
|
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
|
-
|
101
|
-
|
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
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
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
|
-
|
122
|
-
|
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
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
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
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
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
|