Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: improve schema pass-through handling #3056

Merged
merged 14 commits into from
Mar 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 39 additions & 6 deletions samtranslator/internal/schema_source/aws_serverless_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
passthrough_prop,
)

PROPERTIES_STEM = "sam-resource-function"

alexaskilleventproperties = get_prop("sam-property-function-alexaskill")
apiauth = get_prop("sam-property-function-apifunctionauth")
apieventproperties = get_prop("sam-property-function-api")
Expand Down Expand Up @@ -502,8 +504,19 @@ class Properties(BaseModel):
DeadLetterQueue: Optional[DeadLetterQueueType] = prop("DeadLetterQueue")
DeploymentPreference: Optional[DeploymentPreference] = prop("DeploymentPreference")
Description: Optional[Description] = prop("Description")
Environment: Optional[Environment] = passthrough_prop("AWS::Lambda::Function", "Environment")
EphemeralStorage: Optional[EphemeralStorage] = passthrough_prop("AWS::Lambda::Function", "EphemeralStorage")
# TODO: Make the notation shorter; resource type and SAM/CFN property names usually same
Environment: Optional[Environment] = passthrough_prop(
PROPERTIES_STEM,
"Environment",
"AWS::Lambda::Function",
"Environment",
)
EphemeralStorage: Optional[EphemeralStorage] = passthrough_prop(
PROPERTIES_STEM,
"EphemeralStorage",
"AWS::Lambda::Function",
"EphemeralStorage",
)
EventInvokeConfig: Optional[EventInvokeConfig] = prop("EventInvokeConfig")
Events: Optional[
Dict[
Expand Down Expand Up @@ -532,7 +545,12 @@ class Properties(BaseModel):
]
] = prop("Events")
FileSystemConfigs: Optional[PassThroughProp] = prop("FileSystemConfigs")
FunctionName: Optional[PassThroughProp] = passthrough_prop("AWS::Lambda::Function", "FunctionName")
FunctionName: Optional[PassThroughProp] = passthrough_prop(
PROPERTIES_STEM,
"FunctionName",
"AWS::Lambda::Function",
"FunctionName",
)
FunctionUrlConfig: Optional[FunctionUrlConfig] = prop("FunctionUrlConfig")
Handler: Optional[Handler] = prop("Handler")
ImageConfig: Optional[PassThroughProp] = prop("ImageConfig")
Expand All @@ -545,7 +563,12 @@ class Properties(BaseModel):
RolePath: Optional[RolePath] = prop("RolePath")
PermissionsBoundary: Optional[PermissionsBoundary] = prop("PermissionsBoundary")
Policies: Optional[Union[str, DictStrAny, List[Union[str, DictStrAny]]]] = prop("Policies")
ProvisionedConcurrencyConfig: Optional[ProvisionedConcurrencyConfig] = prop("ProvisionedConcurrencyConfig")
ProvisionedConcurrencyConfig: Optional[ProvisionedConcurrencyConfig] = passthrough_prop(
PROPERTIES_STEM,
"ProvisionedConcurrencyConfig",
"AWS::Lambda::Alias",
"ProvisionedConcurrencyConfig",
)
ReservedConcurrentExecutions: Optional[ReservedConcurrentExecutions] = prop("ReservedConcurrentExecutions")
Role: Optional[SamIntrinsicable[str]] = prop("Role")
Runtime: Optional[Runtime] = prop("Runtime")
Expand All @@ -567,7 +590,12 @@ class Globals(BaseModel):
MemorySize: Optional[MemorySize] = prop("MemorySize")
Timeout: Optional[Timeout] = prop("Timeout")
VpcConfig: Optional[VpcConfig] = prop("VpcConfig")
Environment: Optional[Environment] = passthrough_prop("AWS::Lambda::Function", "Environment")
Environment: Optional[Environment] = passthrough_prop(
PROPERTIES_STEM,
"Environment",
"AWS::Lambda::Function",
"Environment",
)
Tags: Optional[Tags] = prop("Tags")
Tracing: Optional[Tracing] = prop("Tracing")
KmsKeyArn: Optional[KmsKeyArn] = prop("KmsKeyArn")
Expand All @@ -581,7 +609,12 @@ class Globals(BaseModel):
AssumeRolePolicyDocument: Optional[AssumeRolePolicyDocument] = prop("AssumeRolePolicyDocument")
EventInvokeConfig: Optional[EventInvokeConfig] = prop("EventInvokeConfig")
Architectures: Optional[Architectures] = prop("Architectures")
EphemeralStorage: Optional[EphemeralStorage] = passthrough_prop("AWS::Lambda::Function", "EphemeralStorage")
EphemeralStorage: Optional[EphemeralStorage] = passthrough_prop(
PROPERTIES_STEM,
"EphemeralStorage",
"AWS::Lambda::Function",
"EphemeralStorage",
)
SnapStart: Optional[SnapStart] = prop("SnapStart")
RuntimeManagementConfig: Optional[RuntimeManagementConfig] = prop("RuntimeManagementConfig")

Expand Down
12 changes: 9 additions & 3 deletions samtranslator/internal/schema_source/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,22 @@ def get_prop(stem: str) -> Any:
return partial(_get_prop, stem)


def passthrough_prop(resource_type: str, path: str) -> Any:
def passthrough_prop(sam_docs_stem: str, sam_docs_name: str, resource_type: str, prop_path: str) -> Any:
"""
Specifies a pass-through field, where resource_type is the CloudFormation
resource type, and path is a `.`-delimitated path to the property.
"""
prop_path = f"definitions.{resource_type}.properties.Properties.properties.{path}"
prop_path = f"definitions.{resource_type}.properties.Properties.properties.{prop_path}"
docs = _DOCS["properties"][sam_docs_stem][sam_docs_name]
return Field(
# We add a custom value to the schema containing the path to the pass-through
# documentation; the dict containing the value is replaced in the final schema
__samPassThroughPath=prop_path,
__samPassThrough={
# To know at schema build-time where to find the property schema
"schemaPath": prop_path,
# Use SAM docs at the top-level pass-through; it can include useful SAM-specific information
"markdownDescriptionOverride": docs,
},
)


Expand Down
11 changes: 9 additions & 2 deletions samtranslator/internal/schema_source/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import argparse
import json
from copy import deepcopy
from pathlib import Path
from typing import Any, Callable, Dict, Optional, Type, Union

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

# Inject CloudFormation documentation to SAM pass-through properties
def replace_passthrough(d: Dict[str, Any]) -> Dict[str, Any]:
passthrough = d["__samPassThrough"]
schema = deepcopy(_deep_get(cfn_schema, passthrough["schemaPath"]))
schema["markdownDescription"] = passthrough["markdownDescriptionOverride"]
return schema

_replace_in_dict(
sam_schema,
"__samPassThroughPath",
lambda d: _deep_get(cfn_schema, d["__samPassThroughPath"]),
"__samPassThrough",
replace_passthrough,
)

# The unified schema should include all supported properties
Expand Down
17 changes: 6 additions & 11 deletions samtranslator/schema/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -200647,12 +200647,12 @@
},
"Environment": {
"$ref": "#/definitions/AWS::Lambda::Function.Environment",
"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)",
"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\\.",
"title": "Environment"
},
"EphemeralStorage": {
"$ref": "#/definitions/AWS::Lambda::Function.EphemeralStorage",
"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)",
"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\\.",
"title": "EphemeralStorage"
},
"EventInvokeConfig": {
Expand Down Expand Up @@ -200934,12 +200934,12 @@
},
"Environment": {
"$ref": "#/definitions/AWS::Lambda::Function.Environment",
"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)",
"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\\.",
"title": "Environment"
},
"EphemeralStorage": {
"$ref": "#/definitions/AWS::Lambda::Function.EphemeralStorage",
"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)",
"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\\.",
"title": "EphemeralStorage"
},
"EventInvokeConfig": {
Expand Down Expand Up @@ -201030,7 +201030,7 @@
"title": "FileSystemConfigs"
},
"FunctionName": {
"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)",
"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\\.",
"title": "FunctionName",
"type": "string"
},
Expand Down Expand Up @@ -201161,12 +201161,7 @@
"title": "Policies"
},
"ProvisionedConcurrencyConfig": {
"allOf": [
{
"$ref": "#/definitions/PassThroughProp"
}
],
"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\\.",
"$ref": "#/definitions/AWS::Lambda::Alias.ProvisionedConcurrencyConfiguration",
"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\\.",
"title": "ProvisionedConcurrencyConfig"
},
Expand Down
Loading