Skip to content

ReconcilerUtils.setSpec() cannot find the spec if it is a Custom Resource #1589

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
fsjovatsen opened this issue Nov 7, 2022 · 1 comment · Fixed by #1591
Closed

ReconcilerUtils.setSpec() cannot find the spec if it is a Custom Resource #1589

fsjovatsen opened this issue Nov 7, 2022 · 1 comment · Fixed by #1591
Assignees
Milestone

Comments

@fsjovatsen
Copy link

Bug Report

What did you do?

When updating an instance of a Custom Resource we get an exception in the ReconcilerUtils.setSpec(HasMetadata resource, Object spec):

io.javaoperatorsdk.operator.AggregatedOperatorException: Exception during workflow.
	at io.javaoperatorsdk.operator.processing.dependent.workflow.WorkflowReconcileResult.createFinalException(WorkflowReconcileResult.java:54) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.dependent.workflow.WorkflowReconcileResult.throwAggregateExceptionIfErrorsPresent(WorkflowReconcileResult.java:48) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.dependent.workflow.Workflow.reconcile(Workflow.java:56) ~[operator-framework-core-3.2.0.jar:na]
	at no.fintlabs.FlaisReconiler.reconcile(FlaisReconiler.java:50) ~[flais-operator-starter-1.0.0-rc-4.jar:na]
	at no.fintlabs.FlaisReconiler.reconcile(FlaisReconiler.java:20) ~[flais-operator-starter-1.0.0-rc-4.jar:na]
	at io.javaoperatorsdk.operator.processing.Controller$1.execute(Controller.java:130) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.Controller$1.execute(Controller.java:88) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.api.monitoring.Metrics.timeControllerExecution(Metrics.java:197) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.Controller.reconcile(Controller.java:87) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.reconcileExecution(ReconciliationDispatcher.java:130) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.handleReconcile(ReconciliationDispatcher.java:110) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.handleDispatch(ReconciliationDispatcher.java:81) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.handleExecution(ReconciliationDispatcher.java:54) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.event.EventProcessor$ReconcilerExecutor.run(EventProcessor.java:395) ~[operator-framework-core-3.2.0.jar:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
	at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
Caused by: java.lang.IllegalStateException: No spec found on resource
	at io.javaoperatorsdk.operator.ReconcilerUtils.setSpec(ReconcilerUtils.java:112) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.dependent.kubernetes.GenericResourceUpdatePreProcessor$3.updateClonedActual(GenericResourceUpdatePreProcessor.java:40) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.dependent.kubernetes.GenericResourceUpdatePreProcessor.replaceSpecOnActual(GenericResourceUpdatePreProcessor.java:48) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource.update(KubernetesDependentResource.java:132) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource.update(CRUDKubernetesDependentResource.java:17) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.dependent.AbstractDependentResource.handleUpdate(AbstractDependentResource.java:111) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource.handleUpdate(KubernetesDependentResource.java:119) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource.handleUpdate(KubernetesDependentResource.java:32) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.dependent.AbstractDependentResource.reconcile(AbstractDependentResource.java:50) ~[operator-framework-core-3.2.0.jar:na]
	at io.javaoperatorsdk.operator.processing.dependent.workflow.WorkflowReconcileExecutor$NodeReconcileExecutor.run(WorkflowReconcileExecutor.java:166) ~[operator-framework-core-3.2.0.jar:na]
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) ~[na:na]
	at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264) ~[na:na]
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java) ~[na:na]
	... 3 common frames omitted
Caused by: java.lang.NoSuchMethodException: no.fintlabs.onepassword.OnePasswordCrd.setSpec(no.fintlabs.onepassword.OnePasswordSpec)
	at java.base/java.lang.Class.getMethod(Class.java:2227) ~[na:na]
	at io.javaoperatorsdk.operator.ReconcilerUtils.setSpec(ReconcilerUtils.java:109) ~[operator-framework-core-3.2.0.jar:na]
	... 15 common frames omitted

This is only happening when we update, not on create.

This is the desired method from the dependent resource class. This is how I create the CRD instance.

    @Override
    protected OnePasswordCrd desired(FlaisApplicationCrd primary, Context<FlaisApplicationCrd> context) {

        OnePasswordCrd onePasswordCrd = new OnePasswordCrd();
        onePasswordCrd.getMetadata().setLabels(LabelFactory.updateRecommendedLabels(primary));
        onePasswordCrd.getMetadata().setName(primary.getMetadata().getName());
        onePasswordCrd.getMetadata().setNamespace(primary.getMetadata().getNamespace());
        onePasswordCrd.getSpec().setItemPath(primary.getSpec().getOnePassword().getItemPath());

        return onePasswordCrd;
    }

This is the CRD class.

@Group("onepassword.com")
@Version("v1")
@Kind("OnePasswordItem")
public class OnePasswordCrd extends CustomResource<OnePasswordSpec, Void> implements Namespaced {
    @Override
    protected OnePasswordSpec initSpec() {
        return new OnePasswordSpec();
    }
}

This is the spec class.

@Data
public class OnePasswordSpec {
    private String itemPath;
}

One can see the source code here

What did you expect to see?

No exception and the resource updated.

What did you see instead? Under which circumstances?

See the description further up.

Environment

Kubernetes cluster type:

Azure Kubernetes Service

io.javaoperatorsdk.operator-framework:3.2.0

openjdk 17.0.2 2022-01-18 LTS

Client Version: v1.24.0
Kustomize Version: v4.5.4
Server Version: v1.22.11

Possible Solution

What happens is that if it is a CustomResource we're not able to get the setSpec() method.
The reason seems to be related to reflection. If I do resource.getClass().getMethod("setSpec", Object.class)
instead of resource.getClass().getMethod("setSpec", spec.getClass()) it seems to work.

It might be a solution to check if the resource extends CustomResource and then do
resource.getClass().getMethod("setSpec", Object.class)

Additional context

@csviri
Copy link
Collaborator

csviri commented Nov 8, 2022

thx @fsjovatsen and @scrocquesel for the fix.

Will release v4.1.1 with this fix soon. @fsjovatsen from 3.2.0 is should be trivial to update to that version

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

Successfully merging a pull request may close this issue.

2 participants