@@ -3,13 +3,15 @@ package nidhogg
33import (
44 "context"
55 "fmt"
6- "github.com/uswitch/nidhogg/pkg/utils"
7- "k8s.io/apimachinery/pkg/api/errors"
86 "reflect"
97 "strings"
108 "time"
119
10+ "github.com/uswitch/nidhogg/pkg/utils"
11+ "k8s.io/apimachinery/pkg/api/errors"
12+
1213 "github.com/prometheus/client_golang/prometheus"
14+ appsv1 "k8s.io/api/apps/v1"
1315 corev1 "k8s.io/api/core/v1"
1416 "k8s.io/apimachinery/pkg/labels"
1517 "k8s.io/apimachinery/pkg/types"
@@ -66,20 +68,25 @@ type HandlerConfig struct {
6668 TaintNamePrefix string `json:"taintNamePrefix,omitempty" yaml:"taintNamePrefix,omitempty"`
6769 TaintRemovalDelayInSeconds int `json:"taintRemovalDelayInSeconds,omitempty" yaml:"taintRemovalDelayInSeconds,omitempty"`
6870 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
7173}
7274
7375func (hc * HandlerConfig ) BuildSelectors () error {
74- hc .Selector = labels .Everything ()
76+ hc .DaemonsetSelectors = make (map [Daemonset ]labels.Selector )
77+ globalSelector := labels .Nothing ()
7578 for _ , rawSelector := range hc .NodeSelector {
7679 if selector , err := labels .Parse (rawSelector ); err != nil {
7780 return fmt .Errorf ("error parsing selector: %v" , err )
7881 } else {
7982 requirements , _ := selector .Requirements ()
80- hc . Selector = hc . Selector .Add (requirements ... )
83+ globalSelector = labels . NewSelector () .Add (requirements ... )
8184 }
8285 }
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+ }
8390 return nil
8491}
8592
@@ -116,15 +123,10 @@ func (h *Handler) HandleNode(ctx context.Context, request reconcile.Request) (re
116123 return reconcile.Result {}, err
117124 }
118125
119- //check whether nodeName matches the nodeSelector
120- if ! h .config .Selector .Matches (labels .Set (latestNode .Labels )) {
121- return reconcile.Result {}, nil
122- }
123-
124126 updatedNode , taintChanges , err := h .calculateTaints (ctx , latestNode )
125127 if err != nil {
126128 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 )
128130 }
129131
130132 taintLess := true
@@ -179,6 +181,18 @@ func (h *Handler) HandleNode(ctx context.Context, request reconcile.Request) (re
179181 return reconcile.Result {}, nil
180182}
181183
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+
182196func (h * Handler ) calculateTaints (ctx context.Context , instance * corev1.Node ) (* corev1.Node , taintChanges , error ) {
183197
184198 nodeCopy := instance .DeepCopy ()
@@ -195,28 +209,42 @@ func (h *Handler) calculateTaints(ctx context.Context, instance *corev1.Node) (*
195209 }
196210 for _ , daemonset := range h .config .Daemonsets {
197211
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+ }
203222 }
204223
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+ }
215245 }
216- // taint is not already present, adding it
217- changes .taintsAdded = append (changes .taintsAdded , taint )
218- nodeCopy .Spec .Taints = addTaint (nodeCopy .Spec .Taints , taint )
219246 }
247+
220248 for taint := range taintsToRemove {
221249 h .applyTaintRemovalDelay ()
222250 nodeCopy .Spec .Taints = removeTaint (nodeCopy .Spec .Taints , taint )
0 commit comments