Repository: kubernetes/kubernetes (language: go)

Issue:
DRA: draplugin fails silently if vital parameter is missing
### What happened?

When calling draplugin.Start without supplying kubeclient no error is reported, while the kubeclient is vital for further announcement of resourceSlice.

### What did you expect to happen?

An error needs to be returned when nodeName or kubeclient parameters are not set.

### How can we reproduce it (as minimally and precisely as possible)?

Do not supply kubeclient parameter when creating draplugin, for isntance here: https://github.com/kubernetes-sigs/dra-example-driver/blob/abc52cfb8adfe5b160c168fd45f40a2e8f08c439/cmd/dra-example-kubeletplugin/driver.go#L50

### Anything else we need to know?

_No response_

### Kubernetes version

master

### Cloud provider

<details>

</details>


### OS version

<details>

```console
# On Linux:
$ cat /etc/os-release
# paste output here
$ uname -a
# paste output here

# On Windows:
C:\> wmic os get Caption, Version, BuildNumber, OSArchitecture
# paste output here
```

</details>


### Install tools

<details>

</details>


### Container runtime (CRI) and version (if applicable)

<details>

</details>


### Related plugins (CNI, CSI, ...) and versions (if applicable)

<details>

</details>



Discussion / hints:

Fix patch:
diff --git a/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/draplugin.go b/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/draplugin.go
index 94b9ae959afda..04eb826122303 100644
--- a/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/draplugin.go
+++ b/staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/draplugin.go
@@ -55,7 +55,10 @@ type DRAPlugin interface {
 	// to the API server.
 	//
 	// The caller must not modify the content after the call.
-	PublishResources(ctx context.Context, resources Resources)
+	//
+	// Returns an error if KubeClient or NodeName options were not
+	// set in Start() to create the DRAPlugin instance.
+	PublishResources(ctx context.Context, resources Resources) error
 
 	// This unexported method ensures that we can modify the interface
 	// without causing an API break of the package
@@ -254,6 +257,9 @@ type draPlugin struct {
 // The context and/or DRAPlugin.Stop can be used to stop all background activity.
 // Stop also blocks. A logger can be stored in the context to add values or
 // a name to all log entries.
+//
+// If the plugin will be used to publish resources, [KubeClient] and [NodeName]
+// options are mandatory.
 func Start(ctx context.Context, nodeServer interface{}, opts ...Option) (result DRAPlugin, finalErr error) {
 	logger := klog.FromContext(ctx)
 	o := options{
@@ -365,8 +371,16 @@ func (d *draPlugin) Stop() {
 	d.wg.Wait()
 }
 
-// PublishResources implements [DRAPlugin.PublishResources].
-func (d *draPlugin) PublishResources(ctx context.Context, resources Resources) {
+// PublishResources implements [DRAPlugin.PublishResources]. Returns en error if
+// kubeClient or nodeName are unset.
+func (d *draPlugin) PublishResources(ctx context.Context, resources Resources) error {
+	if d.kubeClient == nil {
+		return errors.New("no KubeClient found to publish resources")
+	}
+	if d.nodeName == "" {
+		return errors.New("no NodeName was set to publish resources")
+	}
+
 	d.mutex.Lock()
 	defer d.mutex.Unlock()
 
@@ -393,11 +407,13 @@ func (d *draPlugin) PublishResources(ctx context.Context, resources Resources) {
 		controllerLogger = klog.LoggerWithName(controllerLogger, "ResourceSlice controller")
 		controllerCtx = klog.NewContext(controllerCtx, controllerLogger)
 		d.resourceSliceController = resourceslice.StartController(controllerCtx, d.kubeClient, d.driverName, owner, driverResources)
-		return
+		return nil
 	}
 
 	// Inform running controller about new information.
 	d.resourceSliceController.Update(driverResources)
+
+	return nil
 }
 
 // RegistrationStatus implements [DRAPlugin.RegistrationStatus].


Test patch:
diff --git a/test/e2e/dra/test-driver/app/kubeletplugin.go b/test/e2e/dra/test-driver/app/kubeletplugin.go
index da6d1f555b325..1cf2716b7fba0 100644
--- a/test/e2e/dra/test-driver/app/kubeletplugin.go
+++ b/test/e2e/dra/test-driver/app/kubeletplugin.go
@@ -182,7 +182,9 @@ func StartPlugin(ctx context.Context, cdiDir, driverName string, kubeClient kube
 		resources := kubeletplugin.Resources{
 			Devices: devices,
 		}
-		ex.d.PublishResources(ctx, resources)
+		if err := ex.d.PublishResources(ctx, resources); err != nil {
+			return nil, fmt.Errorf("start kubelet plugin: publish resources: %w", err)
+		}
 	} else if len(ex.fileOps.Devices) > 0 {
 		devices := make([]resourceapi.Device, len(ex.fileOps.Devices))
 		for i, deviceName := range sets.List(ex.deviceNames) {
@@ -194,7 +196,9 @@ func StartPlugin(ctx context.Context, cdiDir, driverName string, kubeClient kube
 		resources := kubeletplugin.Resources{
 			Devices: devices,
 		}
-		ex.d.PublishResources(ctx, resources)
+		if err := ex.d.PublishResources(ctx, resources); err != nil {
+			return nil, fmt.Errorf("start kubelet plugin: publish resources: %w", err)
+		}
 	}
 
 	return ex, nil