cfndsl 1.0.6 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CfnDsl
4
- VERSION = '1.0.6'
4
+ VERSION = '1.3.1'
5
5
  end
@@ -120,16 +120,16 @@ module DeepMerge
120
120
  puts "#{di} looping: #{src_key.inspect} => #{src_value.inspect} :: #{dest.inspect}" if merge_debug
121
121
  if dest[src_key]
122
122
  puts "#{di} ==>merging: #{src_key.inspect} => #{src_value.inspect} :: #{dest[src_key].inspect}" if merge_debug
123
- dest[src_key] = deep_merge!(src_value, dest[src_key], options.merge(debug_indent: di + ' '))
123
+ dest[src_key] = deep_merge!(src_value, dest[src_key], options.merge(debug_indent: "#{di} "))
124
124
  else # dest[src_key] doesn't exist so we want to create and overwrite it (but we do this via deep_merge!)
125
125
  puts "#{di} ==>merging over: #{src_key.inspect} => #{src_value.inspect}" if merge_debug
126
- # note: we rescue here b/c some classes respond to "dup" but don't implement it (Numeric, TrueClass, FalseClass, NilClass among maybe others)
126
+ # NOTE: we rescue here b/c some classes respond to "dup" but don't implement it (Numeric, TrueClass, FalseClass, NilClass among maybe others)
127
127
  begin
128
128
  src_dup = src_value.dup # we dup src_value if possible because we're going to merge into it (since dest is empty)
129
129
  rescue TypeError
130
130
  src_dup = src_value
131
131
  end
132
- dest[src_key] = deep_merge!(src_value, src_dup, options.merge(debug_indent: di + ' '))
132
+ dest[src_key] = deep_merge!(src_value, src_dup, options.merge(debug_indent: "#{di} "))
133
133
  end
134
134
  elsif dest.is_a?(Array) && extend_existing_arrays
135
135
  dest.push(source)
@@ -181,12 +181,12 @@ module DeepMerge
181
181
  list = []
182
182
  dest.each_index do |i|
183
183
  list[i] = deep_merge!(source[i] || {}, dest[i],
184
- options.merge(debug_indent: di + ' '))
184
+ options.merge(debug_indent: "#{di} "))
185
185
  end
186
- list += source[dest.count..-1] if source.count > dest.count
186
+ list += source[dest.count..] if source.count > dest.count
187
187
  dest = list
188
188
  elsif keep_array_duplicates
189
- dest = dest.concat(source)
189
+ dest.concat(source)
190
190
  else
191
191
  dest |= source
192
192
  end
@@ -215,9 +215,10 @@ module DeepMerge
215
215
  knockout_prefix = options[:knockout_prefix] || false
216
216
  di = options[:debug_indent] || ''
217
217
  if knockout_prefix && overwrite_unmergeable
218
- src_tmp = if source.is_a?(String) # remove knockout string from source before overwriting dest
218
+ src_tmp = case source
219
+ when String # remove knockout string from source before overwriting dest
219
220
  source.gsub(/^#{knockout_prefix}/, '')
220
- elsif source.is_a?(Array) # remove all knockout elements before overwriting dest
221
+ when Array # remove all knockout elements before overwriting dest
221
222
  source.delete_if { |ko_item| ko_item.is_a?(String) && ko_item.match(/^#{knockout_prefix}/) }
222
223
  else
223
224
  source
@@ -23,8 +23,8 @@ CloudFormation do
23
23
 
24
24
  10.times do |i|
25
25
  subnet = "subnet#{i}"
26
- route_table = subnet + 'RouteTable'
27
- route_table_assoc = route_table + 'Assoc'
26
+ route_table = "#{subnet}RouteTable"
27
+ route_table_assoc = "#{route_table}Assoc"
28
28
 
29
29
  Subnet(subnet) do
30
30
  VpcId Ref(:VPC)
@@ -42,7 +42,7 @@ CloudFormation do
42
42
  RouteTableId Ref(route_table)
43
43
  end
44
44
 
45
- EC2_Route(subnet + 'GatewayRoute') do
45
+ EC2_Route("#{subnet}GatewayRoute") do
46
46
  DependsOn :GatewayToInternet
47
47
  RouteTableId Ref(route_table)
48
48
  DestinationCidrBlock '0.0.0.0/0'
@@ -41,8 +41,8 @@ CloudFormation do
41
41
 
42
42
  10.times do |i|
43
43
  subnet = "subnet#{i}"
44
- route_table = subnet + 'RouteTable'
45
- route_table_assoc = route_table + 'Assoc'
44
+ route_table = "#{subnet}RouteTable"
45
+ route_table_assoc = "#{route_table}Assoc"
46
46
 
47
47
  Subnet(subnet) do
48
48
  VpcId Ref(:VPC)
@@ -60,7 +60,7 @@ CloudFormation do
60
60
  RouteTableId Ref(route_table)
61
61
  end
62
62
 
63
- EC2_Route(subnet + 'GatewayRoute') do
63
+ EC2_Route("#{subnet}GatewayRoute") do
64
64
  DependsOn :GatewayToInternet
65
65
  RouteTableId Ref(route_table)
66
66
  DestinationCidrBlock '0.0.0.0/0'
@@ -188,6 +188,26 @@ describe CfnDsl::CloudFormationTemplate do
188
188
  end
189
189
  end
190
190
 
191
+ it 'composes DependsOn' do
192
+ spec = self
193
+ subject.Resource('SomeResource') do
194
+ d = DependsOn('X')
195
+ spec.expect(d).to spec.eq('X') # start with a single value, stays a single value
196
+ d = DependsOn(%w[Y Z])
197
+ spec.expect(d).to spec.eq(%w[X Y Z]) # concatenates values
198
+ d = DependsOn('Y') # uniqeness
199
+ spec.expect(d).to spec.eq(%w[X Y Z])
200
+ end
201
+ expect(subject.to_json).to eq('{"AWSTemplateFormatVersion":"2010-09-09","Resources":{"SomeResource":{"DependsOn":["X","Y","Z"]}}}')
202
+ end
203
+
204
+ it 'supports single value DependsOn' do
205
+ subject.Resource('SomeResource') do
206
+ DependsOn(:ADependency)
207
+ end
208
+ expect(subject.to_json).to eq('{"AWSTemplateFormatVersion":"2010-09-09","Resources":{"SomeResource":{"DependsOn":"ADependency"}}}')
209
+ end
210
+
191
211
  context 'built-in functions' do
192
212
  it 'FnGetAtt' do
193
213
  func = subject.FnGetAtt('A', 'B')
@@ -36,7 +36,9 @@ describe 'cfndsl', type: :aruba do
36
36
  before(:each) { write_file('template.rb', template_content) }
37
37
 
38
38
  # The known working version is the embedded version
39
+ # rubocop:disable Lint/ConstantDefinitionInBlock
39
40
  WORKING_SPEC_VERSION = JSON.parse(File.read(CfnDsl::LOCAL_SPEC_FILE))['ResourceSpecificationVersion']
41
+ # rubocop:enable Lint/ConstantDefinitionInBlock
40
42
 
41
43
  context "cfndsl -u #{WORKING_SPEC_VERSION}" do
42
44
  it 'updates the specification file' do
@@ -40,10 +40,31 @@ describe CfnDsl::CloudFormationTemplate do
40
40
  expect(subject.validate).to equal(subject)
41
41
  end
42
42
 
43
+ it 'returns self if there are valid Fn::Sub references to other resources' do
44
+ tr = subject.Resource(:TestResource)
45
+ tr.Type('Custom-TestType')
46
+ tr.Property(:AProperty, tr.FnSub('prefix ${TestResource2}suffix'))
47
+
48
+ t2 = subject.Resource('TestResource2')
49
+ t2.Type('Custom-TestType')
50
+ expect(subject.validate).to equal(subject)
51
+ end
52
+
53
+ it 'returns self if there are valid Fn::Sub references to other resource attributes' do
54
+ tr = subject.Resource(:TestResource)
55
+ tr.Type('Custom-TestType')
56
+ tr.Property(:AProperty, tr.FnSub('prefix ${TestResource2.AnAttribute}suffix'))
57
+
58
+ t2 = subject.Resource('TestResource2')
59
+ t2.Type('Custom-TestType')
60
+ expect(subject.validate).to equal(subject)
61
+ end
62
+
43
63
  it 'returns self if there are valid DependsOn to other resources' do
44
64
  tr = subject.Resource(:TestResource)
45
65
  tr.Type('Custom-TestType')
46
66
  tr.DependsOn(:TestResource2)
67
+ tr.DependsOn(:TestResource2)
47
68
 
48
69
  t2 = subject.Resource('TestResource2')
49
70
  t2.Type('Custom-TestType')
@@ -119,6 +140,13 @@ describe CfnDsl::CloudFormationTemplate do
119
140
  expect { subject.validate }.to raise_error(CfnDsl::Error, /TestResource.*itself/i)
120
141
  end
121
142
 
143
+ it 'raises CfnDsl::Error if a resourcs references itself in Fn::Sub attribute expression' do
144
+ tr = subject.Resource(:TestResource)
145
+ tr.Type('Custom-TestType')
146
+ tr.Property(:AProperty, tr.FnSub('${TestResource.attr}'))
147
+ expect { subject.validate }.to raise_error(CfnDsl::Error, /TestResource.*itself/i)
148
+ end
149
+
122
150
  it 'raises CfnDsl::Error if there are cyclic DependsOn references' do
123
151
  tr = subject.Resource(:ResourceOne)
124
152
  tr.Type('Custom-TestType')
@@ -211,6 +239,12 @@ describe CfnDsl::CloudFormationTemplate do
211
239
  expect(subject.validate).to equal(subject)
212
240
  end
213
241
 
242
+ it 'returns self if there are valid Fn::Sub references to resource attributes' do
243
+ subject.Resource(:TestResource)
244
+ subject.Output('TestResourceOutput').Value(subject.FnSub('prefix ${TestResource.attr}suffix'))
245
+ expect(subject.validate).to equal(subject)
246
+ end
247
+
214
248
  it 'raises CfnDsl::Error if references a non existent condition' do
215
249
  subject.Output(:TestOutput).Condition('NoCondition')
216
250
  expect { subject.validate }.to raise_error(CfnDsl::Error, /TestOutput.*NoCondition/)
@@ -102,6 +102,13 @@ shared_examples 'an orchestration template' do
102
102
  expect(plural_value).to eq([{ foo: 'bar' }])
103
103
  end
104
104
 
105
+ it 'allows array returning function for otherwise array value when singular name == plural name' do
106
+ security_group = described_class.type_module.const_get('AWS_EC2_SecurityGroup').new
107
+ security_group.Property('SecurityGroupIngress', security_group.FnFindInMap('x', 'y', 'z'))
108
+ plural_value = security_group.instance_variable_get('@Properties')['SecurityGroupIngress'].value
109
+ expect(plural_value.to_json).to eql('{"Fn::FindInMap":["x","y","z"]}')
110
+ end
111
+
105
112
  it 'sets the type of each resource correctly' do
106
113
  ec2_instance = subject.EC2_Instance(:foo)
107
114
  expect(ec2_instance.instance_variable_get('@Type')).to eq('AWS::EC2::Instance')
@@ -27,9 +27,10 @@ RSpec.describe 'Type Definitions' do
27
27
  it "#{name} has all property types defined" do
28
28
  type = type['Properties'] if type.is_a?(Hash) && type.key?('Properties')
29
29
  type = type.first if type.is_a?(Array)
30
- if type.is_a?(String)
30
+ case type
31
+ when String
31
32
  expect(types).to have_key(type)
32
- elsif type.is_a?(Hash)
33
+ when Hash
33
34
  type.values.flatten.each { |t| expect(types).to have_key(t) }
34
35
  else
35
36
  raise "A defined type should only be of the form String, Array or Hash, got #{type.class}"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cfndsl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.6
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Jack
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2020-04-23 00:00:00.000000000 Z
14
+ date: 2021-01-23 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -19,14 +19,14 @@ dependencies:
19
19
  requirements:
20
20
  - - "~>"
21
21
  - !ruby/object:Gem::Version
22
- version: '2.1'
22
+ version: '2.2'
23
23
  type: :development
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: '2.1'
29
+ version: '2.2'
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: hana
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -71,6 +71,7 @@ files:
71
71
  - lib/cfndsl/aws/patches/100_sam.spec_DeploymentPreference_patch.json
72
72
  - lib/cfndsl/aws/patches/200_Scrutinies_patch.json
73
73
  - lib/cfndsl/aws/patches/500_BadTagsv13.0.0_patch.json
74
+ - lib/cfndsl/aws/patches/500_BadTagsv16.2.0_patch.json
74
75
  - lib/cfndsl/aws/patches/500_Cognito_IdentityPoolRoleAttachment_patches.json
75
76
  - lib/cfndsl/aws/patches/500_IoT1Click_patch_PlacementTemplate_DeviceTemplates.json
76
77
  - lib/cfndsl/aws/patches/500_NetworkAclEntry_patch.json
@@ -83,6 +84,7 @@ files:
83
84
  - lib/cfndsl/aws/patches/600_RefKinds_patch.json
84
85
  - lib/cfndsl/aws/patches/700_SAM_Serverless_Function_InlineCode_patch.json
85
86
  - lib/cfndsl/aws/patches/800_List_types_patch.json
87
+ - lib/cfndsl/aws/patches/900_SageMakerTags_patch.json
86
88
  - lib/cfndsl/aws/resource_specification.json
87
89
  - lib/cfndsl/aws/types.rb
88
90
  - lib/cfndsl/aws/types.yaml
@@ -182,17 +184,16 @@ require_paths:
182
184
  - lib
183
185
  required_ruby_version: !ruby/object:Gem::Requirement
184
186
  requirements:
185
- - - "~>"
187
+ - - ">="
186
188
  - !ruby/object:Gem::Version
187
- version: '2.4'
189
+ version: '2.7'
188
190
  required_rubygems_version: !ruby/object:Gem::Requirement
189
191
  requirements:
190
192
  - - ">="
191
193
  - !ruby/object:Gem::Version
192
194
  version: '0'
193
195
  requirements: []
194
- rubyforge_project:
195
- rubygems_version: 2.7.7
196
+ rubygems_version: 3.0.8
196
197
  signing_key:
197
198
  specification_version: 4
198
199
  summary: AWS Cloudformation DSL