Class: Jets::Cfn::Deploy
- Inherits:
-
Stack
- Object
- Stack
- Jets::Cfn::Deploy
show all
- Defined in:
- lib/jets/cfn/deploy.rb
Instance Method Summary
collapse
Methods inherited from Stack
#check_stack_exist!, #initialize
#check_deployable!
#continue_update_rollback!, #delete_rollback_complete!, #rollback_complete?, #update_rollback_failed?
#log
#find_stack
#apigateway, #aws_options, #cfn, #codebuild, #dynamodb, #lambda_client, #logs, #s3, #s3_resource, #sns, #sqs, #ssm, #sts, #wafv2
#output_value, #stack_exists?
included, #reset_cache!
Instance Method Details
#capabilities ⇒ Object
149
150
151
|
# File 'lib/jets/cfn/deploy.rb', line 149
def capabilities
["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"]
end
|
#cfn_status ⇒ Object
note: required method: rollback.rb module uses
46
47
48
|
# File 'lib/jets/cfn/deploy.rb', line 46
def cfn_status
Jets::Cfn::Status.new
end
|
#changed? ⇒ Boolean
CloudFormation always performs an update there are nested templates, even when the parent template has not changed at all. Note: Jets ressurects the template body with a slight difference
!Ref S3Bucket vs {Ref: S3Bucket}
However, tested with the exact template body without this difference and cloudformation still performs an update. So we have to check if the template has changed ourselves. This is useful for the bootstrap genesis update.
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
# File 'lib/jets/cfn/deploy.rb', line 59
def changed?
return true if @options[:force_changed]
return true unless stack_exists?(stack_name)
template_body = cfn.get_template(stack_name: stack_name).template_body
existing = Yamler.load(template_body)
fresh = Yamler.load(template.body)
FileUtils.mkdir_p("#{Jets.build_root}/cfn/diff")
IO.write("#{Jets.build_root}/cfn/diff/existing.yml", YAML.dump(existing))
IO.write("#{Jets.build_root}/cfn/diff/fresh.yml", YAML.dump(fresh))
existing != fresh
end
|
#command_with_iam(capabilities) ⇒ Object
145
146
147
|
# File 'lib/jets/cfn/deploy.rb', line 145
def command_with_iam(capabilities)
"#{File.basename($0)} #{ARGV.join(" ")} --capabilities #{capabilities}"
end
|
#create_stack ⇒ Object
97
98
99
100
|
# File 'lib/jets/cfn/deploy.rb', line 97
def create_stack
cfn.create_stack(stack_options)
end
|
#deploy_message ⇒ Object
75
76
77
78
79
80
81
82
83
|
# File 'lib/jets/cfn/deploy.rb', line 75
def deploy_message
if @options[:bootstrap_message]
log.info "#{@options[:bootstrap_message]}: #{stack_name}"
elsif @options[:bootstrap]
log.info "Syncing bootstrap: #{stack_name}"
else
log.info "Deploying app: #{stack_name}"
end
end
|
#prompt_for_iam(capabilities) ⇒ Object
137
138
139
140
141
142
143
|
# File 'lib/jets/cfn/deploy.rb', line 137
def prompt_for_iam(capabilities)
log.info "This stack will create IAM resources. Please approve to run the command again with #{capabilities} capabilities."
log.info " #{command_with_iam(capabilities)}"
log.info "Please confirm (y/n)"
$stdin.gets end
|
85
86
87
|
# File 'lib/jets/cfn/deploy.rb', line 85
def set_resource_tags
@tags = Jets.bootstrap.config.cfn.resource_tags.map { |k, v| {key: k, value: v} }
end
|
#stack_options ⇒ Object
options common to both create_stack and update_stack
116
117
118
119
120
121
122
|
# File 'lib/jets/cfn/deploy.rb', line 116
def stack_options
{
stack_name: stack_name,
capabilities: capabilities,
tags: @tags
}.merge(template.template_option)
end
|
#stack_status ⇒ Object
131
132
133
134
135
|
# File 'lib/jets/cfn/deploy.rb', line 131
def stack_status
resp = cfn.describe_stacks(stack_name: stack_name)
status = resp.stacks[0].stack_status
[resp, status]
end
|
#sync ⇒ Object
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
# File 'lib/jets/cfn/deploy.rb', line 3
def sync
delete_rollback_complete!
continue_update_rollback!
check_deployable!
log.debug "Parent template changed: #{changed?.inspect}"
return true unless changed?
quiet_sync = @options[:bootstrap] == true && stack_exists?(stack_name)
deploy_message
set_resource_tags
begin
sync_stack
rescue Aws::CloudFormation::Errors::InsufficientCapabilitiesException => e
capabilities = e.message.match(/\[(.*)\]/)[1]
confirm = prompt_for_iam(capabilities)
if /^y/.match?(confirm)
@options.merge!(capabilities: [capabilities])
log.info "Re-running: #{command_with_iam(capabilities).color(:green)}"
retry
else
log.error "ERROR: Unable to deploy #{e.message}"
exit 1
end
end
success = cfn_status.wait(quiet: quiet_sync)
if success
log.info "Bootstrap synced" if @options[:bootstrap] == true else
if quiet_sync cfn_status.run
end
cfn_status.failure_message
end
success
end
|
#sync_stack ⇒ Object
89
90
91
92
93
94
95
|
# File 'lib/jets/cfn/deploy.rb', line 89
def sync_stack
if stack_exists?(stack_name)
update_stack
else
create_stack
end
end
|
#template ⇒ Object
124
125
126
|
# File 'lib/jets/cfn/deploy.rb', line 124
def template
Template.new(@options)
end
|
#update_stack ⇒ Object
102
103
104
105
106
107
108
109
110
111
112
113
|
# File 'lib/jets/cfn/deploy.rb', line 102
def update_stack
cfn.update_stack(stack_options)
rescue Aws::CloudFormation::Errors::ValidationError => e
if e.message.include?("No updates are to be performed")
log.debug "DEBUG bootstrap sync update_stack #{e.message}" else
log.info "ERROR bootstrap sync update_stack #{e.message}" raise
end
true
end
|