sparkle_formation 0.2.2 → 0.2.4
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 +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!
|