From 8bc94e16081b0301cd1011f78873a7eb0cf52f57 Mon Sep 17 00:00:00 2001 From: "rohaan@redhat.com" Date: Wed, 2 Dec 2020 22:00:28 +0530 Subject: [PATCH] Fix #2510: Yaml containing aliases rejected due to FasterXML bug + Fallback to SnakeYAML while deserializing Kubernetes YAML manifests + Refactored SerializationUtils#dumpAsYaml(...) to use SnakeYAML instead of Jackson + Moved `SerializationUtils` to `io.fabric8.kubernetes.client.utils` --- CHANGELOG.md | 4 + .../dsl/internal/apps/v1/RollingUpdater.java | 2 +- .../kubernetes/client/utils/IOHelpers.java | 18 +++++ .../client/utils/Serialization.java | 39 ++++++++- .../SerializationUtils.java | 62 +++++++++++---- .../client/utils/IOHelpersTest.java | 79 +++++++++++++++++++ .../client/utils/SerializationTest.java | 30 ++++++- .../client/utils/SerializationUtilsTest.java | 56 +++++++++++++ .../test-pod-manifest-with-aliases.yml | 33 ++++++++ .../kubernetes/examples/FullExample.java | 2 +- .../examples/PodPresetExamples.java | 2 +- .../internal/KubernetesDeserializer.java | 11 +++ .../internal/KubernetesDeserializerTest.java | 10 +++ 13 files changed, 325 insertions(+), 23 deletions(-) rename kubernetes-client/src/main/java/io/fabric8/kubernetes/client/{internal => utils}/SerializationUtils.java (52%) create mode 100644 kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/IOHelpersTest.java create mode 100644 kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/SerializationUtilsTest.java create mode 100644 kubernetes-client/src/test/resources/test-pod-manifest-with-aliases.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 52b844ba900..63ec04bc5a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ #### Bugs * Fix #2519: Generated schemas contains a valid meta-schema URI reference (`http://json-schema.org/draft-05/schema#`) +* FIx #2510 : Yaml containing aliases rejected due to FasterXML bug #### Improvements @@ -11,6 +12,9 @@ #### New Features +#### Breaking Changes +- `io.fabric8.kubernetes.client.internal.SerializationUtils` moved to `io.fabric8.kubernetes.client.utils.SerializationUtils` + ### 5.0.0-alpha-3 (2020-11-24) #### Improvements diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/RollingUpdater.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/RollingUpdater.java index e46b66f2383..f84e0373682 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/RollingUpdater.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/RollingUpdater.java @@ -48,7 +48,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import static io.fabric8.kubernetes.client.internal.SerializationUtils.dumpWithoutRuntimeStateAsYaml; +import static io.fabric8.kubernetes.client.utils.SerializationUtils.dumpWithoutRuntimeStateAsYaml; public abstract class RollingUpdater { public static final String DEPLOYMENT_KEY = "deployment"; diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/IOHelpers.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/IOHelpers.java index 0306534b035..c2b48fb904c 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/IOHelpers.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/IOHelpers.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -29,6 +30,7 @@ /** */ public class IOHelpers { + private IOHelpers() { } public static String readFully(InputStream in) throws IOException { Reader r = new BufferedReader(new InputStreamReader(in)); @@ -75,4 +77,20 @@ public static String convertYamlToJson(String yaml) throws IOException { return jsonWriter.writeValueAsString(obj); } + /** + * Helper method to copy data from InputStream to ByteArrayOutputStream so that stream contents + * could be re-used. + * + * @param inputStream source InputStream containing data + * @param byteArrayOutputStream output ByteArrayOutputStream which will store InputStream contents + * @throws IOException in case of failure while reading stream + */ + public static void copy(InputStream inputStream, ByteArrayOutputStream byteArrayOutputStream) throws IOException { + int nRead; + byte[] data = new byte[1024]; + while ((nRead = inputStream.read(data, 0, data.length)) != -1) { + byteArrayOutputStream.write(data, 0, nRead); + } + } + } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/Serialization.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/Serialization.java index a965520dbb6..ea6b3bc1bfa 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/Serialization.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/Serialization.java @@ -22,6 +22,8 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import io.fabric8.kubernetes.api.model.KubernetesResource; import io.fabric8.kubernetes.client.KubernetesClientException; +import io.fabric8.kubernetes.internal.KubernetesDeserializer; +import org.yaml.snakeyaml.Yaml; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; @@ -46,6 +48,7 @@ private Serialization() { } JSON_MAPPER.registerModule(new JavaTimeModule()); } private static final ObjectMapper YAML_MAPPER = new ObjectMapper(new YAMLFactory()); + private static final Yaml SNAKE_YAML_MAPPER = new Yaml(); private static final String DOCUMENT_DELIMITER = "---"; public static ObjectMapper jsonMapper() { @@ -56,6 +59,10 @@ public static ObjectMapper yamlMapper() { return YAML_MAPPER; } + public static Yaml snakeYamlMapper() { + return SNAKE_YAML_MAPPER; + } + public static String asJson(T object) { try { return JSON_MAPPER.writeValueAsString(object); @@ -132,7 +139,7 @@ public static T unmarshal(InputStream is, ObjectMapper mapper, Map T unmarshal(InputStream is, TypeReference type, Map T unmarshalYaml(TypeReference type, BufferedInputStream bis) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + IOHelpers.copy(bis, baos); + byte[] bytes = baos.toByteArray(); + try { + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + if (type == null) { + return yamlMapper().readerFor(KubernetesResource.class).readValue(bais); + } + return yamlMapper().readValue(bais, type); + } catch (IOException e) { + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + return unmarshalUsingSnakeYAML(bais); + } + } + + private static T unmarshalUsingSnakeYAML(ByteArrayInputStream bis) { + Map yamlAsMap = snakeYamlMapper().load(bis); + String apiVersion = yamlAsMap.get("apiVersion").toString(); + String kind = yamlAsMap.get("kind").toString(); + bis.reset(); + return (T) unmarshalUsingSnakeYAML(bis, KubernetesDeserializer.getTypeFromName(apiVersion, kind)); + } + + private static T unmarshalUsingSnakeYAML(ByteArrayInputStream bis, Class type) { + return snakeYamlMapper().loadAs(bis, type); + } } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/internal/SerializationUtils.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/SerializationUtils.java similarity index 52% rename from kubernetes-client/src/main/java/io/fabric8/kubernetes/client/internal/SerializationUtils.java rename to kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/SerializationUtils.java index 22f1437e372..eba344ec92f 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/internal/SerializationUtils.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/SerializationUtils.java @@ -13,30 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.fabric8.kubernetes.client.internal; +package io.fabric8.kubernetes.client.utils; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.api.model.KubernetesResource; import io.fabric8.kubernetes.api.model.ObjectMeta; import io.fabric8.kubernetes.api.model.ReplicationController; import io.fabric8.kubernetes.client.internal.serializationmixins.ObjectMetaMixIn; import io.fabric8.kubernetes.client.internal.serializationmixins.ReplicationControllerMixIn; -import io.fabric8.kubernetes.client.utils.Serialization; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.introspector.Property; +import org.yaml.snakeyaml.nodes.CollectionNode; +import org.yaml.snakeyaml.nodes.Node; +import org.yaml.snakeyaml.nodes.NodeTuple; +import org.yaml.snakeyaml.nodes.SequenceNode; +import org.yaml.snakeyaml.nodes.Tag; +import org.yaml.snakeyaml.representer.Representer; public class SerializationUtils { + private SerializationUtils() { } private static ObjectMapper mapper; @@ -58,12 +56,46 @@ public static ObjectMapper getMapper() { return mapper; } - public static String dumpAsYaml(HasMetadata obj) throws JsonProcessingException { - return getMapper().writeValueAsString(obj); + public static Yaml snakeYamlMapper(Representer representer, DumperOptions options) { + return new Yaml(representer, options); + } + + /** + * Dump any Kubernetes resource which extends {@link HasMetadata} object as a YAML + * + * @param obj {@link HasMetadata} Kubernetes resource + * @return String as YAML output + */ + public static String dumpAsYaml(HasMetadata obj) { + Representer representer = new SkipNullAndEmptyNodeRepresenter(); + representer.addClassTag(obj.getClass(), Tag.MAP); + DumperOptions options = new DumperOptions(); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + + return snakeYamlMapper(representer, options).dump(obj); } public static String dumpWithoutRuntimeStateAsYaml(HasMetadata obj) throws JsonProcessingException { return getStatelessMapper().writeValueAsString(obj); } + private static class SkipNullAndEmptyNodeRepresenter extends Representer { + @Override + protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) { + if (propertyValue == null) { + return null; + } + NodeTuple tuple = super + .representJavaBeanProperty(javaBean, property, propertyValue, customTag); + Node valueNode = tuple.getValueNode(); + if (valueNode instanceof CollectionNode && Tag.SEQ.equals(valueNode.getTag())) { + SequenceNode seq = (SequenceNode) valueNode; + if (seq.getValue().isEmpty()) { + return null; + } + } + return tuple; + } + } + } diff --git a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/IOHelpersTest.java b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/IOHelpersTest.java new file mode 100644 index 00000000000..0450a0bad8d --- /dev/null +++ b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/IOHelpersTest.java @@ -0,0 +1,79 @@ +/** + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fabric8.kubernetes.client.utils; + +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class IOHelpersTest { + @Test + void testCopyInputStream() throws IOException { + // Given + String inputStr = "testStr"; + InputStream is = new ByteArrayInputStream(inputStr.getBytes()); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(128); + + // When + IOHelpers.copy(is, byteArrayOutputStream); + + // Then + assertEquals(inputStr, new String(byteArrayOutputStream.toByteArray())); + } + + @Test + void testConvertYamlToJson() throws IOException { + // Given + String yaml = "apiVersion: apps/v1\n" + + "kind: Deployment"; + + // When + String result = IOHelpers.convertYamlToJson(yaml); + + // Then + assertNotNull(result); + assertEquals("{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\"}", result); + } + + @Test + void testIsJsonValid() { + assertTrue(IOHelpers.isJSONValid("{\"a\": 3}")); + assertFalse(IOHelpers.isJSONValid("{\"a\": 3]}")); + assertFalse(IOHelpers.isJSONValid("apiVersion: v1\nkind: Pod")); + } + + @Test + void testReadFully() throws IOException { + // Given + String inputStr = "testStr"; + InputStream is = new ByteArrayInputStream(inputStr.getBytes()); + + // When + String result = IOHelpers.readFully(is); + + // Then + assertNotNull(result); + assertEquals(inputStr, result); + } +} diff --git a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/SerializationTest.java b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/SerializationTest.java index 02469e3eda9..155399d5ab0 100644 --- a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/SerializationTest.java +++ b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/SerializationTest.java @@ -17,17 +17,19 @@ import io.fabric8.kubernetes.api.model.KubernetesList; import io.fabric8.kubernetes.api.model.KubernetesResource; +import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.api.model.Quantity; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.apiextensions.v1beta1.CustomResourceDefinition; import io.fabric8.kubernetes.api.model.apiextensions.v1beta1.JSONSchemaProps; import io.fabric8.kubernetes.api.model.apps.Deployment; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Map; @@ -43,8 +45,6 @@ import com.fasterxml.jackson.databind.node.TextNode; public class SerializationTest { - - @Test void unmarshalCRDWithSchema() throws Exception { final String input = readYamlToString("/test-crd-schema.yml"); @@ -139,4 +139,28 @@ void containsMultipleDocumentsWithSingleDocumentAndLinuxLineEnds() { // Then assertFalse(result); } + + @Test + void testSerializeYamlWithAlias() { + // Given + InputStream fileInputStream = getClass().getResourceAsStream("/test-pod-manifest-with-aliases.yml"); + + // When + Pod pod = Serialization.unmarshal(fileInputStream); + + // Then + assertNotNull(pod); + assertEquals("test-pod-with-alias", pod.getMetadata().getName()); + assertEquals("build", pod.getSpec().getNodeSelector().get("workload")); + assertEquals(1, pod.getSpec().getTolerations().size()); + assertEquals(1000, pod.getSpec().getSecurityContext().getRunAsGroup().intValue()); + assertEquals(1000, pod.getSpec().getSecurityContext().getRunAsUser().intValue()); + assertEquals(2, pod.getSpec().getContainers().size()); + assertEquals("ubuntu", pod.getSpec().getContainers().get(0).getName()); + assertEquals("ubuntu:bionic", pod.getSpec().getContainers().get(0).getImage()); + assertEquals(new Quantity("100m"), pod.getSpec().getContainers().get(0).getResources().getRequests().get("cpu")); + assertEquals("python3", pod.getSpec().getContainers().get(1).getName()); + assertEquals("python:3.7", pod.getSpec().getContainers().get(1).getImage()); + assertEquals(new Quantity("100m"), pod.getSpec().getContainers().get(1).getResources().getRequests().get("cpu")); + } } diff --git a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/SerializationUtilsTest.java b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/SerializationUtilsTest.java new file mode 100644 index 00000000000..c5228e67bd2 --- /dev/null +++ b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/SerializationUtilsTest.java @@ -0,0 +1,56 @@ +/** + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fabric8.kubernetes.client.utils; + +import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.api.model.PodBuilder; +import org.junit.jupiter.api.Test; + +import java.io.InputStream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class SerializationUtilsTest { + @Test + void testDumpAsYaml() { + // Given + Pod pod = new PodBuilder() + .withNewMetadata().withName("foo").endMetadata() + .withNewSpec() + .addNewContainer() + .withName("test-container") + .withImage("test/test-image:0.0.1") + .endContainer() + .endSpec() + .build(); + + // When + String[] podAsStringArr = SerializationUtils.dumpAsYaml(pod).split("\n"); + + // Then + assertNotNull(podAsStringArr); + assertEquals(8, podAsStringArr.length); + assertEquals("apiVersion: v1", podAsStringArr[0]); + assertEquals("kind: Pod", podAsStringArr[1]); + assertEquals("metadata:", podAsStringArr[2]); + assertEquals(" name: foo", podAsStringArr[3]); + assertEquals("spec:", podAsStringArr[4]); + assertEquals(" containers:", podAsStringArr[5]); + assertEquals(" - image: test/test-image:0.0.1", podAsStringArr[6]); + assertEquals(" name: test-container", podAsStringArr[7]); + } +} diff --git a/kubernetes-client/src/test/resources/test-pod-manifest-with-aliases.yml b/kubernetes-client/src/test/resources/test-pod-manifest-with-aliases.yml new file mode 100644 index 00000000000..3de5553357e --- /dev/null +++ b/kubernetes-client/src/test/resources/test-pod-manifest-with-aliases.yml @@ -0,0 +1,33 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-pod-with-alias +spec: + nodeSelector: + workload: build + tolerations: + - key: nodeType + operator: Equal + value: build + effect: NoSchedule + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + containers: + - name: ubuntu + image: ubuntu:bionic + imagePullPolicy: Always + command: + - cat + tty: true + resources: + requests: &id001 + cpu: 100m + - name: python3 + image: python:3.7 + imagePullPolicy: Always + command: + - cat + tty: true + resources: + requests: *id001 diff --git a/kubernetes-examples/src/main/java/io/fabric8/kubernetes/examples/FullExample.java b/kubernetes-examples/src/main/java/io/fabric8/kubernetes/examples/FullExample.java index 2f2c02f96e7..83e3240ac86 100644 --- a/kubernetes-examples/src/main/java/io/fabric8/kubernetes/examples/FullExample.java +++ b/kubernetes-examples/src/main/java/io/fabric8/kubernetes/examples/FullExample.java @@ -31,7 +31,7 @@ import io.fabric8.kubernetes.client.Watch; import io.fabric8.kubernetes.client.Watcher; import io.fabric8.kubernetes.client.WatcherException; -import io.fabric8.kubernetes.client.internal.SerializationUtils; +import io.fabric8.kubernetes.client.utils.SerializationUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/kubernetes-examples/src/main/java/io/fabric8/kubernetes/examples/PodPresetExamples.java b/kubernetes-examples/src/main/java/io/fabric8/kubernetes/examples/PodPresetExamples.java index 146766e6bf8..b18b6bb4f2e 100644 --- a/kubernetes-examples/src/main/java/io/fabric8/kubernetes/examples/PodPresetExamples.java +++ b/kubernetes-examples/src/main/java/io/fabric8/kubernetes/examples/PodPresetExamples.java @@ -26,7 +26,7 @@ import io.fabric8.kubernetes.client.ConfigBuilder; import io.fabric8.kubernetes.client.DefaultKubernetesClient; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.internal.SerializationUtils; +import io.fabric8.kubernetes.client.utils.SerializationUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/internal/KubernetesDeserializer.java b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/internal/KubernetesDeserializer.java index c44f4b9d218..db87f927bb2 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/internal/KubernetesDeserializer.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/internal/KubernetesDeserializer.java @@ -123,6 +123,17 @@ public static void registerProvider(KubernetesResourceMappingProvider provider) mapping.registerProvider(provider); } + /** + * Get Type from ApiVersion and Kind. + * + * @param apiGroupAndVersion ApiVersion of Kubernetes resource + * @param kind Kind of Kubernetes resource + * @return {@link Class} if a class with provided Kind and ApiVersion exists + */ + public static Class getTypeFromName(String apiGroupAndVersion, String kind) { + return mapping.getInternalTypeForName(mapping.createKey(apiGroupAndVersion, kind)); + } + static class Mapping { private static final String KEY_SEPARATOR = "#"; diff --git a/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/internal/KubernetesDeserializerTest.java b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/internal/KubernetesDeserializerTest.java index 03f0be78b1a..5e89b4be6ad 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/internal/KubernetesDeserializerTest.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/internal/KubernetesDeserializerTest.java @@ -19,11 +19,14 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.stream.Collectors; import java.util.stream.Stream; +import io.fabric8.kubernetes.api.model.Service; import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -146,6 +149,13 @@ public void shouldLoadClassIfKeyOnlyHasKind() { assertThat(clazz, equalTo(Pod.class)); } + @Test + void testGetTypeFromName() { + assertEquals(Pod.class, KubernetesDeserializer.getTypeFromName("v1", "Pod")); + assertEquals(Service.class, KubernetesDeserializer.getTypeFromName("v1", "Service")); + assertNull(KubernetesDeserializer.getTypeFromName(null, null)); + } + private KubernetesResourceMappingProvider createProvider(Pair>... mappings) { return () -> Stream.of(mappings) .collect(Collectors.toMap(Pair::getKey, Pair::getValue));