class Sfn::Planner::Aws::Translator

Customized translator to dereference template

Constants

FN_MAPPING
MAP
REF_MAPPING
UNKNOWN_RUNTIME_RESULT

Attributes

flagged[R]

@return [Array<String>] flagged items for value replacement

Public Class Methods

new(template_hash, args = {}) click to toggle source

Override to init flagged array

Calls superclass method
# File lib/sfn/planner/aws.rb, line 22
def initialize(template_hash, args = {})
  super
  @flagged = []
end

Public Instance Methods

apply_condition(name) click to toggle source

Evaluate given condition

@param name [String] condition name @return [TrueClass, FalseClass]

# File lib/sfn/planner/aws.rb, line 89
def apply_condition(name)
  condition = conditions[name]
  if condition
    apply_function(condition, [:all, "DEREF"])
  else
    raise "Failed to locate condition with name `#{name}`!"
  end
end
apply_function(hash, funcs = []) click to toggle source

Apply function if possible

@param hash [Hash] @param funcs [Array] allowed functions @return [Hash] @note also allows 'Ref' within funcs to provide mapping

replacements using the REF_MAPPING constant
# File lib/sfn/planner/aws.rb, line 56
def apply_function(hash, funcs = [])
  if hash.is_a?(Hash)
    k, v = hash.first
    if hash.size == 1 && (k.start_with?("Fn") || k == "Ref") && (funcs.include?(:all) || funcs.empty? || funcs.include?(k) || funcs == ["DEREF"])
      method_name = Bogo::Utility.snake(k.gsub("::", ""))
      if (funcs.include?(k) || funcs.include?(:all)) && respond_to?(method_name)
        apply_function(send(method_name, v), funcs)
      else
        case k
        when "Fn::GetAtt"
          funcs.include?("DEREF") ? dereference(hash) : hash
        when "Ref"
          if funcs.include?("DEREF")
            dereference(hash)
          else
            {"Ref" => self.class.const_get(:REF_MAPPING).fetch(v, v)}
          end
        else
          hash
        end
      end
    else
      hash
    end
  else
    hash
  end
end
conditions() click to toggle source

@return [Hash] defined conditions

# File lib/sfn/planner/aws.rb, line 28
def conditions
  @original.fetch("Conditions", {})
end
dereference(hash) click to toggle source

Override the parent dereference behavior to return junk value on flagged resource match

@param hash [Hash] @return [Hash, String]

Calls superclass method
# File lib/sfn/planner/aws.rb, line 202
def dereference(hash)
  result = nil
  if hash.is_a?(Hash)
    if hash.keys.first == "Ref" && flagged?(hash.values.first)
      result = RUNTIME_MODIFIED
    elsif hash.keys.first == "Fn::GetAtt"
      if hash.values.last.last.start_with?("Outputs.")
        if flagged?(hash.values.join("_"))
          result = RUNTIME_MODIFIED
        end
      elsif flagged?(hash.values.first)
        result = RUNTIME_MODIFIED
      end
    end
  end
  result = result.nil? ? super : result
  unless result.is_a?(Enumerable)
    result = result.to_s
  end
  result
end
flag_ref(ref_name) click to toggle source

Flag a reference as modified

@param ref_name [String] @return [Array<String>]

# File lib/sfn/planner/aws.rb, line 36
def flag_ref(ref_name)
  @flagged << ref_name.to_s
  @flagged.uniq!
end
flagged?(name) click to toggle source

Check if resource name is flagged

@param name [String] @return [TrueClass, FalseClass]

# File lib/sfn/planner/aws.rb, line 45
def flagged?(name)
  @flagged.include?(name.to_s)
end
fn_and(value) click to toggle source

Determine if all conditions are true

@param value [Array<String>] condition names @return [TrueClass, FalseClass]

# File lib/sfn/planner/aws.rb, line 116
def fn_and(value)
  result = value.map do |val|
    apply_condition(val)
  end
  if result.to_s.include?(RUNTIME_MODIFIED)
    UNKNOWN_RUNTIME_RESULT
  else
    result.all?
  end
end
fn_equals(value) click to toggle source

Determine if values are equal

@param value [Array] values @return [TrueClass, FalseClass]

# File lib/sfn/planner/aws.rb, line 155
def fn_equals(value)
  value = value.map do |val|
    apply_function(val)
  end
  if value.to_s.include?(RUNTIME_MODIFIED)
    UNKNOWN_RUNTIME_RESULT
  else
    value.first == value.last
  end
end
fn_find_in_map(value) click to toggle source

Lookup value in mappings

@param value [Array] @return [String, Fixnum]

# File lib/sfn/planner/aws.rb, line 183
def fn_find_in_map(value)
  map_holder = mappings[value[0]]
  if map_holder
    map_item = map_holder[dereference(value[1])]
    if map_item
      map_item[value[2]]
    else
      raise "Failed to find mapping item! (#{value[0]} -> #{value[1]})"
    end
  else
    raise "Failed to find mapping! (#{value[0]})"
  end
end
fn_if(value) click to toggle source

Evaluate `if` conditional

@param value [Array] {0: condition name, 1: true value, 2: false value} @return [Object] true or false value

# File lib/sfn/planner/aws.rb, line 102
def fn_if(value)
  result = apply_condition(value[0])
  if result != UNKNOWN_RUNTIME_RESULT
    result ? value[1] : value[2]
  else
    UNKNOWN_RUNTIME_RESULT
    result
  end
end
fn_join(value) click to toggle source

Join values with given delimiter

@param value [Array<String,Array<String>>] @return [String]

# File lib/sfn/planner/aws.rb, line 170
def fn_join(value)
  unless value.last.is_a?(Array)
    val = value.last.to_s.split(",")
  else
    val = value.last
  end
  val.join(value.first)
end
fn_not(value) click to toggle source

Negate given value

@param value [Array<Hash>] @return [TrueClass, FalseClass]

# File lib/sfn/planner/aws.rb, line 146
def fn_not(value)
  result = apply_function(value)
  result == RUNTIME_MODIFIED ? UNKNOWN_RUNTIME_RESULT : !result
end
fn_or(value) click to toggle source

Determine if any values are true

@param value [Array<String>] condition names @return [TrueClass, FalseClass]

# File lib/sfn/planner/aws.rb, line 131
def fn_or(value)
  result = value.map do |val|
    apply_condition(val)
  end
  if result.to_s.include?(RUNTIME_MODIFIED)
    UNKNOWN_RUNTIME_RESULT
  else
    result.any?
  end
end