From 73f839f98ec8aa82979877377d0aafd99d5904c3 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Tue, 10 Sep 2024 16:34:52 -0500 Subject: [PATCH 1/3] fix: Correct the AMI selector label requirements for NVIDIA and Neuron variants --- pkg/providers/amifamily/types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/providers/amifamily/types.go b/pkg/providers/amifamily/types.go index ac37d20b06b0..5dae3150a1cc 100644 --- a/pkg/providers/amifamily/types.go +++ b/pkg/providers/amifamily/types.go @@ -82,9 +82,9 @@ func (v Variant) Requirements() scheduling.Requirements { scheduling.NewRequirement(v1.LabelInstanceGPUCount, corev1.NodeSelectorOpDoesNotExist), ) case VariantNvidia: - return scheduling.NewRequirements(scheduling.NewRequirement(v1.LabelInstanceAcceleratorCount, corev1.NodeSelectorOpExists)) - case VariantNeuron: return scheduling.NewRequirements(scheduling.NewRequirement(v1.LabelInstanceGPUCount, corev1.NodeSelectorOpExists)) + case VariantNeuron: + return scheduling.NewRequirements(scheduling.NewRequirement(v1.LabelInstanceAcceleratorCount, corev1.NodeSelectorOpExists)) } return nil } From 573a01773efe99a4509bd7a97046cba3d34e37a2 Mon Sep 17 00:00:00 2001 From: Jason Deal Date: Wed, 11 Sep 2024 18:31:24 -0700 Subject: [PATCH 2/3] test: add tests for all amifamilies with reqs --- pkg/controllers/nodeclass/status/ami_test.go | 493 +++++++++++++++---- 1 file changed, 394 insertions(+), 99 deletions(-) diff --git a/pkg/controllers/nodeclass/status/ami_test.go b/pkg/controllers/nodeclass/status/ami_test.go index 6ce1caefc5ea..7618f56d6275 100644 --- a/pkg/controllers/nodeclass/status/ami_test.go +++ b/pkg/controllers/nodeclass/status/ami_test.go @@ -33,7 +33,9 @@ import ( ) var _ = Describe("NodeClass AMI Status Controller", func() { + var k8sVersion string BeforeEach(func() { + k8sVersion = lo.Must(awsEnv.VersionProvider.Get(ctx)) nodeClass = test.EC2NodeClass(v1.EC2NodeClass{ Spec: v1.EC2NodeClassSpec{ SubnetSelectorTerms: []v1.SubnetSelectorTerm{ @@ -89,133 +91,426 @@ var _ = Describe("NodeClass AMI Status Controller", func() { }, }) }) - It("should resolve amiSelector AMIs and requirements into status", func() { - version := lo.Must(awsEnv.VersionProvider.Get(ctx)) + Context("Aliases", func() { + BeforeEach(func() { + awsEnv.EC2API.DescribeImagesOutput.Set(&ec2.DescribeImagesOutput{ + Images: []*ec2.Image{ + { + Name: aws.String("amd64-standard"), + ImageId: aws.String("ami-amd64-standard"), + CreationDate: aws.String(time.Now().Format(time.RFC3339)), + Architecture: aws.String("x86_64"), + Tags: []*ec2.Tag{ + {Key: aws.String("Name"), Value: aws.String("test-ami-1")}, + {Key: aws.String("foo"), Value: aws.String("bar")}, + }, + }, + { + Name: aws.String("amd64-nvidia"), + ImageId: aws.String("ami-amd64-nvidia"), + CreationDate: aws.String(time.Now().Add(time.Minute).Format(time.RFC3339)), + Architecture: aws.String("x86_64"), + Tags: []*ec2.Tag{ + {Key: aws.String("Name"), Value: aws.String("test-ami-2")}, + {Key: aws.String("foo"), Value: aws.String("bar")}, + }, + }, + { + Name: aws.String("amd64-neuron"), + ImageId: aws.String("ami-amd64-neuron"), + CreationDate: aws.String(time.Now().Add(2 * time.Minute).Format(time.RFC3339)), + Architecture: aws.String("x86_64"), + Tags: []*ec2.Tag{ + {Key: aws.String("Name"), Value: aws.String("test-ami-3")}, + {Key: aws.String("foo"), Value: aws.String("bar")}, + }, + }, + { + Name: aws.String("arm64-standard"), + ImageId: aws.String("ami-arm64-standard"), + CreationDate: aws.String(time.Now().Format(time.RFC3339)), + Architecture: aws.String("arm64"), + Tags: []*ec2.Tag{ + {Key: aws.String("Name"), Value: aws.String("test-ami-1")}, + {Key: aws.String("foo"), Value: aws.String("bar")}, + }, + }, + { + Name: aws.String("arm64-nvidia"), + ImageId: aws.String("ami-arm64-nvidia"), + CreationDate: aws.String(time.Now().Add(time.Minute).Format(time.RFC3339)), + Architecture: aws.String("arm64"), + Tags: []*ec2.Tag{ + {Key: aws.String("Name"), Value: aws.String("test-ami-2")}, + {Key: aws.String("foo"), Value: aws.String("bar")}, + }, + }, + }, + }) - awsEnv.SSMAPI.Parameters = map[string]string{ - fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2/recommended/image_id", version): "ami-id-123", - fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2-gpu/recommended/image_id", version): "ami-id-456", - fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2%s/recommended/image_id", version, fmt.Sprintf("-%s", karpv1.ArchitectureArm64)): "ami-id-789", - } + }) + It("Should resolve all AMIs with correct requirements for AL2023", func() { + awsEnv.SSMAPI.Parameters = map[string]string{ + fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2023/x86_64/standard/recommended/image_id", k8sVersion): "ami-amd64-standard", + fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2023/x86_64/nvidia/recommended/image_id", k8sVersion): "ami-amd64-nvidia", + fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2023/x86_64/neuron/recommended/image_id", k8sVersion): "ami-amd64-neuron", + fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2023/arm64/standard/recommended/image_id", k8sVersion): "ami-arm64-standard", + } + nodeClass.Spec.AMISelectorTerms = []v1.AMISelectorTerm{{Alias: "al2023@latest"}} + ExpectApplied(ctx, env.Client, nodeClass) + ExpectObjectReconciled(ctx, env.Client, statusController, nodeClass) + nodeClass = ExpectExists(ctx, env.Client, nodeClass) - awsEnv.EC2API.DescribeImagesOutput.Set(&ec2.DescribeImagesOutput{ - Images: []*ec2.Image{ + Expect(len(nodeClass.Status.AMIs)).To(Equal(4)) + Expect(nodeClass.Status.AMIs).To(ContainElements([]v1.AMI{ { - Name: aws.String("test-ami-1"), - ImageId: aws.String("ami-id-123"), - CreationDate: aws.String(time.Now().Format(time.RFC3339)), - Architecture: aws.String("x86_64"), - Tags: []*ec2.Tag{ - {Key: aws.String("Name"), Value: aws.String("test-ami-1")}, - {Key: aws.String("foo"), Value: aws.String("bar")}, + Name: "amd64-standard", + ID: "ami-amd64-standard", + Requirements: []corev1.NodeSelectorRequirement{ + { + Key: corev1.LabelArchStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{karpv1.ArchitectureAmd64}, + }, + { + Key: v1.LabelInstanceGPUCount, + Operator: corev1.NodeSelectorOpDoesNotExist, + }, + { + Key: v1.LabelInstanceAcceleratorCount, + Operator: corev1.NodeSelectorOpDoesNotExist, + }, }, }, { - Name: aws.String("test-ami-2"), - ImageId: aws.String("ami-id-456"), - CreationDate: aws.String(time.Now().Add(time.Minute).Format(time.RFC3339)), - Architecture: aws.String("x86_64"), - Tags: []*ec2.Tag{ - {Key: aws.String("Name"), Value: aws.String("test-ami-2")}, - {Key: aws.String("foo"), Value: aws.String("bar")}, + Name: "amd64-nvidia", + ID: "ami-amd64-nvidia", + Requirements: []corev1.NodeSelectorRequirement{ + { + Key: corev1.LabelArchStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{karpv1.ArchitectureAmd64}, + }, + { + Key: v1.LabelInstanceGPUCount, + Operator: corev1.NodeSelectorOpExists, + }, }, }, { - Name: aws.String("test-ami-3"), - ImageId: aws.String("ami-id-789"), - CreationDate: aws.String(time.Now().Add(2 * time.Minute).Format(time.RFC3339)), - Architecture: aws.String("arm64"), - Tags: []*ec2.Tag{ - {Key: aws.String("Name"), Value: aws.String("test-ami-3")}, - {Key: aws.String("foo"), Value: aws.String("bar")}, + Name: "amd64-neuron", + ID: "ami-amd64-neuron", + Requirements: []corev1.NodeSelectorRequirement{ + { + Key: corev1.LabelArchStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{karpv1.ArchitectureAmd64}, + }, + { + Key: v1.LabelInstanceAcceleratorCount, + Operator: corev1.NodeSelectorOpExists, + }, }, }, - }, + { + Name: "arm64-standard", + ID: "ami-arm64-standard", + Requirements: []corev1.NodeSelectorRequirement{ + { + Key: corev1.LabelArchStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{karpv1.ArchitectureArm64}, + }, + { + Key: v1.LabelInstanceGPUCount, + Operator: corev1.NodeSelectorOpDoesNotExist, + }, + { + Key: v1.LabelInstanceAcceleratorCount, + Operator: corev1.NodeSelectorOpDoesNotExist, + }, + }, + }, + })) + Expect(nodeClass.StatusConditions().IsTrue(v1.ConditionTypeAMIsReady)).To(BeTrue()) }) - nodeClass.Spec.AMIFamily = lo.ToPtr(v1.AMIFamilyAL2) - nodeClass.Spec.AMISelectorTerms = []v1.AMISelectorTerm{{Alias: "al2@latest"}} - ExpectApplied(ctx, env.Client, nodeClass) - ExpectObjectReconciled(ctx, env.Client, statusController, nodeClass) - nodeClass = ExpectExists(ctx, env.Client, nodeClass) - Expect(len(nodeClass.Status.AMIs)).To(Equal(4)) - Expect(nodeClass.Status.AMIs).To(ContainElements([]v1.AMI{ - { - Name: "test-ami-3", - ID: "ami-id-789", - Requirements: []corev1.NodeSelectorRequirement{ - { - Key: corev1.LabelArchStable, - Operator: corev1.NodeSelectorOpIn, - Values: []string{karpv1.ArchitectureArm64}, + It("Should resolve all AMIs with correct requirements for AL2", func() { + awsEnv.SSMAPI.Parameters = map[string]string{ + fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2/recommended/image_id", k8sVersion): "ami-amd64-standard", + fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2-gpu/recommended/image_id", k8sVersion): "ami-amd64-nvidia", + fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2-arm64/recommended/image_id", k8sVersion): "ami-arm64-standard", + } + nodeClass.Spec.AMISelectorTerms = []v1.AMISelectorTerm{{Alias: "al2@latest"}} + ExpectApplied(ctx, env.Client, nodeClass) + ExpectObjectReconciled(ctx, env.Client, statusController, nodeClass) + nodeClass = ExpectExists(ctx, env.Client, nodeClass) + + Expect(len(nodeClass.Status.AMIs)).To(Equal(4)) + Expect(nodeClass.Status.AMIs).To(ContainElements([]v1.AMI{ + { + Name: "amd64-standard", + ID: "ami-amd64-standard", + Requirements: []corev1.NodeSelectorRequirement{ + { + Key: corev1.LabelArchStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{karpv1.ArchitectureAmd64}, + }, + { + Key: v1.LabelInstanceGPUCount, + Operator: corev1.NodeSelectorOpDoesNotExist, + }, + { + Key: v1.LabelInstanceAcceleratorCount, + Operator: corev1.NodeSelectorOpDoesNotExist, + }, }, - { - Key: v1.LabelInstanceGPUCount, - Operator: corev1.NodeSelectorOpDoesNotExist, + }, + { + Name: "amd64-nvidia", + ID: "ami-amd64-nvidia", + Requirements: []corev1.NodeSelectorRequirement{ + { + Key: corev1.LabelArchStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{karpv1.ArchitectureAmd64}, + }, + { + Key: v1.LabelInstanceGPUCount, + Operator: corev1.NodeSelectorOpExists, + }, }, - { - Key: v1.LabelInstanceAcceleratorCount, - Operator: corev1.NodeSelectorOpDoesNotExist, + }, + // Note: AL2 uses the same AMI for nvidia and neuron, we use the nvidia AMI here + { + Name: "amd64-nvidia", + ID: "ami-amd64-nvidia", + Requirements: []corev1.NodeSelectorRequirement{ + { + Key: corev1.LabelArchStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{karpv1.ArchitectureAmd64}, + }, + { + Key: v1.LabelInstanceAcceleratorCount, + Operator: corev1.NodeSelectorOpExists, + }, }, }, - }, - { - Name: "test-ami-2", - ID: "ami-id-456", - Requirements: []corev1.NodeSelectorRequirement{ - { - Key: corev1.LabelArchStable, - Operator: corev1.NodeSelectorOpIn, - Values: []string{karpv1.ArchitectureAmd64}, + { + Name: "arm64-standard", + ID: "ami-arm64-standard", + Requirements: []corev1.NodeSelectorRequirement{ + { + Key: corev1.LabelArchStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{karpv1.ArchitectureArm64}, + }, + { + Key: v1.LabelInstanceGPUCount, + Operator: corev1.NodeSelectorOpDoesNotExist, + }, + { + Key: v1.LabelInstanceAcceleratorCount, + Operator: corev1.NodeSelectorOpDoesNotExist, + }, }, - { - Key: v1.LabelInstanceGPUCount, - Operator: corev1.NodeSelectorOpExists, + }, + })) + Expect(nodeClass.StatusConditions().IsTrue(v1.ConditionTypeAMIsReady)).To(BeTrue()) + }) + It("Should resolve all AMIs with correct requirements for Bottlerocket", func() { + awsEnv.SSMAPI.Parameters = map[string]string{ + fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s/x86_64/latest/image_id", k8sVersion): "ami-amd64-standard", + fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s/arm64/latest/image_id", k8sVersion): "ami-arm64-standard", + fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s-nvidia/x86_64/latest/image_id", k8sVersion): "ami-amd64-nvidia", + fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s-nvidia/arm64/latest/image_id", k8sVersion): "ami-arm64-nvidia", + } + nodeClass.Spec.AMISelectorTerms = []v1.AMISelectorTerm{{Alias: "bottlerocket@latest"}} + ExpectApplied(ctx, env.Client, nodeClass) + ExpectObjectReconciled(ctx, env.Client, statusController, nodeClass) + nodeClass = ExpectExists(ctx, env.Client, nodeClass) + + Expect(len(nodeClass.Status.AMIs)).To(Equal(6)) + Expect(nodeClass.Status.AMIs).To(ContainElements([]v1.AMI{ + { + Name: "amd64-standard", + ID: "ami-amd64-standard", + Requirements: []corev1.NodeSelectorRequirement{ + { + Key: corev1.LabelArchStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{karpv1.ArchitectureAmd64}, + }, + { + Key: v1.LabelInstanceGPUCount, + Operator: corev1.NodeSelectorOpDoesNotExist, + }, + { + Key: v1.LabelInstanceAcceleratorCount, + Operator: corev1.NodeSelectorOpDoesNotExist, + }, }, }, - }, - { - Name: "test-ami-2", - ID: "ami-id-456", - Requirements: []corev1.NodeSelectorRequirement{ - { - Key: corev1.LabelArchStable, - Operator: corev1.NodeSelectorOpIn, - Values: []string{karpv1.ArchitectureAmd64}, + { + Name: "arm64-standard", + ID: "ami-arm64-standard", + Requirements: []corev1.NodeSelectorRequirement{ + { + Key: corev1.LabelArchStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{karpv1.ArchitectureArm64}, + }, + { + Key: v1.LabelInstanceGPUCount, + Operator: corev1.NodeSelectorOpDoesNotExist, + }, + { + Key: v1.LabelInstanceAcceleratorCount, + Operator: corev1.NodeSelectorOpDoesNotExist, + }, }, - { - Key: v1.LabelInstanceAcceleratorCount, - Operator: corev1.NodeSelectorOpExists, + }, + { + Name: "amd64-nvidia", + ID: "ami-amd64-nvidia", + Requirements: []corev1.NodeSelectorRequirement{ + { + Key: corev1.LabelArchStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{karpv1.ArchitectureAmd64}, + }, + { + Key: v1.LabelInstanceGPUCount, + Operator: corev1.NodeSelectorOpExists, + }, }, }, - }, - { - Name: "test-ami-1", - ID: "ami-id-123", - Requirements: []corev1.NodeSelectorRequirement{ - { - Key: corev1.LabelArchStable, - Operator: corev1.NodeSelectorOpIn, - Values: []string{karpv1.ArchitectureAmd64}, + { + Name: "arm64-nvidia", + ID: "ami-arm64-nvidia", + Requirements: []corev1.NodeSelectorRequirement{ + { + Key: corev1.LabelArchStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{karpv1.ArchitectureArm64}, + }, + { + Key: v1.LabelInstanceGPUCount, + Operator: corev1.NodeSelectorOpExists, + }, }, - { - Key: v1.LabelInstanceGPUCount, - Operator: corev1.NodeSelectorOpDoesNotExist, + }, + // Note: Bottlerocket uses the same AMI for nvidia and neuron, we use the nvidia AMI here + { + Name: "amd64-nvidia", + ID: "ami-amd64-nvidia", + Requirements: []corev1.NodeSelectorRequirement{ + { + Key: corev1.LabelArchStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{karpv1.ArchitectureAmd64}, + }, + { + Key: v1.LabelInstanceAcceleratorCount, + Operator: corev1.NodeSelectorOpExists, + }, }, - { - Key: v1.LabelInstanceAcceleratorCount, - Operator: corev1.NodeSelectorOpDoesNotExist, + }, + { + Name: "arm64-nvidia", + ID: "ami-arm64-nvidia", + Requirements: []corev1.NodeSelectorRequirement{ + { + Key: corev1.LabelArchStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{karpv1.ArchitectureArm64}, + }, + { + Key: v1.LabelInstanceAcceleratorCount, + Operator: corev1.NodeSelectorOpExists, + }, }, }, - }, - })) - Expect(nodeClass.StatusConditions().IsTrue(v1.ConditionTypeAMIsReady)).To(BeTrue()) + })) + Expect(nodeClass.StatusConditions().IsTrue(v1.ConditionTypeAMIsReady)).To(BeTrue()) + }) + It("Should resolve all AMIs with correct requirements for Windows2019", func() { + awsEnv.SSMAPI.Parameters = map[string]string{ + fmt.Sprintf("/aws/service/ami-windows-latest/Windows_Server-2019-English-Core-EKS_Optimized-%s/image_id", k8sVersion): "ami-amd64-standard", + } + nodeClass.Spec.AMISelectorTerms = []v1.AMISelectorTerm{{Alias: "windows2019@latest"}} + ExpectApplied(ctx, env.Client, nodeClass) + ExpectObjectReconciled(ctx, env.Client, statusController, nodeClass) + nodeClass = ExpectExists(ctx, env.Client, nodeClass) + + Expect(len(nodeClass.Status.AMIs)).To(Equal(1)) + Expect(nodeClass.Status.AMIs).To(ContainElements([]v1.AMI{ + { + Name: "amd64-standard", + ID: "ami-amd64-standard", + Requirements: []corev1.NodeSelectorRequirement{ + { + Key: corev1.LabelOSStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{string(corev1.Windows)}, + }, + { + Key: corev1.LabelArchStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{karpv1.ArchitectureAmd64}, + }, + { + Key: corev1.LabelWindowsBuild, + Operator: corev1.NodeSelectorOpIn, + Values: []string{v1.Windows2019Build}, + }, + }, + }, + })) + Expect(nodeClass.StatusConditions().IsTrue(v1.ConditionTypeAMIsReady)).To(BeTrue()) + }) + It("Should resolve all AMIs with correct requirements for Windows2022", func() { + awsEnv.SSMAPI.Parameters = map[string]string{ + fmt.Sprintf("/aws/service/ami-windows-latest/Windows_Server-2022-English-Core-EKS_Optimized-%s/image_id", k8sVersion): "ami-amd64-standard", + } + nodeClass.Spec.AMISelectorTerms = []v1.AMISelectorTerm{{Alias: "windows2022@latest"}} + ExpectApplied(ctx, env.Client, nodeClass) + ExpectObjectReconciled(ctx, env.Client, statusController, nodeClass) + nodeClass = ExpectExists(ctx, env.Client, nodeClass) + + Expect(len(nodeClass.Status.AMIs)).To(Equal(1)) + Expect(nodeClass.Status.AMIs).To(ContainElements([]v1.AMI{ + { + Name: "amd64-standard", + ID: "ami-amd64-standard", + Requirements: []corev1.NodeSelectorRequirement{ + { + Key: corev1.LabelOSStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{string(corev1.Windows)}, + }, + { + Key: corev1.LabelArchStable, + Operator: corev1.NodeSelectorOpIn, + Values: []string{karpv1.ArchitectureAmd64}, + }, + { + Key: corev1.LabelWindowsBuild, + Operator: corev1.NodeSelectorOpIn, + Values: []string{v1.Windows2022Build}, + }, + }, + }, + })) + Expect(nodeClass.StatusConditions().IsTrue(v1.ConditionTypeAMIsReady)).To(BeTrue()) + }) }) - It("should resolve amiSelector AMis and requirements into status when all SSM aliases don't resolve", func() { - version := lo.Must(awsEnv.VersionProvider.Get(ctx)) + It("should resolve amiSelector AMis and requirements into status when all SSM parameters don't resolve", func() { // This parameter set doesn't include any of the Nvidia AMIs awsEnv.SSMAPI.Parameters = map[string]string{ - fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s/x86_64/latest/image_id", version): "ami-id-123", - fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s/arm64/latest/image_id", version): "ami-id-456", + fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s/x86_64/latest/image_id", k8sVersion): "ami-id-123", + fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s/arm64/latest/image_id", k8sVersion): "ami-id-456", } nodeClass.Spec.AMISelectorTerms = []v1.AMISelectorTerm{{ Alias: "bottlerocket@latest", @@ -291,7 +586,7 @@ var _ = Describe("NodeClass AMI Status Controller", func() { })) Expect(nodeClass.StatusConditions().IsTrue(v1.ConditionTypeAMIsReady)).To(BeTrue()) }) - It("Should resolve a valid AMI selector", func() { + It("should resolve a valid AMI selector", func() { ExpectApplied(ctx, env.Client, nodeClass) ExpectObjectReconciled(ctx, env.Client, statusController, nodeClass) nodeClass = ExpectExists(ctx, env.Client, nodeClass) From 00d59a00c219f255bbf2d3eaf7ca49d337b470f0 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Fri, 13 Sep 2024 14:12:17 -0500 Subject: [PATCH 3/3] chore: Run `make codegen` and `go fmt` --- pkg/controllers/nodeclass/status/ami_test.go | 177 +++++++------------ 1 file changed, 64 insertions(+), 113 deletions(-) diff --git a/pkg/controllers/nodeclass/status/ami_test.go b/pkg/controllers/nodeclass/status/ami_test.go index 7618f56d6275..16cfaf6682de 100644 --- a/pkg/controllers/nodeclass/status/ami_test.go +++ b/pkg/controllers/nodeclass/status/ami_test.go @@ -59,101 +59,74 @@ var _ = Describe("NodeClass AMI Status Controller", func() { awsEnv.EC2API.DescribeImagesOutput.Set(&ec2.DescribeImagesOutput{ Images: []*ec2.Image{ { - Name: aws.String("test-ami-1"), - ImageId: aws.String("ami-test1"), + Name: aws.String("amd64-standard"), + ImageId: aws.String("ami-amd64-standard"), CreationDate: aws.String(time.Now().Format(time.RFC3339)), Architecture: aws.String("x86_64"), Tags: []*ec2.Tag{ - {Key: aws.String("Name"), Value: aws.String("test-ami-1")}, + {Key: aws.String("Name"), Value: aws.String("amd64-standard")}, {Key: aws.String("foo"), Value: aws.String("bar")}, }, }, { - Name: aws.String("test-ami-2"), - ImageId: aws.String("ami-test2"), + Name: aws.String("amd64-standard-new"), + ImageId: aws.String("ami-amd64-standard-new"), CreationDate: aws.String(time.Now().Add(time.Minute).Format(time.RFC3339)), Architecture: aws.String("x86_64"), Tags: []*ec2.Tag{ - {Key: aws.String("Name"), Value: aws.String("test-ami-2")}, + {Key: aws.String("Name"), Value: aws.String("amd64-standard")}, {Key: aws.String("foo"), Value: aws.String("bar")}, }, }, { - Name: aws.String("test-ami-3"), - ImageId: aws.String("ami-test3"), - CreationDate: aws.String(time.Now().Add(2 * time.Minute).Format(time.RFC3339)), + Name: aws.String("amd64-nvidia"), + ImageId: aws.String("ami-amd64-nvidia"), + CreationDate: aws.String(time.Now().Format(time.RFC3339)), Architecture: aws.String("x86_64"), Tags: []*ec2.Tag{ - {Key: aws.String("Name"), Value: aws.String("test-ami-3")}, + {Key: aws.String("Name"), Value: aws.String("amd64-nvidia")}, {Key: aws.String("foo"), Value: aws.String("bar")}, }, }, - }, - }) - }) - Context("Aliases", func() { - BeforeEach(func() { - awsEnv.EC2API.DescribeImagesOutput.Set(&ec2.DescribeImagesOutput{ - Images: []*ec2.Image{ - { - Name: aws.String("amd64-standard"), - ImageId: aws.String("ami-amd64-standard"), - CreationDate: aws.String(time.Now().Format(time.RFC3339)), - Architecture: aws.String("x86_64"), - Tags: []*ec2.Tag{ - {Key: aws.String("Name"), Value: aws.String("test-ami-1")}, - {Key: aws.String("foo"), Value: aws.String("bar")}, - }, - }, - { - Name: aws.String("amd64-nvidia"), - ImageId: aws.String("ami-amd64-nvidia"), - CreationDate: aws.String(time.Now().Add(time.Minute).Format(time.RFC3339)), - Architecture: aws.String("x86_64"), - Tags: []*ec2.Tag{ - {Key: aws.String("Name"), Value: aws.String("test-ami-2")}, - {Key: aws.String("foo"), Value: aws.String("bar")}, - }, - }, - { - Name: aws.String("amd64-neuron"), - ImageId: aws.String("ami-amd64-neuron"), - CreationDate: aws.String(time.Now().Add(2 * time.Minute).Format(time.RFC3339)), - Architecture: aws.String("x86_64"), - Tags: []*ec2.Tag{ - {Key: aws.String("Name"), Value: aws.String("test-ami-3")}, - {Key: aws.String("foo"), Value: aws.String("bar")}, - }, + { + Name: aws.String("amd64-neuron"), + ImageId: aws.String("ami-amd64-neuron"), + CreationDate: aws.String(time.Now().Format(time.RFC3339)), + Architecture: aws.String("x86_64"), + Tags: []*ec2.Tag{ + {Key: aws.String("Name"), Value: aws.String("amd64-neuron")}, + {Key: aws.String("foo"), Value: aws.String("bar")}, }, - { - Name: aws.String("arm64-standard"), - ImageId: aws.String("ami-arm64-standard"), - CreationDate: aws.String(time.Now().Format(time.RFC3339)), - Architecture: aws.String("arm64"), - Tags: []*ec2.Tag{ - {Key: aws.String("Name"), Value: aws.String("test-ami-1")}, - {Key: aws.String("foo"), Value: aws.String("bar")}, - }, + }, + { + Name: aws.String("arm64-standard"), + ImageId: aws.String("ami-arm64-standard"), + CreationDate: aws.String(time.Now().Format(time.RFC3339)), + Architecture: aws.String("arm64"), + Tags: []*ec2.Tag{ + {Key: aws.String("Name"), Value: aws.String("arm64-standard")}, + {Key: aws.String("foo"), Value: aws.String("bar")}, }, - { - Name: aws.String("arm64-nvidia"), - ImageId: aws.String("ami-arm64-nvidia"), - CreationDate: aws.String(time.Now().Add(time.Minute).Format(time.RFC3339)), - Architecture: aws.String("arm64"), - Tags: []*ec2.Tag{ - {Key: aws.String("Name"), Value: aws.String("test-ami-2")}, - {Key: aws.String("foo"), Value: aws.String("bar")}, - }, + }, + { + Name: aws.String("arm64-nvidia"), + ImageId: aws.String("ami-arm64-nvidia"), + CreationDate: aws.String(time.Now().Format(time.RFC3339)), + Architecture: aws.String("arm64"), + Tags: []*ec2.Tag{ + {Key: aws.String("Name"), Value: aws.String("arm64-nvidia")}, + {Key: aws.String("foo"), Value: aws.String("bar")}, }, }, - }) - + }, }) + }) + Context("Aliases", func() { It("Should resolve all AMIs with correct requirements for AL2023", func() { awsEnv.SSMAPI.Parameters = map[string]string{ fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2023/x86_64/standard/recommended/image_id", k8sVersion): "ami-amd64-standard", - fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2023/x86_64/nvidia/recommended/image_id", k8sVersion): "ami-amd64-nvidia", - fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2023/x86_64/neuron/recommended/image_id", k8sVersion): "ami-amd64-neuron", + fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2023/x86_64/nvidia/recommended/image_id", k8sVersion): "ami-amd64-nvidia", + fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2023/x86_64/neuron/recommended/image_id", k8sVersion): "ami-amd64-neuron", fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2023/arm64/standard/recommended/image_id", k8sVersion): "ami-arm64-standard", } nodeClass.Spec.AMISelectorTerms = []v1.AMISelectorTerm{{Alias: "al2023@latest"}} @@ -236,9 +209,9 @@ var _ = Describe("NodeClass AMI Status Controller", func() { }) It("Should resolve all AMIs with correct requirements for AL2", func() { awsEnv.SSMAPI.Parameters = map[string]string{ - fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2/recommended/image_id", k8sVersion): "ami-amd64-standard", - fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2-gpu/recommended/image_id", k8sVersion): "ami-amd64-nvidia", - fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2-arm64/recommended/image_id", k8sVersion): "ami-arm64-standard", + fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2/recommended/image_id", k8sVersion): "ami-amd64-standard", + fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2-gpu/recommended/image_id", k8sVersion): "ami-amd64-nvidia", + fmt.Sprintf("/aws/service/eks/optimized-ami/%s/amazon-linux-2-arm64/recommended/image_id", k8sVersion): "ami-arm64-standard", } nodeClass.Spec.AMISelectorTerms = []v1.AMISelectorTerm{{Alias: "al2@latest"}} ExpectApplied(ctx, env.Client, nodeClass) @@ -321,10 +294,10 @@ var _ = Describe("NodeClass AMI Status Controller", func() { }) It("Should resolve all AMIs with correct requirements for Bottlerocket", func() { awsEnv.SSMAPI.Parameters = map[string]string{ - fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s/x86_64/latest/image_id", k8sVersion): "ami-amd64-standard", - fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s/arm64/latest/image_id", k8sVersion): "ami-arm64-standard", + fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s/x86_64/latest/image_id", k8sVersion): "ami-amd64-standard", + fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s/arm64/latest/image_id", k8sVersion): "ami-arm64-standard", fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s-nvidia/x86_64/latest/image_id", k8sVersion): "ami-amd64-nvidia", - fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s-nvidia/arm64/latest/image_id", k8sVersion): "ami-arm64-nvidia", + fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s-nvidia/arm64/latest/image_id", k8sVersion): "ami-arm64-nvidia", } nodeClass.Spec.AMISelectorTerms = []v1.AMISelectorTerm{{Alias: "bottlerocket@latest"}} ExpectApplied(ctx, env.Client, nodeClass) @@ -453,7 +426,7 @@ var _ = Describe("NodeClass AMI Status Controller", func() { { Key: corev1.LabelOSStable, Operator: corev1.NodeSelectorOpIn, - Values: []string{string(corev1.Windows)}, + Values: []string{string(corev1.Windows)}, }, { Key: corev1.LabelArchStable, @@ -463,7 +436,7 @@ var _ = Describe("NodeClass AMI Status Controller", func() { { Key: corev1.LabelWindowsBuild, Operator: corev1.NodeSelectorOpIn, - Values: []string{v1.Windows2019Build}, + Values: []string{v1.Windows2019Build}, }, }, }, @@ -488,7 +461,7 @@ var _ = Describe("NodeClass AMI Status Controller", func() { { Key: corev1.LabelOSStable, Operator: corev1.NodeSelectorOpIn, - Values: []string{string(corev1.Windows)}, + Values: []string{string(corev1.Windows)}, }, { Key: corev1.LabelArchStable, @@ -498,7 +471,7 @@ var _ = Describe("NodeClass AMI Status Controller", func() { { Key: corev1.LabelWindowsBuild, Operator: corev1.NodeSelectorOpIn, - Values: []string{v1.Windows2022Build}, + Values: []string{v1.Windows2022Build}, }, }, }, @@ -506,39 +479,15 @@ var _ = Describe("NodeClass AMI Status Controller", func() { Expect(nodeClass.StatusConditions().IsTrue(v1.ConditionTypeAMIsReady)).To(BeTrue()) }) }) - It("should resolve amiSelector AMis and requirements into status when all SSM parameters don't resolve", func() { + It("should resolve amiSelector AMIs and requirements into status when all SSM parameters don't resolve", func() { // This parameter set doesn't include any of the Nvidia AMIs awsEnv.SSMAPI.Parameters = map[string]string{ - fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s/x86_64/latest/image_id", k8sVersion): "ami-id-123", - fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s/arm64/latest/image_id", k8sVersion): "ami-id-456", + fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s/x86_64/latest/image_id", k8sVersion): "ami-amd64-standard", + fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s/arm64/latest/image_id", k8sVersion): "ami-arm64-standard", } nodeClass.Spec.AMISelectorTerms = []v1.AMISelectorTerm{{ Alias: "bottlerocket@latest", }} - awsEnv.EC2API.DescribeImagesOutput.Set(&ec2.DescribeImagesOutput{ - Images: []*ec2.Image{ - { - Name: aws.String("test-ami-1"), - ImageId: aws.String("ami-id-123"), - CreationDate: aws.String(time.Now().Format(time.RFC3339)), - Architecture: aws.String("x86_64"), - Tags: []*ec2.Tag{ - {Key: aws.String("Name"), Value: aws.String("test-ami-1")}, - {Key: aws.String("foo"), Value: aws.String("bar")}, - }, - }, - { - Name: aws.String("test-ami-2"), - ImageId: aws.String("ami-id-456"), - CreationDate: aws.String(time.Now().Add(time.Minute).Format(time.RFC3339)), - Architecture: aws.String("arm64"), - Tags: []*ec2.Tag{ - {Key: aws.String("Name"), Value: aws.String("test-ami-2")}, - {Key: aws.String("foo"), Value: aws.String("bar")}, - }, - }, - }, - }) ExpectApplied(ctx, env.Client, nodeClass) ExpectObjectReconciled(ctx, env.Client, statusController, nodeClass) nodeClass = ExpectExists(ctx, env.Client, nodeClass) @@ -546,8 +495,8 @@ var _ = Describe("NodeClass AMI Status Controller", func() { Expect(len(nodeClass.Status.AMIs)).To(Equal(2)) Expect(nodeClass.Status.AMIs).To(ContainElements([]v1.AMI{ { - Name: "test-ami-2", - ID: "ami-id-456", + Name: "arm64-standard", + ID: "ami-arm64-standard", Requirements: []corev1.NodeSelectorRequirement{ { Key: corev1.LabelArchStable, @@ -565,8 +514,8 @@ var _ = Describe("NodeClass AMI Status Controller", func() { }, }, { - Name: "test-ami-1", - ID: "ami-id-123", + Name: "amd64-standard", + ID: "ami-amd64-standard", Requirements: []corev1.NodeSelectorRequirement{ { Key: corev1.LabelArchStable, @@ -587,20 +536,22 @@ var _ = Describe("NodeClass AMI Status Controller", func() { Expect(nodeClass.StatusConditions().IsTrue(v1.ConditionTypeAMIsReady)).To(BeTrue()) }) It("should resolve a valid AMI selector", func() { + nodeClass.Spec.AMISelectorTerms = []v1.AMISelectorTerm{{ + Tags: map[string]string{"Name": "amd64-standard"}, + }} ExpectApplied(ctx, env.Client, nodeClass) ExpectObjectReconciled(ctx, env.Client, statusController, nodeClass) nodeClass = ExpectExists(ctx, env.Client, nodeClass) Expect(nodeClass.Status.AMIs).To(Equal( []v1.AMI{ { - Name: "test-ami-3", - ID: "ami-test3", + Name: "amd64-standard-new", + ID: "ami-amd64-standard-new", Requirements: []corev1.NodeSelectorRequirement{{ Key: corev1.LabelArchStable, Operator: corev1.NodeSelectorOpIn, Values: []string{karpv1.ArchitectureAmd64}, - }, - }, + }}, }, }, ))