Class: Ufo::Cfn::Stack
- Inherits:
-
Base
- Object
- Ufo::CLI::Base
- Base
- Ufo::Cfn::Stack
- Extended by:
- Memoist
- Includes:
- Hooks::Concern, TaskDefinition::Helpers::AwsHelper
- Defined in:
- lib/ufo/cfn/stack/status.rb,
lib/ufo/cfn/stack.rb,
lib/ufo/cfn/stack/vpc.rb,
lib/ufo/cfn/stack/vars.rb,
lib/ufo/cfn/stack/params.rb,
lib/ufo/cfn/stack/builder.rb,
lib/ufo/cfn/stack/template.rb,
lib/ufo/cfn/stack/custom_properties.rb
Overview
CloudFormation status codes, full list:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-describing-stacks.html
CREATE_COMPLETE
ROLLBACK_COMPLETE
DELETE_COMPLETE
UPDATE_COMPLETE
UPDATE_ROLLBACK_COMPLETE
CREATE_FAILED
DELETE_FAILED
ROLLBACK_FAILED
UPDATE_ROLLBACK_FAILED
CREATE_IN_PROGRESS
DELETE_IN_PROGRESS
REVIEW_IN_PROGRESS
ROLLBACK_IN_PROGRESS
UPDATE_COMPLETE_CLEANUP_IN_PROGRESS
UPDATE_IN_PROGRESS
UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS
UPDATE_ROLLBACK_IN_PROGRESS
Defined Under Namespace
Classes: Builder, CustomProperties, Params, Status, Template, Vars, Vpc
Instance Attribute Summary
Attributes inherited from Ufo::CLI::Base
Instance Method Summary collapse
-
#build ⇒ Object
Run hooks here so both ufo docker and ufo ship runs it ufo docker => CLI::Build#build => Cfn::Stack#build.
- #cancel ⇒ Object
-
#continue_update_rollback(e) ⇒ Object
Super edge case where stack is in UPDATE_ROLLBACK_FAILED.
- #deploy ⇒ Object
- #exit_with_message(stack) ⇒ Object
-
#handle_stack_error(e) ⇒ Object
Assume only first container_definition to get the container info.
- #perform(action) ⇒ Object
- #print_code(exception) ⇒ Object
- #rollback_complete?(stack) ⇒ Boolean
- #scheduling_strategy ⇒ Object
- #stack_options ⇒ Object
- #tags(hash) ⇒ Object
- #updatable?(stack) ⇒ Boolean
Methods included from Hooks::Concern
Methods included from TaskDefinition::Helpers::AwsHelper
Methods included from Ufo::Concerns
Methods included from Ufo::Concerns::Names
Methods included from AwsServices
#acm, #applicationautoscaling, #aws_options, #cfn, #cloudwatchlogs, #ec2, #ecr, #ecs, #elb, #s3, #ssm_client, #waf_client
Methods included from AwsServices::Concerns
#find_stack, #find_stack_resources, #stack_resources, #status, #task_definition_arns
Methods inherited from Ufo::CLI::Base
Methods included from Utils::Sure
Methods included from Utils::Pretty
#pretty_home, #pretty_path, #pretty_time
Methods included from Utils::Logging
Constructor Details
This class inherits a constructor from Ufo::CLI::Base
Instance Method Details
#build ⇒ Object
106 107 108 109 110 111 112 113 114 115 |
# File 'lib/ufo/cfn/stack.rb', line 106 def build run_hooks(name: "build", file: "ufo.rb") do vars = Vars.new(@options).values = @options.dup.merge(vars: vars) params = Params.new() @parameters = params.build template = Template.new() @template_body = template.body end end |
#cancel ⇒ Object
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/ufo/cfn/stack.rb', line 174 def cancel stack = find_stack(@stack_name) unless stack logger.error "No #{@stack_name} stack to cancel".color(:red) exit 1 end if stack.stack_status == "CREATE_IN_PROGRESS" cfn.delete_stack(stack_name: @stack_name) logger.info "Canceling stack creation" elsif stack.stack_status == "UPDATE_IN_PROGRESS" cfn.cancel_update_stack(stack_name: @stack_name) logger.info "Canceling stack update" else logger.info "The stack is not in a state to that is cancelable: #{stack.stack_status}" end end |
#continue_update_rollback(e) ⇒ Object
Super edge case where stack is in UPDATE_ROLLBACK_FAILED. Can reproduce by:
1. spinning ECS cluster down to 0 and deploying with ufo ship
2. after 3h will timeout and fail and goes into UPDATE_ROLLBACK_FAILED
Screenshot: capture.dropbox.com/Pdr8gijnaQvoMp2y
Will auto-retry once
72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/ufo/cfn/stack.rb', line 72 def continue_update_rollback(e) if e..include?('UPDATE_ROLLBACK_FAILED') && !@continue_update_rollback_tried logger.info "Stack in UPDATE_ROLLBACK_FAILED" logger.info "Trying a continue_update_rollback and will retry again once" cfn.continue_update_rollback(stack_name: @stack_name) status.wait @continue_update_rollback_tried ||= true else false end end |
#deploy ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/ufo/cfn/stack.rb', line 30 def deploy build @stack = find_stack(@stack_name) if @stack && rollback_complete?(@stack) logger.info "Existing stack in ROLLBACK_COMPLETE state. Deleting stack before continuing." cfn.delete_stack(stack_name: @stack_name) status.wait status.reset @stack = nil # at this point stack has been deleted end (@stack) if @stack && !updatable?(@stack) run_hooks(name: "ship", file: "ufo.rb") do @stack ? perform(:update) : perform(:create) stop_old_tasks if @options[:stop_old_task] return unless @options[:wait] status.wait end logger.info status. if status.update_rollback? status.success? end |
#exit_with_message(stack) ⇒ Object
122 123 124 125 126 127 |
# File 'lib/ufo/cfn/stack.rb', line 122 def (stack) url = "https://console.aws.amazon.com/cloudformation/home?region=#{region}#/stacks" logger.info "The stack is not in an updateable state: #{stack.stack_status.color(:yellow)}." logger.info "Here's the CloudFormation url to check for more details #{url}" exit 1 end |
#handle_stack_error(e) ⇒ Object
Assume only first container_definition to get the container info. Stack:arn:aws:cloudformation:… is in ROLLBACK_COMPLETE state and can not be updated.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/ufo/cfn/stack.rb', line 131 def handle_stack_error(e) case e. when /state and can not be updated/ logger.info "The #{@stack_name} stack is in a state that cannot be updated. Deleted the stack and try again." logger.info "ERROR: #{e.}" if e..include?('UPDATE_ROLLBACK_FAILED') logger.info "You might be able to do a 'Continue Update Rollback' and skip some resources to get the stack back into a good state." end url = "https://console.aws.amazon.com/cloudformation/home?region=#{region}" logger.info "Here's the CloudFormation console url: #{url}" exit 1 when /No updates are to be performed/ logger.info "There are no updates to be performed. Exiting.".color(:yellow) exit 1 when /YAML not well-formed/ # happens if a value is a serialize Ruby Object. See: https://gist.github.com/tongueroo/737531d0bc8c92d92b5cd00493e15d9e # e.message: Template format error: YAML not well-formed. (line 207, column 9) print_code(e) else raise end end |
#perform(action) ⇒ Object
54 55 56 57 58 59 60 61 |
# File 'lib/ufo/cfn/stack.rb', line 54 def perform(action) logger.info "#{action[0..-2].capitalize}ing stack #{@stack_name.color(:green)}" cfn.send("#{action}_stack", ) # Example: cfn.send("update_stack", stack_options) rescue Aws::CloudFormation::Errors::ValidationError => e try_continue_update_rollback = continue_update_rollback(e) try_continue_update_rollback && retry handle_stack_error(e) end |
#print_code(exception) ⇒ Object
153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/ufo/cfn/stack.rb', line 153 def print_code(exception) path = ".ufo/output/template.yml" md = exception..match(/line (\d+),/) line_number = md[1] logger.error "Template for debugging: #{path}" if md DslEvaluator.print_code(path, line_number) exit 1 else raise end end |
#rollback_complete?(stack) ⇒ Boolean
166 167 168 |
# File 'lib/ufo/cfn/stack.rb', line 166 def rollback_complete?(stack) stack.stack_status == 'ROLLBACK_COMPLETE' end |
#scheduling_strategy ⇒ Object
117 118 119 120 |
# File 'lib/ufo/cfn/stack.rb', line 117 def scheduling_strategy scheduling_strategy = Ufo.config.ecs.scheduling_strategy scheduling_strategy.upcase if scheduling_strategy end |
#stack_options ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/ufo/cfn/stack.rb', line 84 def = { capabilities: ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"], parameters: @parameters, stack_name: @stack_name, template_body: @template_body, } cfn = Ufo.config.cfn [:notification_arns] = cfn.notification_arns if cfn.notification_arns [:disable_rollback] = cfn.disable_rollback unless cfn.disable_rollback.nil? [:tags] = (cfn.) if cfn. end |
#tags(hash) ⇒ Object
98 99 100 101 102 |
# File 'lib/ufo/cfn/stack.rb', line 98 def (hash) hash.map do |k,v| { key: v, value: v } end end |
#updatable?(stack) ⇒ Boolean
170 171 172 |
# File 'lib/ufo/cfn/stack.rb', line 170 def updatable?(stack) stack.stack_status =~ /_COMPLETE$/ || stack.stack_status == 'UPDATE_ROLLBACK_FAILED' end |