Skip to content
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
23 changes: 15 additions & 8 deletions samtranslator/model/connector/connector.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from collections import namedtuple
from typing import Any, Dict, Optional
from typing import Any, Dict, List, Optional

from samtranslator.model import ResourceResolver
from samtranslator.model.intrinsics import get_logical_id_from_intrinsic, ref, fnGetAtt
from samtranslator.utils.utils import as_array, insert_unique


# TODO: Switch to dataclass
Expand Down Expand Up @@ -31,10 +32,6 @@ def _is_nonblank_str(s: Any) -> bool:
return s and isinstance(s, str)


def _as_array(x: Any):
return x if isinstance(x, list) else [x]


def add_depends_on(logical_id: str, depends_on: str, resource_resolver: ResourceResolver):
"""
Add DependsOn attribute to resource.
Expand All @@ -43,13 +40,23 @@ def add_depends_on(logical_id: str, depends_on: str, resource_resolver: Resource
if not resource:
return

deps = _as_array(resource.get("DependsOn", []))
if depends_on not in deps:
deps.append(depends_on)
old_deps = resource.get("DependsOn", [])
deps = insert_unique(old_deps, depends_on)

resource["DependsOn"] = deps


def replace_depends_on_logical_id(logical_id: str, replacement: List[str], resource_resolver: ResourceResolver) -> None:
"""
For every resource's `DependsOn`, replace `logical_id` by `replacement`.
"""
for resource in resource_resolver.get_all_resources().values():
depends_on = as_array(resource.get("DependsOn", []))
if logical_id in depends_on:
depends_on.remove(logical_id)
resource["DependsOn"] = insert_unique(depends_on, replacement)


def get_event_source_mappings(event_source_id: str, function_id: str, resource_resolver: ResourceResolver):
"""
Get logical IDs of `AWS::Lambda::EventSourceMapping`s between resource logical IDs.
Expand Down
4 changes: 4 additions & 0 deletions samtranslator/model/sam_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
ConnectorResourceReference,
ConnectorResourceError,
add_depends_on,
replace_depends_on_logical_id,
get_event_source_mappings,
get_resource_reference,
)
Expand Down Expand Up @@ -1709,6 +1710,9 @@ def to_cloudformation(self, **kwargs) -> List:
self._construct_lambda_permission_policy(source, destination, profile_properties)
)

generated_logical_ids = [resource.logical_id for resource in generated_resources]
replace_depends_on_logical_id(self.logical_id, generated_logical_ids, resource_resolver)

self._add_connector_metadata(generated_resources, original_template, source, destination)
if generated_resources:
return generated_resources
Expand Down
23 changes: 23 additions & 0 deletions samtranslator/utils/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import copy
from typing import cast, Any, List


def as_array(x: Any) -> List[Any]:
"""Convert value to list if it already isn't."""
return x if isinstance(x, list) else [x]


def insert_unique(xs: Any, vs: Any) -> List[Any]:
"""
Return copy of `xs` extended with values of `vs` that do not exist in `xs`.
Inputs are converted to lists if they already aren't.
"""
xs = as_array(copy.deepcopy(xs))
vs = as_array(copy.deepcopy(vs))

for v in vs:
if v not in xs:
xs.append(v)

return cast(List[Any], xs) # mypy doesn't recognize it
2 changes: 1 addition & 1 deletion tests/translator/input/connector_bucket_to_function.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Resources:

Bucket:
# See also https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-notificationconfig.html
DependsOn: [MyConnectorWriteLambdaPermission]
DependsOn: MyConnector
Type: AWS::S3::Bucket
Properties:
BucketName: 'random-bucket-name'
Expand Down
84 changes: 84 additions & 0 deletions tests/translator/input/connector_dependson_replace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
Transform: AWS::Serverless-2016-10-31
Resources:
# Stub resources
SomeFunction:
Type: AWS::Lambda::Function
Properties:
Role: !Ref SomeRole
SomeTable:
Type: AWS::DynamoDB::Table
SomeTopic:
Type: AWS::SNS::Topic
SomeQueue:
Type: AWS::SQS::Queue
SomeRule:
Type: AWS::Events::Rule

# Test AWS_IAM_ROLE_MANAGED_POLICY
IamRolePolicyConnector:
Type: AWS::Serverless::Connector
Properties:
Source:
Id: SomeFunction
Destination:
Id: SomeTable
Permissions:
- Read
- Write
TestIamRolePolicyConnector:
DependsOn: IamRolePolicyConnector
Type: AWS::Foo::Bar
TestIamRolePolicyConnectorMulti:
DependsOn: [Foo, Egg, IamRolePolicyConnector]
Type: AWS::Foo::Bar

# Test AWS_SNS_TOPIC_POLICY
SnsTopicPolicyConnector:
Type: AWS::Serverless::Connector
Properties:
Source:
Id: SomeRule
Destination:
Id: SomeTopic
Permissions:
- Write
TestSnsTopicPolicyConnector:
DependsOn: SnsTopicPolicyConnector
Type: AWS::Foo::Bar
TestSnsTopicPolicyConnectorMulti:
DependsOn: [Foo, SnsTopicPolicyConnector]
Type: AWS::Foo::Bar

# Test AWS_LAMBDA_PERMISSION
LambdaPermissionConnector:
Type: AWS::Serverless::Connector
Properties:
Source:
Id: SomeTopic
Destination:
Id: SomeFunction
Permissions:
- Write
TestLambdaPermissionConnector:
DependsOn: LambdaPermissionConnector
Type: AWS::Foo::Bar
TestLambdaPermissionConnectorMulti:
DependsOn: [Foo, LambdaPermissionConnector, Bar]
Type: AWS::Foo::Bar

# Test AWS_SQS_QUEUE_POLICY
SqsQueuePolicyConnector:
Type: AWS::Serverless::Connector
Properties:
Source:
Id: SomeTopic
Destination:
Id: SomeQueue
Permissions:
- Write
TestSqsQueuePolicyConnector:
DependsOn: SqsQueuePolicyConnector
Type: AWS::Foo::Bar
TestSqsQueuePolicyConnectorMulti:
DependsOn: [SqsQueuePolicyConnector, Foo]
Type: AWS::Foo::Bar
Loading