sparkle_formation 1.2.0 → 2.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.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +9 -0
 - data/bin/generate_sparkle_docs +21 -6
 - data/docs/helper-methods.md +26 -49
 - data/lib/sparkle_formation.rb +3 -0
 - data/lib/sparkle_formation/error.rb +8 -0
 - data/lib/sparkle_formation/function_struct.rb +123 -0
 - data/lib/sparkle_formation/provider.rb +12 -0
 - data/lib/sparkle_formation/provider/aws.rb +201 -0
 - data/lib/sparkle_formation/provider/azure.rb +168 -0
 - data/lib/sparkle_formation/provider/heat.rb +163 -0
 - data/lib/sparkle_formation/resources.rb +27 -10
 - data/lib/sparkle_formation/resources/azure.rb +42 -0
 - data/lib/sparkle_formation/resources/azure_resources.json +353 -0
 - data/lib/sparkle_formation/resources/heat.rb +39 -0
 - data/lib/sparkle_formation/resources/heat_resources.json +4994 -0
 - data/lib/sparkle_formation/resources/rackspace.rb +39 -0
 - data/lib/sparkle_formation/resources/rackspace_resources.json +2561 -0
 - data/lib/sparkle_formation/sparkle_attribute.rb +14 -19
 - data/lib/sparkle_formation/sparkle_attribute/aws.rb +12 -12
 - data/lib/sparkle_formation/sparkle_attribute/azure.rb +161 -0
 - data/lib/sparkle_formation/sparkle_attribute/heat.rb +177 -0
 - data/lib/sparkle_formation/sparkle_attribute/rackspace.rb +21 -0
 - data/lib/sparkle_formation/sparkle_formation.rb +70 -154
 - data/lib/sparkle_formation/sparkle_struct.rb +39 -2
 - data/lib/sparkle_formation/version.rb +1 -1
 - data/sparkle_formation.gemspec +7 -3
 - metadata +63 -7
 
| 
         @@ -0,0 +1,168 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'sparkle_formation'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class SparkleFormation
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Provider
         
     | 
| 
      
 5 
     | 
    
         
            +
                # Azure specific implementation
         
     | 
| 
      
 6 
     | 
    
         
            +
                module Azure
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  # @return [String] Type string for Azure Resource Manager stack resource
         
     | 
| 
      
 9 
     | 
    
         
            +
                  def stack_resource_type
         
     | 
| 
      
 10 
     | 
    
         
            +
                    'Microsoft.Resources/deployments'
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  # Generate policy for stack
         
     | 
| 
      
 14 
     | 
    
         
            +
                  #
         
     | 
| 
      
 15 
     | 
    
         
            +
                  # @return [Hash]
         
     | 
| 
      
 16 
     | 
    
         
            +
                  def generate_policy
         
     | 
| 
      
 17 
     | 
    
         
            +
                    {}
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  # Apply deeply nested stacks. This is the new nesting approach and
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # does not bubble parameters up to the root stack. Parameters are
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # isolated to the stack resource itself and output mapping is
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # automatically applied.
         
     | 
| 
      
 24 
     | 
    
         
            +
                  #
         
     | 
| 
      
 25 
     | 
    
         
            +
                  # @yieldparam stack [SparkleFormation] stack instance
         
     | 
| 
      
 26 
     | 
    
         
            +
                  # @yieldparam resource [AttributeStruct] the stack resource
         
     | 
| 
      
 27 
     | 
    
         
            +
                  # @yieldparam s_name [String] stack resource name
         
     | 
| 
      
 28 
     | 
    
         
            +
                  # @yieldreturn [Hash] key/values to be merged into resource properties
         
     | 
| 
      
 29 
     | 
    
         
            +
                  # @return [Hash] dumped stack
         
     | 
| 
      
 30 
     | 
    
         
            +
                  def apply_deep_nesting(*args, &block)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    outputs = collect_outputs
         
     | 
| 
      
 32 
     | 
    
         
            +
                    nested_stacks(:with_resource).each do |stack, resource|
         
     | 
| 
      
 33 
     | 
    
         
            +
                      unless(stack.nested_stacks.empty?)
         
     | 
| 
      
 34 
     | 
    
         
            +
                        stack.apply_deep_nesting(*args)
         
     | 
| 
      
 35 
     | 
    
         
            +
                      end
         
     | 
| 
      
 36 
     | 
    
         
            +
                      stack.compile.parameters.keys!.each do |parameter_name|
         
     | 
| 
      
 37 
     | 
    
         
            +
                        if(output_name = output_matched?(parameter_name, outputs.keys))
         
     | 
| 
      
 38 
     | 
    
         
            +
                          next if outputs[output_name] == stack
         
     | 
| 
      
 39 
     | 
    
         
            +
                          stack_output = stack.make_output_available(output_name, outputs)
         
     | 
| 
      
 40 
     | 
    
         
            +
                          resource.properties.parameters._set(parameter_name).value stack_output
         
     | 
| 
      
 41 
     | 
    
         
            +
                        end
         
     | 
| 
      
 42 
     | 
    
         
            +
                      end
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
                    if(block_given?)
         
     | 
| 
      
 45 
     | 
    
         
            +
                      extract_templates(&block)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    end
         
     | 
| 
      
 47 
     | 
    
         
            +
                    compile.dump!
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  # Apply shallow nesting. This style of nesting will bubble
         
     | 
| 
      
 51 
     | 
    
         
            +
                  # parameters up to the root stack. This type of nesting is the
         
     | 
| 
      
 52 
     | 
    
         
            +
                  # original and now deprecated, but remains for compat issues so any
         
     | 
| 
      
 53 
     | 
    
         
            +
                  # existing usage won't be automatically busted.
         
     | 
| 
      
 54 
     | 
    
         
            +
                  #
         
     | 
| 
      
 55 
     | 
    
         
            +
                  # @yieldparam resource_name [String] name of stack resource
         
     | 
| 
      
 56 
     | 
    
         
            +
                  # @yieldparam stack [SparkleFormation] nested stack
         
     | 
| 
      
 57 
     | 
    
         
            +
                  # @yieldreturn [String] Remote URL storage for template
         
     | 
| 
      
 58 
     | 
    
         
            +
                  # @return [Hash]
         
     | 
| 
      
 59 
     | 
    
         
            +
                  def apply_shallow_nesting(*args, &block)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    parameters = compile.parameters
         
     | 
| 
      
 61 
     | 
    
         
            +
                    output_map = {}
         
     | 
| 
      
 62 
     | 
    
         
            +
                    nested_stacks(:with_resource, :with_name).each do |_stack, stack_resource, stack_name|
         
     | 
| 
      
 63 
     | 
    
         
            +
                      remap_nested_parameters(compile, parameters, stack_name, stack_resource, output_map)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    end
         
     | 
| 
      
 65 
     | 
    
         
            +
                    extract_templates(&block)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    if(args.include?(:bubble_outputs))
         
     | 
| 
      
 67 
     | 
    
         
            +
                      output_map.each do |o_name, o_val|
         
     | 
| 
      
 68 
     | 
    
         
            +
                        compile.outputs._set(o_name).value compile._stack_output(*o_val)
         
     | 
| 
      
 69 
     | 
    
         
            +
                      end
         
     | 
| 
      
 70 
     | 
    
         
            +
                    end
         
     | 
| 
      
 71 
     | 
    
         
            +
                    compile.dump!
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                  # Extract output to make available for stack parameter usage at the
         
     | 
| 
      
 75 
     | 
    
         
            +
                  # current depth
         
     | 
| 
      
 76 
     | 
    
         
            +
                  #
         
     | 
| 
      
 77 
     | 
    
         
            +
                  # @param output_name [String] name of output
         
     | 
| 
      
 78 
     | 
    
         
            +
                  # @param outputs [Hash] listing of outputs
         
     | 
| 
      
 79 
     | 
    
         
            +
                  # @reutrn [Hash] reference to output value (used for setting parameter)
         
     | 
| 
      
 80 
     | 
    
         
            +
                  def make_output_available(output_name, outputs)
         
     | 
| 
      
 81 
     | 
    
         
            +
                    bubble_path = outputs[output_name].root_path - root_path
         
     | 
| 
      
 82 
     | 
    
         
            +
                    drip_path = root_path - outputs[output_name].root_path
         
     | 
| 
      
 83 
     | 
    
         
            +
                    bubble_path.each_slice(2) do |base_sparkle, ref_sparkle|
         
     | 
| 
      
 84 
     | 
    
         
            +
                      next unless ref_sparkle
         
     | 
| 
      
 85 
     | 
    
         
            +
                      base_sparkle.compile.outputs._set(output_name)._set(
         
     | 
| 
      
 86 
     | 
    
         
            +
                        :value, base_sparkle.compile._stack_output(
         
     | 
| 
      
 87 
     | 
    
         
            +
                          ref_sparkle.name, output_name
         
     | 
| 
      
 88 
     | 
    
         
            +
                        )
         
     | 
| 
      
 89 
     | 
    
         
            +
                      )
         
     | 
| 
      
 90 
     | 
    
         
            +
                    end
         
     | 
| 
      
 91 
     | 
    
         
            +
                    if(bubble_path.empty?)
         
     | 
| 
      
 92 
     | 
    
         
            +
                      if(drip_path.size == 1)
         
     | 
| 
      
 93 
     | 
    
         
            +
                        parent = drip_path.first.parent
         
     | 
| 
      
 94 
     | 
    
         
            +
                        if(parent && !parent.compile.parameters._set(output_name).nil?)
         
     | 
| 
      
 95 
     | 
    
         
            +
                          return compile.parameter!(output_name)
         
     | 
| 
      
 96 
     | 
    
         
            +
                        end
         
     | 
| 
      
 97 
     | 
    
         
            +
                      end
         
     | 
| 
      
 98 
     | 
    
         
            +
                      raise ArgumentError.new "Failed to detect available bubbling path for output `#{output_name}`. " <<
         
     | 
| 
      
 99 
     | 
    
         
            +
                        'This may be due to a circular dependency! ' <<
         
     | 
| 
      
 100 
     | 
    
         
            +
                        "(Output Path: #{outputs[output_name].root_path.map(&:name).join(' > ')} " <<
         
     | 
| 
      
 101 
     | 
    
         
            +
                        "Requester Path: #{root_path.map(&:name).join(' > ')})"
         
     | 
| 
      
 102 
     | 
    
         
            +
                    end
         
     | 
| 
      
 103 
     | 
    
         
            +
                    result = compile._stack_output(bubble_path.first.name, output_name)
         
     | 
| 
      
 104 
     | 
    
         
            +
                    if(drip_path.size > 1)
         
     | 
| 
      
 105 
     | 
    
         
            +
                      parent = drip_path.first.parent
         
     | 
| 
      
 106 
     | 
    
         
            +
                      drip_path.unshift(parent) if parent
         
     | 
| 
      
 107 
     | 
    
         
            +
                      drip_path.each_slice(2) do |base_sparkle, ref_sparkle|
         
     | 
| 
      
 108 
     | 
    
         
            +
                        next unless ref_sparkle
         
     | 
| 
      
 109 
     | 
    
         
            +
                        base_sparkle.compile.resources[ref_sparkle.name].properties.parameters.value._set(output_name, result)
         
     | 
| 
      
 110 
     | 
    
         
            +
                        ref_sparkle.compile.parameters._set(output_name).type 'string' # TODO: <<<<------ type check and prop
         
     | 
| 
      
 111 
     | 
    
         
            +
                        result = compile._parameter(output_name)
         
     | 
| 
      
 112 
     | 
    
         
            +
                      end
         
     | 
| 
      
 113 
     | 
    
         
            +
                    end
         
     | 
| 
      
 114 
     | 
    
         
            +
                    result
         
     | 
| 
      
 115 
     | 
    
         
            +
                  end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                  # Extract parameters from nested stacks. Check for previous nested
         
     | 
| 
      
 118 
     | 
    
         
            +
                  # stack outputs that match parameter. If match, set parameter to use
         
     | 
| 
      
 119 
     | 
    
         
            +
                  # output. If no match, check container stack parameters for match.
         
     | 
| 
      
 120 
     | 
    
         
            +
                  # If match, set to use ref. If no match, add parameter to container
         
     | 
| 
      
 121 
     | 
    
         
            +
                  # stack parameters and set to use ref.
         
     | 
| 
      
 122 
     | 
    
         
            +
                  #
         
     | 
| 
      
 123 
     | 
    
         
            +
                  # @param template [Hash] template being processed
         
     | 
| 
      
 124 
     | 
    
         
            +
                  # @param parameters [Hash] top level parameter set being built
         
     | 
| 
      
 125 
     | 
    
         
            +
                  # @param stack_name [String] name of stack resource
         
     | 
| 
      
 126 
     | 
    
         
            +
                  # @param stack_resource [Hash] duplicate of stack resource contents
         
     | 
| 
      
 127 
     | 
    
         
            +
                  # @param output_map [Hash] mapping of output names to required stack output access
         
     | 
| 
      
 128 
     | 
    
         
            +
                  # @return [TrueClass]
         
     | 
| 
      
 129 
     | 
    
         
            +
                  # @note if parameter has includes `StackUnique` a new parameter will
         
     | 
| 
      
 130 
     | 
    
         
            +
                  #   be added to container stack and it will not use outputs
         
     | 
| 
      
 131 
     | 
    
         
            +
                  def remap_nested_parameters(template, parameters, stack_name, stack_resource, output_map)
         
     | 
| 
      
 132 
     | 
    
         
            +
                    nested_template = stack_resource.properties.stack.compile
         
     | 
| 
      
 133 
     | 
    
         
            +
                    stack_parameters = nested_template.parameters
         
     | 
| 
      
 134 
     | 
    
         
            +
                    unless(stack_parameters.nil?)
         
     | 
| 
      
 135 
     | 
    
         
            +
                      stack_parameters._keys.each do |pname|
         
     | 
| 
      
 136 
     | 
    
         
            +
                        pval = stack_parameters[pname]
         
     | 
| 
      
 137 
     | 
    
         
            +
                        unless(pval.stack_unique.nil?)
         
     | 
| 
      
 138 
     | 
    
         
            +
                          check_name = [stack_name, pname].join
         
     | 
| 
      
 139 
     | 
    
         
            +
                        else
         
     | 
| 
      
 140 
     | 
    
         
            +
                          check_name = pname
         
     | 
| 
      
 141 
     | 
    
         
            +
                        end
         
     | 
| 
      
 142 
     | 
    
         
            +
                        if(!parameters._set(check_name).nil?)
         
     | 
| 
      
 143 
     | 
    
         
            +
                          template.resources._set(stack_name).properties.parameters._set(pname).value(
         
     | 
| 
      
 144 
     | 
    
         
            +
                            template._parameter(check_name)
         
     | 
| 
      
 145 
     | 
    
         
            +
                          )
         
     | 
| 
      
 146 
     | 
    
         
            +
                        elsif(output_map[check_name])
         
     | 
| 
      
 147 
     | 
    
         
            +
                          template.resources._set(stack_name).properties.parameters._set(pname).value(
         
     | 
| 
      
 148 
     | 
    
         
            +
                            template._stack_output(*output_map[check_name])
         
     | 
| 
      
 149 
     | 
    
         
            +
                          )
         
     | 
| 
      
 150 
     | 
    
         
            +
                        else
         
     | 
| 
      
 151 
     | 
    
         
            +
                          parameters._set(check_name, pval)
         
     | 
| 
      
 152 
     | 
    
         
            +
                          template.resources._set(stack_name).properties.parameters._set(pname).value(
         
     | 
| 
      
 153 
     | 
    
         
            +
                            template._parameter(check_name)
         
     | 
| 
      
 154 
     | 
    
         
            +
                          )
         
     | 
| 
      
 155 
     | 
    
         
            +
                        end
         
     | 
| 
      
 156 
     | 
    
         
            +
                      end
         
     | 
| 
      
 157 
     | 
    
         
            +
                    end
         
     | 
| 
      
 158 
     | 
    
         
            +
                    unless(nested_template.outputs.nil?)
         
     | 
| 
      
 159 
     | 
    
         
            +
                      nested_template.outputs.keys!.each do |oname|
         
     | 
| 
      
 160 
     | 
    
         
            +
                        output_map[oname] = [stack_name, oname]
         
     | 
| 
      
 161 
     | 
    
         
            +
                      end
         
     | 
| 
      
 162 
     | 
    
         
            +
                    end
         
     | 
| 
      
 163 
     | 
    
         
            +
                    true
         
     | 
| 
      
 164 
     | 
    
         
            +
                  end
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                end
         
     | 
| 
      
 167 
     | 
    
         
            +
              end
         
     | 
| 
      
 168 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,163 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'sparkle_formation'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class SparkleFormation
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Provider
         
     | 
| 
      
 5 
     | 
    
         
            +
                # Heat specific implementation
         
     | 
| 
      
 6 
     | 
    
         
            +
                module Heat
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  # @return [String] Type string for OpenStack HEAT stack resource
         
     | 
| 
      
 9 
     | 
    
         
            +
                  def stack_resource_type
         
     | 
| 
      
 10 
     | 
    
         
            +
                    'OS::Heat::Stack'
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  # Generate policy for stack
         
     | 
| 
      
 14 
     | 
    
         
            +
                  #
         
     | 
| 
      
 15 
     | 
    
         
            +
                  # @return [Hash]
         
     | 
| 
      
 16 
     | 
    
         
            +
                  def generate_policy
         
     | 
| 
      
 17 
     | 
    
         
            +
                    {}
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  # Apply deeply nested stacks. This is the new nesting approach and
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # does not bubble parameters up to the root stack. Parameters are
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # isolated to the stack resource itself and output mapping is
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # automatically applied.
         
     | 
| 
      
 24 
     | 
    
         
            +
                  #
         
     | 
| 
      
 25 
     | 
    
         
            +
                  # @yieldparam stack [SparkleFormation] stack instance
         
     | 
| 
      
 26 
     | 
    
         
            +
                  # @yieldparam resource [AttributeStruct] the stack resource
         
     | 
| 
      
 27 
     | 
    
         
            +
                  # @yieldparam s_name [String] stack resource name
         
     | 
| 
      
 28 
     | 
    
         
            +
                  # @yieldreturn [Hash] key/values to be merged into resource properties
         
     | 
| 
      
 29 
     | 
    
         
            +
                  # @return [Hash] dumped stack
         
     | 
| 
      
 30 
     | 
    
         
            +
                  def apply_deep_nesting(*args, &block)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    outputs = collect_outputs
         
     | 
| 
      
 32 
     | 
    
         
            +
                    nested_stacks(:with_resource).each do |stack, resource|
         
     | 
| 
      
 33 
     | 
    
         
            +
                      unless(stack.nested_stacks.empty?)
         
     | 
| 
      
 34 
     | 
    
         
            +
                        stack.apply_deep_nesting(*args)
         
     | 
| 
      
 35 
     | 
    
         
            +
                      end
         
     | 
| 
      
 36 
     | 
    
         
            +
                      stack.compile.parameters.keys!.each do |parameter_name|
         
     | 
| 
      
 37 
     | 
    
         
            +
                        if(output_name = output_matched?(parameter_name, outputs.keys))
         
     | 
| 
      
 38 
     | 
    
         
            +
                          next if outputs[output_name] == stack
         
     | 
| 
      
 39 
     | 
    
         
            +
                          stack_output = stack.make_output_available(output_name, outputs)
         
     | 
| 
      
 40 
     | 
    
         
            +
                          resource.properties.parameters._set(parameter_name, stack_output)
         
     | 
| 
      
 41 
     | 
    
         
            +
                        end
         
     | 
| 
      
 42 
     | 
    
         
            +
                      end
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
                    if(block_given?)
         
     | 
| 
      
 45 
     | 
    
         
            +
                      extract_templates(&block)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    end
         
     | 
| 
      
 47 
     | 
    
         
            +
                    compile.dump!
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  # Apply shallow nesting. This style of nesting will bubble
         
     | 
| 
      
 51 
     | 
    
         
            +
                  # parameters up to the root stack. This type of nesting is the
         
     | 
| 
      
 52 
     | 
    
         
            +
                  # original and now deprecated, but remains for compat issues so any
         
     | 
| 
      
 53 
     | 
    
         
            +
                  # existing usage won't be automatically busted.
         
     | 
| 
      
 54 
     | 
    
         
            +
                  #
         
     | 
| 
      
 55 
     | 
    
         
            +
                  # @yieldparam resource_name [String] name of stack resource
         
     | 
| 
      
 56 
     | 
    
         
            +
                  # @yieldparam stack [SparkleFormation] nested stack
         
     | 
| 
      
 57 
     | 
    
         
            +
                  # @yieldreturn [String] Remote URL storage for template
         
     | 
| 
      
 58 
     | 
    
         
            +
                  # @return [Hash]
         
     | 
| 
      
 59 
     | 
    
         
            +
                  def apply_shallow_nesting(*args, &block)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    parameters = compile.parameters
         
     | 
| 
      
 61 
     | 
    
         
            +
                    output_map = {}
         
     | 
| 
      
 62 
     | 
    
         
            +
                    nested_stacks(:with_resource, :with_name).each do |_stack, stack_resource, stack_name|
         
     | 
| 
      
 63 
     | 
    
         
            +
                      remap_nested_parameters(compile, parameters, stack_name, stack_resource, output_map)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    end
         
     | 
| 
      
 65 
     | 
    
         
            +
                    extract_templates(&block)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    if(args.include?(:bubble_outputs))
         
     | 
| 
      
 67 
     | 
    
         
            +
                      output_map.each do |o_name, o_val|
         
     | 
| 
      
 68 
     | 
    
         
            +
                        compile.outputs._set(o_name).value compile._stack_output(*o_val)
         
     | 
| 
      
 69 
     | 
    
         
            +
                      end
         
     | 
| 
      
 70 
     | 
    
         
            +
                    end
         
     | 
| 
      
 71 
     | 
    
         
            +
                    compile.dump!
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                  # Extract output to make available for stack parameter usage at the
         
     | 
| 
      
 75 
     | 
    
         
            +
                  # current depth
         
     | 
| 
      
 76 
     | 
    
         
            +
                  #
         
     | 
| 
      
 77 
     | 
    
         
            +
                  # @param output_name [String] name of output
         
     | 
| 
      
 78 
     | 
    
         
            +
                  # @param outputs [Hash] listing of outputs
         
     | 
| 
      
 79 
     | 
    
         
            +
                  # @reutrn [Hash] reference to output value (used for setting parameter)
         
     | 
| 
      
 80 
     | 
    
         
            +
                  def make_output_available(output_name, outputs)
         
     | 
| 
      
 81 
     | 
    
         
            +
                    bubble_path = outputs[output_name].root_path - root_path
         
     | 
| 
      
 82 
     | 
    
         
            +
                    drip_path = root_path - outputs[output_name].root_path
         
     | 
| 
      
 83 
     | 
    
         
            +
                    bubble_path.each_slice(2) do |base_sparkle, ref_sparkle|
         
     | 
| 
      
 84 
     | 
    
         
            +
                      next unless ref_sparkle
         
     | 
| 
      
 85 
     | 
    
         
            +
                      base_sparkle.compile.outputs._set(output_name)._set(
         
     | 
| 
      
 86 
     | 
    
         
            +
                        :value, base_sparkle.compile._stack_output(
         
     | 
| 
      
 87 
     | 
    
         
            +
                          ref_sparkle.name, output_name
         
     | 
| 
      
 88 
     | 
    
         
            +
                        )
         
     | 
| 
      
 89 
     | 
    
         
            +
                      )
         
     | 
| 
      
 90 
     | 
    
         
            +
                    end
         
     | 
| 
      
 91 
     | 
    
         
            +
                    if(bubble_path.empty?)
         
     | 
| 
      
 92 
     | 
    
         
            +
                      if(drip_path.size == 1)
         
     | 
| 
      
 93 
     | 
    
         
            +
                        parent = drip_path.first.parent
         
     | 
| 
      
 94 
     | 
    
         
            +
                        if(parent && !parent.compile.parameters._set(output_name).nil?)
         
     | 
| 
      
 95 
     | 
    
         
            +
                          return compile.parameter!(output_name)
         
     | 
| 
      
 96 
     | 
    
         
            +
                        end
         
     | 
| 
      
 97 
     | 
    
         
            +
                      end
         
     | 
| 
      
 98 
     | 
    
         
            +
                      raise ArgumentError.new "Failed to detect available bubbling path for output `#{output_name}`. " <<
         
     | 
| 
      
 99 
     | 
    
         
            +
                        'This may be due to a circular dependency! ' <<
         
     | 
| 
      
 100 
     | 
    
         
            +
                        "(Output Path: #{outputs[output_name].root_path.map(&:name).join(' > ')} " <<
         
     | 
| 
      
 101 
     | 
    
         
            +
                        "Requester Path: #{root_path.map(&:name).join(' > ')})"
         
     | 
| 
      
 102 
     | 
    
         
            +
                    end
         
     | 
| 
      
 103 
     | 
    
         
            +
                    result = compile._stack_output(bubble_path.first.name, output_name)
         
     | 
| 
      
 104 
     | 
    
         
            +
                    if(drip_path.size > 1)
         
     | 
| 
      
 105 
     | 
    
         
            +
                      parent = drip_path.first.parent
         
     | 
| 
      
 106 
     | 
    
         
            +
                      drip_path.unshift(parent) if parent
         
     | 
| 
      
 107 
     | 
    
         
            +
                      drip_path.each_slice(2) do |base_sparkle, ref_sparkle|
         
     | 
| 
      
 108 
     | 
    
         
            +
                        next unless ref_sparkle
         
     | 
| 
      
 109 
     | 
    
         
            +
                        base_sparkle.compile.resources[ref_sparkle.name].properties.parameters._set(output_name, result)
         
     | 
| 
      
 110 
     | 
    
         
            +
                        ref_sparkle.compile.parameters._set(output_name).type 'string' # TODO: <<<<------ type check and prop
         
     | 
| 
      
 111 
     | 
    
         
            +
                        result = compile._parameter(output_name)
         
     | 
| 
      
 112 
     | 
    
         
            +
                      end
         
     | 
| 
      
 113 
     | 
    
         
            +
                    end
         
     | 
| 
      
 114 
     | 
    
         
            +
                    result
         
     | 
| 
      
 115 
     | 
    
         
            +
                  end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                  # Extract parameters from nested stacks. Check for previous nested
         
     | 
| 
      
 118 
     | 
    
         
            +
                  # stack outputs that match parameter. If match, set parameter to use
         
     | 
| 
      
 119 
     | 
    
         
            +
                  # output. If no match, check container stack parameters for match.
         
     | 
| 
      
 120 
     | 
    
         
            +
                  # If match, set to use ref. If no match, add parameter to container
         
     | 
| 
      
 121 
     | 
    
         
            +
                  # stack parameters and set to use ref.
         
     | 
| 
      
 122 
     | 
    
         
            +
                  #
         
     | 
| 
      
 123 
     | 
    
         
            +
                  # @param template [Hash] template being processed
         
     | 
| 
      
 124 
     | 
    
         
            +
                  # @param parameters [Hash] top level parameter set being built
         
     | 
| 
      
 125 
     | 
    
         
            +
                  # @param stack_name [String] name of stack resource
         
     | 
| 
      
 126 
     | 
    
         
            +
                  # @param stack_resource [Hash] duplicate of stack resource contents
         
     | 
| 
      
 127 
     | 
    
         
            +
                  # @param output_map [Hash] mapping of output names to required stack output access
         
     | 
| 
      
 128 
     | 
    
         
            +
                  # @return [TrueClass]
         
     | 
| 
      
 129 
     | 
    
         
            +
                  # @note if parameter has includes `StackUnique` a new parameter will
         
     | 
| 
      
 130 
     | 
    
         
            +
                  #   be added to container stack and it will not use outputs
         
     | 
| 
      
 131 
     | 
    
         
            +
                  def remap_nested_parameters(template, parameters, stack_name, stack_resource, output_map)
         
     | 
| 
      
 132 
     | 
    
         
            +
                    nested_template = stack_resource.properties.stack.compile
         
     | 
| 
      
 133 
     | 
    
         
            +
                    stack_parameters = nested_template.parameters
         
     | 
| 
      
 134 
     | 
    
         
            +
                    unless(stack_parameters.nil?)
         
     | 
| 
      
 135 
     | 
    
         
            +
                      stack_parameters._keys.each do |pname|
         
     | 
| 
      
 136 
     | 
    
         
            +
                        pval = stack_parameters[pname]
         
     | 
| 
      
 137 
     | 
    
         
            +
                        unless(pval.stack_unique.nil?)
         
     | 
| 
      
 138 
     | 
    
         
            +
                          check_name = [stack_name, pname].join
         
     | 
| 
      
 139 
     | 
    
         
            +
                        else
         
     | 
| 
      
 140 
     | 
    
         
            +
                          check_name = pname
         
     | 
| 
      
 141 
     | 
    
         
            +
                        end
         
     | 
| 
      
 142 
     | 
    
         
            +
                        if(!parameters._set(check_name).nil?)
         
     | 
| 
      
 143 
     | 
    
         
            +
                          template.resources._set(stack_name).properties.parameters._set(pname, template._parameter(check_name))
         
     | 
| 
      
 144 
     | 
    
         
            +
                        elsif(output_map[check_name])
         
     | 
| 
      
 145 
     | 
    
         
            +
                          template.resources._set(stack_name).properties.parameters._set(pname)
         
     | 
| 
      
 146 
     | 
    
         
            +
                          template._stack_output(*output_map[check_name])
         
     | 
| 
      
 147 
     | 
    
         
            +
                        else
         
     | 
| 
      
 148 
     | 
    
         
            +
                          parameters._set(check_name, pval)
         
     | 
| 
      
 149 
     | 
    
         
            +
                          template.resources._set(stack_name).properties.parameters._set(pname, template._parameter(check_name))
         
     | 
| 
      
 150 
     | 
    
         
            +
                        end
         
     | 
| 
      
 151 
     | 
    
         
            +
                      end
         
     | 
| 
      
 152 
     | 
    
         
            +
                    end
         
     | 
| 
      
 153 
     | 
    
         
            +
                    unless(nested_template.outputs.nil?)
         
     | 
| 
      
 154 
     | 
    
         
            +
                      nested_template.outputs.keys!.each do |oname|
         
     | 
| 
      
 155 
     | 
    
         
            +
                        output_map[oname] = [stack_name, oname]
         
     | 
| 
      
 156 
     | 
    
         
            +
                      end
         
     | 
| 
      
 157 
     | 
    
         
            +
                    end
         
     | 
| 
      
 158 
     | 
    
         
            +
                    true
         
     | 
| 
      
 159 
     | 
    
         
            +
                  end
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                end
         
     | 
| 
      
 162 
     | 
    
         
            +
              end
         
     | 
| 
      
 163 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -5,12 +5,25 @@ class SparkleFormation 
     | 
|
| 
       5 
5 
     | 
    
         
             
              class Resources
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
                autoload :Aws, 'sparkle_formation/resources/aws'
         
     | 
| 
      
 8 
     | 
    
         
            +
                autoload :Azure, 'sparkle_formation/resources/azure'
         
     | 
| 
      
 9 
     | 
    
         
            +
                autoload :Heat, 'sparkle_formation/resources/heat'
         
     | 
| 
      
 10 
     | 
    
         
            +
                autoload :Rackspace, 'sparkle_formation/resources/rackspace'
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                # Characters to be removed from supplied key on matching
         
     | 
| 
      
 13 
     | 
    
         
            +
                RESOURCE_TYPE_TR = '_'
         
     | 
| 
      
 14 
     | 
    
         
            +
                # String to split for resource namespacing
         
     | 
| 
      
 15 
     | 
    
         
            +
                RESOURCE_TYPE_NAMESPACE_SPLITTER = '::'
         
     | 
| 
       8 
16 
     | 
    
         | 
| 
       9 
17 
     | 
    
         
             
                class << self
         
     | 
| 
       10 
18 
     | 
    
         | 
| 
       11 
19 
     | 
    
         
             
                  include SparkleFormation::Utils::AnimalStrings
         
     | 
| 
       12 
20 
     | 
    
         
             
                  # @!parse include SparkleFormation::Utils::AnimalStrings
         
     | 
| 
       13 
21 
     | 
    
         | 
| 
      
 22 
     | 
    
         
            +
                  # @return [String] base registry key
         
     | 
| 
      
 23 
     | 
    
         
            +
                  def base_key
         
     | 
| 
      
 24 
     | 
    
         
            +
                    Bogo::Utility.snake(self.name.split('::').last) # rubocop:disable Style/RedundantSelf
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
       14 
27 
     | 
    
         
             
                  # Register resource
         
     | 
| 
       15 
28 
     | 
    
         
             
                  #
         
     | 
| 
       16 
29 
     | 
    
         
             
                  # @param type [String] Orchestration resource type
         
     | 
| 
         @@ -20,7 +33,8 @@ class SparkleFormation 
     | 
|
| 
       20 
33 
     | 
    
         
             
                    unless(class_variable_defined?(:@@registry))
         
     | 
| 
       21 
34 
     | 
    
         
             
                      @@registry = AttributeStruct.hashish.new
         
     | 
| 
       22 
35 
     | 
    
         
             
                    end
         
     | 
| 
       23 
     | 
    
         
            -
                    @@registry[ 
     | 
| 
      
 36 
     | 
    
         
            +
                    @@registry[base_key] ||= AttributeStruct.hashish.new
         
     | 
| 
      
 37 
     | 
    
         
            +
                    @@registry[base_key][type] = hash
         
     | 
| 
       24 
38 
     | 
    
         
             
                    true
         
     | 
| 
       25 
39 
     | 
    
         
             
                  end
         
     | 
| 
       26 
40 
     | 
    
         | 
| 
         @@ -67,11 +81,13 @@ class SparkleFormation 
     | 
|
| 
       67 
81 
     | 
    
         
             
                  # @return [String, NilClass]
         
     | 
| 
       68 
82 
     | 
    
         
             
                  def registry_key(key)
         
     | 
| 
       69 
83 
     | 
    
         
             
                    o_key = key
         
     | 
| 
       70 
     | 
    
         
            -
                    key = key.to_s.tr( 
     | 
| 
      
 84 
     | 
    
         
            +
                    key = key.to_s.tr(self.const_get(:RESOURCE_TYPE_TR), '') # rubocop:disable Style/RedundantSelf
         
     | 
| 
       71 
85 
     | 
    
         
             
                    snake_parts = nil
         
     | 
| 
       72 
     | 
    
         
            -
                    result = @@registry.keys.detect do |ref|
         
     | 
| 
      
 86 
     | 
    
         
            +
                    result = @@registry[base_key].keys.detect do |ref|
         
     | 
| 
       73 
87 
     | 
    
         
             
                      ref = ref.downcase
         
     | 
| 
       74 
     | 
    
         
            -
                      snake_parts = ref.split( 
     | 
| 
      
 88 
     | 
    
         
            +
                      snake_parts = ref.split(
         
     | 
| 
      
 89 
     | 
    
         
            +
                        self.const_get(:RESOURCE_TYPE_NAMESPACE_SPLITTER) # rubocop:disable Style/RedundantSelf
         
     | 
| 
      
 90 
     | 
    
         
            +
                      )
         
     | 
| 
       75 
91 
     | 
    
         
             
                      until(snake_parts.empty?)
         
     | 
| 
       76 
92 
     | 
    
         
             
                        break if snake_parts.join('') == key
         
     | 
| 
       77 
93 
     | 
    
         
             
                        snake_parts.shift
         
     | 
| 
         @@ -79,8 +95,10 @@ class SparkleFormation 
     | 
|
| 
       79 
95 
     | 
    
         
             
                      !snake_parts.empty?
         
     | 
| 
       80 
96 
     | 
    
         
             
                    end
         
     | 
| 
       81 
97 
     | 
    
         
             
                    if(result)
         
     | 
| 
       82 
     | 
    
         
            -
                      collisions = @@registry.keys.find_all do |ref|
         
     | 
| 
       83 
     | 
    
         
            -
                        split_ref = ref.downcase.split( 
     | 
| 
      
 98 
     | 
    
         
            +
                      collisions = @@registry[base_key].keys.find_all do |ref|
         
     | 
| 
      
 99 
     | 
    
         
            +
                        split_ref = ref.downcase.split(
         
     | 
| 
      
 100 
     | 
    
         
            +
                          self.const_get(:RESOURCE_TYPE_NAMESPACE_SPLITTER) # rubocop:disable Style/RedundantSelf
         
     | 
| 
      
 101 
     | 
    
         
            +
                        )
         
     | 
| 
       84 
102 
     | 
    
         
             
                        ref = split_ref.slice(split_ref.size - snake_parts.size, split_ref.size).join('')
         
     | 
| 
       85 
103 
     | 
    
         
             
                        key == ref
         
     | 
| 
       86 
104 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -97,16 +115,15 @@ class SparkleFormation 
     | 
|
| 
       97 
115 
     | 
    
         
             
                  # @param key [String, Symbol]
         
     | 
| 
       98 
116 
     | 
    
         
             
                  # @return [Hashish, NilClass]
         
     | 
| 
       99 
117 
     | 
    
         
             
                  def lookup(key)
         
     | 
| 
       100 
     | 
    
         
            -
                    @@registry[registry_key(key)]
         
     | 
| 
      
 118 
     | 
    
         
            +
                    @@registry[base_key][registry_key(key)]
         
     | 
| 
       101 
119 
     | 
    
         
             
                  end
         
     | 
| 
       102 
120 
     | 
    
         | 
| 
       103 
121 
     | 
    
         
             
                  # @return [Hashish] currently loaded AWS registry
         
     | 
| 
       104 
122 
     | 
    
         
             
                  def registry
         
     | 
| 
       105 
     | 
    
         
            -
                     
     | 
| 
       106 
     | 
    
         
            -
                      @@registry
         
     | 
| 
       107 
     | 
    
         
            -
                    else
         
     | 
| 
      
 123 
     | 
    
         
            +
                    unless(class_variable_defined?(:@@registry))
         
     | 
| 
       108 
124 
     | 
    
         
             
                      @@registry = AttributeStruct.hashish.new
         
     | 
| 
       109 
125 
     | 
    
         
             
                    end
         
     | 
| 
      
 126 
     | 
    
         
            +
                    @@registry[base_key]
         
     | 
| 
       110 
127 
     | 
    
         
             
                  end
         
     | 
| 
       111 
128 
     | 
    
         | 
| 
       112 
129 
     | 
    
         
             
                end
         
     | 
| 
         @@ -0,0 +1,42 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'sparkle_formation'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class SparkleFormation
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              # Resources helper
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Resources
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                # Azure specific resources collection
         
     | 
| 
      
 9 
     | 
    
         
            +
                class Azure < Resources
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  # String to split for resource namespacing
         
     | 
| 
      
 12 
     | 
    
         
            +
                  RESOURCE_TYPE_NAMESPACE_SPLITTER = '/'
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    include Bogo::Memoization
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    # Load the builtin AWS resources
         
     | 
| 
      
 19 
     | 
    
         
            +
                    #
         
     | 
| 
      
 20 
     | 
    
         
            +
                    # @return [TrueClass]
         
     | 
| 
      
 21 
     | 
    
         
            +
                    def load!
         
     | 
| 
      
 22 
     | 
    
         
            +
                      memoize(:azure_resources, :global) do
         
     | 
| 
      
 23 
     | 
    
         
            +
                        load(
         
     | 
| 
      
 24 
     | 
    
         
            +
                          File.join(
         
     | 
| 
      
 25 
     | 
    
         
            +
                            File.dirname(__FILE__),
         
     | 
| 
      
 26 
     | 
    
         
            +
                            'azure_resources.json'
         
     | 
| 
      
 27 
     | 
    
         
            +
                          )
         
     | 
| 
      
 28 
     | 
    
         
            +
                        )
         
     | 
| 
      
 29 
     | 
    
         
            +
                        true
         
     | 
| 
      
 30 
     | 
    
         
            +
                      end
         
     | 
| 
      
 31 
     | 
    
         
            +
                    end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                    # Auto load data when included
         
     | 
| 
      
 34 
     | 
    
         
            +
                    def included(_klass)
         
     | 
| 
      
 35 
     | 
    
         
            +
                      load!
         
     | 
| 
      
 36 
     | 
    
         
            +
                    end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     |