mirror of
https://github.com/replicatedhq/troubleshoot.git
synced 2026-02-14 10:19:54 +00:00
Allow filtering node resources on taint. (#1840)
* allow filtering node resources on taint
This commit is contained in:
@@ -1282,6 +1282,34 @@ spec:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
taint:
|
||||
description: |-
|
||||
The node this Taint is attached to has the "effect" on
|
||||
any pod that does not tolerate the Taint.
|
||||
properties:
|
||||
effect:
|
||||
description: |-
|
||||
Required. The effect of the taint on pods
|
||||
that do not tolerate the taint.
|
||||
Valid effects are NoSchedule, PreferNoSchedule and NoExecute.
|
||||
type: string
|
||||
key:
|
||||
description: Required. The taint key to be applied
|
||||
to a node.
|
||||
type: string
|
||||
timeAdded:
|
||||
description: TimeAdded represents the time at which
|
||||
the taint was added.
|
||||
format: date-time
|
||||
type: string
|
||||
value:
|
||||
description: The taint value corresponding to the
|
||||
taint key.
|
||||
type: string
|
||||
required:
|
||||
- effect
|
||||
- key
|
||||
type: object
|
||||
type: object
|
||||
outcomes:
|
||||
items:
|
||||
|
||||
@@ -1282,6 +1282,34 @@ spec:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
taint:
|
||||
description: |-
|
||||
The node this Taint is attached to has the "effect" on
|
||||
any pod that does not tolerate the Taint.
|
||||
properties:
|
||||
effect:
|
||||
description: |-
|
||||
Required. The effect of the taint on pods
|
||||
that do not tolerate the taint.
|
||||
Valid effects are NoSchedule, PreferNoSchedule and NoExecute.
|
||||
type: string
|
||||
key:
|
||||
description: Required. The taint key to be applied
|
||||
to a node.
|
||||
type: string
|
||||
timeAdded:
|
||||
description: TimeAdded represents the time at which
|
||||
the taint was added.
|
||||
format: date-time
|
||||
type: string
|
||||
value:
|
||||
description: The taint value corresponding to the
|
||||
taint key.
|
||||
type: string
|
||||
required:
|
||||
- effect
|
||||
- key
|
||||
type: object
|
||||
type: object
|
||||
outcomes:
|
||||
items:
|
||||
|
||||
@@ -1313,6 +1313,34 @@ spec:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
taint:
|
||||
description: |-
|
||||
The node this Taint is attached to has the "effect" on
|
||||
any pod that does not tolerate the Taint.
|
||||
properties:
|
||||
effect:
|
||||
description: |-
|
||||
Required. The effect of the taint on pods
|
||||
that do not tolerate the taint.
|
||||
Valid effects are NoSchedule, PreferNoSchedule and NoExecute.
|
||||
type: string
|
||||
key:
|
||||
description: Required. The taint key to be applied
|
||||
to a node.
|
||||
type: string
|
||||
timeAdded:
|
||||
description: TimeAdded represents the time at which
|
||||
the taint was added.
|
||||
format: date-time
|
||||
type: string
|
||||
value:
|
||||
description: The taint value corresponding to the
|
||||
taint key.
|
||||
type: string
|
||||
required:
|
||||
- effect
|
||||
- key
|
||||
type: object
|
||||
type: object
|
||||
outcomes:
|
||||
items:
|
||||
|
||||
1
go.mod
1
go.mod
@@ -55,6 +55,7 @@ require (
|
||||
k8s.io/cli-runtime v0.34.0
|
||||
k8s.io/client-go v0.34.0
|
||||
k8s.io/klog/v2 v2.130.1
|
||||
k8s.io/kubernetes v1.33.4
|
||||
oras.land/oras-go v1.2.6
|
||||
sigs.k8s.io/controller-runtime v0.22.0
|
||||
sigs.k8s.io/e2e-framework v0.6.0
|
||||
|
||||
2
go.sum
2
go.sum
@@ -2261,6 +2261,8 @@ k8s.io/kubectl v0.33.3 h1:r/phHvH1iU7gO/l7tTjQk2K01ER7/OAJi8uFHHyWSac=
|
||||
k8s.io/kubectl v0.33.3/go.mod h1:euj2bG56L6kUGOE/ckZbCoudPwuj4Kud7BR0GzyNiT0=
|
||||
k8s.io/kubelet v0.34.0 h1:1nZt1Q6Kfx7xCaTS9vnqR9sjZDxf3cRSQkAFCczULmc=
|
||||
k8s.io/kubelet v0.34.0/go.mod h1:NqbF8ViVettlZbf9hw9DJhubaWn7rGvDDTcLMDm6tQ0=
|
||||
k8s.io/kubernetes v1.33.4 h1:T1d5FLUYm3/KyUeV7YJhKTR980zHCHb7K2xhCSo3lE8=
|
||||
k8s.io/kubernetes v1.33.4/go.mod h1:nrt8sldmckKz2fCZhgRX3SKfS2e+CzXATPv6ITNkU00=
|
||||
k8s.io/metrics v0.34.0 h1:nYSfG2+tnL6/MRC2I+sGHjtNEGoEoM/KktgGOoQFwws=
|
||||
k8s.io/metrics v0.34.0/go.mod h1:KCuXmotE0v4AvoARKUP8NC4lUnbK/Du1mluGdor5h4M=
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y=
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/util/taints"
|
||||
|
||||
"github.com/replicatedhq/troubleshoot/internal/util"
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
@@ -451,6 +452,10 @@ func nodeMatchesFilters(node corev1.Node, filters *troubleshootv1beta2.NodeResou
|
||||
}
|
||||
}
|
||||
|
||||
if filters.Taint != nil {
|
||||
return taints.TaintExists(node.Spec.Taints, filters.Taint), nil
|
||||
}
|
||||
|
||||
if filters.CPUArchitecture != "" {
|
||||
parsed := filters.CPUArchitecture
|
||||
|
||||
|
||||
@@ -702,6 +702,191 @@ func Test_nodeMatchesFilters(t *testing.T) {
|
||||
},
|
||||
expectResult: false,
|
||||
},
|
||||
{
|
||||
name: "true when taint exists",
|
||||
node: corev1.Node{
|
||||
Spec: corev1.NodeSpec{
|
||||
Taints: []corev1.Taint{
|
||||
{
|
||||
Key: "node.kubernetes.io/not-ready",
|
||||
Value: "",
|
||||
Effect: corev1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
filters: &troubleshootv1beta2.NodeResourceFilters{
|
||||
Taint: &corev1.Taint{
|
||||
Key: "node.kubernetes.io/not-ready",
|
||||
Effect: corev1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectResult: true,
|
||||
},
|
||||
{
|
||||
name: "true when taint exists with value match",
|
||||
node: corev1.Node{
|
||||
Spec: corev1.NodeSpec{
|
||||
Taints: []corev1.Taint{
|
||||
{
|
||||
Key: "dedicated",
|
||||
Value: "gpu",
|
||||
Effect: corev1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
filters: &troubleshootv1beta2.NodeResourceFilters{
|
||||
Taint: &corev1.Taint{
|
||||
Key: "dedicated",
|
||||
Value: "gpu",
|
||||
Effect: corev1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectResult: true,
|
||||
},
|
||||
{
|
||||
name: "false when taint key does not exist",
|
||||
node: corev1.Node{
|
||||
Spec: corev1.NodeSpec{
|
||||
Taints: []corev1.Taint{
|
||||
{
|
||||
Key: "node.kubernetes.io/not-ready",
|
||||
Value: "",
|
||||
Effect: corev1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
filters: &troubleshootv1beta2.NodeResourceFilters{
|
||||
Taint: &corev1.Taint{
|
||||
Key: "different-key",
|
||||
Effect: corev1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectResult: false,
|
||||
},
|
||||
{
|
||||
name: "false when taint effect does not match",
|
||||
node: corev1.Node{
|
||||
Spec: corev1.NodeSpec{
|
||||
Taints: []corev1.Taint{
|
||||
{
|
||||
Key: "node.kubernetes.io/not-ready",
|
||||
Value: "",
|
||||
Effect: corev1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
filters: &troubleshootv1beta2.NodeResourceFilters{
|
||||
Taint: &corev1.Taint{
|
||||
Key: "node.kubernetes.io/not-ready",
|
||||
Effect: corev1.TaintEffectNoExecute,
|
||||
},
|
||||
},
|
||||
expectResult: false,
|
||||
},
|
||||
{
|
||||
name: "true when taint value does not match but key and effect do (TaintExists only matches key and effect)",
|
||||
node: corev1.Node{
|
||||
Spec: corev1.NodeSpec{
|
||||
Taints: []corev1.Taint{
|
||||
{
|
||||
Key: "dedicated",
|
||||
Value: "gpu",
|
||||
Effect: corev1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
filters: &troubleshootv1beta2.NodeResourceFilters{
|
||||
Taint: &corev1.Taint{
|
||||
Key: "dedicated",
|
||||
Value: "cpu",
|
||||
Effect: corev1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectResult: true,
|
||||
},
|
||||
{
|
||||
name: "true when node has multiple taints and filter matches one",
|
||||
node: corev1.Node{
|
||||
Spec: corev1.NodeSpec{
|
||||
Taints: []corev1.Taint{
|
||||
{
|
||||
Key: "node.kubernetes.io/not-ready",
|
||||
Value: "",
|
||||
Effect: corev1.TaintEffectNoSchedule,
|
||||
},
|
||||
{
|
||||
Key: "dedicated",
|
||||
Value: "gpu",
|
||||
Effect: corev1.TaintEffectNoSchedule,
|
||||
},
|
||||
{
|
||||
Key: "example.com/special-hardware",
|
||||
Value: "true",
|
||||
Effect: corev1.TaintEffectNoExecute,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
filters: &troubleshootv1beta2.NodeResourceFilters{
|
||||
Taint: &corev1.Taint{
|
||||
Key: "dedicated",
|
||||
Value: "gpu",
|
||||
Effect: corev1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectResult: true,
|
||||
},
|
||||
{
|
||||
name: "true when node has no taints but no taint filter is specified",
|
||||
node: corev1.Node{
|
||||
Spec: corev1.NodeSpec{
|
||||
Taints: []corev1.Taint{},
|
||||
},
|
||||
},
|
||||
filters: &troubleshootv1beta2.NodeResourceFilters{},
|
||||
expectResult: true,
|
||||
},
|
||||
{
|
||||
name: "false when node has no taints but taint filter is specified",
|
||||
node: corev1.Node{
|
||||
Spec: corev1.NodeSpec{
|
||||
Taints: []corev1.Taint{},
|
||||
},
|
||||
},
|
||||
filters: &troubleshootv1beta2.NodeResourceFilters{
|
||||
Taint: &corev1.Taint{
|
||||
Key: "node.kubernetes.io/not-ready",
|
||||
Effect: corev1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectResult: false,
|
||||
},
|
||||
{
|
||||
name: "true when matching taint with PreferNoSchedule effect",
|
||||
node: corev1.Node{
|
||||
Spec: corev1.NodeSpec{
|
||||
Taints: []corev1.Taint{
|
||||
{
|
||||
Key: "node.kubernetes.io/memory-pressure",
|
||||
Value: "",
|
||||
Effect: corev1.TaintEffectPreferNoSchedule,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
filters: &troubleshootv1beta2.NodeResourceFilters{
|
||||
Taint: &corev1.Taint{
|
||||
Key: "node.kubernetes.io/memory-pressure",
|
||||
Effect: corev1.TaintEffectPreferNoSchedule,
|
||||
},
|
||||
},
|
||||
expectResult: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package v1beta2
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/replicatedhq/troubleshoot/pkg/multitype"
|
||||
@@ -142,6 +143,7 @@ type NodeResourceFilters struct {
|
||||
ResourceName string `json:"resourceName,omitempty" yaml:"resourceName,omitempty"`
|
||||
ResourceAllocatable string `json:"resourceAllocatable,omitempty" yaml:"resourceAllocatable,omitempty"`
|
||||
ResourceCapacity string `json:"resourceCapacity,omitempty" yaml:"resourceCapacity,omitempty"`
|
||||
Taint *corev1.Taint `json:"taint,omitempty" yaml:"taint,omitempty"`
|
||||
}
|
||||
|
||||
type NodeResourceSelectors struct {
|
||||
|
||||
@@ -22,7 +22,8 @@ package v1beta2
|
||||
|
||||
import (
|
||||
"github.com/replicatedhq/troubleshoot/pkg/multitype"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
@@ -3429,6 +3430,11 @@ func (in *NodeResourceFilters) DeepCopyInto(out *NodeResourceFilters) {
|
||||
*out = new(NodeResourceSelectors)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Taint != nil {
|
||||
in, out := &in.Taint, &out.Taint
|
||||
*out = new(v1.Taint)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeResourceFilters.
|
||||
@@ -3453,7 +3459,7 @@ func (in *NodeResourceSelectors) DeepCopyInto(out *NodeResourceSelectors) {
|
||||
}
|
||||
if in.MatchExpressions != nil {
|
||||
in, out := &in.MatchExpressions, &out.MatchExpressions
|
||||
*out = make([]v1.LabelSelectorRequirement, len(*in))
|
||||
*out = make([]metav1.LabelSelectorRequirement, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
|
||||
@@ -1914,6 +1914,33 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"taint": {
|
||||
"description": "The node this Taint is attached to has the \"effect\" on\nany pod that does not tolerate the Taint.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"effect",
|
||||
"key"
|
||||
],
|
||||
"properties": {
|
||||
"effect": {
|
||||
"description": "Required. The effect of the taint on pods\nthat do not tolerate the taint.\nValid effects are NoSchedule, PreferNoSchedule and NoExecute.",
|
||||
"type": "string"
|
||||
},
|
||||
"key": {
|
||||
"description": "Required. The taint key to be applied to a node.",
|
||||
"type": "string"
|
||||
},
|
||||
"timeAdded": {
|
||||
"description": "TimeAdded represents the time at which the taint was added.",
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"value": {
|
||||
"description": "The taint value corresponding to the taint key.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1914,6 +1914,33 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"taint": {
|
||||
"description": "The node this Taint is attached to has the \"effect\" on\nany pod that does not tolerate the Taint.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"effect",
|
||||
"key"
|
||||
],
|
||||
"properties": {
|
||||
"effect": {
|
||||
"description": "Required. The effect of the taint on pods\nthat do not tolerate the taint.\nValid effects are NoSchedule, PreferNoSchedule and NoExecute.",
|
||||
"type": "string"
|
||||
},
|
||||
"key": {
|
||||
"description": "Required. The taint key to be applied to a node.",
|
||||
"type": "string"
|
||||
},
|
||||
"timeAdded": {
|
||||
"description": "TimeAdded represents the time at which the taint was added.",
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"value": {
|
||||
"description": "The taint value corresponding to the taint key.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1960,6 +1960,33 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"taint": {
|
||||
"description": "The node this Taint is attached to has the \"effect\" on\nany pod that does not tolerate the Taint.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"effect",
|
||||
"key"
|
||||
],
|
||||
"properties": {
|
||||
"effect": {
|
||||
"description": "Required. The effect of the taint on pods\nthat do not tolerate the taint.\nValid effects are NoSchedule, PreferNoSchedule and NoExecute.",
|
||||
"type": "string"
|
||||
},
|
||||
"key": {
|
||||
"description": "Required. The taint key to be applied to a node.",
|
||||
"type": "string"
|
||||
},
|
||||
"timeAdded": {
|
||||
"description": "TimeAdded represents the time at which the taint was added.",
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"value": {
|
||||
"description": "The taint value corresponding to the taint key.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user