Skip to content

Commit

Permalink
chore(eks-v2-alpha): remove nested stack (#32692)
Browse files Browse the repository at this point in the history
### Reason for this change

In the current EKS module, `kubectlProvider` is created in a nested stack. The nested stack here is not necessary and hence moving it to the main stack.

### Description of changes

Move `kubectlProvider` to the main stack.



### Describe any new or updated permissions being added

<!— What new or updated IAM permissions are needed to support the changes being introduced ? -->


### Description of how you validated changes
Updated unit tests so they all passed

### Checklist
- [ ] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md)

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
xazhao authored Jan 9, 2025
1 parent d82f214 commit 8a96454
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 126 deletions.
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-eks-v2-alpha/lib/kubectl-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Construct, IConstruct } from 'constructs';
import { ICluster, Cluster } from './cluster';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { Duration, Stack, NestedStack, Names, CfnCondition, Fn, Aws } from 'aws-cdk-lib/core';
import { Duration, Stack, Names, CfnCondition, Fn, Aws } from 'aws-cdk-lib/core';
import * as cr from 'aws-cdk-lib/custom-resources';
import { AwsCliLayer } from 'aws-cdk-lib/lambda-layer-awscli';
import { KubectlLayer } from 'aws-cdk-lib/lambda-layer-kubectl';
Expand Down Expand Up @@ -61,7 +61,7 @@ export interface IKubectlProvider extends IConstruct {
/**
* Implementation of Kubectl Lambda
*/
export class KubectlProvider extends NestedStack implements IKubectlProvider {
export class KubectlProvider extends Construct implements IKubectlProvider {

/**
* Take existing provider or create new based on cluster
Expand Down
153 changes: 43 additions & 110 deletions packages/@aws-cdk/aws-eks-v2-alpha/test/cluster.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1084,7 +1084,7 @@ describe('cluster', () => {
Type: 'Custom::AWSCDK-EKS-KubernetesResource',
Properties: {
ServiceToken: {
'Fn::ImportValue': 'Stack:ExportsOutputFnGetAttawscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6BOutputsStackawscdkawseksKubectlProviderframeworkonEvent8897FD9BArn49BEF20C',
'Fn::ImportValue': 'Stack:ExportsOutputFnGetAttawscdkawseksKubectlProviderframeworkonEvent0A650005Arn27EC41A8',
},
Manifest: '[{\"foo\":\"bar\"}]',
ClusterName: { 'Fn::ImportValue': 'Stack:ExportsOutputRefcluster611F8AFFA07FC079' },
Expand Down Expand Up @@ -2069,11 +2069,9 @@ describe('cluster', () => {
},
});

// the kubectl provider is inside a nested stack.
const nested = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;
Template.fromStack(nested).hasResourceProperties('AWS::Lambda::Function', {
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
VpcConfig: {
SecurityGroupIds: [{ Ref: 'referencetoStackCluster17032651AClusterSecurityGroupId' }],
SecurityGroupIds: [{ 'Fn::GetAtt': ['Cluster192CD0375', 'ClusterSecurityGroupId'] }],
},
});
});
Expand Down Expand Up @@ -2101,9 +2099,7 @@ describe('cluster', () => {
},
});

// the kubectl provider is inside a nested stack.
const nested = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;
Template.fromStack(nested).hasResourceProperties('AWS::Lambda::Function', {
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
Environment: {
Variables: {
Foo: 'Bar',
Expand Down Expand Up @@ -2139,11 +2135,9 @@ describe('cluster', () => {
},
});

// the kubectl provider is inside a nested stack.
const nested = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;
Template.fromStack(nested).hasResourceProperties('AWS::Lambda::Function', {
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
Role: {
Ref: 'referencetoStackKubectlIamRole02F8947EArn',
'Fn::GetAtt': ['awscdkawseksKubectlProviderframeworkonEventServiceRoleF4FAF053', 'Arn'],
},
});
});
Expand All @@ -2165,10 +2159,9 @@ describe('cluster', () => {
chart,
});

const nested = stack.node.tryFindChild('Imported-KubectlProvider') as cdk.NestedStack;
Template.fromStack(nested).hasResourceProperties('AWS::Lambda::Function', {
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
Role: {
Ref: 'referencetoKubectlLambdaRole7D084D94Arn',
'Fn::GetAtt': ['ImportedKubectlProviderframeworkonEventServiceRole6603B49A', 'Arn'],
},
});
Template.fromStack(stack).hasResourceProperties(HelmChart.RESOURCE_TYPE, {
Expand Down Expand Up @@ -2199,11 +2192,9 @@ describe('cluster', () => {
vpcSubnets: [{ subnetType: ec2.SubnetType.PUBLIC }],
});

const nested = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;

// we don't attach vpc config in case endpoint is public only, regardless of whether
// the vpc has private subnets or not.
Template.fromStack(nested).hasResourceProperties('AWS::Lambda::Function', {
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
VpcConfig: Match.absent(),
});
});
Expand All @@ -2217,11 +2208,9 @@ describe('cluster', () => {
endpointAccess: eks.EndpointAccess.PUBLIC,
});

const nested = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;

// we don't attach vpc config in case endpoint is public only, regardless of whether
// the vpc has private subnets or not.
Template.fromStack(nested).hasResourceProperties('AWS::Lambda::Function', {
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
VpcConfig: Match.absent(),
});
});
Expand All @@ -2248,11 +2237,9 @@ describe('cluster', () => {
endpointAccess: eks.EndpointAccess.PRIVATE,
});

const nested = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;

const functions = Template.fromStack(nested).findResources('AWS::Lambda::Function');
expect(functions.Handler886CB40B.Properties.VpcConfig.SubnetIds.length).not.toEqual(0);
expect(functions.Handler886CB40B.Properties.VpcConfig.SecurityGroupIds.length).not.toEqual(0);
const functions = Template.fromStack(stack).findResources('AWS::Lambda::Function');
expect(functions.awscdkawseksKubectlProviderHandlerAABA4423.Properties.VpcConfig.SubnetIds.length).not.toEqual(0);
expect(functions.awscdkawseksKubectlProviderHandlerAABA4423.Properties.VpcConfig.SecurityGroupIds.length).not.toEqual(0);
});

test('private and non restricted public without private subnets', () => {
Expand All @@ -2265,11 +2252,9 @@ describe('cluster', () => {
vpcSubnets: [{ subnetType: ec2.SubnetType.PUBLIC }],
});

const nested = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;

// we don't have private subnets, but we don't need them since public access
// is not restricted.
Template.fromStack(nested).hasResourceProperties('AWS::Lambda::Function', {
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
VpcConfig: Match.absent(),
});
});
Expand All @@ -2283,12 +2268,10 @@ describe('cluster', () => {
endpointAccess: eks.EndpointAccess.PUBLIC_AND_PRIVATE,
});

const nested = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;

// we have private subnets so we should use them.
const functions = Template.fromStack(nested).findResources('AWS::Lambda::Function');
expect(functions.Handler886CB40B.Properties.VpcConfig.SubnetIds.length).not.toEqual(0);
expect(functions.Handler886CB40B.Properties.VpcConfig.SecurityGroupIds.length).not.toEqual(0);
const functions = Template.fromStack(stack).findResources('AWS::Lambda::Function');
expect(functions.awscdkawseksKubectlProviderHandlerAABA4423.Properties.VpcConfig.SubnetIds.length).not.toEqual(0);
expect(functions.awscdkawseksKubectlProviderHandlerAABA4423.Properties.VpcConfig.SecurityGroupIds.length).not.toEqual(0);
});

test('private and restricted public without private subnets', () => {
Expand All @@ -2313,12 +2296,10 @@ describe('cluster', () => {
endpointAccess: eks.EndpointAccess.PUBLIC_AND_PRIVATE.onlyFrom('1.2.3.4/32'),
});

const nested = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;

// we have private subnets so we should use them.
const functions = Template.fromStack(nested).findResources('AWS::Lambda::Function');
expect(functions.Handler886CB40B.Properties.VpcConfig.SubnetIds.length).not.toEqual(0);
expect(functions.Handler886CB40B.Properties.VpcConfig.SecurityGroupIds.length).not.toEqual(0);
const functions = Template.fromStack(stack).findResources('AWS::Lambda::Function');
expect(functions.awscdkawseksKubectlProviderHandlerAABA4423.Properties.VpcConfig.SubnetIds.length).not.toEqual(0);
expect(functions.awscdkawseksKubectlProviderHandlerAABA4423.Properties.VpcConfig.SecurityGroupIds.length).not.toEqual(0);
});

test('private endpoint access selects only private subnets from looked up vpc', () => {
Expand Down Expand Up @@ -2372,8 +2353,7 @@ describe('cluster', () => {
endpointAccess: eks.EndpointAccess.PRIVATE,
});

const nested = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;
Template.fromStack(nested).hasResourceProperties('AWS::Lambda::Function', {
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
VpcConfig: { SubnetIds: ['subnet-private-in-us-east-1a'] },
});
});
Expand Down Expand Up @@ -2437,8 +2417,7 @@ describe('cluster', () => {
}],
});

const nested = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;
Template.fromStack(nested).hasResourceProperties('AWS::Lambda::Function', {
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
VpcConfig: { SubnetIds: ['subnet-private-in-us-east-1a'] },
});
});
Expand All @@ -2462,11 +2441,10 @@ describe('cluster', () => {
}],
});

const nested = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;
Template.fromStack(nested).hasResourceProperties('AWS::Lambda::Function', {
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
VpcConfig: {
SubnetIds: [
{ Ref: 'referencetoStackVpcPrivateSubnet1Subnet8E6A14CBRef' },
{ Ref: 'VpcPrivateSubnet1Subnet536B997A' },
'subnet-unknown',
],
},
Expand All @@ -2488,8 +2466,7 @@ describe('cluster', () => {
}],
});

const nested = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;
Template.fromStack(nested).hasResourceProperties('AWS::Lambda::Function', {
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
VpcConfig: { SubnetIds: ['subnet1'] },
});
});
Expand Down Expand Up @@ -2541,21 +2518,19 @@ describe('cluster', () => {
},
});

// the kubectl provider is inside a nested stack.
const nested = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;
Template.fromStack(nested).hasResourceProperties('AWS::Lambda::Function', {
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
VpcConfig: {
SecurityGroupIds: [
{
Ref: 'referencetoStackCluster17032651AClusterSecurityGroupId',
'Fn::GetAtt': ['Cluster192CD0375', 'ClusterSecurityGroupId'],
},
],
SubnetIds: [
{
Ref: 'referencetoStackVpcPrivate1Subnet1Subnet6764A0F6Ref',
Ref: 'VpcPrivate1Subnet1SubnetC688B2B1',
},
{
Ref: 'referencetoStackVpcPrivate1Subnet2SubnetDFD49645Ref',
Ref: 'VpcPrivate1Subnet2SubnetA2AF15C7',
},
],
},
Expand Down Expand Up @@ -2604,10 +2579,8 @@ describe('cluster', () => {
},
});

// the kubectl provider is inside a nested stack.
const nested = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;
const functions = Template.fromStack(nested).findResources('AWS::Lambda::Function');
expect(functions.Handler886CB40B.Properties.VpcConfig.SubnetIds.length).toEqual(16);
const functions = Template.fromStack(stack).findResources('AWS::Lambda::Function');
expect(functions.awscdkawseksKubectlProviderHandlerAABA4423.Properties.VpcConfig.SubnetIds.length).toEqual(16);
});

test('kubectl provider considers vpc subnet selection', () => {
Expand Down Expand Up @@ -2653,27 +2626,25 @@ describe('cluster', () => {
},
});

// the kubectl provider is inside a nested stack.
const nested = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;
Template.fromStack(nested).hasResourceProperties('AWS::Lambda::Function', {
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
VpcConfig: {
SecurityGroupIds: [
{
Ref: 'referencetoStackCluster17032651AClusterSecurityGroupId',
'Fn::GetAtt': ['Cluster192CD0375', 'ClusterSecurityGroupId'],
},
],
SubnetIds: [
{
Ref: 'referencetoStackVpcPrivate1Subnet1Subnet6764A0F6Ref',
Ref: 'VpcPrivate1Subnet1SubnetC688B2B1',
},
{
Ref: 'referencetoStackVpcPrivate1Subnet2SubnetDFD49645Ref',
Ref: 'VpcPrivate1Subnet2SubnetA2AF15C7',
},
{
Ref: 'referencetoStackVpcPrivate2Subnet1Subnet586AD392Ref',
Ref: 'VpcPrivate2Subnet1SubnetE13E2E30',
},
{
Ref: 'referencetoStackVpcPrivate2Subnet2SubnetE42148C0Ref',
Ref: 'VpcPrivate2Subnet2Subnet158A38AB',
},
],
},
Expand Down Expand Up @@ -2734,8 +2705,8 @@ describe('cluster', () => {
expect(resources[expectedKubernetesGetId].Properties).toEqual({
ServiceToken: {
'Fn::GetAtt': [
'awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B',
'Outputs.StackawscdkawseksKubectlProviderframeworkonEvent8897FD9BArn',
'awscdkawseksKubectlProviderframeworkonEvent0A650005',
'Arn',
],
},
ClusterName: {
Expand Down Expand Up @@ -2773,10 +2744,9 @@ describe('cluster', () => {
});

// THEN
const providerStack = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;
Template.fromStack(providerStack).hasResourceProperties('AWS::Lambda::Function', {
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
Layers: [
{ Ref: 'AwsCliLayerF44AAF94' },
{ Ref: 'awscdkawseksKubectlProviderAwsCliLayerF72FE066' },
'arn:of:layer',
],
});
Expand Down Expand Up @@ -2833,11 +2803,10 @@ describe('cluster', () => {
});

// THEN
const providerStack = stack.node.tryFindChild('@aws-cdk/aws-eks.KubectlProvider') as cdk.NestedStack;
Template.fromStack(providerStack).hasResourceProperties('AWS::Lambda::Function', {
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
Layers: [
'arn:of:layer',
{ Ref: 'KubectlLayer600207B5' },
{ Ref: 'awscdkawseksKubectlProviderKubectlLayerA7F2FE55' },
],
});
});
Expand Down Expand Up @@ -2870,42 +2839,6 @@ describe('cluster', () => {
});
});

test('custom memory size for kubectl provider', () => {
// GIVEN
const { stack, vpc, app } = testFixture();

// WHEN
new eks.Cluster(stack, 'Cluster', {
vpc,
version: CLUSTER_VERSION,
kubectlMemory: cdk.Size.gibibytes(2),
});

// THEN
const casm = app.synth();
const providerNestedStackTemplate = JSON.parse(fs.readFileSync(path.join(casm.directory, 'StackawscdkawseksKubectlProvider7346F799.nested.template.json'), 'utf-8'));
expect(providerNestedStackTemplate?.Resources?.Handler886CB40B?.Properties?.MemorySize).toEqual(2048);
});

test('custom memory size for imported clusters', () => {
// GIVEN
const { stack, app } = testFixture();

// WHEN
const cluster = eks.Cluster.fromClusterAttributes(stack, 'Imported', {
clusterName: 'my-cluster',
kubectlRoleArn: 'arn:aws:iam::123456789012:role/MyRole',
kubectlMemory: cdk.Size.gibibytes(4),
});

cluster.addManifest('foo', { bar: 123 });

// THEN
const casm = app.synth();
const providerNestedStackTemplate = JSON.parse(fs.readFileSync(path.join(casm.directory, 'StackStackImported1CBA9C50KubectlProviderAA00BA49.nested.template.json'), 'utf-8'));
expect(providerNestedStackTemplate?.Resources?.Handler886CB40B?.Properties?.MemorySize).toEqual(4096);
});

test('create a cluster using custom kubernetes network config', () => {
// GIVEN
const { stack } = testFixture();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ describe('k8s object value', () => {
Properties: {
ServiceToken: {
'Fn::GetAtt': [
'awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B',
'Outputs.awscdkawseksKubectlProviderframeworkonEvent0A650005Arn',
'awscdkawseksKubectlProviderframeworkonEvent0A650005',
'Arn',
],
},
ClusterName: { Ref: 'MyCluster4C1BA579' },
Expand Down Expand Up @@ -70,8 +70,8 @@ describe('k8s object value', () => {
Properties: {
ServiceToken: {
'Fn::GetAtt': [
'awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B',
'Outputs.awscdkawseksKubectlProviderframeworkonEvent0A650005Arn',
'awscdkawseksKubectlProviderframeworkonEvent0A650005',
'Arn',
],
},
ClusterName: { Ref: 'MyCluster4C1BA579' },
Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-eks-v2-alpha/test/k8s-patch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ describe('k8s patch', () => {
Template.fromStack(stack).hasResourceProperties('Custom::AWSCDK-EKS-KubernetesPatch', {
ServiceToken: {
'Fn::GetAtt': [
'awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B',
'Outputs.awscdkawseksKubectlProviderframeworkonEvent0A650005Arn',
'awscdkawseksKubectlProviderframeworkonEvent0A650005',
'Arn',
],
},
ResourceName: 'myResourceName',
Expand Down
Loading

0 comments on commit 8a96454

Please sign in to comment.