awx 0.4.2 → 0.5.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_cloudformation.rb +6 -5
- data/lib/aws/aws_profile.rb +3 -2
- data/lib/awx.rb +3 -2
- data/lib/routes/aws_cloudformation_create.rb +95 -49
- data/lib/version.rb +1 -1
- data/opt/config/schema.yml +29 -6
- data/opt/config/template.yml +12 -4
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54e617e3d455c0aa8d4f5d3dce0573cbb8ed86c3
|
4
|
+
data.tar.gz: 2039dffe2e3f9cc5e391fca408d726313280fcc7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d050dcd91c40b5fb9fc39f38bba5854fe6790cc9cf77f262ab656bb0d8e666d63d0bafcd567a84a75c7142501e0e730bb559dfb5e48d73687d3528ebb02af699
|
7
|
+
data.tar.gz: 0cb3de40b28af605e5bbf33124a8c348c38441a95faa9a8fa90b81eafb8619fdf91d2ff6d8b74c0adadc71ae55739e6c50f70ba9d6ea35710f47406cecb3c1dc
|
@@ -5,7 +5,8 @@ module App
|
|
5
5
|
# Gets the path to the root of the cloudformation templates in blufin-secrets repo.
|
6
6
|
# @return string
|
7
7
|
def self.get_cloudformation_path
|
8
|
-
|
8
|
+
# TODO AWX PROFILE - Must support S3.
|
9
|
+
path = App::AWSProfile::get_profile['CloudFormation']['Templates']['Local']['Path']
|
9
10
|
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)
|
10
11
|
path
|
11
12
|
end
|
@@ -26,7 +27,7 @@ module App
|
|
26
27
|
parsing_parameters = true
|
27
28
|
Blufin::Files::read_file(tmp_file).each do |line|
|
28
29
|
line = line.gsub("\n", '')
|
29
|
-
if line.strip =~ /^description:/i
|
30
|
+
if line.strip =~ /^description:/i && !description_found
|
30
31
|
new_lines << line unless description_found
|
31
32
|
description_found = true
|
32
33
|
else
|
@@ -44,7 +45,7 @@ module App
|
|
44
45
|
template_filename = "#{template_category}-#{template_name}-#{DateTime.now.strftime('%Y%m%d-%H%M%S')}.yml"
|
45
46
|
bucket_path = get_s3_bucket_path
|
46
47
|
bucket_path = bucket_path == '' ? '' : "#{bucket_path}/"
|
47
|
-
App::AWSCli::s3_upload(tmp_file, App::AWSProfile::get_profile['CloudFormation']['S3Bucket'], "#{bucket_path}#{template_filename}")
|
48
|
+
App::AWSCli::s3_upload(tmp_file, App::AWSProfile::get_profile['CloudFormation']['Uploads']['S3Bucket']['Name'], "#{bucket_path}#{template_filename}")
|
48
49
|
# Return the S3 bucket URL.
|
49
50
|
"#{get_s3_bucket_url}/#{template_filename}"
|
50
51
|
end
|
@@ -54,13 +55,13 @@ module App
|
|
54
55
|
def self.get_s3_bucket_url
|
55
56
|
bucket_path = get_s3_bucket_path
|
56
57
|
bucket_path = bucket_path == '' ? '' : "/#{bucket_path}"
|
57
|
-
"https://#{App::AWSProfile::get_profile['CloudFormation']['S3Bucket']}.s3-#{App::AWSProfile::get_profile['CloudFormation']['
|
58
|
+
"https://#{App::AWSProfile::get_profile['CloudFormation']['Uploads']['S3Bucket']['Name']}.s3-#{App::AWSProfile::get_profile['CloudFormation']['Uploads']['S3Bucket']['Region']}.amazonaws.com#{bucket_path}"
|
58
59
|
end
|
59
60
|
|
60
61
|
# Returns the S3 bucket path based on config parameters.
|
61
62
|
# @return string
|
62
63
|
def self.get_s3_bucket_path
|
63
|
-
bucket_path = App::AWSProfile::get_profile['CloudFormation']['
|
64
|
+
bucket_path = App::AWSProfile::get_profile['CloudFormation']['Uploads']['S3Bucket']['Path']
|
64
65
|
bucket_path.nil? || bucket_path.to_s.strip == '' ? '' : bucket_path
|
65
66
|
end
|
66
67
|
|
data/lib/aws/aws_profile.rb
CHANGED
@@ -48,8 +48,9 @@ module App
|
|
48
48
|
|
49
49
|
# Validate CloudFormation data (if exists)
|
50
50
|
if @@profile.has_key?(CLOUDFORMATION)
|
51
|
-
|
52
|
-
|
51
|
+
# TODO AWX PROFILE - Must support S3.
|
52
|
+
cloudformation_template_path = @@profile[CLOUDFORMATION]['Templates']['Local']['Path']
|
53
|
+
s3_region = @@profile[CLOUDFORMATION]['Uploads']['S3Bucket']['Region']
|
53
54
|
default_regions = @@profile[CLOUDFORMATION]['Defaults']['Regions']
|
54
55
|
errors << "Path not found: #{Blufin::Terminal::format_invalid(cloudformation_template_path)}" unless Blufin::Files::path_exists(cloudformation_template_path)
|
55
56
|
errors << "Invalid region: #{Blufin::Terminal::format_invalid(s3_region)}" unless App::AWS::VALID_REGIONS.include?(s3_region)
|
data/lib/awx.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
+
require 'blufin-lib'
|
1
2
|
require 'columnist'
|
2
3
|
require 'convoy'
|
3
4
|
require 'yaml'
|
4
|
-
require 'blufin-lib'
|
5
5
|
|
6
6
|
require_relative 'version'
|
7
7
|
require 'core/opt'
|
@@ -52,7 +52,8 @@ TEMPLATE
|
|
52
52
|
awx_cloudformation.command :create, :aliases => [:c] do |awx_cloudformation_create|
|
53
53
|
awx_cloudformation_create.summary 'Create stack'
|
54
54
|
awx_cloudformation_create.options do |opts|
|
55
|
-
|
55
|
+
# TODO AWX PROFILE - Must support S3.
|
56
|
+
if Blufin::Files::path_exists("#{File.expand_path(App::AWSProfile::get_profile['CloudFormation']['Templates']['Local']['Path'])}/test")
|
56
57
|
opts.opt :test, 'Run through test-template.', :short => '-t', :long => '--test', :type => :boolean
|
57
58
|
end
|
58
59
|
opts.opt :test, "Re-run previous with cached values (if exists) \xe2\x80\x94 #{Blufin::Terminal::format_invalid('@NotImplemented')}", :short => '-R', :long => '--re-run', :type => :boolean
|
@@ -29,6 +29,8 @@ module AppCommand
|
|
29
29
|
SPACER = '<<--Spacer-->>'
|
30
30
|
CAPABILITIES = 'Capabilities'
|
31
31
|
RETURN_VALUE = 'PjNkHK33EopWxCpzOQfuku3la'
|
32
|
+
EC2_USER_DATA = 'EC2UserData'
|
33
|
+
EC2_USER_DATA_FILE = 'cloud-config.yml'
|
32
34
|
|
33
35
|
def execute
|
34
36
|
|
@@ -71,6 +73,9 @@ module AppCommand
|
|
71
73
|
|
72
74
|
def opts_validate
|
73
75
|
|
76
|
+
# Windows is currently not supported, so bomb-out.
|
77
|
+
Blufin::Tools::os_not_supported([Blufin::Tools::OS_WINDOWS])
|
78
|
+
|
74
79
|
# If Terminal window is smaller than 230, bomb-out.
|
75
80
|
terminal_width_actual = Blufin::Terminal::get_terminal_width
|
76
81
|
terminal_required_width = 227
|
@@ -94,6 +99,7 @@ module AppCommand
|
|
94
99
|
ps = path_inner.split('/')
|
95
100
|
template = ps[ps.length - 1]
|
96
101
|
template_name = "#{category}/#{template}"
|
102
|
+
template_path = nil
|
97
103
|
file_cloudformation = nil
|
98
104
|
file_ruby = nil
|
99
105
|
method_before_create = nil
|
@@ -110,10 +116,12 @@ module AppCommand
|
|
110
116
|
single_serve = false
|
111
117
|
deployment_stack = nil
|
112
118
|
parameters = {}
|
119
|
+
parameters_no_sort = nil
|
113
120
|
warnings_count = @warnings.length
|
114
121
|
raise RuntimeError, "Template name must consist of [service]/[service-description] with exactly one slash, instead got: #{template_name}" if template_name.strip.split('/').length != 2
|
115
122
|
Blufin::Files::get_files_in_dir(path_inner).each do |file|
|
116
|
-
filename
|
123
|
+
filename = Blufin::Files::extract_file_name(file)
|
124
|
+
template_path = Blufin::Files::extract_path_name(file)
|
117
125
|
if filename == 'template.yml'
|
118
126
|
begin
|
119
127
|
yml_data = YAML.load_file(File.expand_path(file))
|
@@ -126,7 +134,7 @@ module AppCommand
|
|
126
134
|
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 AWSTemplateFormatVersion: '2010-09-09' is missing." unless yml_data.has_key?('AWSTemplateFormatVersion')
|
127
135
|
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 This template either has no resources, invalid resources, or something else wrong with the resources." if !yml_data.has_key?('Resources') || yml_data['Resources'].nil? || !yml_data['Resources'].is_a?(Hash) || yml_data['Resources'].length == 0
|
128
136
|
if yml_data.has_key?(PARAMETERS) && yml_data[PARAMETERS].is_a?(Hash) && yml_data[PARAMETERS].length > 0
|
129
|
-
yml_data[PARAMETERS].each do |
|
137
|
+
yml_data[PARAMETERS].each do |param_name, param_data|
|
130
138
|
# Validate keys are in specific order.
|
131
139
|
expected = {
|
132
140
|
'Type' => true,
|
@@ -140,72 +148,77 @@ module AppCommand
|
|
140
148
|
'MaxValue' => false,
|
141
149
|
'ConstraintDescription' => false,
|
142
150
|
}
|
143
|
-
Blufin::Validate::assert_valid_keys(expected,
|
144
|
-
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 Template has reserved parameter: #{Blufin::Terminal::format_invalid(
|
145
|
-
parameters[
|
146
|
-
if @auto_fetch_resources.has_key?(
|
147
|
-
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 Parameter: #{
|
151
|
+
Blufin::Validate::assert_valid_keys(expected, param_data.keys, "#{file} \xe2\x86\x92 #{param_name}")
|
152
|
+
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 Template has reserved parameter: #{Blufin::Terminal::format_invalid(param_name)}" if [OPTION_STACK_NAME.downcase].concat(RESERVED_WORDS).include?(param_name.downcase)
|
153
|
+
parameters[param_name] = param_data
|
154
|
+
if @auto_fetch_resources.has_key?(param_name)
|
155
|
+
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 Parameter: #{param_name} cannot have default value: '#{param_data[DEFAULT]}' because it is a live look-up list (from AWS)." if param_data.keys.include?(DEFAULT)
|
148
156
|
end
|
149
157
|
# Validate parameter type.
|
150
158
|
valid_parameter_types = %w(String Number List<Number> CommaDelimitedList)
|
151
159
|
valid_parameter_regexes = [/^AWS::[A-Za-z0-9]+::[A-Za-z0-9]+::[A-Za-z0-9]+$/, /^List<AWS::[A-Za-z0-9]+::[A-Za-z0-9]+::[A-Za-z0-9]+>$/]
|
152
|
-
unless valid_parameter_types.include?(
|
160
|
+
unless valid_parameter_types.include?(param_data['Type'])
|
153
161
|
matches_vpr = false
|
154
162
|
valid_parameter_regexes.each do |vpr|
|
155
|
-
matches_vpr = true if
|
163
|
+
matches_vpr = true if param_data['Type'] =~ vpr
|
156
164
|
end
|
157
165
|
if matches_vpr
|
158
166
|
constraints = []
|
159
|
-
constraints << 'AllowedPattern' if
|
160
|
-
constraints << 'MinLength' if
|
161
|
-
constraints << 'MaxLength' if
|
162
|
-
constraints << 'MinValue' if
|
163
|
-
constraints << 'MaxValue' if
|
167
|
+
constraints << 'AllowedPattern' if param_data.has_key?('AllowedPattern')
|
168
|
+
constraints << 'MinLength' if param_data.has_key?('MinLength')
|
169
|
+
constraints << 'MaxLength' if param_data.has_key?('MaxLength')
|
170
|
+
constraints << 'MinValue' if param_data.has_key?('MinValue')
|
171
|
+
constraints << 'MaxValue' if param_data.has_key?('MaxValue')
|
164
172
|
if constraints.any?
|
165
173
|
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 Invalid parameter constraint(s): #{Blufin::Terminal::format_invalid(constraints.join(','))}. These don't apply to AWS-Specific parameters."
|
166
174
|
end
|
167
175
|
else
|
168
|
-
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 Invalid parameter type: #{Blufin::Terminal::format_invalid(
|
176
|
+
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 Invalid parameter type: #{Blufin::Terminal::format_invalid(param_data['Type'])}"
|
169
177
|
end
|
170
178
|
end
|
171
179
|
# Can only have Max/MinLength if this is a String.
|
172
|
-
if
|
173
|
-
unless
|
180
|
+
if param_data.has_key?('MinLength') || param_data.has_key?('MaxLength') || param_data.has_key?('AllowedPattern')
|
181
|
+
unless param_data['Type'] == 'String'
|
174
182
|
constraints = []
|
175
|
-
constraints << 'MinLength' if
|
176
|
-
constraints << 'MaxLength' if
|
177
|
-
constraints << 'AllowedPattern' if
|
183
|
+
constraints << 'MinLength' if param_data.has_key?('MinLength')
|
184
|
+
constraints << 'MaxLength' if param_data.has_key?('MaxLength')
|
185
|
+
constraints << 'AllowedPattern' if param_data.has_key?('AllowedPattern')
|
178
186
|
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 Invalid parameter constraint(s): #{Blufin::Terminal::format_invalid(constraints.join(','))}. To use these, type must be String."
|
179
187
|
end
|
180
188
|
end
|
181
189
|
# Can only have Max/MinValue if this is a Number.
|
182
|
-
if
|
183
|
-
unless
|
190
|
+
if param_data.has_key?('MinValue') || param_data.has_key?('MaxValue')
|
191
|
+
unless param_data['Type'] == 'Number'
|
184
192
|
constraints = []
|
185
|
-
constraints << 'MinValue' if
|
186
|
-
constraints << 'MaxValue' if
|
193
|
+
constraints << 'MinValue' if param_data.has_key?('MinValue')
|
194
|
+
constraints << 'MaxValue' if param_data.has_key?('MaxValue')
|
187
195
|
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 Invalid parameter constraint(s): #{Blufin::Terminal::format_invalid(constraints.join(','))}. To use these, type must be Number."
|
188
196
|
end
|
189
197
|
end
|
190
198
|
# If Allowed Values is set, certain conditions must apply.
|
191
|
-
if
|
199
|
+
if param_data.has_key?('AllowedValues')
|
192
200
|
%w(AllowedPattern MinLength MaxLength MinValue MaxValue).each do |invalid_key|
|
193
|
-
if
|
194
|
-
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 AllowedValues is set so cannot have: #{Blufin::Terminal::format_invalid(
|
201
|
+
if param_data.has_key?(invalid_key)
|
202
|
+
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 AllowedValues is set so cannot have: #{Blufin::Terminal::format_invalid(param_data['invalid_key'])}"
|
195
203
|
end
|
196
204
|
end
|
197
205
|
# Must be Array.
|
198
|
-
unless
|
199
|
-
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 AllowedValues must be Array, instead got: #{Blufin::Terminal::format_invalid(
|
206
|
+
unless param_data['AllowedValues'].is_a?(Array)
|
207
|
+
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 AllowedValues must be Array, instead got: #{Blufin::Terminal::format_invalid(param_data['AllowedValues'].class)}"
|
200
208
|
end
|
201
209
|
end
|
210
|
+
# Validate EC2UserData parameter (make sure cloud-init.txt exists).
|
211
|
+
if param_name == EC2_USER_DATA
|
212
|
+
cloud_init_file = "#{template_path}/#{EC2_USER_DATA_FILE}"
|
213
|
+
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 Template has #{Blufin::Terminal::format_highlight(EC2_USER_DATA)} parameter but no #{Blufin::Terminal::format_invalid(EC2_USER_DATA_FILE)} file." unless Blufin::Files::file_exists(cloud_init_file)
|
214
|
+
end
|
202
215
|
end
|
203
216
|
end
|
204
217
|
# Validate description (if exists).
|
205
218
|
if yml_data.has_key?(OPTION_DESCRIPTION)
|
206
219
|
description = yml_data[OPTION_DESCRIPTION]
|
207
220
|
# Validate replaceable value(s) exist.
|
208
|
-
matches
|
221
|
+
matches = description.scan(/{{[A-Za-z0-9]+}}/)
|
209
222
|
matches.each do |match|
|
210
223
|
match = match.gsub(/^{{/, '').gsub(/}}$/, '')
|
211
224
|
unless parameters.keys.include?(match)
|
@@ -242,13 +255,14 @@ module AppCommand
|
|
242
255
|
constant = constant.to_s
|
243
256
|
expected_constants.delete(constant) if expected_constants.include?(constant)
|
244
257
|
# Optional constants.
|
245
|
-
intro
|
246
|
-
stack_name
|
247
|
-
projects
|
248
|
-
environments
|
249
|
-
regions
|
250
|
-
timeout
|
251
|
-
deployment_stack
|
258
|
+
intro = Template::INTRO if constant == 'INTRO'
|
259
|
+
stack_name = Template::STACK_NAME if constant == 'STACK_NAME'
|
260
|
+
projects = Template::PROJECTS if constant == 'PROJECTS'
|
261
|
+
environments = Template::ENVIRONMENTS if constant == 'ENVIRONMENTS'
|
262
|
+
regions = Template::REGIONS if constant == 'REGIONS'
|
263
|
+
timeout = Template::TIMEOUT if constant == 'TIMEOUT'
|
264
|
+
deployment_stack = Template::DEPLOYMENT_STACK if constant == 'DEPLOYMENT_STACK'
|
265
|
+
parameters_no_sort = Template::PARAMETERS_NO_SORT if constant == 'PARAMETERS_NO_SORT'
|
252
266
|
end
|
253
267
|
# Validate stack name.
|
254
268
|
if stack_name.nil? || stack_name.strip == ''
|
@@ -320,6 +334,16 @@ module AppCommand
|
|
320
334
|
Object.send(:remove_const, :Template)
|
321
335
|
end
|
322
336
|
end
|
337
|
+
# Make sure no-sort parameters exist.
|
338
|
+
unless parameters_no_sort.nil?
|
339
|
+
if parameters_no_sort.is_a?(Array)
|
340
|
+
parameters_no_sort.each do |pns|
|
341
|
+
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 Non-existent #{Blufin::Terminal::format_highlight('PARAMETERS_NO_SORT')} parameter: #{Blufin::Terminal::format_invalid(pns)}" unless parameters.keys.include?(pns)
|
342
|
+
end
|
343
|
+
else
|
344
|
+
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 Expected constant #{Blufin::Terminal::format_highlight('PARAMETERS_NO_SORT')} to be Array, instead got: #{Blufin::Terminal::format_invalid(parameters_no_sort.class)}"
|
345
|
+
end
|
346
|
+
end
|
323
347
|
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 The #{Blufin::Terminal::format_highlight('template.yml')}\x1B[38;5;240m is missing, empty or invalid." if file_cloudformation.nil?
|
324
348
|
@warnings << "\x1B[38;5;196m#{template_name}\x1B[38;5;240m \xe2\x80\x94 The #{Blufin::Terminal::format_highlight('template.rb')}\x1B[38;5;240m is missing, empty or invalid." if file_ruby.nil?
|
325
349
|
@templates[category] = {} unless @templates.has_key?(category)
|
@@ -331,6 +355,7 @@ module AppCommand
|
|
331
355
|
else
|
332
356
|
@templates[category][template] = {
|
333
357
|
:name => template,
|
358
|
+
:path => template_path,
|
334
359
|
:broken => false,
|
335
360
|
:file_cloudformation => file_cloudformation,
|
336
361
|
:file_ruby => file_ruby,
|
@@ -339,6 +364,7 @@ module AppCommand
|
|
339
364
|
:method_before_teardown => method_before_teardown,
|
340
365
|
:method_after_teardown => method_after_teardown,
|
341
366
|
:parameters => parameters,
|
367
|
+
:parameters_no_sort => parameters_no_sort,
|
342
368
|
:intro => intro,
|
343
369
|
:description => description,
|
344
370
|
:stack_name => stack_name,
|
@@ -365,8 +391,8 @@ module AppCommand
|
|
365
391
|
|
366
392
|
def opts_routing
|
367
393
|
|
368
|
-
used_cache
|
369
|
-
showing_tags
|
394
|
+
used_cache = true
|
395
|
+
showing_tags = false
|
370
396
|
|
371
397
|
# Show prompt to select template.
|
372
398
|
category, template, @template = select_template_prompt
|
@@ -430,10 +456,10 @@ module AppCommand
|
|
430
456
|
capabilities_str = nil
|
431
457
|
|
432
458
|
# Upload the template to S3.
|
433
|
-
s3_url
|
459
|
+
s3_url = App::AWSCloudFormation::upload_cloudformation_template(category, template, @params[OPTION_DESCRIPTION])
|
434
460
|
|
435
461
|
# Validates the template.
|
436
|
-
validation
|
462
|
+
validation = App::AWSCli::cloudformation_stack_validate(@params[OPTION_REGION], s3_url)
|
437
463
|
|
438
464
|
# Check if validation output is JSON (and output appropriate format).
|
439
465
|
begin
|
@@ -645,6 +671,10 @@ module AppCommand
|
|
645
671
|
OPTION_DESCRIPTION => 'Should this stack be protected against accidental Termination?'
|
646
672
|
}
|
647
673
|
end
|
674
|
+
# If one of the parameters is EC2UserData, this parameter gets handled differently.
|
675
|
+
if @template[:parameters].is_a?(Hash) && @template[:parameters].has_key?(EC2_USER_DATA)
|
676
|
+
@template[:parameters][EC2_USER_DATA][OPTION_DESCRIPTION] = "#{EC2_USER_DATA_FILE} (base64 encoded & sent automatically)"
|
677
|
+
end
|
648
678
|
# Get cached values (if exist and parameters haven't changed).
|
649
679
|
# Even a one-character change in a description will invalidate the cache.
|
650
680
|
cache_file = get_cache_file(category, template)
|
@@ -716,11 +746,11 @@ module AppCommand
|
|
716
746
|
puts
|
717
747
|
choices = []
|
718
748
|
else
|
719
|
-
choices = [{
|
720
|
-
choices << {
|
749
|
+
choices = [{value: 'y', text: 'Select this template'}]
|
750
|
+
choices << {value: 'Y', text: "Select this template \x1B[38;5;198m(and apply cached values)\x1B[0m"} if @cache_valid
|
721
751
|
end
|
722
752
|
# The prompt at the end of the intro.
|
723
|
-
choices << {
|
753
|
+
choices << {value: 'n', text: "\x1B[38;5;240m#{Blufin::Strings::RETURN_CHARACTER}\x1B[0m"}
|
724
754
|
choice = Blufin::Terminal::prompt_select('What would you like to do?', choices)
|
725
755
|
case choice
|
726
756
|
when 'y'
|
@@ -767,10 +797,14 @@ module AppCommand
|
|
767
797
|
end
|
768
798
|
help_text = 'Description (will be displayed in CloudFormation console).'
|
769
799
|
return Blufin::Terminal::prompt_ask("Enter #{param_name}#{render_constraints(constraints)}", default: default, help: help_text)
|
800
|
+
elsif param_name == EC2_USER_DATA
|
801
|
+
puts Blufin::Terminal::display_prompt_text(EC2_USER_DATA, EC2_USER_DATA_FILE)
|
802
|
+
return "#{@template[:path]}/#{EC2_USER_DATA_FILE}"
|
770
803
|
elsif param_name == OPTION_TIMEOUT
|
771
804
|
return param_data[DEFAULT]
|
772
805
|
elsif param_name == OPTION_TERM_PROTECT
|
773
|
-
|
806
|
+
# Basically, by default Termination Protection is off (because most of the time your just testing and want to press Enter).
|
807
|
+
return !Blufin::Terminal::prompt_yes?("Allow accidental Termination? (type 'n' to enable Termination Protection)")
|
774
808
|
elsif @auto_fetch_resources.has_key?(param_name)
|
775
809
|
# Sort alphabetically.
|
776
810
|
options = fetch_autocomplete_options(param_name, silent: true)
|
@@ -787,9 +821,11 @@ module AppCommand
|
|
787
821
|
puts Blufin::Terminal::display_prompt_text(options_text, default_option)
|
788
822
|
return default_option
|
789
823
|
else
|
790
|
-
|
791
|
-
|
792
|
-
|
824
|
+
unless @template[:parameters_no_sort].is_a?(Array) && @template[:parameters_no_sort].include?(param_name)
|
825
|
+
# Sort alphabetically.
|
826
|
+
options.uniq!
|
827
|
+
options.sort!
|
828
|
+
end
|
793
829
|
# If we have a cached value, make that the first in the options list.
|
794
830
|
options = move_default_option_to_top(options, param_name) if @cache.has_key?(param_name)
|
795
831
|
puts Blufin::Terminal::display_prompt_help(param_data[OPTION_DESCRIPTION]) if param_data.has_key?(OPTION_DESCRIPTION)
|
@@ -921,6 +957,16 @@ module AppCommand
|
|
921
957
|
def assemble_params(params)
|
922
958
|
output = []
|
923
959
|
params.each do |key, value|
|
960
|
+
if key == EC2_USER_DATA
|
961
|
+
b64_cmd = Blufin::Tools::value_based_on_os(mac: "openssl base64 -in #{value}", linux: "base64 -w0 #{value}")
|
962
|
+
result = Blufin::Terminal::command_capture(b64_cmd, nil, nil, nil)[0]
|
963
|
+
result = result.split("\n").join('')
|
964
|
+
output << {
|
965
|
+
'ParameterKey' => key,
|
966
|
+
'ParameterValue' => result
|
967
|
+
}
|
968
|
+
next
|
969
|
+
end
|
924
970
|
unless RESERVED_WORDS.include?(key.downcase)
|
925
971
|
output << {
|
926
972
|
'ParameterKey' => key,
|
@@ -979,7 +1025,7 @@ module AppCommand
|
|
979
1025
|
# Replaces current random stack suffix with another one.
|
980
1026
|
# @return string
|
981
1027
|
def replace_stack_suffix(current)
|
982
|
-
current.gsub(/a[0-9a-z]{
|
1028
|
+
current.gsub(/a[0-9a-z]{16}10w17[0-9a-z]{16}x/, random_stack_suffix)
|
983
1029
|
end
|
984
1030
|
|
985
1031
|
end
|
data/lib/version.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
AWX_VERSION = '0.
|
1
|
+
AWX_VERSION = '0.5.0'
|
data/opt/config/schema.yml
CHANGED
@@ -22,14 +22,37 @@ mapping:
|
|
22
22
|
CloudFormation:
|
23
23
|
type: map
|
24
24
|
mapping:
|
25
|
-
|
26
|
-
required: yes
|
27
|
-
S3BucketPath:
|
25
|
+
Templates:
|
28
26
|
required: yes
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
type: map
|
28
|
+
mapping:
|
29
|
+
Local:
|
30
|
+
type: map
|
31
|
+
mapping:
|
32
|
+
Path:
|
33
|
+
required: yes
|
34
|
+
S3Bucket:
|
35
|
+
type: map
|
36
|
+
mapping:
|
37
|
+
Name:
|
38
|
+
required: yes
|
39
|
+
Path:
|
40
|
+
required: yes
|
41
|
+
Region:
|
42
|
+
required: yes
|
43
|
+
Uploads:
|
32
44
|
required: yes
|
45
|
+
type: map
|
46
|
+
mapping:
|
47
|
+
S3Bucket:
|
48
|
+
type: map
|
49
|
+
mapping:
|
50
|
+
Name:
|
51
|
+
required: yes
|
52
|
+
Path:
|
53
|
+
required: yes
|
54
|
+
Region:
|
55
|
+
required: yes
|
33
56
|
Defaults:
|
34
57
|
type: map
|
35
58
|
required: yes
|
data/opt/config/template.yml
CHANGED
@@ -3,10 +3,18 @@ DynamoDBPath: <<-path/to/folder->>
|
|
3
3
|
Profiles:
|
4
4
|
- Profile: default
|
5
5
|
CloudFormation:
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
Templates:
|
7
|
+
Local:
|
8
|
+
Path: <<-path->>
|
9
|
+
S3Bucket:
|
10
|
+
Name: <<-S3-bucket-name->>
|
11
|
+
Path: <<-S3-bucket-path->>
|
12
|
+
Region: <<-S3-bucket-region->>
|
13
|
+
Uploads:
|
14
|
+
S3Bucket:
|
15
|
+
Name: <<-S3-bucket-name->>
|
16
|
+
Path: <<-S3-bucket-path->>
|
17
|
+
Region: <<-S3-bucket-region->>
|
10
18
|
Defaults:
|
11
19
|
StackName: "{{CATEGORY}}-{{TEMPLATE}}-{{PROJECT}}-{{ENVIRONMENT}}-{{REGION}}-{{UUID}}"
|
12
20
|
Timeout: 60
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: awx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Albert Rannetsperger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-08-
|
11
|
+
date: 2019-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: blufin-lib
|
@@ -122,7 +122,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
122
122
|
requirements:
|
123
123
|
- - ">="
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version: '2.
|
125
|
+
version: '2.3'
|
126
126
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
127
|
requirements:
|
128
128
|
- - ">="
|
@@ -130,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
130
|
version: '0'
|
131
131
|
requirements: []
|
132
132
|
rubyforge_project:
|
133
|
-
rubygems_version: 2.
|
133
|
+
rubygems_version: 2.5.1
|
134
134
|
signing_key:
|
135
135
|
specification_version: 4
|
136
136
|
summary: An AWS-cli wrapper.
|