class Cfer::Auster::Step

Attributes

count[R]
directory[R]
repo[R]
tag[R]

Public Class Methods

new(repo:, count:, tag:, directory:) click to toggle source
# File lib/cfer/auster/step.rb, line 16
def initialize(repo:, count:, tag:, directory:)
  raise "directory '#{directory}' does not exist." unless File.directory?(directory)
  @repo = repo

  @count = count.to_i
  @tag = tag.dup.freeze

  @directory = directory.dup.freeze

  @cfer_directory = File.join(@directory, "cfer")
  raise "directory '#{@cfer_directory}' does not exist." unless File.directory?(directory)
end

Public Instance Methods

apply(config_set) click to toggle source
# File lib/cfer/auster/step.rb, line 65
def apply(config_set)
  raise "config_set must be a Cfer::Auster::Config." unless config_set.is_a?(Cfer::Auster::Config)

  with_cfer(config_set) do |cfer|
    do_on_create(config_set) unless cfn_stack(config_set).exists?
    do_pre_converge(config_set)

    logger.info "Converging Cfer stack as '#{cfn_stack_name(config_set)}'."
    cfer.converge!(block: true)

    do_post_converge(config_set, cfn_data(config_set))
  end
end
cfn_data(config_set) click to toggle source
# File lib/cfer/auster/step.rb, line 46
def cfn_data(config_set)
  stack = cfn_stack(config_set)

  if !stack.exists?
    nil
  else
    cfn_parameters = stack.parameters.map { |p| [p.parameter_key, p.parameter_value] }.to_h
    cfn_outputs = stack.outputs.map { |o| [o.output_key, o.output_value] }.to_h

    cfn_combined = cfn_parameters.merge(cfn_outputs)

    {
      inputs: cfn_parameters.symbolize_keys,
      outputs: cfn_outputs.symbolize_keys,
      combined: cfn_combined.symbolize_keys
    }
  end
end
cfn_stack(config_set) click to toggle source
# File lib/cfer/auster/step.rb, line 41
def cfn_stack(config_set)
  cfn_client = Aws::CloudFormation::Resource.new(region: config_set.aws_region)
  cfn_client.stack(cfn_stack_name(config_set))
end
cfn_stack_name(config_set) click to toggle source
# File lib/cfer/auster/step.rb, line 37
def cfn_stack_name(config_set)
  "#{config_set.name}-step#{count.to_s.rjust(2, '0')}"
end
destroy(config_set) click to toggle source
# File lib/cfer/auster/step.rb, line 79
def destroy(config_set)
  raise "config_set must be a Cfer::Auster::Config." unless config_set.is_a?(Cfer::Auster::Config)

  stack_name = cfn_stack_name(config_set)
  stack = cfn_stack(config_set)

  if !stack.exists?
    logger.warn "No underlying CloudFormation stack '#{stack_name}' exists."
  else
    logger.info "Deleting CloudFormation stack '#{stack_name}'."
    with_cfer(config_set) do |cfer|
      cfer.destroy!(block: true)
    end

    do_on_destroy(config_set)
  end
end
json(config_set) click to toggle source
# File lib/cfer/auster/step.rb, line 29
def json(config_set)
  raise "config_set must be a Cfer::Auster::Config." unless config_set.is_a?(Cfer::Auster::Config)

  with_cfer(config_set) do |cfer|
    cfer.generate_json
  end
end

Private Instance Methods

converge_cfn(config_set) click to toggle source
# File lib/cfer/auster/step.rb, line 140
def converge_cfn(config_set)
end
do_on_create(config_set) click to toggle source
# File lib/cfer/auster/step.rb, line 99
def do_on_create(config_set)
  run_scripts("on-create", config_set)
end
do_on_destroy(config_set) click to toggle source
# File lib/cfer/auster/step.rb, line 103
def do_on_destroy(config_set)
  run_scripts("on-destroy", config_set)
end
do_post_converge(config_set, cfn_data) click to toggle source
# File lib/cfer/auster/step.rb, line 111
def do_post_converge(config_set, cfn_data)
  run_scripts("post-converge", config_set, cfn_data: cfn_data)
end
do_pre_converge(config_set) click to toggle source
# File lib/cfer/auster/step.rb, line 107
def do_pre_converge(config_set)
  run_scripts("pre-converge", config_set)
end
run_scripts(event_type, config_set, rb_vars = {}) click to toggle source
# File lib/cfer/auster/step.rb, line 143
def run_scripts(event_type, config_set, rb_vars = {})
  logger.info "Running scripts for #{event_type}"
  env_vars = config_set.env_vars_for_shell

  injected_vars = env_vars.merge(rb_vars).merge(
    repo: repo,
    step: self,
    config_set: config_set
  )

  scripts_for_event(event_type).each do |script_name|
    case File.extname(script_name)
    when ".rb"
      logger.debug "Executing #{script_name} in-process."
      Cfer::Auster::ScriptExecutor.new(injected_vars).run(script_name)
    else
      logger.debug "Executing #{script_name} through system()."
      system(env_vars, script_name)

      raise "#{script_name} failed with exit code #{$?.exitstatus}." unless $?.success?
    end
  end
end
scripts_for_event(event_type) click to toggle source
# File lib/cfer/auster/step.rb, line 167
def scripts_for_event(event_type)
  dir = File.join(directory, "#{event_type}.d")

  raise "#{dir} exists, but it isn't a directory.'" \
    if File.exist?(dir) && !File.directory?(dir)

  if !File.directory?(dir)
    []
  else
    Dir[File.join(dir, "*")].select { |f| File.executable?(f) }
  end
end
stack_metadata() click to toggle source
# File lib/cfer/auster/step.rb, line 134
def stack_metadata
  {
    Version: Semantic::Version.new(Cfer::Auster::VERSION).to_h.reject { |k, v| v.nil? }
  }
end
with_cfer(config_set, &block) click to toggle source
# File lib/cfer/auster/step.rb, line 115
def with_cfer(config_set, &block)
  parameters = config_set.data
  validation_errors = repo.param_validator.validate(parameters)

  unless validation_errors.empty?
    logger.error "Config set '#{config_set.full_name}' failed to validate with the following errors:"
    validation_errors.each do |e|
      logger.error " - #{e}"
    end

    raise "Validation of config set '#{config_set.full_name}' failed during Cfer build."
  end

  cfer = CferEvaluator.new(path: @cfer_directory, stack_name: cfn_stack_name(config_set),
                           parameters: parameters, metadata: stack_metadata)

  block.call(cfer)
end