stack-kicker 0.0.18 → 0.0.19
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/stack-kicker/version.rb +1 -1
- data/lib/stack.rb +53 -19
- metadata +1 -1
data/lib/stack-kicker/version.rb
CHANGED
data/lib/stack.rb
CHANGED
@@ -30,6 +30,7 @@ require 'tempfile'
|
|
30
30
|
# This really needs to be converted into a class....
|
31
31
|
#
|
32
32
|
module Stack
|
33
|
+
include Methadone::SH
|
33
34
|
|
34
35
|
# Shadow the global constant Logger with Stack::Logger
|
35
36
|
# (if you want access to the global constant, use ::Logger from inside the Stack module)
|
@@ -39,6 +40,7 @@ module Stack
|
|
39
40
|
Logger.formatter = proc do |severity, datetime, progname, msg|
|
40
41
|
"#{datetime} #{severity}: #{msg}\n"
|
41
42
|
end
|
43
|
+
set_sh_logger(Logger)
|
42
44
|
|
43
45
|
# location of gem, where config[:gemhome]/lib contains our default cloud-init templates
|
44
46
|
@@gemhome = File.absolute_path(File.realpath(File.dirname(File.expand_path(__FILE__)) + '/..'))
|
@@ -142,7 +144,7 @@ module Stack
|
|
142
144
|
# check that we have semi-sensible Chef setup
|
143
145
|
# at a bare minimum, we need the directory where we're going to download
|
144
146
|
# validation.pem to to exist
|
145
|
-
dot_chef_abs = File.absolute_path(config[:stackhome]
|
147
|
+
dot_chef_abs = File.absolute_path(File.join(config[:stackhome], config[:dot_chef]))
|
146
148
|
if !File.directory?(dot_chef_abs)
|
147
149
|
Logger.warn "#{dot_chef_abs} doesn't exist"
|
148
150
|
end
|
@@ -166,7 +168,7 @@ module Stack
|
|
166
168
|
# this lazily assumes that the :key_pair name matches the file the keys were loaded
|
167
169
|
# from
|
168
170
|
if (0 == 1)
|
169
|
-
ssh_keys_loaded =
|
171
|
+
ssh_keys_loaded = Stack.shellout(config, "ssh-add -L")
|
170
172
|
Logger.debug "ssh_keys_loaded: #{ssh_keys_loaded}"
|
171
173
|
Logger.debug "Looking for #{config[:key_pair]}"
|
172
174
|
if ssh_keys_loaded.include?(config[:key_pair])
|
@@ -242,15 +244,15 @@ module Stack
|
|
242
244
|
end
|
243
245
|
|
244
246
|
# CWD shoud be chef-repo/bootstrap, so the project .chef directory should be
|
245
|
-
dot_chef_abs = File.absolute_path(config[:stackhome]
|
247
|
+
dot_chef_abs = File.absolute_path(File.join(config[:stackhome],config[:dot_chef]))
|
246
248
|
|
247
249
|
if !File.directory?(dot_chef_abs)
|
248
250
|
Logger.warn "#{dot_chef_abs} doesn't exist, creating it..."
|
249
251
|
Dir.mkdir(dot_chef_abs)
|
250
252
|
end
|
251
253
|
|
252
|
-
client_key = dot_chef_abs
|
253
|
-
validation_key = dot_chef_abs
|
254
|
+
client_key = File.join(dot_chef_abs, config[:name] + '-' + ENV['USER'] + '.pem')
|
255
|
+
validation_key = File.join(dot_chef_abs, config[:name] + '-' + 'validation.pem')
|
254
256
|
|
255
257
|
Logger.debug "stackhome: #{config[:stackhome]}"
|
256
258
|
Logger.debug "Current user client key: #{client_key}"
|
@@ -260,9 +262,9 @@ module Stack
|
|
260
262
|
log_level :info
|
261
263
|
log_location STDOUT
|
262
264
|
node_name '<%=ENV['USER']%>'
|
263
|
-
client_key '<%=
|
265
|
+
client_key '<%=client_key%>'
|
264
266
|
validation_client_name 'chef-validator'
|
265
|
-
validation_key '<%=
|
267
|
+
validation_key '<%=validation_key%>'
|
266
268
|
chef_server_url '<%=config[:chef_server_public]%>'
|
267
269
|
cache_type 'BasicFile'
|
268
270
|
cache_options( :path => '<%=dot_chef_abs%>/checksums' )
|
@@ -306,6 +308,10 @@ cookbook_path [ '<%=config[:stackhome]%>/cookbooks' ]
|
|
306
308
|
# config[:role_details] contains built out role details with defaults filled in from stack defaults
|
307
309
|
# config[:node_details] contains node details built out from role_details
|
308
310
|
|
311
|
+
if config[:find_file_paths].nil?
|
312
|
+
config[:find_file_paths] = Array.new
|
313
|
+
end
|
314
|
+
|
309
315
|
# set some sensible defaults to the stack-wide defaults if they haven't been set in the Stackfile.
|
310
316
|
if config[:provisioner].nil?
|
311
317
|
Logger.warn { "Defaulting to chef for config[:provisioner] "}
|
@@ -326,6 +332,7 @@ cookbook_path [ '<%=config[:stackhome]%>/cookbooks' ]
|
|
326
332
|
Logger.warn { "Defaulting to .chef/validation.pem for config[:chef_validation_pem]" }
|
327
333
|
config[:chef_validation_pem] = '.chef/validation.pem'
|
328
334
|
end
|
335
|
+
config[:chef_validation_pem] = Stack.find_file(config, config[:chef_validation_pem])
|
329
336
|
|
330
337
|
if config[:name_template].nil?
|
331
338
|
Logger.warn { "Defaulting to '%s-%s-%s%04d' for config[:name_template]" }
|
@@ -346,10 +353,6 @@ cookbook_path [ '<%=config[:stackhome]%>/cookbooks' ]
|
|
346
353
|
config[:metadata] = Hash.new
|
347
354
|
end
|
348
355
|
|
349
|
-
if config[:find_file_paths].nil?
|
350
|
-
config[:find_file_paths] = Array.new
|
351
|
-
end
|
352
|
-
|
353
356
|
if config[:node_details].nil?
|
354
357
|
Logger.debug { "Initializing config[:node_details] and config[:azs]" }
|
355
358
|
config[:node_details] = Hash.new
|
@@ -531,7 +534,7 @@ cookbook_path [ '<%=config[:stackhome]%>/cookbooks' ]
|
|
531
534
|
servers.each do |host, details|
|
532
535
|
public_ip = Stack.get_public_ip(config, host)
|
533
536
|
Logger.info { "#{host} #{public_ip}" }
|
534
|
-
cmd_output =
|
537
|
+
cmd_output = Stack.shellout(config, %Q[ssh -oStrictHostKeyChecking=no -l #{user} #{public_ip} "#{command}"])
|
535
538
|
Logger.info { "#{host} #{public_ip} #{cmd_output}" }
|
536
539
|
end
|
537
540
|
else
|
@@ -708,11 +711,11 @@ cookbook_path [ '<%=config[:stackhome]%>/cookbooks' ]
|
|
708
711
|
else
|
709
712
|
# Prepare Chef
|
710
713
|
# 1) delete the client if it exists
|
711
|
-
knife_client_list =
|
714
|
+
knife_client_list = Stack.shellout(config, "knife client list | grep #{hostname}")
|
712
715
|
knife_client_list.sub!(/\s/,'')
|
713
716
|
if knife_client_list.length() > 0
|
714
717
|
# we should delete the client to make way for this new machine
|
715
|
-
|
718
|
+
Stack.shellout(config, "knife client delete --yes #{hostname}")
|
716
719
|
end
|
717
720
|
|
718
721
|
# knife node create -d --environment $CHEF_ENVIRONMENT $SERVER_NAME
|
@@ -720,12 +723,12 @@ cookbook_path [ '<%=config[:stackhome]%>/cookbooks' ]
|
|
720
723
|
# this relies on .chef matching the stacks config (TODO: poke the Chef API directly?)
|
721
724
|
cmd = "EDITOR=\"perl -p -i -e 's/_default/#{config[:chef_environment]}/'\" knife node create --server-url #{config[:chef_server_public]} #{hostname}"
|
722
725
|
Logger.debug cmd
|
723
|
-
knife_node_create =
|
726
|
+
knife_node_create = Stack.shellout(config, cmd)
|
724
727
|
Logger.info "Priming Chef Server: #{knife_node_create}"
|
725
728
|
|
726
729
|
cmd = "knife node run_list add -d --environment #{config[:chef_environment]} #{hostname} \"role[#{role}]\""
|
727
730
|
Logger.info cmd
|
728
|
-
knife_node_run_list =
|
731
|
+
knife_node_run_list = Stack.shellout(config, cmd)
|
729
732
|
Logger.info "Priming Chef Server: #{knife_node_run_list}"
|
730
733
|
end
|
731
734
|
|
@@ -746,9 +749,14 @@ cookbook_path [ '<%=config[:stackhome]%>/cookbooks' ]
|
|
746
749
|
|
747
750
|
if config[:chef_server_hostname].nil?
|
748
751
|
Logger.info "config[:chef_server_hostname] is nil, skipping chef server substitution"
|
752
|
+
elsif (role_details[:chef_server])
|
753
|
+
Logger.info "This is the Chef Server - setting up to talk to ourselves"
|
754
|
+
multipart.gsub!(%q!%CHEF_SERVER%!, 'http://127.0.0.1:4000/')
|
755
|
+
multipart.gsub!(%q!%CHEF_ENVIRONMENT%!, config[:chef_environment])
|
749
756
|
else
|
750
757
|
Logger.info "Chef server is #{config[:chef_server_hostname]}, which is in #{config[:node_details][config[:chef_server_hostname]][:region]}"
|
751
758
|
Logger.info "#{hostname}'s region is #{config[:node_details][hostname][:region]}"
|
759
|
+
|
752
760
|
# if this host is in the same region/az, use the private URL, if not, use the public url
|
753
761
|
if (config[:node_details][hostname][:region] == config[:node_details][config[:chef_server_hostname]][:region]) && !config[:chef_server_private].nil?
|
754
762
|
multipart.gsub!(%q!%CHEF_SERVER%!, config[:chef_server_private])
|
@@ -757,7 +765,9 @@ cookbook_path [ '<%=config[:stackhome]%>/cookbooks' ]
|
|
757
765
|
else
|
758
766
|
Logger.warn { "Not setting the chef url for #{hostname} as neither chef_server_private or chef_server_public are valid yet" }
|
759
767
|
end
|
768
|
+
|
760
769
|
multipart.gsub!(%q!%CHEF_ENVIRONMENT%!, config[:chef_environment])
|
770
|
+
|
761
771
|
if File.exists?(config[:chef_validation_pem])
|
762
772
|
multipart.gsub!(%q!%CHEF_VALIDATION_PEM%!, File.read(config[:chef_validation_pem]))
|
763
773
|
else
|
@@ -783,6 +793,7 @@ cookbook_path [ '<%=config[:stackhome]%>/cookbooks' ]
|
|
783
793
|
Logger.debug { "multipart_complete after erb => #{multipart_complete} " }
|
784
794
|
multipart = multipart_complete
|
785
795
|
end
|
796
|
+
Logger.debug { "multipart = #{multipart}" }
|
786
797
|
|
787
798
|
Logger.info "Creating #{hostname} in #{node_details[hostname][:az]} with role #{role}"
|
788
799
|
|
@@ -847,7 +858,7 @@ cookbook_path [ '<%=config[:stackhome]%>/cookbooks' ]
|
|
847
858
|
if role_details[:post_install_script]
|
848
859
|
Logger.debug { "This role has a post-install script (#{role_details[:post_install_script]}), preparing to run" }
|
849
860
|
# convert when we got passed to an absolute path
|
850
|
-
post_install_script_abs =
|
861
|
+
post_install_script_abs = Stack.find_file(config, role_details[:post_install_script])
|
851
862
|
post_install_cwd_abs = File.realpath(config[:stackhome] + '/' + role_details[:post_install_cwd])
|
852
863
|
|
853
864
|
# replace any tokens in the argument
|
@@ -871,16 +882,22 @@ cookbook_path [ '<%=config[:stackhome]%>/cookbooks' ]
|
|
871
882
|
# 2) stackhome
|
872
883
|
# 2) stackhome + find_file_paths
|
873
884
|
# 3) gemhome/lib
|
874
|
-
|
885
|
+
|
886
|
+
if filename.nil? || filename.empty?
|
887
|
+
raise ArgumentError
|
888
|
+
end
|
889
|
+
|
890
|
+
dirs = [ '.' ] # current directory
|
875
891
|
dirs.push(config[:stackhome])
|
876
892
|
config[:find_file_paths].each { |fp| dirs.push(File.join(config[:stackhome], fp)) }
|
877
893
|
dirs.push(File.join(@@gemhome, 'lib'))
|
894
|
+
dirs.push('') # find absolute paths
|
878
895
|
dirs.flatten!
|
879
896
|
|
880
897
|
Logger.debug "find_file, looking for #{filename} in #{dirs}"
|
881
898
|
filename_fqp = ''
|
882
899
|
dirs.each do |dir|
|
883
|
-
fqp = dir
|
900
|
+
fqp = File.join(dir, filename)
|
884
901
|
Logger.debug "find_file: checking #{fqp}"
|
885
902
|
if File.file?(fqp)
|
886
903
|
Logger.debug "find_file: found #{fqp}!"
|
@@ -894,5 +911,22 @@ cookbook_path [ '<%=config[:stackhome]%>/cookbooks' ]
|
|
894
911
|
filename_fqp
|
895
912
|
end
|
896
913
|
|
914
|
+
def Stack.shellout(config, command, cwd=nil)
|
915
|
+
# wrapper to exec things in a knife friendly way
|
916
|
+
|
917
|
+
if cwd.nil?
|
918
|
+
cwd = config[:stackhome]
|
919
|
+
end
|
920
|
+
|
921
|
+
saved_wd = Dir.getwd()
|
922
|
+
output = ""
|
923
|
+
Dir.chdir(cwd)
|
924
|
+
sh command do |stdout, stderr, exitstatus|
|
925
|
+
output = stdout
|
926
|
+
end
|
927
|
+
Dir.chdir(saved_wd)
|
928
|
+
|
929
|
+
return output
|
930
|
+
end
|
897
931
|
end
|
898
932
|
|