class EbDeployer::CloudFormationProvisioner

Constants

FAILED_STATS
SUCCESS_STATS

Public Class Methods

new(stack_name, cf_driver) click to toggle source
# File lib/eb_deployer/cloud_formation_provisioner.rb, line 9
def initialize(stack_name, cf_driver)
  @stack_name = stack_name
  @cf_driver = cf_driver
  @poller = EventPoller.new(CfEventSource.new(@stack_name, @cf_driver))
end

Public Instance Methods

output(key) click to toggle source
# File lib/eb_deployer/cloud_formation_provisioner.rb, line 49
def output(key)
  @cf_driver.query_output(@stack_name, key)
rescue Aws::CloudFormation::Errors::ValidationError
  raise ResourceNotInReadyState.new("Resource stack not in ready state yet, perhaps you should provision it first?")
end
provision(resources) click to toggle source
# File lib/eb_deployer/cloud_formation_provisioner.rb, line 15
def provision(resources)
  resources = symbolize_keys(resources)
  template = File.read(resources[:template])
  capabilities = resources[:capabilities] || []
  params = resources[:inputs] || resources[:parameters] || {}
  policy = File.read(resources[:policy]) if resources[:policy]
  override_policy = resources[:override_policy] || false
  anchor = nil
  begin
    if stack_exists?
      anchor = @poller.get_anchor
      update_stack(template, params, capabilities, policy, override_policy)
    else
      create_stack(template, params, capabilities, policy)
    end
  rescue Aws::CloudFormation::Errors::ValidationError => e
    if e.message =~ /No updates are to be performed/
      log(e.message)
      return
    else
      raise
    end
  end
  wait_for_stack_op_terminate(anchor)
  log("Resource stack provisioned successfully")
end
transform_outputs(resources) click to toggle source
# File lib/eb_deployer/cloud_formation_provisioner.rb, line 42
def transform_outputs(resources)
  resources = symbolize_keys(resources)
  outputs = resources[:outputs] || {}
  transforms = resources[:transforms] || {}
  transform_output_to_settings(convert_to_transforms(outputs).merge(transforms))
end

Private Instance Methods

convert_to_transforms(outputs) click to toggle source
# File lib/eb_deployer/cloud_formation_provisioner.rb, line 63
def convert_to_transforms(outputs)
  outputs.inject({}) do |memo, (key, value)|
    memo[key] = lambda { |output_value| value.merge('value' => output_value) }
    memo
  end
end
create_stack(template, params, capabilities, policy) click to toggle source
# File lib/eb_deployer/cloud_formation_provisioner.rb, line 85
def create_stack(template, params, capabilities, policy)
  opts = {:disable_rollback => true, :capabilities => capabilities, :parameters => params}
  opts[:stack_policy_body] = policy if policy
  log("Applying stack policy to new resource stack") if policy
  @cf_driver.create_stack(@stack_name, template, opts)
end
log(msg) click to toggle source
# File lib/eb_deployer/cloud_formation_provisioner.rb, line 116
def log(msg)
  puts "[#{Time.now.utc}][cloud_formation_provisioner] #{msg}"
end
log_event(event) click to toggle source
# File lib/eb_deployer/cloud_formation_provisioner.rb, line 111
def log_event(event)
  puts "[#{event.timestamp}][cloud_formation_provisioner] #{event.resource_type}(#{event.logical_resource_id}) #{event.resource_status} \"#{event.resource_status_reason}\""
end
stack_exists?() click to toggle source
# File lib/eb_deployer/cloud_formation_provisioner.rb, line 81
def stack_exists?
  @cf_driver.stack_exists?(@stack_name)
end
symbolize_keys(hash) click to toggle source

todo: remove duplication

# File lib/eb_deployer/cloud_formation_provisioner.rb, line 58
def symbolize_keys(hash)
  hash.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
end
transform_output_to_settings(transforms) click to toggle source
# File lib/eb_deployer/cloud_formation_provisioner.rb, line 92
def transform_output_to_settings(transforms)
  (transforms || []).inject([]) do |settings, pair|
    key, transform = pair
    settings << transform.call(output(key))
    settings
  end.flatten
end
update_stack(template, params, capabilities, policy, override_policy) click to toggle source
# File lib/eb_deployer/cloud_formation_provisioner.rb, line 70
def update_stack(template, params, capabilities, policy, override_policy)
  opts = {:capabilities => capabilities, :parameters => params}
  if (policy)
    opts[:stack_policy_during_update_body] = policy if override_policy
    log("Using temporary stack policy to apply resource stack updates") if override_policy
    opts[:stack_policy_body] = policy unless override_policy
    log("Applying new stack policy to existing resource stack") unless override_policy
  end
  @cf_driver.update_stack(@stack_name, template, opts)
end
wait_for_stack_op_terminate(anchor) click to toggle source
# File lib/eb_deployer/cloud_formation_provisioner.rb, line 100
def wait_for_stack_op_terminate(anchor)
  @poller.poll(anchor) do |event|
    log_event(event)
    if FAILED_STATS.include?(event.resource_status)
      raise "Resource stack update failed!"
    end

    break if event.logical_resource_id == @stack_name && SUCCESS_STATS.include?(event.resource_status)
  end
end