jets 1.5.9 → 1.5.10

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: 139636b38cc75e1677d5590c3ed58b2aa62615d8eb0ab2881e10617a7ecbcf42
4
- data.tar.gz: e319b191d08ed15475f644c8348edac60e8a55c9e21f9b4aa8b3605a12fa6f10
3
+ metadata.gz: 39b6cde7b66e43e4c253e0f055952680298287d9e7c534c4a465ca075b3dfb62
4
+ data.tar.gz: d3312104416979ca67bd31cebd3a7c2ba604185349c2c368de438d50a68914ef
5
5
  SHA512:
6
- metadata.gz: e1dbcc0bf66eb73a9d2ff93b1ba95044d4026734beff95bf16ead0ff3f2c5d2461738cf3ff82fc0f116729024a4a7c4ffb49d5bf7babe6469be6145610ca55c8
7
- data.tar.gz: 3f6987b22c59c6dfdd294cfd81ce1de23eec5e386ec7b82b91c698c9a6956874f479a5bb31274790b511953329eca208a98eab7a98b33b7483448229ddc772bd
6
+ metadata.gz: 1b670d6b6a2c0189fd608d4a7ba61a02206a4ddf78d2c8eda2c4f06d8c4c1beddb2588b417211e697ea0b24f8c426975c9ab08819a56fc3da41f6c959fb272ca
7
+ data.tar.gz: c84383ea55a03f9b0576fb5ea7c4a895a9e5ae818bd79df008a9e7f621f93ce2d5e4e189d7f4aa9a9a2c0fef12ae7a668747308b263785de0b8d0c46da8330f7
@@ -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/), even before v1.0.
5
5
 
6
+ ## [1.5.10]
7
+ - #157 Improve Route Change Detection: Path Variables
8
+
6
9
  ## [1.5.9]
7
10
  - #154 from tongueroo/variable-collision raise error on multiple sibling variable paths collision
8
11
  - #156 from konnected-io/master: don't prewarm jobs, only prewarm controllers
@@ -11,7 +11,7 @@ GIT
11
11
  PATH
12
12
  remote: .
13
13
  specs:
14
- jets (1.5.9)
14
+ jets (1.5.10)
15
15
  activerecord (~> 5.2.1)
16
16
  activesupport (~> 5.2.1)
17
17
  aws-sdk-apigateway
@@ -66,7 +66,7 @@ GEM
66
66
  tzinfo (~> 1.1)
67
67
  arel (9.0.0)
68
68
  aws-eventstream (1.0.1)
69
- aws-partitions (1.132.0)
69
+ aws-partitions (1.133.0)
70
70
  aws-sdk-apigateway (1.23.0)
71
71
  aws-sdk-core (~> 3, >= 3.39.0)
72
72
  aws-sigv4 (~> 1.0)
@@ -87,7 +87,7 @@ GEM
87
87
  aws-sdk-kms (1.13.0)
88
88
  aws-sdk-core (~> 3, >= 3.39.0)
89
89
  aws-sigv4 (~> 1.0)
90
- aws-sdk-lambda (1.16.0)
90
+ aws-sdk-lambda (1.17.0)
91
91
  aws-sdk-core (~> 3, >= 3.39.0)
92
92
  aws-sigv4 (~> 1.0)
93
93
  aws-sdk-s3 (1.30.1)
@@ -134,6 +134,7 @@ JS
134
134
 
135
135
  Scaffold example:
136
136
  jets generate scaffold Post title:string body:text published:boolean
137
+ jets db:create db:migrate
137
138
 
138
139
  To deploy to AWS Lambda, edit your .env.development.remote and add a DATABASE_URL endpoint.
139
140
  Then run:
@@ -55,7 +55,7 @@ module Jets::Resource::ApiGateway::BasePath
55
55
  # Duplicated in rest_api/change_detection.rb, base_path/role.rb, rest_api/routes.rb
56
56
  def rest_api_id
57
57
  stack_name = Jets::Naming.parent_stack_name
58
- return default unless stack_exists?(stack_name)
58
+ return "RestApi" unless stack_exists?(stack_name)
59
59
 
60
60
  stack = cfn.describe_stacks(stack_name: stack_name).stacks.first
61
61
 
@@ -6,7 +6,6 @@ class Jets::Resource::ApiGateway::RestApi
6
6
  def get
7
7
  return default unless stack_exists?(parent_stack_name) && api_gateway_exists?
8
8
 
9
-
10
9
  if changed?
11
10
  new_id
12
11
  else
@@ -1,114 +1,12 @@
1
1
  # Detects route changes
2
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)
3
+ class Change
4
+ autoload :Base, 'jets/resource/api_gateway/rest_api/routes/change/base'
5
+ autoload :To, 'jets/resource/api_gateway/rest_api/routes/change/to'
6
+ autoload :Variable, 'jets/resource/api_gateway/rest_api/routes/change/variable'
37
7
 
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
8
+ def changed?
9
+ To.changed? || Variable.changed? || ENV['JETS_REPLACE_API']
111
10
  end
112
- memoize :rest_api_id
113
11
  end
114
12
  end
@@ -0,0 +1,100 @@
1
+ class Jets::Resource::ApiGateway::RestApi::Routes::Change
2
+ class Base
3
+ extend Memoist
4
+ include Jets::AwsServices
5
+
6
+ # Build up deployed routes from the existing CloudFormation resources.
7
+ def deployed_routes
8
+ routes = []
9
+
10
+ resources, position = [], true
11
+ while position
12
+ position = nil if position == true # start of loop
13
+ resp = apigateway.get_resources(
14
+ rest_api_id: rest_api_id,
15
+ position: position,
16
+ )
17
+ resources += resp.items
18
+ position = resp.position
19
+ end
20
+
21
+ resources.each do |resource|
22
+ resource_methods = resource.resource_methods
23
+ next if resource_methods.nil?
24
+
25
+ resource_methods.each do |http_verb, resource_method|
26
+ # puts "#{http_verb} #{resource.path} | resource.id #{resource.id}"
27
+ # puts to(resource.id, http_verb)
28
+
29
+ # Test changing config.cors and CloudFormation does an in-place update
30
+ # on the resource. So no need to do bluegreen deployments for OPTIONS.
31
+ next if http_verb == "OPTIONS"
32
+
33
+ path = recreate_path(resource.path)
34
+ method = http_verb.downcase.to_sym
35
+ to = to(resource.id, http_verb)
36
+ route = Jets::Route.new(path: path, method: method, to: to)
37
+ routes << route
38
+ end
39
+ end
40
+ routes
41
+ end
42
+ memoize :deployed_routes
43
+
44
+ def recreate_path(path)
45
+ path = path.gsub(%r{^/},'')
46
+ path = path.sub(/{(.*)\+}/, '*\1')
47
+ path.sub(/{(.*)}/, ':\1')
48
+ end
49
+
50
+ def to(resource_id, http_method)
51
+ uri = method_uri(resource_id, http_method)
52
+ recreate_to(uri) unless uri.nil?
53
+ end
54
+
55
+ def method_uri(resource_id, http_method)
56
+ resp = apigateway.get_method(
57
+ rest_api_id: rest_api_id,
58
+ resource_id: resource_id,
59
+ http_method: http_method
60
+ )
61
+ resp.method_integration.uri
62
+ end
63
+
64
+ # Parses method uri and recreates a Route to argument.
65
+ # So:
66
+ # "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"
67
+ # Returns:
68
+ # posts#new
69
+ def recreate_to(method_uri)
70
+ md = method_uri.match(/function:(.*)\//)
71
+ function_name = md[1] # IE: demo-dev-posts_controller-new
72
+ controller_action = function_name.sub("#{Jets.project_namespace}-", '')
73
+ md = controller_action.match(/(.*)_controller-(.*)/)
74
+ controller = md[1]
75
+ controller = controller.gsub('-','/')
76
+ action = md[2]
77
+ "#{controller}##{action}" # IE: posts#new
78
+ end
79
+
80
+ # Duplicated in rest_api/change_detection.rb, base_path/role.rb, rest_api/routes.rb
81
+ def rest_api_id
82
+ stack_name = Jets::Naming.parent_stack_name
83
+ return "RestApi" unless stack_exists?(stack_name)
84
+
85
+ stack = cfn.describe_stacks(stack_name: stack_name).stacks.first
86
+
87
+ api_gateway_stack_arn = lookup(stack[:outputs], "ApiGateway")
88
+
89
+ # resources = cfn.describe_stack_resources(stack_name: api_gateway_stack_arn).stack_resources
90
+ stack = cfn.describe_stacks(stack_name: api_gateway_stack_arn).stacks.first
91
+ lookup(stack[:outputs], "RestApi") # rest_api_id
92
+ end
93
+ memoize :rest_api_id
94
+
95
+ def new_routes
96
+ Jets::Router.routes
97
+ end
98
+ memoize :new_routes
99
+ end
100
+ end
@@ -0,0 +1,29 @@
1
+ # Detects route to changes
2
+ class Jets::Resource::ApiGateway::RestApi::Routes::Change
3
+ class To < Base
4
+ def self.changed?
5
+ new.changed?
6
+ end
7
+
8
+ def changed?
9
+ deployed_routes.each do |deployed_route|
10
+ new_route = find_comparable_route(deployed_route)
11
+ if new_route && new_route.to != deployed_route.to
12
+ # change in already deployed route has been detected, requires bluegreen deploy
13
+ return true
14
+ end
15
+ end
16
+ false # Reaching here means no routes have been changed in a way that requires a bluegreen deploy
17
+ end
18
+
19
+ # Find a route that has the same path and method. This is a comparable route
20
+ # Then we will compare the to or controller action to see if an already
21
+ # deployed route has been changed.
22
+ def find_comparable_route(deployed_route)
23
+ new_routes.find do |new_route|
24
+ new_route.path == deployed_route.path &&
25
+ new_route.method == deployed_route.method
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,39 @@
1
+ # Detects route variable changes
2
+ class Jets::Resource::ApiGateway::RestApi::Routes::Change
3
+ class Variable < Base
4
+ def self.changed?
5
+ new.changed?
6
+ end
7
+
8
+ def changed?
9
+ changed = false
10
+ deployed_routes.each do |deployed_route|
11
+ parent = collision.variable_parent(deployed_route.path)
12
+ parent_variables = collision.parent_variables(parent, [deployed_route.path])
13
+ new_parent_variables = collision.parent_variables(parent, new_paths)
14
+
15
+ changed = parent_variables.size > 0 && new_parent_variables.size > 0 &&
16
+ parent_variables != new_parent_variables
17
+ break if changed
18
+ end
19
+ changed
20
+ end
21
+
22
+ # Only consider paths with variables
23
+ def new_paths
24
+ new_routes.map(&:path).select {|p| p.include?(':')}.uniq
25
+ end
26
+
27
+ # Only consider deployed routes with variables
28
+ def deployed_routes
29
+ deployed_routes = super
30
+ deployed_routes.select do |route|
31
+ route.path.include?(':')
32
+ end
33
+ end
34
+
35
+ def collision
36
+ @collision ||= Jets::Resource::ApiGateway::RestApi::Routes::Collision.new
37
+ end
38
+ end
39
+ end
@@ -1,16 +1,15 @@
1
1
  # Detects path variable collisions
2
2
  class Jets::Resource::ApiGateway::RestApi::Routes
3
- class Collision < Base
3
+ class Collision
4
4
  autoload :VariableException, 'jets/resource/api_gateway/rest_api/routes/collision/variable_exception'
5
5
 
6
6
  attr_reader :collisions
7
- def initialize(routes)
8
- @routes = routes
7
+ def initialize
9
8
  @collisions = []
10
9
  end
11
10
 
12
- def collision?
13
- paths = paths_with_variables(@routes.map(&:path))
11
+ def collision?(paths)
12
+ paths = paths_with_variables(paths)
14
13
  parents = variable_parents(paths)
15
14
 
16
15
  collide = false
@@ -21,7 +20,11 @@ class Jets::Resource::ApiGateway::RestApi::Routes
21
20
  end
22
21
 
23
22
  def exception
24
- collision_message = <<~EOL
23
+ VariableException.new(collision_message)
24
+ end
25
+
26
+ def collision_message
27
+ <<~EOL
25
28
  There are routes with sibling variables under the same parent that collide.
26
29
 
27
30
  Collisions:
@@ -34,7 +37,6 @@ class Jets::Resource::ApiGateway::RestApi::Routes
34
37
  Please check your `config/routes.rb` and remove the colliding routes.
35
38
  More info: http://rubyonjets.com/docs/considerations-api-gateway/
36
39
  EOL
37
- VariableException.new(collision_message)
38
40
  end
39
41
 
40
42
  def variable_collision_exists?(parent, paths)
@@ -88,13 +90,9 @@ class Jets::Resource::ApiGateway::RestApi::Routes
88
90
  parents.uniq.sort
89
91
  end
90
92
 
91
- def paths_with_variables(paths)
92
- paths.select { |p| p.include?(':') }.uniq
93
- end
94
-
95
93
  # Strips the path down until only the leaf node part is a variable
96
94
  # Example: users/:user_id/posts/:post_id/edit
97
- # Returns: users/:user_id/posts/:post_id
95
+ # Returns: users/:user_id/posts
98
96
  def variable_parent(path)
99
97
  path = variable_leaf(path)
100
98
  # drop last variable to leave behind the parent
@@ -105,7 +103,7 @@ class Jets::Resource::ApiGateway::RestApi::Routes
105
103
  # Example: users/:user_id/posts/:post_id/edit
106
104
  # Returns: users/:user_id/posts
107
105
  def variable_leaf(path)
108
- return unless path.include?(':')
106
+ return '' unless path.include?(':')
109
107
 
110
108
  parts = path.split('/')
111
109
  is_variable = parts.last.include?(':')
@@ -115,5 +113,9 @@ class Jets::Resource::ApiGateway::RestApi::Routes
115
113
  end
116
114
  parts[0..-1].join('/') # parent
117
115
  end
116
+
117
+ def paths_with_variables(paths)
118
+ paths.select { |p| p.include?(':') }.uniq
119
+ end
118
120
  end
119
121
  end
@@ -16,8 +16,9 @@ module Jets
16
16
 
17
17
  # Validate routes that deployable
18
18
  def check_collision!
19
- collision = Jets::Resource::ApiGateway::RestApi::Routes::Collision.new(self.routes)
20
- collide = collision.collision?
19
+ paths = self.routes.map(&:path)
20
+ collision = Jets::Resource::ApiGateway::RestApi::Routes::Collision.new
21
+ collide = collision.collision?(paths)
21
22
  raise collision.exception if collide
22
23
  end
23
24
 
@@ -1,3 +1,3 @@
1
1
  module Jets
2
- VERSION = "1.5.9"
2
+ VERSION = "1.5.10"
3
3
  end
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: 1.5.9
4
+ version: 1.5.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-17 00:00:00.000000000 Z
11
+ date: 2019-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -704,8 +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
707
  - lib/jets/resource/api_gateway/rest_api/routes/change.rb
708
+ - lib/jets/resource/api_gateway/rest_api/routes/change/base.rb
709
+ - lib/jets/resource/api_gateway/rest_api/routes/change/to.rb
710
+ - lib/jets/resource/api_gateway/rest_api/routes/change/variable.rb
709
711
  - lib/jets/resource/api_gateway/rest_api/routes/collision.rb
710
712
  - lib/jets/resource/api_gateway/rest_api/routes/collision/variable_exception.rb
711
713
  - lib/jets/resource/associated.rb
@@ -1,11 +0,0 @@
1
- class Jets::Resource::ApiGateway::RestApi::Routes
2
- class Base
3
- extend Memoist
4
- include Jets::AwsServices
5
-
6
- def new_routes
7
- Jets::Router.routes
8
- end
9
- memoize :new_routes
10
- end
11
- end