sparkle_formation 2.1.8 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,9 +8,12 @@ class SparkleFormation
8
8
  # AWS specific helper implementations
9
9
  module Aws
10
10
 
11
- # Fn::Join generator
12
- #
13
- # @param args [Object]
11
+ # @overload _cf_join(*args, opts={})
12
+ # Fn::Join generator
13
+ # @param args [String, Hash] list of items to join
14
+ # @param opts [Hash]
15
+ # @option opts [Hash] :options options for join function
16
+ # @option options [String] :delimiter value used for joining items. Defaults to ''
14
17
  # @return [Hash]
15
18
  def _cf_join(*args)
16
19
  options = args.detect{|i| i.is_a?(Hash) && i[:options]} || {:options => {}}
@@ -34,11 +37,11 @@ class SparkleFormation
34
37
  alias_method :_ref, :_cf_ref
35
38
  alias_method :ref!, :_cf_ref
36
39
 
37
- # Fn::FindInMap generator
38
- #
39
- # @param thing [String, Symbol] thing to find
40
- # @param key [String, Symbol] thing to search
41
- # @param suffix [Object] additional args
40
+ # @overload _cf_map(map_name, top_level_key, second_level_key)
41
+ # Fn::FindInMap generator
42
+ # @param map_name [String, Symbol] name of map
43
+ # @param top_level_key [String, Symbol, Hash] top level key name
44
+ # @param second_level_key [String, Symbol, Hash] second level key name
42
45
  # @return [Hash]
43
46
  def _cf_map(thing, key, *suffix)
44
47
  __t_stringish(thing)
@@ -59,9 +62,10 @@ class SparkleFormation
59
62
  alias_method :find_in_map!, :_cf_map
60
63
  alias_method :map!, :_cf_map
61
64
 
62
- # Fn::GetAtt generator
63
- #
64
- # @param [Object] pass through arguments
65
+ # @overload _cf_attr(logical_id, attribute_name)
66
+ # Fn::GetAtt generator
67
+ # @param logical_id [String, Symbol] logical resource name
68
+ # @param attribute_name [String, Symbol] name of desired resource attribute
65
69
  # @return [Hash]
66
70
  def _cf_attr(*args)
67
71
  r_name = args.first
@@ -82,7 +86,7 @@ class SparkleFormation
82
86
 
83
87
  # Fn::Base64 generator
84
88
  #
85
- # @param arg [Object] pass through
89
+ # @param arg [Object] argument to be encoded
86
90
  # @return [Hash]
87
91
  def _cf_base64(arg)
88
92
  {'Fn::Base64' => arg}
@@ -143,8 +147,8 @@ class SparkleFormation
143
147
  # Fn::If generator
144
148
  #
145
149
  # @param cond [String, Symbol] symbol will be case processed
146
- # @param true_value [Object]
147
- # @param false_value [Object]
150
+ # @param true_value [Object] item to be used when true
151
+ # @param false_value [Object] item to be used when false
148
152
  # @return [Hash]
149
153
  def _if(cond, true_value, false_value)
150
154
  {'Fn::If' => _array(__attribute_key(cond), true_value, false_value)}
@@ -153,7 +157,7 @@ class SparkleFormation
153
157
 
154
158
  # Fn::And generator
155
159
  #
156
- # @param args [Object]
160
+ # @param args [Object] items to be AND'ed together
157
161
  # @return [Hash]
158
162
  # @note symbols will be processed and set as condition. strings
159
163
  # will be set as condition directly. procs will be evaluated
@@ -218,7 +222,7 @@ class SparkleFormation
218
222
 
219
223
  # No value generator
220
224
  #
221
- # @return [String]
225
+ # @return [Hash]
222
226
  def _no_value
223
227
  _ref('AWS::NoValue')
224
228
  end
@@ -265,9 +269,14 @@ class SparkleFormation
265
269
  alias_method :stack_name!, :_stack_name
266
270
 
267
271
  # Resource dependency generator
268
- #
269
- # @param [Symbol, String, Array<Symbol, String>] resource names
272
+ # @overload _depends_on(resource_name)
273
+ # @param resource_name [String, Symbol] logical resource name
274
+ # @overload _depends_on(resource_names)
275
+ # @param resource_names [Array<String, Symbol>] list of logical resource names
276
+ # @overload _depends_on(*resource_names)
277
+ # @param resource_names [Array<String, Symbol>] list of logical resource names
270
278
  # @return [Array<String>]
279
+ # @note this will directly modify the struct at its current context to inject depends on structure
271
280
  def _depends_on(*args)
272
281
  _set('DependsOn', [args].flatten.compact.map{|s| __attribute_key(s)})
273
282
  end
@@ -77,6 +77,9 @@ class SparkleFormation
77
77
  'subscription'
78
78
  ]
79
79
 
80
+ # NOTE: Alias implementation disabled due to Ruby 2.3 __callee__ bug
81
+ # see: https://bugs.ruby-lang.org/issues/12176
82
+
80
83
  # Generate a builtin azure function
81
84
  #
82
85
  # @return [SparkleFormation::FunctionStruct]
@@ -89,15 +92,22 @@ class SparkleFormation
89
92
  AZURE_FUNCTIONS.map do |f_name|
90
93
  ::Bogo::Utility.snake(f_name)
91
94
  end.each do |f_name|
92
- alias_method "_#{f_name}".to_sym, :_fn_format
93
- alias_method "#{f_name}!".to_sym, :_fn_format
95
+ # alias_method "_#{f_name}".to_sym, :_fn_format
96
+ # alias_method "#{f_name}!".to_sym, :_fn_format
97
+
98
+ define_method("_#{f_name}".to_sym) do |*args|
99
+ src = ::Kernel.__callee__.to_s
100
+ src = ::Bogo::Utility.camel(src.sub(/(^_|\!$)/, ''), false)
101
+ ::SparkleFormation::FunctionStruct.new(src, *args)
102
+ end
103
+ alias_method "#{f_name}!".to_sym, "_#{f_name}".to_sym
94
104
  end
95
105
 
96
- # Customized resourceId generator that will perform automatic
97
- # lookup on defined resources for building the function if Symbol
98
- # type is provided
99
- #
100
- # @param args [Object]
106
+ # @overload _resource_id(resource_name)
107
+ # Customized resourceId generator that will perform automatic
108
+ # lookup on defined resources for building the function if Symbol
109
+ # type is provided
110
+ # @param [String, Symbol] name of resource
101
111
  # @return [FunctionStruct]
102
112
  def _resource_id(*args)
103
113
  if(args.size > 1)
@@ -118,12 +128,15 @@ class SparkleFormation
118
128
  end
119
129
  alias_method :resource_id!, :_resource_id
120
130
 
121
- # Customized dependsOn generator. Will automatically build resource
122
- # reference value using defined resources for Symbol type values. Sets
123
- # directly into current context.
124
- #
125
- # @param args [Object]
131
+ # Resource dependency generator
132
+ # @overload _depends_on(resource_name)
133
+ # @param resource_name [String, Symbol] logical resource name
134
+ # @overload _depends_on(resource_names)
135
+ # @param resource_names [Array<String, Symbol>] list of logical resource names
136
+ # @overload _depends_on(*resource_names)
137
+ # @param resource_names [Array<String, Symbol>] list of logical resource names
126
138
  # @return [Array<String>]
139
+ # @note this will directly modify the struct at its current context to inject depends on structure
127
140
  def _depends_on(*args)
128
141
  args = args.map do |item|
129
142
  case item
@@ -0,0 +1,149 @@
1
+ require 'zlib'
2
+ require 'sparkle_formation'
3
+
4
+ class SparkleFormation
5
+ module SparkleAttribute
6
+
7
+ # Google specific helper implementations
8
+ module Google
9
+
10
+ CHARACTER_COLLECTION = ('a'..'z').to_a
11
+
12
+ def self.included(klass)
13
+ klass.const_set(:CAMEL_STYLE, :no_leading)
14
+
15
+ klass.class_eval do
16
+ def _google_dump
17
+ result = _non_google_attribute_struct_dump
18
+ if(_parent.nil?)
19
+ sparkle_root = {}
20
+ if(result.key?('resources') && result['resources'].is_a?(Hash))
21
+ resources = result.delete('resources') || {}
22
+ sparkle_root = (resources.delete(_self.name) || {}).fetch('properties', {})
23
+ result['resources'] = resources.map do |r_name, r_content|
24
+ r_content.merge('name' => r_name)
25
+ end
26
+ outputs = result.delete('outputs') || {}
27
+ result['outputs'] = outputs.map do |o_name, o_content|
28
+ o_content.merge('name' => o_name)
29
+ end
30
+ if(_self.parent.nil?)
31
+ result = {
32
+ 'resources' => [{
33
+ 'name' => _self.name,
34
+ 'type' => _self.stack_resource_type,
35
+ 'properties' => {
36
+ 'stack' => result
37
+ }.merge(sparkle_root)
38
+ }]
39
+ }
40
+ end
41
+ end
42
+ end
43
+ result
44
+ end
45
+ alias_method :_non_google_attribute_struct_dump, :_dump
46
+ alias_method :_dump, :_google_dump
47
+ alias_method :dump!, :_google_dump
48
+ alias_method :_non_google_dynamic!, :dynamic!
49
+ alias_method :dynamic!, :_google_dynamic!
50
+ end
51
+ end
52
+
53
+ # Customized dynamic to provide automatic unique name generation for
54
+ # built in resources
55
+ #
56
+ # @see SparkleFormation::SparkleAttribute#dynamic!
57
+ # @note generate unique names using the `:sparkle_unique` argument
58
+ def _google_dynamic!(name, *args, &block)
59
+ if(args.delete(:sparkle_unique))
60
+ seed = Zlib.crc32(_self.root_path.map(&:name).join('-'))
61
+ gen = Random.new(seed)
62
+ suffix = Array.new(10) do
63
+ CHARACTER_COLLECTION.at(
64
+ gen.rand(CHARACTER_COLLECTION.size
65
+ )
66
+ )
67
+ end.join
68
+ config_hash = args.detect{|a| a.is_a?(Hash)}
69
+ unless(config_hash)
70
+ config_hash = {}
71
+ args.push(config_hash)
72
+ end
73
+ config_hash[:resource_name_suffix] = "-#{suffix}"
74
+ args[0] = args.first.to_s.tr('_', '-').downcase
75
+ end
76
+ _non_google_dynamic!(name, *args, &block)
77
+ end
78
+
79
+ # Reference generator. Will lookup defined resource name
80
+ # to validate exist.
81
+ #
82
+ # @param r_name [String, Symbol] resource name
83
+ # @return [SparkleFormation::GoogleStruct]
84
+ def _ref(r_name)
85
+ __t_stringish(r_name)
86
+ if(_root.resources.set!(r_name).nil?)
87
+ ::Kernel.raise ::SparkleFormation::Error::NotFound::Resource.new(:name => r_name)
88
+ else
89
+ ::SparkleFormation::GoogleStruct.new('ref').set!(__attribute_key(r_name))
90
+ end
91
+ end
92
+ alias_method :ref!, :_ref
93
+
94
+ # Jinja function string wrapper
95
+ #
96
+ # @return [SparkleFormation::JinjaExpressionStruct]
97
+ def _jinja
98
+ ::SparkleFormation::JinjaExpressionStruct.new
99
+ end
100
+ alias_method :jinja!, :_jinja
101
+ alias_method :fn!, :_jinja
102
+
103
+ # Request deployment manager environment variable
104
+ #
105
+ # @param e_name [String, Symbol] environment variable name
106
+ # @return [SparkleFormation::JinjaExpressionStruct]
107
+ def _env(e_name)
108
+ __t_stringish(e_name)
109
+ _jinja.env[__attribute_key(e_name)]
110
+ end
111
+ alias_method :env!, :_env
112
+
113
+ # Access a property value supplied to template
114
+ #
115
+ # @param p_name [String, Symbol] parameter name
116
+ # @return [SparkleFormation::JinjaExpressionStruct]
117
+ # @todo Provide lookup validation that defined p_name is valid
118
+ def _property(p_name)
119
+ __t_stringish(p_name)
120
+ _jinja.properties[__attribute_key(p_name)]
121
+ end
122
+ alias_method :property!, :_property
123
+ alias_method :properties!, :_property
124
+
125
+ # Generate a statement
126
+ #
127
+ # @param line [String]
128
+ # @return [SparkleFormation::JinjaStatementStruct]
129
+ def _statement(line)
130
+ ::SparkleFormation::JinjaStatementStruct.new(line)
131
+ end
132
+ alias_method :statement!, :_statement
133
+
134
+ # Reference output value from nested stack
135
+ #
136
+ # @param stack_name [String, Symbol] logical resource name of stack
137
+ # @param output_name [String, Symbol] stack output name
138
+ # @return [SparkleFormation::JinjaExpressionStruct]
139
+ def _stack_output(stack_name, output_name)
140
+ __t_stringish(stack_name)
141
+ __t_stringish(output_name)
142
+ _ref(stack_name)._set(output_name)
143
+ end
144
+ alias_method :stack_output!, :_stack_output
145
+
146
+ end
147
+
148
+ end
149
+ end
@@ -13,9 +13,10 @@ class SparkleFormation
13
13
  klass.const_set(:CAMEL_KEYS, false)
14
14
  end
15
15
 
16
- # get_attr generator
17
- #
18
- # @param [Object] pass through arguments
16
+ # @overload _get_attr(logical_id, attribute_name)
17
+ # get_attr generator
18
+ # @param logical_id [String, Symbol] logical resource name
19
+ # @param attribute_name [String, Symbol] name of desired resource attribute
19
20
  # @return [Hash]
20
21
  def _get_attr(*args)
21
22
  __t_stringish(args.first)
@@ -27,9 +28,12 @@ class SparkleFormation
27
28
  alias_method :_attr, :_get_attr
28
29
  alias_method :attr!, :_get_attr
29
30
 
30
- # list_join generator
31
- #
32
- # @param args [Object]
31
+ # @overload _list_join(*args, opts={})
32
+ # list_join generator
33
+ # @param args [String, Hash] list of items to join
34
+ # @param opts [Hash]
35
+ # @option opts [Hash] :options options for join function
36
+ # @option options [String] :delimiter value used for joining items. Defaults to ''
33
37
  # @return [Hash]
34
38
  def _list_join(*args)
35
39
  options = args.detect{|i| i.is_a?(::Hash) && i[:options]} || {:options => {}}
@@ -53,9 +57,14 @@ class SparkleFormation
53
57
  alias_method :_file, :_get_file
54
58
  alias_method :file!, :_get_file
55
59
 
56
- # get_param generator
57
- #
58
- # @param args [Object]
60
+ # @overload _get_param(name)
61
+ # get_param generator
62
+ # @param name [String, Symbol] name of parameter
63
+ # @overload _get_param(name, index1, index2, ...)
64
+ # get_param generator accessing complex data
65
+ # @param name [String, Symbol] name of parameter
66
+ # @param index1 [Object] value for key/index
67
+ # @param index2 [Object] value for key/index
59
68
  # @return [Hash]
60
69
  def _get_param(*args)
61
70
  __t_stringish(args.first)
@@ -78,6 +87,10 @@ class SparkleFormation
78
87
  alias_method :_resource, :_get_resource
79
88
  alias_method :resource!, :_get_resource
80
89
 
90
+ # digest generator
91
+ #
92
+ # @param value [String, Hash] thing to be hashed
93
+ # @param algorithm [String] algorithm to use (defaults to 'sha512')
81
94
  def _digest(value, algorithm='sha512')
82
95
  __t_string(algorithm)
83
96
  {'digest' => [algorithm, value]}
@@ -122,9 +135,10 @@ class SparkleFormation
122
135
  alias_method :_split, :_str_split
123
136
  alias_method :split!, :_str_split
124
137
 
125
- # map_merge generator
126
- #
127
- # @param args [Object]
138
+ # @overload _map_merge(hash1, hash2, ...)
139
+ # map_merge generator
140
+ # @param hash1 [Hash] item to merge
141
+ # @param hash2 [Hash] item to merge
128
142
  # @return [Hash]
129
143
  def _map_merge(*args)
130
144
  {'map_merge' => args}
@@ -150,9 +164,14 @@ class SparkleFormation
150
164
  alias_method :project_id!, :_project_id
151
165
 
152
166
  # Resource dependency generator
153
- #
154
- # @param [Symbol, String, Array<Symbol, String>] resource names
167
+ # @overload _depends_on(resource_name)
168
+ # @param resource_name [String, Symbol] logical resource name
169
+ # @overload _depends_on(resource_names)
170
+ # @param resource_names [Array<String, Symbol>] list of logical resource names
171
+ # @overload _depends_on(*resource_names)
172
+ # @param resource_names [Array<String, Symbol>] list of logical resource names
155
173
  # @return [Array<String>]
174
+ # @note this will directly modify the struct at its current context to inject depends on structure
156
175
  def _depends_on(*args)
157
176
  _set('depends_on', [args].flatten.compact.map{|s| __attribute_key(s) })
158
177
  end
@@ -8,10 +8,16 @@ class SparkleFormation
8
8
 
9
9
  autoload :Rainbow, 'sparkle_formation/sparkle_collection/rainbow'
10
10
 
11
+ # @return [Symbol] provider
12
+ attr_accessor :provider
13
+
11
14
  # Create a new collection of sparkles
12
15
  #
16
+ # @param args [Hash]
17
+ # @option args [Symbol, String] :provider name of default provider
13
18
  # @return [self]
14
- def initialize(*_)
19
+ def initialize(args={})
20
+ @provider = Bogo::Utility.snake(args.to_smash.fetch(:provider, 'aws')).to_sym
15
21
  @root = nil
16
22
  @sparkles = []
17
23
  end
@@ -81,9 +87,13 @@ class SparkleFormation
81
87
  memoize("components_#{checksum}") do
82
88
  Smash.new.tap do |hsh|
83
89
  sparkles.each do |sprkl|
84
- sprkl.components.each_pair do |c_name, c_value|
85
- hsh[c_name] ||= Rainbow.new(c_name, :component)
86
- hsh[c_name].add_layer(c_value)
90
+ sprkl.components.each_pair do |c_provider, c_info|
91
+ c_info.each_pair do |c_name, c_value|
92
+ unless(hsh.get(c_provider, c_name))
93
+ hsh.set(c_provider, c_name, Rainbow.new(c_name, :component))
94
+ end
95
+ hsh.get(c_provider, c_name).add_layer(c_value)
96
+ end
87
97
  end
88
98
  end
89
99
  end
@@ -95,9 +105,13 @@ class SparkleFormation
95
105
  memoize("dynamics_#{checksum}") do
96
106
  Smash.new.tap do |hsh|
97
107
  sparkles.each do |sprkl|
98
- sprkl.dynamics.each_pair do |c_name, c_value|
99
- hsh[c_name] ||= Rainbow.new(c_name, :dynamic)
100
- hsh[c_name].add_layer(c_value)
108
+ sprkl.dynamics.each_pair do |c_provider, c_info|
109
+ c_info.each_pair do |c_name, c_value|
110
+ unless(hsh.get(c_provider, c_name))
111
+ hsh.set(c_provider, c_name, Rainbow.new(c_name, :dynamic))
112
+ end
113
+ hsh.get(c_provider, c_name).add_layer(c_value)
114
+ end
101
115
  end
102
116
  end
103
117
  end
@@ -109,7 +123,7 @@ class SparkleFormation
109
123
  memoize("registries_#{checksum}") do
110
124
  Smash.new.tap do |hsh|
111
125
  sparkles.each do |sprkl|
112
- hsh.merge!(sprkl.registries)
126
+ hsh.deep_merge!(sprkl.registries)
113
127
  end
114
128
  end
115
129
  end
@@ -120,9 +134,13 @@ class SparkleFormation
120
134
  memoize("templates_#{checksum}") do
121
135
  Smash.new.tap do |hsh|
122
136
  sparkles.each do |sprkl|
123
- sprkl.templates.each_pair do |c_name, c_value|
124
- hsh[c_name] ||= Rainbow.new(c_name, :template)
125
- hsh[c_name].add_layer(c_value)
137
+ sprkl.templates.each_pair do |c_provider, c_info|
138
+ c_info.each_pair do |c_name, c_value|
139
+ unless(hsh.get(c_provider, c_name))
140
+ hsh.set(c_provider, c_name, Rainbow.new(c_name, :template))
141
+ end
142
+ hsh.get(c_provider, c_name).add_layer(c_value)
143
+ end
126
144
  end
127
145
  end
128
146
  end
@@ -133,25 +151,29 @@ class SparkleFormation
133
151
  #
134
152
  # @param type [String, Symbol] item type (see: TYPES)
135
153
  # @param name [String, Symbol] name of item
154
+ # @param target_provider [String, Symbol] restrict to provider
136
155
  # @return [Smash] requested item
137
156
  # @raises [NameError, Error::NotFound]
138
- def get(type, name)
157
+ def get(type, name, target_provider=nil)
139
158
  type_name = Sparkle::TYPES[type.to_s]
140
159
  unless(type_name)
141
160
  raise ArgumentError.new "Unknown file type requested from collection `#{type}`"
142
161
  end
143
162
  result = nil
144
163
  error = nil
145
- result = send(type_name)[name]
164
+ unless(target_provider)
165
+ target_provider = provider
166
+ end
167
+ result = send(type_name).get(target_provider, name)
146
168
  if(result.nil? && type_name == 'templates')
147
169
  t_direct = sparkles.map do |pack|
148
170
  begin
149
- pack.get(:template, name)
171
+ pack.get(:template, name, target_provider)
150
172
  rescue Error::NotFound
151
173
  end
152
174
  end.compact.last
153
175
  if(t_direct)
154
- result = send(type_name)[t_direct[:name]]
176
+ result = send(type_name).get(target_provider, t_direct[:name])
155
177
  end
156
178
  end
157
179
  unless(result)