Skip to content

Commit a156221

Browse files
chore(s3): update s3 integ tests to use IntegTest construct (#24375)
Integ test cleanup continued. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent c2296a8 commit a156221

File tree

134 files changed

+3061
-1008
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

134 files changed

+3061
-1008
lines changed

packages/@aws-cdk/aws-s3/README.md

+149-97
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Amazon S3 Construct Library
2+
23
<!--BEGIN STABILITY BANNER-->
34

45
---
@@ -19,24 +20,24 @@ const bucket = new s3.Bucket(this, 'MyFirstBucket');
1920

2021
`Bucket` constructs expose the following deploy-time attributes:
2122

22-
* `bucketArn` - the ARN of the bucket (i.e. `arn:aws:s3:::bucket_name`)
23-
* `bucketName` - the name of the bucket (i.e. `bucket_name`)
24-
* `bucketWebsiteUrl` - the Website URL of the bucket (i.e.
25-
`http://bucket_name.s3-website-us-west-1.amazonaws.com`)
26-
* `bucketDomainName` - the URL of the bucket (i.e. `bucket_name.s3.amazonaws.com`)
27-
* `bucketDualStackDomainName` - the dual-stack URL of the bucket (i.e.
28-
`bucket_name.s3.dualstack.eu-west-1.amazonaws.com`)
29-
* `bucketRegionalDomainName` - the regional URL of the bucket (i.e.
30-
`bucket_name.s3.eu-west-1.amazonaws.com`)
31-
* `arnForObjects(pattern)` - the ARN of an object or objects within the bucket (i.e.
32-
`arn:aws:s3:::bucket_name/exampleobject.png` or
33-
`arn:aws:s3:::bucket_name/Development/*`)
34-
* `urlForObject(key)` - the HTTP URL of an object within the bucket (i.e.
35-
`https://s3.cn-north-1.amazonaws.com.cn/china-bucket/mykey`)
36-
* `virtualHostedUrlForObject(key)` - the virtual-hosted style HTTP URL of an object
37-
within the bucket (i.e. `https://china-bucket-s3.cn-north-1.amazonaws.com.cn/mykey`)
38-
* `s3UrlForObject(key)` - the S3 URL of an object within the bucket (i.e.
39-
`s3://bucket/mykey`)
23+
- `bucketArn` - the ARN of the bucket (i.e. `arn:aws:s3:::bucket_name`)
24+
- `bucketName` - the name of the bucket (i.e. `bucket_name`)
25+
- `bucketWebsiteUrl` - the Website URL of the bucket (i.e.
26+
`http://bucket_name.s3-website-us-west-1.amazonaws.com`)
27+
- `bucketDomainName` - the URL of the bucket (i.e. `bucket_name.s3.amazonaws.com`)
28+
- `bucketDualStackDomainName` - the dual-stack URL of the bucket (i.e.
29+
`bucket_name.s3.dualstack.eu-west-1.amazonaws.com`)
30+
- `bucketRegionalDomainName` - the regional URL of the bucket (i.e.
31+
`bucket_name.s3.eu-west-1.amazonaws.com`)
32+
- `arnForObjects(pattern)` - the ARN of an object or objects within the bucket (i.e.
33+
`arn:aws:s3:::bucket_name/exampleobject.png` or
34+
`arn:aws:s3:::bucket_name/Development/*`)
35+
- `urlForObject(key)` - the HTTP URL of an object within the bucket (i.e.
36+
`https://s3.cn-north-1.amazonaws.com.cn/china-bucket/mykey`)
37+
- `virtualHostedUrlForObject(key)` - the virtual-hosted style HTTP URL of an object
38+
within the bucket (i.e. `https://china-bucket-s3.cn-north-1.amazonaws.com.cn/mykey`)
39+
- `s3UrlForObject(key)` - the S3 URL of an object within the bucket (i.e.
40+
`s3://bucket/mykey`)
4041

4142
## Encryption
4243

@@ -90,11 +91,13 @@ A bucket policy will be automatically created for the bucket upon the first call
9091

9192
```ts
9293
const bucket = new s3.Bucket(this, 'MyBucket');
93-
const result = bucket.addToResourcePolicy(new iam.PolicyStatement({
94-
actions: ['s3:GetObject'],
95-
resources: [bucket.arnForObjects('file.txt')],
96-
principals: [new iam.AccountRootPrincipal()],
97-
}));
94+
const result = bucket.addToResourcePolicy(
95+
new iam.PolicyStatement({
96+
actions: ['s3:GetObject'],
97+
resources: [bucket.arnForObjects('file.txt')],
98+
principals: [new iam.AccountRootPrincipal()],
99+
})
100+
);
98101
```
99102

100103
If you try to add a policy statement to an existing bucket, this method will
@@ -104,11 +107,13 @@ not do anything:
104107
const bucket = s3.Bucket.fromBucketName(this, 'existingBucket', 'bucket-name');
105108

106109
// No policy statement will be added to the resource
107-
const result = bucket.addToResourcePolicy(new iam.PolicyStatement({
108-
actions: ['s3:GetObject'],
109-
resources: [bucket.arnForObjects('file.txt')],
110-
principals: [new iam.AccountRootPrincipal()],
111-
}));
110+
const result = bucket.addToResourcePolicy(
111+
new iam.PolicyStatement({
112+
actions: ['s3:GetObject'],
113+
resources: [bucket.arnForObjects('file.txt')],
114+
principals: [new iam.AccountRootPrincipal()],
115+
})
116+
);
112117
```
113118

114119
That's because it's not possible to tell whether the bucket
@@ -117,11 +122,13 @@ statements to it. We recommend that you always check the result of the call:
117122

118123
```ts
119124
const bucket = new s3.Bucket(this, 'MyBucket');
120-
const result = bucket.addToResourcePolicy(new iam.PolicyStatement({
121-
actions: ['s3:GetObject'],
122-
resources: [bucket.arnForObjects('file.txt')],
123-
principals: [new iam.AccountRootPrincipal()],
124-
}));
125+
const result = bucket.addToResourcePolicy(
126+
new iam.PolicyStatement({
127+
actions: ['s3:GetObject'],
128+
resources: [bucket.arnForObjects('file.txt')],
129+
principals: [new iam.AccountRootPrincipal()],
130+
})
131+
);
125132

126133
if (!result.statementAdded) {
127134
// Uh-oh! Someone probably made a mistake here.
@@ -166,7 +173,42 @@ const bucket = new s3.Bucket(this, 'Bucket', {
166173

167174
To use a bucket in a different stack in the same CDK application, pass the object to the other stack:
168175

169-
[sharing bucket between stacks](test/integ.bucket-sharing.lit.ts)
176+
```ts
177+
/**
178+
* Stack that defines the bucket
179+
*/
180+
class Producer extends cdk.Stack {
181+
public readonly myBucket: s3.Bucket;
182+
183+
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
184+
super(scope, id, props);
185+
186+
const bucket = new s3.Bucket(this, 'MyBucket', {
187+
removalPolicy: cdk.RemovalPolicy.DESTROY,
188+
});
189+
this.myBucket = bucket;
190+
}
191+
}
192+
193+
interface ConsumerProps extends cdk.StackProps {
194+
userBucket: s3.IBucket;
195+
}
196+
197+
/**
198+
* Stack that consumes the bucket
199+
*/
200+
class Consumer extends cdk.Stack {
201+
constructor(scope: cdk.App, id: string, props: ConsumerProps) {
202+
super(scope, id, props);
203+
204+
const user = new iam.User(this, 'MyUser');
205+
props.userBucket.grantReadWrite(user);
206+
}
207+
}
208+
209+
const producer = new Producer(app, 'ProducerStack');
210+
new Consumer(app, 'ConsumerStack', { userBucket: producer.myBucket });
211+
```
170212

171213
## Importing existing buckets
172214

@@ -181,7 +223,9 @@ const bucket = s3.Bucket.fromBucketAttributes(this, 'ImportedBucket', {
181223
});
182224

183225
// now you can just call methods on the bucket
184-
bucket.addEventNotification(s3.EventType.OBJECT_CREATED, new s3n.LambdaDestination(myLambda), {prefix: 'home/myusername/*'});
226+
bucket.addEventNotification(s3.EventType.OBJECT_CREATED, new s3n.LambdaDestination(myLambda), {
227+
prefix: 'home/myusername/*',
228+
});
185229
```
186230

187231
Alternatively, short-hand factories are available as `Bucket.fromBucketName` and
@@ -190,7 +234,7 @@ name or ARN respectively:
190234

191235
```ts
192236
const byName = s3.Bucket.fromBucketName(this, 'BucketByName', 'my-bucket');
193-
const byArn = s3.Bucket.fromBucketArn(this, 'BucketByArn', 'arn:aws:s3:::my-bucket');
237+
const byArn = s3.Bucket.fromBucketArn(this, 'BucketByArn', 'arn:aws:s3:::my-bucket');
194238
```
195239

196240
The bucket's region defaults to the current stack's region, but can also be explicitly set in cases where one of the bucket's
@@ -234,9 +278,10 @@ have the `.jpg` suffix are removed from the bucket.
234278
```ts
235279
declare const myQueue: sqs.Queue;
236280
const bucket = new s3.Bucket(this, 'MyBucket');
237-
bucket.addEventNotification(s3.EventType.OBJECT_REMOVED,
238-
new s3n.SqsDestination(myQueue),
239-
{ prefix: 'foo/', suffix: '.jpg' });
281+
bucket.addEventNotification(s3.EventType.OBJECT_REMOVED, new s3n.SqsDestination(myQueue), {
282+
prefix: 'foo/',
283+
suffix: '.jpg',
284+
});
240285
```
241286

242287
Adding notifications on existing buckets:
@@ -249,7 +294,7 @@ const bucket = s3.Bucket.fromBucketAttributes(this, 'ImportedBucket', {
249294
bucket.addEventNotification(s3.EventType.OBJECT_CREATED, new s3n.SnsDestination(topic));
250295
```
251296

252-
When you add an event notification to a bucket, a custom resource is created to
297+
When you add an event notification to a bucket, a custom resource is created to
253298
manage the notifications. By default, a new role is created for the Lambda
254299
function that implements this feature. If you want to use your own role instead,
255300
you should provide it in the `Bucket` constructor:
@@ -261,10 +306,10 @@ const bucket = new s3.Bucket(this, 'MyBucket', {
261306
});
262307
```
263308

264-
Whatever role you provide, the CDK will try to modify it by adding the
265-
permissions from `AWSLambdaBasicExecutionRole` (an AWS managed policy) as well
266-
as the permissions `s3:PutBucketNotification` and `s3:GetBucketNotification`.
267-
If you’re passing an imported role, and you don’t want this to happen, configure
309+
Whatever role you provide, the CDK will try to modify it by adding the
310+
permissions from `AWSLambdaBasicExecutionRole` (an AWS managed policy) as well
311+
as the permissions `s3:PutBucketNotification` and `s3:GetBucketNotification`.
312+
If you’re passing an imported role, and you don’t want this to happen, configure
268313
it to be immutable:
269314

270315
```ts
@@ -273,11 +318,10 @@ const importedRole = iam.Role.fromRoleArn(this, 'role', 'arn:aws:iam::1234567890
273318
});
274319
```
275320

276-
> If you provide an imported immutable role, make sure that it has at least all
321+
> If you provide an imported immutable role, make sure that it has at least all
277322
> the permissions mentioned above. Otherwise, the deployment will fail!
278323
279-
[S3 Bucket Notifications]: https://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html
280-
324+
[s3 bucket notifications]: https://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html
281325

282326
### EventBridge notifications
283327

@@ -292,7 +336,7 @@ const bucket = new s3.Bucket(this, 'MyEventBridgeBucket', {
292336
});
293337
```
294338

295-
[S3 EventBridge notifications]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/EventBridge.html
339+
[s3 eventbridge notifications]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/EventBridge.html
296340

297341
## Block Public Access
298342

@@ -439,16 +483,18 @@ Alternatively, you can also define multiple `websiteRoutingRules`, to define com
439483

440484
```ts
441485
const bucket = new s3.Bucket(this, 'MyRedirectedBucket', {
442-
websiteRoutingRules: [{
443-
hostName: 'www.example.com',
444-
httpRedirectCode: '302',
445-
protocol: s3.RedirectProtocol.HTTPS,
446-
replaceKey: s3.ReplaceKey.prefixWith('test/'),
447-
condition: {
448-
httpErrorCodeReturnedEquals: '200',
449-
keyPrefixEquals: 'prefix',
486+
websiteRoutingRules: [
487+
{
488+
hostName: 'www.example.com',
489+
httpRedirectCode: '302',
490+
protocol: s3.RedirectProtocol.HTTPS,
491+
replaceKey: s3.ReplaceKey.prefixWith('test/'),
492+
condition: {
493+
httpErrorCodeReturnedEquals: '200',
494+
keyPrefixEquals: 'prefix',
495+
},
450496
},
451-
}],
497+
],
452498
});
453499
```
454500

@@ -479,7 +525,7 @@ bucket.virtualHostedUrlForObject('objectname', { regional: false }); // Virtual
479525

480526
You can use one of following properties to specify the bucket [object Ownership].
481527

482-
[object Ownership]: https://docs.aws.amazon.com/AmazonS3/latest/dev/about-object-ownership.html
528+
[object ownership]: https://docs.aws.amazon.com/AmazonS3/latest/dev/about-object-ownership.html
483529

484530
### Object writer
485531

@@ -516,9 +562,9 @@ new s3.Bucket(this, 'MyBucket', {
516562
Some services may not not support log delivery to buckets that have object ownership
517563
set to bucket owner enforced, such as
518564
[S3 buckets using ACLs](#allowing-access-log-delivery-using-a-bucket-policy-recommended)
519-
or [CloudFront Distributions][CloudFront S3 Bucket].
565+
or [CloudFront Distributions][cloudfront s3 bucket].
520566

521-
[CloudFront S3 Bucket]: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html#AccessLogsBucketAndFileOwnership
567+
[cloudfront s3 bucket]: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html#AccessLogsBucketAndFileOwnership
522568

523569
## Bucket deletion
524570

@@ -539,7 +585,7 @@ const bucket = new s3.Bucket(this, 'MyTempFileBucket', {
539585
```
540586

541587
**Warning** if you have deployed a bucket with `autoDeleteObjects: true`,
542-
switching this to `false` in a CDK version *before* `1.126.0` will lead to
588+
switching this to `false` in a CDK version _before_ `1.126.0` will lead to
543589
all objects in the bucket being deleted. Be sure to update your bucket resources
544590
by deploying with CDK version `1.126.0` or later **before** switching this value to `false`.
545591

@@ -568,15 +614,16 @@ bucket.transferAccelerationUrlForObject('objectname');
568614

569615
```ts
570616
new s3.Bucket(this, 'MyBucket', {
571-
intelligentTieringConfigurations: [{
572-
name: 'foo',
573-
prefix: 'folder/name',
574-
archiveAccessTierTime: cdk.Duration.days(90),
575-
deepArchiveAccessTierTime: cdk.Duration.days(180),
576-
tags: [{key: 'tagname', value: 'tagvalue'}]
577-
}],
617+
intelligentTieringConfigurations: [
618+
{
619+
name: 'foo',
620+
prefix: 'folder/name',
621+
archiveAccessTierTime: cdk.Duration.days(90),
622+
deepArchiveAccessTierTime: cdk.Duration.days(180),
623+
tags: [{ key: 'tagname', value: 'tagvalue' }],
624+
},
625+
],
578626
});
579-
580627
```
581628

582629
## Lifecycle Rule
@@ -585,35 +632,41 @@ new s3.Bucket(this, 'MyBucket', {
585632

586633
```ts
587634
const bucket = new s3.Bucket(this, 'MyBucket', {
588-
lifecycleRules: [{
589-
abortIncompleteMultipartUploadAfter: cdk.Duration.minutes(30),
590-
enabled: false,
591-
expiration: cdk.Duration.days(30),
592-
expirationDate: new Date(),
593-
expiredObjectDeleteMarker: false,
594-
id: 'id',
595-
noncurrentVersionExpiration: cdk.Duration.days(30),
596-
597-
// the properties below are optional
598-
noncurrentVersionsToRetain: 123,
599-
noncurrentVersionTransitions: [{
600-
storageClass: s3.StorageClass.GLACIER,
601-
transitionAfter: cdk.Duration.days(30),
635+
lifecycleRules: [
636+
{
637+
abortIncompleteMultipartUploadAfter: cdk.Duration.minutes(30),
638+
enabled: false,
639+
expiration: cdk.Duration.days(30),
640+
expirationDate: new Date(),
641+
expiredObjectDeleteMarker: false,
642+
id: 'id',
643+
noncurrentVersionExpiration: cdk.Duration.days(30),
602644

603645
// the properties below are optional
604646
noncurrentVersionsToRetain: 123,
605-
}],
606-
objectSizeGreaterThan: 500,
607-
prefix: 'prefix',
608-
objectSizeLessThan: 10000,
609-
transitions: [{
610-
storageClass: s3.StorageClass.GLACIER,
611-
612-
// the properties below are optional
613-
transitionAfter: cdk.Duration.days(30),
614-
transitionDate: new Date(),
615-
}],
616-
}]
647+
noncurrentVersionTransitions: [
648+
{
649+
storageClass: s3.StorageClass.GLACIER,
650+
transitionAfter: cdk.Duration.days(30),
651+
652+
// the properties below are optional
653+
noncurrentVersionsToRetain: 123,
654+
},
655+
],
656+
objectSizeGreaterThan: 500,
657+
prefix: 'prefix',
658+
objectSizeLessThan: 10000,
659+
transitions: [
660+
{
661+
storageClass: s3.StorageClass.GLACIER,
662+
663+
// the properties below are optional
664+
transitionAfter: cdk.Duration.days(30),
665+
transitionDate: new Date(),
666+
},
667+
],
668+
},
669+
],
617670
});
618671
```
619672

@@ -628,7 +681,7 @@ Object Lock can be enabled on an S3 bucket by specifying:
628681

629682
```ts
630683
const bucket = new s3.Bucket(this, 'MyBucket', {
631-
objectLockEnabled: true
684+
objectLockEnabled: true,
632685
});
633686
```
634687

@@ -647,5 +700,4 @@ new s3.Bucket(this, 'Bucket1', {
647700
new s3.Bucket(this, 'Bucket2', {
648701
objectLockDefaultRetention: s3.ObjectLockRetention.compliance(cdk.Duration.days(365)),
649702
});
650-
651703
```

0 commit comments

Comments
 (0)