operator-framework / josdk-spring-boot-starter Goto Github PK
View Code? Open in Web Editor NEWLicense: Apache License 2.0
License: Apache License 2.0
I have heard that this project is unfortunatly in maintenance mode.
I also have made the experience to use an own base instead of this project if an operator based on spring boot is required. We had some problems overriding defaults.
I would like to change this and make it again a useful base for spring-boot based operators.
Would you change your mind if I would create a PR with some major changes?
I will add here some details in the next days/weeks.
The Kubernetes connection cannot be created because of an exception when I start my operator.
Using io.javaoperatorsdk:operator-framework-spring-boot-starter:5.1.0 I'm instantiating my Reconciler through the annotation.
My operator starts running.
14:51:19.800 INFO c.t.c.c.CMCCOperatorApplication - Starting CMCCOperatorApplication using Java 17.0.7 on XXXX with PID 90946 (/Users/stbe/develop/cmcc-operator/build/classes/java/main started by stbe in /Users/stbe/develop/cmcc-operator)
14:51:19.802 DEBUG c.t.c.c.CMCCOperatorApplication - Running with Spring Boot v2.7.13, Spring v5.3.28
14:51:19.802 INFO c.t.c.c.CMCCOperatorApplication - The following 1 profile is active: "dev"
14:51:20.300 INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http)
14:51:20.304 INFO o.a.catalina.core.StandardService - Starting service [Tomcat]
14:51:20.304 INFO o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.76]
14:51:20.381 INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
14:51:20.381 INFO o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 561 ms
14:51:20.860 WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'coreMediaContentCloudReconciler' defined in com.tsystemsmms.cmcc.cmccoperator.CMCCOperatorApplication: Unsatisfied dependency expressed through method 'coreMediaContentCloudReconciler' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'kubernetesClient' defined in class path resource [io/javaoperatorsdk/operator/springboot/starter/OperatorAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.fabric8.kubernetes.client.KubernetesClient]: Factory method 'kubernetesClient' threw exception; nested exception is java.lang.NoSuchFieldError: readTimeout
14:51:20.862 INFO o.a.catalina.core.StandardService - Stopping service [Tomcat]
14:51:20.870 INFO o.s.b.a.l.ConditionEvaluationReportLoggingListener -
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
14:51:20.880 ERROR o.s.boot.SpringApplication - Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'coreMediaContentCloudReconciler' defined in com.tsystemsmms.cmcc.cmccoperator.CMCCOperatorApplication: Unsatisfied dependency expressed through method 'coreMediaContentCloudReconciler' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'kubernetesClient' defined in class path resource [io/javaoperatorsdk/operator/springboot/starter/OperatorAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.fabric8.kubernetes.client.KubernetesClient]: Factory method 'kubernetesClient' threw exception; nested exception is java.lang.NoSuchFieldError: readTimeout
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:541)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:920)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292)
at com.tsystemsmms.cmcc.cmccoperator.CMCCOperatorApplication.main(CMCCOperatorApplication.java:97)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'kubernetesClient' defined in class path resource [io/javaoperatorsdk/operator/springboot/starter/OperatorAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.fabric8.kubernetes.client.KubernetesClient]: Factory method 'kubernetesClient' threw exception; nested exception is java.lang.NoSuchFieldError: readTimeout
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
... 19 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.fabric8.kubernetes.client.KubernetesClient]: Factory method 'kubernetesClient' threw exception; nested exception is java.lang.NoSuchFieldError: readTimeout
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)
... 33 common frames omitted
Caused by: java.lang.NoSuchFieldError: readTimeout
at io.fabric8.kubernetes.client.okhttp.OkHttpClientBuilderImpl.derivedBuild(OkHttpClientBuilderImpl.java:94)
at io.fabric8.kubernetes.client.okhttp.OkHttpClientBuilderImpl.initialBuild(OkHttpClientBuilderImpl.java:90)
at io.fabric8.kubernetes.client.okhttp.OkHttpClientBuilderImpl.build(OkHttpClientBuilderImpl.java:52)
at io.fabric8.kubernetes.client.okhttp.OkHttpClientBuilderImpl.build(OkHttpClientBuilderImpl.java:33)
at io.fabric8.kubernetes.client.KubernetesClientBuilder.getHttpClient(KubernetesClientBuilder.java:94)
at io.fabric8.kubernetes.client.KubernetesClientBuilder.build(KubernetesClientBuilder.java:79)
at io.javaoperatorsdk.operator.springboot.starter.OperatorAutoConfiguration.lambda$kubernetesClient$3(OperatorAutoConfiguration.java:60)
at java.base/java.util.Optional.orElseGet(Optional.java:364)
at io.javaoperatorsdk.operator.springboot.starter.OperatorAutoConfiguration.kubernetesClient(OperatorAutoConfiguration.java:59)
at io.javaoperatorsdk.operator.springboot.starter.OperatorAutoConfiguration$$EnhancerBySpringCGLIB$$2ec03ae0.CGLIB$kubernetesClient$7(<generated>)
at io.javaoperatorsdk.operator.springboot.starter.OperatorAutoConfiguration$$EnhancerBySpringCGLIB$$2ec03ae0$$FastClassBySpringCGLIB$$94def8d5.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331)
at io.javaoperatorsdk.operator.springboot.starter.OperatorAutoConfiguration$$EnhancerBySpringCGLIB$$2ec03ae0.kubernetesClient(<generated>)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 34 common frames omitted
n/a
There seems to be a discrepancy in the version for io.fabric8:kubernetes-httpclient-okhttp. When I force 6.7.1 through gradle, it appears to be working correctly.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter:3.1.1'
// developmentOnly 'org.springframework.boot:spring-boot-devtools:3.1.1'
implementation 'org.springframework.boot:spring-boot-starter-actuator:3.1.1'
implementation 'org.springframework.boot:spring-boot-starter-web:3.1.1'
implementation 'io.javaoperatorsdk:operator-framework-spring-boot-starter:5.1.0'
constraints {
implementation('io.fabric8:kubernetes-httpclient-okhttp:6.7.1') {
because 'some internal dependencies seem to be for 6.6.2 which works differently'
}
}
implementation 'org.bouncycastle:bcpkix-jdk15on:1.70'
// required for the fabric8 k8s client to grok k3d certificates
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor:3.1.1'
compileOnly 'org.projectlombok:lombok'
testCompileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'io.fabric8:crd-generator-apt:6.5.0'
testImplementation 'org.springframework.boot:spring-boot-starter-test:3.1.1'
testImplementation 'io.javaoperatorsdk:operator-framework-spring-boot-starter-test:5.1.0'
}
Create the following integration test
On the last step controller will not get the resource update / delete event. This happens because of two things:
generation
metadata property to decide what to do with resource event. There is a function called CustomResourceEventSource.skipBecauseOfGeneration, which rejects events with a generation lower or equal to existing one.generation
property.Only if to set @Controller(generationAwareEventProcessing = false)
then update events will reach out to controller.
I think the MockServer should be updated to be in sync with a default Controller settings.
Auto configuration is currently not working in projects using Spring Boot 3, because the spring.factories
file is no longer supported (source).
There might be more issues, but I did not get past auto configuration.
Are there any plans to add support for Spring Boot 3?
With these dependencies:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter:3.2.3'
// developmentOnly 'org.springframework.boot:spring-boot-devtools:3.2.0'
implementation 'org.springframework.boot:spring-boot-starter-actuator:3.2.3'
implementation 'org.springframework.boot:spring-boot-starter-web:3.2.3'
implementation 'io.javaoperatorsdk:operator-framework-spring-boot-starter:5.4.1'
implementation 'org.bouncycastle:bcpkix-jdk15on:1.70'
// required for the fabric8 k8s client to grok k3d certificates
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor:3.2.3'
compileOnly 'org.projectlombok:lombok'
testCompileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'io.fabric8:crd-generator-apt:6.10.0'
testImplementation 'org.springframework.boot:spring-boot-starter-test:3.2.3'
testImplementation 'io.javaoperatorsdk:operator-framework-spring-boot-starter-test:5.4.1'
}
I'm getting this error on startup:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'coreMediaContentCloudReconciler' defined in com.tsystemsmms.cmcc.cmccoperator.CMCCOperatorApplication: Unsatisfied dependency expressed through method 'coreMediaContentCloudReconciler' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'kubernetesClient' defined in class path resource [io/javaoperatorsdk/operator/springboot/starter/OperatorAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.fabric8.kubernetes.client.KubernetesClient]: Factory method 'kubernetesClient' threw exception; nested exception is java.lang.IncompatibleClassChangeError: class io.fabric8.kubernetes.client.okhttp.OkHttpClientImpl overrides final method io.fabric8.kubernetes.client.http.StandardHttpClient.close()V
...
Caused by: java.lang.IncompatibleClassChangeError: class io.fabric8.kubernetes.client.okhttp.OkHttpClientImpl overrides final method io.fabric8.kubernetes.client.http.StandardHttpClient.close()V
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1012)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
at io.fabric8.kubernetes.client.okhttp.OkHttpClientBuilderImpl.completeBuild(OkHttpClientBuilderImpl.java:122)
at io.fabric8.kubernetes.client.okhttp.OkHttpClientBuilderImpl.initialBuild(OkHttpClientBuilderImpl.java:94)
at io.fabric8.kubernetes.client.okhttp.OkHttpClientBuilderImpl.build(OkHttpClientBuilderImpl.java:55)
at io.fabric8.kubernetes.client.okhttp.OkHttpClientBuilderImpl.build(OkHttpClientBuilderImpl.java:36)
at io.fabric8.kubernetes.client.KubernetesClientBuilder.getHttpClient(KubernetesClientBuilder.java:94)
at io.fabric8.kubernetes.client.KubernetesClientBuilder.build(KubernetesClientBuilder.java:79)
at io.javaoperatorsdk.operator.springboot.starter.OperatorAutoConfiguration.lambda$kubernetesClient$3(OperatorAutoConfiguration.java:61)
I'm not sure what to do here.
To have better IDE support on configuration files, metadata for the configuration properties should be added.
I had some problems with my test related to security and because of that I wanted to ue the KubernetesMockServer started in non secure mode. Unfortunatelly this is not configurable in the TestConfiguration class.
What I want to propose is to make this configurable through the class TestConfigurationProperties.
I can offer a PR if you consider this acceptable
The starter project and starter-test project have circular dependencies.
Move starter-test inside this project.
When using
The OperatorAutoConfiguration
fails to create the Operator
-Bean due to multiple candidates for Bean of type Consumer<ConfigurationServiceOverrider>
:
Parameter 1 of method operator in io.javaoperatorsdk.operator.springboot.starter.OperatorAutoConfiguration required a single bean, but 2 were found:
- compositeConfigurationServiceOverrider: defined by method 'compositeConfigurationServiceOverrider' in class path resource [io/javaoperatorsdk/operator/springboot/starter/OperatorAutoConfiguration.class]
- defaultConfigServiceOverrider: defined by method 'defaultConfigServiceOverrider' in class path resource [io/javaoperatorsdk/operator/springboot/starter/OperatorAutoConfiguration.class]
Cause
This behaviour is because there are two @Bean
-Methods both producing a Bean of type Consumer<ConfigurationServiceOverrider>
:
public Consumer<ConfigurationServiceOverrider> compositeConfigurationServiceOverrider(..)
at OperatorAutoConfiguration.java#L112public Consumer<ConfigurationServiceOverrider> defaultConfigServiceOverrider(...)
at OperatorAutoConfiguration.java#L122As far as i understand the intention is to have a default implementation for an overrider (with a low order) and another one that aggregates all overrider beans.
With that in mind, the usual use-case would be to just use the aggregate (aka compositeConfigurationServiceOverride) on the consumer side, thus this bean could probably be the "primary".
Workaround
A workaround would be to provide the Operator-Bean manually via:
@Configuration
public class OperatorConfig {
@Bean(destroyMethod = "stop")
@ConditionalOnMissingBean(Operator.class)
public Operator operator(
BiConsumer<Operator, Reconciler<?>> reconcilerRegisterer,
@Qualifier("compositeConfigurationServiceOverrider")
Consumer<ConfigurationServiceOverrider> compositeConfigurationServiceOverrider,
KubernetesClient kubernetesClient,
List<Reconciler<?>> reconcilers) {
var operator = new Operator(kubernetesClient, compositeConfigurationServiceOverrider);
reconcilers.forEach(reconciler -> reconcilerRegisterer.accept(operator, reconciler));
return operator;
}
}
Note: The only difference to the AutoConfiguration (OperatorAutoConfiguration.java#L89) is the @Qualifier("compositeConfigurationServiceOverrider")
.
Solution
IMHO this could also be the Solution: just add the Qualifier Annotation to the AutoConfiguration method.
Another option is to Annotate the OperatorAutoConfiguration.java#compositeConfigurationServiceOverrider-Method with @Primary
but i think thats probably too restrictive.
What do you think?
I'm want to compile and run my operator as a native image in a setup with Kotlin/Java 21 + Spring Boot 3 + GraalVM.
So far Native Build is currently only explicitly supported by the Quarkus extension. A explicit Native Build support for Spring Boot is missing and has to be added.
If anybody knows already any examples or reference projects/repos that have done the same, please shout out :) Otherwise, I will look into adding support in a reasonable amount of time.
hello
Since upgrading fabric8 client from 6.7.2 to 6.8.0
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getClientConfiguration' defined in class path resource [io/javaoperatorsdk/operator/springboot/starter/OperatorAutoConfiguration.class]: Failed to instantiate [io.fabric8.kubernetes.client.Config]: Factory method 'getClientConfiguration' threw exception with message: io/fabric8/kubernetes/client/ConfigFluentImpl
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:655) ~[spring-beans-6.1.2.jar:6.1.2]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:643) ~[spring-beans-6.1.2.jar:6.1.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334) ~[spring-beans-6.1.2.jar:6.1.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1164) ~[spring-beans-6.1.2.jar:6.1.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[spring-beans-6.1.2.jar:6.1.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[spring-beans-6.1.2.jar:6.1.2]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[spring-beans-6.1.2.jar:6.1.2]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.2.jar:6.1.2]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[spring-beans-6.1.2.jar:6.1.2]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-6.1.2.jar:6.1.2]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.2.jar:6.1.2]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:960) ~[spring-context-6.1.2.jar:6.1.2]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625) ~[spring-context-6.1.2.jar:6.1.2]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.2.1.jar:3.2.1]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:762) [spring-boot-3.2.1.jar:3.2.1]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:464) [spring-boot-3.2.1.jar:3.2.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:334) [spring-boot-3.2.1.jar:3.2.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1358) [spring-boot-3.2.1.jar:3.2.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1347) [spring-boot-3.2.1.jar:3.2.1]
at com.navercorp.opensearch.operator.OpenSearchOperatorApplicationKt.main(OpenSearchOperatorApplication.kt:15) [main/:?]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.fabric8.kubernetes.client.Config]: Factory method 'getClientConfiguration' threw exception with message: io/fabric8/kubernetes/client/ConfigFluentImpl
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:177) ~[spring-beans-6.1.2.jar:6.1.2]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651) ~[spring-beans-6.1.2.jar:6.1.2]
... 19 more
I get this error message
Do you know why??
A new version of the java-operator-sdk was released and this starter should be updated to comply with changes for that version.
Details for migration can be found https://javaoperatorsdk.io/docs/v3-migration
In operator-framework-spring-boot-starter module
, username/password authentication is supported for newly created kubernetes client. However, in some cases, username/password is unsupported and only OAuth token is supported, the later one is more secure. Maybe we can support both.
More details are in method io.javaoperatorsdk.operator.springboot.starter.OperatorAutoConfiguration#getClientConfiguration
:
xxx
.orElseGet(() -> {
final var clientCfg = configuration.getClient();
ConfigBuilder config = new ConfigBuilder();
config.withTrustCerts(clientCfg.isTrustSelfSignedCertificates());
clientCfg.getMasterUrl().ifPresent(config::withMasterUrl);
clientCfg.getUsername().ifPresent(config::withUsername);
clientCfg.getPassword().ifPresent(config::withPassword);
More details can be found at java-operator-sdk issue 1282.
Currently, the kubernetes-server-mock in test scope in operator-framework-spring-boot-starter-parent is 5.11.2, but the latest operator-framework-core has the kubernetes-server-mock with version 5.12.2. The two versions are incompatible because of their transitive dependency on kubernetes-module-core.
In operator-framework-core 3.0.2, io.javaoperatorsdk.operator.ReconcilerUtils#isFinalizerValid
called HashMetadata.validateFinalizer(finalizer)
, but this method is not available for kubernetes-server-mock 5.11.2 (in fact, it's dependency kubernetes-model-core 5.11.2 doesn't have this method, but version 5.12.2 has this method).
I have a test dependency for Reconcilers:
<dependency>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework-spring-boot-starter-test</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
But the test will failed to compile because:
Exception in thread "OkHttp Dispatcher" java.lang.NoSuchMethodError: io.fabric8.kubernetes.api.model.HasMetadata.validateFinalizer(Ljava/lang/String;)Z
at io.javaoperatorsdk.operator.ReconcilerUtils.isFinalizerValid(ReconcilerUtils.java:30)
at io.javaoperatorsdk.operator.api.config.AnnotationControllerConfiguration.getFinalizerName(AnnotationControllerConfiguration.java:59)
at io.javaoperatorsdk.operator.springboot.starter.OperatorAutoConfiguration$ConfigurationWrapper.getFinalizerName(OperatorAutoConfiguration.java:167)
at io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilters.lambda$static$0(ResourceEventFilters.java:13)
at io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilters.lambda$or$6(ResourceEventFilters.java:157)
at io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter.lambda$and$0(ResourceEventFilter.java:39)
at io.javaoperatorsdk.operator.processing.event.source.controller.ControllerResourceEventSource.eventReceived(ControllerResourceEventSource.java:63)
at io.javaoperatorsdk.operator.processing.event.source.controller.ControllerResourceEventSource.onAdd(ControllerResourceEventSource.java:78)
at io.javaoperatorsdk.operator.processing.event.source.controller.ControllerResourceEventSource.onAdd(ControllerResourceEventSource.java:23)
at io.fabric8.kubernetes.client.informers.cache.ProcessorListener$AddNotification.handle(ProcessorListener.java:96)
at io.fabric8.kubernetes.client.informers.cache.ProcessorListener.add(ProcessorListener.java:47)
at io.fabric8.kubernetes.client.informers.cache.SharedProcessor.lambda$distribute$0(SharedProcessor.java:79)
I have to manually add kubernetes-server-mock 5.12.2 to override the default version 5.11.2 provided by the starter-test to make it compile successfully.
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-server-mock</artifactId>
<version>5.12.2</version>
<scope>test</scope>
</dependency>
I'm very happy to help fix this if the team agree me to do this.
Uploading CRDs on app startup would ease development of operators. This could be toggled via javaoperatorsdk.upload-crds-on-startup
, and would default false
.
There's a few different approaches that could be taken here, but I'll outline 2:
A CRDUploader
class could be written as a BeanPostProcessor
that uploads CRDs immediately after the KubernetesClient
has been initialized. The benefit of this direction is that it's really easy to implement without modifying any of the starter. The downside is that it's somewhat misusing BeanPostProcessor
.
Create an OperatorInitializer
that implements ApplicationListener<ApplicationReadyEvent>
and move the Operator.start
method that's currently in the Operator
factory bean method to this class. This class would then upload the CRDs when configured to do so, then start the Operator. Since the Spring application would've already been started by this point, any failure in starting the Operator would not crash the application process, so we'd need to handle Operator errors and crash the application explicitly from this location to maintain existing behavior. Benefits of this approach is that it's "more correct" than the first option, but it does have the drawbacks of being more complex.
Happy to hear alternative approaches.
I found a weird behaviour creating a test using @EnableMockOperator
.
When I return the control using patchStatus
:
return UpdateControl.patchStatus(resource);
I receive immediately a new event for that resource, but if I'm not wrong, this is not the behaviour expected. I mean in a real Kubernetes cluster after patchStatus
I don't receive a new event for that resource.
In the other hand, if I use updateStatus
with @EnableMockOperator
it works fine, I mean I don't receive a new event.
Running a simple test using @EnableMockOperator
annotation:
@SpringBootTest
@ActiveProfiles("test")
@EnableMockOperator
public class MyReconcilerSpringBootIT {
@Test
void contextLoads() {
}
}
At the beginning of the execution, my reconciler receives events for each custom resource from my real kubernetes cluster (configured in .kube/config
).
Is this correct?
Hello,
is there a way to configure the Operator with Metrics?
I'm currently using the java-operator-sdk with ConfigurationServiceOverrider to add MicrometerMetrics. Now I want to change to spring boot for adding actuator, and otherthings to the operator, but I struggle to configure the configuration, without override the AutoConfig Implementation.
Kind Regards
Just a short questions. it seems that the spring boot starter is a few versions behind the actual sdk. Are there any plans to release a new version? If I'm not wrong than the sdk is already on 4.2.7 while the starter is still on 4.1.1
Working on #127 i had many auto formatting issues (indent style, indent size, new line eof).
It would be awesome if the contributors could add a EditorConfig file so others can easier contribute to this starter project.
Regards
A new version of the java-operator-sdk was released and this starter must be updated to comply with changes for that version.
Details for migration can be found https://javaoperatorsdk.io/docs/v2-migration
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.