class Stackit::ManagedStack
Constants
- DRY_RUN_RESPONSE
- REDACTED_TEXT
Attributes
debug[RW]
depends[RW]
dry_run[RW]
file_parameters[RW]
force[RW]
notifier[RW]
parameter_map[RW]
template[RW]
template_path[RW]
user_defined_parameters[RW]
wait[RW]
Public Class Methods
new(options={})
click to toggle source
Calls superclass method
Stackit::Stack::new
# File lib/stackit/stack/managed_stack.rb, line 18 def initialize(options={}) super(options) self.template_path = options[:template] self.user_defined_parameters = symbolized_user_defined_parameters(options[:user_defined_parameters]) self.parameter_map = symbolized_parameter_map(options[:parameter_map]) self.stack_name = options[:stack_name] || default_stack_name self.depends = options[:depends] || [] self.disable_rollback = self.debug ? true : !!options[:disable_rollback] self.debug = !!options[:debug] || Stackit.debug self.force = options[:force] self.wait = options[:wait] self.dry_run = options[:dry_run] self.notifier = options[:notifier] || Stackit::ThorNotifier.new parse_file_parameters(options[:parameters_file]) if options[:parameters_file] create_stack_policy(options[:stack_policy]) create_stack_policy_during_update(options[:stack_policy_during_update]) end
Public Instance Methods
change_set!()
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 130 def change_set! begin response = cloudformation_request(:create_change_set) notifier.response(response) rescue ::Aws::CloudFormation::Errors::AlreadyExistsException => e notifier.backtrace(e) if Stackit.debug notifier.error(e.message) rescue ::Aws::CloudFormation::Errors::ValidationError => e notifier.backtrace(e) if Stackit.debug notifier.error(e.message) end response end
create!()
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 36 def create! begin response = cloudformation_request(:create_stack) notifier.response(response) rescue ::Aws::CloudFormation::Errors::AlreadyExistsException => e notifier.backtrace(e) if Stackit.debug notifier.error(e.message) rescue ::Aws::CloudFormation::Errors::ValidationError => e notifier.backtrace(e) if Stackit.debug notifier.error(e.message) end response end
delete!()
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 68 def delete! begin response = cloudformation_request(:delete_stack) notifier.response(response) rescue ::Aws::CloudFormation::Errors::AlreadyExistsException => e notifier.backtrace(e) if Stackit.debug notifier.error(e.message) rescue ::Aws::CloudFormation::Errors::ValidationError => e notifier.backtrace(e) if Stackit.debug notifier.error(e.message) end response end
deploy!()
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 82 def deploy! if !File.exist?(template) delete! wait_for_stack_to_delete notifier.success('Delete successful') elsif exist? begin update! wait_for_stack notifier.success('Update successful') rescue ::Aws::CloudFormation::Errors::ValidationError => e if e.message.include? "No updates are to be performed" Stackit.logger.info "No updates are to be performed" elsif e.message.include? "_FAILED state and can not be updated" Stackit.logger.info 'Stack is in a failed state and can\'t be updated. Deleting/creating a new stack.' delete! wait_for_stack_to_delete create! wait_for_stack notifier.success('Stack deleted and re-created') else raise e end end else begin create! wait_for_stack notifier.success('Created successfully') rescue ::Aws::CloudFormation::Errors::ValidationError => e if e.message.include? "_FAILED state and can not be updated" Stackit.logger.info 'Stack already exists, is in a failed state, and can\'t be updated. Deleting and creating a new stack.' delete! wait_for_stack_to_delete create! wait_for_stack notifier.success('Stack deleted and re-created') else raise e end end end end
describe()
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 144 def describe response = cloudformation_request(:describe_stacks) if response && response[:stacks] response[:stacks].first else nil end rescue ::Aws::CloudFormation::Errors::ValidationError nil end
exist?()
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 126 def exist? describe != nil end
update!()
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 50 def update! begin response = cloudformation_request(:update_stack) notifier.response(response) rescue ::Aws::CloudFormation::Errors::AlreadyExistsException => e notifier.backtrace(e) if Stackit.debug notifier.error(e.message) rescue ::Aws::CloudFormation::Errors::ValidationError => e if e.message =~ /No updates are to be performed./ notifier.success(e.message) else notifier.backtrace(e) if Stackit.debug notifier.error(e.message) end end response end
Private Instance Methods
capabilities()
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 228 def capabilities template.needs_iam_capability? ? ['CAPABILITY_IAM'] : [] end
cloudformation_request(action)
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 232 def cloudformation_request(action) Stackit.logger.debug "ManagedStack CloudFormation API request: #{action}" self.template = create_template(template_path, action); cloudformation_options = create_cloudformation_options(action) if debug Stackit.logger.debug "#{action} request parameters: " opts = cloudformation_options.clone if opts[:parameters] opts[:parameters].each do |param| key = param['parameter_key'] param['parameter_value'] = REDACTED_TEXT if key =~ /username|password/i && !debug end end opts[:template_body] = REDACTED_TEXT if opts[:template_body] opts[:stack_policy_body] = JSON.parse(opts[:stack_policy_body]) if opts[:stack_policy_body] opts[:stack_policy_during_update_body] = JSON.parse(opts[:stack_policy_during_update_body]) if opts[:stack_policy_during_update_body] pp opts end response = dry_run ? dry_run_response : cloudformation.send(action, cloudformation_options) wait_for_stack if wait response end
create_cloudformation_options(action)
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 256 def create_cloudformation_options(action) case action when :create_stack create_stack_request_params.merge(template.options).merge( parameters: to_request_parameters(merged_parameters), capabilities: capabilities ) when :update_stack update_stack_request_params.merge(template.options).merge( parameters: to_request_parameters(merged_parameters), capabilities: capabilities, use_previous_template: template.options[:template_body].nil? && template.options[:template_url].nil? ) when :delete_stack delete_stack_request_params when :create_change_set change_set_request_params.merge(template.options).merge( parameters: to_request_parameters(merged_parameters), capabilities: capabilities, use_previous_template: template.options[:template_body].nil? && template.options[:template_url].nil? ) end end
create_stack_policy(f)
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 193 def create_stack_policy(f) policy_path = f ? f : File.join(Stackit.home, 'stackit', 'stack', 'default-stack-policy.json') if policy_path =~ /^http/ self.stack_policy_url = policy_path else raise "Unable to locate policy: #{policy_path}" unless File.exist?(policy_path) self.stack_policy_body = File.read(policy_path) end end
create_stack_policy_during_update(f)
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 203 def create_stack_policy_during_update(f) policy_path = f ? f : File.join(Dir.pwd, "#{stack_name}-update-policy.json") if !File.exist?(policy_path) Stackit.logger.warn "Unable to locate stack policy during update file: #{policy_path}" return end if policy_path =~ /^http/ self.stack_policy_during_update_url = policy_path else raise "Unable to locate update policy: #{policy_path}" unless File.exist?(policy_path) self.stack_policy_during_update_body = File.read(policy_path) end end
create_template(t, action)
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 180 def create_template(t, action) template_path = t ? t : File.join(Dir.pwd, 'cloudformation', "#{stack_name.underscore.dasherize}.json") if !File.exist?(template_path) return if action == :delete_stack raise "Unable to locate template: #{template_path}" end template = Template.new( :cloudformation => cloudformation, :template_path => template_path ) template.parse! end
default_stack_name()
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 176 def default_stack_name self.class.name.demodulize end
dry_run_response()
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 308 def dry_run_response DRY_RUN_RESPONSE.new('arn:stackit:dry-run:complete') end
mapped_key(param)
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 300 def mapped_key(param) if parameter_map.has_key?(param.to_sym) parameter_map[param.to_sym] else param.to_sym end end
merged_parameters()
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 280 def merged_parameters merged_params = template.parsed_parameters merged_params.merge!(file_parameters) if file_parameters depends.each do |dependent_stack_name| this_stack = Stack.new({ cloudformation: cloudformation, stack_name: dependent_stack_name }) merged_params.select { |param| !this_stack[mapped_key(param.to_s)].nil? }.each do | param_name, param_value | merged_params.merge!(param_name => this_stack[mapped_key(param_name)]) end end user_defined_parameters.each { |k, v| user_defined_parameters[k] = v.to_s } merged_params.merge!(user_defined_parameters) end
parse_file_parameters(parameters_file)
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 217 def parse_file_parameters(parameters_file) if File.exist?(parameters_file) Stackit.logger.info "Parsing cloudformation parameters file: #{parameters_file}" @file_parameters = {} file_params = JSON.parse(File.read(parameters_file)) file_params.inject(@file_parameters) do |hash, param| hash.merge!(param['ParameterKey'].to_sym => param['ParameterValue']) end end end
symbolized_parameter_map(param_map)
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 168 def symbolized_parameter_map(param_map) if param_map param_map.symbolize_keys! else {} end end
symbolized_user_defined_parameters(params)
click to toggle source
# File lib/stackit/stack/managed_stack.rb, line 160 def symbolized_user_defined_parameters(params) if params params.symbolize_keys! else {} end end