sfn 2.2.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/bin/command-config-generator +44 -0
- data/bin/sfn +1 -5
- data/docs/README.md +2 -1
- data/docs/callbacks.md +18 -0
- data/docs/command-config.md +1276 -0
- data/docs/configuration.md +0 -105
- data/docs/overview.md +1 -0
- data/lib/sfn.rb +1 -0
- data/lib/sfn/api_provider.rb +9 -0
- data/lib/sfn/api_provider/google.rb +84 -0
- data/lib/sfn/command.rb +22 -0
- data/lib/sfn/command/create.rb +33 -45
- data/lib/sfn/command/describe.rb +1 -1
- data/lib/sfn/command/destroy.rb +7 -1
- data/lib/sfn/command/diff.rb +4 -5
- data/lib/sfn/command/graph.rb +1 -3
- data/lib/sfn/command/print.rb +3 -4
- data/lib/sfn/command/update.rb +89 -87
- data/lib/sfn/command/validate.rb +24 -11
- data/lib/sfn/command_module/base.rb +1 -12
- data/lib/sfn/command_module/stack.rb +45 -56
- data/lib/sfn/command_module/template.rb +74 -33
- data/lib/sfn/config/print.rb +5 -0
- data/lib/sfn/config/update.rb +4 -0
- data/lib/sfn/config/validate.rb +4 -0
- data/lib/sfn/monkey_patch/stack.rb +153 -83
- data/lib/sfn/monkey_patch/stack/azure.rb +23 -0
- data/lib/sfn/monkey_patch/stack/google.rb +129 -0
- data/lib/sfn/planner/aws.rb +111 -72
- data/lib/sfn/utils/json.rb +3 -0
- data/lib/sfn/utils/stack_parameter_scrubber.rb +20 -23
- data/lib/sfn/utils/stack_parameter_validator.rb +162 -157
- data/lib/sfn/version.rb +1 -1
- data/sfn.gemspec +3 -2
- metadata +34 -8
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'sfn'
|
2
|
+
|
3
|
+
module Sfn
|
4
|
+
module MonkeyPatch
|
5
|
+
module Stack
|
6
|
+
# Azure specific monkey patch implementations
|
7
|
+
module Azure
|
8
|
+
|
9
|
+
# @return [Hash] restructured azure template
|
10
|
+
# @note Will return #template if name collision encountered within resources
|
11
|
+
def sparkleish_template_azure
|
12
|
+
new_template = template.to_smash
|
13
|
+
resources = new_template.delete(:resources)
|
14
|
+
resources.each do |resource|
|
15
|
+
new_template.set(:resources, resource.delete(:name), resource)
|
16
|
+
end
|
17
|
+
resources.size == new_template[:resources].size ? new_template : template
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'sfn'
|
2
|
+
|
3
|
+
module Sfn
|
4
|
+
module MonkeyPatch
|
5
|
+
module Stack
|
6
|
+
# Google specific monkey patch implementations
|
7
|
+
module Google
|
8
|
+
|
9
|
+
# Helper module to allow nested stack behavior to function as expected
|
10
|
+
# internally within sfn
|
11
|
+
module PretendStack
|
12
|
+
|
13
|
+
# disable reload
|
14
|
+
def reload
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
# disable template load
|
19
|
+
def perform_template_load
|
20
|
+
Smash.new
|
21
|
+
end
|
22
|
+
|
23
|
+
# only show resources associated to this stack
|
24
|
+
def resources
|
25
|
+
collection = Miasma::Models::Orchestration::Stack::Resources.new(self)
|
26
|
+
collection.define_singleton_method(:perform_population) do
|
27
|
+
valid = stack.sparkleish_template.fetch(:resources, {}).keys
|
28
|
+
stack.custom[:resources].find_all{|r| valid.include?(r[:name])}.map do |attrs|
|
29
|
+
Miasma::Models::Orchestration::Stack::Resource.new(stack, attrs).valid_state
|
30
|
+
end
|
31
|
+
end
|
32
|
+
collection
|
33
|
+
end
|
34
|
+
|
35
|
+
# Sub-stacks never provide events
|
36
|
+
def events
|
37
|
+
collection = Miasma::Models::Orchestration::Stack::Events.new(self)
|
38
|
+
collection.define_singleton_method(:perform_population){ [] }
|
39
|
+
collection
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Return all stacks contained within this stack
|
44
|
+
#
|
45
|
+
# @param recurse [TrueClass, FalseClass] recurse to fetch _all_ stacks
|
46
|
+
# @return [Array<Miasma::Models::Orchestration::Stack>]
|
47
|
+
def nested_stacks_google(recurse=true)
|
48
|
+
my_template = sparkleish_template
|
49
|
+
if(my_template[:resources][name])
|
50
|
+
my_template = my_template.get(:resources, name, :properties, :stack)
|
51
|
+
end
|
52
|
+
n_stacks = my_template[:resources].map do |s_name, content|
|
53
|
+
if(content[:type] == 'sparkleformation.stack')
|
54
|
+
n_stack = self.class.new(api)
|
55
|
+
n_stack.extend PretendStack
|
56
|
+
n_layout = custom.fetch(:layout, {}).fetch(:resources, []).detect{|r| r[:name] == name}
|
57
|
+
n_layout = (n_layout || custom.fetch(:layout, {})).fetch(:resources, []).detect{|r| r[:name] == s_name} || Smash.new
|
58
|
+
n_stack.load_data(
|
59
|
+
:name => s_name,
|
60
|
+
:id => s_name,
|
61
|
+
:template => content.get(:properties, :stack),
|
62
|
+
:outputs => n_layout.fetch('outputs', []).map{|o_val| Smash.new(:key => o_val[:name], :value => o_val['finalValue'])},
|
63
|
+
:custom => {
|
64
|
+
:resources => resources.all.map(&:attributes),
|
65
|
+
:layout => n_layout
|
66
|
+
}
|
67
|
+
).valid_state
|
68
|
+
n_stack.data[:logical_id] = s_name
|
69
|
+
n_stack.data[:parent_stack] = self
|
70
|
+
n_stack
|
71
|
+
end
|
72
|
+
end.compact
|
73
|
+
if(recurse)
|
74
|
+
(n_stacks + n_stacks.map(&:nested_stacks)).flatten.compact
|
75
|
+
else
|
76
|
+
n_stacks
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# @return [Hash] restructured google template
|
81
|
+
def sparkleish_template_google(*args)
|
82
|
+
copy_template = template.to_smash
|
83
|
+
deref = lambda do |template|
|
84
|
+
result = template.to_smash
|
85
|
+
(result.delete(:resources) || []).each do |t_resource|
|
86
|
+
t_name = t_resource.delete(:name)
|
87
|
+
if(t_resource[:type].to_s.end_with?('.jinja'))
|
88
|
+
schema = copy_template.fetch(:config, :content, :imports, []).delete("#{t_resource[:type]}.schema")
|
89
|
+
schema_content = copy_template.fetch(:imports, []).detect do |s_item|
|
90
|
+
s_item[:name] == schema
|
91
|
+
end
|
92
|
+
if(schema_content)
|
93
|
+
t_resource.set(:parameters, schema_content.get(:content, :properties))
|
94
|
+
end
|
95
|
+
n_template = copy_template.fetch(:imports, []).detect do |s_item|
|
96
|
+
s_item[:name] == t_resource[:type]
|
97
|
+
end
|
98
|
+
if(n_template)
|
99
|
+
t_resource[:type] = 'sparkleformation.stack'
|
100
|
+
current_properties = t_resource.delete(:properties)
|
101
|
+
t_resource.set(:properties, :parameters, current_properties) if current_properties
|
102
|
+
t_resource.set(:properties, :stack, deref.call(n_template[:content]))
|
103
|
+
end
|
104
|
+
end
|
105
|
+
result.set(:resources, t_name, t_resource)
|
106
|
+
end
|
107
|
+
result
|
108
|
+
end
|
109
|
+
s_template = deref.call(Smash.new(:resources => copy_template.get(:config, :content, :resources)))
|
110
|
+
if(s_template.empty?)
|
111
|
+
template.to_smash
|
112
|
+
else
|
113
|
+
layout = custom.fetch(:layout, {}).to_smash
|
114
|
+
(layout.delete(:resources) || []).each do |l_resource|
|
115
|
+
layout.set(:resources, l_resource.delete(:name), l_resource)
|
116
|
+
end
|
117
|
+
args.include?(:remove_wrapper) ? s_template.get(:resources, name, :properties, :stack) : s_template
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# @return [Hash]
|
122
|
+
def root_parameters_google
|
123
|
+
sparkleish_template.fetch(:resources, name, :properties, :parameters, Smash.new)
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
data/lib/sfn/planner/aws.rb
CHANGED
@@ -108,7 +108,8 @@ module Sfn
|
|
108
108
|
|
109
109
|
# Resources that will be replaced on metadata init updates
|
110
110
|
REPLACE_ON_CFN_INIT_UPDATE = [
|
111
|
-
'AWS::AutoScaling::LaunchConfiguration'
|
111
|
+
'AWS::AutoScaling::LaunchConfiguration',
|
112
|
+
'AWS::EC2::Instance'
|
112
113
|
]
|
113
114
|
|
114
115
|
# @return [Smash] initialized translators
|
@@ -145,7 +146,6 @@ module Sfn
|
|
145
146
|
:unavailable => Smash.new,
|
146
147
|
:unknown => Smash.new
|
147
148
|
)
|
148
|
-
# scrub_stack_properties(template)
|
149
149
|
result
|
150
150
|
end
|
151
151
|
|
@@ -203,17 +203,21 @@ module Sfn
|
|
203
203
|
origin_template = dereference_template(
|
204
204
|
"#{stack.data.checksum}_origin",
|
205
205
|
stack.template,
|
206
|
-
Smash[
|
206
|
+
Smash[
|
207
|
+
stack.parameters.map do |k,v|
|
208
|
+
[k, v.to_s]
|
209
|
+
end
|
210
|
+
].merge(get_global_parameters(stack))
|
207
211
|
)
|
208
212
|
|
209
|
-
|
210
|
-
run_stack_diff(stack,
|
213
|
+
translator_key = "#{stack.data.checksum}_#{stack.data.fetch(:logical_id, stack.name)}"
|
214
|
+
run_stack_diff(stack, translator_key, plan_results, origin_template, new_template, new_parameters)
|
211
215
|
|
212
216
|
new_checksum = nil
|
213
217
|
current_checksum = false
|
214
218
|
until(new_checksum == current_checksum)
|
215
219
|
current_checksum = plan_results.checksum
|
216
|
-
run_stack_diff(stack,
|
220
|
+
run_stack_diff(stack, translator_key, plan_results, origin_template, new_template, new_parameters)
|
217
221
|
new_checksum = plan_results.checksum
|
218
222
|
end
|
219
223
|
scrub_plan(plan_results)
|
@@ -249,6 +253,7 @@ module Sfn
|
|
249
253
|
# Run the stack diff and populate the result set
|
250
254
|
#
|
251
255
|
# @param stack [Miasma::Models::Orchestration::Stack] existing stack
|
256
|
+
# @param t_key [String] translator key
|
252
257
|
# @param plan_result [Smash] plan data to populate
|
253
258
|
# @param origin_template [Smash] template of existing stack
|
254
259
|
# @param new_template [Smash] template to replace existing
|
@@ -256,7 +261,6 @@ module Sfn
|
|
256
261
|
# @return [NilClass]
|
257
262
|
def run_stack_diff(stack, t_key, plan_results, origin_template, new_template, new_parameters)
|
258
263
|
translator = translator_for(t_key)
|
259
|
-
|
260
264
|
new_parameters = new_parameters.dup
|
261
265
|
if(stack.parameters)
|
262
266
|
stack.parameters.each do |k,v|
|
@@ -266,50 +270,12 @@ module Sfn
|
|
266
270
|
end
|
267
271
|
end
|
268
272
|
end
|
269
|
-
|
270
273
|
new_parameters.merge!(get_global_parameters(stack))
|
271
|
-
|
272
274
|
new_template_hash = new_template.to_smash
|
273
|
-
|
274
|
-
o_nested_stacks = origin_template.fetch('Resources', {}).find_all do |s_name, s_val|
|
275
|
-
is_stack?(s_val['Type'])
|
276
|
-
end.map(&:first)
|
277
|
-
n_nested_stacks = (new_template_hash['Resources'] || {}).find_all do |s_name, s_val|
|
278
|
-
is_stack?(s_val['Type'])
|
279
|
-
end.map(&:first)
|
280
|
-
[o_nested_stacks + n_nested_stacks].flatten.compact.uniq.each do |n_name|
|
281
|
-
o_stack = stack.nested_stacks(false).detect{|s| s.data[:logical_id] == n_name}
|
282
|
-
n_exists = is_stack?(new_template_hash.get('Resources', n_name, 'Type'))
|
283
|
-
n_template = new_template_hash.get('Resources', n_name, 'Properties', 'Stack')
|
284
|
-
n_parameters = new_template_hash.fetch('Resources', n_name, 'Properties', 'Parameters', Smash.new)
|
285
|
-
n_type = new_template_hash.fetch('Resources', n_name, 'Type',
|
286
|
-
origin_template.get('Resources', n_name, 'Type')
|
287
|
-
)
|
288
|
-
resource = Smash.new(
|
289
|
-
:name => n_name,
|
290
|
-
:type => n_type,
|
291
|
-
:properties => []
|
292
|
-
)
|
293
|
-
if(o_stack && n_template)
|
294
|
-
n_parameters.keys.each do |n_key|
|
295
|
-
n_parameters[n_key] = translator.dereference(n_parameters[n_key])
|
296
|
-
end
|
297
|
-
n_results = plan_stack(o_stack, n_template, n_parameters)
|
298
|
-
unless(n_results[:outputs].empty?)
|
299
|
-
n_results[:outputs].keys.each do |n_output|
|
300
|
-
translator.flag_ref("#{n_name}_Outputs.#{n_output}")
|
301
|
-
end
|
302
|
-
end
|
303
|
-
plan_results[:stacks][n_name] = n_results
|
304
|
-
elsif(o_stack && (!n_template && !n_exists))
|
305
|
-
plan_results[:removed][n_name] = resource
|
306
|
-
elsif(n_template && !o_stack)
|
307
|
-
plan_results[:added][n_name] = resource
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
275
|
scrub_stack_properties(new_template_hash)
|
312
276
|
|
277
|
+
plan_nested_stacks(stack, translator, origin_template, new_template_hash, plan_results)
|
278
|
+
|
313
279
|
update_template = dereference_template(
|
314
280
|
t_key, new_template_hash, new_parameters,
|
315
281
|
plan_results[:replace].keys + plan_results[:unavailable].keys
|
@@ -320,23 +286,72 @@ module Sfn
|
|
320
286
|
end.each do |a_path, diff_items|
|
321
287
|
register_diff(
|
322
288
|
plan_results, a_path, diff_items, translator_for(t_key),
|
323
|
-
|
324
|
-
|
289
|
+
Smash.new(
|
290
|
+
:origin => origin_template,
|
291
|
+
:update => update_template
|
292
|
+
)
|
325
293
|
)
|
326
294
|
end
|
327
295
|
nil
|
328
296
|
end
|
329
297
|
|
330
|
-
#
|
298
|
+
# Extract nested stacks and generate plans
|
331
299
|
#
|
332
|
-
# @param
|
333
|
-
# @param
|
334
|
-
# @param
|
335
|
-
# @param
|
336
|
-
# @
|
337
|
-
# @
|
338
|
-
def
|
339
|
-
|
300
|
+
# @param stack [Miasma::Orchestration::Models::Stack]
|
301
|
+
# @param translator [Translator]
|
302
|
+
# @param origin_template [Smash]
|
303
|
+
# @param new_template_hash [Smash]
|
304
|
+
# @param plan_results [Smash]
|
305
|
+
# @return [NilClass]
|
306
|
+
def plan_nested_stacks(stack, translator, origin_template, new_template_hash, plan_results)
|
307
|
+
origin_stacks = origin_template.fetch('Resources', {}).find_all do |s_name, s_val|
|
308
|
+
is_stack?(s_val['Type'])
|
309
|
+
end.map(&:first)
|
310
|
+
new_stacks = (new_template_hash['Resources'] || {}).find_all do |s_name, s_val|
|
311
|
+
is_stack?(s_val['Type'])
|
312
|
+
end.map(&:first)
|
313
|
+
[origin_stacks + new_stacks].flatten.compact.uniq.each do |stack_name|
|
314
|
+
original_stack = stack.nested_stacks(false).detect do |stk|
|
315
|
+
stk.data[:logical_id] == stack_name
|
316
|
+
end
|
317
|
+
new_stack_exists = is_stack?(new_template_hash.get('Resources', stack_name, 'Type'))
|
318
|
+
new_stack_template = new_template_hash.get('Resources', stack_name, 'Properties', 'Stack')
|
319
|
+
new_stack_parameters = new_stack_template.fetch('Parameters', Smash.new)
|
320
|
+
new_stack_type = new_template_hash.fetch('Resources', stack_name, 'Type',
|
321
|
+
origin_template.get('Resources', stack_name, 'Type')
|
322
|
+
)
|
323
|
+
resource = Smash.new(
|
324
|
+
:name => stack_name,
|
325
|
+
:type => new_stack_type,
|
326
|
+
:properties => []
|
327
|
+
)
|
328
|
+
if(original_stack && new_stack_template)
|
329
|
+
new_stack_parameters = Smash[
|
330
|
+
new_stack_parameters.map do |new_param_key, new_param_value|
|
331
|
+
[new_param_key, translator.dereference(new_param_value)]
|
332
|
+
end
|
333
|
+
]
|
334
|
+
result = plan_stack(original_stack, new_stack_template, new_stack_parameters)
|
335
|
+
result[:outputs].keys.each do |modified_output|
|
336
|
+
translator.flag_ref("#{stack_name}_Outputs.#{modified_output}")
|
337
|
+
end
|
338
|
+
plan_results[:stacks][stack_name] = result
|
339
|
+
elsif(original_stack && (!new_stack_template && !new_stack_exists))
|
340
|
+
plan_results[:removed][stack_name] = resource
|
341
|
+
elsif(new_stack_template && !original_stack)
|
342
|
+
plan_results[:added][stack_name] = resource
|
343
|
+
end
|
344
|
+
end
|
345
|
+
nil
|
346
|
+
end
|
347
|
+
|
348
|
+
# Initialize the diff result hash
|
349
|
+
#
|
350
|
+
# @param diff [Array] Hashdiff result entry
|
351
|
+
# @param path [String] modification path within structure
|
352
|
+
# @return [Smash]
|
353
|
+
def diff_init(diff, path)
|
354
|
+
Smash.new.tap do |di|
|
340
355
|
if(diff.size > 1)
|
341
356
|
updated = diff.detect{|x| x.first == '+'}
|
342
357
|
original = diff.detect{|x| x.first == '-'}
|
@@ -353,12 +368,24 @@ module Sfn
|
|
353
368
|
end
|
354
369
|
end
|
355
370
|
end
|
371
|
+
end
|
372
|
+
|
373
|
+
# Register a diff item into the results set
|
374
|
+
#
|
375
|
+
# @param results [Hash]
|
376
|
+
# @param path [String]
|
377
|
+
# @param diff [Array]
|
378
|
+
# @param templates [Smash]
|
379
|
+
# @option :templates [Smash] :origin
|
380
|
+
# @option :templates [Smash] :update
|
381
|
+
def register_diff(results, path, diff, translator, templates)
|
382
|
+
diff_info = diff_init(diff, path)
|
356
383
|
if(path.start_with?('Resources'))
|
357
384
|
p_path = path.split('.')
|
358
385
|
if(p_path.size == 2)
|
359
386
|
diff = diff.first
|
360
387
|
key = diff.first == '+' ? :added : :removed
|
361
|
-
type = (key == :added ? templates[:update] : templates[:origin])
|
388
|
+
type = (key == :added ? templates[:update] : templates[:origin]).get('Resources', p_path.last, 'Type')
|
362
389
|
results[key][p_path.last] = Smash.new(
|
363
390
|
:name => p_path.last,
|
364
391
|
:type => type,
|
@@ -375,9 +402,7 @@ module Sfn
|
|
375
402
|
else
|
376
403
|
property_name = p_path[3].to_s.sub(/\[\d+\]$/, '')
|
377
404
|
end
|
378
|
-
type = templates
|
379
|
-
info = SfnAws.registry.fetch(type, {}).to_smash
|
380
|
-
effect = info.fetch(:full_properties, property_name, :update_causes, :unknown).to_sym
|
405
|
+
type = templates.get(:origin, 'Resources', resource_name, 'Type')
|
381
406
|
resource = Smash.new(
|
382
407
|
:name => resource_name,
|
383
408
|
:type => type,
|
@@ -386,16 +411,30 @@ module Sfn
|
|
386
411
|
diff_info.merge(:property_name => property_name)
|
387
412
|
]
|
388
413
|
)
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
414
|
+
begin
|
415
|
+
r_info = SparkleFormation::Resources::Aws.resource_lookup(type)
|
416
|
+
r_property = r_info.property(property_name)
|
417
|
+
if(r_property)
|
418
|
+
effect = r_property.update_causes(
|
419
|
+
templates.get(:update, 'Resources', resource_name),
|
420
|
+
templates.get(:origin, 'Resources', resource_name)
|
421
|
+
)
|
422
|
+
else
|
423
|
+
raise KeyError.new 'Unknown property'
|
424
|
+
end
|
425
|
+
case effect.to_sym
|
426
|
+
when :replacement
|
427
|
+
set_resource(:replace, results, resource_name, resource)
|
428
|
+
when :interrupt
|
429
|
+
set_resource(:interrupt, results, resource_name, resource)
|
430
|
+
when :unavailable
|
431
|
+
set_resource(:unavailable, results, resource_name, resource)
|
432
|
+
when :none
|
433
|
+
# \o/
|
434
|
+
else
|
435
|
+
set_resource(:unknown, results, resource_name, resource)
|
436
|
+
end
|
437
|
+
rescue KeyError
|
399
438
|
set_resource(:unknown, results, resource_name, resource)
|
400
439
|
end
|
401
440
|
elsif(p_path.include?('AWS::CloudFormation::Init'))
|
data/lib/sfn/utils/json.rb
CHANGED
@@ -13,6 +13,7 @@ module Sfn
|
|
13
13
|
def _to_json(thing)
|
14
14
|
MultiJson.dump(thing)
|
15
15
|
end
|
16
|
+
alias_method :dump_json, :_to_json
|
16
17
|
|
17
18
|
# Load JSON data
|
18
19
|
#
|
@@ -21,6 +22,7 @@ module Sfn
|
|
21
22
|
def _from_json(thing)
|
22
23
|
MultiJson.load(thing)
|
23
24
|
end
|
25
|
+
alias_method :load_json, :_from_json
|
24
26
|
|
25
27
|
# Format object into pretty JSON
|
26
28
|
#
|
@@ -30,6 +32,7 @@ module Sfn
|
|
30
32
|
thing = _from_json(thing) if thing.is_a?(String)
|
31
33
|
MultiJson.dump(thing, :pretty => true)
|
32
34
|
end
|
35
|
+
alias_method :format_json, :_format_json
|
33
36
|
|
34
37
|
end
|
35
38
|
|
@@ -3,35 +3,32 @@ require 'sfn'
|
|
3
3
|
module Sfn
|
4
4
|
module Utils
|
5
5
|
# Helper for scrubbing stack parameters
|
6
|
-
|
6
|
+
module StackParameterScrubber
|
7
7
|
|
8
|
-
|
8
|
+
# Validate attributes within Parameter blocks
|
9
|
+
ALLOWED_PARAMETER_ATTRIBUTES = %w(
|
10
|
+
Type Default NoEcho AllowedValues AllowedPattern
|
11
|
+
MaxLength MinLength MaxValue MinValue Description
|
12
|
+
ConstraintDescription
|
13
|
+
)
|
9
14
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
# @return [Hash] template
|
21
|
-
def scrub!(template)
|
22
|
-
parameters = template['Parameters']
|
23
|
-
if(parameters)
|
24
|
-
parameters.each do |name, options|
|
25
|
-
options.delete_if do |attribute, value|
|
26
|
-
!ALLOWED_PARAMETER_ATTRIBUTES.include?(attribute)
|
27
|
-
end
|
15
|
+
# Clean the parameters of the template
|
16
|
+
#
|
17
|
+
# @param template [Hash]
|
18
|
+
# @return [Hash] template
|
19
|
+
def parameter_scrub!(template)
|
20
|
+
parameters = template['Parameters']
|
21
|
+
if(parameters)
|
22
|
+
parameters.each do |name, options|
|
23
|
+
options.delete_if do |attribute, value|
|
24
|
+
!ALLOWED_PARAMETER_ATTRIBUTES.include?(attribute)
|
28
25
|
end
|
29
|
-
template['Parameters'] = parameters
|
30
26
|
end
|
31
|
-
template
|
27
|
+
template['Parameters'] = parameters
|
32
28
|
end
|
33
|
-
|
29
|
+
template
|
34
30
|
end
|
31
|
+
|
35
32
|
end
|
36
33
|
end
|
37
34
|
end
|