cloudformation-ruby-dsl 1.3.2 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 57fff8ca0d99312692f6c33807de5aa47a6985c0
4
- data.tar.gz: c8b847f425907f314e78696a856ffd1179e7f715
3
+ metadata.gz: 1fc27537e778d1d9bf9b8886047e87f578e93f3a
4
+ data.tar.gz: ba288ca3b0e250854b5f7c45485d963a4cd27a37
5
5
  SHA512:
6
- metadata.gz: d4caeec967852e730b440ceb33975a8c863fabed84e92907aea1b8c158490cdf0a7b485f42a1e23cb2e1586ff70dd6026b80997791fe6693b0065e2946c2885d
7
- data.tar.gz: f906f46d8980cc727d1db1c21c7a8468c8ee37f324e833783ed3807fc108ed48d759c80f9171f092f994ca4e00b1966a87b32a4fe8eefa7b0dd00959a133fddc
6
+ metadata.gz: 7179312a3f4a3462c7de36b9e0ec77f42d1c2bca68e8d52e0cfe9cb3a19d9c97abcf3d04aaa92a3e844aa0a5dc27d67757e0777d5d6e9ac6cd55d6c597ff09ab
7
+ data.tar.gz: b6f097b17b653d267a0f07a946fbeab1996b82604bf9386b749c3bc88337f82de741adc3fe02bc697c0f260f1f2ffef975c1e7d26319351e55268218ed331e5e
@@ -2,8 +2,9 @@
2
2
  require 'bundler/setup'
3
3
  require 'cloudformation-ruby-dsl/cfntemplate'
4
4
 
5
- template = template do
5
+ tmpl = template do
6
+ @stack_name = "hello-bucket-example"
6
7
  resource "HelloBucket", :Type => "AWS::S3::Bucket"
7
8
  end
8
9
 
9
- template.exec!
10
+ tmpl.exec!
@@ -91,9 +91,10 @@ def parse_args
91
91
  when '--stack-name'
92
92
  args[:stack_name] = value
93
93
  when '--parameters'
94
- args[:parameters] = Hash[value.split(/;\s*/).map { |pair| pair.split(/=/, 2) }] #/# fix for syntax highlighting
94
+ args[:parameters] = Hash[value.split(/;/).map { |pair| parts = pair.split(/=/, 2); [ parts[0], Parameter.new(parts[1]) ] }] #/# fix for syntax highlighting
95
95
  when '--interactive'
96
96
  args[:interactive] = true
97
+ default and previous values of a parameter. Updated excise_parameter_attributes! to support multiple parameters.
97
98
  when '--region'
98
99
  args[:region] = value
99
100
  when '--profile'
@@ -155,9 +156,9 @@ def cfn(template)
155
156
 
156
157
  action = validate_action( ARGV[0] )
157
158
 
158
- # Find parameters where extension attribute :Immutable is true then remove it from the
159
+ # Find parameters where extension attributes are true then remove them from the
159
160
  # cfn template since we can't pass it to CloudFormation.
160
- immutable_parameters = template.excise_parameter_attribute!(:Immutable)
161
+ excised_parameters = template.excise_parameter_attributes!([:Immutable, :UsePreviousValue])
161
162
 
162
163
  # Tag CloudFormation stacks based on :Tags defined in the template.
163
164
  # Remove them from the template as well, so that the template is valid.
@@ -231,15 +232,15 @@ def cfn(template)
231
232
  # there is only ever one stack, since stack names are unique
232
233
  old_attributes = cfn_client.describe_stacks({stack_name: stack_name}).stacks[0]
233
234
  old_tags = old_attributes.tags
234
- old_parameters = old_attributes.parameters
235
+ old_parameters = Hash[old_attributes.parameters.map { |p| [p.parameter_key, p.parameter_value]}]
235
236
 
236
237
  # Sort the tag strings alphabetically to make them easily comparable
237
238
  old_tags_string = old_tags.map { |tag| %Q(TAG "#{tag.key}=#{tag.value}"\n) }.sort.join
238
239
  tags_string = cfn_tags.map { |k, v| %Q(TAG "#{k.to_s}=#{v}"\n) }.sort.join
239
240
 
240
241
  # Sort the parameter strings alphabetically to make them easily comparable
241
- old_parameters_string = old_parameters.sort! {|pCurrent, pNext| pCurrent.parameter_key <=> pNext.parameter_key }.map { |param| %Q(PARAMETER "#{param.parameter_key}=#{param.parameter_value}"\n) }.join
242
- parameters_string = template.parameters.sort.map { |key, value| "PARAMETER \"#{key}=#{value}\"\n" }.join
242
+ old_parameters_string = old_parameters.sort.map { |key, value| %Q(PARAMETER "#{key}=#{value}"\n) }.join
243
+ parameters_string = template.parameters.sort.map { |key, value| "PARAMETER \"#{key}=#{!(value.empty? && value.use_previous_value) ? value : old_parameters[key]}\"\n" }.join
243
244
 
244
245
  # set default diff options
245
246
  Diffy::Diff.default_options.merge!(
@@ -294,6 +295,9 @@ def cfn(template)
294
295
  when 'create'
295
296
  begin
296
297
 
298
+ # Apply any default parameter values
299
+ apply_parameter_defaults(template.parameters)
300
+
297
301
  # default options (not overridable)
298
302
  create_stack_opts = {
299
303
  stack_name: stack_name,
@@ -435,16 +439,30 @@ def cfn(template)
435
439
  end
436
440
 
437
441
  # If updating a stack and some parameters or tags are marked as immutable, set the variable to true.
438
- immutables_exist = nil
439
-
440
- if not immutable_parameters.empty?
441
- old_parameters = Hash[old_stack.parameters.map { |p| [p.parameter_key, p.parameter_value]}]
442
- new_parameters = template.parameters
443
- immutable_parameters.sort.each do |param|
444
- if old_parameters[param].to_s != new_parameters[param].to_s && old_parameters.key?(param)
445
- $stderr.puts "Error: unable to update immutable parameter " +
446
- "'#{param}=#{old_parameters[param]}' to '#{param}=#{new_parameters[param]}'."
447
- immutables_exist = true
442
+ immutables_exist = nil
443
+
444
+ old_parameters = Hash[old_stack.parameters.map { |p| [p.parameter_key, p.parameter_value]}]
445
+ new_parameters = template.parameters
446
+ excised_parameters.each do |extension_attribute, parameters|
447
+ if !parameters.empty?
448
+ parameters.sort.each do |param|
449
+ if old_parameters[param] != new_parameters[param] && old_parameters.key?(param)
450
+ case extension_attribute
451
+ when :Immutable
452
+ if !excised_parameters[:UsePreviousValue].include?(param)
453
+ $stderr.puts "Error: unable to update immutable parameter " +
454
+ "'#{param}=#{old_parameters[param]}' to '#{param}=#{new_parameters[param]}'."
455
+ immutables_exist = true
456
+ end
457
+ when :UsePreviousValue
458
+ if !immutables_exist && new_parameters[param].empty?
459
+ $stderr.puts "Using previous parameter " +
460
+ "'#{param}=#{old_parameters[param]}'."
461
+ new_parameters[param] = Parameter.new(old_parameters[param])
462
+ new_parameters[param].use_previous_value = true
463
+ end
464
+ end
465
+ end
448
466
  end
449
467
  end
450
468
  end
@@ -466,6 +484,9 @@ def cfn(template)
466
484
  exit(false)
467
485
  end
468
486
 
487
+ # Apply any default parameter values
488
+ apply_parameter_defaults(template.parameters)
489
+
469
490
  # Compare the sorted arrays of parameters for an exact match and print difference.
470
491
  old_parameters = old_stack.parameters.map { |p| [p.parameter_key, p.parameter_value]}.sort
471
492
  new_parameters = template.parameters.sort
@@ -493,7 +514,7 @@ def cfn(template)
493
514
  update_stack_opts = {
494
515
  stack_name: stack_name,
495
516
  template_body: template_string,
496
- parameters: template.parameters.map { |k,v| {parameter_key: k, parameter_value: v}}.to_a,
517
+ parameters: template.parameters.map { |k,v| (v.use_previous_value && old_parameters[0].include?(k)) ? {parameter_key: k, use_previous_value: v.use_previous_value.to_s} : {parameter_key: k, parameter_value: v}}.to_a,
497
518
  tags: cfn_tags.map { |k,v| {"key" => k.to_s, "value" => v.to_s} }.to_a,
498
519
  capabilities: ["CAPABILITY_NAMED_IAM"],
499
520
  }
@@ -569,6 +590,17 @@ def parse_arg_array_as_hash(options)
569
590
  result
570
591
  end
571
592
 
593
+ # Apply the default value for any parameter not assigned by the user
594
+ def apply_parameter_defaults(parameters)
595
+ parameters.each do |k, v|
596
+ if v.empty?
597
+ parameters[k] = Parameter.new(v.default)
598
+ $stderr.puts "Using default parameter value " +
599
+ "'#{k}=#{parameters[k]}'."
600
+ end
601
+ end
602
+ end
603
+
572
604
  ##################################### Additional dsl logic
573
605
  # Core interpreter for the DSL
574
606
  class TemplateDSL < JsonObjectDSL
@@ -52,6 +52,14 @@ def default_region
52
52
  ENV['EC2_REGION'] || ENV['AWS_DEFAULT_REGION'] || 'us-east-1'
53
53
  end
54
54
 
55
+ class Parameter < String
56
+ attr_accessor :default, :use_previous_value
57
+
58
+ def initialize string
59
+ super string.to_s
60
+ end
61
+ end
62
+
55
63
  # Core interpreter for the DSL
56
64
  class TemplateDSL < JsonObjectDSL
57
65
  attr_reader :parameters,
@@ -81,16 +89,21 @@ class TemplateDSL < JsonObjectDSL
81
89
  if @interactive
82
90
  @parameters[name] ||= _get_parameter_from_cli(name, options)
83
91
  else
84
- @parameters[name] ||= options[:Default]
92
+ @parameters[name] ||= Parameter.new('')
93
+ @parameters[name].default = options[:Default]
94
+ @parameters[name].use_previous_value = options[:UsePreviousValue]
85
95
  end
86
96
  end
87
97
 
88
98
  # Find parameters where the specified attribute is true then remove the attribute from the cfn template.
89
- def excise_parameter_attribute!(attribute)
90
- marked_parameters = []
99
+ def excise_parameter_attributes!(attributes)
100
+ marked_parameters = {}
91
101
  @dict.fetch(:Parameters, {}).each do |param, options|
92
- if options.delete(attribute.to_sym) or options.delete(attribute.to_s)
93
- marked_parameters << param
102
+ attributes.each do |attribute|
103
+ marked_parameters[attribute] ||= []
104
+ if options.delete(attribute.to_sym) or options.delete(attribute.to_s)
105
+ marked_parameters[attribute] << param
106
+ end
94
107
  end
95
108
  end
96
109
  marked_parameters
@@ -15,7 +15,7 @@
15
15
  module Cfn
16
16
  module Ruby
17
17
  module Dsl
18
- VERSION = "1.3.2"
18
+ VERSION = "1.4.0"
19
19
  end
20
20
  end
21
21
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudformation-ruby-dsl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shawn Smith