diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/DefaultKubernetesClient.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/DefaultKubernetesClient.java index 292aaf456d7..47ef633c919 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/DefaultKubernetesClient.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/DefaultKubernetesClient.java @@ -21,9 +21,6 @@ import io.fabric8.kubernetes.client.http.HttpClient.Factory; import io.fabric8.kubernetes.client.http.StandardHttpClientBuilder; import io.fabric8.kubernetes.client.utils.HttpClientUtils; -import io.fabric8.kubernetes.client.utils.Serialization; - -import java.io.InputStream; /** * Class for Default Kubernetes Client implementing KubernetesClient interface. @@ -36,14 +33,6 @@ public class DefaultKubernetesClient extends NamespacedKubernetesClientAdapter clazz; private ExecutorSupplier executorSupplier; private Consumer builderConsumer; + private KubernetesSerialization kubernetesSerialization = new KubernetesSerialization(new ObjectMapper()); public KubernetesClientBuilder() { // basically the same logic as in KubernetesResourceUtil for finding list types @@ -98,12 +100,12 @@ public KubernetesClientBuilder withConfig(Config config) { } public KubernetesClientBuilder withConfig(String config) { - this.config = Serialization.unmarshal(config, Config.class); + this.config = kubernetesSerialization.unmarshal(config, Config.class); return this; } public KubernetesClientBuilder withConfig(InputStream config) { - this.config = Serialization.unmarshal(config, Config.class); + this.config = kubernetesSerialization.unmarshal(config, Config.class); return this; } diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/extension/ExtensibleResource.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/extension/ExtensibleResource.java index 249fc812ca5..d3a2eb144f4 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/extension/ExtensibleResource.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/extension/ExtensibleResource.java @@ -22,6 +22,7 @@ import io.fabric8.kubernetes.client.dsl.Nameable; import io.fabric8.kubernetes.client.dsl.Resource; import io.fabric8.kubernetes.client.dsl.WritableOperation; +import io.fabric8.kubernetes.client.utils.KubernetesSerialization; import java.util.List; import java.util.Map; @@ -105,4 +106,6 @@ enum Scope { X operation(Scope scope, String operation, String method, Object payload, Class responseType); + KubernetesSerialization getKubernetesSerialization(); + } diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/extension/ExtensibleResourceAdapter.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/extension/ExtensibleResourceAdapter.java index 225fbc3e174..170aee4fb42 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/extension/ExtensibleResourceAdapter.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/extension/ExtensibleResourceAdapter.java @@ -19,6 +19,7 @@ import io.fabric8.kubernetes.api.model.DeletionPropagation; import io.fabric8.kubernetes.client.Client; import io.fabric8.kubernetes.client.OperationInfo; +import io.fabric8.kubernetes.client.utils.KubernetesSerialization; import java.util.List; import java.util.Map; @@ -138,4 +139,8 @@ public X operation(Scope scope, String operation, String method, Object payl return this.resource.operation(scope, operation, method, payload, responseType); } + public KubernetesSerialization getKubernetesSerialization() { + return this.resource.getKubernetesSerialization(); + } + } diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/informers/cache/ReducedStateItemStore.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/informers/cache/ReducedStateItemStore.java index 14fc2be6e3e..010939594e7 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/informers/cache/ReducedStateItemStore.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/informers/cache/ReducedStateItemStore.java @@ -18,7 +18,7 @@ import io.fabric8.kubernetes.api.model.GenericKubernetesResource; import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.client.utils.Serialization; +import io.fabric8.kubernetes.client.utils.KubernetesSerialization; import java.util.ArrayList; import java.util.Arrays; @@ -42,6 +42,7 @@ public class ReducedStateItemStore implements ItemStore fields = new ArrayList<>(); private final Class typeClass; private final KeyState keyState; + private KubernetesSerialization serialization; public static class KeyState { @@ -101,7 +102,8 @@ public KeyState(Function keyFunction, Function typeClass, String... valueFields) { + public ReducedStateItemStore(KeyState keyState, Class typeClass, KubernetesSerialization serialization, + String... valueFields) { this.keyState = keyState; fields.add(new String[] { METADATA, "resourceVersion" }); if (valueFields != null) { @@ -110,13 +112,14 @@ public ReducedStateItemStore(KeyState keyState, Class typeClass, String... va } } this.typeClass = typeClass; + this.serialization = serialization; } Object[] store(V value) { if (value == null) { return null; } - Map raw = Serialization.convertValue(value, Map.class); + Map raw = serialization.convertValue(value, Map.class); return fields.stream().map(f -> GenericKubernetesResource.get(raw, (Object[]) f)).toArray(); } @@ -129,7 +132,7 @@ V restore(String key, Object[] values) { String[] keyParts = this.keyState.keyFieldFunction.apply(key); applyFields(keyParts, raw, this.keyState.keyFields); - return Serialization.convertValue(raw, typeClass); + return serialization.convertValue(raw, typeClass); } private static void applyFields(Object[] values, Map raw, List fields) { diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/KubernetesResourceUtil.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/KubernetesResourceUtil.java index bf74d5a48b4..bae7c20bc6d 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/KubernetesResourceUtil.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/KubernetesResourceUtil.java @@ -383,7 +383,7 @@ public static List convertMapToEnvVarList(Map envVarMap) * Check whether a Kubernetes resource is Ready or not. Applicable only to * Deployment, ReplicaSet, Pod, ReplicationController, Endpoints, Node and * StatefulSet - * + * * @param item item which needs to be checked * @return boolean value indicating it's status */ @@ -393,7 +393,7 @@ public static boolean isResourceReady(HasMetadata item) { /** * Calculates age of a kubernetes resource - * + * * @param kubernetesResource * @return a positive duration indicating age of the kubernetes resource */ @@ -435,7 +435,7 @@ private static Class loadRelated(Class type, String suffix, Class defau public static Secret createDockerRegistrySecret(String dockerServer, String username, String password) throws JsonProcessingException { Map dockerConfigMap = createDockerRegistryConfigMap(dockerServer, username, password); - String dockerConfigAsStr = Serialization.jsonMapper().writeValueAsString(dockerConfigMap); + String dockerConfigAsStr = Serialization.asJson(dockerConfigMap); return createDockerSecret(DEFAULT_CONTAINER_IMAGE_REGISTRY_SECRET_NAME, dockerConfigAsStr); } @@ -452,7 +452,7 @@ public static Secret createDockerRegistrySecret(String dockerServer, String user public static Secret createDockerRegistrySecret(String dockerServer, String username, String password, String secretName) throws JsonProcessingException { Map dockerConfigMap = createDockerRegistryConfigMap(dockerServer, username, password); - String dockerConfigAsStr = Serialization.jsonMapper().writeValueAsString(dockerConfigMap); + String dockerConfigAsStr = Serialization.asJson(dockerConfigMap); return createDockerSecret(secretName, dockerConfigAsStr); } diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/KubernetesSerialization.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/KubernetesSerialization.java new file mode 100644 index 00000000000..a3daaea6698 --- /dev/null +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/KubernetesSerialization.java @@ -0,0 +1,370 @@ +package io.fabric8.kubernetes.client.utils; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationConfig; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.KeyDeserializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationConfig; +import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; +import com.fasterxml.jackson.databind.cfg.MapperConfig; +import com.fasterxml.jackson.databind.introspect.Annotated; +import com.fasterxml.jackson.databind.jsontype.TypeIdResolver; +import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import io.fabric8.kubernetes.api.model.KubernetesResource; +import io.fabric8.kubernetes.api.model.runtime.RawExtension; +import io.fabric8.kubernetes.client.KubernetesClientException; +import io.fabric8.kubernetes.internal.KubernetesDeserializer; +import io.fabric8.kubernetes.model.jackson.UnmatchedFieldTypeModule; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.DumperOptions.FlowStyle; +import org.yaml.snakeyaml.LoaderOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.SafeConstructor; +import org.yaml.snakeyaml.nodes.Tag; +import org.yaml.snakeyaml.representer.Representer; +import org.yaml.snakeyaml.resolver.Resolver; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class KubernetesSerialization { + + private final ObjectMapper mapper; + private final UnmatchedFieldTypeModule unmatchedFieldTypeModule = new UnmatchedFieldTypeModule(); + private final KubernetesDeserializer kubernetesDeserializer = new KubernetesDeserializer(); + + public KubernetesSerialization(ObjectMapper mapper) { + this.mapper = mapper; + mapper.registerModules(new JavaTimeModule(), unmatchedFieldTypeModule); + mapper.disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE); + HandlerInstantiator instanciator = mapper.getDeserializationConfig().getHandlerInstantiator(); + mapper.setConfig(mapper.getDeserializationConfig().with(new HandlerInstantiator() { + + @Override + public JsonDeserializer deserializerInstance(DeserializationConfig config, Annotated annotated, Class deserClass) { + if (deserClass == KubernetesDeserializer.class) { + return kubernetesDeserializer; + } + if (instanciator == null) { + return null; + } + return instanciator.deserializerInstance(config, annotated, deserClass); + } + + @Override + public KeyDeserializer keyDeserializerInstance(DeserializationConfig config, Annotated annotated, + Class keyDeserClass) { + if (instanciator == null) { + return null; + } + return instanciator.keyDeserializerInstance(config, annotated, keyDeserClass); + } + + @Override + public JsonSerializer serializerInstance(SerializationConfig config, Annotated annotated, Class serClass) { + if (instanciator == null) { + return null; + } + return instanciator.serializerInstance(config, annotated, serClass); + } + + @Override + public TypeResolverBuilder typeResolverBuilderInstance(MapperConfig config, Annotated annotated, + Class builderClass) { + if (instanciator == null) { + return null; + } + return instanciator.typeResolverBuilderInstance(config, annotated, builderClass); + } + + @Override + public TypeIdResolver typeIdResolverInstance(MapperConfig config, Annotated annotated, Class resolverClass) { + if (instanciator == null) { + return null; + } + return instanciator.typeIdResolverInstance(config, annotated, resolverClass); + } + + })); + } + + private static final String DOCUMENT_DELIMITER = "---"; + + /** + * Returns a JSON representation of the given object. + * + *

+ * If the provided object contains a JsonAnyGetter annotated method with a Map that contains an entry that + * overrides a field of the provided object, the Map entry will take precedence upon serialization. Properties won't + * be duplicated. + * + * @param object the object to serialize. + * @param the type of the object being serialized. + * @return a String containing a JSON representation of the provided object. + */ + public String asJson(T object) { + try { + return mapper.writeValueAsString(object); + } catch (JsonProcessingException e) { + throw KubernetesClientException.launderThrowable(e); + } + } + + /** + * Returns a YAML representation of the given object. + * + *

+ * If the provided object contains a JsonAnyGetter annotated method with a Map that contains an entry that + * overrides a field of the provided object, the Map entry will take precedence upon serialization. Properties won't + * be duplicated. + * + * @param object the object to serialize. + * @param the type of the object being serialized. + * @return a String containing a JSON representation of the provided object. + */ + public String asYaml(T object) { + Yaml yaml = yaml(); + try { + return yaml.dump(convertValue(object, Map.class)); + } catch (IllegalArgumentException e) { + return yaml.dump(convertValue(convertValue(object, JsonNode.class), Object.class)); + } + } + + /** + * Unmarshals a stream. + *

+ * The type is assumed to be {@link KubernetesResource}, but will also look for multiple + * yaml documents in the same file. That result will be returned as List of {@link KubernetesResource}. + * + * @param is The {@link InputStream}. + * @param The target type. + * + * @return returns de-serialized object + */ + public T unmarshal(InputStream is) { + String specFile; + try { + specFile = IOHelpers.readFully(is); + } catch (IOException e1) { + throw new RuntimeException("Could not read stream"); + } + if (containsMultipleDocuments(specFile)) { + return (T) getKubernetesResourceList(Collections.emptyMap(), specFile); + } else if (specFile.contains(DOCUMENT_DELIMITER)) { + specFile = specFile.replaceAll("^---([ \\t].*?)?\\r?\\n", ""); + specFile = specFile.replaceAll("\\n---([ \\t].*?)?\\r?\\n?$", "\n"); + } + + return unmarshal(new ByteArrayInputStream(specFile.getBytes(StandardCharsets.UTF_8)), new TypeReference() { + @Override + public Type getType() { + return KubernetesResource.class; + } + }); + } + + public T unmarshal(InputStream is, TypeReference type) { + try (BufferedInputStream bis = new BufferedInputStream(is)) { + bis.mark(-1); + int intch; + do { + intch = bis.read(); + } while (intch > -1 && Character.isWhitespace(intch)); + bis.reset(); + + final T result; + if (intch != '{' && intch != '[') { + Yaml yaml = yaml(); + final Object obj = yaml.load(bis); + try { + if (obj instanceof Map) { + result = mapper.convertValue(obj, type); + } else { + result = mapper.convertValue(new RawExtension(obj), type); + } + } catch (IllegalArgumentException e) { + throw new KubernetesClientException("Could not convert from yaml to requested type", e); + } + } else { + result = mapper.readerFor(type).readValue(bis); + } + return result; + } catch (IOException e) { + throw KubernetesClientException.launderThrowable(e); + } + } + + private static Yaml yaml() { + LoaderOptions loaderOptions = new LoaderOptions(); + DumperOptions dumperOptions = new DumperOptions(); + dumperOptions.setExplicitStart(true); + dumperOptions.setDefaultFlowStyle(FlowStyle.BLOCK); + Yaml yaml = new Yaml(new SafeConstructor(loaderOptions), new Representer(dumperOptions), dumperOptions, + loaderOptions, new CustomYamlTagResolverWithLimit()); + return yaml; + } + + /** + * Unmarshals a {@link String} + *

+ * The type is assumed to be {@link KubernetesResource} + * + * @param str The {@link String}. + * @param template argument denoting type + * @return returns de-serialized object + */ + public T unmarshal(String str) { + return (T) unmarshal(str, KubernetesResource.class); + } + + /** + * Unmarshals a {@link String} + * + * @param str The {@link String}. + * @param type The target type. + * @param template argument denoting type + * @return returns de-serialized object + */ + public T unmarshal(String str, final Class type) { + try (InputStream is = new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8))) { + return unmarshal(is, type); + } catch (IOException e) { + throw KubernetesClientException.launderThrowable(e); + } + } + + /** + * Unmarshals an {@link InputStream}. + * + * @param is The {@link InputStream}. + * @param type The type. + * @param Template argument denoting type + * @return returns de-serialized object + */ + public T unmarshal(InputStream is, final Class type) { + return unmarshal(is, new TypeReference() { + @Override + public Type getType() { + return type; + } + }); + } + + private List getKubernetesResourceList(Map parameters, String specFile) { + return splitSpecFile(specFile).stream().filter(KubernetesSerialization::validate) + .map( + document -> (KubernetesResource) unmarshal(document)) + .collect(Collectors.toList()); + } + + static boolean containsMultipleDocuments(String specFile) { + final long validDocumentCount = splitSpecFile(specFile).stream().filter(KubernetesSerialization::validate) + .count(); + return validDocumentCount > 1; + } + + private static List splitSpecFile(String aSpecFile) { + final List documents = new ArrayList<>(); + final StringBuilder documentBuilder = new StringBuilder(); + for (String line : aSpecFile.split("\r?\n")) { + if (line.startsWith(DOCUMENT_DELIMITER)) { + documents.add(documentBuilder.toString()); + documentBuilder.setLength(0); + } else { + documentBuilder.append(line).append(System.lineSeparator()); + } + } + if (documentBuilder.length() > 0) { + documents.add(documentBuilder.toString()); + } + return documents; + } + + private static boolean validate(String document) { + Matcher keyValueMatcher = Pattern.compile("(\\S+):\\s(\\S*)(?:\\b(?!:)|$)").matcher(document); + return !document.isEmpty() && keyValueMatcher.find(); + } + + /** + * Create a copy of the resource via serialization. + * + * @return a deep clone of the resource + * @throws IllegalArgumentException if the cloning cannot be performed + */ + public T clone(T resource) { + // if full serialization seems too expensive, there is also + //return (T) JSON_MAPPER.convertValue(resource, resource.getClass()); + try { + return (T) mapper.readValue( + mapper.writeValueAsString(resource), resource.getClass()); + } catch (JsonProcessingException e) { + throw new IllegalStateException(e); + } + } + + private static class CustomYamlTagResolverWithLimit extends Resolver { + @Override + public void addImplicitResolver(Tag tag, Pattern regexp, String first, int limit) { + if (tag == Tag.TIMESTAMP) + return; + if (tag.equals(Tag.BOOL)) { + regexp = Pattern.compile("^(?:true|True|TRUE|false|False|FALSE)$"); + first = "tTfF"; + } + super.addImplicitResolver(tag, regexp, first, limit); + } + } + + public T convertValue(Object value, Class type) { + return mapper.convertValue(value, type); + } + + public Type constructParametricType(Class parameterizedClass, Class parameterType) { + return mapper.getTypeFactory().constructParametricType(parameterizedClass, parameterType); + } + + public Class getRegisteredKind(String apiVersion, String kind) { + return this.kubernetesDeserializer.getRegisteredKind(apiVersion, kind); + } + + public UnmatchedFieldTypeModule getUnmatchedFieldTypeModule() { + return unmatchedFieldTypeModule; + } + + ObjectMapper getMapper() { + return mapper; + } + + /** + * Registers a Custom Resource Definition Kind + */ + public void registerCustomKind(String kind, Class clazz) { + registerCustomKind(null, kind, clazz); + } + + /** + * Registers a Custom Resource Definition Kind + */ + public void registerCustomKind(String apiVersion, String kind, Class clazz) { + kubernetesDeserializer.registerCustomKind(apiVersion, kind, clazz); + } + +} diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtils.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtils.java index e38658dbc6f..aa4ae18d5a0 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtils.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/OpenIDConnectionUtils.java @@ -282,7 +282,7 @@ static boolean persistKubeConfigWithUpdatedToken(String kubeConfigPath, Map convertJsonStringToMap(String jsonString) throws JsonProcessingException { - return Serialization.jsonMapper().readValue(jsonString, Map.class); + return Serialization.convertValue(jsonString, Map.class); } private static HttpClient getDefaultHttpClientWithPemCert(String idpCert, HttpClient.Builder clientBuilder) { diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/Serialization.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/Serialization.java index 64deef42972..76078afc640 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/Serialization.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/Serialization.java @@ -17,11 +17,9 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import io.fabric8.kubernetes.api.model.KubernetesResource; import io.fabric8.kubernetes.api.model.runtime.RawExtension; import io.fabric8.kubernetes.client.KubernetesClientException; @@ -53,13 +51,11 @@ public class Serialization { private Serialization() { } - public static final UnmatchedFieldTypeModule UNMATCHED_FIELD_TYPE_MODULE = new UnmatchedFieldTypeModule(); + private static KubernetesSerialization kubernetesSerialization = new KubernetesSerialization(new ObjectMapper()); + public static final UnmatchedFieldTypeModule UNMATCHED_FIELD_TYPE_MODULE = kubernetesSerialization + .getUnmatchedFieldTypeModule(); - private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); - static { - JSON_MAPPER.registerModules(new JavaTimeModule(), UNMATCHED_FIELD_TYPE_MODULE); - JSON_MAPPER.disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE); - } + private static final ObjectMapper JSON_MAPPER = kubernetesSerialization.getMapper(); private static volatile ObjectMapper YAML_MAPPER; @@ -217,7 +213,10 @@ public static T unmarshal(InputStream is, Map parameters) { * @param mapper The {@link ObjectMapper} to use. * @param The target type. * @return returns de-serialized object + * + * @deprecated to be removed in future versions */ + @Deprecated public static T unmarshal(InputStream is, ObjectMapper mapper) { return unmarshal(is, mapper, Collections.emptyMap()); } @@ -493,4 +492,13 @@ public static T convertValue(Object value, Class type) { public static Type constructParametricType(Class parameterizedClass, Class parameterType) { return JSON_MAPPER.getTypeFactory().constructParametricType(parameterizedClass, parameterType); } + + /** + * + * @deprecated + */ + @Deprecated + public static KubernetesSerialization getKubernetesSerialization() { + return kubernetesSerialization; + } } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/AbstractWatchManager.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/AbstractWatchManager.java index eecfb40a508..47ec36a60d1 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/AbstractWatchManager.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/AbstractWatchManager.java @@ -29,7 +29,7 @@ import io.fabric8.kubernetes.client.Watcher.Action; import io.fabric8.kubernetes.client.WatcherException; import io.fabric8.kubernetes.client.http.HttpClient; -import io.fabric8.kubernetes.client.utils.Serialization; +import io.fabric8.kubernetes.client.utils.KubernetesSerialization; import io.fabric8.kubernetes.client.utils.Utils; import io.fabric8.kubernetes.client.utils.internal.ExponentialBackoffIntervalCalculator; import org.slf4j.Logger; @@ -183,7 +183,7 @@ void eventReceived(Watcher.Action action, HasMetadata resource) { // the WatchEvent deserialization is not specifically typed // modify the type here if needed if (resource != null && !baseOperation.getType().isAssignableFrom(resource.getClass())) { - resource = Serialization.convertValue(resource, baseOperation.getType()); + resource = this.baseOperation.getKubernetesSerialization().convertValue(resource, baseOperation.getType()); } @SuppressWarnings("unchecked") final T t = (T) resource; @@ -231,17 +231,20 @@ public void close() { private WatchEvent contextAwareWatchEventDeserializer(String messageSource) throws JsonProcessingException { + KubernetesSerialization kubernetesSerialization = this.baseOperation.getKubernetesSerialization(); try { - return Serialization.unmarshal(messageSource, WatchEvent.class); + return kubernetesSerialization.unmarshal(messageSource, WatchEvent.class); } catch (Exception ex1) { - JsonNode json = Serialization.unmarshal(messageSource, JsonNode.class); + // TODO: this is not necessarily correct - it will force the object to be the expected type + // even though it is not (for example Status could be converted to the typed result) + JsonNode json = kubernetesSerialization.unmarshal(messageSource, JsonNode.class); JsonNode objectJson = null; if (json instanceof ObjectNode && json.has("object")) { objectJson = ((ObjectNode) json).remove("object"); } - WatchEvent watchEvent = Serialization.convertValue(json, WatchEvent.class); - KubernetesResource object = Serialization.convertValue(objectJson, baseOperation.getType()); + WatchEvent watchEvent = kubernetesSerialization.convertValue(json, WatchEvent.class); + KubernetesResource object = kubernetesSerialization.convertValue(objectJson, baseOperation.getType()); watchEvent.setObject(object); return watchEvent; diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/BaseOperation.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/BaseOperation.java index 7662bd20eac..b707aef54bf 100755 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/BaseOperation.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/BaseOperation.java @@ -57,7 +57,6 @@ import io.fabric8.kubernetes.client.readiness.Readiness; import io.fabric8.kubernetes.client.utils.ApiVersionUtil; import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil; -import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.kubernetes.client.utils.URLUtils; import io.fabric8.kubernetes.client.utils.URLUtils.URLBuilder; import io.fabric8.kubernetes.client.utils.Utils; @@ -170,7 +169,7 @@ public T require() { public T getMandatory() { if (item != null && !reloadingFromServer) { - return Serialization.clone(item); + return this.getKubernetesSerialization().clone(item); } try { URL requestUrl = getCompleteResourceUrl(); @@ -249,7 +248,7 @@ public BaseOperation inAnyNamespace() { @Override public R load(InputStream is) { - T unmarshal = Serialization.unmarshal(is, type); + T unmarshal = this.getKubernetesSerialization().unmarshal(is, type); // if you do something like client.foo().v2().load(v1 resource) // it will parse as v2, but have a v1 apiVersion, so we need to // force the apiVersion @@ -296,7 +295,7 @@ public final T createOrReplace() { resource::create, resource::replace, m -> resource.waitUntilCondition(Objects::nonNull, 1, TimeUnit.SECONDS), - m -> resource.fromServer().get()); + m -> resource.fromServer().get(), this.getKubernetesSerialization()); return createOrReplaceHelper.createOrReplace(item); } @@ -394,7 +393,7 @@ public CompletableFuture submitList(ListOptions listOptions) { URL fetchListUrl = fetchListUrl(getNamespacedUrl(), defaultListOptions(listOptions, null)); HttpRequest.Builder requestBuilder = httpClient.newHttpRequestBuilder().url(fetchListUrl); Type refinedType = listType.equals(DefaultKubernetesResourceList.class) - ? Serialization.constructParametricType(listType, type) + ? this.getKubernetesSerialization().constructParametricType(listType, type) : listType; TypeReference listTypeReference = new TypeReference() { @Override @@ -740,7 +739,7 @@ public X operation(Scope scope, String operation, String method, Object payl HttpRequest.Builder requestBuilder = httpClient.newHttpRequestBuilder() .uri(baseUrl + "/" + operation); if (payload != null) { - requestBuilder.method(method, JSON, Serialization.asJson(payload)); + requestBuilder.method(method, JSON, this.getKubernetesSerialization().asJson(payload)); } return handleResponse(requestBuilder, responseType); } catch (IOException e) { diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/ExecWebSocketListener.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/ExecWebSocketListener.java index fb127ac8c7f..522c62cb5a4 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/ExecWebSocketListener.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/ExecWebSocketListener.java @@ -28,6 +28,7 @@ import io.fabric8.kubernetes.client.http.WebSocket; import io.fabric8.kubernetes.client.http.WebSocketHandshakeException; import io.fabric8.kubernetes.client.utils.InputStreamPumper; +import io.fabric8.kubernetes.client.utils.KubernetesSerialization; import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.kubernetes.client.utils.internal.SerialExecutor; import org.slf4j.Logger; @@ -142,16 +143,18 @@ private void handle(ByteBuffer byteString, WebSocket webSocket) throws IOExcepti private final AtomicBoolean closed = new AtomicBoolean(false); private final CompletableFuture exitCode = new CompletableFuture<>(); private ObjectMapper objectMapper = new ObjectMapper(); + private KubernetesSerialization serialization; public static String toString(ByteBuffer buffer) { return StandardCharsets.UTF_8.decode(buffer).toString(); } - public ExecWebSocketListener(PodOperationContext context) { - this(context, Runnable::run); + ExecWebSocketListener(PodOperationContext context) { + this(context, Runnable::run, Serialization.getKubernetesSerialization()); } - public ExecWebSocketListener(PodOperationContext context, Executor executor) { + public ExecWebSocketListener(PodOperationContext context, Executor executor, KubernetesSerialization serialization) { + this.serialization = serialization; this.listener = context.getExecListener(); Integer bufferSize = context.getBufferSize(); @@ -201,7 +204,7 @@ private void asyncWrite(WritableByteChannel channel, ByteBuffer b) { if (closed.get()) { LOGGER.debug("Stream write failed after close", t); } else { - // This could happen if the user simply closes their stream prior to completion + // This could happen if the user simply closes their stream prior to completion LOGGER.warn("Stream write failed", t); } } @@ -211,7 +214,7 @@ private void asyncWrite(WritableByteChannel channel, ByteBuffer b) { @Override public void close() { // simply sends a close, which will shut down the output - // it's expected that the server will respond with a close, but if not the input will be shutdown implicitly + // it's expected that the server will respond with a close, but if not the input will be shutdown implicitly closeWebSocketOnce(1000, "Closing..."); } @@ -276,7 +279,7 @@ public void onError(WebSocket webSocket, Throwable t) { if (t instanceof WebSocketHandshakeException) { response = ((WebSocketHandshakeException) t).getResponse(); } - Status status = OperationSupport.createStatus(response); + Status status = OperationSupport.createStatus(response, serialization); status.setMessage(t.getMessage()); cleanUpOnce(); } finally { @@ -345,7 +348,7 @@ private void handleExitStatus(ByteBuffer bytes) { int code = -1; try { String stringValue = toString(bytes); - status = Serialization.unmarshal(stringValue, Status.class); + status = serialization.unmarshal(stringValue, Status.class); if (status != null) { code = parseExitCode(status); } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/HasMetadataOperation.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/HasMetadataOperation.java index f8aaf83aa31..12b0d2e0ad9 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/HasMetadataOperation.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/HasMetadataOperation.java @@ -27,7 +27,6 @@ import io.fabric8.kubernetes.client.dsl.base.PatchContext; import io.fabric8.kubernetes.client.dsl.base.PatchType; import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil; -import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.kubernetes.client.utils.Utils; import java.io.IOException; @@ -59,7 +58,7 @@ public T edit(UnaryOperator function) { } private T clone(T item) { - return Serialization.clone(item); + return this.getKubernetesSerialization().clone(item); } @Override diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/NamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/NamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl.java index 2e42e16a614..eea61d12eeb 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/NamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/NamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl.java @@ -20,7 +20,6 @@ import io.fabric8.kubernetes.api.builder.Visitor; import io.fabric8.kubernetes.api.model.DeletionPropagation; import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.api.model.KubernetesList; import io.fabric8.kubernetes.api.model.KubernetesResourceList; import io.fabric8.kubernetes.api.model.StatusDetails; import io.fabric8.kubernetes.client.Client; @@ -36,11 +35,9 @@ import io.fabric8.kubernetes.client.dsl.Resource; import io.fabric8.kubernetes.client.dsl.Waitable; import io.fabric8.kubernetes.client.readiness.Readiness; -import io.fabric8.kubernetes.client.utils.Serialization; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -83,11 +80,6 @@ public List waitUntilReady(final long amount, final TimeUnit timeUn List getItems() { Object item = context.getItem(); - if (item instanceof InputStream) { - item = Serialization.unmarshal((InputStream) item); - context = context.withItem(item); // late realization of the inputstream - } - return asHasMetadata(item).stream() .map(meta -> acceptVisitors(meta, Collections.emptyList(), this.context)) @@ -241,19 +233,13 @@ protected Readiness getReadiness() { protected List asHasMetadata(Object item) { List result = new ArrayList<>(); - if (item instanceof KubernetesList) { - result.addAll(((KubernetesList) item).getItems()); - } else if (item instanceof KubernetesResourceList) { + if (item instanceof KubernetesResourceList) { result.addAll(((KubernetesResourceList) item).getItems()); } else if (item instanceof HasMetadata) { result.add((HasMetadata) item); - } else if (item instanceof String) { - return asHasMetadata(Serialization.unmarshal((String) item)); } else if (item instanceof Collection) { for (Object o : (Collection) item) { - if (o instanceof HasMetadata) { - result.add((HasMetadata) o); - } + result.add((HasMetadata) o); } } else if (item != null) { throw new IllegalArgumentException("Could not convert item to a list of HasMetadata"); diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/OperationSupport.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/OperationSupport.java index 203610de99f..56eb33e24b5 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/OperationSupport.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/OperationSupport.java @@ -33,8 +33,9 @@ import io.fabric8.kubernetes.client.http.HttpClient; import io.fabric8.kubernetes.client.http.HttpRequest; import io.fabric8.kubernetes.client.http.HttpResponse; +import io.fabric8.kubernetes.client.impl.BaseClient; import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil; -import io.fabric8.kubernetes.client.utils.Serialization; +import io.fabric8.kubernetes.client.utils.KubernetesSerialization; import io.fabric8.kubernetes.client.utils.URLUtils; import io.fabric8.kubernetes.client.utils.Utils; import io.fabric8.kubernetes.client.utils.internal.ExponentialBackoffIntervalCalculator; @@ -253,7 +254,7 @@ protected T correctNamespace(T item) { String itemNs = KubernetesResourceUtil.getNamespace((HasMetadata) item); if (Utils.isNotNullOrEmpty(namespace) && Utils.isNotNullOrEmpty(itemNs) && !namespace.equals(itemNs)) { - item = Serialization.clone(item); + item = getKubernetesSerialization().clone(item); KubernetesResourceUtil.setNamespace((HasMetadata) item, namespace); } return item; @@ -318,7 +319,7 @@ protected KubernetesResource handleDelete(URL requestUrl, long gracePeriodSecond } HttpRequest.Builder requestBuilder = httpClient.newHttpRequestBuilder() - .delete(JSON, Serialization.asJson(deleteOptions)).url(requestUrl); + .delete(JSON, getKubernetesSerialization().asJson(deleteOptions)).url(requestUrl); return handleResponse(requestBuilder, KubernetesResource.class); } @@ -338,7 +339,7 @@ protected KubernetesResource handleDelete(URL requestUrl, long gracePeriodSecond protected T handleCreate(I resource, Class outputType) throws InterruptedException, IOException { resource = correctNamespace(resource); HttpRequest.Builder requestBuilder = httpClient.newHttpRequestBuilder() - .post(JSON, Serialization.asJson(resource)) + .post(JSON, getKubernetesSerialization().asJson(resource)) .url(getResourceURLForWriteOperation(getResourceUrl(checkNamespace(resource), null))); return handleResponse(requestBuilder, outputType); } @@ -357,7 +358,7 @@ protected T handleCreate(I resource, Class outputType) throws Interrup protected T handleUpdate(T updated, Class type, boolean status) throws IOException { updated = correctNamespace(updated); HttpRequest.Builder requestBuilder = httpClient.newHttpRequestBuilder() - .put(JSON, Serialization.asJson(updated)) + .put(JSON, getKubernetesSerialization().asJson(updated)) .url(getResourceURLForWriteOperation(getResourceUrl(checkNamespace(updated), checkName(updated), status))); return handleResponse(requestBuilder, type); } @@ -400,7 +401,7 @@ protected T handlePatch(PatchContext patchContext, T current, T updated, Cla } } } - patchForUpdate = Serialization.asJson(updated); + patchForUpdate = getKubernetesSerialization().asJson(updated); current = updated; // use the updated to determine the path } return handlePatch(patchContext, current, patchForUpdate, type, status); @@ -447,7 +448,7 @@ protected T handleGet(URL resourceUrl, Class type) throws IOException { protected T handleApproveOrDeny(T csr, Class type) throws IOException, InterruptedException { String uri = URLUtils.join(getResourceUrl(null, csr.getMetadata().getName(), false).toString(), "approval"); HttpRequest.Builder requestBuilder = httpClient.newHttpRequestBuilder() - .put(JSON, Serialization.asJson(csr)).uri(uri); + .put(JSON, getKubernetesSerialization().asJson(csr)).uri(uri); return handleResponse(requestBuilder, type); } @@ -540,7 +541,7 @@ protected CompletableFuture handleResponse(HttpClient client, HttpRequest try { assertResponseCode(request, response); if (type != null && type.getType() != null) { - return Serialization.unmarshal(new ByteArrayInputStream(response.body()), type); + return getKubernetesSerialization().unmarshal(new ByteArrayInputStream(response.body()), type); } else { return null; } @@ -608,9 +609,10 @@ protected void assertResponseCode(HttpRequest request, HttpResponse response) String customMessage = config.getErrorMessages().get(statusCode); if (customMessage != null) { - throw requestFailure(request, createStatus(statusCode, combineMessages(customMessage, createStatus(response)))); + throw requestFailure(request, + createStatus(statusCode, combineMessages(customMessage, createStatus(response, getKubernetesSerialization())))); } else { - throw requestFailure(request, createStatus(response)); + throw requestFailure(request, createStatus(response, getKubernetesSerialization())); } } @@ -624,7 +626,7 @@ private String combineMessages(String customMessage, Status defaultStatus) { return customMessage; } - public static Status createStatus(HttpResponse response) { + public static Status createStatus(HttpResponse response, KubernetesSerialization kubernetesSerialization) { String statusMessage = ""; int statusCode = response != null ? response.code() : 0; if (response == null) { @@ -633,7 +635,7 @@ public static Status createStatus(HttpResponse response) { try { String bodyString = response.bodyString(); if (Utils.isNotNullOrEmpty(bodyString)) { - Status status = Serialization.unmarshal(bodyString, Status.class); + Status status = kubernetesSerialization.unmarshal(bodyString, Status.class); if (status.getCode() == null) { status = new StatusBuilder(status).withCode(statusCode).build(); } @@ -729,4 +731,8 @@ public R1 restCall(Class result, String... path) { } } + public KubernetesSerialization getKubernetesSerialization() { + return context.getClient().adapt(BaseClient.class).getKubernetesSerialization(); + } + } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/WatchConnectionManager.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/WatchConnectionManager.java index 5f8416b12db..101640bfbf9 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/WatchConnectionManager.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/WatchConnectionManager.java @@ -119,7 +119,7 @@ protected void start(URL url, Map headers) { // We do not expect a 200 in response to the websocket connection. If it occurs, we throw // an exception and try the watch via a persistent HTTP Get. // Newer Kubernetes might also return 503 Service Unavailable in case WebSockets are not supported - Status status = OperationSupport.createStatus(response); + Status status = OperationSupport.createStatus(response, this.baseOperation.getKubernetesSerialization()); if (HTTP_OK == code || HTTP_UNAVAILABLE == code) { throw OperationSupport.requestFailure(client.newHttpRequestBuilder().url(url).build(), status, "Received " + code + " on websocket"); diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/RollableScalableResourceOperation.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/RollableScalableResourceOperation.java index 7c6d82dca2b..60e42e994c8 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/RollableScalableResourceOperation.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/RollableScalableResourceOperation.java @@ -31,7 +31,6 @@ import io.fabric8.kubernetes.client.dsl.internal.HasMetadataOperation; import io.fabric8.kubernetes.client.dsl.internal.OperationContext; import io.fabric8.kubernetes.client.dsl.internal.PodOperationContext; -import io.fabric8.kubernetes.client.utils.Serialization; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -141,7 +140,7 @@ public T edit(UnaryOperator function) { } try { T oldObj = getMandatory(); - T newObj = function.apply(Serialization.clone(oldObj)); + T newObj = function.apply(getKubernetesSerialization().clone(oldObj)); return getRollingUpdater(context.getTimeout(), context.getTimeoutUnit()).rollUpdate(oldObj, newObj); } catch (Exception e) { throw KubernetesClientException.launderThrowable(e); @@ -222,7 +221,7 @@ public T updateImage(Map containerToImageMap) { throw new KubernetesClientException("Resource doesn't exist"); } - T base = Serialization.clone(value); + T base = getKubernetesSerialization().clone(value); List containers = getContainers(value); 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 208b991bfa4..a026b1ca189 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 @@ -35,7 +35,7 @@ import io.fabric8.kubernetes.client.dsl.internal.PatchUtils; import io.fabric8.kubernetes.client.dsl.internal.PatchUtils.Format; import io.fabric8.kubernetes.client.dsl.internal.core.v1.PodOperationsImpl; -import io.fabric8.kubernetes.client.utils.Serialization; +import io.fabric8.kubernetes.client.utils.KubernetesSerialization; import io.fabric8.kubernetes.client.utils.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -175,20 +175,20 @@ public T rollUpdate(T oldObj, T newObj) { } } - private static T applyPatch(Resource resource, Map map) { - return resource.patch(PatchContext.of(PatchType.STRATEGIC_MERGE), Serialization.asJson(map)); + private static T applyPatch(Resource resource, Map map, KubernetesSerialization serialization) { + return resource.patch(PatchContext.of(PatchType.STRATEGIC_MERGE), serialization.asJson(map)); } - public static T resume(Resource resource) { - return applyPatch(resource, RollingUpdater.requestPayLoadForRolloutResume()); + public static T resume(RollableScalableResourceOperation resource) { + return applyPatch(resource, RollingUpdater.requestPayLoadForRolloutResume(), resource.getKubernetesSerialization()); } - public static T pause(Resource resource) { - return applyPatch(resource, RollingUpdater.requestPayLoadForRolloutPause()); + public static T pause(RollableScalableResourceOperation resource) { + return applyPatch(resource, RollingUpdater.requestPayLoadForRolloutPause(), resource.getKubernetesSerialization()); } - public static T restart(Resource resource) { - return applyPatch(resource, RollingUpdater.requestPayLoadForRolloutRestart()); + public static T restart(RollableScalableResourceOperation resource) { + return applyPatch(resource, RollingUpdater.requestPayLoadForRolloutRestart(), resource.getKubernetesSerialization()); } public static Map requestPayLoadForRolloutPause() { diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/StatefulSetOperationsImpl.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/StatefulSetOperationsImpl.java index c2dc2207d92..0b99a1de72e 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/StatefulSetOperationsImpl.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/StatefulSetOperationsImpl.java @@ -38,7 +38,6 @@ import io.fabric8.kubernetes.client.dsl.internal.HasMetadataOperationsImpl; import io.fabric8.kubernetes.client.dsl.internal.OperationContext; import io.fabric8.kubernetes.client.dsl.internal.PodOperationContext; -import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.kubernetes.client.utils.internal.PodOperationUtil; import java.io.InputStream; @@ -182,7 +181,8 @@ public StatefulSet undo() { }); ControllerRevision previousControllerRevision = controllerRevisions.get(1); - return patch(PatchContext.of(PatchType.STRATEGIC_MERGE), Serialization.asJson(previousControllerRevision.getData())); + return patch(PatchContext.of(PatchType.STRATEGIC_MERGE), + getKubernetesSerialization().asJson(previousControllerRevision.getData())); } private ControllerRevisionList getControllerRevisionListForStatefulSet(StatefulSet statefulSet) { diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/core/v1/PodOperationsImpl.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/core/v1/PodOperationsImpl.java index 2ec347901d3..999142f0307 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/core/v1/PodOperationsImpl.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/core/v1/PodOperationsImpl.java @@ -55,7 +55,6 @@ import io.fabric8.kubernetes.client.http.HttpRequest; import io.fabric8.kubernetes.client.http.WebSocket; import io.fabric8.kubernetes.client.lib.FilenameUtils; -import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.kubernetes.client.utils.URLUtils; import io.fabric8.kubernetes.client.utils.URLUtils.URLBuilder; import io.fabric8.kubernetes.client.utils.Utils; @@ -254,7 +253,7 @@ private boolean handleEvict(HasMetadata eviction) { URL requestUrl = new URL(URLUtils.join(getResourceUrl().toString(), "eviction")); HttpRequest.Builder requestBuilder = httpClient.newHttpRequestBuilder() - .post(JSON, Serialization.asJson(eviction)).url(requestUrl); + .post(JSON, getKubernetesSerialization().asJson(eviction)).url(requestUrl); handleResponse(requestBuilder, null); return true; } catch (KubernetesClientException e) { @@ -341,7 +340,8 @@ private boolean hasContainer(List containers, String toFind) { private ExecWebSocketListener setupConnectionToPod(URI uri) { HttpClient clone = httpClient.newBuilder().readTimeout(0, TimeUnit.MILLISECONDS).build(); - ExecWebSocketListener execWebSocketListener = new ExecWebSocketListener(getContext(), this.context.getExecutor()); + ExecWebSocketListener execWebSocketListener = new ExecWebSocketListener(getContext(), this.context.getExecutor(), + this.getKubernetesSerialization()); CompletableFuture startedFuture = clone.newWebSocketBuilder() .subprotocol("v4.channel.k8s.io") .uri(uri) diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/impl/BaseClient.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/impl/BaseClient.java index 8ff5dd2033b..0102defcf32 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/impl/BaseClient.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/impl/BaseClient.java @@ -16,6 +16,7 @@ package io.fabric8.kubernetes.client.impl; +import com.fasterxml.jackson.databind.ObjectMapper; import io.fabric8.kubernetes.api.model.APIGroup; import io.fabric8.kubernetes.api.model.APIGroupList; import io.fabric8.kubernetes.api.model.APIResourceList; @@ -39,6 +40,7 @@ import io.fabric8.kubernetes.client.extension.SupportTestingClient; import io.fabric8.kubernetes.client.http.HttpClient; import io.fabric8.kubernetes.client.utils.ApiVersionUtil; +import io.fabric8.kubernetes.client.utils.KubernetesSerialization; import io.fabric8.kubernetes.client.utils.Utils; import java.net.MalformedURLException; @@ -81,6 +83,7 @@ public void onClose(Executor executor) { private OperationSupport operationSupport; private ExecutorSupplier executorSupplier; private Executor executor; + protected KubernetesSerialization kubernetesSerialization = new KubernetesSerialization(new ObjectMapper()); private OperationContext operationContext; @@ -338,4 +341,8 @@ public Executor getExecutor() { return executor; } + public KubernetesSerialization getKubernetesSerialization() { + return kubernetesSerialization; + } + } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/impl/Handlers.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/impl/Handlers.java index 66c55868800..5c9cc53ce8d 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/impl/Handlers.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/impl/Handlers.java @@ -21,6 +21,7 @@ import io.fabric8.kubernetes.api.model.GenericKubernetesResource; import io.fabric8.kubernetes.api.model.GenericKubernetesResourceList; import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.KubernetesResource; import io.fabric8.kubernetes.api.model.KubernetesResourceList; import io.fabric8.kubernetes.client.Client; import io.fabric8.kubernetes.client.KubernetesClientException; @@ -30,7 +31,6 @@ import io.fabric8.kubernetes.client.dsl.internal.HasMetadataOperation; import io.fabric8.kubernetes.client.utils.ApiVersionUtil; import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil; -import io.fabric8.kubernetes.client.utils.Serialization; import java.util.Arrays; import java.util.List; @@ -57,7 +57,7 @@ public void unregister(Class type) { /** * Returns a {@link ResourceHandler} for the given item. The client is optional, if it is supplied, then the server can be * consulted for resource metadata if a generic item is passed in. - * + * * @return the handler * @throws KubernetesClientException if a handler cannot be found */ @@ -65,7 +65,8 @@ public > ResourceHandler Class type = (Class) meta.getClass(); if (type.equals(GenericKubernetesResource.class)) { - ResourceDefinitionContext rdc = getResourceDefinitionContext((GenericKubernetesResource) meta, client); + GenericKubernetesResource gkr = (GenericKubernetesResource) meta; + ResourceDefinitionContext rdc = getResourceDefinitionContext(gkr.getApiVersion(), gkr.getKind(), client); if (rdc != null) { return new ResourceHandlerImpl(GenericKubernetesResource.class, GenericKubernetesResourceList.class, rdc); @@ -79,26 +80,17 @@ public > ResourceHandler return result; } - public ResourceDefinitionContext getResourceDefinitionContext(String apiVersion, String kind, BaseClient client) { - GenericKubernetesResource resource = new GenericKubernetesResource(); - resource.setKind(kind); - resource.setApiVersion(apiVersion); - return getResourceDefinitionContext(resource, client); - } - - public ResourceDefinitionContext getResourceDefinitionContext(GenericKubernetesResource meta, + public ResourceDefinitionContext getResourceDefinitionContext(String apiVersion, String kind, Client client) { // check if it's built-in - Object value = Serialization.unmarshal(Serialization.asJson(meta)); - Class parsedType = (Class) value.getClass(); + Class clazz = client.adapt(BaseClient.class).getKubernetesSerialization() + .getRegisteredKind(apiVersion, kind); ResourceDefinitionContext rdc = null; - if (!parsedType.equals(GenericKubernetesResource.class)) { - rdc = ResourceDefinitionContext.fromResourceType(parsedType); + if (clazz != null) { + rdc = ResourceDefinitionContext.fromResourceType(clazz); } else if (client != null) { // if a client has been supplied, we can try to look this up from the server - String kind = meta.getKind(); - String apiVersion = meta.getApiVersion(); if (kind == null || apiVersion == null) { return null; } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/impl/KubernetesClientImpl.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/impl/KubernetesClientImpl.java index 760b0f5eb1c..9933eb40194 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/impl/KubernetesClientImpl.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/impl/KubernetesClientImpl.java @@ -151,7 +151,6 @@ import io.fabric8.kubernetes.client.informers.impl.SharedInformerFactoryImpl; import io.fabric8.kubernetes.client.utils.ApiVersionUtil; import io.fabric8.kubernetes.client.utils.HttpClientUtils; -import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.kubernetes.client.utils.Utils; import java.io.InputStream; @@ -256,14 +255,6 @@ protected KubernetesClientImpl(Config config, BaseClient client) { super(config, client); } - public static KubernetesClientImpl fromConfig(String config) { - return new KubernetesClientImpl(Serialization.unmarshal(config, Config.class)); - } - - public static KubernetesClientImpl fromConfig(InputStream is) { - return new KubernetesClientImpl(Serialization.unmarshal(is, Config.class)); - } - @Override public NamespacedKubernetesClient inNamespace(String name) { return newInstance(createInNamespaceConfig(name, false)); @@ -306,7 +297,7 @@ public NonNamespaceOperation load(InputStream is) { - return resourceListFor(is); + return resourceListFor(kubernetesSerialization.unmarshal(is)); } /** @@ -343,7 +334,7 @@ public NamespaceListVisitFromServerGetDeleteRecreateWaitApplicable */ @Override public NamespaceListVisitFromServerGetDeleteRecreateWaitApplicable resourceList(String s) { - return resourceListFor(s); + return resourceListFor(kubernetesSerialization.unmarshal(s)); } @Override @@ -367,7 +358,7 @@ private NamespaceableResource resource(Object resource) { */ @Override public NamespaceableResource resource(String s) { - return resource(Serialization. unmarshal(s)); + return resource(kubernetesSerialization. unmarshal(s)); } /** @@ -375,7 +366,7 @@ public NamespaceableResource resource(String s) { */ @Override public NamespaceableResource resource(InputStream is) { - return resource(Serialization. unmarshal(is)); + return resource(kubernetesSerialization. unmarshal(is)); } /** diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/internal/CreateOrReplaceHelper.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/internal/CreateOrReplaceHelper.java index 6671516336d..7abf75db7f2 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/internal/CreateOrReplaceHelper.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/internal/CreateOrReplaceHelper.java @@ -18,7 +18,7 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil; -import io.fabric8.kubernetes.client.utils.Serialization; +import io.fabric8.kubernetes.client.utils.KubernetesSerialization; import java.net.HttpURLConnection; import java.util.concurrent.CompletableFuture; @@ -30,20 +30,22 @@ public class CreateOrReplaceHelper { private final UnaryOperator replaceTask; private final UnaryOperator waitTask; private final UnaryOperator reloadTask; + private final KubernetesSerialization serialization; public CreateOrReplaceHelper(UnaryOperator createTask, UnaryOperator replaceTask, UnaryOperator waitTask, - UnaryOperator reloadTask) { + UnaryOperator reloadTask, KubernetesSerialization serialization) { this.createTask = createTask; this.replaceTask = replaceTask; this.waitTask = waitTask; this.reloadTask = reloadTask; + this.serialization = serialization; } public T createOrReplace(T item) { String resourceVersion = KubernetesResourceUtil.getResourceVersion(item); final CompletableFuture future = new CompletableFuture<>(); int nTries = 0; - item = Serialization.clone(item); + item = serialization.clone(item); while (!future.isDone() && nTries < CREATE_OR_REPLACE_RETRIES) { try { // Create diff --git a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/impl/KubernetesClientImplTest.java b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/impl/KubernetesClientImplTest.java index 1068fe893f1..251acc2b8d8 100644 --- a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/impl/KubernetesClientImplTest.java +++ b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/impl/KubernetesClientImplTest.java @@ -22,6 +22,7 @@ import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.ConfigBuilder; import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClientBuilder; import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.client.dsl.NamespaceListVisitFromServerGetDeleteRecreateWaitApplicable; import io.fabric8.kubernetes.client.http.BasicBuilder; @@ -120,7 +121,7 @@ void loadWithWindowsLineSeparatorsString() throws Exception { void shouldInstantiateClientUsingYaml() { File configYml = new File(TEST_CONFIG_YML_FILE); try (InputStream is = new FileInputStream(configYml)) { - KubernetesClient client = KubernetesClientImpl.fromConfig(is); + KubernetesClient client = new KubernetesClientBuilder().withConfig(is).build(); assertEquals("http://some.url/", client.getMasterUrl().toString()); } catch (Exception e) { fail(); @@ -131,7 +132,7 @@ void shouldInstantiateClientUsingYaml() { void shouldInstantiateClientUsingSerializeDeserialize() { KubernetesClientImpl original = new KubernetesClientImpl(); String json = Serialization.asJson(original.getConfiguration()); - KubernetesClientImpl copy = KubernetesClientImpl.fromConfig(json); + KubernetesClient copy = new KubernetesClientBuilder().withConfig(json).build(); assertEquals(original.getConfiguration().getMasterUrl(), copy.getConfiguration().getMasterUrl()); assertEquals(original.getConfiguration().getOauthToken(), copy.getConfiguration().getOauthToken()); diff --git a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/internal/CreateOrReplaceHelperTest.java b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/internal/CreateOrReplaceHelperTest.java index 7940721f077..aef8f57b7cc 100644 --- a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/internal/CreateOrReplaceHelperTest.java +++ b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/internal/CreateOrReplaceHelperTest.java @@ -19,6 +19,7 @@ import io.fabric8.kubernetes.api.model.PodBuilder; import io.fabric8.kubernetes.api.model.StatusBuilder; import io.fabric8.kubernetes.client.KubernetesClientException; +import io.fabric8.kubernetes.client.utils.Serialization; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -47,7 +48,7 @@ void testCreateOrReplaceShouldCreate() { createPodTask, p -> getPod(), p -> getPod(), - p -> getPod()); + p -> getPod(), Serialization.getKubernetesSerialization()); Pod p = getPod(); p.getMetadata().setResourceVersion("1"); @@ -77,7 +78,7 @@ void testCreateOrReplaceShouldReplace() { createPodTask, replacePodTask, p -> getPod(), - p -> getPod()); + p -> getPod(), Serialization.getKubernetesSerialization()); // When Pod podCreated = podCreateOrReplaceHelper.createOrReplace(getPod()); @@ -106,7 +107,7 @@ HttpURLConnection.HTTP_INTERNAL_ERROR, new StatusBuilder().withCode(HttpURLConne createPodTask, p -> getPod(), waitTask, - reloadTask); + reloadTask, Serialization.getKubernetesSerialization()); // When Pod podCreated = podCreateOrReplaceHelper.createOrReplace(getPod()); @@ -125,7 +126,7 @@ void testCreateOrReplaceThrowExceptionOnErrorCodeLessThan500() { HttpURLConnection.HTTP_BAD_REQUEST, new StatusBuilder().withCode(HttpURLConnection.HTTP_BAD_REQUEST).build()); }; CreateOrReplaceHelper podCreateOrReplaceHelper = new CreateOrReplaceHelper<>(createPodTask, - p -> getPod(), p -> getPod(), p -> getPod()); + p -> getPod(), p -> getPod(), p -> getPod(), Serialization.getKubernetesSerialization()); Pod podToCreate = getPod(); // When 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 7aa89cbfdda..a78c388c067 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 @@ -75,7 +75,7 @@ public boolean equals(Object obj) { private static final String KIND = "kind"; private static final String API_VERSION = "apiVersion"; - private static final Mapping mapping = new Mapping(); + private final Mapping mapping = new Mapping(); @Override public KubernetesResource deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { @@ -110,7 +110,7 @@ private KubernetesResource fromArrayNode(JsonParser jp, JsonNode node) throws IO return new KubernetesListBuilder().withItems(list).build(); } - private static KubernetesResource fromObjectNode(JsonParser jp, JsonNode node) throws IOException { + private KubernetesResource fromObjectNode(JsonParser jp, JsonNode node) throws IOException { TypeKey key = getKey(node); Class resourceType = mapping.getForKey(key); if (resourceType == null) { @@ -132,7 +132,7 @@ private static KubernetesResource fromObjectNode(JsonParser jp, JsonNode node) t /** * Return a string representation of the key of the type: #. */ - private static TypeKey getKey(JsonNode node) { + private TypeKey getKey(JsonNode node) { JsonNode apiVersion = node.get(API_VERSION); JsonNode kind = node.get(KIND); @@ -144,14 +144,14 @@ private static TypeKey getKey(JsonNode node) { /** * Registers a Custom Resource Definition Kind */ - public static void registerCustomKind(String kind, Class clazz) { + public void registerCustomKind(String kind, Class clazz) { registerCustomKind(null, kind, clazz); } /** * Registers a Custom Resource Definition Kind */ - public static void registerCustomKind(String apiVersion, String kind, Class clazz) { + public void registerCustomKind(String apiVersion, String kind, Class clazz) { mapping.registerKind(apiVersion, kind, clazz); } @@ -223,4 +223,8 @@ private void addMapping(Class clazz) { } } } + + public Class getRegisteredKind(String apiVersion, String kind) { + return mapping.getForKey(mapping.createKey(apiVersion, kind)); + } } diff --git a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/CustomResourceCrudTest.java b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/CustomResourceCrudTest.java index ee0c0b4cc14..acc1727e949 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/CustomResourceCrudTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/CustomResourceCrudTest.java @@ -22,11 +22,11 @@ import io.fabric8.kubernetes.client.dsl.MixedOperation; import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation; import io.fabric8.kubernetes.client.dsl.Resource; +import io.fabric8.kubernetes.client.impl.BaseClient; import io.fabric8.kubernetes.client.mock.crd.CronTab; import io.fabric8.kubernetes.client.mock.crd.CronTabSpec; import io.fabric8.kubernetes.client.mock.crd.CronTabStatus; import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import io.fabric8.kubernetes.internal.KubernetesDeserializer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -48,7 +48,8 @@ class CustomResourceCrudTest { @BeforeEach void setUp() { - KubernetesDeserializer.registerCustomKind("stable.example.com/v1", "CronTab", CronTab.class); + client.adapt(BaseClient.class).getKubernetesSerialization().registerCustomKind("stable.example.com/v1", "CronTab", + CronTab.class); cronTabCrd = client .apiextensions().v1() .customResourceDefinitions() diff --git a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/CustomResourceCrudWithCRDContextTest.java b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/CustomResourceCrudWithCRDContextTest.java index cdfe80b955f..cf03b8af945 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/CustomResourceCrudWithCRDContextTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/CustomResourceCrudWithCRDContextTest.java @@ -20,11 +20,11 @@ import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.dsl.MixedOperation; import io.fabric8.kubernetes.client.dsl.Resource; +import io.fabric8.kubernetes.client.impl.BaseClient; import io.fabric8.kubernetes.client.mock.crd.EntandoBundleRelease; import io.fabric8.kubernetes.client.mock.crd.EntandoBundleReleaseList; import io.fabric8.kubernetes.client.mock.crd.EntandoBundleReleaseSpec; import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import io.fabric8.kubernetes.internal.KubernetesDeserializer; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -38,7 +38,8 @@ class CustomResourceCrudWithCRDContextTest { @Test void testCreateAndGet() { // Given - KubernetesDeserializer.registerCustomKind("demo.fabric8.io/v1alpha1", "EntandoBundleRelease", EntandoBundleRelease.class); + client.adapt(BaseClient.class).getKubernetesSerialization().registerCustomKind("demo.fabric8.io/v1alpha1", + "EntandoBundleRelease", EntandoBundleRelease.class); MixedOperation> ebrClient = client .resources(EntandoBundleRelease.class, EntandoBundleReleaseList.class); @@ -54,7 +55,8 @@ void testCreateAndGet() { @Test void testCreateAndGetWithInferredContext() { // Given - KubernetesDeserializer.registerCustomKind("demo.fabric8.io/v1alpha1", "EntandoBundleRelease", EntandoBundleRelease.class); + client.adapt(BaseClient.class).getKubernetesSerialization().registerCustomKind("demo.fabric8.io/v1alpha1", + "EntandoBundleRelease", EntandoBundleRelease.class); MixedOperation, Resource> ebrClient = client .resources(EntandoBundleRelease.class); diff --git a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/DefaultSharedIndexInformerTest.java b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/DefaultSharedIndexInformerTest.java index 3c4ef8e41f7..872d5eaae08 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/DefaultSharedIndexInformerTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/DefaultSharedIndexInformerTest.java @@ -42,6 +42,7 @@ import io.fabric8.kubernetes.client.WatcherException; import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext; import io.fabric8.kubernetes.client.dsl.base.ResourceDefinitionContext; +import io.fabric8.kubernetes.client.impl.BaseClient; import io.fabric8.kubernetes.client.informers.ResourceEventHandler; import io.fabric8.kubernetes.client.informers.SharedIndexInformer; import io.fabric8.kubernetes.client.informers.SharedInformerFactory; @@ -56,7 +57,6 @@ import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; import io.fabric8.kubernetes.client.utils.Utils; -import io.fabric8.kubernetes.internal.KubernetesDeserializer; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -1002,7 +1002,8 @@ void testGenericKubernetesResourceSharedIndexInformerWithAdditionalDeserializers r -> new WatchEvent(getAnimal("red-panda", "Carnivora", r), "ADDED"), null, null); // When - KubernetesDeserializer.registerCustomKind("jungle.example.com/v1", "Animal", CronTab.class); + client.adapt(BaseClient.class).getKubernetesSerialization().registerCustomKind("jungle.example.com/v1", "Animal", + CronTab.class); SharedIndexInformer animalSharedIndexInformer = client .genericKubernetesResources(animalContext).inNamespace("ns1").runnableInformer(60 * WATCH_EVENT_EMIT_TIME); CountDownLatch foundExistingAnimal = new CountDownLatch(1); diff --git a/openshift-client-api/src/main/java/io/fabric8/openshift/client/DefaultOpenShiftClient.java b/openshift-client-api/src/main/java/io/fabric8/openshift/client/DefaultOpenShiftClient.java index 21169f5aaa3..2e9e98ca0b1 100644 --- a/openshift-client-api/src/main/java/io/fabric8/openshift/client/DefaultOpenShiftClient.java +++ b/openshift-client-api/src/main/java/io/fabric8/openshift/client/DefaultOpenShiftClient.java @@ -22,9 +22,6 @@ import io.fabric8.kubernetes.client.http.HttpClient.Factory; import io.fabric8.kubernetes.client.http.StandardHttpClientBuilder; import io.fabric8.kubernetes.client.utils.HttpClientUtils; -import io.fabric8.kubernetes.client.utils.Serialization; - -import java.io.InputStream; /** * Class for Default Openshift Client implementing KubernetesClient interface. @@ -37,14 +34,6 @@ public class DefaultOpenShiftClient extends NamespacedOpenShiftClientAdapter { public static final String OPENSHIFT_VERSION_ENDPOINT = "version/openshift"; - public static DefaultOpenShiftClient fromConfig(String config) { - return new DefaultOpenShiftClient(Serialization.unmarshal(config, OpenShiftConfig.class)); - } - - public static DefaultOpenShiftClient fromConfig(InputStream is) { - return new DefaultOpenShiftClient(Serialization.unmarshal(is, OpenShiftConfig.class)); - } - public DefaultOpenShiftClient() { this(new OpenShiftConfigBuilder().build()); } diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/build/BuildConfigOperationsImpl.java b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/build/BuildConfigOperationsImpl.java index 17fa1d10e69..60db6d3f641 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/build/BuildConfigOperationsImpl.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/build/BuildConfigOperationsImpl.java @@ -28,7 +28,6 @@ import io.fabric8.kubernetes.client.http.HttpClient; import io.fabric8.kubernetes.client.http.HttpRequest; import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil; -import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.kubernetes.client.utils.URLUtils; import io.fabric8.kubernetes.client.utils.Utils; import io.fabric8.openshift.api.model.Build; @@ -129,7 +128,7 @@ public Void trigger(WebHookTrigger trigger) { //TODO: This needs some attention. String triggerUrl = URLUtils.join(getResourceUrl().toString(), "webhooks", secret, triggerType); HttpRequest.Builder requestBuilder = this.httpClient.newHttpRequestBuilder() - .post(JSON, Serialization.asJson(trigger)) + .post(JSON, getKubernetesSerialization().asJson(trigger)) .uri(triggerUrl) .header("X-Github-Event", "push"); handleResponse(requestBuilder, null); diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/core/TemplateOperationsImpl.java b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/core/TemplateOperationsImpl.java index a0f60dd336f..b1dc1a7c661 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/core/TemplateOperationsImpl.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/core/TemplateOperationsImpl.java @@ -22,7 +22,6 @@ import io.fabric8.kubernetes.api.model.KubernetesListBuilder; import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.client.extension.ExtensibleResourceAdapter; -import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.kubernetes.client.utils.Utils; import io.fabric8.openshift.api.model.Parameter; import io.fabric8.openshift.api.model.Template; @@ -66,7 +65,7 @@ public KubernetesList process(File f) { @Override public KubernetesList process(InputStream is) { - return process(Serialization.unmarshal(is, MAPS_REFERENCE)); + return process(getKubernetesSerialization().unmarshal(is, MAPS_REFERENCE)); } @Override @@ -113,7 +112,7 @@ public KubernetesList processLocally(File f) { @Override public KubernetesList processLocally(InputStream is) { - return processLocally(Serialization.unmarshal(is, MAPS_REFERENCE)); + return processLocally(getKubernetesSerialization().unmarshal(is, MAPS_REFERENCE)); } @Override @@ -134,7 +133,7 @@ public KubernetesList processLocally(Map valuesMap) { .withItems(t != null && t.getObjects() != null ? t.getObjects() : Collections. emptyList()) .build(); - String json = Serialization.asJson(list); + String json = getKubernetesSerialization().asJson(list); String last = null; if (parameters != null && !parameters.isEmpty()) { @@ -164,7 +163,7 @@ public KubernetesList processLocally(Map valuesMap) { } } - return Serialization.unmarshal(json, KubernetesList.class); + return getKubernetesSerialization().unmarshal(json, KubernetesList.class); } } diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/impl/OpenShiftClientImpl.java b/openshift-client/src/main/java/io/fabric8/openshift/client/impl/OpenShiftClientImpl.java index 8fd486d5b03..9279ada921a 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/impl/OpenShiftClientImpl.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/impl/OpenShiftClientImpl.java @@ -40,7 +40,6 @@ import io.fabric8.kubernetes.client.impl.ExtensionsAPIGroupClient; import io.fabric8.kubernetes.client.impl.KubernetesClientImpl; import io.fabric8.kubernetes.client.utils.HttpClientUtils; -import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.kubernetes.client.utils.TokenRefreshInterceptor; import io.fabric8.openshift.api.model.BrokerTemplateInstance; import io.fabric8.openshift.api.model.BrokerTemplateInstanceList; @@ -169,7 +168,6 @@ import io.fabric8.openshift.client.dsl.internal.project.ProjectOperationsImpl; import io.fabric8.openshift.client.internal.OpenShiftOAuthInterceptor; -import java.io.InputStream; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; @@ -218,14 +216,6 @@ public OpenShiftClientImpl(HttpClient httpClient, OpenShiftConfig config) { this.openShiftUrl = client.openShiftUrl; } - public static OpenShiftClientImpl fromConfig(String config) { - return new OpenShiftClientImpl(Serialization.unmarshal(config, OpenShiftConfig.class)); - } - - public static OpenShiftClientImpl fromConfig(InputStream is) { - return new OpenShiftClientImpl(Serialization.unmarshal(is, OpenShiftConfig.class)); - } - @Override public URL getOpenshiftUrl() { return openShiftUrl; diff --git a/openshift-client/src/test/java/io/fabric8/openshift/client/impl/OpenShiftConfigTest.java b/openshift-client/src/test/java/io/fabric8/openshift/client/impl/OpenShiftConfigTest.java index 89e370b3ae4..c92872e31a8 100644 --- a/openshift-client/src/test/java/io/fabric8/openshift/client/impl/OpenShiftConfigTest.java +++ b/openshift-client/src/test/java/io/fabric8/openshift/client/impl/OpenShiftConfigTest.java @@ -17,6 +17,8 @@ import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.ConfigBuilder; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClientBuilder; import io.fabric8.kubernetes.client.utils.Serialization; import io.fabric8.openshift.client.OpenShiftConfig; import org.junit.jupiter.api.AfterEach; @@ -80,7 +82,7 @@ void testNoOpenshiftURL() { void shouldInstantiateClientUsingSerializeDeserialize() { OpenShiftClientImpl original = new OpenShiftClientImpl(); String json = Serialization.asJson(original.getConfiguration()); - OpenShiftClientImpl copy = OpenShiftClientImpl.fromConfig(json); + KubernetesClient copy = new KubernetesClientBuilder().withConfig(json).build(); assertEquals(original.getConfiguration().getMasterUrl(), copy.getConfiguration().getMasterUrl()); assertEquals(original.getConfiguration().getOauthToken(), copy.getConfiguration().getOauthToken());