jets 1.5.8 → 1.5.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +4 -4
- data/jets.gemspec +5 -5
- data/lib/jets/builders/ruby_packager.rb +10 -5
- data/lib/jets/commands/deploy.rb +5 -1
- data/lib/jets/commands/upgrade.rb +14 -0
- data/lib/jets/preheat.rb +2 -2
- data/lib/jets/resource/api_gateway/rest_api/routes.rb +4 -120
- data/lib/jets/resource/api_gateway/rest_api/routes/base.rb +11 -0
- data/lib/jets/resource/api_gateway/rest_api/routes/change.rb +114 -0
- data/lib/jets/resource/api_gateway/rest_api/routes/collision.rb +119 -0
- data/lib/jets/resource/api_gateway/rest_api/routes/collision/variable_exception.rb +7 -0
- data/lib/jets/router.rb +8 -0
- data/lib/jets/version.rb +1 -1
- metadata +11 -8
- data/lib/jets/turbo/project/Gemfile.lock +0 -185
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 139636b38cc75e1677d5590c3ed58b2aa62615d8eb0ab2881e10617a7ecbcf42
|
4
|
+
data.tar.gz: e319b191d08ed15475f644c8348edac60e8a55c9e21f9b4aa8b3605a12fa6f10
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1dbcc0bf66eb73a9d2ff93b1ba95044d4026734beff95bf16ead0ff3f2c5d2461738cf3ff82fc0f116729024a4a7c4ffb49d5bf7babe6469be6145610ca55c8
|
7
|
+
data.tar.gz: 3f6987b22c59c6dfdd294cfd81ce1de23eec5e386ec7b82b91c698c9a6956874f479a5bb31274790b511953329eca208a98eab7a98b33b7483448229ddc772bd
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,15 @@
|
|
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/), even before v1.0.
|
5
5
|
|
6
|
+
## [1.5.9]
|
7
|
+
- #154 from tongueroo/variable-collision raise error on multiple sibling variable paths collision
|
8
|
+
- #156 from konnected-io/master: don't prewarm jobs, only prewarm controllers
|
9
|
+
- ensure remove BUNDLED WITH remove when no project Gemfile.lock and it gets created by build process
|
10
|
+
- jets upgrade: add dynomite to gemfile if needed
|
11
|
+
- only clean submodules for bundler version 2+
|
12
|
+
- turbo wrapper project: remove Gemfile.lock and let afterburner mode run on latest jets version
|
13
|
+
- use pessimistic version for dependencies
|
14
|
+
|
6
15
|
## [1.5.8]
|
7
16
|
- #155 remove BUNDLED WITH from Gemfile.lock to fix newly released bundler issue
|
8
17
|
|
data/Gemfile.lock
CHANGED
@@ -11,9 +11,9 @@ GIT
|
|
11
11
|
PATH
|
12
12
|
remote: .
|
13
13
|
specs:
|
14
|
-
jets (1.5.
|
15
|
-
activerecord (
|
16
|
-
activesupport (
|
14
|
+
jets (1.5.9)
|
15
|
+
activerecord (~> 5.2.1)
|
16
|
+
activesupport (~> 5.2.1)
|
17
17
|
aws-sdk-apigateway
|
18
18
|
aws-sdk-cloudformation
|
19
19
|
aws-sdk-cloudwatchlogs
|
@@ -32,7 +32,7 @@ PATH
|
|
32
32
|
memoist
|
33
33
|
mimemagic
|
34
34
|
rack
|
35
|
-
railties (
|
35
|
+
railties (~> 5.2.1)
|
36
36
|
recursive-open-struct
|
37
37
|
text-table
|
38
38
|
thor
|
data/jets.gemspec
CHANGED
@@ -27,10 +27,10 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
28
28
|
spec.require_paths = ["lib"]
|
29
29
|
|
30
|
-
# spec.add_dependency "actionpack", "
|
31
|
-
# spec.add_dependency "actionview", "
|
32
|
-
spec.add_dependency "activerecord", "
|
33
|
-
spec.add_dependency "activesupport", "
|
30
|
+
# spec.add_dependency "actionpack", "~> 5.2.1" # using vendor/rails version
|
31
|
+
# spec.add_dependency "actionview", "~> 5.2.1" # using vendor/rails version
|
32
|
+
spec.add_dependency "activerecord", "~> 5.2.1"
|
33
|
+
spec.add_dependency "activesupport", "~> 5.2.1"
|
34
34
|
spec.add_dependency "aws-sdk-apigateway"
|
35
35
|
spec.add_dependency "aws-sdk-cloudformation"
|
36
36
|
spec.add_dependency "aws-sdk-cloudwatchlogs"
|
@@ -49,7 +49,7 @@ Gem::Specification.new do |spec|
|
|
49
49
|
spec.add_dependency "memoist"
|
50
50
|
spec.add_dependency "mimemagic"
|
51
51
|
spec.add_dependency "rack"
|
52
|
-
spec.add_dependency "railties", "
|
52
|
+
spec.add_dependency "railties", "~> 5.2.1" # ActiveRecord database_tasks.rb require this
|
53
53
|
spec.add_dependency "recursive-open-struct"
|
54
54
|
spec.add_dependency "text-table"
|
55
55
|
spec.add_dependency "thor"
|
@@ -58,6 +58,8 @@ class Jets::Builders
|
|
58
58
|
)
|
59
59
|
end
|
60
60
|
|
61
|
+
remove_bundled_with("#{cache_area}/Gemfile.lock")
|
62
|
+
|
61
63
|
# Copy the Gemfile.lock back to the project in case it was updated.
|
62
64
|
# For example we add the jets-rails to the Gemfile.
|
63
65
|
copy_back_gemfile_lock
|
@@ -99,6 +101,8 @@ class Jets::Builders
|
|
99
101
|
lockfile = "#{cache_area}/Gemfile.lock"
|
100
102
|
return unless File.exist?(lockfile)
|
101
103
|
|
104
|
+
return if Bundler.bundler_major_version <= 1 # LockfileParser only works for Bundler version 2+
|
105
|
+
|
102
106
|
parser = Bundler::LockfileParser.new(Bundler.read_file(lockfile))
|
103
107
|
specs = parser.specs
|
104
108
|
|
@@ -131,20 +135,21 @@ class Jets::Builders
|
|
131
135
|
|
132
136
|
gemfile_lock = "#{full_project_path}/Gemfile.lock"
|
133
137
|
dest = "#{cache_area}/Gemfile.lock"
|
134
|
-
|
135
|
-
|
138
|
+
return unless File.exist?(gemfile_lock)
|
139
|
+
|
140
|
+
FileUtils.cp(gemfile_lock, dest)
|
136
141
|
end
|
137
142
|
|
138
143
|
# Remove the BUNDLED WITH line since we don't control the bundler gem version on AWS Lambda
|
139
144
|
# And this can cause issues with require 'bundler/setup'
|
140
|
-
def
|
141
|
-
lines = IO.readlines(
|
145
|
+
def remove_bundled_with(gemfile_lock)
|
146
|
+
lines = IO.readlines(gemfile_lock)
|
142
147
|
n = lines.index { |l| l.include?("BUNDLED WITH") }
|
143
148
|
return unless n
|
144
149
|
|
145
150
|
new_lines = lines[0..n-1]
|
146
151
|
content = new_lines.join('')
|
147
|
-
IO.write(
|
152
|
+
IO.write(gemfile_lock, content)
|
148
153
|
end
|
149
154
|
|
150
155
|
def setup_bundle_config
|
data/lib/jets/commands/deploy.rb
CHANGED
@@ -49,8 +49,12 @@ module Jets::Commands
|
|
49
49
|
Jets::Commands::Build.new(@options).build_code
|
50
50
|
end
|
51
51
|
|
52
|
-
# Checks that all routes are validate and have corresponding lambda functions
|
53
52
|
def validate_routes!
|
53
|
+
check_route_connected_functions
|
54
|
+
end
|
55
|
+
|
56
|
+
# Checks that all routes are validate and have corresponding lambda functions
|
57
|
+
def check_route_connected_functions
|
54
58
|
return if Jets::Router.all_routes_valid
|
55
59
|
|
56
60
|
puts "Deploy fail: The jets application contain invalid routes.".colorize(:red)
|
@@ -15,6 +15,7 @@ module Jets::Commands
|
|
15
15
|
update_config_ru
|
16
16
|
remove_ruby_lazy_load
|
17
17
|
update_webpack_binstubs
|
18
|
+
add_dynomite_to_gemfile
|
18
19
|
puts "Upgrade complete."
|
19
20
|
end
|
20
21
|
|
@@ -116,6 +117,19 @@ module Jets::Commands
|
|
116
117
|
puts "Updated webpack binstubs."
|
117
118
|
end
|
118
119
|
|
120
|
+
def add_dynomite_to_gemfile
|
121
|
+
return unless File.exist?("app/models/application_item.rb")
|
122
|
+
|
123
|
+
lines = IO.readlines("Gemfile")
|
124
|
+
dynomite_found = lines.detect { |l| l =~ /dynomite/ }
|
125
|
+
return if dynomite_found
|
126
|
+
|
127
|
+
File.open('Gemfile', 'a') do |f|
|
128
|
+
f.puts 'gem "dynomite"'
|
129
|
+
end
|
130
|
+
puts "Updated Gemfile: add dynomite gem"
|
131
|
+
end
|
132
|
+
|
119
133
|
private
|
120
134
|
def update_project_file(relative_path)
|
121
135
|
templates = File.expand_path("upgrade/templates", File.dirname(__FILE__))
|
data/lib/jets/preheat.rb
CHANGED
@@ -104,8 +104,8 @@ module Jets
|
|
104
104
|
|
105
105
|
def classes
|
106
106
|
Jets::Commands::Build.app_files.map do |path|
|
107
|
-
next if path.include?("preheat_job.rb") # dont want to cause an infinite loop
|
108
|
-
next
|
107
|
+
next if path.include?("preheat_job.rb") # dont want to cause an infinite loop, just in case
|
108
|
+
next unless path =~ %r{app/controllers} # only prewarm controllers
|
109
109
|
|
110
110
|
class_path = path.sub(%r{.*app/\w+/},'').sub(/\.rb$/,'')
|
111
111
|
class_name = class_path.classify
|
@@ -1,127 +1,11 @@
|
|
1
1
|
class Jets::Resource::ApiGateway::RestApi
|
2
2
|
class Routes
|
3
|
-
|
4
|
-
|
3
|
+
autoload :Base, 'jets/resource/api_gateway/rest_api/routes/base'
|
4
|
+
autoload :Change, 'jets/resource/api_gateway/rest_api/routes/change'
|
5
|
+
autoload :Collision, 'jets/resource/api_gateway/rest_api/routes/collision'
|
5
6
|
|
6
7
|
def self.changed?
|
7
|
-
new.changed?
|
8
|
+
Change.new.changed?
|
8
9
|
end
|
9
|
-
|
10
|
-
def changed?
|
11
|
-
deployed_routes = build
|
12
|
-
deployed_routes.each do |deployed_route|
|
13
|
-
new_route = find_comparable_route(deployed_route)
|
14
|
-
if new_route && new_route.to != deployed_route.to
|
15
|
-
# change in already deployed route has been detected, requires bluegreen deploy
|
16
|
-
return true
|
17
|
-
end
|
18
|
-
end
|
19
|
-
false # Reaching here means no routes have been changed in a way that requires a bluegreen deploy
|
20
|
-
end
|
21
|
-
|
22
|
-
# Build up deployed routes from the existing CloudFormation resources.
|
23
|
-
def build
|
24
|
-
routes = []
|
25
|
-
|
26
|
-
resources, position = [], true
|
27
|
-
while position
|
28
|
-
position = nil if position == true # start of loop
|
29
|
-
resp = apigateway.get_resources(
|
30
|
-
rest_api_id: rest_api_id,
|
31
|
-
position: position,
|
32
|
-
)
|
33
|
-
resources += resp.items
|
34
|
-
position = resp.position
|
35
|
-
end
|
36
|
-
|
37
|
-
resources.each do |resource|
|
38
|
-
resource_methods = resource.resource_methods
|
39
|
-
next if resource_methods.nil?
|
40
|
-
|
41
|
-
resource_methods.each do |http_verb, resource_method|
|
42
|
-
# puts "#{http_verb} #{resource.path} | resource.id #{resource.id}"
|
43
|
-
# puts to(resource.id, http_verb)
|
44
|
-
|
45
|
-
# Test changing config.cors and CloudFormation does an in-place update
|
46
|
-
# on the resource. So no need to do bluegreen deployments for OPTIONS.
|
47
|
-
next if http_verb == "OPTIONS"
|
48
|
-
|
49
|
-
path = recreate_path(resource.path)
|
50
|
-
method = http_verb.downcase.to_sym
|
51
|
-
to = to(resource.id, http_verb)
|
52
|
-
route = Jets::Route.new(path: path, method: method, to: to)
|
53
|
-
routes << route
|
54
|
-
end
|
55
|
-
end
|
56
|
-
routes
|
57
|
-
end
|
58
|
-
|
59
|
-
# Find a route that has the same path and method. This is a comparable route
|
60
|
-
# Then we will compare the to or controller action to see if an already
|
61
|
-
# deployed route has been changed.
|
62
|
-
def find_comparable_route(deployed_route)
|
63
|
-
new_routes.find do |new_route|
|
64
|
-
new_route.path == deployed_route.path &&
|
65
|
-
new_route.method == deployed_route.method
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def new_routes
|
70
|
-
Jets::Router.routes
|
71
|
-
end
|
72
|
-
memoize :new_routes
|
73
|
-
|
74
|
-
def recreate_path(path)
|
75
|
-
path = path.gsub(%r{^/},'')
|
76
|
-
path = path.sub(/{(.*)\+}/, '*\1')
|
77
|
-
path.sub(/{(.*)}/, ':\1')
|
78
|
-
end
|
79
|
-
|
80
|
-
def to(resource_id, http_method)
|
81
|
-
uri = method_uri(resource_id, http_method)
|
82
|
-
recreate_to(uri) unless uri.nil?
|
83
|
-
end
|
84
|
-
|
85
|
-
def method_uri(resource_id, http_method)
|
86
|
-
resp = apigateway.get_method(
|
87
|
-
rest_api_id: rest_api_id,
|
88
|
-
resource_id: resource_id,
|
89
|
-
http_method: http_method
|
90
|
-
)
|
91
|
-
resp.method_integration.uri
|
92
|
-
end
|
93
|
-
|
94
|
-
# Parses method uri and recreates a Route to argument.
|
95
|
-
# So:
|
96
|
-
# "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:112233445566:function:demo-test-posts_controller-new/invocations"
|
97
|
-
# Returns:
|
98
|
-
# posts#new
|
99
|
-
def recreate_to(method_uri)
|
100
|
-
md = method_uri.match(/function:(.*)\//)
|
101
|
-
function_name = md[1] # IE: demo-dev-posts_controller-new
|
102
|
-
controller_action = function_name.sub("#{Jets.project_namespace}-", '')
|
103
|
-
md = controller_action.match(/(.*)_controller-(.*)/)
|
104
|
-
controller = md[1]
|
105
|
-
controller = controller.gsub('-','/')
|
106
|
-
action = md[2]
|
107
|
-
"#{controller}##{action}" # IE: posts#new
|
108
|
-
end
|
109
|
-
|
110
|
-
# Duplicated in rest_api/change_detection.rb, base_path/role.rb, rest_api/routes.rb
|
111
|
-
def rest_api_id
|
112
|
-
stack_name = Jets::Naming.parent_stack_name
|
113
|
-
return default unless stack_exists?(stack_name)
|
114
|
-
|
115
|
-
stack = cfn.describe_stacks(stack_name: stack_name).stacks.first
|
116
|
-
|
117
|
-
api_gateway_stack_arn = lookup(stack[:outputs], "ApiGateway")
|
118
|
-
|
119
|
-
# resources = cfn.describe_stack_resources(stack_name: api_gateway_stack_arn).stack_resources
|
120
|
-
stack = cfn.describe_stacks(stack_name: api_gateway_stack_arn).stacks.first
|
121
|
-
rest_api_id = lookup(stack[:outputs], "RestApi")
|
122
|
-
end
|
123
|
-
memoize :rest_api_id
|
124
|
-
|
125
|
-
# apigateway.get_rest_api(rest_api_id: rest_api_id) # resp
|
126
10
|
end
|
127
11
|
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# Detects route changes
|
2
|
+
class Jets::Resource::ApiGateway::RestApi::Routes
|
3
|
+
class Change < Base
|
4
|
+
def changed?
|
5
|
+
deployed_routes.each do |deployed_route|
|
6
|
+
new_route = find_comparable_route(deployed_route)
|
7
|
+
if new_route && new_route.to != deployed_route.to
|
8
|
+
# change in already deployed route has been detected, requires bluegreen deploy
|
9
|
+
return true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
false # Reaching here means no routes have been changed in a way that requires a bluegreen deploy
|
13
|
+
end
|
14
|
+
|
15
|
+
# Build up deployed routes from the existing CloudFormation resources.
|
16
|
+
def deployed_routes
|
17
|
+
routes = []
|
18
|
+
|
19
|
+
resources, position = [], true
|
20
|
+
while position
|
21
|
+
position = nil if position == true # start of loop
|
22
|
+
resp = apigateway.get_resources(
|
23
|
+
rest_api_id: rest_api_id,
|
24
|
+
position: position,
|
25
|
+
)
|
26
|
+
resources += resp.items
|
27
|
+
position = resp.position
|
28
|
+
end
|
29
|
+
|
30
|
+
resources.each do |resource|
|
31
|
+
resource_methods = resource.resource_methods
|
32
|
+
next if resource_methods.nil?
|
33
|
+
|
34
|
+
resource_methods.each do |http_verb, resource_method|
|
35
|
+
# puts "#{http_verb} #{resource.path} | resource.id #{resource.id}"
|
36
|
+
# puts to(resource.id, http_verb)
|
37
|
+
|
38
|
+
# Test changing config.cors and CloudFormation does an in-place update
|
39
|
+
# on the resource. So no need to do bluegreen deployments for OPTIONS.
|
40
|
+
next if http_verb == "OPTIONS"
|
41
|
+
|
42
|
+
path = recreate_path(resource.path)
|
43
|
+
method = http_verb.downcase.to_sym
|
44
|
+
to = to(resource.id, http_verb)
|
45
|
+
route = Jets::Route.new(path: path, method: method, to: to)
|
46
|
+
routes << route
|
47
|
+
end
|
48
|
+
end
|
49
|
+
routes
|
50
|
+
end
|
51
|
+
memoize :deployed_routes
|
52
|
+
|
53
|
+
# Find a route that has the same path and method. This is a comparable route
|
54
|
+
# Then we will compare the to or controller action to see if an already
|
55
|
+
# deployed route has been changed.
|
56
|
+
def find_comparable_route(deployed_route)
|
57
|
+
new_routes.find do |new_route|
|
58
|
+
new_route.path == deployed_route.path &&
|
59
|
+
new_route.method == deployed_route.method
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def recreate_path(path)
|
64
|
+
path = path.gsub(%r{^/},'')
|
65
|
+
path = path.sub(/{(.*)\+}/, '*\1')
|
66
|
+
path.sub(/{(.*)}/, ':\1')
|
67
|
+
end
|
68
|
+
|
69
|
+
def to(resource_id, http_method)
|
70
|
+
uri = method_uri(resource_id, http_method)
|
71
|
+
recreate_to(uri) unless uri.nil?
|
72
|
+
end
|
73
|
+
|
74
|
+
def method_uri(resource_id, http_method)
|
75
|
+
resp = apigateway.get_method(
|
76
|
+
rest_api_id: rest_api_id,
|
77
|
+
resource_id: resource_id,
|
78
|
+
http_method: http_method
|
79
|
+
)
|
80
|
+
resp.method_integration.uri
|
81
|
+
end
|
82
|
+
|
83
|
+
# Parses method uri and recreates a Route to argument.
|
84
|
+
# So:
|
85
|
+
# "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:112233445566:function:demo-test-posts_controller-new/invocations"
|
86
|
+
# Returns:
|
87
|
+
# posts#new
|
88
|
+
def recreate_to(method_uri)
|
89
|
+
md = method_uri.match(/function:(.*)\//)
|
90
|
+
function_name = md[1] # IE: demo-dev-posts_controller-new
|
91
|
+
controller_action = function_name.sub("#{Jets.project_namespace}-", '')
|
92
|
+
md = controller_action.match(/(.*)_controller-(.*)/)
|
93
|
+
controller = md[1]
|
94
|
+
controller = controller.gsub('-','/')
|
95
|
+
action = md[2]
|
96
|
+
"#{controller}##{action}" # IE: posts#new
|
97
|
+
end
|
98
|
+
|
99
|
+
# Duplicated in rest_api/change_detection.rb, base_path/role.rb, rest_api/routes.rb
|
100
|
+
def rest_api_id
|
101
|
+
stack_name = Jets::Naming.parent_stack_name
|
102
|
+
return default unless stack_exists?(stack_name)
|
103
|
+
|
104
|
+
stack = cfn.describe_stacks(stack_name: stack_name).stacks.first
|
105
|
+
|
106
|
+
api_gateway_stack_arn = lookup(stack[:outputs], "ApiGateway")
|
107
|
+
|
108
|
+
# resources = cfn.describe_stack_resources(stack_name: api_gateway_stack_arn).stack_resources
|
109
|
+
stack = cfn.describe_stacks(stack_name: api_gateway_stack_arn).stacks.first
|
110
|
+
lookup(stack[:outputs], "RestApi") # rest_api_id
|
111
|
+
end
|
112
|
+
memoize :rest_api_id
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# Detects path variable collisions
|
2
|
+
class Jets::Resource::ApiGateway::RestApi::Routes
|
3
|
+
class Collision < Base
|
4
|
+
autoload :VariableException, 'jets/resource/api_gateway/rest_api/routes/collision/variable_exception'
|
5
|
+
|
6
|
+
attr_reader :collisions
|
7
|
+
def initialize(routes)
|
8
|
+
@routes = routes
|
9
|
+
@collisions = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def collision?
|
13
|
+
paths = paths_with_variables(@routes.map(&:path))
|
14
|
+
parents = variable_parents(paths)
|
15
|
+
|
16
|
+
collide = false
|
17
|
+
parents.each do |parent|
|
18
|
+
collide ||= variable_collision_exists?(parent, paths)
|
19
|
+
end
|
20
|
+
collide
|
21
|
+
end
|
22
|
+
|
23
|
+
def exception
|
24
|
+
collision_message = <<~EOL
|
25
|
+
There are routes with sibling variables under the same parent that collide.
|
26
|
+
|
27
|
+
Collisions:
|
28
|
+
#{@collisions.join("\n ")}
|
29
|
+
|
30
|
+
API Gateway only allows one unique variable path You must use the same variable name within
|
31
|
+
the same parent route path.
|
32
|
+
Example: /posts/:id and /posts/:post_id/reveal should both be /posts/:id and /posts/:id/reveal.
|
33
|
+
|
34
|
+
Please check your `config/routes.rb` and remove the colliding routes.
|
35
|
+
More info: http://rubyonjets.com/docs/considerations-api-gateway/
|
36
|
+
EOL
|
37
|
+
VariableException.new(collision_message)
|
38
|
+
end
|
39
|
+
|
40
|
+
def variable_collision_exists?(parent, paths)
|
41
|
+
paths = paths_with_variables(paths)
|
42
|
+
variables = parent_variables(parent, paths)
|
43
|
+
collide = variables.uniq.size > 1
|
44
|
+
register_collision(parent, variables) if collide
|
45
|
+
collide
|
46
|
+
end
|
47
|
+
|
48
|
+
# register collision for later display
|
49
|
+
# We don't register the full path but this might be more helpful.
|
50
|
+
def register_collision(parent, variables)
|
51
|
+
return unless variables.uniq.size # check again just in case
|
52
|
+
|
53
|
+
variables.each do |v|
|
54
|
+
@collisions << "#{parent}/#{v}"
|
55
|
+
end
|
56
|
+
@collisions.uniq!
|
57
|
+
end
|
58
|
+
|
59
|
+
def parent_variables(parent, paths)
|
60
|
+
paths = paths.select do |path|
|
61
|
+
parent?(parent, path)
|
62
|
+
end
|
63
|
+
paths.map do |path|
|
64
|
+
path.sub("#{parent}/",'').gsub(%r{/.*},'')
|
65
|
+
end.uniq.sort
|
66
|
+
end
|
67
|
+
|
68
|
+
def parent?(parent, path)
|
69
|
+
parent_parts = parent.split('/')
|
70
|
+
path_parts = path.split('/')
|
71
|
+
|
72
|
+
n = parent_parts.size-1
|
73
|
+
parent_parts[0..n] == path_parts[0..n]
|
74
|
+
end
|
75
|
+
|
76
|
+
def direct_parent?(parent, path)
|
77
|
+
leaf = variable_leaf(path)
|
78
|
+
leaf_parent = leaf.split('/')[0..-2].join('/')
|
79
|
+
parent == leaf_parent
|
80
|
+
end
|
81
|
+
|
82
|
+
def variable_parents(paths)
|
83
|
+
parents = []
|
84
|
+
paths = paths_with_variables(paths)
|
85
|
+
paths.each do |path|
|
86
|
+
parents << variable_parent(path)
|
87
|
+
end
|
88
|
+
parents.uniq.sort
|
89
|
+
end
|
90
|
+
|
91
|
+
def paths_with_variables(paths)
|
92
|
+
paths.select { |p| p.include?(':') }.uniq
|
93
|
+
end
|
94
|
+
|
95
|
+
# Strips the path down until only the leaf node part is a variable
|
96
|
+
# Example: users/:user_id/posts/:post_id/edit
|
97
|
+
# Returns: users/:user_id/posts/:post_id
|
98
|
+
def variable_parent(path)
|
99
|
+
path = variable_leaf(path)
|
100
|
+
# drop last variable to leave behind the parent
|
101
|
+
path.split('/')[0..-2].join('/')
|
102
|
+
end
|
103
|
+
|
104
|
+
# Strips the path down until only the leaf node part is a variable
|
105
|
+
# Example: users/:user_id/posts/:post_id/edit
|
106
|
+
# Returns: users/:user_id/posts
|
107
|
+
def variable_leaf(path)
|
108
|
+
return unless path.include?(':')
|
109
|
+
|
110
|
+
parts = path.split('/')
|
111
|
+
is_variable = parts.last.include?(':')
|
112
|
+
until is_variable
|
113
|
+
parts.pop
|
114
|
+
is_variable = parts.last.include?(':')
|
115
|
+
end
|
116
|
+
parts[0..-1].join('/') # parent
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
data/lib/jets/router.rb
CHANGED
@@ -11,6 +11,14 @@ module Jets
|
|
11
11
|
|
12
12
|
def draw(&block)
|
13
13
|
instance_eval(&block)
|
14
|
+
check_collision!
|
15
|
+
end
|
16
|
+
|
17
|
+
# Validate routes that deployable
|
18
|
+
def check_collision!
|
19
|
+
collision = Jets::Resource::ApiGateway::RestApi::Routes::Collision.new(self.routes)
|
20
|
+
collide = collision.collision?
|
21
|
+
raise collision.exception if collide
|
14
22
|
end
|
15
23
|
|
16
24
|
# Methods supported by API Gateway
|
data/lib/jets/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tung Nguyen
|
@@ -14,28 +14,28 @@ dependencies:
|
|
14
14
|
name: activerecord
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 5.2.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 5.2.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activesupport
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 5.2.1
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 5.2.1
|
41
41
|
- !ruby/object:Gem::Dependency
|
@@ -294,14 +294,14 @@ dependencies:
|
|
294
294
|
name: railties
|
295
295
|
requirement: !ruby/object:Gem::Requirement
|
296
296
|
requirements:
|
297
|
-
- - "
|
297
|
+
- - "~>"
|
298
298
|
- !ruby/object:Gem::Version
|
299
299
|
version: 5.2.1
|
300
300
|
type: :runtime
|
301
301
|
prerelease: false
|
302
302
|
version_requirements: !ruby/object:Gem::Requirement
|
303
303
|
requirements:
|
304
|
-
- - "
|
304
|
+
- - "~>"
|
305
305
|
- !ruby/object:Gem::Version
|
306
306
|
version: 5.2.1
|
307
307
|
- !ruby/object:Gem::Dependency
|
@@ -704,6 +704,10 @@ files:
|
|
704
704
|
- lib/jets/resource/api_gateway/rest_api/change_detection.rb
|
705
705
|
- lib/jets/resource/api_gateway/rest_api/logical_id.rb
|
706
706
|
- lib/jets/resource/api_gateway/rest_api/routes.rb
|
707
|
+
- lib/jets/resource/api_gateway/rest_api/routes/base.rb
|
708
|
+
- lib/jets/resource/api_gateway/rest_api/routes/change.rb
|
709
|
+
- lib/jets/resource/api_gateway/rest_api/routes/collision.rb
|
710
|
+
- lib/jets/resource/api_gateway/rest_api/routes/collision/variable_exception.rb
|
707
711
|
- lib/jets/resource/associated.rb
|
708
712
|
- lib/jets/resource/base.rb
|
709
713
|
- lib/jets/resource/child_stack.rb
|
@@ -768,7 +772,6 @@ files:
|
|
768
772
|
- lib/jets/turbo/project/.gitignore
|
769
773
|
- lib/jets/turbo/project/.jetskeep
|
770
774
|
- lib/jets/turbo/project/Gemfile
|
771
|
-
- lib/jets/turbo/project/Gemfile.lock
|
772
775
|
- lib/jets/turbo/project/Rakefile
|
773
776
|
- lib/jets/turbo/project/app/controllers/application_controller.rb
|
774
777
|
- lib/jets/turbo/project/app/helpers/application_helper.rb
|
@@ -1,185 +0,0 @@
|
|
1
|
-
GEM
|
2
|
-
remote: https://rubygems.org/
|
3
|
-
specs:
|
4
|
-
actionpack (5.2.2)
|
5
|
-
actionview (= 5.2.2)
|
6
|
-
activesupport (= 5.2.2)
|
7
|
-
rack (~> 2.0)
|
8
|
-
rack-test (>= 0.6.3)
|
9
|
-
rails-dom-testing (~> 2.0)
|
10
|
-
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
11
|
-
actionview (5.2.2)
|
12
|
-
activesupport (= 5.2.2)
|
13
|
-
builder (~> 3.1)
|
14
|
-
erubi (~> 1.4)
|
15
|
-
rails-dom-testing (~> 2.0)
|
16
|
-
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
17
|
-
activemodel (5.2.2)
|
18
|
-
activesupport (= 5.2.2)
|
19
|
-
activerecord (5.2.2)
|
20
|
-
activemodel (= 5.2.2)
|
21
|
-
activesupport (= 5.2.2)
|
22
|
-
arel (>= 9.0)
|
23
|
-
activesupport (5.2.2)
|
24
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
25
|
-
i18n (>= 0.7, < 2)
|
26
|
-
minitest (~> 5.1)
|
27
|
-
tzinfo (~> 1.1)
|
28
|
-
addressable (2.5.2)
|
29
|
-
public_suffix (>= 2.0.2, < 4.0)
|
30
|
-
arel (9.0.0)
|
31
|
-
aws-eventstream (1.0.1)
|
32
|
-
aws-partitions (1.131.0)
|
33
|
-
aws-sdk-apigateway (1.23.0)
|
34
|
-
aws-sdk-core (~> 3, >= 3.39.0)
|
35
|
-
aws-sigv4 (~> 1.0)
|
36
|
-
aws-sdk-cloudformation (1.14.0)
|
37
|
-
aws-sdk-core (~> 3, >= 3.39.0)
|
38
|
-
aws-sigv4 (~> 1.0)
|
39
|
-
aws-sdk-cloudwatchlogs (1.12.0)
|
40
|
-
aws-sdk-core (~> 3, >= 3.39.0)
|
41
|
-
aws-sigv4 (~> 1.0)
|
42
|
-
aws-sdk-core (3.45.0)
|
43
|
-
aws-eventstream (~> 1.0)
|
44
|
-
aws-partitions (~> 1.0)
|
45
|
-
aws-sigv4 (~> 1.0)
|
46
|
-
jmespath (~> 1.0)
|
47
|
-
aws-sdk-dynamodb (1.19.0)
|
48
|
-
aws-sdk-core (~> 3, >= 3.39.0)
|
49
|
-
aws-sigv4 (~> 1.0)
|
50
|
-
aws-sdk-kms (1.13.0)
|
51
|
-
aws-sdk-core (~> 3, >= 3.39.0)
|
52
|
-
aws-sigv4 (~> 1.0)
|
53
|
-
aws-sdk-lambda (1.16.0)
|
54
|
-
aws-sdk-core (~> 3, >= 3.39.0)
|
55
|
-
aws-sigv4 (~> 1.0)
|
56
|
-
aws-sdk-s3 (1.30.1)
|
57
|
-
aws-sdk-core (~> 3, >= 3.39.0)
|
58
|
-
aws-sdk-kms (~> 1)
|
59
|
-
aws-sigv4 (~> 1.0)
|
60
|
-
aws-sdk-sns (1.9.0)
|
61
|
-
aws-sdk-core (~> 3, >= 3.39.0)
|
62
|
-
aws-sigv4 (~> 1.0)
|
63
|
-
aws-sdk-sqs (1.10.0)
|
64
|
-
aws-sdk-core (~> 3, >= 3.39.0)
|
65
|
-
aws-sigv4 (~> 1.0)
|
66
|
-
aws-sigv4 (1.0.3)
|
67
|
-
builder (3.2.3)
|
68
|
-
byebug (10.0.2)
|
69
|
-
capybara (3.12.0)
|
70
|
-
addressable
|
71
|
-
mini_mime (>= 0.1.3)
|
72
|
-
nokogiri (~> 1.8)
|
73
|
-
rack (>= 1.6.0)
|
74
|
-
rack-test (>= 0.6.3)
|
75
|
-
regexp_parser (~> 1.2)
|
76
|
-
xpath (~> 3.2)
|
77
|
-
colorize (0.8.1)
|
78
|
-
concurrent-ruby (1.1.4)
|
79
|
-
crass (1.0.4)
|
80
|
-
diff-lcs (1.3)
|
81
|
-
dotenv (2.6.0)
|
82
|
-
erubi (1.8.0)
|
83
|
-
gems (1.1.1)
|
84
|
-
json
|
85
|
-
hashie (3.6.0)
|
86
|
-
i18n (1.5.2)
|
87
|
-
concurrent-ruby (~> 1.0)
|
88
|
-
jets (1.5.3)
|
89
|
-
activerecord (>= 5.2.1)
|
90
|
-
activesupport (>= 5.2.1)
|
91
|
-
aws-sdk-apigateway
|
92
|
-
aws-sdk-cloudformation
|
93
|
-
aws-sdk-cloudwatchlogs
|
94
|
-
aws-sdk-dynamodb
|
95
|
-
aws-sdk-lambda
|
96
|
-
aws-sdk-s3
|
97
|
-
aws-sdk-sns
|
98
|
-
aws-sdk-sqs
|
99
|
-
colorize
|
100
|
-
dotenv
|
101
|
-
gems
|
102
|
-
hashie
|
103
|
-
jets-html-sanitizer
|
104
|
-
json
|
105
|
-
kramdown
|
106
|
-
memoist
|
107
|
-
mimemagic
|
108
|
-
rack
|
109
|
-
railties (>= 5.2.1)
|
110
|
-
recursive-open-struct
|
111
|
-
text-table
|
112
|
-
thor
|
113
|
-
jets-html-sanitizer (1.0.4)
|
114
|
-
loofah (~> 2.2, >= 2.2.2)
|
115
|
-
jmespath (1.4.0)
|
116
|
-
json (2.1.0)
|
117
|
-
kramdown (1.17.0)
|
118
|
-
launchy (2.4.3)
|
119
|
-
addressable (~> 2.3)
|
120
|
-
loofah (2.2.3)
|
121
|
-
crass (~> 1.0.2)
|
122
|
-
nokogiri (>= 1.5.9)
|
123
|
-
memoist (0.16.0)
|
124
|
-
method_source (0.9.2)
|
125
|
-
mimemagic (0.3.3)
|
126
|
-
mini_mime (1.0.1)
|
127
|
-
mini_portile2 (2.4.0)
|
128
|
-
minitest (5.11.3)
|
129
|
-
nokogiri (1.10.1)
|
130
|
-
mini_portile2 (~> 2.4.0)
|
131
|
-
public_suffix (3.0.3)
|
132
|
-
rack (2.0.6)
|
133
|
-
rack-test (1.1.0)
|
134
|
-
rack (>= 1.0, < 3)
|
135
|
-
rails-dom-testing (2.0.3)
|
136
|
-
activesupport (>= 4.2.0)
|
137
|
-
nokogiri (>= 1.6)
|
138
|
-
rails-html-sanitizer (1.0.4)
|
139
|
-
loofah (~> 2.2, >= 2.2.2)
|
140
|
-
railties (5.2.2)
|
141
|
-
actionpack (= 5.2.2)
|
142
|
-
activesupport (= 5.2.2)
|
143
|
-
method_source
|
144
|
-
rake (>= 0.8.7)
|
145
|
-
thor (>= 0.19.0, < 2.0)
|
146
|
-
rake (12.3.2)
|
147
|
-
recursive-open-struct (1.1.0)
|
148
|
-
regexp_parser (1.3.0)
|
149
|
-
rspec (3.8.0)
|
150
|
-
rspec-core (~> 3.8.0)
|
151
|
-
rspec-expectations (~> 3.8.0)
|
152
|
-
rspec-mocks (~> 3.8.0)
|
153
|
-
rspec-core (3.8.0)
|
154
|
-
rspec-support (~> 3.8.0)
|
155
|
-
rspec-expectations (3.8.2)
|
156
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
157
|
-
rspec-support (~> 3.8.0)
|
158
|
-
rspec-mocks (3.8.0)
|
159
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
160
|
-
rspec-support (~> 3.8.0)
|
161
|
-
rspec-support (3.8.0)
|
162
|
-
shotgun (0.9.2)
|
163
|
-
rack (>= 1.0)
|
164
|
-
text-table (1.2.4)
|
165
|
-
thor (0.20.3)
|
166
|
-
thread_safe (0.3.6)
|
167
|
-
tzinfo (1.2.5)
|
168
|
-
thread_safe (~> 0.1)
|
169
|
-
xpath (3.2.0)
|
170
|
-
nokogiri (~> 1.8)
|
171
|
-
|
172
|
-
PLATFORMS
|
173
|
-
ruby
|
174
|
-
|
175
|
-
DEPENDENCIES
|
176
|
-
byebug
|
177
|
-
capybara
|
178
|
-
jets
|
179
|
-
launchy
|
180
|
-
rack
|
181
|
-
rspec
|
182
|
-
shotgun
|
183
|
-
|
184
|
-
BUNDLED WITH
|
185
|
-
1.17.2
|