operator-framework / java-operator-sdk

Java SDK for building Kubernetes Operators
https://javaoperatorsdk.io/
Apache License 2.0
797 stars 215 forks source link

Spring beans are not loaded in managed dependent resource #2166

Open rameshmalla opened 10 months ago

rameshmalla commented 10 months ago

Bug Report

What did you do?

I'm using josdk-spring-boot-starter to build an operator with a managed dependent resource, something similar to this example. When I inject a spring bean inside the dependent resource, on application startup I noticed that the spring beans were not instantiated and were always null. For example, in this demo application the operator fails due to NPE here

In a nutshell, the whole spring proxied dependent resource was ignored by the operator framework and instead created another instance of the dependent resource.

What did you expect to see?

The expectation from the framework is not to ignore spring proxied beans.

What did you see instead? Under which circumstances?

Spring beans are not instantiated.

Environment

Kubernetes cluster type: vanilla

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

implementation 'io.javaoperatorsdk:operator-framework-spring-boot-starter:5.0.0'
    annotationProcessor 'io.javaoperatorsdk:operator-framework:4.3.1'
    annotationProcessor 'io.fabric8:crd-generator-apt:6.5.1'

$ java -version 17

$ kubectl version

Possible Solution

Additional context

I have a demo application with the similar setup. The tests were failing because of the above mentioned issue.

csviri commented 10 months ago

Hi @rameshmalla , The managed dependent resources are not interconnected with spring bean container, basically you cannot do this.

(Also calling an external service during desired is probably not a good idea, this might slow down the reconciliation even if nothing changed)

csviri commented 10 months ago

Note that this work in Quarkus extension, if you want to give that a try.

kosmoz commented 10 months ago

This is a valid use-case IMO. It is very common to receive configuration properties via Spring DI, for example.

The only way I found to work around this limitation was to create a custom DependentResourceFactory that creates the DR instance via the Spring AppicationContext, thus registering it as a Bean. It still has to call DependentResourceConfigurationResolver.configure with the DR instance.

The last time I checked, this was not possible when using josdk-spring-boot-starter, but this was already some time ago so things might have changed in the meantime.

csviri commented 10 months ago

I mean in general it is a valid use cases to have these beans injected, and have some config params in their.

Was referring to this part: https://github.com/rameshmalla/demo-operator/blob/be32d49ac2804f23338b74d2ac254cdfda1e41b6/src/main/java/com/example/demo/ConfigMapDependentResource.java#L27

calling an external service while computing a desired. At least would cache the result (with some timeout) for some time on client side so it is not called every time desired is computed (what can be very frequent in some cases ).

csviri commented 10 months ago

Only problem is that we don't have the bandwidth for such improvements, if anybody would volunteer to implement it in the SB starter, would be a big help.

rameshmalla commented 10 months ago

Thanks, @csviri and @kosmoz for your inputs and suggestions, Indeed quarkus looks like a promising option I will explore the possibilities of migrating from spring-boot to quarkus. Meanwhile I will try to replicate @kosmoz suggestion on having a custom DependentResourceFactory that respects spring context.

github-actions[bot] commented 8 months ago

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 14 days.