Skip to content

Using the CRUDKubernetesDependentResource with a cluster-scoped secondary resource results in KubernetesClientException: namespace cannot be null #1682

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
silenium-dev opened this issue Dec 26, 2022 · 0 comments

Comments

@silenium-dev
Copy link
Contributor

silenium-dev commented Dec 26, 2022

Bug Report

What did you do?

I've used a namespace with the Dependent Resource Feature, the dependent resource implementation below:

@KubernetesDependent(labelSelector = ProjectReconciler.SELECTOR)
class NamespaceDR : CRUDKubernetesDependentResource<Namespace, Project>(Namespace::class.java) {
    override fun desired(primary: Project, context: Context<Project>): Namespace {
        return NamespaceBuilder()
            .withNewMetadata()
            .withName(primary.targetNamespace)
            .addToLabels(ProjectReconciler.SELECTOR, primary.metadata.name)
            .endMetadata()
            .build()
    }
}

What did you expect to see?

It creates, updates and deletes the namespace according to changes in the primary resource.

What did you see instead? Under which circumstances?

As soon as I've created the primary resource, the operator logs the following exception:

Caused by: io.fabric8.kubernetes.client.KubernetesClientException: namespace cannot be null
	at io.javaoperatorsdk.operator.processing.dependent.workflow.WorkflowResult.throwAggregateExceptionIfErrorsPresent(WorkflowResult.java:40)
	at io.javaoperatorsdk.operator.processing.dependent.workflow.WorkflowReconcileResult.throwAggregateExceptionIfErrorsPresent(WorkflowReconcileResult.java:9)
	at io.javaoperatorsdk.operator.processing.dependent.workflow.DefaultWorkflow.reconcile(DefaultWorkflow.java:92)
	at io.javaoperatorsdk.operator.processing.Controller$1.execute(Controller.java:140)
	at io.javaoperatorsdk.operator.processing.Controller$1.execute(Controller.java:103)
	at io.javaoperatorsdk.operator.api.monitoring.Metrics.timeControllerExecution(Metrics.java:206)
	at io.javaoperatorsdk.operator.processing.Controller.reconcile(Controller.java:102)
	at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.reconcileExecution(ReconciliationDispatcher.java:141)
	at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.handleReconcile(ReconciliationDispatcher.java:121)
	at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.handleDispatch(ReconciliationDispatcher.java:91)
	at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.handleExecution(ReconciliationDispatcher.java:64)
	at io.javaoperatorsdk.operator.processing.event.EventProcessor$ReconcilerExecutor.run(EventProcessor.java:415)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:833)

Environment

Kubernetes cluster type:

I'm using a local minikube on libvirt and CRI-O.

$ Mention java-operator-sdk version from pom.xml file

java-operator-sdk version used: 4.2.0

$ java -version

openjdk version "17.0.5" 2022-10-18
OpenJDK Runtime Environment GraalVM CE 22.3.0 (build 17.0.5+8-jvmci-22.3-b08)
OpenJDK 64-Bit Server VM GraalVM CE 22.3.0 (build 17.0.5+8-jvmci-22.3-b08, mixed mode, sharing)

$ kubectl version

Client Version: version.Info{Major:"1", Minor:"24", GitVersion:"v1.24.4", GitCommit:"95ee5ab382d64cfe6c28967f36b53970b8374491", GitTreeState:"clean", BuildDate:"2022-08-17T18:54:23Z", GoVersion:"go1.18.5", Compiler:"gc", Platform:"linux/amd64"}
Kustomize Version: v4.5.4
Server Version: version.Info{Major:"1", Minor:"25", GitVersion:"v1.25.3", GitCommit:"434bfd82814af038ad94d62ebe59b133fcb50506", GitTreeState:"clean", BuildDate:"2022-10-12T10:49:09Z", GoVersion:"go1.19.2", Compiler:"gc", Platform:"linux/amd64"}

Possible Solution

A possible fix would be to check in KubernetesDependentResource.prepare() whether the secondary resource implements Namespaced:

@Override
protected Resource<R> prepare(R desired, P primary, String actionName) {
    log.debug("{} target resource with type: {}, with id: {}",
            actionName,
            desired.getClass(),
            ResourceID.fromResource(desired));
    if (addOwnerReference()) {
        desired.addOwnerReference(primary);
    } else if (useDefaultAnnotationsToIdentifyPrimary()) {
        addDefaultSecondaryToPrimaryMapperAnnotations(desired, primary);
    }
    if (desired instanceof Namespaced) {
        return client.resource(desired).inNamespace(desired.getMetadata().getNamespace());
    } else {
        return client.resource(desired);
    }
}

Additional context

I'm using the Quarkiverse Operator SDK extension for Quarkus to integrate the Operator SDK with Quarkus, but this should be causing the issue.

@silenium-dev silenium-dev changed the title Using the CRUDKubernetesDependentResource with a namespace results in KubernetesClientException: namespace cannot be null Using the CRUDKubernetesDependentResource with cluster-scoped secondary resource results in KubernetesClientException: namespace cannot be null Dec 26, 2022
@silenium-dev silenium-dev changed the title Using the CRUDKubernetesDependentResource with cluster-scoped secondary resource results in KubernetesClientException: namespace cannot be null Using the CRUDKubernetesDependentResource with a cluster-scoped secondary resource results in KubernetesClientException: namespace cannot be null Dec 26, 2022
@csviri csviri closed this as completed Dec 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants