JsonMappingException while loading yaml Kafka configuration via Fabric8io kubernetes-client

3/18/2021

I have a problem with fabric8io kubernetes-client using.

What i want: Creating Kafka cluster with Strimzi operator in Kubernetes. If i do all steps from Strimzi quickstart guide with CLI and kubectl it's all good.

But when i load yaml resources with kubernetes-client:5.2.1 library from Java code, there is an Exception occurs:

io.fabric8.kubernetes.client.KubernetesClientException: An error has occurred.
  at io.fabric8.kubernetes.client.KubernetesClientException.launderThrowable(KubernetesClientException.java:64)
  at io.fabric8.kubernetes.client.KubernetesClientException.launderThrowable(KubernetesClientException.java:53)
  at io.fabric8.kubernetes.client.utils.Serialization.unmarshal(Serialization.java:140)
  at io.fabric8.kubernetes.client.utils.Serialization.unmarshal(Serialization.java:101)
  at io.fabric8.kubernetes.client.dsl.internal.NamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl.<init>(NamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl.java:272)
  at io.fabric8.kubernetes.client.dsl.internal.NamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl.<init>(NamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl.java:252)
  at io.fabric8.kubernetes.client.DefaultKubernetesClient$1.<init>(DefaultKubernetesClient.java:175)
  at io.fabric8.kubernetes.client.DefaultKubernetesClient.load(DefaultKubernetesClient.java:175)
  at app.test.main(test.java:38)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: No resource type found for:kafka.strimzi.io/v1#Kafka
 at [Source: (String)"{"apiVersion":"kafka.strimzi.io/v1","kind":"Kafka","metadata":{"name":"my-cluster"},"spec":{"kafka":{"replicas":1,"listeners":[{"name":"plain","port":9092,"type":"internal","tls":false},{"name":"tls","port":9093,"type":"internal","tls":true,"authentication":{"type":"tls"}},{"name":"external","port":9094,"type":"nodeport","tls":false}],"storage":{"type":"jbod","volumes":[{"id":0,"type":"persistent-claim","size":"1Gi","deleteClaim":false}]},"config":{"offsets.topic.replication.factor":1,"transacti"[truncated 226 chars]; line: 1, column: 726]

Problem occurs when i load this file: yaml config.

I load resource like:

 KubernetesClient client = new DefaultKubernetesClient();
InputStream is = ...;
client.load(is).inNamespace("my_namespace").createOrReplace();

Please help me!

P.S: And sorry for my English.

-- aarexer
fabric8
java
kubernetes

1 Answer

3/19/2021

I'm from Fabric8 team. Kafka is a Custom Resource which means it's model is not registered in KubernetesClient so this is the reason why you're facing No resource type found for:kafka.strimzi.io/v1#Kafka error from KubenetesClient. KubernetesClient provides two methods for dealing with Custom Resources:

  1. Typeless API - Usage of CustomResources as raw Hashmaps
  2. Typed API - Provide POJOs for CustomResource types

I'll provide examples of using both APIs to load your Kafka yaml fragment.

Typeless API:

For Typeless API you would need to provide a CustomResourceDefinitionContext, an object with details of CustomResource group, version, kind, plural etc. Here is how it would look like: KafkaLoadTypeless.java

try (KubernetesClient client = new DefaultKubernetesClient()) {
    CustomResourceDefinitionContext context = new CustomResourceDefinitionContext.Builder()
            .withScope("Namespaced")
            .withVersion("v1beta2")
            .withGroup("kafka.strimzi.io")
            .withPlural("kafkas")
            .build();

    InputStream is = KafkaLoadTypeles.class.getResourceAsStream("/test-kafka.yml");

    Map<String, Object> createdKafka = client.customResource(context).inNamespace("default").createOrReplace(is);
} catch (IOException ioException) {
    ioException.printStackTrace();
}

Typed API:

For typed API, you would need to provide types for Kafka resource. You can find these types in Strimzi API dependency. I had to add this dependency in my project in order to use Kafka classes:

		<dependency>
			<groupId>io.strimzi</groupId>
			<artifactId>api</artifactId>
			<version>0.22.0</version>
			<exclusions>
				<exclusion>
					<groupId>io.fabric8</groupId>
					<artifactId>kubernetes-client</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

After adding this, I was able to use Typed API like this: KafkaLoadTyped.java

try (KubernetesClient client = new DefaultKubernetesClient()) {
    MixedOperation<Kafka, KafkaList, Resource<Kafka>> kafkaClient = client.customResources(Kafka.class, KafkaList.class);

    InputStream is = KafkaLoadTyped.class.getResourceAsStream("/test-kafka.yml");
    Kafka myClusterkafka = kafkaClient.load(is).get();
    kafkaClient.inNamespace("default").createOrReplace(myClusterkafka);
}
-- Rohan Kumar
Source: StackOverflow