Skip to content

Commit

Permalink
feat: Attach connectors to source (#2772)
Browse files Browse the repository at this point in the history
Co-authored-by: Sam Liu <xinhol@amazon.com>
Co-authored-by: aws-sam-cli-bot <46753707+aws-sam-cli-bot@users.noreply.github.com>
Co-authored-by: _sam <3804518+aahung@users.noreply.github.com>
  • Loading branch information
4 people authored Jan 24, 2023
1 parent b4f9ea1 commit 96691c1
Show file tree
Hide file tree
Showing 56 changed files with 9,311 additions and 19 deletions.
1 change: 1 addition & 0 deletions integration/combination/test_connectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def tearDown(self):
("combination/connector_sqs_to_function",),
("combination/connector_sns_to_function_write",),
("combination/connector_table_to_function_read",),
("combination/embedded_connector",),
]
)
@retry_once
Expand Down
22 changes: 22 additions & 0 deletions integration/resources/expected/combination/embedded_connector.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[
{
"LogicalResourceId": "MyRole1",
"ResourceType": "AWS::IAM::Role"
},
{
"LogicalResourceId": "MyRole2",
"ResourceType": "AWS::IAM::Role"
},
{
"LogicalResourceId": "TriggerFunction",
"ResourceType": "AWS::Lambda::Function"
},
{
"LogicalResourceId": "MyFunction2",
"ResourceType": "AWS::Lambda::Function"
},
{
"LogicalResourceId": "TriggerFunctionMyConnectorPolicy",
"ResourceType": "AWS::IAM::ManagedPolicy"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
Resources:
MyRole1:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service: lambda.amazonaws.com
ManagedPolicyArns:
- !Sub arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

MyRole2:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service: lambda.amazonaws.com
ManagedPolicyArns:
- !Sub arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

TriggerFunction:
Type: AWS::Lambda::Function
Connectors:
MyConnector:
Properties:
Destination:
Id: MyFunction2
Permissions:
- Write
Properties:
Role: !GetAtt MyRole1.Arn
Runtime: nodejs14.x
Handler: index.handler
Code:
ZipFile: |
const AWS = require('aws-sdk');
exports.handler = async (event) => {
const params = {
FunctionName: process.env.FUNCTION_NAME,
InvocationType: 'RequestResponse',
Payload: '{}',
};
const lambda = new AWS.Lambda();
const response = await lambda.invoke(params).promise();
if(response.StatusCode !== 200){
throw new Error('Failed to get response from lambda function')
}
return response;
};
Environment:
Variables:
FUNCTION_NAME: !Ref MyFunction2

MyFunction2:
Type: AWS::Lambda::Function
Properties:
Role: !GetAtt MyRole2.Arn
Runtime: nodejs14.x
Handler: index.handler
Code:
ZipFile: |
const AWS = require('aws-sdk');
exports.handler = async (event) => {
console.log(JSON.stringify(event));
};
Metadata:
SamTransformTest: true
2 changes: 1 addition & 1 deletion samtranslator/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def get_pass_through_attributes(cls) -> Tuple[str, ...]:
return tuple(cls._pass_through_attributes)

@classmethod
def from_dict(cls, logical_id, resource_dict, relative_id=None, sam_plugins=None): # type: ignore[no-untyped-def]
def from_dict(cls, logical_id: str, resource_dict: Dict[str, Any], relative_id: Optional[str] = None, sam_plugins=None) -> "Resource": # type: ignore[no-untyped-def]
"""Constructs a Resource object with the given logical id, based on the given resource dict. The resource dict
is the value associated with the logical id in a CloudFormation template's Resources section, and takes the
following format. ::
Expand Down
1 change: 1 addition & 0 deletions samtranslator/model/connector/connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ def get_event_source_mappings(

def _is_valid_resource_reference(obj: Dict[str, Any]) -> bool:
id_provided = "Id" in obj
# Every property in ResourceReference can be implied using 'Id', except for 'Qualifier', so users should be able to combine 'Id' and 'Qualifier'
non_id_provided = len([k for k in obj.keys() if k not in ["Id", "Qualifier"]]) > 0
# Must provide Id (with optional Qualifier) or a supported combination of other properties.
return id_provided != non_id_provided
Expand Down
4 changes: 2 additions & 2 deletions samtranslator/model/eventsources/push.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def]
# The de-dupe happens inside `samtranslator.translator.Translator.translate` method when merging results of
# to_cloudformation() to output template.
self._inject_notification_configuration(function, bucket, bucket_id) # type: ignore[no-untyped-call]
resources.append(S3Bucket.from_dict(bucket_id, bucket)) # type: ignore[no-untyped-call]
resources.append(S3Bucket.from_dict(bucket_id, bucket))

return resources

Expand Down Expand Up @@ -1142,7 +1142,7 @@ def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def]
resources.append(lambda_permission)

self._inject_lambda_config(function, userpool) # type: ignore[no-untyped-call]
resources.append(CognitoUserPool.from_dict(userpool_id, userpool)) # type: ignore[no-untyped-call]
resources.append(CognitoUserPool.from_dict(userpool_id, userpool))
return resources

def _inject_lambda_config(self, function, userpool): # type: ignore[no-untyped-def]
Expand Down
2 changes: 1 addition & 1 deletion samtranslator/plugins/globals/globals.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict, List
from typing import Any, Dict, List

from samtranslator.model.exceptions import ExceptionWithMessage
from samtranslator.public.sdk.resource import SamResourceType
Expand Down
10 changes: 9 additions & 1 deletion samtranslator/schema/aws_serverless_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@

from typing_extensions import Literal

from samtranslator.schema.common import PassThroughProp, BaseModel, SamIntrinsicable, get_prop, DictStrAny
from samtranslator.schema.common import (
PassThroughProp,
BaseModel,
SamIntrinsicable,
get_prop,
DictStrAny,
)
from samtranslator.schema.aws_serverless_connector import EmbeddedConnector

resourcepolicy = get_prop("sam-property-api-resourcepolicystatement")
cognitoauthorizeridentity = get_prop("sam-property-api-cognitoauthorizationidentity")
Expand Down Expand Up @@ -217,6 +224,7 @@ class Resource(BaseModel):
Properties: Properties
Condition: Optional[PassThroughProp]
DeletionPolicy: Optional[PassThroughProp]
Connectors: Optional[Dict[str, EmbeddedConnector]]
UpdatePolicy: Optional[PassThroughProp]
UpdateReplacePolicy: Optional[PassThroughProp]
DependsOn: Optional[PassThroughProp]
Expand Down
23 changes: 22 additions & 1 deletion samtranslator/schema/aws_serverless_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
resourcereference = get_prop("sam-property-connector-resourcereference")
properties = get_prop("sam-resource-connector")

PermissionsType = List[Literal["Read", "Write"]]


class ResourceReference(BaseModel):
Id: Optional[str] = resourcereference("Id")
Expand All @@ -22,9 +24,28 @@ class ResourceReference(BaseModel):
class Properties(BaseModel):
Source: ResourceReference = properties("Source")
Destination: ResourceReference = properties("Destination")
Permissions: List[Literal["Read", "Write"]] = properties("Permissions")
Permissions: PermissionsType = properties("Permissions")


class Resource(BaseModel):
Type: Literal["AWS::Serverless::Connector"]
Properties: Properties


class SourceReference(BaseModel):
Qualifier: Optional[PassThroughProp] = resourcereference("Qualifier")


class EmbeddedConnectorProperties(BaseModel):
SourceReference: Optional[SourceReference] # TODO: add docs for SourceReference
Destination: ResourceReference = properties("Destination")
Permissions: PermissionsType = properties("Permissions")


# TODO make connectors a part of all CFN Resources
class EmbeddedConnector(BaseModel):
Properties: EmbeddedConnectorProperties
DependsOn: Optional[PassThroughProp]
DeletionPolicy: Optional[PassThroughProp]
Metadata: Optional[PassThroughProp]
UpdatePolicy: Optional[PassThroughProp]
11 changes: 10 additions & 1 deletion samtranslator/schema/aws_serverless_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@

from typing_extensions import Literal

from samtranslator.schema.common import PassThroughProp, BaseModel, SamIntrinsicable, get_prop, DictStrAny, Ref
from samtranslator.schema.common import (
PassThroughProp,
BaseModel,
SamIntrinsicable,
get_prop,
DictStrAny,
Ref,
)
from samtranslator.schema.aws_serverless_connector import EmbeddedConnector


alexaskilleventproperties = get_prop("sam-property-function-alexaskill")
Expand Down Expand Up @@ -547,6 +555,7 @@ class Globals(BaseModel):
class Resource(BaseModel):
Type: Literal["AWS::Serverless::Function"]
Properties: Optional[Properties]
Connectors: Optional[Dict[str, EmbeddedConnector]]
DeletionPolicy: Optional[PassThroughProp]
UpdateReplacePolicy: Optional[PassThroughProp]
Condition: Optional[PassThroughProp]
Expand Down
10 changes: 9 additions & 1 deletion samtranslator/schema/aws_serverless_httpapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@

from typing_extensions import Literal

from samtranslator.schema.common import PassThroughProp, BaseModel, SamIntrinsicable, get_prop, DictStrAny
from samtranslator.schema.common import (
PassThroughProp,
BaseModel,
SamIntrinsicable,
get_prop,
DictStrAny,
)
from samtranslator.schema.aws_serverless_connector import EmbeddedConnector

oauth2authorizer = get_prop("sam-property-httpapi-oauth2authorizer")
lambdauthorizeridentity = get_prop("sam-property-httpapi-lambdaauthorizationidentity")
Expand Down Expand Up @@ -136,3 +143,4 @@ class Resource(BaseModel):
Properties: Optional[Properties]
Metadata: Optional[PassThroughProp]
Condition: Optional[PassThroughProp]
Connectors: Optional[Dict[str, EmbeddedConnector]]
2 changes: 2 additions & 0 deletions samtranslator/schema/aws_serverless_simpletable.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing_extensions import Literal

from samtranslator.schema.common import PassThroughProp, BaseModel, get_prop
from samtranslator.schema.aws_serverless_connector import EmbeddedConnector

primarykey = get_prop("sam-property-simpletable-primarykeyobject")
properties = get_prop("sam-resource-simpletable")
Expand Down Expand Up @@ -33,3 +34,4 @@ class Globals(BaseModel):
class Resource(BaseModel):
Type: Literal["AWS::Serverless::SimpleTable"]
Properties: Optional[Properties]
Connectors: Optional[Dict[str, EmbeddedConnector]]
10 changes: 9 additions & 1 deletion samtranslator/schema/aws_serverless_statemachine.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@

from typing_extensions import Literal

from samtranslator.schema.common import PassThroughProp, BaseModel, SamIntrinsicable, DictStrAny, get_prop
from samtranslator.schema.common import (
PassThroughProp,
BaseModel,
SamIntrinsicable,
DictStrAny,
get_prop,
)
from samtranslator.schema.aws_serverless_connector import EmbeddedConnector

properties = get_prop("sam-resource-statemachine")
deadletterconfig = get_prop("sam-property-statemachine-statemachinedeadletterconfig")
Expand Down Expand Up @@ -165,3 +172,4 @@ class Resource(BaseModel):
Type: Literal["AWS::Serverless::StateMachine"]
Properties: Properties
Condition: Optional[PassThroughProp]
Connectors: Optional[Dict[str, EmbeddedConnector]]
1 change: 0 additions & 1 deletion samtranslator/schema/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from pathlib import Path
from typing import Any, Dict, Optional, Union, TypeVar
from functools import partial

import pydantic
from pydantic import Extra, Field

Expand Down
Loading

0 comments on commit 96691c1

Please sign in to comment.