@@ -39,7 +39,7 @@ import (
3939 "k8s.io/apimachinery/pkg/api/errors"
4040 "k8s.io/apimachinery/pkg/types"
4141 "k8s.io/apimachinery/pkg/util/validation"
42- "k8s.io/client-go/kubernetes"
42+ k8sclient "k8s.io/client-go/kubernetes"
4343 "k8s.io/klog/v2"
4444 klogutils "sigs.k8s.io/node-feature-discovery/pkg/utils/klog"
4545 "sigs.k8s.io/yaml"
@@ -131,6 +131,7 @@ type nfdWorker struct {
131131 kubernetesNamespace string
132132 grpcClient pb.LabelerClient
133133 healthServer * grpc.Server
134+ k8sClient k8sclient.Interface
134135 nfdClient * nfdclient.Clientset
135136 stop chan struct {} // channel for signaling stop
136137 featureSources []source.FeatureSource
@@ -143,30 +144,70 @@ type infiniteTicker struct {
143144 * time.Ticker
144145}
145146
147+ // NfdWorkerOption sets properties of the NfdWorker instance.
148+ type NfdWorkerOption interface {
149+ apply (* nfdWorker )
150+ }
151+
152+ // WithArgs is used for passing settings from command line arguments.
153+ func WithArgs (args * Args ) NfdWorkerOption {
154+ return & nfdMWorkerOpt {f : func (n * nfdWorker ) { n .args = * args }}
155+ }
156+
157+ // WithKuberneteClient forces to use the given kubernetes client, without
158+ // initializing one from kubeconfig.
159+ func WithKubernetesClient (cli k8sclient.Interface ) NfdWorkerOption {
160+ return & nfdMWorkerOpt {f : func (n * nfdWorker ) { n .k8sClient = cli }}
161+ }
162+
163+ type nfdMWorkerOpt struct {
164+ f func (* nfdWorker )
165+ }
166+
167+ func (f * nfdMWorkerOpt ) apply (n * nfdWorker ) {
168+ f .f (n )
169+ }
170+
146171// NewNfdWorker creates new NfdWorker instance.
147- func NewNfdWorker (args * Args ) (NfdWorker , error ) {
172+ func NewNfdWorker (opts ... NfdWorkerOption ) (NfdWorker , error ) {
148173 nfd := & nfdWorker {
149- args : * args ,
150174 config : & NFDConfig {},
151175 kubernetesNamespace : utils .GetKubernetesNamespace (),
152176 stop : make (chan struct {}),
153177 }
154178
179+ for _ , o := range opts {
180+ o .apply (nfd )
181+ }
182+
155183 // Check TLS related args
156- if args .CertFile != "" || args .KeyFile != "" || args .CaFile != "" {
157- if args .CertFile == "" {
184+ if nfd . args .CertFile != "" || nfd . args .KeyFile != "" || nfd . args .CaFile != "" {
185+ if nfd . args .CertFile == "" {
158186 return nfd , fmt .Errorf ("-cert-file needs to be specified alongside -key-file and -ca-file" )
159187 }
160- if args .KeyFile == "" {
188+ if nfd . args .KeyFile == "" {
161189 return nfd , fmt .Errorf ("-key-file needs to be specified alongside -cert-file and -ca-file" )
162190 }
163- if args .CaFile == "" {
191+ if nfd . args .CaFile == "" {
164192 return nfd , fmt .Errorf ("-ca-file needs to be specified alongside -cert-file and -key-file" )
165193 }
166194 }
167195
168- if args .ConfigFile != "" {
169- nfd .configFilePath = filepath .Clean (args .ConfigFile )
196+ if nfd .args .ConfigFile != "" {
197+ nfd .configFilePath = filepath .Clean (nfd .args .ConfigFile )
198+ }
199+
200+ // k8sClient might've been set via opts by tests
201+ if nfd .k8sClient == nil {
202+ kubeconfig , err := utils .GetKubeconfig (nfd .args .Kubeconfig )
203+ if err != nil {
204+ return nfd , err
205+ }
206+ cli , err := k8sclient .NewForConfig (kubeconfig )
207+ if err != nil {
208+ return nfd , err
209+ }
210+ nfd .k8sClient = cli
170211 }
171212
172213 return nfd , nil
@@ -273,32 +314,33 @@ func (w *nfdWorker) Run() error {
273314 labelTrigger .Reset (w .config .Core .SleepInterval .Duration )
274315 defer labelTrigger .Stop ()
275316
317+ // Create owner ref
318+ ownerReference := []metav1.OwnerReference {}
276319 // Get pod owner reference
277320 podName := os .Getenv ("POD_NAME" )
278- client , err := w .getKubeClient ()
279- if err != nil {
280- return fmt .Errorf ("failed to get kube client: %w" , err )
281- }
282-
283- selfPod , err := client .CoreV1 ().Pods (w .kubernetesNamespace ).Get (context .TODO (), podName , metav1.GetOptions {})
284- if err != nil {
285- return fmt .Errorf ("failed to get pod %q: %w" , podName , err )
286- }
287-
288- // Create owner ref
289- ownerReference := selfPod .OwnerReferences
290321
291322 // Add pod owner reference if it exists
292- podUID := os .Getenv ("POD_UID" )
293- if podName != "" && podUID != "" {
294- isTrue := true
295- ownerReference = append (ownerReference , metav1.OwnerReference {
296- APIVersion : "v1" ,
297- Kind : "Pod" ,
298- Name : podName ,
299- UID : types .UID (podUID ),
300- Controller : & isTrue ,
301- })
323+ if podName != "" {
324+ if selfPod , err := w .k8sClient .CoreV1 ().Pods (w .kubernetesNamespace ).Get (context .TODO (), podName , metav1.GetOptions {}); err != nil {
325+ klog .ErrorS (err , "failed to get self pod, cannot inherit ownerReference for NodeFeature" )
326+ return err
327+ } else {
328+ ownerReference = append (ownerReference , selfPod .OwnerReferences ... )
329+ }
330+
331+ podUID := os .Getenv ("POD_UID" )
332+ if podUID != "" {
333+ ownerReference = append (ownerReference , metav1.OwnerReference {
334+ APIVersion : "v1" ,
335+ Kind : "Pod" ,
336+ Name : podName ,
337+ UID : types .UID (podUID ),
338+ })
339+ } else {
340+ klog .InfoS ("Cannot append POD ownerReference to NodeFeature, POD_UID not specified" )
341+ }
342+ } else {
343+ klog .InfoS ("Cannot set NodeFeature owner references, POD_NAME not specified" )
302344 }
303345
304346 w .ownerReference = ownerReference
@@ -814,22 +856,6 @@ func (m *nfdWorker) getNfdClient() (*nfdclient.Clientset, error) {
814856 return c , nil
815857}
816858
817- func (m * nfdWorker ) getKubeClient () (* kubernetes.Clientset , error ) {
818- // creates the in-cluster config
819- kubeconfig , err := utils .GetKubeconfig (m .args .Kubeconfig )
820- if err != nil {
821- return nil , err
822- }
823-
824- // creates the clientset
825- clientset , err := kubernetes .NewForConfig (kubeconfig )
826- if err != nil {
827- return nil , err
828- }
829-
830- return clientset , nil
831- }
832-
833859// UnmarshalJSON implements the Unmarshaler interface from "encoding/json"
834860func (c * sourcesConfig ) UnmarshalJSON (data []byte ) error {
835861 // First do a raw parse to get the per-source data
0 commit comments