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.
@@ -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)