jets 1.1.5 → 1.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 +7 -0
- data/Gemfile.lock +10 -6
- data/README/testing.md +5 -1
- data/jets.gemspec +1 -0
- data/lib/jets.rb +5 -1
- data/lib/jets/application.rb +39 -19
- data/lib/jets/aws_services.rb +16 -10
- data/lib/jets/aws_services/stack_status.rb +7 -0
- data/lib/jets/booter.rb +6 -2
- data/lib/jets/builders/code_builder.rb +14 -0
- data/lib/jets/builders/handler_generator.rb +15 -0
- data/lib/jets/builders/shim_vars/app.rb +4 -3
- data/lib/jets/builders/shim_vars/shared.rb +8 -4
- data/lib/jets/builders/templates/shim.js +7 -3
- data/lib/jets/camelizer.rb +2 -1
- data/lib/jets/cfn/builders.rb +0 -1
- data/lib/jets/cfn/builders/api_deployment_builder.rb +27 -0
- data/lib/jets/cfn/builders/api_gateway_builder.rb +22 -2
- data/lib/jets/cfn/ship.rb +38 -6
- data/lib/jets/commands/call.rb +0 -1
- data/lib/jets/commands/call/guesser.rb +0 -3
- data/lib/jets/commands/clean/log.rb +18 -0
- data/lib/jets/commands/console.rb +1 -1
- data/lib/jets/commands/import/sequence.rb +2 -3
- data/lib/jets/commands/runner.rb +1 -1
- data/lib/jets/commands/sequence.rb +0 -1
- data/lib/jets/commands/templates/skeleton/config/application.rb.tt +11 -0
- data/lib/jets/commands/url.rb +32 -7
- data/lib/jets/controller/base.rb +21 -5
- data/lib/jets/controller/layout.rb +0 -3
- data/lib/jets/controller/middleware/local/api_gateway.rb +2 -5
- data/lib/jets/controller/middleware/local/mimic_aws_call.rb +2 -2
- data/lib/jets/controller/params.rb +42 -10
- data/lib/jets/controller/rack/adapter.rb +5 -2
- data/lib/jets/controller/rack/env.rb +17 -8
- data/lib/jets/controller/renderers/rack_renderer.rb +1 -1
- data/lib/jets/controller/rendering.rb +4 -1
- data/lib/jets/core.rb +8 -16
- data/lib/jets/internal/app/functions/jets/base_path.rb +153 -0
- data/lib/jets/klass.rb +38 -5
- data/lib/jets/lambda/dsl.rb +0 -2
- data/lib/jets/mega/request.rb +44 -13
- data/lib/jets/mega/request/source.rb +21 -0
- data/lib/jets/middleware/configurator.rb +1 -1
- data/lib/jets/middleware/default_stack.rb +2 -2
- data/lib/jets/resource.rb +1 -0
- data/lib/jets/resource/api_gateway.rb +5 -3
- data/lib/jets/resource/api_gateway/base_path.rb +5 -0
- data/lib/jets/resource/api_gateway/base_path/function.rb +42 -0
- data/lib/jets/resource/api_gateway/base_path/mapping.rb +44 -0
- data/lib/jets/resource/api_gateway/base_path/role.rb +76 -0
- data/lib/jets/resource/api_gateway/cors.rb +1 -1
- data/lib/jets/resource/api_gateway/deployment.rb +9 -5
- data/lib/jets/resource/api_gateway/domain_name.rb +56 -0
- data/lib/jets/resource/api_gateway/method.rb +3 -4
- data/lib/jets/resource/api_gateway/resource.rb +4 -3
- data/lib/jets/resource/api_gateway/rest_api.rb +42 -14
- data/lib/jets/resource/api_gateway/rest_api/change_detection.rb +42 -0
- data/lib/jets/resource/api_gateway/rest_api/logical_id.rb +59 -0
- data/lib/jets/resource/api_gateway/rest_api/routes.rb +127 -0
- data/lib/jets/resource/child_stack/api_deployment.rb +5 -1
- data/lib/jets/resource/function.rb +3 -20
- data/lib/jets/resource/function/environment.rb +23 -0
- data/lib/jets/resource/iam/application_role.rb +1 -1
- data/lib/jets/resource/route53.rb +3 -0
- data/lib/jets/resource/route53/record_set.rb +70 -0
- data/lib/jets/router.rb +2 -0
- data/lib/jets/ruby_server.rb +6 -3
- data/lib/jets/stack.rb +1 -3
- data/lib/jets/stack/main/dsl.rb +1 -1
- data/lib/jets/stack/main/extensions/lambda.rb +4 -2
- data/lib/jets/turbine.rb +0 -3
- data/lib/jets/version.rb +1 -1
- data/vendor/jets-gems/lib/jets/gems.rb +1 -0
- data/vendor/jets-gems/lib/jets/gems/agree.rb +41 -0
- data/vendor/jets-gems/lib/jets/gems/check.rb +15 -2
- metadata +30 -2
@@ -0,0 +1,21 @@
|
|
1
|
+
class Jets::Mega::Request
|
2
|
+
class Source
|
3
|
+
def initialize(event)
|
4
|
+
@event = event
|
5
|
+
env = Jets::Controller::Rack::Env.new(@event, {}).convert # convert to Rack env
|
6
|
+
@source_request = Rack::Request.new(env)
|
7
|
+
end
|
8
|
+
|
9
|
+
def body
|
10
|
+
if @source_request.body.respond_to?(:read)
|
11
|
+
body = @source_request.body.read
|
12
|
+
@source_request.body.rewind
|
13
|
+
end
|
14
|
+
body
|
15
|
+
end
|
16
|
+
|
17
|
+
def content_length
|
18
|
+
@source_request.content_length.to_i
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Based on Rails MiddlewareStackProxy
|
2
2
|
#
|
3
|
-
# Configurator is a
|
3
|
+
# Configurator is a recorder for the Jets middleware stack that allows
|
4
4
|
# you to configure middlewares in your application. It works basically as a
|
5
5
|
# command recorder, saving each command to be applied after initialization
|
6
6
|
# over the default middleware stack, so you can add, swap, or remove any
|
@@ -8,9 +8,9 @@ module Jets::Middleware
|
|
8
8
|
|
9
9
|
def build_stack
|
10
10
|
Stack.new do |middleware|
|
11
|
-
middleware.use Jets::Controller::Middleware::Local # mimics AWS Lambda for local server only
|
12
11
|
middleware.use Rack::Runtime
|
13
|
-
middleware.use Rack::MethodOverride
|
12
|
+
middleware.use Rack::MethodOverride # must come before Middleware::Local for multipart post forms to work
|
13
|
+
middleware.use Jets::Controller::Middleware::Local # mimics AWS Lambda for local server only
|
14
14
|
middleware.use session_store, session_options # use session_store, session_options
|
15
15
|
middleware.use Rack::Head
|
16
16
|
middleware.use Rack::ConditionalGet
|
data/lib/jets/resource.rb
CHANGED
@@ -11,6 +11,7 @@ class Jets::Resource
|
|
11
11
|
autoload :Iam, 'jets/resource/iam'
|
12
12
|
autoload :Permission, 'jets/resource/permission'
|
13
13
|
autoload :Replacer, 'jets/resource/replacer'
|
14
|
+
autoload :Route53, 'jets/resource/route53'
|
14
15
|
autoload :S3, 'jets/resource/s3'
|
15
16
|
autoload :Sns, 'jets/resource/sns'
|
16
17
|
autoload :Standardizer, 'jets/resource/standardizer'
|
@@ -1,7 +1,9 @@
|
|
1
1
|
module Jets::Resource::ApiGateway
|
2
|
-
autoload :
|
3
|
-
autoload :
|
2
|
+
autoload :BasePath, 'jets/resource/api_gateway/base_path'
|
3
|
+
autoload :Cors, 'jets/resource/api_gateway/cors'
|
4
4
|
autoload :Deployment, 'jets/resource/api_gateway/deployment'
|
5
|
+
autoload :DomainName, 'jets/resource/api_gateway/domain_name'
|
5
6
|
autoload :Method, 'jets/resource/api_gateway/method'
|
6
|
-
autoload :
|
7
|
+
autoload :Resource, 'jets/resource/api_gateway/resource'
|
8
|
+
autoload :RestApi, 'jets/resource/api_gateway/rest_api'
|
7
9
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Jets::Resource::ApiGateway::BasePath
|
2
|
+
class Function < Jets::Resource::Base
|
3
|
+
include Jets::Resource::Function::Environment
|
4
|
+
|
5
|
+
def definition
|
6
|
+
{
|
7
|
+
base_path_function: {
|
8
|
+
type: "AWS::Lambda::Function",
|
9
|
+
properties: {
|
10
|
+
function_name: function_name,
|
11
|
+
code: {
|
12
|
+
s3_bucket: "!Ref S3Bucket",
|
13
|
+
s3_key: code_s3_key,
|
14
|
+
},
|
15
|
+
role: "!GetAtt BasePathRole.Arn",
|
16
|
+
handler: handler,
|
17
|
+
runtime: "ruby2.5",
|
18
|
+
timeout: 60,
|
19
|
+
memory_size: 1536,
|
20
|
+
environment: env_properties[:environment],
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def function_name
|
27
|
+
method = "jets-base-path"
|
28
|
+
# need to add the deployment timestamp because or else function name collides between deploys
|
29
|
+
timestamp = Jets::Resource::ApiGateway::Deployment.timestamp
|
30
|
+
"#{Jets.config.project_namespace}-#{method}-#{timestamp}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def handler
|
34
|
+
"handlers/functions/jets/base_path.lambda_handler"
|
35
|
+
end
|
36
|
+
|
37
|
+
def code_s3_key
|
38
|
+
checksum = Jets::Builders::Md5.checksums["stage/code"]
|
39
|
+
"jets/code/code-#{checksum}.zip" # s3_key
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# CloudFormation Docs AWS::ApiGateway::DomainName: https://amzn.to/2BsrSqo
|
2
|
+
#
|
3
|
+
# Example:
|
4
|
+
#
|
5
|
+
# Type: AWS::ApiGateway::BasePathMapping
|
6
|
+
# Properties:
|
7
|
+
# BasePath: String
|
8
|
+
# DomainName: String
|
9
|
+
# RestApiId: String
|
10
|
+
# Stage: String
|
11
|
+
#
|
12
|
+
# Currently unable to add base path mapping in-place with CloudFormation.
|
13
|
+
# The workaround for this is to do it post deployment with raw API calls outside
|
14
|
+
# of CloudFormation. Leaving this around for now in case there's a workaround
|
15
|
+
# to get this into CloudFormation instead of raw API calls. Some notes:
|
16
|
+
# * Also tried to change the domain name of to something like demo-dev-[random].mydomain.com
|
17
|
+
# That does not work because the domain name has to match the route53 record exactly.
|
18
|
+
#
|
19
|
+
module Jets::Resource::ApiGateway::BasePath
|
20
|
+
class Mapping < Jets::Resource::Base
|
21
|
+
def definition
|
22
|
+
function_logical_id = "BasePathFunction" # lambda function that supports custom resource
|
23
|
+
{
|
24
|
+
base_path_mapping: {
|
25
|
+
type: "Custom::BasePathMapping",
|
26
|
+
properties: {
|
27
|
+
service_token: "!GetAtt #{function_logical_id}.Arn",
|
28
|
+
# base_path: '', # empty path represents root
|
29
|
+
# domain_name: "!Ref DomainName",
|
30
|
+
# rest_api_id: "!Ref RestApi", # since this is in the Deployment template
|
31
|
+
# stage: Deployment.stage_name,
|
32
|
+
},
|
33
|
+
depends_on: Jets::Resource::ApiGateway::Deployment.logical_id,
|
34
|
+
}
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def outputs
|
39
|
+
{
|
40
|
+
"BasePathMapping" => "!Ref BasePathMapping",
|
41
|
+
}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Jets::Resource::ApiGateway::BasePath
|
2
|
+
class Role < Jets::Resource::Base
|
3
|
+
extend Memoist
|
4
|
+
include Jets::AwsServices
|
5
|
+
|
6
|
+
def definition
|
7
|
+
{
|
8
|
+
base_path_role: {
|
9
|
+
type: "AWS::IAM::Role",
|
10
|
+
properties: {
|
11
|
+
role_name: role_name,
|
12
|
+
path: "/",
|
13
|
+
assume_role_policy_document: {
|
14
|
+
version: "2012-10-17",
|
15
|
+
statement: [{
|
16
|
+
effect: "Allow",
|
17
|
+
principal: {service: ["lambda.amazonaws.com"]},
|
18
|
+
action: ["sts:AssumeRole"]}
|
19
|
+
]
|
20
|
+
},
|
21
|
+
policies: [
|
22
|
+
policy_name: "#{role_name}-policy",
|
23
|
+
policy_document: policy_document,
|
24
|
+
]
|
25
|
+
},
|
26
|
+
}
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def policy_document
|
31
|
+
project_namespace = Jets.config.project_namespace
|
32
|
+
default_policy_statements = Jets::Application.default_iam_policy # Array of Hashes
|
33
|
+
apigateway = [{
|
34
|
+
action: [ "apigateway:*" ],
|
35
|
+
effect: "Allow",
|
36
|
+
resource: "arn:aws:apigateway:#{Jets.aws.region}::/restapis/*", # scoped to all restapis because this changes
|
37
|
+
},{
|
38
|
+
action: [ "apigateway:*" ],
|
39
|
+
effect: "Allow",
|
40
|
+
resource: "arn:aws:apigateway:#{Jets.aws.region}::/domainnames/*", # scoped to all restapis because this changes
|
41
|
+
}]
|
42
|
+
cloudformation = [{
|
43
|
+
action: ["cloudformation:DescribeStacks"],
|
44
|
+
effect: "Allow",
|
45
|
+
resource: "arn:aws:cloudformation:#{Jets.aws.region}:#{Jets.aws.account}:stack/#{project_namespace}*",
|
46
|
+
}]
|
47
|
+
|
48
|
+
# Combine the statements
|
49
|
+
{
|
50
|
+
version: '2012-10-17',
|
51
|
+
statement: default_policy_statements + apigateway + cloudformation
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
# Duplicated in rest_api/change_detection.rb, base_path/role.rb, rest_api/routes.rb
|
56
|
+
def rest_api_id
|
57
|
+
stack_name = Jets::Naming.parent_stack_name
|
58
|
+
return default unless stack_exists?(stack_name)
|
59
|
+
|
60
|
+
stack = cfn.describe_stacks(stack_name: stack_name).stacks.first
|
61
|
+
|
62
|
+
api_gateway_stack_arn = lookup(stack[:outputs], "ApiGateway")
|
63
|
+
|
64
|
+
# resources = cfn.describe_stack_resources(stack_name: api_gateway_stack_arn).stack_resources
|
65
|
+
stack = cfn.describe_stacks(stack_name: api_gateway_stack_arn).stacks.first
|
66
|
+
rest_api_id = lookup(stack[:outputs], "RestApi")
|
67
|
+
end
|
68
|
+
memoize :rest_api_id
|
69
|
+
|
70
|
+
def role_name
|
71
|
+
# TODO: dont think we should change the role name every time but have to right now because the deployment logical id changes
|
72
|
+
timestamp = Jets::Resource::ApiGateway::Deployment.timestamp
|
73
|
+
"#{Jets.config.project_namespace}-base-path-mapping-#{timestamp}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -9,7 +9,7 @@ module Jets::Resource::ApiGateway
|
|
9
9
|
|
10
10
|
properties: {
|
11
11
|
resource_id: "!Ref #{resource_id}",
|
12
|
-
rest_api_id: "!Ref RestApi",
|
12
|
+
rest_api_id: "!Ref #{RestApi.logical_id}",
|
13
13
|
authorization_type: authorization_type,
|
14
14
|
http_method: "OPTIONS",
|
15
15
|
method_responses: [{
|
@@ -6,23 +6,27 @@ module Jets::Resource::ApiGateway
|
|
6
6
|
type: "AWS::ApiGateway::Deployment",
|
7
7
|
properties: {
|
8
8
|
description: "Version #{timestamp} deployed by jets",
|
9
|
-
rest_api_id: "!Ref RestApi",
|
9
|
+
rest_api_id: "!Ref #{RestApi.logical_id}",
|
10
10
|
stage_name: stage_name,
|
11
11
|
}
|
12
12
|
}
|
13
13
|
}
|
14
14
|
end
|
15
15
|
|
16
|
-
# value is Description
|
17
16
|
def parameters
|
18
|
-
{
|
17
|
+
p = {
|
18
|
+
"IamRole" => "IamRole",
|
19
19
|
"RestApi" => "RestApi",
|
20
|
+
"S3Bucket" => "S3Bucket",
|
20
21
|
}
|
22
|
+
p[:DomainName] = "DomainName" if Jets.custom_domain?
|
23
|
+
p
|
21
24
|
end
|
22
25
|
|
23
|
-
def outputs
|
26
|
+
def outputs(internal=false)
|
27
|
+
rest_api = internal ? RestApi.internal_logical_id : "RestApi"
|
24
28
|
{
|
25
|
-
"RestApiUrl" => "!Sub 'https://${
|
29
|
+
"RestApiUrl" => "!Sub 'https://${#{rest_api}}.execute-api.${AWS::Region}.amazonaws.com/#{stage_name}/'",
|
26
30
|
}
|
27
31
|
end
|
28
32
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# CloudFormation Docs AWS::ApiGateway::DomainName: https://amzn.to/2Bsnmbq
|
2
|
+
#
|
3
|
+
# Example:
|
4
|
+
#
|
5
|
+
# MyDomainName:
|
6
|
+
# Type: 'AWS::ApiGateway::DomainName'
|
7
|
+
# Properties:
|
8
|
+
# DomainName: api.mydomain.com
|
9
|
+
# CertificateArn: arn:aws:acm:us-east-1:111122223333:certificate/fb1b9770-a305-495d-aefb-27e5e101ff3
|
10
|
+
#
|
11
|
+
module Jets::Resource::ApiGateway
|
12
|
+
class DomainName < Jets::Resource::Base
|
13
|
+
def definition
|
14
|
+
properties = {
|
15
|
+
domain_name: domain_name,
|
16
|
+
endpoint_configuration: {
|
17
|
+
types: endpoint_types
|
18
|
+
}
|
19
|
+
}
|
20
|
+
# Can really only be REGIONAL or EDGE
|
21
|
+
if endpoint_types.include?("REGIONAL")
|
22
|
+
properties[:regional_certificate_arn] = cert_arn
|
23
|
+
end
|
24
|
+
if endpoint_types.include?("EDGE")
|
25
|
+
properties[:certificate_arn] = cert_arn
|
26
|
+
end
|
27
|
+
|
28
|
+
{
|
29
|
+
domain_name: {
|
30
|
+
type: "AWS::ApiGateway::DomainName",
|
31
|
+
properties: properties
|
32
|
+
}
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def outputs
|
37
|
+
{
|
38
|
+
"DomainName" => "!Ref DomainName",
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def domain_name
|
43
|
+
subdomain = Jets.project_namespace
|
44
|
+
managed_domain_name = "#{subdomain}.#{Jets.config.domain.hosted_zone_name}"
|
45
|
+
Jets.config.domain.name || managed_domain_name
|
46
|
+
end
|
47
|
+
|
48
|
+
def endpoint_types
|
49
|
+
[Jets.config.domain.endpoint_type].flatten
|
50
|
+
end
|
51
|
+
|
52
|
+
def cert_arn
|
53
|
+
Jets.config.domain.cert_arn
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require "active_support/core_ext/object"
|
2
|
-
|
3
1
|
# Converts a Jets::Route to a CloudFormation Jets::Resource::ApiGateway::Method resource
|
4
2
|
module Jets::Resource::ApiGateway
|
5
3
|
class Method < Jets::Resource::Base
|
@@ -18,7 +16,7 @@ module Jets::Resource::ApiGateway
|
|
18
16
|
type: "AWS::ApiGateway::Method",
|
19
17
|
properties: {
|
20
18
|
resource_id: "!Ref #{resource_id}",
|
21
|
-
rest_api_id: "!Ref RestApi",
|
19
|
+
rest_api_id: "!Ref #{RestApi.logical_id}",
|
22
20
|
http_method: @route.method,
|
23
21
|
request_parameters: {},
|
24
22
|
authorization_type: authorization_type,
|
@@ -47,7 +45,8 @@ module Jets::Resource::ApiGateway
|
|
47
45
|
.gsub(/[^0-9a-z]/i, ' ')
|
48
46
|
.gsub(/\s+/, '_')
|
49
47
|
path = nil if path == ''
|
50
|
-
|
48
|
+
http_verb = @route.method.downcase
|
49
|
+
[path, "{namespace}_#{http_verb}_api_method"].compact.join('_')
|
51
50
|
end
|
52
51
|
|
53
52
|
def replacements
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module Jets::Resource::ApiGateway
|
2
2
|
class Resource < Jets::Resource::Base
|
3
|
-
def initialize(path)
|
3
|
+
def initialize(path, internal: false)
|
4
4
|
@path = path # Examples: "posts/:id/edit" or "posts"
|
5
|
+
@internal = internal
|
5
6
|
end
|
6
7
|
|
7
8
|
def definition
|
@@ -11,7 +12,7 @@ module Jets::Resource::ApiGateway
|
|
11
12
|
properties: {
|
12
13
|
parent_id: parent_id,
|
13
14
|
path_part: path_part,
|
14
|
-
rest_api_id: "!Ref RestApi",
|
15
|
+
rest_api_id: "!Ref #{RestApi.logical_id(@internal)}",
|
15
16
|
}
|
16
17
|
}
|
17
18
|
}
|
@@ -42,7 +43,7 @@ module Jets::Resource::ApiGateway
|
|
42
43
|
parent_logical_id = path_logical_id(parent_path)
|
43
44
|
"!Ref #{parent_logical_id}ApiResource"
|
44
45
|
else
|
45
|
-
"!GetAtt RestApi.RootResourceId"
|
46
|
+
"!GetAtt #{RestApi.logical_id(@internal)}.RootResourceId"
|
46
47
|
end
|
47
48
|
end
|
48
49
|
|
@@ -1,32 +1,60 @@
|
|
1
1
|
module Jets::Resource::ApiGateway
|
2
2
|
class RestApi < Jets::Resource::Base
|
3
|
+
autoload :ChangeDetection, 'jets/resource/api_gateway/rest_api/change_detection'
|
4
|
+
autoload :LogicalId, 'jets/resource/api_gateway/rest_api/logical_id'
|
5
|
+
autoload :Routes, 'jets/resource/api_gateway/rest_api/routes'
|
3
6
|
|
4
7
|
def definition
|
8
|
+
properties = {
|
9
|
+
name: Jets::Naming.gateway_api_name,
|
10
|
+
endpoint_configuration: { types: endpoint_types }
|
11
|
+
}
|
12
|
+
properties[:binary_media_types] = binary_media_types if binary_media_types
|
13
|
+
|
5
14
|
{
|
6
|
-
|
15
|
+
internal_logical_id => {
|
7
16
|
type: "AWS::ApiGateway::RestApi",
|
8
|
-
properties:
|
9
|
-
name: Jets::Naming.gateway_api_name,
|
10
|
-
endpoint_configuration: {
|
11
|
-
types: types
|
12
|
-
}
|
13
|
-
# binary_media_types: ['*/*'], # TODO: comment out, breaking form post
|
14
|
-
}
|
17
|
+
properties: properties
|
15
18
|
}
|
16
19
|
}
|
17
20
|
end
|
18
|
-
|
21
|
+
|
22
|
+
def internal_logical_id
|
23
|
+
self.class.logical_id(true)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.logical_id(internal=false)
|
27
|
+
internal ? internal_logical_id : "RestApi"
|
28
|
+
end
|
29
|
+
|
30
|
+
@@internal_logical_id = nil
|
31
|
+
def self.internal_logical_id
|
32
|
+
@@internal_logical_id ||= LogicalId.new.get
|
33
|
+
end
|
34
|
+
|
19
35
|
def outputs
|
20
36
|
{
|
21
|
-
"RestApi" => "!Ref
|
37
|
+
"RestApi" => "!Ref #{internal_logical_id}",
|
22
38
|
"Region" => "!Ref AWS::Region",
|
23
|
-
"RootResourceId" => "!GetAtt
|
39
|
+
"RootResourceId" => "!GetAtt #{internal_logical_id}.RootResourceId",
|
24
40
|
}
|
25
41
|
end
|
26
42
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
43
|
+
def endpoint_types
|
44
|
+
[Jets.config.api.endpoint_type].flatten
|
45
|
+
end
|
46
|
+
|
47
|
+
# TODO: Looks like there's a bug with CloudFormation. On an API Gateway update
|
48
|
+
# we need to pass in the escaped version: multipart~1form-data
|
49
|
+
# On a brand new API Gateway creation, we need to pass in the unescaped form:
|
50
|
+
# multipart/form-data
|
51
|
+
# We are handling this with a full API Gateway replacement instead because it
|
52
|
+
# can be generalized more easily.
|
53
|
+
def binary_media_types
|
54
|
+
types = Jets.config.api.binary_media_types
|
55
|
+
return nil if types.nil? || types.empty?
|
56
|
+
|
57
|
+
[types].flatten
|
30
58
|
end
|
31
59
|
end
|
32
60
|
end
|