sparkle_formation 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,24 +1,31 @@
1
1
  require 'sparkle_formation'
2
2
 
3
3
  class SparkleFormation
4
+ # AWS resource helper
4
5
  class Aws
5
6
  class << self
6
7
 
7
8
  include SparkleFormation::Utils::AnimalStrings
9
+ # @!parse include SparkleFormation::Utils::AnimalStrings
8
10
 
9
- # type:: AWS CFN resource type
10
- # hash:: Hash of information
11
11
  # Register an AWS resource
12
+ #
13
+ # @param type [String] AWS CFN resource type
14
+ # @param hash [Hash] metadata information
15
+ # @return [TrueClass]
12
16
  def register(type, hash)
13
17
  unless(class_variable_defined?(:@@registry))
14
18
  @@registry = AttributeStruct.hashish.new
15
19
  end
16
20
  @@registry[type] = hash
21
+ true
17
22
  end
18
23
 
19
- # identifier:: resource identifier
20
- # key:: key of value to return from information hash
21
- # Return the associated aws resource information
24
+ # Resource information
25
+ #
26
+ # @param identifier [String, Symbol] resource identifier
27
+ # @param key [String, Symbol] specific data
28
+ # @return [Hashish]
22
29
  def resource(identifier, key=nil)
23
30
  res = lookup(identifier)
24
31
  if(key && res)
@@ -28,8 +35,10 @@ class SparkleFormation
28
35
  end
29
36
  end
30
37
 
31
- # json_path_or_hash:: Path to JSON file or Hash instance of resources
32
38
  # Register all discovered resources
39
+ #
40
+ # @param json_path_or_hash [String, Hashish] path to files or hash
41
+ # @return [TrueClass]
33
42
  def load(json_path_or_hash)
34
43
  if(json_path_or_hash.is_a?(String))
35
44
  require 'json'
@@ -44,14 +53,18 @@ class SparkleFormation
44
53
  end
45
54
 
46
55
  # Load the builtin AWS resources
56
+ #
57
+ # @return [TrueClass]
47
58
  def load!
48
59
  require File.join(File.dirname(__FILE__), 'aws', 'cfn_resources.rb')
49
60
  load(AWS_RESOURCES)
61
+ true
50
62
  end
51
63
 
52
- # key:: string or symbol
53
- # Return matching registry key. Uses snaked resource type for
54
- # matching and will attempt all parts for match
64
+ # Discover registry key via part searching
65
+ #
66
+ # @param key [String, Symbol]
67
+ # @return [String, NilClass]
55
68
  def registry_key(key)
56
69
  key = key.to_s
57
70
  @@registry.keys.detect do |ref|
@@ -66,19 +79,20 @@ class SparkleFormation
66
79
  end
67
80
  end
68
81
 
69
- # key:: string or symbol
70
- # Returns resource information of type discovered via matching
71
- # using #registry_key
82
+ # Registry information for given type
83
+ #
84
+ # @param key [String, Symbol]
85
+ # @return [Hashish, NilClass]
72
86
  def lookup(key)
73
87
  @@registry[registry_key(key)]
74
88
  end
75
89
 
76
- # Return the currently loaded AWS registry
90
+ # @return [Hashish] currently loaded AWS registry
77
91
  def registry
78
92
  if(class_variable_defined?(:@@registry))
79
93
  @@registry
80
94
  else
81
- {}
95
+ @@registry = AttributeStruct.hashish.new
82
96
  end
83
97
  end
84
98
 
@@ -86,4 +100,5 @@ class SparkleFormation
86
100
  end
87
101
  end
88
102
 
103
+ # Shortcut helper constant
89
104
  SfnAws = SparkleFormation::Aws
@@ -19,8 +19,14 @@
19
19
  require 'sparkle_formation'
20
20
 
21
21
  class SparkleFormation
22
+
23
+ # Provides template helper methods
22
24
  module SparkleAttribute
23
25
 
26
+ # Fn::Join generator
27
+ #
28
+ # @param args [Object]
29
+ # @return [Hash]
24
30
  def _cf_join(*args)
25
31
  options = args.detect{|i| i.is_a?(Hash) && i[:options]} || {:options => {}}
26
32
  args.delete(options)
@@ -29,13 +35,26 @@ class SparkleFormation
29
35
  end
30
36
  {'Fn::Join' => [options[:options][:delimiter] || '', *args]}
31
37
  end
38
+ alias_method :join!, :_cf_join
32
39
 
40
+ # Ref generator
41
+ #
42
+ # @param thing [String, Symbol] reference name
43
+ # @return [Hash]
44
+ # @note Symbol value will force key processing
33
45
  def _cf_ref(thing)
34
46
  thing = _process_key(thing, :force) if thing.is_a?(Symbol)
35
47
  {'Ref' => thing}
36
48
  end
37
49
  alias_method :_ref, :_cf_ref
38
-
50
+ alias_method :ref!, :_cf_ref
51
+
52
+ # Fn::FindInMap generator
53
+ #
54
+ # @param thing [String, Symbol] thing to find
55
+ # @param key [String, Symbol] thing to search
56
+ # @param suffix [Object] additional args
57
+ # @return [Hash]
39
58
  def _cf_map(thing, key, *suffix)
40
59
  suffix = suffix.map do |item|
41
60
  if(item.is_a?(Symbol))
@@ -49,7 +68,13 @@ class SparkleFormation
49
68
  {'Fn::FindInMap' => [_process_key(thing), {'Ref' => _process_key(key)}, *suffix]}
50
69
  end
51
70
  alias_method :_cf_find_in_map, :_cf_map
71
+ alias_method :find_in_map!, :_cf_map
72
+ alias_method :map!, :_cf_map
52
73
 
74
+ # Fn::GetAtt generator
75
+ #
76
+ # @param [Object] pass through arguments
77
+ # @return [Hash]
53
78
  def _cf_attr(*args)
54
79
  args = args.map do |thing|
55
80
  if(thing.is_a?(Symbol))
@@ -62,11 +87,22 @@ class SparkleFormation
62
87
  {'Fn::GetAtt' => args}
63
88
  end
64
89
  alias_method :_cf_get_att, :_cf_attr
90
+ alias_method :get_att!, :_cf_attr
91
+ alias_method :attr!, :_cf_attr
65
92
 
93
+ # Fn::Base64 generator
94
+ #
95
+ # @param arg [Object] pass through
96
+ # @return [Hash]
66
97
  def _cf_base64(arg)
67
98
  {'Fn::Base64' => arg}
68
99
  end
100
+ alias_method :base64!, :_cf_base64
69
101
 
102
+ # Fn::GetAZs generator
103
+ #
104
+ # @param region [String, Symbol] String will pass through. Symbol will be converted to ref
105
+ # @return [Hash]
70
106
  def _cf_get_azs(region=nil)
71
107
  region = case region
72
108
  when Symbol
@@ -78,30 +114,55 @@ class SparkleFormation
78
114
  end
79
115
  {'Fn::GetAZs' => region}
80
116
  end
81
-
117
+ alias_method :get_azs!, :_cf_get_azs
118
+ alias_method :azs!, :_cf_get_azs
119
+
120
+ # Fn::Select generator
121
+ #
122
+ # @param index [String, Symbol, Integer] Symbol will be converted to ref
123
+ # @param item [Object, Symbol] Symbol will be converted to ref
124
+ # @return [Hash]
82
125
  def _cf_select(index, item)
126
+ index = index.is_a?(Symbol) ? _cf_ref(index) : index
83
127
  item = _cf_ref(item) if item.is_a?(Symbol)
84
- {'Fn::Select' => [index.to_i.to_s, item]}
128
+ {'Fn::Select' => [index, item]}
85
129
  end
130
+ alias_method :select!, :_cf_select
86
131
 
132
+ # @return [TrueClass, FalseClass]
87
133
  def rhel?
88
134
  !!@platform[:rhel]
89
135
  end
90
136
 
137
+ # @return [TrueClass, FalseClass]
91
138
  def debian?
92
139
  !!@platform[:debian]
93
140
  end
94
141
 
142
+ # Set the destination platform
143
+ #
144
+ # @param plat [String, Symbol] one of :rhel or :debian
145
+ # @return [TrueClass]
95
146
  def _platform=(plat)
96
147
  @platform || __hashish
97
148
  @platform.clear
98
149
  @platform[plat.to_sym] = true
99
150
  end
100
151
 
152
+ # Dynamic insertion helper method
153
+ #
154
+ # @param name [String, Symbol] dynamic name
155
+ # @param args [Object] argument list for dynamic
156
+ # @return [self]
101
157
  def dynamic!(name, *args, &block)
102
158
  SparkleFormation.insert(name, self, *args, &block)
103
159
  end
104
160
 
161
+ # Registry insertion helper method
162
+ #
163
+ # @param name [String, Symbol] name of registry item
164
+ # @param args [Object] argument list for registry
165
+ # @return [self]
105
166
  def registry!(name, *args)
106
167
  SfnRegistry.insert(name, self, *args)
107
168
  end
@@ -20,24 +20,31 @@ require 'sparkle_formation'
20
20
 
21
21
  SparkleFormation::SparkleStruct.camel_keys = true
22
22
 
23
+ # Formation container
23
24
  class SparkleFormation
24
25
 
25
26
  include SparkleFormation::Utils::AnimalStrings
27
+ # @!parse include SparkleFormation::Utils::AnimalStrings
28
+ extend SparkleFormation::Utils::AnimalStrings
29
+ # @!parse extend SparkleFormation::Utils::AnimalStrings
26
30
 
27
31
  class << self
28
32
 
29
- include SparkleFormation::Utils::AnimalStrings
30
-
31
- attr_reader :dynamics
33
+ # @return [Hashish] loaded dynamics
34
+ def dynamics
35
+ @dynamics ||= SparkleStruct.hashish.new
36
+ end
32
37
 
33
- # Return custom paths
38
+ # @return [Hashish] custom paths
34
39
  def custom_paths
35
- @_paths ||= {}
40
+ @_paths ||= SparkleStruct.hashish.new
36
41
  @_paths
37
42
  end
38
43
 
39
- # path:: Path
40
- # Path to sparkle directory
44
+ # Get/set path to sparkle directory
45
+ #
46
+ # @param path [String] path to directory
47
+ # @return [String] path to directory
41
48
  def sparkle_path=(path=nil)
42
49
  if(path)
43
50
  custom_paths[:sparkle_path] = path
@@ -49,8 +56,10 @@ class SparkleFormation
49
56
  end
50
57
  alias_method(:sparkle_path, :sparkle_path=)
51
58
 
52
- # path:: Path
53
- # Set path to component files
59
+ # Get/set path to component files
60
+ #
61
+ # @param path [String] path to component files
62
+ # @return [String] path to component files
54
63
  def components_path=(path=nil)
55
64
  if(path)
56
65
  custom_paths[:components_directory] = path
@@ -59,8 +68,10 @@ class SparkleFormation
59
68
  end
60
69
  alias_method(:components_path, :components_path=)
61
70
 
62
- # path:: Path
63
- # Set path to dynamic files
71
+ # Get/set path to dynamic files
72
+ #
73
+ # @param path [String] path to dynamic files
74
+ # @return [String] path to dynamic files
64
75
  def dynamics_path=(path=nil)
65
76
  if(path)
66
77
  custom_paths[:dynamics_directory] = path
@@ -69,8 +80,10 @@ class SparkleFormation
69
80
  end
70
81
  alias_method(:dynamics_path, :dynamics_path=)
71
82
 
72
- # path:: Path
73
- # Set path to registry files
83
+ # Get/set path to registry files
84
+ #
85
+ # @param path [String] path to registry files
86
+ # @return [String] path to registry files
74
87
  def registry_path=(path=nil)
75
88
  if(path)
76
89
  custom_paths[:registry_directory] = path
@@ -79,32 +92,40 @@ class SparkleFormation
79
92
  end
80
93
  alias_method(:registry_path, :registry_path=)
81
94
 
82
- # path:: Path
83
- # args:: Option symbols
84
- # - :sparkle:: Return formation instead of Hash
85
- # Compile file at given path and return Hash
95
+ # Compile file
96
+ #
97
+ # @param path [String] path to file
98
+ # @param args [Object] use :sparkle to return struct
99
+ # @return [Hashish, SparkleStruct]
86
100
  def compile(path, *args)
87
101
  formation = self.instance_eval(IO.read(path), path, 1)
88
102
  args.include?(:sparkle) ? formation : formation.compile._dump
89
103
  end
90
104
 
91
- # base:: Base SparkleStruct
92
- # Execute given block within base
105
+ # Execute given block within struct context
106
+ #
107
+ # @param base [SparkleStruct] context for block
108
+ # @yield block to execute
109
+ # @return [SparkleStruct] provided base or new struct
93
110
  def build(base=nil, &block)
94
111
  struct = base || SparkleStruct.new
95
112
  struct.instance_exec(&block)
96
113
  @_struct = struct
97
114
  end
98
115
 
99
- # path:: Path
100
- # Load component at given path
116
+ # Load component
117
+ #
118
+ # @param path [String] path to component
119
+ # @return [SparkleStruct] resulting struct
101
120
  def load_component(path)
102
121
  self.instance_eval(IO.read(path), path, 1)
103
122
  @_struct
104
123
  end
105
124
 
106
- # directory:: Path
107
- # Load all dynamics within given directory
125
+ # Load all dynamics within a directory
126
+ #
127
+ # @param directory [String]
128
+ # @return [TrueClass]
108
129
  def load_dynamics!(directory)
109
130
  @loaded_dynamics ||= []
110
131
  Dir.glob(File.join(directory, '*.rb')).each do |dyn|
@@ -117,8 +138,10 @@ class SparkleFormation
117
138
  true
118
139
  end
119
140
 
120
- # directory:: Path
121
- # Load all registry entries within given directory
141
+ # Load all registry entries within a directory
142
+ #
143
+ # @param directory [String]
144
+ # @return [TrueClass]
122
145
  def load_registry!(directory)
123
146
  Dir.glob(File.join(directory, '*.rb')).each do |reg|
124
147
  reg = File.expand_path(reg)
@@ -127,49 +150,66 @@ class SparkleFormation
127
150
  true
128
151
  end
129
152
 
130
- # name:: Name of dynamic
131
- # args:: Optional dynamic metadata
132
- # Define a new dynamic and store associated block
153
+ # Define and register new dynamic
154
+ #
155
+ # @param name [String, Symbol] name of dynamic
156
+ # @param args [Hash] dynamic metadata
157
+ # @param args [Hash] :parameters description of _config parameters
158
+ # @example
159
+ # metadata describes dynamic parameters for _config hash:
160
+ # :item_name => {:description => 'Defines item name', :type => 'String'}
161
+ # @yield dynamic block
162
+ # @return [TrueClass]
133
163
  def dynamic(name, args={}, &block)
134
164
  @dynamics ||= SparkleStruct.hashish.new
135
- @dynamics[name] = SparkleStruct.hashish[
165
+ dynamics[name] = SparkleStruct.hashish[
136
166
  :block, block, :args, SparkleStruct.hashish[args.map(&:to_a)]
137
167
  ]
168
+ true
138
169
  end
139
170
 
140
- # name:: Name of dynamic
141
- # Return metadata about dynamic
171
+ # Metadata for dynamic
172
+ #
173
+ # @param name [String, Symbol] dynamic name
174
+ # @return [Hashish] metadata information
142
175
  def dynamic_info(name)
143
- if(@dynamics[name])
144
- @dynamics[name][:args]
176
+ if(dynamics[name])
177
+ dynamics[name][:args] ||= SparkleStruct.hashish.new
145
178
  else
146
179
  raise KeyError.new("No dynamic registered with provided name (#{name})")
147
180
  end
148
181
  end
149
182
  alias_method :dynamic_information, :dynamic_info
150
183
 
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
184
+ # Insert a dynamic into a context
185
+ #
186
+ # @param dynamic_name [String, Symbol] dynamic name
187
+ # @param struct [SparkleStruct] context for insertion
188
+ # @param args [Object] parameters for dynamic
189
+ # @return [SparkleStruct]
155
190
  def insert(dynamic_name, struct, *args, &block)
156
191
  result = false
157
192
  if(@dynamics && @dynamics[dynamic_name])
158
- struct.instance_exec(*args, &@dynamics[dynamic_name][:block])
193
+ result = struct.instance_exec(*args, &@dynamics[dynamic_name][:block])
194
+ if(block_given?)
195
+ result.instance_exec(&block)
196
+ end
159
197
  result = struct
160
198
  else
161
199
  result = builtin_insert(dynamic_name, struct, *args, &block)
162
200
  end
163
201
  unless(result)
164
- raise "Failed to locate requested dynamic block for insertion: #{dynamic_name} (valid: #{@dynamics.keys.sort.join(', ')})"
202
+ raise "Failed to locate requested dynamic block for insertion: #{dynamic_name} (valid: #{(@dynamics || {}).keys.sort.join(', ')})"
165
203
  end
166
204
  result
167
205
  end
168
206
 
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
207
+ # Insert a builtin dynamic into a context
208
+ #
209
+ # @param dynamic_name [String, Symbol] dynamic name
210
+ # @param struct [SparkleStruct] context for insertion
211
+ # @param args [Object] parameters for dynamic
212
+ # @return [SparkleStruct]
173
213
  def builtin_insert(dynamic_name, struct, *args, &block)
174
214
  if(defined?(SfnAws) && lookup_key = SfnAws.registry_key(dynamic_name))
175
215
  _name, _config = *args
@@ -195,10 +235,11 @@ class SparkleFormation
195
235
  end
196
236
  end
197
237
 
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
238
+ # Convert hash to SparkleStruct instance
239
+ #
240
+ # @param hash [Hashish]
241
+ # @return [SparkleStruct]
242
+ # @note will do best effort on camel key auto discovery
202
243
  def from_hash(hash)
203
244
  struct = SparkleStruct.new
204
245
  struct._camel_keys_set(:auto_discovery)
@@ -208,16 +249,33 @@ class SparkleFormation
208
249
  end
209
250
  end
210
251
 
252
+ # @return [Symbol] name of formation
211
253
  attr_reader :name
254
+ # @return [String] base path
212
255
  attr_reader :sparkle_path
256
+ # @return [String] components path
213
257
  attr_reader :components_directory
258
+ # @return [String] dynamics path
214
259
  attr_reader :dynamics_directory
260
+ # @return [String] registry path
215
261
  attr_reader :registry_directory
262
+ # @return [Array] components to load
216
263
  attr_reader :components
264
+ # @return [Array] order of loading
217
265
  attr_reader :load_order
218
266
 
267
+ # Create new instance
268
+ #
269
+ # @param name [String, Symbol] name of formation
270
+ # @param options [Hash] options
271
+ # @option options [String] :sparkle_path custom base path
272
+ # @option options [String] :components_directory custom components path
273
+ # @option options [String] :dynamics_directory custom dynamics path
274
+ # @option options [String] :registry_directory custom registry path
275
+ # @option options [Truthy, Falsey] :disable_aws_builtins do not load builtins
276
+ # @yield base context
219
277
  def initialize(name, options={}, &block)
220
- @name = name
278
+ @name = name.to_sym
221
279
  @sparkle_path = options[:sparkle_path] ||
222
280
  self.class.custom_paths[:sparkle_path] ||
223
281
  File.join(Dir.pwd, 'cloudformation')
@@ -244,15 +302,21 @@ class SparkleFormation
244
302
  end
245
303
  end
246
304
 
247
- # block:: block to execute
248
- # Loads block
249
- def load_block(block)
305
+ # Add block to load order
306
+ #
307
+ # @param block [Proc]
308
+ # @return [TrueClass]
309
+ def block(block)
250
310
  @components[:__base__] = self.class.build(&block)
251
311
  @load_order << :__base__
312
+ true
252
313
  end
314
+ alias_method :load_block, :block
253
315
 
254
- # args:: symbols or paths for component loads
255
- # Loads components into instance
316
+ # Load components into instance
317
+ #
318
+ # @param args [String, Symbol] Symbol component names or String paths
319
+ # @return [self]
256
320
  def load(*args)
257
321
  args.each do |thing|
258
322
  if(thing.is_a?(Symbol))
@@ -268,12 +332,17 @@ class SparkleFormation
268
332
  end
269
333
 
270
334
  # Registers block into overrides
335
+ #
336
+ # @param args [Hash] optional arguments to provide state
337
+ # @yield override block
271
338
  def overrides(args={}, &block)
272
339
  @overrides << {:args => args, :block => block}
273
340
  self
274
341
  end
275
342
 
276
- # Returns compiled Mash instance
343
+ # Compile the formation
344
+ #
345
+ # @return [SparkleStruct]
277
346
  def compile
278
347
  compiled = SparkleStruct.new
279
348
  @load_order.each do |key|
@@ -288,4 +357,14 @@ class SparkleFormation
288
357
  compiled
289
358
  end
290
359
 
360
+ # @return [Hash] dumped hash
361
+ def dump
362
+ MultiJson.load(self.to_json)
363
+ end
364
+
365
+ # @return [String] dumped hash JSON
366
+ def to_json
367
+ MultiJson.dump(compile.dump!)
368
+ end
369
+
291
370
  end