From 4d492aafc6ca8eb6a28814174fbac0d6dd81519c Mon Sep 17 00:00:00 2001 From: Mehmet Nuri Deveci <5735811+mndeveci@users.noreply.github.com> Date: Wed, 19 May 2021 17:21:43 -0700 Subject: [PATCH 1/7] do not propagate attributes to CognitoUserPool --- samtranslator/model/eventsources/push.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/samtranslator/model/eventsources/push.py b/samtranslator/model/eventsources/push.py index 39792c2118..de0f996379 100644 --- a/samtranslator/model/eventsources/push.py +++ b/samtranslator/model/eventsources/push.py @@ -960,9 +960,6 @@ def to_cloudformation(self, **kwargs): resources.append(lambda_permission) self._inject_lambda_config(function, userpool) - userpool_resource = CognitoUserPool.from_dict(userpool_id, userpool) - for attribute, value in function.get_passthrough_resource_attributes().items(): - userpool_resource.set_resource_attribute(attribute, value) resources.append(CognitoUserPool.from_dict(userpool_id, userpool)) return resources From eed0d81076abf4583f2ccdc680565d09530cff51 Mon Sep 17 00:00:00 2001 From: Mehmet Nuri Deveci <5735811+mndeveci@users.noreply.github.com> Date: Wed, 19 May 2021 19:14:28 -0700 Subject: [PATCH 2/7] shared usage plan with propagated resource level attributes --- samtranslator/model/api/api_generator.py | 92 ++++++++++++++++++++++-- samtranslator/model/sam_resources.py | 2 + 2 files changed, 87 insertions(+), 7 deletions(-) diff --git a/samtranslator/model/api/api_generator.py b/samtranslator/model/api/api_generator.py index eef1d3d27f..5fe55b24e5 100644 --- a/samtranslator/model/api/api_generator.py +++ b/samtranslator/model/api/api_generator.py @@ -1,7 +1,9 @@ import logging from collections import namedtuple +from copy import deepcopy + from six import string_types -from samtranslator.model.intrinsics import ref, fnGetAtt +from samtranslator.model.intrinsics import ref, fnGetAtt, make_or_condition from samtranslator.model.apigateway import ( ApiGatewayDeployment, ApiGatewayRestApi, @@ -15,7 +17,7 @@ ApiGatewayApiKey, ) from samtranslator.model.route53 import Route53RecordSetGroup -from samtranslator.model.exceptions import InvalidResourceException +from samtranslator.model.exceptions import InvalidResourceException, InvalidTemplateException from samtranslator.model.s3_utils.uri_parser import parse_s3_uri from samtranslator.region_configuration import RegionConfiguration from samtranslator.swagger.swagger import SwaggerEditor @@ -61,12 +63,80 @@ class SharedApiUsagePlan(object): so that these information can be used in the shared usage plan """ + SHARED_USAGE_PLAN_CONDITION_NAME = "SharedUsagePlanCondition" + def __init__(self): self.usage_plan_shared = False self.stage_keys_shared = list() self.api_stages_shared = list() self.depends_on_shared = list() + # shared resource level attributes + self.conditions = set() + self.any_api_without_condition = False + self.deletion_policy = None + self.update_replace_policy = None + + def get_combined_resource_attributes(self, resource_attributes, conditions): + self.set_deletion_policy(resource_attributes.get("DeletionPolicy")) + self.set_update_replace_policy(resource_attributes.get("UpdateReplacePolicy")) + self.set_condition(resource_attributes.get("Condition"), conditions) + + combined_resource_attributes = deepcopy(resource_attributes) + if self.deletion_policy: + combined_resource_attributes["DeletionPolicy"] = self.deletion_policy + if self.update_replace_policy: + combined_resource_attributes["UpdateReplacePolicy"] = self.update_replace_policy + if self.conditions and not self.any_api_without_condition: + combined_resource_attributes["Condition"] = SharedApiUsagePlan.SHARED_USAGE_PLAN_CONDITION_NAME + + return combined_resource_attributes + + def set_deletion_policy(self, deletion_policy): + if deletion_policy: + if self.deletion_policy: + # update only if new deletion policy is Retain + if deletion_policy == "Retain": + self.deletion_policy = deletion_policy + else: + self.deletion_policy = deletion_policy + + def set_update_replace_policy(self, update_replace_policy): + if update_replace_policy: + if self.update_replace_policy: + # if new value is Retain or + # new value is retain and current value is Delete then update its value + if (update_replace_policy == "Retain") or ( + update_replace_policy == "Snapshot" and self.update_replace_policy == "Delete" + ): + self.update_replace_policy = update_replace_policy + else: + self.update_replace_policy = update_replace_policy + + def set_condition(self, condition, template_conditions): + # if there are any API without condition, then skip + if self.any_api_without_condition: + return + + if condition and condition not in self.conditions: + + if template_conditions is None: + raise InvalidTemplateException( + "Can't have condition without having 'Conditions' section in the template" + ) + + if self.conditions: + self.conditions.add(condition) + or_condition = make_or_condition(self.conditions) + template_conditions[SharedApiUsagePlan.SHARED_USAGE_PLAN_CONDITION_NAME] = or_condition + else: + self.conditions.add(condition) + template_conditions[SharedApiUsagePlan.SHARED_USAGE_PLAN_CONDITION_NAME] = condition + elif condition is None: + self.any_api_without_condition = True + if template_conditions and SharedApiUsagePlan.SHARED_USAGE_PLAN_CONDITION_NAME in template_conditions: + del template_conditions[SharedApiUsagePlan.SHARED_USAGE_PLAN_CONDITION_NAME] + class ApiGenerator(object): def __init__( @@ -81,6 +151,7 @@ def __init__( name, stage_name, shared_api_usage_plan, + template_conditions, tags=None, endpoint_configuration=None, method_settings=None, @@ -147,6 +218,7 @@ def __init__( self.domain = domain self.description = description self.shared_api_usage_plan = shared_api_usage_plan + self.template_conditions = template_conditions def _construct_rest_api(self): """Constructs and returns the ApiGateway RestApi. @@ -654,7 +726,9 @@ def _construct_usage_plan(self, rest_api_stage=None): usage_plan = ApiGatewayUsagePlan( logical_id=usage_plan_logical_id, depends_on=self.shared_api_usage_plan.depends_on_shared, - attributes=self.passthrough_resource_attributes, + attributes=self.shared_api_usage_plan.get_combined_resource_attributes( + self.passthrough_resource_attributes, self.template_conditions + ), ) api_stage = dict() api_stage["ApiId"] = ref(self.logical_id) @@ -692,7 +766,9 @@ def _construct_api_key(self, usage_plan_logical_id, create_usage_plan, rest_api_ api_key = ApiGatewayApiKey( logical_id=api_key_logical_id, depends_on=[usage_plan_logical_id], - attributes=self.passthrough_resource_attributes, + attributes=self.shared_api_usage_plan.get_combined_resource_attributes( + self.passthrough_resource_attributes, self.template_conditions + ), ) api_key.Enabled = True stage_key = dict() @@ -710,7 +786,6 @@ def _construct_api_key(self, usage_plan_logical_id, create_usage_plan, rest_api_ depends_on=[usage_plan_logical_id], attributes=self.passthrough_resource_attributes, ) - # api_key = ApiGatewayApiKey(logical_id=api_key_logical_id, depends_on=[usage_plan_logical_id]) api_key.Enabled = True stage_keys = list() stage_key = dict() @@ -730,17 +805,20 @@ def _construct_usage_plan_key(self, usage_plan_logical_id, create_usage_plan, ap if create_usage_plan == "SHARED": # create a mapping between api key and the usage plan usage_plan_key_logical_id = "ServerlessUsagePlanKey" + resource_attributes = self.shared_api_usage_plan.get_combined_resource_attributes( + self.passthrough_resource_attributes, self.template_conditions + ) # for create_usage_plan = "PER_API" else: # create a mapping between api key and the usage plan usage_plan_key_logical_id = self.logical_id + "UsagePlanKey" + resource_attributes = self.passthrough_resource_attributes usage_plan_key = ApiGatewayUsagePlanKey( logical_id=usage_plan_key_logical_id, depends_on=[api_key.logical_id], - attributes=self.passthrough_resource_attributes, + attributes=resource_attributes, ) - # usage_plan_key = ApiGatewayUsagePlanKey(logical_id=usage_plan_key_logical_id, depends_on=[api_key.logical_id]) usage_plan_key.KeyId = ref(api_key.logical_id) usage_plan_key.KeyType = "API_KEY" usage_plan_key.UsagePlanId = ref(usage_plan_logical_id) diff --git a/samtranslator/model/sam_resources.py b/samtranslator/model/sam_resources.py index b0d179c2f4..516d5b3de5 100644 --- a/samtranslator/model/sam_resources.py +++ b/samtranslator/model/sam_resources.py @@ -862,6 +862,7 @@ def to_cloudformation(self, **kwargs): self.Auth = intrinsics_resolver.resolve_parameter_refs(self.Auth) redeploy_restapi_parameters = kwargs.get("redeploy_restapi_parameters") shared_api_usage_plan = kwargs.get("shared_api_usage_plan") + template_conditions = kwargs.get("conditions") api_generator = ApiGenerator( self.logical_id, @@ -874,6 +875,7 @@ def to_cloudformation(self, **kwargs): self.Name, self.StageName, shared_api_usage_plan, + template_conditions, tags=self.Tags, endpoint_configuration=self.EndpointConfiguration, method_settings=self.MethodSettings, From 60214201750dd160adf3d194ef38c3d7fc10ce0c Mon Sep 17 00:00:00 2001 From: Mehmet Nuri Deveci <5735811+mndeveci@users.noreply.github.com> Date: Wed, 19 May 2021 20:04:15 -0700 Subject: [PATCH 3/7] add unit tests --- samtranslator/model/api/api_generator.py | 26 ++- .../unit/model/api/TestSharedApiUsagePlan.py | 158 ++++++++++++++++++ 2 files changed, 177 insertions(+), 7 deletions(-) create mode 100644 tests/unit/model/api/TestSharedApiUsagePlan.py diff --git a/samtranslator/model/api/api_generator.py b/samtranslator/model/api/api_generator.py index 5fe55b24e5..60e0f54c83 100644 --- a/samtranslator/model/api/api_generator.py +++ b/samtranslator/model/api/api_generator.py @@ -78,21 +78,33 @@ def __init__(self): self.update_replace_policy = None def get_combined_resource_attributes(self, resource_attributes, conditions): - self.set_deletion_policy(resource_attributes.get("DeletionPolicy")) - self.set_update_replace_policy(resource_attributes.get("UpdateReplacePolicy")) - self.set_condition(resource_attributes.get("Condition"), conditions) + """ + This method returns a dictionary which combines 'DeletionPolicy', 'UpdateReplacePolicy' and 'Condition' + values of API definitions that could be used in Shared Usage Plan resources. + + Parameters + ---------- + resource_attributes: Dict[str] + A dictionary of resource level attributes of the API resource + conditions: Dict[str] + Conditions section of the template + """ + self._set_deletion_policy(resource_attributes.get("DeletionPolicy")) + self._set_update_replace_policy(resource_attributes.get("UpdateReplacePolicy")) + self._set_condition(resource_attributes.get("Condition"), conditions) - combined_resource_attributes = deepcopy(resource_attributes) + combined_resource_attributes = dict() if self.deletion_policy: combined_resource_attributes["DeletionPolicy"] = self.deletion_policy if self.update_replace_policy: combined_resource_attributes["UpdateReplacePolicy"] = self.update_replace_policy + # do not set Condition if any of the API resource does not have Condition in it if self.conditions and not self.any_api_without_condition: combined_resource_attributes["Condition"] = SharedApiUsagePlan.SHARED_USAGE_PLAN_CONDITION_NAME return combined_resource_attributes - def set_deletion_policy(self, deletion_policy): + def _set_deletion_policy(self, deletion_policy): if deletion_policy: if self.deletion_policy: # update only if new deletion policy is Retain @@ -101,7 +113,7 @@ def set_deletion_policy(self, deletion_policy): else: self.deletion_policy = deletion_policy - def set_update_replace_policy(self, update_replace_policy): + def _set_update_replace_policy(self, update_replace_policy): if update_replace_policy: if self.update_replace_policy: # if new value is Retain or @@ -113,7 +125,7 @@ def set_update_replace_policy(self, update_replace_policy): else: self.update_replace_policy = update_replace_policy - def set_condition(self, condition, template_conditions): + def _set_condition(self, condition, template_conditions): # if there are any API without condition, then skip if self.any_api_without_condition: return diff --git a/tests/unit/model/api/TestSharedApiUsagePlan.py b/tests/unit/model/api/TestSharedApiUsagePlan.py new file mode 100644 index 0000000000..5a7cd59986 --- /dev/null +++ b/tests/unit/model/api/TestSharedApiUsagePlan.py @@ -0,0 +1,158 @@ +from unittest import TestCase + +from parameterized import parameterized, param + +from samtranslator.model.api.api_generator import SharedApiUsagePlan +from samtranslator.model.exceptions import InvalidTemplateException + + +class TestSharedApiUsagePlan(TestCase): + + def setUp(self): + self.shared_usage_plan = SharedApiUsagePlan() + + def test_values_should_be_propagated(self): + conditions = {} + actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( + { + "Condition": "C1", + "DeletionPolicy": "Delete", + "UpdateReplacePolicy": "Delete", + }, + conditions + ) + + self.assertEqual( + { + "Condition": SharedApiUsagePlan.SHARED_USAGE_PLAN_CONDITION_NAME, + "DeletionPolicy": "Delete", + "UpdateReplacePolicy": "Delete", + }, + actual_attributes + ) + + self.assertEqual(conditions, {'SharedUsagePlanCondition': 'C1'}) + + @parameterized.expand([ + ([None], ), + ([None, "C1"], ), + (["C1", None], ), + (["C1", "C2"], ), + (["C1", "C2", "C3"], ), + ]) + def test_multiple_apis_with_conditions(self, api_conditions): + template_conditions = dict() + result = {} + for api_condition in api_conditions: + result = self.shared_usage_plan.get_combined_resource_attributes( + {"Condition": api_condition}, + template_conditions + ) + print(f"Calling with {api_condition} result {result}") + + if None in api_conditions: + self.assertEqual({}, result) + self.assertEqual({}, template_conditions) + else: + print(template_conditions) + self.assertTrue("SharedUsagePlanCondition" in template_conditions) + self.assertEqual({"Condition": "SharedUsagePlanCondition"}, result) + combined_conditions = [ + condition.get("Condition") + for condition in + template_conditions.get("SharedUsagePlanCondition", {}).get("Fn::Or") + ] + for combined_condition in combined_conditions: + self.assertTrue(combined_condition in api_conditions) + + + def test_should_raise_invalid_template_when_no_conditions_section(self): + with self.assertRaises(InvalidTemplateException): + self.shared_usage_plan.get_combined_resource_attributes( + {"Condition": "C1"}, + None + ) + + def test_deletion_policy_priority(self): + # first api sets it to delete + actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( + { + "DeletionPolicy": "Delete" + }, + {} + ) + self.assertEqual(actual_attributes["DeletionPolicy"], "Delete") + + # then second api sets it to Retain + actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( + { + "DeletionPolicy": "Retain" + }, + {} + ) + self.assertEqual(actual_attributes["DeletionPolicy"], "Retain") + + # if third api sets it to delete, it should keep retain value + actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( + { + "DeletionPolicy": "Delete" + }, + {} + ) + self.assertEqual(actual_attributes["DeletionPolicy"], "Retain") + + def test_update_replace_policy_priority(self): + # first api sets it to delete + actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( + { + "UpdateReplacePolicy": "Delete" + }, + {} + ) + self.assertEqual(actual_attributes["UpdateReplacePolicy"], "Delete") + + # then second api sets it to Retain + actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( + { + "UpdateReplacePolicy": "Snapshot" + }, + {} + ) + self.assertEqual(actual_attributes["UpdateReplacePolicy"], "Snapshot") + + # if third api sets it to delete, it should keep retain value + actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( + { + "UpdateReplacePolicy": "Delete" + }, + {} + ) + self.assertEqual(actual_attributes["UpdateReplacePolicy"], "Snapshot") + + # if third api sets it to delete, it should keep retain value + actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( + { + "UpdateReplacePolicy": "Retain" + }, + {} + ) + self.assertEqual(actual_attributes["UpdateReplacePolicy"], "Retain") + + # if third api sets it to delete, it should keep retain value + actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( + { + "UpdateReplacePolicy": "Snapshot" + }, + {} + ) + self.assertEqual(actual_attributes["UpdateReplacePolicy"], "Retain") + + # if third api sets it to delete, it should keep retain value + actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( + { + "UpdateReplacePolicy": "Delete" + }, + {} + ) + self.assertEqual(actual_attributes["UpdateReplacePolicy"], "Retain") + From c3703eb1aea80de4615000d9875f554cc44c1c3a Mon Sep 17 00:00:00 2001 From: Qingchuan Ma Date: Wed, 19 May 2021 20:21:31 -0700 Subject: [PATCH 4/7] Added test templates for shared usage plan with resource attributes --- ...th_usageplans_shared_attributes_three.yaml | 102 ++++ ...with_usageplans_shared_attributes_two.yaml | 75 +++ ...th_usageplans_shared_attributes_three.json | 524 +++++++++++++++++ ...with_usageplans_shared_attributes_two.json | 385 ++++++++++++ ...th_usageplans_shared_attributes_three.json | 548 ++++++++++++++++++ ...with_usageplans_shared_attributes_two.json | 401 +++++++++++++ ...th_usageplans_shared_attributes_three.json | 548 ++++++++++++++++++ ...with_usageplans_shared_attributes_two.json | 401 +++++++++++++ tests/translator/test_translator.py | 2 + 9 files changed, 2986 insertions(+) create mode 100644 tests/translator/input/api_with_usageplans_shared_attributes_three.yaml create mode 100644 tests/translator/input/api_with_usageplans_shared_attributes_two.yaml create mode 100644 tests/translator/output/api_with_usageplans_shared_attributes_three.json create mode 100644 tests/translator/output/api_with_usageplans_shared_attributes_two.json create mode 100644 tests/translator/output/aws-cn/api_with_usageplans_shared_attributes_three.json create mode 100644 tests/translator/output/aws-cn/api_with_usageplans_shared_attributes_two.json create mode 100644 tests/translator/output/aws-us-gov/api_with_usageplans_shared_attributes_three.json create mode 100644 tests/translator/output/aws-us-gov/api_with_usageplans_shared_attributes_two.json diff --git a/tests/translator/input/api_with_usageplans_shared_attributes_three.yaml b/tests/translator/input/api_with_usageplans_shared_attributes_three.yaml new file mode 100644 index 0000000000..aed811ca0a --- /dev/null +++ b/tests/translator/input/api_with_usageplans_shared_attributes_three.yaml @@ -0,0 +1,102 @@ +Globals: + Api: + Auth: + ApiKeyRequired: true + UsagePlan: + CreateUsagePlan: SHARED + +Conditions: + C1: + Fn::Equals: + - test + - test + C2: + Fn::Equals: + - test + - test + +Resources: + MyApiOne: + Type: AWS::Serverless::Api + Condition: C1 + UpdateReplacePolicy: Delete + Properties: + StageName: Prod + + MyApiTwo: + Type: AWS::Serverless::Api + Condition: C2 + UpdateReplacePolicy: Snapshot + Properties: + StageName: Prod + + MyApiThree: + Type: AWS::Serverless::Api + Properties: + StageName: Prod + + MyFunctionOne: + Type: AWS::Serverless::Function + Properties: + Handler: index.handler + Runtime: nodejs12.x + InlineCode: | + exports.handler = async (event) => { + return { + statusCode: 200, + body: JSON.stringify(event), + headers: {} + } + } + Events: + ApiKey: + Type: Api + Properties: + RestApiId: + Ref: MyApiOne + Method: get + Path: /path/one + + MyFunctionTwo: + Type: AWS::Serverless::Function + Properties: + Handler: index.handler + Runtime: nodejs12.x + InlineCode: | + exports.handler = async (event) => { + return { + statusCode: 200, + body: JSON.stringify(event), + headers: {} + } + } + Events: + ApiKey: + Type: Api + Properties: + RestApiId: + Ref: MyApiTwo + Method: get + Path: /path/two + + MyFunctionThree: + Type: AWS::Serverless::Function + Properties: + Handler: index.handler + Runtime: nodejs12.x + InlineCode: | + exports.handler = async (event) => { + return { + statusCode: 200, + body: JSON.stringify(event), + headers: {} + } + } + Events: + ApiKey: + Type: Api + Properties: + RestApiId: + Ref: MyApiThree + Method: get + Path: /path/three \ No newline at end of file diff --git a/tests/translator/input/api_with_usageplans_shared_attributes_two.yaml b/tests/translator/input/api_with_usageplans_shared_attributes_two.yaml new file mode 100644 index 0000000000..36c5bab657 --- /dev/null +++ b/tests/translator/input/api_with_usageplans_shared_attributes_two.yaml @@ -0,0 +1,75 @@ +Globals: + Api: + Auth: + ApiKeyRequired: true + UsagePlan: + CreateUsagePlan: SHARED + +Conditions: + C1: + Fn::Equals: + - test + - test + C2: + Fn::Equals: + - test + - test + +Resources: + MyApiOne: + Type: AWS::Serverless::Api + DeletionPolicy: Delete + Condition: C1 + Properties: + StageName: Prod + + MyApiTwo: + Type: AWS::Serverless::Api + DeletionPolicy: Retain + Condition: C2 + Properties: + StageName: Prod + + MyFunctionOne: + Type: AWS::Serverless::Function + Properties: + Handler: index.handler + Runtime: nodejs12.x + InlineCode: | + exports.handler = async (event) => { + return { + statusCode: 200, + body: JSON.stringify(event), + headers: {} + } + } + Events: + ApiKey: + Type: Api + Properties: + RestApiId: + Ref: MyApiOne + Method: get + Path: /path/one + + MyFunctionTwo: + Type: AWS::Serverless::Function + Properties: + Handler: index.handler + Runtime: nodejs12.x + InlineCode: | + exports.handler = async (event) => { + return { + statusCode: 200, + body: JSON.stringify(event), + headers: {} + } + } + Events: + ApiKey: + Type: Api + Properties: + RestApiId: + Ref: MyApiTwo + Method: get + Path: /path/two \ No newline at end of file diff --git a/tests/translator/output/api_with_usageplans_shared_attributes_three.json b/tests/translator/output/api_with_usageplans_shared_attributes_three.json new file mode 100644 index 0000000000..764b7ed357 --- /dev/null +++ b/tests/translator/output/api_with_usageplans_shared_attributes_three.json @@ -0,0 +1,524 @@ +{ + "Conditions": { + "C1": { + "Fn::Equals": [ + "test", + "test" + ] + }, + "C2": { + "Fn::Equals": [ + "test", + "test" + ] + } + }, + "Resources": { + "MyFunctionOne": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (event) => {\n return {\n statusCode: 200,\n body: JSON.stringify(event),\n headers: {}\n }\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyFunctionOneRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionOneRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionOneApiKeyPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionOne" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/path/one", + { + "__ApiId__": { + "Ref": "MyApiOne" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyFunctionTwo": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (event) => {\n return {\n statusCode: 200,\n body: JSON.stringify(event),\n headers: {}\n }\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyFunctionTwoRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionTwoRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionTwoApiKeyPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionTwo" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/path/two", + { + "__ApiId__": { + "Ref": "MyApiTwo" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyFunctionThree": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (event) => {\n return {\n statusCode: 200,\n body: JSON.stringify(event),\n headers: {}\n }\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyFunctionThreeRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionThreeRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionThreeApiKeyPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionThree" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/path/three", + { + "__ApiId__": { + "Ref": "MyApiThree" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyApiOne": { + "Type": "AWS::ApiGateway::RestApi", + "Condition": "C1", + "UpdateReplacePolicy": "Delete", + "Properties": { + "Body": { + "swagger": "2.0", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/path/one": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionOne.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "api_key": [] + } + ] + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "x-api-key", + "in": "header" + } + } + } + } + }, + "MyApiOneDeployment593a0a0946": { + "Type": "AWS::ApiGateway::Deployment", + "Condition": "C1", + "UpdateReplacePolicy": "Delete", + "Properties": { + "Description": "RestApi deployment id: 593a0a094683480e951e7daed89e6f2ea946b7c4", + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": "Stage" + } + }, + "MyApiOneProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Condition": "C1", + "UpdateReplacePolicy": "Delete", + "Properties": { + "DeploymentId": { + "Ref": "MyApiOneDeployment593a0a0946" + }, + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": "Prod" + } + }, + "ServerlessUsagePlan": { + "Type": "AWS::ApiGateway::UsagePlan", + "DependsOn": [ + "MyApiOne", + "MyApiTwo", + "MyApiThree" + ], + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "ApiStages": [ + { + "ApiId": { + "Ref": "MyApiOne" + }, + "Stage": { + "Ref": "MyApiOneProdStage" + } + }, + { + "ApiId": { + "Ref": "MyApiTwo" + }, + "Stage": { + "Ref": "MyApiTwoProdStage" + } + }, + { + "ApiId": { + "Ref": "MyApiThree" + }, + "Stage": { + "Ref": "MyApiThreeProdStage" + } + } + ] + } + }, + "ServerlessApiKey": { + "Type": "AWS::ApiGateway::ApiKey", + "DependsOn": [ + "ServerlessUsagePlan" + ], + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "Enabled": true, + "StageKeys": [ + { + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": { + "Ref": "MyApiOneProdStage" + } + }, + { + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": { + "Ref": "MyApiTwoProdStage" + } + }, + { + "RestApiId": { + "Ref": "MyApiThree" + }, + "StageName": { + "Ref": "MyApiThreeProdStage" + } + } + ] + } + }, + "ServerlessUsagePlanKey": { + "Type": "AWS::ApiGateway::UsagePlanKey", + "DependsOn": [ + "ServerlessApiKey" + ], + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "KeyId": { + "Ref": "ServerlessApiKey" + }, + "KeyType": "API_KEY", + "UsagePlanId": { + "Ref": "ServerlessUsagePlan" + } + } + }, + "MyApiTwo": { + "Type": "AWS::ApiGateway::RestApi", + "Condition": "C2", + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "Body": { + "swagger": "2.0", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/path/two": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionTwo.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "api_key": [] + } + ] + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "x-api-key", + "in": "header" + } + } + } + } + }, + "MyApiTwoDeployment0c6c2a5588": { + "Type": "AWS::ApiGateway::Deployment", + "Condition": "C2", + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "Description": "RestApi deployment id: 0c6c2a5588069f784aaa1c010c10055bdb5fd7f7", + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": "Stage" + } + }, + "MyApiTwoProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Condition": "C2", + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "DeploymentId": { + "Ref": "MyApiTwoDeployment0c6c2a5588" + }, + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": "Prod" + } + }, + "MyApiThree": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "swagger": "2.0", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/path/three": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionThree.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "api_key": [] + } + ] + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "x-api-key", + "in": "header" + } + } + } + } + }, + "MyApiThreeDeployment8af42ea6fa": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "Description": "RestApi deployment id: 8af42ea6fa6c0dc81aa34a29baae4eb4670a7b8a", + "RestApiId": { + "Ref": "MyApiThree" + }, + "StageName": "Stage" + } + }, + "MyApiThreeProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "MyApiThreeDeployment8af42ea6fa" + }, + "RestApiId": { + "Ref": "MyApiThree" + }, + "StageName": "Prod" + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/api_with_usageplans_shared_attributes_two.json b/tests/translator/output/api_with_usageplans_shared_attributes_two.json new file mode 100644 index 0000000000..4705bd9238 --- /dev/null +++ b/tests/translator/output/api_with_usageplans_shared_attributes_two.json @@ -0,0 +1,385 @@ +{ + "Conditions": { + "C1": { + "Fn::Equals": [ + "test", + "test" + ] + }, + "C2": { + "Fn::Equals": [ + "test", + "test" + ] + }, + "SharedUsagePlanCondition": { + "Fn::Or": [ + { + "Condition": "C2" + }, + { + "Condition": "C1" + } + ] + } + }, + "Resources": { + "MyFunctionOne": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (event) => {\n return {\n statusCode: 200,\n body: JSON.stringify(event),\n headers: {}\n }\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyFunctionOneRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionOneRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionOneApiKeyPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionOne" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/path/one", + { + "__ApiId__": { + "Ref": "MyApiOne" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyFunctionTwo": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (event) => {\n return {\n statusCode: 200,\n body: JSON.stringify(event),\n headers: {}\n }\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyFunctionTwoRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionTwoRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionTwoApiKeyPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionTwo" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/path/two", + { + "__ApiId__": { + "Ref": "MyApiTwo" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyApiOne": { + "Type": "AWS::ApiGateway::RestApi", + "DeletionPolicy": "Delete", + "Condition": "C1", + "Properties": { + "Body": { + "swagger": "2.0", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/path/one": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionOne.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "api_key": [] + } + ] + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "x-api-key", + "in": "header" + } + } + } + } + }, + "MyApiOneDeployment593a0a0946": { + "Type": "AWS::ApiGateway::Deployment", + "Condition": "C1", + "DeletionPolicy": "Delete", + "Properties": { + "Description": "RestApi deployment id: 593a0a094683480e951e7daed89e6f2ea946b7c4", + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": "Stage" + } + }, + "MyApiOneProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Condition": "C1", + "DeletionPolicy": "Delete", + "Properties": { + "DeploymentId": { + "Ref": "MyApiOneDeployment593a0a0946" + }, + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": "Prod" + } + }, + "ServerlessUsagePlan": { + "Type": "AWS::ApiGateway::UsagePlan", + "DependsOn": [ + "MyApiOne", + "MyApiTwo" + ], + "Condition": "SharedUsagePlanCondition", + "DeletionPolicy": "Retain", + "Properties": { + "ApiStages": [ + { + "ApiId": { + "Ref": "MyApiOne" + }, + "Stage": { + "Ref": "MyApiOneProdStage" + } + }, + { + "ApiId": { + "Ref": "MyApiTwo" + }, + "Stage": { + "Ref": "MyApiTwoProdStage" + } + } + ] + } + }, + "ServerlessApiKey": { + "Type": "AWS::ApiGateway::ApiKey", + "DependsOn": [ + "ServerlessUsagePlan" + ], + "Condition": "SharedUsagePlanCondition", + "DeletionPolicy": "Retain", + "Properties": { + "Enabled": true, + "StageKeys": [ + { + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": { + "Ref": "MyApiOneProdStage" + } + }, + { + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": { + "Ref": "MyApiTwoProdStage" + } + } + ] + } + }, + "ServerlessUsagePlanKey": { + "Type": "AWS::ApiGateway::UsagePlanKey", + "DependsOn": [ + "ServerlessApiKey" + ], + "Condition": "SharedUsagePlanCondition", + "DeletionPolicy": "Retain", + "Properties": { + "KeyId": { + "Ref": "ServerlessApiKey" + }, + "KeyType": "API_KEY", + "UsagePlanId": { + "Ref": "ServerlessUsagePlan" + } + } + }, + "MyApiTwo": { + "Type": "AWS::ApiGateway::RestApi", + "DeletionPolicy": "Retain", + "Condition": "C2", + "Properties": { + "Body": { + "swagger": "2.0", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/path/two": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "uri": { + "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionTwo.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "api_key": [] + } + ] + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "x-api-key", + "in": "header" + } + } + } + } + }, + "MyApiTwoDeployment0c6c2a5588": { + "Type": "AWS::ApiGateway::Deployment", + "Condition": "C2", + "DeletionPolicy": "Retain", + "Properties": { + "Description": "RestApi deployment id: 0c6c2a5588069f784aaa1c010c10055bdb5fd7f7", + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": "Stage" + } + }, + "MyApiTwoProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Condition": "C2", + "DeletionPolicy": "Retain", + "Properties": { + "DeploymentId": { + "Ref": "MyApiTwoDeployment0c6c2a5588" + }, + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": "Prod" + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/aws-cn/api_with_usageplans_shared_attributes_three.json b/tests/translator/output/aws-cn/api_with_usageplans_shared_attributes_three.json new file mode 100644 index 0000000000..45fab46e5e --- /dev/null +++ b/tests/translator/output/aws-cn/api_with_usageplans_shared_attributes_three.json @@ -0,0 +1,548 @@ +{ + "Conditions": { + "C1": { + "Fn::Equals": [ + "test", + "test" + ] + }, + "C2": { + "Fn::Equals": [ + "test", + "test" + ] + } + }, + "Resources": { + "MyFunctionOne": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (event) => {\n return {\n statusCode: 200,\n body: JSON.stringify(event),\n headers: {}\n }\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyFunctionOneRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionOneRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionOneApiKeyPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionOne" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/path/one", + { + "__ApiId__": { + "Ref": "MyApiOne" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyFunctionTwo": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (event) => {\n return {\n statusCode: 200,\n body: JSON.stringify(event),\n headers: {}\n }\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyFunctionTwoRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionTwoRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionTwoApiKeyPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionTwo" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/path/two", + { + "__ApiId__": { + "Ref": "MyApiTwo" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyFunctionThree": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (event) => {\n return {\n statusCode: 200,\n body: JSON.stringify(event),\n headers: {}\n }\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyFunctionThreeRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionThreeRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionThreeApiKeyPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionThree" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/path/three", + { + "__ApiId__": { + "Ref": "MyApiThree" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyApiOne": { + "Type": "AWS::ApiGateway::RestApi", + "Condition": "C1", + "UpdateReplacePolicy": "Delete", + "Properties": { + "Body": { + "swagger": "2.0", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/path/one": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "uri": { + "Fn::Sub": "arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionOne.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "api_key": [] + } + ] + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "x-api-key", + "in": "header" + } + } + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + } + } + }, + "MyApiOneDeploymented8916593e": { + "Type": "AWS::ApiGateway::Deployment", + "Condition": "C1", + "UpdateReplacePolicy": "Delete", + "Properties": { + "Description": "RestApi deployment id: ed8916593eee3d5996ff3d7912710b8fac532e60", + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": "Stage" + } + }, + "MyApiOneProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Condition": "C1", + "UpdateReplacePolicy": "Delete", + "Properties": { + "DeploymentId": { + "Ref": "MyApiOneDeploymented8916593e" + }, + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": "Prod" + } + }, + "ServerlessUsagePlan": { + "Type": "AWS::ApiGateway::UsagePlan", + "DependsOn": [ + "MyApiOne", + "MyApiTwo", + "MyApiThree" + ], + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "ApiStages": [ + { + "ApiId": { + "Ref": "MyApiOne" + }, + "Stage": { + "Ref": "MyApiOneProdStage" + } + }, + { + "ApiId": { + "Ref": "MyApiTwo" + }, + "Stage": { + "Ref": "MyApiTwoProdStage" + } + }, + { + "ApiId": { + "Ref": "MyApiThree" + }, + "Stage": { + "Ref": "MyApiThreeProdStage" + } + } + ] + } + }, + "ServerlessApiKey": { + "Type": "AWS::ApiGateway::ApiKey", + "DependsOn": [ + "ServerlessUsagePlan" + ], + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "Enabled": true, + "StageKeys": [ + { + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": { + "Ref": "MyApiOneProdStage" + } + }, + { + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": { + "Ref": "MyApiTwoProdStage" + } + }, + { + "RestApiId": { + "Ref": "MyApiThree" + }, + "StageName": { + "Ref": "MyApiThreeProdStage" + } + } + ] + } + }, + "ServerlessUsagePlanKey": { + "Type": "AWS::ApiGateway::UsagePlanKey", + "DependsOn": [ + "ServerlessApiKey" + ], + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "KeyId": { + "Ref": "ServerlessApiKey" + }, + "KeyType": "API_KEY", + "UsagePlanId": { + "Ref": "ServerlessUsagePlan" + } + } + }, + "MyApiTwo": { + "Type": "AWS::ApiGateway::RestApi", + "Condition": "C2", + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "Body": { + "swagger": "2.0", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/path/two": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "uri": { + "Fn::Sub": "arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionTwo.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "api_key": [] + } + ] + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "x-api-key", + "in": "header" + } + } + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + } + } + }, + "MyApiTwoDeployment17dd9ed926": { + "Type": "AWS::ApiGateway::Deployment", + "Condition": "C2", + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "Description": "RestApi deployment id: 17dd9ed92642dde88467fc566c4a64befb1d3a2d", + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": "Stage" + } + }, + "MyApiTwoProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Condition": "C2", + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "DeploymentId": { + "Ref": "MyApiTwoDeployment17dd9ed926" + }, + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": "Prod" + } + }, + "MyApiThree": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "swagger": "2.0", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/path/three": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "uri": { + "Fn::Sub": "arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionThree.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "api_key": [] + } + ] + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "x-api-key", + "in": "header" + } + } + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + } + } + }, + "MyApiThreeDeployment0ac39d26ff": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "Description": "RestApi deployment id: 0ac39d26ffc79dae8849daf66e76214028279104", + "RestApiId": { + "Ref": "MyApiThree" + }, + "StageName": "Stage" + } + }, + "MyApiThreeProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "MyApiThreeDeployment0ac39d26ff" + }, + "RestApiId": { + "Ref": "MyApiThree" + }, + "StageName": "Prod" + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/aws-cn/api_with_usageplans_shared_attributes_two.json b/tests/translator/output/aws-cn/api_with_usageplans_shared_attributes_two.json new file mode 100644 index 0000000000..515af3e7f9 --- /dev/null +++ b/tests/translator/output/aws-cn/api_with_usageplans_shared_attributes_two.json @@ -0,0 +1,401 @@ +{ + "Conditions": { + "C1": { + "Fn::Equals": [ + "test", + "test" + ] + }, + "C2": { + "Fn::Equals": [ + "test", + "test" + ] + }, + "SharedUsagePlanCondition": { + "Fn::Or": [ + { + "Condition": "C1" + }, + { + "Condition": "C2" + } + ] + } + }, + "Resources": { + "MyFunctionOne": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (event) => {\n return {\n statusCode: 200,\n body: JSON.stringify(event),\n headers: {}\n }\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyFunctionOneRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionOneRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionOneApiKeyPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionOne" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/path/one", + { + "__ApiId__": { + "Ref": "MyApiOne" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyFunctionTwo": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (event) => {\n return {\n statusCode: 200,\n body: JSON.stringify(event),\n headers: {}\n }\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyFunctionTwoRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionTwoRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionTwoApiKeyPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionTwo" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws-cn:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/path/two", + { + "__ApiId__": { + "Ref": "MyApiTwo" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyApiOne": { + "Type": "AWS::ApiGateway::RestApi", + "DeletionPolicy": "Delete", + "Condition": "C1", + "Properties": { + "Body": { + "swagger": "2.0", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/path/one": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "uri": { + "Fn::Sub": "arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionOne.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "api_key": [] + } + ] + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "x-api-key", + "in": "header" + } + } + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + } + } + }, + "MyApiOneDeploymented8916593e": { + "Type": "AWS::ApiGateway::Deployment", + "Condition": "C1", + "DeletionPolicy": "Delete", + "Properties": { + "Description": "RestApi deployment id: ed8916593eee3d5996ff3d7912710b8fac532e60", + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": "Stage" + } + }, + "MyApiOneProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Condition": "C1", + "DeletionPolicy": "Delete", + "Properties": { + "DeploymentId": { + "Ref": "MyApiOneDeploymented8916593e" + }, + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": "Prod" + } + }, + "ServerlessUsagePlan": { + "Type": "AWS::ApiGateway::UsagePlan", + "DependsOn": [ + "MyApiOne", + "MyApiTwo" + ], + "Condition": "SharedUsagePlanCondition", + "DeletionPolicy": "Retain", + "Properties": { + "ApiStages": [ + { + "ApiId": { + "Ref": "MyApiOne" + }, + "Stage": { + "Ref": "MyApiOneProdStage" + } + }, + { + "ApiId": { + "Ref": "MyApiTwo" + }, + "Stage": { + "Ref": "MyApiTwoProdStage" + } + } + ] + } + }, + "ServerlessApiKey": { + "Type": "AWS::ApiGateway::ApiKey", + "DependsOn": [ + "ServerlessUsagePlan" + ], + "Condition": "SharedUsagePlanCondition", + "DeletionPolicy": "Retain", + "Properties": { + "Enabled": true, + "StageKeys": [ + { + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": { + "Ref": "MyApiOneProdStage" + } + }, + { + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": { + "Ref": "MyApiTwoProdStage" + } + } + ] + } + }, + "ServerlessUsagePlanKey": { + "Type": "AWS::ApiGateway::UsagePlanKey", + "DependsOn": [ + "ServerlessApiKey" + ], + "Condition": "SharedUsagePlanCondition", + "DeletionPolicy": "Retain", + "Properties": { + "KeyId": { + "Ref": "ServerlessApiKey" + }, + "KeyType": "API_KEY", + "UsagePlanId": { + "Ref": "ServerlessUsagePlan" + } + } + }, + "MyApiTwo": { + "Type": "AWS::ApiGateway::RestApi", + "DeletionPolicy": "Retain", + "Condition": "C2", + "Properties": { + "Body": { + "swagger": "2.0", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/path/two": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "uri": { + "Fn::Sub": "arn:aws-cn:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionTwo.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "api_key": [] + } + ] + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "x-api-key", + "in": "header" + } + } + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + } + } + }, + "MyApiTwoDeployment17dd9ed926": { + "Type": "AWS::ApiGateway::Deployment", + "Condition": "C2", + "DeletionPolicy": "Retain", + "Properties": { + "Description": "RestApi deployment id: 17dd9ed92642dde88467fc566c4a64befb1d3a2d", + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": "Stage" + } + }, + "MyApiTwoProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Condition": "C2", + "DeletionPolicy": "Retain", + "Properties": { + "DeploymentId": { + "Ref": "MyApiTwoDeployment17dd9ed926" + }, + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": "Prod" + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/aws-us-gov/api_with_usageplans_shared_attributes_three.json b/tests/translator/output/aws-us-gov/api_with_usageplans_shared_attributes_three.json new file mode 100644 index 0000000000..7fd9dbe508 --- /dev/null +++ b/tests/translator/output/aws-us-gov/api_with_usageplans_shared_attributes_three.json @@ -0,0 +1,548 @@ +{ + "Conditions": { + "C1": { + "Fn::Equals": [ + "test", + "test" + ] + }, + "C2": { + "Fn::Equals": [ + "test", + "test" + ] + } + }, + "Resources": { + "MyFunctionOne": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (event) => {\n return {\n statusCode: 200,\n body: JSON.stringify(event),\n headers: {}\n }\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyFunctionOneRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionOneRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionOneApiKeyPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionOne" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/path/one", + { + "__ApiId__": { + "Ref": "MyApiOne" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyFunctionTwo": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (event) => {\n return {\n statusCode: 200,\n body: JSON.stringify(event),\n headers: {}\n }\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyFunctionTwoRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionTwoRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionTwoApiKeyPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionTwo" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/path/two", + { + "__ApiId__": { + "Ref": "MyApiTwo" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyFunctionThree": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (event) => {\n return {\n statusCode: 200,\n body: JSON.stringify(event),\n headers: {}\n }\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyFunctionThreeRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionThreeRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionThreeApiKeyPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionThree" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/path/three", + { + "__ApiId__": { + "Ref": "MyApiThree" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyApiOne": { + "Type": "AWS::ApiGateway::RestApi", + "Condition": "C1", + "UpdateReplacePolicy": "Delete", + "Properties": { + "Body": { + "swagger": "2.0", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/path/one": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "uri": { + "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionOne.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "api_key": [] + } + ] + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "x-api-key", + "in": "header" + } + } + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + } + } + }, + "MyApiOneDeploymentb12c8b5b0a": { + "Type": "AWS::ApiGateway::Deployment", + "Condition": "C1", + "UpdateReplacePolicy": "Delete", + "Properties": { + "Description": "RestApi deployment id: b12c8b5b0aed50622a06dd52b372f8213a63b39b", + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": "Stage" + } + }, + "MyApiOneProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Condition": "C1", + "UpdateReplacePolicy": "Delete", + "Properties": { + "DeploymentId": { + "Ref": "MyApiOneDeploymentb12c8b5b0a" + }, + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": "Prod" + } + }, + "ServerlessUsagePlan": { + "Type": "AWS::ApiGateway::UsagePlan", + "DependsOn": [ + "MyApiOne", + "MyApiTwo", + "MyApiThree" + ], + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "ApiStages": [ + { + "ApiId": { + "Ref": "MyApiOne" + }, + "Stage": { + "Ref": "MyApiOneProdStage" + } + }, + { + "ApiId": { + "Ref": "MyApiTwo" + }, + "Stage": { + "Ref": "MyApiTwoProdStage" + } + }, + { + "ApiId": { + "Ref": "MyApiThree" + }, + "Stage": { + "Ref": "MyApiThreeProdStage" + } + } + ] + } + }, + "ServerlessApiKey": { + "Type": "AWS::ApiGateway::ApiKey", + "DependsOn": [ + "ServerlessUsagePlan" + ], + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "Enabled": true, + "StageKeys": [ + { + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": { + "Ref": "MyApiOneProdStage" + } + }, + { + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": { + "Ref": "MyApiTwoProdStage" + } + }, + { + "RestApiId": { + "Ref": "MyApiThree" + }, + "StageName": { + "Ref": "MyApiThreeProdStage" + } + } + ] + } + }, + "ServerlessUsagePlanKey": { + "Type": "AWS::ApiGateway::UsagePlanKey", + "DependsOn": [ + "ServerlessApiKey" + ], + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "KeyId": { + "Ref": "ServerlessApiKey" + }, + "KeyType": "API_KEY", + "UsagePlanId": { + "Ref": "ServerlessUsagePlan" + } + } + }, + "MyApiTwo": { + "Type": "AWS::ApiGateway::RestApi", + "Condition": "C2", + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "Body": { + "swagger": "2.0", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/path/two": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "uri": { + "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionTwo.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "api_key": [] + } + ] + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "x-api-key", + "in": "header" + } + } + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + } + } + }, + "MyApiTwoDeployment15a3902b45": { + "Type": "AWS::ApiGateway::Deployment", + "Condition": "C2", + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "Description": "RestApi deployment id: 15a3902b458d0a1a4f8803252344e76b43375bbb", + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": "Stage" + } + }, + "MyApiTwoProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Condition": "C2", + "UpdateReplacePolicy": "Snapshot", + "Properties": { + "DeploymentId": { + "Ref": "MyApiTwoDeployment15a3902b45" + }, + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": "Prod" + } + }, + "MyApiThree": { + "Type": "AWS::ApiGateway::RestApi", + "Properties": { + "Body": { + "swagger": "2.0", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/path/three": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "uri": { + "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionThree.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "api_key": [] + } + ] + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "x-api-key", + "in": "header" + } + } + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + } + } + }, + "MyApiThreeDeploymentac8c00f0e1": { + "Type": "AWS::ApiGateway::Deployment", + "Properties": { + "Description": "RestApi deployment id: ac8c00f0e1e81ee603d7b7bd216d64a1cd4f93c4", + "RestApiId": { + "Ref": "MyApiThree" + }, + "StageName": "Stage" + } + }, + "MyApiThreeProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Properties": { + "DeploymentId": { + "Ref": "MyApiThreeDeploymentac8c00f0e1" + }, + "RestApiId": { + "Ref": "MyApiThree" + }, + "StageName": "Prod" + } + } + } +} \ No newline at end of file diff --git a/tests/translator/output/aws-us-gov/api_with_usageplans_shared_attributes_two.json b/tests/translator/output/aws-us-gov/api_with_usageplans_shared_attributes_two.json new file mode 100644 index 0000000000..1901782288 --- /dev/null +++ b/tests/translator/output/aws-us-gov/api_with_usageplans_shared_attributes_two.json @@ -0,0 +1,401 @@ +{ + "Conditions": { + "C1": { + "Fn::Equals": [ + "test", + "test" + ] + }, + "C2": { + "Fn::Equals": [ + "test", + "test" + ] + }, + "SharedUsagePlanCondition": { + "Fn::Or": [ + { + "Condition": "C1" + }, + { + "Condition": "C2" + } + ] + } + }, + "Resources": { + "MyFunctionOne": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (event) => {\n return {\n statusCode: 200,\n body: JSON.stringify(event),\n headers: {}\n }\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyFunctionOneRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionOneRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionOneApiKeyPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionOne" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/path/one", + { + "__ApiId__": { + "Ref": "MyApiOne" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyFunctionTwo": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (event) => {\n return {\n statusCode: 200,\n body: JSON.stringify(event),\n headers: {}\n }\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "MyFunctionTwoRole", + "Arn" + ] + }, + "Runtime": "nodejs12.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionTwoRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + } + }, + "MyFunctionTwoApiKeyPermissionProd": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "MyFunctionTwo" + }, + "Principal": "apigateway.amazonaws.com", + "SourceArn": { + "Fn::Sub": [ + "arn:aws-us-gov:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/${__Stage__}/GET/path/two", + { + "__ApiId__": { + "Ref": "MyApiTwo" + }, + "__Stage__": "*" + } + ] + } + } + }, + "MyApiOne": { + "Type": "AWS::ApiGateway::RestApi", + "DeletionPolicy": "Delete", + "Condition": "C1", + "Properties": { + "Body": { + "swagger": "2.0", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/path/one": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "uri": { + "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionOne.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "api_key": [] + } + ] + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "x-api-key", + "in": "header" + } + } + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + } + } + }, + "MyApiOneDeploymentb12c8b5b0a": { + "Type": "AWS::ApiGateway::Deployment", + "Condition": "C1", + "DeletionPolicy": "Delete", + "Properties": { + "Description": "RestApi deployment id: b12c8b5b0aed50622a06dd52b372f8213a63b39b", + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": "Stage" + } + }, + "MyApiOneProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Condition": "C1", + "DeletionPolicy": "Delete", + "Properties": { + "DeploymentId": { + "Ref": "MyApiOneDeploymentb12c8b5b0a" + }, + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": "Prod" + } + }, + "ServerlessUsagePlan": { + "Type": "AWS::ApiGateway::UsagePlan", + "DependsOn": [ + "MyApiOne", + "MyApiTwo" + ], + "Condition": "SharedUsagePlanCondition", + "DeletionPolicy": "Retain", + "Properties": { + "ApiStages": [ + { + "ApiId": { + "Ref": "MyApiOne" + }, + "Stage": { + "Ref": "MyApiOneProdStage" + } + }, + { + "ApiId": { + "Ref": "MyApiTwo" + }, + "Stage": { + "Ref": "MyApiTwoProdStage" + } + } + ] + } + }, + "ServerlessApiKey": { + "Type": "AWS::ApiGateway::ApiKey", + "DependsOn": [ + "ServerlessUsagePlan" + ], + "Condition": "SharedUsagePlanCondition", + "DeletionPolicy": "Retain", + "Properties": { + "Enabled": true, + "StageKeys": [ + { + "RestApiId": { + "Ref": "MyApiOne" + }, + "StageName": { + "Ref": "MyApiOneProdStage" + } + }, + { + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": { + "Ref": "MyApiTwoProdStage" + } + } + ] + } + }, + "ServerlessUsagePlanKey": { + "Type": "AWS::ApiGateway::UsagePlanKey", + "DependsOn": [ + "ServerlessApiKey" + ], + "Condition": "SharedUsagePlanCondition", + "DeletionPolicy": "Retain", + "Properties": { + "KeyId": { + "Ref": "ServerlessApiKey" + }, + "KeyType": "API_KEY", + "UsagePlanId": { + "Ref": "ServerlessUsagePlan" + } + } + }, + "MyApiTwo": { + "Type": "AWS::ApiGateway::RestApi", + "DeletionPolicy": "Retain", + "Condition": "C2", + "Properties": { + "Body": { + "swagger": "2.0", + "info": { + "version": "1.0", + "title": { + "Ref": "AWS::StackName" + } + }, + "paths": { + "/path/two": { + "get": { + "x-amazon-apigateway-integration": { + "type": "aws_proxy", + "httpMethod": "POST", + "uri": { + "Fn::Sub": "arn:aws-us-gov:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunctionTwo.Arn}/invocations" + } + }, + "responses": {}, + "security": [ + { + "api_key": [] + } + ] + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "x-api-key", + "in": "header" + } + } + }, + "Parameters": { + "endpointConfigurationTypes": "REGIONAL" + }, + "EndpointConfiguration": { + "Types": [ + "REGIONAL" + ] + } + } + }, + "MyApiTwoDeployment15a3902b45": { + "Type": "AWS::ApiGateway::Deployment", + "Condition": "C2", + "DeletionPolicy": "Retain", + "Properties": { + "Description": "RestApi deployment id: 15a3902b458d0a1a4f8803252344e76b43375bbb", + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": "Stage" + } + }, + "MyApiTwoProdStage": { + "Type": "AWS::ApiGateway::Stage", + "Condition": "C2", + "DeletionPolicy": "Retain", + "Properties": { + "DeploymentId": { + "Ref": "MyApiTwoDeployment15a3902b45" + }, + "RestApiId": { + "Ref": "MyApiTwo" + }, + "StageName": "Prod" + } + } + } +} \ No newline at end of file diff --git a/tests/translator/test_translator.py b/tests/translator/test_translator.py index 5a100fe38a..3d93ab5712 100644 --- a/tests/translator/test_translator.py +++ b/tests/translator/test_translator.py @@ -400,6 +400,8 @@ class TestTranslatorEndToEnd(AbstractTestTranslator): "function_with_event_dest_basic", "function_with_event_dest_conditional", "api_with_usageplans", + "api_with_usageplans_shared_attributes_two", + "api_with_usageplans_shared_attributes_three", "api_with_usageplans_intrinsics", "state_machine_with_inline_definition", "state_machine_with_tags", From 15d3b710d7f25285617ef227c10b06fa460a1ac4 Mon Sep 17 00:00:00 2001 From: Qingchuan Ma Date: Wed, 19 May 2021 20:26:16 -0700 Subject: [PATCH 5/7] Black reformatting --- .../unit/model/api/TestSharedApiUsagePlan.py | 89 ++++++------------- 1 file changed, 25 insertions(+), 64 deletions(-) diff --git a/tests/unit/model/api/TestSharedApiUsagePlan.py b/tests/unit/model/api/TestSharedApiUsagePlan.py index 5a7cd59986..7c9e84699b 100644 --- a/tests/unit/model/api/TestSharedApiUsagePlan.py +++ b/tests/unit/model/api/TestSharedApiUsagePlan.py @@ -7,7 +7,6 @@ class TestSharedApiUsagePlan(TestCase): - def setUp(self): self.shared_usage_plan = SharedApiUsagePlan() @@ -19,7 +18,7 @@ def test_values_should_be_propagated(self): "DeletionPolicy": "Delete", "UpdateReplacePolicy": "Delete", }, - conditions + conditions, ) self.assertEqual( @@ -28,25 +27,26 @@ def test_values_should_be_propagated(self): "DeletionPolicy": "Delete", "UpdateReplacePolicy": "Delete", }, - actual_attributes + actual_attributes, ) - self.assertEqual(conditions, {'SharedUsagePlanCondition': 'C1'}) - - @parameterized.expand([ - ([None], ), - ([None, "C1"], ), - (["C1", None], ), - (["C1", "C2"], ), - (["C1", "C2", "C3"], ), - ]) + self.assertEqual(conditions, {"SharedUsagePlanCondition": "C1"}) + + @parameterized.expand( + [ + ([None],), + ([None, "C1"],), + (["C1", None],), + (["C1", "C2"],), + (["C1", "C2", "C3"],), + ] + ) def test_multiple_apis_with_conditions(self, api_conditions): template_conditions = dict() result = {} for api_condition in api_conditions: result = self.shared_usage_plan.get_combined_resource_attributes( - {"Condition": api_condition}, - template_conditions + {"Condition": api_condition}, template_conditions ) print(f"Calling with {api_condition} result {result}") @@ -59,100 +59,61 @@ def test_multiple_apis_with_conditions(self, api_conditions): self.assertEqual({"Condition": "SharedUsagePlanCondition"}, result) combined_conditions = [ condition.get("Condition") - for condition in - template_conditions.get("SharedUsagePlanCondition", {}).get("Fn::Or") + for condition in template_conditions.get("SharedUsagePlanCondition", {}).get("Fn::Or") ] for combined_condition in combined_conditions: self.assertTrue(combined_condition in api_conditions) - def test_should_raise_invalid_template_when_no_conditions_section(self): with self.assertRaises(InvalidTemplateException): - self.shared_usage_plan.get_combined_resource_attributes( - {"Condition": "C1"}, - None - ) + self.shared_usage_plan.get_combined_resource_attributes({"Condition": "C1"}, None) def test_deletion_policy_priority(self): # first api sets it to delete - actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( - { - "DeletionPolicy": "Delete" - }, - {} - ) + actual_attributes = self.shared_usage_plan.get_combined_resource_attributes({"DeletionPolicy": "Delete"}, {}) self.assertEqual(actual_attributes["DeletionPolicy"], "Delete") # then second api sets it to Retain - actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( - { - "DeletionPolicy": "Retain" - }, - {} - ) + actual_attributes = self.shared_usage_plan.get_combined_resource_attributes({"DeletionPolicy": "Retain"}, {}) self.assertEqual(actual_attributes["DeletionPolicy"], "Retain") # if third api sets it to delete, it should keep retain value - actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( - { - "DeletionPolicy": "Delete" - }, - {} - ) + actual_attributes = self.shared_usage_plan.get_combined_resource_attributes({"DeletionPolicy": "Delete"}, {}) self.assertEqual(actual_attributes["DeletionPolicy"], "Retain") def test_update_replace_policy_priority(self): # first api sets it to delete actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( - { - "UpdateReplacePolicy": "Delete" - }, - {} + {"UpdateReplacePolicy": "Delete"}, {} ) self.assertEqual(actual_attributes["UpdateReplacePolicy"], "Delete") # then second api sets it to Retain actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( - { - "UpdateReplacePolicy": "Snapshot" - }, - {} + {"UpdateReplacePolicy": "Snapshot"}, {} ) self.assertEqual(actual_attributes["UpdateReplacePolicy"], "Snapshot") # if third api sets it to delete, it should keep retain value actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( - { - "UpdateReplacePolicy": "Delete" - }, - {} + {"UpdateReplacePolicy": "Delete"}, {} ) self.assertEqual(actual_attributes["UpdateReplacePolicy"], "Snapshot") # if third api sets it to delete, it should keep retain value actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( - { - "UpdateReplacePolicy": "Retain" - }, - {} + {"UpdateReplacePolicy": "Retain"}, {} ) self.assertEqual(actual_attributes["UpdateReplacePolicy"], "Retain") # if third api sets it to delete, it should keep retain value actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( - { - "UpdateReplacePolicy": "Snapshot" - }, - {} + {"UpdateReplacePolicy": "Snapshot"}, {} ) self.assertEqual(actual_attributes["UpdateReplacePolicy"], "Retain") # if third api sets it to delete, it should keep retain value actual_attributes = self.shared_usage_plan.get_combined_resource_attributes( - { - "UpdateReplacePolicy": "Delete" - }, - {} + {"UpdateReplacePolicy": "Delete"}, {} ) self.assertEqual(actual_attributes["UpdateReplacePolicy"], "Retain") - From ce604725b8dbb6a75c26ef43f64df22aae5ac2e2 Mon Sep 17 00:00:00 2001 From: Qingchuan Ma Date: Wed, 19 May 2021 20:35:06 -0700 Subject: [PATCH 6/7] Removing unused import --- samtranslator/model/api/api_generator.py | 1 - 1 file changed, 1 deletion(-) diff --git a/samtranslator/model/api/api_generator.py b/samtranslator/model/api/api_generator.py index 60e0f54c83..3cd9ec0825 100644 --- a/samtranslator/model/api/api_generator.py +++ b/samtranslator/model/api/api_generator.py @@ -1,6 +1,5 @@ import logging from collections import namedtuple -from copy import deepcopy from six import string_types from samtranslator.model.intrinsics import ref, fnGetAtt, make_or_condition From 51ef81f604dfbd391db60a21a83a8e9b9686286a Mon Sep 17 00:00:00 2001 From: Mehmet Nuri Deveci <5735811+mndeveci@users.noreply.github.com> Date: Thu, 20 May 2021 00:48:57 -0700 Subject: [PATCH 7/7] fix python2 hashes --- ...ith_usageplans_shared_attributes_three.json | 18 +++++++++--------- ..._with_usageplans_shared_attributes_two.json | 12 ++++++------ ...ith_usageplans_shared_attributes_three.json | 18 +++++++++--------- ..._with_usageplans_shared_attributes_two.json | 12 ++++++------ ...ith_usageplans_shared_attributes_three.json | 18 +++++++++--------- ..._with_usageplans_shared_attributes_two.json | 12 ++++++------ 6 files changed, 45 insertions(+), 45 deletions(-) diff --git a/tests/translator/output/api_with_usageplans_shared_attributes_three.json b/tests/translator/output/api_with_usageplans_shared_attributes_three.json index 764b7ed357..7d6b336e1c 100644 --- a/tests/translator/output/api_with_usageplans_shared_attributes_three.json +++ b/tests/translator/output/api_with_usageplans_shared_attributes_three.json @@ -275,12 +275,12 @@ } } }, - "MyApiOneDeployment593a0a0946": { + "MyApiOneDeployment46fb22a429": { "Type": "AWS::ApiGateway::Deployment", "Condition": "C1", "UpdateReplacePolicy": "Delete", "Properties": { - "Description": "RestApi deployment id: 593a0a094683480e951e7daed89e6f2ea946b7c4", + "Description": "RestApi deployment id: 46fb22a42926db6f64e09966936d074ec6bb9392", "RestApiId": { "Ref": "MyApiOne" }, @@ -293,7 +293,7 @@ "UpdateReplacePolicy": "Delete", "Properties": { "DeploymentId": { - "Ref": "MyApiOneDeployment593a0a0946" + "Ref": "MyApiOneDeployment46fb22a429" }, "RestApiId": { "Ref": "MyApiOne" @@ -432,12 +432,12 @@ } } }, - "MyApiTwoDeployment0c6c2a5588": { + "MyApiTwoDeploymente9d97923b9": { "Type": "AWS::ApiGateway::Deployment", "Condition": "C2", "UpdateReplacePolicy": "Snapshot", "Properties": { - "Description": "RestApi deployment id: 0c6c2a5588069f784aaa1c010c10055bdb5fd7f7", + "Description": "RestApi deployment id: e9d97923b94d0801cd85a8970b3c3f84aa274003", "RestApiId": { "Ref": "MyApiTwo" }, @@ -450,7 +450,7 @@ "UpdateReplacePolicy": "Snapshot", "Properties": { "DeploymentId": { - "Ref": "MyApiTwoDeployment0c6c2a5588" + "Ref": "MyApiTwoDeploymente9d97923b9" }, "RestApiId": { "Ref": "MyApiTwo" @@ -498,10 +498,10 @@ } } }, - "MyApiThreeDeployment8af42ea6fa": { + "MyApiThreeDeployment1d9cff47dc": { "Type": "AWS::ApiGateway::Deployment", "Properties": { - "Description": "RestApi deployment id: 8af42ea6fa6c0dc81aa34a29baae4eb4670a7b8a", + "Description": "RestApi deployment id: 1d9cff47dc9b822750c668c73b4534022483de6d", "RestApiId": { "Ref": "MyApiThree" }, @@ -512,7 +512,7 @@ "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "MyApiThreeDeployment8af42ea6fa" + "Ref": "MyApiThreeDeployment1d9cff47dc" }, "RestApiId": { "Ref": "MyApiThree" diff --git a/tests/translator/output/api_with_usageplans_shared_attributes_two.json b/tests/translator/output/api_with_usageplans_shared_attributes_two.json index 4705bd9238..3412bb0415 100644 --- a/tests/translator/output/api_with_usageplans_shared_attributes_two.json +++ b/tests/translator/output/api_with_usageplans_shared_attributes_two.json @@ -212,12 +212,12 @@ } } }, - "MyApiOneDeployment593a0a0946": { + "MyApiOneDeployment46fb22a429": { "Type": "AWS::ApiGateway::Deployment", "Condition": "C1", "DeletionPolicy": "Delete", "Properties": { - "Description": "RestApi deployment id: 593a0a094683480e951e7daed89e6f2ea946b7c4", + "Description": "RestApi deployment id: 46fb22a42926db6f64e09966936d074ec6bb9392", "RestApiId": { "Ref": "MyApiOne" }, @@ -230,7 +230,7 @@ "DeletionPolicy": "Delete", "Properties": { "DeploymentId": { - "Ref": "MyApiOneDeployment593a0a0946" + "Ref": "MyApiOneDeployment46fb22a429" }, "RestApiId": { "Ref": "MyApiOne" @@ -355,12 +355,12 @@ } } }, - "MyApiTwoDeployment0c6c2a5588": { + "MyApiTwoDeploymente9d97923b9": { "Type": "AWS::ApiGateway::Deployment", "Condition": "C2", "DeletionPolicy": "Retain", "Properties": { - "Description": "RestApi deployment id: 0c6c2a5588069f784aaa1c010c10055bdb5fd7f7", + "Description": "RestApi deployment id: e9d97923b94d0801cd85a8970b3c3f84aa274003", "RestApiId": { "Ref": "MyApiTwo" }, @@ -373,7 +373,7 @@ "DeletionPolicy": "Retain", "Properties": { "DeploymentId": { - "Ref": "MyApiTwoDeployment0c6c2a5588" + "Ref": "MyApiTwoDeploymente9d97923b9" }, "RestApiId": { "Ref": "MyApiTwo" diff --git a/tests/translator/output/aws-cn/api_with_usageplans_shared_attributes_three.json b/tests/translator/output/aws-cn/api_with_usageplans_shared_attributes_three.json index 45fab46e5e..3f37e5bf0d 100644 --- a/tests/translator/output/aws-cn/api_with_usageplans_shared_attributes_three.json +++ b/tests/translator/output/aws-cn/api_with_usageplans_shared_attributes_three.json @@ -283,12 +283,12 @@ } } }, - "MyApiOneDeploymented8916593e": { + "MyApiOneDeployment7997029260": { "Type": "AWS::ApiGateway::Deployment", "Condition": "C1", "UpdateReplacePolicy": "Delete", "Properties": { - "Description": "RestApi deployment id: ed8916593eee3d5996ff3d7912710b8fac532e60", + "Description": "RestApi deployment id: 79970292604071da8105ffd8503f82af32b30550", "RestApiId": { "Ref": "MyApiOne" }, @@ -301,7 +301,7 @@ "UpdateReplacePolicy": "Delete", "Properties": { "DeploymentId": { - "Ref": "MyApiOneDeploymented8916593e" + "Ref": "MyApiOneDeployment7997029260" }, "RestApiId": { "Ref": "MyApiOne" @@ -448,12 +448,12 @@ } } }, - "MyApiTwoDeployment17dd9ed926": { + "MyApiTwoDeployment03730b64c4": { "Type": "AWS::ApiGateway::Deployment", "Condition": "C2", "UpdateReplacePolicy": "Snapshot", "Properties": { - "Description": "RestApi deployment id: 17dd9ed92642dde88467fc566c4a64befb1d3a2d", + "Description": "RestApi deployment id: 03730b64c486cc490deefb3b8225244b0fe85d34", "RestApiId": { "Ref": "MyApiTwo" }, @@ -466,7 +466,7 @@ "UpdateReplacePolicy": "Snapshot", "Properties": { "DeploymentId": { - "Ref": "MyApiTwoDeployment17dd9ed926" + "Ref": "MyApiTwoDeployment03730b64c4" }, "RestApiId": { "Ref": "MyApiTwo" @@ -522,10 +522,10 @@ } } }, - "MyApiThreeDeployment0ac39d26ff": { + "MyApiThreeDeploymentfa9f73f027": { "Type": "AWS::ApiGateway::Deployment", "Properties": { - "Description": "RestApi deployment id: 0ac39d26ffc79dae8849daf66e76214028279104", + "Description": "RestApi deployment id: fa9f73f0272017527c24cc93cc4440dd4476b9f4", "RestApiId": { "Ref": "MyApiThree" }, @@ -536,7 +536,7 @@ "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "MyApiThreeDeployment0ac39d26ff" + "Ref": "MyApiThreeDeploymentfa9f73f027" }, "RestApiId": { "Ref": "MyApiThree" diff --git a/tests/translator/output/aws-cn/api_with_usageplans_shared_attributes_two.json b/tests/translator/output/aws-cn/api_with_usageplans_shared_attributes_two.json index 515af3e7f9..bf555befa1 100644 --- a/tests/translator/output/aws-cn/api_with_usageplans_shared_attributes_two.json +++ b/tests/translator/output/aws-cn/api_with_usageplans_shared_attributes_two.json @@ -220,12 +220,12 @@ } } }, - "MyApiOneDeploymented8916593e": { + "MyApiOneDeployment7997029260": { "Type": "AWS::ApiGateway::Deployment", "Condition": "C1", "DeletionPolicy": "Delete", "Properties": { - "Description": "RestApi deployment id: ed8916593eee3d5996ff3d7912710b8fac532e60", + "Description": "RestApi deployment id: 79970292604071da8105ffd8503f82af32b30550", "RestApiId": { "Ref": "MyApiOne" }, @@ -238,7 +238,7 @@ "DeletionPolicy": "Delete", "Properties": { "DeploymentId": { - "Ref": "MyApiOneDeploymented8916593e" + "Ref": "MyApiOneDeployment7997029260" }, "RestApiId": { "Ref": "MyApiOne" @@ -371,12 +371,12 @@ } } }, - "MyApiTwoDeployment17dd9ed926": { + "MyApiTwoDeployment03730b64c4": { "Type": "AWS::ApiGateway::Deployment", "Condition": "C2", "DeletionPolicy": "Retain", "Properties": { - "Description": "RestApi deployment id: 17dd9ed92642dde88467fc566c4a64befb1d3a2d", + "Description": "RestApi deployment id: 03730b64c486cc490deefb3b8225244b0fe85d34", "RestApiId": { "Ref": "MyApiTwo" }, @@ -389,7 +389,7 @@ "DeletionPolicy": "Retain", "Properties": { "DeploymentId": { - "Ref": "MyApiTwoDeployment17dd9ed926" + "Ref": "MyApiTwoDeployment03730b64c4" }, "RestApiId": { "Ref": "MyApiTwo" diff --git a/tests/translator/output/aws-us-gov/api_with_usageplans_shared_attributes_three.json b/tests/translator/output/aws-us-gov/api_with_usageplans_shared_attributes_three.json index 7fd9dbe508..26b69c39b7 100644 --- a/tests/translator/output/aws-us-gov/api_with_usageplans_shared_attributes_three.json +++ b/tests/translator/output/aws-us-gov/api_with_usageplans_shared_attributes_three.json @@ -283,12 +283,12 @@ } } }, - "MyApiOneDeploymentb12c8b5b0a": { + "MyApiOneDeploymentdccbc5fda1": { "Type": "AWS::ApiGateway::Deployment", "Condition": "C1", "UpdateReplacePolicy": "Delete", "Properties": { - "Description": "RestApi deployment id: b12c8b5b0aed50622a06dd52b372f8213a63b39b", + "Description": "RestApi deployment id: dccbc5fda163e1abe712073ffacdcc47776a5a09", "RestApiId": { "Ref": "MyApiOne" }, @@ -301,7 +301,7 @@ "UpdateReplacePolicy": "Delete", "Properties": { "DeploymentId": { - "Ref": "MyApiOneDeploymentb12c8b5b0a" + "Ref": "MyApiOneDeploymentdccbc5fda1" }, "RestApiId": { "Ref": "MyApiOne" @@ -448,12 +448,12 @@ } } }, - "MyApiTwoDeployment15a3902b45": { + "MyApiTwoDeployment0e45b81469": { "Type": "AWS::ApiGateway::Deployment", "Condition": "C2", "UpdateReplacePolicy": "Snapshot", "Properties": { - "Description": "RestApi deployment id: 15a3902b458d0a1a4f8803252344e76b43375bbb", + "Description": "RestApi deployment id: 0e45b814691166a59217a088512ee30710a12369", "RestApiId": { "Ref": "MyApiTwo" }, @@ -466,7 +466,7 @@ "UpdateReplacePolicy": "Snapshot", "Properties": { "DeploymentId": { - "Ref": "MyApiTwoDeployment15a3902b45" + "Ref": "MyApiTwoDeployment0e45b81469" }, "RestApiId": { "Ref": "MyApiTwo" @@ -522,10 +522,10 @@ } } }, - "MyApiThreeDeploymentac8c00f0e1": { + "MyApiThreeDeployment5206882d23": { "Type": "AWS::ApiGateway::Deployment", "Properties": { - "Description": "RestApi deployment id: ac8c00f0e1e81ee603d7b7bd216d64a1cd4f93c4", + "Description": "RestApi deployment id: 5206882d23d2cf7913f0fffea98644f959b433f2", "RestApiId": { "Ref": "MyApiThree" }, @@ -536,7 +536,7 @@ "Type": "AWS::ApiGateway::Stage", "Properties": { "DeploymentId": { - "Ref": "MyApiThreeDeploymentac8c00f0e1" + "Ref": "MyApiThreeDeployment5206882d23" }, "RestApiId": { "Ref": "MyApiThree" diff --git a/tests/translator/output/aws-us-gov/api_with_usageplans_shared_attributes_two.json b/tests/translator/output/aws-us-gov/api_with_usageplans_shared_attributes_two.json index 1901782288..346ef6a12d 100644 --- a/tests/translator/output/aws-us-gov/api_with_usageplans_shared_attributes_two.json +++ b/tests/translator/output/aws-us-gov/api_with_usageplans_shared_attributes_two.json @@ -220,12 +220,12 @@ } } }, - "MyApiOneDeploymentb12c8b5b0a": { + "MyApiOneDeploymentdccbc5fda1": { "Type": "AWS::ApiGateway::Deployment", "Condition": "C1", "DeletionPolicy": "Delete", "Properties": { - "Description": "RestApi deployment id: b12c8b5b0aed50622a06dd52b372f8213a63b39b", + "Description": "RestApi deployment id: dccbc5fda163e1abe712073ffacdcc47776a5a09", "RestApiId": { "Ref": "MyApiOne" }, @@ -238,7 +238,7 @@ "DeletionPolicy": "Delete", "Properties": { "DeploymentId": { - "Ref": "MyApiOneDeploymentb12c8b5b0a" + "Ref": "MyApiOneDeploymentdccbc5fda1" }, "RestApiId": { "Ref": "MyApiOne" @@ -371,12 +371,12 @@ } } }, - "MyApiTwoDeployment15a3902b45": { + "MyApiTwoDeployment0e45b81469": { "Type": "AWS::ApiGateway::Deployment", "Condition": "C2", "DeletionPolicy": "Retain", "Properties": { - "Description": "RestApi deployment id: 15a3902b458d0a1a4f8803252344e76b43375bbb", + "Description": "RestApi deployment id: 0e45b814691166a59217a088512ee30710a12369", "RestApiId": { "Ref": "MyApiTwo" }, @@ -389,7 +389,7 @@ "DeletionPolicy": "Retain", "Properties": { "DeploymentId": { - "Ref": "MyApiTwoDeployment15a3902b45" + "Ref": "MyApiTwoDeployment0e45b81469" }, "RestApiId": { "Ref": "MyApiTwo"