@@ -3,13 +3,15 @@ package nidhogg
3
3
import (
4
4
"context"
5
5
"fmt"
6
- "github.com/uswitch/nidhogg/pkg/utils"
7
- "k8s.io/apimachinery/pkg/api/errors"
8
6
"reflect"
9
7
"strings"
10
8
"time"
11
9
10
+ "github.com/uswitch/nidhogg/pkg/utils"
11
+ "k8s.io/apimachinery/pkg/api/errors"
12
+
12
13
"github.com/prometheus/client_golang/prometheus"
14
+ appsv1 "k8s.io/api/apps/v1"
13
15
corev1 "k8s.io/api/core/v1"
14
16
"k8s.io/apimachinery/pkg/labels"
15
17
"k8s.io/apimachinery/pkg/types"
@@ -66,20 +68,25 @@ type HandlerConfig struct {
66
68
TaintNamePrefix string `json:"taintNamePrefix,omitempty" yaml:"taintNamePrefix,omitempty"`
67
69
TaintRemovalDelayInSeconds int `json:"taintRemovalDelayInSeconds,omitempty" yaml:"taintRemovalDelayInSeconds,omitempty"`
68
70
Daemonsets []Daemonset `json:"daemonsets" yaml:"daemonsets"`
69
- NodeSelector []string `json:"nodeSelector" yaml:"nodeSelector"`
70
- Selector labels.Selector
71
+ NodeSelector []string `json:"nodeSelector,omitempty " yaml:"nodeSelector,omitempty "`
72
+ DaemonsetSelectors map [ Daemonset ] labels.Selector
71
73
}
72
74
73
75
func (hc * HandlerConfig ) BuildSelectors () error {
74
- hc .Selector = labels .Everything ()
76
+ hc .DaemonsetSelectors = make (map [Daemonset ]labels.Selector )
77
+ globalSelector := labels .Nothing ()
75
78
for _ , rawSelector := range hc .NodeSelector {
76
79
if selector , err := labels .Parse (rawSelector ); err != nil {
77
80
return fmt .Errorf ("error parsing selector: %v" , err )
78
81
} else {
79
82
requirements , _ := selector .Requirements ()
80
- hc . Selector = hc . Selector .Add (requirements ... )
83
+ globalSelector = labels . NewSelector () .Add (requirements ... )
81
84
}
82
85
}
86
+ //Will initialize all daemonsets with the same selector, either representing the NodeSelector config or labels.Nothing if no config was provided for NodeSelector
87
+ for _ , daemonset := range hc .Daemonsets {
88
+ hc .DaemonsetSelectors [daemonset ] = globalSelector
89
+ }
83
90
return nil
84
91
}
85
92
@@ -116,15 +123,10 @@ func (h *Handler) HandleNode(ctx context.Context, request reconcile.Request) (re
116
123
return reconcile.Result {}, err
117
124
}
118
125
119
- //check whether nodeName matches the nodeSelector
120
- if ! h .config .Selector .Matches (labels .Set (latestNode .Labels )) {
121
- return reconcile.Result {}, nil
122
- }
123
-
124
126
updatedNode , taintChanges , err := h .calculateTaints (ctx , latestNode )
125
127
if err != nil {
126
128
taintOperationErrors .WithLabelValues ("calculateTaints" ).Inc ()
127
- return reconcile.Result {}, fmt .Errorf ("error caluclating taints for nodeName: %v" , err )
129
+ return reconcile.Result {}, fmt .Errorf ("error calculating taints for nodeName: %v" , err )
128
130
}
129
131
130
132
taintLess := true
@@ -179,6 +181,18 @@ func (h *Handler) HandleNode(ctx context.Context, request reconcile.Request) (re
179
181
return reconcile.Result {}, nil
180
182
}
181
183
184
+ func (h * Handler ) getSelectorFromDaemonSet (ctx context.Context , daemonset Daemonset ) (labels.Selector , error ) {
185
+ ds := & appsv1.DaemonSet {}
186
+ err := h .Get (ctx , types.NamespacedName {Namespace : daemonset .Namespace , Name : daemonset .Name }, ds )
187
+ if err != nil {
188
+ logf .Log .Info (fmt .Sprintf ("Could not fetch daemonset %s from namespace %s" , daemonset .Name , daemonset .Namespace ))
189
+ return nil , err
190
+ }
191
+ selector := labels .SelectorFromSet (ds .Spec .Template .Spec .NodeSelector )
192
+
193
+ return selector , nil
194
+ }
195
+
182
196
func (h * Handler ) calculateTaints (ctx context.Context , instance * corev1.Node ) (* corev1.Node , taintChanges , error ) {
183
197
184
198
nodeCopy := instance .DeepCopy ()
@@ -195,28 +209,42 @@ func (h *Handler) calculateTaints(ctx context.Context, instance *corev1.Node) (*
195
209
}
196
210
for _ , daemonset := range h .config .Daemonsets {
197
211
198
- taint := fmt .Sprintf ("%s/%s.%s" , h .getTaintNamePrefix (), daemonset .Namespace , daemonset .Name )
199
- // Get Pod for nodeName
200
- pods , err := h .getDaemonsetPods (ctx , instance .Name , daemonset )
201
- if err != nil {
202
- return nil , taintChanges {}, fmt .Errorf ("error fetching pods: %v" , err )
212
+ //If NodeSelector was not provided upfront through config
213
+ if h .config .NodeSelector == nil {
214
+ //Will try to get selectors from daemonset directly
215
+ selector , err := h .getSelectorFromDaemonSet (ctx , daemonset )
216
+ if err != nil {
217
+ logf .Log .Info (fmt .Sprintf ("Could not fetch selector from daemonset %s in namespace %s" , daemonset .Name , daemonset .Namespace ))
218
+ } else {
219
+ //Override existing daemonset selector with the one freshly retrieved from the daemonset
220
+ h .config .DaemonsetSelectors [daemonset ] = selector
221
+ }
203
222
}
204
223
205
- if len (pods ) > 0 && utils .AllTrue (pods , func (pod * corev1.Pod ) bool { return podReady (pod ) }) {
206
- // if the taint is in the taintsToRemove map, it'll be removed
207
- continue
208
- }
209
- // pod doesn't exist or is not ready
210
- _ , ok := taintsToRemove [taint ]
211
- if ok {
212
- // we want to keep this already existing taint on it
213
- delete (taintsToRemove , taint )
214
- continue
224
+ //make sure daemonset selector matches node selector
225
+ if h .config .DaemonsetSelectors [daemonset ].Matches (labels .Set (instance .Labels )) {
226
+ taint := fmt .Sprintf ("%s/%s.%s" , h .getTaintNamePrefix (), daemonset .Namespace , daemonset .Name )
227
+ // Get Pod for nodeName
228
+ pods , err := h .getDaemonsetPods (ctx , instance .Name , daemonset )
229
+ if err != nil {
230
+ return nil , taintChanges {}, fmt .Errorf ("error fetching pods: %v" , err )
231
+ }
232
+
233
+ if len (pods ) == 0 || (len (pods ) > 0 && ! utils .AllTrue (pods , func (pod * corev1.Pod ) bool { return podReady (pod ) })) {
234
+ // pod doesn't exist or is not ready
235
+ _ , ok := taintsToRemove [taint ]
236
+ if ok {
237
+ // we want to keep this already existing taint on it
238
+ delete (taintsToRemove , taint )
239
+ } else {
240
+ // taint is not already present, adding it
241
+ changes .taintsAdded = append (changes .taintsAdded , taint )
242
+ nodeCopy .Spec .Taints = addTaint (nodeCopy .Spec .Taints , taint )
243
+ }
244
+ }
215
245
}
216
- // taint is not already present, adding it
217
- changes .taintsAdded = append (changes .taintsAdded , taint )
218
- nodeCopy .Spec .Taints = addTaint (nodeCopy .Spec .Taints , taint )
219
246
}
247
+
220
248
for taint := range taintsToRemove {
221
249
h .applyTaintRemovalDelay ()
222
250
nodeCopy .Spec .Taints = removeTaint (nodeCopy .Spec .Taints , taint )
0 commit comments