diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/aws-stepfunctions-tasks-athena-start-query-execution-integ.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/aws-stepfunctions-tasks-athena-start-query-execution-integ.assets.json index edd08de11d7f9..8d01d68b2fb9d 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/aws-stepfunctions-tasks-athena-start-query-execution-integ.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/aws-stepfunctions-tasks-athena-start-query-execution-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "32.0.0", + "version": "34.0.0", "files": { - "d5b0852cda8e09b47bbf34672fc71a205e9a3e7dcd0ce808bb607ce6714fab1a": { + "5e42e5abe3feac0f74bcc82bdf7d7b42821b880689fbdedb6cae92bc42b58829": { "source": { "path": "aws-stepfunctions-tasks-athena-start-query-execution-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "d5b0852cda8e09b47bbf34672fc71a205e9a3e7dcd0ce808bb607ce6714fab1a.json", + "objectKey": "5e42e5abe3feac0f74bcc82bdf7d7b42821b880689fbdedb6cae92bc42b58829.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/aws-stepfunctions-tasks-athena-start-query-execution-integ.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/aws-stepfunctions-tasks-athena-start-query-execution-integ.template.json index 22315b3749901..053557d3ba5c4 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/aws-stepfunctions-tasks-athena-start-query-execution-integ.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/aws-stepfunctions-tasks-athena-start-query-execution-integ.template.json @@ -1,295 +1,295 @@ { - "Resources": { - "StateMachineRoleB840431D": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "states.amazonaws.com" - } - } - ], - "Version": "2012-10-17" + "Resources": { + "StateMachineRoleB840431D": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "states.amazonaws.com" } } - }, - "StateMachineRoleDefaultPolicyDF1E6607": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "athena:getDataCatalog", - "athena:getQueryExecution", - "athena:startQueryExecution" - ], - "Effect": "Allow", - "Resource": [ + ], + "Version": "2012-10-17" + } + } + }, + "StateMachineRoleDefaultPolicyDF1E6607": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "athena:getDataCatalog", + "athena:getQueryExecution", + "athena:startQueryExecution" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":athena:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":datacatalog/AwsDataCatalog" - ] - ] + "Ref": "AWS::Partition" }, + ":athena:", { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":athena:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":workgroup/primary" - ] - ] - } - ] - }, - { - "Action": [ - "lakeformation:GetDataAccess", - "s3:CreateBucket", - "s3:GetBucketLocation", - "s3:GetObject", - "s3:ListBucket" - ], - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": [ - "s3:AbortMultipartUpload", - "s3:ListBucketMultipartUploads", - "s3:ListMultipartUploadParts", - "s3:PutObject" - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":s3:::query-results-bucket/folder/*" - ] - ] - } - }, - { - "Action": [ - "glue:BatchCreatePartition", - "glue:BatchDeletePartition", - "glue:BatchDeleteTable", - "glue:BatchGetPartition", - "glue:CreateDatabase", - "glue:CreatePartition", - "glue:CreateTable", - "glue:DeleteDatabase", - "glue:DeletePartition", - "glue:DeleteTable", - "glue:GetDatabase", - "glue:GetDatabases", - "glue:GetPartition", - "glue:GetPartitions", - "glue:GetTable", - "glue:GetTables", - "glue:UpdateDatabase", - "glue:UpdatePartition", - "glue:UpdateTable" - ], - "Effect": "Allow", - "Resource": [ + "Ref": "AWS::Region" + }, + ":", { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":glue:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":catalog" - ] - ] + "Ref": "AWS::AccountId" }, + ":datacatalog/AwsDataCatalog" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":glue:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":database/mydatabase" - ] - ] + "Ref": "AWS::Partition" }, + ":athena:", { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":glue:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":table/mydatabase/*" - ] - ] + "Ref": "AWS::Region" }, + ":", { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":glue:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":userDefinedFunction/mydatabase/*" - ] - ] - } + "Ref": "AWS::AccountId" + }, + ":workgroup/primary" ] - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "StateMachineRoleDefaultPolicyDF1E6607", - "Roles": [ - { - "Ref": "StateMachineRoleB840431D" + ] } ] - } - }, - "StateMachine2E01A3A5": { - "Type": "AWS::StepFunctions::StateMachine", - "Properties": { - "RoleArn": { - "Fn::GetAtt": [ - "StateMachineRoleB840431D", - "Arn" - ] - }, - "DefinitionString": { + }, + { + "Action": [ + "lakeformation:GetDataAccess", + "s3:CreateBucket", + "s3:GetBucketLocation", + "s3:GetObject", + "s3:ListBucket" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "s3:AbortMultipartUpload", + "s3:ListBucketMultipartUploads", + "s3:ListMultipartUploadParts", + "s3:PutObject" + ], + "Effect": "Allow", + "Resource": { "Fn::Join": [ "", [ - "{\"StartAt\":\"Start Athena Query\",\"States\":{\"Start Athena Query\":{\"End\":true,\"Type\":\"Task\",\"Resource\":\"arn:", + "arn:", { "Ref": "AWS::Partition" }, - ":states:::athena:startQueryExecution\",\"Parameters\":{\"QueryString.$\":\"$.queryString\",\"QueryExecutionContext\":{\"Database\":\"mydatabase\"},\"ResultConfiguration\":{\"EncryptionConfiguration\":{\"EncryptionOption\":\"SSE_S3\"},\"OutputLocation\":\"s3://query-results-bucket/folder/\"}}}},\"TimeoutSeconds\":30}" + ":s3:::query-results-bucket/folder/*" ] ] } }, - "DependsOn": [ - "StateMachineRoleDefaultPolicyDF1E6607", - "StateMachineRoleB840431D" - ], - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - } - }, - "Outputs": { - "stateMachineArn": { - "Value": { - "Ref": "StateMachine2E01A3A5" + { + "Action": [ + "glue:BatchCreatePartition", + "glue:BatchDeletePartition", + "glue:BatchDeleteTable", + "glue:BatchGetPartition", + "glue:CreateDatabase", + "glue:CreatePartition", + "glue:CreateTable", + "glue:DeleteDatabase", + "glue:DeletePartition", + "glue:DeleteTable", + "glue:GetDatabase", + "glue:GetDatabases", + "glue:GetPartition", + "glue:GetPartitions", + "glue:GetTable", + "glue:GetTables", + "glue:UpdateDatabase", + "glue:UpdatePartition", + "glue:UpdateTable" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":glue:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":catalog" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":glue:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":database/mydatabase" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":glue:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":table/mydatabase/*" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":glue:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":userDefinedFunction/mydatabase/*" + ] + ] + } + ] } - } + ], + "Version": "2012-10-17" }, - "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]" + "PolicyName": "StateMachineRoleDefaultPolicyDF1E6607", + "Roles": [ + { + "Ref": "StateMachineRoleB840431D" } + ] + } + }, + "StateMachine2E01A3A5": { + "Type": "AWS::StepFunctions::StateMachine", + "Properties": { + "DefinitionString": { + "Fn::Join": [ + "", + [ + "{\"StartAt\":\"Start Athena Query\",\"States\":{\"Start Athena Query\":{\"End\":true,\"Type\":\"Task\",\"Resource\":\"arn:", + { + "Ref": "AWS::Partition" + }, + ":states:::athena:startQueryExecution\",\"Parameters\":{\"QueryString.$\":\"$.queryString\",\"QueryExecutionContext\":{\"Database\":\"mydatabase\"},\"ResultConfiguration\":{\"EncryptionConfiguration\":{\"EncryptionOption\":\"SSE_S3\"},\"OutputLocation\":\"s3://query-results-bucket/folder/\"},\"ExecutionParameters\":[\"param1\",\"param2\"]}}},\"TimeoutSeconds\":30}" + ] + ] }, - "Rules": { - "CheckBootstrapVersion": { - "Assertions": [ + "RoleArn": { + "Fn::GetAtt": [ + "StateMachineRoleB840431D", + "Arn" + ] + } + }, + "DependsOn": [ + "StateMachineRoleDefaultPolicyDF1E6607", + "StateMachineRoleB840431D" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Outputs": { + "stateMachineArn": { + "Value": { + "Ref": "StateMachine2E01A3A5" + } + } + }, + "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": [ { - "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." + "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 + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/cdk.out index f0b901e7c06e5..2313ab5436501 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"32.0.0"} \ No newline at end of file +{"version":"34.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/integ.json index 41c6be68e645c..f6522bd304f0b 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "32.0.0", + "version": "34.0.0", "testCases": { "integ.start-query-execution": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/manifest.json index 4eccb39ef5dda..ee09cf369e60f 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "32.0.0", + "version": "34.0.0", "artifacts": { "aws-stepfunctions-tasks-athena-start-query-execution-integ.assets": { "type": "cdk:asset-manifest", @@ -14,10 +14,11 @@ "environment": "aws://unknown-account/unknown-region", "properties": { "templateFile": "aws-stepfunctions-tasks-athena-start-query-execution-integ.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}/d5b0852cda8e09b47bbf34672fc71a205e9a3e7dcd0ce808bb607ce6714fab1a.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/5e42e5abe3feac0f74bcc82bdf7d7b42821b880689fbdedb6cae92bc42b58829.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/tree.json index 88e0ef6559fff..fd5d7f31f8e05 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.js.snapshot/tree.json @@ -291,12 +291,6 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::StepFunctions::StateMachine", "aws:cdk:cloudformation:props": { - "roleArn": { - "Fn::GetAtt": [ - "StateMachineRoleB840431D", - "Arn" - ] - }, "definitionString": { "Fn::Join": [ "", @@ -305,9 +299,15 @@ { "Ref": "AWS::Partition" }, - ":states:::athena:startQueryExecution\",\"Parameters\":{\"QueryString.$\":\"$.queryString\",\"QueryExecutionContext\":{\"Database\":\"mydatabase\"},\"ResultConfiguration\":{\"EncryptionConfiguration\":{\"EncryptionOption\":\"SSE_S3\"},\"OutputLocation\":\"s3://query-results-bucket/folder/\"}}}},\"TimeoutSeconds\":30}" + ":states:::athena:startQueryExecution\",\"Parameters\":{\"QueryString.$\":\"$.queryString\",\"QueryExecutionContext\":{\"Database\":\"mydatabase\"},\"ResultConfiguration\":{\"EncryptionConfiguration\":{\"EncryptionOption\":\"SSE_S3\"},\"OutputLocation\":\"s3://query-results-bucket/folder/\"},\"ExecutionParameters\":[\"param1\",\"param2\"]}}},\"TimeoutSeconds\":30}" ] ] + }, + "roleArn": { + "Fn::GetAtt": [ + "StateMachineRoleB840431D", + "Arn" + ] } } }, @@ -357,7 +357,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.2.26" + "version": "10.2.70" } } }, diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.ts index c91bd76b6b6ed..a5a22501b2a8c 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions-tasks/test/athena/integ.start-query-execution.ts @@ -25,6 +25,7 @@ const startQueryExecutionJob = new AthenaStartQueryExecution(stack, 'Start Athen objectKey: 'folder', }, }, + executionParameters: ['param1', 'param2'], }); const chain = sfn.Chain.start(startQueryExecutionJob); diff --git a/packages/aws-cdk-lib/aws-stepfunctions-tasks/README.md b/packages/aws-cdk-lib/aws-stepfunctions-tasks/README.md index eb0c35a0f3eec..3e88ca972e8bf 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions-tasks/README.md +++ b/packages/aws-cdk-lib/aws-stepfunctions-tasks/README.md @@ -257,6 +257,7 @@ const startQueryExecutionJob = new tasks.AthenaStartQueryExecution(this, 'Start objectKey: 'folder', }, }, + executionParameters: ['param1', 'param2'], }); ``` diff --git a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/athena/start-query-execution.ts b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/athena/start-query-execution.ts index f25df300a9c58..adacda49e7c32 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/athena/start-query-execution.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/athena/start-query-execution.ts @@ -42,6 +42,16 @@ export interface AthenaStartQueryExecutionProps extends sfn.TaskStateBaseProps { * @default - No work group */ readonly workGroup?: string; + + /** + * A list of values for the parameters in a query. + * + * The values are applied sequentially to the parameters in the query in the order + * in which the parameters occur. + * + * @default - No parameters + */ + readonly executionParameters?: string[]; } /** @@ -66,10 +76,22 @@ export class AthenaStartQueryExecution extends sfn.TaskStateBase { this.integrationPattern = props.integrationPattern ?? sfn.IntegrationPattern.REQUEST_RESPONSE; validatePatternSupported(this.integrationPattern, AthenaStartQueryExecution.SUPPORTED_INTEGRATION_PATTERNS); + this.validateExecutionParameters(props.executionParameters); this.taskPolicies = this.createPolicyStatements(); } + private validateExecutionParameters(executionParameters?: string[]) { + if (executionParameters === undefined || cdk.Token.isUnresolved(executionParameters)) return; + if (executionParameters.length == 0) { + throw new Error('\'executionParameters\' must be a non-empty list'); + } + const invalidExecutionParameters = executionParameters.some(p => p.length < 1 || p.length > 1024); + if (invalidExecutionParameters) { + throw new Error('\'executionParameters\' items\'s length must be between 1 and 1024 characters'); + } + } + private createPolicyStatements(): iam.PolicyStatement[] { const policyStatements = [ new iam.PolicyStatement({ @@ -208,7 +230,8 @@ export class AthenaStartQueryExecution extends sfn.TaskStateBase { EncryptionConfiguration: this.renderEncryption(), OutputLocation: this.props.resultConfiguration?.outputLocation ? `s3://${this.props.resultConfiguration.outputLocation.bucketName}/${this.props.resultConfiguration.outputLocation.objectKey}/` : undefined, }, - WorkGroup: this.props?.workGroup, + WorkGroup: this.props.workGroup, + ExecutionParameters: this.props.executionParameters, }), }; } diff --git a/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/athena/start-query-execution.test.ts b/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/athena/start-query-execution.test.ts index fb59a3a15ce8f..1dc69f1520c26 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/athena/start-query-execution.test.ts +++ b/packages/aws-cdk-lib/aws-stepfunctions-tasks/test/athena/start-query-execution.test.ts @@ -224,4 +224,190 @@ describe('Start Query Execution', () => { }), }); }); + + test('execution parameters succeeds', () => { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + const task = new AthenaStartQueryExecution(stack, 'Query', { + queryString: 'CREATE DATABASE ?', + clientRequestToken: 'unique-client-request-token', + queryExecutionContext: { + databaseName: 'mydatabase', + catalogName: 'AwsDataCatalog', + }, + resultConfiguration: { + outputLocation: { + bucketName: 'query-results-bucket', + objectKey: 'folder', + }, + }, + workGroup: 'primary', + executionParameters: ['database'], + }); + + // THEN + expect(stack.resolve(task.toStateJson())).toEqual({ + Type: 'Task', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':states:::athena:startQueryExecution', + ], + ], + }, + End: true, + Parameters: { + QueryString: 'CREATE DATABASE ?', + ClientRequestToken: 'unique-client-request-token', + QueryExecutionContext: { + Database: 'mydatabase', + Catalog: 'AwsDataCatalog', + }, + ResultConfiguration: { + OutputLocation: 's3://query-results-bucket/folder/', + }, + WorkGroup: 'primary', + ExecutionParameters: ['database'], + }, + }); + }); + + test('execution parameters succeeds with token', () => { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + const task = new AthenaStartQueryExecution(stack, 'Query', { + queryString: 'CREATE DATABASE ?', + clientRequestToken: 'unique-client-request-token', + queryExecutionContext: { + databaseName: 'mydatabase', + catalogName: 'AwsDataCatalog', + }, + resultConfiguration: { + outputLocation: { + bucketName: 'query-results-bucket', + objectKey: 'folder', + }, + }, + workGroup: 'primary', + executionParameters: sfn.JsonPath.listAt('$.executionParameters'), + }); + + // THEN + expect(stack.resolve(task.toStateJson())).toEqual({ + Type: 'Task', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':states:::athena:startQueryExecution', + ], + ], + }, + End: true, + Parameters: { + 'QueryString': 'CREATE DATABASE ?', + 'ClientRequestToken': 'unique-client-request-token', + 'QueryExecutionContext': { + Database: 'mydatabase', + Catalog: 'AwsDataCatalog', + }, + 'ResultConfiguration': { + OutputLocation: 's3://query-results-bucket/folder/', + }, + 'WorkGroup': 'primary', + 'ExecutionParameters.$': '$.executionParameters', + }, + }); + }); + + test('execution parameters fails on too long string', () => { + // GIVEN + const stack = new cdk.Stack(); + + expect(() => { + // WHEN + const task = new AthenaStartQueryExecution(stack, 'Query', { + queryString: 'CREATE DATABASE ?', + clientRequestToken: 'unique-client-request-token', + queryExecutionContext: { + databaseName: 'mydatabase', + catalogName: 'AwsDataCatalog', + }, + resultConfiguration: { + outputLocation: { + bucketName: 'query-results-bucket', + objectKey: 'folder', + }, + }, + workGroup: 'primary', + executionParameters: ['valid1', 'database'.repeat(129), 'valid2'], + }); + // THEN + }).toThrow(/length must be between 1 and 1024 characters/); + }); + + test('execution parameters fails on empty string', () => { + // GIVEN + const stack = new cdk.Stack(); + + expect(() => { + // WHEN + const task = new AthenaStartQueryExecution(stack, 'Query', { + queryString: 'CREATE DATABASE ?', + clientRequestToken: 'unique-client-request-token', + queryExecutionContext: { + databaseName: 'mydatabase', + catalogName: 'AwsDataCatalog', + }, + resultConfiguration: { + outputLocation: { + bucketName: 'query-results-bucket', + objectKey: 'folder', + }, + }, + workGroup: 'primary', + executionParameters: [''], + }); + // THEN + }).toThrow(/length must be between 1 and 1024 characters/); + }); + + test('execution parameters fails on empty list', () => { + // GIVEN + const stack = new cdk.Stack(); + + expect(() => { + // WHEN + const task = new AthenaStartQueryExecution(stack, 'Query', { + queryString: 'CREATE DATABASE ?', + clientRequestToken: 'unique-client-request-token', + queryExecutionContext: { + databaseName: 'mydatabase', + catalogName: 'AwsDataCatalog', + }, + resultConfiguration: { + outputLocation: { + bucketName: 'query-results-bucket', + objectKey: 'folder', + }, + }, + workGroup: 'primary', + executionParameters: [], + }); + // THEN + }).toThrow(/must be a non-empty list/); + }); });