sparkle_formation 2.1.8 → 3.0.0

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.
@@ -5,6 +5,123 @@ class SparkleFormation
5
5
  # Independent collection of SparkleFormation items
6
6
  class Sparkle
7
7
 
8
+ # Evaluation context wrapper for loading SparkleFormation files
9
+ class EvalWrapper < BasicObject
10
+
11
+ # @!visibility private
12
+ def require(*args)
13
+ ::Kernel.require(*args)
14
+ end
15
+
16
+ # @!visibility private
17
+ class SparkleFormation
18
+
19
+ attr_accessor :sparkle_path
20
+
21
+ class << self
22
+
23
+ def insert(*args, &block)
24
+ ::SparkleFormation.insert(*args, &block)
25
+ end
26
+
27
+ def part_data(data=nil)
28
+ if(data)
29
+ @data = data
30
+ else
31
+ @data
32
+ end
33
+ end
34
+
35
+ def dynamic(name, args={}, &block)
36
+ part_data[:dynamic].push(
37
+ ::Smash.new(
38
+ :name => name,
39
+ :block => block,
40
+ :args => ::Smash[
41
+ args.map(&:to_a)
42
+ ],
43
+ :type => :dynamic
44
+ )
45
+ ).last
46
+ end
47
+
48
+ def build(&block)
49
+ part_data[:component].push(
50
+ ::Smash.new(
51
+ :block => block,
52
+ :type => :component
53
+ )
54
+ ).last
55
+ end
56
+
57
+ def component(name, args={}, &block)
58
+ part_data[:component].push(
59
+ ::Smash.new(
60
+ :name => name,
61
+ :block => block,
62
+ :args => ::Smash[
63
+ args.map(&:to_a)
64
+ ],
65
+ :type => :component
66
+ )
67
+ ).last
68
+ end
69
+
70
+ def dynamic_info(*args)
71
+ ::Smash.new(:metadata => {}, :args => {})
72
+ end
73
+
74
+ end
75
+
76
+ def initialize(*args)
77
+ opts = args.detect{|a| a.is_a?(Hash)} || {}
78
+ SparkleFormation.part_data[:template].push(
79
+ ::Smash.new(
80
+ :name => args.first,
81
+ :args => opts
82
+ )
83
+ )
84
+ raise ::TypeError
85
+ end
86
+
87
+ # @!visibility private
88
+ class Registry
89
+
90
+ def self.register(name, args={}, &block)
91
+ SparkleFormation.part_data[:registry].push(
92
+ ::Smash.new(
93
+ :name => name,
94
+ :block => block,
95
+ :args => ::Smash[
96
+ args.map(&:to_a)
97
+ ],
98
+ :type => :registry
99
+ )
100
+ ).last
101
+ end
102
+
103
+ end
104
+ end
105
+
106
+ # @!visibility private
107
+ SfnRegistry = SparkleFormation::Registry
108
+
109
+ # NOTE: Enable access to top level constants but do not
110
+ # include deprecated constants to prevent warning outputs
111
+ ::Object.constants.each do |const|
112
+ unless(self.const_defined?(const)) # rubocop:disable Style/RedundantSelf
113
+ next if const == :Config || const == :TimeoutError
114
+ self.const_set(const, ::Object.const_get(const)) # rubocop:disable Style/RedundantSelf
115
+ end
116
+ end
117
+
118
+ # @!visibility private
119
+ def part_data(arg)
120
+ SparkleFormation.part_data(arg)
121
+ end
122
+
123
+ end
124
+
8
125
  class << self
9
126
 
10
127
  @@_pack_registry = Smash.new
@@ -61,113 +178,9 @@ class SparkleFormation
61
178
  end
62
179
 
63
180
  # Wrapper for evaluating sfn files to store within sparkle
64
- # container and remove global application
65
- # rubocop:disable Metrics/MethodLength
181
+ # container
66
182
  def eval_wrapper
67
- klass = Class.new(BasicObject)
68
- klass.class_eval(<<-EOS
69
- def require(*args)
70
- ::Kernel.require *args
71
- end
72
-
73
- class SparkleFormation
74
-
75
- attr_accessor :sparkle_path
76
-
77
- class << self
78
-
79
- def insert(*args, &block)
80
- ::SparkleFormation.insert(*args, &block)
81
- end
82
-
83
- def part_data(data=nil)
84
- if(data)
85
- @data = data
86
- else
87
- @data
88
- end
89
- end
90
-
91
- def dynamic(name, args={}, &block)
92
- part_data[:dynamic].push(
93
- ::Smash.new(
94
- :name => name,
95
- :block => block,
96
- :args => Smash[
97
- args.map(&:to_a)
98
- ],
99
- :type => :dynamic
100
- )
101
- ).last
102
- end
103
-
104
- def build(&block)
105
- part_data[:component].push(
106
- ::Smash.new(
107
- :block => block,
108
- :type => :component
109
- )
110
- ).last
111
- end
112
-
113
- def component(name, args={}, &block)
114
- part_data[:component].push(
115
- ::Smash.new(
116
- :name => name,
117
- :block => block,
118
- :args => Smash[
119
- args.map(&:to_a)
120
- ],
121
- :type => :component
122
- )
123
- ).last
124
- end
125
-
126
- def dynamic_info(*args)
127
- Smash.new(:metadata => {}, :args => {})
128
- end
129
-
130
- end
131
-
132
- def initialize(*args)
133
- SparkleFormation.part_data[:template].push(
134
- ::Smash.new(
135
- :name => args.first
136
- )
137
- )
138
- raise TypeError
139
- end
140
-
141
- class Registry
142
-
143
- def self.register(name, &block)
144
- SparkleFormation.part_data[:registry].push(
145
- ::Smash.new(
146
- :name => name,
147
- :block => block,
148
- :type => :registry
149
- )
150
- ).last
151
- end
152
-
153
- end
154
- end
155
-
156
- SfnRegistry = SparkleFormation::Registry
157
-
158
- ::Object.constants.each do |const|
159
- unless(self.const_defined?(const))
160
- next if const == :Config || const == :TimeoutError # prevent warning output
161
- self.const_set(const, ::Object.const_get(const))
162
- end
163
- end
164
-
165
- def part_data(arg)
166
- SparkleFormation.part_data(arg)
167
- end
168
- EOS
169
- )
170
- klass
183
+ Class.new(EvalWrapper)
171
184
  end
172
185
 
173
186
  include Bogo::Memoization
@@ -200,12 +213,15 @@ class SparkleFormation
200
213
  attr_reader :root
201
214
  # @return [Smash] raw part data
202
215
  attr_reader :raw_data
216
+ # @return [Symbol] provider
217
+ attr_accessor :provider
203
218
 
204
219
  # Create new sparkle instance
205
220
  #
206
221
  # @param args [Hash]
207
222
  # @option args [String] :root path to sparkle directories
208
223
  # @option args [String, Symbol] :name registered pack name
224
+ # @option args [String, Symbol] :provider name of default provider
209
225
  # @return [self]
210
226
  def initialize(args={})
211
227
  if(args[:name])
@@ -213,7 +229,7 @@ class SparkleFormation
213
229
  else
214
230
  @root = args.fetch(:root, locate_root)
215
231
  end
216
- unless(File.directory?(@root))
232
+ if(@root != :none && !File.directory?(@root))
217
233
  raise Errno::ENOENT.new("No such directory - #{@root}")
218
234
  end
219
235
  @raw_data = Smash.new(
@@ -222,9 +238,10 @@ class SparkleFormation
222
238
  :registry => [],
223
239
  :template => []
224
240
  )
241
+ @provider = Bogo::Utility.snake(args.fetch(:provider, 'aws').to_s).to_sym
225
242
  @wrapper = eval_wrapper.new
226
243
  wrapper.part_data(raw_data)
227
- load_parts!
244
+ load_parts! unless @root == :none
228
245
  end
229
246
 
230
247
  # @return [Smash<name:block>]
@@ -259,16 +276,20 @@ class SparkleFormation
259
276
  #
260
277
  # @param type [String, Symbol] item type (see: TYPES)
261
278
  # @param name [String, Symbol] name of item
279
+ # @param target_provider [String, Symbol] restrict to provider
262
280
  # @return [Smash] requested item
263
281
  # @raises [NameError, Error::NotFound]
264
- def get(type, name)
282
+ def get(type, name, target_provider=nil)
265
283
  unless(TYPES.keys.include?(type.to_s))
266
284
  raise NameError.new "Invalid type requested (#{type})! Valid types: #{TYPES.keys.join(', ')}"
267
285
  end
268
- result = send(TYPES[type])[name]
286
+ unless(target_provider)
287
+ target_provider = provider
288
+ end
289
+ result = send(TYPES[type]).get(target_provider, name)
269
290
  if(result.nil? && TYPES[type] == 'templates')
270
291
  result = (
271
- send(TYPES[type]).detect{|_, v|
292
+ send(TYPES[type]).fetch(target_provider, Smash.new).detect{|_, v|
272
293
  name = name.to_s
273
294
  short_name = v[:path].sub(%r{#{Regexp.escape(root)}/?}, '')
274
295
  v[:path] == name ||
@@ -323,13 +344,16 @@ class SparkleFormation
323
344
  unless(data[:name])
324
345
  data[:name] = slim_path.tr('/', '__').sub(/\.(rb|json)$/, '')
325
346
  end
326
- if(templates[data[:name]])
327
- raise KeyError.new "Template name is already in use within pack! (`#{data[:name]}`)"
347
+ t_provider = data.fetch(:args, :provider, :aws)
348
+ if(templates.get(t_provider, data[:name]))
349
+ raise KeyError.new "Template name is already in use within pack! (`#{data[:name]}` -> `#{t_provider}`)"
328
350
  end
329
- templates[data[:name]] = data.merge(
330
- :type => :template,
331
- :path => file,
332
- :serialized => !file.end_with?('.rb')
351
+ templates.set(t_provider, data[:name],
352
+ data.merge(
353
+ :type => :template,
354
+ :path => file,
355
+ :serialized => !file.end_with?('.rb')
356
+ )
333
357
  )
334
358
  end
335
359
  end
@@ -343,10 +367,11 @@ class SparkleFormation
343
367
  type, name = path.slice(path.size - 2, 2)
344
368
  collection = send(type)
345
369
  end
346
- if(collection[name])
347
- raise KeyError.new "#{key.capitalize} name is already in use within pack! (`#{name}`)"
370
+ i_provider = item.fetch(:args, :provider, :aws)
371
+ if(collection.get(i_provider, name))
372
+ raise KeyError.new "#{key.capitalize} name is already in use within pack! (`#{name}` -> #{i_provider})"
348
373
  end
349
- collection[name] = item
374
+ collection.set(i_provider, name, item)
350
375
  end
351
376
  end
352
377
  end
@@ -7,6 +7,7 @@ class SparkleFormation
7
7
 
8
8
  autoload :Aws, 'sparkle_formation/sparkle_attribute/aws'
9
9
  autoload :Azure, 'sparkle_formation/sparkle_attribute/azure'
10
+ autoload :Google, 'sparkle_formation/sparkle_attribute/google'
10
11
  autoload :Heat, 'sparkle_formation/sparkle_attribute/heat'
11
12
  autoload :Rackspace, 'sparkle_formation/sparkle_attribute/rackspace'
12
13
 
@@ -41,9 +42,10 @@ class SparkleFormation
41
42
  end
42
43
  alias_method :system!, :_system
43
44
 
44
- # Print to stdout
45
- #
46
- # @param args
45
+ # @overload _puts(obj, ...)
46
+ # Print to stdout
47
+ # @param obj [Object] object to print
48
+ # @see Kernel.puts
47
49
  # @return [NilClass]
48
50
  def _puts(*args)
49
51
  $stdout.puts(*args)
@@ -51,45 +53,82 @@ class SparkleFormation
51
53
  alias_method :puts!, :_puts
52
54
 
53
55
  # Raise an exception
56
+ # @see Kernel.raise
54
57
  def _raise(*args)
55
58
  ::Kernel.raise(*args)
56
59
  end
57
60
  alias_method :raise!, :_raise
58
61
 
59
- # Lookup a method definition on self
60
- # usually used as `puts! method!(:foo).source_location`
62
+ # @overload _method(sym)
63
+ # Lookup a method definition on self
64
+ # @param sym [Symbol] name of method
65
+ # @note usually used as `puts! method!(:foo).source_location`
66
+ # @see Object#method
61
67
  # @return [Method]
62
68
  def _method(*args)
63
69
  ::Kernel.instance_method(:method).bind(self).call(*args)
64
70
  end
65
71
  alias_method :method!, :_method
66
72
 
67
- # Dynamic insertion helper method
68
- #
69
- # @param name [String, Symbol] dynamic name
70
- # @param args [Object] argument list for dynamic
73
+ # @overload _dynamic(resource_type, custom_name, options={})
74
+ # Insert builtin resource
75
+ # @param resource_type [String, Symbol] provider resource type
76
+ # @param custom_name [String, Symbol] custom name used for resource name generation
77
+ # @param options [Hash]
78
+ # @option options [String, NilClass] :resource_name_suffix custom suffix to use for
79
+ # name generation (defaults to resource_type)
80
+ # @note All other options are set into the new resource's properties
81
+ # @overload _dynamic(dynamic_name, custom_name, options={})
82
+ # Call custom dynamic from available sparkle packs
83
+ # @param dynamic_name [Symbol] name of registered dynamic
84
+ # @param custom_name [Symbol, String] unique name passed directly to registered dynamic
85
+ # @param options [Hash]
86
+ # @option options [String, Symbol] :provider override provider restriction when fetching dynamic
87
+ # @note All options are passed to dynamic with custom_name
88
+ # @yieldblock [new_struct] Provides newly inserted structure
89
+ # @yieldparam new_struct [SparkleStruct] newly inserted structure which can be modified
90
+ # @yieldreturn [Object] discarded
71
91
  # @return [self]
72
- def dynamic!(name, *args, &block)
92
+ def _dynamic(name, *args, &block)
73
93
  SparkleFormation.insert(name, self, *args, &block)
74
94
  end
95
+ alias_method :dynamic!, :_dynamic
75
96
 
76
- # Registry insertion helper method
77
- #
78
- # @param name [String, Symbol] name of registry item
79
- # @param args [Object] argument list for registry
80
- # @return [self]
81
- def registry!(name, *args)
97
+ # @overload _registry(name)
98
+ # Return value from registry item with given name
99
+ # @param name [String, Symbol] registry item name
100
+ # @overload _registry(name, *args, options={})
101
+ # Pass given parameters to registry item with given name and
102
+ # return the value
103
+ # @param name [String, Symbol] registry item name
104
+ # @param options [Hash]
105
+ # @param options [Hash] :provider override provider restriction when fetching registry item
106
+ # @param args [Object] argument list
107
+ # @note args and options will be passed directly to registry item when called
108
+ # @return [Object] return value of registry item
109
+ def _registry(name, *args)
82
110
  SparkleFormation.registry(name, self, *args)
83
111
  end
112
+ alias_method :registry!, :_registry
84
113
 
85
- # Stack nesting helper method
86
- #
87
- # @param template [String, Symbol] template to nest
88
- # @param args [String, Symbol] stringified and underscore joined for name
114
+ # @overload _nest(template, *names, options={})
115
+ # Nest a stack resource
116
+ # @param template [String, Symbol] name of desired template
117
+ # @param names [String, Symbol] list of optional string/symbol values for resource name generation
118
+ # @param options [Hash]
119
+ # @option options [String, Symbol] :provider override provider restriction when
120
+ # fetching template
121
+ # @option options [Truthy, Falsey] :overwrite_name when set to true, will not include
122
+ # template name in resource name
123
+ # @option options [Hash] :parameters compile time parameter values to pass to nested template
124
+ # @yieldblock [new_struct] Provides newly inserted structure
125
+ # @yieldparam new_struct [SparkleStruct] newly inserted structure which can be modified
126
+ # @yieldreturn [Object] discarded
89
127
  # @return [self]
90
- def nest!(template, *args, &block)
128
+ def _nest(template, *args, &block)
91
129
  SparkleFormation.nest(template, self, *args, &block)
92
130
  end
131
+ alias_method :nest!, :_nest
93
132
 
94
133
  # Format the provided key. If symbol type is provided
95
134
  # formatting is forced. Otherwise the default formatting