Skip to content

Commit de9673e

Browse files
authored
feat: scaffolding for improved pass-throughs in schema (#3055)
1 parent 8814f6a commit de9673e

File tree

6 files changed

+78
-59
lines changed

6 files changed

+78
-59
lines changed

samtranslator/internal/schema_source/aws_serverless_function.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
ResourceAttributes,
1414
SamIntrinsicable,
1515
get_prop,
16+
passthrough_prop,
1617
)
1718

1819
alexaskilleventproperties = get_prop("sam-property-function-alexaskill")
@@ -501,8 +502,8 @@ class Properties(BaseModel):
501502
DeadLetterQueue: Optional[DeadLetterQueueType] = prop("DeadLetterQueue")
502503
DeploymentPreference: Optional[DeploymentPreference] = prop("DeploymentPreference")
503504
Description: Optional[Description] = prop("Description")
504-
Environment: Optional[Environment] = prop("Environment")
505-
EphemeralStorage: Optional[EphemeralStorage] = prop("EphemeralStorage")
505+
Environment: Optional[Environment] = passthrough_prop("AWS::Lambda::Function", "Environment")
506+
EphemeralStorage: Optional[EphemeralStorage] = passthrough_prop("AWS::Lambda::Function", "EphemeralStorage")
506507
EventInvokeConfig: Optional[EventInvokeConfig] = prop("EventInvokeConfig")
507508
Events: Optional[
508509
Dict[
@@ -531,7 +532,7 @@ class Properties(BaseModel):
531532
]
532533
] = prop("Events")
533534
FileSystemConfigs: Optional[PassThroughProp] = prop("FileSystemConfigs")
534-
FunctionName: Optional[PassThroughProp] = prop("FunctionName")
535+
FunctionName: Optional[PassThroughProp] = passthrough_prop("AWS::Lambda::Function", "FunctionName")
535536
FunctionUrlConfig: Optional[FunctionUrlConfig] = prop("FunctionUrlConfig")
536537
Handler: Optional[Handler] = prop("Handler")
537538
ImageConfig: Optional[PassThroughProp] = prop("ImageConfig")
@@ -566,7 +567,7 @@ class Globals(BaseModel):
566567
MemorySize: Optional[MemorySize] = prop("MemorySize")
567568
Timeout: Optional[Timeout] = prop("Timeout")
568569
VpcConfig: Optional[VpcConfig] = prop("VpcConfig")
569-
Environment: Optional[Environment] = prop("Environment")
570+
Environment: Optional[Environment] = passthrough_prop("AWS::Lambda::Function", "Environment")
570571
Tags: Optional[Tags] = prop("Tags")
571572
Tracing: Optional[Tracing] = prop("Tracing")
572573
KmsKeyArn: Optional[KmsKeyArn] = prop("KmsKeyArn")
@@ -580,7 +581,7 @@ class Globals(BaseModel):
580581
AssumeRolePolicyDocument: Optional[AssumeRolePolicyDocument] = prop("AssumeRolePolicyDocument")
581582
EventInvokeConfig: Optional[EventInvokeConfig] = prop("EventInvokeConfig")
582583
Architectures: Optional[Architectures] = prop("Architectures")
583-
EphemeralStorage: Optional[EphemeralStorage] = prop("EphemeralStorage")
584+
EphemeralStorage: Optional[EphemeralStorage] = passthrough_prop("AWS::Lambda::Function", "EphemeralStorage")
584585
SnapStart: Optional[SnapStart] = prop("SnapStart")
585586
RuntimeManagementConfig: Optional[RuntimeManagementConfig] = prop("RuntimeManagementConfig")
586587

samtranslator/internal/schema_source/common.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,19 @@ def get_prop(stem: str) -> Any:
4040
return partial(_get_prop, stem)
4141

4242

43+
def passthrough_prop(resource_type: str, path: str) -> Any:
44+
"""
45+
Specifies a pass-through field, where resource_type is the CloudFormation
46+
resource type, and path is a `.`-delimitated path to the property.
47+
"""
48+
prop_path = f"definitions.{resource_type}.properties.Properties.properties.{path}"
49+
return Field(
50+
# We add a custom value to the schema containing the path to the pass-through
51+
# documentation; the dict containing the value is replaced in the final schema
52+
__samPassThroughPath=prop_path,
53+
)
54+
55+
4356
def _get_prop(stem: str, name: str) -> Any:
4457
docs = _DOCS["properties"][stem][name]
4558
return Field(

samtranslator/internal/schema_source/schema.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import argparse
44
import json
55
from pathlib import Path
6-
from typing import Any, Dict, Optional, Type, Union
6+
from typing import Any, Callable, Dict, Optional, Type, Union
77

88
import pydantic
99

@@ -79,6 +79,30 @@ def json_dumps(obj: Any) -> str:
7979
return json.dumps(obj, indent=2, sort_keys=True) + "\n"
8080

8181

82+
def _replace_in_dict(d: Dict[str, Any], keyword: str, replace: Callable[[Dict[str, Any]], Any]) -> Dict[str, Any]:
83+
"""
84+
Replace any dict containing keyword.
85+
86+
replace() takes the containing dict as input, and returns its replacement.
87+
"""
88+
if keyword in d:
89+
d = replace(d)
90+
for k, v in d.items():
91+
if isinstance(v, dict):
92+
d[k] = _replace_in_dict(v, keyword, replace)
93+
return d
94+
95+
96+
def _deep_get(d: Dict[str, Any], path: str) -> Dict[str, Any]:
97+
"""
98+
Returns value at path, where `.` in path delimitates the keys.
99+
"""
100+
keys = path.split(".")
101+
for k in keys:
102+
d = d[k]
103+
return d
104+
105+
82106
def _add_embedded_connectors(schema: Dict[str, Any]) -> None:
83107
"""
84108
Add embedded Connectors resource attribute to supported CloudFormation resources.
@@ -124,6 +148,13 @@ def extend_with_cfn_schema(sam_schema: Dict[str, Any], cfn_schema: Dict[str, Any
124148

125149
_add_embedded_connectors(sam_schema)
126150

151+
# Inject CloudFormation documentation to SAM pass-through properties
152+
_replace_in_dict(
153+
sam_schema,
154+
"__samPassThroughPath",
155+
lambda d: _deep_get(cfn_schema, d["__samPassThroughPath"]),
156+
)
157+
127158
# The unified schema should include all supported properties
128159
sam_schema["additionalProperties"] = False
129160

samtranslator/schema/schema.json

Lines changed: 11 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -200646,23 +200646,13 @@
200646200646
"title": "Description"
200647200647
},
200648200648
"Environment": {
200649-
"allOf": [
200650-
{
200651-
"$ref": "#/definitions/PassThroughProp"
200652-
}
200653-
],
200654-
"description": "The configuration for the runtime environment\\. \n*Type*: [Environment](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-environment.html) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`Environment`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-environment.html) property of an `AWS::Lambda::Function` resource\\.",
200655-
"markdownDescription": "The configuration for the runtime environment\\. \n*Type*: [Environment](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-environment.html) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`Environment`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-environment.html) property of an `AWS::Lambda::Function` resource\\.",
200649+
"$ref": "#/definitions/AWS::Lambda::Function.Environment",
200650+
"markdownDescription": "Environment variables that are accessible from function code during execution\\. \n*Required*: No \n*Type*: [Environment](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-environment.html) \n*Update requires*: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)",
200656200651
"title": "Environment"
200657200652
},
200658200653
"EphemeralStorage": {
200659-
"allOf": [
200660-
{
200661-
"$ref": "#/definitions/PassThroughProp"
200662-
}
200663-
],
200664-
"description": "An object that specifies the disk space, in MB, available to your Lambda function in `/tmp`\\. \nFor more information about this property, see [Lambda execution environment](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-context.html) in the *AWS Lambda Developer Guide*\\. \n*Type*: [EphemeralStorage](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-ephemeralstorage) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`EphemeralStorage`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-ephemeralstorage) property of an `AWS::Lambda::Function` resource\\.",
200665-
"markdownDescription": "An object that specifies the disk space, in MB, available to your Lambda function in `/tmp`\\. \nFor more information about this property, see [Lambda execution environment](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-context.html) in the *AWS Lambda Developer Guide*\\. \n*Type*: [EphemeralStorage](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-ephemeralstorage) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`EphemeralStorage`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-ephemeralstorage) property of an `AWS::Lambda::Function` resource\\.",
200654+
"$ref": "#/definitions/AWS::Lambda::Function.EphemeralStorage",
200655+
"markdownDescription": "The size of the function's `/tmp` directory in MB\\. The default value is 512, but it can be any whole number between 512 and 10,240 MB\\. \n*Required*: No \n*Type*: [EphemeralStorage](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-ephemeralstorage.html) \n*Update requires*: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)",
200666200656
"title": "EphemeralStorage"
200667200657
},
200668200658
"EventInvokeConfig": {
@@ -200943,23 +200933,13 @@
200943200933
"title": "Description"
200944200934
},
200945200935
"Environment": {
200946-
"allOf": [
200947-
{
200948-
"$ref": "#/definitions/PassThroughProp"
200949-
}
200950-
],
200951-
"description": "The configuration for the runtime environment\\. \n*Type*: [Environment](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-environment.html) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`Environment`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-environment.html) property of an `AWS::Lambda::Function` resource\\.",
200952-
"markdownDescription": "The configuration for the runtime environment\\. \n*Type*: [Environment](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-environment.html) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`Environment`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-environment.html) property of an `AWS::Lambda::Function` resource\\.",
200936+
"$ref": "#/definitions/AWS::Lambda::Function.Environment",
200937+
"markdownDescription": "Environment variables that are accessible from function code during execution\\. \n*Required*: No \n*Type*: [Environment](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-environment.html) \n*Update requires*: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)",
200953200938
"title": "Environment"
200954200939
},
200955200940
"EphemeralStorage": {
200956-
"allOf": [
200957-
{
200958-
"$ref": "#/definitions/PassThroughProp"
200959-
}
200960-
],
200961-
"description": "An object that specifies the disk space, in MB, available to your Lambda function in `/tmp`\\. \nFor more information about this property, see [Lambda execution environment](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-context.html) in the *AWS Lambda Developer Guide*\\. \n*Type*: [EphemeralStorage](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-ephemeralstorage) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`EphemeralStorage`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-ephemeralstorage) property of an `AWS::Lambda::Function` resource\\.",
200962-
"markdownDescription": "An object that specifies the disk space, in MB, available to your Lambda function in `/tmp`\\. \nFor more information about this property, see [Lambda execution environment](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-context.html) in the *AWS Lambda Developer Guide*\\. \n*Type*: [EphemeralStorage](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-ephemeralstorage) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`EphemeralStorage`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-ephemeralstorage) property of an `AWS::Lambda::Function` resource\\.",
200941+
"$ref": "#/definitions/AWS::Lambda::Function.EphemeralStorage",
200942+
"markdownDescription": "The size of the function's `/tmp` directory in MB\\. The default value is 512, but it can be any whole number between 512 and 10,240 MB\\. \n*Required*: No \n*Type*: [EphemeralStorage](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-ephemeralstorage.html) \n*Update requires*: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)",
200963200943
"title": "EphemeralStorage"
200964200944
},
200965200945
"EventInvokeConfig": {
@@ -201050,14 +201030,9 @@
201050201030
"title": "FileSystemConfigs"
201051201031
},
201052201032
"FunctionName": {
201053-
"allOf": [
201054-
{
201055-
"$ref": "#/definitions/PassThroughProp"
201056-
}
201057-
],
201058-
"description": "A name for the function\\. If you don't specify a name, a unique name is generated for you\\. \n*Type*: String \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`FunctionName`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-functionname) property of an `AWS::Lambda::Function` resource\\.",
201059-
"markdownDescription": "A name for the function\\. If you don't specify a name, a unique name is generated for you\\. \n*Type*: String \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`FunctionName`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-functionname) property of an `AWS::Lambda::Function` resource\\.",
201060-
"title": "FunctionName"
201033+
"markdownDescription": "The name of the Lambda function, up to 64 characters in length\\. If you don't specify a name, AWS CloudFormation generates one\\. \nIf you specify a name, you cannot perform updates that require replacement of this resource\\. You can perform updates that require no or some interruption\\. If you must replace the resource, specify a new name\\. \n*Required*: No \n*Type*: String \n*Update requires*: [Replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement)",
201034+
"title": "FunctionName",
201035+
"type": "string"
201061201036
},
201062201037
"FunctionUrlConfig": {
201063201038
"allOf": [

0 commit comments

Comments
 (0)