cfn-model 0.4.12 → 0.4.13
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
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82992d31bca207f0fdccac49ce35cd26042703ea19c9cccd6c84166c534fcb30
|
4
|
+
data.tar.gz: c73dfff8dc47c2112b3d7c31ed9ff9c88d00cb7e9519495383b54d924d4110e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0de79a70b411c0655e60e0fbc61454b4fd8b662a132a66ec56512c5ce9dce7a338c3994dd8df1fa988bc281defed281e0300197b23383034bb147b05e8dec399
|
7
|
+
data.tar.gz: 02a845a5e38a29d9d097ec1a31fdd6be34ce28760150c381e7070776fb864864a70659b58ed409eacb1b02185ec17d8debdfe00d18348c0f9da2b20e9c1f8d47
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require_relative 'references'
|
4
4
|
|
5
5
|
class CfnModel
|
6
|
-
attr_reader :resources, :parameters, :line_numbers
|
6
|
+
attr_reader :resources, :parameters, :line_numbers, :conditions
|
7
7
|
|
8
8
|
##
|
9
9
|
# if you really want it, here it is - the raw Hash from YAML.load. you'll have to mess with structural nits of
|
@@ -14,6 +14,7 @@ class CfnModel
|
|
14
14
|
def initialize
|
15
15
|
@parameters = {}
|
16
16
|
@resources = {}
|
17
|
+
@conditions = {}
|
17
18
|
@raw_model = nil
|
18
19
|
@line_numbers = {}
|
19
20
|
end
|
@@ -24,6 +25,9 @@ class CfnModel
|
|
24
25
|
# the Hash is a clone
|
25
26
|
def copy
|
26
27
|
new_cfn_model = CfnModel.new
|
28
|
+
@conditions.each do |k,v|
|
29
|
+
new_cfn_model.conditions[k] = v
|
30
|
+
end
|
27
31
|
@parameters.each do |k,v|
|
28
32
|
new_cfn_model.parameters[k] = v
|
29
33
|
end
|
@@ -38,8 +38,8 @@ class CfnParser
|
|
38
38
|
##
|
39
39
|
# Given raw json/yml CloudFormation template, returns a CfnModel object
|
40
40
|
# or raise ParserErrors if something is amiss with the format
|
41
|
-
def parse(cloudformation_yml, parameter_values_json=nil, with_line_numbers=false)
|
42
|
-
cfn_model = parse_without_parameters(cloudformation_yml, with_line_numbers)
|
41
|
+
def parse(cloudformation_yml, parameter_values_json=nil, with_line_numbers=false, condition_values_json=nil)
|
42
|
+
cfn_model = parse_without_parameters(cloudformation_yml, with_line_numbers, condition_values_json)
|
43
43
|
|
44
44
|
apply_parameter_values(cfn_model, parameter_values_json)
|
45
45
|
|
@@ -54,7 +54,7 @@ class CfnParser
|
|
54
54
|
ToRubyWithLineNumbers.create.accept(handler.root).first
|
55
55
|
end
|
56
56
|
|
57
|
-
def parse_without_parameters(cloudformation_yml, with_line_numbers=false)
|
57
|
+
def parse_without_parameters(cloudformation_yml, with_line_numbers=false, condition_values_json=nil)
|
58
58
|
pre_validate_model cloudformation_yml
|
59
59
|
|
60
60
|
cfn_hash =
|
@@ -73,6 +73,8 @@ class CfnParser
|
|
73
73
|
cfn_model = CfnModel.new
|
74
74
|
cfn_model.raw_model = cfn_hash
|
75
75
|
|
76
|
+
process_conditions cfn_hash, cfn_model, condition_values_json
|
77
|
+
|
76
78
|
# pass 1: wire properties into ModelElement objects
|
77
79
|
if with_line_numbers
|
78
80
|
transform_hash_into_model_elements_with_numbers cfn_hash, cfn_model
|
@@ -89,6 +91,24 @@ class CfnParser
|
|
89
91
|
|
90
92
|
private
|
91
93
|
|
94
|
+
def process_conditions(cfn_hash, cfn_model, condition_values_json)
|
95
|
+
if cfn_hash.key?('Conditions')
|
96
|
+
if condition_values_json.nil?
|
97
|
+
condition_values = {}
|
98
|
+
else
|
99
|
+
condition_values = JSON.load condition_values_json
|
100
|
+
end
|
101
|
+
|
102
|
+
cfn_hash['Conditions'].each do |condition_key, _|
|
103
|
+
if condition_values.key?(condition_key) && [true, false].include?(condition_values[condition_key])
|
104
|
+
cfn_model.conditions[condition_key] = condition_values[condition_key]
|
105
|
+
else
|
106
|
+
cfn_model.conditions[condition_key] = true
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
92
112
|
def apply_parameter_values(cfn_model, parameter_values_json)
|
93
113
|
ParameterSubstitution.new.apply_parameter_values(
|
94
114
|
cfn_model,
|
@@ -119,7 +139,7 @@ class CfnParser
|
|
119
139
|
resource_object.resource_type = resource['Type']
|
120
140
|
resource_object.metadata = resource['Metadata']
|
121
141
|
|
122
|
-
assign_fields_based_upon_properties resource_object, resource
|
142
|
+
assign_fields_based_upon_properties resource_object, resource, cfn_model
|
123
143
|
|
124
144
|
cfn_model.resources[resource_name] = resource_object
|
125
145
|
end
|
@@ -135,7 +155,7 @@ class CfnParser
|
|
135
155
|
resource_object.resource_type = resource['Type']['value']
|
136
156
|
resource_object.metadata = resource['Metadata']
|
137
157
|
|
138
|
-
assign_fields_based_upon_properties resource_object, resource
|
158
|
+
assign_fields_based_upon_properties resource_object, resource, cfn_model
|
139
159
|
|
140
160
|
cfn_model.resources[resource_name] = resource_object
|
141
161
|
cfn_model.line_numbers[resource_name] = resource['Type']['line']
|
@@ -175,11 +195,31 @@ class CfnParser
|
|
175
195
|
end
|
176
196
|
end
|
177
197
|
|
178
|
-
def
|
198
|
+
def deal_with_conditional_property_definitions(resource, cfn_model)
|
199
|
+
all_extra_concrete_properties = []
|
200
|
+
resource['Properties'].each do |property_name, property_value|
|
201
|
+
next if %w(Fn::Transform).include? property_name
|
202
|
+
if property_name == 'Fn::If'
|
203
|
+
concrete_properties = ExpressionEvaluator.new.evaluate(
|
204
|
+
{'Fn::If'=>property_value},
|
205
|
+
cfn_model.conditions
|
206
|
+
)
|
207
|
+
all_extra_concrete_properties << concrete_properties
|
208
|
+
end
|
209
|
+
end
|
210
|
+
all_extra_concrete_properties.each do |extra_concrete_properties|
|
211
|
+
resource['Properties'].merge!(extra_concrete_properties)
|
212
|
+
end
|
213
|
+
resource['Properties'].delete('Fn::If')
|
214
|
+
end
|
215
|
+
|
216
|
+
def assign_fields_based_upon_properties(resource_object, resource, cfn_model)
|
179
217
|
unless resource['Properties'].nil?
|
218
|
+
deal_with_conditional_property_definitions(resource, cfn_model)
|
219
|
+
|
180
220
|
resource['Properties'].each do |property_name, property_value|
|
181
|
-
next if %w(Fn::Transform
|
182
|
-
resource_object.send("#{map_property_name_to_attribute(property_name)}=", property_value)
|
221
|
+
next if %w(Fn::Transform).include? property_name
|
222
|
+
resource_object.send("#{map_property_name_to_attribute(property_name)}=", map_property_value(property_value, cfn_model))
|
183
223
|
end
|
184
224
|
end
|
185
225
|
end
|
@@ -194,6 +234,10 @@ class CfnParser
|
|
194
234
|
resource_class
|
195
235
|
end
|
196
236
|
|
237
|
+
def map_property_value(property_value, cfn_model)
|
238
|
+
ExpressionEvaluator.new.evaluate(property_value, cfn_model.conditions)
|
239
|
+
end
|
240
|
+
|
197
241
|
def map_property_name_to_attribute(str)
|
198
242
|
(str.slice(0).downcase + str[1..(str.length)]).gsub /-/, '_'
|
199
243
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class ExpressionEvaluator
|
2
|
+
FN_IF = 'Fn::If'
|
3
|
+
|
4
|
+
##
|
5
|
+
# {'Fn::If'=>[Condition,X,Y]} returns X if conditions doesn't include Condition, otherwise it return X or Y depending
|
6
|
+
#
|
7
|
+
# Other than Fn::If, it just returns the value itself
|
8
|
+
def evaluate(expression, conditions)
|
9
|
+
if if_condition?(expression)
|
10
|
+
outcome(expression, conditions)
|
11
|
+
else
|
12
|
+
expression
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def outcome(expression, conditions)
|
19
|
+
if if_condition?(expression)
|
20
|
+
if_expression = expression[FN_IF]
|
21
|
+
condition_name = if_expression[0]
|
22
|
+
if conditions[condition_name]
|
23
|
+
outcome(if_expression[1], conditions)
|
24
|
+
else
|
25
|
+
outcome(if_expression[2], conditions)
|
26
|
+
end
|
27
|
+
elsif expression.is_a?(Hash) # plain dict
|
28
|
+
expression.each do |k,v|
|
29
|
+
expression[k] = outcome(v, conditions)
|
30
|
+
end
|
31
|
+
else
|
32
|
+
expression
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def if_condition?(property_value)
|
37
|
+
property_value.is_a?(Hash) && property_value.key?(FN_IF) && property_value.size == 1
|
38
|
+
end
|
39
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cfn-model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Kascic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-01-
|
11
|
+
date: 2020-01-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubocop
|
@@ -89,6 +89,7 @@ files:
|
|
89
89
|
- lib/cfn-model/parser/cfn_parser.rb
|
90
90
|
- lib/cfn-model/parser/ec2_instance_parser.rb
|
91
91
|
- lib/cfn-model/parser/ec2_network_interface_parser.rb
|
92
|
+
- lib/cfn-model/parser/expression_evaluator.rb
|
92
93
|
- lib/cfn-model/parser/iam_group_parser.rb
|
93
94
|
- lib/cfn-model/parser/iam_role_parser.rb
|
94
95
|
- lib/cfn-model/parser/iam_user_parser.rb
|