@@ -36,7 +36,7 @@ import (
3636 "k8s.io/apimachinery/pkg/api/errors"
3737 "k8s.io/apimachinery/pkg/types"
3838 "k8s.io/apimachinery/pkg/util/validation"
39- "k8s.io/client-go/kubernetes"
39+ k8sclient "k8s.io/client-go/kubernetes"
4040 "k8s.io/klog/v2"
4141 klogutils "sigs.k8s.io/node-feature-discovery/pkg/utils/klog"
4242 "sigs.k8s.io/yaml"
@@ -126,42 +126,84 @@ type nfdWorker struct {
126126 config * NFDConfig
127127 kubernetesNamespace string
128128 grpcClient pb.LabelerClient
129- nfdClient * nfdclient.Clientset
130- stop chan struct {} // channel for signaling stop
131- featureSources []source.FeatureSource
132- labelSources []source.LabelSource
133- ownerReference []metav1.OwnerReference
129+
130+ k8sClient k8sclient.Interface
131+ nfdClient * nfdclient.Clientset
132+ stop chan struct {} // channel for signaling stop
133+ featureSources []source.FeatureSource
134+ labelSources []source.LabelSource
135+ ownerReference []metav1.OwnerReference
134136}
135137
136138// This ticker can represent infinite and normal intervals.
137139type infiniteTicker struct {
138140 * time.Ticker
139141}
140142
143+ // NfdWorkerOption sets properties of the NfdWorker instance.
144+ type NfdWorkerOption interface {
145+ apply (* nfdWorker )
146+ }
147+
148+ // WithArgs is used for passing settings from command line arguments.
149+ func WithArgs (args * Args ) NfdWorkerOption {
150+ return & nfdMWorkerOpt {f : func (n * nfdWorker ) { n .args = * args }}
151+ }
152+
153+ // WithKuberneteClient forces to use the given kubernetes client, without
154+ // initializing one from kubeconfig.
155+ func WithKubernetesClient (cli k8sclient.Interface ) NfdWorkerOption {
156+ return & nfdMWorkerOpt {f : func (n * nfdWorker ) { n .k8sClient = cli }}
157+ }
158+
159+ type nfdMWorkerOpt struct {
160+ f func (* nfdWorker )
161+ }
162+
163+ func (f * nfdMWorkerOpt ) apply (n * nfdWorker ) {
164+ f .f (n )
165+ }
166+
141167// NewNfdWorker creates new NfdWorker instance.
142- func NewNfdWorker (args * Args ) (NfdWorker , error ) {
168+ func NewNfdWorker (opts ... NfdWorkerOption ) (NfdWorker , error ) {
143169 nfd := & nfdWorker {
144- args : * args ,
145170 config : & NFDConfig {},
146171 kubernetesNamespace : utils .GetKubernetesNamespace (),
147172 stop : make (chan struct {}, 1 ),
148173 }
149174
175+ for _ , o := range opts {
176+ o .apply (nfd )
177+ }
178+
150179 // Check TLS related args
151- if args .CertFile != "" || args .KeyFile != "" || args .CaFile != "" {
152- if args .CertFile == "" {
180+ if nfd . args .CertFile != "" || nfd . args .KeyFile != "" || nfd . args .CaFile != "" {
181+ if nfd . args .CertFile == "" {
153182 return nfd , fmt .Errorf ("-cert-file needs to be specified alongside -key-file and -ca-file" )
154183 }
155- if args .KeyFile == "" {
184+ if nfd . args .KeyFile == "" {
156185 return nfd , fmt .Errorf ("-key-file needs to be specified alongside -cert-file and -ca-file" )
157186 }
158- if args .CaFile == "" {
187+ if nfd . args .CaFile == "" {
159188 return nfd , fmt .Errorf ("-ca-file needs to be specified alongside -cert-file and -key-file" )
160189 }
161190 }
162191
163- if args .ConfigFile != "" {
164- nfd .configFilePath = filepath .Clean (args .ConfigFile )
192+ if nfd .args .ConfigFile != "" {
193+ nfd .configFilePath = filepath .Clean (nfd .args .ConfigFile )
194+ }
195+
196+ // k8sClient might've been set via opts by tests
197+ if nfd .k8sClient == nil {
198+ kubeconfig , err := apihelper .GetKubeconfig (nfd .args .Kubeconfig )
199+ if err != nil {
200+ return nfd , err
201+ }
202+ cli , err := k8sclient .NewForConfig (kubeconfig )
203+ if err != nil {
204+ return nfd , err
205+ }
206+ nfd .k8sClient = cli
165207 }
166208
167209 return nfd , nil
@@ -245,32 +287,33 @@ func (w *nfdWorker) Run() error {
245287 labelTrigger .Reset (w .config .Core .SleepInterval .Duration )
246288 defer labelTrigger .Stop ()
247289
290+ // Create owner ref
291+ ownerReference := []metav1.OwnerReference {}
248292 // Get pod owner reference
249293 podName := os .Getenv ("POD_NAME" )
250- client , err := w .getKubeClient ()
251- if err != nil {
252- return fmt .Errorf ("failed to get kube client: %w" , err )
253- }
254-
255- selfPod , err := client .CoreV1 ().Pods (w .kubernetesNamespace ).Get (context .TODO (), podName , metav1.GetOptions {})
256- if err != nil {
257- return fmt .Errorf ("failed to get pod %q: %w" , podName , err )
258- }
259-
260- // Create owner ref
261- ownerReference := selfPod .OwnerReferences
262294
263295 // Add pod owner reference if it exists
264- podUID := os .Getenv ("POD_UID" )
265- if podName != "" && podUID != "" {
266- isTrue := true
267- ownerReference = append (ownerReference , metav1.OwnerReference {
268- APIVersion : "v1" ,
269- Kind : "Pod" ,
270- Name : podName ,
271- UID : types .UID (podUID ),
272- Controller : & isTrue ,
273- })
296+ if podName != "" {
297+ if selfPod , err := w .k8sClient .CoreV1 ().Pods (w .kubernetesNamespace ).Get (context .TODO (), podName , metav1.GetOptions {}); err != nil {
298+ klog .ErrorS (err , "failed to get self pod, cannot inherit ownerReference for NodeFeature" )
299+ return err
300+ } else {
301+ ownerReference = append (ownerReference , selfPod .OwnerReferences ... )
302+ }
303+
304+ podUID := os .Getenv ("POD_UID" )
305+ if podUID != "" {
306+ ownerReference = append (ownerReference , metav1.OwnerReference {
307+ APIVersion : "v1" ,
308+ Kind : "Pod" ,
309+ Name : podName ,
310+ UID : types .UID (podUID ),
311+ })
312+ } else {
313+ klog .InfoS ("Cannot append POD ownerReference to NodeFeature, POD_UID not specified" )
314+ }
315+ } else {
316+ klog .InfoS ("Cannot set NodeFeature owner references, POD_NAME not specified" )
274317 }
275318
276319 w .ownerReference = ownerReference
@@ -774,22 +817,6 @@ func (m *nfdWorker) getNfdClient() (*nfdclient.Clientset, error) {
774817 return c , nil
775818}
776819
777- func (m * nfdWorker ) getKubeClient () (* kubernetes.Clientset , error ) {
778- // creates the in-cluster config
779- kubeconfig , err := utils .GetKubeconfig (m .args .Kubeconfig )
780- if err != nil {
781- return nil , err
782- }
783-
784- // creates the clientset
785- clientset , err := kubernetes .NewForConfig (kubeconfig )
786- if err != nil {
787- return nil , err
788- }
789-
790- return clientset , nil
791- }
792-
793820// UnmarshalJSON implements the Unmarshaler interface from "encoding/json"
794821func (c * sourcesConfig ) UnmarshalJSON (data []byte ) error {
795822 // First do a raw parse to get the per-source data
0 commit comments