Class: App::AWSCli

Inherits:
Object
  • Object
show all
Defined in:
lib/aws/aws_cli.rb

Constant Summary collapse

BLANK =
'BLANK'
REGION_SKIP =

Must provide this to skip region (so it can’t easily be done accidentally)

'E+e^P7p?KYWvc~R/'
@@valid_regions =
BLANK
@@ec2_instances =
{}
@@ec2_volumes =
{}
@@ec2_security_groups =
{}
@@s3_buckets =
{}
@@rds_mysql_instances =
{}
@@sqs_queues =
{}
@@cloudformation_stacks =
{}

Class Method Summary collapse

Class Method Details

.cloudformation_stack_create(region, stack_name, s3_url, params: nil, tags: nil, capabilities: [], term_protect: false, term_script: false, timeout: nil, open_chrome: true) ⇒ Object

Create a CloudFormation Stack.



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
102
103
104
105
106
107
108
109
110
# File 'lib/aws/aws_cli.rb', line 69

def self.cloudformation_stack_create(region, stack_name, s3_url, params: nil, tags: nil, capabilities: [], term_protect: false, term_script: false, timeout: nil, open_chrome: true)
    params       = params.nil? ? '' : " --parameters '#{params.gsub("'", "\\'")}'"
    tags         = tags.nil? ? '' : " --tags '#{tags.gsub("'", "\\'")}'"
    capabilities = !capabilities.any? ? '' : " --capabilities #{capabilities.join(' ')}"
    term_protect = term_protect ? ' --enable-termination-protection' : ' --no-enable-termination-protection'
    timeout      = timeout.nil? ? '' : " --timeout-in-minutes #{timeout}"
    command      = "cloudformation create-stack --stack-name #{stack_name} --template-url #{s3_url}#{params}#{tags}#{capabilities}#{term_protect}#{timeout}"
    App::AWSOutputter::output_cli_command("aws #{command} --region #{region}#{App::AWS::get_profile_for_cli}")
    puts
    stack_send = execute_as_proc("Sending CloudFormation Stack: #{Blufin::Terminal::format_highlight(stack_name)}", command, region, json: true)
    begin
        if stack_send.has_key?('StackId')
            Blufin::Terminal::success('Template was accepted by AWS.', ["\x1B[38;5;240mStackId \xe2\x80\x94 \x1B[38;5;40m#{stack_send['StackId']}"])
            stack_url = "https://#{region}.console.aws.amazon.com/cloudformation/home?region=#{region}#/stacks?filter=active&tab=events&stackId=#{URI::encode(stack_send['StackId'])}"
            system("/usr/bin/open -a '/Applications/Google Chrome.app' '#{stack_url}'") if open_chrome
        else
            Blufin::Terminal::error("Key not found in response: #{Blufin::Terminal::format_invalid('StackId')}", stack_send.inspect, true)
        end
    rescue
        Blufin::Terminal::error('Stack was not accepted by AWS.', App::AWSCli::format_cli_error(stack_send), true)
    end
    unless term_script
        stack_complete = execute_as_proc("Creating CloudFormation Stack: #{Blufin::Terminal::format_highlight(stack_name)}", "cloudformation wait stack-create-complete --stack-name #{stack_name}", region, json: true)
        if stack_complete.to_s.strip == ''
            puts
            puts "    \x1B[38;5;40mCREATE_COMPLETE\x1B[0m"
            puts
            stack_details = execute_as_proc("Getting CloudFormation Stack: #{Blufin::Terminal::format_highlight(stack_name)}", "cloudformation describe-stacks --stack-name #{stack_name}", region, json: true)
            begin
                stack_json = JSON.parse(stack_details.to_json)
                raise RuntimeError, 'Not a Hash' unless stack_json.is_a?(Hash)
                puts
                Blufin::Terminal::code_highlight(stack_json.to_yaml, 'yml', 4)
            rescue
                Blufin::Terminal::error('It seems you Stack was created (but then something went wrong).', stack_details.inspect, false)
            end
        else
            Blufin::Terminal::error("Something went wrong. Go to: #{Blufin::Terminal::format_highlight("https://#{region}.console.aws.amazon.com/cloudformation/home")} to see what happened.", format_cli_error(stack_complete.to_s), true)
        end
    end
    stack_send['StackId']
end

.cloudformation_stack_validate(region, s3_url) ⇒ Object

Validate a CloudFormation Stack.

Returns:

  • Hash



62
63
64
65
# File 'lib/aws/aws_cli.rb', line 62

def self.cloudformation_stack_validate(region, s3_url)
    command = "cloudformation validate-template --template-url #{s3_url}"
    execute_as_proc('Validating Template', command, region, json: true)
end

.format_cli_error(error_string) ⇒ Object

Use this when a common such as “aws do-something” returns an error (such as: Stack [cognito-public-pool-go-eat-local-albert] already exists). This removes the generic error prefix and preceding blank line.

Returns:

  • string



115
116
117
118
119
120
121
122
123
# File 'lib/aws/aws_cli.rb', line 115

def self.format_cli_error(error_string)
    error = ''
    error_string.split("\n").each do |line|
        if line.strip.length > 0
            error = "#{error}#{line.gsub(/(An error occurred \(.*\) when calling the [A-Za-z0-9]+ operation:)\s*/, '')}"
        end
    end
    error
end

.get_regionsObject

Returns void.

Returns:

  • void



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/aws/aws_cli.rb', line 21

def self.get_regions

    # TODO - Remove the following line(s) and add actual caching...

    @@valid_regions = %w(ap-south-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-2 ap-northeast-1 sa-east-1 ca-central-1 ap-southeast-1 ap-southeast-2 eu-central-1 us-east-1 us-east-2 us-west-1 us-west-2)
    @@valid_regions = %w(us-east-1 us-east-2 us-west-1 us-west-2)

    if @@valid_regions == BLANK
        @@valid_regions = []
        regions         = execute('ec2 describe-regions', nil)
        regions['Regions'].each do |region|
            @@valid_regions << region['RegionName']
        end
    end

    @@valid_regions
end

.s3_sync(source, bucket_name, bucket_path, delete: false) ⇒ Object

Perform S3 sync.

Returns:

  • Array



50
51
52
53
54
55
56
57
58
# File 'lib/aws/aws_cli.rb', line 50

def self.s3_sync(source, bucket_name, bucket_path, delete: false)

    # TODO - This was written but is untested! Remove this comment once this method has been used successfully.

    Blufin::Terminal::error("Source does not exist: #{source}", true) unless Blufin::Files::path_exists(source) || Blufin::Files::file_exists(source)
    source  = File.expand_path(source)
    command = "s3 sync #{source} s3://#{bucket_name}/#{bucket_path}#{delete ? ' --delete' : ''}"
    execute(command, REGION_SKIP, json: false)
end

.s3_upload(source, bucket_name, bucket_path) ⇒ Object

Perform S3 upload. Will overwrite existing file (if exists)!

Returns:

  • Array



41
42
43
44
45
46
# File 'lib/aws/aws_cli.rb', line 41

def self.s3_upload(source, bucket_name, bucket_path)
    Blufin::Terminal::error("Source does not exist: #{source}", true) unless Blufin::Files::path_exists(source) || Blufin::Files::file_exists(source)
    source  = File.expand_path(source)
    command = "s3 cp #{source} s3://#{bucket_name}/#{bucket_path}"
    execute_as_proc("Uploading Template to S3: #{Blufin::Terminal::format_highlight("s3://#{bucket_name}/#{bucket_path}")}", command, REGION_SKIP)
end