clc-cheffish 0.8.clc

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 (63) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/README.md +4 -0
  4. data/Rakefile +23 -0
  5. data/lib/chef/provider/chef_acl.rb +434 -0
  6. data/lib/chef/provider/chef_client.rb +48 -0
  7. data/lib/chef/provider/chef_container.rb +50 -0
  8. data/lib/chef/provider/chef_data_bag.rb +50 -0
  9. data/lib/chef/provider/chef_data_bag_item.rb +273 -0
  10. data/lib/chef/provider/chef_environment.rb +78 -0
  11. data/lib/chef/provider/chef_group.rb +78 -0
  12. data/lib/chef/provider/chef_mirror.rb +138 -0
  13. data/lib/chef/provider/chef_node.rb +82 -0
  14. data/lib/chef/provider/chef_organization.rb +150 -0
  15. data/lib/chef/provider/chef_resolved_cookbooks.rb +41 -0
  16. data/lib/chef/provider/chef_role.rb +79 -0
  17. data/lib/chef/provider/chef_user.rb +53 -0
  18. data/lib/chef/provider/private_key.rb +219 -0
  19. data/lib/chef/provider/public_key.rb +82 -0
  20. data/lib/chef/resource/chef_acl.rb +65 -0
  21. data/lib/chef/resource/chef_client.rb +44 -0
  22. data/lib/chef/resource/chef_container.rb +18 -0
  23. data/lib/chef/resource/chef_data_bag.rb +18 -0
  24. data/lib/chef/resource/chef_data_bag_item.rb +114 -0
  25. data/lib/chef/resource/chef_environment.rb +71 -0
  26. data/lib/chef/resource/chef_group.rb +49 -0
  27. data/lib/chef/resource/chef_mirror.rb +47 -0
  28. data/lib/chef/resource/chef_node.rb +18 -0
  29. data/lib/chef/resource/chef_organization.rb +64 -0
  30. data/lib/chef/resource/chef_resolved_cookbooks.rb +31 -0
  31. data/lib/chef/resource/chef_role.rb +104 -0
  32. data/lib/chef/resource/chef_user.rb +51 -0
  33. data/lib/chef/resource/private_key.rb +44 -0
  34. data/lib/chef/resource/public_key.rb +21 -0
  35. data/lib/cheffish.rb +222 -0
  36. data/lib/cheffish/actor_provider_base.rb +131 -0
  37. data/lib/cheffish/basic_chef_client.rb +115 -0
  38. data/lib/cheffish/chef_provider_base.rb +231 -0
  39. data/lib/cheffish/chef_run_data.rb +19 -0
  40. data/lib/cheffish/chef_run_listener.rb +28 -0
  41. data/lib/cheffish/key_formatter.rb +109 -0
  42. data/lib/cheffish/merged_config.rb +94 -0
  43. data/lib/cheffish/recipe_dsl.rb +147 -0
  44. data/lib/cheffish/server_api.rb +52 -0
  45. data/lib/cheffish/version.rb +3 -0
  46. data/lib/cheffish/with_pattern.rb +21 -0
  47. data/spec/functional/fingerprint_spec.rb +64 -0
  48. data/spec/functional/merged_config_spec.rb +20 -0
  49. data/spec/integration/chef_acl_spec.rb +914 -0
  50. data/spec/integration/chef_client_spec.rb +110 -0
  51. data/spec/integration/chef_container_spec.rb +34 -0
  52. data/spec/integration/chef_group_spec.rb +324 -0
  53. data/spec/integration/chef_mirror_spec.rb +244 -0
  54. data/spec/integration/chef_node_spec.rb +211 -0
  55. data/spec/integration/chef_organization_spec.rb +244 -0
  56. data/spec/integration/chef_user_spec.rb +90 -0
  57. data/spec/integration/private_key_spec.rb +446 -0
  58. data/spec/integration/recipe_dsl_spec.rb +29 -0
  59. data/spec/support/key_support.rb +29 -0
  60. data/spec/support/repository_support.rb +103 -0
  61. data/spec/support/spec_support.rb +176 -0
  62. data/spec/unit/get_private_key_spec.rb +93 -0
  63. metadata +162 -0
@@ -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
@@ -0,0 +1,211 @@
1
+ require 'support/spec_support'
2
+ require 'chef/resource/chef_node'
3
+ require 'chef/provider/chef_node'
4
+
5
+ describe Chef::Resource::ChefNode 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
+ context 'and we run a recipe that creates node "blah"' do
17
+ with_converge do
18
+ chef_node 'blah'
19
+ end
20
+
21
+ it 'the node gets created' do
22
+ expect(chef_run).to have_updated 'chef_node[blah]', :create
23
+ expect(get('nodes/blah')['name']).to eq('blah')
24
+ end
25
+ end
26
+
27
+ # TODO why-run mode
28
+
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
33
+ end
34
+
35
+ after :each do
36
+ @server.stop
37
+ end
38
+
39
+ context 'and a recipe is run that creates node "blah" on the second chef server using with_chef_server' do
40
+
41
+ with_converge do
42
+ with_chef_server 'http://127.0.0.1:8899'
43
+ chef_node 'blah'
44
+ end
45
+
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
54
+
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
68
+ end
69
+
70
+ context 'and has a node named "blah"' do
71
+ node 'blah', {}
72
+
73
+ with_converge do
74
+ chef_node 'blah'
75
+ end
76
+
77
+ it 'chef_node "blah" does not get created or updated' do
78
+ expect(chef_run).not_to have_updated 'chef_node[blah]', :create
79
+ end
80
+ end
81
+
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' ])
96
+ end
97
+ end
98
+
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
109
+ end
110
+ end
111
+
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
130
+ end
131
+
132
+ context 'with chef_node "blah" and an updated normal attribute value' do
133
+ with_converge do
134
+ chef_node 'blah' do
135
+ attributes 'foo' => 'fum'
136
+ end
137
+ end
138
+
139
+ it 'new normal attribute is added' do
140
+ expect(chef_run).to have_updated 'chef_node[blah]', :create
141
+ node = get('nodes/blah')
142
+ expect(node['normal']).to eq({ 'foo' => 'fum', 'tags' => [ 'a', 'b' ] })
143
+ end
144
+ end
145
+
146
+ context 'with chef_node "blah" and a new normal attribute' do
147
+ with_converge do
148
+ chef_node 'blah' do
149
+ attributes 'foe' => 'fum'
150
+ end
151
+ end
152
+
153
+ it 'new normal attribute is added' do
154
+ expect(chef_run).to have_updated 'chef_node[blah]', :create
155
+ node = get('nodes/blah')
156
+ expect(node['normal']).to eq({ 'foe' => 'fum', 'foo' => 'bar', 'tags' => [ 'a', 'b' ] })
157
+ end
158
+ end
159
+
160
+ context 'with chef_node "blah" with complete true' do
161
+ with_converge do
162
+ chef_node 'blah' do
163
+ complete true
164
+ end
165
+ end
166
+
167
+ it 'default, automatic and override attributes are left alone' do
168
+ expect(chef_run).to have_updated 'chef_node[blah]', :create
169
+ node = get('nodes/blah')
170
+ expect(node['chef_environment']).to eq('_default')
171
+ expect(node['run_list']).to eq([])
172
+ expect(node['normal']).to eq({ 'tags' => [ 'a', 'b' ] })
173
+ expect(node['default']).to eq({ 'foo2' => 'bar2' })
174
+ expect(node['automatic']).to eq({ 'foo3' => 'bar3' })
175
+ expect(node['override']).to eq({ 'foo4' => 'bar4' })
176
+ end
177
+ end
178
+
179
+ context 'with chef_node "blah", complete true and a new normal attribute' do
180
+ with_converge do
181
+ chef_node 'blah' do
182
+ attributes 'foe' => 'fum'
183
+ complete true
184
+ end
185
+ end
186
+
187
+ it 'normal foo attribute is replaced with new attribute' do
188
+ expect(chef_run).to have_updated 'chef_node[blah]', :create
189
+ node = get('nodes/blah')
190
+ expect(node['normal']).to eq({ 'foe' => 'fum', 'tags' => [ 'a', 'b' ] })
191
+ end
192
+ end
193
+
194
+ end
195
+ end
196
+
197
+ when_the_chef_server 'is in OSC mode' do
198
+ context 'and is empty' do
199
+ context 'and we run a recipe that creates node "blah"' do
200
+ with_converge do
201
+ chef_node 'blah'
202
+ end
203
+
204
+ it 'the node gets created' do
205
+ expect(chef_run).to have_updated 'chef_node[blah]', :create
206
+ expect(get('nodes/blah')['name']).to eq('blah')
207
+ end
208
+ end
209
+ end
210
+ end
211
+ end