/
stack.rb
170 lines (154 loc) · 5.26 KB
/
stack.rb
1
2
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
require 'fog/orchestration/models/stack'
require 'fog/aws/models/orchestration/events'
require 'fog/aws/models/orchestration/resources'
require 'fog/aws/models/orchestration/outputs'
module Fog
module Orchestration
class AWS
# Stack instance
class Stack < Fog::Orchestration::Stack
# Register stack resources class
resources Fog::Orchestration::AWS::Resources
# Register stack events class
events Fog::Orchestration::AWS::Events
# Register stack outputs class
outputs Fog::Orchestration::AWS::Outputs
attribute :stack_name, :aliases => ['StackName']
attribute :id, :aliases => ['StackId']
attribute :template_description, :aliases => ['TemplateDescription']
attribute :creation_time, :aliases => ['CreationTime']
attribute :stack_status, :aliases => ['StackStatus']
attribute :deletion_time, :aliases => ['DeletionTime']
attribute :disable_rollback, :aliases => ['DisableRollback']
attribute :parameters, :aliases => ['Parameters']
attribute :capabilities, :aliases => ['Capabilities']
# valid options for stack create and update actions
ALLOWED_OPTIONS = {
:create => [
:template, :template_url, :disable_rollback, :parameters, :timeout_in_minutes, :capabilities, :notification_topics
],
:update => [
:template, :template_url, :parameters
]
}
# option name remapping for API request
OPTIONS_MAPPING = {
:template => 'TemplateBody',
:parameters => 'Parameters',
:capabilities => 'Capabilities',
:disable_rollback => 'DisableRollback',
:timeout_in_minutes => 'TimeoutInMinutes',
:notification_topics => 'NotificationARNs'
}
# Generate API options hash for action
#
# @param action [String, Symbol] :create or :update
# @return [Hash]
def api_arguments_for(action)
args = Hash[
self.attributes.find_all do |key, value|
ALLOWED_OPTIONS[action.to_sym].include?(key)
end
]
OPTIONS_MAPPING.each do |original, mapped|
val = args.delete(original)
if(val)
args[mapped] = val
end
end
args
end
# Create the stack
#
# @return [self]
def create
requires :stack_name
args = api_arguments_for(:create)
service.create_stack(stack_name, args)
self
end
# Update the stack
#
# @return [self]
def update
requires :stack_name, :id
args = api_arguments_for(:update)
service.update_stack(stack_name, args)
self
end
# Destroy the stack
#
# @return [self]
def destroy
requires :stack_name, :id
service.delete_stack(self.stack_name)
self
end
# @return [String] template JSON
def template
if(persisted? && !attributes[:template])
attributes[:template] = service.get_template(stack_name).
body['TemplateBody']
end
attributes[:template]
end
# Set stack template
#
# @param template_body [String, Hash] stack template
# @return [String]
# @note if data structure provided, it will be dumped to JSON
# content and stored
def template=(template_body)
unless(template_body.is_a?(String))
template_body = Fog::JSON.encode(template_body)
end
attributes[:template] = template_body
end
# Validate the template of the stack
#
# @return [TrueClass]
# @raises [Fog::Errors::OrchestrationError::InvalidTemplate]
def validate
unless(self.template || self.template_url)
raise ArgumentError.new('Stack must defined `template` or `template_url`')
end
begin
if(template)
validate_args = {'TemplateBody' => self.template}
else
validate_args = {'TemplateURL' => self.template_url}
end
service.validate_template(validate_args)
true
rescue Fog::AWS::CloudFormation::NotFound => e
raise Fog::Errors::OrchestrationError::InvalidTemplate.new e.message
end
end
# @return [TrueClass, FalseClass]
def exists?
persisted? &&
self.stack_status != 'DELETE_COMPLETE'
end
# @return [Hash] stack parameters
def parameters
Hash[
attributes.fetch(:parameters, []).map do |param_hash|
[param_hash['ParameterKey'], param_hash['ParameterValue']]
end
]
end
# Customized reload to affect only this instance
#
# @return [self]
def reload
requires :identity
describe = service.describe_stacks('StackName' => stack_name).body['Stacks'].first
merge_attributes(self.class.new(describe).attributes)
attributes.delete('Events')
attributes.delete('Resources')
self
end
end
end
end
end