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

Primitive default values in specifications break the object instantiation #4530

Closed
mteubner opened this issue Oct 25, 2022 · 12 comments · Fixed by #4536 or #4533
Closed

Primitive default values in specifications break the object instantiation #4530

mteubner opened this issue Oct 25, 2022 · 12 comments · Fixed by #4536 or #4533
Assignees
Milestone

Comments

@mteubner
Copy link

Describe the bug

Requested situation of Issue #3869 and fix on Task
#3817 lead to a situation where primitive default values in specs lead to generated classes which can't be istantiated.

Caused by: java.lang.ClassCastException: class java.lang.String cannot be cast to class java.util.Map (java.lang.String and java.util.Map are in module java.base of loader 'bootstrap')
[INFO] at io.fabric8.kubernetes.client.utils.Serialization.unmarshal(Serialization.java:237)

Fabric8 Kubernetes Client version

6.2.0

Steps to reproduce

  1. Change for instance https://github.com/fabric8io/kubernetes-client/blob/master/java-generator/it/src/it/enum-ser-deser/src/test/resources/cert-manager.crds.1.7.1.yaml and add default value to
    spec
    properties:
    description: Desired state of the CertificateRequest resource.
    duration:
    type: string
    default: "100"

  2. Execute "mvn clean verify -Dinvoker.test=enum-ser-deser"

  3. See unmarshall exception during tests.

Generated code for the object flield can not be created, because primitive object is not json.

@com.fasterxml.jackson.annotation.JsonProperty("duration")
@com.fasterxml.jackson.annotation.JsonPropertyDescription("The requested 'duration' (i.e. lifetime) of the Certificate. This option may be ignored/overridden by some issuer types.")
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SKIP)
private String duration = io.fabric8.kubernetes.client.utils.Serialization.unmarshal("\"100\"", String.class);

Same behaviour for integers or enumerations.

Expected behavior

Primitive objects may not need io.fabric8.kubernetes.client.utils.Serialization.unmarshal

It would be nice to generate Classes that can be initialized.

Runtime

other (please specify in additional context)

Kubernetes API Server version

1.24

Environment

Windows

Fabric8 Kubernetes Client Logs

[ERROR] io.fabric8.it.certmanager.TestEnumSerialization.testDeserialization  Time elapsed: 0.015 s  <<< ERROR!
[INFO] java.lang.IllegalArgumentException:
[INFO] Cannot construct instance of `io.cert_manager.v1.CertificateRequestSpec`, problem: class java.lang.String cannot be cast to class java.util.Map (java.lang.String and java.util.Map are in module java.base of loader 'bootstrap')
[INFO]  at [Source: UNKNOWN; byte offset: #UNKNOWN] (through reference chain: io.cert_manager.v1.CertificateRequest["spec"])
[INFO]  at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:4393)
[INFO]  at com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:4334)
[INFO]  at io.fabric8.kubernetes.client.utils.Serialization.unmarshal(Serialization.java:238)
[INFO]  at io.fabric8.kubernetes.client.utils.Serialization.unmarshal(Serialization.java:351)
[INFO]  at io.fabric8.kubernetes.client.utils.Serialization.unmarshal(Serialization.java:320)
[INFO]  at io.fabric8.kubernetes.client.utils.Serialization.unmarshal(Serialization.java:307)
[INFO]  at io.fabric8.it.certmanager.TestEnumSerialization.testDeserialization(TestEnumSerialization.java:38)
[INFO]  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[INFO]  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[INFO]  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[INFO]  at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[INFO]  at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
[INFO]  at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
[INFO]  at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
[INFO]  at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
[INFO]  at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
[INFO]  at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
[INFO]  at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
[INFO]  at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
[INFO]  at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
[INFO]  at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
[INFO]  at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
[INFO]  at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
[INFO]  at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
[INFO]  at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
[INFO]  at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
[INFO]  at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
[INFO]  at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
[INFO]  at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
[INFO]  at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
[INFO]  at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
[INFO]  at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
[INFO]  at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
[INFO]  at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
[INFO]  at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
[INFO]  at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
[INFO]  at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
[INFO]  at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
[INFO]  at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
[INFO]  at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
[INFO]  at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
[INFO]  at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
[INFO]  at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
[INFO]  at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
[INFO]  at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
[INFO]  at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
[INFO]  at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
[INFO]  at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
[INFO]  at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
[INFO]  at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
[INFO]  at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
[INFO]  at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
[INFO]  at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
[INFO]  at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
[INFO]  at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
[INFO]  at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
[INFO]  at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
[INFO]  at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
[INFO]  at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
[INFO]  at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
[INFO]  at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
[INFO]  at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
[INFO]  at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
[INFO]  at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
[INFO]  at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
[INFO]  at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
[INFO]  at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
[INFO]  at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
[INFO]  at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
[INFO]  at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
[INFO]  at org.apache.maven.surefire.junitplatform.LazyLauncher.execute(LazyLauncher.java:55)
[INFO]  at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:223)
[INFO]  at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:175)
[INFO]  at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:139)
[INFO]  at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:456)
[INFO]  at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:169)
[INFO]  at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:595)
[INFO]  at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:581)
[INFO] Caused by: com.fasterxml.jackson.databind.exc.ValueInstantiationException: Cannot construct instance of `io.cert_manager.v1.CertificateRequestSpec`, problem: class java.lang.String cannot be cast to class java.util.Map (java.lang.String and java.util.Map are in module java.base of loader 'bootstrap')
[INFO]  at [Source: UNKNOWN; byte offset: #UNKNOWN] (through reference chain: io.cert_manager.v1.CertificateRequest["spec"])
[INFO]  at com.fasterxml.jackson.databind.exc.ValueInstantiationException.from(ValueInstantiationException.java:47)
[INFO]  at com.fasterxml.jackson.databind.DeserializationContext.instantiationException(DeserializationContext.java:2047)
[INFO]  at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.wrapAsJsonMappingException(StdValueInstantiator.java:587)
[INFO]  at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.rewrapCtorProblem(StdValueInstantiator.java:610)
[INFO]  at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createUsingDefault(StdValueInstantiator.java:280)
[INFO]  at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:303)
[INFO]  at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
[INFO]  at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
[INFO]  at io.fabric8.kubernetes.model.jackson.SettableBeanPropertyDelegate.deserializeAndSet(SettableBeanPropertyDelegate.java:134)
[INFO]  at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:314)
[INFO]  at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
[INFO]  at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:4388)
[INFO]  ... 77 more
[INFO] Caused by: java.lang.ClassCastException: class java.lang.String cannot be cast to class java.util.Map (java.lang.String and java.util.Map are in module java.base of loader 'bootstrap')
[INFO]  at io.fabric8.kubernetes.client.utils.Serialization.unmarshal(Serialization.java:237)
[INFO]  at io.fabric8.kubernetes.client.utils.Serialization.unmarshal(Serialization.java:351)
[INFO]  at io.fabric8.kubernetes.client.utils.Serialization.unmarshal(Serialization.java:287)
[INFO]  at io.fabric8.kubernetes.client.utils.Serialization.unmarshal(Serialization.java:272)
[INFO]  at io.cert_manager.v1.CertificateRequestSpec.<init>(CertificateRequestSpec.java:14)
[INFO]  at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
[INFO]  at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
[INFO]  at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
[INFO]  at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
[INFO]  at com.fasterxml.jackson.databind.introspect.AnnotatedConstructor.call(AnnotatedConstructor.java:123)
[INFO]  at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createUsingDefault(StdValueInstantiator.java:278)
[INFO]  ... 84 more

Additional context

No additional requirements other then maven and change of one specification file.

@andreaTP andreaTP self-assigned this Oct 26, 2022
@andreaTP
Copy link
Member

Hi @mteubner , thanks for the report, I will look into this, cc. @fabiobrz FYI

@shawkins
Copy link
Contributor

@andreaTP see if #4533 works for you to address this. It allows the serialization logic to handle primitives with or without a type specified.

@mteubner
Copy link
Author

@shawkins the change looks promising but I can'z get the master to be build with all Tests. So I can't proof the correctness.

Failures:
[ERROR] SerializationTest.testSerializeYamlWithAlias:184

Expecting
Pod(apiVersion=v1, kind=Pod, metadata=ObjectMeta(annotations={}, creationTimestamp=null, deletionGracePeriodSeconds=null, deletionTimestamp=null, finalizers=[], generateName=null, generation=null, labels={}, managedFields=[], name=test-pod-with-alias, namespace=null, ownerReferences=[], resourceVersion=null, selfLink=null, uid=null, additionalProperties={}), spec=PodSpec(activeDeadlineSeconds=null, affinity=null, automountServiceAccountToken=null, containers=[Container(args=[], command=[cat], env=[], envFrom=[], image=ubuntu:bionic, imagePullPolicy=Always, lifecycle=null, livenessProbe=null, name=ubuntu, ports=[], readinessProbe=null, resources=ResourceRequirements(limits={}, requests={cpu=100m}, additionalProperties={}), securityContext=null, startupProbe=null, stdin=null, stdinOnce=null, terminationMessagePath=null, terminationMessagePolicy=null, tty=true, volumeDevices=[], volumeMounts=[], workingDir=null, additionalProperties={}), Container(args=[], command=[cat], env=[], envFrom=[], image=python:3.7, imagePullPolicy=Always, lifecycle=null, livenessProbe=null, name=python3, ports=[], readinessProbe=null, resources=ResourceRequirements(limits={}, requests={cpu=100m}, additionalProperties={}), securityContext=null, startupProbe=null, stdin=null, stdinOnce=null, terminationMessagePath=null, terminationMessagePolicy=null, tty=true, volumeDevices=[], volumeMounts=[], workingDir=null, additionalProperties={})], dnsConfig=null, dnsPolicy=null, enableServiceLinks=null, ephemeralContainers=[], hostAliases=[], hostIPC=null, hostNetwork=null, hostPID=null, hostUsers=null, hostname=null, imagePullSecrets=[], initContainers=[], nodeName=null, nodeSelector={workload=build}, os=null, overhead={}, preemptionPolicy=null, priority=null, priorityClassName=null, readinessGates=[], restartPolicy=null, runtimeClassName=null, schedulerName=null, securityContext=PodSecurityContext(fsGroup=null, fsGroupChangePolicy=null, runAsGroup=1000, runAsNonRoot=null, runAsUser=1000, seLinuxOptions=null, seccompProfile=null, supplementalGroups=[], sysctls=[], windowsOptions=null, additionalProperties={}), serviceAccount=null, serviceAccountName=null, setHostnameAsFQDN=null, shareProcessNamespace=null, subdomain=null, terminationGracePeriodSeconds=null, tolerations=[Toleration(effect=NoSchedule, key=nodeType, operator=Equal, tolerationSeconds=null, value=build, additionalProperties={})], topologySpreadConstraints=[], volumes=[], additionalProperties={}), status=null, additionalProperties={})
to have a property or a field named "spec.tolerations.size"
(static and synthetic fields are ignored)
at io.fabric8.kubernetes.client.utils.SerializationTest.testSerializeYamlWithAlias(SerializationTest.java:184)

@shawkins
Copy link
Contributor

That shouldn't be related to this pr, there's #4485 to address that test error - I'm not sure why that was closed though.

@mteubner
Copy link
Author

@shawkins okay build complete project with skipTest and afterwards just build test of java-generator test worked for me.

@mteubner
Copy link
Author

private String duration = io.fabric8.kubernetes.client.utils.Serialization.unmarshal(""100"", String.class);

is able to be executed.

@adriansuarez
Copy link

adriansuarez commented Oct 31, 2022

Is there a workaround for this while we wait for a fix to be delivered?

@andreaTP
Copy link
Member

andreaTP commented Nov 3, 2022

@adriansuarez I cannot think about any, unfortunately ... as we start to merge PRs you might be able to use the SNAPSHOT versions.
But we have 2 PRs open for fixing it, so, it will for sure be available in the next version.

@adriansuarez
Copy link

adriansuarez commented Nov 4, 2022

@andreaTP: Thank you.

I've actually been working off of 51c3be8beb7a6d59beade631c912a26c18277ee4 and using the java-gen tool directly, which works. I guess I can update the commit we're pinned at when your PR is merged, and wait for the next release if we want to use the Maven plugin to do code generation.

@mteubner
Copy link
Author

Hello,

Tested new version 6.3.0 most default version working now, beside enumerations are not; created issue #4674.

@mteubner
Copy link
Author

Enumerations are working with 6.3.1 👍

@andreaTP
Copy link
Member

Thanks for the feedback @mteubner !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment