lib/stack.rb in stack-kicker-0.0.21 vs lib/stack.rb in stack-kicker-0.0.22
- old
+ new
@@ -55,13 +55,15 @@
def Stack.log_format(format_proc)
Logger.formatter = format_proc
end
def Stack.show_stacks(stackfile = 'Stackfile')
- # our local config file
- config_raw = File.read(stackfile)
- eval(config_raw)
+ # evaluate our Stackfile, but only the once
+ if defined?(StackConfig::Stacks).nil?
+ config_raw = File.read(stackfile)
+ eval(config_raw)
+ end
Logger.info { "Stacks:" }
StackConfig::Stacks.each do |name, details|
Logger.info { " #{name}" }
end
@@ -75,18 +77,24 @@
hostnames.each { |hostname| Logger.info " #{hostname}" }
end
def Stack.select_stack(stackfile = 'Stackfile', stack_name)
- # our local config file
- config_raw = File.read(stackfile)
- eval(config_raw)
+ # evaluate our Stackfile, but only the once
+ if defined?(StackConfig::Stacks).nil?
+ config_raw = File.read(stackfile)
+ eval(config_raw)
+ end
# if there is only one stack defined in the Stackfile, load it:
if StackConfig::Stacks.count == 1 && stack_name.nil?
stack_name = StackConfig::Stacks.keys[0]
Logger.info { "Defaulting to #{stack_name} as there is a single stack defined and no stack named" }
+ elsif stack_name.nil?
+ Logger.info { "You didn't specify a stack, and there are multiple stacks defined in #{stackfile}" }
+ Stack.show_stacks(stackfile)
+ exit
end
# returns a config object, injecting the name into the returned config
if StackConfig::Stacks[stack_name].nil?
Logger.error { "#{stack_name} is invalid, defined stacks are:" }
@@ -133,46 +141,52 @@
address_description
end
# check that all the required config items are set
def Stack.check_config(config)
- if config['REGION'].nil? || config['USERNAME'].nil? || config['PASSWORD'].nil? || config['AUTH_URL'].nil? || config['TENANT_NAME'].nil? &&
- config['REGION'].empty? || config['USERNAME'].empty? || config['PASSWORD'].empty? || config['AUTH_URL'].empty? || config['TENANT_NAME'].empty?
- Logger.error { "REGION, USERNAME, PASSWORD, AUTH_URL & TENANT_NAME must all be set" }
- exit
- end
+ if config[:checked].nil?
+ if config['REGION'].nil? || config['USERNAME'].nil? || config['PASSWORD'].nil? || config['AUTH_URL'].nil? || config['TENANT_NAME'].nil? &&
+ config['REGION'].empty? || config['USERNAME'].empty? || config['PASSWORD'].empty? || config['AUTH_URL'].empty? || config['TENANT_NAME'].empty?
+ Logger.error { "REGION, USERNAME, PASSWORD, AUTH_URL & TENANT_NAME must all be set" }
+ exit
+ end
- # load defaults for any items not configured
- Stack.populate_config(config)
-
- if config[:provisioner] == 'chef'
- # check that we have semi-sensible Chef setup
- # at a bare minimum, we need the directory where we're going to download
- # validation.pem to to exist
- dot_chef_abs = File.absolute_path(File.join(config[:stackhome], config[:dot_chef]))
- if !File.directory?(dot_chef_abs)
- Logger.warn "#{dot_chef_abs} doesn't exist"
+ if config[:roles].nil?
+ Logger.error { "No roles defined in #{config[:name]}, aborting." }
+ exit
end
- # Check we have a #{dot_chef_abs}/.chef/knife.rb
- knife_rb_abs = dot_chef_abs + '/knife.rb'
- if File.exists?(knife_rb_abs)
- Logger.info "Found #{knife_rb_abs}, lets hope it contains something sensible"
- else
- Logger.warn "#{knife_rb_abs} doesn't exist, please run 'stack-kicker configure-knife <stack-name>'"
+ # load defaults for any items not configured
+ Stack.populate_config(config)
+
+ if config[:provisioner] == 'chef'
+ # check that we have semi-sensible Chef setup
+ # at a bare minimum, we need the directory where we're going to download
+ # validation.pem to to exist
+ dot_chef_abs = File.absolute_path(File.join(config[:stackhome], config[:dot_chef]))
+ if !File.directory?(dot_chef_abs)
+ Logger.warn "#{dot_chef_abs} doesn't exist"
+ end
+
+ # Check we have a #{dot_chef_abs}/.chef/knife.rb
+ knife_rb_abs = dot_chef_abs + '/knife.rb'
+ if File.exists?(knife_rb_abs)
+ Logger.info "Found #{knife_rb_abs}, lets hope it contains something sensible"
+ else
+ Logger.warn "#{knife_rb_abs} doesn't exist, please run 'stack-kicker configure-knife <stack-name>'"
+ end
end
end
+ config[:checked] = true
end
# validate that all our OpenStack creds, image_id, flavors, keys etc are valid
def Stack.validate(config)
+ # check & populate the config with defaults for anything not specified.
Stack.check_config(config)
- # populate the config & then walk through the AZs verifying the config
- Stack.populate_config(config)
-
# check that the ssh-key is loaded, otherwise most post-install scripts will fail
# this lazily assumes that the :key_pair name matches the file the keys were loaded
# from
if (0 == 1)
ssh_keys_loaded = Stack.shellout(config, "ssh-add -L")
@@ -311,136 +325,138 @@
def Stack.populate_config(config)
# config[:role_details] contains built out role details with defaults filled in from stack defaults
# config[:node_details] contains node details built out from role_details
- if config[:find_file_paths].nil?
- config[:find_file_paths] = Array.new
- end
+ if config[:populated].nil?
+ if config[:find_file_paths].nil?
+ config[:find_file_paths] = Array.new
+ end
- # set some sensible defaults to the stack-wide defaults if they haven't been set in the Stackfile.
- if config[:provisioner].nil?
- Logger.warn { "Defaulting to chef for config[:provisioner] "}
- config[:provisioner] = 'chef'
- end
+ # set some sensible defaults to the stack-wide defaults if they haven't been set in the Stackfile.
+ if config[:provisioner].nil?
+ Logger.warn { "Defaulting to chef for config[:provisioner] "}
+ config[:provisioner] = 'chef'
+ end
- if config[:dot_chef].nil?
- Logger.warn { "Defaulting to .chef for config[:dot_chef] "}
- config[:dot_chef] = '.chef'
- end
+ if config[:dot_chef].nil?
+ Logger.warn { "Defaulting to .chef for config[:dot_chef] "}
+ config[:dot_chef] = '.chef'
+ end
- if config[:chef_environment].nil?
- Logger.warn { "Defaulting to _default for config[:chef_environment]" }
- config[:chef_environment] = '_default'
- end
+ if config[:chef_environment].nil?
+ Logger.warn { "Defaulting to _default for config[:chef_environment]" }
+ config[:chef_environment] = '_default'
+ end
- if config[:chef_validation_pem].nil?
- Logger.warn { "Defaulting to .chef/validation.pem for config[:chef_validation_pem]" }
- config[:chef_validation_pem] = '.chef/validation.pem'
- end
- chef_validation_pem_abs = Stack.find_file(config, config[:chef_validation_pem])
- # only store the abs if we found it...
- config[:chef_validation_pem] = chef_validation_pem_abs unless chef_validation_pem_abs.nil?
+ if config[:chef_validation_pem].nil?
+ Logger.warn { "Defaulting to .chef/validation.pem for config[:chef_validation_pem]" }
+ config[:chef_validation_pem] = '.chef/validation.pem'
+ end
+ chef_validation_pem_abs = Stack.find_file(config, config[:chef_validation_pem])
+ # only store the abs if we found it...
+ config[:chef_validation_pem] = chef_validation_pem_abs unless chef_validation_pem_abs.nil?
- if config[:name_template].nil?
- Logger.warn { "Defaulting to '%s-%s-%s%04d' for config[:name_template]" }
- config[:name_template] = '%s-%s-%s%04d'
- end
+ if config[:name_template].nil?
+ Logger.warn { "Defaulting to '%s-%s-%s%04d' for config[:name_template]" }
+ config[:name_template] = '%s-%s-%s%04d'
+ end
- if config[:site_template].nil?
- Logger.warn { "Defaulting to '%s' for config[:site_template]" }
- config[:site_template] = '%s'
- end
+ if config[:site_template].nil?
+ Logger.warn { "Defaulting to '%s' for config[:site_template]" }
+ config[:site_template] = '%s'
+ end
- if config[:global_service_name].nil?
- Logger.error { "Defaulting to 'UNKNOWN' for config[:global_service_name]" }
- config[:site_template] = 'UNKNOWN'
- end
+ if config[:global_service_name].nil?
+ Logger.error { "Defaulting to 'UNKNOWN' for config[:global_service_name]" }
+ config[:site_template] = 'UNKNOWN'
+ end
- if config[:metadata].nil?
- config[:metadata] = Hash.new
- end
+ if config[:metadata].nil?
+ config[:metadata] = Hash.new
+ end
- if config[:node_details].nil?
- Logger.debug { "Initializing config[:node_details] and config[:azs]" }
- config[:node_details] = Hash.new
- config[:azs] = Array.new
+ if config[:node_details].nil?
+ Logger.debug { "Initializing config[:node_details] and config[:azs]" }
+ config[:node_details] = Hash.new
+ config[:azs] = Array.new
- config[:roles].each do |role,role_details|
- Logger.debug { "Setting defaults for #{role}" }
+ config[:roles].each do |role,role_details|
+ Logger.debug { "Setting defaults for #{role}" }
- # default to 1 node of this role if :count isn't set
- if role_details[:count].nil?
- role_details[:count] = 1
- end
+ # default to 1 node of this role if :count isn't set
+ if role_details[:count].nil?
+ role_details[:count] = 1
+ end
- if (role_details[:data_dir].nil?)
- role_details[:data_dir] = '/dummy'
- end
+ if (role_details[:data_dir].nil?)
+ role_details[:data_dir] = '/dummy'
+ end
- # Has the cloud_config_yaml been overridden?
- if (role_details[:cloud_config_yaml])
- role_details[:cloud_config_yaml] = Stack.find_file(config, role_details[:cloud_config_yaml])
- else
- role_details[:cloud_config_yaml] = Stack.find_file(config, 'cloud-config.yaml')
- end
+ # Has the cloud_config_yaml been overridden?
+ if (role_details[:cloud_config_yaml])
+ role_details[:cloud_config_yaml] = Stack.find_file(config, role_details[:cloud_config_yaml])
+ else
+ role_details[:cloud_config_yaml] = Stack.find_file(config, 'cloud-config.yaml')
+ end
- # Has the default bootstrap script been overridden
- if (role_details[:bootstrap])
- if (role_details[:bootstrap].empty?)
- Logger.debug { "role_details[:bootstrap] is empty, ignoring" }
+ # Has the default bootstrap script been overridden
+ if (role_details[:bootstrap])
+ if (role_details[:bootstrap].empty?)
+ Logger.debug { "role_details[:bootstrap] is empty, ignoring" }
+ else
+ role_details[:bootstrap] = Stack.find_file(config, role_details[:bootstrap])
+ end
else
- role_details[:bootstrap] = Stack.find_file(config, role_details[:bootstrap])
+ role_details[:bootstrap] = Stack.find_file(config, 'chef-client-bootstrap-excl-validation-pem.sh')
end
- else
- role_details[:bootstrap] = Stack.find_file(config, 'chef-client-bootstrap-excl-validation-pem.sh')
- end
- # we default to the role name for the security group unless explicitly set
- if role_details[:security_group].nil?
- role_details[:security_group] = role.to_s
- end
+ # we default to the role name for the security group unless explicitly set
+ if role_details[:security_group].nil?
+ role_details[:security_group] = role.to_s
+ end
- # default to execing post install scripts in stackhome is a cwd wasn't set
- # (cwd is calculated relative to stackhome)
- if role_details[:post_install_cwd].nil?
- role_details[:post_install_cwd] = '/.'
- end
+ # default to execing post install scripts in stackhome is a cwd wasn't set
+ # (cwd is calculated relative to stackhome)
+ if role_details[:post_install_cwd].nil?
+ role_details[:post_install_cwd] = '/.'
+ end
- if role_details[:post_install_args].nil?
- role_details[:post_install_args] = ''
- end
+ if role_details[:post_install_args].nil?
+ role_details[:post_install_args] = ''
+ end
- (1..role_details[:count]).each do |p|
- Logger.debug { "Populating the config[:role_details][:azs] array with AZ" }
- role_details[:azs] = Array.new if role_details[:azs].nil?
+ (1..role_details[:count]).each do |p|
+ Logger.debug { "Populating the config[:role_details][:azs] array with AZ" }
+ role_details[:azs] = Array.new if role_details[:azs].nil?
- # is there an az set for this node?
- if role_details[:azs][p-1].nil?
- # inherit the global az
- Logger.debug { "Inheriting the AZ for #{role} (#{config['REGION']})" }
- role_details[:azs][p-1] = config['REGION']
- end
+ # is there an az set for this node?
+ if role_details[:azs][p-1].nil?
+ # inherit the global az
+ Logger.debug { "Inheriting the AZ for #{role} (#{config['REGION']})" }
+ role_details[:azs][p-1] = config['REGION']
+ end
- # add this AZ to the AZ list, we'll dedupe later
- config[:azs] << role_details[:azs][p-1]
+ # add this AZ to the AZ list, we'll dedupe later
+ config[:azs] << role_details[:azs][p-1]
- hostname = Stack.generate_hostname(config, role, p)
- Logger.debug { "Setting node_details for #{hostname}, using element #{p}-1 from #{role_details[:azs]}" }
- config[:node_details][hostname] = { :az => role_details[:azs][p-1], :region => role_details[:azs][p-1], :role => role }
+ hostname = Stack.generate_hostname(config, role, p)
+ Logger.debug { "Setting node_details for #{hostname}, using element #{p}-1 from #{role_details[:azs]}" }
+ config[:node_details][hostname] = { :az => role_details[:azs][p-1], :region => role_details[:azs][p-1], :role => role }
+ end
end
end
- end
- config[:azs].uniq!
+ config[:azs].uniq!
- # if set the region specific settings from the global settings if not already specified
- config[:azs].each do |az|
- # we store region spefic stuff in hash
- config[az] = Hash.new if config[az].nil?
+ # if set the region specific settings from the global settings if not already specified
+ config[:azs].each do |az|
+ # we store region spefic stuff in hash
+ config[az] = Hash.new if config[az].nil?
- config[az]['image_id'] = config['image_id'] if config[az]['image_id'].nil?
+ config[az]['image_id'] = config['image_id'] if config[az]['image_id'].nil?
+ end
end
-
+ config[:populated] = true
config[:node_details]
end
# get all instances running in the current config
# return a hash where key is the instance name, value is another hash containing :region, :id, :addresses