sparkle_formation 0.2.2 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +7 -1
- data/bin/generate_sparkle_docs +31 -0
- data/lib/sparkle_formation/aws.rb +6 -7
- data/lib/sparkle_formation/sparkle_attribute.rb +97 -0
- data/lib/sparkle_formation/translation/heat.rb +184 -2
- data/lib/sparkle_formation/translation/rackspace.rb +7 -3
- data/lib/sparkle_formation/translation.rb +28 -2
- data/lib/sparkle_formation/version.rb +1 -1
- data/sparkle_formation.gemspec +2 -1
- metadata +5 -33
- data/CONTRIBUTING.md +0 -25
- data/Gemfile +0 -3
- data/Gemfile.lock +0 -18
- data/bin/aws_resources +0 -85
- data/bin/heat_resources +0 -33
- data/docs/README.md +0 -177
- data/docs/anatomy.md +0 -203
- data/docs/building-blocks.md +0 -275
- data/docs/examples/cloudformation/components/base.rb +0 -25
- data/docs/examples/cloudformation/dynamics/elb.rb +0 -23
- data/docs/examples/cloudformation/templates/website.rb +0 -30
- data/docs/examples/template_json/website.json +0 -88
- data/docs/examples/website.rb +0 -74
- data/docs/functions.md +0 -41
- data/docs/properties.md +0 -32
- data/docs/provisioning.md +0 -82
- data/docs/resource-reference.md +0 -49
- data/examples/allinone/cloudformation/ec2_example.rb +0 -59
- data/examples/allinone/parse.rb +0 -14
- data/examples/ami_component/cloudformation/components/ami.rb +0 -21
- data/examples/ami_component/cloudformation/ec2_example.rb +0 -39
- data/examples/ami_component/parse.rb +0 -14
- data/test/spec.rb +0 -6
- data/test/specs/attribute.rb +0 -72
- data/test/specs/basic.rb +0 -76
- data/test/specs/cloudformation/components/ami.rb +0 -14
- data/test/specs/cloudformation/dynamics/node.rb +0 -16
- data/test/specs/results/base.json +0 -43
- data/test/specs/results/base_with_map.json +0 -50
- data/test/specs/results/component.json +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3f49e3aceb2896698cfb226e53c06f02ed9607d7
|
4
|
+
data.tar.gz: 4db5fff53aff957f05f6e933a22a273d52548457
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b5a8aea5a9c132d0f7bddf6fa537c37f2d03e7b4e4d93a58690a29c65dc441ab26e6cec640ac7965b4281f68bced0954078762f10b86c84a5e68d7af92190c58
|
7
|
+
data.tar.gz: db9da97bd24fe89858a8b822ed4ebb7ec328e24c2dc3d1646d8582236aa6f41ce8d2942a64916a8d5b4d925c9294db668916c8249afd647ee342913e117a59bc
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## v0.2.4
|
2
|
+
* Update builtin registry lookup to better handle all caps types
|
3
|
+
* Add helper methods for conditionals
|
4
|
+
* Provide better error message when dereferencing mappings that do not exist
|
5
|
+
* Add more coverage within heat translation
|
6
|
+
|
1
7
|
## v0.2.2
|
2
8
|
* Lots of translation updates (AWS -> RS "hot")
|
3
9
|
* User Documentation!
|
data/README.md
CHANGED
@@ -13,6 +13,10 @@ Yes. Well, kinda. It also has some extra features, like defining
|
|
13
13
|
components, dynamics, merging, AWS builtin function helpers, and
|
14
14
|
conjouring magic (to get unicorns).
|
15
15
|
|
16
|
+
## Expanded User Docs
|
17
|
+
|
18
|
+
New user documentation is now here! [User Documentation](http://sparkleformation.github.io/sparkle_formation/UserDocs/)
|
19
|
+
|
16
20
|
## What's it look like?
|
17
21
|
|
18
22
|
Lets use one of the example CF templates that creates an EC2 instance. First
|
@@ -266,5 +270,7 @@ end
|
|
266
270
|
* Add examples of accessing parent hash elements
|
267
271
|
|
268
272
|
# Infos
|
269
|
-
*
|
273
|
+
* Documentation: http://sparkleformation.github.io/sparkle_formation
|
274
|
+
* User Documentation: http://sparkleformation.github.io/sparkle_formation/UserDocs/README.html
|
275
|
+
* Repository: https://github.com/sparkleformation/sparkle_formation
|
270
276
|
* IRC: Freenode @ #heavywater
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
unless(system("yardoc"))
|
5
|
+
$stderr.puts 'ACK: Failed to create docs!'
|
6
|
+
exit -1
|
7
|
+
end
|
8
|
+
|
9
|
+
FileUtils.mkdir_p('doc/UserDocs')
|
10
|
+
|
11
|
+
Dir.glob('docs/**/*').each do |path|
|
12
|
+
next unless File.file?(path)
|
13
|
+
content = File.read(path)
|
14
|
+
new_path = File.join('doc/UserDocs', path.sub(/.*?docs\//, ''))
|
15
|
+
FileUtils.mkdir_p(File.dirname(new_path))
|
16
|
+
File.open(new_path.sub('.md', '.html'), 'w') do |file|
|
17
|
+
if(path.end_with?('.md'))
|
18
|
+
file.puts '<!DOCTYPE html><html><title>SparkleFormation User Documentation</title><xmp theme="simplex" style="display:none;">'
|
19
|
+
file.puts content.gsub('.md', '.html')
|
20
|
+
file.puts '</xmp><script src="http://strapdownjs.com/v/0.2/strapdown.js"></script></html>'
|
21
|
+
else
|
22
|
+
file.puts content
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
File.open('doc/UserDocs/index.html', 'w') do |file|
|
28
|
+
file.puts '<html><head><meta http-equiv="refresh" content="0; url=README.html" /></head></html>'
|
29
|
+
end
|
30
|
+
|
31
|
+
puts 'done.'
|
@@ -41,8 +41,8 @@ class SparkleFormation
|
|
41
41
|
# @return [TrueClass]
|
42
42
|
def load(json_path_or_hash)
|
43
43
|
if(json_path_or_hash.is_a?(String))
|
44
|
-
require '
|
45
|
-
content = AttributeStruct.hashish.new(
|
44
|
+
require 'multi_json'
|
45
|
+
content = AttributeStruct.hashish.new(MultiJson.load(File.read(json)))
|
46
46
|
else
|
47
47
|
content = json_path_or_hash
|
48
48
|
end
|
@@ -66,13 +66,12 @@ class SparkleFormation
|
|
66
66
|
# @param key [String, Symbol]
|
67
67
|
# @return [String, NilClass]
|
68
68
|
def registry_key(key)
|
69
|
-
key = key.to_s
|
69
|
+
key = key.to_s.tr('_', '')
|
70
70
|
@@registry.keys.detect do |ref|
|
71
|
-
ref = ref.
|
72
|
-
|
73
|
-
snake_parts = snake_ref.split('_')
|
71
|
+
ref = ref.downcase
|
72
|
+
snake_parts = ref.split('::')
|
74
73
|
until(snake_parts.empty?)
|
75
|
-
break if snake_parts.join('
|
74
|
+
break if snake_parts.join('') == key
|
76
75
|
snake_parts.shift
|
77
76
|
end
|
78
77
|
!snake_parts.empty?
|
@@ -129,6 +129,103 @@ class SparkleFormation
|
|
129
129
|
end
|
130
130
|
alias_method :select!, :_cf_select
|
131
131
|
|
132
|
+
# Condition generator
|
133
|
+
#
|
134
|
+
# @param name [String, Symbol] symbol will be processed
|
135
|
+
# @return [Hash]
|
136
|
+
def _condition(name)
|
137
|
+
{'Condition' => name.is_a?(Symbol) ? _process_key(name) : name}
|
138
|
+
end
|
139
|
+
alias_method :condition!, :_condition
|
140
|
+
|
141
|
+
# Condition setter
|
142
|
+
#
|
143
|
+
# @param name [String, Symbol] condition name
|
144
|
+
# @return [SparkleStruct]
|
145
|
+
# @note this is used to set a {"Condition" => "Name"} into the
|
146
|
+
# current context, generally the top level of a resource
|
147
|
+
def _on_condition(name)
|
148
|
+
_set(*_condition(name).to_a.flatten)
|
149
|
+
end
|
150
|
+
alias_method :on_condition!, :_on_condition
|
151
|
+
|
152
|
+
# Fn::If generator
|
153
|
+
#
|
154
|
+
# @param cond [String, Symbol] symbol will be converted to condition
|
155
|
+
# @param true_value [Object]
|
156
|
+
# @param false_value [Object]
|
157
|
+
# @return [Hash]
|
158
|
+
def _if(cond, true_value, false_value)
|
159
|
+
cond = cond.is_a?(Symbol) ? _condition(cond) : cond
|
160
|
+
{'Fn::If' => _array(true_value, false_value)}
|
161
|
+
end
|
162
|
+
alias_method :if!, :_if
|
163
|
+
|
164
|
+
# Fn::And generator
|
165
|
+
#
|
166
|
+
# @param args [Object]
|
167
|
+
# @return [Hash]
|
168
|
+
# @note symbols will be processed and set as condition. strings
|
169
|
+
# will be set as condition directly. procs will be evaluated
|
170
|
+
def _and(*args)
|
171
|
+
{
|
172
|
+
'Fn::And' => _array(
|
173
|
+
args.map{|v|
|
174
|
+
if(v.is_a?(Symbol) || v.is_a?(String))
|
175
|
+
_condition(v)
|
176
|
+
else
|
177
|
+
v
|
178
|
+
end
|
179
|
+
}
|
180
|
+
)
|
181
|
+
}
|
182
|
+
end
|
183
|
+
alias_method :and!, :_and
|
184
|
+
|
185
|
+
# Fn::Equals generator
|
186
|
+
#
|
187
|
+
# @param v1 [Object]
|
188
|
+
# @param v2 [Object]
|
189
|
+
# @return [Hash]
|
190
|
+
def _equals(v1, v2)
|
191
|
+
{'Fn::Equals' => _array(v1, v2)}
|
192
|
+
end
|
193
|
+
alias_method :equals!, :_equals
|
194
|
+
|
195
|
+
# Fn::Not generator
|
196
|
+
#
|
197
|
+
# @param arg [Object]
|
198
|
+
# @return [Hash]
|
199
|
+
def _not(arg)
|
200
|
+
if(arg.is_a?(String) || arg.is_a?(Symbol))
|
201
|
+
arg = _condition(arg)
|
202
|
+
else
|
203
|
+
arg = _array(arg).first
|
204
|
+
end
|
205
|
+
{'Fn::Not' => [arg]}
|
206
|
+
end
|
207
|
+
alias_method :not!, :_not
|
208
|
+
|
209
|
+
# Fn::Or generator
|
210
|
+
#
|
211
|
+
# @param v1 [Object]
|
212
|
+
# @param v2 [Object]
|
213
|
+
# @return [Hash]
|
214
|
+
def _or(v1, v2)
|
215
|
+
{
|
216
|
+
'Fn::Or' => _array(
|
217
|
+
[v1,v2].map{|v|
|
218
|
+
if(v.is_a?(Symbol) || v.is_a?(String))
|
219
|
+
_condition(v)
|
220
|
+
else
|
221
|
+
v
|
222
|
+
end
|
223
|
+
}
|
224
|
+
)
|
225
|
+
}
|
226
|
+
end
|
227
|
+
alias_method :or!, :_or
|
228
|
+
|
132
229
|
# @return [TrueClass, FalseClass]
|
133
230
|
def rhel?
|
134
231
|
!!@platform[:rhel]
|
@@ -60,6 +60,132 @@ class SparkleFormation
|
|
60
60
|
translated['outputs'] = rename_processor(translated['outputs'])
|
61
61
|
end
|
62
62
|
translated.delete('mappings')
|
63
|
+
complete_launch_config_lb_setups
|
64
|
+
true
|
65
|
+
end
|
66
|
+
|
67
|
+
# Finalizer for the neutron load balancer resource. This
|
68
|
+
# finalizer may generate new resources if the load balancer has
|
69
|
+
# multiple listeners defined (neutron lb implementation defines
|
70
|
+
# multiple isolated resources sharing a common virtual IP)
|
71
|
+
#
|
72
|
+
#
|
73
|
+
# @param resource_name [String]
|
74
|
+
# @param new_resource [Hash]
|
75
|
+
# @param old_resource [Hash]
|
76
|
+
# @return [Object]
|
77
|
+
def neutron_loadbalancer_finalizer(resource_name, new_resource, old_resource)
|
78
|
+
listeners = new_resource['Properties'].delete('listeners') || []
|
79
|
+
healthcheck = new_resource['Properties'].delete('health_check')
|
80
|
+
subnet = (new_resource['Properties'].delete('subnets') || []).first
|
81
|
+
|
82
|
+
# if health check is provided, create resource and apply to
|
83
|
+
# all pools generated
|
84
|
+
if(healthcheck)
|
85
|
+
healthcheck_name = "#{resource_name}HealthCheck"
|
86
|
+
check = {
|
87
|
+
healthcheck_name => {
|
88
|
+
'Type' => 'OS::Neutron::HealthMonitor',
|
89
|
+
'Properties' => {}.tap{ |properties|
|
90
|
+
{'Timeout' => 'timeout', 'Interval' => 'delay', 'HealthyThreshold' => 'max_retries'}.each do |aws, hot|
|
91
|
+
if(healthcheck[aws])
|
92
|
+
properties[hot] = healthcheck[aws]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
type, port, path = healthcheck['Target'].split(/(:|\/.*)/).find_all{|x| x != ':'}
|
96
|
+
properties['type'] = type
|
97
|
+
if(path)
|
98
|
+
properties['url_path'] = path
|
99
|
+
end
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
translated['Resources'].merge!(check)
|
104
|
+
end
|
105
|
+
|
106
|
+
base_listener = listeners.shift
|
107
|
+
base_pool_name = "#{resource_name}Pool"
|
108
|
+
base_pool = {
|
109
|
+
base_pool_name => {
|
110
|
+
'Type' => 'OS::Neutron::Pool',
|
111
|
+
'Properties' => {
|
112
|
+
'lb_method' => 'ROUND_ROBIN',
|
113
|
+
'monitors' => [
|
114
|
+
{'get_resource' => healthcheck_name}
|
115
|
+
],
|
116
|
+
'protocol' => base_listener['Protocol'],
|
117
|
+
'vip' => {
|
118
|
+
'protocol_port' => base_listener['LoadBalancerPort']
|
119
|
+
},
|
120
|
+
'subnet' => subnet
|
121
|
+
}
|
122
|
+
}
|
123
|
+
}
|
124
|
+
if(healthcheck)
|
125
|
+
base_pool[base_pool_name]['Properties'].merge(
|
126
|
+
'monitors' => [
|
127
|
+
{'get_resource' => healthcheck_name}
|
128
|
+
]
|
129
|
+
)
|
130
|
+
end
|
131
|
+
|
132
|
+
translated['Resources'].merge!(base_pool)
|
133
|
+
new_resource['Properties']['pool_id'] = {'get_resource' => base_pool_name}
|
134
|
+
new_resource['Properties']['protocol_port'] = base_listener['InstancePort']
|
135
|
+
|
136
|
+
listeners.each_with_index do |listener, count|
|
137
|
+
pool_name = "#{resource_name}PoolVip#{count}"
|
138
|
+
pool = {
|
139
|
+
pool_name => {
|
140
|
+
'Type' => 'OS::Neutron::Pool',
|
141
|
+
'Properties' => {
|
142
|
+
'lb_method' => 'ROUND_ROBIN',
|
143
|
+
'protocol' => listener['Protocol'],
|
144
|
+
'subnet' => subnet,
|
145
|
+
'vip' => {
|
146
|
+
'protocol_port' => listener['LoadBalancerPort']
|
147
|
+
}
|
148
|
+
}
|
149
|
+
}
|
150
|
+
}
|
151
|
+
if(healthcheck)
|
152
|
+
pool[pool_name]['Properties'].merge(
|
153
|
+
'monitors' => [
|
154
|
+
{'get_resource' => healthcheck_name}
|
155
|
+
]
|
156
|
+
)
|
157
|
+
end
|
158
|
+
|
159
|
+
lb_name = "#{resource_name}Vip#{count}"
|
160
|
+
lb = {lb_name => MultiJson.load(MultiJson.dump(new_resource))}
|
161
|
+
lb[lb_name]['Properties']['pool_id'] = {'get_resource' => pool_name}
|
162
|
+
lb[lb_name]['Properties']['protocol_port'] = listener['InstancePort']
|
163
|
+
translated['Resources'].merge!(pool)
|
164
|
+
translated['Resources'].merge!(lb)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# Update any launch configuration which define load balancers to
|
169
|
+
# ensure they are attached to the correct resources when
|
170
|
+
# multiple listeners (ports) have been defined resulting in
|
171
|
+
# multiple isolated LB resources
|
172
|
+
def complete_launch_config_lb_setups
|
173
|
+
translated['resources'].find_all do |resource_name, resource|
|
174
|
+
resource['type'] == 'OS::Heat::AutoScalingGroup'
|
175
|
+
end.each do |name, value|
|
176
|
+
if(lbs = value['properties'].delete('load_balancers'))
|
177
|
+
lbs.each do |lb_ref|
|
178
|
+
lb_name = resource_name(lb_ref)
|
179
|
+
lb_resource = translated['resources'][lb_name]
|
180
|
+
vip_resources = translated['resources'].find_all do |k, v|
|
181
|
+
k.match(/#{lb_name}Vip\d+/) && v['type'] == 'OS::Neutron::LoadBalancer'
|
182
|
+
end
|
183
|
+
value['properties']['load_balancers'] = vip_resources.map do |vip_name|
|
184
|
+
{'get_resource' => vip_name}
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
63
189
|
true
|
64
190
|
end
|
65
191
|
|
@@ -129,6 +255,37 @@ class SparkleFormation
|
|
129
255
|
end
|
130
256
|
end
|
131
257
|
|
258
|
+
# Finalizer for the neutron subnet resource. Creates a stub
|
259
|
+
# network to attach subnet if availability zones are defined
|
260
|
+
# (aws classic)
|
261
|
+
#
|
262
|
+
# @param resource_name [String]
|
263
|
+
# @param new_resource [Hash]
|
264
|
+
# @param old_resource [Hash]
|
265
|
+
# @return [TrueClass]
|
266
|
+
def neutron_subnet_finalizer(resource_name, new_resource, old_resource)
|
267
|
+
azs = new_resource['Properties'].delete('availability_zone')
|
268
|
+
if(azs)
|
269
|
+
network_name = "NetworkFor#{resource_name}"
|
270
|
+
translated['Resources'][network_name] = {
|
271
|
+
'type' => 'OS::Neutron::Network'
|
272
|
+
}
|
273
|
+
new_resource['Properties']['network'] = {'get_resource' => network_name}
|
274
|
+
end
|
275
|
+
true
|
276
|
+
end
|
277
|
+
|
278
|
+
# Finalizer for the neutron net resource. Scrub properties.
|
279
|
+
#
|
280
|
+
# @param resource_name [String]
|
281
|
+
# @param new_resource [Hash]
|
282
|
+
# @param old_resource [Hash]
|
283
|
+
# @return [TrueClass]
|
284
|
+
def neutron_net_finalizer(resource_name, new_resource, old_resource)
|
285
|
+
new_resource['Properties'].clear
|
286
|
+
true
|
287
|
+
end
|
288
|
+
|
132
289
|
# Finalizer applied to all new resources
|
133
290
|
#
|
134
291
|
# @param resource_name [String]
|
@@ -194,7 +351,32 @@ class SparkleFormation
|
|
194
351
|
'LaunchConfigurationName' => :autoscaling_group_launchconfig
|
195
352
|
}
|
196
353
|
},
|
197
|
-
'AWS::AutoScaling::LaunchConfiguration' => :delete
|
354
|
+
'AWS::AutoScaling::LaunchConfiguration' => :delete,
|
355
|
+
'AWS::ElasticLoadBalancing::LoadBalancer' => {
|
356
|
+
:name => 'OS::Neutron::LoadBalancer',
|
357
|
+
:finalizer => :neutron_loadbalancer_finalizer,
|
358
|
+
:properties => {
|
359
|
+
'Instances' => 'members',
|
360
|
+
'Listeners' => 'listeners',
|
361
|
+
'HealthCheck' => 'health_check',
|
362
|
+
'Subnets' => 'subnets'
|
363
|
+
}
|
364
|
+
},
|
365
|
+
'AWS::EC2::VPC' => {
|
366
|
+
:name => 'OS::Neutron::Net',
|
367
|
+
:finalizer => :neutron_net_finalizer,
|
368
|
+
:properties => {
|
369
|
+
}
|
370
|
+
},
|
371
|
+
'AWS::EC2::Subnet' => {
|
372
|
+
:name => 'OS::Neutron::Subnet',
|
373
|
+
:finalizer => :neutron_subnet_finalizer,
|
374
|
+
:properties => {
|
375
|
+
'CidrBlock' => 'cidr',
|
376
|
+
'VpcId' => 'network',
|
377
|
+
'AvailabilityZone' => 'availability_zone'
|
378
|
+
}
|
379
|
+
}
|
198
380
|
}
|
199
381
|
}
|
200
382
|
|
@@ -206,7 +388,7 @@ class SparkleFormation
|
|
206
388
|
|
207
389
|
FN_MAPPING = {
|
208
390
|
'Fn::GetAtt' => 'get_attr',
|
209
|
-
'Fn::Join' => 'list_join'
|
391
|
+
'Fn::Join' => 'list_join'
|
210
392
|
}
|
211
393
|
|
212
394
|
end
|
@@ -164,7 +164,11 @@ class SparkleFormation
|
|
164
164
|
source_listener = listeners.shift
|
165
165
|
if(source_listener)
|
166
166
|
new_resource['Properties']['port'] = source_listener['LoadBalancerPort']
|
167
|
-
|
167
|
+
if(['HTTP', 'HTTPS'].include?(source_listener['Protocol']))
|
168
|
+
new_resource['Properties']['protocol'] = source_listener['Protocol']
|
169
|
+
else
|
170
|
+
new_resource['Properties']['protocol'] = 'TCP_CLIENT_FIRST'
|
171
|
+
end
|
168
172
|
new_resource['cache_instance_port'] = source_listener['InstancePort']
|
169
173
|
end
|
170
174
|
new_resource['Properties']['virtualIps'] = ['type' => 'PUBLIC', 'ipVersion' => 'IPV4']
|
@@ -183,14 +187,14 @@ class SparkleFormation
|
|
183
187
|
check['type'] = check_type
|
184
188
|
check['path'] = check_args.last
|
185
189
|
else
|
186
|
-
check['type'] = '
|
190
|
+
check['type'] = 'TCP_CLIENT_FIRST'
|
187
191
|
end
|
188
192
|
end
|
189
193
|
end
|
190
194
|
unless(listeners.empty?)
|
191
195
|
listeners.each_with_index do |listener, idx|
|
192
196
|
port = listener['LoadBalancerPort']
|
193
|
-
proto = listener['Protocol']
|
197
|
+
proto = ['HTTP', 'HTTPS'].include?(listener['Protocol']) ? listener['Protocol'] : 'TCP_CLIENT_FIRST'
|
194
198
|
vip_name = "#{resource_name}Vip#{idx}"
|
195
199
|
vip_resource = MultiJson.load(MultiJson.dump(new_resource))
|
196
200
|
vip_resource['Properties']['name'] = vip_name
|
@@ -260,7 +260,7 @@ class SparkleFormation
|
|
260
260
|
k,v = hash.first
|
261
261
|
if(hash.size == 1)
|
262
262
|
if(k.start_with?('Fn::'))
|
263
|
-
{self.class.const_get(:FN_MAPPING).fetch(k, k) => v}
|
263
|
+
{self.class.const_get(:FN_MAPPING).fetch(k, k) => attr_mapping(*v)}
|
264
264
|
elsif(k == 'Ref')
|
265
265
|
if(resources.has_key?(v))
|
266
266
|
{'get_resource' => v}
|
@@ -275,6 +275,22 @@ class SparkleFormation
|
|
275
275
|
end
|
276
276
|
end
|
277
277
|
|
278
|
+
# Apply `GetAttr` mapping if available
|
279
|
+
#
|
280
|
+
# @param resource_name [String]
|
281
|
+
# @param value [String]
|
282
|
+
# @return [Array]
|
283
|
+
def attr_mapping(resource_name, value)
|
284
|
+
result = [resource_name, value]
|
285
|
+
if(r = resources[resource_name])
|
286
|
+
attr_map = self.class.const_get(:FN_ATT_MAPPING)
|
287
|
+
if(attr_map[r['Type']] && replacement = attr_map[r['Type']][value])
|
288
|
+
result = [resource_name, *[replacement].flatten.compact]
|
289
|
+
end
|
290
|
+
end
|
291
|
+
result
|
292
|
+
end
|
293
|
+
|
278
294
|
# Apply function if possible
|
279
295
|
#
|
280
296
|
# @param hash [Hash]
|
@@ -289,7 +305,17 @@ class SparkleFormation
|
|
289
305
|
when 'Fn::Join'
|
290
306
|
v.last.join(v.first)
|
291
307
|
when 'Fn::FindInMap'
|
292
|
-
mappings[v[0]]
|
308
|
+
map_holder = mappings[v[0]]
|
309
|
+
if(map_holder)
|
310
|
+
map_item = map_holder[dereference(v[1])]
|
311
|
+
if(map_item)
|
312
|
+
map_item[v[2]]
|
313
|
+
else
|
314
|
+
raise "Failed to find mapping item! (#{v[0]} -> #{v[1]})"
|
315
|
+
end
|
316
|
+
else
|
317
|
+
raise "Failed to find mapping! (#{v[0]})"
|
318
|
+
end
|
293
319
|
when 'Ref'
|
294
320
|
{'Ref' => self.class.const_get(:REF_MAPPING).fetch(v, v)}
|
295
321
|
else
|
data/sparkle_formation.gemspec
CHANGED
@@ -12,5 +12,6 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.require_path = 'lib'
|
13
13
|
s.add_dependency 'attribute_struct', '~> 0.2.2'
|
14
14
|
s.add_dependency 'multi_json'
|
15
|
-
s.
|
15
|
+
s.executables << 'generate_sparkle_docs'
|
16
|
+
s.files = Dir['lib/**/*'] + %w(sparkle_formation.gemspec README.md CHANGELOG.md LICENSE)
|
16
17
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sparkle_formation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Roberts
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: attribute_struct
|
@@ -40,35 +40,15 @@ dependencies:
|
|
40
40
|
version: '0'
|
41
41
|
description: Cloud Formation builder
|
42
42
|
email: chrisroberts.code@gmail.com
|
43
|
-
executables:
|
43
|
+
executables:
|
44
|
+
- generate_sparkle_docs
|
44
45
|
extensions: []
|
45
46
|
extra_rdoc_files: []
|
46
47
|
files:
|
47
48
|
- CHANGELOG.md
|
48
|
-
- CONTRIBUTING.md
|
49
|
-
- Gemfile
|
50
|
-
- Gemfile.lock
|
51
49
|
- LICENSE
|
52
50
|
- README.md
|
53
|
-
- bin/
|
54
|
-
- bin/heat_resources
|
55
|
-
- docs/README.md
|
56
|
-
- docs/anatomy.md
|
57
|
-
- docs/building-blocks.md
|
58
|
-
- docs/examples/cloudformation/components/base.rb
|
59
|
-
- docs/examples/cloudformation/dynamics/elb.rb
|
60
|
-
- docs/examples/cloudformation/templates/website.rb
|
61
|
-
- docs/examples/template_json/website.json
|
62
|
-
- docs/examples/website.rb
|
63
|
-
- docs/functions.md
|
64
|
-
- docs/properties.md
|
65
|
-
- docs/provisioning.md
|
66
|
-
- docs/resource-reference.md
|
67
|
-
- examples/allinone/cloudformation/ec2_example.rb
|
68
|
-
- examples/allinone/parse.rb
|
69
|
-
- examples/ami_component/cloudformation/components/ami.rb
|
70
|
-
- examples/ami_component/cloudformation/ec2_example.rb
|
71
|
-
- examples/ami_component/parse.rb
|
51
|
+
- bin/generate_sparkle_docs
|
72
52
|
- lib/sparkle_formation.rb
|
73
53
|
- lib/sparkle_formation/aws.rb
|
74
54
|
- lib/sparkle_formation/aws/cfn_resources.rb
|
@@ -81,14 +61,6 @@ files:
|
|
81
61
|
- lib/sparkle_formation/utils.rb
|
82
62
|
- lib/sparkle_formation/version.rb
|
83
63
|
- sparkle_formation.gemspec
|
84
|
-
- test/spec.rb
|
85
|
-
- test/specs/attribute.rb
|
86
|
-
- test/specs/basic.rb
|
87
|
-
- test/specs/cloudformation/components/ami.rb
|
88
|
-
- test/specs/cloudformation/dynamics/node.rb
|
89
|
-
- test/specs/results/base.json
|
90
|
-
- test/specs/results/base_with_map.json
|
91
|
-
- test/specs/results/component.json
|
92
64
|
homepage: http://github.com/heavywater/sparkle_formation
|
93
65
|
licenses:
|
94
66
|
- Apache-2.0
|
data/CONTRIBUTING.md
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# Contributing
|
2
|
-
|
3
|
-
## Branches
|
4
|
-
|
5
|
-
### `master` branch
|
6
|
-
|
7
|
-
The master branch is the current stable released version.
|
8
|
-
|
9
|
-
### `develop` branch
|
10
|
-
|
11
|
-
The develop branch is the current edge of development.
|
12
|
-
|
13
|
-
## Pull requests
|
14
|
-
|
15
|
-
* https://github.com/heavywater/sparkle_formation/pulls
|
16
|
-
|
17
|
-
Please base all pull requests off the `develop` branch. Merges to
|
18
|
-
`master` only occur through the `develop` branch. Pull requests
|
19
|
-
based on `master` will likely be cherry picked.
|
20
|
-
|
21
|
-
## Issues
|
22
|
-
|
23
|
-
Need to report an issue? Use the github issues:
|
24
|
-
|
25
|
-
* https://github.com/heavywater/sparkle_formation/issues
|
data/Gemfile
DELETED
data/Gemfile.lock
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
sparkle_formation (0.2.2)
|
5
|
-
attribute_struct (~> 0.2.2)
|
6
|
-
multi_json
|
7
|
-
|
8
|
-
GEM
|
9
|
-
remote: https://rubygems.org/
|
10
|
-
specs:
|
11
|
-
attribute_struct (0.2.8)
|
12
|
-
multi_json (1.10.1)
|
13
|
-
|
14
|
-
PLATFORMS
|
15
|
-
ruby
|
16
|
-
|
17
|
-
DEPENDENCIES
|
18
|
-
sparkle_formation!
|