awx 0.4.2 → 0.5.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_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.
|