module Sfn::MonkeyPatch::Stack

Expand stack model functionality

Public Instance Methods

apply_stack(remote_stack, opts = {}, ignore_params = nil) click to toggle source

Apply stack outputs to current stack parameters

@param opts [Hash] @option opts [String] :parameter_key key used for parameters block @option opts [String] :default_key key used within parameter for default value @option opts [Hash] :mapping custom output -> parameter name mapping @param remote_stack [Miasma::Orchestration::Stack] @return [self] @note setting `DisableApply` within parameter hash will

prevent parameters being overridden
# File lib/sfn/monkey_patch/stack.rb, line 168
def apply_stack(remote_stack, opts = {}, ignore_params = nil)
  if self.respond_to?("apply_stack_#{api.provider}")
    self.send("apply_stack_#{api.provider}", remote_stack, opts, ignore_params)
  else
    unless opts[:mapping]
      opts[:mapping] = {}
    end
    if opts[:parameter_key]
      stack_parameters = template[opts[:parameter_key]]
      default_key = opts.fetch(
        :default_key,
        opts[:parameter_key].to_s[0, 1].match(/[a-z]/) ? "default" : "Default"
      )
    else
      if template["Parameters"]
        default_key = "Default"
        stack_parameters = template["Parameters"]
      else
        default_key = "default"
        stack_parameters = template["parameters"]
      end
    end
    if stack_parameters
      valid_parameters = stack_parameters.find_all do |key, val|
        !val["DisableApply"] && !val["disable_apply"]
      end.map(&:first)
      if ignore_params
        valid_parameters.reject! do |key|
          ignore_params.include?(key)
        end
      end
      remote_stack.outputs.each do |output|
        o_key = output.key.downcase.tr("_", "")
        p_key = valid_parameters.detect do |v_param|
          v_param.downcase.tr("_", "") == o_key
        end
        unless p_key
          map_key = opts[:mapping].keys.detect do |map_key|
            map_key.downcase.tr("_", "") == o_key
          end
          if map_key
            p_key = valid_parameters.detect do |v_param|
              v_param.downcase.tr("_", "") == opts[:mapping][map_key].downcase.tr("_", "")
            end
          end
        end
        if p_key
          self.parameters = parameters.merge(p_key => output.value)
        end
      end
    end
  end
  self
end
color_state() click to toggle source

Provides color of stack state. Red is an error state, yellow is a warning state and green is a success state

@return [Symbol] color of state (:red, :yellow, :green)

# File lib/sfn/monkey_patch/stack.rb, line 120
def color_state
  red? ? :red : green? ? :green : :yellow
end
complete?() click to toggle source

@return [TrueClass, FalseClass] stack is in complete state

# File lib/sfn/monkey_patch/stack.rb, line 57
def complete?
  status_ends_with?(:complete, :failed)
end
creating?() click to toggle source

@return [TrueClass, FalseClass] stack is creating

# File lib/sfn/monkey_patch/stack.rb, line 73
def creating?
  in_progress? && status_starts_with?(:create)
end
deleting?() click to toggle source

@return [TrueClass, FalseClass] stack is deleting

# File lib/sfn/monkey_patch/stack.rb, line 78
def deleting?
  in_progress? && status_starts_with?(:delete)
end
encoded_id() click to toggle source

@return [String] URL safe encoded stack id

# File lib/sfn/monkey_patch/stack.rb, line 133
def encoded_id
  Base64.urlsafe_encode64(id)
end
failed?() click to toggle source

@return [TrueClass, FalseClass] stack is failed state

# File lib/sfn/monkey_patch/stack.rb, line 62
def failed?
  status_ends_with?(:failed) ||
    (status_includes?(:rollback) && status_ends_with?(:complete))
end
green?() click to toggle source

@return [TrueClass, FalseClass] stack is in green state

# File lib/sfn/monkey_patch/stack.rb, line 107
def green?
  success?
end
in_progress?() click to toggle source

@return [TrueClass, FalseClass] stack is in progress

# File lib/sfn/monkey_patch/stack.rb, line 52
def in_progress?
  status_ends_with?(:in_progress)
end
nested?() click to toggle source

@return [TrueClass, FalseClass] stack contains nested stacks

# File lib/sfn/monkey_patch/stack.rb, line 262
def nested?
  if self.respond_to?("nested_#{api.provider}?")
    self.send("nested_#{api.provider}?")
  else
    !!resources.detect do |resource|
      api.data.fetch(:stack_types, []).include?(resource.type)
    end
  end
end
nested_stacks(recurse = true) click to toggle source

Return all stacks contained within this stack

@param recurse [TrueClass, FalseClass] recurse to fetch all stacks @return [Array<Miasma::Models::Orchestration::Stack>]

# File lib/sfn/monkey_patch/stack.rb, line 227
def nested_stacks(recurse = true)
  if self.respond_to?("nested_stacks_#{api.provider}")
    self.send("nested_stacks_#{api.provider}", recurse)
  else
    resources.reload.all.map do |resource|
      if api.data.fetch(:stack_types, []).include?(resource.type)
        # Custom remote load support
        if resource.type == "Custom::JackalStack"
          location, stack_id = resource.id.to_s.split("-", 2)
          if l_conf = api.data[:locations][location]
            n_stack = Miasma.api(
              :type => :orchestration,
              :provider => l_conf[:provider],
              :credentials => l_conf,
            ).stacks.get(stack_id)
          end
        else
          n_stack = resource.expand
        end
        if n_stack
          n_stack.data[:logical_id] = resource.name
          n_stack.data[:parent_stack] = self
          n_stack.api.data[:stack_types] = api.data[:stack_types]
          if recurse
            [n_stack] + n_stack.nested_stacks(recurse)
          else
            n_stack
          end
        end
      end
    end.flatten.compact
  end
end
nesting_style() click to toggle source

Detect the nesting style in use by the stack

@return [Symbol, NilClass] style of nesting (:shallow, :deep)

or `nil` if no nesting detected

@note in shallow nesting style, stack resources will not

contain any direct values for parameters (which is what we
are testing for)
# File lib/sfn/monkey_patch/stack.rb, line 308
def nesting_style
  if self.respond_to?("nesting_style_#{api.provider}")
    self.send("nesting_style_#{api.provider}")
  else
    if nested?
      self.template["Resources"].find_all do |t_resource|
        t_resource["Type"] == self.api.class.const_get(:RESOURCE_MAPPING).key(self.class)
      end.detect do |t_resource|
        t_resource["Properties"].fetch("Parameters", {}).values.detect do |t_value|
          !t_value.is_a?(Hash)
        end
      end ? :deep : :shallow
    end
  end
end
percent_complete(min = 5) click to toggle source

Whole number representation of current completion

@param min [Integer] lowest allowed return value (defaults 5) @return [Integer] percent complete (0..100)

# File lib/sfn/monkey_patch/stack.rb, line 141
def percent_complete(min = 5)
  if self.respond_to?("percent_complete_#{api.provider}")
    self.send("percent_complete_#{api.provider}", min)
  else
    if in_progress?
      total_resources = template.fetch("Resources", []).size
      total_complete = resources.all.find_all do |resource|
        resource.status.downcase.end_with?("complete")
      end.size
      result = ((total_complete.to_f / total_resources) * 100).to_i
      result > min.to_i ? result : min
    else
      100
    end
  end
end
performing() click to toggle source

@return [String] action currently being performed

# File lib/sfn/monkey_patch/stack.rb, line 93
def performing
  if in_progress?
    status.to_s.downcase.split("_").first.to_sym
  end
end
policy() click to toggle source

Return stack policy if available

@return [Smash, NilClass]

# File lib/sfn/monkey_patch/stack.rb, line 275
def policy
  if self.respond_to?("policy_#{api.provider}")
    self.send("policy_#{api.provider}")
  else
    if (self.api.provider == :aws) # cause this is the only one
      begin
        result = self.api.request(
          :path => "/",
          :form => Smash.new(
            "Action" => "GetStackPolicy",
            "StackName" => self.id,
          ),
        )
        serialized_policy = result.get(:body, "GetStackPolicyResult", "StackPolicyBody")
        MultiJson.load(serialized_policy).to_smash
      rescue Miasma::Error::ApiError::RequestError => e
        if e.response.code == 404
          nil
        else
          raise
        end
      end
    end
  end
end
red?() click to toggle source

@return [TrueClass, FalseClass] stack is in red state

# File lib/sfn/monkey_patch/stack.rb, line 102
def red?
  failed? || deleting?
end
rollbacking?() click to toggle source

@return [TrueClass, FalseClass] stack is rolling back

# File lib/sfn/monkey_patch/stack.rb, line 88
def rollbacking?
  in_progress? && status_starts_with?(:rollback)
end
root_parameters() click to toggle source

Provide easy parameters override

@return [Hash]

# File lib/sfn/monkey_patch/stack.rb, line 338
def root_parameters
  if self.respond_to?("root_parameters_#{api.provider}")
    self.send("root_parameters_#{api.provider}")
  else
    parameters
  end
end
sparkleish_template(*args) click to toggle source

Reformat template data structure to SparkleFormation style structure

@return [Hash]

# File lib/sfn/monkey_patch/stack.rb, line 327
def sparkleish_template(*args)
  if self.respond_to?("sparkleish_template_#{api.provider}")
    self.send("sparkleish_template_#{api.provider}", *args)
  else
    template
  end
end
status_ends_with?(*args) click to toggle source

Check for state suffix

@param args [String, Symbol] state suffix to check for (multiple allowed) @return [TrueClass, FalseClass] true if any matches found in argument list

# File lib/sfn/monkey_patch/stack.rb, line 22
def status_ends_with?(*args)
  stat = status.to_s.downcase
  !!args.map(&:to_s).map(&:downcase).detect do |suffix|
    stat.end_with?(suffix) || state.to_s.end_with?(suffix)
  end
end
status_includes?(*args) click to toggle source

Check for state inclusion

@param args [String, Symbol] state string to check for (multiple allowed) @return [TrueClass, FalseClass] true if any matches found in argument list

# File lib/sfn/monkey_patch/stack.rb, line 44
def status_includes?(*args)
  stat = status.to_s.downcase
  !!args.map(&:to_s).map(&:downcase).detect do |string|
    stat.include?(string)
  end
end
status_starts_with?(*args) click to toggle source

Check for state prefix

@param args [String, Symbol] state prefix to check for (multiple allowed) @return [TrueClass, FalseClass] true if any matches found in argument list

# File lib/sfn/monkey_patch/stack.rb, line 33
def status_starts_with?(*args)
  stat = status.to_s.downcase
  !!args.map(&:to_s).map(&:downcase).detect do |prefix|
    stat.start_with?(prefix) || state.to_s.start_with?(prefix)
  end
end
success?() click to toggle source

@return [TrueClass, FalseClass] stack is in success state

# File lib/sfn/monkey_patch/stack.rb, line 68
def success?
  !failed? && complete?
end
text_state() click to toggle source

Provides text of stack state. Danger is an error state, warning is a warning state and success is a success state

@return [Symbol] color of state (:danger, :warning, :success)

# File lib/sfn/monkey_patch/stack.rb, line 128
def text_state
  red? ? :danger : green? ? :success : :warning
end
updating?() click to toggle source

@return [TrueClass, FalseClass] stack is updating

# File lib/sfn/monkey_patch/stack.rb, line 83
def updating?
  in_progress? && status_starts_with?(:update)
end
yellow?() click to toggle source

@return [TrueClass, FalseClass] stack is in yellow state

# File lib/sfn/monkey_patch/stack.rb, line 112
def yellow?
  !red? && !green?
end