Skip to content

Commit f4dfc0f

Browse files
committed
testing
1 parent bb68557 commit f4dfc0f

File tree

1 file changed

+103
-31
lines changed

1 file changed

+103
-31
lines changed

pkg/controllers/nodeclass/validation_test.go

Lines changed: 103 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
ekstypes "github.com/aws/aws-sdk-go-v2/service/eks/types"
3131
"github.com/aws/smithy-go"
3232
corev1 "k8s.io/api/core/v1"
33+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3334
"k8s.io/client-go/tools/record"
3435
karpv1 "sigs.k8s.io/karpenter/pkg/apis/v1"
3536
"sigs.k8s.io/karpenter/pkg/events"
@@ -271,6 +272,26 @@ var _ = Describe("NodeClass Validation Status Controller", func() {
271272
}, fake.MaxCalls(1))
272273
}, nodeclass.ConditionReasonCreateLaunchTemplateAuthFailed),
273274
)
275+
Context("Windows AMI Validation", func() {
276+
DescribeTable(
277+
"should fallback to static instance types when windows ami is used",
278+
func(family string, terms []v1.AMISelectorTerm, expectedInstanceType ec2types.InstanceType, expectedAMIID string) {
279+
// Skip Windows 2025 on versions < 1.35
280+
if family == v1.AMIFamilyWindows2025 && version.MustParseGeneric(awsEnv.VersionProvider.Get(ctx)).Minor() < 35 {
281+
Skip("Windows 2025 requires EKS version 1.35+, current version: " + awsEnv.VersionProvider.Get(ctx))
282+
}
283+
nodeClass.Spec.AMIFamily = lo.ToPtr(family)
284+
nodeClass.Spec.AMISelectorTerms = terms
285+
ExpectApplied(ctx, env.Client, nodeClass)
286+
ExpectObjectReconciled(ctx, env.Client, controller, nodeClass)
287+
runInstancesInput := awsEnv.EC2API.RunInstancesBehavior.CalledWithInput.Pop()
288+
Expect(runInstancesInput.InstanceType).To(Equal(expectedInstanceType))
289+
},
290+
Entry("Windows2019 with m5.large", v1.AMIFamilyWindows2019, []v1.AMISelectorTerm{{Alias: "windows2019@latest"}}, ec2types.InstanceTypeM5Large, "amd64-ami-id"),
291+
Entry("Windows2022 with m5.large", v1.AMIFamilyWindows2022, []v1.AMISelectorTerm{{Alias: "windows2022@latest"}}, ec2types.InstanceTypeM5Large, "amd64-ami-id"),
292+
Entry("Windows2025 with m6g.large", v1.AMIFamilyWindows2025, []v1.AMISelectorTerm{{Alias: "windows2025@latest"}}, ec2types.InstanceTypeM6gLarge, "arm64-ami-id"),
293+
)
294+
})
274295
Context("Instance Type Prioritization Validation", func() {
275296
BeforeEach(func() {
276297
awsEnv.EC2API.DescribeImagesOutput.Set(&ec2.DescribeImagesOutput{
@@ -307,37 +328,6 @@ var _ = Describe("NodeClass Validation Status Controller", func() {
307328
Expect(awsEnv.InstanceTypesProvider.UpdateInstanceTypes(ctx)).To(Succeed())
308329
Expect(awsEnv.InstanceTypesProvider.UpdateInstanceTypeOfferings(ctx)).To(Succeed())
309330
})
310-
DescribeTable(
311-
"should fallback to static instance types when windows ami is used",
312-
func(family string, terms []v1.AMISelectorTerm, expectedInstanceType ec2types.InstanceType, expectedAMIID string) {
313-
// Skip Windows 2025 on versions < 1.35
314-
if family == v1.AMIFamilyWindows2025 && version.MustParseGeneric(awsEnv.VersionProvider.Get(ctx)).Minor() < 35 {
315-
Skip("Windows 2025 requires EKS version 1.35+, current version: " + awsEnv.VersionProvider.Get(ctx))
316-
}
317-
nodeClass.Spec.AMIFamily = lo.ToPtr(family)
318-
nodeClass.Spec.AMISelectorTerms = []v1.AMISelectorTerm{
319-
{
320-
Tags: map[string]string{"*": "*"},
321-
},
322-
}
323-
// Filter DescribeImages to use only the expected AMI
324-
allImages := awsEnv.EC2API.DescribeImagesOutput.Clone().Images
325-
awsEnv.EC2API.DescribeImagesOutput.Set(&ec2.DescribeImagesOutput{
326-
Images: lo.Filter(allImages, func(img ec2types.Image, _ int) bool {
327-
return lo.FromPtr(img.ImageId) == expectedAMIID
328-
}),
329-
})
330-
ExpectApplied(ctx, env.Client, nodeClass)
331-
ExpectObjectReconciled(ctx, env.Client, controller, nodeClass)
332-
launchTemplateInput := awsEnv.EC2API.CreateLaunchTemplateBehavior.CalledWithInput.Pop()
333-
runInstancesInput := awsEnv.EC2API.RunInstancesBehavior.CalledWithInput.Pop()
334-
Expect(runInstancesInput.InstanceType).To(Equal(expectedInstanceType))
335-
Expect(launchTemplateInput.LaunchTemplateData.ImageId).To(PointTo(Equal(expectedAMIID)))
336-
},
337-
Entry("Windows2019 with m5.large", v1.AMIFamilyWindows2019, []v1.AMISelectorTerm{{Alias: "windows2019@latest"}}, ec2types.InstanceTypeM5Large, "amd64-ami-id"),
338-
Entry("Windows2022 with m5.large", v1.AMIFamilyWindows2022, []v1.AMISelectorTerm{{Alias: "windows2022@latest"}}, ec2types.InstanceTypeM5Large, "amd64-ami-id"),
339-
Entry("Windows2025 with m6g.large", v1.AMIFamilyWindows2025, []v1.AMISelectorTerm{{Alias: "windows2025@latest"}}, ec2types.InstanceTypeM6gLarge, "arm64-ami-id"),
340-
)
341331
It("should prioritize non-GPU instances", func() {
342332
nodePool := coretest.NodePool(karpv1.NodePool{Spec: karpv1.NodePoolSpec{Template: karpv1.NodeClaimTemplate{
343333
Spec: karpv1.NodeClaimTemplateSpec{
@@ -518,4 +508,86 @@ var _ = Describe("NodeClass Validation Status Controller", func() {
518508
Expect(awsEnv.EC2API.CreateLaunchTemplateBehavior.Calls()).To(Equal(0))
519509
Expect(awsEnv.EC2API.RunInstancesBehavior.Calls()).To(Equal(0))
520510
})
511+
Context("Cache Key Generation", func() {
512+
It("should generate same cache key when NodePools are in different order", func() {
513+
nodePool1 := coretest.NodePool(karpv1.NodePool{
514+
ObjectMeta: metav1.ObjectMeta{Name: "np-aaa"},
515+
Spec: karpv1.NodePoolSpec{Template: karpv1.NodeClaimTemplate{
516+
Spec: karpv1.NodeClaimTemplateSpec{
517+
Requirements: []karpv1.NodeSelectorRequirementWithMinValues{
518+
{Key: corev1.LabelInstanceTypeStable, Operator: corev1.NodeSelectorOpIn, Values: []string{"m5.large"}},
519+
},
520+
NodeClassRef: &karpv1.NodeClassReference{
521+
Group: object.GVK(nodeClass).Group,
522+
Kind: object.GVK(nodeClass).Kind,
523+
Name: nodeClass.Name,
524+
},
525+
},
526+
}}})
527+
nodePool2 := coretest.NodePool(karpv1.NodePool{
528+
ObjectMeta: metav1.ObjectMeta{Name: "np-zzz"},
529+
Spec: karpv1.NodePoolSpec{Template: karpv1.NodeClaimTemplate{
530+
Spec: karpv1.NodeClaimTemplateSpec{
531+
Requirements: []karpv1.NodeSelectorRequirementWithMinValues{
532+
{Key: corev1.LabelInstanceTypeStable, Operator: corev1.NodeSelectorOpIn, Values: []string{"m5.xlarge"}},
533+
},
534+
NodeClassRef: &karpv1.NodeClassReference{
535+
Group: object.GVK(nodeClass).Group,
536+
Kind: object.GVK(nodeClass).Kind,
537+
Name: nodeClass.Name,
538+
},
539+
},
540+
}}})
541+
542+
// Apply in one order
543+
ExpectApplied(ctx, env.Client, nodeClass, nodePool1, nodePool2)
544+
ExpectObjectReconciled(ctx, env.Client, controller, nodeClass)
545+
items1 := awsEnv.ValidationCache.Items()
546+
Expect(items1).To(HaveLen(1))
547+
key1 := lo.Keys(items1)[0]
548+
549+
// Clear cache and apply in different order
550+
awsEnv.ValidationCache.Flush()
551+
ExpectApplied(ctx, env.Client, nodeClass, nodePool2, nodePool1)
552+
ExpectObjectReconciled(ctx, env.Client, controller, nodeClass)
553+
items2 := awsEnv.ValidationCache.Items()
554+
Expect(items2).To(HaveLen(1))
555+
key2 := lo.Keys(items2)[0]
556+
557+
// Keys should be identical
558+
Expect(key1).To(Equal(key2))
559+
})
560+
It("should generate different cache key when NodePool requirements change", func() {
561+
nodePool := coretest.NodePool(karpv1.NodePool{Spec: karpv1.NodePoolSpec{Template: karpv1.NodeClaimTemplate{
562+
Spec: karpv1.NodeClaimTemplateSpec{
563+
Requirements: []karpv1.NodeSelectorRequirementWithMinValues{
564+
{Key: corev1.LabelInstanceTypeStable, Operator: corev1.NodeSelectorOpIn, Values: []string{"m5.large"}},
565+
},
566+
NodeClassRef: &karpv1.NodeClassReference{
567+
Group: object.GVK(nodeClass).Group,
568+
Kind: object.GVK(nodeClass).Kind,
569+
Name: nodeClass.Name,
570+
},
571+
},
572+
}}})
573+
574+
ExpectApplied(ctx, env.Client, nodeClass, nodePool)
575+
ExpectObjectReconciled(ctx, env.Client, controller, nodeClass)
576+
items1 := awsEnv.ValidationCache.Items()
577+
Expect(items1).To(HaveLen(1))
578+
key1 := lo.Keys(items1)[0]
579+
580+
// Update NodePool requirements
581+
nodePool.Spec.Template.Spec.Requirements[0].Values = []string{"m5.xlarge"}
582+
ExpectApplied(ctx, env.Client, nodePool)
583+
ExpectObjectReconciled(ctx, env.Client, controller, nodeClass)
584+
items2 := awsEnv.ValidationCache.Items()
585+
Expect(items2).To(HaveLen(2)) // Should have both old and new cache entries
586+
keys := lo.Keys(items2)
587+
588+
// Should have a new key
589+
Expect(keys).To(ContainElement(key1))
590+
Expect(keys).To(ContainElement(Not(Equal(key1))))
591+
})
592+
})
521593
})

0 commit comments

Comments
 (0)