class Stacker::Cli

Public Class Methods

new(*args) click to toggle source
Calls superclass method
# File lib/stacker/cli.rb, line 22
def initialize(*args); super(*args) end

Public Instance Methods

diff(stack_name = nil) click to toggle source
# File lib/stacker/cli.rb, line 56
def diff stack_name = nil
  with_one_or_all(stack_name) do |stack|
    resolve stack
    next unless full_diff stack
  end
end
dump(stack_name = nil) click to toggle source
# File lib/stacker/cli.rb, line 93
def dump stack_name = nil
  with_one_or_all(stack_name) do |stack|
    if stack.exists?
      diff = stack.template.diff :down, :color
      next Stacker.logger.warn 'Stack up-to-date' if diff.length == 0

      Stacker.logger.debug "\n" + diff.indent
      if yes? "Update local template with these changes (y/n)?"
        stack.template.dump
      else
        Stacker.logger.warn 'Pull skipped'
      end
    else
      Stacker.logger.warn "#{stack.name} does not exist"
    end
  end
end
fmt(stack_name = nil) click to toggle source
# File lib/stacker/cli.rb, line 112
def fmt stack_name = nil
  with_one_or_all(stack_name) do |stack|
    if stack.template.exists?
      Stacker.logger.warn 'Formatting...'
      stack.template.write
    else
      Stacker.logger.warn "#{stack.name} does not exist"
    end
  end
end
init(path = nil) click to toggle source
# File lib/stacker/cli.rb, line 25
def init path = nil
  init_project path || options['path']
end
list() click to toggle source
# File lib/stacker/cli.rb, line 30
def list
  Stacker.logger.inspect region.stacks.map(&:name)
end
show(stack_name) click to toggle source
# File lib/stacker/cli.rb, line 35
def show stack_name
  with_one_or_all stack_name do |stack|
    Stacker.logger.inspect(
      'Description'  => stack.description,
      'Status'       => stack.status,
      'Updated'      => stack.last_updated_time || stack.creation_time,
      'Capabilities' => stack.capabilities.remote,
      'Parameters'   => stack.parameters.remote,
      'Outputs'      => stack.outputs
    )
  end
end
status(stack_name = nil) click to toggle source
# File lib/stacker/cli.rb, line 49
def status stack_name = nil
  with_one_or_all(stack_name) do |stack|
    Stacker.logger.debug stack.status.indent
  end
end
update(stack_name = nil) click to toggle source
# File lib/stacker/cli.rb, line 64
def update stack_name = nil
  with_one_or_all(stack_name) do |stack|
    resolve stack

    if stack.exists?
      next unless full_diff stack

      if yes? "Update remote template with these changes (y/n)?"
        time = Benchmark.realtime do
          stack.update allow_destructive: options['allow_destructive']
        end
        Stacker.logger.info formatted_time stack_name, 'updated', time
      else
        Stacker.logger.warn 'Update skipped'
      end
    else
      if yes? "#{stack.name} does not exist. Create it (y/n)?"
        time = Benchmark.realtime do
          stack.create
        end
        Stacker.logger.info formatted_time stack_name, 'created', time
      else
        Stacker.logger.warn 'Create skipped'
      end
    end
  end
end

Private Instance Methods

formatted_time(stack, action, benchmark) click to toggle source
# File lib/stacker/cli.rb, line 149
def formatted_time stack, action, benchmark
  "Stack #{stack} #{action} in: #{(benchmark / 60).floor} min and #{(benchmark % 60).round} seconds."
end
full_diff(stack) click to toggle source
# File lib/stacker/cli.rb, line 153
def full_diff stack
  templ_diff = stack.template.diff :color
  param_diff = stack.parameters.diff :color

  if (templ_diff + param_diff).length == 0
    Stacker.logger.warn 'Stack up-to-date'
    return false
  end

  Stacker.logger.info "\n#{templ_diff.indent}\n" if templ_diff.length > 0
  Stacker.logger.info "\n#{param_diff.indent}\n" if param_diff.length > 0

  true
end
init_project(path) click to toggle source
# File lib/stacker/cli.rb, line 125
    def init_project path
      project_path = File.expand_path path

      %w[ regions templates ].each do |dir|
        directory_path = File.join project_path, dir
        unless Dir.exists? directory_path
          Stacker.logger.debug "Creating directory at #{directory_path}"
          FileUtils.mkdir_p directory_path
        end
      end

      region_path = File.join project_path, 'regions', 'us-east-1.yml'
      unless File.exists? region_path
        Stacker.logger.debug "Creating region file at #{region_path}"
        File.open(region_path, 'w+') { |f| f.print <<-YAML }
defaults:
  parameters:
    CidrBlock: '10.0'
stacks:
  - name: VPC
YAML
      end
    end
region() click to toggle source
# File lib/stacker/cli.rb, line 168
def region
  @region ||= begin
    config_path =  File.join working_path, 'regions', "#{options['region']}.yml"
    if File.exists? config_path
      begin
        config = YAML.load_file(config_path)
      rescue Psych::SyntaxError => err
        Stacker.logger.fatal err.message
        exit 1
      end

      defaults = config.fetch 'defaults', {}
      stacks = config.fetch 'stacks', {}

      Region.new options['region'], defaults, stacks, templates_path
    else
      Stacker.logger.fatal "#{options['region']}.yml does not exist. Please configure or use stacker init"
      exit 1
    end
  end
end
resolve(stack) click to toggle source
# File lib/stacker/cli.rb, line 190
def resolve stack
  return {} if stack.parameters.resolver.dependencies.none?
  Stacker.logger.debug 'Resolving dependencies...'
  stack.parameters.resolved
end
templates_path() click to toggle source
# File lib/stacker/cli.rb, line 222
def templates_path
  File.join working_path, 'templates'
end
with_one_or_all(stack_name = nil) { |stack| ... } click to toggle source
# File lib/stacker/cli.rb, line 196
def with_one_or_all stack_name = nil, &block
  yield_with_stack = proc do |stack|
    Stacker.logger.info "#{stack.name}:"
    yield stack
    Stacker.logger.info ''
  end

  if stack_name
    yield_with_stack.call region.stack(stack_name)
  else
    region.stacks.each(&yield_with_stack)
  end

rescue Stacker::Stack::StackPolicyError => err
  if options['allow_destructive']
    Stacker.logger.fatal err.message
  else
    Stacker.logger.fatal 'Stack update policy prevents replacing or destroying resources.'
    Stacker.logger.warn 'Try running again with \'--allow-destructive\''
  end
  exit 1
rescue Stacker::Stack::Error => err
  Stacker.logger.fatal err.message
  exit 1
end
working_path() click to toggle source
# File lib/stacker/cli.rb, line 226
def working_path
  File.expand_path options['path']
end