Skip to content

Bug: Webhook validations swallow GetResourceIfExist errors across 7 call sites #373

Description

@Elvand-Lie

📜 Description

Seven call sites across three webhook validation files discard the error return from util.GetResourceIfExist, using the pattern exist, _ := util.GetResourceIfExist(...). When the API server is temporarily unreachable, GetResourceIfExist returns (false, err). The discarded error causes the webhook to misinterpret an API failure as "resource not found" and return a misleading validation error to the user.

Affected call sites:

# File Line What's being looked up Misleading error returned
1 service/cluster_webhook_validation.go 73 Project namespace "cluster must be applied on project namespace"
2 service/service_export_config_webhook_validation.go 65 Source cluster "Cluster is not registered"
3 service/service_export_config_webhook_validation.go 67 SliceConfig "There is no valid slice with this name"
4 service/service_export_config_webhook_validation.go 93 Endpoint cluster "Cluster is not registered"
5 service/service_export_config_webhook_validation.go 95 Endpoint slice "There is no valid slice with this name"
6 service/service_export_config_webhook_validation.go 119 Project namespace "ServiceExportConfig must be applied on project namespace"
7 service/slice_qos_config_webhook_validation.go 60 Project namespace "SliceQosConfig must be applied on project namespace"

Example from cluster_webhook_validation.go:

// service/cluster_webhook_validation.go, lines 71-78
func validateAppliedInProjectNamespace(ctx context.Context, c *controllerv1alpha1.Cluster) *field.Error {
    namespace := &corev1.Namespace{}
    exist, _ := util.GetResourceIfExist(ctx, client.ObjectKey{Name: c.Namespace}, namespace)
    //     ^ error silently discarded
    if !exist || !util.CheckForProjectNamespace(namespace) {
        return field.Invalid(field.NewPath("metadata").Child("namespace"), c.Namespace,
            "cluster must be applied on project namespace")
    }
    return nil
}

Example from service_export_config_webhook_validation.go:

// service/service_export_config_webhook_validation.go, lines 63-73
func validateServiceExportClusterAndSlice(ctx context.Context, serviceExport *controllerv1alpha1.ServiceExportConfig) *field.Error {
    cluster := &controllerv1alpha1.Cluster{}
    clusterExist, _ := util.GetResourceIfExist(ctx, client.ObjectKey{...}, cluster)
    //             ^ error discarded
    sliceConfig := &controllerv1alpha1.SliceConfig{}
    sliceExist, _ := util.GetResourceIfExist(ctx, client.ObjectKey{...}, sliceConfig)
    //            ^ error discarded
    if !sliceExist {
        return field.Invalid(..., "There is no valid slice with this name")
    }
    if !clusterExist {
        return field.Invalid(..., "Cluster is not registered")
    }
    // ...
}

Note: this is distinct from issue #360 (SliceConfig validating webhook performing writes). This issue is about swallowed read errors across the three other webhook validation files.

👟 Reproduction steps

  1. Have a working kubeslice-controller with clusters, slices, and service exports configured.

  2. Induce a transient API server failure affecting GET requests. This can occur naturally during:

    • etcd leader failover (typically 1-5 seconds)
    • API server rolling restart
    • Network partition between the webhook pod and the API server
    • API server resource pressure (high QPS causing throttling)
  3. During the transient failure, attempt any of these operations:

    • Create or update a Cluster → rejected with "cluster must be applied on project namespace"
    • Create or update a ServiceExportConfig → rejected with "Cluster is not registered" or "There is no valid slice with this name"
    • Create a SliceQoSConfig → rejected with "SliceQosConfig must be applied on project namespace"
  4. The error messages are misleading — the resources exist and the namespace is correct, but the API lookup failed transiently.

  5. Automated tooling (Helm, ArgoCD, GitOps pipelines) retries the operation, gets the same misleading error, and may escalate as a configuration issue instead of a transient infrastructure issue.

👍 Expected behavior

When GetResourceIfExist returns an error, the webhook should return a field.InternalError that accurately describes the API failure. This allows:

  • Users to see the real error ("internal error: failed to look up namespace") instead of a misleading validation error
  • Automated tooling to distinguish transient failures from genuine configuration errors
  • Operators to troubleshoot the actual root cause

👎 Actual Behavior

The error is discarded. The webhook returns a validation error that incorrectly blames the user's input:

  • "cluster must be applied on project namespace" (when the namespace IS correct)
  • "Cluster is not registered" (when the cluster IS registered)
  • "There is no valid slice with this name" (when the slice DOES exist)

This is confusing for operators, wastes debugging time, and causes false alerts in CI/CD pipelines.

🐚 Relevant log output

No error is logged by the webhook validation functions. The actual API error
from GetResourceIfExist is silently discarded.

The user sees only the misleading admission rejection:

Error from server (Invalid): error when creating "cluster.yaml":
Cluster.controller.kubeslice.io "worker-1" is invalid:
  metadata.namespace: Invalid value: "kubeslice-my-project":
    cluster must be applied on project namespace

This is indistinguishable from a genuinely misconfigured cluster, making the
transient failure extremely difficult to diagnose.

Version

master branch (latest HEAD as of 2026-05-15). The bug exists since the initial implementation of webhook validations in all three files.

🖥️ What operating system are you seeing the problem on?

No response

✅ Proposed Solution

At each of the 7 call sites, check the error and return field.InternalError when non-nil.

Example fix for cluster_webhook_validation.go line 73:

Current code:

exist, _ := util.GetResourceIfExist(ctx, client.ObjectKey{Name: c.Namespace}, namespace)
if !exist || !util.CheckForProjectNamespace(namespace) {

Fixed code:

exist, err := util.GetResourceIfExist(ctx, client.ObjectKey{Name: c.Namespace}, namespace)
if err != nil {
    return field.InternalError(field.NewPath("metadata").Child("namespace"),
        fmt.Errorf("failed to look up namespace %s: %w", c.Namespace, err))
}
if !exist || !util.CheckForProjectNamespace(namespace) {

Apply the same pattern to all 7 sites. Each fix is 3-4 lines. Total change: ~25 lines across 3 files.

This is consistent with how the VpnKeyRotation webhook validation handles errors (returning err directly at lines 26-28 of vpn_key_rotation_webhook_validation.go).

👀 Have you spent some time to check if this issue has been raised before?

  • I checked and didn't find any similar issue

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions