diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/AppSyncFunctionMaxBatchSizeDefaultTestDeployAssert21899F3D.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/AppSyncFunctionMaxBatchSizeDefaultTestDeployAssert21899F3D.assets.json new file mode 100644 index 0000000000000..00b0607293a37 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/AppSyncFunctionMaxBatchSizeDefaultTestDeployAssert21899F3D.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "AppSyncFunctionMaxBatchSizeDefaultTestDeployAssert21899F3D.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/AppSyncFunctionMaxBatchSizeDefaultTestDeployAssert21899F3D.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/AppSyncFunctionMaxBatchSizeDefaultTestDeployAssert21899F3D.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/AppSyncFunctionMaxBatchSizeDefaultTestDeployAssert21899F3D.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/asset.df9f207d681056c35badb6bc0d60a945b44c887b227b759715fd6a6443486443/lambda-tutorial.js b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/asset.df9f207d681056c35badb6bc0d60a945b44c887b227b759715fd6a6443486443/lambda-tutorial.js new file mode 100644 index 0000000000000..5a08f83ef4f0a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/asset.df9f207d681056c35badb6bc0d60a945b44c887b227b759715fd6a6443486443/lambda-tutorial.js @@ -0,0 +1,70 @@ +exports.handler = (event, context, callback) => { + console.log("Received event {}", JSON.stringify(event, 3)); + var posts = { + "1": {"id": "1", "title": "First book", "author": "Author1", "url": "https://amazon.com/", "content": "SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1", "ups": "100", "downs": "10"}, + "2": {"id": "2", "title": "Second book", "author": "Author2", "url": "https://amazon.com", "content": "SAMPLE TEXT AUTHOR 2 SAMPLE TEXT AUTHOR 2 SAMPLE TEXT", "ups": "100", "downs": "10"}, + "3": {"id": "3", "title": "Third book", "author": "Author3", "url": null, "content": null, "ups": null, "downs": null }, + "4": {"id": "4", "title": "Fourth book", "author": "Author4", "url": "https://www.amazon.com/", "content": "SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4", "ups": "1000", "downs": "0"}, + "5": {"id": "5", "title": "Fifth book", "author": "Author5", "url": "https://www.amazon.com/", "content": "SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT", "ups": "50", "downs": "0"} }; + + var relatedPosts = { + "1": [posts['4']], + "2": [posts['3'], posts['5']], + "3": [posts['2'], posts['1']], + "4": [posts['2'], posts['1']], + "5": [] + }; + const isBatch = Array.isArray(event); + if (isBatch) { + console.log("Got an BatchInvoke Request. The payload has %d items to resolve.", event.length); + const field = event[0].field; + switch(field) { + case "relatedPostsMaxBatchSize": + case "relatedPosts": + var results = []; + // the response MUST contain the same number + // of entries as the payload array + for (var i=0; i< event.length; i++) { + console.log("post {}", JSON.stringify(event[i].source)); + results.push(relatedPosts[event[i].source.id]); + } + console.log("results {}", JSON.stringify(results)); + callback(null, results); + break; + default: + callback("Unknown field, unable to resolve" + field, null); + break; + } + } + else { + console.log("Got an Invoke Request."); + switch(event.field) { + case "getPost": + var id = event.arguments.id; + callback(null, posts[id]); + break; + case "allPosts": + var values = []; + for(var d in posts){ + values.push(posts[d]); + } + callback(null, values); + break; + case "addPost": + // return the arguments back + callback(null, event.arguments); + break; + case "addPostErrorWithData": + var id = event.arguments.id; + var result = posts[id]; + // attached additional error information to the post + result.errorMessage = 'Error with the mutation, data has changed'; + result.errorType = 'MUTATION_ERROR'; + callback(null, result); + break; + default: + callback("Unknown field, unable to resolve" + event.field, null); + break; + } + } +}; \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/aws-cdk-appsync-function-max-batch-size.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/aws-cdk-appsync-function-max-batch-size.assets.json new file mode 100644 index 0000000000000..45ee5c3868767 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/aws-cdk-appsync-function-max-batch-size.assets.json @@ -0,0 +1,32 @@ +{ + "version": "36.0.0", + "files": { + "df9f207d681056c35badb6bc0d60a945b44c887b227b759715fd6a6443486443": { + "source": { + "path": "asset.df9f207d681056c35badb6bc0d60a945b44c887b227b759715fd6a6443486443", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "df9f207d681056c35badb6bc0d60a945b44c887b227b759715fd6a6443486443.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "89224c8b14895e605e4e19b7170dc69e61ea0a0c0e3809b2fde62ea258c510b5": { + "source": { + "path": "aws-cdk-appsync-function-max-batch-size.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "89224c8b14895e605e4e19b7170dc69e61ea0a0c0e3809b2fde62ea258c510b5.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/aws-cdk-appsync-function-max-batch-size.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/aws-cdk-appsync-function-max-batch-size.template.json new file mode 100644 index 0000000000000..9f84d02263f3f --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/aws-cdk-appsync-function-max-batch-size.template.json @@ -0,0 +1,229 @@ +{ + "Resources": { + "LambdaAPID6A5A92B": { + "Type": "AWS::AppSync::GraphQLApi", + "Properties": { + "AuthenticationType": "API_KEY", + "Name": "LambdaAPI" + } + }, + "LambdaAPISchemaCC5CA3D2": { + "Type": "AWS::AppSync::GraphQLSchema", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "LambdaAPID6A5A92B", + "ApiId" + ] + }, + "Definition": "schema {\n query: Query\n mutation: Mutation\n}\n\ntype Query {\n getPost(id:ID!): Post\n allPosts: [Post]\n}\n\ntype Mutation {\n addPost(id: ID!, author: String!, title: String, content: String, url: String): Post!\n}\n\ntype Post {\n id: ID!\n author: String!\n title: String\n content: String\n url: String\n ups: Int\n downs: Int\n relatedPosts: [Post]\n relatedPostsMaxBatchSize: [Post]\n}" + } + }, + "LambdaAPIDefaultApiKey15F6897D": { + "Type": "AWS::AppSync::ApiKey", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "LambdaAPID6A5A92B", + "ApiId" + ] + } + }, + "DependsOn": [ + "LambdaAPISchemaCC5CA3D2" + ] + }, + "LambdaAPILambdaDSServiceRole21CACDF8": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "appsync.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "LambdaAPILambdaDSServiceRoleDefaultPolicyFB1B9CE8": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "lambda:InvokeFunction", + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "funcC3A0C2E2", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "funcC3A0C2E2", + "Arn" + ] + }, + ":*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "LambdaAPILambdaDSServiceRoleDefaultPolicyFB1B9CE8", + "Roles": [ + { + "Ref": "LambdaAPILambdaDSServiceRole21CACDF8" + } + ] + } + }, + "LambdaAPILambdaDSFD6DF39B": { + "Type": "AWS::AppSync::DataSource", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "LambdaAPID6A5A92B", + "ApiId" + ] + }, + "LambdaConfig": { + "LambdaFunctionArn": { + "Fn::GetAtt": [ + "funcC3A0C2E2", + "Arn" + ] + } + }, + "Name": "LambdaDS", + "ServiceRoleArn": { + "Fn::GetAtt": [ + "LambdaAPILambdaDSServiceRole21CACDF8", + "Arn" + ] + }, + "Type": "AWS_LAMBDA" + } + }, + "LambdaAPITestFunction64FA697F": { + "Type": "AWS::AppSync::FunctionConfiguration", + "Properties": { + "ApiId": { + "Fn::GetAtt": [ + "LambdaAPID6A5A92B", + "ApiId" + ] + }, + "DataSourceName": "LambdaDS", + "FunctionVersion": "2018-05-29", + "MaxBatchSize": 10, + "Name": "test" + }, + "DependsOn": [ + "LambdaAPILambdaDSFD6DF39B", + "LambdaAPISchemaCC5CA3D2" + ] + }, + "funcServiceRoleA96CCB44": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "funcC3A0C2E2": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "df9f207d681056c35badb6bc0d60a945b44c887b227b759715fd6a6443486443.zip" + }, + "Handler": "lambda-tutorial.handler", + "Role": { + "Fn::GetAtt": [ + "funcServiceRoleA96CCB44", + "Arn" + ] + }, + "Runtime": "nodejs18.x" + }, + "DependsOn": [ + "funcServiceRoleA96CCB44" + ] + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/integ.json new file mode 100644 index 0000000000000..99070c3472406 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "AppSyncFunctionMaxBatchSize/DefaultTest": { + "stacks": [ + "aws-cdk-appsync-function-max-batch-size" + ], + "assertionStack": "AppSyncFunctionMaxBatchSize/DefaultTest/DeployAssert", + "assertionStackName": "AppSyncFunctionMaxBatchSizeDefaultTestDeployAssert21899F3D" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/manifest.json new file mode 100644 index 0000000000000..487410ad91efc --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/manifest.json @@ -0,0 +1,161 @@ +{ + "version": "36.0.0", + "artifacts": { + "aws-cdk-appsync-function-max-batch-size.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-appsync-function-max-batch-size.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-appsync-function-max-batch-size": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-appsync-function-max-batch-size.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/89224c8b14895e605e4e19b7170dc69e61ea0a0c0e3809b2fde62ea258c510b5.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-appsync-function-max-batch-size.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-appsync-function-max-batch-size.assets" + ], + "metadata": { + "/aws-cdk-appsync-function-max-batch-size/LambdaAPI/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaAPID6A5A92B" + } + ], + "/aws-cdk-appsync-function-max-batch-size/LambdaAPI/Schema": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaAPISchemaCC5CA3D2" + } + ], + "/aws-cdk-appsync-function-max-batch-size/LambdaAPI/DefaultApiKey": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaAPIDefaultApiKey15F6897D" + } + ], + "/aws-cdk-appsync-function-max-batch-size/LambdaAPI/LambdaDS/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaAPILambdaDSServiceRole21CACDF8" + } + ], + "/aws-cdk-appsync-function-max-batch-size/LambdaAPI/LambdaDS/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaAPILambdaDSServiceRoleDefaultPolicyFB1B9CE8" + } + ], + "/aws-cdk-appsync-function-max-batch-size/LambdaAPI/LambdaDS/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaAPILambdaDSFD6DF39B" + } + ], + "/aws-cdk-appsync-function-max-batch-size/LambdaAPI/TestFunction/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LambdaAPITestFunction64FA697F" + } + ], + "/aws-cdk-appsync-function-max-batch-size/func/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "funcServiceRoleA96CCB44" + } + ], + "/aws-cdk-appsync-function-max-batch-size/func/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "funcC3A0C2E2" + } + ], + "/aws-cdk-appsync-function-max-batch-size/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-appsync-function-max-batch-size/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-appsync-function-max-batch-size" + }, + "AppSyncFunctionMaxBatchSizeDefaultTestDeployAssert21899F3D.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "AppSyncFunctionMaxBatchSizeDefaultTestDeployAssert21899F3D.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "AppSyncFunctionMaxBatchSizeDefaultTestDeployAssert21899F3D": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "AppSyncFunctionMaxBatchSizeDefaultTestDeployAssert21899F3D.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "AppSyncFunctionMaxBatchSizeDefaultTestDeployAssert21899F3D.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "AppSyncFunctionMaxBatchSizeDefaultTestDeployAssert21899F3D.assets" + ], + "metadata": { + "/AppSyncFunctionMaxBatchSize/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/AppSyncFunctionMaxBatchSize/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "AppSyncFunctionMaxBatchSize/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/tree.json new file mode 100644 index 0000000000000..3e44a41b95859 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.js.snapshot/tree.json @@ -0,0 +1,474 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-appsync-function-max-batch-size": { + "id": "aws-cdk-appsync-function-max-batch-size", + "path": "aws-cdk-appsync-function-max-batch-size", + "children": { + "LambdaAPI": { + "id": "LambdaAPI", + "path": "aws-cdk-appsync-function-max-batch-size/LambdaAPI", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-appsync-function-max-batch-size/LambdaAPI/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::GraphQLApi", + "aws:cdk:cloudformation:props": { + "authenticationType": "API_KEY", + "name": "LambdaAPI" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnGraphQLApi", + "version": "0.0.0" + } + }, + "Schema": { + "id": "Schema", + "path": "aws-cdk-appsync-function-max-batch-size/LambdaAPI/Schema", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::GraphQLSchema", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "LambdaAPID6A5A92B", + "ApiId" + ] + }, + "definition": "schema {\n query: Query\n mutation: Mutation\n}\n\ntype Query {\n getPost(id:ID!): Post\n allPosts: [Post]\n}\n\ntype Mutation {\n addPost(id: ID!, author: String!, title: String, content: String, url: String): Post!\n}\n\ntype Post {\n id: ID!\n author: String!\n title: String\n content: String\n url: String\n ups: Int\n downs: Int\n relatedPosts: [Post]\n relatedPostsMaxBatchSize: [Post]\n}" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnGraphQLSchema", + "version": "0.0.0" + } + }, + "DefaultApiKey": { + "id": "DefaultApiKey", + "path": "aws-cdk-appsync-function-max-batch-size/LambdaAPI/DefaultApiKey", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::ApiKey", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "LambdaAPID6A5A92B", + "ApiId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnApiKey", + "version": "0.0.0" + } + }, + "LogGroup": { + "id": "LogGroup", + "path": "aws-cdk-appsync-function-max-batch-size/LambdaAPI/LogGroup", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "LambdaDS": { + "id": "LambdaDS", + "path": "aws-cdk-appsync-function-max-batch-size/LambdaAPI/LambdaDS", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "aws-cdk-appsync-function-max-batch-size/LambdaAPI/LambdaDS/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "aws-cdk-appsync-function-max-batch-size/LambdaAPI/LambdaDS/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-appsync-function-max-batch-size/LambdaAPI/LambdaDS/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "appsync.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "aws-cdk-appsync-function-max-batch-size/LambdaAPI/LambdaDS/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-appsync-function-max-batch-size/LambdaAPI/LambdaDS/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "lambda:InvokeFunction", + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "funcC3A0C2E2", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "funcC3A0C2E2", + "Arn" + ] + }, + ":*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "policyName": "LambdaAPILambdaDSServiceRoleDefaultPolicyFB1B9CE8", + "roles": [ + { + "Ref": "LambdaAPILambdaDSServiceRole21CACDF8" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-appsync-function-max-batch-size/LambdaAPI/LambdaDS/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::DataSource", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "LambdaAPID6A5A92B", + "ApiId" + ] + }, + "lambdaConfig": { + "lambdaFunctionArn": { + "Fn::GetAtt": [ + "funcC3A0C2E2", + "Arn" + ] + } + }, + "name": "LambdaDS", + "serviceRoleArn": { + "Fn::GetAtt": [ + "LambdaAPILambdaDSServiceRole21CACDF8", + "Arn" + ] + }, + "type": "AWS_LAMBDA" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnDataSource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.LambdaDataSource", + "version": "0.0.0" + } + }, + "TestFunction": { + "id": "TestFunction", + "path": "aws-cdk-appsync-function-max-batch-size/LambdaAPI/TestFunction", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-appsync-function-max-batch-size/LambdaAPI/TestFunction/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppSync::FunctionConfiguration", + "aws:cdk:cloudformation:props": { + "apiId": { + "Fn::GetAtt": [ + "LambdaAPID6A5A92B", + "ApiId" + ] + }, + "dataSourceName": "LambdaDS", + "functionVersion": "2018-05-29", + "maxBatchSize": 10, + "name": "test" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.CfnFunctionConfiguration", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.AppsyncFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appsync.GraphqlApi", + "version": "0.0.0" + } + }, + "func": { + "id": "func", + "path": "aws-cdk-appsync-function-max-batch-size/func", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "aws-cdk-appsync-function-max-batch-size/func/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "aws-cdk-appsync-function-max-batch-size/func/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-appsync-function-max-batch-size/func/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Code": { + "id": "Code", + "path": "aws-cdk-appsync-function-max-batch-size/func/Code", + "children": { + "Stage": { + "id": "Stage", + "path": "aws-cdk-appsync-function-max-batch-size/func/Code/Stage", + "constructInfo": { + "fqn": "aws-cdk-lib.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "aws-cdk-appsync-function-max-batch-size/func/Code/AssetBucket", + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3_assets.Asset", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-appsync-function-max-batch-size/func/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "s3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "s3Key": "df9f207d681056c35badb6bc0d60a945b44c887b227b759715fd6a6443486443.zip" + }, + "handler": "lambda-tutorial.handler", + "role": { + "Fn::GetAtt": [ + "funcServiceRoleA96CCB44", + "Arn" + ] + }, + "runtime": "nodejs18.x" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.Function", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-appsync-function-max-batch-size/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-appsync-function-max-batch-size/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "AppSyncFunctionMaxBatchSize": { + "id": "AppSyncFunctionMaxBatchSize", + "path": "AppSyncFunctionMaxBatchSize", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "AppSyncFunctionMaxBatchSize/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "AppSyncFunctionMaxBatchSize/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "AppSyncFunctionMaxBatchSize/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "AppSyncFunctionMaxBatchSize/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "AppSyncFunctionMaxBatchSize/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.ts new file mode 100644 index 0000000000000..ae02a794edfcb --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-appsync/test/integ.appsync-function-max-batch-size.ts @@ -0,0 +1,33 @@ +import * as path from 'path'; +import * as lambda from 'aws-cdk-lib/aws-lambda'; +import * as cdk from 'aws-cdk-lib'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as appsync from 'aws-cdk-lib/aws-appsync'; +import { STANDARD_NODEJS_RUNTIME } from '../../config'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-appsync-function-max-batch-size'); + +const api = new appsync.GraphqlApi(stack, 'LambdaAPI', { + name: 'LambdaAPI', + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.lambda.graphql')), +}); + +const func = new lambda.Function(stack, 'func', { + code: lambda.Code.fromAsset(path.join(__dirname, 'verify', 'lambda-tutorial')), + handler: 'lambda-tutorial.handler', + runtime: STANDARD_NODEJS_RUNTIME, +}); + +const lambdaDS = api.addLambdaDataSource('LambdaDS', func); + +lambdaDS.createFunction('TestFunction', { + name: 'test', + maxBatchSize: 10, +}); + +new IntegTest(app, 'AppSyncFunctionMaxBatchSize', { + testCases: [stack], +}); + +app.synth(); diff --git a/packages/aws-cdk-lib/aws-appsync/README.md b/packages/aws-cdk-lib/aws-appsync/README.md index a239a481e057a..675d10dadbfc2 100644 --- a/packages/aws-cdk-lib/aws-appsync/README.md +++ b/packages/aws-cdk-lib/aws-appsync/README.md @@ -755,6 +755,22 @@ const appsyncFunction = new appsync.AppsyncFunction(this, 'function', { }); ``` +When using the `LambdaDataSource`, you can control the maximum number of resolver request +inputs that will be sent to a single AWS Lambda function in a BatchInvoke operation +by setting the `maxBatchSize` property. + +```ts +declare const api: appsync.GraphqlApi; +declare const lambdaDataSource: appsync.LambdaDataSource; + +const appsyncFunction = new appsync.AppsyncFunction(this, 'function', { + name: 'appsync_function', + api, + dataSource: lambdaDataSource, + maxBatchSize: 10, +}); +``` + AppSync Functions are used in tandem with pipeline resolvers to compose multiple operations. @@ -864,7 +880,7 @@ const api = new appsync.GraphqlApi(this, 'api', { definition: appsync.Definition.fromFile(path.join(__dirname, 'appsync.schema.graphql')), environmentVariables: { EnvKey1: 'non-empty-1', - }, + }, }); api.addEnvironmentVariable('EnvKey2', 'non-empty-2'); diff --git a/packages/aws-cdk-lib/aws-appsync/lib/appsync-function.ts b/packages/aws-cdk-lib/aws-appsync/lib/appsync-function.ts index 19c1a959a90b5..c4378622eb142 100644 --- a/packages/aws-cdk-lib/aws-appsync/lib/appsync-function.ts +++ b/packages/aws-cdk-lib/aws-appsync/lib/appsync-function.ts @@ -1,7 +1,7 @@ import { Construct } from 'constructs'; import { CfnFunctionConfiguration } from './appsync.generated'; import { Code } from './code'; -import { BaseDataSource } from './data-source'; +import { BaseDataSource, LambdaDataSource } from './data-source'; import { IGraphqlApi } from './graphqlapi-base'; import { MappingTemplate } from './mapping-template'; import { FunctionRuntime } from './runtime'; @@ -15,36 +15,51 @@ export interface BaseAppsyncFunctionProps { * the name of the AppSync Function */ readonly name: string; + /** * the description for this AppSync Function * * @default - no description */ readonly description?: string; + /** * the request mapping template for the AppSync Function * * @default - no request mapping template */ readonly requestMappingTemplate?: MappingTemplate; + /** * the response mapping template for the AppSync Function * * @default - no response mapping template */ readonly responseMappingTemplate?: MappingTemplate; + /** * The functions runtime * * @default - no function runtime, VTL mapping templates used */ readonly runtime?: FunctionRuntime; + /** * The function code * * @default - no code is used */ readonly code?: Code; + + /** + * The maximum number of resolver request inputs that will be sent to a single AWS Lambda function + * in a BatchInvoke operation. + * + * Can only be set when using LambdaDataSource. + * + * @default - No max batch size + */ + readonly maxBatchSize?: number; } /** @@ -106,7 +121,7 @@ export class AppsyncFunction extends Resource implements IAppsyncFunction { produce: () => Fn.select(3, Fn.split('/', attrs.functionArn)), }); public readonly functionArn = attrs.functionArn; - constructor (s: Construct, i: string) { + constructor(s: Construct, i: string) { super(s, i); } } @@ -152,6 +167,10 @@ export class AppsyncFunction extends Resource implements IAppsyncFunction { throw new Error('Mapping templates cannot be used alongside code'); } + if (props.maxBatchSize && !(props.dataSource instanceof LambdaDataSource)) { + throw new Error('maxBatchSize can only be set for the data source of type \LambdaDataSource\''); + } + const code = props.code?.bind(this); this.function = new CfnFunctionConfiguration(this, 'Resource', { name: props.name, @@ -164,6 +183,7 @@ export class AppsyncFunction extends Resource implements IAppsyncFunction { functionVersion: '2018-05-29', requestMappingTemplate: props.requestMappingTemplate?.renderTemplate(), responseMappingTemplate: props.responseMappingTemplate?.renderTemplate(), + maxBatchSize: props.maxBatchSize, }); this.functionName = this.function.attrName; this.functionArn = this.function.attrFunctionArn; diff --git a/packages/aws-cdk-lib/aws-appsync/test/appsync-function.test.ts b/packages/aws-cdk-lib/aws-appsync/test/appsync-function.test.ts new file mode 100644 index 0000000000000..d9e88fc72989b --- /dev/null +++ b/packages/aws-cdk-lib/aws-appsync/test/appsync-function.test.ts @@ -0,0 +1,50 @@ +import * as path from 'path'; +import { Template } from '../../assertions'; +import * as lambda from '../../aws-lambda'; +import * as cdk from '../../core'; +import * as appsync from '../lib'; + +// GLOBAL GIVEN +let stack: cdk.Stack; +let api: appsync.GraphqlApi; +beforeEach(() => { + stack = new cdk.Stack(); + api = new appsync.GraphqlApi(stack, 'baseApi', { + name: 'api', + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + }); +}); + +test('maxBatchSize property can be set in AppSync Function with Lambda DataSource.', () => { + // GIVEN + const func = new lambda.Function(stack, 'func', { + code: lambda.Code.fromAsset(path.join(__dirname, 'verify', 'iam-query')), + handler: 'iam-query.handler', + runtime: lambda.Runtime.NODEJS_LATEST, + }); + const dataSource = api.addLambdaDataSource('ds', func); + + // WHEN + dataSource.createFunction('TestFunction', { + name: 'test', + maxBatchSize: 10, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::AppSync::FunctionConfiguration', { + Name: 'test', + MaxBatchSize: 10, + }); +}); + +test('maxBatchSize property cannot be set in AppSync Function if data source is not Lambda.', () => { + const dataSource = api.addNoneDataSource('none'); + + expect(() => { + dataSource.createFunction('TestFunction', { + name: 'test', + maxBatchSize: 10, + }); + }).toThrow('maxBatchSize can only be set for the data source of type \LambdaDataSource\''); +}); +