diff --git a/samtranslator/internal/schema_source/aws_serverless_api.py b/samtranslator/internal/schema_source/aws_serverless_api.py index 2912489e5..0148b9193 100644 --- a/samtranslator/internal/schema_source/aws_serverless_api.py +++ b/samtranslator/internal/schema_source/aws_serverless_api.py @@ -134,6 +134,7 @@ class Route53(BaseModel): IpV6: Optional[bool] = route53("IpV6") SetIdentifier: Optional[PassThroughProp] # TODO: add docs Region: Optional[PassThroughProp] # TODO: add docs + SeparateRecordSetGroup: Optional[bool] # TODO: add docs class Domain(BaseModel): diff --git a/samtranslator/model/api/api_generator.py b/samtranslator/model/api/api_generator.py index 837ad4dd6..d3de468d8 100644 --- a/samtranslator/model/api/api_generator.py +++ b/samtranslator/model/api/api_generator.py @@ -1,8 +1,10 @@ import logging from collections import namedtuple +from dataclasses import dataclass from typing import Any, Dict, List, Optional, Set, Tuple, Union, cast from samtranslator.metrics.method_decorator import cw_timer +from samtranslator.model import Resource from samtranslator.model.apigateway import ( ApiGatewayApiKey, ApiGatewayAuthorizer, @@ -67,6 +69,13 @@ GatewayResponseProperties = ["ResponseParameters", "ResponseTemplates", "StatusCode"] +@dataclass +class ApiDomainResponse: + domain: Optional[ApiGatewayDomainName] + apigw_basepath_mapping_list: Optional[List[ApiGatewayBasePathMapping]] + recordset_group: Any + + class SharedApiUsagePlan: """ Collects API information from different API resources in the same template, @@ -443,12 +452,12 @@ def _construct_stage( def _construct_api_domain( # noqa: too-many-branches self, rest_api: ApiGatewayRestApi, route53_record_set_groups: Any - ) -> Tuple[Optional[ApiGatewayDomainName], Optional[List[ApiGatewayBasePathMapping]], Any]: + ) -> ApiDomainResponse: """ Constructs and returns the ApiGateway Domain and BasepathMapping """ if self.domain is None: - return None, None, None + return ApiDomainResponse(None, None, None) sam_expect(self.domain, self.logical_id, "Domain").to_be_a_map() domain_name: PassThrough = sam_expect( @@ -565,6 +574,17 @@ def _construct_api_domain( # noqa: too-many-branches logical_id = "RecordSetGroup" + logical_id_suffix record_set_group = route53_record_set_groups.get(logical_id) + + if route53.get("SeparateRecordSetGroup"): + sam_expect( + route53.get("SeparateRecordSetGroup"), self.logical_id, "Domain.Route53.SeparateRecordSetGroup" + ).to_be_a_bool() + return ApiDomainResponse( + domain, + basepath_resource_list, + self._construct_single_record_set_group(self.domain, api_domain_name, route53), + ) + if not record_set_group: record_set_group = Route53RecordSetGroup(logical_id, attributes=self.passthrough_resource_attributes) if "HostedZoneId" in route53: @@ -576,17 +596,38 @@ def _construct_api_domain( # noqa: too-many-branches record_set_group.RecordSets += self._construct_record_sets_for_domain(self.domain, api_domain_name, route53) - return domain, basepath_resource_list, record_set_group + return ApiDomainResponse(domain, basepath_resource_list, record_set_group) + + def _construct_single_record_set_group( + self, domain: Dict[str, Any], api_domain_name: str, route53: Any + ) -> Route53RecordSetGroup: + hostedZoneId = route53.get("HostedZoneId") + hostedZoneName = route53.get("HostedZoneName") + domainName = domain.get("DomainName") + logical_id = logical_id = LogicalIdGenerator( + "RecordSetGroup", [hostedZoneId or hostedZoneName, domainName] + ).gen() + + record_set_group = Route53RecordSetGroup(logical_id, attributes=self.passthrough_resource_attributes) + if hostedZoneId: + record_set_group.HostedZoneId = hostedZoneId + if hostedZoneName: + record_set_group.HostedZoneName = hostedZoneName + + record_set_group.RecordSets = [] + record_set_group.RecordSets += self._construct_record_sets_for_domain(domain, api_domain_name, route53) + + return record_set_group def _construct_record_sets_for_domain( self, custom_domain_config: Dict[str, Any], api_domain_name: str, route53_config: Dict[str, Any] ) -> List[Dict[str, Any]]: recordset_list = [] - + alias_target = self._construct_alias_target(custom_domain_config, api_domain_name, route53_config) recordset = {} recordset["Name"] = custom_domain_config.get("DomainName") recordset["Type"] = "A" - recordset["AliasTarget"] = self._construct_alias_target(custom_domain_config, api_domain_name, route53_config) + recordset["AliasTarget"] = alias_target self._update_route53_routing_policy_properties(route53_config, recordset) recordset_list.append(recordset) @@ -594,9 +635,7 @@ def _construct_record_sets_for_domain( recordset_ipv6 = {} recordset_ipv6["Name"] = custom_domain_config.get("DomainName") recordset_ipv6["Type"] = "AAAA" - recordset_ipv6["AliasTarget"] = self._construct_alias_target( - custom_domain_config, api_domain_name, route53_config - ) + recordset_ipv6["AliasTarget"] = alias_target self._update_route53_routing_policy_properties(route53_config, recordset_ipv6) recordset_list.append(recordset_ipv6) @@ -626,14 +665,20 @@ def _construct_alias_target(self, domain: Dict[str, Any], api_domain_name: str, return alias_target @cw_timer(prefix="Generator", name="Api") - def to_cloudformation(self, redeploy_restapi_parameters, route53_record_set_groups): # type: ignore[no-untyped-def] + def to_cloudformation( + self, redeploy_restapi_parameters: Optional[Any], route53_record_set_groups: Dict[str, Route53RecordSetGroup] + ) -> List[Resource]: """Generates CloudFormation resources from a SAM API resource :returns: a tuple containing the RestApi, Deployment, and Stage for an empty Api. :rtype: tuple """ rest_api = self._construct_rest_api() - domain, basepath_mapping, route53 = self._construct_api_domain(rest_api, route53_record_set_groups) + api_domain_response = self._construct_api_domain(rest_api, route53_record_set_groups) + domain = api_domain_response.domain + basepath_mapping = api_domain_response.apigw_basepath_mapping_list + route53_recordsetGroup = api_domain_response.recordset_group + deployment = self._construct_deployment(rest_api) swagger = None @@ -646,7 +691,41 @@ def to_cloudformation(self, redeploy_restapi_parameters, route53_record_set_grou permissions = self._construct_authorizer_lambda_permission() usage_plan = self._construct_usage_plan(rest_api_stage=stage) - return rest_api, deployment, stage, permissions, domain, basepath_mapping, route53, usage_plan + # mypy complains if the type in List doesn't match exactly + # TODO: refactor to have a list of single resource + generated_resources: List[ + Union[ + Optional[Resource], + List[Resource], + Tuple[Resource], + List[LambdaPermission], + List[ApiGatewayBasePathMapping], + ], + ] = [] + + generated_resources.extend( + [ + rest_api, + deployment, + stage, + permissions, + domain, + basepath_mapping, + route53_recordsetGroup, + usage_plan, + ] + ) + + # Make a list of single resources + generated_resources_list: List[Resource] = [] + for resource in generated_resources: + if resource: + if isinstance(resource, (list, tuple)): + generated_resources_list.extend(resource) + else: + generated_resources_list.extend([resource]) + + return generated_resources_list def _add_cors(self) -> None: """ diff --git a/samtranslator/model/sam_resources.py b/samtranslator/model/sam_resources.py index 63ce47f77..4b9f372ea 100644 --- a/samtranslator/model/sam_resources.py +++ b/samtranslator/model/sam_resources.py @@ -1220,7 +1220,7 @@ class SamApi(SamResourceMacro): } @cw_timer - def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def] + def to_cloudformation(self, **kwargs) -> List[Resource]: # type: ignore[no-untyped-def] """Returns the API Gateway RestApi, Deployment, and Stage to which this SAM Api corresponds. :param dict kwargs: already-converted resources that may need to be modified when converting this \ @@ -1228,7 +1228,6 @@ def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def] :returns: a list of vanilla CloudFormation Resources, to which this Function expands :rtype: list """ - resources = [] intrinsics_resolver = kwargs["intrinsics_resolver"] self.BinaryMediaTypes = intrinsics_resolver.resolve_parameter_refs(self.BinaryMediaTypes) @@ -1276,29 +1275,7 @@ def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def] always_deploy=self.AlwaysDeploy, ) - ( - rest_api, - deployment, - stage, - permissions, - domain, - basepath_mapping, - route53, - usage_plan_resources, - ) = api_generator.to_cloudformation(redeploy_restapi_parameters, route53_record_set_groups) - - resources.extend([rest_api, deployment, stage]) - resources.extend(permissions) - if domain: - resources.extend([domain]) - if basepath_mapping: - resources.extend(basepath_mapping) - if route53: - resources.extend([route53]) - # contains usage plan, api key and usageplan key resources - if usage_plan_resources: - resources.extend(usage_plan_resources) - return resources + return api_generator.to_cloudformation(redeploy_restapi_parameters, route53_record_set_groups) class SamHttpApi(SamResourceMacro): diff --git a/samtranslator/schema/schema.json b/samtranslator/schema/schema.json index c9e218e01..3278c8d8d 100644 --- a/samtranslator/schema/schema.json +++ b/samtranslator/schema/schema.json @@ -198371,6 +198371,10 @@ "Region": { "$ref": "#/definitions/PassThroughProp" }, + "SeparateRecordSetGroup": { + "title": "Separaterecordsetgroup", + "type": "boolean" + }, "SetIdentifier": { "$ref": "#/definitions/PassThroughProp" } diff --git a/schema_source/sam.schema.json b/schema_source/sam.schema.json index 27895adc4..c5458bec7 100644 --- a/schema_source/sam.schema.json +++ b/schema_source/sam.schema.json @@ -4094,6 +4094,10 @@ "Region": { "$ref": "#/definitions/PassThroughProp" }, + "SeparateRecordSetGroup": { + "title": "Separaterecordsetgroup", + "type": "boolean" + }, "SetIdentifier": { "$ref": "#/definitions/PassThroughProp" } diff --git a/tests/translator/input/error_separate_route53_recordset_group.yaml b/tests/translator/input/error_separate_route53_recordset_group.yaml new file mode 100644 index 000000000..9be24513f --- /dev/null +++ b/tests/translator/input/error_separate_route53_recordset_group.yaml @@ -0,0 +1,82 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: > + apigateway-2402 + + Sample SAM Template for apigateway-2402 + +Parameters: + EnvType: + Description: Environment type. + Default: test + Type: String + AllowedValues: + - prod + - test + ConstraintDescription: must specify prod or test. +Conditions: + CreateProdResources: !Equals + - !Ref EnvType + - prod +Resources: + ApiGatewayAdminOne: + Type: AWS::Serverless::Api + Properties: + Name: App-Prod-Web + StageName: Prod + TracingEnabled: true + MethodSettings: + - LoggingLevel: Info + ResourcePath: /* + HttpMethod: '*' + Domain: + DomainName: admin.one.amazon.com + CertificateArn: arn::cert::abc + EndpointConfiguration: REGIONAL + Route53: + HostedZoneId: abc123456 + EndpointConfiguration: + Type: REGIONAL + + + ApiGatewayAdminTwo: + Type: AWS::Serverless::Api + Condition: CreateProdResources + Properties: + Name: App-Prod-Web + StageName: Prod + TracingEnabled: true + MethodSettings: + - LoggingLevel: Info + ResourcePath: /* + HttpMethod: '*' + Domain: + DomainName: admin.two.amazon.com + CertificateArn: arn::cert::abc + EndpointConfiguration: REGIONAL + Route53: + HostedZoneId: abc123456 + SeparateRecordSetGroup: [true] + EndpointConfiguration: + Type: REGIONAL + + + ApiGatewayAdminThree: + Type: AWS::Serverless::Api + Properties: + Name: App-Prod-Web + StageName: Prod + TracingEnabled: true + MethodSettings: + - LoggingLevel: Info + ResourcePath: /* + HttpMethod: '*' + Domain: + DomainName: admin.three.amazon.com + CertificateArn: arn::cert::abc + EndpointConfiguration: REGIONAL + Route53: + HostedZoneId: abc123456 + SeparateRecordSetGroup: true + EndpointConfiguration: + Type: REGIONAL diff --git a/tests/translator/input/separate_route53_recordset_group.yaml b/tests/translator/input/separate_route53_recordset_group.yaml new file mode 100644 index 000000000..67d323987 --- /dev/null +++ b/tests/translator/input/separate_route53_recordset_group.yaml @@ -0,0 +1,82 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: > + apigateway-2402 + + Sample SAM Template for apigateway-2402 + +Parameters: + EnvType: + Description: Environment type. + Default: test + Type: String + AllowedValues: + - prod + - test + ConstraintDescription: must specify prod or test. +Conditions: + CreateProdResources: !Equals + - !Ref EnvType + - prod +Resources: + ApiGatewayAdminOne: + Type: AWS::Serverless::Api + Properties: + Name: App-Prod-Web + StageName: Prod + TracingEnabled: true + MethodSettings: + - LoggingLevel: Info + ResourcePath: /* + HttpMethod: '*' + Domain: + DomainName: admin.one.amazon.com + CertificateArn: arn::cert::abc + EndpointConfiguration: REGIONAL + Route53: + HostedZoneId: abc123456 + EndpointConfiguration: + Type: REGIONAL + + + ApiGatewayAdminTwo: + Type: AWS::Serverless::Api + Condition: CreateProdResources + Properties: + Name: App-Prod-Web + StageName: Prod + TracingEnabled: true + MethodSettings: + - LoggingLevel: Info + ResourcePath: /* + HttpMethod: '*' + Domain: + DomainName: admin.two.amazon.com + CertificateArn: arn::cert::abc + EndpointConfiguration: REGIONAL + Route53: + HostedZoneId: abc123456 + SeparateRecordSetGroup: true + EndpointConfiguration: + Type: REGIONAL + + + ApiGatewayAdminThree: + Type: AWS::Serverless::Api + Properties: + Name: App-Prod-Web + StageName: Prod + TracingEnabled: true + MethodSettings: + - LoggingLevel: Info + ResourcePath: /* + HttpMethod: '*' + Domain: + DomainName: admin.three.amazon.com + CertificateArn: arn::cert::abc + EndpointConfiguration: REGIONAL + Route53: + HostedZoneId: abc123456 + SeparateRecordSetGroup: true + EndpointConfiguration: + Type: REGIONAL diff --git a/tests/translator/output/aws-cn/separate_route53_recordset_group.json b/tests/translator/output/aws-cn/separate_route53_recordset_group.json new file mode 100644 index 000000000..5575d8d71 --- /dev/null +++ b/tests/translator/output/aws-cn/separate_route53_recordset_group.json @@ -0,0 +1,352 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Conditions": { + "CreateProdResources": { + "Fn::Equals": [ + { + "Ref": "EnvType" + }, + "prod" + ] + } + }, + "Description": "apigateway-2402\nSample SAM Template for apigateway-2402\n", + "Parameters": { + "EnvType": { + "AllowedValues": [ + "prod", + "test" + ], + "ConstraintDescription": "must specify prod or test.", + "Default": "test", + "Description": "Environment type.", + "Type": "String" + } + }, + "Resources": { + "ApiGatewayAdminOne": { + "Properties": { + "Body": { + "info": { + "title": { + "Ref": "AWS::StackName" + }, + "version": "1.0" + }, + "paths": {}, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Name": "App-Prod-Web", + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + }, + "Type": "AWS::ApiGateway::RestApi" + }, + "ApiGatewayAdminOneBasePathMapping": { + "Properties": { + "DomainName": { + "Ref": "ApiGatewayDomainName5fe29fe649" + }, + "RestApiId": { + "Ref": "ApiGatewayAdminOne" + }, + "Stage": { + "Ref": "ApiGatewayAdminOneProdStage" + } + }, + "Type": "AWS::ApiGateway::BasePathMapping" + }, + "ApiGatewayAdminOneDeploymentdd3f545183": { + "Properties": { + "Description": "RestApi deployment id: dd3f545183668c401e771fd9a377cfeadcf88a35", + "RestApiId": { + "Ref": "ApiGatewayAdminOne" + }, + "StageName": "Stage" + }, + "Type": "AWS::ApiGateway::Deployment" + }, + "ApiGatewayAdminOneProdStage": { + "Properties": { + "DeploymentId": { + "Ref": "ApiGatewayAdminOneDeploymentdd3f545183" + }, + "MethodSettings": [ + { + "HttpMethod": "*", + "LoggingLevel": "Info", + "ResourcePath": "/*" + } + ], + "RestApiId": { + "Ref": "ApiGatewayAdminOne" + }, + "StageName": "Prod", + "TracingEnabled": true + }, + "Type": "AWS::ApiGateway::Stage" + }, + "ApiGatewayAdminThree": { + "Properties": { + "Body": { + "info": { + "title": { + "Ref": "AWS::StackName" + }, + "version": "1.0" + }, + "paths": {}, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Name": "App-Prod-Web", + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + }, + "Type": "AWS::ApiGateway::RestApi" + }, + "ApiGatewayAdminThreeBasePathMapping": { + "Properties": { + "DomainName": { + "Ref": "ApiGatewayDomainName41bfc7f9c4" + }, + "RestApiId": { + "Ref": "ApiGatewayAdminThree" + }, + "Stage": { + "Ref": "ApiGatewayAdminThreeProdStage" + } + }, + "Type": "AWS::ApiGateway::BasePathMapping" + }, + "ApiGatewayAdminThreeDeploymentc2e9ae5463": { + "Properties": { + "Description": "RestApi deployment id: c2e9ae5463d31ad96611e5aab9b4ddd4fd7bde73", + "RestApiId": { + "Ref": "ApiGatewayAdminThree" + }, + "StageName": "Stage" + }, + "Type": "AWS::ApiGateway::Deployment" + }, + "ApiGatewayAdminThreeProdStage": { + "Properties": { + "DeploymentId": { + "Ref": "ApiGatewayAdminThreeDeploymentc2e9ae5463" + }, + "MethodSettings": [ + { + "HttpMethod": "*", + "LoggingLevel": "Info", + "ResourcePath": "/*" + } + ], + "RestApiId": { + "Ref": "ApiGatewayAdminThree" + }, + "StageName": "Prod", + "TracingEnabled": true + }, + "Type": "AWS::ApiGateway::Stage" + }, + "ApiGatewayAdminTwo": { + "Condition": "CreateProdResources", + "Properties": { + "Body": { + "info": { + "title": { + "Ref": "AWS::StackName" + }, + "version": "1.0" + }, + "paths": {}, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Name": "App-Prod-Web", + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + }, + "Type": "AWS::ApiGateway::RestApi" + }, + "ApiGatewayAdminTwoBasePathMapping": { + "Condition": "CreateProdResources", + "Properties": { + "DomainName": { + "Ref": "ApiGatewayDomainName3fd2dbd8f8" + }, + "RestApiId": { + "Ref": "ApiGatewayAdminTwo" + }, + "Stage": { + "Ref": "ApiGatewayAdminTwoProdStage" + } + }, + "Type": "AWS::ApiGateway::BasePathMapping" + }, + "ApiGatewayAdminTwoDeployment2a68098964": { + "Condition": "CreateProdResources", + "Properties": { + "Description": "RestApi deployment id: 2a6809896451eb172efffcdcd18396e1a83df12a", + "RestApiId": { + "Ref": "ApiGatewayAdminTwo" + }, + "StageName": "Stage" + }, + "Type": "AWS::ApiGateway::Deployment" + }, + "ApiGatewayAdminTwoProdStage": { + "Condition": "CreateProdResources", + "Properties": { + "DeploymentId": { + "Ref": "ApiGatewayAdminTwoDeployment2a68098964" + }, + "MethodSettings": [ + { + "HttpMethod": "*", + "LoggingLevel": "Info", + "ResourcePath": "/*" + } + ], + "RestApiId": { + "Ref": "ApiGatewayAdminTwo" + }, + "StageName": "Prod", + "TracingEnabled": true + }, + "Type": "AWS::ApiGateway::Stage" + }, + "ApiGatewayDomainName3fd2dbd8f8": { + "Condition": "CreateProdResources", + "Properties": { + "DomainName": "admin.two.amazon.com", + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "RegionalCertificateArn": "arn::cert::abc" + }, + "Type": "AWS::ApiGateway::DomainName" + }, + "ApiGatewayDomainName41bfc7f9c4": { + "Properties": { + "DomainName": "admin.three.amazon.com", + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "RegionalCertificateArn": "arn::cert::abc" + }, + "Type": "AWS::ApiGateway::DomainName" + }, + "ApiGatewayDomainName5fe29fe649": { + "Properties": { + "DomainName": "admin.one.amazon.com", + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "RegionalCertificateArn": "arn::cert::abc" + }, + "Type": "AWS::ApiGateway::DomainName" + }, + "RecordSetGroup370194ff6e": { + "Properties": { + "HostedZoneId": "abc123456", + "RecordSets": [ + { + "AliasTarget": { + "DNSName": { + "Fn::GetAtt": [ + "ApiGatewayDomainName5fe29fe649", + "RegionalDomainName" + ] + }, + "HostedZoneId": { + "Fn::GetAtt": [ + "ApiGatewayDomainName5fe29fe649", + "RegionalHostedZoneId" + ] + } + }, + "Name": "admin.one.amazon.com", + "Type": "A" + } + ] + }, + "Type": "AWS::Route53::RecordSetGroup" + }, + "RecordSetGroup81840409a4": { + "Properties": { + "HostedZoneId": "abc123456", + "RecordSets": [ + { + "AliasTarget": { + "DNSName": { + "Fn::GetAtt": [ + "ApiGatewayDomainName41bfc7f9c4", + "RegionalDomainName" + ] + }, + "HostedZoneId": { + "Fn::GetAtt": [ + "ApiGatewayDomainName41bfc7f9c4", + "RegionalHostedZoneId" + ] + } + }, + "Name": "admin.three.amazon.com", + "Type": "A" + } + ] + }, + "Type": "AWS::Route53::RecordSetGroup" + }, + "RecordSetGroupb3fa99c196": { + "Condition": "CreateProdResources", + "Properties": { + "HostedZoneId": "abc123456", + "RecordSets": [ + { + "AliasTarget": { + "DNSName": { + "Fn::GetAtt": [ + "ApiGatewayDomainName3fd2dbd8f8", + "RegionalDomainName" + ] + }, + "HostedZoneId": { + "Fn::GetAtt": [ + "ApiGatewayDomainName3fd2dbd8f8", + "RegionalHostedZoneId" + ] + } + }, + "Name": "admin.two.amazon.com", + "Type": "A" + } + ] + }, + "Type": "AWS::Route53::RecordSetGroup" + } + } +} diff --git a/tests/translator/output/aws-us-gov/separate_route53_recordset_group.json b/tests/translator/output/aws-us-gov/separate_route53_recordset_group.json new file mode 100644 index 000000000..5575d8d71 --- /dev/null +++ b/tests/translator/output/aws-us-gov/separate_route53_recordset_group.json @@ -0,0 +1,352 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Conditions": { + "CreateProdResources": { + "Fn::Equals": [ + { + "Ref": "EnvType" + }, + "prod" + ] + } + }, + "Description": "apigateway-2402\nSample SAM Template for apigateway-2402\n", + "Parameters": { + "EnvType": { + "AllowedValues": [ + "prod", + "test" + ], + "ConstraintDescription": "must specify prod or test.", + "Default": "test", + "Description": "Environment type.", + "Type": "String" + } + }, + "Resources": { + "ApiGatewayAdminOne": { + "Properties": { + "Body": { + "info": { + "title": { + "Ref": "AWS::StackName" + }, + "version": "1.0" + }, + "paths": {}, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Name": "App-Prod-Web", + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + }, + "Type": "AWS::ApiGateway::RestApi" + }, + "ApiGatewayAdminOneBasePathMapping": { + "Properties": { + "DomainName": { + "Ref": "ApiGatewayDomainName5fe29fe649" + }, + "RestApiId": { + "Ref": "ApiGatewayAdminOne" + }, + "Stage": { + "Ref": "ApiGatewayAdminOneProdStage" + } + }, + "Type": "AWS::ApiGateway::BasePathMapping" + }, + "ApiGatewayAdminOneDeploymentdd3f545183": { + "Properties": { + "Description": "RestApi deployment id: dd3f545183668c401e771fd9a377cfeadcf88a35", + "RestApiId": { + "Ref": "ApiGatewayAdminOne" + }, + "StageName": "Stage" + }, + "Type": "AWS::ApiGateway::Deployment" + }, + "ApiGatewayAdminOneProdStage": { + "Properties": { + "DeploymentId": { + "Ref": "ApiGatewayAdminOneDeploymentdd3f545183" + }, + "MethodSettings": [ + { + "HttpMethod": "*", + "LoggingLevel": "Info", + "ResourcePath": "/*" + } + ], + "RestApiId": { + "Ref": "ApiGatewayAdminOne" + }, + "StageName": "Prod", + "TracingEnabled": true + }, + "Type": "AWS::ApiGateway::Stage" + }, + "ApiGatewayAdminThree": { + "Properties": { + "Body": { + "info": { + "title": { + "Ref": "AWS::StackName" + }, + "version": "1.0" + }, + "paths": {}, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Name": "App-Prod-Web", + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + }, + "Type": "AWS::ApiGateway::RestApi" + }, + "ApiGatewayAdminThreeBasePathMapping": { + "Properties": { + "DomainName": { + "Ref": "ApiGatewayDomainName41bfc7f9c4" + }, + "RestApiId": { + "Ref": "ApiGatewayAdminThree" + }, + "Stage": { + "Ref": "ApiGatewayAdminThreeProdStage" + } + }, + "Type": "AWS::ApiGateway::BasePathMapping" + }, + "ApiGatewayAdminThreeDeploymentc2e9ae5463": { + "Properties": { + "Description": "RestApi deployment id: c2e9ae5463d31ad96611e5aab9b4ddd4fd7bde73", + "RestApiId": { + "Ref": "ApiGatewayAdminThree" + }, + "StageName": "Stage" + }, + "Type": "AWS::ApiGateway::Deployment" + }, + "ApiGatewayAdminThreeProdStage": { + "Properties": { + "DeploymentId": { + "Ref": "ApiGatewayAdminThreeDeploymentc2e9ae5463" + }, + "MethodSettings": [ + { + "HttpMethod": "*", + "LoggingLevel": "Info", + "ResourcePath": "/*" + } + ], + "RestApiId": { + "Ref": "ApiGatewayAdminThree" + }, + "StageName": "Prod", + "TracingEnabled": true + }, + "Type": "AWS::ApiGateway::Stage" + }, + "ApiGatewayAdminTwo": { + "Condition": "CreateProdResources", + "Properties": { + "Body": { + "info": { + "title": { + "Ref": "AWS::StackName" + }, + "version": "1.0" + }, + "paths": {}, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Name": "App-Prod-Web", + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + }, + "Type": "AWS::ApiGateway::RestApi" + }, + "ApiGatewayAdminTwoBasePathMapping": { + "Condition": "CreateProdResources", + "Properties": { + "DomainName": { + "Ref": "ApiGatewayDomainName3fd2dbd8f8" + }, + "RestApiId": { + "Ref": "ApiGatewayAdminTwo" + }, + "Stage": { + "Ref": "ApiGatewayAdminTwoProdStage" + } + }, + "Type": "AWS::ApiGateway::BasePathMapping" + }, + "ApiGatewayAdminTwoDeployment2a68098964": { + "Condition": "CreateProdResources", + "Properties": { + "Description": "RestApi deployment id: 2a6809896451eb172efffcdcd18396e1a83df12a", + "RestApiId": { + "Ref": "ApiGatewayAdminTwo" + }, + "StageName": "Stage" + }, + "Type": "AWS::ApiGateway::Deployment" + }, + "ApiGatewayAdminTwoProdStage": { + "Condition": "CreateProdResources", + "Properties": { + "DeploymentId": { + "Ref": "ApiGatewayAdminTwoDeployment2a68098964" + }, + "MethodSettings": [ + { + "HttpMethod": "*", + "LoggingLevel": "Info", + "ResourcePath": "/*" + } + ], + "RestApiId": { + "Ref": "ApiGatewayAdminTwo" + }, + "StageName": "Prod", + "TracingEnabled": true + }, + "Type": "AWS::ApiGateway::Stage" + }, + "ApiGatewayDomainName3fd2dbd8f8": { + "Condition": "CreateProdResources", + "Properties": { + "DomainName": "admin.two.amazon.com", + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "RegionalCertificateArn": "arn::cert::abc" + }, + "Type": "AWS::ApiGateway::DomainName" + }, + "ApiGatewayDomainName41bfc7f9c4": { + "Properties": { + "DomainName": "admin.three.amazon.com", + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "RegionalCertificateArn": "arn::cert::abc" + }, + "Type": "AWS::ApiGateway::DomainName" + }, + "ApiGatewayDomainName5fe29fe649": { + "Properties": { + "DomainName": "admin.one.amazon.com", + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "RegionalCertificateArn": "arn::cert::abc" + }, + "Type": "AWS::ApiGateway::DomainName" + }, + "RecordSetGroup370194ff6e": { + "Properties": { + "HostedZoneId": "abc123456", + "RecordSets": [ + { + "AliasTarget": { + "DNSName": { + "Fn::GetAtt": [ + "ApiGatewayDomainName5fe29fe649", + "RegionalDomainName" + ] + }, + "HostedZoneId": { + "Fn::GetAtt": [ + "ApiGatewayDomainName5fe29fe649", + "RegionalHostedZoneId" + ] + } + }, + "Name": "admin.one.amazon.com", + "Type": "A" + } + ] + }, + "Type": "AWS::Route53::RecordSetGroup" + }, + "RecordSetGroup81840409a4": { + "Properties": { + "HostedZoneId": "abc123456", + "RecordSets": [ + { + "AliasTarget": { + "DNSName": { + "Fn::GetAtt": [ + "ApiGatewayDomainName41bfc7f9c4", + "RegionalDomainName" + ] + }, + "HostedZoneId": { + "Fn::GetAtt": [ + "ApiGatewayDomainName41bfc7f9c4", + "RegionalHostedZoneId" + ] + } + }, + "Name": "admin.three.amazon.com", + "Type": "A" + } + ] + }, + "Type": "AWS::Route53::RecordSetGroup" + }, + "RecordSetGroupb3fa99c196": { + "Condition": "CreateProdResources", + "Properties": { + "HostedZoneId": "abc123456", + "RecordSets": [ + { + "AliasTarget": { + "DNSName": { + "Fn::GetAtt": [ + "ApiGatewayDomainName3fd2dbd8f8", + "RegionalDomainName" + ] + }, + "HostedZoneId": { + "Fn::GetAtt": [ + "ApiGatewayDomainName3fd2dbd8f8", + "RegionalHostedZoneId" + ] + } + }, + "Name": "admin.two.amazon.com", + "Type": "A" + } + ] + }, + "Type": "AWS::Route53::RecordSetGroup" + } + } +} diff --git a/tests/translator/output/error_separate_route53_recordset_group.json b/tests/translator/output/error_separate_route53_recordset_group.json new file mode 100644 index 000000000..ae418b685 --- /dev/null +++ b/tests/translator/output/error_separate_route53_recordset_group.json @@ -0,0 +1,9 @@ +{ + "_autoGeneratedBreakdownErrorMessage": [ + "Invalid Serverless Application Specification document. ", + "Number of errors found: 1. ", + "Resource with id [ApiGatewayAdminTwo] is invalid. ", + "Property 'Domain.Route53.SeparateRecordSetGroup' should be a boolean." + ], + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [ApiGatewayAdminTwo] is invalid. Property 'Domain.Route53.SeparateRecordSetGroup' should be a boolean." +} diff --git a/tests/translator/output/separate_route53_recordset_group.json b/tests/translator/output/separate_route53_recordset_group.json new file mode 100644 index 000000000..5575d8d71 --- /dev/null +++ b/tests/translator/output/separate_route53_recordset_group.json @@ -0,0 +1,352 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Conditions": { + "CreateProdResources": { + "Fn::Equals": [ + { + "Ref": "EnvType" + }, + "prod" + ] + } + }, + "Description": "apigateway-2402\nSample SAM Template for apigateway-2402\n", + "Parameters": { + "EnvType": { + "AllowedValues": [ + "prod", + "test" + ], + "ConstraintDescription": "must specify prod or test.", + "Default": "test", + "Description": "Environment type.", + "Type": "String" + } + }, + "Resources": { + "ApiGatewayAdminOne": { + "Properties": { + "Body": { + "info": { + "title": { + "Ref": "AWS::StackName" + }, + "version": "1.0" + }, + "paths": {}, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Name": "App-Prod-Web", + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + }, + "Type": "AWS::ApiGateway::RestApi" + }, + "ApiGatewayAdminOneBasePathMapping": { + "Properties": { + "DomainName": { + "Ref": "ApiGatewayDomainName5fe29fe649" + }, + "RestApiId": { + "Ref": "ApiGatewayAdminOne" + }, + "Stage": { + "Ref": "ApiGatewayAdminOneProdStage" + } + }, + "Type": "AWS::ApiGateway::BasePathMapping" + }, + "ApiGatewayAdminOneDeploymentdd3f545183": { + "Properties": { + "Description": "RestApi deployment id: dd3f545183668c401e771fd9a377cfeadcf88a35", + "RestApiId": { + "Ref": "ApiGatewayAdminOne" + }, + "StageName": "Stage" + }, + "Type": "AWS::ApiGateway::Deployment" + }, + "ApiGatewayAdminOneProdStage": { + "Properties": { + "DeploymentId": { + "Ref": "ApiGatewayAdminOneDeploymentdd3f545183" + }, + "MethodSettings": [ + { + "HttpMethod": "*", + "LoggingLevel": "Info", + "ResourcePath": "/*" + } + ], + "RestApiId": { + "Ref": "ApiGatewayAdminOne" + }, + "StageName": "Prod", + "TracingEnabled": true + }, + "Type": "AWS::ApiGateway::Stage" + }, + "ApiGatewayAdminThree": { + "Properties": { + "Body": { + "info": { + "title": { + "Ref": "AWS::StackName" + }, + "version": "1.0" + }, + "paths": {}, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Name": "App-Prod-Web", + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + }, + "Type": "AWS::ApiGateway::RestApi" + }, + "ApiGatewayAdminThreeBasePathMapping": { + "Properties": { + "DomainName": { + "Ref": "ApiGatewayDomainName41bfc7f9c4" + }, + "RestApiId": { + "Ref": "ApiGatewayAdminThree" + }, + "Stage": { + "Ref": "ApiGatewayAdminThreeProdStage" + } + }, + "Type": "AWS::ApiGateway::BasePathMapping" + }, + "ApiGatewayAdminThreeDeploymentc2e9ae5463": { + "Properties": { + "Description": "RestApi deployment id: c2e9ae5463d31ad96611e5aab9b4ddd4fd7bde73", + "RestApiId": { + "Ref": "ApiGatewayAdminThree" + }, + "StageName": "Stage" + }, + "Type": "AWS::ApiGateway::Deployment" + }, + "ApiGatewayAdminThreeProdStage": { + "Properties": { + "DeploymentId": { + "Ref": "ApiGatewayAdminThreeDeploymentc2e9ae5463" + }, + "MethodSettings": [ + { + "HttpMethod": "*", + "LoggingLevel": "Info", + "ResourcePath": "/*" + } + ], + "RestApiId": { + "Ref": "ApiGatewayAdminThree" + }, + "StageName": "Prod", + "TracingEnabled": true + }, + "Type": "AWS::ApiGateway::Stage" + }, + "ApiGatewayAdminTwo": { + "Condition": "CreateProdResources", + "Properties": { + "Body": { + "info": { + "title": { + "Ref": "AWS::StackName" + }, + "version": "1.0" + }, + "paths": {}, + "swagger": "2.0" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "Name": "App-Prod-Web", + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + } + }, + "Type": "AWS::ApiGateway::RestApi" + }, + "ApiGatewayAdminTwoBasePathMapping": { + "Condition": "CreateProdResources", + "Properties": { + "DomainName": { + "Ref": "ApiGatewayDomainName3fd2dbd8f8" + }, + "RestApiId": { + "Ref": "ApiGatewayAdminTwo" + }, + "Stage": { + "Ref": "ApiGatewayAdminTwoProdStage" + } + }, + "Type": "AWS::ApiGateway::BasePathMapping" + }, + "ApiGatewayAdminTwoDeployment2a68098964": { + "Condition": "CreateProdResources", + "Properties": { + "Description": "RestApi deployment id: 2a6809896451eb172efffcdcd18396e1a83df12a", + "RestApiId": { + "Ref": "ApiGatewayAdminTwo" + }, + "StageName": "Stage" + }, + "Type": "AWS::ApiGateway::Deployment" + }, + "ApiGatewayAdminTwoProdStage": { + "Condition": "CreateProdResources", + "Properties": { + "DeploymentId": { + "Ref": "ApiGatewayAdminTwoDeployment2a68098964" + }, + "MethodSettings": [ + { + "HttpMethod": "*", + "LoggingLevel": "Info", + "ResourcePath": "/*" + } + ], + "RestApiId": { + "Ref": "ApiGatewayAdminTwo" + }, + "StageName": "Prod", + "TracingEnabled": true + }, + "Type": "AWS::ApiGateway::Stage" + }, + "ApiGatewayDomainName3fd2dbd8f8": { + "Condition": "CreateProdResources", + "Properties": { + "DomainName": "admin.two.amazon.com", + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "RegionalCertificateArn": "arn::cert::abc" + }, + "Type": "AWS::ApiGateway::DomainName" + }, + "ApiGatewayDomainName41bfc7f9c4": { + "Properties": { + "DomainName": "admin.three.amazon.com", + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "RegionalCertificateArn": "arn::cert::abc" + }, + "Type": "AWS::ApiGateway::DomainName" + }, + "ApiGatewayDomainName5fe29fe649": { + "Properties": { + "DomainName": "admin.one.amazon.com", + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + }, + "RegionalCertificateArn": "arn::cert::abc" + }, + "Type": "AWS::ApiGateway::DomainName" + }, + "RecordSetGroup370194ff6e": { + "Properties": { + "HostedZoneId": "abc123456", + "RecordSets": [ + { + "AliasTarget": { + "DNSName": { + "Fn::GetAtt": [ + "ApiGatewayDomainName5fe29fe649", + "RegionalDomainName" + ] + }, + "HostedZoneId": { + "Fn::GetAtt": [ + "ApiGatewayDomainName5fe29fe649", + "RegionalHostedZoneId" + ] + } + }, + "Name": "admin.one.amazon.com", + "Type": "A" + } + ] + }, + "Type": "AWS::Route53::RecordSetGroup" + }, + "RecordSetGroup81840409a4": { + "Properties": { + "HostedZoneId": "abc123456", + "RecordSets": [ + { + "AliasTarget": { + "DNSName": { + "Fn::GetAtt": [ + "ApiGatewayDomainName41bfc7f9c4", + "RegionalDomainName" + ] + }, + "HostedZoneId": { + "Fn::GetAtt": [ + "ApiGatewayDomainName41bfc7f9c4", + "RegionalHostedZoneId" + ] + } + }, + "Name": "admin.three.amazon.com", + "Type": "A" + } + ] + }, + "Type": "AWS::Route53::RecordSetGroup" + }, + "RecordSetGroupb3fa99c196": { + "Condition": "CreateProdResources", + "Properties": { + "HostedZoneId": "abc123456", + "RecordSets": [ + { + "AliasTarget": { + "DNSName": { + "Fn::GetAtt": [ + "ApiGatewayDomainName3fd2dbd8f8", + "RegionalDomainName" + ] + }, + "HostedZoneId": { + "Fn::GetAtt": [ + "ApiGatewayDomainName3fd2dbd8f8", + "RegionalHostedZoneId" + ] + } + }, + "Name": "admin.two.amazon.com", + "Type": "A" + } + ] + }, + "Type": "AWS::Route53::RecordSetGroup" + } + } +}