Skip to content

Commit 42afd7a

Browse files
committed
feat: Support RecursiveLoop property in SAM function
1 parent 16da6e7 commit 42afd7a

15 files changed

+436
-25
lines changed

.cfnlintrc.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ ignore_templates:
129129
- tests/translator/output/**/managed_policies_minimal.json # Intentionally has non-existent managed policy name
130130
- tests/translator/output/**/function_with_mq.json # Property "EventSourceArn" can Fn::GetAtt to a resource of types [AWS::DynamoDB::GlobalTable, AWS::DynamoDB::Table, AWS::Kinesis::Stream, AWS::Kinesis::StreamConsumer, AWS::SQS::Queue]
131131
- tests/translator/output/**/function_with_mq_using_autogen_role.json # Property "EventSourceArn" can Fn::GetAtt to a resource of types [AWS::DynamoDB::GlobalTable, AWS::DynamoDB::Table, AWS::Kinesis::Stream, AWS::Kinesis::StreamConsumer, AWS::SQS::Queue]
132+
- tests/translator/output/**/function_with_recursive_loop.json # Invalid Property Resources/RecursiveLoopParameterFunction/Properties/RecursiveLoop
132133
- tests/translator/output/**/function_with_tracing.json # Obsolete DependsOn on resource
133134
- tests/translator/output/**/api_with_propagate_tags.json # TODO: Intentional error transform tests. Will be updated.
134135
- tests/translator/output/**/function_with_intrinsics_resource_attribute.json # CFN now supports intrinsics in DeletionPolicy

samtranslator/internal/schema_source/aws_serverless_function.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ class ScheduleV2Event(BaseModel):
506506
SnapStart = Optional[PassThroughProp] # TODO: check the type
507507
RuntimeManagementConfig = Optional[PassThroughProp] # TODO: check the type
508508
LoggingConfig = Optional[PassThroughProp] # TODO: add documentation
509+
RecursiveLoop = Optional[PassThroughProp]
509510

510511

511512
class Properties(BaseModel):
@@ -632,6 +633,7 @@ class Properties(BaseModel):
632633
VersionDescription: Optional[PassThroughProp] = prop("VersionDescription")
633634
VpcConfig: Optional[VpcConfig] = prop("VpcConfig")
634635
LoggingConfig: Optional[PassThroughProp] # TODO: add documentation
636+
RecursiveLoop: Optional[PassThroughProp] # TODO: add documentation
635637

636638

637639
class Globals(BaseModel):
@@ -690,6 +692,7 @@ class Globals(BaseModel):
690692
SnapStart: Optional[SnapStart] = prop("SnapStart")
691693
RuntimeManagementConfig: Optional[RuntimeManagementConfig] = prop("RuntimeManagementConfig")
692694
LoggingConfig: Optional[PassThroughProp] # TODO: add documentation
695+
RecursiveLoop: Optional[PassThroughProp] # TODO: add documentation
693696

694697

695698
class Resource(ResourceAttributes):

samtranslator/model/lambda_.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class LambdaFunction(Resource):
3535
"EphemeralStorage": GeneratedProperty(),
3636
"RuntimeManagementConfig": GeneratedProperty(),
3737
"LoggingConfig": GeneratedProperty(),
38+
"RecursiveLoop": GeneratedProperty(),
3839
}
3940

4041
Code: Dict[str, Any]
@@ -62,6 +63,7 @@ class LambdaFunction(Resource):
6263
EphemeralStorage: Optional[Dict[str, Any]]
6364
RuntimeManagementConfig: Optional[Dict[str, Any]]
6465
LoggingConfig: Optional[Dict[str, Any]]
66+
RecursiveLoop: Optional[str]
6567

6668
runtime_attrs = {"name": lambda self: ref(self.logical_id), "arn": lambda self: fnGetAtt(self.logical_id, "Arn")}
6769

samtranslator/model/sam_resources.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ class SamFunction(SamResourceMacro):
179179
"FunctionUrlConfig": PropertyType(False, IS_DICT),
180180
"RuntimeManagementConfig": PassThroughProperty(False),
181181
"LoggingConfig": PassThroughProperty(False),
182+
"RecursiveLoop": PassThroughProperty(False),
182183
}
183184

184185
FunctionName: Optional[Intrinsicable[str]]
@@ -221,6 +222,7 @@ class SamFunction(SamResourceMacro):
221222
SnapStart: Optional[Dict[str, Any]]
222223
FunctionUrlConfig: Optional[Dict[str, Any]]
223224
LoggingConfig: Optional[Dict[str, Any]]
225+
RecursiveLoop: Optional[str]
224226

225227
event_resolver = ResourceTypeResolver(
226228
samtranslator.model.eventsources,
@@ -605,6 +607,7 @@ def _construct_lambda_function(self, intrinsics_resolver: IntrinsicsResolver) ->
605607

606608
lambda_function.RuntimeManagementConfig = self.RuntimeManagementConfig # type: ignore[attr-defined]
607609
lambda_function.LoggingConfig = self.LoggingConfig
610+
lambda_function.RecursiveLoop = self.RecursiveLoop
608611
self._validate_package_type(lambda_function)
609612
return lambda_function
610613

samtranslator/plugins/globals/globals.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class Globals:
5454
"FunctionUrlConfig",
5555
"RuntimeManagementConfig",
5656
"LoggingConfig",
57+
"RecursiveLoop",
5758
],
5859
# Everything except
5960
# DefinitionBody: because its hard to reason about merge of Swagger dictionaries
@@ -98,7 +99,7 @@ class Globals:
9899
}
99100
# unreleased_properties *must be* part of supported_properties too
100101
unreleased_properties: Dict[str, List[str]] = {
101-
SamResourceType.Function.value: ["RuntimeManagementConfig"],
102+
SamResourceType.Function.value: ["RuntimeManagementConfig", "RecursiveLoop"],
102103
}
103104

104105
def __init__(self, template: Dict[str, Any]) -> None:

samtranslator/schema/schema.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278744,6 +278744,9 @@
278744278744
"markdownDescription": "The provisioned concurrency configuration of a function's alias\\. \n`ProvisionedConcurrencyConfig` can be specified only if the `AutoPublishAlias` is set\\. Otherwise, an error results\\.\n*Type*: [ProvisionedConcurrencyConfig](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-alias.html#cfn-lambda-alias-provisionedconcurrencyconfig) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`ProvisionedConcurrencyConfig`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-alias.html#cfn-lambda-alias-provisionedconcurrencyconfig) property of an `AWS::Lambda::Alias` resource\\.",
278745278745
"title": "ProvisionedConcurrencyConfig"
278746278746
},
278747+
"RecursiveLoop": {
278748+
"$ref": "#/definitions/PassThroughProp"
278749+
},
278747278750
"ReservedConcurrentExecutions": {
278748278751
"allOf": [
278749278752
{
@@ -279123,6 +279126,9 @@
279123279126
"markdownDescription": "The provisioned concurrency configuration of a function's alias\\. \n`ProvisionedConcurrencyConfig` can be specified only if the `AutoPublishAlias` is set\\. Otherwise, an error results\\.\n*Type*: [ProvisionedConcurrencyConfig](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-alias.html#cfn-lambda-alias-provisionedconcurrencyconfig) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`ProvisionedConcurrencyConfig`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-alias.html#cfn-lambda-alias-provisionedconcurrencyconfig) property of an `AWS::Lambda::Alias` resource\\.",
279124279127
"title": "ProvisionedConcurrencyConfig"
279125279128
},
279129+
"RecursiveLoop": {
279130+
"$ref": "#/definitions/PassThroughProp"
279131+
},
279126279132
"ReservedConcurrentExecutions": {
279127279133
"allOf": [
279128279134
{

schema_source/sam.schema.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5439,6 +5439,9 @@
54395439
"markdownDescription": "The provisioned concurrency configuration of a function's alias\\. \n`ProvisionedConcurrencyConfig` can be specified only if the `AutoPublishAlias` is set\\. Otherwise, an error results\\.\n*Type*: [ProvisionedConcurrencyConfig](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-alias.html#cfn-lambda-alias-provisionedconcurrencyconfig) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`ProvisionedConcurrencyConfig`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-alias.html#cfn-lambda-alias-provisionedconcurrencyconfig) property of an `AWS::Lambda::Alias` resource\\.",
54405440
"title": "ProvisionedConcurrencyConfig"
54415441
},
5442+
"RecursiveLoop": {
5443+
"$ref": "#/definitions/PassThroughProp"
5444+
},
54425445
"ReservedConcurrentExecutions": {
54435446
"allOf": [
54445447
{
@@ -6009,6 +6012,9 @@
60096012
],
60106013
"title": "ProvisionedConcurrencyConfig"
60116014
},
6015+
"RecursiveLoop": {
6016+
"$ref": "#/definitions/PassThroughProp"
6017+
},
60126018
"ReservedConcurrentExecutions": {
60136019
"allOf": [
60146020
{
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Parameters:
2+
RecursiveLoopParam:
3+
Type: String
4+
Default: ALLOW
5+
6+
Resources:
7+
RecursiveLoopFunction:
8+
Type: AWS::Serverless::Function
9+
Properties:
10+
CodeUri: s3://sam-demo-bucket/hello.zip
11+
Handler: hello.handler
12+
Runtime: python3.9
13+
RecursiveLoop: TERMINATE
14+
15+
RecursiveLoopParameterFunction:
16+
Type: AWS::Serverless::Function
17+
Properties:
18+
CodeUri: s3://sam-demo-bucket/hello.zip
19+
Handler: hello.handler
20+
Runtime: python3.9
21+
RecursiveLoop: !Ref RecursiveLoopParam

tests/translator/input/globals_for_function.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Globals:
3232
UpdateRuntimeOn: Auto
3333
LoggingConfig:
3434
LogGroup: myJsonStructuredLogs
35+
RecursiveLoop: ALLOW
3536

3637

3738

@@ -65,3 +66,4 @@ Resources:
6566
ReservedConcurrentExecutions: 100
6667
RuntimeManagementConfig:
6768
UpdateRuntimeOn: FunctionChange
69+
RecursiveLoop: TERMINATE
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
{
2+
"Parameters": {
3+
"RecursiveLoopParam": {
4+
"Default": "ALLOW",
5+
"Type": "String"
6+
}
7+
},
8+
"Resources": {
9+
"RecursiveLoopFunction": {
10+
"Properties": {
11+
"Code": {
12+
"S3Bucket": "sam-demo-bucket",
13+
"S3Key": "hello.zip"
14+
},
15+
"Handler": "hello.handler",
16+
"RecursiveLoop": "TERMINATE",
17+
"Role": {
18+
"Fn::GetAtt": [
19+
"RecursiveLoopFunctionRole",
20+
"Arn"
21+
]
22+
},
23+
"Runtime": "python3.9",
24+
"Tags": [
25+
{
26+
"Key": "lambda:createdBy",
27+
"Value": "SAM"
28+
}
29+
]
30+
},
31+
"Type": "AWS::Lambda::Function"
32+
},
33+
"RecursiveLoopFunctionRole": {
34+
"Properties": {
35+
"AssumeRolePolicyDocument": {
36+
"Statement": [
37+
{
38+
"Action": [
39+
"sts:AssumeRole"
40+
],
41+
"Effect": "Allow",
42+
"Principal": {
43+
"Service": [
44+
"lambda.amazonaws.com"
45+
]
46+
}
47+
}
48+
],
49+
"Version": "2012-10-17"
50+
},
51+
"ManagedPolicyArns": [
52+
"arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
53+
],
54+
"Tags": [
55+
{
56+
"Key": "lambda:createdBy",
57+
"Value": "SAM"
58+
}
59+
]
60+
},
61+
"Type": "AWS::IAM::Role"
62+
},
63+
"RecursiveLoopParameterFunction": {
64+
"Properties": {
65+
"Code": {
66+
"S3Bucket": "sam-demo-bucket",
67+
"S3Key": "hello.zip"
68+
},
69+
"Handler": "hello.handler",
70+
"RecursiveLoop": {
71+
"Ref": "RecursiveLoopParam"
72+
},
73+
"Role": {
74+
"Fn::GetAtt": [
75+
"RecursiveLoopParameterFunctionRole",
76+
"Arn"
77+
]
78+
},
79+
"Runtime": "python3.9",
80+
"Tags": [
81+
{
82+
"Key": "lambda:createdBy",
83+
"Value": "SAM"
84+
}
85+
]
86+
},
87+
"Type": "AWS::Lambda::Function"
88+
},
89+
"RecursiveLoopParameterFunctionRole": {
90+
"Properties": {
91+
"AssumeRolePolicyDocument": {
92+
"Statement": [
93+
{
94+
"Action": [
95+
"sts:AssumeRole"
96+
],
97+
"Effect": "Allow",
98+
"Principal": {
99+
"Service": [
100+
"lambda.amazonaws.com"
101+
]
102+
}
103+
}
104+
],
105+
"Version": "2012-10-17"
106+
},
107+
"ManagedPolicyArns": [
108+
"arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
109+
],
110+
"Tags": [
111+
{
112+
"Key": "lambda:createdBy",
113+
"Value": "SAM"
114+
}
115+
]
116+
},
117+
"Type": "AWS::IAM::Role"
118+
}
119+
}
120+
}

0 commit comments

Comments
 (0)