Skip to content

Commit be0ddc2

Browse files
authored
fix: Useful error message when "Properties" key is missing in embedded connectors (#2966)
1 parent b9d4f81 commit be0ddc2

File tree

3 files changed

+56
-32
lines changed

3 files changed

+56
-32
lines changed

samtranslator/translator/translator.py

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ def _get_embedded_connectors(self, resources: Dict[str, Any]) -> List[Resource]:
340340
generated_connector = self._get_generated_connector(
341341
source_logical_id,
342342
full_connector_logical_id,
343+
connector_logical_id,
343344
connector_dict,
344345
)
345346

@@ -354,40 +355,47 @@ def _get_embedded_connectors(self, resources: Dict[str, Any]) -> List[Resource]:
354355
return connectors
355356

356357
def _get_generated_connector(
357-
self, source_logical_id: str, connector_logical_id: str, connector_dict: Dict[str, Any]
358+
self,
359+
source_logical_id: str,
360+
full_connector_logical_id: str,
361+
connector_logical_id: str,
362+
connector_dict: Dict[str, Any],
358363
) -> Resource:
359364
"""
360365
Generates the connector resource from the embedded connector
361366
362367
:param str source_logical_id: Logical id of the resource the connector is attached to
363-
:param str connector_logical_id: Logical id of the connector
368+
:param str full_connector_logical_id: source_logical_id + connector_logical_id
369+
:param str connector_logical_id: Logical id of the connector defined by the user
364370
:param dict connector_dict: The properties of the connector including the Destination, Permissions and optionally the SourceReference
365371
:return: The generated SAMConnector resource
366372
"""
367373
connector = copy.deepcopy(connector_dict)
368374
connector["Type"] = SamConnector.resource_type
369375

370-
# No need to raise an error for this instance as the error will be caught by the parser
371-
if "Properties" in connector_dict and isinstance(connector_dict["Properties"], dict):
372-
properties = connector["Properties"]
373-
properties["Source"] = {"Id": source_logical_id}
374-
if "SourceReference" in properties:
375-
sam_expect(
376-
properties.get("SourceReference"),
377-
connector_logical_id,
378-
f"{connector_logical_id}.Properties.SourceReference",
379-
).to_be_a_map()
380-
381-
# can't allow user to override the Id using SourceReference
382-
if "Id" in properties["SourceReference"]:
383-
raise InvalidResourceException(
384-
connector_logical_id, "'Id' shouldn't be defined in 'SourceReference'."
385-
)
386-
387-
properties["Source"].update(properties["SourceReference"])
388-
del properties["SourceReference"]
389-
390-
return SamConnector.from_dict(connector_logical_id, connector)
376+
properties = sam_expect(
377+
connector.get("Properties"),
378+
source_logical_id,
379+
f"Connectors.{connector_logical_id}.Properties",
380+
is_resource_attribute=True,
381+
).to_be_a_map()
382+
383+
properties["Source"] = {"Id": source_logical_id}
384+
if "SourceReference" in properties:
385+
source_reference = sam_expect(
386+
properties.get("SourceReference"),
387+
source_logical_id,
388+
f"Connectors.{connector_logical_id}.Properties.SourceReference",
389+
).to_be_a_map()
390+
391+
# can't allow user to override the Id using SourceReference
392+
if "Id" in source_reference:
393+
raise InvalidResourceException(connector_logical_id, "'Id' shouldn't be defined in 'SourceReference'.")
394+
395+
properties["Source"].update(source_reference)
396+
del properties["SourceReference"]
397+
398+
return SamConnector.from_dict(full_connector_logical_id, connector)
391399

392400

393401
def prepare_plugins(plugins: Optional[List[BasePlugin]], parameters: Optional[Dict[str, Any]] = None) -> SamPlugins:

tests/translator/input/error_embedded_connectors.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ Resources:
1010
MyFunction:
1111
Type: AWS::Serverless::Function
1212
Connectors:
13+
NoProperties:
14+
Destination:
15+
Id: MyQueue
16+
Permissions:
17+
- Write
1318
NonDictProperties:
1419
Properties: foo
1520
EmptyProperties:
@@ -79,6 +84,13 @@ Resources:
7984
Id: MyQueue
8085
Permissions:
8186
- Write
87+
NonDictSourceReference:
88+
Properties:
89+
SourceReference: foo
90+
Destination:
91+
Id: MyQueue
92+
Permissions:
93+
- Write
8294
Properties:
8395
Runtime: python3.9
8496
InlineCode: foo
Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"_autoGeneratedBreakdownErrorMessage": [
33
"Invalid Serverless Application Specification document. ",
4-
"Number of errors found: 22. ",
4+
"Number of errors found: 24. ",
55
"Transforming resource with id [DuplicateTest] attempts to create a new resource with id [DuplicateTestDuplicateId] and type \"AWS::Serverless::Connector\". ",
66
"A resource with that id already exists within this template. ",
77
"Please use a different id for that resource. ",
@@ -11,6 +11,14 @@
1111
"Destination.Arn is missing. ",
1212
"Resource with id [EventsRuleMissingSqsQueueUrl] is invalid. ",
1313
"Unable to create connector from AWS::Events::Rule to AWS::SQS:Queue; it's not supported or the template is invalid. ",
14+
"Resource with id [MyFunction] is invalid. ",
15+
"Attribute 'Connectors.NoProperties.Properties' should be a map. ",
16+
"Resource with id [MyFunction] is invalid. ",
17+
"Attribute 'Connectors.NonDictProperties.Properties' should be a map. ",
18+
"Resource with id [MyFunction] is invalid. ",
19+
"Attribute 'Connectors.EmptyProperties.Properties' should be a map. ",
20+
"Resource with id [MyFunction] is invalid. ",
21+
"Property 'Connectors.NonDictSourceReference.Properties.SourceReference' should be a map. ",
1422
"Resource with id [MyFunctionBothIdAndOtherProps] is invalid. ",
1523
"Must provide 'Id' (with optional 'Qualifier') or a supported combination of other properties. ",
1624
"Resource with id [MyFunctionEmptyDestination] is invalid. ",
@@ -19,8 +27,6 @@
1927
"Missing required property 'Permissions'. ",
2028
"Resource with id [MyFunctionEmptyPermissionsList] is invalid. ",
2129
"'Permissions' cannot be empty; valid values are: Read, Write. ",
22-
"Resource with id [MyFunctionEmptyProperties] is invalid. ",
23-
"Properties of a resource must be an object. ",
2430
"Resource with id [MyFunctionMissingRoleMissingRole] is invalid. ",
2531
"Unable to get IAM role name from 'Source' resource. ",
2632
"Resource with id [MyFunctionNoDestination] is invalid. ",
@@ -33,20 +39,18 @@
3339
"Missing required property 'Permissions'. ",
3440
"Resource with id [MyFunctionNoStrId] is invalid. ",
3541
"'Id' is missing or not a string. ",
36-
"Resource with id [MyFunctionNonDictProperties] is invalid. ",
37-
"Properties of a resource must be an object. ",
3842
"Resource with id [MyFunctionNonExistentId] is invalid. ",
3943
"Unable to find resource with logical ID 'ThisDoesntExist'. ",
40-
"Resource with id [MyFunctionTestSourceReferenceId] is invalid. ",
41-
"'Id' shouldn't be defined in 'SourceReference'. ",
4244
"Resource with id [MyFunctionUnsupportedAccessCategory] is invalid. ",
4345
"Unsupported 'Permissions' provided for connector from AWS::Lambda::Function to AWS::SQS::Queue; valid values are: Read, Write. ",
4446
"Resource with id [MyQueueMissingRoleDestination] is invalid. ",
4547
"Unable to get IAM role name from 'Destination' resource. ",
4648
"Resource with id [MyQueueUnsupportedAccessCategoryCombination] is invalid. ",
4749
"Unsupported 'Permissions' provided for connector from AWS::SQS::Queue to AWS::Lambda::Function; valid combinations are: Read + Write. ",
4850
"Resource with id [MyResourceWithoutTypeResourceWithoutType] is invalid. ",
49-
"'Type' is missing or not a string."
51+
"'Type' is missing or not a string. ",
52+
"Resource with id [TestSourceReferenceId] is invalid. ",
53+
"'Id' shouldn't be defined in 'SourceReference'."
5054
],
51-
"errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 22. Transforming resource with id [DuplicateTest] attempts to create a new resource with id [DuplicateTestDuplicateId] and type \"AWS::Serverless::Connector\". A resource with that id already exists within this template. Please use a different id for that resource. Resource with id [EventsRuleMissingLambdaFunctionArn] is invalid. Unable to get Lambda function ARN from 'Destination' resource. Resource with id [EventsRuleMissingSnsTopicArn] is invalid. Destination.Arn is missing. Resource with id [EventsRuleMissingSqsQueueUrl] is invalid. Unable to create connector from AWS::Events::Rule to AWS::SQS:Queue; it's not supported or the template is invalid. Resource with id [MyFunctionBothIdAndOtherProps] is invalid. Must provide 'Id' (with optional 'Qualifier') or a supported combination of other properties. Resource with id [MyFunctionEmptyDestination] is invalid. Missing required property 'Destination'. Resource with id [MyFunctionEmptyPermissions] is invalid. Missing required property 'Permissions'. Resource with id [MyFunctionEmptyPermissionsList] is invalid. 'Permissions' cannot be empty; valid values are: Read, Write. Resource with id [MyFunctionEmptyProperties] is invalid. Properties of a resource must be an object. Resource with id [MyFunctionMissingRoleMissingRole] is invalid. Unable to get IAM role name from 'Source' resource. Resource with id [MyFunctionNoDestination] is invalid. Missing required property 'Destination'. Resource with id [MyFunctionNoDictConnectorNonDictConnector] is invalid. MyFunctionNoDictConnector.MyFunctionNoDictConnectorNonDictConnector should be a map. Resource with id [MyFunctionNoIdMissingType] is invalid. 'Type' is missing or not a string. Resource with id [MyFunctionNoPermissions] is invalid. Missing required property 'Permissions'. Resource with id [MyFunctionNoStrId] is invalid. 'Id' is missing or not a string. Resource with id [MyFunctionNonDictProperties] is invalid. Properties of a resource must be an object. Resource with id [MyFunctionNonExistentId] is invalid. Unable to find resource with logical ID 'ThisDoesntExist'. Resource with id [MyFunctionTestSourceReferenceId] is invalid. 'Id' shouldn't be defined in 'SourceReference'. Resource with id [MyFunctionUnsupportedAccessCategory] is invalid. Unsupported 'Permissions' provided for connector from AWS::Lambda::Function to AWS::SQS::Queue; valid values are: Read, Write. Resource with id [MyQueueMissingRoleDestination] is invalid. Unable to get IAM role name from 'Destination' resource. Resource with id [MyQueueUnsupportedAccessCategoryCombination] is invalid. Unsupported 'Permissions' provided for connector from AWS::SQS::Queue to AWS::Lambda::Function; valid combinations are: Read + Write. Resource with id [MyResourceWithoutTypeResourceWithoutType] is invalid. 'Type' is missing or not a string."
55+
"errorMessage": "Invalid Serverless Application Specification document. Number of errors found: 24. Transforming resource with id [DuplicateTest] attempts to create a new resource with id [DuplicateTestDuplicateId] and type \"AWS::Serverless::Connector\". A resource with that id already exists within this template. Please use a different id for that resource. Resource with id [EventsRuleMissingLambdaFunctionArn] is invalid. Unable to get Lambda function ARN from 'Destination' resource. Resource with id [EventsRuleMissingSnsTopicArn] is invalid. Destination.Arn is missing. Resource with id [EventsRuleMissingSqsQueueUrl] is invalid. Unable to create connector from AWS::Events::Rule to AWS::SQS:Queue; it's not supported or the template is invalid. Resource with id [MyFunction] is invalid. Attribute 'Connectors.NoProperties.Properties' should be a map. Resource with id [MyFunction] is invalid. Attribute 'Connectors.NonDictProperties.Properties' should be a map. Resource with id [MyFunction] is invalid. Attribute 'Connectors.EmptyProperties.Properties' should be a map. Resource with id [MyFunction] is invalid. Property 'Connectors.NonDictSourceReference.Properties.SourceReference' should be a map. Resource with id [MyFunctionBothIdAndOtherProps] is invalid. Must provide 'Id' (with optional 'Qualifier') or a supported combination of other properties. Resource with id [MyFunctionEmptyDestination] is invalid. Missing required property 'Destination'. Resource with id [MyFunctionEmptyPermissions] is invalid. Missing required property 'Permissions'. Resource with id [MyFunctionEmptyPermissionsList] is invalid. 'Permissions' cannot be empty; valid values are: Read, Write. Resource with id [MyFunctionMissingRoleMissingRole] is invalid. Unable to get IAM role name from 'Source' resource. Resource with id [MyFunctionNoDestination] is invalid. Missing required property 'Destination'. Resource with id [MyFunctionNoDictConnectorNonDictConnector] is invalid. MyFunctionNoDictConnector.MyFunctionNoDictConnectorNonDictConnector should be a map. Resource with id [MyFunctionNoIdMissingType] is invalid. 'Type' is missing or not a string. Resource with id [MyFunctionNoPermissions] is invalid. Missing required property 'Permissions'. Resource with id [MyFunctionNoStrId] is invalid. 'Id' is missing or not a string. Resource with id [MyFunctionNonExistentId] is invalid. Unable to find resource with logical ID 'ThisDoesntExist'. Resource with id [MyFunctionUnsupportedAccessCategory] is invalid. Unsupported 'Permissions' provided for connector from AWS::Lambda::Function to AWS::SQS::Queue; valid values are: Read, Write. Resource with id [MyQueueMissingRoleDestination] is invalid. Unable to get IAM role name from 'Destination' resource. Resource with id [MyQueueUnsupportedAccessCategoryCombination] is invalid. Unsupported 'Permissions' provided for connector from AWS::SQS::Queue to AWS::Lambda::Function; valid combinations are: Read + Write. Resource with id [MyResourceWithoutTypeResourceWithoutType] is invalid. 'Type' is missing or not a string. Resource with id [TestSourceReferenceId] is invalid. 'Id' shouldn't be defined in 'SourceReference'."
5256
}

0 commit comments

Comments
 (0)