jets 3.2.1 → 3.2.2
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 12689dd61b554f0b5a049ee578cf14566593788a3a2ebb7353ea26a5f7bd803c
|
4
|
+
data.tar.gz: c54ebb36356ac71a8e9d211eb9187e761eba9aca2c650abd50e55ffdbf14f6d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9834c8acaa032e002820e7ba7855f62f318160942287e2c1d23b31f4746d62cbb92253c97097bc94ca6d463044b95d7ef97f5030c6c8105682155ec6d568941d
|
7
|
+
data.tar.gz: 707f58aae8c4b8730db0a6e160830eea8a45fc840300a1f1e2a79ffb656118774446e24f1b91722e974bd0f5126a1b755c68eaea6147a8403d2aad76cfc4e697
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,9 @@
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
This project *loosely tries* to adhere to [Semantic Versioning](http://semver.org/).
|
5
5
|
|
6
|
+
## [3.2.2] - 2023-05-19
|
7
|
+
- [#640](https://github.com/boltops-tools/jets/pull/640) Base path mapping CloudFormation custom resource and lambda function hardening
|
8
|
+
|
6
9
|
## [3.2.1] - 2023-05-03
|
7
10
|
- [#637](https://github.com/boltops-tools/jets/pull/637) Readme: Replace "splat out" with "had" a baby
|
8
11
|
- [#638](https://github.com/boltops-tools/jets/pull/638) feature: update an array of reserved variables in aws lambda
|
@@ -1,13 +1,49 @@
|
|
1
|
-
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
# When require bundler/setup fails, AWS Lambda won't be able to load base_path_mapping
|
4
|
+
# So we'll require base_path_mapping within begin/rescue block so that it does not also
|
5
|
+
# fail the entire lambda function.
|
6
|
+
require 'jets/internal/app/functions/jets/base_path_mapping'
|
7
|
+
rescue Exception => e
|
8
|
+
# Note: rescue LoadError is not enough in AWS Lambda environment
|
9
|
+
# Actual exceptions:
|
10
|
+
# require bundler/setup: Ruby exception "Bundler::GemNotFound"
|
11
|
+
# require base_path_mappnig: AWS Lambda reported error "errorType": "Init<LoadError>"
|
12
|
+
# Will use a generic rescue Exception though in case error changes in the future.
|
13
|
+
puts "WARN: #{e.class} #{e.message}"
|
14
|
+
puts <<~EOL
|
15
|
+
Could not require bundler/setup.
|
16
|
+
This can happen for weird timeout missing error. Example:
|
17
|
+
|
18
|
+
Could not find timeout-0.3.2 in locally installed gems
|
19
|
+
|
20
|
+
Happens when the gem command is out-of-date on old versions of ruby 2.7.
|
21
|
+
See: https://community.boltops.com/t/could-not-find-timeout-0-3-1-in-any-of-the-sources/996
|
22
|
+
EOL
|
23
|
+
end
|
2
24
|
require 'cfn_response'
|
3
|
-
require 'jets/internal/app/functions/jets/base_path_mapping'
|
4
25
|
|
5
26
|
STAGE_NAME = "<%= @stage_name %>"
|
6
27
|
|
7
28
|
def lambda_handler(event:, context:)
|
8
29
|
cfn = CfnResponse.new(event, context)
|
9
30
|
cfn.response do
|
10
|
-
mapping
|
31
|
+
# Super edge case: mapping is nil when require bundler/setup fails
|
32
|
+
begin
|
33
|
+
mapping = BasePathMapping.new(event, STAGE_NAME)
|
34
|
+
rescue NameError => e
|
35
|
+
puts "ERROR: #{e.class} #{e.message}"
|
36
|
+
puts error_message
|
37
|
+
end
|
38
|
+
|
39
|
+
# This is the "second pass" of CloudFormation when it tries to delete the BasePathMapping during rollback
|
40
|
+
if mapping.nil? && event['RequestType'] == "Delete"
|
41
|
+
cfn.success # so that CloudFormation can continue the delete process from a rollback
|
42
|
+
delay
|
43
|
+
return
|
44
|
+
end
|
45
|
+
|
46
|
+
# Normal behavior when mapping is not nil when bundler/setup loads successfully
|
11
47
|
case event['RequestType']
|
12
48
|
when "Create", "Update"
|
13
49
|
mapping.update
|
@@ -16,3 +52,57 @@ def lambda_handler(event:, context:)
|
|
16
52
|
end
|
17
53
|
end
|
18
54
|
end
|
55
|
+
|
56
|
+
def delay
|
57
|
+
puts "Delaying 60 seconds to allow user some time to see lambda function logs."
|
58
|
+
60.times do
|
59
|
+
puts Time.now
|
60
|
+
sleep 1
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def error_message
|
65
|
+
<<~EOL
|
66
|
+
This is ultimately the result of require bundler/setup failing to load.
|
67
|
+
On the CloudFormation first pass, the BasePathMapping fails to CREATE.
|
68
|
+
CloudFormation does a rollback and tries to delete the BasePathMapping.
|
69
|
+
|
70
|
+
Jets will send a success response to CloudFormation so it can continue and delete
|
71
|
+
BasePathMapping on the rollback. Otherwise, CloudFormation ends up in the terminal
|
72
|
+
UPDATE_FAILED state and the CloudFormation console provides 3 options:
|
73
|
+
|
74
|
+
1) retry 2) update 3) rollback.
|
75
|
+
|
76
|
+
The only option that seems to work is rollback to get it out of UPDATE_FAILED to
|
77
|
+
UPDATE_ROLLBACK_COMPLETE. But then, if we `jets deploy` again without fixing the
|
78
|
+
require bundler/setup issue, we'll end back up in the UPDATE_FAILED state.
|
79
|
+
|
80
|
+
Will handle this error so we can continue the stack because we do not want it to fail
|
81
|
+
and never be able to send the CfnResponse. Then we have to wait hours for a CloudFormation timeout.
|
82
|
+
Sometimes deleting the APP-dev-ApiDeployment20230518230443-EXAMPLEY8YQP0 stack
|
83
|
+
allows the cloudformation stacks to continue, but usually, it'll only just slightly speed up the rollback.
|
84
|
+
|
85
|
+
Some examples of actual rollback times:
|
86
|
+
|
87
|
+
When left alone, the rollback takes about 2.5 hours.
|
88
|
+
|
89
|
+
2023-05-19 05:39:25 User Initiated
|
90
|
+
2023-05-19 08:01:48 UPDATE_ROLLBACK_COMPLETE
|
91
|
+
|
92
|
+
When deleting the APP-dev-ApiDeployment20230518230443-EXAMPLEY8YQP0 stack, it takes about 1.5 hours.
|
93
|
+
|
94
|
+
2023-05-19 06:25:41 User Initiated
|
95
|
+
2023-05-19 07:47:03 UPDATE_ROLLBACK_COMPLETE
|
96
|
+
|
97
|
+
Rescuing and handling the error here allows the CloudFormation stack to continue and finish the rollback process.
|
98
|
+
It takes the rollback time down to about 3 minutes. Example:
|
99
|
+
|
100
|
+
2023-05-19 16:34:19 User Initiated
|
101
|
+
2023-05-19 16:37:34 UPDATE_ROLLBACK_COMPLETE
|
102
|
+
|
103
|
+
Note: The first cloudformation CREATE pass sends FAILED Status to CloudFormation,
|
104
|
+
and the second cloudformation DELETE pass sends SUCCESS Status to CloudFormation.
|
105
|
+
|
106
|
+
Related: https://community.boltops.com/t/could-not-find-timeout-0-3-1-in-any-of-the-sources/996
|
107
|
+
EOL
|
108
|
+
end
|
@@ -28,8 +28,28 @@ class BasePathMapping
|
|
28
28
|
# Cannot use update_base_path_mapping to update the base_mapping because it doesnt
|
29
29
|
# allow us to change the rest_api_id. So we delete and create.
|
30
30
|
def update
|
31
|
-
|
32
|
-
|
31
|
+
puts "BasePathMapping update"
|
32
|
+
if rest_api_changed?
|
33
|
+
delete(true)
|
34
|
+
create
|
35
|
+
else
|
36
|
+
puts "BasePathMapping update: rest_api_id #{rest_api_id} did not change. Skipping."
|
37
|
+
end
|
38
|
+
|
39
|
+
puts "BasePathMapping update complete"
|
40
|
+
end
|
41
|
+
|
42
|
+
def rest_api_changed?
|
43
|
+
puts "BasePathMapping checking if rest_api_id changed"
|
44
|
+
mapping = current_base_path_mapping
|
45
|
+
return true unless mapping
|
46
|
+
mapping.rest_api_id != rest_api_id
|
47
|
+
end
|
48
|
+
|
49
|
+
def current_base_path_mapping
|
50
|
+
resp = apigateway.get_base_path_mapping(base_path: "(none)", domain_name: domain_name)
|
51
|
+
rescue Aws::APIGateway::Errors::NotFoundException
|
52
|
+
return nil
|
33
53
|
end
|
34
54
|
|
35
55
|
# Dont delete the newly created base path mapping unless this is an operation
|
@@ -39,10 +59,14 @@ class BasePathMapping
|
|
39
59
|
end
|
40
60
|
|
41
61
|
def delete(fail_silently=false)
|
42
|
-
|
62
|
+
puts "BasePathMapping delete"
|
63
|
+
options = {
|
43
64
|
domain_name: domain_name, # required
|
44
65
|
base_path: base_path.empty? ? '(none)' : base_path,
|
45
|
-
|
66
|
+
}
|
67
|
+
puts "BasePathMapping delete options #{options.inspect}"
|
68
|
+
apigateway.delete_base_path_mapping(options)
|
69
|
+
puts "BasePathMapping delete complete"
|
46
70
|
# https://github.com/tongueroo/jets/issues/255
|
47
71
|
# Used to return: Aws::APIGateway::Errors::NotFoundException
|
48
72
|
# Now returns: Aws::APIGateway::Errors::InternalFailure
|
@@ -52,12 +76,41 @@ class BasePathMapping
|
|
52
76
|
end
|
53
77
|
|
54
78
|
def create
|
55
|
-
|
79
|
+
puts "BasePathMapping create"
|
80
|
+
options = {
|
56
81
|
domain_name: domain_name, # required
|
57
82
|
base_path: base_path,
|
58
83
|
rest_api_id: rest_api_id, # required
|
59
84
|
stage: @stage_name,
|
60
|
-
|
85
|
+
}
|
86
|
+
puts "BasePathMapping create options #{options.inspect}"
|
87
|
+
apigateway.create_base_path_mapping(options)
|
88
|
+
puts "BasePathMapping create complete"
|
89
|
+
rescue Aws::APIGateway::Errors::ServiceError => e
|
90
|
+
puts "ERROR: #{e.class}: #{e.message}"
|
91
|
+
puts "BasePathMapping create failed"
|
92
|
+
if e.message.include?("Invalid domain name identifier specified")
|
93
|
+
puts <<~EOL
|
94
|
+
This super edge case error seems to happen when the cloudformation stack does a rollback
|
95
|
+
because the BasePathMapping custom resource fails. This has happened with a strange combination of
|
96
|
+
ruby 2.7 and the timeout gem not being picked up in the AWS Lambda runtime environment
|
97
|
+
Specifically, when jets deploy was used with a rubygems install that is out-of-date.
|
98
|
+
See: https://community.boltops.com/t/could-not-find-timeout-0-3-1-in-any-of-the-sources/996
|
99
|
+
|
100
|
+
The new base path mapping is not created correctly and the old base path mapping is not properly deleted.
|
101
|
+
The old ghost base mapping interferes with the new base path mapping.
|
102
|
+
The workaround solution seems to require removing all the config.domain settings and deploying again. Example:
|
103
|
+
|
104
|
+
config/application.rb
|
105
|
+
|
106
|
+
config.domain.cert_arn = "arn:aws:acm:us-west-2:111111111111:certificate/EXAMPLE1-a3de-4fe7-b72e-4cc153c5303e"
|
107
|
+
config.domain.hosted_zone_name = "example.com"
|
108
|
+
|
109
|
+
Comment out those settings, deploy, then uncomment and deploy again.
|
110
|
+
If there's a better workaround, please let us know.
|
111
|
+
EOL
|
112
|
+
end
|
113
|
+
raise(e)
|
61
114
|
end
|
62
115
|
|
63
116
|
def deployment_stack
|
@@ -110,3 +163,9 @@ class BasePathMapping
|
|
110
163
|
options
|
111
164
|
end
|
112
165
|
end
|
166
|
+
|
167
|
+
if __FILE__ == $0
|
168
|
+
event = JSON.load(File.read(ARGV[0]))
|
169
|
+
context = nil # stub out
|
170
|
+
BasePathMapping.new(event, context).update
|
171
|
+
end
|
data/lib/jets/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.2.
|
4
|
+
version: 3.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tung Nguyen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-05-
|
11
|
+
date: 2023-05-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionmailer
|
@@ -1103,7 +1103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1103
1103
|
- !ruby/object:Gem::Version
|
1104
1104
|
version: '0'
|
1105
1105
|
requirements: []
|
1106
|
-
rubygems_version: 3.4.
|
1106
|
+
rubygems_version: 3.4.13
|
1107
1107
|
signing_key:
|
1108
1108
|
specification_version: 4
|
1109
1109
|
summary: Ruby Serverless Framework
|