Skip to content

Commit 37a385b

Browse files
authored
More flexible selectors for force drain (#183)
* Add `namespaceSelector` to node force drainer * Pod JQ selector and tests * Safeguard JQ execution * Test and highlight that it's ok to return a boolean stream
1 parent fa63630 commit 37a385b

8 files changed

Lines changed: 466 additions & 166 deletions

File tree

api/v1beta1/node_force_drain_types.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,25 @@ import (
77
// NodeForceDrainSpec defines the desired state of NodeForceDrain
88
type NodeForceDrainSpec struct {
99
// NodeSelector is a selector to select which nodes to drain
10-
// A nil selector matches no nodes, while an empty selector matches all nodes.
11-
NodeSelector *metav1.LabelSelector `json:"nodeSelector"`
10+
// An empty selector matches all nodes.
11+
NodeSelector metav1.LabelSelector `json:"nodeSelector"`
12+
// NamespaceSelector is a selector to select which namespaces to drain
13+
// An empty selector matches all namespaces.
14+
NamespaceSelector metav1.LabelSelector `json:"namespaceSelector,omitempty"`
15+
// PodJQSelector is a selector to select which pods to drain.
16+
// The selector is a JQ selector that should return a stream of one or more booleans.
17+
// If any of the booleans are true, the pod will be drained.
18+
// An empty stream will not drain the pod.
19+
// Any non-boolean value will be ignored but will not halt the program.
20+
// Under the hood https://github.com/itchyny/gojq is used which is mostly compatible
21+
// with https://jqlang.org/manual/ but has some small limitations and might lag a bit behind upstream.
22+
// If the program is halted - due to error or explicit `halt` - before any boolean is returned, the pod will not be drained.
23+
// If the program is halted - due to error or explicit `halt` - after a truthy boolean is returned, the pod will be drained.
24+
// Examples:
25+
// .metadata.namespace | test("-dev$")
26+
// .spec.containers[] | .image | test("oktodrain")
27+
// [.spec.containers[] | .image | test("oktodrain")] | all
28+
PodJQSelector string `json:"podJQSelector,omitempty"`
1229
// NodeDrainGracePeriod is the duration until the controller starts to delete pods on the node.
1330
// The duration is calculated from the OpenShist node drain annotation.
1431
// This circumvents the eviction API and means that PDBs are ignored.

api/v1beta1/zz_generated.deepcopy.go

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

config/crd/bases/managedupgrade.appuio.io_nodeforcedrains.yaml

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,54 @@ spec:
3939
spec:
4040
description: NodeForceDrainSpec defines the desired state of NodeForceDrain
4141
properties:
42+
namespaceSelector:
43+
description: |-
44+
NamespaceSelector is a selector to select which namespaces to drain
45+
An empty selector matches all namespaces.
46+
properties:
47+
matchExpressions:
48+
description: matchExpressions is a list of label selector requirements.
49+
The requirements are ANDed.
50+
items:
51+
description: |-
52+
A label selector requirement is a selector that contains values, a key, and an operator that
53+
relates the key and values.
54+
properties:
55+
key:
56+
description: key is the label key that the selector applies
57+
to.
58+
type: string
59+
operator:
60+
description: |-
61+
operator represents a key's relationship to a set of values.
62+
Valid operators are In, NotIn, Exists and DoesNotExist.
63+
type: string
64+
values:
65+
description: |-
66+
values is an array of string values. If the operator is In or NotIn,
67+
the values array must be non-empty. If the operator is Exists or DoesNotExist,
68+
the values array must be empty. This array is replaced during a strategic
69+
merge patch.
70+
items:
71+
type: string
72+
type: array
73+
x-kubernetes-list-type: atomic
74+
required:
75+
- key
76+
- operator
77+
type: object
78+
type: array
79+
x-kubernetes-list-type: atomic
80+
matchLabels:
81+
additionalProperties:
82+
type: string
83+
description: |-
84+
matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
85+
map is equivalent to an element of matchExpressions, whose key field is "key", the
86+
operator is "In", and the values array contains only "value". The requirements are ANDed.
87+
type: object
88+
type: object
89+
x-kubernetes-map-type: atomic
4290
nodeDrainGracePeriod:
4391
description: |-
4492
NodeDrainGracePeriod is the duration until the controller starts to delete pods on the node.
@@ -50,7 +98,7 @@ spec:
5098
nodeSelector:
5199
description: |-
52100
NodeSelector is a selector to select which nodes to drain
53-
A nil selector matches no nodes, while an empty selector matches all nodes.
101+
An empty selector matches all nodes.
54102
properties:
55103
matchExpressions:
56104
description: matchExpressions is a list of label selector requirements.
@@ -106,6 +154,22 @@ spec:
106154
Such pods do block the reboot of the node and the node will stay in a `NotReady` state for extended periods.
107155
A zero value disables the force delete.
108156
type: string
157+
podJQSelector:
158+
description: |-
159+
PodJQSelector is a selector to select which pods to drain.
160+
The selector is a JQ selector that should return a stream of one or more booleans.
161+
If any of the booleans are true, the pod will be drained.
162+
An empty stream will not drain the pod.
163+
Any non-boolean value will be ignored but will not halt the program.
164+
Under the hood https://github.com/itchyny/gojq is used which is mostly compatible
165+
with https://jqlang.org/manual/ but has some small limitations and might lag a bit behind upstream.
166+
If the program is halted - due to error or explicit `halt` - before any boolean is returned, the pod will not be drained.
167+
If the program is halted - due to error or explicit `halt` - after a truthy boolean is returned, the pod will be drained.
168+
Examples:
169+
.metadata.namespace | test("-dev$")
170+
.spec.containers[] | .image | test("oktodrain")
171+
[.spec.containers[] | .image | test("oktodrain")] | all
172+
type: string
109173
required:
110174
- nodeDrainGracePeriod
111175
- nodeSelector

config/rbac/role.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ rules:
1414
- apiGroups:
1515
- ""
1616
resources:
17+
- namespaces
1718
- nodes
1819
verbs:
1920
- get

0 commit comments

Comments
 (0)