knife-stackbuilder 0.5.2
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 +7 -0
- data/README.md +115 -0
- data/Rakefile +42 -0
- data/bin/stackbuilder_debug +0 -0
- data/lib/chef/knife/stack_build.rb +114 -0
- data/lib/chef/knife/stack_delete.rb +50 -0
- data/lib/chef/knife/stack_initialize_repo.rb +62 -0
- data/lib/chef/knife/stack_upload_certificates.rb +38 -0
- data/lib/chef/knife/stack_upload_cookbooks.rb +49 -0
- data/lib/chef/knife/stack_upload_data_bags.rb +36 -0
- data/lib/chef/knife/stack_upload_environments.rb +31 -0
- data/lib/chef/knife/stack_upload_repo.rb +39 -0
- data/lib/chef/knife/stack_upload_roles.rb +33 -0
- data/lib/chef/knife/stackbuilder_base.rb +32 -0
- data/lib/stackbuilder/chef/repo.rb +442 -0
- data/lib/stackbuilder/chef/stack_generic_node.rb +67 -0
- data/lib/stackbuilder/chef/stack_node_manager.rb +251 -0
- data/lib/stackbuilder/chef/stack_provider.rb +77 -0
- data/lib/stackbuilder/chef/stack_vagrant_node.rb +72 -0
- data/lib/stackbuilder/common/config.rb +44 -0
- data/lib/stackbuilder/common/errors.rb +18 -0
- data/lib/stackbuilder/common/helpers.rb +379 -0
- data/lib/stackbuilder/common/semaphore.rb +54 -0
- data/lib/stackbuilder/common/teeio.rb +29 -0
- data/lib/stackbuilder/stack/node_manager.rb +38 -0
- data/lib/stackbuilder/stack/node_provider.rb +21 -0
- data/lib/stackbuilder/stack/node_task.rb +424 -0
- data/lib/stackbuilder/stack/stack.rb +224 -0
- data/lib/stackbuilder/version.rb +8 -0
- data/lib/stackbuilder.rb +53 -0
- metadata +100 -0
@@ -0,0 +1,442 @@
|
|
1
|
+
# Copyright (c) 2014 Mevan Samaratunga
|
2
|
+
|
3
|
+
include StackBuilder::Common::Helpers
|
4
|
+
|
5
|
+
module StackBuilder::Chef
|
6
|
+
|
7
|
+
class RepoNotFoundError < StackBuilder::Common::StackBuilderError; end
|
8
|
+
class InvalidRepoError < StackBuilder::Common::StackBuilderError; end
|
9
|
+
|
10
|
+
class Repo
|
11
|
+
|
12
|
+
include ERB::Util
|
13
|
+
|
14
|
+
attr_reader :environments
|
15
|
+
|
16
|
+
REPO_DIRS = [
|
17
|
+
'etc',
|
18
|
+
'cookbooks',
|
19
|
+
'environments',
|
20
|
+
'secrets',
|
21
|
+
'data_bags',
|
22
|
+
'roles'
|
23
|
+
]
|
24
|
+
|
25
|
+
def initialize(path, certificates = nil, environments = nil, cookbooks = nil)
|
26
|
+
|
27
|
+
raise StackBuilder::Common::StackBuilderError, "Repo path cannot be nil." if path.nil?
|
28
|
+
|
29
|
+
@logger = StackBuilder::Common::Config.logger
|
30
|
+
@repo_path = File.expand_path(path)
|
31
|
+
|
32
|
+
if Dir.exist?(@repo_path)
|
33
|
+
|
34
|
+
REPO_DIRS.each do |folder|
|
35
|
+
|
36
|
+
next if [ 'cookbooks' ].include?(folder)
|
37
|
+
|
38
|
+
repo_folder = "#{@repo_path}/#{folder}"
|
39
|
+
raise InvalidRepoError,
|
40
|
+
"Repo folder #{repo_folder} is missing" unless Dir.exist?(repo_folder)
|
41
|
+
end
|
42
|
+
|
43
|
+
@environments = [ ]
|
44
|
+
Dir["#{@repo_path}/environments/**/*.rb"].each do |envfile|
|
45
|
+
@environments << envfile[/\/(\w+).rb$/, 1]
|
46
|
+
end
|
47
|
+
|
48
|
+
@logger.debug("Found stack environments #{@environments}")
|
49
|
+
else
|
50
|
+
raise RepoNotFoundError,
|
51
|
+
"Unable to load repo @ #{@repo_path}. If you need to create a repo please " +
|
52
|
+
"provide the list of environments at a minimum" if environments.nil?
|
53
|
+
|
54
|
+
REPO_DIRS.each do |folder|
|
55
|
+
system("mkdir -p #{@repo_path}/#{folder}")
|
56
|
+
end
|
57
|
+
|
58
|
+
# Create Berksfile
|
59
|
+
@berks_cookbooks = cookbooks.nil? ? [] : cookbooks.split(',').map { |s| s.strip.split(':') }
|
60
|
+
berksfile_template = IO.read(File.expand_path('../../resources/Berksfile.erb', __FILE__))
|
61
|
+
|
62
|
+
berksfile = ERB.new(berksfile_template, nil, '-<>').result(binding)
|
63
|
+
File.open("#{@repo_path}/Berksfile", 'w+') { |f| f.write(berksfile) }
|
64
|
+
|
65
|
+
# Create Environments and Stacks
|
66
|
+
@environments = environments.split(',').map { |s| s.strip }
|
67
|
+
configfile_template = IO.read(File.expand_path('../../resources/Config.yml.erb', __FILE__))
|
68
|
+
envfile_template = IO.read(File.expand_path('../../resources/Environment.rb.erb', __FILE__))
|
69
|
+
stackfile_template = IO.read(File.expand_path('../../resources/Stack.yml.erb', __FILE__))
|
70
|
+
|
71
|
+
i = 1
|
72
|
+
@environments.each do |env_name|
|
73
|
+
|
74
|
+
@environment = env_name
|
75
|
+
|
76
|
+
configfile = ERB.new(configfile_template, nil, '-<>').result(binding)
|
77
|
+
File.open("#{@repo_path}/etc/#{env_name}.yml", 'w+') { |f| f.write(configfile) }
|
78
|
+
|
79
|
+
envfile = ERB.new(envfile_template, nil, '-<>').result(binding)
|
80
|
+
File.open("#{@repo_path}/environments/#{env_name}.rb", 'w+') { |f| f.write(envfile) }
|
81
|
+
|
82
|
+
stackfile = ERB.new(stackfile_template, nil, '-<>').result(binding)
|
83
|
+
File.open("#{@repo_path}/stack#{i}.yml", 'w+') { |f| f.write(stackfile) }
|
84
|
+
i += 1
|
85
|
+
end
|
86
|
+
@environment = nil
|
87
|
+
|
88
|
+
# Create or copy certs
|
89
|
+
create_certs(certificates) unless certificates.nil?
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def upload_environments(environment = nil)
|
94
|
+
|
95
|
+
environments = (environment.nil? ? @environments : [ environment ])
|
96
|
+
knife_cmd = Chef::Knife::EnvironmentFromFile.new
|
97
|
+
|
98
|
+
environments.each do |env_name|
|
99
|
+
|
100
|
+
# TODO: Handle JSON environment files. JSON files should be processed similar to roles.
|
101
|
+
|
102
|
+
knife_cmd.name_args = [ "#{@repo_path}/environments/#{env_name}.rb" ]
|
103
|
+
run_knife(knife_cmd)
|
104
|
+
puts "Uploaded environment '#{env_name}' to '#{Chef::Config.chef_server_url}'."
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def upload_certificates(environment = nil, server = nil)
|
109
|
+
|
110
|
+
create_certs(server) unless server.nil?
|
111
|
+
|
112
|
+
knife_cmd = Chef::Knife::DataBagList.new
|
113
|
+
data_bag_list = run_knife(knife_cmd).split
|
114
|
+
|
115
|
+
# Create environment specific data bags to hold certificates
|
116
|
+
@environments.each do |env_name|
|
117
|
+
|
118
|
+
data_bag_env = 'certificates-' + env_name
|
119
|
+
unless data_bag_list.include?(data_bag_env)
|
120
|
+
knife_cmd = Chef::Knife::DataBagCreate.new
|
121
|
+
knife_cmd.name_args = data_bag_env
|
122
|
+
run_knife(knife_cmd)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
Dir["#{@repo_path}/.certs/*"].each do |server_cert_dir|
|
127
|
+
|
128
|
+
if File.directory?(server_cert_dir)
|
129
|
+
|
130
|
+
s = server_cert_dir.split('/').last
|
131
|
+
|
132
|
+
server_env_name = s[/.*_(\w+)$/, 1]
|
133
|
+
server_name = server_env_name.nil? ? s : s[/(.*)_\w+$/, 1]
|
134
|
+
|
135
|
+
if server.nil? || server==server_name
|
136
|
+
|
137
|
+
if server_env_name.nil?
|
138
|
+
|
139
|
+
environments = (environment.nil? ? @environments : [ environment ])
|
140
|
+
environments.each do |env_name|
|
141
|
+
upload_certificate(server_cert_dir, server_name, env_name)
|
142
|
+
end
|
143
|
+
|
144
|
+
elsif environment.nil? || environment==server_env_name
|
145
|
+
upload_certificate(server_cert_dir, server_name, server_env_name)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def upload_data_bags(environment = nil, data_bag = nil)
|
153
|
+
|
154
|
+
environments = (environment.nil? ? @environments : [ environment ])
|
155
|
+
|
156
|
+
knife_cmd = Chef::Knife::DataBagList.new
|
157
|
+
data_bag_list = run_knife(knife_cmd).split
|
158
|
+
|
159
|
+
Dir["#{@repo_path}/data_bags/*"].each do |data_bag_dir|
|
160
|
+
|
161
|
+
data_bag_name = data_bag_dir[/\/(\w+)$/, 1]
|
162
|
+
if data_bag.nil? || data_bag==data_bag_name
|
163
|
+
|
164
|
+
environments.each do |env_name|
|
165
|
+
|
166
|
+
data_bag_env = data_bag_name + '-' + env_name
|
167
|
+
unless data_bag_list.include?(data_bag_env)
|
168
|
+
knife_cmd = Chef::Knife::DataBagCreate.new
|
169
|
+
knife_cmd.name_args = data_bag_env
|
170
|
+
run_knife(knife_cmd)
|
171
|
+
end
|
172
|
+
|
173
|
+
env_file = "#{@repo_path}/etc/#{env_name}.yml"
|
174
|
+
env_vars = File.exist?(env_file) ?
|
175
|
+
StackBuilder::Common.load_yaml("#{@repo_path}/etc/#{env_name}.yml", ENV) : { }
|
176
|
+
|
177
|
+
secret = get_secret(env_name)
|
178
|
+
|
179
|
+
upload_data_bag_items(secret, data_bag_dir, data_bag_env, env_vars)
|
180
|
+
|
181
|
+
env_item_dir = data_bag_dir + '/' + env_name
|
182
|
+
upload_data_bag_items(secret, env_item_dir, data_bag_env, env_vars) if Dir.exist?(env_item_dir)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def upload_cookbooks(cookbook = nil, upload_options = '--no-freeze')
|
189
|
+
|
190
|
+
berksfile_path = "#{@repo_path}/Berksfile"
|
191
|
+
debug_flag = (@logger.debug? ? ' --debug' : '')
|
192
|
+
|
193
|
+
# Need to invoke Berkshelf from the shell as directly invoking it causes
|
194
|
+
# cookbook validation to throw an exception when 'Berksfile.upload' is
|
195
|
+
# called.
|
196
|
+
#
|
197
|
+
# TBD: More research needs to be done as direct invocation is preferable
|
198
|
+
|
199
|
+
cmd = ""
|
200
|
+
|
201
|
+
cmd += "export BERKSHELF_CHEF_CONFIG=#{ENV['BERKSHELF_CHEF_CONFIG']}; " \
|
202
|
+
if ENV.has_key?('BERKSHELF_CHEF_CONFIG')
|
203
|
+
|
204
|
+
if cookbook.nil?
|
205
|
+
cmd += "berks install#{debug_flag} --berksfile=#{berksfile_path}; "
|
206
|
+
cmd += "berks upload#{debug_flag} --berksfile=#{berksfile_path} #{upload_options}; "
|
207
|
+
else
|
208
|
+
cmd += "berks upload#{debug_flag} --berksfile=#{berksfile_path} #{upload_options} #{cookbook}; "
|
209
|
+
end
|
210
|
+
|
211
|
+
system(cmd)
|
212
|
+
end
|
213
|
+
|
214
|
+
def upload_roles(role = nil)
|
215
|
+
|
216
|
+
if role.nil?
|
217
|
+
Dir["#{@repo_path}/roles/*.json"].each do |role_file|
|
218
|
+
upload_role(role_file)
|
219
|
+
end
|
220
|
+
else
|
221
|
+
role_file = "#{@repo_path}/roles/#{role}.json"
|
222
|
+
upload_role(role_file) if File.exist?(role_file)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def get_secret(env_name)
|
227
|
+
|
228
|
+
secretfile = "#{@repo_path}/secrets/#{env_name}"
|
229
|
+
if File.exists?(secretfile)
|
230
|
+
key = IO.read(secretfile)
|
231
|
+
else
|
232
|
+
key = SecureRandom.uuid()
|
233
|
+
File.open("#{@repo_path}/secrets/#{env_name}", 'w+') { |f| f.write(key) }
|
234
|
+
end
|
235
|
+
|
236
|
+
key
|
237
|
+
end
|
238
|
+
|
239
|
+
private
|
240
|
+
|
241
|
+
def create_certs(certificates)
|
242
|
+
|
243
|
+
repo_cert_dir = @repo_path + '/.certs'
|
244
|
+
FileUtils.mkdir_p(repo_cert_dir)
|
245
|
+
|
246
|
+
if Dir.exist?(certificates)
|
247
|
+
|
248
|
+
raise CertificateError, "Unable to locate public CA certificate for server " +
|
249
|
+
"@#{certificates}/cacert.pem" unless File.exist?("#{certificates}/cacert.pem")
|
250
|
+
|
251
|
+
system("rsync -ru #{certificates}/* #{repo_cert_dir}")
|
252
|
+
else
|
253
|
+
|
254
|
+
cacert_file = "#{repo_cert_dir}/cacert.pem"
|
255
|
+
cakey_file = "#{repo_cert_dir}/cakey.pem"
|
256
|
+
|
257
|
+
if File.exist?(cacert_file) && File.exist?(cakey_file)
|
258
|
+
|
259
|
+
ca_cert = OpenSSL::X509::Certificate.new(IO.read(cacert_file))
|
260
|
+
ca_key = OpenSSL::PKey::RSA.new(IO.read(cakey_file))
|
261
|
+
else
|
262
|
+
ca_key = OpenSSL::PKey::RSA.new(2048)
|
263
|
+
File.open(cakey_file, 'w+') { |f| f.write(ca_key.to_pem) }
|
264
|
+
|
265
|
+
ca_subject = "/CN=ca/DC=stackbuilder.org"
|
266
|
+
ca_cert = create_ca_cert(ca_key, ca_subject)
|
267
|
+
File.open(cacert_file, 'w+') { |f| f.write(ca_cert.to_pem) }
|
268
|
+
end
|
269
|
+
|
270
|
+
servers = certificates.split(',')
|
271
|
+
servers.each do |server|
|
272
|
+
|
273
|
+
server_dir = "#{repo_cert_dir}/#{server}"
|
274
|
+
server_cert_file = "#{server_dir}/cert.pem"
|
275
|
+
server_key_file = "#{server_dir}/key.pem"
|
276
|
+
|
277
|
+
unless File.exist?(server_cert_file) && File.exist?(server_key_file)
|
278
|
+
|
279
|
+
server_key = OpenSSL::PKey::RSA.new(2048)
|
280
|
+
server_subject = "/C=US/O=#{server}/OU=Chef Community/CN=#{server}"
|
281
|
+
server_cert = create_server_cert(create_csr(server_key, server_subject), ca_key, ca_cert)
|
282
|
+
|
283
|
+
FileUtils.mkdir_p(server_dir)
|
284
|
+
|
285
|
+
File.open(server_cert_file, 'w+') { |f| f.write(server_cert.to_pem) }
|
286
|
+
File.open(server_key_file, 'w+') { |f| f.write(server_key.to_pem) }
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
def create_ca_cert(ca_key, ca_subject)
|
293
|
+
|
294
|
+
ca_cert = create_cert(ca_key, ca_subject)
|
295
|
+
|
296
|
+
extension_factory = OpenSSL::X509::ExtensionFactory.new
|
297
|
+
extension_factory.subject_certificate = ca_cert
|
298
|
+
extension_factory.issuer_certificate = ca_cert
|
299
|
+
|
300
|
+
ca_cert.add_extension extension_factory
|
301
|
+
.create_extension('subjectKeyIdentifier', 'hash')
|
302
|
+
ca_cert.add_extension extension_factory
|
303
|
+
.create_extension('basicConstraints', 'CA:TRUE', true)
|
304
|
+
ca_cert.add_extension extension_factory
|
305
|
+
.create_extension('keyUsage', 'cRLSign,keyCertSign', true)
|
306
|
+
|
307
|
+
ca_cert.sign ca_key, OpenSSL::Digest::SHA256.new
|
308
|
+
|
309
|
+
ca_cert
|
310
|
+
end
|
311
|
+
|
312
|
+
def create_csr(key, subject)
|
313
|
+
|
314
|
+
csr = OpenSSL::X509::Request.new
|
315
|
+
csr.version = 0
|
316
|
+
csr.subject = OpenSSL::X509::Name.parse(subject)
|
317
|
+
csr.public_key = key.public_key
|
318
|
+
csr.sign key, OpenSSL::Digest::SHA256.new
|
319
|
+
|
320
|
+
csr
|
321
|
+
end
|
322
|
+
|
323
|
+
def create_server_cert(csr, ca_key, ca_cert)
|
324
|
+
|
325
|
+
csr_cert = create_cert(csr.public_key, csr.subject, ca_cert.subject)
|
326
|
+
|
327
|
+
extension_factory = OpenSSL::X509::ExtensionFactory.new
|
328
|
+
extension_factory.subject_certificate = csr_cert
|
329
|
+
extension_factory.issuer_certificate = ca_cert
|
330
|
+
|
331
|
+
csr_cert.add_extension extension_factory
|
332
|
+
.create_extension('basicConstraints', 'CA:FALSE')
|
333
|
+
csr_cert.add_extension extension_factory
|
334
|
+
.create_extension('keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature')
|
335
|
+
csr_cert.add_extension extension_factory
|
336
|
+
.create_extension('subjectKeyIdentifier', 'hash')
|
337
|
+
|
338
|
+
csr_cert.sign ca_key, OpenSSL::Digest::SHA256.new
|
339
|
+
|
340
|
+
csr_cert
|
341
|
+
end
|
342
|
+
|
343
|
+
def create_cert(key, subject, issuer = nil)
|
344
|
+
|
345
|
+
cert = OpenSSL::X509::Certificate.new
|
346
|
+
cert.serial = 0x0
|
347
|
+
cert.version = 2
|
348
|
+
cert.not_before = Time.now
|
349
|
+
cert.not_after = Time.now + (10 * 365 * 24 * 60 * 60) # 10 years
|
350
|
+
|
351
|
+
cert.public_key = key.public_key
|
352
|
+
|
353
|
+
cert.subject = subject.is_a?(OpenSSL::X509::Name) ?
|
354
|
+
subject : OpenSSL::X509::Name.parse(subject)
|
355
|
+
|
356
|
+
cert.issuer = issuer.is_a?(OpenSSL::X509::Name) ?
|
357
|
+
issuer : OpenSSL::X509::Name.parse(issuer.nil? ? subject : issuer)
|
358
|
+
|
359
|
+
cert
|
360
|
+
end
|
361
|
+
|
362
|
+
def upload_certificate(server_cert_dir, server_name, server_env_name)
|
363
|
+
|
364
|
+
data_bag_name = 'certificates-' + server_env_name
|
365
|
+
|
366
|
+
data_bag_item = {
|
367
|
+
'id' => server_name,
|
368
|
+
'cacert' => IO.read(server_cert_dir + "/../cacert.pem"),
|
369
|
+
'cert' => IO.read(server_cert_dir + "/cert.pem"),
|
370
|
+
'key' => IO.read(server_cert_dir + "/key.pem") }
|
371
|
+
|
372
|
+
tmpfile = "#{Dir.tmpdir}/#{server_name}.json"
|
373
|
+
File.open("#{tmpfile}", 'w+') { |f| f.write(data_bag_item.to_json) }
|
374
|
+
|
375
|
+
knife_cmd = Chef::Knife::DataBagFromFile.new
|
376
|
+
knife_cmd.name_args = [ data_bag_name, tmpfile ]
|
377
|
+
knife_cmd.config[:secret] = get_secret(server_env_name)
|
378
|
+
run_knife(knife_cmd)
|
379
|
+
|
380
|
+
puts "Uploaded '#{server_env_name}' certificate for server '#{server_name}' " +
|
381
|
+
"to data bag '#{data_bag_name}' at '#{Chef::Config.chef_server_url}'."
|
382
|
+
|
383
|
+
rescue Exception => msg
|
384
|
+
@logger.error(msg)
|
385
|
+
ensure
|
386
|
+
File.delete(tmpfile) unless tmpfile.nil? || !File.exist?(tmpfile)
|
387
|
+
end
|
388
|
+
|
389
|
+
def upload_data_bag_items(secret, path, data_bag_name, env_vars)
|
390
|
+
|
391
|
+
tmpfile = nil
|
392
|
+
|
393
|
+
Dir["#{path}/*.json"].each do |data_bag_file|
|
394
|
+
|
395
|
+
data_bag_item = eval_map_values(JSON.load(File.new(data_bag_file, 'r')), env_vars, data_bag_file)
|
396
|
+
|
397
|
+
data_bag_item_name = data_bag_item['id']
|
398
|
+
@logger.debug("Uploading data bag '#{data_bag_item_name}' with contents:\n#{data_bag_item.to_yaml}")
|
399
|
+
|
400
|
+
tmpfile = "#{Dir.tmpdir}/#{data_bag_item_name}.json"
|
401
|
+
File.open("#{tmpfile}", 'w+') { |f| f.write(data_bag_item.to_json) }
|
402
|
+
|
403
|
+
knife_cmd = Chef::Knife::DataBagFromFile.new
|
404
|
+
knife_cmd.name_args = [ data_bag_name, tmpfile ]
|
405
|
+
knife_cmd.config[:secret] = secret
|
406
|
+
run_knife(knife_cmd)
|
407
|
+
|
408
|
+
File.delete(tmpfile)
|
409
|
+
|
410
|
+
puts "Uploaded item '#{data_bag_item_name}' of data bag " +
|
411
|
+
"'#{data_bag_name}' to '#{Chef::Config.chef_server_url}'."
|
412
|
+
end
|
413
|
+
|
414
|
+
rescue Exception => msg
|
415
|
+
@logger.error(msg)
|
416
|
+
ensure
|
417
|
+
File.delete(tmpfile) unless tmpfile.nil? || !File.exist?(tmpfile)
|
418
|
+
end
|
419
|
+
|
420
|
+
def upload_role(role_file)
|
421
|
+
|
422
|
+
role_content = eval_map_values(JSON.load(File.new(role_file, 'r')), ENV)
|
423
|
+
|
424
|
+
role_name = role_content.is_a?(Chef::Role) ? role_content.name : role_content['name']
|
425
|
+
@logger.debug("Uploading role '#{role_name}' with contents:\n#{role_content.to_yaml}")
|
426
|
+
|
427
|
+
tmpfile = "#{Dir.tmpdir}/#{role_name}.json"
|
428
|
+
File.open("#{tmpfile}", 'w+') { |f| f.write(role_content.to_json) }
|
429
|
+
|
430
|
+
knife_cmd = Chef::Knife::RoleFromFile.new
|
431
|
+
knife_cmd.name_args = [ tmpfile ]
|
432
|
+
run_knife(knife_cmd)
|
433
|
+
|
434
|
+
puts "Uploaded role '#{role_name}' to '#{Chef::Config.chef_server_url}'."
|
435
|
+
|
436
|
+
rescue Exception => msg
|
437
|
+
@logger.error(msg)
|
438
|
+
ensure
|
439
|
+
File.delete(tmpfile) unless tmpfile.nil? || !File.exist?(tmpfile)
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# Copyright (c) 2014 Mevan Samaratunga
|
2
|
+
|
3
|
+
include StackBuilder::Common::Helpers
|
4
|
+
|
5
|
+
module StackBuilder::Chef
|
6
|
+
|
7
|
+
class GenericNodeManager < StackBuilder::Chef::NodeManager
|
8
|
+
|
9
|
+
def create_vm(name, knife_config)
|
10
|
+
|
11
|
+
create_class_name = knife_config['create']['class']
|
12
|
+
raise ArgumentError, "Knife plugin's server 'create' class name not provided." \
|
13
|
+
if create_class_name.nil?
|
14
|
+
|
15
|
+
knife_cmd = eval(create_class_name + '.new')
|
16
|
+
|
17
|
+
if knife_config['create'].has_key?('name_key')
|
18
|
+
name_key = knife_config['create']['name_key']
|
19
|
+
knife_cmd.config[name_key.to_sym] = name
|
20
|
+
else
|
21
|
+
knife_cmd.name_args = [ name ]
|
22
|
+
end
|
23
|
+
|
24
|
+
config_knife(knife_cmd, knife_config['create']['options'] || { })
|
25
|
+
config_knife(knife_cmd, knife_config['options'] || { })
|
26
|
+
|
27
|
+
if knife_config['create']['synchronized']
|
28
|
+
@@sync ||= Mutex.new
|
29
|
+
@@sync.synchronize {
|
30
|
+
run_knife(knife_cmd, knife_config['create']['retries'] || 0)
|
31
|
+
}
|
32
|
+
else
|
33
|
+
run_knife(knife_cmd, knife_config['create']['retries'] || 0)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete_vm(name, knife_config)
|
38
|
+
|
39
|
+
return unless knife_config.has_key?('delete')
|
40
|
+
|
41
|
+
delete_class_name = knife_config['delete']['class']
|
42
|
+
raise ArgumentError, "Knife plugin's server 'delete' class name not provided." \
|
43
|
+
if delete_class_name.nil?
|
44
|
+
|
45
|
+
knife_cmd = eval(delete_class_name + '.new')
|
46
|
+
|
47
|
+
if knife_config['delete'].has_key?('name_key')
|
48
|
+
name_key = knife_config['create']['name_key']
|
49
|
+
knife_cmd.config[name_key.to_sym] = name
|
50
|
+
else
|
51
|
+
knife_cmd.name_args = [ name ]
|
52
|
+
end
|
53
|
+
|
54
|
+
config_knife(knife_cmd, knife_config['delete']['options'] || { })
|
55
|
+
config_knife(knife_cmd, knife_config['options'] || { })
|
56
|
+
|
57
|
+
if knife_config['delete']['synchronized']
|
58
|
+
@@sync ||= Mutex.new
|
59
|
+
@@sync.synchronize {
|
60
|
+
run_knife(knife_cmd, knife_config['delete']['retries'] || 0)
|
61
|
+
}
|
62
|
+
else
|
63
|
+
run_knife(knife_cmd, knife_config['delete']['retries'] || 0)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|