From cdef07f0827d9b88c7fffa5968767a56f01504c7 Mon Sep 17 00:00:00 2001 From: Gavin Zhang Date: Thu, 22 Jun 2023 18:12:04 +0000 Subject: [PATCH 1/3] feat: Add AutoPublishAlias to StateMachine for managed traffic shifting --- .cfnlintrc.yaml | 6 ++ .../aws_serverless_statemachine.py | 2 + samtranslator/model/__init__.py | 9 +++ samtranslator/model/sam_resources.py | 7 ++ samtranslator/model/stepfunctions/__init__.py | 10 ++- .../model/stepfunctions/generators.py | 81 ++++++++++++++++++- .../model/stepfunctions/resources.py | 16 ++++ samtranslator/schema/schema.json | 6 ++ schema_source/sam.schema.json | 6 ++ .../test_state_machine_generator.py | 44 +++++++++- ...preference_missing_auto_publish_alias.yaml | 15 ++++ ...state_machine_with_auto_publish_alias.yaml | 14 ++++ .../state_machine_with_deletion_policy.yaml | 17 ++++ ...ith_deployment_preference_all_at_once.yaml | 16 ++++ ...ine_with_deployment_preference_canary.yaml | 21 +++++ ...ine_with_deployment_preference_linear.yaml | 21 +++++ ...te_machine_with_update_replace_policy.yaml | 16 ++++ ...state_machine_with_auto_publish_alias.json | 64 +++++++++++++++ .../state_machine_with_deletion_policy.json | 66 +++++++++++++++ ...ith_deployment_preference_all_at_once.json | 64 +++++++++++++++ ...ine_with_deployment_preference_canary.json | 70 ++++++++++++++++ ...ine_with_deployment_preference_linear.json | 70 ++++++++++++++++ ...te_machine_with_update_replace_policy.json | 64 +++++++++++++++ ...state_machine_with_auto_publish_alias.json | 64 +++++++++++++++ .../state_machine_with_deletion_policy.json | 66 +++++++++++++++ ...ith_deployment_preference_all_at_once.json | 64 +++++++++++++++ ...ine_with_deployment_preference_canary.json | 70 ++++++++++++++++ ...ine_with_deployment_preference_linear.json | 70 ++++++++++++++++ ...te_machine_with_update_replace_policy.json | 64 +++++++++++++++ ...preference_missing_auto_publish_alias.json | 9 +++ ...state_machine_with_auto_publish_alias.json | 64 +++++++++++++++ .../state_machine_with_deletion_policy.json | 66 +++++++++++++++ ...ith_deployment_preference_all_at_once.json | 64 +++++++++++++++ ...ine_with_deployment_preference_canary.json | 70 ++++++++++++++++ ...ine_with_deployment_preference_linear.json | 70 ++++++++++++++++ ...te_machine_with_update_replace_policy.json | 64 +++++++++++++++ 36 files changed, 1506 insertions(+), 4 deletions(-) create mode 100644 tests/translator/input/error_state_machine_with_deployment_preference_missing_auto_publish_alias.yaml create mode 100644 tests/translator/input/state_machine_with_auto_publish_alias.yaml create mode 100644 tests/translator/input/state_machine_with_deletion_policy.yaml create mode 100644 tests/translator/input/state_machine_with_deployment_preference_all_at_once.yaml create mode 100644 tests/translator/input/state_machine_with_deployment_preference_canary.yaml create mode 100644 tests/translator/input/state_machine_with_deployment_preference_linear.yaml create mode 100644 tests/translator/input/state_machine_with_update_replace_policy.yaml create mode 100644 tests/translator/output/aws-cn/state_machine_with_auto_publish_alias.json create mode 100644 tests/translator/output/aws-cn/state_machine_with_deletion_policy.json create mode 100644 tests/translator/output/aws-cn/state_machine_with_deployment_preference_all_at_once.json create mode 100644 tests/translator/output/aws-cn/state_machine_with_deployment_preference_canary.json create mode 100644 tests/translator/output/aws-cn/state_machine_with_deployment_preference_linear.json create mode 100644 tests/translator/output/aws-cn/state_machine_with_update_replace_policy.json create mode 100644 tests/translator/output/aws-us-gov/state_machine_with_auto_publish_alias.json create mode 100644 tests/translator/output/aws-us-gov/state_machine_with_deletion_policy.json create mode 100644 tests/translator/output/aws-us-gov/state_machine_with_deployment_preference_all_at_once.json create mode 100644 tests/translator/output/aws-us-gov/state_machine_with_deployment_preference_canary.json create mode 100644 tests/translator/output/aws-us-gov/state_machine_with_deployment_preference_linear.json create mode 100644 tests/translator/output/aws-us-gov/state_machine_with_update_replace_policy.json create mode 100644 tests/translator/output/error_state_machine_with_deployment_preference_missing_auto_publish_alias.json create mode 100644 tests/translator/output/state_machine_with_auto_publish_alias.json create mode 100644 tests/translator/output/state_machine_with_deletion_policy.json create mode 100644 tests/translator/output/state_machine_with_deployment_preference_all_at_once.json create mode 100644 tests/translator/output/state_machine_with_deployment_preference_canary.json create mode 100644 tests/translator/output/state_machine_with_deployment_preference_linear.json create mode 100644 tests/translator/output/state_machine_with_update_replace_policy.json diff --git a/.cfnlintrc.yaml b/.cfnlintrc.yaml index 594accf77..5d4cbdab5 100644 --- a/.cfnlintrc.yaml +++ b/.cfnlintrc.yaml @@ -118,6 +118,12 @@ ignore_templates: - tests/translator/output/**/state_machine_with_event_schedule_state.json - tests/translator/output/**/state_machine_with_schedule.json - tests/translator/output/**/state_machine_with_schedule_dlq_retry_policy.json + - tests/translator/output/**/state_machine_with_auto_publish_alias.json + - tests/translator/output/**/state_machine_with_deployment_preference_all_at_once.json + - tests/translator/output/**/state_machine_with_deployment_preference_canary.json + - tests/translator/output/**/state_machine_with_deployment_preference_linear.json + - tests/translator/output/**/state_machine_with_deletion_policy.json + - tests/translator/output/**/state_machine_with_update_replace_policy.json - tests/translator/output/**/globals_for_function.json # RuntimeManagementConfig - tests/translator/output/**/function_with_runtime_config.json # RuntimeManagementConfig - tests/translator/output/**/managed_policies_minimal.json # Intentionally has non-existent managed policy name diff --git a/samtranslator/internal/schema_source/aws_serverless_statemachine.py b/samtranslator/internal/schema_source/aws_serverless_statemachine.py index 2e94f65c6..5d7acc6c2 100644 --- a/samtranslator/internal/schema_source/aws_serverless_statemachine.py +++ b/samtranslator/internal/schema_source/aws_serverless_statemachine.py @@ -171,6 +171,8 @@ class Properties(BaseModel): Tags: Optional[DictStrAny] = properties("Tags") Tracing: Optional[PassThroughProp] = properties("Tracing") Type: Optional[PassThroughProp] = properties("Type") + AutoPublishAlias: Optional[PassThroughProp] + DeploymentPreference: Optional[PassThroughProp] class Resource(ResourceAttributes): diff --git a/samtranslator/model/__init__.py b/samtranslator/model/__init__.py index 52bde69a7..fdd383c59 100644 --- a/samtranslator/model/__init__.py +++ b/samtranslator/model/__init__.py @@ -74,6 +74,14 @@ def __init__(self, required: bool) -> None: super().__init__(required, any_type(), False) +class MutatedPassThroughProperty(PassThroughProperty): + """ + Mutated pass-through property. + + SAM Translator may read and add/remove/modify the value before passing it to underlaying CFN resources. + """ + + class GeneratedProperty(PropertyType): """ Property of a generated CloudFormation resource. @@ -631,6 +639,7 @@ def get_resource_by_logical_id(self, _input: str) -> Dict[str, Any]: "PropertyType", "Property", "PassThroughProperty", + "MutatedPassThroughProperty", "Resource", "ResourceMacro", "SamResourceMacro", diff --git a/samtranslator/model/sam_resources.py b/samtranslator/model/sam_resources.py index d0de132bd..6101a4669 100644 --- a/samtranslator/model/sam_resources.py +++ b/samtranslator/model/sam_resources.py @@ -14,6 +14,7 @@ from samtranslator.intrinsics.resolver import IntrinsicsResolver from samtranslator.metrics.method_decorator import cw_timer from samtranslator.model import ( + MutatedPassThroughProperty, PassThroughProperty, Property, PropertyType, @@ -1709,6 +1710,8 @@ class SamStateMachine(SamResourceMacro): "Policies": PropertyType(False, one_of(IS_STR, list_of(one_of(IS_STR, IS_DICT, IS_DICT)))), "Tracing": PropertyType(False, IS_DICT), "PermissionsBoundary": PropertyType(False, IS_STR), + "AutoPublishAlias": PassThroughProperty(False), + "DeploymentPreference": MutatedPassThroughProperty(False), } Definition: Optional[Dict[str, Any]] @@ -1724,6 +1727,8 @@ class SamStateMachine(SamResourceMacro): Policies: Optional[List[Any]] Tracing: Optional[Dict[str, Any]] PermissionsBoundary: Optional[Intrinsicable[str]] + AutoPublishAlias: Optional[PassThrough] + DeploymentPreference: Optional[PassThrough] event_resolver = ResourceTypeResolver( samtranslator.model.stepfunctions.events, @@ -1760,6 +1765,8 @@ def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def] resource_attributes=self.resource_attributes, passthrough_resource_attributes=self.get_passthrough_resource_attributes(), get_managed_policy_map=get_managed_policy_map, + auto_publish_alias=self.AutoPublishAlias, + deployment_preference=self.DeploymentPreference, ) return state_machine_generator.to_cloudformation() diff --git a/samtranslator/model/stepfunctions/__init__.py b/samtranslator/model/stepfunctions/__init__.py index 351faa72a..2ce3fe4ea 100644 --- a/samtranslator/model/stepfunctions/__init__.py +++ b/samtranslator/model/stepfunctions/__init__.py @@ -1,5 +1,11 @@ -__all__ = ["StepFunctionsStateMachine", "StateMachineGenerator", "events"] +__all__ = [ + "StepFunctionsStateMachine", + "StepFunctionsStateMachineVersion", + "StepFunctionsStateMachineAlias", + "StateMachineGenerator", + "events", +] from . import events from .generators import StateMachineGenerator -from .resources import StepFunctionsStateMachine +from .resources import StepFunctionsStateMachine, StepFunctionsStateMachineAlias, StepFunctionsStateMachineVersion diff --git a/samtranslator/model/stepfunctions/generators.py b/samtranslator/model/stepfunctions/generators.py index c1e33a54b..14ecad38b 100644 --- a/samtranslator/model/stepfunctions/generators.py +++ b/samtranslator/model/stepfunctions/generators.py @@ -9,7 +9,11 @@ from samtranslator.model.resource_policies import ResourcePolicies from samtranslator.model.role_utils import construct_role_for_resource from samtranslator.model.s3_utils.uri_parser import parse_s3_uri -from samtranslator.model.stepfunctions.resources import StepFunctionsStateMachine +from samtranslator.model.stepfunctions.resources import ( + StepFunctionsStateMachine, + StepFunctionsStateMachineAlias, + StepFunctionsStateMachineVersion, +) from samtranslator.model.tags.resource_tagging import get_tag_list from samtranslator.model.xray_utils import get_xray_managed_policy_name from samtranslator.utils.cfn_dynamic_references import is_dynamic_reference @@ -48,6 +52,8 @@ def __init__( # type: ignore[no-untyped-def] # noqa: too-many-arguments resource_attributes=None, passthrough_resource_attributes=None, get_managed_policy_map=None, + auto_publish_alias=None, + deployment_preference=None, ): """ Constructs an State Machine Generator class that generates a State Machine resource @@ -73,6 +79,8 @@ def __init__( # type: ignore[no-untyped-def] # noqa: too-many-arguments :param tags: Tags to be associated with the State Machine resource :param resource_attributes: Resource attributes to add to the State Machine resource :param passthrough_resource_attributes: Attributes such as `Condition` that are added to derived resources + :param auto_publish_alias: Name of the state machine alias to automatically create and update + :deployment_preference: Settings to enable gradual state machine deployments """ self.logical_id = logical_id self.depends_on = depends_on @@ -100,6 +108,8 @@ def __init__( # type: ignore[no-untyped-def] # noqa: too-many-arguments ) self.substitution_counter = 1 self.get_managed_policy_map = get_managed_policy_map + self.auto_publish_alias = auto_publish_alias + self.deployment_preference = deployment_preference @cw_timer(prefix="Generator", name="StateMachine") def to_cloudformation(self): # type: ignore[no-untyped-def] @@ -152,6 +162,9 @@ def to_cloudformation(self): # type: ignore[no-untyped-def] self.state_machine.TracingConfiguration = self.tracing self.state_machine.Tags = self._construct_tag_list() + managed_traffic_shifting_resources = self._generate_managed_traffic_shifting_resources() + resources.extend(managed_traffic_shifting_resources) + event_resources = self._generate_event_resources() resources.extend(event_resources) @@ -241,6 +254,72 @@ def _construct_tag_list(self) -> List[Dict[str, Any]]: sam_tag = {self._SAM_KEY: self._SAM_VALUE} return get_tag_list(sam_tag) + get_tag_list(self.tags) + def _construct_version(self) -> StepFunctionsStateMachineVersion: + """Constructs a state machine version resource that will be auto-published when the revision id of the state machine changes. + + :return: Step Functions state machine version resource + """ + + # Unlike Lambda function versions, state machine versions do not need a hash suffix because + # they are always replaced when their corresponding state machine is updated. + # I.e. A SAM StateMachine resource will never have multiple version resources at the same time. + logical_id = f"{self.logical_id}Version" + attributes = self.passthrough_resource_attributes.copy() + + # Both UpdateReplacePolicy and DeletionPolicy are needed to protect previous version from deletion + # to ensure gradual deployment works. + if "DeletionPolicy" not in attributes: + attributes["DeletionPolicy"] = "Retain" + if "UpdateReplacePolicy" not in attributes: + attributes["UpdateReplacePolicy"] = "Retain" + + state_machine_version = StepFunctionsStateMachineVersion(logical_id=logical_id, attributes=attributes) + state_machine_version.StateMachineArn = self.state_machine.get_runtime_attr("arn") + state_machine_version.StateMachineRevisionId = self.state_machine.get_runtime_attr("state_machine_revision_id") + + return state_machine_version + + def _construct_alias(self, version: StepFunctionsStateMachineVersion) -> StepFunctionsStateMachineAlias: + """Constructs a state machine alias resource pointing to the given state machine version. + :return: Step Functions state machine alias resource + """ + logical_id = f"{self.logical_id}Alias{self.auto_publish_alias}" + attributes = self.passthrough_resource_attributes + + state_machine_alias = StepFunctionsStateMachineAlias(logical_id=logical_id, attributes=attributes) + state_machine_alias.Name = self.auto_publish_alias + + state_machine_version_arn = version.get_runtime_attr("arn") + + deployment_preference = {} + if self.deployment_preference: + deployment_preference = self.deployment_preference + else: + deployment_preference["Type"] = "ALL_AT_ONCE" + + deployment_preference["StateMachineVersionArn"] = state_machine_version_arn + state_machine_alias.DeploymentPreference = deployment_preference + + return state_machine_alias + + def _generate_managed_traffic_shifting_resources( + self, + ) -> List[Any]: + """Generates and returns the version and alias resources associated with this state machine's managed traffic shifting. + + :returns: a list containing the state machine's version and alias resources + :rtype: list + """ + if not self.auto_publish_alias and not self.deployment_preference: + return [] + if not self.auto_publish_alias and self.deployment_preference: + raise InvalidResourceException( + self.logical_id, "'DeploymentPreference' requires 'AutoPublishAlias' property to be specified." + ) + + state_machine_version = self._construct_version() + return [state_machine_version, self._construct_alias(state_machine_version)] + def _generate_event_resources(self) -> List[Dict[str, Any]]: """Generates and returns the resources associated with this state machine's event sources. diff --git a/samtranslator/model/stepfunctions/resources.py b/samtranslator/model/stepfunctions/resources.py index ed945de9d..7cb07ba90 100644 --- a/samtranslator/model/stepfunctions/resources.py +++ b/samtranslator/model/stepfunctions/resources.py @@ -33,4 +33,20 @@ class StepFunctionsStateMachine(Resource): runtime_attrs = { "arn": lambda self: ref(self.logical_id), "name": lambda self: fnGetAtt(self.logical_id, "Name"), + "state_machine_revision_id": lambda self: fnGetAtt(self.logical_id, "StateMachineRevisionId"), } + + +class StepFunctionsStateMachineVersion(Resource): + resource_type = "AWS::StepFunctions::StateMachineVersion" + + property_types = {"StateMachineArn": GeneratedProperty(), "StateMachineRevisionId": GeneratedProperty()} + + runtime_attrs = {"arn": lambda self: ref(self.logical_id)} + + +class StepFunctionsStateMachineAlias(Resource): + resource_type = "AWS::StepFunctions::StateMachineAlias" + property_types = {"Name": GeneratedProperty(), "DeploymentPreference": GeneratedProperty()} + + runtime_attrs = {"arn": lambda self: ref(self.logical_id)} diff --git a/samtranslator/schema/schema.json b/samtranslator/schema/schema.json index 7c46399ca..4479f1891 100644 --- a/samtranslator/schema/schema.json +++ b/samtranslator/schema/schema.json @@ -242465,6 +242465,9 @@ "samtranslator__internal__schema_source__aws_serverless_statemachine__Properties": { "additionalProperties": false, "properties": { + "AutoPublishAlias": { + "$ref": "#/definitions/PassThroughProp" + }, "Definition": { "markdownDescription": "The state machine definition is an object, where the format of the object matches the format of your AWS SAM template file, for example, JSON or YAML\\. State machine definitions adhere to the [Amazon States Language](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html)\\. \nFor an example of an inline state machine definition, see [Examples](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/#sam-resource-statemachine--examples.html#sam-resource-statemachine--examples)\\. \nYou must provide either a `Definition` or a `DefinitionUri`\\. \n*Type*: Map \n*Required*: Conditional \n*AWS CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an AWS CloudFormation equivalent\\.", "title": "Definition", @@ -242487,6 +242490,9 @@ "markdownDescription": "The Amazon Simple Storage Service \\(Amazon S3\\) URI or local file path of the state machine definition written in the [Amazon States Language](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html)\\. \nIf you provide a local file path, the template must go through the workflow that includes the `sam deploy` or `sam package` command to correctly transform the definition\\. To do this, you must use version 0\\.52\\.0 or later of the AWS SAM CLI\\. \nYou must provide either a `Definition` or a `DefinitionUri`\\. \n*Type*: String \\| [S3Location](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-stepfunctions-statemachine.html#cfn-stepfunctions-statemachine-definitions3location) \n*Required*: Conditional \n*AWS CloudFormation compatibility*: This property is passed directly to the [`DefinitionS3Location`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-stepfunctions-statemachine.html#cfn-stepfunctions-statemachine-definitions3location) property of an `AWS::StepFunctions::StateMachine` resource\\.", "title": "DefinitionUri" }, + "DeploymentPreference": { + "$ref": "#/definitions/PassThroughProp" + }, "Events": { "additionalProperties": { "anyOf": [ diff --git a/schema_source/sam.schema.json b/schema_source/sam.schema.json index 59dddf380..4ecd6ae4b 100644 --- a/schema_source/sam.schema.json +++ b/schema_source/sam.schema.json @@ -7102,6 +7102,9 @@ "samtranslator__internal__schema_source__aws_serverless_statemachine__Properties": { "additionalProperties": false, "properties": { + "AutoPublishAlias": { + "$ref": "#/definitions/PassThroughProp" + }, "Definition": { "markdownDescription": "The state machine definition is an object, where the format of the object matches the format of your AWS SAM template file, for example, JSON or YAML\\. State machine definitions adhere to the [Amazon States Language](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html)\\. \nFor an example of an inline state machine definition, see [Examples](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/#sam-resource-statemachine--examples.html#sam-resource-statemachine--examples)\\. \nYou must provide either a `Definition` or a `DefinitionUri`\\. \n*Type*: Map \n*Required*: Conditional \n*AWS CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an AWS CloudFormation equivalent\\.", "title": "Definition", @@ -7124,6 +7127,9 @@ "markdownDescription": "The Amazon Simple Storage Service \\(Amazon S3\\) URI or local file path of the state machine definition written in the [Amazon States Language](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html)\\. \nIf you provide a local file path, the template must go through the workflow that includes the `sam deploy` or `sam package` command to correctly transform the definition\\. To do this, you must use version 0\\.52\\.0 or later of the AWS SAM CLI\\. \nYou must provide either a `Definition` or a `DefinitionUri`\\. \n*Type*: String \\| [S3Location](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-stepfunctions-statemachine.html#cfn-stepfunctions-statemachine-definitions3location) \n*Required*: Conditional \n*AWS CloudFormation compatibility*: This property is passed directly to the [`DefinitionS3Location`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-stepfunctions-statemachine.html#cfn-stepfunctions-statemachine-definitions3location) property of an `AWS::StepFunctions::StateMachine` resource\\.", "title": "DefinitionUri" }, + "DeploymentPreference": { + "$ref": "#/definitions/PassThroughProp" + }, "Events": { "additionalProperties": { "anyOf": [ diff --git a/tests/model/stepfunctions/test_state_machine_generator.py b/tests/model/stepfunctions/test_state_machine_generator.py index 9fc03b1ec..a4f801c81 100644 --- a/tests/model/stepfunctions/test_state_machine_generator.py +++ b/tests/model/stepfunctions/test_state_machine_generator.py @@ -28,7 +28,9 @@ def setUp(self): "event_resolver": None, "tags": None, "resource_attributes": None, - "passthrough_resource_attributes": None, + "passthrough_resource_attributes": {}, + "auto_publish_alias": None, + "deployment_preference": None, } def test_state_machine_no_definition_source(self): @@ -145,3 +147,43 @@ def test_state_machine_with_unsupported_event_source(self): self.kwargs["event_resources"] = {"KinesesEvent": {}} with self.assertRaises(InvalidEventException): StateMachineGenerator(**self.kwargs).to_cloudformation() + + def test_state_machine_with_managed_traffic_shifting_properties(self): + self.kwargs["definition_uri"] = "s3://mybucket/myASLfile" + self.kwargs["role"] = "my-test-role-arn" + self.kwargs["auto_publish_alias"] = "live" + self.kwargs["deployment_preference"] = {"Type": "ALL_AT_ONCE"} + generated_managed_traffic_shifting_resources = StateMachineGenerator( + **self.kwargs + )._generate_managed_traffic_shifting_resources() + self.assertEqual( + generated_managed_traffic_shifting_resources[0].resource_type, "AWS::StepFunctions::StateMachineVersion" + ) + self.assertEqual( + generated_managed_traffic_shifting_resources[1].resource_type, "AWS::StepFunctions::StateMachineAlias" + ) + + def test_state_machine_with_auto_publish_alias_and_no_deployment_preference(self): + self.kwargs["definition_uri"] = "s3://mybucket/myASLfile" + self.kwargs["role"] = "my-test-role-arn" + self.kwargs["auto_publish_alias"] = "live" + generated_managed_traffic_shifting_resources = StateMachineGenerator( + **self.kwargs + )._generate_managed_traffic_shifting_resources() + self.assertEqual( + generated_managed_traffic_shifting_resources[0].resource_type, "AWS::StepFunctions::StateMachineVersion" + ) + self.assertEqual( + generated_managed_traffic_shifting_resources[1].resource_type, "AWS::StepFunctions::StateMachineAlias" + ) + + def test_state_machine_with_deployment_preference_and_no_auto_publish_alias(self): + self.kwargs["definition_uri"] = "s3://mybucket/myASLfile" + self.kwargs["role"] = "my-test-role-arn" + self.kwargs["deployment_preference"] = {"Type": "ALL_AT_ONCE"} + with self.assertRaises(InvalidResourceException) as error: + StateMachineGenerator(**self.kwargs).to_cloudformation() + self.assertEqual( + error.exception.message, + "Resource with id [StateMachineId] is invalid. 'DeploymentPreference' requires 'AutoPublishAlias' property to be specified.", + ) diff --git a/tests/translator/input/error_state_machine_with_deployment_preference_missing_auto_publish_alias.yaml b/tests/translator/input/error_state_machine_with_deployment_preference_missing_auto_publish_alias.yaml new file mode 100644 index 000000000..e769728e6 --- /dev/null +++ b/tests/translator/input/error_state_machine_with_deployment_preference_missing_auto_publish_alias.yaml @@ -0,0 +1,15 @@ +Resources: + MyStateMachine: + Type: AWS::Serverless::StateMachine + Properties: + Type: STANDARD + Definition: + StartAt: HelloWorld + States: + HelloWorld: + Type: Pass + Result: 1 + End: true + Role: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + DeploymentPreference: + Type: ALL_AT_ONCE diff --git a/tests/translator/input/state_machine_with_auto_publish_alias.yaml b/tests/translator/input/state_machine_with_auto_publish_alias.yaml new file mode 100644 index 000000000..96b548a7a --- /dev/null +++ b/tests/translator/input/state_machine_with_auto_publish_alias.yaml @@ -0,0 +1,14 @@ +Resources: + MyStateMachine: + Type: AWS::Serverless::StateMachine + Properties: + Type: STANDARD + Definition: + StartAt: HelloWorld + States: + HelloWorld: + Type: Pass + Result: 1 + End: true + Role: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + AutoPublishAlias: test diff --git a/tests/translator/input/state_machine_with_deletion_policy.yaml b/tests/translator/input/state_machine_with_deletion_policy.yaml new file mode 100644 index 000000000..db110820b --- /dev/null +++ b/tests/translator/input/state_machine_with_deletion_policy.yaml @@ -0,0 +1,17 @@ +Resources: + MyStateMachine: + Type: AWS::Serverless::StateMachine + DeletionPolicy: Delete + Properties: + Type: STANDARD + Definition: + StartAt: HelloWorld + States: + HelloWorld: + Type: Pass + Result: 1 + End: true + Role: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + AutoPublishAlias: test + DeploymentPreference: + Type: ALL_AT_ONCE diff --git a/tests/translator/input/state_machine_with_deployment_preference_all_at_once.yaml b/tests/translator/input/state_machine_with_deployment_preference_all_at_once.yaml new file mode 100644 index 000000000..d8d16c609 --- /dev/null +++ b/tests/translator/input/state_machine_with_deployment_preference_all_at_once.yaml @@ -0,0 +1,16 @@ +Resources: + MyStateMachine: + Type: AWS::Serverless::StateMachine + Properties: + Type: STANDARD + Definition: + StartAt: HelloWorld + States: + HelloWorld: + Type: Pass + Result: 1 + End: true + Role: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + AutoPublishAlias: test + DeploymentPreference: + Type: ALL_AT_ONCE diff --git a/tests/translator/input/state_machine_with_deployment_preference_canary.yaml b/tests/translator/input/state_machine_with_deployment_preference_canary.yaml new file mode 100644 index 000000000..2ffd4b5ba --- /dev/null +++ b/tests/translator/input/state_machine_with_deployment_preference_canary.yaml @@ -0,0 +1,21 @@ +Resources: + MyStateMachine: + Type: AWS::Serverless::StateMachine + Properties: + Type: STANDARD + Definition: + StartAt: HelloWorld + States: + HelloWorld: + Type: Pass + Result: 1 + End: true + Role: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + AutoPublishAlias: test + DeploymentPreference: + Type: CANARY + Percentage: 1 + Interval: 1 + Alarms: + - alarm 1 + - alarm 2 diff --git a/tests/translator/input/state_machine_with_deployment_preference_linear.yaml b/tests/translator/input/state_machine_with_deployment_preference_linear.yaml new file mode 100644 index 000000000..6b5606718 --- /dev/null +++ b/tests/translator/input/state_machine_with_deployment_preference_linear.yaml @@ -0,0 +1,21 @@ +Resources: + MyStateMachine: + Type: AWS::Serverless::StateMachine + Properties: + Type: STANDARD + Definition: + StartAt: HelloWorld + States: + HelloWorld: + Type: Pass + Result: 1 + End: true + Role: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + AutoPublishAlias: test + DeploymentPreference: + Type: LINEAR + Percentage: 1 + Interval: 1 + Alarms: + - alarm 1 + - alarm 2 diff --git a/tests/translator/input/state_machine_with_update_replace_policy.yaml b/tests/translator/input/state_machine_with_update_replace_policy.yaml new file mode 100644 index 000000000..d8d16c609 --- /dev/null +++ b/tests/translator/input/state_machine_with_update_replace_policy.yaml @@ -0,0 +1,16 @@ +Resources: + MyStateMachine: + Type: AWS::Serverless::StateMachine + Properties: + Type: STANDARD + Definition: + StartAt: HelloWorld + States: + HelloWorld: + Type: Pass + Result: 1 + End: true + Role: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + AutoPublishAlias: test + DeploymentPreference: + Type: ALL_AT_ONCE diff --git a/tests/translator/output/aws-cn/state_machine_with_auto_publish_alias.json b/tests/translator/output/aws-cn/state_machine_with_auto_publish_alias.json new file mode 100644 index 000000000..fe3310327 --- /dev/null +++ b/tests/translator/output/aws-cn/state_machine_with_auto_publish_alias.json @@ -0,0 +1,64 @@ +{ + "Resources": { + "MyStateMachine": { + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "Properties": { + "DeploymentPreference": { + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "ALL_AT_ONCE" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Retain", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} diff --git a/tests/translator/output/aws-cn/state_machine_with_deletion_policy.json b/tests/translator/output/aws-cn/state_machine_with_deletion_policy.json new file mode 100644 index 000000000..7fa1ebebd --- /dev/null +++ b/tests/translator/output/aws-cn/state_machine_with_deletion_policy.json @@ -0,0 +1,66 @@ +{ + "Resources": { + "MyStateMachine": { + "DeletionPolicy": "Delete", + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "DeletionPolicy": "Delete", + "Properties": { + "DeploymentPreference": { + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "ALL_AT_ONCE" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Delete", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} diff --git a/tests/translator/output/aws-cn/state_machine_with_deployment_preference_all_at_once.json b/tests/translator/output/aws-cn/state_machine_with_deployment_preference_all_at_once.json new file mode 100644 index 000000000..fe3310327 --- /dev/null +++ b/tests/translator/output/aws-cn/state_machine_with_deployment_preference_all_at_once.json @@ -0,0 +1,64 @@ +{ + "Resources": { + "MyStateMachine": { + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "Properties": { + "DeploymentPreference": { + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "ALL_AT_ONCE" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Retain", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} diff --git a/tests/translator/output/aws-cn/state_machine_with_deployment_preference_canary.json b/tests/translator/output/aws-cn/state_machine_with_deployment_preference_canary.json new file mode 100644 index 000000000..83f5465f4 --- /dev/null +++ b/tests/translator/output/aws-cn/state_machine_with_deployment_preference_canary.json @@ -0,0 +1,70 @@ +{ + "Resources": { + "MyStateMachine": { + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "Properties": { + "DeploymentPreference": { + "Alarms": [ + "alarm 1", + "alarm 2" + ], + "Interval": 1, + "Percentage": 1, + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "CANARY" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Retain", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} diff --git a/tests/translator/output/aws-cn/state_machine_with_deployment_preference_linear.json b/tests/translator/output/aws-cn/state_machine_with_deployment_preference_linear.json new file mode 100644 index 000000000..9031354c9 --- /dev/null +++ b/tests/translator/output/aws-cn/state_machine_with_deployment_preference_linear.json @@ -0,0 +1,70 @@ +{ + "Resources": { + "MyStateMachine": { + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "Properties": { + "DeploymentPreference": { + "Alarms": [ + "alarm 1", + "alarm 2" + ], + "Interval": 1, + "Percentage": 1, + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "LINEAR" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Retain", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} diff --git a/tests/translator/output/aws-cn/state_machine_with_update_replace_policy.json b/tests/translator/output/aws-cn/state_machine_with_update_replace_policy.json new file mode 100644 index 000000000..fe3310327 --- /dev/null +++ b/tests/translator/output/aws-cn/state_machine_with_update_replace_policy.json @@ -0,0 +1,64 @@ +{ + "Resources": { + "MyStateMachine": { + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "Properties": { + "DeploymentPreference": { + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "ALL_AT_ONCE" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Retain", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} diff --git a/tests/translator/output/aws-us-gov/state_machine_with_auto_publish_alias.json b/tests/translator/output/aws-us-gov/state_machine_with_auto_publish_alias.json new file mode 100644 index 000000000..fe3310327 --- /dev/null +++ b/tests/translator/output/aws-us-gov/state_machine_with_auto_publish_alias.json @@ -0,0 +1,64 @@ +{ + "Resources": { + "MyStateMachine": { + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "Properties": { + "DeploymentPreference": { + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "ALL_AT_ONCE" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Retain", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} diff --git a/tests/translator/output/aws-us-gov/state_machine_with_deletion_policy.json b/tests/translator/output/aws-us-gov/state_machine_with_deletion_policy.json new file mode 100644 index 000000000..7fa1ebebd --- /dev/null +++ b/tests/translator/output/aws-us-gov/state_machine_with_deletion_policy.json @@ -0,0 +1,66 @@ +{ + "Resources": { + "MyStateMachine": { + "DeletionPolicy": "Delete", + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "DeletionPolicy": "Delete", + "Properties": { + "DeploymentPreference": { + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "ALL_AT_ONCE" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Delete", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} diff --git a/tests/translator/output/aws-us-gov/state_machine_with_deployment_preference_all_at_once.json b/tests/translator/output/aws-us-gov/state_machine_with_deployment_preference_all_at_once.json new file mode 100644 index 000000000..fe3310327 --- /dev/null +++ b/tests/translator/output/aws-us-gov/state_machine_with_deployment_preference_all_at_once.json @@ -0,0 +1,64 @@ +{ + "Resources": { + "MyStateMachine": { + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "Properties": { + "DeploymentPreference": { + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "ALL_AT_ONCE" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Retain", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} diff --git a/tests/translator/output/aws-us-gov/state_machine_with_deployment_preference_canary.json b/tests/translator/output/aws-us-gov/state_machine_with_deployment_preference_canary.json new file mode 100644 index 000000000..83f5465f4 --- /dev/null +++ b/tests/translator/output/aws-us-gov/state_machine_with_deployment_preference_canary.json @@ -0,0 +1,70 @@ +{ + "Resources": { + "MyStateMachine": { + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "Properties": { + "DeploymentPreference": { + "Alarms": [ + "alarm 1", + "alarm 2" + ], + "Interval": 1, + "Percentage": 1, + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "CANARY" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Retain", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} diff --git a/tests/translator/output/aws-us-gov/state_machine_with_deployment_preference_linear.json b/tests/translator/output/aws-us-gov/state_machine_with_deployment_preference_linear.json new file mode 100644 index 000000000..9031354c9 --- /dev/null +++ b/tests/translator/output/aws-us-gov/state_machine_with_deployment_preference_linear.json @@ -0,0 +1,70 @@ +{ + "Resources": { + "MyStateMachine": { + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "Properties": { + "DeploymentPreference": { + "Alarms": [ + "alarm 1", + "alarm 2" + ], + "Interval": 1, + "Percentage": 1, + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "LINEAR" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Retain", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} diff --git a/tests/translator/output/aws-us-gov/state_machine_with_update_replace_policy.json b/tests/translator/output/aws-us-gov/state_machine_with_update_replace_policy.json new file mode 100644 index 000000000..fe3310327 --- /dev/null +++ b/tests/translator/output/aws-us-gov/state_machine_with_update_replace_policy.json @@ -0,0 +1,64 @@ +{ + "Resources": { + "MyStateMachine": { + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "Properties": { + "DeploymentPreference": { + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "ALL_AT_ONCE" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Retain", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} diff --git a/tests/translator/output/error_state_machine_with_deployment_preference_missing_auto_publish_alias.json b/tests/translator/output/error_state_machine_with_deployment_preference_missing_auto_publish_alias.json new file mode 100644 index 000000000..0409ec37f --- /dev/null +++ b/tests/translator/output/error_state_machine_with_deployment_preference_missing_auto_publish_alias.json @@ -0,0 +1,9 @@ +{ + "_autoGeneratedBreakdownErrorMessage": [ + "Invalid Serverless Application Specification document. ", + "Number of errors found: 1. ", + "Resource with id [MyStateMachine] is invalid. ", + "'DeploymentPreference' requires 'AutoPublishAlias' property to be specified." + ], + "errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 1. Resource with id [MyStateMachine] is invalid. 'DeploymentPreference' requires 'AutoPublishAlias' property to be specified." +} diff --git a/tests/translator/output/state_machine_with_auto_publish_alias.json b/tests/translator/output/state_machine_with_auto_publish_alias.json new file mode 100644 index 000000000..fe3310327 --- /dev/null +++ b/tests/translator/output/state_machine_with_auto_publish_alias.json @@ -0,0 +1,64 @@ +{ + "Resources": { + "MyStateMachine": { + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "Properties": { + "DeploymentPreference": { + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "ALL_AT_ONCE" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Retain", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} diff --git a/tests/translator/output/state_machine_with_deletion_policy.json b/tests/translator/output/state_machine_with_deletion_policy.json new file mode 100644 index 000000000..7fa1ebebd --- /dev/null +++ b/tests/translator/output/state_machine_with_deletion_policy.json @@ -0,0 +1,66 @@ +{ + "Resources": { + "MyStateMachine": { + "DeletionPolicy": "Delete", + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "DeletionPolicy": "Delete", + "Properties": { + "DeploymentPreference": { + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "ALL_AT_ONCE" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Delete", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} diff --git a/tests/translator/output/state_machine_with_deployment_preference_all_at_once.json b/tests/translator/output/state_machine_with_deployment_preference_all_at_once.json new file mode 100644 index 000000000..fe3310327 --- /dev/null +++ b/tests/translator/output/state_machine_with_deployment_preference_all_at_once.json @@ -0,0 +1,64 @@ +{ + "Resources": { + "MyStateMachine": { + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "Properties": { + "DeploymentPreference": { + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "ALL_AT_ONCE" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Retain", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} diff --git a/tests/translator/output/state_machine_with_deployment_preference_canary.json b/tests/translator/output/state_machine_with_deployment_preference_canary.json new file mode 100644 index 000000000..83f5465f4 --- /dev/null +++ b/tests/translator/output/state_machine_with_deployment_preference_canary.json @@ -0,0 +1,70 @@ +{ + "Resources": { + "MyStateMachine": { + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "Properties": { + "DeploymentPreference": { + "Alarms": [ + "alarm 1", + "alarm 2" + ], + "Interval": 1, + "Percentage": 1, + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "CANARY" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Retain", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} diff --git a/tests/translator/output/state_machine_with_deployment_preference_linear.json b/tests/translator/output/state_machine_with_deployment_preference_linear.json new file mode 100644 index 000000000..9031354c9 --- /dev/null +++ b/tests/translator/output/state_machine_with_deployment_preference_linear.json @@ -0,0 +1,70 @@ +{ + "Resources": { + "MyStateMachine": { + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "Properties": { + "DeploymentPreference": { + "Alarms": [ + "alarm 1", + "alarm 2" + ], + "Interval": 1, + "Percentage": 1, + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "LINEAR" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Retain", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} diff --git a/tests/translator/output/state_machine_with_update_replace_policy.json b/tests/translator/output/state_machine_with_update_replace_policy.json new file mode 100644 index 000000000..fe3310327 --- /dev/null +++ b/tests/translator/output/state_machine_with_update_replace_policy.json @@ -0,0 +1,64 @@ +{ + "Resources": { + "MyStateMachine": { + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "\n", + [ + "{", + " \"StartAt\": \"HelloWorld\",", + " \"States\": {", + " \"HelloWorld\": {", + " \"End\": true,", + " \"Result\": 1,", + " \"Type\": \"Pass\"", + " }", + " }", + "}" + ] + ] + }, + "RoleArn": { + "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/doesNotExist" + }, + "StateMachineType": "STANDARD", + "Tags": [ + { + "Key": "stateMachine:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::StepFunctions::StateMachine" + }, + "MyStateMachineAliastest": { + "Properties": { + "DeploymentPreference": { + "StateMachineVersionArn": { + "Ref": "MyStateMachineVersion" + }, + "Type": "ALL_AT_ONCE" + }, + "Name": "test" + }, + "Type": "AWS::StepFunctions::StateMachineAlias" + }, + "MyStateMachineVersion": { + "DeletionPolicy": "Retain", + "Properties": { + "StateMachineArn": { + "Ref": "MyStateMachine" + }, + "StateMachineRevisionId": { + "Fn::GetAtt": [ + "MyStateMachine", + "StateMachineRevisionId" + ] + } + }, + "Type": "AWS::StepFunctions::StateMachineVersion", + "UpdateReplacePolicy": "Retain" + } + } +} From cfdaebba20828d695bc52873924b770c879e482a Mon Sep 17 00:00:00 2001 From: Gavin Zhang Date: Thu, 22 Jun 2023 18:12:05 +0000 Subject: [PATCH 2/3] feat: Add StartingPositionTimestamp to SelfManagedKafka --- .../internal/schema_source/aws_serverless_function.py | 2 ++ samtranslator/schema/schema.json | 6 ++++++ schema_source/sam.schema.json | 6 ++++++ .../translator/input/function_with_self_managed_kafka.yaml | 2 ++ .../output/aws-cn/function_with_self_managed_kafka.json | 2 ++ .../output/aws-us-gov/function_with_self_managed_kafka.json | 2 ++ .../translator/output/function_with_self_managed_kafka.json | 2 ++ 7 files changed, 22 insertions(+) diff --git a/samtranslator/internal/schema_source/aws_serverless_function.py b/samtranslator/internal/schema_source/aws_serverless_function.py index d0015a182..9a3dbb05f 100644 --- a/samtranslator/internal/schema_source/aws_serverless_function.py +++ b/samtranslator/internal/schema_source/aws_serverless_function.py @@ -441,6 +441,8 @@ class SelfManagedKafkaEventProperties(BaseModel): "KafkaBootstrapServers" ) SourceAccessConfigurations: PassThroughProp = selfmanagedkafkaeventproperties("SourceAccessConfigurations") + StartingPosition: Optional[PassThroughProp] # TODO: add documentation + StartingPositionTimestamp: Optional[PassThroughProp] # TODO: add documentation Topics: PassThroughProp = selfmanagedkafkaeventproperties("Topics") diff --git a/samtranslator/schema/schema.json b/samtranslator/schema/schema.json index 4479f1891..9b57cc83b 100644 --- a/samtranslator/schema/schema.json +++ b/samtranslator/schema/schema.json @@ -238958,6 +238958,12 @@ "markdownDescription": "An array of the authentication protocol, VPC components, or virtual host to secure and define your event source\\. \n*Valid values*: `BASIC_AUTH | CLIENT_CERTIFICATE_TLS_AUTH | SASL_SCRAM_256_AUTH | SASL_SCRAM_512_AUTH | SERVER_ROOT_CA_CERTIFICATE` \n*Type*: List of [SourceAccessConfiguration](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-eventsourcemapping-sourceaccessconfiguration.html) \n*Required*: Yes \n*AWS CloudFormation compatibility*: This property is passed directly to the `[ SourceAccessConfigurations](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html#cfn-lambda-eventsourcemapping-sourceaccessconfigurations)` property of an `AWS::Lambda::EventSourceMapping` resource\\.", "title": "SourceAccessConfigurations" }, + "StartingPosition": { + "$ref": "#/definitions/PassThroughProp" + }, + "StartingPositionTimestamp": { + "$ref": "#/definitions/PassThroughProp" + }, "Topics": { "allOf": [ { diff --git a/schema_source/sam.schema.json b/schema_source/sam.schema.json index 4ecd6ae4b..6de0adf76 100644 --- a/schema_source/sam.schema.json +++ b/schema_source/sam.schema.json @@ -2753,6 +2753,12 @@ "markdownDescription": "An array of the authentication protocol, VPC components, or virtual host to secure and define your event source\\. \n*Valid values*: `BASIC_AUTH | CLIENT_CERTIFICATE_TLS_AUTH | SASL_SCRAM_256_AUTH | SASL_SCRAM_512_AUTH | SERVER_ROOT_CA_CERTIFICATE` \n*Type*: List of [SourceAccessConfiguration](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-eventsourcemapping-sourceaccessconfiguration.html) \n*Required*: Yes \n*AWS CloudFormation compatibility*: This property is passed directly to the `[ SourceAccessConfigurations](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html#cfn-lambda-eventsourcemapping-sourceaccessconfigurations)` property of an `AWS::Lambda::EventSourceMapping` resource\\.", "title": "SourceAccessConfigurations" }, + "StartingPosition": { + "$ref": "#/definitions/PassThroughProp" + }, + "StartingPositionTimestamp": { + "$ref": "#/definitions/PassThroughProp" + }, "Topics": { "allOf": [ { diff --git a/tests/translator/input/function_with_self_managed_kafka.yaml b/tests/translator/input/function_with_self_managed_kafka.yaml index b155b23ec..d9555522d 100644 --- a/tests/translator/input/function_with_self_managed_kafka.yaml +++ b/tests/translator/input/function_with_self_managed_kafka.yaml @@ -24,3 +24,5 @@ Resources: - Type: VPC_SECURITY_GROUP URI: security_group:sg-67890 ConsumerGroupId: consumergroup1 + StartingPosition: AT_TIMESTAMP + StartingPositionTimestamp: 1672560000 diff --git a/tests/translator/output/aws-cn/function_with_self_managed_kafka.json b/tests/translator/output/aws-cn/function_with_self_managed_kafka.json index 827fe9796..421817b28 100644 --- a/tests/translator/output/aws-cn/function_with_self_managed_kafka.json +++ b/tests/translator/output/aws-cn/function_with_self_managed_kafka.json @@ -55,6 +55,8 @@ "URI": "security_group:sg-67890" } ], + "StartingPosition": "AT_TIMESTAMP", + "StartingPositionTimestamp": 1672560000, "Topics": [ "Topic1" ] diff --git a/tests/translator/output/aws-us-gov/function_with_self_managed_kafka.json b/tests/translator/output/aws-us-gov/function_with_self_managed_kafka.json index f39db6c53..fa55db2f6 100644 --- a/tests/translator/output/aws-us-gov/function_with_self_managed_kafka.json +++ b/tests/translator/output/aws-us-gov/function_with_self_managed_kafka.json @@ -55,6 +55,8 @@ "URI": "security_group:sg-67890" } ], + "StartingPosition": "AT_TIMESTAMP", + "StartingPositionTimestamp": 1672560000, "Topics": [ "Topic1" ] diff --git a/tests/translator/output/function_with_self_managed_kafka.json b/tests/translator/output/function_with_self_managed_kafka.json index fe5de62f9..fee30a363 100644 --- a/tests/translator/output/function_with_self_managed_kafka.json +++ b/tests/translator/output/function_with_self_managed_kafka.json @@ -55,6 +55,8 @@ "URI": "security_group:sg-67890" } ], + "StartingPosition": "AT_TIMESTAMP", + "StartingPositionTimestamp": 1672560000, "Topics": [ "Topic1" ] From b5dbc6f91846896fe2c463407e8001ed82bfbd18 Mon Sep 17 00:00:00 2001 From: aws-sam-cli-bot <46753707+aws-sam-cli-bot@users.noreply.github.com> Date: Thu, 22 Jun 2023 18:12:06 +0000 Subject: [PATCH 3/3] chore: bump version to 1.70.0 --- samtranslator/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samtranslator/__init__.py b/samtranslator/__init__.py index 6685d00e0..f84f7c67b 100644 --- a/samtranslator/__init__.py +++ b/samtranslator/__init__.py @@ -1 +1 @@ -__version__ = "1.68.0" +__version__ = "1.70.0"