cfn_response 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +62 -18
- data/lib/cfn_response.rb +33 -16
- data/lib/cfn_response/version.rb +1 -1
- data/spec/cfn_response_spec.rb +11 -4
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f02c2b2c1e2f9496d23609923e4f05fb727f2b0f220641799f54ea619cc2503
|
4
|
+
data.tar.gz: ead5ce51b9ef94bc75b7ecff70f3b85fa191d5fc40999347c9c480a75cbd1363
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a635427683777b6bfe9dc1f90bb74615e3cee9773e95b4f3be3ee87c8d01387caacb5705fe82c1440c406d5d7fa52d686b569df381fa2146bcb40d3430140441
|
7
|
+
data.tar.gz: c2ea1e73f2b2279000eaaa371a1a798ae1024d5a611a13415f67db4b234bafc392d0f8df6ad912a80ae9a3690f89a7406661a9c09101ba29511ab760a637ecbe
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# Change Log
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
This project *loosely tries* to adhere to [Semantic Versioning](http://semver.org/).
|
5
|
+
|
6
|
+
## [0.2.0] - 2021-01-06
|
7
|
+
- [#1](https://github.com/tongueroo/cfn_response/pull/1) improve interface with response method
|
8
|
+
- improve interface: response method and auto send success to cloudformation
|
9
|
+
|
10
|
+
## [0.1.0]
|
11
|
+
- Initial release
|
data/README.md
CHANGED
@@ -6,7 +6,49 @@ CfnResponse helps with writing [Custom CloudFormation resources](https://docs.aw
|
|
6
6
|
|
7
7
|
## Usage
|
8
8
|
|
9
|
-
The block form with the `
|
9
|
+
The block form with the `response` method will ensure a SUCCESS or FAILED status is sent to CloudFormation regardless. If there's an Exception in the code, FAILED status is automatically sent. Otherwise an implicit SUCCESS status is sent.
|
10
|
+
|
11
|
+
This prevents us from waiting for over an hour for the stack operation to timeout and rollback. A `sleep 10` is also called at the end to provide enough time for the Lambda function to send logs to CloudWatch.
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
require "cfn_response"
|
15
|
+
require "json"
|
16
|
+
|
17
|
+
def lambda_handler(event:, context:)
|
18
|
+
puts "event: #{JSON.pretty_generate(event)}"
|
19
|
+
cfn = CfnResponse.new(event, context)
|
20
|
+
|
21
|
+
# will call cfn.fail on Exceptions so CloudFormation can continue
|
22
|
+
cfn.response do
|
23
|
+
case event['RequestType']
|
24
|
+
when "Create", "Update"
|
25
|
+
# create or update logic
|
26
|
+
when "Delete"
|
27
|
+
# delete logic
|
28
|
+
end
|
29
|
+
# Note: cfn.success doesnt need to be called because it is called implicitly at the end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
If you always want to return a success, here's the simpliest form:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
require "cfn_response"
|
38
|
+
require "json"
|
39
|
+
|
40
|
+
def lambda_handler(event:, context:)
|
41
|
+
puts "event: #{JSON.pretty_generate(event)}"
|
42
|
+
cfn = CfnResponse.new(event, context)
|
43
|
+
cfn.response
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
Reminder, `cfn.success` or `cfn.fail` is not called explicitly, a `cfn.success` is automatically called.
|
48
|
+
|
49
|
+
### Calling success or fail explicitly
|
50
|
+
|
51
|
+
You can also call `cfn.success` or `cfn.fail explicitly`, doing so gives you the ability to pass custom `Data`.
|
10
52
|
|
11
53
|
```ruby
|
12
54
|
require "cfn_response"
|
@@ -14,26 +56,28 @@ require "json"
|
|
14
56
|
|
15
57
|
def lambda_handler(event:, context:)
|
16
58
|
puts "event: #{JSON.pretty_generate(event)}"
|
17
|
-
|
59
|
+
cfn = CfnResponse.new(event, context)
|
18
60
|
|
19
|
-
# will call
|
20
|
-
|
61
|
+
# will call cfn.fail on Exceptions so CloudFormation can continue
|
62
|
+
cfn.response do
|
21
63
|
case event['RequestType']
|
22
64
|
when "Create", "Update"
|
23
65
|
# create or update logic
|
24
66
|
data = {a: 1, b: 2}
|
25
|
-
|
67
|
+
cfn.success(Data: data)
|
26
68
|
# or
|
27
|
-
#
|
69
|
+
# cfn.failed
|
28
70
|
when "Delete"
|
29
71
|
# delete logic
|
30
|
-
|
72
|
+
cfn.success # optional
|
31
73
|
end
|
32
74
|
end
|
33
75
|
end
|
34
76
|
```
|
35
77
|
|
36
|
-
|
78
|
+
### Non-block form
|
79
|
+
|
80
|
+
You can also call `success` and `failed` methods without wrapping the in a `response` block. Just remember to handle Exceptions. Example:
|
37
81
|
|
38
82
|
```ruby
|
39
83
|
require "cfn_response"
|
@@ -41,12 +85,12 @@ require "json"
|
|
41
85
|
|
42
86
|
def lambda_handler(event:, context:)
|
43
87
|
puts "event: #{JSON.pretty_generate(event)}"
|
44
|
-
|
88
|
+
cfn = CfnResponse.new(event, context)
|
45
89
|
|
46
90
|
data = {a: 1, b: 2}
|
47
|
-
|
91
|
+
cfn.success(Data: data)
|
48
92
|
# or
|
49
|
-
#
|
93
|
+
# cfn.failed
|
50
94
|
|
51
95
|
sleep 10 # a little time for logs to be sent to CloudWatch
|
52
96
|
# Rescue all exceptions and send FAIL to CloudFormation so we don't have to
|
@@ -55,7 +99,7 @@ rescue Exception => e
|
|
55
99
|
puts e.message
|
56
100
|
puts e.backtrace
|
57
101
|
sleep 10 # a little time for logs to be sent to CloudWatch
|
58
|
-
|
102
|
+
cfn.failed
|
59
103
|
end
|
60
104
|
```
|
61
105
|
|
@@ -66,8 +110,8 @@ Ultimately, CloudFormation expects a JSON body to be sent to it with these possi
|
|
66
110
|
The `success` and `failed` methods accept a Hash which is simply merged down to the final JSON body that is sent to CloudFormation. Most of the fields are prefilled conveniently by this library. You may want to pass some values. Example:
|
67
111
|
|
68
112
|
```ruby
|
69
|
-
|
70
|
-
|
113
|
+
cfn = CfnResponse.new(event, context)
|
114
|
+
cfn.success(Data: {a: 1, b: 2}, NoEcho: true)
|
71
115
|
```
|
72
116
|
|
73
117
|
### PhysicalResourceId
|
@@ -75,16 +119,16 @@ resp.success(Data: {a: 1, b: 2}, NoEcho: true)
|
|
75
119
|
The default PhysicalResourceId is `PhysicalResourceId`. If your logic calls for a new physical resource and you want to tell CloudFormation to replace the resource. Then you can provide a value with the symbol `:new_id` and the library will add a counter value to end of the current physical id.
|
76
120
|
|
77
121
|
```ruby
|
78
|
-
|
79
|
-
|
122
|
+
cfn = CfnResponse.new(event, context)
|
123
|
+
cfn.success(PhysicalResourceId: :new_id)
|
80
124
|
# PhysicalResourceId => PhysicalResourceId1 => PhysicalResourceId2 => etc
|
81
125
|
```
|
82
126
|
|
83
127
|
Or you replace it with your own unique physical resource id value of course.
|
84
128
|
|
85
129
|
```ruby
|
86
|
-
|
87
|
-
|
130
|
+
cfn = CfnResponse.new(event, context)
|
131
|
+
cfn.success(PhysicalResourceId: "MyId")
|
88
132
|
```
|
89
133
|
|
90
134
|
## Installation
|
data/lib/cfn_response.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "cfn_response/version"
|
2
|
+
require "json"
|
2
3
|
|
3
4
|
class CfnResponse
|
4
5
|
autoload :Base, "cfn_response/base"
|
@@ -11,36 +12,52 @@ class CfnResponse
|
|
11
12
|
@event, @context = event, context
|
12
13
|
end
|
13
14
|
|
14
|
-
def
|
15
|
+
def response
|
16
|
+
show_event if show_event?
|
17
|
+
result = yield if block_given?
|
18
|
+
success unless @finished
|
19
|
+
pause_for_cloudwatch
|
20
|
+
result
|
21
|
+
rescue Exception => e
|
22
|
+
puts "ERROR #{e.message}"
|
23
|
+
puts "BACKTRACE:\n#{e.backtrace.join("\n")}"
|
24
|
+
pause_for_cloudwatch
|
25
|
+
failed
|
26
|
+
end
|
27
|
+
alias_method :respond, :response
|
28
|
+
|
29
|
+
def show_event?
|
30
|
+
ENV['CFN_RESPONSE_VERBOSE'].nil? ? true : ENV['CFN_RESPONSE_VERBOSE'] == '1'
|
31
|
+
end
|
32
|
+
|
33
|
+
def show_event
|
34
|
+
puts("event['RequestType'] #{@event['RequestType']}")
|
35
|
+
puts("event: #{JSON.dump(@event)}")
|
36
|
+
puts("context: #{JSON.dump(@context)}")
|
37
|
+
puts("context.log_stream_name #{@context.log_stream_name.inspect}")
|
38
|
+
end
|
39
|
+
|
40
|
+
def send_to_cloudformation(input={})
|
15
41
|
builder = Builder.new(@event, @context)
|
16
42
|
response_data = builder.call(input)
|
17
43
|
sender = Sender.new(@event, @context)
|
18
|
-
sender.call(response_data)
|
44
|
+
result = sender.call(response_data) unless ENV['CFN_RESPONSE_SEND'] == '0'
|
45
|
+
@finished = true
|
46
|
+
result
|
19
47
|
end
|
20
48
|
|
21
49
|
def success(input={})
|
22
50
|
input[:Status] = "SUCCESS"
|
23
|
-
|
51
|
+
send_to_cloudformation(input)
|
24
52
|
end
|
25
53
|
|
26
54
|
def failed(input={})
|
27
55
|
input[:Status] = "FAILED"
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
def safely
|
32
|
-
result = yield
|
33
|
-
pause_for_cloudwatch
|
34
|
-
result
|
35
|
-
rescue Exception => e
|
36
|
-
puts "ERROR #{e.message}"
|
37
|
-
puts "BACKTRACE:\n#{e.backtrace.join("\n")}"
|
38
|
-
pause_for_cloudwatch
|
39
|
-
failed
|
56
|
+
send_to_cloudformation(input)
|
40
57
|
end
|
41
58
|
|
42
59
|
def pause_for_cloudwatch
|
43
|
-
return if ENV['CFN_RESPONSE_TEST']
|
60
|
+
return if ENV['CFN_RESPONSE_TEST'] || ENV['CFN_RESPONSE_SEND']
|
44
61
|
sleep 10 # a little time for logs to be sent to CloudWatch
|
45
62
|
end
|
46
63
|
end
|
data/lib/cfn_response/version.rb
CHANGED
data/spec/cfn_response_spec.rb
CHANGED
@@ -22,13 +22,20 @@ RSpec.describe CfnResponse do
|
|
22
22
|
expect(resp.to_s).to eq(null.to_s) # due to stub
|
23
23
|
end
|
24
24
|
|
25
|
-
it "
|
26
|
-
resp = subject.
|
25
|
+
it "send_to_cloudformation" do
|
26
|
+
resp = subject.send_to_cloudformation
|
27
27
|
expect(resp.to_s).to eq(null.to_s) # due to stub
|
28
28
|
end
|
29
29
|
|
30
|
-
it "
|
31
|
-
resp = subject.
|
30
|
+
it "response" do
|
31
|
+
resp = subject.response do
|
32
|
+
subject.success
|
33
|
+
end
|
34
|
+
expect(resp.to_s).to eq(null.to_s) # due to stub
|
35
|
+
end
|
36
|
+
|
37
|
+
it "respond" do
|
38
|
+
resp = subject.respond do
|
32
39
|
subject.success
|
33
40
|
end
|
34
41
|
expect(resp.to_s).to eq(null.to_s) # due to stub
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cfn_response
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tung Nguyen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-06 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -19,6 +19,7 @@ extra_rdoc_files: []
|
|
19
19
|
files:
|
20
20
|
- ".gitignore"
|
21
21
|
- ".rspec"
|
22
|
+
- CHANGELOG.md
|
22
23
|
- Gemfile
|
23
24
|
- LICENSE.txt
|
24
25
|
- README.md
|
@@ -62,7 +63,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
62
63
|
- !ruby/object:Gem::Version
|
63
64
|
version: '0'
|
64
65
|
requirements: []
|
65
|
-
rubygems_version: 3.1.
|
66
|
+
rubygems_version: 3.1.4
|
66
67
|
signing_key:
|
67
68
|
specification_version: 4
|
68
69
|
summary: CfnResponse makes it easier to build and send the CloudFormation Custom Resource
|