sfn 3.0.20 → 3.0.22
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 +6 -0
- data/README.md +1 -0
- data/lib/sfn/api_provider.rb +1 -0
- data/lib/sfn/api_provider/terraform.rb +71 -0
- data/lib/sfn/callback/stack_policy.rb +16 -7
- data/lib/sfn/command/conf.rb +9 -1
- data/lib/sfn/command/destroy.rb +8 -2
- data/lib/sfn/command/graph.rb +8 -9
- data/lib/sfn/command/update.rb +0 -1
- data/lib/sfn/command_module/stack.rb +27 -11
- data/lib/sfn/command_module/template.rb +27 -10
- data/lib/sfn/config/validate.rb +13 -4
- data/lib/sfn/planner/aws.rb +163 -39
- data/lib/sfn/provider.rb +1 -1
- data/lib/sfn/version.rb +1 -1
- data/sfn.gemspec +5 -2
- metadata +56 -7
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 279982d00c24881c257eff78a3d14ed604952146
         | 
| 4 | 
            +
              data.tar.gz: 9a093919f17154f3fc20920b933691f0438c0583
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 01741b34e7ef10214fa4f8902d2d35d1f175752d822f632e8f21e20ffdf5721e0a667fdf2f5ed1d5d56c87e87d3c8afb24319622bcbd62af70aa8e4c509b1a45
         | 
| 7 | 
            +
              data.tar.gz: 57220d7bc625e74aa0b7f9f5ecbbc4fc22e77f56d11a3fda68bd1d5583ef4b84bb0084322496f7188b16d061212c51eeaf839c731290bc12e85ec523733a61ec
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,3 +1,9 @@ | |
| 1 | 
            +
            # v3.0.22
         | 
| 2 | 
            +
            * [fix] Properly match compile time parameters (#235)
         | 
| 3 | 
            +
            * [fix] Remove AWS policy statements for undefined resources (#240)
         | 
| 4 | 
            +
            * [enhancement] Support conditions when possible within planner (#230)
         | 
| 5 | 
            +
            * [feature] Add alpha support for Terraform (#236)
         | 
| 6 | 
            +
             | 
| 1 7 | 
             
            # v3.0.20
         | 
| 2 8 | 
             
            * [fix] Only dump templates when dumpable (#220, #223)
         | 
| 3 9 | 
             
            * [enhancement] Support NoEcho template parameters (#226)
         | 
    
        data/README.md
    CHANGED
    
    
    
        data/lib/sfn/api_provider.rb
    CHANGED
    
    
| @@ -0,0 +1,71 @@ | |
| 1 | 
            +
            require 'sfn'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Sfn
         | 
| 4 | 
            +
              module ApiProvider
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                module Terraform
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  # Disable remote template storage
         | 
| 9 | 
            +
                  def store_template(*_)
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  # No formatting required on stack results
         | 
| 13 | 
            +
                  def format_nested_stack_results(*_)
         | 
| 14 | 
            +
                    {}
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  # Extract current parameters from parent template
         | 
| 18 | 
            +
                  #
         | 
| 19 | 
            +
                  # @param stack [SparkleFormation]
         | 
| 20 | 
            +
                  # @param stack_name [String]
         | 
| 21 | 
            +
                  # @param c_stack [Miasma::Models::Orchestration::Stack]
         | 
| 22 | 
            +
                  # @return [Hash]
         | 
| 23 | 
            +
                  def extract_current_nested_template_parameters(stack, stack_name, c_stack)
         | 
| 24 | 
            +
                    if(c_stack && c_stack.data[:parent_stack])
         | 
| 25 | 
            +
                      c_stack.data[:parent_stack].sparkleish_template(:remove_wrapper).fetch(
         | 
| 26 | 
            +
                        :resources, stack_name, :properties, :parameters, Smash.new
         | 
| 27 | 
            +
                      )
         | 
| 28 | 
            +
                    elsif(stack.parent)
         | 
| 29 | 
            +
                      val = stack.parent.compile.resources.set!(stack_name).properties
         | 
| 30 | 
            +
                      val.nil? ? Smash.new : val._dump
         | 
| 31 | 
            +
                    else
         | 
| 32 | 
            +
                      Smash.new
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  # Disable parameter validate as we can't adjust them without template modifications
         | 
| 37 | 
            +
                  def validate_stack_parameter(*_)
         | 
| 38 | 
            +
                    true
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  # Determine if parameter was set via intrinsic function
         | 
| 42 | 
            +
                  #
         | 
| 43 | 
            +
                  # @param val [Object]
         | 
| 44 | 
            +
                  # @return [TrueClass, FalseClass]
         | 
| 45 | 
            +
                  def function_set_parameter?(val)
         | 
| 46 | 
            +
                    if(val)
         | 
| 47 | 
            +
                      val.start_with?('${')
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  # Override requirement of nesting bucket
         | 
| 52 | 
            +
                  def validate_nesting_bucket!
         | 
| 53 | 
            +
                    true
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  # Override template content extraction to disable scrub behavior
         | 
| 57 | 
            +
                  #
         | 
| 58 | 
            +
                  # @param thing [SparkleFormation, Hash]
         | 
| 59 | 
            +
                  # @return [Hash]
         | 
| 60 | 
            +
                  def template_content(thing, *_)
         | 
| 61 | 
            +
                    if(thing.is_a?(SparkleFormation))
         | 
| 62 | 
            +
                      config[:sparkle_dump] ? thing.sparkle_dump : thing.dump
         | 
| 63 | 
            +
                    else
         | 
| 64 | 
            +
                      thing
         | 
| 65 | 
            +
                    end
         | 
| 66 | 
            +
                  end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
              end
         | 
| 71 | 
            +
            end
         | 
| @@ -74,19 +74,28 @@ module Sfn | |
| 74 74 | 
             
                  # @param p_stack [Miasma::Models::Orchestration::Stack]
         | 
| 75 75 | 
             
                  # @return [NilClass]
         | 
| 76 76 | 
             
                  def save_stack_policy(p_stack)
         | 
| 77 | 
            +
                    valid_logical_ids = p_stack.resources.reload.all.map(&:logical_id)
         | 
| 78 | 
            +
                    stack_policy = @policies.fetch(p_stack.id,
         | 
| 79 | 
            +
                      @policies.fetch(p_stack.data[:logical_id]),
         | 
| 80 | 
            +
                      @policies[p_stack.name]
         | 
| 81 | 
            +
                    ).to_smash
         | 
| 82 | 
            +
                    if(stack_policy)
         | 
| 83 | 
            +
                      stack_policy[:statement].delete_if do |policy_item|
         | 
| 84 | 
            +
                        policy_match = policy_item[:resource].to_s.match(
         | 
| 85 | 
            +
                          %r{LogicalResourceId/(?<logical_id>.+)$}
         | 
| 86 | 
            +
                        )
         | 
| 87 | 
            +
                        if(policy_match)
         | 
| 88 | 
            +
                          !valid_logical_ids.include?(policy_match["logical_id"])
         | 
| 89 | 
            +
                        end
         | 
| 90 | 
            +
                      end
         | 
| 91 | 
            +
                    end
         | 
| 77 92 | 
             
                    result = p_stack.api.request(
         | 
| 78 93 | 
             
                      :path => '/',
         | 
| 79 94 | 
             
                      :method => :post,
         | 
| 80 95 | 
             
                      :form => Smash.new(
         | 
| 81 96 | 
             
                        'Action' => 'SetStackPolicy',
         | 
| 82 97 | 
             
                        'StackName' => p_stack.id,
         | 
| 83 | 
            -
                        'StackPolicyBody' => MultiJson.dump(
         | 
| 84 | 
            -
                          @policies.fetch(p_stack.id,
         | 
| 85 | 
            -
                            @policies.fetch(p_stack.data[:logical_id],
         | 
| 86 | 
            -
                              @policies[p_stack.name]
         | 
| 87 | 
            -
                            )
         | 
| 88 | 
            -
                          )
         | 
| 89 | 
            -
                        )
         | 
| 98 | 
            +
                        'StackPolicyBody' => MultiJson.dump(stack_policy)
         | 
| 90 99 | 
             
                      )
         | 
| 91 100 | 
             
                    )
         | 
| 92 101 | 
             
                  end
         | 
    
        data/lib/sfn/command/conf.rb
    CHANGED
    
    | @@ -83,7 +83,7 @@ Configuration.new do | |
| 83 83 | 
             
              # nesting_prefix 'nested-templates'
         | 
| 84 84 | 
             
              #   Remote provider credentials
         | 
| 85 85 | 
             
              credentials do
         | 
| 86 | 
            -
                #  Remote provider name (:aws, :azure, :google, :open_stack, :rackspace)
         | 
| 86 | 
            +
                #  Remote provider name (:aws, :azure, :google, :open_stack, :rackspace, :terraform)
         | 
| 87 87 | 
             
                provider :aws
         | 
| 88 88 | 
             
                #  AWS credentials information
         | 
| 89 89 | 
             
                aws_access_key_id ENV['AWS_ACCESS_KEY_ID']
         | 
| @@ -123,6 +123,14 @@ Configuration.new do | |
| 123 123 | 
             
                google_service_account_email ENV['GOOGLE_SERVICE_ACCOUNT_EMAIL']
         | 
| 124 124 | 
             
                google_service_account_private_key ENV['GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY']
         | 
| 125 125 | 
             
                google_project ENV['GOOGLE_PROJECT']
         | 
| 126 | 
            +
                #  Terraform credentials information
         | 
| 127 | 
            +
                #  Valid driver names: :tfe, :boule, :local
         | 
| 128 | 
            +
                terraform_driver :local
         | 
| 129 | 
            +
                terraform_tfe_endpoint ENV['TFE_URL']
         | 
| 130 | 
            +
                terraform_tfe_token ENV['TFE_TOKEN']
         | 
| 131 | 
            +
                terraform_boule_endpoint ENV['BOULE_URL']
         | 
| 132 | 
            +
                terraform_local_directory './terraform-stacks'
         | 
| 133 | 
            +
                terraform_local_scrub_destroyed false
         | 
| 126 134 | 
             
              end
         | 
| 127 135 | 
             
            end
         | 
| 128 136 | 
             
            EOF
         | 
    
        data/lib/sfn/command/destroy.rb
    CHANGED
    
    | @@ -30,8 +30,14 @@ module Sfn | |
| 30 30 | 
             
                      stack = provider.connection.stacks.get(stack_name)
         | 
| 31 31 | 
             
                      if(stack)
         | 
| 32 32 | 
             
                        nested_stack_cleanup!(stack)
         | 
| 33 | 
            -
                         | 
| 34 | 
            -
                          stack | 
| 33 | 
            +
                        begin
         | 
| 34 | 
            +
                          api_action!(:api_stack => stack) do
         | 
| 35 | 
            +
                            stack.destroy
         | 
| 36 | 
            +
                          end
         | 
| 37 | 
            +
                        rescue Miasma::Error::ApiError::RequestError => error
         | 
| 38 | 
            +
                          raise unless error.response.code == 404
         | 
| 39 | 
            +
                          # if stack is already gone, disable polling
         | 
| 40 | 
            +
                          config[:poll] = false
         | 
| 35 41 | 
             
                        end
         | 
| 36 42 | 
             
                        ui.info "Destroy request complete for stack: #{ui.color(stack_name, :red)}"
         | 
| 37 43 | 
             
                      else
         | 
    
        data/lib/sfn/command/graph.rb
    CHANGED
    
    | @@ -21,9 +21,7 @@ module Sfn | |
| 21 21 | 
             
                    config[:print_only] = true
         | 
| 22 22 | 
             
                    validate_graph_style!
         | 
| 23 23 | 
             
                    file = load_template_file
         | 
| 24 | 
            -
                    file = parameter_scrub!(file.sparkle_dump)
         | 
| 25 24 | 
             
                    @outputs = Smash.new
         | 
| 26 | 
            -
                    file = file.to_smash
         | 
| 27 25 | 
             
                    ui.info "Template resource graph generation - Style: #{ui.color(config[:graph_style], :bold)}"
         | 
| 28 26 | 
             
                    if(config[:file])
         | 
| 29 27 | 
             
                      ui.puts "  -> path: #{config[:file]}"
         | 
| @@ -38,14 +36,14 @@ module Sfn | |
| 38 36 | 
             
                    end
         | 
| 39 37 | 
             
                    graph = nil
         | 
| 40 38 | 
             
                    run_action 'Generating resource graph' do
         | 
| 41 | 
            -
                      graph = generate_graph(file | 
| 39 | 
            +
                      graph = generate_graph(file)
         | 
| 42 40 | 
             
                      nil
         | 
| 43 41 | 
             
                    end
         | 
| 44 42 | 
             
                    run_action 'Writing graph result' do
         | 
| 45 43 | 
             
                      FileUtils.mkdir_p(File.dirname(config[:output_file]))
         | 
| 46 44 | 
             
                      if(config[:output_type] == 'dot')
         | 
| 47 | 
            -
                        File.open("#{config[:output_file]}.dot", 'w') do | | 
| 48 | 
            -
                           | 
| 45 | 
            +
                        File.open("#{config[:output_file]}.dot", 'w') do |o_file|
         | 
| 46 | 
            +
                          o_file.puts graph.to_s
         | 
| 49 47 | 
             
                        end
         | 
| 50 48 | 
             
                      else
         | 
| 51 49 | 
             
                        graph.save config[:output_file], config[:output_type]
         | 
| @@ -74,10 +72,11 @@ module Sfn | |
| 74 72 | 
             
                  end
         | 
| 75 73 |  | 
| 76 74 | 
             
                  def output_discovery(template, outputs, resource_name, parent_template, name='')
         | 
| 77 | 
            -
                     | 
| 78 | 
            -
                      template | 
| 79 | 
            -
                         | 
| 80 | 
            -
             | 
| 75 | 
            +
                    unless(template.resources.nil?)
         | 
| 76 | 
            +
                      template.resources.keys!.each do |r_name|
         | 
| 77 | 
            +
                        r_info = template.resources[r_name]
         | 
| 78 | 
            +
                        if(r_info.type == template._self.stack_resource_name)
         | 
| 79 | 
            +
                          output_discovery(r_info.properties.stack, outputs, r_name, template, r_name)
         | 
| 81 80 | 
             
                        end
         | 
| 82 81 | 
             
                      end
         | 
| 83 82 | 
             
                    end
         | 
    
        data/lib/sfn/command/update.rb
    CHANGED
    
    
| @@ -16,6 +16,8 @@ module Sfn | |
| 16 16 | 
             
                    TEMPLATE_PARAMETER_DEFAULTS = ['Default', 'defaultValue', 'default']
         | 
| 17 17 | 
             
                    # Template parameter no echo locations
         | 
| 18 18 | 
             
                    TEMPLATE_PARAMETER_NOECHO = ['NoEcho']
         | 
| 19 | 
            +
                    # Template parameter no echo custom
         | 
| 20 | 
            +
                    TEMPLATE_PARAMETER_SFN_NOECHO = ['Quiet', 'quiet']
         | 
| 19 21 |  | 
| 20 22 | 
             
                    # Apply any defined remote stacks
         | 
| 21 23 | 
             
                    #
         | 
| @@ -143,16 +145,19 @@ module Sfn | |
| 143 145 | 
             
                    # @param parameter_prefix [Array<String>] nesting prefix names
         | 
| 144 146 | 
             
                    # @param parameter_name [String] parameter name
         | 
| 145 147 | 
             
                    # @return [Array<String>] [expected_template_key, configuration_used_key]
         | 
| 146 | 
            -
                    def locate_config_parameter_key(parameter_prefix, parameter_name)
         | 
| 148 | 
            +
                    def locate_config_parameter_key(parameter_prefix, parameter_name, root_name)
         | 
| 147 149 | 
             
                      check_name = parameter_name.downcase.tr('-_', '')
         | 
| 148 150 | 
             
                      check_prefix = parameter_prefix.map{|i| i.downcase.tr('-_', '') }
         | 
| 149 151 | 
             
                      key_match = config[:parameters].keys.detect do |cp_key|
         | 
| 150 152 | 
             
                        cp_key = cp_key.to_s.downcase.split('__').map{|i| i.tr('-_', '') }.join('__')
         | 
| 151 | 
            -
                         | 
| 152 | 
            -
             | 
| 153 | 
            +
                        non_root_matcher = (check_prefix + [check_name]).join('__')
         | 
| 154 | 
            +
                        root_matcher = ([root_name] + check_prefix + [check_name]).join('__')
         | 
| 155 | 
            +
                        cp_key == non_root_matcher ||
         | 
| 156 | 
            +
                          cp_key == root_matcher
         | 
| 153 157 | 
             
                      end
         | 
| 154 158 | 
             
                      actual_key = (parameter_prefix + [parameter_name]).compact.join('__')
         | 
| 155 159 | 
             
                      if(key_match)
         | 
| 160 | 
            +
                        ui.debug "Remapping configuration runtime parameter `#{key_match}` -> `#{actual_key}`"
         | 
| 156 161 | 
             
                        config[:parameters][actual_key] = config[:parameters].delete(key_match)
         | 
| 157 162 | 
             
                      end
         | 
| 158 163 | 
             
                      actual_key
         | 
| @@ -186,12 +191,19 @@ module Sfn | |
| 186 191 | 
             
                          )
         | 
| 187 192 | 
             
                        )
         | 
| 188 193 | 
             
                        if(config[:interactive_parameters])
         | 
| 194 | 
            +
                          no_echo = !!TEMPLATE_PARAMETER_NOECHO.detect{|loc_key|
         | 
| 195 | 
            +
                            param_value[loc_key].to_s.downcase == 'true'
         | 
| 196 | 
            +
                          }
         | 
| 197 | 
            +
                          sfn_no_echo = TEMPLATE_PARAMETER_SFN_NOECHO.map do |loc_key|
         | 
| 198 | 
            +
                            res = param_value.delete(loc_key).to_s.downcase
         | 
| 199 | 
            +
                            res if !res.empty? && res != 'false'
         | 
| 200 | 
            +
                          end.compact.first
         | 
| 201 | 
            +
                          no_echo = sfn_no_echo if sfn_no_echo
         | 
| 189 202 | 
             
                          answer = ui.ask_question(
         | 
| 190 203 | 
             
                            "#{param_name.split(/([A-Z]+[^A-Z]*)/).find_all{|s|!s.empty?}.join(' ')}",
         | 
| 191 204 | 
             
                            :default => default,
         | 
| 192 | 
            -
                            : | 
| 193 | 
            -
             | 
| 194 | 
            -
                            }
         | 
| 205 | 
            +
                            :hide_default => sfn_no_echo == 'all',
         | 
| 206 | 
            +
                            :no_echo => !!no_echo
         | 
| 195 207 | 
             
                          )
         | 
| 196 208 | 
             
                        else
         | 
| 197 209 | 
             
                          answer = default
         | 
| @@ -221,21 +233,25 @@ module Sfn | |
| 221 233 | 
             
                    # @option opts [Miasma::Models::Orchestration::Stack] :stack existing stack
         | 
| 222 234 | 
             
                    # @return [Hash]
         | 
| 223 235 | 
             
                    def populate_parameters!(sparkle, opts={})
         | 
| 224 | 
            -
                      current_parameters = opts | 
| 236 | 
            +
                      current_parameters = opts[:current_parameters] || {}
         | 
| 225 237 | 
             
                      current_stack = opts[:stack]
         | 
| 226 238 | 
             
                      parameter_prefix, stack_parameters = prefix_parameters_setup(sparkle)
         | 
| 227 239 | 
             
                      unless(stack_parameters.empty?)
         | 
| 228 240 | 
             
                        format_config_parameters!
         | 
| 229 241 | 
             
                        param_banner = false
         | 
| 230 242 | 
             
                        stack_parameters.each do |param_name, param_value|
         | 
| 231 | 
            -
                          ns_key = locate_config_parameter_key(parameter_prefix, param_name)
         | 
| 243 | 
            +
                          ns_key = locate_config_parameter_key(parameter_prefix, param_name, sparkle.root.name)
         | 
| 232 244 | 
             
                          # When parameter is a hash type, it is being set via
         | 
| 233 245 | 
             
                          # intrinsic function and we don't modify
         | 
| 234 246 | 
             
                          if(function_set_parameter?(current_parameters[param_name]))
         | 
| 235 | 
            -
                            if( | 
| 236 | 
            -
                               | 
| 247 | 
            +
                            if(!config[:parameters][ns_key].nil?)
         | 
| 248 | 
            +
                              ui.warn "Overriding mapped parameter value with explicit assignment `#{ns_key}`!"
         | 
| 237 249 | 
             
                            else
         | 
| 238 | 
            -
                               | 
| 250 | 
            +
                              if(current_stack)
         | 
| 251 | 
            +
                                enable_set = validate_stack_parameter(current_stack, param_name, ns_key, current_parameters[param_name])
         | 
| 252 | 
            +
                              else
         | 
| 253 | 
            +
                                enable_set = true
         | 
| 254 | 
            +
                              end
         | 
| 239 255 | 
             
                            end
         | 
| 240 256 | 
             
                            if(enable_set)
         | 
| 241 257 | 
             
                              # NOTE: direct set dumps the stack (nfi). Smash will
         | 
| @@ -180,13 +180,30 @@ module Sfn | |
| 180 180 | 
             
                            else
         | 
| 181 181 | 
             
                              current_state = compile_state.fetch(f_name, Smash.new)
         | 
| 182 182 | 
             
                            end
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                            # NOTE: Prevent nesting stack compile state within stack compile state
         | 
| 185 | 
            +
                            current_state.delete("#{f_name}__#{f_name}")
         | 
| 186 | 
            +
             | 
| 183 187 | 
             
                            if(formation.compile_state)
         | 
| 184 188 | 
             
                              current_state = current_state.merge(formation.compile_state)
         | 
| 185 189 | 
             
                            end
         | 
| 186 190 | 
             
                            unless(formation.parameters.empty?)
         | 
| 187 191 | 
             
                              ui.info "#{ui.color('Compile time parameters:', :bold)} - template: #{ui.color(pathed_name, :green, :bold)}" unless config[:print_only]
         | 
| 188 192 | 
             
                              formation.parameters.each do |k,v|
         | 
| 189 | 
            -
                                 | 
| 193 | 
            +
                                valid_keys = [
         | 
| 194 | 
            +
                                  "#{f_name}__#{k}",
         | 
| 195 | 
            +
                                  Bogo::Utility.camel("#{f_name}__#{k}").downcase,
         | 
| 196 | 
            +
                                  k,
         | 
| 197 | 
            +
                                  Bogo::Utility.camel(k).downcase
         | 
| 198 | 
            +
                                ]
         | 
| 199 | 
            +
                                current_value = valid_keys.map do |key|
         | 
| 200 | 
            +
                                  current_state[key]
         | 
| 201 | 
            +
                                end.compact.first
         | 
| 202 | 
            +
                                primary_key, secondary_key = ["#{f_name}__#{k}", k]
         | 
| 203 | 
            +
                                current_state[k] = request_compile_parameter(k, v,
         | 
| 204 | 
            +
                                  current_value,
         | 
| 205 | 
            +
                                  !!formation.parent
         | 
| 206 | 
            +
                                )
         | 
| 190 207 | 
             
                              end
         | 
| 191 208 | 
             
                              formation.compile_state = current_state
         | 
| 192 209 | 
             
                            end
         | 
| @@ -231,19 +248,19 @@ module Sfn | |
| 231 248 | 
             
                    # core parameter set
         | 
| 232 249 | 
             
                    def merge_compile_time_parameters
         | 
| 233 250 | 
             
                      compile_state = config.fetch(:compile_parameters, Smash.new)
         | 
| 251 | 
            +
                      ui.debug "Initial compile parameters - #{compile_state}"
         | 
| 234 252 | 
             
                      compile_state.keys.each do |cs_key|
         | 
| 235 | 
            -
                         | 
| 236 | 
            -
                           | 
| 237 | 
            -
                           | 
| 238 | 
            -
             | 
| 253 | 
            +
                        unless(cs_key.to_s.start_with?("#{arguments.first}__"))
         | 
| 254 | 
            +
                          named_cs_key = "#{arguments.first}__#{cs_key}"
         | 
| 255 | 
            +
                          non_named = compile_state.delete(cs_key)
         | 
| 256 | 
            +
                          if(non_named && !compile_state.key?(named_cs_key))
         | 
| 257 | 
            +
                            ui.debug "Setting non-named compile parameter `#{cs_key}` into `#{named_cs_key}`"
         | 
| 258 | 
            +
                            compile_state[named_cs_key] = non_named
         | 
| 259 | 
            +
                          else
         | 
| 260 | 
            +
                            ui.debug "Discarding non-named compile parameter due to set named - `#{cs_key}` </> `#{named_cs_key}`"
         | 
| 239 261 | 
             
                          end
         | 
| 240 262 | 
             
                        end
         | 
| 241 263 | 
             
                      end
         | 
| 242 | 
            -
                      compile_state.keys.each do |cs_key|
         | 
| 243 | 
            -
                        unless(cs_key.start_with?("#{arguments.first}__"))
         | 
| 244 | 
            -
                          compile_state["#{arguments.first}__#{cs_key}"] = compile_state.delete(cs_key)
         | 
| 245 | 
            -
                        end
         | 
| 246 | 
            -
                      end
         | 
| 247 264 | 
             
                      ui.debug "Merged compile parameters - #{compile_state}"
         | 
| 248 265 | 
             
                      compile_state
         | 
| 249 266 | 
             
                    end
         | 
    
        data/lib/sfn/config/validate.rb
    CHANGED
    
    | @@ -82,13 +82,22 @@ module Sfn | |
| 82 82 | 
             
                        result = Smash.new
         | 
| 83 83 | 
             
                        v.split(',').each do |item_pair|
         | 
| 84 84 | 
             
                          key, value = item_pair.split(/[=:]/, 2)
         | 
| 85 | 
            -
                          key =  | 
| 86 | 
            -
                          key = [key.pop, key.join('__')].reverse
         | 
| 87 | 
            -
                          result.set(*key, value)
         | 
| 85 | 
            +
                          result[key] = value
         | 
| 88 86 | 
             
                        end
         | 
| 89 87 | 
             
                        result
         | 
| 90 88 | 
             
                      when Hash
         | 
| 91 | 
            -
                         | 
| 89 | 
            +
                        result = Smash.new
         | 
| 90 | 
            +
                        extractor = lambda do |data, prefix|
         | 
| 91 | 
            +
                          data.each_pair do |key, value|
         | 
| 92 | 
            +
                            local_key = "#{prefix}__#{key}"
         | 
| 93 | 
            +
                            if(value.is_a?(Hash))
         | 
| 94 | 
            +
                              extractor.call(value, local_key)
         | 
| 95 | 
            +
                            else
         | 
| 96 | 
            +
                              result[local_key] = data
         | 
| 97 | 
            +
                            end
         | 
| 98 | 
            +
                          end
         | 
| 99 | 
            +
                        end
         | 
| 100 | 
            +
                        result
         | 
| 92 101 | 
             
                      else
         | 
| 93 102 | 
             
                        v
         | 
| 94 103 | 
             
                      end
         | 
    
        data/lib/sfn/planner/aws.rb
    CHANGED
    
    | @@ -14,6 +14,8 @@ module Sfn | |
| 14 14 | 
             
                    REF_MAPPING = {}
         | 
| 15 15 | 
             
                    FN_MAPPING = {}
         | 
| 16 16 |  | 
| 17 | 
            +
                    UNKNOWN_RUNTIME_RESULT = '__UNKNOWN_RUNTIME_RESULT__'
         | 
| 18 | 
            +
             | 
| 17 19 | 
             
                    # @return [Array<String>] flagged items for value replacement
         | 
| 18 20 | 
             
                    attr_reader :flagged
         | 
| 19 21 |  | 
| @@ -23,6 +25,11 @@ module Sfn | |
| 23 25 | 
             
                      @flagged = []
         | 
| 24 26 | 
             
                    end
         | 
| 25 27 |  | 
| 28 | 
            +
                    # @return [Hash] defined conditions
         | 
| 29 | 
            +
                    def conditions
         | 
| 30 | 
            +
                      @original.fetch('Conditions', {})
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
             | 
| 26 33 | 
             
                    # Flag a reference as modified
         | 
| 27 34 | 
             
                    #
         | 
| 28 35 | 
             
                    # @param ref_name [String]
         | 
| @@ -48,30 +55,25 @@ module Sfn | |
| 48 55 | 
             
                    # @note also allows 'Ref' within funcs to provide mapping
         | 
| 49 56 | 
             
                    #   replacements using the REF_MAPPING constant
         | 
| 50 57 | 
             
                    def apply_function(hash, funcs=[])
         | 
| 51 | 
            -
                       | 
| 52 | 
            -
             | 
| 53 | 
            -
                         | 
| 54 | 
            -
             | 
| 55 | 
            -
                           | 
| 56 | 
            -
             | 
| 57 | 
            -
                           | 
| 58 | 
            -
             | 
| 59 | 
            -
                             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 58 | 
            +
                      if(hash.is_a?(Hash))
         | 
| 59 | 
            +
                        k,v = hash.first
         | 
| 60 | 
            +
                        if(hash.size == 1 && (k.start_with?('Fn') || k == 'Ref') && (funcs.include?(:all) || funcs.empty? || funcs.include?(k) || funcs == ['DEREF']))
         | 
| 61 | 
            +
                          method_name = Bogo::Utility.snake(k.gsub('::', ''))
         | 
| 62 | 
            +
                          if((funcs.include?(k) || funcs.include?(:all)) && respond_to?(method_name))
         | 
| 63 | 
            +
                            apply_function(send(method_name, v), funcs)
         | 
| 64 | 
            +
                          else
         | 
| 65 | 
            +
                            case k
         | 
| 66 | 
            +
                            when 'Fn::GetAtt'
         | 
| 67 | 
            +
                              funcs.include?('DEREF') ? dereference(hash) : hash
         | 
| 68 | 
            +
                            when 'Ref'
         | 
| 69 | 
            +
                              if(funcs.include?('DEREF'))
         | 
| 70 | 
            +
                                dereference(hash)
         | 
| 71 | 
            +
                              else
         | 
| 72 | 
            +
                                {'Ref' => self.class.const_get(:REF_MAPPING).fetch(v, v)}
         | 
| 73 | 
            +
                              end
         | 
| 62 74 | 
             
                            else
         | 
| 63 | 
            -
                               | 
| 75 | 
            +
                              hash
         | 
| 64 76 | 
             
                            end
         | 
| 65 | 
            -
                          else
         | 
| 66 | 
            -
                            raise "Failed to find mapping! (#{v[0]})"
         | 
| 67 | 
            -
                          end
         | 
| 68 | 
            -
                        when 'Fn::GetAtt'
         | 
| 69 | 
            -
                          func.include?('DEREF') ? dereference(hash) : hash
         | 
| 70 | 
            -
                        when 'Ref'
         | 
| 71 | 
            -
                          if(funcs.include?('DEREF'))
         | 
| 72 | 
            -
                            dereference(hash)
         | 
| 73 | 
            -
                          else
         | 
| 74 | 
            -
                            {'Ref' => self.class.const_get(:REF_MAPPING).fetch(v, v)}
         | 
| 75 77 | 
             
                          end
         | 
| 76 78 | 
             
                        else
         | 
| 77 79 | 
             
                          hash
         | 
| @@ -81,6 +83,113 @@ module Sfn | |
| 81 83 | 
             
                      end
         | 
| 82 84 | 
             
                    end
         | 
| 83 85 |  | 
| 86 | 
            +
                    # Evaluate given condition
         | 
| 87 | 
            +
                    #
         | 
| 88 | 
            +
                    # @param name [String] condition name
         | 
| 89 | 
            +
                    # @return [TrueClass, FalseClass]
         | 
| 90 | 
            +
                    def apply_condition(name)
         | 
| 91 | 
            +
                      condition = conditions[name]
         | 
| 92 | 
            +
                      if(condition)
         | 
| 93 | 
            +
                        apply_function(condition, [:all, 'DEREF'])
         | 
| 94 | 
            +
                      else
         | 
| 95 | 
            +
                        raise "Failed to locate condition with name `#{name}`!"
         | 
| 96 | 
            +
                      end
         | 
| 97 | 
            +
                    end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                    # Evaluate `if` conditional
         | 
| 100 | 
            +
                    #
         | 
| 101 | 
            +
                    # @param value [Array] {0: condition name, 1: true value, 2: false value}
         | 
| 102 | 
            +
                    # @return [Object] true or false value
         | 
| 103 | 
            +
                    def fn_if(value)
         | 
| 104 | 
            +
                      result = apply_condition(value[0])
         | 
| 105 | 
            +
                      if(result != UNKNOWN_RUNTIME_RESULT)
         | 
| 106 | 
            +
                        result ? value[1] : value[2]
         | 
| 107 | 
            +
                      else
         | 
| 108 | 
            +
                        UNKNOWN_RUNTIME_RESULT
         | 
| 109 | 
            +
                        result
         | 
| 110 | 
            +
                      end
         | 
| 111 | 
            +
                    end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                    # Determine if all conditions are true
         | 
| 114 | 
            +
                    #
         | 
| 115 | 
            +
                    # @param value [Array<String>] condition names
         | 
| 116 | 
            +
                    # @return [TrueClass, FalseClass]
         | 
| 117 | 
            +
                    def fn_and(value)
         | 
| 118 | 
            +
                      result = value.map do |val|
         | 
| 119 | 
            +
                        apply_condition(val)
         | 
| 120 | 
            +
                      end
         | 
| 121 | 
            +
                      if(result.to_s.include?(RUNTIME_MODIFIED))
         | 
| 122 | 
            +
                        UNKNOWN_RUNTIME_RESULT
         | 
| 123 | 
            +
                      else
         | 
| 124 | 
            +
                        result.all?
         | 
| 125 | 
            +
                      end
         | 
| 126 | 
            +
                    end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                    # Determine if any values are true
         | 
| 129 | 
            +
                    #
         | 
| 130 | 
            +
                    # @param value [Array<String>] condition names
         | 
| 131 | 
            +
                    # @return [TrueClass, FalseClass]
         | 
| 132 | 
            +
                    def fn_or(value)
         | 
| 133 | 
            +
                      result = value.map do |val|
         | 
| 134 | 
            +
                        apply_condition(val)
         | 
| 135 | 
            +
                      end
         | 
| 136 | 
            +
                      if(result.to_s.include?(RUNTIME_MODIFIED))
         | 
| 137 | 
            +
                        UNKNOWN_RUNTIME_RESULT
         | 
| 138 | 
            +
                      else
         | 
| 139 | 
            +
                        result.any?
         | 
| 140 | 
            +
                      end
         | 
| 141 | 
            +
                    end
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                    # Negate given value
         | 
| 144 | 
            +
                    #
         | 
| 145 | 
            +
                    # @param value [Array<Hash>]
         | 
| 146 | 
            +
                    # @return [TrueClass, FalseClass]
         | 
| 147 | 
            +
                    def fn_not(value)
         | 
| 148 | 
            +
                      result = apply_function(value)
         | 
| 149 | 
            +
                      result == RUNTIME_MODIFIED ? UNKNOWN_RUNTIME_RESULT : !result
         | 
| 150 | 
            +
                    end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                    # Determine if values are equal
         | 
| 153 | 
            +
                    #
         | 
| 154 | 
            +
                    # @param value [Array] values
         | 
| 155 | 
            +
                    # @return [TrueClass, FalseClass]
         | 
| 156 | 
            +
                    def fn_equals(value)
         | 
| 157 | 
            +
                      value = value.map do |val|
         | 
| 158 | 
            +
                        apply_function(val)
         | 
| 159 | 
            +
                      end
         | 
| 160 | 
            +
                      if(value.to_s.include?(RUNTIME_MODIFIED))
         | 
| 161 | 
            +
                        UNKNOWN_RUNTIME_RESULT
         | 
| 162 | 
            +
                      else
         | 
| 163 | 
            +
                        value.first == value.last
         | 
| 164 | 
            +
                      end
         | 
| 165 | 
            +
                    end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                    # Join values with given delimiter
         | 
| 168 | 
            +
                    #
         | 
| 169 | 
            +
                    # @param value [Array<String,Array<String>>]
         | 
| 170 | 
            +
                    # @return [String]
         | 
| 171 | 
            +
                    def fn_join(value)
         | 
| 172 | 
            +
                      value.last.join(value.first)
         | 
| 173 | 
            +
                    end
         | 
| 174 | 
            +
             | 
| 175 | 
            +
                    # Lookup value in mappings
         | 
| 176 | 
            +
                    #
         | 
| 177 | 
            +
                    # @param value [Array]
         | 
| 178 | 
            +
                    # @return [String, Fixnum]
         | 
| 179 | 
            +
                    def fn_find_in_map(value)
         | 
| 180 | 
            +
                      map_holder = mappings[value[0]]
         | 
| 181 | 
            +
                      if(map_holder)
         | 
| 182 | 
            +
                        map_item = map_holder[dereference(value[1])]
         | 
| 183 | 
            +
                        if(map_item)
         | 
| 184 | 
            +
                          map_item[value[2]]
         | 
| 185 | 
            +
                        else
         | 
| 186 | 
            +
                          raise "Failed to find mapping item! (#{value[0]} -> #{value[1]})"
         | 
| 187 | 
            +
                        end
         | 
| 188 | 
            +
                      else
         | 
| 189 | 
            +
                        raise "Failed to find mapping! (#{value[0]})"
         | 
| 190 | 
            +
                      end
         | 
| 191 | 
            +
                    end
         | 
| 192 | 
            +
             | 
| 84 193 | 
             
                    # Override the parent dereference behavior to return junk
         | 
| 85 194 | 
             
                    # value on flagged resource match
         | 
| 86 195 | 
             
                    #
         | 
| @@ -416,15 +525,19 @@ module Sfn | |
| 416 525 | 
             
                            ]
         | 
| 417 526 | 
             
                          )
         | 
| 418 527 | 
             
                          begin
         | 
| 419 | 
            -
                             | 
| 420 | 
            -
             | 
| 421 | 
            -
                            if(r_property)
         | 
| 422 | 
            -
                              effect = r_property.update_causes(
         | 
| 423 | 
            -
                                templates.get(:update, 'Resources', resource_name),
         | 
| 424 | 
            -
                                templates.get(:origin, 'Resources', resource_name)
         | 
| 425 | 
            -
                              )
         | 
| 528 | 
            +
                            if(templates.get(:update, 'Resources', resource_name, 'Properties', property_name) == Translator::UNKNOWN_RUNTIME_RESULT)
         | 
| 529 | 
            +
                              effect = :unknown
         | 
| 426 530 | 
             
                            else
         | 
| 427 | 
            -
                               | 
| 531 | 
            +
                              r_info = SparkleFormation::Resources::Aws.resource_lookup(type)
         | 
| 532 | 
            +
                              r_property = r_info.property(property_name)
         | 
| 533 | 
            +
                              if(r_property)
         | 
| 534 | 
            +
                                effect = r_property.update_causes(
         | 
| 535 | 
            +
                                  templates.get(:update, 'Resources', resource_name),
         | 
| 536 | 
            +
                                  templates.get(:origin, 'Resources', resource_name)
         | 
| 537 | 
            +
                                )
         | 
| 538 | 
            +
                              else
         | 
| 539 | 
            +
                                raise KeyError.new 'Unknown property'
         | 
| 540 | 
            +
                              end
         | 
| 428 541 | 
             
                            end
         | 
| 429 542 | 
             
                            case effect.to_sym
         | 
| 430 543 | 
             
                            when :replacement
         | 
| @@ -507,19 +620,30 @@ module Sfn | |
| 507 620 | 
             
                    template.keys.each do |t_key|
         | 
| 508 621 | 
             
                      next if ['Outputs', 'Resources'].include?(t_key)
         | 
| 509 622 | 
             
                      template[t_key] = translator.dereference_processor(
         | 
| 510 | 
            -
                        template[t_key], [' | 
| 623 | 
            +
                        template[t_key], ['DEREF']
         | 
| 511 624 | 
             
                      )
         | 
| 512 625 | 
             
                    end
         | 
| 513 626 | 
             
                    translator.original.replace(template)
         | 
| 514 | 
            -
                     | 
| 515 | 
            -
                      template[ | 
| 516 | 
            -
                        template[ | 
| 517 | 
            -
             | 
| 627 | 
            +
                    ['Outputs', 'Resources'].each do |t_key|
         | 
| 628 | 
            +
                      if(template[t_key])
         | 
| 629 | 
            +
                        template[t_key] = translator.dereference_processor(
         | 
| 630 | 
            +
                          template[t_key], ['DEREF', :all]
         | 
| 631 | 
            +
                        )
         | 
| 632 | 
            +
                      end
         | 
| 518 633 | 
             
                    end
         | 
| 519 | 
            -
                    if(template[' | 
| 520 | 
            -
                      template[' | 
| 521 | 
            -
                         | 
| 522 | 
            -
             | 
| 634 | 
            +
                    if(template['Resources'])
         | 
| 635 | 
            +
                      valid_resources = template['Resources'].map do |resource_name, resource_value|
         | 
| 636 | 
            +
                        if(resource_value['OnCondition'])
         | 
| 637 | 
            +
                          if(translator.apply_condition(resource_value['OnCondition']))
         | 
| 638 | 
            +
                            resource_name
         | 
| 639 | 
            +
                          end
         | 
| 640 | 
            +
                        else
         | 
| 641 | 
            +
                          resource_name
         | 
| 642 | 
            +
                        end
         | 
| 643 | 
            +
                      end.compact
         | 
| 644 | 
            +
                      (template['Resources'].keys - valid_resources).each do |resource_to_remove|
         | 
| 645 | 
            +
                        template['Resources'].delete(resource_to_remove)
         | 
| 646 | 
            +
                      end
         | 
| 523 647 | 
             
                    end
         | 
| 524 648 | 
             
                    translator.original.replace({})
         | 
| 525 649 | 
             
                    template
         | 
    
        data/lib/sfn/provider.rb
    CHANGED
    
    | @@ -78,7 +78,7 @@ module Sfn | |
| 78 78 | 
             
                  )
         | 
| 79 79 | 
             
                  @cache = args.fetch(:cache, Cache.new(:local))
         | 
| 80 80 | 
             
                  @async = args.fetch(:async, true)
         | 
| 81 | 
            -
                  @ | 
| 81 | 
            +
                  @miasma_args = args[:miasma].dup
         | 
| 82 82 | 
             
                  cache.init(:stacks_lock, :lock, :timeout => 0.1)
         | 
| 83 83 | 
             
                  cache.init(:stacks, :stamped)
         | 
| 84 84 | 
             
                  cache.init(:stack_expansion_lock, :lock, :timeout => 0.1)
         | 
    
        data/lib/sfn/version.rb
    CHANGED
    
    
    
        data/sfn.gemspec
    CHANGED
    
    | @@ -11,20 +11,23 @@ Gem::Specification.new do |s| | |
| 11 11 | 
             
              s.license = 'Apache-2.0'
         | 
| 12 12 | 
             
              s.require_path = 'lib'
         | 
| 13 13 | 
             
              s.add_runtime_dependency 'bogo-cli', '>= 0.2.5', '< 0.4'
         | 
| 14 | 
            -
              s.add_runtime_dependency 'bogo-ui', '>= 0.1. | 
| 14 | 
            +
              s.add_runtime_dependency 'bogo-ui', '>= 0.1.22', '< 0.4'
         | 
| 15 15 | 
             
              s.add_runtime_dependency 'miasma', '>= 0.3.0', '< 0.4'
         | 
| 16 16 | 
             
              s.add_runtime_dependency 'miasma-aws', '>= 0.3.6', '< 0.4'
         | 
| 17 17 | 
             
              s.add_runtime_dependency 'miasma-azure', '>= 0.1.0', '< 0.3'
         | 
| 18 18 | 
             
              s.add_runtime_dependency 'miasma-open-stack', '>= 0.1.0', '< 0.3'
         | 
| 19 19 | 
             
              s.add_runtime_dependency 'miasma-rackspace', '>= 0.1.0', '< 0.3'
         | 
| 20 20 | 
             
              s.add_runtime_dependency 'miasma-google', '>= 0.1.0', '< 0.3'
         | 
| 21 | 
            +
              s.add_runtime_dependency 'miasma-terraform', '>= 0.1.0', '< 0.2.0'
         | 
| 21 22 | 
             
              s.add_runtime_dependency 'jmespath'
         | 
| 22 23 | 
             
              s.add_runtime_dependency 'net-ssh'
         | 
| 23 | 
            -
              s.add_runtime_dependency 'sparkle_formation', '>= 3.0. | 
| 24 | 
            +
              s.add_runtime_dependency 'sparkle_formation', '>= 3.0.11', '< 4'
         | 
| 24 25 | 
             
              s.add_runtime_dependency 'hashdiff', '~> 0.2.2'
         | 
| 25 26 | 
             
              s.add_runtime_dependency 'graph', '~> 2.8.1'
         | 
| 26 27 | 
             
              s.add_development_dependency 'rake', '~> 10'
         | 
| 27 28 | 
             
              s.add_development_dependency 'minitest'
         | 
| 29 | 
            +
              s.add_development_dependency 'rspec', '~> 3.5'
         | 
| 30 | 
            +
              s.add_development_dependency 'rubocop', '0.38.0'
         | 
| 28 31 | 
             
              s.add_development_dependency 'mocha'
         | 
| 29 32 | 
             
              s.add_development_dependency 'yard'
         | 
| 30 33 | 
             
              s.executables << 'sfn'
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: sfn
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 3.0. | 
| 4 | 
            +
              version: 3.0.22
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Chris Roberts
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2017-02-04 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bogo-cli
         | 
| @@ -36,7 +36,7 @@ dependencies: | |
| 36 36 | 
             
                requirements:
         | 
| 37 37 | 
             
                - - ">="
         | 
| 38 38 | 
             
                  - !ruby/object:Gem::Version
         | 
| 39 | 
            -
                    version: 0.1. | 
| 39 | 
            +
                    version: 0.1.22
         | 
| 40 40 | 
             
                - - "<"
         | 
| 41 41 | 
             
                  - !ruby/object:Gem::Version
         | 
| 42 42 | 
             
                    version: '0.4'
         | 
| @@ -46,7 +46,7 @@ dependencies: | |
| 46 46 | 
             
                requirements:
         | 
| 47 47 | 
             
                - - ">="
         | 
| 48 48 | 
             
                  - !ruby/object:Gem::Version
         | 
| 49 | 
            -
                    version: 0.1. | 
| 49 | 
            +
                    version: 0.1.22
         | 
| 50 50 | 
             
                - - "<"
         | 
| 51 51 | 
             
                  - !ruby/object:Gem::Version
         | 
| 52 52 | 
             
                    version: '0.4'
         | 
| @@ -170,6 +170,26 @@ dependencies: | |
| 170 170 | 
             
                - - "<"
         | 
| 171 171 | 
             
                  - !ruby/object:Gem::Version
         | 
| 172 172 | 
             
                    version: '0.3'
         | 
| 173 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 174 | 
            +
              name: miasma-terraform
         | 
| 175 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 176 | 
            +
                requirements:
         | 
| 177 | 
            +
                - - ">="
         | 
| 178 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 179 | 
            +
                    version: 0.1.0
         | 
| 180 | 
            +
                - - "<"
         | 
| 181 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 182 | 
            +
                    version: 0.2.0
         | 
| 183 | 
            +
              type: :runtime
         | 
| 184 | 
            +
              prerelease: false
         | 
| 185 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 186 | 
            +
                requirements:
         | 
| 187 | 
            +
                - - ">="
         | 
| 188 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 189 | 
            +
                    version: 0.1.0
         | 
| 190 | 
            +
                - - "<"
         | 
| 191 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 192 | 
            +
                    version: 0.2.0
         | 
| 173 193 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 174 194 | 
             
              name: jmespath
         | 
| 175 195 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -204,7 +224,7 @@ dependencies: | |
| 204 224 | 
             
                requirements:
         | 
| 205 225 | 
             
                - - ">="
         | 
| 206 226 | 
             
                  - !ruby/object:Gem::Version
         | 
| 207 | 
            -
                    version: 3.0. | 
| 227 | 
            +
                    version: 3.0.11
         | 
| 208 228 | 
             
                - - "<"
         | 
| 209 229 | 
             
                  - !ruby/object:Gem::Version
         | 
| 210 230 | 
             
                    version: '4'
         | 
| @@ -214,7 +234,7 @@ dependencies: | |
| 214 234 | 
             
                requirements:
         | 
| 215 235 | 
             
                - - ">="
         | 
| 216 236 | 
             
                  - !ruby/object:Gem::Version
         | 
| 217 | 
            -
                    version: 3.0. | 
| 237 | 
            +
                    version: 3.0.11
         | 
| 218 238 | 
             
                - - "<"
         | 
| 219 239 | 
             
                  - !ruby/object:Gem::Version
         | 
| 220 240 | 
             
                    version: '4'
         | 
| @@ -274,6 +294,34 @@ dependencies: | |
| 274 294 | 
             
                - - ">="
         | 
| 275 295 | 
             
                  - !ruby/object:Gem::Version
         | 
| 276 296 | 
             
                    version: '0'
         | 
| 297 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 298 | 
            +
              name: rspec
         | 
| 299 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 300 | 
            +
                requirements:
         | 
| 301 | 
            +
                - - "~>"
         | 
| 302 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 303 | 
            +
                    version: '3.5'
         | 
| 304 | 
            +
              type: :development
         | 
| 305 | 
            +
              prerelease: false
         | 
| 306 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 307 | 
            +
                requirements:
         | 
| 308 | 
            +
                - - "~>"
         | 
| 309 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 310 | 
            +
                    version: '3.5'
         | 
| 311 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 312 | 
            +
              name: rubocop
         | 
| 313 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 314 | 
            +
                requirements:
         | 
| 315 | 
            +
                - - '='
         | 
| 316 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 317 | 
            +
                    version: 0.38.0
         | 
| 318 | 
            +
              type: :development
         | 
| 319 | 
            +
              prerelease: false
         | 
| 320 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 321 | 
            +
                requirements:
         | 
| 322 | 
            +
                - - '='
         | 
| 323 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 324 | 
            +
                    version: 0.38.0
         | 
| 277 325 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 278 326 | 
             
              name: mocha
         | 
| 279 327 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -346,6 +394,7 @@ files: | |
| 346 394 | 
             
            - lib/sfn.rb
         | 
| 347 395 | 
             
            - lib/sfn/api_provider.rb
         | 
| 348 396 | 
             
            - lib/sfn/api_provider/google.rb
         | 
| 397 | 
            +
            - lib/sfn/api_provider/terraform.rb
         | 
| 349 398 | 
             
            - lib/sfn/cache.rb
         | 
| 350 399 | 
             
            - lib/sfn/callback.rb
         | 
| 351 400 | 
             
            - lib/sfn/callback/aws_assume_role.rb
         | 
| @@ -435,7 +484,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 435 484 | 
             
                  version: '0'
         | 
| 436 485 | 
             
            requirements: []
         | 
| 437 486 | 
             
            rubyforge_project: 
         | 
| 438 | 
            -
            rubygems_version: 2. | 
| 487 | 
            +
            rubygems_version: 2.4.8
         | 
| 439 488 | 
             
            signing_key: 
         | 
| 440 489 | 
             
            specification_version: 4
         | 
| 441 490 | 
             
            summary: SparkleFormation CLI
         |