Skip to content
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

Informer library implementation influencing and limiting the naming of Custom Resource java classes #639

Open
tired-old-man opened this issue Sep 18, 2023 · 1 comment

Comments

@tired-old-man
Copy link

Expected Behavior

Using Informer to fetch Custom Resources has limitations.
When naming classes that will represent Custom Resource, one must prepend them with the version number.
This is a nice design choice, but the current implementation in not correct.
It will be nice to specify this design choice in the official documentation.

Correct examples:
V1MySettings
V1alpha1Operation

Incorrect examples:
MyCustomResource
V2Example

The library should support multiple versions, and not be limited to the predefined versions list (io.micronaut.kubernetes.client.ModelMapper.preBuiltApiVersions).

Now it is not possible to define Custom Resource using any other version other than one specified in the predefined versions list.

Actual Behaviour

Naming java class for custom resource will influence instantiation of shared index informer.
If not named correctly (ex: V2CustomResource) the following exception will be thrown:

18:50:34.229 [main] ERROR io.micronaut.runtime.Micronaut - Error starting Micronaut server: Bean definition [org.foo.bar.V2CustomResourceInformer] could not be loaded: version must not be null
io.micronaut.context.exceptions.BeanInstantiationException: Bean definition [org.foo.bar.V2CustomResourceInformer] could not be loaded: version must not be null
        at io.micronaut.context.DefaultBeanContext.initializeContext(DefaultBeanContext.java:1979)
        at io.micronaut.context.DefaultApplicationContext.initializeContext(DefaultApplicationContext.java:290)
        at io.micronaut.context.DefaultBeanContext.readAllBeanDefinitionClasses(DefaultBeanContext.java:3340)
        at io.micronaut.context.DefaultBeanContext.finalizeConfiguration(DefaultBeanContext.java:3693)
        at io.micronaut.context.DefaultBeanContext.start(DefaultBeanContext.java:345)
        at io.micronaut.context.DefaultApplicationContext.start(DefaultApplicationContext.java:198)
        at io.micronaut.runtime.Micronaut.start(Micronaut.java:73)
        at io.micronaut.runtime.Micronaut.run(Micronaut.java:322)
        at io.micronaut.runtime.Micronaut.run(Micronaut.java:308)
        at org.foo.bar.Application.main(Application.java:37)
Caused by: java.lang.IllegalArgumentException: version must not be null
        at io.kubernetes.client.util.Preconditions.precondition(Preconditions.java:41)
        at io.kubernetes.client.apimachinery.GroupVersion.<init>(GroupVersion.java:42)
        at io.kubernetes.client.apimachinery.GroupVersionKind.<init>(GroupVersionKind.java:24)
        at io.micronaut.kubernetes.client.ModelMapper.getGroupVersionKindByClass(ModelMapper.java:114)
        at io.micronaut.kubernetes.client.informer.DefaultSharedIndexInformerFactory.sharedIndexInformerFor(DefaultSharedIndexInformerFactory.java:116)
        at io.micronaut.kubernetes.client.informer.DefaultSharedIndexInformerFactory.sharedIndexInformersFor(DefaultSharedIndexInformerFactory.java:226)
        at io.micronaut.kubernetes.client.informer.ResourceEventHandlerBeanListener.onCreated(ResourceEventHandlerBeanListener.java:97)
        at io.micronaut.kubernetes.client.informer.ResourceEventHandlerBeanListener.onCreated(ResourceEventHandlerBeanListener.java:50)
        at io.micronaut.context.DefaultBeanContext.triggerBeanCreatedEventListener(DefaultBeanContext.java:2360)
        at io.micronaut.context.DefaultBeanContext.postBeanCreated(DefaultBeanContext.java:2337)
        at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:2281)
        at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:2289)
        at io.micronaut.context.DefaultBeanContext.createRegistration(DefaultBeanContext.java:3056)
        at io.micronaut.context.SingletonScope.getOrCreate(SingletonScope.java:81)
        at io.micronaut.context.DefaultBeanContext.findOrCreateSingletonBeanRegistration(DefaultBeanContext.java:2958)
        at io.micronaut.context.DefaultBeanContext.initializeEagerBean(DefaultBeanContext.java:2676)
        at io.micronaut.context.DefaultBeanContext.initializeContext(DefaultBeanContext.java:1973)
        ... 9 common frames omitted

Using either @Informer annotation, or calling sharedIndexInformerFor method on DefaultSharedIndexInformerFactory class will result in exception.

The problem can be traced to line 116 in DefaultSharedIndexInformerFactory class.
The internal class ModelMapper will try to parse class name and extract group, kind and version from it.
Unfortunately, if class representing custom resource doesn't start with one of the prebuild versions, the null will be used for the version.
This will cause validation to fail in io.kubernetes.client.apimachinery.GroupVersion.

Steps To Reproduce

Write a class representing Custom Resource and use the "unsupported" version in the class name.

Examples of problematic class names:
V2Setting
V1beta3Operation
V3Customer

Make a class implements KubernetesObject and try to instantiate new Informer for the class.

@Informer(
        apiType = V2Setting.class,
        apiListType = V2SettingList.class,
        apiGroup = "org.foo.bar",
        resourcePlural = "settings",
        namespace = "default")

or directly using SharedInformerFactory

factory.sharedIndexInformerFor(
    V2Setting.class,
    V2SettingList.class,
    "settings",
    "org.foo.bar",
    "default",
    null,
    null,
    true
);

Environment Information

OS: Windows 11 / WSL 2 (Ubuntu)

$ java -version
openjdk version "17.0.8.1" 2023-08-24
OpenJDK Runtime Environment Temurin-17.0.8.1+1 (build 17.0.8.1+1)
OpenJDK 64-Bit Server VM Temurin-17.0.8.1+1 (build 17.0.8.1+1, mixed mode, sharing)

mvn --version
Apache Maven 3.9.4 (dfbb324ad4a7c8fb0bf182e6d91b0ae20e3d2dd9)
Maven home: /home/user/.sdkman/candidates/maven/current
Java version: 17.0.8.1, vendor: Eclipse Adoptium, runtime: /home/user/.sdkman/candidates/java/17.0.8.1-tem
Default locale: en, platform encoding: UTF-8
OS name: "linux", version: "5.15.90.1-microsoft-standard-wsl2", arch: "amd64", family: "unix"

mn --version
Micronaut Version: 4.1.1

Example Application

No response

Version

4.1.1

@cambierr
Copy link

I lots a few tens of minutes on this issue too ...

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