lib/cfer.rb in cfer-0.5.0.pre.rc1 vs lib/cfer.rb in cfer-0.5.0.pre.rc2

- old
+ new

@@ -12,10 +12,12 @@ end end # Contains the core Cfer logic module Cfer + DEBUG = false unless defined? DEBUG + # Code relating to working with Amazon CloudFormation module Cfn end # Code relating to building the CloudFormation document out of the Ruby DSL @@ -60,17 +62,19 @@ options[:on_failure].upcase! if options[:on_failure] tmpl = options[:template] || "#{stack_name}.rb" cfn = options[:aws_options] || {} cfn_stack = options[:cfer_client] || Cfer::Cfn::Client.new(cfn.merge(stack_name: stack_name)) - stack = options[:cfer_stack] || - Cfer::stack_from_file(tmpl, - options.merge( - client: cfn_stack, - parameters: generate_final_parameters(options) - ) - ) + raise Cfer::Util::CferError, "No such template file: #{tmpl}" unless File.exists?(tmpl) + stack = + options[:cfer_stack] || + Cfer::stack_from_file(tmpl, + options.merge( + client: cfn_stack, + parameters: generate_final_parameters(options) + ) + ) begin operation = stack.converge!(options) if options[:follow] && !options[:change] begin @@ -89,11 +93,12 @@ end retry end end end - describe! stack_name, options rescue nil # It's fine if we can't do this. + # This is allowed to fail, particularly if we decided to roll back + describe! stack_name, options rescue nil rescue Aws::CloudFormation::Errors::ValidationError => e Cfer::LOGGER.info "CFN validation error: #{e.message}" end stack end @@ -107,11 +112,11 @@ cfer_version = cfn_metadata.fetch("Cfer", {}).fetch("Version", nil) if cfer_version cfer_version_str = [cfer_version["major"], cfer_version["minor"], cfer_version["patch"]].join '.' cfer_version_str << '-' << cfer_version["pre"] unless cfer_version["pre"].nil? - cfer_version_str << '+' << cfer_version["pre"] unless cfer_version["pre"].nil? + cfer_version_str << '+' << cfer_version["build"] unless cfer_version["build"].nil? end Cfer::LOGGER.debug "Describe stack: #{cfn_stack}" Cfer::LOGGER.debug "Describe metadata: #{cfn_metadata}" @@ -158,10 +163,11 @@ def generate!(tmpl, options = {}) config(options) cfn = options[:aws_options] || {} cfn_stack = options[:cfer_client] || Cfer::Cfn::Client.new(cfn) + raise Cfer::Util::CferError, "No such template file: #{tmpl}" unless File.exists?(tmpl) stack = options[:cfer_stack] || Cfer::stack_from_file(tmpl, options.merge(client: cfn_stack, parameters: generate_final_parameters(options))).to_h puts render_json(stack, options) end @@ -177,11 +183,11 @@ def delete!(stack_name, options = {}) config(options) cfn = options[:aws_options] || {} cfn_stack = options[:cfer_client] || cfn_stack = Cfer::Cfn::Client.new(cfn.merge(stack_name: stack_name)) - cfn_stack.delete_stack(stack_name) + cfn_stack.delete_stack(stack_name: stack_name) if options[:follow] tail! stack_name, options.merge(cfer_client: cfn_stack) end end @@ -207,16 +213,12 @@ # @return [Cfer::Core::Stack] The assembled stack object def stack_from_file(file, options = {}) return stack_from_stdin(options) if file == '-' s = Cfer::Core::Stack.new(options) - if file.ends_with?('.json') - s.deep_merge! JSON.parse(File.read(file)) - else - templatize_errors(file) do - s.build_from_file file - end + templatize_errors(file) do + s.build_from_file file end s end # Builds a Cfer::Core::Stack from stdin @@ -240,36 +242,32 @@ Aws.config.update region: options[:region] if options[:region] Aws.config.update credentials: Cfer::Cfn::CferCredentialsProvider.new(profile_name: options[:profile]) if options[:profile] end def generate_final_parameters(options) - raise "parameter-environment set but parameter_file not set" \ + raise Cfer::Util::CferError, "parameter-environment set but parameter_file not set" \ if options[:parameter_environment] && options[:parameter_file].nil? - file_params = - if options[:parameter_file] - case File.extname(options[:parameter_file]) - when '.yaml' - require 'yaml' - YAML.load_file(options[:parameter_file]) - when '.json' - JSON.parse(IO.read(options[:parameter_file])) - else - raise "Unrecognized parameter file format: #{File.extname(options[:parameter_file])}" - end - else - {} - end + final_params = HashWithIndifferentAccess.new + final_params.deep_merge! Cfer::Config.new(cfer: options) \ + .build_from_file(options[:parameter_file]) \ + .to_h if options[:parameter_file] + if options[:parameter_environment] - raise "no key '#{options[:parameter_environment]}' found in parameters file." \ - unless file_params.key?(options[:parameter_environment]) + raise Cfer::Util::CferError, "no key '#{options[:parameter_environment]}' found in parameters file." \ + unless final_params.key?(options[:parameter_environment]) - file_params = file_params.deep_merge(file_params[options[:parameter_environment]]) + Cfer::LOGGER.debug "Merging in environment key #{options[:parameter_environment]}" + + final_params.deep_merge!(final_params[options[:parameter_environment]]) end - file_params.deep_merge(options[:parameters] || {}) + final_params.deep_merge!(options[:parameters] || {}) + + Cfer::LOGGER.debug "Final parameters: #{final_params}" + final_params end def render_json(obj, options = {}) if options[:pretty_print] puts JSON.pretty_generate(obj, options) @@ -296,57 +294,28 @@ } end COLORS_MAP = { - 'CREATE_IN_PROGRESS' => { - color: :yellow - }, - 'DELETE_IN_PROGRESS' => { - color: :yellow - }, - 'UPDATE_IN_PROGRESS' => { - color: :green - }, + 'CREATE_IN_PROGRESS' => { color: :yellow }, + 'DELETE_IN_PROGRESS' => { color: :yellow }, + 'UPDATE_IN_PROGRESS' => { color: :green }, - 'CREATE_FAILED' => { - color: :red, - finished: true - }, - 'DELETE_FAILED' => { - color: :red, - finished: true - }, - 'UPDATE_FAILED' => { - color: :red, - finished: true - }, + 'CREATE_FAILED' => { color: :red, finished: true }, + 'DELETE_FAILED' => { color: :red, finished: true }, + 'UPDATE_FAILED' => { color: :red, finished: true }, - 'CREATE_COMPLETE' => { - color: :green, - finished: true - }, - 'DELETE_COMPLETE' => { - color: :green, - finished: true - }, - 'UPDATE_COMPLETE' => { - color: :green, - finished: true - }, + 'CREATE_COMPLETE' => { color: :green, finished: true }, + 'DELETE_COMPLETE' => { color: :green, finished: true }, + 'UPDATE_COMPLETE' => { color: :green, finished: true }, - 'DELETE_SKIPPED' => { - color: :yellow - }, + 'DELETE_SKIPPED' => { color: :yellow }, - 'ROLLBACK_IN_PROGRESS' => { - color: :red - }, - 'ROLLBACK_COMPLETE' => { - color: :red, - finished: true - } + 'ROLLBACK_IN_PROGRESS' => { color: :red }, + + 'UPDATE_ROLLBACK_COMPLETE' => { color: :red, finished: true }, + 'ROLLBACK_COMPLETE' => { color: :red, finished: true } } def color_map(str) if COLORS_MAP.include?(str) Rainbow(str).send(COLORS_MAP[str][:color]) @@ -359,9 +328,8 @@ COLORS_MAP[str][:finished] || false end end end -Dir["#{File.dirname(__FILE__)}/cfer/*.rb"].each { |f| require(f) } -Dir["#{File.dirname(__FILE__)}/cfer/**/*.rb"].each { |f| require(f) } +Dir["#{File.dirname(__FILE__)}/cfer/**/*.rb"].each { |f| require(f) unless f.ends_with?('console.rb') } Dir["#{File.dirname(__FILE__)}/cferext/**/*.rb"].each { |f| require(f) }