sparkle_formation 0.1.4 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +7 -10
- data/bin/aws_resources +51 -0
- data/bin/heat_resources +33 -0
- data/lib/sparkle_formation.rb +11 -1
- data/lib/sparkle_formation/aws.rb +89 -0
- data/lib/sparkle_formation/aws/cfn_resources.rb +461 -0
- data/lib/sparkle_formation/sparkle_attribute.rb +75 -67
- data/lib/sparkle_formation/sparkle_formation.rb +164 -28
- data/lib/sparkle_formation/sparkle_struct.rb +11 -0
- data/lib/sparkle_formation/translation.rb +87 -0
- data/lib/sparkle_formation/translation/heat.rb +66 -0
- data/lib/sparkle_formation/translation/rackspace.rb +34 -0
- data/lib/sparkle_formation/utils.rb +50 -0
- data/lib/sparkle_formation/version.rb +1 -1
- data/sparkle_formation-0.2.0.gem +0 -0
- data/sparkle_formation.gemspec +1 -0
- metadata +27 -2
@@ -16,87 +16,95 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require '
|
19
|
+
require 'sparkle_formation'
|
20
20
|
|
21
|
-
|
21
|
+
class SparkleFormation
|
22
|
+
module SparkleAttribute
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
def _cf_join(*args)
|
25
|
+
options = args.detect{|i| i.is_a?(Hash) && i[:options]} || {:options => {}}
|
26
|
+
args.delete(options)
|
27
|
+
unless(args.size == 1)
|
28
|
+
args = [args]
|
29
|
+
end
|
30
|
+
{'Fn::Join' => [options[:options][:delimiter] || '', *args]}
|
28
31
|
end
|
29
|
-
{'Fn::Join' => [options[:options][:delimiter] || '', *args]}
|
30
|
-
end
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
33
|
+
def _cf_ref(thing)
|
34
|
+
thing = _process_key(thing, :force) if thing.is_a?(Symbol)
|
35
|
+
{'Ref' => thing}
|
36
|
+
end
|
37
|
+
alias_method :_ref, :_cf_ref
|
38
|
+
|
39
|
+
def _cf_map(thing, key, *suffix)
|
40
|
+
suffix = suffix.map do |item|
|
41
|
+
if(item.is_a?(Symbol))
|
42
|
+
_process_key(item, :force)
|
43
|
+
else
|
44
|
+
item
|
45
|
+
end
|
44
46
|
end
|
47
|
+
thing = _process_key(thing, :force) if thing.is_a?(Symbol)
|
48
|
+
key = _process_key(key, :force) if key.is_a?(Symbol)
|
49
|
+
{'Fn::FindInMap' => [_process_key(thing), {'Ref' => _process_key(key)}, *suffix]}
|
45
50
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
else
|
57
|
-
thing
|
51
|
+
alias_method :_cf_find_in_map, :_cf_map
|
52
|
+
|
53
|
+
def _cf_attr(*args)
|
54
|
+
args = args.map do |thing|
|
55
|
+
if(thing.is_a?(Symbol))
|
56
|
+
_process_key(thing, :force)
|
57
|
+
else
|
58
|
+
thing
|
59
|
+
end
|
60
|
+
|
58
61
|
end
|
62
|
+
{'Fn::GetAtt' => args}
|
63
|
+
end
|
64
|
+
alias_method :_cf_get_att, :_cf_attr
|
59
65
|
|
66
|
+
def _cf_base64(arg)
|
67
|
+
{'Fn::Base64' => arg}
|
60
68
|
end
|
61
|
-
{'Fn::GetAtt' => args}
|
62
|
-
end
|
63
|
-
alias_method :_cf_get_att, :_cf_attr
|
64
69
|
|
65
|
-
|
66
|
-
|
67
|
-
|
70
|
+
def _cf_get_azs(region=nil)
|
71
|
+
region = case region
|
72
|
+
when Symbol
|
73
|
+
_cf_ref(region)
|
74
|
+
when NilClass
|
75
|
+
''
|
76
|
+
else
|
77
|
+
region
|
78
|
+
end
|
79
|
+
{'Fn::GetAZs' => region}
|
80
|
+
end
|
68
81
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
when NilClass
|
74
|
-
''
|
75
|
-
else
|
76
|
-
region
|
77
|
-
end
|
78
|
-
{'Fn::GetAZs' => region}
|
79
|
-
end
|
82
|
+
def _cf_select(index, item)
|
83
|
+
item = _cf_ref(item) if item.is_a?(Symbol)
|
84
|
+
{'Fn::Select' => [index.to_i.to_s, item]}
|
85
|
+
end
|
80
86
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
end
|
87
|
+
def rhel?
|
88
|
+
!!@platform[:rhel]
|
89
|
+
end
|
85
90
|
|
86
|
-
|
87
|
-
|
88
|
-
|
91
|
+
def debian?
|
92
|
+
!!@platform[:debian]
|
93
|
+
end
|
89
94
|
|
90
|
-
|
91
|
-
|
92
|
-
|
95
|
+
def _platform=(plat)
|
96
|
+
@platform || __hashish
|
97
|
+
@platform.clear
|
98
|
+
@platform[plat.to_sym] = true
|
99
|
+
end
|
93
100
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
@platform[plat.to_sym] = true
|
98
|
-
end
|
101
|
+
def dynamic!(name, *args, &block)
|
102
|
+
SparkleFormation.insert(name, self, *args, &block)
|
103
|
+
end
|
99
104
|
|
100
|
-
|
105
|
+
def registry!(name, *args)
|
106
|
+
SfnRegistry.insert(name, self, *args)
|
107
|
+
end
|
101
108
|
|
102
|
-
|
109
|
+
end
|
110
|
+
end
|
@@ -16,11 +16,9 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require '
|
20
|
-
require 'sparkle_formation/sparkle_attribute'
|
21
|
-
require 'sparkle_formation/utils'
|
19
|
+
require 'sparkle_formation'
|
22
20
|
|
23
|
-
|
21
|
+
SparkleFormation::SparkleStruct.camel_keys = true
|
24
22
|
|
25
23
|
class SparkleFormation
|
26
24
|
|
@@ -28,38 +26,85 @@ class SparkleFormation
|
|
28
26
|
|
29
27
|
class << self
|
30
28
|
|
29
|
+
include SparkleFormation::Utils::AnimalStrings
|
30
|
+
|
31
31
|
attr_reader :dynamics
|
32
|
-
attr_reader :components_path
|
33
|
-
attr_reader :dynamics_path
|
34
32
|
|
33
|
+
# Return custom paths
|
35
34
|
def custom_paths
|
36
35
|
@_paths ||= {}
|
37
36
|
@_paths
|
38
37
|
end
|
39
38
|
|
40
|
-
|
41
|
-
|
39
|
+
# path:: Path
|
40
|
+
# Path to sparkle directory
|
41
|
+
def sparkle_path=(path=nil)
|
42
|
+
if(path)
|
43
|
+
custom_paths[:sparkle_path] = path
|
44
|
+
custom_paths[:components_directory] ||= File.join(path, 'components')
|
45
|
+
custom_paths[:dynamics_directory] ||= File.join(path, 'dynamics')
|
46
|
+
custom_paths[:registry_directory] ||= File.join(path, 'registry')
|
47
|
+
end
|
48
|
+
custom_paths[:sparkle_path]
|
49
|
+
end
|
50
|
+
alias_method(:sparkle_path, :sparkle_path=)
|
51
|
+
|
52
|
+
# path:: Path
|
53
|
+
# Set path to component files
|
54
|
+
def components_path=(path=nil)
|
55
|
+
if(path)
|
56
|
+
custom_paths[:components_directory] = path
|
57
|
+
end
|
58
|
+
custom_paths[:components_directory]
|
59
|
+
end
|
60
|
+
alias_method(:components_path, :components_path=)
|
61
|
+
|
62
|
+
# path:: Path
|
63
|
+
# Set path to dynamic files
|
64
|
+
def dynamics_path=(path=nil)
|
65
|
+
if(path)
|
66
|
+
custom_paths[:dynamics_directory] = path
|
67
|
+
end
|
68
|
+
custom_paths[:dynamics_directory]
|
42
69
|
end
|
70
|
+
alias_method(:dynamics_path, :dynamics_path=)
|
43
71
|
|
44
|
-
|
45
|
-
|
72
|
+
# path:: Path
|
73
|
+
# Set path to registry files
|
74
|
+
def registry_path=(path=nil)
|
75
|
+
if(path)
|
76
|
+
custom_paths[:registry_directory] = path
|
77
|
+
end
|
78
|
+
custom_paths[:registry_directory]
|
46
79
|
end
|
80
|
+
alias_method(:registry_path, :registry_path=)
|
47
81
|
|
82
|
+
# path:: Path
|
83
|
+
# args:: Option symbols
|
84
|
+
# - :sparkle:: Return formation instead of Hash
|
85
|
+
# Compile file at given path and return Hash
|
48
86
|
def compile(path, *args)
|
49
87
|
formation = self.instance_eval(IO.read(path), path, 1)
|
50
88
|
args.include?(:sparkle) ? formation : formation.compile._dump
|
51
89
|
end
|
52
90
|
|
91
|
+
# base:: Base SparkleStruct
|
92
|
+
# Execute given block within base
|
53
93
|
def build(base=nil, &block)
|
54
|
-
struct = base ||
|
94
|
+
struct = base || SparkleStruct.new
|
55
95
|
struct.instance_exec(&block)
|
56
|
-
struct
|
96
|
+
@_struct = struct
|
57
97
|
end
|
58
98
|
|
99
|
+
# path:: Path
|
100
|
+
# Load component at given path
|
59
101
|
def load_component(path)
|
60
102
|
self.instance_eval(IO.read(path), path, 1)
|
103
|
+
@_struct
|
61
104
|
end
|
62
105
|
|
106
|
+
# directory:: Path
|
107
|
+
# Load all dynamics within given directory
|
63
108
|
def load_dynamics!(directory)
|
64
109
|
@loaded_dynamics ||= []
|
65
110
|
Dir.glob(File.join(directory, '*.rb')).each do |dyn|
|
@@ -72,22 +117,90 @@ class SparkleFormation
|
|
72
117
|
true
|
73
118
|
end
|
74
119
|
|
75
|
-
|
76
|
-
|
77
|
-
|
120
|
+
# directory:: Path
|
121
|
+
# Load all registry entries within given directory
|
122
|
+
def load_registry!(directory)
|
123
|
+
Dir.glob(File.join(directory, '*.rb')).each do |reg|
|
124
|
+
reg = File.expand_path(reg)
|
125
|
+
require reg
|
126
|
+
end
|
127
|
+
true
|
128
|
+
end
|
129
|
+
|
130
|
+
# name:: Name of dynamic
|
131
|
+
# args:: Optional dynamic metadata
|
132
|
+
# Define a new dynamic and store associated block
|
133
|
+
def dynamic(name, args={}, &block)
|
134
|
+
@dynamics ||= SparkleStruct.hashish.new
|
135
|
+
@dynamics[name] = SparkleStruct.hashish[
|
136
|
+
:block, block, :args, SparkleStruct.hashish[args.map(&:to_a)]
|
137
|
+
]
|
138
|
+
end
|
139
|
+
|
140
|
+
# name:: Name of dynamic
|
141
|
+
# Return metadata about dynamic
|
142
|
+
def dynamic_info(name)
|
143
|
+
if(@dynamics[name])
|
144
|
+
@dynamics[name][:args]
|
145
|
+
else
|
146
|
+
raise KeyError.new("No dynamic registered with provided name (#{name})")
|
147
|
+
end
|
78
148
|
end
|
149
|
+
alias_method :dynamic_information, :dynamic_info
|
79
150
|
|
80
|
-
|
151
|
+
# dynamic_name:: Name of dynamic
|
152
|
+
# struct:: SparkleStruct instances
|
153
|
+
# args:: Args to pass to dynamic
|
154
|
+
# Inserts a dynamic into the given SparkleStruct instance
|
155
|
+
def insert(dynamic_name, struct, *args, &block)
|
156
|
+
result = false
|
81
157
|
if(@dynamics && @dynamics[dynamic_name])
|
82
|
-
struct.instance_exec(*args, &@dynamics[dynamic_name])
|
83
|
-
struct
|
158
|
+
struct.instance_exec(*args, &@dynamics[dynamic_name][:block])
|
159
|
+
result = struct
|
84
160
|
else
|
161
|
+
result = builtin_insert(dynamic_name, struct, *args, &block)
|
162
|
+
end
|
163
|
+
unless(result)
|
85
164
|
raise "Failed to locate requested dynamic block for insertion: #{dynamic_name} (valid: #{@dynamics.keys.sort.join(', ')})"
|
86
165
|
end
|
166
|
+
result
|
167
|
+
end
|
168
|
+
|
169
|
+
# dynamic_name:: Name of dynamic
|
170
|
+
# struct:: SparkleStruct instances
|
171
|
+
# args:: Args to pass to dynamic
|
172
|
+
# Inserts a builtin dynamic into the given SparkleStruct instance
|
173
|
+
def builtin_insert(dynamic_name, struct, *args, &block)
|
174
|
+
if(defined?(SfnAws) && lookup_key = SfnAws.registry_key(dynamic_name))
|
175
|
+
_name, _config = *args
|
176
|
+
_config ||= {}
|
177
|
+
return unless _name
|
178
|
+
new_resource = struct.resources.__send__("#{_name}_#{dynamic_name}".to_sym)
|
179
|
+
new_resource.type lookup_key
|
180
|
+
properties = new_resource.properties
|
181
|
+
SfnAws.resource(dynamic_name, :properties).each do |prop_name|
|
182
|
+
value = [prop_name, snake(prop_name)].map do |key|
|
183
|
+
_config[key] || _config[key.to_sym]
|
184
|
+
end.compact.first
|
185
|
+
if(value)
|
186
|
+
if(value.is_a?(Proc))
|
187
|
+
properties.__send__(prop_name).instance_exec(&value)
|
188
|
+
else
|
189
|
+
properties.__send__(prop_name, value)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
new_resource.instance_exec(&block) if block
|
194
|
+
new_resource
|
195
|
+
end
|
87
196
|
end
|
88
197
|
|
198
|
+
# hash:: Hash
|
199
|
+
# Attempts to load an SparkleStruct instance from and existing
|
200
|
+
# Hash instance
|
201
|
+
# NOTE: camel keys will do best effort at auto discovery
|
89
202
|
def from_hash(hash)
|
90
|
-
struct =
|
203
|
+
struct = SparkleStruct.new
|
91
204
|
struct._camel_keys_set(:auto_discovery)
|
92
205
|
struct._load(hash)
|
93
206
|
struct._camel_keys_set(nil)
|
@@ -97,6 +210,9 @@ class SparkleFormation
|
|
97
210
|
|
98
211
|
attr_reader :name
|
99
212
|
attr_reader :sparkle_path
|
213
|
+
attr_reader :components_directory
|
214
|
+
attr_reader :dynamics_directory
|
215
|
+
attr_reader :registry_directory
|
100
216
|
attr_reader :components
|
101
217
|
attr_reader :load_order
|
102
218
|
|
@@ -104,27 +220,43 @@ class SparkleFormation
|
|
104
220
|
@name = name
|
105
221
|
@sparkle_path = options[:sparkle_path] ||
|
106
222
|
self.class.custom_paths[:sparkle_path] ||
|
107
|
-
File.join(Dir.pwd, 'cloudformation
|
223
|
+
File.join(Dir.pwd, 'cloudformation')
|
224
|
+
@components_directory = options[:components_directory] ||
|
225
|
+
self.class.custom_paths[:components_directory] ||
|
226
|
+
File.join(sparkle_path, 'components')
|
108
227
|
@dynamics_directory = options[:dynamics_directory] ||
|
109
228
|
self.class.custom_paths[:dynamics_directory] ||
|
110
|
-
File.join(
|
229
|
+
File.join(sparkle_path, 'dynamics')
|
230
|
+
@registry_directory = options[:registry_directory] ||
|
231
|
+
self.class.custom_paths[:registry_directory] ||
|
232
|
+
File.join(sparkle_path, 'registry')
|
111
233
|
self.class.load_dynamics!(@dynamics_directory)
|
112
|
-
|
234
|
+
self.class.load_registry!(@registry_directory)
|
235
|
+
unless(options[:disable_aws_builtins])
|
236
|
+
require 'sparkle_formation/aws'
|
237
|
+
SfnAws.load!
|
238
|
+
end
|
239
|
+
@components = SparkleStruct.hashish.new
|
113
240
|
@load_order = []
|
241
|
+
@overrides = []
|
114
242
|
if(block)
|
115
243
|
load_block(block)
|
116
244
|
end
|
117
245
|
end
|
118
246
|
|
247
|
+
# block:: block to execute
|
248
|
+
# Loads block
|
119
249
|
def load_block(block)
|
120
250
|
@components[:__base__] = self.class.build(&block)
|
121
251
|
@load_order << :__base__
|
122
252
|
end
|
123
253
|
|
254
|
+
# args:: symbols or paths for component loads
|
255
|
+
# Loads components into instance
|
124
256
|
def load(*args)
|
125
257
|
args.each do |thing|
|
126
258
|
if(thing.is_a?(Symbol))
|
127
|
-
path = File.join(
|
259
|
+
path = File.join(components_directory, "#{thing}.rb")
|
128
260
|
else
|
129
261
|
path = thing
|
130
262
|
end
|
@@ -135,19 +267,23 @@ class SparkleFormation
|
|
135
267
|
self
|
136
268
|
end
|
137
269
|
|
138
|
-
|
139
|
-
|
270
|
+
# Registers block into overrides
|
271
|
+
def overrides(args={}, &block)
|
272
|
+
@overrides << {:args => args, :block => block}
|
140
273
|
self
|
141
274
|
end
|
142
275
|
|
143
276
|
# Returns compiled Mash instance
|
144
277
|
def compile
|
145
|
-
compiled =
|
278
|
+
compiled = SparkleStruct.new
|
146
279
|
@load_order.each do |key|
|
147
280
|
compiled._merge!(components[key])
|
148
281
|
end
|
149
|
-
|
150
|
-
|
282
|
+
@overrides.each do |override|
|
283
|
+
if(override[:args] && !override[:args].empty?)
|
284
|
+
compiled._set_state(override[:args])
|
285
|
+
end
|
286
|
+
self.class.build(compiled, &override[:block])
|
151
287
|
end
|
152
288
|
compiled
|
153
289
|
end
|