aws-cfn-stacker 0.0.1 → 0.0.5
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 +5 -13
- data/aws-cfn-stacker.gemspec +5 -0
- data/aws-cfn-stacker.iml +21 -3
- data/bin/cfn-stacker +25 -0
- data/lib/aws/cfn/stacker/base.rb +10 -0
- data/lib/aws/cfn/stacker/mixins/errors.rb +13 -0
- data/lib/aws/cfn/stacker/mixins/logging.rb +18 -0
- data/lib/aws/cfn/stacker/mixins/main.rb +192 -0
- data/lib/aws/cfn/stacker/mixins/options.rb +495 -0
- data/lib/aws/cfn/stacker/mixins/patches.rb +46 -0
- data/lib/aws/cfn/stacker/mixins/prerequisites.rb +188 -0
- data/lib/aws/cfn/stacker/mixins/setup.rb +58 -0
- data/lib/aws/cfn/stacker/version.rb +6 -1
- data/lib/aws/cfn/stacker.rb +21 -1
- metadata +106 -14
@@ -0,0 +1,495 @@
|
|
1
|
+
|
2
|
+
module Aws
|
3
|
+
module Cfn
|
4
|
+
module Stacker
|
5
|
+
|
6
|
+
module Options
|
7
|
+
include ::DLDInternet::Mixlib::CLI
|
8
|
+
|
9
|
+
# --------------------------------------------------------------------------------
|
10
|
+
#
|
11
|
+
# Override Mixlib::CLI.parse_options and
|
12
|
+
# knowingly add extra paramater to track argument source
|
13
|
+
#
|
14
|
+
# We do this by monkey patching this override method at include time instead of statically declaring it
|
15
|
+
# in which case the Mixlib::CLI.parse_options seems to "win" most of the time OR the interpreter complains.
|
16
|
+
#
|
17
|
+
def parse_options(args,source=nil)
|
18
|
+
# noinspection RubySuperCallWithoutSuperclassInspection
|
19
|
+
argv = super(args)
|
20
|
+
|
21
|
+
prescreen_options(argv)
|
22
|
+
|
23
|
+
@config = parse_and_validate_options(@config,source ? source : "ARGV - #{__LINE__}")
|
24
|
+
|
25
|
+
unless @config[:actions]
|
26
|
+
@config[:actions] = [ argv[1].to_sym ]
|
27
|
+
end
|
28
|
+
@actors[argv[1].to_sym] = self
|
29
|
+
others = @config[:actions].select{|a|
|
30
|
+
a != argv[1].to_sym
|
31
|
+
}
|
32
|
+
index = args.index '--action'
|
33
|
+
argv
|
34
|
+
end
|
35
|
+
|
36
|
+
# --------------------------------------------------------------------------------------------------------------
|
37
|
+
#
|
38
|
+
# Do a quick prescreening of the arguments and bail early for some obvious cases
|
39
|
+
#
|
40
|
+
def prescreen_options(argv=ARGV)
|
41
|
+
# Checking ARGV validity *before* parse_options because parse_options
|
42
|
+
# mangles ARGV in some situations
|
43
|
+
if no_command_given?
|
44
|
+
print_help_and_exit(1, NO_COMMAND_GIVEN)
|
45
|
+
elsif no_subcommand_given?
|
46
|
+
if want_help? || want_version?
|
47
|
+
print_help_and_exit
|
48
|
+
else
|
49
|
+
print_help_and_exit(2, NO_COMMAND_GIVEN)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# --------------------------------------------------------------------------------------------------------------
|
55
|
+
# private
|
56
|
+
# --------------------------------------------------------------------------------------------------------------
|
57
|
+
def no_subcommand_given?(argv=ARGV)
|
58
|
+
argv[0] =~ /^--?[^a]/
|
59
|
+
end
|
60
|
+
|
61
|
+
def no_command_given?(argv=ARGV)
|
62
|
+
argv.empty?
|
63
|
+
end
|
64
|
+
|
65
|
+
def want_help?
|
66
|
+
ARGV[0] =~ /^(--help|-h)$/
|
67
|
+
end
|
68
|
+
|
69
|
+
def want_version?
|
70
|
+
ARGV[0] =~ /^(--version|-v)$/
|
71
|
+
end
|
72
|
+
|
73
|
+
def print_help_and_exit(exitcode=1, fatal_message=nil)
|
74
|
+
puts "FATAL: #{fatal_message}" if fatal_message
|
75
|
+
|
76
|
+
puts self.opt_parser
|
77
|
+
puts
|
78
|
+
exit exitcode
|
79
|
+
end
|
80
|
+
|
81
|
+
# --------------------------------------------------------------------------------
|
82
|
+
def parseActionSymbol(v)
|
83
|
+
if v.to_sym == :all
|
84
|
+
::Aws::Cfn::Stacker::Application.allactions
|
85
|
+
else
|
86
|
+
s = v.to_sym
|
87
|
+
allactions = [::Aws::Cfn::Stacker::Application.allactions, :all].flatten
|
88
|
+
unless allactions.include?(s)
|
89
|
+
allactions.each{ |p|
|
90
|
+
s = p if p.match(%r/^#{s}/)
|
91
|
+
}
|
92
|
+
end
|
93
|
+
s = ::Aws::Cfn::Stacker::Application.allactions if s == :all
|
94
|
+
s
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# --------------------------------------------------------------------------------
|
99
|
+
def parsePrecedence(v)
|
100
|
+
@prec_max += 1
|
101
|
+
match = v.match(%r/^(json|rb|yaml)$/i)
|
102
|
+
unless match
|
103
|
+
m = "ERROR: Invalid precedence argument: #{v}. Accept only from this set: [json,rb,yaml]"
|
104
|
+
puts m
|
105
|
+
raise Exception.new(m)
|
106
|
+
end
|
107
|
+
s = { v => @prec_max }
|
108
|
+
match = v.match(%r/^(\S+):(\d+)$/)
|
109
|
+
if match
|
110
|
+
begin
|
111
|
+
a = match[1]
|
112
|
+
i = match[2].to_i
|
113
|
+
s = { a => i }
|
114
|
+
rescue => e
|
115
|
+
puts "ERROR: Unable to match precedence #{v}"
|
116
|
+
raise e
|
117
|
+
end
|
118
|
+
end
|
119
|
+
s
|
120
|
+
end
|
121
|
+
|
122
|
+
# --------------------------------------------------------------------------------
|
123
|
+
def parseINIFile(options=nil)
|
124
|
+
options = @config unless options
|
125
|
+
if options.key?(:inifile)
|
126
|
+
logStep "Parse INI file - #{options[:inifile]}"
|
127
|
+
raise StackerError.new("Cannot find inifile (#{options[:inifile]})") unless File.exist?(options[:inifile])
|
128
|
+
raise StackerError.new("Recursive call to inifile == '#{options[:inifile]}'") if @inis.include?(options[:inifile])
|
129
|
+
ini = nil
|
130
|
+
begin
|
131
|
+
ini = IniFile.load(options[:inifile])
|
132
|
+
@inis << options[:inifile]
|
133
|
+
ini['global'].each { |key, value|
|
134
|
+
#puts "#{key}=#{value}"
|
135
|
+
ENV[key]=value
|
136
|
+
}
|
137
|
+
argv=[]
|
138
|
+
cli = ini['cli'] || []
|
139
|
+
cli.each{ |key,value|
|
140
|
+
argv << key.gsub(%r/:[0-9]+$/, '').gsub(%r/^([^-])/, '--\1')
|
141
|
+
argv << value
|
142
|
+
}
|
143
|
+
if argv.size > 0
|
144
|
+
parse_options(argv,"INI-#{options[:inifile]}")
|
145
|
+
end
|
146
|
+
rescue => e
|
147
|
+
puts e.message.light_red
|
148
|
+
raise e
|
149
|
+
end
|
150
|
+
end
|
151
|
+
options
|
152
|
+
end
|
153
|
+
|
154
|
+
# -----------------------------------------------------------------------------
|
155
|
+
def setDefaultOptions(options)
|
156
|
+
@options.each{|name,args|
|
157
|
+
if args[:default]
|
158
|
+
options[name] = args[:default] unless options[name]
|
159
|
+
end
|
160
|
+
}
|
161
|
+
setOrigins(options,'default')
|
162
|
+
end
|
163
|
+
|
164
|
+
# -----------------------------------------------------------------------------
|
165
|
+
def validate_options(options=nil)
|
166
|
+
options = @config unless options
|
167
|
+
|
168
|
+
# Check for the necessary environment variables
|
169
|
+
logStep ('Check ENVironment')
|
170
|
+
env = ENV.to_hash
|
171
|
+
missing = {}
|
172
|
+
%w(AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY).each { |k|
|
173
|
+
missing[k] = true unless ENV.has_key?(k)
|
174
|
+
}
|
175
|
+
if options[:use_chef]
|
176
|
+
%w(KNIFE_CHEF_SERVER_URL KNIFE_CLIENT_KEY KNIFE_CLIENT_NAME).each { |k|
|
177
|
+
missing[k] = true unless ENV.has_key?(k)
|
178
|
+
}
|
179
|
+
end
|
180
|
+
|
181
|
+
if missing.count() > 0
|
182
|
+
#@logger.error "Missing keys: #{missing.keys.ai}"
|
183
|
+
raise StackerError.new("Missing environment variables: #{missing.keys}")
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# -----------------------------------------------------------------------------
|
188
|
+
def parse_and_validate_options(options=nil,source='ARGV')
|
189
|
+
options = @config unless options
|
190
|
+
setOrigins(options,source)
|
191
|
+
|
192
|
+
#options = parseOptions(options,source)
|
193
|
+
unless @origins and @name_key_map
|
194
|
+
# These are the essential default options which things like parseOptions depend on
|
195
|
+
{
|
196
|
+
:verbosity => @verbosity,
|
197
|
+
:auto_purge => false,
|
198
|
+
}.each{ |k,v|
|
199
|
+
options[k] = v unless options[k]
|
200
|
+
}
|
201
|
+
setOrigins(options,'hardcoded-default')
|
202
|
+
|
203
|
+
@name_key_map = {} unless @name_key_map
|
204
|
+
@options.each{ |name,args|
|
205
|
+
@name_key_map[name] = {} unless @name_key_map[name]
|
206
|
+
[:short,:long,:description].each{|key|
|
207
|
+
@name_key_map[name][key] = args[key] if args[key]
|
208
|
+
}
|
209
|
+
}
|
210
|
+
end
|
211
|
+
|
212
|
+
begin
|
213
|
+
parseINIFile(options)
|
214
|
+
setDefaultOptions(options)
|
215
|
+
# Check for all the necessary options
|
216
|
+
validate_options(options)
|
217
|
+
checkArgsSources(options)
|
218
|
+
#findRootPath(options)
|
219
|
+
rescue StackerError => e
|
220
|
+
puts e.message.light_red
|
221
|
+
puts "#{__FILE__}::#{__LINE__} reraising ... "
|
222
|
+
raise e
|
223
|
+
exit -1
|
224
|
+
rescue Exception => e
|
225
|
+
puts e.message.light_red
|
226
|
+
puts "#{__FILE__}::#{__LINE__} reraising ... "
|
227
|
+
raise e
|
228
|
+
exit -2
|
229
|
+
end
|
230
|
+
|
231
|
+
options
|
232
|
+
end
|
233
|
+
|
234
|
+
# ---------------------------------------------------------------------------------------------------------------
|
235
|
+
def setOrigins(options,source)
|
236
|
+
@origins = {} unless @origins
|
237
|
+
options.each { |key, val|
|
238
|
+
@origins[key] = source unless (@origins[key])
|
239
|
+
}
|
240
|
+
end
|
241
|
+
|
242
|
+
# ---------------------------------------------------------------------------------------------------------------
|
243
|
+
def checkArgsSources(options)
|
244
|
+
if @origins
|
245
|
+
missing = @origins.select{ |k,v|
|
246
|
+
v.nil?
|
247
|
+
}.map{ |k,v| k }
|
248
|
+
raise StackerError.new("Missing origins: #{missing.ai}") if missing.size > 0
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
module ClassMethods
|
253
|
+
|
254
|
+
# noinspection RubyInstanceVariableNamingConvention
|
255
|
+
def defaultoptions=(options)
|
256
|
+
@DEFAULTOPTIONS = options || {}
|
257
|
+
end
|
258
|
+
|
259
|
+
def defaultoptions
|
260
|
+
@DEFAULTOPTIONS
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
264
|
+
|
265
|
+
# --------------------------------------------------------------------------------------------------------------
|
266
|
+
#
|
267
|
+
# If this module is included we inject this payload into the including class.
|
268
|
+
#
|
269
|
+
def self.included(includer)
|
270
|
+
includer.extend(::DLDInternet::Mixlib::CLI::ClassMethods)
|
271
|
+
includer.extend(ClassMethods)
|
272
|
+
|
273
|
+
includer.class_eval do
|
274
|
+
self.defaultoptions = {}
|
275
|
+
|
276
|
+
<<-EOF
|
277
|
+
|
278
|
+
-c CONFIG_FILE, --config-file CONFIG_FILE
|
279
|
+
An ini file to use that contains one section per stack, with all the parameters for the stack enumerated
|
280
|
+
-v, --verbose Increase verbosity, can be specified multiple times (currently just sets the debug level for AWS)
|
281
|
+
--debug Increase debug, can be specified multiple times
|
282
|
+
-r, --remove Delete the requested stack. WARNING: No second chances!
|
283
|
+
-d, --delete Delete the requested stack. WARNING: No second chances!
|
284
|
+
-l, --list-params List the parameters in the template, and show what values are supplied by your config file
|
285
|
+
-t TEMPLATE, --template TEMPLATE
|
286
|
+
Specify a different template to run. Note that specific outputs are expected, so results may vary.
|
287
|
+
--template_url TEMPLATE_URL
|
288
|
+
Specify the key of a template stored in an S3 bucket to run. This method assumes the template has already been uploaded.
|
289
|
+
--use_s3 Use an S3 bucket to upload the template to before attempting stack run. This method assumes the template needs to be uploaded and may overwrite a key with the same name.
|
290
|
+
-k KEYFILE, --keyfile KEYFILE
|
291
|
+
The path to the SSH key file to use for SSH to hosts
|
292
|
+
-b, --build Build configuration directory for use with Ansible.
|
293
|
+
-i INITIAL_SETUP, --initial_setup INITIAL_SETUP
|
294
|
+
An initial setup file for Ansible
|
295
|
+
-o OUTPUT, --output OUTPUT
|
296
|
+
Output folder for the Ansible build configuration
|
297
|
+
-R ROLES_PATH, --roles_path ROLES_PATH
|
298
|
+
Folder for the Ansible roles
|
299
|
+
--ssh_user SSH_USER SSH User name
|
300
|
+
--ssh_user_bastion SSH_USER_BASTION
|
301
|
+
Bastion SSH User name
|
302
|
+
-u, --update Update the configuration of an existing stack
|
303
|
+
-C, --configure Run pre-defined ansible playbooks against the given stack. Implies -b
|
304
|
+
-s, --status Print the current status of a given stack.
|
305
|
+
-p, --progress Print a progress indicator during stack create/update/delete.
|
306
|
+
|
307
|
+
EOF
|
308
|
+
|
309
|
+
option :help,
|
310
|
+
short: '-h',
|
311
|
+
long: '--help',
|
312
|
+
description: 'Show this message',
|
313
|
+
show_options: true,
|
314
|
+
exit: 1
|
315
|
+
# print the version.
|
316
|
+
option :version,
|
317
|
+
short: '-V',
|
318
|
+
long: '--version',
|
319
|
+
description: 'Show version',
|
320
|
+
proc: Proc.new{ puts ::Aws::Cfn::Stacker::Application::VERSION },
|
321
|
+
exit: 2
|
322
|
+
option :config_file_alt,
|
323
|
+
short: '-c',
|
324
|
+
long: '--config-file FILE',
|
325
|
+
description: 'A config file to use that contains one section per stack, with all the parameters for the stack enumerated. INI, YAML and JSON formats supported.',
|
326
|
+
proc: lambda{ |v|
|
327
|
+
@options[:config_file] = v
|
328
|
+
}
|
329
|
+
option :config_file,
|
330
|
+
short: '-c',
|
331
|
+
long: '--config_file FILE',
|
332
|
+
description: 'A config file to use that contains one section per stack, with all the parameters for the stack enumerated. INI, YAML and JSON formats supported.'
|
333
|
+
option :verbose,
|
334
|
+
short: '-v',
|
335
|
+
long: '--verbose',
|
336
|
+
description: 'Increase verbosity, can be specified multiple times',
|
337
|
+
proc: lambda {|v|
|
338
|
+
index = ::Aws::Cfn::Stacker::Application.loglevels.index(@options[:log_level]) || ::Aws::Cfn::Stacker::Application.loglevels.index(:warn)
|
339
|
+
index -= 1 if index > 0
|
340
|
+
@options[:log_level] = ::Aws::Cfn::Stacker::Application.loglevels[index]
|
341
|
+
}
|
342
|
+
option :log_level,
|
343
|
+
long: '--debug',
|
344
|
+
description: 'Set debug level logging. No effect if specified second time.',
|
345
|
+
value: :debug
|
346
|
+
option :action,
|
347
|
+
short: '-a',
|
348
|
+
long: '--action ACTION',
|
349
|
+
description: "Perform the requested action against the stack. (#{::Aws::Cfn::Stacker::Application.allactions.to_s})",
|
350
|
+
proc: lambda{|v|
|
351
|
+
actions = $STKR.parseOptionString(v,',', 'parseActionSymbol')
|
352
|
+
all = [::Aws::Cfn::Stacker::Application.allactions, :all].flatten
|
353
|
+
actions.each{ |act|
|
354
|
+
unless all.include?(act.to_sym)
|
355
|
+
raise ::OptionParser::InvalidOption.new("Invalid action: #{act.to_s}. Valid actions are: #{all.to_s}")
|
356
|
+
end
|
357
|
+
}
|
358
|
+
actions
|
359
|
+
}
|
360
|
+
option :build,
|
361
|
+
short: '-b',
|
362
|
+
long: '--build',
|
363
|
+
description: 'Build configuration directory for use with Ansible.',
|
364
|
+
proc: lambda { |v| @options[:action] = :build}
|
365
|
+
|
366
|
+
option :remove,
|
367
|
+
short: '-r',
|
368
|
+
long: '--remove',
|
369
|
+
description: 'Delete the requested stack. WARNING: No second chances!',
|
370
|
+
proc: lambda { |v| @options[:action] = :delete }
|
371
|
+
option :delete,
|
372
|
+
short: '-d',
|
373
|
+
long: '--delete',
|
374
|
+
description: 'Delete the requested stack. WARNING: No second chances!',
|
375
|
+
proc: lambda { |v| @options[:action] = :delete }
|
376
|
+
option :update,
|
377
|
+
short: '-u',
|
378
|
+
long: '--update',
|
379
|
+
description: 'Update the configuration of an existing stack',
|
380
|
+
proc: lambda { |v| @options[:action] = :update}
|
381
|
+
option :listparams,
|
382
|
+
short: '-l',
|
383
|
+
long: '--list-params',
|
384
|
+
description: 'List the parameters in the template, and show what values are supplied by your config file',
|
385
|
+
proc: lambda { |v| @options[:action] = :listparams}
|
386
|
+
option :configure,
|
387
|
+
short: '-C',
|
388
|
+
long: '--configure',
|
389
|
+
description: 'Run pre-defined ansible playbooks against the given stack. Implies -b',
|
390
|
+
proc: lambda { |v| @options[:action] = :configure}
|
391
|
+
option :status,
|
392
|
+
short: '-s',
|
393
|
+
long: '--status',
|
394
|
+
description: 'Run pre-defined ansible playbooks against the given stack. Implies -b',
|
395
|
+
proc: lambda { |v| @options[:action] = :status}
|
396
|
+
option :template,
|
397
|
+
short: '-t',
|
398
|
+
long: '--template FILE',
|
399
|
+
description: "Specify a template to run. Note that specific outputs are expected, so results may vary. Default #{::Aws::Cfn::Stacker::Application.defaultoptions[:template_file]}",
|
400
|
+
proc: lambda { |v| @options[:template_file] = v }
|
401
|
+
option :template_file,
|
402
|
+
long: '--template-file FILE',
|
403
|
+
description: "Specify a template to run. Note that specific outputs are expected, so results may vary. Default #{::Aws::Cfn::Stacker::Application.defaultoptions[:template_file]}"
|
404
|
+
option :template_file_alt,
|
405
|
+
long: '--template_file FILE',
|
406
|
+
description: "Specify a template to run. Note that specific outputs are expected, so results may vary. Default #{::Aws::Cfn::Stacker::Application.defaultoptions[:template_file]}",
|
407
|
+
proc: lambda { |v| @options[:template_file] = v }
|
408
|
+
option :template_url_alt,
|
409
|
+
long: '--template-url URL',
|
410
|
+
description: 'Specify the URL of a template stored in an S3 bucket to run. This method assumes the template has already been uploaded.',
|
411
|
+
proc: lambda { |v| @options[:template_url] = v }
|
412
|
+
option :template_url,
|
413
|
+
long: '--template_url URL',
|
414
|
+
description: 'Specify the URL of a template stored in an S3 bucket to run. This method assumes the template has already been uploaded.'
|
415
|
+
option :use_s3,
|
416
|
+
long: '--use_s3',
|
417
|
+
description: 'Use an S3 bucket to upload the template to before attempting stack run. This method assumes the template needs to be uploaded and may overwrite a key with the same name.'
|
418
|
+
option :ssh_keyfile,
|
419
|
+
short: '-k',
|
420
|
+
long: '--keyfile FILE',
|
421
|
+
description: 'The path to the SSH key file to use for SSH to hosts'
|
422
|
+
option :ssh_user,
|
423
|
+
long: '--ssh_user USER',
|
424
|
+
description: 'SSH User name'
|
425
|
+
option :ssh_user_bastion,
|
426
|
+
long: '--ssh_user_bastion USER',
|
427
|
+
description: 'Bastion SSH User name'
|
428
|
+
option :initial_setup,
|
429
|
+
short: '-i',
|
430
|
+
long: '--initial_setup FILE',
|
431
|
+
description: 'An initial setup file for Ansible'
|
432
|
+
option :output_path,
|
433
|
+
short: '-o',
|
434
|
+
long: '--output PATH',
|
435
|
+
description: 'Output folder for the Ansible build configuration'
|
436
|
+
option :roles_path,
|
437
|
+
short: '-r',
|
438
|
+
long: '--roles_path PATH',
|
439
|
+
description: 'Output folder for the Ansible build configuration'
|
440
|
+
option :progress,
|
441
|
+
short: '-p',
|
442
|
+
long: '--progress',
|
443
|
+
description: 'Print a progress indicator during stack create/update/delete.'
|
444
|
+
option :log_file_alt,
|
445
|
+
long: '--log-file PATH',
|
446
|
+
description: 'Log destination file',
|
447
|
+
proc: lambda { |v| @options[:log_file] = v }
|
448
|
+
option :log_file,
|
449
|
+
long: '--log_file PATH',
|
450
|
+
description: 'Log destination file'
|
451
|
+
option :log_level_alt,
|
452
|
+
long: '--log-level LEVEL',
|
453
|
+
description: 'Logging level',
|
454
|
+
proc: lambda{|v|
|
455
|
+
if ::Aws::Cfn::Stacker::Application.loglevels.include? v.to_sym
|
456
|
+
v.to_sym
|
457
|
+
else
|
458
|
+
level = ::Aws::Cfn::Stacker::Application.loglevels.select{|l| l.to_s.match(%r(^#{v}))}
|
459
|
+
unless level.size > 0
|
460
|
+
raise ::OptionParser::InvalidOption.new("Invalid log level: #{v}. Valid levels are #{::Aws::Cfn::Stacker::Application.loglevels.ai}")
|
461
|
+
end
|
462
|
+
level[0].to_sym
|
463
|
+
end
|
464
|
+
}
|
465
|
+
option :log_level,
|
466
|
+
long: '--log_level LEVEL',
|
467
|
+
description: 'Logging level',
|
468
|
+
proc: lambda{|v|
|
469
|
+
if ::Aws::Cfn::Stacker::Application.loglevels.include? v.to_sym
|
470
|
+
v.to_sym
|
471
|
+
else
|
472
|
+
level = ::Aws::Cfn::Stacker::Application.loglevels.select{|l| l.to_s.match(%r(^#{v}))}
|
473
|
+
unless level.size > 0
|
474
|
+
raise ::OptionParser::InvalidOption.new("Invalid log level: #{v}. Valid levels are #{::Aws::Cfn::Stacker::Application.loglevels.ai}")
|
475
|
+
end
|
476
|
+
level[0].to_sym
|
477
|
+
end
|
478
|
+
}
|
479
|
+
option :report_config_alt,
|
480
|
+
long: '--report-config',
|
481
|
+
description: 'Report Configuration',
|
482
|
+
proc: lambda { |v| @options[:report_config] = true }
|
483
|
+
option :report_config,
|
484
|
+
long: '--report-config',
|
485
|
+
description: 'Report Configuration'
|
486
|
+
|
487
|
+
end # included
|
488
|
+
# ------------------------------------------------------------------------------------------------------------
|
489
|
+
|
490
|
+
end
|
491
|
+
|
492
|
+
end
|
493
|
+
end
|
494
|
+
end
|
495
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Aws
|
2
|
+
module Cfn
|
3
|
+
module Stacker
|
4
|
+
module Patches
|
5
|
+
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class ::TrueClass
|
12
|
+
def to_rb
|
13
|
+
to_s
|
14
|
+
end
|
15
|
+
def to_sym
|
16
|
+
:true
|
17
|
+
end
|
18
|
+
def yesno
|
19
|
+
"yes"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class ::FalseClass
|
24
|
+
def to_rb
|
25
|
+
to_s
|
26
|
+
end
|
27
|
+
def to_sym
|
28
|
+
:false
|
29
|
+
end
|
30
|
+
def yesno
|
31
|
+
"no"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module ::Logging
|
36
|
+
class << self
|
37
|
+
def levelnames=(lnames)
|
38
|
+
remove_const(:LNAMES)
|
39
|
+
const_set(:LNAMES, lnames)
|
40
|
+
end
|
41
|
+
def levelnames()
|
42
|
+
LNAMES
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|