awx 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/aws/aws.rb +9 -0
- data/lib/aws/aws_cli.rb +36 -30
- data/lib/aws/aws_cloudformation.rb +59 -36
- data/lib/aws/aws_outputter.rb +33 -2
- data/lib/aws/aws_profile.rb +116 -0
- data/lib/aws/aws_reports.rb +47 -26
- data/lib/awx.rb +98 -45
- data/lib/core/opt.rb +1 -1
- data/lib/routes/aws_cloudformation_create.rb +447 -192
- data/lib/routes/aws_cloudformation_detect_drift.rb +33 -7
- data/lib/routes/aws_deploy.rb +486 -0
- data/lib/routes/aws_dynamo_db.rb +43 -0
- data/lib/routes/aws_list.rb +17 -11
- data/lib/routes/aws_switch.rb +76 -0
- data/lib/version.rb +1 -1
- data/opt/{yml/aws-reports.yml → awx/reports.yml} +15 -12
- data/opt/config/schema.yml +63 -0
- data/opt/config/template.yml +21 -0
- metadata +25 -23
- data/lib/aws/aws_config.rb +0 -39
- data/lib/core/config.rb +0 -127
- data/lib/core/config_unique.rb +0 -64
- data/lib/routes/aws_lambda.rb +0 -122
- data/lib/routes/setup.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f9b808a6cbb91894ebd76305daa497467f62018a
|
4
|
+
data.tar.gz: 368253cb9c5c47013181e6e570b5ce216bf124b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff832f18916908040ef981c4f6823feeb0c33f7625d61d212036911a064ddfa453da307ab51491ce6e9ddab1f0cdfa8eda24636315bb45f3f9134cb41d43acc0
|
7
|
+
data.tar.gz: 90bef958997255122411c66e1801e8cf0300c85625750d8af6a921f3b3161d9cd97f1199637625cac3449de5176db8a9703dd0d31356eb61e31afb1a55bc569a
|
data/lib/aws/aws.rb
ADDED
data/lib/aws/aws_cli.rb
CHANGED
@@ -65,40 +65,48 @@ module App
|
|
65
65
|
end
|
66
66
|
|
67
67
|
# Create a CloudFormation Stack.
|
68
|
-
# @return
|
69
|
-
def self.cloudformation_stack_create(region, stack_name, s3_url, params: nil, tags: nil, capabilities: [])
|
68
|
+
# @return string (StackID)
|
69
|
+
def self.cloudformation_stack_create(region, stack_name, s3_url, params: nil, tags: nil, capabilities: [], term_protect: false, term_script: false, timeout: nil)
|
70
70
|
params = params.nil? ? '' : " --parameters '#{params.gsub("'", "\\'")}'"
|
71
71
|
tags = tags.nil? ? '' : " --tags '#{tags.gsub("'", "\\'")}'"
|
72
72
|
capabilities = !capabilities.any? ? '' : " --capabilities #{capabilities.join(' ')}"
|
73
|
-
|
74
|
-
|
73
|
+
term_protect = term_protect ? ' --enable-termination-protection' : ' --no-enable-termination-protection'
|
74
|
+
timeout = timeout.nil? ? '' : " --timeout-in-minutes #{timeout}"
|
75
|
+
command = "cloudformation create-stack --stack-name #{stack_name} --template-url #{s3_url}#{params}#{tags}#{capabilities}#{term_protect}#{timeout}"
|
76
|
+
App::AWSOutputter::output_cli_command("aws #{command} --region #{region} --profile #{App::AWSProfile::get_profile_name}")
|
77
|
+
puts
|
78
|
+
stack_send = execute_as_proc("Sending CloudFormation Stack: #{Blufin::Terminal::format_highlight(stack_name)}", command, region, json: true)
|
75
79
|
begin
|
76
80
|
if stack_send.has_key?('StackId')
|
77
|
-
Blufin::Terminal::success('Template was accepted by AWS.', "\x1B[38;5;240mStackId \xe2\x80\x94 \x1B[38;5;40m#{stack_send['StackId']}")
|
78
|
-
|
81
|
+
Blufin::Terminal::success('Template was accepted by AWS.', ["\x1B[38;5;240mStackId \xe2\x80\x94 \x1B[38;5;40m#{stack_send['StackId']}"])
|
82
|
+
stack_url = "https://#{region}.console.aws.amazon.com/cloudformation/home?region=#{region}#/stacks?filter=active&tab=events&stackId=#{URI::encode(stack_send['StackId'])}"
|
83
|
+
system("/usr/bin/open -a '/Applications/Google Chrome.app' '#{stack_url}'")
|
79
84
|
else
|
80
85
|
Blufin::Terminal::error("Key not found in response: #{Blufin::Terminal::format_invalid('StackId')}", stack_send.inspect, true)
|
81
86
|
end
|
82
87
|
rescue
|
83
88
|
Blufin::Terminal::error('Stack was not accepted by AWS.', App::AWSCli::format_cli_error(stack_send), true)
|
84
89
|
end
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
stack_details = execute_as_proc("Getting CloudFormation Stack: #{Blufin::Terminal::format_highlight(stack_name)}", "cloudformation describe-stacks --stack-name #{stack_name}", region, json: true)
|
91
|
-
begin
|
92
|
-
stack_json = JSON.parse(stack_details.to_json)
|
93
|
-
raise RuntimeError, 'Not a Hash' unless stack_json.is_a?(Hash)
|
90
|
+
unless term_script
|
91
|
+
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)
|
92
|
+
if stack_complete.to_s.strip == ''
|
93
|
+
puts
|
94
|
+
puts " \x1B[38;5;40mCREATE_COMPLETE\x1B[0m"
|
94
95
|
puts
|
95
|
-
Blufin::Terminal::
|
96
|
-
|
97
|
-
|
96
|
+
stack_details = execute_as_proc("Getting CloudFormation Stack: #{Blufin::Terminal::format_highlight(stack_name)}", "cloudformation describe-stacks --stack-name #{stack_name}", region, json: true)
|
97
|
+
begin
|
98
|
+
stack_json = JSON.parse(stack_details.to_json)
|
99
|
+
raise RuntimeError, 'Not a Hash' unless stack_json.is_a?(Hash)
|
100
|
+
puts
|
101
|
+
Blufin::Terminal::code_highlight(stack_json.to_yaml, 'yml', 4)
|
102
|
+
rescue
|
103
|
+
Blufin::Terminal::error('It seems you Stack was created (but then something went wrong).', stack_details.inspect, false)
|
104
|
+
end
|
105
|
+
else
|
106
|
+
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)
|
98
107
|
end
|
99
|
-
else
|
100
|
-
Blufin::Terminal::error("Something went wrong. Go to: #{Blufin::Terminal::format_highlight('https://us-west-2.console.aws.amazon.com/cloudformation/home')} to see what happened.", format_cli_error(stack_complete.to_s), true)
|
101
108
|
end
|
109
|
+
stack_send['StackId']
|
102
110
|
end
|
103
111
|
|
104
112
|
# 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).
|
@@ -122,12 +130,10 @@ module App
|
|
122
130
|
raise RuntimeError, 'Must provide region.' if region.nil? || region.strip == ''
|
123
131
|
raise RuntimeError, "Invalid region: #{region}" unless get_regions.include?(region) || region == REGION_SKIP
|
124
132
|
begin
|
125
|
-
region
|
126
|
-
|
127
|
-
region = aws_credentials.region if region.nil?
|
128
|
-
puts "\x1B[38;5;70m$ \x1B[38;5;240maws #{command}#{region}\x1B[0m" if verbose
|
133
|
+
region = region == REGION_SKIP ? '' : " --region #{region}"
|
134
|
+
puts "\x1B[38;5;70m$ \x1B[38;5;240maws #{command}#{region} --profile #{App::AWSProfile::get_profile_name}\x1B[0m" if verbose
|
129
135
|
if json
|
130
|
-
result = `aws #{command}#{region} 2>/tmp/execute-output-aws`
|
136
|
+
result = `aws #{command}#{region} --profile #{App::AWSProfile::get_profile_name} 2>/tmp/execute-output-aws`
|
131
137
|
# If no JSON, simply return the output.
|
132
138
|
return `cat /tmp/execute-output-aws` if result == ''
|
133
139
|
begin
|
@@ -136,12 +142,12 @@ module App
|
|
136
142
|
raise RuntimeError, "JSON Parsing Failed:\n\n#{e.message}"
|
137
143
|
end
|
138
144
|
else
|
139
|
-
result = system("aws #{command}#{region}
|
140
|
-
|
145
|
+
result = system("aws #{command}#{region} --profile #{App::AWSProfile::get_profile_name} 1>/dev/null 2>/tmp/execute-output-aws")
|
146
|
+
`cat /tmp/execute-output-aws` unless result
|
141
147
|
return result
|
142
148
|
end
|
143
149
|
rescue => e
|
144
|
-
Blufin::Terminal::error("Command Failed: #{Blufin::Terminal::format_command("aws #{command}#{region}")}", e.message, true)
|
150
|
+
Blufin::Terminal::error("Command Failed: #{Blufin::Terminal::format_command("aws #{command}#{region} --profile #{App::AWSProfile::get_profile_name}")}", e.message, true)
|
145
151
|
end
|
146
152
|
end
|
147
153
|
|
@@ -149,7 +155,7 @@ module App
|
|
149
155
|
# Set JSON to TRUE if you expect JSON output back, otherwise return value will be boolean (TRUE if successful).
|
150
156
|
# Highly recommended to keep verbose set to FALSE.
|
151
157
|
# @return void
|
152
|
-
def self.execute_as_proc(title, command, region, json: false, verbose: false
|
158
|
+
def self.execute_as_proc(title, command, region, json: false, verbose: false)
|
153
159
|
output = nil
|
154
160
|
threads = []
|
155
161
|
threads << Thread.new {
|
@@ -157,7 +163,7 @@ module App
|
|
157
163
|
}
|
158
164
|
sleep(0.1)
|
159
165
|
puts if verbose
|
160
|
-
Blufin::Terminal::execute_proc("AWS
|
166
|
+
Blufin::Terminal::execute_proc("AWS \xe2\x80\x94 #{title}", Proc.new { threads.each { |thread| thread.join } })
|
161
167
|
output
|
162
168
|
end
|
163
169
|
|
@@ -2,15 +2,10 @@ module App
|
|
2
2
|
|
3
3
|
class AWSCloudFormation
|
4
4
|
|
5
|
-
S3_BUCKET_CLOUDFORMATION = 'blufin-cloudformation-templates'
|
6
|
-
S3_BUCKET_CLOUDFORMATION_REGION = 'us-west-2'
|
7
|
-
PATH_CLOUDFORMATION = 'aws-cloudformation'
|
8
|
-
FILE_CLOUDFORMATION_DEFAULTS = 'cloudformation.rb'
|
9
|
-
|
10
5
|
# Gets the path to the root of the cloudformation templates in blufin-secrets repo.
|
11
6
|
# @return string
|
12
|
-
def self.get_cloudformation_path
|
13
|
-
path =
|
7
|
+
def self.get_cloudformation_path
|
8
|
+
path = App::AWSProfile::get_profile['CloudFormation']['TemplatePath']
|
14
9
|
Blufin::Terminal::error("CloudFormation path not found: #{Blufin::Terminal::format_directory(path)}", 'This probably means directories got renamed or code got changed.', true) unless Blufin::Files::path_exists(path)
|
15
10
|
path
|
16
11
|
end
|
@@ -19,48 +14,76 @@ module App
|
|
19
14
|
# Returns the S3 URL.
|
20
15
|
# @return string
|
21
16
|
def self.upload_cloudformation_template(template_category, template_name, description)
|
22
|
-
source
|
17
|
+
source = "#{get_cloudformation_path}/#{template_category}/#{template_name}/template.yml"
|
18
|
+
tmp_file = "/tmp/aws-cf-upload-#{template_category}-#{template_name}-#{Blufin::Strings::random_string}.yml"
|
23
19
|
raise RuntimeError, "File does not exist: #{source}" unless Blufin::Files::file_exists(source)
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
20
|
+
Blufin::Terminal::execute("cp #{source} #{tmp_file}", text: "Preparing template: \x1B[38;5;240m#{tmp_file}\x1B[0m")
|
21
|
+
# Add description to final YML file.
|
22
|
+
Blufin::Files::write_line_to_file(tmp_file, "Description: \"#{description.gsub('"', '\"')}\"", /AWSTemplateFormatVersion:\s*("|')?[0-9\-]+("|')?/i)
|
23
|
+
# This block of code removes the 2nd description tag.
|
24
|
+
new_lines = []
|
25
|
+
description_found = false
|
26
|
+
parsing_parameters = true
|
27
|
+
Blufin::Files::read_file(tmp_file).each do |line|
|
28
|
+
line = line.gsub("\n", '')
|
29
|
+
if line.strip =~ /^description:/i
|
30
|
+
new_lines << line unless description_found
|
31
|
+
description_found = true
|
31
32
|
else
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
parsing_parameters = true if line.strip =~ /^parameters:$/i
|
34
|
+
if parsing_parameters
|
35
|
+
# AWS Template Anatomy: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html
|
36
|
+
parsing_parameters = false if line.strip =~ /^(Metadata|Mappings|Conditions|Transform|Resources|Outputs)+:$/
|
37
|
+
# This skips all the parameter defaults (as they may contain weird data which won't pass regex validation when initially sent to AWS).
|
38
|
+
next if line.strip =~ /^default:/i && parsing_parameters
|
35
39
|
end
|
36
|
-
|
40
|
+
new_lines << line
|
37
41
|
end
|
38
42
|
end
|
39
|
-
tmp_file
|
40
|
-
|
41
|
-
|
43
|
+
Blufin::Files::write_file(tmp_file, new_lines)
|
44
|
+
template_filename = "#{template_category}-#{template_name}-#{DateTime.now.strftime('%Y%m%d-%H%M%S')}.yml"
|
45
|
+
bucket_path = get_s3_bucket_path
|
46
|
+
bucket_path = bucket_path == '' ? '' : "#{bucket_path}/"
|
47
|
+
App::AWSCli::s3_upload(tmp_file, App::AWSProfile::get_profile['CloudFormation']['S3Bucket'], "#{bucket_path}#{template_filename}")
|
48
|
+
# Return the S3 bucket URL.
|
49
|
+
"#{get_s3_bucket_url}/#{template_filename}"
|
42
50
|
end
|
43
51
|
|
44
|
-
#
|
52
|
+
# Returns S3 bucket URL based on config parameters.
|
45
53
|
# @return string
|
46
|
-
def self.
|
47
|
-
|
54
|
+
def self.get_s3_bucket_url
|
55
|
+
bucket_path = get_s3_bucket_path
|
56
|
+
bucket_path = bucket_path == '' ? '' : "/#{bucket_path}"
|
57
|
+
"https://#{App::AWSProfile::get_profile['CloudFormation']['S3Bucket']}.s3-#{App::AWSProfile::get_profile['CloudFormation']['S3BucketRegion']}.amazonaws.com#{bucket_path}"
|
48
58
|
end
|
49
59
|
|
50
|
-
#
|
60
|
+
# Returns the S3 bucket path based on config parameters.
|
51
61
|
# @return string
|
52
|
-
def self.
|
53
|
-
|
62
|
+
def self.get_s3_bucket_path
|
63
|
+
bucket_path = App::AWSProfile::get_profile['CloudFormation']['S3BucketPath']
|
64
|
+
bucket_path.nil? || bucket_path.to_s.strip == '' ? '' : bucket_path
|
54
65
|
end
|
55
66
|
|
56
|
-
#
|
57
|
-
# @return
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
67
|
+
# Returns an array of cloudformation stack-names.
|
68
|
+
# @return Array of Hashes
|
69
|
+
def self.get_stacks
|
70
|
+
results = []
|
71
|
+
json = Blufin::Terminal::execute('awx l -r CloudFormationStacks -j', capture: true, text: "AWS \xe2\x80\x94 Getting CloudFormation Stacks...")
|
72
|
+
begin
|
73
|
+
data = JSON.parse(json)
|
74
|
+
rescue => e
|
75
|
+
puts
|
76
|
+
puts json
|
77
|
+
Blufin::Terminal::error('Failed to parse AWS response JSON.', e.message)
|
78
|
+
end
|
79
|
+
data.each do |stack|
|
80
|
+
results << {
|
81
|
+
:name => stack['StackName'],
|
82
|
+
:region => stack['region']
|
83
|
+
}
|
84
|
+
end
|
85
|
+
results.sort_by! { |hsh| hsh[:name] }
|
86
|
+
results
|
64
87
|
end
|
65
88
|
|
66
89
|
end
|
data/lib/aws/aws_outputter.rb
CHANGED
@@ -91,7 +91,7 @@ module App
|
|
91
91
|
column('Max-L', :width => column_short, :color => HEADER_COLOR)
|
92
92
|
column('Min-V', :width => column_short, :color => HEADER_COLOR)
|
93
93
|
column('Max-V', :width => column_short, :color => HEADER_COLOR)
|
94
|
-
column('Cached Value(s)', :width => remaining, :color => HEADER_COLOR)
|
94
|
+
column('Cached/Default Value(s)', :width => remaining, :color => HEADER_COLOR)
|
95
95
|
column('', :width => 2, :color => HEADER_COLOR)
|
96
96
|
end
|
97
97
|
row do
|
@@ -109,7 +109,13 @@ module App
|
|
109
109
|
mav = data[:max_value]
|
110
110
|
cop = 'light-green'
|
111
111
|
cop = 'purple' if data[:type_internal] == :autocomplete
|
112
|
-
cop = '
|
112
|
+
cop = 'light-grey' if data[:type_internal] == :system || [
|
113
|
+
AppCommand::AWSCloudFormationCreate::OPTION_STACK_NAME,
|
114
|
+
AppCommand::AWSCloudFormationCreate::OPTION_PROJECT_ID,
|
115
|
+
AppCommand::AWSCloudFormationCreate::OPTION_DESCRIPTION,
|
116
|
+
AppCommand::AWSCloudFormationCreate::OPTION_TERM_PROTECT,
|
117
|
+
AppCommand::AWSCloudFormationCreate::OPTION_TIMEOUT
|
118
|
+
].include?(data[:parameter])
|
113
119
|
# In case you want to change color in future, currently this is redundant.
|
114
120
|
cod = data[:type_internal] == :system ? 'default' : 'default'
|
115
121
|
cot = data[:type_internal] == :system ? 'default' : 'default'
|
@@ -152,10 +158,15 @@ module App
|
|
152
158
|
# @return void
|
153
159
|
def self.get_formatter(key = nil, resource: nil, color: 'default')
|
154
160
|
formatters = {
|
161
|
+
'cloudformation-stack' => Proc.new { |n|
|
162
|
+
[n.gsub(/^arn:aws:cloudformation:[a-z]{2}-[a-z]{2,12}-\d+\D?:\d{10,14}:stack\//, ''), color]
|
163
|
+
},
|
155
164
|
'cloudfront-status' => Proc.new { |n|
|
156
165
|
case n
|
157
166
|
when 'Deployed'
|
158
167
|
color = 'green'
|
168
|
+
when 'InProgress'
|
169
|
+
color = 'orange'
|
159
170
|
else
|
160
171
|
Blufin::Terminal::output("Add something to aws_outputter switch statement for: #{n}", Blufin::Terminal::MSG_TODO)
|
161
172
|
color = 'default'
|
@@ -188,6 +199,7 @@ module App
|
|
188
199
|
color = 'dark-grey'
|
189
200
|
when 'terminated'
|
190
201
|
color = 'red'
|
202
|
+
|
191
203
|
else
|
192
204
|
Blufin::Terminal::output("Add something to aws_outputter switch statement for: #{n}", Blufin::Terminal::MSG_TODO)
|
193
205
|
color = 'default'
|
@@ -203,11 +215,15 @@ module App
|
|
203
215
|
region = n.ljust(10, ' ')
|
204
216
|
[region, region_color]
|
205
217
|
},
|
218
|
+
'route-53-domain-name' => Proc.new { |n|
|
219
|
+
[n.gsub(/\.$/, ''), color]
|
220
|
+
},
|
206
221
|
'route-53-hosted-zone-id' => Proc.new { |n|
|
207
222
|
zone_color = color
|
208
223
|
ns = n.split('/')
|
209
224
|
[ns[ns.length - 1], zone_color]
|
210
225
|
},
|
226
|
+
|
211
227
|
}
|
212
228
|
raise RuntimeError, "Key not found: #{key}" unless key.nil? || formatters.has_key?(key)
|
213
229
|
return formatters.keys if key.nil?
|
@@ -242,6 +258,21 @@ module App
|
|
242
258
|
(width == '*') ? wildcard_width : width
|
243
259
|
end
|
244
260
|
|
261
|
+
# Standardized way of outputting a command.
|
262
|
+
# @return void
|
263
|
+
def self.output_cli_command(command, path = nil)
|
264
|
+
puts " \x1B[38;5;70m$ \x1B[38;5;240m#{command}\x1B[0m" if path.nil?
|
265
|
+
puts " \x1B[38;5;70m$ \x1B[38;5;240m#{command} [\x1B[38;5;246m#{path}\x1B[240m]\x1B[0m" unless path.nil?
|
266
|
+
end
|
267
|
+
|
268
|
+
# Standardized way of rendering selection output.
|
269
|
+
# @return string
|
270
|
+
def self.render_selection(primary, secondary = nil, tertiary = nil)
|
271
|
+
return "#{Blufin::Terminal::format_action(primary)} \x1B[38;5;240m[#{Blufin::Terminal::format_highlight(secondary)}\x1B[38;5;240m]\x1B[38;5;240m[#{Blufin::Terminal::format_highlight(tertiary)}\x1B[38;5;240m]" if !tertiary.nil? && !secondary.nil?
|
272
|
+
return "#{Blufin::Terminal::format_action(primary)} \x1B[38;5;240m[#{Blufin::Terminal::format_highlight(secondary)}\x1B[38;5;240m]" unless secondary.nil?
|
273
|
+
return "#{Blufin::Terminal::format_action(primary)}" if secondary.nil?
|
274
|
+
end
|
275
|
+
|
245
276
|
end
|
246
277
|
|
247
278
|
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module App
|
2
|
+
|
3
|
+
class AWSProfile
|
4
|
+
|
5
|
+
@@profiles = nil
|
6
|
+
@@profile = nil
|
7
|
+
@@credentials = nil
|
8
|
+
|
9
|
+
FILE_AWS_CONFIG = File.expand_path('~/.aws/config')
|
10
|
+
FILE_AWS_CREDENTIALS = File.expand_path('~/.aws/credentials')
|
11
|
+
PROFILE_DEFAULT = 'DefaultProfile'
|
12
|
+
PROFILE = 'Profile'
|
13
|
+
PROFILES = 'Profiles'
|
14
|
+
CLOUDFORMATION = 'CloudFormation'
|
15
|
+
|
16
|
+
# Reads the config data and decides what profile to use.
|
17
|
+
# @return void
|
18
|
+
def self.init(config_data)
|
19
|
+
|
20
|
+
raise RuntimeError, 'Cannot run App::AWSProfile::init more than once.' unless @@profiles.nil? && @@profile.nil? && @@credentials.nil?
|
21
|
+
|
22
|
+
@@profiles = {}
|
23
|
+
@@profile = {}
|
24
|
+
|
25
|
+
first_key = nil
|
26
|
+
|
27
|
+
# Put all the profiles in a global Hash.
|
28
|
+
config_data[PROFILES].each do |profile|
|
29
|
+
first_key = profile[PROFILE] if first_key.nil?
|
30
|
+
@@profiles[profile[PROFILE]] = profile
|
31
|
+
end
|
32
|
+
|
33
|
+
if @@profiles.length == 1
|
34
|
+
@@profile = @@profiles[first_key]
|
35
|
+
elsif @@profiles.length > 1
|
36
|
+
if config_data[PROFILE_DEFAULT].nil?
|
37
|
+
Blufin::Terminal::error('No default profile found.', "When more than 1 profile is specified, you must also specify a #{Blufin::Terminal::format_highlight('DefaultProfile:')}", true)
|
38
|
+
elsif !@@profiles.keys.include?(config_data[PROFILE_DEFAULT])
|
39
|
+
Blufin::Terminal::error("Invalid profile: #{Blufin::Terminal::format_invalid(config_data[PROFILE_DEFAULT])}. Available profiles are:", @@profiles.keys, true)
|
40
|
+
else
|
41
|
+
@@profile = @@profiles[config_data[PROFILE_DEFAULT]]
|
42
|
+
end
|
43
|
+
else
|
44
|
+
raise RuntimeError, 'No profiles found.'
|
45
|
+
end
|
46
|
+
|
47
|
+
errors = []
|
48
|
+
|
49
|
+
# Validate CloudFormation data (if exists)
|
50
|
+
if @@profile.has_key?(CLOUDFORMATION)
|
51
|
+
cloudformation_template_path = @@profile[CLOUDFORMATION]['TemplatePath']
|
52
|
+
s3_region = @@profile[CLOUDFORMATION]['S3BucketRegion']
|
53
|
+
default_regions = @@profile[CLOUDFORMATION]['Defaults']['Regions']
|
54
|
+
errors << "Path not found: #{Blufin::Terminal::format_invalid(cloudformation_template_path)}" unless Blufin::Files::path_exists(cloudformation_template_path)
|
55
|
+
errors << "Invalid region: #{Blufin::Terminal::format_invalid(s3_region)}" unless App::AWS::VALID_REGIONS.include?(s3_region)
|
56
|
+
errors << "Need atleast 1 default region for: #{Blufin::Terminal::format_invalid('Profiles[].CloudFormation.Defaults.Regions')}" if default_regions.nil? || !default_regions.any?
|
57
|
+
default_regions.each do |default_region|
|
58
|
+
errors << "Invalid region: #{Blufin::Terminal::format_invalid(default_region)}" unless App::AWS::VALID_REGIONS.include?(default_region)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Check the credentials exist.
|
63
|
+
if Blufin::Files::file_exists(FILE_AWS_CREDENTIALS)
|
64
|
+
@@aws_credentials = App::AWSCredentials.new
|
65
|
+
profile = @@profile[PROFILE]
|
66
|
+
config = Blufin::Files::file_exists(FILE_AWS_CONFIG) ? ParseConfig.new(FILE_AWS_CONFIG) : nil
|
67
|
+
credentials = ParseConfig.new(FILE_AWS_CREDENTIALS)
|
68
|
+
unless credentials.params[profile].nil?
|
69
|
+
# Currently not used/required (but here just in case).
|
70
|
+
unless config.nil? || config.params[profile].nil?
|
71
|
+
@@aws_credentials.region = config.params[profile]['region'] unless config.params[profile]['region'].nil?
|
72
|
+
@@aws_credentials.output = config.params[profile]['output'] unless config.params[profile]['output'].nil?
|
73
|
+
|
74
|
+
end
|
75
|
+
@@aws_credentials.aws_key = credentials.params[profile]['aws_access_key_id'] unless credentials.params[profile]['aws_access_key_id'].nil?
|
76
|
+
@@aws_credentials.aws_secret = credentials.params[profile]['aws_secret_access_key'] unless credentials.params[profile]['aws_secret_access_key'].nil?
|
77
|
+
end
|
78
|
+
errors << "aws-cli error. Cannot find #{profile}: #{Blufin::Terminal::format_invalid('aws_access_key_id')} in: #{Blufin::Terminal::format_directory(FILE_AWS_CREDENTIALS)}" if @@aws_credentials.aws_key.nil?
|
79
|
+
errors << "aws-cli error. Cannot find #{profile}: #{Blufin::Terminal::format_invalid('aws_secret_access_key')} in: #{Blufin::Terminal::format_directory(FILE_AWS_CREDENTIALS)}" if @@aws_credentials.aws_secret.nil?
|
80
|
+
else
|
81
|
+
errors << "aws-cli error. Cannot find file: #{Blufin::Terminal::format_invalid(FILE_AWS_CREDENTIALS)}"
|
82
|
+
end
|
83
|
+
|
84
|
+
# If anything is wrong, output error(s).
|
85
|
+
Blufin::Config::invalid_configuration(App::GEM_NAME, errors) if errors.any?
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
# Gets the active profile.
|
90
|
+
# @return Hash
|
91
|
+
def self.get_profile
|
92
|
+
@@profile
|
93
|
+
end
|
94
|
+
|
95
|
+
# Convenience method to just get the profile name.
|
96
|
+
# @return string
|
97
|
+
def self.get_profile_name
|
98
|
+
@@profile[PROFILE]
|
99
|
+
end
|
100
|
+
|
101
|
+
# Returns an Array of all available profile names (not the entire profile).
|
102
|
+
# @return Array
|
103
|
+
def self.get_profile_names
|
104
|
+
@@profiles.keys
|
105
|
+
end
|
106
|
+
|
107
|
+
# Gets AWS credentials from ~/.aws directory for given profile.
|
108
|
+
# If credentials don't exist (or are missing information) -- nil is returned.
|
109
|
+
# @return App::AWSCredentials
|
110
|
+
def self.get_credentials
|
111
|
+
@@aws_credentials
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|