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

Exceptions in io.quarkiverse.operatorsdk.deployment.AddClusterRolesDecorator with QOSDK 6.8.0 #961

Open
Donnerbart opened this issue Sep 20, 2024 · 7 comments · May be fixed by #962
Open
Assignees

Comments

@Donnerbart
Copy link
Contributor

I'm just updating QOSDK from 6.7.3 to 6.8.0 and noticed these exceptions in the AddClusterRolesDecorator during a quarkusBuild run.

Ignoring com.hivemq.platform.operator.dependants.StatefulSetResource for generic resource role processing as it cannot be instantiated
io.javaoperatorsdk.operator.OperatorException: Couldn't instantiate KubernetesDependentResource 'com.hivemq.platform.operator.dependants.StatefulSetResource'. Context: AddClusterRolesDecorator
	at io.javaoperatorsdk.operator.api.config.Utils.instantiateAndConfigureIfNeeded(Utils.java:237)
	at io.javaoperatorsdk.operator.api.config.Utils.instantiate(Utils.java:255)
	at io.quarkiverse.operatorsdk.deployment.AddClusterRolesDecorator.lambda$getClusterRolePolicyRulesFromDependentResources$4(AddClusterRolesDecorator.java:134)
	at java.base@21.0.4/java.util.HashMap.forEach(HashMap.java:1429)
	at io.quarkiverse.operatorsdk.deployment.AddClusterRolesDecorator.getClusterRolePolicyRulesFromDependentResources(AddClusterRolesDecorator.java:109)
	at io.quarkiverse.operatorsdk.deployment.AddClusterRolesDecorator.createClusterRole(AddClusterRolesDecorator.java:76)
	at io.quarkiverse.operatorsdk.deployment.AddClusterRolesDecorator.lambda$visit$0(AddClusterRolesDecorator.java:58)
	at java.base@21.0.4/java.util.HashMap$Values.forEach(HashMap.java:1073)
	at io.quarkiverse.operatorsdk.deployment.AddClusterRolesDecorator.visit(AddClusterRolesDecorator.java:57)
	at io.quarkiverse.operatorsdk.deployment.AddClusterRolesDecorator.visit(AddClusterRolesDecorator.java:32)
	at io.fabric8.kubernetes.api.builder.Visitor.visit(Visitor.java:30)
	at io.fabric8.kubernetes.api.builder.VisitorWiretap.visit(VisitorWiretap.java:49)
	at io.fabric8.kubernetes.api.builder.Visitable.accept(Visitable.java:53)
	at io.fabric8.kubernetes.api.builder.Visitable.accept(Visitable.java:39)
	at io.fabric8.kubernetes.api.builder.Visitable.accept(Visitable.java:35)
	at io.dekorate.ResourceRegistry.lambda$generate$2(ResourceRegistry.java:181)
	at java.base@21.0.4/java.util.HashMap.forEach(HashMap.java:1429)
	at io.dekorate.ResourceRegistry.generate(ResourceRegistry.java:173)
	at io.dekorate.Session.generate(Session.java:293)
	at io.dekorate.Session.close(Session.java:256)
	at io.quarkus.kubernetes.deployment.KubernetesProcessor.lambda$build$5(KubernetesProcessor.java:203)
	at java.base@21.0.4/java.util.Optional.ifPresent(Optional.java:178)
	at io.quarkus.kubernetes.deployment.KubernetesProcessor.build(KubernetesProcessor.java:146)
	at java.base@21.0.4/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:733)
	at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:854)
	at io.quarkus.builder.BuildContext.run(BuildContext.java:256)
	at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
	at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2516)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2495)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1521)
	at java.base@21.0.4/java.lang.Thread.run(Thread.java:1583)
	at org.jboss.threads.JBossThread.run(JBossThread.java:483)
Caused by: java.lang.IllegalStateException: Couldn't find a no-arg constructor for com.hivemq.platform.operator.dependants.StatefulSetResource
	at io.javaoperatorsdk.operator.api.config.Utils.getConstructor(Utils.java:247)
	at io.javaoperatorsdk.operator.api.config.Utils.instantiateAndConfigureIfNeeded(Utils.java:226)
	... 31 more
Caused by: java.lang.NoSuchMethodException: com.hivemq.platform.operator.dependants.StatefulSetResource.<init>()
Caused by: java.lang.IllegalStateException: Couldn't find a no-arg constructor for com.hivemq.platform.operator.dependants.StatefulSetResource

We get this for basically all of our dependent resources, because they use dependency injection in their constructors (which is supported to my knowledge).

For example, the resource from that stacktrace looks like this:

@Singleton
@KubernetesDependent(labelSelector = HiveMQPlatformReconciler.LABEL_SELECTOR)
public class StatefulSetResource extends CRUDKubernetesDependentResource<StatefulSet, HiveMQPlatform> {

    private final @NotNull HiveMQPlatformOperatorProperties properties;
    private final @NotNull HiveMQPlatformReconcilerConfig config;

    StatefulSetResource(
            final @NotNull HiveMQPlatformOperatorProperties properties,
            final @NotNull HiveMQPlatformReconcilerConfig config) {
        super(StatefulSet.class);
        this.properties = properties;
        this.config = config;
    }
}

I would appreciate feedback if we're using DI in a wrong way or if this is a bug in the AddClusterRolesDecorator or Utils class. This doesn't happen with QOSDK 6.7.3 (just double checked).

Everything still seems to work though. The Quarkus build is successful and all of our tests are still green. The build window in IntelliJ just looks like the NCC-1701 on red alert.
image

@metacosm
Copy link
Member

Looks like an issue with the decorator, indeed.

@metacosm metacosm self-assigned this Sep 20, 2024
@metacosm
Copy link
Member

The issue is that we've added support for generic kubernetes resources in the RBAC generator and to be able to know which resource is actually targeted, we have no choice (at this time) than instantiate the class to retrieve that information. We also leverage the instance to determine whether it uses SSA, which also can impact RBACs.

However, we do so assuming a default, no-arg constructor (which, in hindsight, wasn't such a great idea). As this only impacts RBAC generation (which happens at build time), this shouldn't cause problems with your operator at runtime (unless, of course, the RBACs are deployed and not correct).

@metacosm
Copy link
Member

Would it be OK with you to provide a no-arg constructor (even if it's not public) for this purpose? Or would that be a no-no?
The alternative to requiring a default no-arg constructor would be to catch the instantiation problem and issue a warning in that situation that the information to generate the proper RBACs is not available.

@Donnerbart
Copy link
Contributor Author

Donnerbart commented Sep 20, 2024

Thanks for the background information, I didn't look yet what the purpose of decorator is. We actually maintain the RBAC permission of the operator ourselves. We also don't deploy it into K8s for ITs (we do that in our Helm chart tests, where we the actual RBAC YAML is located).

So I guess for us quarkus.operator-sdk.disable-rbac-generation=true is the better option. I can confirm that this doesn't throw any exceptions.

If we would need that feature, it would be a bit strange to have a no-args constructor, but we could manage. Those dependencies are not too hard to instantiate. But for now I'll just deactivate the feature.

I would appreciate an improved error message though with less stack traces and more information what I have to do (a hint to the feature would already help, the info that it either needs a no-args constructor or can be disabled would be a bonus for the lazy ones).

@metacosm
Copy link
Member

Thanks for the background information, I didn't look yet what the purpose of decorator is. We actually maintain the RBAC permission of the operator ourselves. We also don't deploy it into K8s for ITs (we do that in our Helm chart tests, where we the actual RBAC YAML is located).

So I guess for us quarkus.operator-sdk.disable-rbac-generation=true is the better option. I can confirm that this doesn't throw any exceptions.

Indeed, this should be the solution for you.

If we would need that feature, it would be a bit strange to have a no-args constructor, but we could manage. Those dependencies are not too hard to instantiate. But for now I'll just deactivate the feature.

Technically, I don't think that any of the dependencies would be needed in that situation unless they somehow get into play for the configuration of the dependent.

I would appreciate an improved error message though with less stack traces and more information what I have to do (a hint to the feature would already help, the info that it either needs a no-args constructor or can be disabled would be a bonus for the lazy ones).

Yep, that was an oversight on our part. Sorry about that.

@metacosm
Copy link
Member

Actually, if you're not using RBAC generation at all, you can also not include the quarkus-operator-sdk-bundle-generator extension altogether instead of setting the property.

@metacosm
Copy link
Member

Give the linked PR a try if you can and let me know if that addresses your issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants