From 61fdc2bc2ef68d468663dc6215d17b0ab520d3fd Mon Sep 17 00:00:00 2001 From: Slava Senchenko Date: Tue, 21 Mar 2023 15:09:10 -0700 Subject: [PATCH 1/9] appsync datasource to lambda connector --- integration/combination/test_connectors.py | 1 + .../connector_appsync_to_lambda.json | 46 +++++ .../connector_appsync_to_lambda.yaml | 188 ++++++++++++++++++ .../model/connector_profiles/profiles.json | 23 +++ .../input/connector_appsync_to_lambda.yaml | 60 ++++++ .../aws-cn/connector_appsync_to_lambda.json | 176 ++++++++++++++++ .../connector_appsync_to_lambda.json | 176 ++++++++++++++++ .../output/connector_appsync_to_lambda.json | 176 ++++++++++++++++ 8 files changed, 846 insertions(+) create mode 100644 integration/resources/expected/combination/connector_appsync_to_lambda.json create mode 100644 integration/resources/templates/combination/connector_appsync_to_lambda.yaml create mode 100644 tests/translator/input/connector_appsync_to_lambda.yaml create mode 100644 tests/translator/output/aws-cn/connector_appsync_to_lambda.json create mode 100644 tests/translator/output/aws-us-gov/connector_appsync_to_lambda.json create mode 100644 tests/translator/output/connector_appsync_to_lambda.json diff --git a/integration/combination/test_connectors.py b/integration/combination/test_connectors.py index 9ac1ad8b7..cfff9ff85 100644 --- a/integration/combination/test_connectors.py +++ b/integration/combination/test_connectors.py @@ -26,6 +26,7 @@ def tearDown(self): @parameterized.expand( [ + ("combination/connector_appsync_to_lambda",), ("combination/connector_appsync_to_table",), ("combination/connector_function_to_function",), ("combination/connector_restapi_to_function",), diff --git a/integration/resources/expected/combination/connector_appsync_to_lambda.json b/integration/resources/expected/combination/connector_appsync_to_lambda.json new file mode 100644 index 000000000..77169dc89 --- /dev/null +++ b/integration/resources/expected/combination/connector_appsync_to_lambda.json @@ -0,0 +1,46 @@ +[ + { + "LogicalResourceId": "HelloLambda", + "ResourceType": "AWS::Lambda::Function" + }, + { + "LogicalResourceId": "HelloLambdaRole", + "ResourceType": "AWS::IAM::Role" + }, + { + "LogicalResourceId": "AppSyncApi", + "ResourceType": "AWS::AppSync::GraphQLApi" + }, + { + "LogicalResourceId": "ApiKey", + "ResourceType": "AWS::AppSync::ApiKey" + }, + { + "LogicalResourceId": "ApiSchema", + "ResourceType": "AWS::AppSync::GraphQLSchema" + }, + { + "LogicalResourceId": "AppSyncLambdaDataSource", + "ResourceType": "AWS::AppSync::DataSource" + }, + { + "LogicalResourceId": "TriggerFunction", + "ResourceType": "AWS::Lambda::Function" + }, + { + "LogicalResourceId": "TriggerFunctionRole", + "ResourceType": "AWS::IAM::Role" + }, + { + "LogicalResourceId": "AppSyncApiLambdaInvocationRole", + "ResourceType": "AWS::IAM::Role" + }, + { + "LogicalResourceId": "DataSourceToLambdaConnectorPolicy", + "ResourceType": "AWS::IAM::ManagedPolicy" + }, + { + "LogicalResourceId": "AppSyncSayHelloResolver", + "ResourceType": "AWS::AppSync::Resolver" + } +] diff --git a/integration/resources/templates/combination/connector_appsync_to_lambda.yaml b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml new file mode 100644 index 000000000..ea2daa83c --- /dev/null +++ b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml @@ -0,0 +1,188 @@ +Resources: + AppSyncApiLambdaInvocationRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: appsync.amazonaws.com + Action: + - sts:AssumeRole + + HelloLambda: + Type: AWS::Serverless::Function + Properties: + InlineCode: | + exports.handler = async (_) => { + return "Hello World" + } + Handler: index.handler + Runtime: nodejs14.x + + AppSyncApi: + Type: AWS::AppSync::GraphQLApi + Properties: + AuthenticationType: API_KEY + Name: AppSyncApi + + ApiSchema: + Type: AWS::AppSync::GraphQLSchema + Properties: + ApiId: !GetAtt AppSyncApi.ApiId + Definition: | + type Query { + sayHello: String! + } + schema { + query: Query + } + + AppSyncLambdaDataSource: + Type: "AWS::AppSync::DataSource" + Properties: + ApiId: !GetAtt AppSyncApi.ApiId + Name: "AppSyncLambdaDataSource" + Type: "AWS_LAMBDA" + ServiceRoleArn: !GetAtt AppSyncApiLambdaInvocationRole.Arn + LambdaConfig: + LambdaFunctionArn: !GetAtt HelloLambda.Arn + + AppSyncSayHelloResolver: + Type: "AWS::AppSync::Resolver" + Properties: + ApiId: !GetAtt AppSyncApi.ApiId + TypeName: "Query" + FieldName: "sayHello" + DataSourceName: !GetAtt AppSyncLambdaDataSource.Name + RequestMappingTemplate: | + { + "version" : "2017-02-28", + "operation": "Invoke", + "payload": $util.toJson($context.args) + } + ResponseMappingTemplate: | + $util.toJson($context.result) + + DataSourceToLambdaConnector: + Type: AWS::Serverless::Connector + Properties: + Source: + Id: AppSyncLambdaDataSource + Destination: + Id: HelloLambda + Permissions: + - Write + + ApiKey: + Type: AWS::AppSync::ApiKey + Properties: + ApiId: !GetAtt AppSyncApi.ApiId + + TriggerFunction: + Type: AWS::Serverless::Function + Properties: + Environment: + Variables: + API_KEY: !GetAtt ApiKey.ApiKey + GRAPHQL_URL: !GetAtt AppSyncApi.GraphQLUrl + Runtime: nodejs14.x + Handler: index.handler + InlineCode: | + const https = require("https"); + + exports.handler = async (_) => { + const queries = { + sayHello: /* GraphQL */ ` + query { + sayHello + } + `, + }; + + const fetch = async (url, options) => + new Promise((resolve, reject) => { + const req = https.request(url, options, (res) => { + const body = []; + res.on("data", (chunk) => body.push(chunk)); + res.on("end", () => { + const resString = Buffer.concat(body).toString(); + resolve(resString); + }); + }); + + req.on("error", (err) => { + reject(err); + }); + + req.on("timeout", () => { + req.destroy(); + reject(new Error("Request time out")); + }); + + req.write(options.body); + req.end(); + }); + + const makeRequest = async (queryName) => { + const options = { + method: "POST", + headers: { + "x-api-key": process.env.API_KEY, + }, + body: JSON.stringify({ query: queries[queryName] }), + timeout: 10000, // ms + }; + + let statusCode; + let body; + let response; + + try { + response = await fetch(process.env.GRAPHQL_URL, options); + body = JSON.parse(response); + const data = body.data?.[queryName]; + const hasNoErrors = body.errors === undefined; + const allFieldsAreSet = + data?.Status === 200 && data?.Body === "Hello World"; + statusCode = hasNoErrors && allFieldsAreSet ? 200 : 400; + if (hasNoErrors) { + body = body.data; + } else { + body = { + [queryName]: { + errors: body.errors, + }, + }; + } + } catch (error) { + statusCode = 400; + body = { + [queryName]: { + errors: [ + { + status: response.status, + message: error.message, + stack: error.stack, + }, + ], + }, + }; + } + return { + statusCode, + body, + }; + }; + + let response = await makeRequest("sayHello"); + return { + StatusCode: response.statusCode, + Body: response.body, + }; + }; + + +Metadata: + SamTransformTest: true diff --git a/samtranslator/model/connector_profiles/profiles.json b/samtranslator/model/connector_profiles/profiles.json index 4960e0fa3..6d22ae63f 100644 --- a/samtranslator/model/connector_profiles/profiles.json +++ b/samtranslator/model/connector_profiles/profiles.json @@ -767,6 +767,29 @@ } } } + }, + "AWS::Lambda::Function": { + "Type": "AWS_IAM_ROLE_MANAGED_POLICY", + "Properties": { + "SourcePolicy": true, + "AccessCategories": { + "Write": { + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "lambda:InvokeAsync", + "lambda:InvokeFunction" + ], + "Resource": [ + "%{Destination.Arn}", + "%{Destination.Arn}:*" + ] + } + ] + } + } + } } } } diff --git a/tests/translator/input/connector_appsync_to_lambda.yaml b/tests/translator/input/connector_appsync_to_lambda.yaml new file mode 100644 index 000000000..e8c94bf29 --- /dev/null +++ b/tests/translator/input/connector_appsync_to_lambda.yaml @@ -0,0 +1,60 @@ +Resources: + AppSyncApiLambdaInvocationRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: appsync.amazonaws.com + Action: + - sts:AssumeRole + + HelloLambda: + Type: AWS::Serverless::Function + Properties: + InlineCode: | + exports.handler = async (_) => { + return "Hello World" + } + Handler: index.handler + Runtime: nodejs14.x + + AppSyncApi: + Type: AWS::AppSync::GraphQLApi + Properties: + AuthenticationType: API_KEY + Name: AppSyncApi + + ApiSchema: + Type: AWS::AppSync::GraphQLSchema + Properties: + ApiId: !GetAtt AppSyncApi.ApiId + Definition: | + type Query { + sayHello: String! + } + schema { + query: Query + } + + AppSyncLambdaDataSource: + Type: AWS::AppSync::DataSource + Properties: + ApiId: !GetAtt AppSyncApi.ApiId + Name: AppSyncLambdaDataSource + Type: AWS_LAMBDA + ServiceRoleArn: !GetAtt AppSyncApiLambdaInvocationRole.Arn + LambdaConfig: + LambdaFunctionArn: !GetAtt HelloLambda.Arn + + DataSourceToLambdaConnector: + Type: AWS::Serverless::Connector + Properties: + Source: + Id: AppSyncLambdaDataSource + Destination: + Id: HelloLambda + Permissions: + - Write diff --git a/tests/translator/output/aws-cn/connector_appsync_to_lambda.json b/tests/translator/output/aws-cn/connector_appsync_to_lambda.json new file mode 100644 index 000000000..5c87af6c1 --- /dev/null +++ b/tests/translator/output/aws-cn/connector_appsync_to_lambda.json @@ -0,0 +1,176 @@ +{ + "Resources": { + "ApiSchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "AppSyncApi", + "ApiId" + ] + }, + "Definition": "type Query {\n sayHello: String!\n}\nschema {\n query: Query\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + }, + "AppSyncApi": { + "Properties": { + "AuthenticationType": "API_KEY", + "Name": "AppSyncApi" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "AppSyncApiLambdaInvocationRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": "appsync.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "Type": "AWS::IAM::Role" + }, + "AppSyncLambdaDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "AppSyncApi", + "ApiId" + ] + }, + "LambdaConfig": { + "LambdaFunctionArn": { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + } + }, + "Name": "AppSyncLambdaDataSource", + "ServiceRoleArn": { + "Fn::GetAtt": [ + "AppSyncApiLambdaInvocationRole", + "Arn" + ] + }, + "Type": "AWS_LAMBDA" + }, + "Type": "AWS::AppSync::DataSource" + }, + "DataSourceToLambdaConnectorPolicy": { + "Metadata": { + "aws:sam:connectors": { + "DataSourceToLambdaConnector": { + "Destination": { + "Type": "AWS::Serverless::Function" + }, + "Source": { + "Type": "AWS::AppSync::DataSource" + } + } + } + }, + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "lambda:InvokeAsync", + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + }, + { + "Fn::Sub": [ + "${DestinationArn}:*", + { + "DestinationArn": { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + } + } + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "Roles": [ + { + "Ref": "AppSyncApiLambdaInvocationRole" + } + ] + }, + "Type": "AWS::IAM::ManagedPolicy" + }, + "HelloLambda": { + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (_) => {\n return \"Hello World\"\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "HelloLambdaRole", + "Arn" + ] + }, + "Runtime": "nodejs14.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "HelloLambdaRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-us-gov/connector_appsync_to_lambda.json b/tests/translator/output/aws-us-gov/connector_appsync_to_lambda.json new file mode 100644 index 000000000..b6b799b2f --- /dev/null +++ b/tests/translator/output/aws-us-gov/connector_appsync_to_lambda.json @@ -0,0 +1,176 @@ +{ + "Resources": { + "ApiSchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "AppSyncApi", + "ApiId" + ] + }, + "Definition": "type Query {\n sayHello: String!\n}\nschema {\n query: Query\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + }, + "AppSyncApi": { + "Properties": { + "AuthenticationType": "API_KEY", + "Name": "AppSyncApi" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "AppSyncApiLambdaInvocationRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": "appsync.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "Type": "AWS::IAM::Role" + }, + "AppSyncLambdaDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "AppSyncApi", + "ApiId" + ] + }, + "LambdaConfig": { + "LambdaFunctionArn": { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + } + }, + "Name": "AppSyncLambdaDataSource", + "ServiceRoleArn": { + "Fn::GetAtt": [ + "AppSyncApiLambdaInvocationRole", + "Arn" + ] + }, + "Type": "AWS_LAMBDA" + }, + "Type": "AWS::AppSync::DataSource" + }, + "DataSourceToLambdaConnectorPolicy": { + "Metadata": { + "aws:sam:connectors": { + "DataSourceToLambdaConnector": { + "Destination": { + "Type": "AWS::Serverless::Function" + }, + "Source": { + "Type": "AWS::AppSync::DataSource" + } + } + } + }, + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "lambda:InvokeAsync", + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + }, + { + "Fn::Sub": [ + "${DestinationArn}:*", + { + "DestinationArn": { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + } + } + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "Roles": [ + { + "Ref": "AppSyncApiLambdaInvocationRole" + } + ] + }, + "Type": "AWS::IAM::ManagedPolicy" + }, + "HelloLambda": { + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (_) => {\n return \"Hello World\"\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "HelloLambdaRole", + "Arn" + ] + }, + "Runtime": "nodejs14.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "HelloLambdaRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/connector_appsync_to_lambda.json b/tests/translator/output/connector_appsync_to_lambda.json new file mode 100644 index 000000000..3e0162c55 --- /dev/null +++ b/tests/translator/output/connector_appsync_to_lambda.json @@ -0,0 +1,176 @@ +{ + "Resources": { + "ApiSchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "AppSyncApi", + "ApiId" + ] + }, + "Definition": "type Query {\n sayHello: String!\n}\nschema {\n query: Query\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + }, + "AppSyncApi": { + "Properties": { + "AuthenticationType": "API_KEY", + "Name": "AppSyncApi" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "AppSyncApiLambdaInvocationRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": "appsync.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "Type": "AWS::IAM::Role" + }, + "AppSyncLambdaDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "AppSyncApi", + "ApiId" + ] + }, + "LambdaConfig": { + "LambdaFunctionArn": { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + } + }, + "Name": "AppSyncLambdaDataSource", + "ServiceRoleArn": { + "Fn::GetAtt": [ + "AppSyncApiLambdaInvocationRole", + "Arn" + ] + }, + "Type": "AWS_LAMBDA" + }, + "Type": "AWS::AppSync::DataSource" + }, + "DataSourceToLambdaConnectorPolicy": { + "Metadata": { + "aws:sam:connectors": { + "DataSourceToLambdaConnector": { + "Destination": { + "Type": "AWS::Serverless::Function" + }, + "Source": { + "Type": "AWS::AppSync::DataSource" + } + } + } + }, + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "lambda:InvokeAsync", + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + }, + { + "Fn::Sub": [ + "${DestinationArn}:*", + { + "DestinationArn": { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + } + } + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "Roles": [ + { + "Ref": "AppSyncApiLambdaInvocationRole" + } + ] + }, + "Type": "AWS::IAM::ManagedPolicy" + }, + "HelloLambda": { + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (_) => {\n return \"Hello World\"\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "HelloLambdaRole", + "Arn" + ] + }, + "Runtime": "nodejs14.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "HelloLambdaRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} From 1a2c996c3b8f41746c826e2b0f290623da281b38 Mon Sep 17 00:00:00 2001 From: Slava Senchenko Date: Tue, 21 Mar 2023 15:21:30 -0700 Subject: [PATCH 2/9] add depends on --- .../templates/combination/connector_appsync_to_lambda.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/integration/resources/templates/combination/connector_appsync_to_lambda.yaml b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml index ea2daa83c..2ca0bafea 100644 --- a/integration/resources/templates/combination/connector_appsync_to_lambda.yaml +++ b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml @@ -50,6 +50,7 @@ Resources: LambdaFunctionArn: !GetAtt HelloLambda.Arn AppSyncSayHelloResolver: + DependsOn: AppSyncSchema Type: "AWS::AppSync::Resolver" Properties: ApiId: !GetAtt AppSyncApi.ApiId From bfd9e668c2aaeaaffa42e28bc81eae95074ed3e2 Mon Sep 17 00:00:00 2001 From: Slava Senchenko Date: Tue, 21 Mar 2023 15:22:29 -0700 Subject: [PATCH 3/9] correct schema name --- .../templates/combination/connector_appsync_to_lambda.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/resources/templates/combination/connector_appsync_to_lambda.yaml b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml index 2ca0bafea..4058fc3f4 100644 --- a/integration/resources/templates/combination/connector_appsync_to_lambda.yaml +++ b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml @@ -50,7 +50,7 @@ Resources: LambdaFunctionArn: !GetAtt HelloLambda.Arn AppSyncSayHelloResolver: - DependsOn: AppSyncSchema + DependsOn: ApiSchema Type: "AWS::AppSync::Resolver" Properties: ApiId: !GetAtt AppSyncApi.ApiId From 48db64df215fd22886f34a64ecf64fd6e08ac17b Mon Sep 17 00:00:00 2001 From: Slava Senchenko Date: Tue, 21 Mar 2023 15:42:10 -0700 Subject: [PATCH 4/9] format --- .../connector_appsync_to_lambda.yaml | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/integration/resources/templates/combination/connector_appsync_to_lambda.yaml b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml index 4058fc3f4..d47b22322 100644 --- a/integration/resources/templates/combination/connector_appsync_to_lambda.yaml +++ b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml @@ -5,11 +5,11 @@ Resources: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - - Effect: Allow - Principal: - Service: appsync.amazonaws.com - Action: - - sts:AssumeRole + - Effect: Allow + Principal: + Service: appsync.amazonaws.com + Action: + - sts:AssumeRole HelloLambda: Type: AWS::Serverless::Function @@ -40,22 +40,22 @@ Resources: } AppSyncLambdaDataSource: - Type: "AWS::AppSync::DataSource" + Type: AWS::AppSync::DataSource Properties: ApiId: !GetAtt AppSyncApi.ApiId - Name: "AppSyncLambdaDataSource" - Type: "AWS_LAMBDA" + Name: AppSyncLambdaDataSource + Type: AWS_LAMBDA ServiceRoleArn: !GetAtt AppSyncApiLambdaInvocationRole.Arn LambdaConfig: LambdaFunctionArn: !GetAtt HelloLambda.Arn AppSyncSayHelloResolver: DependsOn: ApiSchema - Type: "AWS::AppSync::Resolver" + Type: AWS::AppSync::Resolver Properties: ApiId: !GetAtt AppSyncApi.ApiId - TypeName: "Query" - FieldName: "sayHello" + TypeName: Query + FieldName: sayHello DataSourceName: !GetAtt AppSyncLambdaDataSource.Name RequestMappingTemplate: | { From 98dc76903b669714b10a962a7719dfe86d943b24 Mon Sep 17 00:00:00 2001 From: Slava Senchenko Date: Tue, 21 Mar 2023 15:09:10 -0700 Subject: [PATCH 5/9] appsync datasource to lambda connector --- integration/combination/test_connectors.py | 1 + .../connector_appsync_to_lambda.json | 46 +++++ .../connector_appsync_to_lambda.yaml | 188 ++++++++++++++++++ .../model/connector_profiles/profiles.json | 23 +++ .../input/connector_appsync_to_lambda.yaml | 60 ++++++ .../aws-cn/connector_appsync_to_lambda.json | 176 ++++++++++++++++ .../connector_appsync_to_lambda.json | 176 ++++++++++++++++ .../output/connector_appsync_to_lambda.json | 176 ++++++++++++++++ 8 files changed, 846 insertions(+) create mode 100644 integration/resources/expected/combination/connector_appsync_to_lambda.json create mode 100644 integration/resources/templates/combination/connector_appsync_to_lambda.yaml create mode 100644 tests/translator/input/connector_appsync_to_lambda.yaml create mode 100644 tests/translator/output/aws-cn/connector_appsync_to_lambda.json create mode 100644 tests/translator/output/aws-us-gov/connector_appsync_to_lambda.json create mode 100644 tests/translator/output/connector_appsync_to_lambda.json diff --git a/integration/combination/test_connectors.py b/integration/combination/test_connectors.py index 9ac1ad8b7..cfff9ff85 100644 --- a/integration/combination/test_connectors.py +++ b/integration/combination/test_connectors.py @@ -26,6 +26,7 @@ def tearDown(self): @parameterized.expand( [ + ("combination/connector_appsync_to_lambda",), ("combination/connector_appsync_to_table",), ("combination/connector_function_to_function",), ("combination/connector_restapi_to_function",), diff --git a/integration/resources/expected/combination/connector_appsync_to_lambda.json b/integration/resources/expected/combination/connector_appsync_to_lambda.json new file mode 100644 index 000000000..77169dc89 --- /dev/null +++ b/integration/resources/expected/combination/connector_appsync_to_lambda.json @@ -0,0 +1,46 @@ +[ + { + "LogicalResourceId": "HelloLambda", + "ResourceType": "AWS::Lambda::Function" + }, + { + "LogicalResourceId": "HelloLambdaRole", + "ResourceType": "AWS::IAM::Role" + }, + { + "LogicalResourceId": "AppSyncApi", + "ResourceType": "AWS::AppSync::GraphQLApi" + }, + { + "LogicalResourceId": "ApiKey", + "ResourceType": "AWS::AppSync::ApiKey" + }, + { + "LogicalResourceId": "ApiSchema", + "ResourceType": "AWS::AppSync::GraphQLSchema" + }, + { + "LogicalResourceId": "AppSyncLambdaDataSource", + "ResourceType": "AWS::AppSync::DataSource" + }, + { + "LogicalResourceId": "TriggerFunction", + "ResourceType": "AWS::Lambda::Function" + }, + { + "LogicalResourceId": "TriggerFunctionRole", + "ResourceType": "AWS::IAM::Role" + }, + { + "LogicalResourceId": "AppSyncApiLambdaInvocationRole", + "ResourceType": "AWS::IAM::Role" + }, + { + "LogicalResourceId": "DataSourceToLambdaConnectorPolicy", + "ResourceType": "AWS::IAM::ManagedPolicy" + }, + { + "LogicalResourceId": "AppSyncSayHelloResolver", + "ResourceType": "AWS::AppSync::Resolver" + } +] diff --git a/integration/resources/templates/combination/connector_appsync_to_lambda.yaml b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml new file mode 100644 index 000000000..ea2daa83c --- /dev/null +++ b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml @@ -0,0 +1,188 @@ +Resources: + AppSyncApiLambdaInvocationRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: appsync.amazonaws.com + Action: + - sts:AssumeRole + + HelloLambda: + Type: AWS::Serverless::Function + Properties: + InlineCode: | + exports.handler = async (_) => { + return "Hello World" + } + Handler: index.handler + Runtime: nodejs14.x + + AppSyncApi: + Type: AWS::AppSync::GraphQLApi + Properties: + AuthenticationType: API_KEY + Name: AppSyncApi + + ApiSchema: + Type: AWS::AppSync::GraphQLSchema + Properties: + ApiId: !GetAtt AppSyncApi.ApiId + Definition: | + type Query { + sayHello: String! + } + schema { + query: Query + } + + AppSyncLambdaDataSource: + Type: "AWS::AppSync::DataSource" + Properties: + ApiId: !GetAtt AppSyncApi.ApiId + Name: "AppSyncLambdaDataSource" + Type: "AWS_LAMBDA" + ServiceRoleArn: !GetAtt AppSyncApiLambdaInvocationRole.Arn + LambdaConfig: + LambdaFunctionArn: !GetAtt HelloLambda.Arn + + AppSyncSayHelloResolver: + Type: "AWS::AppSync::Resolver" + Properties: + ApiId: !GetAtt AppSyncApi.ApiId + TypeName: "Query" + FieldName: "sayHello" + DataSourceName: !GetAtt AppSyncLambdaDataSource.Name + RequestMappingTemplate: | + { + "version" : "2017-02-28", + "operation": "Invoke", + "payload": $util.toJson($context.args) + } + ResponseMappingTemplate: | + $util.toJson($context.result) + + DataSourceToLambdaConnector: + Type: AWS::Serverless::Connector + Properties: + Source: + Id: AppSyncLambdaDataSource + Destination: + Id: HelloLambda + Permissions: + - Write + + ApiKey: + Type: AWS::AppSync::ApiKey + Properties: + ApiId: !GetAtt AppSyncApi.ApiId + + TriggerFunction: + Type: AWS::Serverless::Function + Properties: + Environment: + Variables: + API_KEY: !GetAtt ApiKey.ApiKey + GRAPHQL_URL: !GetAtt AppSyncApi.GraphQLUrl + Runtime: nodejs14.x + Handler: index.handler + InlineCode: | + const https = require("https"); + + exports.handler = async (_) => { + const queries = { + sayHello: /* GraphQL */ ` + query { + sayHello + } + `, + }; + + const fetch = async (url, options) => + new Promise((resolve, reject) => { + const req = https.request(url, options, (res) => { + const body = []; + res.on("data", (chunk) => body.push(chunk)); + res.on("end", () => { + const resString = Buffer.concat(body).toString(); + resolve(resString); + }); + }); + + req.on("error", (err) => { + reject(err); + }); + + req.on("timeout", () => { + req.destroy(); + reject(new Error("Request time out")); + }); + + req.write(options.body); + req.end(); + }); + + const makeRequest = async (queryName) => { + const options = { + method: "POST", + headers: { + "x-api-key": process.env.API_KEY, + }, + body: JSON.stringify({ query: queries[queryName] }), + timeout: 10000, // ms + }; + + let statusCode; + let body; + let response; + + try { + response = await fetch(process.env.GRAPHQL_URL, options); + body = JSON.parse(response); + const data = body.data?.[queryName]; + const hasNoErrors = body.errors === undefined; + const allFieldsAreSet = + data?.Status === 200 && data?.Body === "Hello World"; + statusCode = hasNoErrors && allFieldsAreSet ? 200 : 400; + if (hasNoErrors) { + body = body.data; + } else { + body = { + [queryName]: { + errors: body.errors, + }, + }; + } + } catch (error) { + statusCode = 400; + body = { + [queryName]: { + errors: [ + { + status: response.status, + message: error.message, + stack: error.stack, + }, + ], + }, + }; + } + return { + statusCode, + body, + }; + }; + + let response = await makeRequest("sayHello"); + return { + StatusCode: response.statusCode, + Body: response.body, + }; + }; + + +Metadata: + SamTransformTest: true diff --git a/samtranslator/model/connector_profiles/profiles.json b/samtranslator/model/connector_profiles/profiles.json index 4960e0fa3..6d22ae63f 100644 --- a/samtranslator/model/connector_profiles/profiles.json +++ b/samtranslator/model/connector_profiles/profiles.json @@ -767,6 +767,29 @@ } } } + }, + "AWS::Lambda::Function": { + "Type": "AWS_IAM_ROLE_MANAGED_POLICY", + "Properties": { + "SourcePolicy": true, + "AccessCategories": { + "Write": { + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "lambda:InvokeAsync", + "lambda:InvokeFunction" + ], + "Resource": [ + "%{Destination.Arn}", + "%{Destination.Arn}:*" + ] + } + ] + } + } + } } } } diff --git a/tests/translator/input/connector_appsync_to_lambda.yaml b/tests/translator/input/connector_appsync_to_lambda.yaml new file mode 100644 index 000000000..e8c94bf29 --- /dev/null +++ b/tests/translator/input/connector_appsync_to_lambda.yaml @@ -0,0 +1,60 @@ +Resources: + AppSyncApiLambdaInvocationRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: appsync.amazonaws.com + Action: + - sts:AssumeRole + + HelloLambda: + Type: AWS::Serverless::Function + Properties: + InlineCode: | + exports.handler = async (_) => { + return "Hello World" + } + Handler: index.handler + Runtime: nodejs14.x + + AppSyncApi: + Type: AWS::AppSync::GraphQLApi + Properties: + AuthenticationType: API_KEY + Name: AppSyncApi + + ApiSchema: + Type: AWS::AppSync::GraphQLSchema + Properties: + ApiId: !GetAtt AppSyncApi.ApiId + Definition: | + type Query { + sayHello: String! + } + schema { + query: Query + } + + AppSyncLambdaDataSource: + Type: AWS::AppSync::DataSource + Properties: + ApiId: !GetAtt AppSyncApi.ApiId + Name: AppSyncLambdaDataSource + Type: AWS_LAMBDA + ServiceRoleArn: !GetAtt AppSyncApiLambdaInvocationRole.Arn + LambdaConfig: + LambdaFunctionArn: !GetAtt HelloLambda.Arn + + DataSourceToLambdaConnector: + Type: AWS::Serverless::Connector + Properties: + Source: + Id: AppSyncLambdaDataSource + Destination: + Id: HelloLambda + Permissions: + - Write diff --git a/tests/translator/output/aws-cn/connector_appsync_to_lambda.json b/tests/translator/output/aws-cn/connector_appsync_to_lambda.json new file mode 100644 index 000000000..5c87af6c1 --- /dev/null +++ b/tests/translator/output/aws-cn/connector_appsync_to_lambda.json @@ -0,0 +1,176 @@ +{ + "Resources": { + "ApiSchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "AppSyncApi", + "ApiId" + ] + }, + "Definition": "type Query {\n sayHello: String!\n}\nschema {\n query: Query\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + }, + "AppSyncApi": { + "Properties": { + "AuthenticationType": "API_KEY", + "Name": "AppSyncApi" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "AppSyncApiLambdaInvocationRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": "appsync.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "Type": "AWS::IAM::Role" + }, + "AppSyncLambdaDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "AppSyncApi", + "ApiId" + ] + }, + "LambdaConfig": { + "LambdaFunctionArn": { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + } + }, + "Name": "AppSyncLambdaDataSource", + "ServiceRoleArn": { + "Fn::GetAtt": [ + "AppSyncApiLambdaInvocationRole", + "Arn" + ] + }, + "Type": "AWS_LAMBDA" + }, + "Type": "AWS::AppSync::DataSource" + }, + "DataSourceToLambdaConnectorPolicy": { + "Metadata": { + "aws:sam:connectors": { + "DataSourceToLambdaConnector": { + "Destination": { + "Type": "AWS::Serverless::Function" + }, + "Source": { + "Type": "AWS::AppSync::DataSource" + } + } + } + }, + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "lambda:InvokeAsync", + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + }, + { + "Fn::Sub": [ + "${DestinationArn}:*", + { + "DestinationArn": { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + } + } + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "Roles": [ + { + "Ref": "AppSyncApiLambdaInvocationRole" + } + ] + }, + "Type": "AWS::IAM::ManagedPolicy" + }, + "HelloLambda": { + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (_) => {\n return \"Hello World\"\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "HelloLambdaRole", + "Arn" + ] + }, + "Runtime": "nodejs14.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "HelloLambdaRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-cn:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/aws-us-gov/connector_appsync_to_lambda.json b/tests/translator/output/aws-us-gov/connector_appsync_to_lambda.json new file mode 100644 index 000000000..b6b799b2f --- /dev/null +++ b/tests/translator/output/aws-us-gov/connector_appsync_to_lambda.json @@ -0,0 +1,176 @@ +{ + "Resources": { + "ApiSchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "AppSyncApi", + "ApiId" + ] + }, + "Definition": "type Query {\n sayHello: String!\n}\nschema {\n query: Query\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + }, + "AppSyncApi": { + "Properties": { + "AuthenticationType": "API_KEY", + "Name": "AppSyncApi" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "AppSyncApiLambdaInvocationRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": "appsync.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "Type": "AWS::IAM::Role" + }, + "AppSyncLambdaDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "AppSyncApi", + "ApiId" + ] + }, + "LambdaConfig": { + "LambdaFunctionArn": { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + } + }, + "Name": "AppSyncLambdaDataSource", + "ServiceRoleArn": { + "Fn::GetAtt": [ + "AppSyncApiLambdaInvocationRole", + "Arn" + ] + }, + "Type": "AWS_LAMBDA" + }, + "Type": "AWS::AppSync::DataSource" + }, + "DataSourceToLambdaConnectorPolicy": { + "Metadata": { + "aws:sam:connectors": { + "DataSourceToLambdaConnector": { + "Destination": { + "Type": "AWS::Serverless::Function" + }, + "Source": { + "Type": "AWS::AppSync::DataSource" + } + } + } + }, + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "lambda:InvokeAsync", + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + }, + { + "Fn::Sub": [ + "${DestinationArn}:*", + { + "DestinationArn": { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + } + } + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "Roles": [ + { + "Ref": "AppSyncApiLambdaInvocationRole" + } + ] + }, + "Type": "AWS::IAM::ManagedPolicy" + }, + "HelloLambda": { + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (_) => {\n return \"Hello World\"\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "HelloLambdaRole", + "Arn" + ] + }, + "Runtime": "nodejs14.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "HelloLambdaRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws-us-gov:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} diff --git a/tests/translator/output/connector_appsync_to_lambda.json b/tests/translator/output/connector_appsync_to_lambda.json new file mode 100644 index 000000000..3e0162c55 --- /dev/null +++ b/tests/translator/output/connector_appsync_to_lambda.json @@ -0,0 +1,176 @@ +{ + "Resources": { + "ApiSchema": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "AppSyncApi", + "ApiId" + ] + }, + "Definition": "type Query {\n sayHello: String!\n}\nschema {\n query: Query\n}\n" + }, + "Type": "AWS::AppSync::GraphQLSchema" + }, + "AppSyncApi": { + "Properties": { + "AuthenticationType": "API_KEY", + "Name": "AppSyncApi" + }, + "Type": "AWS::AppSync::GraphQLApi" + }, + "AppSyncApiLambdaInvocationRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": "appsync.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "Type": "AWS::IAM::Role" + }, + "AppSyncLambdaDataSource": { + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "AppSyncApi", + "ApiId" + ] + }, + "LambdaConfig": { + "LambdaFunctionArn": { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + } + }, + "Name": "AppSyncLambdaDataSource", + "ServiceRoleArn": { + "Fn::GetAtt": [ + "AppSyncApiLambdaInvocationRole", + "Arn" + ] + }, + "Type": "AWS_LAMBDA" + }, + "Type": "AWS::AppSync::DataSource" + }, + "DataSourceToLambdaConnectorPolicy": { + "Metadata": { + "aws:sam:connectors": { + "DataSourceToLambdaConnector": { + "Destination": { + "Type": "AWS::Serverless::Function" + }, + "Source": { + "Type": "AWS::AppSync::DataSource" + } + } + } + }, + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "lambda:InvokeAsync", + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + }, + { + "Fn::Sub": [ + "${DestinationArn}:*", + { + "DestinationArn": { + "Fn::GetAtt": [ + "HelloLambda", + "Arn" + ] + } + } + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "Roles": [ + { + "Ref": "AppSyncApiLambdaInvocationRole" + } + ] + }, + "Type": "AWS::IAM::ManagedPolicy" + }, + "HelloLambda": { + "Properties": { + "Code": { + "ZipFile": "exports.handler = async (_) => {\n return \"Hello World\"\n}\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "HelloLambdaRole", + "Arn" + ] + }, + "Runtime": "nodejs14.x", + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::Lambda::Function" + }, + "HelloLambdaRole": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ], + "Tags": [ + { + "Key": "lambda:createdBy", + "Value": "SAM" + } + ] + }, + "Type": "AWS::IAM::Role" + } + } +} From bc6a600081b9449af7b40f9374ef75938ed95fc4 Mon Sep 17 00:00:00 2001 From: Slava Senchenko Date: Tue, 21 Mar 2023 15:21:30 -0700 Subject: [PATCH 6/9] add depends on --- .../templates/combination/connector_appsync_to_lambda.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/integration/resources/templates/combination/connector_appsync_to_lambda.yaml b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml index ea2daa83c..2ca0bafea 100644 --- a/integration/resources/templates/combination/connector_appsync_to_lambda.yaml +++ b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml @@ -50,6 +50,7 @@ Resources: LambdaFunctionArn: !GetAtt HelloLambda.Arn AppSyncSayHelloResolver: + DependsOn: AppSyncSchema Type: "AWS::AppSync::Resolver" Properties: ApiId: !GetAtt AppSyncApi.ApiId From fc83de884719a9cc2719ef94e59caa21c84b5b34 Mon Sep 17 00:00:00 2001 From: Slava Senchenko Date: Tue, 21 Mar 2023 15:22:29 -0700 Subject: [PATCH 7/9] correct schema name --- .../templates/combination/connector_appsync_to_lambda.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/resources/templates/combination/connector_appsync_to_lambda.yaml b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml index 2ca0bafea..4058fc3f4 100644 --- a/integration/resources/templates/combination/connector_appsync_to_lambda.yaml +++ b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml @@ -50,7 +50,7 @@ Resources: LambdaFunctionArn: !GetAtt HelloLambda.Arn AppSyncSayHelloResolver: - DependsOn: AppSyncSchema + DependsOn: ApiSchema Type: "AWS::AppSync::Resolver" Properties: ApiId: !GetAtt AppSyncApi.ApiId From a9f1c4d0e93168ee65374fed6311ceb93d03969a Mon Sep 17 00:00:00 2001 From: Slava Senchenko Date: Tue, 21 Mar 2023 15:42:10 -0700 Subject: [PATCH 8/9] format --- .../connector_appsync_to_lambda.yaml | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/integration/resources/templates/combination/connector_appsync_to_lambda.yaml b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml index 4058fc3f4..d47b22322 100644 --- a/integration/resources/templates/combination/connector_appsync_to_lambda.yaml +++ b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml @@ -5,11 +5,11 @@ Resources: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - - Effect: Allow - Principal: - Service: appsync.amazonaws.com - Action: - - sts:AssumeRole + - Effect: Allow + Principal: + Service: appsync.amazonaws.com + Action: + - sts:AssumeRole HelloLambda: Type: AWS::Serverless::Function @@ -40,22 +40,22 @@ Resources: } AppSyncLambdaDataSource: - Type: "AWS::AppSync::DataSource" + Type: AWS::AppSync::DataSource Properties: ApiId: !GetAtt AppSyncApi.ApiId - Name: "AppSyncLambdaDataSource" - Type: "AWS_LAMBDA" + Name: AppSyncLambdaDataSource + Type: AWS_LAMBDA ServiceRoleArn: !GetAtt AppSyncApiLambdaInvocationRole.Arn LambdaConfig: LambdaFunctionArn: !GetAtt HelloLambda.Arn AppSyncSayHelloResolver: DependsOn: ApiSchema - Type: "AWS::AppSync::Resolver" + Type: AWS::AppSync::Resolver Properties: ApiId: !GetAtt AppSyncApi.ApiId - TypeName: "Query" - FieldName: "sayHello" + TypeName: Query + FieldName: sayHello DataSourceName: !GetAtt AppSyncLambdaDataSource.Name RequestMappingTemplate: | { From ab118bb43ecff04c007896ce0b4040dfef9a793d Mon Sep 17 00:00:00 2001 From: Slava Senchenko Date: Tue, 21 Mar 2023 23:16:28 -0700 Subject: [PATCH 9/9] raise in trigger function --- .../connector_appsync_to_lambda.yaml | 59 +++++-------------- 1 file changed, 16 insertions(+), 43 deletions(-) diff --git a/integration/resources/templates/combination/connector_appsync_to_lambda.yaml b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml index d47b22322..5e521c11c 100644 --- a/integration/resources/templates/combination/connector_appsync_to_lambda.yaml +++ b/integration/resources/templates/combination/connector_appsync_to_lambda.yaml @@ -102,6 +102,7 @@ Resources: `, }; + const fetch = async (url, options) => new Promise((resolve, reject) => { const req = https.request(url, options, (res) => { @@ -126,6 +127,7 @@ Resources: req.end(); }); + const makeRequest = async (queryName) => { const options = { method: "POST", @@ -136,52 +138,23 @@ Resources: timeout: 10000, // ms }; - let statusCode; - let body; - let response; - - try { - response = await fetch(process.env.GRAPHQL_URL, options); - body = JSON.parse(response); - const data = body.data?.[queryName]; - const hasNoErrors = body.errors === undefined; - const allFieldsAreSet = - data?.Status === 200 && data?.Body === "Hello World"; - statusCode = hasNoErrors && allFieldsAreSet ? 200 : 400; - if (hasNoErrors) { - body = body.data; - } else { - body = { - [queryName]: { - errors: body.errors, - }, - }; - } - } catch (error) { - statusCode = 400; - body = { - [queryName]: { - errors: [ - { - status: response.status, - message: error.message, - stack: error.stack, - }, - ], - }, - }; + const response = await fetch(process.env.GRAPHQL_URL, options); + const body = JSON.parse(response); + const data = body.data?.[queryName]; + + if (body.errors !== undefined) { + throw JSON.stringify(body.errors); + } + + if (data !== "Hello World") { + throw new Error(`${queryName} error: '${data}' must be 'Hello World'`); } - return { - statusCode, - body, - }; - }; - let response = await makeRequest("sayHello"); - return { - StatusCode: response.statusCode, - Body: response.body, + return body.data; }; + + + return await makeRequest("sayHello"); };