module Sfn::MonkeyPatch::Stack
Expand stack model functionality
Public Instance Methods
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
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
@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
@return [TrueClass, FalseClass] stack is creating
# File lib/sfn/monkey_patch/stack.rb, line 73 def creating? in_progress? && status_starts_with?(:create) end
@return [TrueClass, FalseClass] stack is deleting
# File lib/sfn/monkey_patch/stack.rb, line 78 def deleting? in_progress? && status_starts_with?(:delete) end
@return [String] URL safe encoded stack id
# File lib/sfn/monkey_patch/stack.rb, line 133 def encoded_id Base64.urlsafe_encode64(id) end
@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
@return [TrueClass, FalseClass] stack is in green state
# File lib/sfn/monkey_patch/stack.rb, line 107 def green? success? end
@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
@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
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
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
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
@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
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
@return [TrueClass, FalseClass] stack is in red state
# File lib/sfn/monkey_patch/stack.rb, line 102 def red? failed? || deleting? end
@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
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
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
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
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
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
@return [TrueClass, FalseClass] stack is in success state
# File lib/sfn/monkey_patch/stack.rb, line 68 def success? !failed? && complete? end
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
@return [TrueClass, FalseClass] stack is updating
# File lib/sfn/monkey_patch/stack.rb, line 83 def updating? in_progress? && status_starts_with?(:update) end
@return [TrueClass, FalseClass] stack is in yellow state
# File lib/sfn/monkey_patch/stack.rb, line 112 def yellow? !red? && !green? end