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
143
144
145
|
# File 'lib/jets/cfn/deploy.rb', line 143
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
139
140
141
|
# File 'lib/jets/cfn/deploy.rb', line 139
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
131
132
133
134
135
136
137
|
# File 'lib/jets/cfn/deploy.rb', line 131
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
110
111
112
113
114
115
116
|
# File 'lib/jets/cfn/deploy.rb', line 110
def stack_options
{
stack_name: stack_name,
capabilities: capabilities,
tags: @tags
}.merge(template.template_option)
end
|
#stack_status ⇒ Object
125
126
127
128
129
|
# File 'lib/jets/cfn/deploy.rb', line 125
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
118
119
120
|
# File 'lib/jets/cfn/deploy.rb', line 118
def template
Template.new(@options)
end
|
#update_stack ⇒ Object
102
103
104
105
106
107
|
# File 'lib/jets/cfn/deploy.rb', line 102
def update_stack
cfn.update_stack(stack_options)
rescue Aws::CloudFormation::Errors::ValidationError => e
log.debug "DEBUG bootstrap/deploy.rb update_stack #{e.message}" true
end
|