Skip to content

Commit 211e30a

Browse files
committed
feat: Restrict NodeReadinessRuleSpec.Taint to "readiness.k8s.io/" prefix
Signed-off-by: Sathvik <Sathvik.S@ibm.com>
1 parent dc4a0b1 commit 211e30a

File tree

7 files changed

+138
-79
lines changed

7 files changed

+138
-79
lines changed

api/v1alpha1/nodereadinessrule_types.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,37 @@ const (
4545
TaintStatusAbsent TaintStatus = "Absent"
4646
)
4747

48+
// TaintSpec defines the specific Taint (Key, Value, and Effect) to be managed.
49+
type TaintSpec struct {
50+
// The taint key to be applied to a node.
51+
//
52+
// +required
53+
// +kubebuilder:validation:MinLength=17
54+
// +kubebuilder:validation:MaxLength=253
55+
// +kubebuilder:validation:Pattern=`^readiness\.k8s\.io\/.*`
56+
Key string `json:"key"`
57+
58+
// The taint value corresponding to the taint key.
59+
//
60+
// +optional
61+
// +kubebuilder:validation:MaxLength=63
62+
Value string `json:"value,omitempty"`
63+
64+
// The effect of the taint on pods
65+
// that do not tolerate the taint.
66+
// Valid effects are NoSchedule, PreferNoSchedule and NoExecute.
67+
//
68+
// +required
69+
// +kubebuilder:validation:Enum=NoSchedule;PreferNoSchedule;NoExecute
70+
Effect corev1.TaintEffect `json:"effect"`
71+
72+
// TimeAdded represents the time at which the taint was added.
73+
// It is only written for NoExecute taints.
74+
//
75+
// +optional
76+
TimeAdded *metav1.Time `json:"timeAdded,omitempty"`
77+
}
78+
4879
// NodeReadinessRuleSpec defines the desired state of NodeReadinessRule.
4980
type NodeReadinessRuleSpec struct {
5081
// conditions contains a list of the Node conditions that defines the specific
@@ -70,7 +101,7 @@ type NodeReadinessRuleSpec struct {
70101
// on Nodes that meet the defined condition criteria.
71102
//
72103
// +required
73-
Taint corev1.Taint `json:"taint,omitempty,omitzero"`
104+
Taint TaintSpec `json:"taint,omitempty,omitzero"`
74105

75106
// nodeSelector limits the scope of this rule to a specific subset of Nodes.
76107
//

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/readiness.node.x-k8s.io_nodereadinessrules.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,16 @@ spec:
163163
Required. The effect of the taint on pods
164164
that do not tolerate the taint.
165165
Valid effects are NoSchedule, PreferNoSchedule and NoExecute.
166+
enum:
167+
- NoSchedule
168+
- PreferNoSchedule
169+
- NoExecute
166170
type: string
167171
key:
168172
description: Required. The taint key to be applied to a node.
173+
maxLength: 253
174+
minLength: 17
175+
pattern: ^readiness\.k8s\.io\/.*
169176
type: string
170177
timeAdded:
171178
description: TimeAdded represents the time at which the taint
@@ -174,6 +181,7 @@ spec:
174181
type: string
175182
value:
176183
description: The taint value corresponding to the taint key.
184+
maxLength: 63
177185
type: string
178186
required:
179187
- effect

internal/controller/node_controller.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ func (r *RuleReadinessController) getConditionStatus(node *corev1.Node, conditio
229229
}
230230

231231
// hasTaintBySpec checks if a node has a specific taint.
232-
func (r *RuleReadinessController) hasTaintBySpec(node *corev1.Node, taintSpec corev1.Taint) bool {
232+
func (r *RuleReadinessController) hasTaintBySpec(node *corev1.Node, taintSpec readinessv1alpha1.TaintSpec) bool {
233233
for _, taint := range node.Spec.Taints {
234234
if taint.Key == taintSpec.Key && taint.Effect == taintSpec.Effect {
235235
return true
@@ -239,18 +239,19 @@ func (r *RuleReadinessController) hasTaintBySpec(node *corev1.Node, taintSpec co
239239
}
240240

241241
// addTaintBySpec adds a taint to a node.
242-
func (r *RuleReadinessController) addTaintBySpec(ctx context.Context, node *corev1.Node, taintSpec corev1.Taint) error {
242+
func (r *RuleReadinessController) addTaintBySpec(ctx context.Context, node *corev1.Node, taintSpec readinessv1alpha1.TaintSpec) error {
243243
patch := client.StrategicMergeFrom(node.DeepCopy())
244244
node.Spec.Taints = append(node.Spec.Taints, corev1.Taint{
245-
Key: taintSpec.Key,
246-
Value: taintSpec.Value,
247-
Effect: taintSpec.Effect,
245+
Key: taintSpec.Key,
246+
Value: taintSpec.Value,
247+
Effect: taintSpec.Effect,
248+
TimeAdded: taintSpec.TimeAdded,
248249
})
249250
return r.Patch(ctx, node, patch)
250251
}
251252

252253
// removeTaintBySpec removes a taint from a node.
253-
func (r *RuleReadinessController) removeTaintBySpec(ctx context.Context, node *corev1.Node, taintSpec corev1.Taint) error {
254+
func (r *RuleReadinessController) removeTaintBySpec(ctx context.Context, node *corev1.Node, taintSpec readinessv1alpha1.TaintSpec) error {
254255
patch := client.StrategicMergeFrom(node.DeepCopy())
255256
var newTaints []corev1.Taint
256257
for _, taint := range node.Spec.Taints {

internal/controller/node_controller_test.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ var _ = Describe("Node Controller", func() {
3636
const (
3737
nodeName = "node-controller-test-node"
3838
ruleName = "node-controller-test-rule"
39-
taintKey = "test-taint"
39+
taintKey = "readiness.k8s.io/test-taint"
4040
conditionType = "TestCondition"
4141
)
4242

@@ -66,19 +66,19 @@ var _ = Describe("Node Controller", func() {
6666

6767
It("should correctly compare node taints", func() {
6868
taint1 := []corev1.Taint{
69-
{Key: "key1", Effect: corev1.TaintEffectNoSchedule, Value: "value1"},
70-
{Key: "key2", Effect: corev1.TaintEffectNoExecute, Value: "value2"},
69+
{Key: "readiness.k8s.io/key1", Effect: corev1.TaintEffectNoSchedule, Value: "value1"},
70+
{Key: "readiness.k8s.io/key2", Effect: corev1.TaintEffectNoExecute, Value: "value2"},
7171
}
7272
taint2 := []corev1.Taint{
73-
{Key: "key1", Effect: corev1.TaintEffectNoSchedule, Value: "value1"},
74-
{Key: "key2", Effect: corev1.TaintEffectNoExecute, Value: "value2"},
73+
{Key: "readiness.k8s.io/key1", Effect: corev1.TaintEffectNoSchedule, Value: "value1"},
74+
{Key: "readiness.k8s.io/key2", Effect: corev1.TaintEffectNoExecute, Value: "value2"},
7575
}
7676
taint3 := []corev1.Taint{
77-
{Key: "key1", Effect: corev1.TaintEffectNoSchedule, Value: "different"},
78-
{Key: "key2", Effect: corev1.TaintEffectNoExecute, Value: "value2"},
77+
{Key: "readiness.k8s.io/key1", Effect: corev1.TaintEffectNoSchedule, Value: "different"},
78+
{Key: "readiness.k8s.io/key2", Effect: corev1.TaintEffectNoExecute, Value: "value2"},
7979
}
8080
taint4 := []corev1.Taint{
81-
{Key: "key1", Effect: corev1.TaintEffectNoSchedule, Value: "value1"},
81+
{Key: "readiness.k8s.io/key1", Effect: corev1.TaintEffectNoSchedule, Value: "value1"},
8282
}
8383

8484
Expect(taintsEqual(taint1, taint2)).To(BeTrue(), "identical taints should be equal")
@@ -153,7 +153,7 @@ var _ = Describe("Node Controller", func() {
153153
Conditions: []nodereadinessiov1alpha1.ConditionRequirement{
154154
{Type: conditionType, RequiredStatus: corev1.ConditionTrue},
155155
},
156-
Taint: corev1.Taint{
156+
Taint: nodereadinessiov1alpha1.TaintSpec{
157157
Key: taintKey,
158158
Effect: corev1.TaintEffectNoSchedule,
159159
},
@@ -398,7 +398,7 @@ var _ = Describe("Node Controller", func() {
398398
Conditions: []nodereadinessiov1alpha1.ConditionRequirement{
399399
{Type: conditionType, RequiredStatus: corev1.ConditionTrue},
400400
},
401-
Taint: corev1.Taint{
401+
Taint: nodereadinessiov1alpha1.TaintSpec{
402402
Key: taintKey,
403403
Effect: corev1.TaintEffectNoSchedule,
404404
},
@@ -547,7 +547,7 @@ var _ = Describe("Node Controller", func() {
547547
},
548548
Spec: corev1.NodeSpec{
549549
Taints: []corev1.Taint{
550-
{Key: "status-test-taint", Effect: corev1.TaintEffectNoSchedule, Value: "pending"},
550+
{Key: "readiness.k8s.io/status-test-taint", Effect: corev1.TaintEffectNoSchedule, Value: "pending"},
551551
},
552552
},
553553
Status: corev1.NodeStatus{
@@ -565,8 +565,8 @@ var _ = Describe("Node Controller", func() {
565565
Conditions: []nodereadinessiov1alpha1.ConditionRequirement{
566566
{Type: "StatusTestCondition", RequiredStatus: corev1.ConditionTrue},
567567
},
568-
Taint: corev1.Taint{
569-
Key: "status-test-taint",
568+
Taint: nodereadinessiov1alpha1.TaintSpec{
569+
Key: "readiness.k8s.io/status-test-taint",
570570
Effect: corev1.TaintEffectNoSchedule,
571571
Value: "pending",
572572
},

internal/controller/nodereadinessrule_controller_test.go

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import (
3434
)
3535

3636
const (
37-
selectorChangeTaintKey = "selector-change-taint"
37+
selectorChangeTaintKey = "readiness.k8s.io/selector-change-taint"
3838
)
3939

4040
var _ = Describe("NodeReadinessRule Controller", func() {
@@ -89,8 +89,8 @@ var _ = Describe("NodeReadinessRule Controller", func() {
8989
"node-role.kubernetes.io/worker": "",
9090
},
9191
},
92-
Taint: corev1.Taint{
93-
Key: "test-taint",
92+
Taint: nodereadinessiov1alpha1.TaintSpec{
93+
Key: "readiness.k8s.io/test-taint",
9494
Effect: corev1.TaintEffectNoSchedule,
9595
},
9696
EnforcementMode: nodereadinessiov1alpha1.EnforcementModeBootstrapOnly,
@@ -132,8 +132,8 @@ var _ = Describe("NodeReadinessRule Controller", func() {
132132
"node-role.kubernetes.io/worker": "",
133133
},
134134
},
135-
Taint: corev1.Taint{
136-
Key: "test-taint",
135+
Taint: nodereadinessiov1alpha1.TaintSpec{
136+
Key: "readiness.k8s.io/test-taint",
137137
Effect: corev1.TaintEffectNoSchedule,
138138
},
139139
EnforcementMode: nodereadinessiov1alpha1.EnforcementModeBootstrapOnly,
@@ -154,7 +154,7 @@ var _ = Describe("NodeReadinessRule Controller", func() {
154154
cachedRule, exists := readinessController.ruleCache["test-rule"]
155155
readinessController.ruleCacheMutex.RUnlock()
156156
Expect(exists).To(BeTrue())
157-
Expect(cachedRule.Spec.Taint.Key).To(Equal("test-taint"))
157+
Expect(cachedRule.Spec.Taint.Key).To(Equal("readiness.k8s.io/test-taint"))
158158

159159
// Cleanup
160160
Expect(k8sClient.Delete(ctx, rule)).To(Succeed())
@@ -175,8 +175,8 @@ var _ = Describe("NodeReadinessRule Controller", func() {
175175
"node-role.kubernetes.io/worker": "",
176176
},
177177
},
178-
Taint: corev1.Taint{
179-
Key: "test-taint",
178+
Taint: nodereadinessiov1alpha1.TaintSpec{
179+
Key: "readiness.k8s.io/test-taint",
180180
Effect: corev1.TaintEffectNoSchedule,
181181
},
182182
EnforcementMode: nodereadinessiov1alpha1.EnforcementModeBootstrapOnly,
@@ -236,8 +236,8 @@ var _ = Describe("NodeReadinessRule Controller", func() {
236236
Conditions: []nodereadinessiov1alpha1.ConditionRequirement{
237237
{Type: "TestCondition", RequiredStatus: corev1.ConditionTrue},
238238
},
239-
Taint: corev1.Taint{
240-
Key: "immediate-test-taint",
239+
Taint: nodereadinessiov1alpha1.TaintSpec{
240+
Key: "readiness.k8s.io/immediate-test-taint",
241241
Effect: corev1.TaintEffectNoSchedule,
242242
},
243243
EnforcementMode: nodereadinessiov1alpha1.EnforcementModeContinuous,
@@ -265,7 +265,7 @@ var _ = Describe("NodeReadinessRule Controller", func() {
265265
return false
266266
}
267267
for _, taint := range updatedNode.Spec.Taints {
268-
if taint.Key == "immediate-test-taint" && taint.Effect == corev1.TaintEffectNoSchedule {
268+
if taint.Key == "readiness.k8s.io/immediate-test-taint" && taint.Effect == corev1.TaintEffectNoSchedule {
269269
return true
270270
}
271271
}
@@ -298,8 +298,8 @@ var _ = Describe("NodeReadinessRule Controller", func() {
298298
"node-role.kubernetes.io/worker": "",
299299
},
300300
},
301-
Taint: corev1.Taint{
302-
Key: "dry-run-taint",
301+
Taint: nodereadinessiov1alpha1.TaintSpec{
302+
Key: "readiness.k8s.io/dry-run-taint",
303303
Effect: corev1.TaintEffectNoSchedule,
304304
},
305305
EnforcementMode: nodereadinessiov1alpha1.EnforcementModeBootstrapOnly,
@@ -368,8 +368,8 @@ var _ = Describe("NodeReadinessRule Controller", func() {
368368
Conditions: []nodereadinessiov1alpha1.ConditionRequirement{
369369
{Type: "Ready", RequiredStatus: corev1.ConditionTrue},
370370
},
371-
Taint: corev1.Taint{
372-
Key: "node-test-taint",
371+
Taint: nodereadinessiov1alpha1.TaintSpec{
372+
Key: "readiness.k8s.io/node-test-taint",
373373
Effect: corev1.TaintEffectNoSchedule,
374374
},
375375
EnforcementMode: nodereadinessiov1alpha1.EnforcementModeBootstrapOnly,
@@ -423,23 +423,23 @@ var _ = Describe("NodeReadinessRule Controller", func() {
423423
node := &corev1.Node{
424424
Spec: corev1.NodeSpec{
425425
Taints: []corev1.Taint{
426-
{Key: "test-key", Effect: corev1.TaintEffectNoSchedule, Value: "test-value"},
427-
{Key: "another-key", Effect: corev1.TaintEffectNoExecute},
426+
{Key: "readiness.k8s.io/test-key", Effect: corev1.TaintEffectNoSchedule, Value: "test-value"},
427+
{Key: "readiness.k8s.io/another-key", Effect: corev1.TaintEffectNoExecute},
428428
},
429429
},
430430
}
431431

432-
taintSpec := corev1.Taint{
433-
Key: "test-key",
432+
taintSpec := nodereadinessiov1alpha1.TaintSpec{
433+
Key: "readiness.k8s.io/test-key",
434434
Effect: corev1.TaintEffectNoSchedule,
435435
}
436436

437437
hasTaint := readinessController.hasTaintBySpec(node, taintSpec)
438438
Expect(hasTaint).To(BeTrue())
439439

440440
// Test non-existent taint
441-
nonExistentTaint := corev1.Taint{
442-
Key: "missing-key",
441+
nonExistentTaint := nodereadinessiov1alpha1.TaintSpec{
442+
Key: "readiness.k8s.io/missing-key",
443443
Effect: corev1.TaintEffectNoSchedule,
444444
}
445445

@@ -534,7 +534,7 @@ var _ = Describe("NodeReadinessRule Controller", func() {
534534
},
535535
Spec: nodereadinessiov1alpha1.NodeReadinessRuleSpec{
536536
Conditions: []nodereadinessiov1alpha1.ConditionRequirement{{Type: "DBReady", RequiredStatus: corev1.ConditionTrue}},
537-
Taint: corev1.Taint{Key: "db-unready", Effect: corev1.TaintEffectNoSchedule},
537+
Taint: nodereadinessiov1alpha1.TaintSpec{Key: "readiness.k8s.io/db-unready", Effect: corev1.TaintEffectNoSchedule},
538538
EnforcementMode: nodereadinessiov1alpha1.EnforcementModeContinuous,
539539
NodeSelector: metav1.LabelSelector{MatchLabels: map[string]string{"app": "backend"}},
540540
},
@@ -590,7 +590,7 @@ var _ = Describe("NodeReadinessRule Controller", func() {
590590
},
591591
Spec: nodereadinessiov1alpha1.NodeReadinessRuleSpec{
592592
Conditions: []nodereadinessiov1alpha1.ConditionRequirement{{Type: "TestReady", RequiredStatus: corev1.ConditionTrue}},
593-
Taint: corev1.Taint{Key: "test-unready", Effect: corev1.TaintEffectNoSchedule},
593+
Taint: nodereadinessiov1alpha1.TaintSpec{Key: "readiness.k8s.io/test-unready", Effect: corev1.TaintEffectNoSchedule},
594594
EnforcementMode: nodereadinessiov1alpha1.EnforcementModeContinuous,
595595
NodeSelector: metav1.LabelSelector{MatchLabels: map[string]string{"node-group": "new-workers"}},
596596
},
@@ -664,7 +664,7 @@ var _ = Describe("NodeReadinessRule Controller", func() {
664664
},
665665
Spec: corev1.NodeSpec{
666666
Taints: []corev1.Taint{
667-
{Key: "cleanup-taint", Effect: corev1.TaintEffectNoSchedule, Value: "pending"},
667+
{Key: "readiness.k8s.io/cleanup-taint", Effect: corev1.TaintEffectNoSchedule, Value: "pending"},
668668
},
669669
},
670670
Status: corev1.NodeStatus{
@@ -679,7 +679,7 @@ var _ = Describe("NodeReadinessRule Controller", func() {
679679
Spec: nodereadinessiov1alpha1.NodeReadinessRuleSpec{
680680
Conditions: []nodereadinessiov1alpha1.ConditionRequirement{{Type: "TestReady", RequiredStatus: corev1.ConditionTrue}},
681681
NodeSelector: metav1.LabelSelector{MatchLabels: map[string]string{"kubernetes.io/hostname": "cleanup-test-node"}},
682-
Taint: corev1.Taint{Key: "cleanup-taint", Effect: corev1.TaintEffectNoSchedule},
682+
Taint: nodereadinessiov1alpha1.TaintSpec{Key: "readiness.k8s.io/cleanup-taint", Effect: corev1.TaintEffectNoSchedule},
683683
EnforcementMode: nodereadinessiov1alpha1.EnforcementModeContinuous,
684684
},
685685
}
@@ -710,7 +710,7 @@ var _ = Describe("NodeReadinessRule Controller", func() {
710710
Expect(k8sClient.Get(ctx, types.NamespacedName{Name: "cleanup-test-node"}, updatedNode)).To(Succeed())
711711
hasTaint := false
712712
for _, taint := range updatedNode.Spec.Taints {
713-
if taint.Key == "cleanup-taint" {
713+
if taint.Key == "readiness.k8s.io/cleanup-taint" {
714714
hasTaint = true
715715
break
716716
}
@@ -731,7 +731,7 @@ var _ = Describe("NodeReadinessRule Controller", func() {
731731
return false
732732
}
733733
for _, taint := range updatedNode.Spec.Taints {
734-
if taint.Key == "cleanup-taint" {
734+
if taint.Key == "readiness.k8s.io/cleanup-taint" {
735735
return false // Taint still exists
736736
}
737737
}
@@ -767,7 +767,7 @@ var _ = Describe("NodeReadinessRule Controller", func() {
767767
},
768768
},
769769
},
770-
Taint: corev1.Taint{Key: "unready", Effect: corev1.TaintEffectNoSchedule},
770+
Taint: nodereadinessiov1alpha1.TaintSpec{Key: "readiness.k8s.io/unready", Effect: corev1.TaintEffectNoSchedule},
771771
EnforcementMode: nodereadinessiov1alpha1.EnforcementModeContinuous,
772772
},
773773
}
@@ -868,7 +868,7 @@ var _ = Describe("NodeReadinessRule Controller", func() {
868868
Conditions: []nodereadinessiov1alpha1.ConditionRequirement{
869869
{Type: "TestReady", RequiredStatus: corev1.ConditionTrue},
870870
},
871-
Taint: corev1.Taint{Key: selectorChangeTaintKey, Effect: corev1.TaintEffectNoSchedule},
871+
Taint: nodereadinessiov1alpha1.TaintSpec{Key: selectorChangeTaintKey, Effect: corev1.TaintEffectNoSchedule},
872872
EnforcementMode: nodereadinessiov1alpha1.EnforcementModeContinuous,
873873
NodeSelector: metav1.LabelSelector{
874874
MatchLabels: map[string]string{"env": "prod"},

0 commit comments

Comments
 (0)