diff --git a/docs/cloudformation_compatibility.rst b/docs/cloudformation_compatibility.rst index fcce6ef052..9118c33955 100644 --- a/docs/cloudformation_compatibility.rst +++ b/docs/cloudformation_compatibility.rst @@ -171,6 +171,7 @@ BinaryMediaTypes All MinimumCompressionSize All Cors All TracingEnabled All +OpenApiVersion None ================================== ======================== ======================== diff --git a/docs/globals.rst b/docs/globals.rst index c0878242e8..c409da5f40 100644 --- a/docs/globals.rst +++ b/docs/globals.rst @@ -88,6 +88,7 @@ Currently, the following resources and properties are being supported: AccessLogSetting: CanarySetting: TracingEnabled: + OpenApiVersion: SimpleTable: # Properties of AWS::Serverless::SimpleTable diff --git a/samtranslator/model/api/api_generator.py b/samtranslator/model/api/api_generator.py index 4946f4d92e..be60b0d5aa 100644 --- a/samtranslator/model/api/api_generator.py +++ b/samtranslator/model/api/api_generator.py @@ -1,5 +1,6 @@ from collections import namedtuple from six import string_types +import re from samtranslator.model.intrinsics import ref from samtranslator.model.apigateway import (ApiGatewayDeployment, ApiGatewayRestApi, @@ -31,7 +32,8 @@ def __init__(self, logical_id, cache_cluster_enabled, cache_cluster_size, variab definition_body, definition_uri, name, stage_name, endpoint_configuration=None, method_settings=None, binary_media=None, minimum_compression_size=None, cors=None, auth=None, gateway_responses=None, access_log_setting=None, canary_setting=None, - tracing_enabled=None, resource_attributes=None, passthrough_resource_attributes=None): + tracing_enabled=None, resource_attributes=None, passthrough_resource_attributes=None, + open_api_version=None): """Constructs an API Generator class that generates API Gateway resources :param logical_id: Logical id of the SAM API Resource @@ -70,6 +72,7 @@ def __init__(self, logical_id, cache_cluster_enabled, cache_cluster_size, variab self.tracing_enabled = tracing_enabled self.resource_attributes = resource_attributes self.passthrough_resource_attributes = passthrough_resource_attributes + self.open_api_version = open_api_version def _construct_rest_api(self): """Constructs and returns the ApiGateway RestApi. @@ -93,6 +96,11 @@ def _construct_rest_api(self): raise InvalidResourceException(self.logical_id, "Specify either 'DefinitionUri' or 'DefinitionBody' property and not both") + if self.open_api_version: + if re.match(SwaggerEditor.get_openapi_versions_supported_regex(), self.open_api_version) is None: + raise InvalidResourceException( + self.logical_id, "The OpenApiVersion value must be of the format 3.0.0") + self._add_cors() self._add_auth() self._add_gateway_responses() @@ -137,7 +145,7 @@ def _construct_body_s3_dict(self): body_s3['Version'] = s3_pointer['Version'] return body_s3 - def _construct_deployment(self, rest_api): + def _construct_deployment(self, rest_api, open_api_version): """Constructs and returns the ApiGateway Deployment. :param model.apigateway.ApiGatewayRestApi rest_api: the RestApi for this Deployment @@ -147,7 +155,8 @@ def _construct_deployment(self, rest_api): deployment = ApiGatewayDeployment(self.logical_id + 'Deployment', attributes=self.passthrough_resource_attributes) deployment.RestApiId = rest_api.get_runtime_attr('rest_api_id') - deployment.StageName = 'Stage' + if not self.open_api_version: + deployment.StageName = 'Stage' return deployment @@ -189,7 +198,7 @@ def to_cloudformation(self): """ rest_api = self._construct_rest_api() - deployment = self._construct_deployment(rest_api) + deployment = self._construct_deployment(rest_api, self.open_api_version) swagger = None if rest_api.Body is not None: diff --git a/samtranslator/model/apigateway.py b/samtranslator/model/apigateway.py index c59983e19d..37347ebdc6 100644 --- a/samtranslator/model/apigateway.py +++ b/samtranslator/model/apigateway.py @@ -66,7 +66,7 @@ class ApiGatewayDeployment(Resource): 'Description': PropertyType(False, is_str()), 'RestApiId': PropertyType(True, is_str()), 'StageDescription': PropertyType(False, is_type(dict)), - 'StageName': PropertyType(True, is_str()) + 'StageName': PropertyType(False, is_str()) } runtime_attrs = { diff --git a/samtranslator/model/sam_resources.py b/samtranslator/model/sam_resources.py index 66008dee57..778143b67f 100644 --- a/samtranslator/model/sam_resources.py +++ b/samtranslator/model/sam_resources.py @@ -445,7 +445,8 @@ class SamApi(SamResourceMacro): 'GatewayResponses': PropertyType(False, is_type(dict)), 'AccessLogSetting': PropertyType(False, is_type(dict)), 'CanarySetting': PropertyType(False, is_type(dict)), - 'TracingEnabled': PropertyType(False, is_type(bool)) + 'TracingEnabled': PropertyType(False, is_type(bool)), + 'OpenApiVersion': PropertyType(False, is_str()) } referable_properties = { @@ -483,7 +484,8 @@ def to_cloudformation(self, **kwargs): canary_setting=self.CanarySetting, tracing_enabled=self.TracingEnabled, resource_attributes=self.resource_attributes, - passthrough_resource_attributes=self.get_passthrough_resource_attributes()) + passthrough_resource_attributes=self.get_passthrough_resource_attributes(), + open_api_version=self.OpenApiVersion) rest_api, deployment, stage, permissions = api_generator.to_cloudformation() diff --git a/samtranslator/plugins/globals/globals.py b/samtranslator/plugins/globals/globals.py index f74029b99c..1e5702ccc7 100644 --- a/samtranslator/plugins/globals/globals.py +++ b/samtranslator/plugins/globals/globals.py @@ -1,5 +1,7 @@ from samtranslator.public.sdk.resource import SamResourceType from samtranslator.public.intrinsics import is_intrinsics +from samtranslator.swagger.swagger import SwaggerEditor +import re class Globals(object): @@ -11,6 +13,9 @@ class Globals(object): # Key of the dictionary containing Globals section in SAM template _KEYWORD = "Globals" _RESOURCE_PREFIX = "AWS::Serverless::" + _OPENAPIVERSION = "OpenApiVersion" + _API_TYPE = "AWS::Serverless::Api" + _MANAGE_SWAGGER = "__MANAGE_SWAGGER" supported_properties = { # Everything on Serverless::Function except Role, Policies, FunctionName, Events @@ -53,7 +58,8 @@ class Globals(object): "GatewayResponses", "AccessLogSetting", "CanarySetting", - "TracingEnabled" + "TracingEnabled", + "OpenApiVersion" ], SamResourceType.SimpleTable.value: [ @@ -68,7 +74,7 @@ def __init__(self, template): :param dict template: SAM template to be parsed """ self.supported_resource_section_names = ([x.replace(self._RESOURCE_PREFIX, "") - for x in self.supported_properties.keys()]) + for x in self.supported_properties.keys()]) # Sort the names for stability in list ordering self.supported_resource_section_names.sort() @@ -107,6 +113,36 @@ def del_section(cls, template): if cls._KEYWORD in template: del template[cls._KEYWORD] + @classmethod + def fix_openapi_definitions(cls, template): + """ + Helper method to postprocess the resources to make sure the swagger doc version matches + the one specified on the resource with flag OpenApiVersion. + + This is done postprocess in globals because, the implicit api plugin runs before globals, \ + and at that point the global flags aren't applied on each resource, so we do not know \ + whether OpenApiVersion flag is specified. Running the globals plugin before implicit api \ + was a risky change, so we decided to postprocess the openapi version here. + + To make sure we don't modify customer defined swagger, we also check for __MANAGE_SWAGGER flag. + + :param dict template: SAM template + :return: Modified SAM template with corrected swagger doc matching the OpenApiVersion. + """ + resources = template["Resources"] + + for _, resource in resources.items(): + if ("Type" in resource) and (resource["Type"] == cls._API_TYPE): + properties = resource["Properties"] + if (cls._OPENAPIVERSION in properties) and (cls._MANAGE_SWAGGER in properties) and \ + (re.match(SwaggerEditor.get_openapi_version_3_regex(), + properties[cls._OPENAPIVERSION]) is not None): + if "DefinitionBody" in properties: + definition_body = properties['DefinitionBody'] + definition_body['openapi'] = properties[cls._OPENAPIVERSION] + if definition_body.get('swagger'): + del definition_body['swagger'] + def _parse(self, globals_dict): """ Takes a SAM template as input and parses the Globals section @@ -398,6 +434,7 @@ class InvalidGlobalsSectionException(Exception): Attributes: message -- explanation of the error """ + def __init__(self, logical_id, message): self._logical_id = logical_id self._message = message diff --git a/samtranslator/plugins/globals/globals_plugin.py b/samtranslator/plugins/globals/globals_plugin.py index 086bfb81b3..3c4872773c 100644 --- a/samtranslator/plugins/globals/globals_plugin.py +++ b/samtranslator/plugins/globals/globals_plugin.py @@ -5,6 +5,8 @@ from samtranslator.plugins.globals.globals import Globals, InvalidGlobalsSectionException +_API_RESOURCE = "AWS::Serverless::Api" + class GlobalsPlugin(BasePlugin): """ @@ -38,3 +40,7 @@ def on_before_transform_template(self, template_dict): # Remove the Globals section from template if necessary Globals.del_section(template_dict) + + # If there was a global openApiVersion flag, check and convert swagger + # to the right version + Globals.fix_openapi_definitions(template_dict) diff --git a/samtranslator/swagger/swagger.py b/samtranslator/swagger/swagger.py index dc95492854..8421cc6d21 100644 --- a/samtranslator/swagger/swagger.py +++ b/samtranslator/swagger/swagger.py @@ -1,4 +1,5 @@ import copy +import re from six import string_types from samtranslator.model.intrinsics import ref @@ -554,10 +555,14 @@ def is_valid(data): :param dict data: Data to be validated :return: True, if data is a Swagger """ - return bool(data) and \ - isinstance(data, dict) and \ - bool(data.get("swagger")) and \ - isinstance(data.get('paths'), dict) + + if bool(data) and isinstance(data, dict) and isinstance(data.get('paths'), dict): + if bool(data.get("swagger")): + return True + elif bool(data.get("openapi")): + return re.search(SwaggerEditor.get_openapi_version_3_regex(), data["openapi"]) is not None + return False + return False @staticmethod def gen_skeleton(): @@ -595,3 +600,13 @@ def _normalize_method_name(method): return SwaggerEditor._X_ANY_METHOD else: return method + + @staticmethod + def get_openapi_versions_supported_regex(): + openapi_version_supported_regex = r"\A[2-3](\.\d)(\.\d)?$" + return openapi_version_supported_regex + + @staticmethod + def get_openapi_version_3_regex(): + openapi_version_3_regex = r"\A3(\.\d)(\.\d)?$" + return openapi_version_3_regex diff --git a/tests/model/test_sam_resources.py b/tests/model/test_sam_resources.py index 73cfdd2635..ff59a063e7 100644 --- a/tests/model/test_sam_resources.py +++ b/tests/model/test_sam_resources.py @@ -5,7 +5,10 @@ from samtranslator.intrinsics.resolver import IntrinsicsResolver from samtranslator.model import InvalidResourceException from samtranslator.model.lambda_ import LambdaFunction, LambdaVersion +from samtranslator.model.apigateway import ApiGatewayRestApi +from samtranslator.model.apigateway import ApiGatewayDeployment from samtranslator.model.sam_resources import SamFunction +from samtranslator.model.sam_resources import SamApi class TestCodeUri(TestCase): @@ -70,3 +73,51 @@ def test_with_version_description(self): cfnResources = function.to_cloudformation(**self.kwargs) generateFunctionVersion = [x for x in cfnResources if isinstance(x, LambdaVersion)] self.assertEqual(generateFunctionVersion[0].Description, test_description) + +class TestOpenApi(TestCase): + kwargs = { + 'intrinsics_resolver': IntrinsicsResolver({}), + 'event_resources': [], + 'managed_policy_map': { + "foo": "bar" + } + } + + @patch('boto3.session.Session.region_name', 'ap-southeast-1') + def test_with_open_api_3_no_stage(self): + api = SamApi("foo") + api.OpenApiVersion = "3.0" + + resources = api.to_cloudformation(**self.kwargs) + deployment = [x for x in resources if isinstance(x, ApiGatewayDeployment)] + + self.assertEqual(deployment.__len__(), 1) + self.assertEqual(deployment[0].StageName, None) + + @patch('boto3.session.Session.region_name', 'ap-southeast-1') + def test_with_open_api_2_no_stage(self): + api = SamApi("foo") + api.OpenApiVersion = "3.0" + + resources = api.to_cloudformation(**self.kwargs) + deployment = [x for x in resources if isinstance(x, ApiGatewayDeployment)] + + self.assertEqual(deployment.__len__(), 1) + self.assertEqual(deployment[0].StageName, None) + + @patch('boto3.session.Session.region_name', 'ap-southeast-1') + def test_with_open_api_bad_value(self): + api = SamApi("foo") + api.OpenApiVersion = "5.0" + with pytest.raises(InvalidResourceException): + api.to_cloudformation(**self.kwargs) + + @patch('boto3.session.Session.region_name', 'ap-southeast-1') + def test_with_swagger_no_stage(self): + api = SamApi("foo") + + resources = api.to_cloudformation(**self.kwargs) + deployment = [x for x in resources if isinstance(x, ApiGatewayDeployment)] + + self.assertEqual(deployment.__len__(), 1) + self.assertEqual(deployment[0].StageName, "Stage") diff --git a/tests/plugins/globals/test_globals.py b/tests/plugins/globals/test_globals.py index 00e30fbb53..5d233f1288 100644 --- a/tests/plugins/globals/test_globals.py +++ b/tests/plugins/globals/test_globals.py @@ -657,3 +657,165 @@ def test_merge_end_to_end_unknown_type(self): result = globals.merge(type, properties) self.assertEqual(expected, result) + +class TestGlobalsOpenApi(TestCase): + template = { + "Globals": { + "Api": { + "OpenApiVersion": "3.0" + } + } + } + + table_driven = [ + { + "name": "happy case", + "input": { + "Resources": { + "MyApi": { + "Type": "AWS::Serverless::Api", + "Properties": { + "__MANAGE_SWAGGER": True, + "OpenApiVersion": "3.0", + "DefinitionBody": { + "swagger": "2.0" + } + } + } + } + }, + "expected": { + "Resources": { + "MyApi": { + "Type": "AWS::Serverless::Api", + "Properties": { + "__MANAGE_SWAGGER": True, + "OpenApiVersion": "3.0", + "DefinitionBody": { + "openapi": "3.0" + } + } + } + } + } + }, + { + "name": "no openapi", + "input": { + "Resources": { + "MyApi": { + "Type": "AWS::Serverless::Api", + "Properties": { + "DefinitionBody": { + "swagger": "2.0" + } + } + } + } + }, + "expected": { + "Resources": { + "MyApi": { + "Type": "AWS::Serverless::Api", + "Properties": { + "DefinitionBody": { + "swagger": "2.0" + } + } + } + } + } + }, + { + "name": "Openapi set to 2.0", + "input": { + "Resources": { + "MyApi": { + "Type": "AWS::Serverless::Api", + "Properties": { + "__MANAGE_SWAGGER": True, + "OpenApiVersion": "2.0", + "DefinitionBody": { + "swagger": "2.0" + } + } + } + } + }, + "expected": { + "Resources": { + "MyApi": { + "Type": "AWS::Serverless::Api", + "Properties": { + "__MANAGE_SWAGGER": True, + "OpenApiVersion": "2.0", + "DefinitionBody": { + "swagger": "2.0" + } + } + } + } + } + }, + { + "name": "No definition body", + "input": { + "Resources": { + "MyApi": { + "Type": "AWS::Serverless::Api", + "Properties": { + "__MANAGE_SWAGGER": True, + "OpenApiVersion": "3.0" + } + } + } + }, + "expected": { + "Resources": { + "MyApi": { + "Type": "AWS::Serverless::Api", + "Properties": { + "__MANAGE_SWAGGER": True, + "OpenApiVersion": "3.0" + } + } + } + } + }, + { + "name": "ignore customer defined swagger", + "input": { + "Resources": { + "MyApi": { + "Type": "AWS::Serverless::Api", + "Properties": { + "OpenApiVersion": "3.0", + "DefinitionBody": { + "swagger": "2.0" + } + } + } + } + }, + "expected": { + "Resources": { + "MyApi": { + "Type": "AWS::Serverless::Api", + "Properties": { + "OpenApiVersion": "3.0", + "DefinitionBody": { + "swagger": "2.0" + } + } + } + } + } + }, + + ] + + def test_openapi_postprocess(self): + for test in self.table_driven: + global_obj = Globals(self.template) + global_obj.fix_openapi_definitions(test["input"]) + self.assertEqual(test["input"], test["expected"], test["name"]) diff --git a/tests/swagger/test_swagger.py b/tests/swagger/test_swagger.py index 3882092132..d7277bb518 100644 --- a/tests/swagger/test_swagger.py +++ b/tests/swagger/test_swagger.py @@ -33,6 +33,44 @@ def test_must_succeed_on_valid_swagger(self): self.assertEqual(editor.paths, {"/foo": {}, "/bar": {}}) + def test_must_fail_on_invalid_openapi_version(self): + invalid_swagger = { + "openapi": "2.3.0", + "paths": { + "/foo": {}, + "/bar": {} + } + } + + with self.assertRaises(ValueError): + SwaggerEditor(invalid_swagger) + + def test_must_fail_on_invalid_openapi_version_2(self): + invalid_swagger = { + "openapi": "3.1.1.1", + "paths": { + "/foo": {}, + "/bar": {} + } + } + + with self.assertRaises(ValueError): + SwaggerEditor(invalid_swagger) + + def test_must_succeed_on_valid_openapi3(self): + valid_swagger = { + "openapi": "3.0.1", + "paths": { + "/foo": {}, + "/bar": {} + } + } + + editor = SwaggerEditor(valid_swagger) + self.assertIsNotNone(editor) + + self.assertEqual(editor.paths, {"/foo": {}, "/bar": {}}) + class TestSwaggerEditor_has_path(TestCase): diff --git a/tests/translator/input/api_with_cors_openapi_3.yaml b/tests/translator/input/api_with_cors_openapi_3.yaml new file mode 100644 index 0000000000..7465b9ee76 --- /dev/null +++ b/tests/translator/input/api_with_cors_openapi_3.yaml @@ -0,0 +1,82 @@ +Globals: + Api: + Cors: { + "Fn::Join": [",", ["www.amazon.com", "www.google.com"]] + } + OpenApiVersion: '3.0' + + +Resources: + ImplicitApiFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/member_portal.zip + Handler: index.gethtml + Runtime: nodejs4.3 + Events: + GetHtml: + Type: Api + Properties: + Path: / + Method: get + AnyApi: + Type: Api + Properties: + Path: /foo + Method: any + RestApiFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/member_portal.zip + Handler: index.handler + Runtime: nodejs8.10 + GetHtmlFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/member_portal.zip + Handler: index.handler + Runtime: nodejs8.10 + ExplicitApi: + Type: AWS::Serverless::Api + Properties: + StageName: Prod + DefinitionBody: { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/add": { + "post": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${RestApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + }, + "/{proxy+}": { + "x-amazon-apigateway-any-method": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetHtmlFunction.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "swagger": "2.0" + } + Cors: + AllowMethods: "methods" + AllowHeaders: "headers" + AllowOrigin: "origins" + AllowCredentials: true diff --git a/tests/translator/input/api_with_gateway_responses_all_openapi_3.yaml b/tests/translator/input/api_with_gateway_responses_all_openapi_3.yaml new file mode 100644 index 0000000000..fe88f63d54 --- /dev/null +++ b/tests/translator/input/api_with_gateway_responses_all_openapi_3.yaml @@ -0,0 +1,38 @@ +Resources: + Function: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/member_portal.zip + Handler: index.gethtml + Runtime: nodejs4.3 + Events: + GetHtml: + Type: Api + Properties: + Path: / + Method: get + RestApiId: !Ref ExplicitApi + + ExplicitApi: + Type: AWS::Serverless::Api + Properties: + StageName: Prod + OpenApiVersion: '3.0' + GatewayResponses: + UNAUTHORIZED: + StatusCode: 401 + ResponseParameters: + Headers: + Access-Control-Expose-Headers: "'WWW-Authenticate'" + Access-Control-Allow-Origin: "'*'" + WWW-Authenticate: >- + 'Bearer realm="admin"' + Paths: + PathKey: "'path-value'" + QueryStrings: + QueryStringKey: "'query-string-value'" + QUOTA_EXCEEDED: + StatusCode: 429 + ResponseParameters: + Headers: + Retry-After: "'31536000'" diff --git a/tests/translator/input/api_with_open_api_version.yaml b/tests/translator/input/api_with_open_api_version.yaml new file mode 100644 index 0000000000..dd91b26c9c --- /dev/null +++ b/tests/translator/input/api_with_open_api_version.yaml @@ -0,0 +1,22 @@ +Globals: + Api: + OpenApiVersion: '3.0.1' + Cors: '*' + +Resources: + ImplicitApiFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/member_portal.zip + Handler: index.gethtml + Runtime: nodejs8.10 + Events: + GetHtml: + Type: Api + Properties: + Path: / + Method: get + ExplicitApi: + Type: AWS::Serverless::Api + Properties: + StageName: Prod diff --git a/tests/translator/input/api_with_open_api_version_2.yaml b/tests/translator/input/api_with_open_api_version_2.yaml new file mode 100644 index 0000000000..b31fc72b93 --- /dev/null +++ b/tests/translator/input/api_with_open_api_version_2.yaml @@ -0,0 +1,22 @@ +Globals: + Api: + OpenApiVersion: '2.0' + Cors: '*' + +Resources: + ImplicitApiFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: s3://sam-demo-bucket/member_portal.zip + Handler: index.gethtml + Runtime: nodejs8.10 + Events: + GetHtml: + Type: Api + Properties: + Path: / + Method: get + ExplicitApi: + Type: AWS::Serverless::Api + Properties: + StageName: Prod diff --git a/tests/translator/input/error_api_with_invalid_open_api_version.yaml b/tests/translator/input/error_api_with_invalid_open_api_version.yaml new file mode 100644 index 0000000000..f7fcb13c10 --- /dev/null +++ b/tests/translator/input/error_api_with_invalid_open_api_version.yaml @@ -0,0 +1,21 @@ +Resources: + MyApi: + Type: AWS::Serverless::Api + Properties: + DefinitionBody: {} + OpenApiVersion: '5.0' + StageName: 'prod' + Function: + Type: AWS::Serverless::Function + Properties: + Handler: lambda.handler + CodeUri: s3://bucket/api + Runtime: nodejs8.10 + Events: + ProxyApiRoot: + Type: Api + Properties: + RestApiId: + Ref: MyApi + Path: "/" + Method: ANY diff --git a/tests/translator/input/explicit_api_openapi_3.yaml b/tests/translator/input/explicit_api_openapi_3.yaml new file mode 100644 index 0000000000..2a1bc936d1 --- /dev/null +++ b/tests/translator/input/explicit_api_openapi_3.yaml @@ -0,0 +1,50 @@ +Parameters: + MyStageName: + Type: String + Default: Production + something: + Type: String + Default: something + +Resources: + GetHtmlFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: + Bucket: sam-demo-bucket + Key: webpage.zip + Handler: index.gethtml + Runtime: nodejs4.3 + Policies: AmazonDynamoDBReadOnlyAccess + Events: + GetHtml: + Type: Api + Properties: + RestApiId: + Ref: GetHtmlApi + Path: / + Method: get + + GetHtmlApi: + Type: AWS::Serverless::Api + Properties: + Name: MyGetApi + StageName: + Ref: MyStageName + DefinitionUri: + Bucket: sam-demo-bucket + Key: webpage_swagger.json + Variables: + EndpointUri: + Ref: something + EndpointUri2: http://example.com + + ApiWithInlineSwagger: + Type: AWS::Serverless::Api + Properties: + StageName: + Ref: MyStageName + OpenApiVersion: '3.0' + DefinitionBody: + "this": "is" + "a": "inline swagger" diff --git a/tests/translator/output/api_with_cors_openapi_3.json b/tests/translator/output/api_with_cors_openapi_3.json new file mode 100644 index 0000000000..02d888397a --- /dev/null +++ b/tests/translator/output/api_with_cors_openapi_3.json @@ -0,0 +1,543 @@ +{ + "Resources": { + "ImplicitApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "ImplicitApiFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs4.3", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ImplicitApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ImplicitApiFunctionGetHtmlPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ImplicitApiFunctionAnyApiPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/*/foo", + { + "__Stage__": "Prod", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ExplicitApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/add": { + "post": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${RestApiFunction.Arn}/invocations" + } + }, + "responses": {} + }, + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Headers": "headers", + "method.response.header.Access-Control-Allow-Origin": "origins", + "method.response.header.Access-Control-Allow-Methods": "methods", + "method.response.header.Access-Control-Allow-Credentials": "'true'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Headers": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + }, + "Access-Control-Allow-Credentials": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + } + }, + "/{proxy+}": { + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Headers": "headers", + "method.response.header.Access-Control-Allow-Origin": "origins", + "method.response.header.Access-Control-Allow-Methods": "methods", + "method.response.header.Access-Control-Allow-Credentials": "'true'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Headers": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + }, + "Access-Control-Allow-Credentials": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + }, + "x-amazon-apigateway-any-method": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetHtmlFunction.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "swagger": "2.0" + } + } + }, + "GetHtmlFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ServerlessRestApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ServerlessRestApiDeployment36174ded39" + }, + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "StageName": "Prod" + } + }, + "ExplicitApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeployment3a5a78688c" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": "Prod" + } + }, + "RestApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ImplicitApiFunctionGetHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "Prod", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ExplicitApiDeployment3a5a78688c": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: 3a5a78688c9bc377d53aa4153a11f0c4f6e7364c" + } + }, + "RestApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.handler", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "RestApiFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs8.10", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ServerlessRestApiDeployment36174ded39": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "Description": "RestApi deployment id: 36174ded3978092f96669107074db6caeaaafddd" + } + }, + "ServerlessRestApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/foo": { + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Origin": { + "Fn::Join": [ + ",", + [ + "www.amazon.com", + "www.google.com" + ] + ] + }, + "method.response.header.Access-Control-Allow-Methods": "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + }, + "x-amazon-apigateway-any-method": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + }, + "/": { + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Origin": { + "Fn::Join": [ + ",", + [ + "www.amazon.com", + "www.google.com" + ] + ] + }, + "method.response.header.Access-Control-Allow-Methods": "'GET,OPTIONS'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + }, + "get": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "openapi": "3.0" + } + } + }, + "GetHtmlFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.handler", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "GetHtmlFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs8.10", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ImplicitApiFunctionAnyApiPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/*/foo", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/api_with_gateway_responses_all_openapi_3.json b/tests/translator/output/api_with_gateway_responses_all_openapi_3.json new file mode 100644 index 0000000000..357ad0e911 --- /dev/null +++ b/tests/translator/output/api_with_gateway_responses_all_openapi_3.json @@ -0,0 +1,162 @@ +{ + "Resources": { + "Function": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "FunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs4.3", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ExplicitApiDeployment47d77987a3": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: 47d77987a3152a97c89d794f2682485b9dafde5d" + } + }, + "FunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ExplicitApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/": { + "get": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Function.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "openapi": "3.0", + "x-amazon-apigateway-gateway-responses": { + "QUOTA_EXCEEDED": { + "responseParameters": { + "gatewayresponse.header.Retry-After": "'31536000'" + }, + "responseTemplates": {}, + "statusCode": "429" + }, + "UNAUTHORIZED": { + "responseParameters": { + "gatewayresponse.header.WWW-Authenticate": "'Bearer realm=\"admin\"'", + "gatewayresponse.header.Access-Control-Expose-Headers": "'WWW-Authenticate'", + "gatewayresponse.header.Access-Control-Allow-Origin": "'*'", + "gatewayresponse.path.PathKey": "'path-value'", + "gatewayresponse.querystring.QueryStringKey": "'query-string-value'" + }, + "responseTemplates": {}, + "statusCode": "401" + } + } + } + } + }, + "ExplicitApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeployment47d77987a3" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": "Prod" + } + }, + "FunctionGetHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "Function" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "Prod", + "__ApiId__": { + "Ref": "ExplicitApi" + } + } + ] + } + } + }, + "FunctionGetHtmlPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "Function" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ExplicitApi" + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/api_with_open_api_version.json b/tests/translator/output/api_with_open_api_version.json new file mode 100644 index 0000000000..1224c70597 --- /dev/null +++ b/tests/translator/output/api_with_open_api_version.json @@ -0,0 +1,218 @@ +{ + "Resources": { + "ImplicitApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "ImplicitApiFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs8.10", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ImplicitApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ImplicitApiFunctionGetHtmlPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ExplicitApiDeployment01dd43a75f": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: 01dd43a75fc0e125c678d20749bacde95d723928" + } + }, + "ImplicitApiFunctionGetHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "Prod", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ExplicitApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": {}, + "openapi": "3.0.1" + } + } + }, + "ServerlessRestApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ServerlessRestApiDeployment82c7b2e316" + }, + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "StageName": "Prod" + } + }, + "ExplicitApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeployment01dd43a75f" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": "Prod" + } + }, + "ServerlessRestApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/": { + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Origin": "*", + "method.response.header.Access-Control-Allow-Methods": "'GET,OPTIONS'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + }, + "get": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "openapi": "3.0.1" + } + } + }, + "ServerlessRestApiDeployment82c7b2e316": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "Description": "RestApi deployment id: 82c7b2e3162ebd01c9b3ccaa1fafa5cc1df94a68" + } + } + } +} diff --git a/tests/translator/output/api_with_open_api_version_2.json b/tests/translator/output/api_with_open_api_version_2.json new file mode 100644 index 0000000000..ba6e1a5fbe --- /dev/null +++ b/tests/translator/output/api_with_open_api_version_2.json @@ -0,0 +1,218 @@ +{ + "Resources": { + "ImplicitApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "ImplicitApiFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs8.10", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ImplicitApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ImplicitApiFunctionGetHtmlPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ImplicitApiFunctionGetHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "Prod", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ExplicitApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": {}, + "swagger": "2.0" + } + } + }, + "ServerlessRestApiDeploymentb9bf7835be": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "Description": "RestApi deployment id: b9bf7835be8ea0cb2c188b846e03ff6f79f4d330" + } + }, + "ExplicitApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeployment5332c373d4" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": "Prod" + } + }, + "ServerlessRestApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ServerlessRestApiDeploymentb9bf7835be" + }, + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "StageName": "Prod" + } + }, + "ServerlessRestApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/": { + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Origin": "*", + "method.response.header.Access-Control-Allow-Methods": "'GET,OPTIONS'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + }, + "get": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "swagger": "2.0" + } + } + }, + "ExplicitApiDeployment5332c373d4": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: 5332c373d45c69e6c0f562b4a419aa8eb311adc7" + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/aws-cn/api_with_cors_openapi_3.json b/tests/translator/output/aws-cn/api_with_cors_openapi_3.json new file mode 100644 index 0000000000..77acdd9cde --- /dev/null +++ b/tests/translator/output/aws-cn/api_with_cors_openapi_3.json @@ -0,0 +1,559 @@ +{ + "Resources": { + "ImplicitApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "ImplicitApiFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs4.3", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ImplicitApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ImplicitApiFunctionGetHtmlPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ImplicitApiFunctionAnyApiPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/*/foo", + { + "__Stage__": "Prod", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ExplicitApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/add": { + "post": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${RestApiFunction.Arn}/invocations" + } + }, + "responses": {} + }, + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Headers": "headers", + "method.response.header.Access-Control-Allow-Origin": "origins", + "method.response.header.Access-Control-Allow-Methods": "methods", + "method.response.header.Access-Control-Allow-Credentials": "'true'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Headers": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + }, + "Access-Control-Allow-Credentials": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + } + }, + "/{proxy+}": { + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Headers": "headers", + "method.response.header.Access-Control-Allow-Origin": "origins", + "method.response.header.Access-Control-Allow-Methods": "methods", + "method.response.header.Access-Control-Allow-Credentials": "'true'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Headers": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + }, + "Access-Control-Allow-Credentials": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + }, + "x-amazon-apigateway-any-method": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetHtmlFunction.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "GetHtmlFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ServerlessRestApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ServerlessRestApiDeployment5f2f2e0731" + }, + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "StageName": "Prod" + } + }, + "ExplicitApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeployment3a5a78688c" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": "Prod" + } + }, + "ServerlessRestApiDeployment5f2f2e0731": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "Description": "RestApi deployment id: 5f2f2e07317e5f71e17f2a1f0cb2c1833f881340" + } + }, + "RestApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ImplicitApiFunctionGetHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "Prod", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ExplicitApiDeployment3a5a78688c": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: 3a5a78688c9bc377d53aa4153a11f0c4f6e7364c" + } + }, + "RestApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.handler", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "RestApiFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs8.10", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ServerlessRestApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/foo": { + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Origin": { + "Fn::Join": [ + ",", + [ + "www.amazon.com", + "www.google.com" + ] + ] + }, + "method.response.header.Access-Control-Allow-Methods": "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + }, + "x-amazon-apigateway-any-method": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + }, + "/": { + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Origin": { + "Fn::Join": [ + ",", + [ + "www.amazon.com", + "www.google.com" + ] + ] + }, + "method.response.header.Access-Control-Allow-Methods": "'GET,OPTIONS'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + }, + "get": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "openapi": "3.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "GetHtmlFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.handler", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "GetHtmlFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs8.10", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ImplicitApiFunctionAnyApiPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/*/foo", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/aws-cn/api_with_gateway_responses_all_openapi_3.json b/tests/translator/output/aws-cn/api_with_gateway_responses_all_openapi_3.json new file mode 100644 index 0000000000..8da7e78f03 --- /dev/null +++ b/tests/translator/output/aws-cn/api_with_gateway_responses_all_openapi_3.json @@ -0,0 +1,170 @@ +{ + "Resources": { + "Function": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "FunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs4.3", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "FunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ExplicitApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/": { + "get": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Function.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "openapi": "3.0", + "x-amazon-apigateway-gateway-responses": { + "QUOTA_EXCEEDED": { + "responseParameters": { + "gatewayresponse.header.Retry-After": "'31536000'" + }, + "responseTemplates": {}, + "statusCode": "429" + }, + "UNAUTHORIZED": { + "responseParameters": { + "gatewayresponse.header.WWW-Authenticate": "'Bearer realm=\"admin\"'", + "gatewayresponse.header.Access-Control-Expose-Headers": "'WWW-Authenticate'", + "gatewayresponse.header.Access-Control-Allow-Origin": "'*'", + "gatewayresponse.path.PathKey": "'path-value'", + "gatewayresponse.querystring.QueryStringKey": "'query-string-value'" + }, + "responseTemplates": {}, + "statusCode": "401" + } + } + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "ExplicitApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeployment4c4177079d" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": "Prod" + } + }, + "FunctionGetHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "Function" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "Prod", + "__ApiId__": { + "Ref": "ExplicitApi" + } + } + ] + } + } + }, + "ExplicitApiDeployment4c4177079d": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: 4c4177079dd342a2b71978bd25721b7b774295ad" + } + }, + "FunctionGetHtmlPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "Function" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ExplicitApi" + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/aws-cn/api_with_open_api_version.json b/tests/translator/output/aws-cn/api_with_open_api_version.json new file mode 100644 index 0000000000..647d4ae32c --- /dev/null +++ b/tests/translator/output/aws-cn/api_with_open_api_version.json @@ -0,0 +1,234 @@ +{ + "Resources": { + "ImplicitApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "ImplicitApiFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs8.10", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ImplicitApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ImplicitApiFunctionGetHtmlPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ExplicitApiDeployment01dd43a75f": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: 01dd43a75fc0e125c678d20749bacde95d723928" + } + }, + "ImplicitApiFunctionGetHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "Prod", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ExplicitApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": {}, + "openapi": "3.0.1" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "ServerlessRestApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ServerlessRestApiDeploymentb86b9dad9d" + }, + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "StageName": "Prod" + } + }, + "ExplicitApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeployment01dd43a75f" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": "Prod" + } + }, + "ServerlessRestApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/": { + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Origin": "*", + "method.response.header.Access-Control-Allow-Methods": "'GET,OPTIONS'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + }, + "get": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "openapi": "3.0.1" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "ServerlessRestApiDeploymentb86b9dad9d": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "Description": "RestApi deployment id: b86b9dad9d2fd5286c7b355dbd5350987cf492c1" + } + } + } +} diff --git a/tests/translator/output/aws-cn/api_with_open_api_version_2.json b/tests/translator/output/aws-cn/api_with_open_api_version_2.json new file mode 100644 index 0000000000..a49aa983b9 --- /dev/null +++ b/tests/translator/output/aws-cn/api_with_open_api_version_2.json @@ -0,0 +1,234 @@ +{ + "Resources": { + "ImplicitApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "ImplicitApiFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs8.10", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ImplicitApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ImplicitApiFunctionGetHtmlPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ImplicitApiFunctionGetHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "Prod", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ExplicitApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": {}, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "ServerlessRestApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ServerlessRestApiDeploymentc444e5d902" + }, + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "StageName": "Prod" + } + }, + "ExplicitApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeployment5332c373d4" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": "Prod" + } + }, + "ServerlessRestApiDeploymentc444e5d902": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "Description": "RestApi deployment id: c444e5d902971761ced658a7ce701149743eb376" + } + }, + "ServerlessRestApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/": { + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Origin": "*", + "method.response.header.Access-Control-Allow-Methods": "'GET,OPTIONS'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + }, + "get": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "ExplicitApiDeployment5332c373d4": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: 5332c373d45c69e6c0f562b4a419aa8eb311adc7" + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/aws-cn/explicit_api_openapi_3.json b/tests/translator/output/aws-cn/explicit_api_openapi_3.json new file mode 100644 index 0000000000..d98d610a6f --- /dev/null +++ b/tests/translator/output/aws-cn/explicit_api_openapi_3.json @@ -0,0 +1,194 @@ +{ + "Parameters": { + "something": { + "Default": "something", + "Type": "String" + }, + "MyStageName": { + "Default": "Production", + "Type": "String" + } + }, + "Resources": { + "GetHtmlFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "webpage.zip" + }, + "Role": { + "Fn::GetAtt": [ + "GetHtmlFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs4.3", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ApiWithInlineSwaggerStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ApiWithInlineSwaggerDeployment09cda3d97b" + }, + "RestApiId": { + "Ref": "ApiWithInlineSwagger" + }, + "StageName": { + "Ref": "MyStageName" + } + } + }, + "GetHtmlFunctionGetHtmlPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "GetHtmlFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "GetHtmlApi" + } + } + ] + } + } + }, + "GetHtmlApiDeploymentf117c932f7": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "GetHtmlApi" + }, + "Description": "RestApi deployment id: f117c932f75cfa87d23dfed64e9430d0081ef289", + "StageName": "Stage" + } + }, + "GetHtmlFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "arn:aws-cn:iam::aws:policy/AmazonDynamoDBReadOnlyAccess" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ApiWithInlineSwagger": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "this": "is", + "a": "inline swagger" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "GetHtmlFunctionGetHtmlPermissionStage": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "GetHtmlFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": { + "Ref": "MyStageName" + }, + "__ApiId__": { + "Ref": "GetHtmlApi" + } + } + ] + } + } + }, + "GetHtmlApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "BodyS3Location": { + "Bucket": "sam-demo-bucket", + "Key": "webpage_swagger.json" + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + }, + "Name": "MyGetApi" + } + }, + "GetHtmlApiStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "GetHtmlApiDeploymentf117c932f7" + }, + "RestApiId": { + "Ref": "GetHtmlApi" + }, + "Variables": { + "EndpointUri": { + "Ref": "something" + }, + "EndpointUri2": "http://example.com" + }, + "StageName": { + "Ref": "MyStageName" + } + } + }, + "ApiWithInlineSwaggerDeployment09cda3d97b": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ApiWithInlineSwagger" + }, + "Description": "RestApi deployment id: 09cda3d97b008bed7bd4ebb1b5304ed622492941" + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/aws-us-gov/api_with_cors_openapi_3.json b/tests/translator/output/aws-us-gov/api_with_cors_openapi_3.json new file mode 100644 index 0000000000..9a66ac27de --- /dev/null +++ b/tests/translator/output/aws-us-gov/api_with_cors_openapi_3.json @@ -0,0 +1,559 @@ +{ + "Resources": { + "ImplicitApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "ImplicitApiFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs4.3", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ImplicitApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ImplicitApiFunctionGetHtmlPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ImplicitApiFunctionAnyApiPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/*/foo", + { + "__Stage__": "Prod", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ExplicitApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/add": { + "post": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${RestApiFunction.Arn}/invocations" + } + }, + "responses": {} + }, + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Headers": "headers", + "method.response.header.Access-Control-Allow-Origin": "origins", + "method.response.header.Access-Control-Allow-Methods": "methods", + "method.response.header.Access-Control-Allow-Credentials": "'true'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Headers": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + }, + "Access-Control-Allow-Credentials": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + } + }, + "/{proxy+}": { + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Headers": "headers", + "method.response.header.Access-Control-Allow-Origin": "origins", + "method.response.header.Access-Control-Allow-Methods": "methods", + "method.response.header.Access-Control-Allow-Credentials": "'true'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Headers": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + }, + "Access-Control-Allow-Credentials": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + }, + "x-amazon-apigateway-any-method": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetHtmlFunction.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "GetHtmlFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ServerlessRestApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ServerlessRestApiDeployment2cd28b2066" + }, + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "StageName": "Prod" + } + }, + "ExplicitApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeployment3a5a78688c" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": "Prod" + } + }, + "RestApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ImplicitApiFunctionGetHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "Prod", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ServerlessRestApiDeployment2cd28b2066": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "Description": "RestApi deployment id: 2cd28b2066d69ecfb44eb7e024734cab2f3f9dac" + } + }, + "ExplicitApiDeployment3a5a78688c": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: 3a5a78688c9bc377d53aa4153a11f0c4f6e7364c" + } + }, + "RestApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.handler", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "RestApiFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs8.10", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ServerlessRestApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/foo": { + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Origin": { + "Fn::Join": [ + ",", + [ + "www.amazon.com", + "www.google.com" + ] + ] + }, + "method.response.header.Access-Control-Allow-Methods": "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + }, + "x-amazon-apigateway-any-method": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + }, + "/": { + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Origin": { + "Fn::Join": [ + ",", + [ + "www.amazon.com", + "www.google.com" + ] + ] + }, + "method.response.header.Access-Control-Allow-Methods": "'GET,OPTIONS'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + }, + "get": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "openapi": "3.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "GetHtmlFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.handler", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "GetHtmlFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs8.10", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ImplicitApiFunctionAnyApiPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/*/foo", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/aws-us-gov/api_with_gateway_responses_all_openapi_3.json b/tests/translator/output/aws-us-gov/api_with_gateway_responses_all_openapi_3.json new file mode 100644 index 0000000000..8b758bbd47 --- /dev/null +++ b/tests/translator/output/aws-us-gov/api_with_gateway_responses_all_openapi_3.json @@ -0,0 +1,170 @@ +{ + "Resources": { + "Function": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "FunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs4.3", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ExplicitApiDeployment3a19adf892": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: 3a19adf892fbe70d360659eb3660359ade61913b" + } + }, + "FunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ExplicitApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/": { + "get": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Function.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "openapi": "3.0", + "x-amazon-apigateway-gateway-responses": { + "QUOTA_EXCEEDED": { + "responseParameters": { + "gatewayresponse.header.Retry-After": "'31536000'" + }, + "responseTemplates": {}, + "statusCode": "429" + }, + "UNAUTHORIZED": { + "responseParameters": { + "gatewayresponse.header.WWW-Authenticate": "'Bearer realm=\"admin\"'", + "gatewayresponse.header.Access-Control-Expose-Headers": "'WWW-Authenticate'", + "gatewayresponse.header.Access-Control-Allow-Origin": "'*'", + "gatewayresponse.path.PathKey": "'path-value'", + "gatewayresponse.querystring.QueryStringKey": "'query-string-value'" + }, + "responseTemplates": {}, + "statusCode": "401" + } + } + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "ExplicitApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeployment3a19adf892" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": "Prod" + } + }, + "FunctionGetHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "Function" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "Prod", + "__ApiId__": { + "Ref": "ExplicitApi" + } + } + ] + } + } + }, + "FunctionGetHtmlPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "Function" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ExplicitApi" + } + } + ] + } + } + } + } +} diff --git a/tests/translator/output/aws-us-gov/api_with_open_api_version.json b/tests/translator/output/aws-us-gov/api_with_open_api_version.json new file mode 100644 index 0000000000..5cd2019b48 --- /dev/null +++ b/tests/translator/output/aws-us-gov/api_with_open_api_version.json @@ -0,0 +1,234 @@ +{ + "Resources": { + "ImplicitApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "ImplicitApiFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs8.10", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ImplicitApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ImplicitApiFunctionGetHtmlPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ImplicitApiFunctionGetHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "Prod", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ExplicitApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": {}, + "openapi": "3.0.1" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "ExplicitApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeployment01dd43a75f" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": "Prod" + } + }, + "ServerlessRestApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ServerlessRestApiDeployment3f1d889857" + }, + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "StageName": "Prod" + } + }, + "ServerlessRestApiDeployment3f1d889857": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "Description": "RestApi deployment id: 3f1d889857c22227451ab7a02be7ea74b2e9d5b4" + } + }, + "ServerlessRestApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/": { + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Origin": "*", + "method.response.header.Access-Control-Allow-Methods": "'GET,OPTIONS'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + }, + "get": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "openapi": "3.0.1" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "ExplicitApiDeployment01dd43a75f": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: 01dd43a75fc0e125c678d20749bacde95d723928" + } + } + } +} diff --git a/tests/translator/output/aws-us-gov/api_with_open_api_version_2.json b/tests/translator/output/aws-us-gov/api_with_open_api_version_2.json new file mode 100644 index 0000000000..466cc85271 --- /dev/null +++ b/tests/translator/output/aws-us-gov/api_with_open_api_version_2.json @@ -0,0 +1,234 @@ +{ + "Resources": { + "ImplicitApiFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "member_portal.zip" + }, + "Role": { + "Fn::GetAtt": [ + "ImplicitApiFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs8.10", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ImplicitApiFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ImplicitApiFunctionGetHtmlPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ImplicitApiFunctionGetHtmlPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "ImplicitApiFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "Prod", + "__ApiId__": { + "Ref": "ServerlessRestApi" + } + } + ] + } + } + }, + "ExplicitApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": {}, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "ServerlessRestApiDeployment3d22acdeb7": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "Description": "RestApi deployment id: 3d22acdeb7a3302c0b978e3dbb15c149380fbe77" + } + }, + "ExplicitApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ExplicitApiDeployment5332c373d4" + }, + "RestApiId": { + "Ref": "ExplicitApi" + }, + "StageName": "Prod" + } + }, + "ServerlessRestApiProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ServerlessRestApiDeployment3d22acdeb7" + }, + "RestApiId": { + "Ref": "ServerlessRestApi" + }, + "StageName": "Prod" + } + }, + "ServerlessRestApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/": { + "options": { + "x-amazon-apigateway-integration": { + "type": "mock", + "requestTemplates": { + "application/json": "{\n \"statusCode\" : 200\n}\n" + }, + "responses": { + "default": { + "statusCode": "200", + "responseTemplates": { + "application/json": "{}\n" + }, + "responseParameters": { + "method.response.header.Access-Control-Allow-Origin": "*", + "method.response.header.Access-Control-Allow-Methods": "'GET,OPTIONS'" + } + } + } + }, + "consumes": [ + "application/json" + ], + "summary": "CORS support", + "responses": { + "200": { + "headers": { + "Access-Control-Allow-Origin": { + "type": "string" + }, + "Access-Control-Allow-Methods": { + "type": "string" + } + }, + "description": "Default response for CORS method" + } + }, + "produces": [ + "application/json" + ] + }, + "get": { + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ImplicitApiFunction.Arn}/invocations" + } + }, + "responses": {} + } + } + }, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "ExplicitApiDeployment5332c373d4": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ExplicitApi" + }, + "Description": "RestApi deployment id: 5332c373d45c69e6c0f562b4a419aa8eb311adc7" + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/aws-us-gov/explicit_api_openapi_3.json b/tests/translator/output/aws-us-gov/explicit_api_openapi_3.json new file mode 100644 index 0000000000..307a76ae2e --- /dev/null +++ b/tests/translator/output/aws-us-gov/explicit_api_openapi_3.json @@ -0,0 +1,194 @@ +{ + "Parameters": { + "something": { + "Default": "something", + "Type": "String" + }, + "MyStageName": { + "Default": "Production", + "Type": "String" + } + }, + "Resources": { + "GetHtmlFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "webpage.zip" + }, + "Role": { + "Fn::GetAtt": [ + "GetHtmlFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs4.3", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ApiWithInlineSwaggerStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ApiWithInlineSwaggerDeployment09cda3d97b" + }, + "RestApiId": { + "Ref": "ApiWithInlineSwagger" + }, + "StageName": { + "Ref": "MyStageName" + } + } + }, + "GetHtmlFunctionGetHtmlPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "GetHtmlFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "GetHtmlApi" + } + } + ] + } + } + }, + "GetHtmlApiDeploymentf117c932f7": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "GetHtmlApi" + }, + "Description": "RestApi deployment id: f117c932f75cfa87d23dfed64e9430d0081ef289", + "StageName": "Stage" + } + }, + "GetHtmlFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "arn:aws-us-gov:iam::aws:policy/AmazonDynamoDBReadOnlyAccess" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ApiWithInlineSwagger": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "this": "is", + "a": "inline swagger" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + } + }, + "GetHtmlFunctionGetHtmlPermissionStage": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "GetHtmlFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": { + "Ref": "MyStageName" + }, + "__ApiId__": { + "Ref": "GetHtmlApi" + } + } + ] + } + } + }, + "GetHtmlApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "BodyS3Location": { + "Bucket": "sam-demo-bucket", + "Key": "webpage_swagger.json" + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + }, + "Name": "MyGetApi" + } + }, + "GetHtmlApiStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "GetHtmlApiDeploymentf117c932f7" + }, + "RestApiId": { + "Ref": "GetHtmlApi" + }, + "Variables": { + "EndpointUri": { + "Ref": "something" + }, + "EndpointUri2": "http://example.com" + }, + "StageName": { + "Ref": "MyStageName" + } + } + }, + "ApiWithInlineSwaggerDeployment09cda3d97b": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ApiWithInlineSwagger" + }, + "Description": "RestApi deployment id: 09cda3d97b008bed7bd4ebb1b5304ed622492941" + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/aws-us-gov/implicit_api_with_serverless_rest_api_resource.json b/tests/translator/output/aws-us-gov/implicit_api_with_serverless_rest_api_resource.json index e8a85e047f..8484b1d55d 100644 --- a/tests/translator/output/aws-us-gov/implicit_api_with_serverless_rest_api_resource.json +++ b/tests/translator/output/aws-us-gov/implicit_api_with_serverless_rest_api_resource.json @@ -155,11 +155,11 @@ "GetHtmlFunction": { "Type": "AWS::Lambda::Function", "Properties": { + "Handler": "index.gethtml", "Code": { "S3Bucket": "sam-demo-bucket", "S3Key": "todo_list.zip" }, - "Handler": "index.gethtml", "Role": { "Fn::GetAtt": [ "GetHtmlFunctionRole", @@ -224,11 +224,11 @@ "RestApiFunction": { "Type": "AWS::Lambda::Function", "Properties": { + "Handler": "index.restapi", "Code": { "S3Bucket": "sam-demo-bucket", "S3Key": "todo_list.zip" }, - "Handler": "index.restapi", "Role": { "Fn::GetAtt": [ "RestApiFunctionRole", @@ -359,4 +359,4 @@ } } } -} \ No newline at end of file +} diff --git a/tests/translator/output/error_api_with_invalid_open_api_version.json b/tests/translator/output/error_api_with_invalid_open_api_version.json new file mode 100644 index 0000000000..8bac5a42d9 --- /dev/null +++ b/tests/translator/output/error_api_with_invalid_open_api_version.json @@ -0,0 +1,8 @@ +{ + "errors": [ + { + "errorMessage": "Resource with id [MyApi] is invalid. The OpenApiVersion value must be of the format 3.0.0" + } + ], + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [MyApi] is invalid. The OpenApiVersion value must be of the format 3.0.0" + } \ No newline at end of file diff --git a/tests/translator/output/error_globals_api_with_stage_name.json b/tests/translator/output/error_globals_api_with_stage_name.json index 899ef37eaa..0b4d867abc 100644 --- a/tests/translator/output/error_globals_api_with_stage_name.json +++ b/tests/translator/output/error_globals_api_with_stage_name.json @@ -1,8 +1,8 @@ { "errors": [ { - "errorMessage": "'Globals' section is invalid. 'StageName' is not a supported property of 'Api'. Must be one of the following values - ['Auth', 'Name', 'DefinitionUri', 'CacheClusterEnabled', 'CacheClusterSize', 'Variables', 'EndpointConfiguration', 'MethodSettings', 'BinaryMediaTypes', 'Cors', 'GatewayResponses', 'AccessLogSetting', 'CanarySetting']" + "errorMessage": "'Globals' section is invalid. 'StageName' is not a supported property of 'Api'. Must be one of the following values - ['Auth', 'Name', 'DefinitionUri', 'CacheClusterEnabled', 'CacheClusterSize', 'Variables', 'EndpointConfiguration', 'MethodSettings', 'BinaryMediaTypes', 'Cors', 'GatewayResponses', 'AccessLogSetting', 'CanarySetting', 'OpenApiVersion']" } ], - "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. 'Globals' section is invalid. 'StageName' is not a supported property of 'Api'. Must be one of the following values - ['Auth', 'Name', 'DefinitionUri', 'CacheClusterEnabled', 'CacheClusterSize', 'Variables', 'EndpointConfiguration', 'MethodSettings', 'BinaryMediaTypes', 'MinimumCompressionSize', 'Cors', 'GatewayResponses', 'AccessLogSetting', 'CanarySetting', 'TracingEnabled']" + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. 'Globals' section is invalid. 'StageName' is not a supported property of 'Api'. Must be one of the following values - ['Auth', 'Name', 'DefinitionUri', 'CacheClusterEnabled', 'CacheClusterSize', 'Variables', 'EndpointConfiguration', 'MethodSettings', 'BinaryMediaTypes', 'MinimumCompressionSize', 'Cors', 'GatewayResponses', 'AccessLogSetting', 'CanarySetting', 'TracingEnabled', 'OpenApiVersion']" } diff --git a/tests/translator/output/explicit_api_openapi_3.json b/tests/translator/output/explicit_api_openapi_3.json new file mode 100644 index 0000000000..327871d4dc --- /dev/null +++ b/tests/translator/output/explicit_api_openapi_3.json @@ -0,0 +1,178 @@ +{ + "Parameters": { + "something": { + "Default": "something", + "Type": "String" + }, + "MyStageName": { + "Default": "Production", + "Type": "String" + } + }, + "Resources": { + "GetHtmlFunction": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Handler": "index.gethtml", + "Code": { + "S3Bucket": "sam-demo-bucket", + "S3Key": "webpage.zip" + }, + "Role": { + "Fn::GetAtt": [ + "GetHtmlFunctionRole", + "Arn" + ] + }, + "Runtime": "nodejs4.3", + "Tags": [ + { + "Value": "SAM", + "Key": "lambda:createdBy" + } + ] + } + }, + "ApiWithInlineSwaggerStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "ApiWithInlineSwaggerDeployment09cda3d97b" + }, + "RestApiId": { + "Ref": "ApiWithInlineSwagger" + }, + "StageName": { + "Ref": "MyStageName" + } + } + }, + "GetHtmlFunctionGetHtmlPermissionTest": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "GetHtmlFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": "*", + "__ApiId__": { + "Ref": "GetHtmlApi" + } + } + ] + } + } + }, + "GetHtmlApiDeploymentf117c932f7": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "GetHtmlApi" + }, + "Description": "RestApi deployment id: f117c932f75cfa87d23dfed64e9430d0081ef289", + "StageName": "Stage" + } + }, + "GetHtmlFunctionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess" + ], + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + } + } + }, + "ApiWithInlineSwagger": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "this": "is", + "a": "inline swagger" + } + } + }, + "GetHtmlFunctionGetHtmlPermissionStage": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:invokeFunction", + "Principal": "apigateway.amazonaws.com", + "FunctionName": { + "Ref": "GetHtmlFunction" + }, + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/", + { + "__Stage__": { + "Ref": "MyStageName" + }, + "__ApiId__": { + "Ref": "GetHtmlApi" + } + } + ] + } + } + }, + "GetHtmlApi": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "BodyS3Location": { + "Bucket": "sam-demo-bucket", + "Key": "webpage_swagger.json" + }, + "Name": "MyGetApi" + } + }, + "GetHtmlApiStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "GetHtmlApiDeploymentf117c932f7" + }, + "RestApiId": { + "Ref": "GetHtmlApi" + }, + "Variables": { + "EndpointUri": { + "Ref": "something" + }, + "EndpointUri2": "http://example.com" + }, + "StageName": { + "Ref": "MyStageName" + } + } + }, + "ApiWithInlineSwaggerDeployment09cda3d97b": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "RestApiId": { + "Ref": "ApiWithInlineSwagger" + }, + "Description": "RestApi deployment id: 09cda3d97b008bed7bd4ebb1b5304ed622492941" + } + } + } +} \ No newline at end of file diff --git a/tests/translator/test_translator.py b/tests/translator/test_translator.py index b304df6e31..20f9df676c 100644 --- a/tests/translator/test_translator.py +++ b/tests/translator/test_translator.py @@ -170,6 +170,7 @@ class TestTranslatorEndToEnd(TestCase): 'simpletable_with_sse', 'implicit_api', 'explicit_api', + 'explicit_api_openapi_3', 'api_endpoint_configuration', 'api_with_auth_all_maximum', 'api_with_auth_all_minimum', @@ -182,6 +183,7 @@ class TestTranslatorEndToEnd(TestCase): 'api_with_minimum_compression_size', 'api_with_resource_refs', 'api_with_cors', + 'api_with_cors_openapi_3', 'api_with_cors_and_only_methods', 'api_with_cors_and_only_headers', 'api_with_cors_and_only_origins', @@ -190,9 +192,12 @@ class TestTranslatorEndToEnd(TestCase): 'api_with_cors_no_definitionbody', 'api_with_gateway_responses', 'api_with_gateway_responses_all', + 'api_with_gateway_responses_all_openapi_3', 'api_with_gateway_responses_minimal', 'api_with_gateway_responses_implicit', 'api_with_gateway_responses_string_status_code', + 'api_with_open_api_version', + 'api_with_open_api_version_2', 'api_cache', 'api_with_access_log_setting', 'api_with_canary_setting', @@ -395,6 +400,7 @@ def _generate_new_deployment_hash(self, logical_id, dict_to_hash, rest_api_to_sw 'error_api_invalid_definitionuri', 'error_api_invalid_definitionbody', 'error_api_invalid_stagename', + 'error_api_with_invalid_open_api_version', 'error_api_invalid_restapiid', 'error_application_properties', 'error_application_does_not_exist',