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

- old
+ new

@@ -12,13 +12,15 @@ end end # Contains the core Cfer logic module Cfer + # Code relating to working with Amazon CloudFormation module Cfn end + # Code relating to building the CloudFormation document out of the Ruby DSL module Core end %w{ DB @@ -48,12 +50,16 @@ "#{msg}\n" } class << self + # Creates or updates a CloudFormation stack + # @param stack_name [String] The name of the stack to update + # @param options [Hash] def converge!(stack_name, options = {}) config(options) + 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] || @@ -83,30 +89,41 @@ end retry end end end + describe! stack_name, options rescue nil # It's fine if we can't do this. rescue Aws::CloudFormation::Errors::ValidationError => e Cfer::LOGGER.info "CFN validation error: #{e.message}" end - describe! stack_name, options unless options[:follow] + stack end def describe!(stack_name, options = {}) config(options) cfn = options[:aws_options] || {} cfn_stack = options[:cfer_client] || Cfer::Cfn::Client.new(cfn.merge(stack_name: stack_name)) + cfn_metadata = cfn_stack.fetch_metadata cfn_stack = cfn_stack.fetch_stack + 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? + end + Cfer::LOGGER.debug "Describe stack: #{cfn_stack}" + Cfer::LOGGER.debug "Describe metadata: #{cfn_metadata}" case options[:output_format] when 'json' puts render_json(cfn_stack, options) when 'table', nil puts "Status: #{cfn_stack[:stack_status]}" puts "Description: #{cfn_stack[:description]}" if cfn_stack[:description] + puts "Created with Cfer version: #{Semantic::Version.new(cfer_version_str).to_s} (current: #{Cfer::SEMANTIC_VERSION.to_s})" if cfer_version puts "" def tablify(list, type) list ||= [] list.map { |param| { @@ -120,10 +137,11 @@ outputs = tablify(cfn_stack[:outputs] || [], 'output') tp parameters + outputs, :Type, :Key, {:Value => {:width => 80}} else raise Cfer::Util::CferError, "Invalid output format #{options[:output_format]}." end + cfn_stack end def tail!(stack_name, options = {}, &block) config(options) cfn = options[:aws_options] || {} @@ -133,11 +151,10 @@ else cfn_client.tail(options) do |event| Cfer::LOGGER.info "%s %-30s %-40s %-20s %s" % [event.timestamp, color_map(event.resource_status), event.resource_type, event.logical_resource_id, event.resource_status_reason] end end - describe! stack_name, options end def generate!(tmpl, options = {}) config(options) cfn = options[:aws_options] || {} @@ -161,10 +178,14 @@ 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) + + if options[:follow] + tail! stack_name, options.merge(cfer_client: cfn_stack) + end end # Builds a Cfer::Core::Stack from a Ruby block # # @param options [Hash] The stack options @@ -179,28 +200,43 @@ s end # Builds a Cfer::Core::Stack from a ruby script # - # @param file [String] The file containing the Cfn DSL + # @param file [String] The file containing the Cfn DSL or plain JSON # @param options [Hash] (see #stack_from_block) # @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) - templatize_errors(file) do - s.build_from_file file + if file.ends_with?('.json') + s.deep_merge! JSON.parse(File.read(file)) + else + templatize_errors(file) do + s.build_from_file file + end end s end + # Builds a Cfer::Core::Stack from stdin + # + # @param options [Hash] (see #stack_from_block) + # @return [Cfer::Core::Stack] The assembled stack object + def stack_from_stdin(options = {}) + s = Cfer::Core::Stack.new(options) + templatize_errors('STDIN') do + s.build_from_string STDIN.read, 'STDIN' + end + s + end + private def config(options) Cfer::LOGGER.debug "Options: #{options}" Cfer::LOGGER.level = Logger::DEBUG if options[:verbose] - - require 'rubygems' - require 'bundler/setup' 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