Class: Ufo::Stack
- Inherits:
-
Object
show all
- Extended by:
- Memoist
- Includes:
- Settings, Helper
- Defined in:
- lib/ufo/stack/status.rb,
lib/ufo/stack.rb,
lib/ufo/stack/helper.rb,
lib/ufo/stack/builder.rb,
lib/ufo/stack/context.rb,
lib/ufo/stack/template_body.rb,
lib/ufo/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
Modules: Helper
Classes: Builder, Context, CustomProperties, Status, TemplateBody
Instance Method Summary
collapse
Methods included from Settings
#cfn, #network, #settings
Methods included from Helper
#adjust_stack_name, #find_stack, #status
Methods included from Util
#default_cluster, #display_params, #execute, #pretty_time, #settings, #task_definition_arns, #user_params
Methods included from AwsService
#cloudformation, #cloudwatchlogs, #ec2, #ecr, #ecs, #elb
Constructor Details
#initialize(options) ⇒ Stack
Returns a new instance of Stack.
30
31
32
33
34
35
36
37
|
# File 'lib/ufo/stack.rb', line 30
def initialize(options)
@options = options
@task_definition = options[:task_definition]
@rollback = options[:rollback]
@service = options[:service]
@cluster = @options[:cluster] || default_cluster(@service)
@stack_name = adjust_stack_name(@cluster, options[:service])
end
|
Instance Method Details
#context ⇒ Object
127
128
129
130
131
132
133
134
135
|
# File 'lib/ufo/stack.rb', line 127
def context
o = @options.merge(
cluster: @cluster,
stack_name: @stack_name,
stack: @stack,
)
o[:rollback_definition_arn] = rollback_definition_arn if rollback_definition_arn
Context.new(o)
end
|
#current_desired_count ⇒ Object
143
144
145
146
147
148
149
150
151
152
153
154
|
# File 'lib/ufo/stack.rb', line 143
def current_desired_count
return '' if scheduling_strategy == "DAEMON"
info = Info.new(@service, @options)
service = info.service
if service
service.desired_count.to_s
else
"1" end
end
|
#deploy ⇒ Object
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
# File 'lib/ufo/stack.rb', line 39
def deploy
@stack = find_stack(@stack_name)
if @stack && rollback_complete?(@stack)
puts "Existing stack in ROLLBACK_COMPLETE state. Deleting stack before continuing."
cloudformation.delete_stack(stack_name: @stack_name)
status.wait
status.reset
@stack = nil end
exit_with_message(@stack) if @stack && !updatable?(@stack)
@stack ? perform(:update) : perform(:create)
stop_old_tasks if @options[:stop_old_task]
return unless @options[:wait]
status.wait
puts status.rollback_error_message if status.update_rollback?
status.success?
end
|
#exit_with_message(stack) ⇒ Object
175
176
177
178
179
180
181
|
# File 'lib/ufo/stack.rb', line 175
def exit_with_message(stack)
region = `aws configure get region`.strip rescue "us-east-1"
url = "https://console.aws.amazon.com/cloudformation/home?region=#{region}#/stacks"
puts "The stack is not in an updateable state: #{stack.stack_status.color(:yellow)}."
puts "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.
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
# File 'lib/ufo/stack.rb', line 185
def handle_stack_error(e)
case e.message
when /state and can not be updated/
puts "The #{@stack_name} stack is in a state that cannot be updated. Deleted the stack and try again."
puts "ERROR: #{e.message}"
if message.include?('UPDATE_ROLLBACK_FAILED')
puts "You might be able to do a 'Continue Update Rollback' and skip some resources to get the stack back into a good state."
end
region = `aws configure get region`.strip rescue 'us-east-1'
url = "https://console.aws.amazon.com/cloudformation/home?region=#{region}"
puts "Here's the CloudFormation console url: #{url}"
exit 1
when /No updates are to be performed/
puts "There are no updates to be performed. Exiting.".color(:yellow)
exit 1
else
raise
end
end
|
#notification_arns ⇒ Object
86
87
88
|
# File 'lib/ufo/stack.rb', line 86
def notification_arns
settings[:notification_arns] || []
end
|
#parameters ⇒ Object
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
# File 'lib/ufo/stack.rb', line 90
def parameters
create_elb, elb_target_group = context.elb_options
elb_subnets = network[:elb_subnets] && !network[:elb_subnets].empty? ?
network[:elb_subnets] :
network[:ecs_subnets]
params = {
Vpc: network[:vpc],
ElbSubnets: elb_subnets.join(','),
EcsSubnets: network[:ecs_subnets].join(','),
CreateElb: create_elb,
ElbTargetGroup: elb_target_group,
ElbEipIds: context.elb_eip_ids,
EcsDesiredCount: current_desired_count,
EcsSchedulingStrategy: scheduling_strategy,
}
params = Ufo::Utils::Squeezer.new(params).squeeze
params.map do |k,v|
if v == :use_previous_value
{ parameter_key: k, use_previous_value: true }
else
{ parameter_key: k, parameter_value: v }
end
end
end
|
63
64
65
66
67
68
69
|
# File 'lib/ufo/stack.rb', line 63
def perform(action)
puts "#{action[0..-2].capitalize}ing stack #{@stack_name.color(:green)}..."
cloudformation.send("#{action}_stack", stack_options)
rescue Aws::CloudFormation::Errors::ValidationError => e
handle_stack_error(e)
end
|
#rollback_complete?(stack) ⇒ Boolean
205
206
207
|
# File 'lib/ufo/stack.rb', line 205
def rollback_complete?(stack)
stack.stack_status == 'ROLLBACK_COMPLETE'
end
|
#rollback_definition_arn ⇒ Object
156
157
158
159
160
|
# File 'lib/ufo/stack.rb', line 156
def rollback_definition_arn
return unless @rollback
resp = ecs.describe_task_definition(task_definition: @task_definition)
resp.task_definition.task_definition_arn
end
|
#save_template ⇒ Object
Store template in tmp in case for debugging
164
165
166
167
168
169
170
171
172
173
|
# File 'lib/ufo/stack.rb', line 164
def save_template
path = "/tmp/ufo/#{@stack_name}/stack.yml"
FileUtils.mkdir_p(File.dirname(path))
IO.write(path, template_body)
puts "Generated template saved at: #{path}"
path = "/tmp/ufo/#{@stack_name}/parameters.yml"
IO.write(path, JSON.pretty_generate(parameters))
puts "Generated parameters saved at: #{path}"
end
|
#scheduling_strategy ⇒ Object
138
139
140
141
|
# File 'lib/ufo/stack.rb', line 138
def scheduling_strategy
strategy = @options[:scheduling_strategy] || context.scheduling_strategy
strategy.upcase
end
|
#stack_options ⇒ Object
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
# File 'lib/ufo/stack.rb', line 71
def stack_options
save_template
if ENV['SAVE_TEMPLATE_EXIT']
puts "Template saved. Exiting."
exit 1
end
{
capabilities: ["CAPABILITY_IAM"],
notification_arns: notification_arns,
parameters: parameters,
stack_name: @stack_name,
template_body: template_body,
}
end
|
#template_body ⇒ Object
do not memoize template_body it can change for a rename retry
122
123
124
|
# File 'lib/ufo/stack.rb', line 122
def template_body
TemplateBody.new(context).build
end
|
#updatable?(stack) ⇒ Boolean
209
210
211
|
# File 'lib/ufo/stack.rb', line 209
def updatable?(stack)
stack.stack_status =~ /_COMPLETE$/ || stack.stack_status == 'UPDATE_ROLLBACK_FAILED'
end
|