cloudformation-ruby-dsl 1.3.2 → 1.4.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 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