Class: SparkleFormation
- Inherits:
-
Object
- Object
- SparkleFormation
- Extended by:
- Utils::AnimalStrings, Utils::TypeCheckers
- Includes:
- Bogo::Memoization, Utils::AnimalStrings
- Defined in:
- lib/sparkle_formation.rb,
lib/sparkle_formation/error.rb,
lib/sparkle_formation/utils.rb,
lib/sparkle_formation/sparkle.rb,
lib/sparkle_formation/version.rb,
lib/sparkle_formation/provider.rb,
lib/sparkle_formation/audit_log.rb,
lib/sparkle_formation/resources.rb,
lib/sparkle_formation/composition.rb,
lib/sparkle_formation/translation.rb,
lib/sparkle_formation/provider/aws.rb,
lib/sparkle_formation/provider/heat.rb,
lib/sparkle_formation/resources/aws.rb,
lib/sparkle_formation/provider/azure.rb,
lib/sparkle_formation/resources/heat.rb,
lib/sparkle_formation/sparkle_struct.rb,
lib/sparkle_formation/function_struct.rb,
lib/sparkle_formation/provider/google.rb,
lib/sparkle_formation/resources/azure.rb,
lib/sparkle_formation/resources/google.rb,
lib/sparkle_formation/translation/heat.rb,
lib/sparkle_formation/sparkle_attribute.rb,
lib/sparkle_formation/sparkle_formation.rb,
lib/sparkle_formation/provider/terraform.rb,
lib/sparkle_formation/sparkle_collection.rb,
lib/sparkle_formation/resources/rackspace.rb,
lib/sparkle_formation/resources/terraform.rb,
lib/sparkle_formation/sparkle_attribute/aws.rb,
lib/sparkle_formation/translation/rackspace.rb,
lib/sparkle_formation/sparkle_attribute/heat.rb,
lib/sparkle_formation/sparkle_attribute/azure.rb,
lib/sparkle_formation/sparkle_attribute/google.rb,
lib/sparkle_formation/sparkle_collection/rainbow.rb,
lib/sparkle_formation/sparkle_attribute/rackspace.rb,
lib/sparkle_formation/sparkle_attribute/terraform.rb
Overview
Formation container
Defined Under Namespace
Modules: Provider, SparkleAttribute, Utils Classes: AuditLog, AzureVariableStruct, Cache, Composition, Error, FunctionStruct, GoogleStruct, JinjaExpressionStruct, JinjaStatementStruct, Registry, Resources, Sparkle, SparkleCollection, SparkleStruct, TerraformStruct, Translation
Constant Summary collapse
- SparklePack =
Alias for interfacing naming
Sparkle
- VERSION =
Current library version
Gem::Version.new("3.0.38")
- IGNORE_DIRECTORIES =
Returns directory names to ignore
[ "components", "dynamics", "registry", ]
- SPARKLEFORMATION_ROOT_LIBRARY =
Returns path to root of this library
File.dirname(File.dirname(File.dirname(__FILE__)))
- DEFAULT_STACK_RESOURCE =
Returns default stack resource name
"AWS::CloudFormation::Stack"
- VALID_STACK_RESOURCES =
Returns collection of valid stack resource types
[DEFAULT_STACK_RESOURCE]
- PROVIDER_MAPPINGS =
Returns name mappings for providers used in lookups (resources/sparkles)
Smash.new( :open_stack => :heat, ).freeze
- ALLOWED_GENERATION_PARAMETERS =
Attributes allowed for generation parameter definitions
[ "type", "default", "description", "multiple", "prompt_when_nested", "allowed_values", "allowed_pattern", "max_length", "min_length", "max_value", "min_value", ]
- VALID_GENERATION_PARAMETER_TYPES =
Allowed data types for parameters
["String", "Number", "Complex"]
Instance Attribute Summary collapse
-
#audit_log ⇒ AuditLog
Records of template composition.
-
#blacklisted_templates ⇒ Array<String>
readonly
Black listed templates.
-
#compile_state ⇒ Hash
State hash for compile time parameters.
-
#components_directory ⇒ String
readonly
Components path.
- #composition ⇒ Composition readonly
-
#dynamics_directory ⇒ String
readonly
Dynamics path.
-
#name ⇒ Symbol
Name of formation.
-
#parameters ⇒ Hash
readonly
Parameters for stack generation.
-
#parent ⇒ SparkleFormation
Parent stack.
-
#provider ⇒ Symbol
Target provider.
-
#provider_resources ⇒ Class
readonly
Provider resources.
-
#registry_directory ⇒ String
readonly
Registry path.
-
#sparkle ⇒ Sparkle
readonly
Parts store.
-
#sparkle_path ⇒ String
readonly
Base path.
-
#stack_resource_types ⇒ Array<String>
readonly
Valid stack resource types.
-
#template_path ⇒ String
Local path to template.
Class Method Summary collapse
-
.__t_check(val, types) ⇒ NilClass
extended
from Utils::TypeCheckers
Validate given value is type defined within valid types.
-
.__t_hashish(val) ⇒ NilClass
extended
from Utils::TypeCheckers
Validate given value is a Hash type.
-
.__t_stringish(val) ⇒ NilClass
extended
from Utils::TypeCheckers
Validate given value is String or Symbol type.
-
.build(base = nil) { ... } ⇒ SparkleStruct
Execute given block within struct context.
-
.builtin_insert(dynamic_name, struct, *args, &block) ⇒ SparkleStruct
Insert a builtin dynamic into a context.
-
.camel(string) ⇒ String
extended
from Utils::AnimalStrings
Camel case string.
-
.compile(path, *args) ⇒ Hashish, SparkleStruct
Compile file.
-
.components_path=(path = nil) ⇒ String
(also: components_path)
Get/set path to component files.
-
.custom_paths ⇒ Hashish
Custom paths.
-
.dynamic(name, args = {}) { ... } ⇒ TrueClass
Define and register new dynamic.
-
.dynamic_info(name) ⇒ Hashish
(also: dynamic_information)
Metadata for dynamic.
-
.dynamics ⇒ Hashish
Loaded dynamics.
-
.dynamics_path=(path = nil) ⇒ String
(also: dynamics_path)
Get/set path to dynamic files.
-
.extract_caller(cinfo) ⇒ Array<String, Integer>
Extract the origin of the caller outside this library.
-
.from_hash(hash) ⇒ SparkleStruct
Convert hash to SparkleStruct instance.
-
.insert(dynamic_name, struct, *args, &block) ⇒ SparkleStruct
Insert a dynamic into a context.
-
.load_component(path) ⇒ SparkleStruct
Load component.
-
.load_dynamics!(directory) ⇒ TrueClass
Load all dynamics within a directory.
-
.load_registry!(directory) ⇒ TrueClass
Load all registry entries within a directory.
-
.nest(template, struct, *args, &block) ⇒ SparkleStruct
Nest a template into a context.
-
.registry(registry_name, struct, *args) ⇒ SparkleStruct
Insert a dynamic into a context.
-
.registry_path=(path = nil) ⇒ String
(also: registry_path)
Get/set path to registry files.
-
.snake(string) ⇒ String
extended
from Utils::AnimalStrings
Snake case (underscore) string.
-
.sparkle_path=(path = nil) ⇒ String
(also: sparkle_path)
Get/set path to sparkle directory.
Instance Method Summary collapse
-
#apply_deep_nesting(*args) {|stack, resource, s_name| ... } ⇒ SparkleFormation::SparkleStruct
Apply deeply nested stacks.
-
#apply_nesting(*args, &block) ⇒ SparkleFormation::SparkleStruct
Apply nesting logic to stack.
-
#apply_shallow_nesting(*args) {|resource_name, stack| ... } ⇒ SparkleFormation::SparkleStruct
Apply shallow nesting.
-
#block(block) ⇒ TrueClass
(also: #load_block)
Add block to load order.
-
#camel(string) ⇒ String
included
from Utils::AnimalStrings
Camel case string.
- #collect_outputs(*args) ⇒ Smash<output_name:SparkleFormation>
-
#compile(args = {}) ⇒ SparkleStruct
Compile the formation.
-
#compile_time_parameter_setter {|| ... } ⇒ Proc, NilClass
Get or set the compile time parameter setting block.
-
#dump ⇒ Hash
Dumped hash.
-
#extract_template_data(template) ⇒ self
Extract information from given template and integrate with current instance.
-
#extract_templates {|stack, resource, s_name| ... } ⇒ Object
Extract and process nested stacks.
-
#generate_policy ⇒ Hash
Generate policy for stack.
-
#includes_policies?(stack_hash = nil) ⇒ TrueClass, FalseClass
Policies defined.
-
#inherit_from(template_name) ⇒ self
Inhert template structure.
-
#initialize(name, options = {}) { ... } ⇒ SparkleFormation
constructor
Create new instance.
-
#isolated_nests?(stack_hash = nil) ⇒ TrueClass, FalseClass
Includes only nested stacks.
-
#load(*args, &user_block) ⇒ self
Load components into instance.
-
#make_output_available(output_name, outputs) ⇒ Hash
Extract output to make available for stack parameter usage at the current depth.
-
#merge_previous! ⇒ self
Merge previous layer template structure.
-
#nested?(stack_hash = nil) ⇒ TrueClass, FalseClass
Includes nested stacks.
- #nested_stacks(*args) ⇒ Array<SparkleFormation>
-
#output_matched?(p_name, output_names) ⇒ String, NilClass
Check if parameter name matches an output name.
-
#overrides(args = {}) { ... } ⇒ Object
Registers block into overrides.
-
#recompile ⇒ SparkleStruct
Clear compiled stack if cached and perform compilation again.
-
#remap_nested_parameters(template, parameters, stack_name, stack_resource, output_map) ⇒ TrueClass
Extract parameters from nested stacks.
-
#root ⇒ SparkleFormation
Root stack.
-
#root? ⇒ TrueClass, FalseClass
Current stack is root.
-
#root_path ⇒ Array<SparkleFormation] path to root
Array<SparkleFormation] path to root.
-
#seed_self ⇒ self
Update underlying data structures based on inherit or layering behavior if defined for this template.
-
#set_compile_time_parameters! ⇒ Object
Set the compile time parameters for the stack if the setter proc is available.
-
#set_compiled_state(compiled) ⇒ AttributeStruct
Set the current compile_state into the compiled result.
-
#set_generation_parameters!(params) ⇒ Hash
Validation parameters used for template generation to ensure they are in the expected format.
-
#snake(string) ⇒ String
included
from Utils::AnimalStrings
Snake case (underscore) string.
-
#sparkle_dump ⇒ Hash
Dumped hash.
-
#stack_resource_type ⇒ String
Provider stack resource type.
-
#stack_resource_type?(type) ⇒ TrueClass, FalseClass
Check if type is a registered stack type.
-
#stack_template_extractor(x_stacks, &block) ⇒ Object
Run the stack extraction.
-
#to_json(*args) ⇒ String
Dumped hash JSON.
-
#wrapped_audit(record) ⇒ Object
Wrap given block within audit log of given record.
Constructor Details
#initialize(name, options = {}) { ... } ⇒ SparkleFormation
Create new instance
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 471 def initialize(name, = {}, &base_block) @name = name.to_sym @component_paths = [] if [:sparkle_collection] @sparkle = [:sparkle_collection] if [:sparkle] @sparkle.add_sparkle([:sparkle]) end else @sparkle = SparkleCollection.new if [:sparkle] @sparkle.set_root([:sparkle]) else @sparkle.set_root( Sparkle.new( Smash.new.tap { |h| s_path = .fetch(:sparkle_path, self.class.custom_paths[:sparkle_path]) if s_path h[:root] = s_path else h[:root] = :none end } ) ) end end self.provider = .fetch(:provider, @parent ? @parent.provider : :aws) if provider == :aws || ![:disable_aws_builtins] require "sparkle_formation/aws" end @parameters = set_generation_parameters!( .fetch(:compile_time_parameters, .fetch(:parameters, {})) ) @stack_resource_types = [ stack_resource_type, *.fetch(:stack_resource_types, []), ].compact.uniq @blacklisted_templates = [name] @composition = Composition.new(self) @parent = [:parent] @seed = Smash.new( :inherit => [:inherit], :layering => [:layering], ) if base_block load_block(base_block) end @audit_log = AuditLog.new @compiled = nil end |
Instance Attribute Details
#audit_log ⇒ AuditLog
Returns records of template composition
428 429 430 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 428 def audit_log @audit_log end |
#blacklisted_templates ⇒ Array<String> (readonly)
Returns black listed templates
456 457 458 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 456 def blacklisted_templates @blacklisted_templates end |
#compile_state ⇒ Hash
Returns state hash for compile time parameters
448 449 450 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 448 def compile_state @compile_state end |
#components_directory ⇒ String (readonly)
Returns components path
436 437 438 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 436 def components_directory @components_directory end |
#composition ⇒ Composition (readonly)
458 459 460 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 458 def composition @composition end |
#dynamics_directory ⇒ String (readonly)
Returns dynamics path
438 439 440 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 438 def dynamics_directory @dynamics_directory end |
#name ⇒ Symbol
Returns name of formation
430 431 432 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 430 def name @name end |
#parameters ⇒ Hash (readonly)
Returns parameters for stack generation
442 443 444 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 442 def parameters @parameters end |
#parent ⇒ SparkleFormation
Returns parent stack
444 445 446 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 444 def parent @parent end |
#provider ⇒ Symbol
Returns target provider
450 451 452 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 450 def provider @provider end |
#provider_resources ⇒ Class (readonly)
Returns Provider resources
452 453 454 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 452 def provider_resources @provider_resources end |
#registry_directory ⇒ String (readonly)
Returns registry path
440 441 442 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 440 def registry_directory @registry_directory end |
#sparkle ⇒ Sparkle (readonly)
Returns parts store
432 433 434 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 432 def sparkle @sparkle end |
#sparkle_path ⇒ String (readonly)
Returns base path
434 435 436 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 434 def sparkle_path @sparkle_path end |
#stack_resource_types ⇒ Array<String> (readonly)
Returns valid stack resource types
446 447 448 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 446 def stack_resource_types @stack_resource_types end |
#template_path ⇒ String
Returns local path to template
454 455 456 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 454 def template_path @template_path end |
Class Method Details
.__t_check(val, types) ⇒ NilClass Originally defined in module Utils::TypeCheckers
Validate given value is type defined within valid types
.__t_hashish(val) ⇒ NilClass Originally defined in module Utils::TypeCheckers
Validate given value is a Hash type
.__t_stringish(val) ⇒ NilClass Originally defined in module Utils::TypeCheckers
Validate given value is String or Symbol type
.build(base = nil) { ... } ⇒ SparkleStruct
Execute given block within struct context
125 126 127 128 129 130 131 132 133 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 125 def build(base = nil, &block) if base || block.nil? struct = base || SparkleStruct.new struct.instance_exec(&block) struct else block end end |
.builtin_insert(dynamic_name, struct, *args, &block) ⇒ SparkleStruct
Insert a builtin dynamic into a context
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 375 def builtin_insert(dynamic_name, struct, *args, &block) if struct._self.provider_resources && lookup_key = struct._self.provider_resources.registry_key(dynamic_name) _name, _config = *args _config ||= {} __t_hashish(_config) unless _name.is_a?(SparkleFormation::FunctionStruct) __t_stringish(_name) resource_name = [ _name, _config.fetch(:resource_name_suffix, dynamic_name), ].compact.join("_").to_sym else resource_name = _name._root end _config.delete(:resource_name_suffix) new_resource = struct.resources.set!(resource_name) new_resource.type lookup_key properties = new_resource.properties config_keys = _config.keys.zip(_config.keys.map { |k| snake(k).to_s.tr("_", "") }) struct._self.provider_resources.resource(dynamic_name, :properties).each do |prop_name| key = (config_keys.detect { |k| k.last == snake(prop_name).to_s.tr("_", "") } || []).first value = _config[key] if key if value if value.is_a?(Proc) properties.set!(prop_name, &value) else properties.set!(prop_name, value) end end end new_resource.instance_exec(&block) if block struct._self.provider_resources.resource_customizer(new_resource, lookup_key) new_resource end end |
.camel(string) ⇒ String Originally defined in module Utils::AnimalStrings
Camel case string
.compile(path, *args) ⇒ Hashish, SparkleStruct
Compile file
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 103 def compile(path, *args) opts = args.detect { |i| i.is_a?(Hash) } || {} unless path.is_a?(String) && File.file?(path.to_s) if spath = (opts.delete(:sparkle_path) || SparkleFormation.custom_paths[:sparkle_path]) container = Sparkle.new(:root => spath) path = container.get(:template, path)[:path] end end formation = instance_eval(IO.read(path), path, 1) formation.template_path = path if args.delete(:sparkle) formation else formation.compile(opts)._dump end end |
.components_path=(path = nil) ⇒ String Also known as: components_path
Get/set path to component files
62 63 64 65 66 67 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 62 def components_path=(path = nil) if path custom_paths[:components_directory] = path end custom_paths[:components_directory] end |
.custom_paths ⇒ Hashish
Returns custom paths
37 38 39 40 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 37 def custom_paths @_paths ||= SparkleStruct.hashish.new @_paths end |
.dynamic(name, args = {}) { ... } ⇒ TrueClass
Define and register new dynamic
182 183 184 185 186 187 188 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 182 def dynamic(name, args = {}, &block) @dynamics ||= SparkleStruct.hashish.new dynamics[name] = SparkleStruct.hashish[ :block, block, :args, SparkleStruct.hashish[args.map(&:to_a)] ] true end |
.dynamic_info(name) ⇒ Hashish Also known as: dynamic_information
Metadata for dynamic
194 195 196 197 198 199 200 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 194 def dynamic_info(name) if dynamics[name] dynamics[name][:args] ||= SparkleStruct.hashish.new else raise KeyError.new("No dynamic registered with provided name (#{name})") end end |
.dynamics ⇒ Hashish
Returns loaded dynamics
32 33 34 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 32 def dynamics @dynamics ||= SparkleStruct.hashish.new end |
.dynamics_path=(path = nil) ⇒ String Also known as: dynamics_path
Get/set path to dynamic files
75 76 77 78 79 80 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 75 def dynamics_path=(path = nil) if path custom_paths[:dynamics_directory] = path end custom_paths[:dynamics_directory] end |
.extract_caller(cinfo) ⇒ Array<String, Integer>
Extract the origin of the caller outside this library
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 208 def extract_caller(cinfo) res = cinfo.detect { |c| !c.include?(SPARKLEFORMATION_ROOT_LIBRARY) }.to_s.split(":")[0, 2] if res.size != 2 line = res.last if line.to_i.to_s != line res << 0 end if res != 2 res.unshift(:unknown) end end res end |
.from_hash(hash) ⇒ SparkleStruct
will do best effort on camel key auto discovery
Convert hash to SparkleStruct instance
416 417 418 419 420 421 422 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 416 def from_hash(hash) struct = SparkleStruct.new struct._camel_keys_set(:auto_discovery) struct._load(hash) struct._camel_keys_set(nil) struct end |
.insert(dynamic_name, struct, *args, &block) ⇒ SparkleStruct
Insert a dynamic into a context
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 251 def insert(dynamic_name, struct, *args, &block) __t_stringish(dynamic_name) result = false begin opts = args.detect { |i| i.is_a?(Hash) } || {} dyn = struct._self.sparkle.get(:dynamic, dynamic_name, opts[:provider]) opts = nil raise dyn if dyn.is_a?(Exception) result = nil dyn.monochrome.each do |dynamic_item| record = struct._self.audit_log.push( type: :dynamic, name: dynamic_name, caller: extract_caller(caller), location: dynamic_item[:block].source_location, ) struct._self.wrapped_audit(record) do if result opts = args.detect { |i| i.is_a?(Hash) } if opts opts[:previous_layer_result] = result else args.push(:previous_layer_result => result) end end result = struct.instance_exec(*args, &dynamic_item[:block]) end end if block_given? result.instance_exec(&block) end rescue Error::NotFound::Dynamic record = struct._self.audit_log.push( type: :dynamic, name: dynamic_name, location: [:builtin, 0], caller: extract_caller(caller), ) result = struct._self.wrapped_audit(record) do builtin_insert(dynamic_name, struct, *args, &block) end unless result = "Failed to locate requested dynamic block for insertion: #{dynamic_name} " \ "(valid: #{struct._self.sparkle.dynamics.fetch(struct._self.sparkle.provider, {}).keys.sort.join(", ")})" if struct._self.provider_resources && struct._self.provider_resources.registry.keys.size > 1 t_name = struct._self.provider_resources.registry.keys.first valid_t_name = Bogo::Utility.snake( t_name.split( struct._self.provider_resources.resource_type_splitter ).join("_") ) << "\nBuiltin dynamics pattern `#{t_name}` -> `:#{Bogo::Utility.snake(valid_t_name)}`" end raise end end result end |
.load_component(path) ⇒ SparkleStruct
Load component
139 140 141 142 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 139 def load_component(path) instance_eval(IO.read(path), path, 1) @_struct end |
.load_dynamics!(directory) ⇒ TrueClass
Load all dynamics within a directory
148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 148 def load_dynamics!(directory) @loaded_dynamics ||= [] Dir.glob(File.join(directory, "*.rb")).each do |dyn| dyn = File.(dyn) next if @loaded_dynamics.include?(dyn) instance_eval(IO.read(dyn), dyn, 1) @loaded_dynamics << dyn end @loaded_dynamics.uniq! true end |
.load_registry!(directory) ⇒ TrueClass
Load all registry entries within a directory
164 165 166 167 168 169 170 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 164 def load_registry!(directory) Dir.glob(File.join(directory, "*.rb")).each do |reg| reg = File.(reg) require reg end true end |
.nest(template, struct, *args, &block) ⇒ SparkleStruct
if symbol is provided for template, double underscores will be used for directory separator and dashes will match underscores
Nest a template into a context
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 318 def nest(template, struct, *args, &block) = args.detect { |i| i.is_a?(Hash) } if args.delete() else = {} end [template, *args].compact.each do |item| __t_stringish(item) end to_nest = struct._self.sparkle.get(:template, template, [:provider]) resource_name = template.to_s.gsub("__", "_") unless args.empty? resource_name = [ .delete(:overwrite_name) ? nil : resource_name, args.map { |a| Bogo::Utility.snake(a) }.join("_"), ].flatten.compact.join("_").to_sym end record = struct._self.audit_log.push( type: :template, caller: extract_caller(caller), name: resource_name, location: to_nest[:path], ) struct._self.wrapped_audit(record) do resource_name = struct._process_key(resource_name.to_sym) nested_template = compile(to_nest[:path], :sparkle) nested_template.parent = struct._self nested_template.audit_log = record.audit_log nested_template.name = resource_name if [:parameters] nested_template.compile_state = [:parameters] end unless struct._self.sparkle.empty? nested_template.sparkle.apply(struct._self.sparkle) end nested_resource = struct.dynamic!( struct._self.stack_resource_type, resource_name, {:resource_name_suffix => nil}, &block ) # Ignore the stack resource that we generated in the # audit log since the wrapping template record will # provide the context with actual information record.audit_log.list.pop nested_resource.properties.stack nested_template nested_resource end end |
.registry(registry_name, struct, *args) ⇒ SparkleStruct
Insert a dynamic into a context
230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 230 def registry(registry_name, struct, *args) __t_stringish(registry_name) opts = args.detect { |item| item.is_a?(Hash) } || {} reg = struct._self.sparkle.get(:registry, registry_name, opts[:provider]) record = struct._self.audit_log.push( type: :registry, name: registry_name, location: reg[:block].source_location, caller: extract_caller(caller), ) struct._self.wrapped_audit(record) do struct.instance_exec(*args, ®[:block]) end end |
.registry_path=(path = nil) ⇒ String Also known as: registry_path
Get/set path to registry files
88 89 90 91 92 93 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 88 def registry_path=(path = nil) if path custom_paths[:registry_directory] = path end custom_paths[:registry_directory] end |
.snake(string) ⇒ String Originally defined in module Utils::AnimalStrings
Snake case (underscore) string
.sparkle_path=(path = nil) ⇒ String Also known as: sparkle_path
Get/set path to sparkle directory
46 47 48 49 50 51 52 53 54 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 46 def sparkle_path=(path = nil) if path custom_paths[:sparkle_path] = path custom_paths[:components_directory] = File.join(path, "components") custom_paths[:dynamics_directory] = File.join(path, "dynamics") custom_paths[:registry_directory] = File.join(path, "registry") end custom_paths[:sparkle_path] end |
Instance Method Details
#apply_deep_nesting(*args) {|stack, resource, s_name| ... } ⇒ SparkleFormation::SparkleStruct
Apply deeply nested stacks. This is the new nesting approach and does not bubble parameters up to the root stack. Parameters are isolated to the stack resource itself and output mapping is automatically applied.
996 997 998 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 996 def apply_deep_nesting(*args, &block) compile end |
#apply_nesting(*args, &block) ⇒ SparkleFormation::SparkleStruct
see specific version for expected block parameters
Apply nesting logic to stack
978 979 980 981 982 983 984 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 978 def apply_nesting(*args, &block) if args.include?(:shallow) apply_shallow_nesting(&block) else apply_deep_nesting(&block) end end |
#apply_shallow_nesting(*args) {|resource_name, stack| ... } ⇒ SparkleFormation::SparkleStruct
Apply shallow nesting. This style of nesting will bubble parameters up to the root stack. This type of nesting is the original and now deprecated, but remains for compat issues so any existing usage won't be automatically busted.
1057 1058 1059 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 1057 def apply_shallow_nesting(*args, &block) compile end |
#block(block) ⇒ TrueClass Also known as: load_block
Add block to load order
742 743 744 745 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 742 def block(block) composition.new_component(:__base__, &block) true end |
#camel(string) ⇒ String Originally defined in module Utils::AnimalStrings
Camel case string
#collect_outputs(*args) ⇒ Smash<output_name:SparkleFormation>
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 1062 def collect_outputs(*args) if args.include?(:force) || root? if !compile.outputs.nil? && !root? outputs = Smash[ compile.outputs.keys!.zip( [self] * compile.outputs.keys!.size ) ] else outputs = Smash.new end nested_stacks.each do |nested_stack| if nested_stack.is_a?(self.class) === true n_stack = nested_stack else n_stack = nested_stack._self end outputs = n_stack.collect_outputs(:force).merge(outputs) end outputs else root.collect_outputs(:force) end end |
#compile(args = {}) ⇒ SparkleStruct
Compile the formation
784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 784 def compile(args = {}) if args.key?(:state) && args.is_a?(Hash) @compile_state = args[:state].to_smash unmemoize(:compile) end memoize(:compile) do # NOTE: this is where we inject inherit or layering seed_self set_compile_time_parameters! if provider && SparkleStruct.const_defined?(camel(provider)) struct_class = SparkleStruct.const_get(camel(provider)) struct_name = [SparkleStruct.name, camel(provider)].join("::") struct_class.define_singleton_method(:name) { struct_name } struct_class.define_singleton_method(:to_s) { struct_name } else struct_class = SparkleStruct end load_resources! compiled = struct_class.new compiled._set_self(self) compiled._struct_class = struct_class if struct_class.const_defined?(:CAMEL_KEYS) compiled._camel_keys = struct_class.const_get(:CAMEL_KEYS) end if struct_class.const_defined?(:CAMEL_STYLE) compiled._camel_style = struct_class.const_get(:CAMEL_STYLE) end if compile_state compiled.set_state!(compile_state) end composition.each do |item| case item when Composition::Component if item.block if item.key == "__base__" if parent.nil? record = audit_log.push( type: :template, name: name, location: item.block.source_location.first, caller: [:template, 0], ) # NOTE: Move audit log records under new record's # audit log. This allows components to be listed # logically under the template record instead of # at the same level. record.audit_log.list.replace(audit_log.list) record.audit_log.list.delete(record) audit_log.list.clear audit_log.list << record end else record = audit_log.push( type: :component, name: item.key, location: item.block.source_location.first, caller: [:template, 0], ) end wrapped_audit(record) do self.class.build(compiled, &item.block) end else sparkle.get(:component, item.key).monochrome.each do |component_block| record = audit_log.push( type: :component, name: item.key, location: component_block[:block].source_location.first, caller: [:template, 0], ) wrapped_audit(record) do self.class.build(compiled, &component_block[:block]) end end end when Composition::Override record = audit_log.push( type: :component, name: :override, location: item.block.source_location.first, caller: [:template, 0], ) if item.args && !item.args.empty? compiled._set_state(item.args) end wrapped_audit(record) do self.class.build(compiled, &item.block) end end end if compile_state && !compile_state.empty? set_compiled_state(compiled) end compiled end end |
#compile_time_parameter_setter {|| ... } ⇒ Proc, NilClass
Get or set the compile time parameter setting block. If a get request the ancestor path will be searched to root
700 701 702 703 704 705 706 707 708 709 710 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 700 def compile_time_parameter_setter(&block) if block @compile_time_parameter_setter = block else if @compile_time_parameter_setter @compile_time_parameter_setter else parent.nil? ? nil : parent.compile_time_parameter_setter end end end |
#dump ⇒ Hash
Returns dumped hash
1106 1107 1108 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 1106 def dump MultiJson.load(to_json) end |
#extract_template_data(template) ⇒ self
Extract information from given template and integrate with current instance
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 601 def extract_template_data(template) # TODO: Should allow forced override here for cases like: openstack -> rackspace if provider != template.provider raise TypeError.new "This template `#{name}` cannot inherit template `#{template.name}`! Provider mismatch: `#{provider}` != `#{template.provider}`" # rubocop:disable Metrics/LineLength end template.sparkle.apply(sparkle) template.seed_self blacklisted_templates.replace( (blacklisted_templates + template.blacklisted_templates).map(&:to_s).uniq ) @parameters = template.parameters.to_smash.deep_merge(parameters.to_smash) new_composition = Composition.new(self, :components => template.composition.composite, :overrides => composition.overrides) composition.components.each do |item| if item.respond_to?(:key) && item.key == "__base__" item.key = Smash.new( :template => name, :component => :__base__, :object_id => object_id, ).checksum.to_s end new_composition.add_component(item) end @composition = new_composition self end |
#extract_templates {|stack, resource, s_name| ... } ⇒ Object
Extract and process nested stacks
1028 1029 1030 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 1028 def extract_templates(&block) stack_template_extractor(nested_stacks(:with_resource, :with_name), &block) end |
#generate_policy ⇒ Hash
Generate policy for stack
969 970 971 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 969 def generate_policy Smash.new end |
#includes_policies?(stack_hash = nil) ⇒ TrueClass, FalseClass
Returns policies defined
955 956 957 958 959 960 961 962 963 964 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 955 def includes_policies?(stack_hash = nil) if stack_hash raise Error::Deprecated.new "Hash parameter no longer valid for this method (`#{self.class}##{__callee__}`)" end unless compile.resources.nil? compile.resources._data.any? do |r_name, r_value| !r_value.policy.nil? end end end |
#inherit_from(template_name) ⇒ self
Inhert template structure
586 587 588 589 590 591 592 593 594 595 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 586 def inherit_from(template_name) if blacklisted_templates.map(&:to_s).include?(template_name.to_s) raise Error::CircularInheritance.new "Circular inheritance detected between templates `#{template_name}` and `#{name}`" # rubocop:disable Metrics/LineLength end template = self.class.compile(sparkle.get(:template, template_name)[:path], :sparkle) template.blacklisted_templates.replace( (template.blacklisted_templates + blacklisted_templates).map(&:to_s).uniq ) extract_template_data(template) end |
#isolated_nests?(stack_hash = nil) ⇒ TrueClass, FalseClass
Returns includes only nested stacks
943 944 945 946 947 948 949 950 951 952 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 943 def isolated_nests?(stack_hash = nil) if stack_hash raise Error::Deprecated.new "Hash parameter no longer valid for this method (`#{self.class}##{__callee__}`)" end unless compile.resources.nil? compile.resources._data.all? do |r_name, r_value| stack_resource_type?(r_value.type) end end end |
#load(*args, &user_block) ⇒ self
Load components into instance
753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 753 def load(*args, &user_block) args.each do |thing| if thing.is_a?(String) # NOTE: This needs to be deprecated and removed # TODO: deprecate key = File.basename(thing.to_s).sub(".rb", "") composition.new_component(key, &self.class.load_component(thing)) else composition.new_component(thing) end end if block_given? block(user_block) end self end |
#make_output_available(output_name, outputs) ⇒ Hash
Extract output to make available for stack parameter usage at the current depth
1018 1019 1020 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 1018 def make_output_available(output_name, outputs) {} end |
#merge_previous! ⇒ self
Merge previous layer template structure
574 575 576 577 578 579 580 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 574 def merge_previous! my_index = sparkle.get(:template, name).spectrum.find_index do |item| item[:path] == template_path end template = self.class.compile(sparkle.get(:template, name).layer_at(my_index - 1)[:path], :sparkle) extract_template_data(template) end |
#nested?(stack_hash = nil) ⇒ TrueClass, FalseClass
Returns includes nested stacks
931 932 933 934 935 936 937 938 939 940 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 931 def nested?(stack_hash = nil) if stack_hash raise Error::Deprecated.new "Hash parameter no longer valid for this method (`#{self.class}##{__callee__}`)" end unless compile.resources.nil? compile.resources._data.any? do |r_name, r_value| stack_resource_type?(r_value.type) end end end |
#nested_stacks(*args) ⇒ Array<SparkleFormation>
909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 909 def nested_stacks(*args) if compile[:resources] compile.resources.keys!.map do |key| if stack_resource_type?(compile.resources[key].type) if !compile.resources[key].properties.stack.nil? result = [compile.resources[key].properties.stack] if args.include?(:with_resource) result.push(compile[:resources][key]) end if args.include?(:with_name) result.push(key) end result.size == 1 ? result.first : result end end end.compact else [] end end |
#output_matched?(p_name, output_names) ⇒ String, NilClass
will auto downcase name prior to comparison
Check if parameter name matches an output name
1006 1007 1008 1009 1010 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 1006 def output_matched?(p_name, output_names) output_names.detect do |o_name| Bogo::Utility.snake(o_name).tr("_", "") == Bogo::Utility.snake(p_name).tr("_", "") end end |
#overrides(args = {}) { ... } ⇒ Object
Registers block into overrides
774 775 776 777 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 774 def overrides(args = {}, &block) composition.new_override(args, &block) self end |
#recompile ⇒ SparkleStruct
Clear compiled stack if cached and perform compilation again
903 904 905 906 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 903 def recompile unmemoize(:compile) compile end |
#remap_nested_parameters(template, parameters, stack_name, stack_resource, output_map) ⇒ TrueClass
if parameter has includes StackUnique
a new parameter will
be added to container stack and it will not use outputs
Extract parameters from nested stacks. Check for previous nested stack outputs that match parameter. If match, set parameter to use output. If no match, check container stack parameters for match. If match, set to use ref. If no match, add parameter to container stack parameters and set to use ref.
1101 1102 1103 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 1101 def remap_nested_parameters(template, parameters, stack_name, stack_resource, output_map) true end |
#root ⇒ SparkleFormation
Returns root stack
663 664 665 666 667 668 669 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 663 def root if parent parent.root else self end end |
#root? ⇒ TrueClass, FalseClass
Returns current stack is root
681 682 683 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 681 def root? root == self end |
#root_path ⇒ Array<SparkleFormation] path to root
Returns Array<SparkleFormation] path to root
672 673 674 675 676 677 678 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 672 def root_path if parent [*parent.root_path, self].compact else [self] end end |
#seed_self ⇒ self
Update underlying data structures based on inherit or layering behavior if defined for this template
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 555 def seed_self memoize(:seed) do = @seed if [:inherit] && [:layering].to_s == "merge" raise ArgumentError.new "Cannot merge and inherit!" end if [:inherit] inherit_from([:inherit]) elsif [:layering].to_s == "merge" merge_previous! end true end self end |
#set_compile_time_parameters! ⇒ Object
Set the compile time parameters for the stack if the setter proc is available
714 715 716 717 718 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 714 def set_compile_time_parameters! if compile_time_parameter_setter compile_time_parameter_setter.call(self) end end |
#set_compiled_state(compiled) ⇒ AttributeStruct
Set the current compile_state into the compiled result
887 888 889 890 891 892 893 894 895 896 897 898 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 887 def set_compiled_state(compiled) storage_compile_state = Smash.new parameters.each do |param_key, param_config| if param_config.fetch(:type, "string").to_s.downcase.to_sym != :complex storage_compile_state[param_key] = compile_state[param_key] end end unless storage_compile_state.empty? compiled.outputs.compile_state.value MultiJson.dump(storage_compile_state) end compiled end |
#set_generation_parameters!(params) ⇒ Hash
Validation parameters used for template generation to ensure they are in the expected format
726 727 728 729 730 731 732 733 734 735 736 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 726 def set_generation_parameters!(params) params.each do |name, value| unless value.is_a?(Hash) raise TypeError.new("Expecting `Hash` type. Received `#{value.class}`") end if key = value.keys.detect { |k| !ALLOWED_GENERATION_PARAMETERS.include?(k.to_s) } raise ArgumentError.new("Invalid generation parameter key provided `#{key}`") end end params end |
#snake(string) ⇒ String Originally defined in module Utils::AnimalStrings
Snake case (underscore) string
#sparkle_dump ⇒ Hash
Returns dumped hash
1111 1112 1113 1114 1115 1116 1117 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 1111 def sparkle_dump MultiJson.load( MultiJson.dump( compile.sparkle_dump! ) ) end |
#stack_resource_type ⇒ String
Returns provider stack resource type
630 631 632 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 630 def stack_resource_type DEFAULT_STACK_RESOURCE end |
#stack_resource_type?(type) ⇒ TrueClass, FalseClass
Check if type is a registered stack type
658 659 660 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 658 def stack_resource_type?(type) stack_resource_types.include?(type) end |
#stack_template_extractor(x_stacks, &block) ⇒ Object
Run the stack extraction
1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 1035 def stack_template_extractor(x_stacks, &block) x_stacks.each do |stack, resource, s_name| unless stack.nested_stacks.empty? stack_template_extractor(stack.nested_stacks(:with_resource, :with_name), &block) end resource.properties._delete(:stack) s_parent = resource.properties.stack stack.compile._parent(s_parent) resource.properties.set!(:stack, stack.compile) block.call(s_name, stack, resource) end end |
#to_json(*args) ⇒ String
Returns dumped hash JSON
1120 1121 1122 1123 1124 1125 1126 1127 1128 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 1120 def to_json(*args) # NOTE: Ported in from batali # Prevent stupid conversion errors of # JSON::Ext::Generator::State into Hash args = args.map do |argument| argument.respond_to?(:to_h) ? argument.to_h : argument end MultiJson.dump(compile.dump!, *args) end |
#wrapped_audit(record) ⇒ Object
Wrap given block within audit log of given record
542 543 544 545 546 547 548 |
# File 'lib/sparkle_formation/sparkle_formation.rb', line 542 def wrapped_audit(record) start_log = audit_log @audit_log = record ? record.audit_log : start_log yield ensure @audit_log = start_log end |