Skip to content

Commit ece46db

Browse files
authored
fix(s3-deployment): wrong URL in BucketDeployment.deployedBucket.bucketWebsiteUrl (#24055)
Fixes #23354 Without pass-through of all attribute values, it is currently not possible to automatically force a dependency on the deployment for every attribute. This change merely sets the bucket's region & account, so that all computed website/domain attributes will now include the correct values. Other attributes, and manually set website/domain attributes are not supported. Additionally the documentation has been extended to highlight the above issue and provide a workaround. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 928f830 commit ece46db

File tree

16 files changed

+2098
-8
lines changed

16 files changed

+2098
-8
lines changed

Diff for: packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts

+18-8
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ export class BucketDeployment extends Construct {
253253
private readonly cr: cdk.CustomResource;
254254
private _deployedBucket?: s3.IBucket;
255255
private requestDestinationArn: boolean = false;
256+
private readonly destinationBucket: s3.IBucket;
256257
private readonly sources: SourceConfig[];
257258
private readonly handlerRole: iam.IRole;
258259

@@ -274,6 +275,8 @@ export class BucketDeployment extends Construct {
274275
throw new Error('Vpc must be specified if useEfs is set');
275276
}
276277

278+
this.destinationBucket = props.destinationBucket;
279+
277280
const accessPointPath = '/lambda';
278281
let accessPoint;
279282
if (props.useEfs && props.vpc) {
@@ -333,9 +336,9 @@ export class BucketDeployment extends Construct {
333336

334337
this.sources = props.sources.map((source: ISource) => source.bind(this, { handlerRole: this.handlerRole }));
335338

336-
props.destinationBucket.grantReadWrite(handler);
339+
this.destinationBucket.grantReadWrite(handler);
337340
if (props.accessControl) {
338-
props.destinationBucket.grantPutAcl(handler);
341+
this.destinationBucket.grantPutAcl(handler);
339342
}
340343
if (props.distribution) {
341344
handler.addToRolePolicy(new iam.PolicyStatement({
@@ -378,7 +381,7 @@ export class BucketDeployment extends Construct {
378381
}, [] as Array<Record<string, any>>);
379382
},
380383
}, { omitEmptyArray: true }),
381-
DestinationBucketName: props.destinationBucket.bucketName,
384+
DestinationBucketName: this.destinationBucket.bucketName,
382385
DestinationBucketKeyPrefix: props.destinationKeyPrefix,
383386
RetainOnDelete: props.retainOnDelete,
384387
Extract: props.extract,
@@ -389,8 +392,8 @@ export class BucketDeployment extends Construct {
389392
SystemMetadata: mapSystemMetadata(props),
390393
DistributionId: props.distribution?.distributionId,
391394
DistributionPaths: props.distributionPaths,
392-
// Passing through the ARN sequences dependencees on the deployment
393-
DestinationBucketArn: cdk.Lazy.string({ produce: () => this.requestDestinationArn ? props.destinationBucket.bucketArn : undefined }),
395+
// Passing through the ARN sequences dependency on the deployment
396+
DestinationBucketArn: cdk.Lazy.string({ produce: () => this.requestDestinationArn ? this.destinationBucket.bucketArn : undefined }),
394397
},
395398
});
396399

@@ -447,7 +450,7 @@ export class BucketDeployment extends Construct {
447450
* want the contents of the bucket to be removed on bucket deletion, then `autoDeleteObjects` property should
448451
* be set to true on the Bucket.
449452
*/
450-
cdk.Tags.of(props.destinationBucket).add(tagKey, 'true');
453+
cdk.Tags.of(this.destinationBucket).add(tagKey, 'true');
451454

452455
}
453456

@@ -458,11 +461,18 @@ export class BucketDeployment extends Construct {
458461
* bucket deployment has happened before the next operation is started, pass the other construct
459462
* a reference to `deployment.deployedBucket`.
460463
*
461-
* Doing this replaces calling `otherResource.node.addDependency(deployment)`.
464+
* Note that this only returns an immutable reference to the destination bucket.
465+
* If sequenced access to the original destination bucket is required, you may add a dependency
466+
* on the bucket deployment instead: `otherResource.node.addDependency(deployment)`
462467
*/
463468
public get deployedBucket(): s3.IBucket {
464469
this.requestDestinationArn = true;
465-
this._deployedBucket = this._deployedBucket ?? s3.Bucket.fromBucketArn(this, 'DestinationBucket', cdk.Token.asString(this.cr.getAtt('DestinationBucketArn')));
470+
this._deployedBucket = this._deployedBucket ?? s3.Bucket.fromBucketAttributes(this, 'DestinationBucket', {
471+
bucketArn: cdk.Token.asString(this.cr.getAtt('DestinationBucketArn')),
472+
region: this.destinationBucket.env.region,
473+
account: this.destinationBucket.env.account,
474+
isWebsite: this.destinationBucket.isWebsite,
475+
});
466476
return this._deployedBucket;
467477
}
468478

Diff for: packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts

+26
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,32 @@ test('s3 deployment bucket is identical to destination bucket', () => {
11111111
});
11121112
});
11131113

1114+
test('s3 deployed bucket in a different region has correct website url', () => {
1115+
// GIVEN
1116+
const stack = new cdk.Stack(undefined, undefined, {
1117+
env: {
1118+
region: 'us-east-1',
1119+
},
1120+
});
1121+
const bucket = s3.Bucket.fromBucketAttributes(stack, 'Dest', {
1122+
bucketName: 'my-bucket',
1123+
// Bucket is in a different region than stack
1124+
region: 'eu-central-1',
1125+
});
1126+
1127+
// WHEN
1128+
const bd = new s3deploy.BucketDeployment(stack, 'Deployment', {
1129+
destinationBucket: bucket,
1130+
sources: [s3deploy.Source.asset(path.join(__dirname, 'my-website'))],
1131+
});
1132+
const websiteUrl = stack.resolve(bd.deployedBucket.bucketWebsiteUrl);
1133+
1134+
// THEN
1135+
// eu-central-1 uses website endpoint format with a `.`
1136+
// see https://docs.aws.amazon.com/general/latest/gr/s3.html#s3_website_region_endpoints
1137+
expect(JSON.stringify(websiteUrl)).toContain('.s3-website.eu-central-1.');
1138+
});
1139+
11141140
test('using deployment bucket references the destination bucket by means of the CustomResource', () => {
11151141
// GIVEN
11161142
const stack = new cdk.Stack();

0 commit comments

Comments
 (0)