chore(s3): use BucketReflection for L1-backed property access#37210
chore(s3): use BucketReflection for L1-backed property access#37210mergify[bot] merged 2 commits intomainfrom
Conversation
7eb72f9 to
f4b5e6a
Compare
f4b5e6a to
588239b
Compare
588239b to
0518552
Compare
0518552 to
3b4e815
Compare
| get isWebsite(): boolean { | ||
| return this._bucket?.websiteConfiguration !== undefined; | ||
| } |
There was a problem hiding this comment.
We need to do make a decision about CFN intrinsics and tokens.
techincally speaking, the value of websiteConfiguration could be Fn.if(someCondition, {}, Aws.NO_VALUE).
In that case, we would return true, even though the correct answer is false (but the correct answer from CDK's point of view is "don't know").
How about returning a
class Answer {
public readonly isTrue: boolean;
public readonly isFalse: boolean;
public readonly isUnknown: boolean;
}Value?
There was a problem hiding this comment.
I mean we already have that with true false and undefined. The issue here is more that the existing code used this check, but never allowed it to be a Fn. Will fix.
b64b5d7 to
b7f9d5d
Compare
b7f9d5d to
ee59eb6
Compare
ee59eb6 to
2833876
Compare
|
Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
Merge Queue Status
This pull request spent 31 minutes 8 seconds in the queue, including 30 minutes 58 seconds running CI. Required conditions to merge
|
|
Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork). |
|
Comments on closed issues and PRs are hard for our team to see. |
Reason for this change
Properties like
isWebsite,disallowPublicAccess, andbucketWebsiteDomainNameon theBucketclass are computed eagerly from constructor props and cached as plain fields. This means the values are frozen at construction time and won't reflect any mutations made to the underlyingCfnBucketresource afterwards. It also means each of these properties has its own bespoke derivation logic scattered across the constructor, making it harder to reason about where the source of truth lives.Description of changes
This introduces
BucketReflection, a new class that reads bucket configuration directly from the L1CfnBucketresource at access time rather than caching prop-derived values. By reading from the L1, the reflection getters provide a single source of truth that stays consistent regardless of whether the bucket was created as an L2 construct, imported, or built directly as aCfnBucket.The
Bucketclass is refactored to delegatebucketWebsiteDomainName,isWebsite, anddisallowPublicAccessthroughBucketReflectiongetters. ThedisallowPublicAccesssetter is now a no-op since the value is derived from theCfnBucketresource via reflection.BucketReflectionis deliberately kept as a non-exported internal class while we iterate on the API shape. Once the pattern stabilizes, it can be promoted to a public API.Beyond the initial three properties,
BucketReflectionalso exposespolicyandencryptionKeygetters that search the construct tree for the associatedCfnBucketPolicyandCfnKeyresources. The previous private helper functions (tryFindBucketPolicyForBucket,tryFindKmsKeyforBucket,tryFindBucketConstruct) inlib/private/reflections.tsare consolidated intoBucketReflectionand the file is deleted. Internal consumers indefault-traits.tsare updated to useBucketReflectioninstead.BucketReflection.of()gracefully handles customIBucketRefimplementations that don't have an underlyingCfnBucketin the construct tree. Thebucketgetter throws lazily on access when no L1 is found, whilepolicyfalls back to searching from the originalIBucketRef, andencryptionKey/disallowPublicAccessreturn safe defaults. This ensures the class works across L1, L2, and custom bucket implementations.To support safe property traversal on L1 resources — where any nested value might be an unresolved CDK token — this adds a
resolvedGetutility tocore/lib/helpers-internal. It walks a dot-separated property path and returns a caller-specified fallback whenever it encounters anIResolvable, rather than silently returning a token object that would be misinterpreted as a truthy value. This distinction between "not configured" (undefined) and "configured but unreadable" (fallback) is important for reflection getters that need to make boolean decisions based on L1 property values.Describe any new or updated permissions being added
No new permissions.
Description of how you validated changes
Existing tests in
bucket-reflection.test.ts(renamed fromreflections.test.ts) are updated to use theBucketReflectionpublic API instead of the deleted private helpers. Additional tests verify behavior with customIBucketRefimplementations that lack aCfnBucket: thebucketgetter throws,policystill finds associated policies, andencryptionKeyreturns undefined. New unit tests forresolvedGetcover simple paths, numeric indexing, missing segments, null segments, and resolvable token handling at root, intermediate, and leaf positions.Checklist
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license