Skip to content

Commit a28afd4

Browse files
authored
feat: improve schema pass-through handling (#3056)
1 parent de9673e commit a28afd4

File tree

9 files changed

+270
-30
lines changed

9 files changed

+270
-30
lines changed

samtranslator/internal/schema_source/aws_serverless_function.py

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
passthrough_prop,
1717
)
1818

19+
PROPERTIES_STEM = "sam-resource-function"
20+
1921
alexaskilleventproperties = get_prop("sam-property-function-alexaskill")
2022
apiauth = get_prop("sam-property-function-apifunctionauth")
2123
apieventproperties = get_prop("sam-property-function-api")
@@ -502,8 +504,19 @@ class Properties(BaseModel):
502504
DeadLetterQueue: Optional[DeadLetterQueueType] = prop("DeadLetterQueue")
503505
DeploymentPreference: Optional[DeploymentPreference] = prop("DeploymentPreference")
504506
Description: Optional[Description] = prop("Description")
505-
Environment: Optional[Environment] = passthrough_prop("AWS::Lambda::Function", "Environment")
506-
EphemeralStorage: Optional[EphemeralStorage] = passthrough_prop("AWS::Lambda::Function", "EphemeralStorage")
507+
# TODO: Make the notation shorter; resource type and SAM/CFN property names usually same
508+
Environment: Optional[Environment] = passthrough_prop(
509+
PROPERTIES_STEM,
510+
"Environment",
511+
"AWS::Lambda::Function",
512+
"Environment",
513+
)
514+
EphemeralStorage: Optional[EphemeralStorage] = passthrough_prop(
515+
PROPERTIES_STEM,
516+
"EphemeralStorage",
517+
"AWS::Lambda::Function",
518+
"EphemeralStorage",
519+
)
507520
EventInvokeConfig: Optional[EventInvokeConfig] = prop("EventInvokeConfig")
508521
Events: Optional[
509522
Dict[
@@ -532,7 +545,12 @@ class Properties(BaseModel):
532545
]
533546
] = prop("Events")
534547
FileSystemConfigs: Optional[PassThroughProp] = prop("FileSystemConfigs")
535-
FunctionName: Optional[PassThroughProp] = passthrough_prop("AWS::Lambda::Function", "FunctionName")
548+
FunctionName: Optional[PassThroughProp] = passthrough_prop(
549+
PROPERTIES_STEM,
550+
"FunctionName",
551+
"AWS::Lambda::Function",
552+
"FunctionName",
553+
)
536554
FunctionUrlConfig: Optional[FunctionUrlConfig] = prop("FunctionUrlConfig")
537555
Handler: Optional[Handler] = prop("Handler")
538556
ImageConfig: Optional[PassThroughProp] = prop("ImageConfig")
@@ -545,7 +563,12 @@ class Properties(BaseModel):
545563
RolePath: Optional[RolePath] = prop("RolePath")
546564
PermissionsBoundary: Optional[PermissionsBoundary] = prop("PermissionsBoundary")
547565
Policies: Optional[Union[str, DictStrAny, List[Union[str, DictStrAny]]]] = prop("Policies")
548-
ProvisionedConcurrencyConfig: Optional[ProvisionedConcurrencyConfig] = prop("ProvisionedConcurrencyConfig")
566+
ProvisionedConcurrencyConfig: Optional[ProvisionedConcurrencyConfig] = passthrough_prop(
567+
PROPERTIES_STEM,
568+
"ProvisionedConcurrencyConfig",
569+
"AWS::Lambda::Alias",
570+
"ProvisionedConcurrencyConfig",
571+
)
549572
ReservedConcurrentExecutions: Optional[ReservedConcurrentExecutions] = prop("ReservedConcurrentExecutions")
550573
Role: Optional[SamIntrinsicable[str]] = prop("Role")
551574
Runtime: Optional[Runtime] = prop("Runtime")
@@ -567,7 +590,12 @@ class Globals(BaseModel):
567590
MemorySize: Optional[MemorySize] = prop("MemorySize")
568591
Timeout: Optional[Timeout] = prop("Timeout")
569592
VpcConfig: Optional[VpcConfig] = prop("VpcConfig")
570-
Environment: Optional[Environment] = passthrough_prop("AWS::Lambda::Function", "Environment")
593+
Environment: Optional[Environment] = passthrough_prop(
594+
PROPERTIES_STEM,
595+
"Environment",
596+
"AWS::Lambda::Function",
597+
"Environment",
598+
)
571599
Tags: Optional[Tags] = prop("Tags")
572600
Tracing: Optional[Tracing] = prop("Tracing")
573601
KmsKeyArn: Optional[KmsKeyArn] = prop("KmsKeyArn")
@@ -581,7 +609,12 @@ class Globals(BaseModel):
581609
AssumeRolePolicyDocument: Optional[AssumeRolePolicyDocument] = prop("AssumeRolePolicyDocument")
582610
EventInvokeConfig: Optional[EventInvokeConfig] = prop("EventInvokeConfig")
583611
Architectures: Optional[Architectures] = prop("Architectures")
584-
EphemeralStorage: Optional[EphemeralStorage] = passthrough_prop("AWS::Lambda::Function", "EphemeralStorage")
612+
EphemeralStorage: Optional[EphemeralStorage] = passthrough_prop(
613+
PROPERTIES_STEM,
614+
"EphemeralStorage",
615+
"AWS::Lambda::Function",
616+
"EphemeralStorage",
617+
)
585618
SnapStart: Optional[SnapStart] = prop("SnapStart")
586619
RuntimeManagementConfig: Optional[RuntimeManagementConfig] = prop("RuntimeManagementConfig")
587620

samtranslator/internal/schema_source/common.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,22 @@ def get_prop(stem: str) -> Any:
4040
return partial(_get_prop, stem)
4141

4242

43-
def passthrough_prop(resource_type: str, path: str) -> Any:
43+
def passthrough_prop(sam_docs_stem: str, sam_docs_name: str, resource_type: str, prop_path: str) -> Any:
4444
"""
4545
Specifies a pass-through field, where resource_type is the CloudFormation
4646
resource type, and path is a `.`-delimitated path to the property.
4747
"""
48-
prop_path = f"definitions.{resource_type}.properties.Properties.properties.{path}"
48+
prop_path = f"definitions.{resource_type}.properties.Properties.properties.{prop_path}"
49+
docs = _DOCS["properties"][sam_docs_stem][sam_docs_name]
4950
return Field(
5051
# We add a custom value to the schema containing the path to the pass-through
5152
# documentation; the dict containing the value is replaced in the final schema
52-
__samPassThroughPath=prop_path,
53+
__samPassThrough={
54+
# To know at schema build-time where to find the property schema
55+
"schemaPath": prop_path,
56+
# Use SAM docs at the top-level pass-through; it can include useful SAM-specific information
57+
"markdownDescriptionOverride": docs,
58+
},
5359
)
5460

5561

samtranslator/internal/schema_source/schema.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import argparse
44
import json
5+
from copy import deepcopy
56
from pathlib import Path
67
from typing import Any, Callable, Dict, Optional, Type, Union
78

@@ -149,10 +150,16 @@ def extend_with_cfn_schema(sam_schema: Dict[str, Any], cfn_schema: Dict[str, Any
149150
_add_embedded_connectors(sam_schema)
150151

151152
# Inject CloudFormation documentation to SAM pass-through properties
153+
def replace_passthrough(d: Dict[str, Any]) -> Dict[str, Any]:
154+
passthrough = d["__samPassThrough"]
155+
schema = deepcopy(_deep_get(cfn_schema, passthrough["schemaPath"]))
156+
schema["markdownDescription"] = passthrough["markdownDescriptionOverride"]
157+
return schema
158+
152159
_replace_in_dict(
153160
sam_schema,
154-
"__samPassThroughPath",
155-
lambda d: _deep_get(cfn_schema, d["__samPassThroughPath"]),
161+
"__samPassThrough",
162+
replace_passthrough,
156163
)
157164

158165
# The unified schema should include all supported properties

samtranslator/schema/schema.json

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -200647,12 +200647,12 @@
200647200647
},
200648200648
"Environment": {
200649200649
"$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)",
200650+
"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\\.",
200651200651
"title": "Environment"
200652200652
},
200653200653
"EphemeralStorage": {
200654200654
"$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)",
200655+
"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\\.",
200656200656
"title": "EphemeralStorage"
200657200657
},
200658200658
"EventInvokeConfig": {
@@ -200934,12 +200934,12 @@
200934200934
},
200935200935
"Environment": {
200936200936
"$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)",
200937+
"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\\.",
200938200938
"title": "Environment"
200939200939
},
200940200940
"EphemeralStorage": {
200941200941
"$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)",
200942+
"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\\.",
200943200943
"title": "EphemeralStorage"
200944200944
},
200945200945
"EventInvokeConfig": {
@@ -201030,7 +201030,7 @@
201030201030
"title": "FileSystemConfigs"
201031201031
},
201032201032
"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)",
201033+
"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\\.",
201034201034
"title": "FunctionName",
201035201035
"type": "string"
201036201036
},
@@ -201161,12 +201161,7 @@
201161201161
"title": "Policies"
201162201162
},
201163201163
"ProvisionedConcurrencyConfig": {
201164-
"allOf": [
201165-
{
201166-
"$ref": "#/definitions/PassThroughProp"
201167-
}
201168-
],
201169-
"description": "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\\.",
201164+
"$ref": "#/definitions/AWS::Lambda::Alias.ProvisionedConcurrencyConfiguration",
201170201165
"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\\.",
201171201166
"title": "ProvisionedConcurrencyConfig"
201172201167
},

0 commit comments

Comments
 (0)