Skip to content

Commit b5670b3

Browse files
authored
2 parents f50b8a4 + 693603e commit b5670b3

File tree

9 files changed

+92
-49
lines changed

9 files changed

+92
-49
lines changed

CHANGELOG.v2.alpha.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
44

5+
## [2.248.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.247.0-alpha.0...v2.248.0-alpha.0) (2026-04-02)
6+
57
## [2.247.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.246.0-alpha.0...v2.247.0-alpha.0) (2026-04-02)
68

79

CHANGELOG.v2.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
44

5+
## [2.248.0](https://github.com/aws/aws-cdk/compare/v2.247.0...v2.248.0) (2026-04-02)
6+
7+
8+
### Bug Fixes
9+
10+
* **eks:** downgrade isolated subnet validation from error to warning ([#37500](https://github.com/aws/aws-cdk/issues/37500)) ([470856c](https://github.com/aws/aws-cdk/commit/470856cadcee34b2ec5e0620fab63838c223fd97)), closes [#37491](https://github.com/aws/aws-cdk/issues/37491)
11+
512
## [2.247.0](https://github.com/aws/aws-cdk/compare/v2.246.0...v2.247.0) (2026-04-02)
613

714

docs/MIXINS_DESIGN_GUIDELINES.md

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,24 @@ Mixins are appropriate when:
2323
- You want to allow users to compose features independently of the L2
2424
construct's props.
2525

26-
Mixins are _not_ appropriate when the feature serves an external consumer rather
27-
than the target resource (use a Facade). For example, granting a role access to
28-
a bucket is about the role's needs, not the bucket's behavior.
26+
Mixins are _not_ appropriate when:
27+
28+
- The feature serves an external consumer rather than the target resource (use
29+
a Facade). For example, granting a role access to a bucket is about the
30+
role's needs, not the bucket's behavior.
31+
- The feature advertises a capability to other constructs (use a Trait).
32+
- You need to change the optionality of construct properties or change construct defaults.
33+
- The feature should remain a normal construct property and the implementation
34+
is primarily passing values through to the L1 resource. In that case, use
35+
`CfnPropsMixin` in the L2 glue code instead of writing a standalone mixin.
2936

3037
Mixins are _not_ a replacement for construct properties. They cannot change the
31-
optionality of properties or change defaults.
38+
optionality of construct properties or change construct defaults.
39+
Applying a mixin is an explicit user action. A mixin may, however, define
40+
its own inputs/props with default values that control the mixin's behavior
41+
once applied. For example, `BucketVersioning` defaults to enabling versioning
42+
when constructed without an explicit argument, but it does not change the
43+
`Bucket` construct's own default behavior.
3244

3345
## Base Class
3446

@@ -136,6 +148,21 @@ supports(construct: IConstruct): construct is CfnBucket {
136148
When applied to an L2 construct via `.with()`, the mixin framework
137149
automatically delegates to the L1 default child.
138150

151+
### Auxiliary Resources
152+
153+
A mixin may create auxiliary resources when the feature requires additional
154+
infrastructure beyond directly configuring the target resource.
155+
An auxiliary resource is any construct created by the mixin whose sole purpose
156+
is to support the target resource's own behavior or lifecycle.
157+
158+
Examples include:
159+
- Custom resource handlers (e.g., auto-delete objects handler in `BucketAutoDeleteObjects`)
160+
- Delivery sources and destinations (e.g., vended log delivery configuration in LogsDelivery Mixins)
161+
- Policy resources (e.g., bucket policy statements in `BucketPolicyStatements`)
162+
163+
Auxiliary resources must serve the primary resource itself. If the additional
164+
resource primarily serves an external consumer, the feature belongs in a Facade, not a Mixin.
165+
139166
### Validation
140167

141168
Mixins have two distinct phases: initialization and application. During
@@ -304,4 +331,13 @@ Mixins are accessed through the `mixins` namespace export:
304331
## README Documentation
305332

306333
Each service module with mixins must include a `## Mixins` section in its
307-
README documenting each mixin with a brief description and usage example.
334+
README documenting each mixin with:
335+
336+
- a brief description of what the mixin does
337+
- a usage code example
338+
- the behavioral impact of applying the mixin
339+
340+
The documented impact must describe what changes occur when the
341+
mixin is applied, including any modified L1 properties, lifecycle
342+
or deletion behavior changes, validation constraints, and any
343+
permissions, policy, or deployment-time implications.

packages/aws-cdk-lib/aws-eks-v2/lib/cluster.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,13 +1397,11 @@ export class Cluster extends ClusterBase {
13971397
const isolatedSubnetIds = new Set(this.vpc.isolatedSubnets.map(s => s.subnetId));
13981398
const hasIsolatedSubnets = privateSubnets.some(s => isolatedSubnetIds.has(s.subnetId));
13991399
if (hasIsolatedSubnets) {
1400-
throw new ValidationError(
1401-
lit`IsolatedKubectlSubnet`,
1402-
'Isolated subnets cannot be used for kubectl private subnets. Isolated subnets have no internet access, '
1403-
+ 'which is required for the kubectl Lambda to reach the EKS API, STS, and other AWS service endpoints. '
1404-
+ 'Use PRIVATE_WITH_EGRESS subnets with a NAT Gateway instead, or configure VPC endpoints for STS, EKS, ECR, S3 '
1405-
+ 'and other AWS services detailed here https://docs.aws.amazon.com/eks/latest/userguide/private-clusters.html',
1406-
this,
1400+
Annotations.of(this).addWarningV2(
1401+
'@aws-cdk/aws-eks:isolatedSubnetsForKubectlPrivateSubnets',
1402+
'Isolated subnets are being used for kubectl private subnets. Isolated subnets have no internet access. '
1403+
+ 'Ensure that VPC endpoints are configured for STS, EKS, ECR, S3 and other AWS services detailed here '
1404+
+ 'https://docs.aws.amazon.com/eks/latest/userguide/private-clusters.html',
14071405
);
14081406
}
14091407
}

packages/aws-cdk-lib/aws-eks-v2/test/cluster.test.ts

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import * as cdk8s from 'cdk8s';
55
import { Construct } from 'constructs';
66
import * as YAML from 'yaml';
77
import { testFixture, testFixtureNoVpc } from './util';
8-
import { Match, Template } from '../../assertions';
8+
import { Annotations, Match, Template } from '../../assertions';
99
import * as asg from '../../aws-autoscaling';
1010
import * as ec2 from '../../aws-ec2';
1111
import * as iam from '../../aws-iam';
@@ -1349,7 +1349,7 @@ describe('cluster', () => {
13491349
});
13501350
});
13511351

1352-
test('throws when kubectl subnets include isolated subnets', () => {
1352+
test('warns when kubectl subnets include isolated subnets', () => {
13531353
// GIVEN
13541354
const { stack } = testFixtureNoVpc();
13551355
const vpc = new ec2.Vpc(stack, 'Vpc', {
@@ -1360,19 +1360,20 @@ describe('cluster', () => {
13601360
],
13611361
});
13621362

1363+
// WHEN
1364+
new eks.Cluster(stack, 'Cluster', {
1365+
version: CLUSTER_VERSION,
1366+
vpc,
1367+
vpcSubnets: [{ subnetType: ec2.SubnetType.PRIVATE_ISOLATED }],
1368+
endpointAccess: eks.EndpointAccess.PRIVATE,
1369+
kubectlProviderOptions: {
1370+
kubectlLayer: new KubectlV33Layer(stack, 'kubectlLayer'),
1371+
},
1372+
prune: false,
1373+
});
1374+
13631375
// THEN
1364-
expect(() => {
1365-
new eks.Cluster(stack, 'Cluster', {
1366-
version: CLUSTER_VERSION,
1367-
vpc,
1368-
vpcSubnets: [{ subnetType: ec2.SubnetType.PRIVATE_ISOLATED }],
1369-
endpointAccess: eks.EndpointAccess.PRIVATE,
1370-
kubectlProviderOptions: {
1371-
kubectlLayer: new KubectlV33Layer(stack, 'kubectlLayer'),
1372-
},
1373-
prune: false,
1374-
});
1375-
}).toThrow(/Isolated subnets cannot be used for kubectl private subnets/);
1376+
Annotations.fromStack(stack).hasWarning('/Stack/Cluster', Match.stringLikeRegexp('Isolated subnets are being used for kubectl private subnets'));
13761377
});
13771378

13781379
test('does not throw when kubectl subnets are PRIVATE_WITH_EGRESS', () => {

packages/aws-cdk-lib/aws-eks/lib/cluster.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1880,13 +1880,11 @@ export class Cluster extends ClusterBase {
18801880
const isolatedSubnetIds = new Set(this.vpc.isolatedSubnets.map(s => s.subnetId));
18811881
const hasIsolatedSubnets = privateSubnets.some(s => isolatedSubnetIds.has(s.subnetId));
18821882
if (hasIsolatedSubnets) {
1883-
throw new ValidationError(
1884-
lit`IsolatedKubectlSubnet`,
1885-
'Isolated subnets cannot be used for kubectl private subnets. Isolated subnets have no internet access, '
1886-
+ 'which is required for the kubectl Lambda to reach the EKS API, STS, and other AWS service endpoints. '
1887-
+ 'Use PRIVATE_WITH_EGRESS subnets with a NAT Gateway instead, or configure VPC endpoints for STS, EKS, ECR, S3 '
1888-
+ 'and other AWS services detailed here https://docs.aws.amazon.com/eks/latest/userguide/private-clusters.html',
1889-
this,
1883+
Annotations.of(this).addWarningV2(
1884+
'@aws-cdk/aws-eks:isolatedSubnetsForKubectlPrivateSubnets',
1885+
'Isolated subnets are being used for kubectl private subnets. Isolated subnets have no internet access. '
1886+
+ 'Ensure that VPC endpoints are configured for STS, EKS, ECR, S3 and other AWS services detailed here '
1887+
+ 'https://docs.aws.amazon.com/eks/latest/userguide/private-clusters.html',
18901888
);
18911889
}
18921890
}

packages/aws-cdk-lib/aws-eks/test/cluster.test.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2328,7 +2328,7 @@ describe('cluster', () => {
23282328
});
23292329
});
23302330

2331-
test('throws when kubectl private subnets include isolated subnets', () => {
2331+
test('warns when kubectl private subnets include isolated subnets', () => {
23322332
// GIVEN
23332333
const { stack } = testFixtureNoVpc();
23342334
const vpc = new ec2.Vpc(stack, 'Vpc', {
@@ -2339,17 +2339,18 @@ describe('cluster', () => {
23392339
],
23402340
});
23412341

2342+
// WHEN
2343+
new eks.Cluster(stack, 'Cluster', {
2344+
version: CLUSTER_VERSION,
2345+
vpc,
2346+
vpcSubnets: [{ subnetType: ec2.SubnetType.PRIVATE_ISOLATED }],
2347+
endpointAccess: eks.EndpointAccess.PRIVATE,
2348+
kubectlLayer: new KubectlV31Layer(stack, 'KubectlLayer'),
2349+
prune: false,
2350+
});
2351+
23422352
// THEN
2343-
expect(() => {
2344-
new eks.Cluster(stack, 'Cluster', {
2345-
version: CLUSTER_VERSION,
2346-
vpc,
2347-
vpcSubnets: [{ subnetType: ec2.SubnetType.PRIVATE_ISOLATED }],
2348-
endpointAccess: eks.EndpointAccess.PRIVATE,
2349-
kubectlLayer: new KubectlV31Layer(stack, 'KubectlLayer'),
2350-
prune: false,
2351-
});
2352-
}).toThrow(/Isolated subnets cannot be used for kubectl private subnets/);
2353+
Annotations.fromStack(stack).hasWarning('/Stack/Cluster', Match.stringLikeRegexp('Isolated subnets are being used for kubectl private subnets'));
23532354
});
23542355

23552356
test('does not throw when kubectl private subnets are PRIVATE_WITH_EGRESS', () => {

version.v2.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"version": "2.247.0",
3-
"alphaVersion": "2.247.0-alpha.0"
2+
"version": "2.248.0",
3+
"alphaVersion": "2.248.0-alpha.0"
44
}

yarn.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11448,9 +11448,9 @@ lodash.truncate@^4.4.2:
1144811448
integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==
1144911449

1145011450
lodash@^4.17.15, lodash@^4.17.21, lodash@^4.17.23:
11451-
version "4.17.23"
11452-
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a"
11453-
integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==
11451+
version "4.18.1"
11452+
resolved "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz#ff2b66c1f6326d59513de2407bf881439812771c"
11453+
integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==
1145411454

1145511455
log-symbols@^4.0.0, log-symbols@^4.1.0:
1145611456
version "4.1.0"

0 commit comments

Comments
 (0)