sparkle_formation 3.0.34 → 3.0.36

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.
@@ -14,6 +14,8 @@ class SparkleFormation
14
14
  "registry",
15
15
  ]
16
16
 
17
+ # @return [String] path to root of this library
18
+ SPARKLEFORMATION_ROOT_LIBRARY = File.dirname(File.dirname(File.dirname(__FILE__)))
17
19
  # @return [String] default stack resource name
18
20
  DEFAULT_STACK_RESOURCE = "AWS::CloudFormation::Stack"
19
21
  # @return [Array<String>] collection of valid stack resource types
@@ -199,6 +201,26 @@ class SparkleFormation
199
201
 
200
202
  alias_method :dynamic_information, :dynamic_info
201
203
 
204
+ # Extract the origin of the caller outside this library
205
+ #
206
+ # @param cinfo [Array<String>] caller info
207
+ # @return [Array<String, Integer>] caller path and line number
208
+ def extract_caller(cinfo)
209
+ res = cinfo.detect { |c|
210
+ !c.include?(SPARKLEFORMATION_ROOT_LIBRARY)
211
+ }.to_s.split(":")[0, 2]
212
+ if res.size != 2
213
+ line = res.last
214
+ if line.to_i.to_s != line
215
+ res << 0
216
+ end
217
+ if res != 2
218
+ res.unshift(:unknown)
219
+ end
220
+ end
221
+ res
222
+ end
223
+
202
224
  # Insert a dynamic into a context
203
225
  #
204
226
  # @param dynamic_name [String, Symbol] dynamic name
@@ -209,7 +231,15 @@ class SparkleFormation
209
231
  __t_stringish(registry_name)
210
232
  opts = args.detect { |item| item.is_a?(Hash) } || {}
211
233
  reg = struct._self.sparkle.get(:registry, registry_name, opts[:provider])
212
- struct.instance_exec(*args, &reg[:block])
234
+ record = struct._self.audit_log.push(
235
+ type: :registry,
236
+ name: registry_name,
237
+ location: reg[:block].source_location,
238
+ caller: extract_caller(caller),
239
+ )
240
+ struct._self.wrapped_audit(record) do
241
+ struct.instance_exec(*args, &reg[:block])
242
+ end
213
243
  end
214
244
 
215
245
  # Insert a dynamic into a context
@@ -226,22 +256,39 @@ class SparkleFormation
226
256
  dyn = struct._self.sparkle.get(:dynamic, dynamic_name, opts[:provider])
227
257
  opts = nil
228
258
  raise dyn if dyn.is_a?(Exception)
259
+ result = nil
229
260
  dyn.monochrome.each do |dynamic_item|
230
- if result
231
- opts = args.detect { |i| i.is_a?(Hash) }
232
- if opts
233
- opts[:previous_layer_result] = result
234
- else
235
- args.push(:previous_layer_result => result)
261
+ record = struct._self.audit_log.push(
262
+ type: :dynamic,
263
+ name: dynamic_name,
264
+ caller: extract_caller(caller),
265
+ location: dynamic_item[:block].source_location,
266
+ )
267
+ struct._self.wrapped_audit(record) do
268
+ if result
269
+ opts = args.detect { |i| i.is_a?(Hash) }
270
+ if opts
271
+ opts[:previous_layer_result] = result
272
+ else
273
+ args.push(:previous_layer_result => result)
274
+ end
236
275
  end
276
+ result = struct.instance_exec(*args, &dynamic_item[:block])
237
277
  end
238
- result = struct.instance_exec(*args, &dynamic_item[:block])
239
278
  end
240
279
  if block_given?
241
280
  result.instance_exec(&block)
242
281
  end
243
282
  rescue Error::NotFound::Dynamic
244
- result = builtin_insert(dynamic_name, struct, *args, &block)
283
+ record = struct._self.audit_log.push(
284
+ type: :dynamic,
285
+ name: dynamic_name,
286
+ location: [:builtin, 0],
287
+ caller: extract_caller(caller),
288
+ )
289
+ result = struct._self.wrapped_audit(record) do
290
+ builtin_insert(dynamic_name, struct, *args, &block)
291
+ end
245
292
  unless result
246
293
  message = "Failed to locate requested dynamic block for insertion: #{dynamic_name} " \
247
294
  "(valid: #{struct._self.sparkle.dynamics.fetch(struct._self.sparkle.provider, {}).keys.sort.join(", ")})"
@@ -286,24 +333,37 @@ class SparkleFormation
286
333
  args.map { |a| Bogo::Utility.snake(a) }.join("_"),
287
334
  ].flatten.compact.join("_").to_sym
288
335
  end
289
- resource_name = struct._process_key(resource_name.to_sym)
290
- nested_template = compile(to_nest[:path], :sparkle)
291
- nested_template.parent = struct._self
292
- nested_template.name = resource_name
293
- if options[:parameters]
294
- nested_template.compile_state = options[:parameters]
295
- end
296
- unless struct._self.sparkle.empty?
297
- nested_template.sparkle.apply(struct._self.sparkle)
298
- end
299
- nested_resource = struct.dynamic!(
300
- struct._self.stack_resource_type,
301
- resource_name,
302
- {:resource_name_suffix => nil},
303
- &block
336
+ record = struct._self.audit_log.push(
337
+ type: :template,
338
+ caller: extract_caller(caller),
339
+ name: resource_name,
340
+ location: to_nest[:path],
304
341
  )
305
- nested_resource.properties.stack nested_template
306
- nested_resource
342
+ struct._self.wrapped_audit(record) do
343
+ resource_name = struct._process_key(resource_name.to_sym)
344
+ nested_template = compile(to_nest[:path], :sparkle)
345
+ nested_template.parent = struct._self
346
+ nested_template.audit_log = record.audit_log
347
+ nested_template.name = resource_name
348
+ if options[:parameters]
349
+ nested_template.compile_state = options[:parameters]
350
+ end
351
+ unless struct._self.sparkle.empty?
352
+ nested_template.sparkle.apply(struct._self.sparkle)
353
+ end
354
+ nested_resource = struct.dynamic!(
355
+ struct._self.stack_resource_type,
356
+ resource_name,
357
+ {:resource_name_suffix => nil},
358
+ &block
359
+ )
360
+ # Ignore the stack resource that we generated in the
361
+ # audit log since the wrapping template record will
362
+ # provide the context with actual information
363
+ record.audit_log.list.pop
364
+ nested_resource.properties.stack nested_template
365
+ nested_resource
366
+ end
307
367
  end
308
368
 
309
369
  # Insert a builtin dynamic into a context
@@ -364,6 +424,8 @@ class SparkleFormation
364
424
 
365
425
  include Bogo::Memoization
366
426
 
427
+ # @return [AuditLog] records of template composition
428
+ attr_accessor :audit_log
367
429
  # @return [Symbol] name of formation
368
430
  attr_accessor :name
369
431
  # @return [Sparkle] parts store
@@ -379,7 +441,7 @@ class SparkleFormation
379
441
  # @return [Hash] parameters for stack generation
380
442
  attr_reader :parameters
381
443
  # @return [SparkleFormation] parent stack
382
- attr_accessor :parent
444
+ attr_reader :parent
383
445
  # @return [Array<String>] valid stack resource types
384
446
  attr_reader :stack_resource_types
385
447
  # @return [Hash] state hash for compile time parameters
@@ -456,9 +518,35 @@ class SparkleFormation
456
518
  if base_block
457
519
  load_block(base_block)
458
520
  end
521
+ @audit_log = AuditLog.new
459
522
  @compiled = nil
460
523
  end
461
524
 
525
+ # Set the parent template
526
+ #
527
+ # @param p [SparkleFormation] parent template
528
+ # @return [self]
529
+ def parent=(p)
530
+ unless p.is_a?(SparkleFormation)
531
+ raise TypeError, "Expected `SparkleFormation` but received `#{p.class.name}`"
532
+ end
533
+ @parent = p
534
+ @audit_log = p.audit_log
535
+ self
536
+ end
537
+
538
+ # Wrap given block within audit log of given record
539
+ #
540
+ # @param record [AuditLog::Record]
541
+ # @return [Object] result of yield
542
+ def wrapped_audit(record)
543
+ start_log = audit_log
544
+ @audit_log = record ? record.audit_log : start_log
545
+ yield
546
+ ensure
547
+ @audit_log = start_log
548
+ end
549
+
462
550
  # Update underlying data structures based on inherit
463
551
  # or layering behavior if defined for this template
464
552
  #
@@ -728,17 +816,50 @@ class SparkleFormation
728
816
  case item
729
817
  when Composition::Component
730
818
  if item.block
731
- self.class.build(compiled, &item.block)
819
+ if item.key == "__base__"
820
+ record = audit_log.push(
821
+ type: :template,
822
+ name: name,
823
+ location: item.block.source_location.first,
824
+ caller: [:template, 0],
825
+ ) if parent.nil?
826
+ else
827
+ record = audit_log.push(
828
+ type: :component,
829
+ name: item.key,
830
+ location: item.block.source_location.first,
831
+ caller: [:template, 0],
832
+ )
833
+ end
834
+ wrapped_audit(record) do
835
+ self.class.build(compiled, &item.block)
836
+ end
732
837
  else
733
838
  sparkle.get(:component, item.key).monochrome.each do |component_block|
734
- self.class.build(compiled, &component_block[:block])
839
+ record = audit_log.push(
840
+ type: :component,
841
+ name: item.key,
842
+ location: component_block[:block].source_location.first,
843
+ caller: [:template, 0],
844
+ )
845
+ wrapped_audit(record) do
846
+ self.class.build(compiled, &component_block[:block])
847
+ end
735
848
  end
736
849
  end
737
850
  when Composition::Override
851
+ record = audit_log.push(
852
+ type: :component,
853
+ name: :override,
854
+ location: item.block.source_location.first,
855
+ caller: [:template, 0],
856
+ )
738
857
  if item.args && !item.args.empty?
739
858
  compiled._set_state(item.args)
740
859
  end
741
- self.class.build(compiled, &item.block)
860
+ wrapped_audit(record) do
861
+ self.class.build(compiled, &item.block)
862
+ end
742
863
  end
743
864
  end
744
865
  if compile_state && !compile_state.empty?
@@ -1,5 +1,5 @@
1
1
  # Unicorns and rainbows
2
2
  class SparkleFormation
3
3
  # Current library version
4
- VERSION = Gem::Version.new("3.0.34")
4
+ VERSION = Gem::Version.new("3.0.36")
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sparkle_formation
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.34
4
+ version: 3.0.36
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Roberts
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-30 00:00:00.000000000 Z
11
+ date: 2019-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: attribute_struct
@@ -188,6 +188,7 @@ files:
188
188
  - docs/v/jquery-2.1.3.min.js
189
189
  - docs/v/loader.js
190
190
  - lib/sparkle_formation.rb
191
+ - lib/sparkle_formation/audit_log.rb
191
192
  - lib/sparkle_formation/aws.rb
192
193
  - lib/sparkle_formation/composition.rb
193
194
  - lib/sparkle_formation/error.rb