jackal-cfn 0.2.8 → 0.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +304 -8
- data/jackal-cfn.gemspec +1 -0
- data/lib/jackal-cfn/resource/ami_manager.rb +0 -2
- data/lib/jackal-cfn/resource/hash_extractor.rb +1 -1
- data/lib/jackal-cfn/resource/jackal_stack.rb +248 -0
- data/lib/jackal-cfn/resource.rb +2 -2
- data/lib/jackal-cfn/utils.rb +1 -1
- data/lib/jackal-cfn/version.rb +1 -1
- data/lib/jackal-cfn.rb +1 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9fddaa1ca5447da20d6c856d2ccdf3ba4d3c89d9
|
4
|
+
data.tar.gz: acddccbce932860d09c048ba04627df5744cd4b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d5f2187fab6e8d42da3ab3351b53720b1cd351a95df76ffe40390e50786a4f457fef306f6b00b93de1dabba807bcdb1f87e1c0c5b08b67d3f9dd8985d6c5b86
|
7
|
+
data.tar.gz: 9b5b9c770c12c9158bdc2ad3bf03041b7200b3aacdaf35f2bbec8c561673646d0b1a2ec63d1acea196e8b246b29468397497291f6b7fb006e6ac96359e2447f6
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,23 +1,319 @@
|
|
1
1
|
# Jackal CFN
|
2
2
|
|
3
|
-
|
3
|
+
Provides jackal integration for AWS CloudFormation custom
|
4
|
+
resources and stack event notifications.
|
4
5
|
|
5
|
-
##
|
6
|
+
## Requirements
|
6
7
|
|
7
|
-
|
8
|
+
This library currently uses the `patron` gem for sending
|
9
|
+
notifications to AWS S3. It requires the curl development
|
10
|
+
libraries to be available, so ensure it is installed.
|
8
11
|
|
9
|
-
|
10
|
-
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
There are two ways to use this library. The first is to process
|
15
|
+
events and resources into proper payloads and inject them into the
|
16
|
+
pipeline. The other is to re-process a formatted payload.
|
17
|
+
|
18
|
+
### Pipeline Injection
|
19
|
+
|
20
|
+
Configuration for pipeline injection of resource and event notifications
|
21
|
+
is very straightforward:
|
22
|
+
|
23
|
+
```json
|
24
|
+
{
|
25
|
+
"jackal": {
|
26
|
+
"cfn": {
|
27
|
+
"config": {
|
28
|
+
},
|
29
|
+
"sources": {
|
30
|
+
"input": {
|
31
|
+
"type": "sqs",
|
32
|
+
"args": {
|
33
|
+
SQS_CONFIG
|
34
|
+
}
|
35
|
+
},
|
36
|
+
"output": {
|
37
|
+
OUTPUT_SOURCE
|
38
|
+
}
|
39
|
+
},
|
40
|
+
"callbacks": [
|
41
|
+
"Jackal::Cfn::Resource",
|
42
|
+
"Jackal::Cfn::Event"
|
43
|
+
]
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
```
|
48
|
+
|
49
|
+
With this configuration in place resources and events will be received,
|
50
|
+
formatted, and delivered to the `OUTPUT_SOURCE`. It will be the job of
|
51
|
+
a later service to handle reply notifications (for resources) in this
|
52
|
+
style of usage.
|
53
|
+
|
54
|
+
### Message Reprocessing
|
55
|
+
|
56
|
+
When using the re-processing configuration, messages do not continue
|
57
|
+
down the pipeline. Instead, the original message is received, formatted,
|
58
|
+
and then re-delivered to the originating source (generally an SQS queue).
|
59
|
+
The message will be fetched again (this time properly formatted) and
|
60
|
+
any matching callbacks will be executed. A sample configuration may look
|
61
|
+
something like this:
|
62
|
+
|
63
|
+
```json
|
64
|
+
{
|
65
|
+
"jackal": {
|
66
|
+
"cfn": {
|
67
|
+
"config": {
|
68
|
+
"reprocess": true,
|
69
|
+
"ami": {
|
70
|
+
"credentials": {
|
71
|
+
CREDENTIALS
|
72
|
+
}
|
73
|
+
}
|
74
|
+
},
|
75
|
+
"sources": {
|
76
|
+
"input": {
|
77
|
+
"type": "sqs",
|
78
|
+
"args": {
|
79
|
+
SQS_CONFIG
|
80
|
+
}
|
81
|
+
},
|
82
|
+
"output": {
|
83
|
+
OUTPUT_SOURCE
|
84
|
+
}
|
85
|
+
},
|
86
|
+
"callbacks": [
|
87
|
+
"Jackal::Cfn::Resource",
|
88
|
+
"Jackal::Cfn::AmiRegister"
|
89
|
+
]
|
90
|
+
}
|
91
|
+
}
|
92
|
+
}
|
93
|
+
```
|
94
|
+
|
95
|
+
The important item to note is the `"reprocess": true` which enables the
|
96
|
+
automatic re-processing of messages.
|
97
|
+
|
98
|
+
## Custom Resources
|
99
|
+
|
100
|
+
This library provides support for creating new custom resources. Creation
|
101
|
+
is as simple as subclassing:
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
module Jackal
|
105
|
+
module Cfn
|
106
|
+
class LocalPrinter < Jackal::Cfn::Resource
|
107
|
+
|
108
|
+
def execute(message)
|
109
|
+
failure_wrap(message) do |payload|
|
110
|
+
cfn_resource = rekey_hash(payload.get(:data, :cfn_resource))
|
111
|
+
cfn_response = build_response(cfn_resource)
|
112
|
+
info "CFN Resource: #{cfn_resource.inspect}"
|
113
|
+
info "CFN Response: #{cfn_response.inspect}"
|
114
|
+
respond_to_stack(cfn_response, cfn_resource[:response_url])
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
```
|
122
|
+
|
123
|
+
This will match `Custom::LocalPrinter` resource requests that are received. It
|
124
|
+
will print information into the log about the request and then send a successful
|
125
|
+
response back to the stack.
|
126
|
+
|
127
|
+
### Builtin Custom Resources
|
128
|
+
|
129
|
+
This library provides a few custom resources builtin. These can be used directly or
|
130
|
+
as examples for building new custom resources.
|
131
|
+
|
132
|
+
#### `Jackal::Cfn::AmiRegister`
|
133
|
+
|
134
|
+
Generates and registers an AMI based on an EC2 resource. This allows for building a
|
135
|
+
single EC2 resource within a stack that is fully configured, creating and registering
|
136
|
+
an AMI based on that EC2 resource, and using the new AMI for instances created within
|
137
|
+
an ASG. It is an integrated way to speed up ASG instance launches, but keep all resources
|
138
|
+
for the stack fully managed.
|
139
|
+
|
140
|
+
Resource usage:
|
11
141
|
|
12
142
|
```json
|
143
|
+
{
|
144
|
+
"Type": "Custom::AmiRegister",
|
145
|
+
"Properties": {
|
146
|
+
"Parameters": {
|
147
|
+
"Name": String,
|
148
|
+
"InstanceId": String,
|
149
|
+
"Description": String,
|
150
|
+
"NoReboot": Boolean,
|
151
|
+
"BlockDeviceMappings": Array,
|
152
|
+
"HaltInstance": Boolean,
|
153
|
+
"Region": String
|
154
|
+
}
|
155
|
+
}
|
156
|
+
}
|
13
157
|
```
|
14
158
|
|
15
|
-
|
159
|
+
Resource Response:
|
160
|
+
|
161
|
+
```json
|
162
|
+
{
|
163
|
+
"AmiId": String
|
164
|
+
}
|
165
|
+
```
|
166
|
+
|
167
|
+
Configuration:
|
168
|
+
|
169
|
+
```json
|
170
|
+
{
|
171
|
+
"jackal": {
|
172
|
+
"cfn": {
|
173
|
+
"config": {
|
174
|
+
"ami": {
|
175
|
+
"credentials": {
|
176
|
+
"compute": {
|
177
|
+
FOG_CREDENTIALS
|
178
|
+
}
|
179
|
+
}
|
180
|
+
}
|
181
|
+
}
|
182
|
+
}
|
183
|
+
}
|
184
|
+
}
|
185
|
+
```
|
186
|
+
|
187
|
+
#### `Jackal::Cfn::AmiManager`
|
188
|
+
|
189
|
+
This resource is a simplification of the `AmiRegister` resource. The
|
190
|
+
`AmiManager` is used to ensure an AMI is removed from the system when
|
191
|
+
a stack is destroyed. This allows for customized AMI generation to be
|
192
|
+
integrated and ensure that once the stack is destroyed all custom AMIs
|
193
|
+
for that stack are destroyed as well.
|
194
|
+
|
195
|
+
Resource usage:
|
196
|
+
|
197
|
+
```json
|
198
|
+
{
|
199
|
+
"Type": "Custom::AmiManager",
|
200
|
+
"Properties": {
|
201
|
+
"Parameters": {
|
202
|
+
"AmiId": "",
|
203
|
+
"Region": ""
|
204
|
+
}
|
205
|
+
}
|
206
|
+
}
|
207
|
+
```
|
208
|
+
|
209
|
+
Resource Response:
|
210
|
+
|
211
|
+
```json
|
212
|
+
{
|
213
|
+
}
|
214
|
+
```
|
215
|
+
|
216
|
+
Configuration:
|
217
|
+
|
218
|
+
```json
|
219
|
+
{
|
220
|
+
"jackal": {
|
221
|
+
"cfn": {
|
222
|
+
"config": {
|
223
|
+
"ami": {
|
224
|
+
"credentials": {
|
225
|
+
"compute": {
|
226
|
+
FOG_CREDENTIALS
|
227
|
+
}
|
228
|
+
}
|
229
|
+
}
|
230
|
+
}
|
231
|
+
}
|
232
|
+
}
|
233
|
+
}
|
234
|
+
```
|
235
|
+
|
236
|
+
#### `Jackal::Cfn::HashExtractor`
|
237
|
+
|
238
|
+
This resource will extract a nested hash value from a JSON string. Useful
|
239
|
+
for when a result may be serialized JSON and a value from that structure
|
240
|
+
is required elsewhere.
|
241
|
+
|
242
|
+
Resource usage:
|
243
|
+
|
244
|
+
```json
|
245
|
+
{
|
246
|
+
"Type": "Custom::HashExtractor",
|
247
|
+
"Properties": {
|
248
|
+
"Parameters": {
|
249
|
+
"Key": "path.to.value.in.hash",
|
250
|
+
"Value": JSON
|
251
|
+
}
|
252
|
+
}
|
253
|
+
}
|
254
|
+
```
|
255
|
+
|
256
|
+
Resource Response:
|
257
|
+
|
258
|
+
```json
|
259
|
+
{
|
260
|
+
"Payload": VALUE
|
261
|
+
}
|
262
|
+
```
|
263
|
+
|
264
|
+
#### `Jackal::Cfn::JackalStack`
|
265
|
+
|
266
|
+
This resource provides an integration point for building stacks
|
267
|
+
on remote endpoints. Remote end points are provided via configuration
|
268
|
+
and referenced via the `Location` property in the custom resource.
|
269
|
+
|
270
|
+
Resource usage:
|
271
|
+
|
272
|
+
```json
|
273
|
+
{
|
274
|
+
"Type": "Custom::JackalStack",
|
275
|
+
"Properties": {
|
276
|
+
"Parameters": {
|
277
|
+
STACK_PARAMETERS
|
278
|
+
},
|
279
|
+
"Location": LOCATION,
|
280
|
+
"TemplateURL": URL
|
281
|
+
}
|
282
|
+
}
|
283
|
+
```
|
284
|
+
|
285
|
+
Resource Response:
|
286
|
+
|
287
|
+
The outputs of the stack will be proxied:
|
288
|
+
|
289
|
+
```json
|
290
|
+
{
|
291
|
+
"Outputs.OUTPUT_NAME": "OUTPUT_VALUE"
|
292
|
+
}
|
293
|
+
```
|
16
294
|
|
17
|
-
|
18
|
-
following structure:
|
295
|
+
Configuration:
|
19
296
|
|
20
297
|
```json
|
298
|
+
{
|
299
|
+
"jackal": {
|
300
|
+
"cfn": {
|
301
|
+
"config": {
|
302
|
+
"jackal_stack": {
|
303
|
+
"credentials": {
|
304
|
+
"storage": {
|
305
|
+
TEMPLATE_S3_CREDENTIALS
|
306
|
+
},
|
307
|
+
LOCATION: {
|
308
|
+
"provider": NAME,
|
309
|
+
MIASMA_CREDENTIALS
|
310
|
+
}
|
311
|
+
}
|
312
|
+
}
|
313
|
+
}
|
314
|
+
}
|
315
|
+
}
|
316
|
+
}
|
21
317
|
```
|
22
318
|
|
23
319
|
## Info
|
data/jackal-cfn.gemspec
CHANGED
@@ -11,6 +11,7 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.require_path = 'lib'
|
12
12
|
s.license = 'Apache 2.0'
|
13
13
|
s.add_dependency 'jackal'
|
14
|
+
s.add_dependency 'miasma'
|
14
15
|
s.add_dependency 'patron'
|
15
16
|
s.files = Dir['lib/**/*'] + %w(jackal-cfn.gemspec README.md CHANGELOG.md CONTRIBUTING.md LICENSE)
|
16
17
|
end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
require 'jackal-cfn'
|
2
|
+
|
3
|
+
module Jackal
|
4
|
+
module Cfn
|
5
|
+
# Manage AMI Resources
|
6
|
+
#
|
7
|
+
# Expected resource:
|
8
|
+
# {
|
9
|
+
# "Type": "Custom::JackalStack",
|
10
|
+
# "Properties": {
|
11
|
+
# "Parameters": {
|
12
|
+
# STACK_PARAMETERS
|
13
|
+
# },
|
14
|
+
# "Location": LOCATION,
|
15
|
+
# "TemplateURL": "URL"
|
16
|
+
# }
|
17
|
+
# }
|
18
|
+
#
|
19
|
+
# Required configuration:
|
20
|
+
# {
|
21
|
+
# "config": {
|
22
|
+
# "jackal_stack": {
|
23
|
+
# "credentials": {
|
24
|
+
# "storage": {
|
25
|
+
# AWS_CREDENTIALS
|
26
|
+
# },
|
27
|
+
# LOCATION: {
|
28
|
+
# "provider": "NAME",
|
29
|
+
# MIAMSA_CREDENTIALS
|
30
|
+
# }
|
31
|
+
# }
|
32
|
+
# }
|
33
|
+
# }
|
34
|
+
# }
|
35
|
+
class JackalStack < Jackal::Cfn::Resource
|
36
|
+
|
37
|
+
# Load miasma for stack building
|
38
|
+
def setup(*_)
|
39
|
+
require 'miasma'
|
40
|
+
end
|
41
|
+
|
42
|
+
# Perform requested stack action
|
43
|
+
#
|
44
|
+
# @param message [Carnivore::Message]
|
45
|
+
def execute(message)
|
46
|
+
failure_wrap(message) do |payload|
|
47
|
+
cfn_resource = rekey_hash(payload.get(:data, :cfn_resource))
|
48
|
+
properties = rekey_hash(cfn_resource[:resource_properties])
|
49
|
+
parameters = rekey_hash(properties[:parameters])
|
50
|
+
cfn_response = build_response(cfn_resource)
|
51
|
+
case cfn_resource[:request_type].to_sym
|
52
|
+
when :create
|
53
|
+
create_stack(cfn_response, cfn_resource, properties, parameters, message)
|
54
|
+
when :update
|
55
|
+
update_stack(cfn_response, cfn_resource, properties, parameters, message)
|
56
|
+
when :delete
|
57
|
+
destroy_stack(cfn_response, cfn_resource, message)
|
58
|
+
else
|
59
|
+
error "Unknown request type received: #{cfn_resource[:request_type].inspect}"
|
60
|
+
cfn_response['Status'] = 'FAILED'
|
61
|
+
cfn_response['Reason'] = 'Unknown request type received'
|
62
|
+
end
|
63
|
+
respond_to_stack(cfn_response, cfn_resource[:response_url])
|
64
|
+
job_completed(:jackal_cfn, payload, message)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Build API connection to base template storage bucket
|
69
|
+
#
|
70
|
+
# @param bucket_region [String] location of bucket
|
71
|
+
# @return [Miasma::Models::Storage]
|
72
|
+
def storage_api(bucket_region)
|
73
|
+
Miasma.api(
|
74
|
+
:type => :storage,
|
75
|
+
:provider => :aws,
|
76
|
+
:credentials => config.get(:jackal_stack, :credentials, :storage).merge(
|
77
|
+
:aws_bucket_region => bucket_region
|
78
|
+
)
|
79
|
+
)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Build orchestration API connection for provided location
|
83
|
+
#
|
84
|
+
# @param location [String, Symbol]
|
85
|
+
# @return [Miasma::Models::Orchestration]
|
86
|
+
def remote_api(location)
|
87
|
+
l_config = config.get(:jackal_stack, :credentials, location)
|
88
|
+
if(l_config)
|
89
|
+
Miasma.api(
|
90
|
+
:type => :orchestration,
|
91
|
+
:provider => l_config[:provider],
|
92
|
+
:credentials => l_config
|
93
|
+
)
|
94
|
+
else
|
95
|
+
raise ArgumentError.new "Unknown target location provided `#{location}`!"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Fetch a template from a storage bucket
|
100
|
+
#
|
101
|
+
# @param endpoint [String] URL to template
|
102
|
+
# @return [Hash] loaded template data
|
103
|
+
def fetch_template(endpoint)
|
104
|
+
url = URI.parse(endpoint)
|
105
|
+
region = url.host.split('.').first.split('-', 2).last
|
106
|
+
if(region == 's3')
|
107
|
+
region = 'us-east-1'
|
108
|
+
end
|
109
|
+
bucket, path = url.path.sub('/', '').split('/', 2)
|
110
|
+
MultiJson.load(
|
111
|
+
storage_api(region).buckets.get(
|
112
|
+
bucket.sub('/', '')
|
113
|
+
).files.get(path).body.read
|
114
|
+
)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Create a new stack and update the response values
|
118
|
+
#
|
119
|
+
# @param response [Hash] response data of action
|
120
|
+
# @param resource [Hash] request resource
|
121
|
+
# @param properties [Hash] properties of request resource
|
122
|
+
# @param parameters [Hash] parmeters provided via properties
|
123
|
+
# @param message [Carnivore::Message] original message
|
124
|
+
# @return [TrueClass, FalseClass]
|
125
|
+
def create_stack(response, resource, properties, parameters, message)
|
126
|
+
stack = remote_api(properties[:location]).stacks.build(
|
127
|
+
:name => [
|
128
|
+
'JackalStack',
|
129
|
+
resource[:logical_resource_id],
|
130
|
+
resource[:stack_id].split('/').last
|
131
|
+
].join('-'),
|
132
|
+
:template => properties.fetch(:stack, fetch_template(properties[:template_url])),
|
133
|
+
:parameters => Hash[parameters.map{|k,v| [Bogo::Utility.camel(k), v] }]
|
134
|
+
)
|
135
|
+
stack.save
|
136
|
+
until(stack.state.to_s.end_with?('complete'))
|
137
|
+
message.touch!
|
138
|
+
debug "Waiting for created stack to reach completion..."
|
139
|
+
sleep 5
|
140
|
+
stack.reload
|
141
|
+
end
|
142
|
+
if(stack.state.to_s.end_with?('complete') || stack.state.to_s.end_with?('failed'))
|
143
|
+
stack.outputs.each do |output|
|
144
|
+
response['Data']["Outputs.#{output.key}"] = output.value
|
145
|
+
end
|
146
|
+
response['PhysicalResourceId'] = "#{properties[:location]}-#{stack.id}"
|
147
|
+
true
|
148
|
+
else
|
149
|
+
response['Status'] = 'FAILED'
|
150
|
+
response['Reason'] = 'Stack creation failed!'
|
151
|
+
stack.destroy
|
152
|
+
false
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Update an existing stack and update the response values
|
157
|
+
#
|
158
|
+
# @param response [Hash] response data of action
|
159
|
+
# @param resource [Hash] request resource
|
160
|
+
# @param properties [Hash] properties of request resource
|
161
|
+
# @param parameters [Hash] parmeters provided via properties
|
162
|
+
# @param message [Carnivore::Message] original message
|
163
|
+
# @return [TrueClass, FalseClass]
|
164
|
+
def update_stack(response, resource, properties, parameters, message)
|
165
|
+
c_location, stack_id = resource[:physical_resource_id].split('-', 2)
|
166
|
+
if(c_location != properties[:location])
|
167
|
+
warn "Stack resource has changed location! #{c_location} -> #{properties[:location]}"
|
168
|
+
warn "Starting destruction of existing resource: #{stack_id}"
|
169
|
+
if(destroy_stack(response, resource, message))
|
170
|
+
info "Destruction of stack `#{stack_id}` complete. Creating replacement stack."
|
171
|
+
create_stack(response, resource, properties, parameters, message)
|
172
|
+
else
|
173
|
+
error "Failed to destroy existing stack for replacement `#{stack_id}`"
|
174
|
+
end
|
175
|
+
else
|
176
|
+
stack = remote_api(c_location).stacks.get(stack_id)
|
177
|
+
if(stack)
|
178
|
+
info "Stack resource update on: #{stack_id}"
|
179
|
+
stack.template = fetch_template(properties['TemplateURL'])
|
180
|
+
stack.parameters = Hash[parameters.map{|k,v| [Bogo::Utility.camel(k), v] }]
|
181
|
+
stack.save
|
182
|
+
until(stack.state.to_s.end_with?('complete') || stack.state.to_s.end_with?('failed'))
|
183
|
+
debug "Waiting for created stack to reach completion..."
|
184
|
+
sleep 5
|
185
|
+
stack.reload
|
186
|
+
end
|
187
|
+
if(stack.state.to_s.end_with?('complete'))
|
188
|
+
stack.outputs.each do |output|
|
189
|
+
response['Data']["Outputs.#{output.key}"] = output.value
|
190
|
+
end
|
191
|
+
response['PhysicalResourceId'] = stack.id
|
192
|
+
else
|
193
|
+
response['Status'] = 'FAILED'
|
194
|
+
response['Reason'] = 'Stack update failed!'
|
195
|
+
end
|
196
|
+
else
|
197
|
+
response['Status'] = 'FAILED'
|
198
|
+
response['Reason'] = "No stack was found matching request: #{stack_id}"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# Destroy the stack
|
204
|
+
#
|
205
|
+
# @param response [Hash] response data of action
|
206
|
+
# @param resource [Hash] request resource
|
207
|
+
# @param message [Carnivore::Message] original message
|
208
|
+
def destroy_stack(response, resource, message)
|
209
|
+
stack = request_destroy(resource[:physical_resource_id])
|
210
|
+
if(stack)
|
211
|
+
until(stack.state.nil? || stack.state.to_s.end_with?('complete') || stack.state.to_s.end_with?('failed'))
|
212
|
+
info "Waiting for stack destruction (#{stack.name})..."
|
213
|
+
message.touch!
|
214
|
+
sleep 5
|
215
|
+
stack.reload
|
216
|
+
end
|
217
|
+
if(stack.state.to_s.end_with?('failed'))
|
218
|
+
response['Status'] = 'FAILED'
|
219
|
+
response['Reason'] = 'Failed to delete remote stack!'
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
# Send a stack delete request
|
225
|
+
#
|
226
|
+
# @param stack_resource_id [String] physical resource ID
|
227
|
+
# @return [Miasma::Models::Orchestration::Stack, FalseClass]
|
228
|
+
def request_destroy(stack_resource_id)
|
229
|
+
location, stack_id = stack_resource_id.split('-', 2)
|
230
|
+
if(stack_id)
|
231
|
+
begin
|
232
|
+
info "Sending stack destruction request to: #{stack_id} in: #{location}"
|
233
|
+
stack = remote_api(location).stacks.get(stack_id)
|
234
|
+
stack.destroy
|
235
|
+
stack
|
236
|
+
rescue => e
|
237
|
+
error "Stack destruction request failed! #{e.class}: #{e.message}"
|
238
|
+
false
|
239
|
+
end
|
240
|
+
else
|
241
|
+
warn "No stack ID registered in resource. Skipping destroy: #{stack_resource_id}"
|
242
|
+
false
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
data/lib/jackal-cfn/resource.rb
CHANGED
@@ -175,12 +175,12 @@ module Jackal
|
|
175
175
|
payload = unpack(message)
|
176
176
|
yield payload
|
177
177
|
rescue => e
|
178
|
-
error "Unexpected error encountered processing custom resource - #{e.class}: #{e}"
|
178
|
+
error "Unexpected error encountered processing custom resource - #{e.class}: #{e.message}"
|
179
179
|
debug "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
|
180
180
|
cfn_resource = payload.get(:data, :cfn_resource)
|
181
181
|
cfn_response = build_response(cfn_resource)
|
182
182
|
cfn_response['Status'] = 'FAILED'
|
183
|
-
cfn_response['Reason'] = "Unexpected error encountered [#{e}]"
|
183
|
+
cfn_response['Reason'] = "Unexpected error encountered [#{e.message}]"
|
184
184
|
respond_to_stack(cfn_response, cfn_resource[:response_url])
|
185
185
|
message.confirm!
|
186
186
|
end
|
data/lib/jackal-cfn/utils.rb
CHANGED
@@ -13,7 +13,7 @@ module Jackal
|
|
13
13
|
# @return [Hash] new hash with snake cased toplevel keys
|
14
14
|
def transform_parameters(params)
|
15
15
|
Smash.new.tap do |new_hash|
|
16
|
-
params.each do |key, value|
|
16
|
+
(params || []).each do |key, value|
|
17
17
|
new_hash[snakecase(key)] = value
|
18
18
|
end
|
19
19
|
end
|
data/lib/jackal-cfn/version.rb
CHANGED
data/lib/jackal-cfn.rb
CHANGED
@@ -12,5 +12,6 @@ module Jackal
|
|
12
12
|
autoload :HashExtractor, 'jackal-cfn/resource/hash_extractor'
|
13
13
|
autoload :AmiManager, 'jackal-cfn/resource/ami_manager'
|
14
14
|
autoload :AmiRegister, 'jackal-cfn/resource/ami_register'
|
15
|
+
autoload :JackalStack, 'jackal-cfn/resource/jackal_stack'
|
15
16
|
end
|
16
17
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jackal-cfn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Roberts
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-08
|
11
|
+
date: 2015-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jackal
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: miasma
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: patron
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,6 +70,7 @@ files:
|
|
56
70
|
- lib/jackal-cfn/resource/ami_manager.rb
|
57
71
|
- lib/jackal-cfn/resource/ami_register.rb
|
58
72
|
- lib/jackal-cfn/resource/hash_extractor.rb
|
73
|
+
- lib/jackal-cfn/resource/jackal_stack.rb
|
59
74
|
- lib/jackal-cfn/utils.rb
|
60
75
|
- lib/jackal-cfn/utils/fog.rb
|
61
76
|
- lib/jackal-cfn/utils/http.rb
|