class DockerRailsProxy::Stack::Create

Constants

YML_EXTENSIONS

Attributes

data[RW]
outputs[RW]
parameters[RW]

Public Instance Methods

process() click to toggle source
# File lib/docker_rails_proxy/commands/stack/create.rb, line 63
      def process
        system <<-EOS
          aws cloudformation create-stack \
            --stack-name '#{options[:stack_name]}' \
            --parameters #{parameters.join(' ')} \
            --template-body 'file://#{options[:jsonfile]}' \
            --capabilities 'CAPABILITY_IAM' \
            --profile '#{options[:profile]}'
        EOS
      end

Private Instance Methods

opt_parser() click to toggle source
Calls superclass method
# File lib/docker_rails_proxy/commands/stack/create.rb, line 239
def opt_parser
  super do |opts|
    opts.on('--stack-name STACK_NAME', 'Stack Name') do |stack_name|
      options[:stack_name] = stack_name
    end

    opts.on('--ymlfile YMLFILE', 'Stack YML file') do |ymlfile|
      options[:ymlfile] = build_path(ymlfile)
    end

    opts.on('--parameters A=val,B=val...', Array, 'CF parameters') do |o|
      options[:parameters] = Hash[o.map { |s| s.split('=', 2) }]
    end

    opts.on('--import-outputs-from a,b...', Array, 'CF stack names') do |list|
      options[:import_outputs_from] = list
    end

    opts.on('--wait-for-stack', 'Wait for the stack to be created') do |v|
      options[:wait_for_stack] = v
    end
  end
end
set_defaults() click to toggle source
# File lib/docker_rails_proxy/commands/stack/create.rb, line 234
def set_defaults
  options[:parameters]          ||= {}
  options[:import_outputs_from] ||= []
end
set_outputs() click to toggle source
# File lib/docker_rails_proxy/commands/stack/create.rb, line 76
      def set_outputs
        jq_command = <<-EOS
            .Stacks[]
            | select(
              .StackName as $name
              | "#{options[:import_outputs_from].join(' ')}"
              | split(" ")
              | map(. == $name)
              | index(true) >= 0
            )
            | .Outputs[]
            | [ .OutputKey, .OutputValue ]
            | join("=")
        EOS

        outputs_data = %x(
          aws cloudformation describe-stacks --profile '#{options[:profile]}' \
            | jq '#{jq_command}' | xargs
        ).strip.split(' ')

        outputs_data.each do |string|
          key, value = string.split('=')
          self.outputs[key] = value
        end
      end
set_parameters() click to toggle source
# File lib/docker_rails_proxy/commands/stack/create.rb, line 102
def set_parameters
  puts '-' * 100
  puts "- #{options[:stack_name]} stack parameters"

  (data['Parameters'] || {}).each do |key, attrs|
    parameters[key] = options[:parameters][key]
    parameters[key] ||= outputs[key]

    next if parameters[key].present?

    puts '-' * 100

    options_hash = {}

    while parameters[key].to_s.blank? do
      value = nil

      case attrs['Type']
      when 'AWS::EC2::KeyPair::KeyName'
        key_pairs ||= %x(
          aws ec2 describe-key-pairs --profile '#{options[:profile]}' \
            | jq '.KeyPairs[] | .KeyName' | xargs
        ).strip.split(' ')

        print_options(key_pairs, "Choose an option for #{key} and press [ENTER]")
        parameters[key] = get_option(key_pairs)

      when 'List<AWS::EC2::Subnet::Id>'
        json_data ||= JSON.load %x(
          aws ec2 describe-subnets --profile '#{options[:profile]}'
        ).strip

        json_data['Subnets'].map{|h|
          options_hash[h['SubnetId']] = "#{h['SubnetId']} (#{h['CidrBlock']})"
        }

        # By VPCs
        json_data['Subnets']
          .group_by{|h| h['VpcId'] }
          .map{|vpc_id, subnets_attrs|
            vpc = [vpc_id, subnets_attrs.first['DefaultForAz'] ? '(Default)' : nil].compact.join(' ')
            subnet_ids = subnets_attrs.map{|h| h['SubnetId']}.join(',')
            options_hash[subnet_ids] = "#{vpc}: [#{subnet_ids}]"
          }

        print_options(options_hash.values, "Choose an option for #{key} and press [ENTER] (Use 0,1,2... to select multiple values)")
        parameters[key] = get_option(options_hash.keys, array: true)

      when 'List<AWS::EC2::AvailabilityZone::Name>'
        json_data ||= JSON.load %x(
          aws ec2 describe-availability-zones --profile '#{options[:profile]}'
        ).strip

        json_data['AvailabilityZones'].map{|h|
          options_hash[h['ZoneName']] = "#{h['ZoneName']} (#{h['State']})"
        }

        all_azs = options_hash.keys.join(',')
        options_hash[all_azs] = "All: [#{all_azs}]"

        print_options(options_hash.values, "Choose an option for #{key} and press [ENTER] (Use 0,1,2... to select multiple values)")
        parameters[key] = get_option(options_hash.keys, array: true)

      when 'AWS::EC2::SecurityGroup::Id'
        json_data ||= JSON.load %x(
          aws ec2 describe-security-groups --profile '#{options[:profile]}'
        ).strip

        json_data['SecurityGroups'].map{|h|
          options_hash[h['GroupId']] = [
            h['GroupName'],
            "(#{h['GroupId']})",
            h['Description'].present? ? "(#{h['Description']})" : nil
          ].compact.join(' ')
        }

        print_options(options_hash.values, "Choose an option for #{key} and press [ENTER]")
        parameters[key] = get_option(options_hash.keys)

      when 'AWS::Route53::HostedZone::Id'
        json_data ||= JSON.load %x(
          aws route53 list-hosted-zones --profile '#{options[:profile]}'
        ).strip

        json_data['HostedZones'].map{|h|
          id   = h['Id'].split('/').last
          type = h['Config']['PrivateZone'] ? 'Private' : 'Public'
          options_hash[id] = "#{h['Name']} (#{id}) (#{type})"
        }

        print_options(options_hash.values, "Choose an option for #{key} and press [ENTER]")
        parameters[key] = get_option(options_hash.keys)

      when 'AWS::EC2::VPC::Id'
        json_data ||= JSON.load %x(
          aws ec2 describe-vpcs --profile '#{options[:profile]}'
        ).strip

        json_data['Vpcs'].map{|h|
          name    = (h['Tags'].detect { |t| t['Key'] == 'Name' } || {})['Value']
          options_hash[h['VpcId']] = [
            h['VpcId'], "(#{h['CidrBlock']})", name ? "(#{name})" : nil
          ].compact.join(' ')
        }

        print_options(options_hash.values, "Choose an option for #{key} and press [ENTER]")
        parameters[key] = get_option(options_hash.keys)

      else
        value ||= attrs['Default']

        allowed_values = Array(attrs['AllowedValues'])

        if allowed_values.empty?
          print "Enter #{key} value and press [ENTER] (Default: #{value}): "
          flush_stdin

          parameters[key] = $stdin.gets.chomp || value
          parameters[key] = value if parameters[key].blank?
        else
          print_options(allowed_values, "Choose an option for #{key} and press [ENTER] (Default: #{value})")
          parameters[key] = get_option(allowed_values, default: value)
        end
      end
    end
  end

  self.parameters = parameters.map do |key, value|
    %{'ParameterKey="#{key}",ParameterValue="#{value}",UsePreviousValue=false'}
  end
end