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..e461c1a91cc98 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": { + "9d36c6b0337d81da7b76c65c2e3cc100d723310386d3f0c335cdea31134a958d": { "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": "9d36c6b0337d81da7b76c65c2e3cc100d723310386d3f0c335cdea31134a958d.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..39712b00076d8 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,313 @@ { - "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" - ] - ] - } + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":datacatalog/AwsDataCatalog" ] - }, - { - "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": [ + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":glue:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":catalog" - ] - ] + "Ref": "AWS::Partition" }, + ":athena:", { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":glue:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":database/mydatabase" - ] - ] + "Ref": "AWS::Region" }, + ":", { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":glue:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":table/mydatabase/*" - ] - ] + "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:", { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":glue:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":userDefinedFunction/mydatabase/*" - ] - ] - } + "Ref": "AWS::Partition" + }, + ":s3::://*" ] - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "StateMachineRoleDefaultPolicyDF1E6607", - "Roles": [ + ] + }, { - "Ref": "StateMachineRoleB840431D" + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::query-results-bucket/folder/*" + ] + ] } ] - } - }, - "StateMachine2E01A3A5": { - "Type": "AWS::StepFunctions::StateMachine", - "Properties": { - "RoleArn": { - "Fn::GetAtt": [ - "StateMachineRoleB840431D", - "Arn" - ] - }, - "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/\"}}}},\"TimeoutSeconds\":30}" - ] - ] - } }, - "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\":{\"Next\":\"Start Athena Query Output String\",\"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/\"}}},\"Start Athena Query Output String\":{\"End\":true,\"Type\":\"Task\",\"Resource\":\"arn:", + { + "Ref": "AWS::Partition" + }, + ":states:::athena:startQueryExecution\",\"Parameters\":{\"QueryString.$\":\"$.queryString\",\"QueryExecutionContext\":{\"Database\":\"mydatabase\"},\"ResultConfiguration\":{\"EncryptionConfiguration\":{\"EncryptionOption\":\"SSE_S3\"},\"OutputLocation.$\":\"States.Format('s3://query-results-bucket/folder/{}', $.output)\"}}}},\"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..c67fb5a4404b8 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", @@ -17,7 +17,7 @@ "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}/9d36c6b0337d81da7b76c65c2e3cc100d723310386d3f0c335cdea31134a958d.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..c40b2a067483a 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 @@ -16,6 +16,14 @@ "version": "0.0.0" } }, + "Start Athena Query Output String": { + "id": "Start Athena Query Output String", + "path": "aws-stepfunctions-tasks-athena-start-query-execution-integ/Start Athena Query Output String", + "constructInfo": { + "fqn": "aws-cdk-lib.aws_stepfunctions_tasks.AthenaStartQueryExecution", + "version": "0.0.0" + } + }, "StateMachine": { "id": "StateMachine", "path": "aws-stepfunctions-tasks-athena-start-query-execution-integ/StateMachine", @@ -138,18 +146,32 @@ "s3:PutObject" ], "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":s3:::query-results-bucket/folder/*" + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3::://*" + ] ] - ] - } + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::query-results-bucket/folder/*" + ] + ] + } + ] }, { "Action": [ @@ -291,23 +313,27 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::StepFunctions::StateMachine", "aws:cdk:cloudformation:props": { - "roleArn": { - "Fn::GetAtt": [ - "StateMachineRoleB840431D", - "Arn" - ] - }, "definitionString": { "Fn::Join": [ "", [ - "{\"StartAt\":\"Start Athena Query\",\"States\":{\"Start Athena Query\":{\"End\":true,\"Type\":\"Task\",\"Resource\":\"arn:", + "{\"StartAt\":\"Start Athena Query\",\"States\":{\"Start Athena Query\":{\"Next\":\"Start Athena Query Output String\",\"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/\"}}}},\"TimeoutSeconds\":30}" + ":states:::athena:startQueryExecution\",\"Parameters\":{\"QueryString.$\":\"$.queryString\",\"QueryExecutionContext\":{\"Database\":\"mydatabase\"},\"ResultConfiguration\":{\"EncryptionConfiguration\":{\"EncryptionOption\":\"SSE_S3\"},\"OutputLocation\":\"s3://query-results-bucket/folder/\"}}},\"Start Athena Query Output String\":{\"End\":true,\"Type\":\"Task\",\"Resource\":\"arn:", + { + "Ref": "AWS::Partition" + }, + ":states:::athena:startQueryExecution\",\"Parameters\":{\"QueryString.$\":\"$.queryString\",\"QueryExecutionContext\":{\"Database\":\"mydatabase\"},\"ResultConfiguration\":{\"EncryptionConfiguration\":{\"EncryptionOption\":\"SSE_S3\"},\"OutputLocation.$\":\"States.Format('s3://query-results-bucket/folder/{}', $.output)\"}}}},\"TimeoutSeconds\":30}" ] ] + }, + "roleArn": { + "Fn::GetAtt": [ + "StateMachineRoleB840431D", + "Arn" + ] } } }, @@ -357,7 +383,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..8421680d37315 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 @@ -27,7 +27,27 @@ const startQueryExecutionJob = new AthenaStartQueryExecution(stack, 'Start Athen }, }); -const chain = sfn.Chain.start(startQueryExecutionJob); +const startQueryExecutionWithOutputLocationString = new AthenaStartQueryExecution( + stack, + 'Start Athena Query Output String', + { + queryString: sfn.JsonPath.stringAt('$.queryString'), + queryExecutionContext: { + databaseName: 'mydatabase', + }, + resultConfiguration: { + encryptionConfiguration: { + encryptionOption: EncryptionOption.S3_MANAGED, + }, + outputLocation: sfn.JsonPath.format( + 's3://query-results-bucket/folder/{}', + sfn.JsonPath.stringAt('$.output'), + ), + }, + }); + +const chain = sfn.Chain.start(startQueryExecutionJob) + .next(startQueryExecutionWithOutputLocationString); const sm = new sfn.StateMachine(stack, 'StateMachine', { definition: chain, diff --git a/packages/aws-cdk-lib/aws-stepfunctions-tasks/README.md b/packages/aws-cdk-lib/aws-stepfunctions-tasks/README.md index d291ebf894b4c..de9a864968f86 100644 --- a/packages/aws-cdk-lib/aws-stepfunctions-tasks/README.md +++ b/packages/aws-cdk-lib/aws-stepfunctions-tasks/README.md @@ -258,6 +258,15 @@ const startQueryExecutionJob = new tasks.AthenaStartQueryExecution(this, 'Start }, }); ``` +Alternatively, we could also use the following for `outputLocation` +``` +resultConfiguration: { + outputLocation: sfn.JsonPath.format( + 's3://query-results-bucket/folder/{}', + sfn.JsonPath.format('$.folder'), + ) +} +``` ### GetQueryExecution 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..07039f978c58e 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 @@ -100,25 +100,31 @@ export class AthenaStartQueryExecution extends sfn.TaskStateBase { }), ); + const outputLocation = this.props.resultConfiguration?.outputLocation; + const makeS3Arn = (resource: string, resourceName: string) => + cdk.Stack.of(this).formatArn({ + // S3 Bucket names are globally unique in a partition, + // and so their ARNs have empty region and account components + region: '', + account: '', + service: 's3', + resource, + resourceName: `${resourceName}/*`, + }); + let resource = '*'; + if (typeof outputLocation === 'string') { + const parts = outputLocation.split('/'); + resource = makeS3Arn(parts[2], parts.at(3) || ''); + } else if (typeof outputLocation === 'object') { + resource = makeS3Arn(outputLocation.bucketName, outputLocation.objectKey); + } policyStatements.push( new iam.PolicyStatement({ actions: ['s3:AbortMultipartUpload', 's3:ListBucketMultipartUploads', 's3:ListMultipartUploadParts', 's3:PutObject'], - resources: [ - this.props.resultConfiguration?.outputLocation?.bucketName - ? cdk.Stack.of(this).formatArn({ - // S3 Bucket names are globally unique in a partition, - // and so their ARNs have empty region and account components - region: '', - account: '', - service: 's3', - resource: this.props.resultConfiguration?.outputLocation?.bucketName, - resourceName: `${this.props.resultConfiguration?.outputLocation?.objectKey}/*`, - }) - : '*', - ], + resources: [resource], }), ); @@ -195,6 +201,10 @@ export class AthenaStartQueryExecution extends sfn.TaskStateBase { * @internal */ protected _renderTask(): any { + let outputLocation = this.props.resultConfiguration?.outputLocation; + if (typeof outputLocation === 'object') { + outputLocation = `s3://${outputLocation.bucketName}/${outputLocation.objectKey}/`; + } return { Resource: integrationResourceArn('athena', 'startQueryExecution', this.integrationPattern), Parameters: sfn.FieldUtils.renderObject({ @@ -206,7 +216,7 @@ export class AthenaStartQueryExecution extends sfn.TaskStateBase { } : undefined, ResultConfiguration: { EncryptionConfiguration: this.renderEncryption(), - OutputLocation: this.props.resultConfiguration?.outputLocation ? `s3://${this.props.resultConfiguration.outputLocation.bucketName}/${this.props.resultConfiguration.outputLocation.objectKey}/` : undefined, + OutputLocation: outputLocation || undefined, }, WorkGroup: this.props?.workGroup, }), @@ -228,7 +238,7 @@ export interface ResultConfiguration { * * @default - Query Result Location set in Athena settings for this workgroup */ - readonly outputLocation?: s3.Location; + readonly outputLocation?: s3.Location | string; /** * Encryption option used if enabled in S3 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..0e45a57fa380f 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,51 @@ describe('Start Query Execution', () => { }), }); }); + + test('bucket arn as expected when outputLocation is string', () => { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + const task = new AthenaStartQueryExecution(stack, 'Query', { + queryString: 'CREATE DATABASE database', + clientRequestToken: 'unique-client-request-token', + resultConfiguration: { + outputLocation: 's3://query-results-bucket/folder/', + }, + }); + + new sfn.StateMachine(stack, 'StateMachine', { + definitionBody: sfn.DefinitionBody.fromChainable(task), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: Match.objectLike({ + Statement: Match.arrayWith([ + { + Action: [ + 's3:AbortMultipartUpload', + 's3:ListBucketMultipartUploads', + 's3:ListMultipartUploadParts', + 's3:PutObject', + ], + Effect: 'Allow', + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':s3:::query-results-bucket/folder/*', + ], + ], + }, + }, + ]), + }), + }); + }); });