Module: Enscalator::Helpers

Includes:
Dns, Stack, Wrappers
Included in:
EnAppTemplateDSL, Plugins::ElasticBeanstalk, Plugins::Elasticache, RichTemplateDSL
Defined in:
lib/enscalator/helpers.rb,
lib/enscalator/helpers/dns.rb,
lib/enscalator/helpers/stack.rb,
lib/enscalator/helpers/wrappers.rb,
lib/enscalator/helpers/sub_process.rb

Overview

Collection of helper classes and static methods

Defined Under Namespace

Modules: Dns, Stack, Wrappers Classes: SubProcess

Instance Method Summary collapse

Methods included from Dns

#get_dns_records, #upsert_dns_record

Methods included from Stack

#cfn_create_stack, #generate_parameters, #get_resource, #get_resources, #wait_stack

Methods included from Wrappers

#cfn_client, #cfn_resource, #ec2_client, #route53_client

Instance Method Details

#cfn_call_script(region, dependent_stack_name, script_path, keys, prepend_args: '', append_args: '') ⇒ Object

Deprecated.

this method is no longer used

Call script

Parameters:

  • region (String)

    AWS region identifier

  • dependent_stack_name (String)

    name of the stack current stack depends on

  • script_path (String)

    path to script

  • keys (Array)

    list of keys

  • prepend_args (String) (defaults to: '')

    prepend arguments

  • append_args (String) (defaults to: '')

    append arguments



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/enscalator/helpers/sub_process.rb', line 40

def cfn_call_script(region,
                    dependent_stack_name,
                    script_path,
                    keys,
                    prepend_args: '',
                    append_args: '')
  cfn = cfn_resource(cfn_client(region))
  stack = wait_stack(cfn, dependent_stack_name)
  args = get_resources(stack, keys).join(' ')
  cmd = [script_path, prepend_args, args, append_args]
  begin
    run_cmd(cmd)
  rescue Errno::ENOENT
    puts $ERROR_INFO.to_s
    STDERR.puts cmd
  end
end

#create_ssh_key(key_name, region, force_create: false) ⇒ Object

Create ssh public/private key pair, save private key for current user

Parameters:

  • key_name (String)

    key name

  • region (String)

    aws region

  • force_create (Boolean) (defaults to: false)

    force to create a new ssh key



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/enscalator/helpers.rb', line 62

def create_ssh_key(key_name, region, force_create: false)
  # Ignoring attempts to generate new ssh key when not deploying
  if @options && @options[:expand]
    warn '[Warning] SSH key can be generated only for create or update stack actions'
    return
  end

  client = ec2_client(region)
  aws_profile = if Aws.config.key?(:credentials)
                  creds = Aws.config[:credentials]
                  creds.profile_name if creds.respond_to?(:profile_name)
                end
  target_dir = File.join(Enscalator::ASSETS_DIR, aws_profile ? aws_profile : 'default')
  FileUtils.mkdir_p(target_dir) unless Dir.exist? target_dir
  if !client.describe_key_pairs.key_pairs.collect(&:key_name).include?(key_name) || force_create
    # delete existed ssh key
    client.delete_key_pair(key_name: key_name)

    # create a new ssh key
    key_pair = client.create_key_pair(key_name: key_name)
    STDERR.puts "Created new ssh key with fingerprint: #{key_pair.key_fingerprint}"

    # save private key for current user
    private_key = File.join(target_dir, key_name)
    File.open(private_key, 'w') do |wfile|
      wfile.write(key_pair.key_material)
    end
    STDERR.puts "Saved created key to: #{private_key}"
    File.chmod(0600, private_key)
  else
    key_fingerprint =
      begin
        Aws::EC2::KeyPair.new(key_name, client: client).key_fingerprint
      rescue NotImplementedError
        # TODO: after upgrade of aws-sdk use only Aws::EC2::KeyPairInfo
        Aws::EC2::KeyPairInfo.new(key_name, client: client).key_fingerprint
      end
    STDERR.puts "Found existing ssh key with fingerprint: #{key_fingerprint}"
  end
end

#find_ami(client, owners: ['self'], filters: nil) ⇒ Hash

Find ami images registered

Parameters:

  • client (Aws::EC2::Client)

    instance of AWS EC2 client

Returns:

  • (Hash)

    images satisfying query conditions

Raises:

  • (ArgumentError)

    when client is not provided or its not expected class type



39
40
41
42
43
44
45
46
# File 'lib/enscalator/helpers.rb', line 39

def find_ami(client, owners: ['self'], filters: nil)
  fail ArgumentError, 'must be instance of Aws::EC2::Client' unless client.instance_of?(Aws::EC2::Client)
  query = {}
  query[:dry_run] = false
  query[:owners] = owners if owners.is_a?(Array) && owners.any?
  query[:filters] = filters if filters.is_a?(Array) && filters.any?
  client.describe_images(query)
end

#flatten_hash(input) ⇒ Object

Convert hash with nested values to flat hash

Parameters:

  • input (Hash)

    that should be flatten



115
116
117
118
119
120
121
122
123
124
125
# File 'lib/enscalator/helpers.rb', line 115

def flatten_hash(input)
  input.each_with_object({}) do |(k, v), h|
    if v.is_a?(Hash)
      flatten_hash(v).map do |h_k, h_v|
        h["#{k}.#{h_k}".to_sym] = h_v
      end
    else
      h[k] = v
    end
  end
end

#gen_ssh_key_name(app_name, region, stack_name) ⇒ Object

Generate ssh keyname from app_name, region and stack name

Parameters:

  • app_name (String)

    application name

  • region (String)

    aws region

  • stack_name (String)

    cloudformation stack name



53
54
55
# File 'lib/enscalator/helpers.rb', line 53

def gen_ssh_key_name(app_name, region, stack_name)
  [app_name, region, stack_name].map(&:underscore).join('_')
end

#init_assets_dirString

Initialize enscalator directory

Returns:

  • (String)


19
20
21
# File 'lib/enscalator/helpers.rb', line 19

def init_assets_dir
  FileUtils.mkdir_p(Enscalator::ASSETS_DIR) unless Dir.exist?(Enscalator::ASSETS_DIR)
end

#init_aws_config(region, profile_name: nil) ⇒ Object

Provision Aws.config with custom settings

Parameters:

  • region (String)

    valid aws region

  • profile_name (String) (defaults to: nil)

    aws credentials profile name



26
27
28
29
30
31
32
# File 'lib/enscalator/helpers.rb', line 26

def init_aws_config(region, profile_name: nil)
  fail ArgumentError, 'Unable to proceed without region' if region.blank?
  opts = {}
  opts[:region] = region
  opts[:credentials] = Aws::SharedCredentials.new(profile_name: profile_name) unless profile_name.blank?
  Aws.config.update(opts)
end

#read_user_data(app_name) ⇒ Object

Read user data from file

Parameters:

  • app_name (String)

    application name



106
107
108
109
110
# File 'lib/enscalator/helpers.rb', line 106

def read_user_data(app_name)
  user_data_path = File.join(File.expand_path('..', __FILE__), 'plugins', 'user-data', app_name)
  fail("User data path #{user_data_path} not exists") unless File.exist?(user_data_path)
  File.read(user_data_path)
end

#run_cmd(cmd) ⇒ String

Run command and print captured output to corresponding standard streams

Parameters:

  • cmd (Array)

    command array to be executed

Returns:

  • (String)

    produced output from executed command



62
63
64
65
66
67
68
69
70
# File 'lib/enscalator/helpers/sub_process.rb', line 62

def run_cmd(cmd)
  # use contracts to get rid of exceptions: https://github.com/egonSchiele/contracts.ruby
  fail ArgumentError, "Expected Array, but actually was given #{cmd.class}" unless cmd.is_a?(Array)
  fail ArgumentError, 'Argument cannot be empty' if cmd.empty?
  SubProcess.new(cmd.join(' ')) do |stdout, stderr, _thread|
    STDOUT.puts stdout if stdout
    STDERR.puts stderr if stderr
  end
end