The concept of Bucket.fromBucketName(...) is crucial in distinguishing a "foreign" bucket, which was not originally created within the current stack. CDK expects this foreign bucket to exist and may encounter errors during stack building if it doesn't. The ideal approach would be to verify the existence of the foreign bucket and, if absent, create a non-"foreign" bucket within the stack that remains intact throughout stack updates. However, this process can become convoluted.
To retain a stack-created bucket through updates, the "new Bucket()" command must be executed unconditionally by CDK, despite its initial complexity. During an update, CDK uses this operation to maintain the presence of the bucket within the stack. Neglecting to execute "new Bucket()" except when the bucket is missing will lead to its creation during the initial build but removal during subsequent updates.
In essence, the goal is to implement a solution where a bucket managed within the stack is created only if a similarly-named foreign bucket does not exist. While achieving this cleanly in CDK might pose challenges, resorting to workaround methods is not advised. It's essential to make a design choice between utilizing a foreign bucket or one generated by the CDK stack. If opting for a foreign bucket, it should be created separately beforehand, either by another stack in /bin, via aws cli, or through the AWS console.
Suggested workaround, endorsed by AWS support:
- Include a distinctive tag after initializing new Bucket(...) in the constructor:
if (!foreignBucketExists) {
// Utilize a stack-managed bucket if no foreign bucket with the same name exists
const myBucket = new Bucket(this, bucketName, {
bucketName: bucketName
});
Tags.of(myBucket).add("CreatedBy", "<a name for this stack>")
} else {
const myBucket = Bucket.fromBucketName(this, bucketName, bucketName);
}
- In /bin, validate the existence of a bucket with the specified name, check its tags to determine whether it's considered "foreign" to this stack, and relay the result to the stack constructor from step 1:
// Verify if a bucket with the given name exists
let request = new AWS.S3().listObjects({
Bucket: MyBucketName
});
let promise = request.promise();
// Handle promise fulfillment/rejection
await promise.then(result => {
foreignBucketExists = true
}).catch(err => {
console.log("No Such Bucket exists.")
foreignBucketExists = false
})
// If the bucket exists, examine its tags to ascertain its origin with respect to the CDK stack
if (foreignBucketExists) {
try {
let tagRequest = new AWS.S3().getBucketTagging({
Bucket: MyBucketName
});
let tagPromise = tagRequest.promise();
await tagPromise.then(result => {
for (let KeyVal of result.TagSet) {
if (KeyVal.Key == "CreatedBy" && KeyVal.Value == "<a name for this stack>") {
// This indicates that the bucket was created by CDK and is not foreign
foreignBucketExists = false;
}
}
}).catch(err => {
// A lack of tags signifies a foreign bucket
foreignBucketExists = true
})
} catch {}
}
console.log("Does bucket Exist?:", foreignBucketExists)