Skip to content

Commit

Permalink
Fix EKS autoMode preview with unknown values (#1603)
Browse files Browse the repository at this point in the history
The diff customizer of the upstream provider is not taking possibly
unknown values into account (see
https://github.com/hashicorp/terraform-provider-aws/blob/ae93494f39ba70fe442e891caf05f8df21bde1ac/internal/service/eks/cluster.go#L1776-L1791),
which causes failures like this one:
```
* compute_config.enabled, kubernetes_networking_config.elastic_load_balancing.enabled, and storage_config.block_storage.enabled must all be set to either true or false
```
This happens because `unknown` attributes just default to their empty
values in a diff customizer if they're unknown .

This change acts a hot fix until we can properly fix upstream's behavior
here. The current diff for auto mode is quite broken and needs some more
involved fixes (see
hashicorp/terraform-provider-aws#40582).

Fixes #1597
  • Loading branch information
flostadler authored Jan 29, 2025
1 parent e2e7a7a commit 8800ecb
Show file tree
Hide file tree
Showing 10 changed files with 286 additions and 12 deletions.
47 changes: 35 additions & 12 deletions nodejs/eks/cluster/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -642,20 +642,43 @@ export function createCore(
);
}

let computeConfig: pulumi.Input<aws.types.input.eks.ClusterComputeConfig> | undefined;
let computeConfig: pulumi.Output<aws.types.input.eks.ClusterComputeConfig> | undefined;
if (args.autoMode?.enabled) {
computeConfig = pulumi.output(args.autoMode.computeConfig).apply((config) => {
return {
enabled: true,
nodeRoleArn: eksAutoNodeRole?.directRole.arn,
nodePools: ["general-purpose", "system"],
...config,
};
});
computeConfig = pulumi
.all([args.autoMode.computeConfig, eksAutoNodeRole?.directRole.arn])
.apply(([config, nodeRoleArn]) => {
return {
enabled: true,
nodeRoleArn,
nodePools: ["general-purpose", "system"],
...config,
};
});
}

const storageConfig = args.autoMode?.enabled ? { blockStorage: { enabled: true } } : undefined;

// The upstream EKS cluster resource requires that all auto mode settings
// are either enabled or disabled and does not handle unknown values.
// Make all eks auto mode options depend on the other options to ensure
// that they're all either known or unknown when auto mode is enabled.
const autoModeConfig =
args.autoMode?.enabled && computeConfig && storageConfig && kubernetesNetworkConfig
? pulumi
.all([computeConfig, storageConfig, kubernetesNetworkConfig])
.apply(([computeConfig, storageConfig, kubernetesNetworkConfig]) => {
return {
computeConfig,
storageConfig,
kubernetesNetworkConfig,
};
})
: {
computeConfig,
storageConfig,
kubernetesNetworkConfig,
};

// Create the EKS cluster
const eksCluster = new aws.eks.Cluster(
`${name}-eksCluster`,
Expand All @@ -664,8 +687,9 @@ export function createCore(
roleArn: args.serviceRole
? pulumi.output(args.serviceRole).arn
: eksServiceRole?.directRole.arn!,
computeConfig,
storageConfig,
computeConfig: autoModeConfig.computeConfig,
storageConfig: autoModeConfig.storageConfig,
kubernetesNetworkConfig: autoModeConfig.kubernetesNetworkConfig,
// When a cluster is created with EKS Auto Mode, it must be created without the addons
bootstrapSelfManagedAddons: args.autoMode?.enabled ? false : undefined,
vpcConfig: {
Expand Down Expand Up @@ -701,7 +725,6 @@ export function createCore(
},
),
encryptionConfig,
kubernetesNetworkConfig,
accessConfig: args.authenticationMode
? {
authenticationMode: args.authenticationMode,
Expand Down
39 changes: 39 additions & 0 deletions tests/nodejs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1118,6 +1118,45 @@ func TestAccEfa(t *testing.T) {
programTestWithExtraOptions(t, &test, nil)
}

func TestAccAutoModeCustomRole(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}

test := getJSBaseOptions(t).
With(integration.ProgramTestOptions{
Dir: path.Join(getTestPrograms(t), "auto-mode-custom-role"),
ExtraRuntimeValidation: func(t *testing.T, info integration.RuntimeValidationStackInfo) {
utils.ValidateClusters(t, info.Deployment.Resources,
utils.WithKubeConfigs(info.Outputs["kubeconfig"]),
utils.ValidateDaemonSets(), // no daemonsets in auto mode
utils.ValidateDeployments(
utils.KubernetesResource{Name: "nginx", Namespace: "nginx"},
utils.KubernetesResource{Name: "coredns", Namespace: "kube-system"},
),
)
},
})

programTestWithExtraOptions(t, &test, nil)
}

func TestAccAutoModePreview(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
cwd, err := os.Getwd()
require.NoError(t, err)
options := []opttest.Option{
opttest.LocalProviderPath("eks", filepath.Join(cwd, "..", "bin")),
opttest.YarnLink("@pulumi/eks"),
}
pt := pulumitest.NewPulumiTest(t, path.Join(getTestPrograms(t), "auto-mode-preview"), options...)

previewResult := pt.Preview(t)
t.Logf("Preview:\n%s", previewResult.StdOut)
}

func randomString(lenght int) string {
const charset = "abcdefghijklmnopqrstuvwxyz0123456789"
random := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
Expand Down
3 changes: 3 additions & 0 deletions tests/testdata/programs/auto-mode-custom-role/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: auto-mode-custom-role
description: EKS Cluster in auto mode with custom node role
runtime: nodejs
51 changes: 51 additions & 0 deletions tests/testdata/programs/auto-mode-custom-role/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import * as awsx from "@pulumi/awsx";
import * as eks from "@pulumi/eks";
import * as aws from "@pulumi/aws";

const eksVpc = new awsx.ec2.Vpc("auto-mode-custom-role", {
enableDnsHostnames: true,
cidrBlock: "10.0.0.0/16",
numberOfAvailabilityZones: 2,
subnetStrategy: "Auto",
});

const nodeRole = new aws.iam.Role("auto-mode-custom-role", {
assumeRolePolicy: aws.iam.getPolicyDocumentOutput({
version: "2012-10-17",
statements: [{
effect: "Allow",
principals: [{
type: "Service",
identifiers: ["ec2.amazonaws.com"]
}],
actions: ["sts:AssumeRole", "sts:TagSession"]
}]
}).json
});

const attachments = [
new aws.iam.RolePolicyAttachment("eks-node-role-policy-worker-node-minimal", {
role: nodeRole,
policyArn: "arn:aws:iam::aws:policy/AmazonEKSWorkerNodeMinimalPolicy",
}),
new aws.iam.RolePolicyAttachment("eks-node-role-policy-ecr-pull", {
role: nodeRole,
policyArn: "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPullOnly",
}),
];

const cluster = new eks.Cluster("auto-mode-custom-role", {
vpcId: eksVpc.vpcId,
authenticationMode: eks.AuthenticationMode.Api,
publicSubnetIds: eksVpc.publicSubnetIds,
privateSubnetIds: eksVpc.privateSubnetIds,
autoMode: {
enabled: true,
createNodeRole: false,
computeConfig: {
nodeRoleArn: nodeRole.arn,
}
}
}, { dependsOn: [...attachments] });

export const kubeconfig = cluster.kubeconfig;
12 changes: 12 additions & 0 deletions tests/testdata/programs/auto-mode-custom-role/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "auto-mode-custom-role",
"devDependencies": {
"typescript": "^4.0.0",
"@types/node": "latest"
},
"dependencies": {
"@pulumi/awsx": "^2.0.2",
"@pulumi/eks": "^3.0.0",
"@pulumi/pulumi": "^3.113.0"
}
}
24 changes: 24 additions & 0 deletions tests/testdata/programs/auto-mode-custom-role/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"compilerOptions": {
"outDir": "bin",
"target": "es6",
"lib": [
"es6"
],
"module": "commonjs",
"moduleResolution": "node",
"declaration": true,
"sourceMap": true,
"stripInternal": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true,
"strictNullChecks": true
},
"files": [
"index.ts"
]
}
3 changes: 3 additions & 0 deletions tests/testdata/programs/auto-mode-preview/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: auto-mode-preview
description: EKS Cluster in auto mode
runtime: nodejs
82 changes: 82 additions & 0 deletions tests/testdata/programs/auto-mode-preview/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import * as awsx from "@pulumi/awsx";
import * as eks from "@pulumi/eks";
import * as aws from "@pulumi/aws";
import * as random from "@pulumi/random";

const eksVpc = new awsx.ec2.Vpc("eks-vpc", {
enableDnsHostnames: true,
cidrBlock: "10.0.0.0/16",
numberOfAvailabilityZones: 2,
subnetStrategy: "Auto",
});

const nodeRole = new aws.iam.Role("eks-node-role", {
assumeRolePolicy: aws.iam.getPolicyDocumentOutput({
version: "2012-10-17",
statements: [{
effect: "Allow",
principals: [{
type: "Service",
identifiers: ["ec2.amazonaws.com"]
}],
actions: ["sts:AssumeRole", "sts:TagSession"]
}]
}).json
});

const attachments = [
new aws.iam.RolePolicyAttachment("eks-node-role-policy-worker-node-minimal", {
role: nodeRole,
policyArn: "arn:aws:iam::aws:policy/AmazonEKSWorkerNodeMinimalPolicy",
}),
new aws.iam.RolePolicyAttachment("eks-node-role-policy-ecr-pull", {
role: nodeRole,
policyArn: "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPullOnly",
}),
];

const randomId = new random.RandomId("random-id", {
byteLength: 8,
});

new eks.Cluster("eks-cluster-unknown-compute-config", {
vpcId: eksVpc.vpcId,
authenticationMode: eks.AuthenticationMode.Api,
publicSubnetIds: eksVpc.publicSubnetIds,
privateSubnetIds: eksVpc.privateSubnetIds,
autoMode: {
enabled: true,
createNodeRole: false,
computeConfig: {
nodeRoleArn: nodeRole.arn,
}
}
}, { dependsOn: [...attachments] });

new eks.Cluster("eks-cluster-unknown-ip-family", {
vpcId: eksVpc.vpcId,
authenticationMode: eks.AuthenticationMode.Api,
publicSubnetIds: eksVpc.publicSubnetIds,
privateSubnetIds: eksVpc.privateSubnetIds,
ipFamily: randomId.dec.apply(_ => "ipv4"),
autoMode: {
enabled: true,
}
});

new eks.Cluster("auto-mode", {
vpcId: eksVpc.vpcId,
authenticationMode: eks.AuthenticationMode.Api,
publicSubnetIds: eksVpc.publicSubnetIds,
privateSubnetIds: eksVpc.privateSubnetIds,
autoMode: {
enabled: true,
}
});

new eks.Cluster("regular-cluster", {
vpcId: eksVpc.vpcId,
authenticationMode: eks.AuthenticationMode.Api,
publicSubnetIds: eksVpc.publicSubnetIds,
privateSubnetIds: eksVpc.privateSubnetIds,
});
13 changes: 13 additions & 0 deletions tests/testdata/programs/auto-mode-preview/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "auto-mode-preview",
"devDependencies": {
"typescript": "^4.0.0",
"@types/node": "latest"
},
"dependencies": {
"@pulumi/awsx": "^2.0.2",
"@pulumi/eks": "^3.0.0",
"@pulumi/pulumi": "^3.113.0",
"@pulumi/random": "^4.17.0"
}
}
24 changes: 24 additions & 0 deletions tests/testdata/programs/auto-mode-preview/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"compilerOptions": {
"outDir": "bin",
"target": "es6",
"lib": [
"es6"
],
"module": "commonjs",
"moduleResolution": "node",
"declaration": true,
"sourceMap": true,
"stripInternal": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true,
"strictNullChecks": true
},
"files": [
"index.ts"
]
}

0 comments on commit 8800ecb

Please sign in to comment.