Skip to content

Commit 106261f

Browse files
fix: capacity respects noeoverlay weight precedence (kubernetes-sigs#2767)
Co-authored-by: Mickaël Carl <mickael@planetscale.com>
1 parent 52c3b91 commit 106261f

2 files changed

Lines changed: 63 additions & 0 deletions

File tree

pkg/controllers/nodeoverlay/store.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,13 @@ func (i *internalInstanceTypeStore) updateInstanceTypeCapacity(nodePoolName stri
171171
}
172172
} else {
173173
for resource, quantity := range nodeOverlay.Spec.Capacity {
174+
if _, foundCapacityUpdate := i.updates[nodePoolName][instanceTypeName].Capacity.OverlayUpdate[resource]; foundCapacityUpdate {
175+
continue
176+
}
177+
174178
i.updates[nodePoolName][instanceTypeName].Capacity.OverlayUpdate[resource] = quantity
175179
}
180+
176181
i.updates[nodePoolName][instanceTypeName].Capacity.lowestWeightCapacityResources = nodeOverlay.Spec.Capacity
177182
i.updates[nodePoolName][instanceTypeName].Capacity.lowestWeight = nodeOverlay.Spec.Weight
178183
}

pkg/controllers/nodeoverlay/suite_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2311,6 +2311,64 @@ var _ = Describe("Instance Type Controller", func() {
23112311
}
23122312
}
23132313
})
2314+
It("should apply higher weight overlay when multiple overlays match the same instance type", func() {
2315+
overlayA := test.NodeOverlay(v1alpha1.NodeOverlay{
2316+
ObjectMeta: metav1.ObjectMeta{
2317+
Name: "overlay-a",
2318+
},
2319+
Spec: v1alpha1.NodeOverlaySpec{
2320+
Requirements: []v1alpha1.NodeSelectorRequirement{
2321+
{
2322+
Key: corev1.LabelInstanceTypeStable,
2323+
Operator: corev1.NodeSelectorOpIn,
2324+
Values: []string{"default-instance-type"},
2325+
},
2326+
},
2327+
Weight: lo.ToPtr(int32(10)),
2328+
Capacity: corev1.ResourceList{
2329+
corev1.ResourceName("smarter-devices/fuse"): resource.MustParse("5"),
2330+
},
2331+
},
2332+
})
2333+
overlayB := test.NodeOverlay(v1alpha1.NodeOverlay{
2334+
ObjectMeta: metav1.ObjectMeta{
2335+
Name: "overlay-b",
2336+
},
2337+
Spec: v1alpha1.NodeOverlaySpec{
2338+
Requirements: []v1alpha1.NodeSelectorRequirement{
2339+
{
2340+
Key: corev1.LabelInstanceTypeStable,
2341+
Operator: corev1.NodeSelectorOpIn,
2342+
Values: []string{"default-instance-type"},
2343+
},
2344+
},
2345+
Weight: lo.ToPtr(int32(20)),
2346+
Capacity: corev1.ResourceList{
2347+
corev1.ResourceName("smarter-devices/fuse"): resource.MustParse("99"),
2348+
},
2349+
},
2350+
})
2351+
2352+
ExpectApplied(ctx, env.Client, nodePool, overlayA, overlayB)
2353+
ExpectReconciled(ctx, nodeOverlayController, reconcile.Request{})
2354+
2355+
// Both overlays should pass validation since they have different weights
2356+
updatedOverlayA := ExpectExists(ctx, env.Client, overlayA)
2357+
Expect(updatedOverlayA.StatusConditions().IsTrue(v1alpha1.ConditionTypeValidationSucceeded)).To(BeTrue())
2358+
updatedOverlayB := ExpectExists(ctx, env.Client, overlayB)
2359+
Expect(updatedOverlayB.StatusConditions().IsTrue(v1alpha1.ConditionTypeValidationSucceeded)).To(BeTrue())
2360+
2361+
instanceTypeList, err := cloudProvider.GetInstanceTypes(ctx, nodePool)
2362+
Expect(err).To(BeNil())
2363+
instanceTypeList, err = store.ApplyAll(nodePool.Name, instanceTypeList)
2364+
Expect(err).To(BeNil())
2365+
2366+
Expect(len(instanceTypeList)).To(BeNumerically("==", 1))
2367+
// The higher weight overlay (overlayB with weight 20) should take precedence
2368+
fuseResource, exist := instanceTypeList[0].Capacity.Name(corev1.ResourceName("smarter-devices/fuse"), resource.DecimalSI).AsInt64()
2369+
Expect(exist).To(BeTrue())
2370+
Expect(fuseResource).To(BeNumerically("==", 99))
2371+
})
23142372
It("should that there is not a partial application for instance types", func() {
23152373
cloudProvider.InstanceTypes = nil
23162374
overlayA := test.NodeOverlay(v1alpha1.NodeOverlay{

0 commit comments

Comments
 (0)