Skip to content

Commit d1685e2

Browse files
authored
Merge branch 'main' into release-v1.71.0
2 parents 51f7bf6 + 75b7858 commit d1685e2

File tree

41 files changed

+1528
-4
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1528
-4
lines changed

.cfnlintrc.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ ignore_templates:
118118
- tests/translator/output/**/state_machine_with_event_schedule_state.json
119119
- tests/translator/output/**/state_machine_with_schedule.json
120120
- tests/translator/output/**/state_machine_with_schedule_dlq_retry_policy.json
121+
- tests/translator/output/**/state_machine_with_auto_publish_alias.json
122+
- tests/translator/output/**/state_machine_with_deployment_preference_all_at_once.json
123+
- tests/translator/output/**/state_machine_with_deployment_preference_canary.json
124+
- tests/translator/output/**/state_machine_with_deployment_preference_linear.json
125+
- tests/translator/output/**/state_machine_with_deletion_policy.json
126+
- tests/translator/output/**/state_machine_with_update_replace_policy.json
121127
- tests/translator/output/**/globals_for_function.json # RuntimeManagementConfig
122128
- tests/translator/output/**/function_with_runtime_config.json # RuntimeManagementConfig
123129
- tests/translator/output/**/managed_policies_minimal.json # Intentionally has non-existent managed policy name

samtranslator/internal/schema_source/aws_serverless_function.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,8 @@ class SelfManagedKafkaEventProperties(BaseModel):
441441
"KafkaBootstrapServers"
442442
)
443443
SourceAccessConfigurations: PassThroughProp = selfmanagedkafkaeventproperties("SourceAccessConfigurations")
444+
StartingPosition: Optional[PassThroughProp] # TODO: add documentation
445+
StartingPositionTimestamp: Optional[PassThroughProp] # TODO: add documentation
444446
Topics: PassThroughProp = selfmanagedkafkaeventproperties("Topics")
445447

446448

samtranslator/internal/schema_source/aws_serverless_statemachine.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ class Properties(BaseModel):
172172
PropagateTags: Optional[bool] # TODO: add docs
173173
Tracing: Optional[PassThroughProp] = properties("Tracing")
174174
Type: Optional[PassThroughProp] = properties("Type")
175+
AutoPublishAlias: Optional[PassThroughProp]
176+
DeploymentPreference: Optional[PassThroughProp]
175177

176178

177179
class Resource(ResourceAttributes):

samtranslator/model/__init__.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ def __init__(self, required: bool) -> None:
7474
super().__init__(required, any_type(), False)
7575

7676

77+
class MutatedPassThroughProperty(PassThroughProperty):
78+
"""
79+
Mutated pass-through property.
80+
81+
SAM Translator may read and add/remove/modify the value before passing it to underlaying CFN resources.
82+
"""
83+
84+
7785
class GeneratedProperty(PropertyType):
7886
"""
7987
Property of a generated CloudFormation resource.
@@ -662,6 +670,7 @@ def get_resource_by_logical_id(self, _input: str) -> Dict[str, Any]:
662670
"PropertyType",
663671
"Property",
664672
"PassThroughProperty",
673+
"MutatedPassThroughProperty",
665674
"Resource",
666675
"ResourceMacro",
667676
"SamResourceMacro",

samtranslator/model/sam_resources.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
from samtranslator.intrinsics.resolver import IntrinsicsResolver
4141
from samtranslator.metrics.method_decorator import cw_timer
4242
from samtranslator.model import (
43+
MutatedPassThroughProperty,
4344
PassThroughProperty,
4445
Property,
4546
PropertyType,
@@ -1761,6 +1762,8 @@ class SamStateMachine(SamResourceMacro):
17611762
"Policies": PropertyType(False, one_of(IS_STR, list_of(one_of(IS_STR, IS_DICT, IS_DICT)))),
17621763
"Tracing": PropertyType(False, IS_DICT),
17631764
"PermissionsBoundary": PropertyType(False, IS_STR),
1765+
"AutoPublishAlias": PassThroughProperty(False),
1766+
"DeploymentPreference": MutatedPassThroughProperty(False),
17641767
}
17651768

17661769
Definition: Optional[Dict[str, Any]]
@@ -1777,6 +1780,8 @@ class SamStateMachine(SamResourceMacro):
17771780
Policies: Optional[List[Any]]
17781781
Tracing: Optional[Dict[str, Any]]
17791782
PermissionsBoundary: Optional[Intrinsicable[str]]
1783+
AutoPublishAlias: Optional[PassThrough]
1784+
DeploymentPreference: Optional[PassThrough]
17801785

17811786
event_resolver = ResourceTypeResolver(
17821787
samtranslator.model.stepfunctions.events,
@@ -1813,6 +1818,8 @@ def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def]
18131818
resource_attributes=self.resource_attributes,
18141819
passthrough_resource_attributes=self.get_passthrough_resource_attributes(),
18151820
get_managed_policy_map=get_managed_policy_map,
1821+
auto_publish_alias=self.AutoPublishAlias,
1822+
deployment_preference=self.DeploymentPreference,
18161823
)
18171824

18181825
generated_resources = state_machine_generator.to_cloudformation()
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1-
__all__ = ["StepFunctionsStateMachine", "StateMachineGenerator", "events"]
1+
__all__ = [
2+
"StepFunctionsStateMachine",
3+
"StepFunctionsStateMachineVersion",
4+
"StepFunctionsStateMachineAlias",
5+
"StateMachineGenerator",
6+
"events",
7+
]
28

39
from . import events
410
from .generators import StateMachineGenerator
5-
from .resources import StepFunctionsStateMachine
11+
from .resources import StepFunctionsStateMachine, StepFunctionsStateMachineAlias, StepFunctionsStateMachineVersion

samtranslator/model/stepfunctions/generators.py

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@
99
from samtranslator.model.resource_policies import ResourcePolicies
1010
from samtranslator.model.role_utils import construct_role_for_resource
1111
from samtranslator.model.s3_utils.uri_parser import parse_s3_uri
12-
from samtranslator.model.stepfunctions.resources import StepFunctionsStateMachine
12+
from samtranslator.model.stepfunctions.resources import (
13+
StepFunctionsStateMachine,
14+
StepFunctionsStateMachineAlias,
15+
StepFunctionsStateMachineVersion,
16+
)
1317
from samtranslator.model.tags.resource_tagging import get_tag_list
1418
from samtranslator.model.xray_utils import get_xray_managed_policy_name
1519
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
4852
resource_attributes=None,
4953
passthrough_resource_attributes=None,
5054
get_managed_policy_map=None,
55+
auto_publish_alias=None,
56+
deployment_preference=None,
5157
):
5258
"""
5359
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
7379
:param tags: Tags to be associated with the State Machine resource
7480
:param resource_attributes: Resource attributes to add to the State Machine resource
7581
:param passthrough_resource_attributes: Attributes such as `Condition` that are added to derived resources
82+
:param auto_publish_alias: Name of the state machine alias to automatically create and update
83+
:deployment_preference: Settings to enable gradual state machine deployments
7684
"""
7785
self.logical_id = logical_id
7886
self.depends_on = depends_on
@@ -100,6 +108,8 @@ def __init__( # type: ignore[no-untyped-def] # noqa: too-many-arguments
100108
)
101109
self.substitution_counter = 1
102110
self.get_managed_policy_map = get_managed_policy_map
111+
self.auto_publish_alias = auto_publish_alias
112+
self.deployment_preference = deployment_preference
103113

104114
@cw_timer(prefix="Generator", name="StateMachine")
105115
def to_cloudformation(self): # type: ignore[no-untyped-def]
@@ -152,6 +162,9 @@ def to_cloudformation(self): # type: ignore[no-untyped-def]
152162
self.state_machine.TracingConfiguration = self.tracing
153163
self.state_machine.Tags = self._construct_tag_list()
154164

165+
managed_traffic_shifting_resources = self._generate_managed_traffic_shifting_resources()
166+
resources.extend(managed_traffic_shifting_resources)
167+
155168
event_resources = self._generate_event_resources()
156169
resources.extend(event_resources)
157170

@@ -241,6 +254,72 @@ def _construct_tag_list(self) -> List[Dict[str, Any]]:
241254
sam_tag = {self._SAM_KEY: self._SAM_VALUE}
242255
return get_tag_list(sam_tag) + get_tag_list(self.tags)
243256

257+
def _construct_version(self) -> StepFunctionsStateMachineVersion:
258+
"""Constructs a state machine version resource that will be auto-published when the revision id of the state machine changes.
259+
260+
:return: Step Functions state machine version resource
261+
"""
262+
263+
# Unlike Lambda function versions, state machine versions do not need a hash suffix because
264+
# they are always replaced when their corresponding state machine is updated.
265+
# I.e. A SAM StateMachine resource will never have multiple version resources at the same time.
266+
logical_id = f"{self.logical_id}Version"
267+
attributes = self.passthrough_resource_attributes.copy()
268+
269+
# Both UpdateReplacePolicy and DeletionPolicy are needed to protect previous version from deletion
270+
# to ensure gradual deployment works.
271+
if "DeletionPolicy" not in attributes:
272+
attributes["DeletionPolicy"] = "Retain"
273+
if "UpdateReplacePolicy" not in attributes:
274+
attributes["UpdateReplacePolicy"] = "Retain"
275+
276+
state_machine_version = StepFunctionsStateMachineVersion(logical_id=logical_id, attributes=attributes)
277+
state_machine_version.StateMachineArn = self.state_machine.get_runtime_attr("arn")
278+
state_machine_version.StateMachineRevisionId = self.state_machine.get_runtime_attr("state_machine_revision_id")
279+
280+
return state_machine_version
281+
282+
def _construct_alias(self, version: StepFunctionsStateMachineVersion) -> StepFunctionsStateMachineAlias:
283+
"""Constructs a state machine alias resource pointing to the given state machine version.
284+
:return: Step Functions state machine alias resource
285+
"""
286+
logical_id = f"{self.logical_id}Alias{self.auto_publish_alias}"
287+
attributes = self.passthrough_resource_attributes
288+
289+
state_machine_alias = StepFunctionsStateMachineAlias(logical_id=logical_id, attributes=attributes)
290+
state_machine_alias.Name = self.auto_publish_alias
291+
292+
state_machine_version_arn = version.get_runtime_attr("arn")
293+
294+
deployment_preference = {}
295+
if self.deployment_preference:
296+
deployment_preference = self.deployment_preference
297+
else:
298+
deployment_preference["Type"] = "ALL_AT_ONCE"
299+
300+
deployment_preference["StateMachineVersionArn"] = state_machine_version_arn
301+
state_machine_alias.DeploymentPreference = deployment_preference
302+
303+
return state_machine_alias
304+
305+
def _generate_managed_traffic_shifting_resources(
306+
self,
307+
) -> List[Any]:
308+
"""Generates and returns the version and alias resources associated with this state machine's managed traffic shifting.
309+
310+
:returns: a list containing the state machine's version and alias resources
311+
:rtype: list
312+
"""
313+
if not self.auto_publish_alias and not self.deployment_preference:
314+
return []
315+
if not self.auto_publish_alias and self.deployment_preference:
316+
raise InvalidResourceException(
317+
self.logical_id, "'DeploymentPreference' requires 'AutoPublishAlias' property to be specified."
318+
)
319+
320+
state_machine_version = self._construct_version()
321+
return [state_machine_version, self._construct_alias(state_machine_version)]
322+
244323
def _generate_event_resources(self) -> List[Dict[str, Any]]:
245324
"""Generates and returns the resources associated with this state machine's event sources.
246325

samtranslator/model/stepfunctions/resources.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,20 @@ class StepFunctionsStateMachine(Resource):
3333
runtime_attrs = {
3434
"arn": lambda self: ref(self.logical_id),
3535
"name": lambda self: fnGetAtt(self.logical_id, "Name"),
36+
"state_machine_revision_id": lambda self: fnGetAtt(self.logical_id, "StateMachineRevisionId"),
3637
}
38+
39+
40+
class StepFunctionsStateMachineVersion(Resource):
41+
resource_type = "AWS::StepFunctions::StateMachineVersion"
42+
43+
property_types = {"StateMachineArn": GeneratedProperty(), "StateMachineRevisionId": GeneratedProperty()}
44+
45+
runtime_attrs = {"arn": lambda self: ref(self.logical_id)}
46+
47+
48+
class StepFunctionsStateMachineAlias(Resource):
49+
resource_type = "AWS::StepFunctions::StateMachineAlias"
50+
property_types = {"Name": GeneratedProperty(), "DeploymentPreference": GeneratedProperty()}
51+
52+
runtime_attrs = {"arn": lambda self: ref(self.logical_id)}

samtranslator/schema/schema.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242330,6 +242330,12 @@
242330242330
"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\\.",
242331242331
"title": "SourceAccessConfigurations"
242332242332
},
242333+
"StartingPosition": {
242334+
"$ref": "#/definitions/PassThroughProp"
242335+
},
242336+
"StartingPositionTimestamp": {
242337+
"$ref": "#/definitions/PassThroughProp"
242338+
},
242333242339
"Topics": {
242334242340
"allOf": [
242335242341
{
@@ -246051,6 +246057,9 @@
246051246057
"samtranslator__internal__schema_source__aws_serverless_statemachine__Properties": {
246052246058
"additionalProperties": false,
246053246059
"properties": {
246060+
"AutoPublishAlias": {
246061+
"$ref": "#/definitions/PassThroughProp"
246062+
},
246054246063
"Definition": {
246055246064
"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\\.",
246056246065
"title": "Definition",
@@ -246073,6 +246082,9 @@
246073246082
"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\\.",
246074246083
"title": "DefinitionUri"
246075246084
},
246085+
"DeploymentPreference": {
246086+
"$ref": "#/definitions/PassThroughProp"
246087+
},
246076246088
"Events": {
246077246089
"additionalProperties": {
246078246090
"anyOf": [

schema_source/sam.schema.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3147,6 +3147,12 @@
31473147
"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\\.",
31483148
"title": "SourceAccessConfigurations"
31493149
},
3150+
"StartingPosition": {
3151+
"$ref": "#/definitions/PassThroughProp"
3152+
},
3153+
"StartingPositionTimestamp": {
3154+
"$ref": "#/definitions/PassThroughProp"
3155+
},
31503156
"Topics": {
31513157
"allOf": [
31523158
{
@@ -7710,6 +7716,9 @@
77107716
"samtranslator__internal__schema_source__aws_serverless_statemachine__Properties": {
77117717
"additionalProperties": false,
77127718
"properties": {
7719+
"AutoPublishAlias": {
7720+
"$ref": "#/definitions/PassThroughProp"
7721+
},
77137722
"Definition": {
77147723
"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\\.",
77157724
"title": "Definition",
@@ -7732,6 +7741,9 @@
77327741
"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\\.",
77337742
"title": "DefinitionUri"
77347743
},
7744+
"DeploymentPreference": {
7745+
"$ref": "#/definitions/PassThroughProp"
7746+
},
77357747
"Events": {
77367748
"additionalProperties": {
77377749
"anyOf": [

0 commit comments

Comments
 (0)