lib/cfer/core/stack.rb in cfer-0.4.2 vs lib/cfer/core/stack.rb in cfer-0.5.0.pre.rc1
- old
+ new
@@ -1,11 +1,11 @@
module Cfer::Core
# Defines the structure of a CloudFormation stack
class Stack < Cfer::Block
- include Cfer::Core
- include Cfer::Cfn
+ include Cfer::Core::Functions
+ include Cfer::Core::Hooks
# The parameters strictly as passed via command line
attr_reader :input_parameters
# The fully resolved parameters, including defaults and parameters fetched from an existing stack during an update
@@ -135,11 +135,11 @@
# @param options [Hash] Additional attributes to add to the resource block (such as the `UpdatePolicy` for an `AWS::AutoScaling::AutoScalingGroup`)
def resource(name, type, options = {}, &block)
Preconditions.check_argument(/[[:alnum:]]+/ =~ name, "Resource name must be alphanumeric")
clazz = Cfer::Core::Resource.resource_class(type)
- rc = clazz.new(name, type, options, &block)
+ rc = clazz.new(name, type, self, options, &block)
self[:Resources][name] = rc
rc
end
@@ -156,83 +156,45 @@
# @return [String] The final template
def to_cfn
to_h.to_json
end
+ # Gets the Cfn client, if one exists, or throws an error if one does not
def client
@options[:client] || raise(Cfer::Util::CferError, "Stack has no associated client.")
end
# Includes template code from one or more files, and evals it in the context of this stack.
# Filenames are relative to the file containing the invocation of this method.
def include_template(*files)
include_base = options[:include_base] || File.dirname(caller.first.split(/:\d/,2).first)
files.each do |file|
path = File.join(include_base, file)
- instance_eval(File.read(path), path)
+ if path.ends_with?('.json')
+ self.deep_merge! JSON.parse(File.read(path))
+ else
+ instance_eval(File.read(path), path)
+ end
end
end
+ # Looks up a specific output of another CloudFormation stack in the same region.
+ # @param stack [String] The name of the stack to fetch an output from
+ # @param out [String] The name of the output to fetch from the stack
def lookup_output(stack, out)
- client = @options[:client] || raise(Cfer::Util::CferError, "Can not fetch stack outputs without a client")
- client.fetch_output(stack, out)
+ lookup_outputs(stack).fetch(out)
end
+ # Looks up a hash of all outputs from another CloudFormation stack in the same region.
+ # @param stack [String] The name of the stack to fetch outputs from
def lookup_outputs(stack)
client = @options[:client] || raise(Cfer::Util::CferError, "Can not fetch stack outputs without a client")
client.fetch_outputs(stack)
end
- private
-
- def post_block
- begin
- validate_stack!(self)
- rescue Cfer::Util::CferValidationError => e
- Cfer::LOGGER.error "Cfer detected #{e.errors.size > 1 ? 'errors' : 'an error'} when generating the stack:"
- e.errors.each do |err|
- Cfer::LOGGER.error "* #{err[:error]} in Stack#{validation_contextualize(err[:context])}"
- end
- raise e
+ class << self
+ def extend_stack(&block)
+ class_eval(&block)
end
end
-
- def validate_stack!(hash)
- errors = []
- context = []
- _inner_validate_stack!(hash, errors, context)
-
- raise Cfer::Util::CferValidationError, errors unless errors.empty?
- end
-
- def _inner_validate_stack!(hash, errors = [], context = [])
- case hash
- when Hash
- hash.each do |k, v|
- _inner_validate_stack!(v, errors, context + [k])
- end
- when Array
- hash.each_index do |i|
- _inner_validate_stack!(hash[i], errors, context + [i])
- end
- when nil
- errors << {
- error: "CloudFormation does not allow nulls in templates",
- context: context
- }
- end
- end
-
- def validation_contextualize(err_ctx)
- err_ctx.inject("") do |err_str, ctx|
- err_str <<
- case ctx
- when String
- ".#{ctx}"
- when Numeric
- "[#{ctx}]"
- end
- end
- end
end
-
end