awx 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|