aws-cfn-stacker 0.0.1 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|