Class: Jets::Resource::ApiGateway::RestApi::Routes

Inherits:
Object
  • Object
show all
Extended by:
Memoist
Includes:
AwsServices
Defined in:
lib/jets/resource/api_gateway/rest_api/routes.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from AwsServices

#apigateway, #cfn, #lambda, #logs, #s3, #s3_resource, #sns, #sqs, #sts

Methods included from AwsServices::StackStatus

#lookup, #stack_exists?, #stack_in_progress?

Class Method Details

.changed?Boolean

Returns:

  • (Boolean)


6
7
8
# File 'lib/jets/resource/api_gateway/rest_api/routes.rb', line 6

def self.changed?
  new.changed?
end

Instance Method Details

#buildObject

Build up deployed routes from the existing CloudFormation resources.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/jets/resource/api_gateway/rest_api/routes.rb', line 23

def build
  routes = []

  resources, position = [], true
  while position
    position = nil if position == true # start of loop
    resp = apigateway.get_resources(
      rest_api_id: rest_api_id,
      position: position,
    )
    resources += resp.items
    position = resp.position
  end

  resources.each do |resource|
    resource_methods = resource.resource_methods
    next if resource_methods.nil?

    resource_methods.each do |http_verb, resource_method|
      # puts "#{http_verb} #{resource.path} | resource.id #{resource.id}"
      # puts to(resource.id, http_verb)

      # Test changing config.cors and CloudFormation does an in-place update
      # on the resource. So no need to do bluegreen deployments for OPTIONS.
      next if http_verb == "OPTIONS"

      path = recreate_path(resource.path)
      method = http_verb.downcase.to_sym
      to = to(resource.id, http_verb)
      route = Jets::Route.new(path: path, method: method, to: to)
      routes << route
    end
  end
  routes
end

#changed?Boolean

Returns:

  • (Boolean)


10
11
12
13
14
15
16
17
18
19
20
# File 'lib/jets/resource/api_gateway/rest_api/routes.rb', line 10

def changed?
  deployed_routes = build
  deployed_routes.each do |deployed_route|
    new_route = find_comparable_route(deployed_route)
    if new_route && new_route.to != deployed_route.to
      # change in already deployed route has been detected, requires bluegreen deploy
      return true
    end
  end
  false # Reaching here means no routes have been changed in a way that requires a bluegreen deploy
end

#find_comparable_route(deployed_route) ⇒ Object

Find a route that has the same path and method. This is a comparable route Then we will compare the to or controller action to see if an already deployed route has been changed.



62
63
64
65
66
67
# File 'lib/jets/resource/api_gateway/rest_api/routes.rb', line 62

def find_comparable_route(deployed_route)
  new_routes.find do |new_route|
    new_route.path == deployed_route.path &&
    new_route.method == deployed_route.method
  end
end

#method_uri(resource_id, http_method) ⇒ Object



85
86
87
88
89
90
91
92
# File 'lib/jets/resource/api_gateway/rest_api/routes.rb', line 85

def method_uri(resource_id, http_method)
  resp = apigateway.get_method(
    rest_api_id: rest_api_id,
    resource_id: resource_id,
    http_method: http_method
  )
  resp.method_integration.uri
end

#new_routesObject



69
70
71
# File 'lib/jets/resource/api_gateway/rest_api/routes.rb', line 69

def new_routes
  Jets::Router.routes
end

#recreate_path(path) ⇒ Object



74
75
76
77
78
# File 'lib/jets/resource/api_gateway/rest_api/routes.rb', line 74

def recreate_path(path)
  path = path.gsub(%r{^/},'')
  path = path.sub(/{(.*)\+}/, '*\1')
  path.sub(/{(.*)}/, ':\1')
end

#recreate_to(method_uri) ⇒ Object

Parses method uri and recreates a Route to argument. So:

"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"

Returns:

posts#new


99
100
101
102
103
104
105
106
107
108
# File 'lib/jets/resource/api_gateway/rest_api/routes.rb', line 99

def recreate_to(method_uri)
  md = method_uri.match(/function:(.*)\//)
  function_name = md[1] # IE: demo-dev-posts_controller-new
  controller_action = function_name.sub("#{Jets.project_namespace}-", '')
  md = controller_action.match(/(.*)_controller-(.*)/)
  controller = md[1]
  controller = controller.gsub('-','/')
  action = md[2]
  "#{controller}##{action}" # IE: posts#new
end

#rest_api_idObject

Duplicated in rest_api/change_detection.rb, base_path/role.rb, rest_api/routes.rb



111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/jets/resource/api_gateway/rest_api/routes.rb', line 111

def rest_api_id
  stack_name = Jets::Naming.parent_stack_name
  return default unless stack_exists?(stack_name)

  stack = cfn.describe_stacks(stack_name: stack_name).stacks.first

  api_gateway_stack_arn = lookup(stack[:outputs], "ApiGateway")

  # resources = cfn.describe_stack_resources(stack_name: api_gateway_stack_arn).stack_resources
  stack = cfn.describe_stacks(stack_name: api_gateway_stack_arn).stacks.first
  rest_api_id = lookup(stack[:outputs], "RestApi")
end

#to(resource_id, http_method) ⇒ Object



80
81
82
83
# File 'lib/jets/resource/api_gateway/rest_api/routes.rb', line 80

def to(resource_id, http_method)
  uri = method_uri(resource_id, http_method)
  recreate_to(uri) unless uri.nil?
end