diff --git a/src/aws-cur/README.md b/src/aws-cur/README.md index f0f8e09..38e3b30 100644 --- a/src/aws-cur/README.md +++ b/src/aws-cur/README.md @@ -23,7 +23,8 @@ Here's how you can create a monthly cost and usage report in Parquet format: ```typescript const app = new App(); -const stack = new Stack(app, 'CostReportStack'); +// Cannot specify regions other than us-east-1 +const stack = new Stack(app, 'CostReportStack', { env: { region: 'us-east-1' } }); new CostReport(stack, 'MyCostReport', { costReportName: 'monthly-business-report', diff --git a/src/aws-cur/cost-report.ts b/src/aws-cur/cost-report.ts index 9fbcfc7..f0950b9 100644 --- a/src/aws-cur/cost-report.ts +++ b/src/aws-cur/cost-report.ts @@ -103,13 +103,17 @@ export class CostReport extends Construct { constructor(scope: Construct, id: string, props: CostReportProps) { super(scope, id); + const currentStack = Stack.of(this); + + if (currentStack.region !== 'us-east-1') { + throw new Error(`The \`CostReport\` construct is only available in the us-east-1 region, got: ${currentStack.region} region`); + } + this.reportBucket = props.bucket ?? this.createReportBucket(this, 'Bucket', { blockPublicAccess: aws_s3.BlockPublicAccess.BLOCK_ALL, enforceSSL: true, }); - const currentStack = Stack.of(this); - const billingPrincipal = new aws_iam.ServicePrincipal('billingreports.amazonaws.com').withConditions({ StringEquals: { 'aws:SourceArn': `arn:aws:cur:${currentStack.region}:${currentStack.account}:definition/*`, diff --git a/test/aws-cur/cost-report.test.ts b/test/aws-cur/cost-report.test.ts index 7d60789..2cdbc44 100644 --- a/test/aws-cur/cost-report.test.ts +++ b/test/aws-cur/cost-report.test.ts @@ -9,7 +9,7 @@ describe('CostReport', () => { beforeEach(() => { app = new App(); - stack = new Stack(app, 'TestStack'); + stack = new Stack(app, 'TestStack', { env: { region: 'us-east-1' } }); }); test('default configuration', () => { @@ -112,4 +112,14 @@ describe('CostReport', () => { template.resourceCountIs('AWS::CUR::ReportDefinition', 2); }); + test('regions other than us-east-1', () => { + const regionOtherStack = new Stack(app, 'OtherRegionStack', { env: { region: 'ap-northeast-1' } }); + + expect(() => new CostReport(regionOtherStack, 'MyCustomCostReport', { + costReportName: 'custom-cur', + reportGranularity: ReportGranularity.DAILY, + format: CurFormat.PARQUET, + })).toThrow(`The \`CostReport\` construct is only available in the us-east-1 region, got: ${regionOtherStack.region} region`); + }); + }); diff --git a/test/aws-cur/integ.cost-report.ts b/test/aws-cur/integ.cost-report.ts index dea74e5..8173ea1 100644 --- a/test/aws-cur/integ.cost-report.ts +++ b/test/aws-cur/integ.cost-report.ts @@ -5,7 +5,7 @@ import * as ocf from '../../src'; class CostReportStack extends cdk.Stack { constructor(scope: Construct) { - super(scope, 'cur-report'); + super(scope, 'cur-report', { env: { region: 'us-east-1' } }); const bucket = new cdk.aws_s3.Bucket(this, 'ReportBucket', { removalPolicy: cdk.RemovalPolicy.DESTROY, diff --git a/test/aws-cur/integ.cost-report.ts.snapshot/cur-report.assets.json b/test/aws-cur/integ.cost-report.ts.snapshot/cur-report.assets.json index f47dce7..ae47fe5 100644 --- a/test/aws-cur/integ.cost-report.ts.snapshot/cur-report.assets.json +++ b/test/aws-cur/integ.cost-report.ts.snapshot/cur-report.assets.json @@ -7,23 +7,25 @@ "packaging": "zip" }, "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "current_account-us-east-1": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1", "objectKey": "b7f33614a69548d6bafe224d751a7ef238cde19097415e553fe8b63a4c8fd8a6.zip", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + "region": "us-east-1", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-east-1" } } }, - "ae9c3c5ffd6c1730f1c1a6319554d1637fade1f5910c4e0e87bcdc05e3d42ce7": { + "ea273a55939f3c24361eca95307fd8752c4fee982b66f7fd4716f69bd89a7ed3": { "source": { "path": "cur-report.template.json", "packaging": "file" }, "destinations": { - "current_account-current_region": { - "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "ae9c3c5ffd6c1730f1c1a6319554d1637fade1f5910c4e0e87bcdc05e3d42ce7.json", - "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + "current_account-us-east-1": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1", + "objectKey": "ea273a55939f3c24361eca95307fd8752c4fee982b66f7fd4716f69bd89a7ed3.json", + "region": "us-east-1", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-east-1" } } } diff --git a/test/aws-cur/integ.cost-report.ts.snapshot/cur-report.template.json b/test/aws-cur/integ.cost-report.ts.snapshot/cur-report.template.json index 805808f..eb447a0 100644 --- a/test/aws-cur/integ.cost-report.ts.snapshot/cur-report.template.json +++ b/test/aws-cur/integ.cost-report.ts.snapshot/cur-report.template.json @@ -81,11 +81,7 @@ "Fn::Join": [ "", [ - "arn:aws:cur:", - { - "Ref": "AWS::Region" - }, - ":", + "arn:aws:cur:us-east-1:", { "Ref": "AWS::AccountId" }, @@ -128,11 +124,7 @@ "Fn::Join": [ "", [ - "arn:aws:cur:", - { - "Ref": "AWS::Region" - }, - ":", + "arn:aws:cur:us-east-1:", { "Ref": "AWS::AccountId" }, @@ -207,7 +199,7 @@ "Properties": { "Code": { "S3Bucket": { - "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, "S3Key": "b7f33614a69548d6bafe224d751a7ef238cde19097415e553fe8b63a4c8fd8a6.zip" }, @@ -253,9 +245,7 @@ "Ref": "ReportBucket577F0FCD" }, "S3Prefix": "reports", - "S3Region": { - "Ref": "AWS::Region" - }, + "S3Region": "us-east-1", "TimeUnit": "HOURLY" }, "DependsOn": [ diff --git a/test/aws-cur/integ.cost-report.ts.snapshot/manifest.json b/test/aws-cur/integ.cost-report.ts.snapshot/manifest.json index 7eb6712..e352483 100644 --- a/test/aws-cur/integ.cost-report.ts.snapshot/manifest.json +++ b/test/aws-cur/integ.cost-report.ts.snapshot/manifest.json @@ -11,21 +11,21 @@ }, "cur-report": { "type": "aws:cloudformation:stack", - "environment": "aws://unknown-account/unknown-region", + "environment": "aws://unknown-account/us-east-1", "properties": { "templateFile": "cur-report.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}/ae9c3c5ffd6c1730f1c1a6319554d1637fade1f5910c4e0e87bcdc05e3d42ce7.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-east-1", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-east-1", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1/ea273a55939f3c24361eca95307fd8752c4fee982b66f7fd4716f69bd89a7ed3.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ "cur-report.assets" ], "lookupRole": { - "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-us-east-1", "requiresBootstrapStackVersion": 8, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" } diff --git a/test/aws-cur/integ.cost-report.ts.snapshot/tree.json b/test/aws-cur/integ.cost-report.ts.snapshot/tree.json index 9f36f30..58892b5 100644 --- a/test/aws-cur/integ.cost-report.ts.snapshot/tree.json +++ b/test/aws-cur/integ.cost-report.ts.snapshot/tree.json @@ -106,11 +106,7 @@ "Fn::Join": [ "", [ - "arn:aws:cur:", - { - "Ref": "AWS::Region" - }, - ":", + "arn:aws:cur:us-east-1:", { "Ref": "AWS::AccountId" }, @@ -153,11 +149,7 @@ "Fn::Join": [ "", [ - "arn:aws:cur:", - { - "Ref": "AWS::Region" - }, - ":", + "arn:aws:cur:us-east-1:", { "Ref": "AWS::AccountId" }, @@ -277,9 +269,7 @@ "Ref": "ReportBucket577F0FCD" }, "s3Prefix": "reports", - "s3Region": { - "Ref": "AWS::Region" - }, + "s3Region": "us-east-1", "timeUnit": "HOURLY" } }, @@ -291,7 +281,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.5" + "version": "10.3.0" } }, "BootstrapVersion": { @@ -329,7 +319,7 @@ "path": "CurReport/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.5" + "version": "10.3.0" } }, "DeployAssert": { @@ -375,7 +365,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.5" + "version": "10.3.0" } } },