From 1d3e263cc6216f4a3adad6b677539186179f41c2 Mon Sep 17 00:00:00 2001 From: Steven Hawkins Date: Thu, 22 Dec 2022 08:59:42 -0500 Subject: [PATCH] fix #3972: preparing for removal of unneeded serialization logic. (#4683) * fix #3972: preparing for removal of unneeded serialization logic. * fix #3972: taking the changes further to remove overloaded load all parameter operations are now localized to template logic (overloaded get and load) also fixes kubernetesclientbuilder.withconfig --- CHANGELOG.md | 3 + .../client/KubernetesClientBuilder.java | 4 +- .../client/dsl/ParameterMixedOperation.java | 5 +- ...ServerGetDeleteRecreateWaitApplicable.java | 6 + .../client/dsl/Parameterizable.java | 5 + .../client/utils/Serialization.java | 62 +++++---- ...ializationSingleDocumentUnmarshalTest.java | 5 +- .../client/dsl/internal/BaseOperation.java | 2 +- ...hDeleteRecreateWaitApplicableListImpl.java | 14 +- .../client/dsl/internal/OperationSupport.java | 38 +----- .../internal/core/v1/PodOperationsImpl.java | 3 - .../client/impl/KubernetesClientImpl.java | 12 +- .../client/impl/KubernetesClientImplTest.java | 10 +- .../client/server/mock/OpenShiftLoadTest.java | 17 ++- .../build/BuildConfigOperationsImpl.java | 2 +- .../internal/core/TemplateOperationsImpl.java | 122 ++++++++---------- .../client/impl/OpenShiftClientImpl.java | 29 ----- ...hDeleteRecreateWaitApplicableListImpl.java | 106 --------------- .../client/impl/OpenShiftConfigTest.java | 4 +- 19 files changed, 139 insertions(+), 310 deletions(-) delete mode 100644 openshift-client/src/main/java/io/fabric8/openshift/client/internal/OpenShiftNamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl.java diff --git a/CHANGELOG.md b/CHANGELOG.md index fcadfb02cbc..eb5f3426d56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ #### New Features #### _**Note**_: Breaking changes +* Fix #3972: deprecated Parameterizable and methods on Serialization accepting parameters - that was only needed as a workaround for non-string parameters. You should instead include those parameter values in the map passed to processLocally. +* Fix #3972: OpenShiftClient.load will no longer implicitly process templates. Use OpenShiftClient.templates().load instead. +* Fix #3972: WARNING: future client versions will not provide the static yaml and json ObjectMappersSerialization. * Fix #4574: fromServer has been deprecated - it no longer needs to be called. All get() operations will fetch the resource(s) from the api server. If you need the context item that was passed in from a resource, load, or resourceList methods, use the item or items method. * Fix #4633: client.run().withRunConfig was deprecated. Use withNewRunConfig instead. * Fix #4663: Config.maxConcurrentRequests and Config.maxConcurrentRequestsPerHost will no longer be used. Instead they will default to unlimited for all clients. Due to the ability of the fabric8 client to start long running requests (either websocket or regular http) and how this is treated by the underlying clients you can easily exhaust these values and enter a state where the client is unresponsive without any additional information on what is occurring. diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/KubernetesClientBuilder.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/KubernetesClientBuilder.java index d0c952a9934..fd34ae75af8 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/KubernetesClientBuilder.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/KubernetesClientBuilder.java @@ -98,12 +98,12 @@ public KubernetesClientBuilder withConfig(Config config) { } public KubernetesClientBuilder withConfig(String config) { - this.config = Serialization.unmarshal(config); + this.config = Serialization.unmarshal(config, Config.class); return this; } public KubernetesClientBuilder withConfig(InputStream config) { - this.config = Serialization.unmarshal(config); + this.config = Serialization.unmarshal(config, Config.class); return this; } diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/ParameterMixedOperation.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/ParameterMixedOperation.java index 3213b4c47b0..57e0b0adcd7 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/ParameterMixedOperation.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/ParameterMixedOperation.java @@ -17,12 +17,15 @@ package io.fabric8.kubernetes.client.dsl; /** - * A {@link Parameterizable} {@link MixedOperation} + * @deprecated It is no longer necessary to associate parameters prior to deserialization. + *

+ * reference {@link MixedOperation} instead * * @param The Kubernetes resource type. * @param The list variant of the Kubernetes resource type. * @param The resource operations. */ +@Deprecated public interface ParameterMixedOperation> extends MixedOperation, Parameterizable> { } diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable.java index f8c39a58fbc..cd5d60582f9 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable.java @@ -16,6 +16,12 @@ package io.fabric8.kubernetes.client.dsl; +/** + * @deprecated It is no longer necessary to associate parameters prior to deserialization. + *

+ * reference {@link NamespaceListVisitFromServerGetDeleteRecreateWaitApplicable} instead + */ +@Deprecated public interface ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable extends NamespaceListVisitFromServerGetDeleteRecreateWaitApplicable, Parameterizable> { diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/Parameterizable.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/Parameterizable.java index 3dfdd74d083..bb8ebc59be3 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/Parameterizable.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/dsl/Parameterizable.java @@ -17,6 +17,11 @@ import java.util.Map; +/** + * @deprecated It is no longer necessary to associate parameters prior to deserialization. Please + * provide the parameters to one of the process methods instead + */ +@Deprecated public interface Parameterizable { T withParameters(Map parameters); 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 a5ffeb936b5..5b2600f189f 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 @@ -35,7 +35,6 @@ import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Type; @@ -180,17 +179,13 @@ public static T unmarshal(InputStream is) { * @param parameters A {@link Map} with parameters for placeholder substitution. * @param The target type. * @return returns returns de-serialized object + * + * @deprecated please directly apply {@link Utils#interpolateString(String, Map)} instead of passing parameters here */ + @Deprecated @SuppressWarnings("unchecked") public static T unmarshal(InputStream is, Map parameters) { - String specFile = readSpecFileFromInputStream(is); - if (containsMultipleDocuments(specFile)) { - return (T) getKubernetesResourceList(parameters, 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()), JSON_MAPPER, parameters); + return unmarshal(is, JSON_MAPPER, parameters); } /** @@ -217,9 +212,27 @@ public static T unmarshal(InputStream is, ObjectMapper mapper) { * @param parameters A {@link Map} with parameters for placeholder substitution. * @param The target type. * @return returns de-serialized object + * + * @deprecated please directly apply {@link Utils#interpolateString(String, Map)} instead of passing parameters here */ + @Deprecated public static T unmarshal(InputStream is, ObjectMapper mapper, Map parameters) { - return unmarshal(is, mapper, new TypeReference() { + // it's not well documented which Serialization methods are aware of input that can contain + // multiple docs + 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)), mapper, new TypeReference() { @Override public Type getType() { return KubernetesResource.class; @@ -228,9 +241,8 @@ public Type getType() { } private static T unmarshal(InputStream is, ObjectMapper mapper, TypeReference type, Map parameters) { - try ( - InputStream wrapped = parameters != null && !parameters.isEmpty() ? ReplaceValueStream.replaceValues(is, parameters) - : is; + try (InputStream wrapped = parameters != null && !parameters.isEmpty() ? ReplaceValueStream.replaceValues(is, parameters) + : is; BufferedInputStream bis = new BufferedInputStream(wrapped)) { bis.mark(-1); int intch; @@ -296,7 +308,10 @@ public static T unmarshal(String str, final Class type) { * @param parameters A hashmap containing parameters * * @return returns de-serialized object + * + * @deprecated please directly apply {@link Utils#interpolateString(String, Map)} instead of passing parameters here */ + @Deprecated public static T unmarshal(String str, final Class type, Map parameters) { try (InputStream is = new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8))) { return unmarshal(is, new TypeReference() { @@ -330,7 +345,10 @@ public static T unmarshal(InputStream is, final Class type) { * @param parameters A {@link Map} with parameters for placeholder substitution. * @param Template argument denoting type * @return returns de-serialized object + * + * @deprecated please directly apply {@link Utils#interpolateString(String, Map)} instead of passing parameters here */ + @Deprecated public static T unmarshal(InputStream is, final Class type, Map parameters) { return unmarshal(is, new TypeReference() { @Override @@ -361,7 +379,10 @@ public static T unmarshal(InputStream is, TypeReference type) { * @param Template argument denoting type * * @return returns de-serialized object + * + * @deprecated please directly apply {@link Utils#interpolateString(String, Map)} instead of passing parameters here */ + @Deprecated public static T unmarshal(InputStream is, TypeReference type, Map parameters) { return unmarshal(is, JSON_MAPPER, type, parameters); } @@ -370,6 +391,7 @@ private static List getKubernetesResourceList(Map (KubernetesResource) Serialization.unmarshal(new ByteArrayInputStream(document.getBytes()), parameters)) + .filter(o -> o != null) .collect(Collectors.toList()); } @@ -401,20 +423,6 @@ private static boolean validate(String document) { return !document.isEmpty() && keyValueMatcher.find(); } - private static String readSpecFileFromInputStream(InputStream inputStream) { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - byte[] buffer = new byte[1024]; - int length; - try { - while ((length = inputStream.read(buffer)) != -1) { - outputStream.write(buffer, 0, length); - } - return outputStream.toString(); - } catch (IOException e) { - throw new RuntimeException("Unable to read InputStream." + e); - } - } - /** * Create a copy of the resource via serialization. * diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/SerializationSingleDocumentUnmarshalTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/SerializationSingleDocumentUnmarshalTest.java index d8bf77536ef..936a85fa64b 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/SerializationSingleDocumentUnmarshalTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/SerializationSingleDocumentUnmarshalTest.java @@ -21,8 +21,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import java.util.Collections; - import static org.assertj.core.api.Assertions.assertThat; class SerializationSingleDocumentUnmarshalTest { @@ -36,8 +34,7 @@ class SerializationSingleDocumentUnmarshalTest { void unmarshalWithSingleDocumentWithDocumentDelimiterShouldReturnKubernetesResource(String arg) { // When final KubernetesResource result = Serialization.unmarshal( - SerializationTest.class.getResourceAsStream(String.format("/serialization/%s", arg)), - Collections.emptyMap()); + SerializationTest.class.getResourceAsStream(String.format("/serialization/%s", arg))); // Then assertThat(result) .asInstanceOf(InstanceOfAssertFactories.type(Service.class)) 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 1fd26e7514a..6b20fc745f8 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 @@ -411,7 +411,7 @@ public Type getType() { return refinedType; } }; - CompletableFuture futureAnswer = handleResponse(httpClient, requestBuilder, listTypeReference, getParameters()); + CompletableFuture futureAnswer = handleResponse(httpClient, requestBuilder, listTypeReference); return futureAnswer.thenApply(l -> { updateApiVersion(l); return l; 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 d4882d76c4e..329c10cf3b2 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; @@ -85,11 +84,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, Collections.emptyMap()); - context = context.withItem(item); // late realization of the inputstream - } - return asHasMetadata(item).stream() .map(meta -> acceptVisitors(meta, Collections.emptyList(), this.context)) @@ -255,17 +249,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) { + if (o != null) { result.add((HasMetadata) o); } } 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 6dad8f97f09..6e00568b9d4 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 @@ -365,7 +365,7 @@ protected T handleUpdate(T updated, Class type, boolean status) throws IO HttpRequest.Builder requestBuilder = httpClient.newHttpRequestBuilder() .put(JSON, JSON_MAPPER.writeValueAsString(updated)) .url(getResourceURLForWriteOperation(getResourceUrl(checkNamespace(updated), checkName(updated), status))); - return handleResponse(requestBuilder, type, getParameters()); + return handleResponse(requestBuilder, type); } /** @@ -481,11 +481,7 @@ protected Status handleDeploymentRollback(String resourceUrl, DeploymentRollback */ protected T handleGet(URL resourceUrl, Class type) throws InterruptedException, IOException { HttpRequest.Builder requestBuilder = httpClient.newHttpRequestBuilder().url(resourceUrl); - return handleResponse(requestBuilder, type, getParameters()); - } - - protected Map getParameters() { - return Collections.emptyMap(); + return handleResponse(requestBuilder, type); } protected T handleApproveOrDeny(T csr, Class type) throws IOException, InterruptedException { @@ -556,32 +552,15 @@ protected T waitForResult(CompletableFuture future) throws IOException { * @param template argument provided * * @return Returns a de-serialized object as api server response of provided type. - * @throws InterruptedException Interrupted Exception * @throws IOException IOException */ - protected T handleResponse(HttpRequest.Builder requestBuilder, Class type) throws InterruptedException, IOException { - return handleResponse(requestBuilder, type, getParameters()); - } - - /** - * Send an http request and handle the response, optionally performing placeholder substitution to the response. - * - * @param requestBuilder request builder - * @param type type of object - * @param parameters a hashmap containing parameters - * @param template argument provided - * - * @return Returns a de-serialized object as api server response of provided type. - * @throws IOException IOException - */ - private T handleResponse(HttpRequest.Builder requestBuilder, Class type, Map parameters) - throws IOException { + protected T handleResponse(HttpRequest.Builder requestBuilder, Class type) throws IOException { return waitForResult(handleResponse(httpClient, requestBuilder, new TypeReference() { @Override public Type getType() { return type; } - }, parameters)); + })); } /** @@ -590,14 +569,12 @@ public Type getType() { * @param client the client * @param requestBuilder Request builder * @param type Type of object provided - * @param parameters A hashmap containing parameters * @param Template argument provided * * @return Returns a de-serialized object as api server response of provided type. */ protected CompletableFuture handleResponse(HttpClient client, HttpRequest.Builder requestBuilder, - TypeReference type, - Map parameters) { + TypeReference type) { VersionUsageUtils.log(this.resourceT, this.apiGroupVersion); HttpRequest request = requestBuilder.build(); CompletableFuture> futureResponse = new CompletableFuture<>(); @@ -609,7 +586,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, parameters); + return Serialization.unmarshal(new ByteArrayInputStream(response.body()), type); } else { return null; } @@ -810,9 +787,6 @@ public R1 restCall(Class result, String... path) { throw e; } return null; - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - throw KubernetesClientException.launderThrowable(ie); } catch (IOException e) { throw KubernetesClientException.launderThrowable(e); } 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 0f08a8ef655..f9705efd57f 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 @@ -263,9 +263,6 @@ private boolean handleEvict(HasMetadata eviction) { return false; } catch (IOException exception) { throw KubernetesClientException.launderThrowable(forOperationType("evict"), exception); - } catch (InterruptedException interruptedException) { - Thread.currentThread().interrupt(); - throw KubernetesClientException.launderThrowable(forOperationType("evict"), interruptedException); } } 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 9e1987b64af..e5a7f72eec8 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 @@ -257,14 +257,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)); @@ -307,7 +299,7 @@ public NonNamespaceOperation load(InputStream is) { - return resourceListFor(is); + return resourceListFor(Serialization.unmarshal(is)); } /** @@ -344,7 +336,7 @@ public NamespaceListVisitFromServerGetDeleteRecreateWaitApplicable */ @Override public ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable resourceList(String s) { - return resourceListFor(s); + return resourceListFor(Serialization.unmarshal(s)); } @Override 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 c728602bee7..9a8cdb24b5c 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.ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable; import io.fabric8.kubernetes.client.http.BasicBuilder; @@ -52,7 +53,6 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.fail; /** * @author wangyushuai2@jd.com @@ -117,13 +117,11 @@ void loadWithWindowsLineSeparatorsString() throws Exception { } @Test - void shouldInstantiateClientUsingYaml() { + void shouldInstantiateClientUsingYaml() throws Exception { 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 +129,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-tests/src/test/java/io/fabric8/openshift/client/server/mock/OpenShiftLoadTest.java b/kubernetes-tests/src/test/java/io/fabric8/openshift/client/server/mock/OpenShiftLoadTest.java index 95490417302..657554c6de5 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/openshift/client/server/mock/OpenShiftLoadTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/openshift/client/server/mock/OpenShiftLoadTest.java @@ -16,25 +16,31 @@ package io.fabric8.openshift.client.server.mock; import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; import io.fabric8.openshift.client.OpenShiftClient; import org.junit.jupiter.api.Test; +import java.util.Collections; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -@EnableOpenShiftMockClient +@EnableKubernetesMockClient class OpenShiftLoadTest { - OpenShiftMockServer server; + KubernetesMockServer server; OpenShiftClient client; @Test void testResourceGetFromLoadWhenSingleDocumentsWithStartingDelimiter() { // when - List result = client.load(getClass().getResourceAsStream("/test-template.yml")).items(); + List result = client.templates() + .load(getClass().getResourceAsStream("/test-template.yml")) + .processLocally(Collections.emptyMap()) + .getItems(); // then assertNotNull(result); @@ -49,7 +55,10 @@ void testResourceGetFromLoadWhenSingleDocumentsWithStartingDelimiter() { void testResourceGetFromLoadWhenSingleDocumentsWithoutDelimiter() { // when - List result = client.load(getClass().getResourceAsStream("/template-with-params.yml")).items(); + List result = client.templates() + .load(getClass().getResourceAsStream("/template-with-params.yml")) + .item() + .getObjects(); // then assertNotNull(result); 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 b3b31b0453c..71c36897e2c 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 @@ -269,7 +269,7 @@ protected Build submitToApiServer(InputStream inputStream, long contentLength) { public Type getType() { return Build.class; } - }, null)); + })); } catch (Throwable e) { // TODO: better determine which exception this should occur on // otherwise we need to have the httpclient api open up to the notion 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 ab20127d404..67077c42749 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 @@ -20,8 +20,8 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.KubernetesList; import io.fabric8.kubernetes.api.model.KubernetesListBuilder; -import io.fabric8.kubernetes.api.model.KubernetesResourceList; import io.fabric8.kubernetes.client.Client; +import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.client.dsl.ParameterMixedOperation; import io.fabric8.kubernetes.client.dsl.internal.HasMetadataOperation; @@ -45,13 +45,12 @@ import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import static io.fabric8.openshift.client.OpenShiftAPIGroups.TEMPLATE; @@ -165,101 +164,82 @@ public TemplateOperationsImpl withParameters(Map parameters) { @Override public KubernetesList processLocally(Map valuesMap) { - Template t = withParameters(valuesMap).getItemOrRequireFromServer(); + Template t = processParameters(getItemOrRequireFromServer()); List parameters = t.getParameters(); KubernetesList list = new KubernetesListBuilder() .withItems(t.getObjects()) .build(); - try { - String json = JSON_MAPPER.writeValueAsString(list); - if (parameters != null && !parameters.isEmpty()) { - // lets make a few passes in case there's expressions in values - for (int i = 0; i < 5; i++) { - for (Parameter parameter : parameters) { - String parameterName = parameter.getName(); - String parameterValue; - if (valuesMap.containsKey(parameterName)) { - parameterValue = valuesMap.get(parameterName); - } else if (Utils.isNotNullOrEmpty(parameter.getValue())) { - parameterValue = parameter.getValue(); - } else if (EXPRESSION.equals(parameter.getGenerate())) { - Generex generex = new Generex(parameter.getFrom()); - parameterValue = generex.random(); - } else if (parameter.getRequired() == null || !parameter.getRequired()) { - parameterValue = ""; - } else { - throw new IllegalArgumentException("No value available for parameter name: " + parameterName); - } - if (parameterValue == null) { - logger.debug("Parameter {} has a null value", parameterName); - parameterValue = ""; - } - json = Utils.interpolateString(json, Collections.singletonMap(parameterName, parameterValue)); + String json = Serialization.asJson(list); + String last = null; + + if (parameters != null && !parameters.isEmpty()) { + while (!Objects.equals(last, json)) { + last = json; + for (Parameter parameter : parameters) { + String parameterName = parameter.getName(); + String parameterValue; + if (valuesMap.containsKey(parameterName)) { + parameterValue = valuesMap.get(parameterName); + } else if (Utils.isNotNullOrEmpty(parameter.getValue())) { + parameterValue = parameter.getValue(); + } else if (EXPRESSION.equals(parameter.getGenerate())) { + Generex generex = new Generex(parameter.getFrom()); + parameterValue = generex.random(); + } else if (parameter.getRequired() == null || !parameter.getRequired()) { + parameterValue = ""; + } else { + throw new IllegalArgumentException("No value available for parameter name: " + parameterName); + } + if (parameterValue == null) { + logger.debug("Parameter {} has a null value", parameterName); + parameterValue = ""; } + json = Utils.interpolateString(json, Collections.singletonMap(parameterName, parameterValue)); } } - - list = JSON_MAPPER.readValue(json, KubernetesList.class); - } catch (IOException e) { - throw KubernetesClientException.launderThrowable(e); } - return list; + + return Serialization.unmarshal(json, KubernetesList.class); } private URL getProcessUrl() throws MalformedURLException { return getNamespacedUrl(getNamespace(), "processedtemplates"); } + @Override + public Template get() { + return processParameters(super.get()); + } + + private Template processParameters(Template t) { + if (this.parameters != null && !this.parameters.isEmpty()) { + return Serialization.unmarshal(Utils.interpolateString(Serialization.asJson(t), this.parameters), Template.class); + } + return t; + } + @Override public TemplateResource load(InputStream is) { - String generatedName = "template-" + Utils.randomString(5); Template template = null; - Object item = Serialization.unmarshal(is, parameters); + List items = this.context.getClient().adapt(KubernetesClient.class).load(is).items(); + Object item = items; + if (items.size() == 1) { + item = items.get(0); + } if (item instanceof Template) { template = (Template) item; - } else if (item instanceof HasMetadata) { - HasMetadata h = (HasMetadata) item; + } else { + String generatedName = "template-" + Utils.randomString(5); template = new TemplateBuilder() .withNewMetadata() .withName(generatedName) - .withNamespace(h.getMetadata() != null ? h.getMetadata().getNamespace() : null) .endMetadata() - .withObjects(h).build(); - } else if (item instanceof KubernetesResourceList) { - List list = ((KubernetesResourceList) item).getItems(); - template = new TemplateBuilder() - .withNewMetadata() - .withName(generatedName) - .endMetadata() - .withObjects(list.toArray(new HasMetadata[list.size()])).build(); - } else if (item instanceof HasMetadata[]) { - template = new TemplateBuilder() - .withNewMetadata() - .withName(generatedName) - .endMetadata() - .withObjects((HasMetadata[]) item).build(); - } else if (item instanceof Collection) { - List items = new ArrayList<>(); - for (Object o : (Collection) item) { - if (o instanceof HasMetadata) { - items.add((HasMetadata) o); - } - } - template = new TemplateBuilder() - .withNewMetadata() - .withName(generatedName) - .endMetadata() - .withObjects(items.toArray(new HasMetadata[items.size()])).build(); + .withObjects(items).build(); } - return newInstance(context.withItem(template)); - } - - @Override - public Map getParameters() { - return parameters; + return resource(template); } } 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 3931bbdc252..75c322cb8de 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 @@ -15,7 +15,6 @@ */ package io.fabric8.openshift.client.impl; -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.RootPaths; @@ -32,12 +31,10 @@ import io.fabric8.kubernetes.client.dsl.InOutCreateable; import io.fabric8.kubernetes.client.dsl.MixedOperation; import io.fabric8.kubernetes.client.dsl.Nameable; -import io.fabric8.kubernetes.client.dsl.NamespaceListVisitFromServerGetDeleteRecreateWaitApplicable; import io.fabric8.kubernetes.client.dsl.Namespaceable; import io.fabric8.kubernetes.client.dsl.NamespacedInOutCreateable; import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation; import io.fabric8.kubernetes.client.dsl.ParameterMixedOperation; -import io.fabric8.kubernetes.client.dsl.ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable; import io.fabric8.kubernetes.client.dsl.Resource; import io.fabric8.kubernetes.client.dsl.internal.HasMetadataOperation; import io.fabric8.kubernetes.client.http.HttpClient; @@ -45,7 +42,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,10 +165,8 @@ import io.fabric8.openshift.client.dsl.internal.build.BuildOperationsImpl; import io.fabric8.openshift.client.dsl.internal.core.TemplateOperationsImpl; import io.fabric8.openshift.client.dsl.internal.project.ProjectOperationsImpl; -import io.fabric8.openshift.client.internal.OpenShiftNamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl; import io.fabric8.openshift.client.internal.OpenShiftOAuthInterceptor; -import java.io.InputStream; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; @@ -222,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; @@ -270,21 +256,6 @@ public OpenShiftOperatorHubAPIGroupDSL operatorHub() { return adapt(OpenShiftOperatorHubAPIGroupClient.class); } - @Override - public ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable load(InputStream is) { - return new OpenShiftNamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl(this, is); - } - - @Override - public NamespaceListVisitFromServerGetDeleteRecreateWaitApplicable resourceList(KubernetesResourceList item) { - return new OpenShiftNamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl(this, item); - } - - @Override - public ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable resourceList(String s) { - return new OpenShiftNamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl(this, s); - } - @Override public MixedOperation builds() { return new BuildOperationsImpl(this); diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/internal/OpenShiftNamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl.java b/openshift-client/src/main/java/io/fabric8/openshift/client/internal/OpenShiftNamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl.java deleted file mode 100644 index ca1f1b76ed4..00000000000 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/internal/OpenShiftNamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl.java +++ /dev/null @@ -1,106 +0,0 @@ -/** - * 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.openshift.client.internal; - -import com.mifmif.common.regex.Generex; -import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.api.model.KubernetesList; -import io.fabric8.kubernetes.api.model.KubernetesListBuilder; -import io.fabric8.kubernetes.client.Client; -import io.fabric8.kubernetes.client.KubernetesClientException; -import io.fabric8.kubernetes.client.dsl.internal.NamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl; -import io.fabric8.kubernetes.client.dsl.internal.OperationContext; -import io.fabric8.kubernetes.client.utils.Utils; -import io.fabric8.openshift.api.model.Parameter; -import io.fabric8.openshift.api.model.Template; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class OpenShiftNamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl - extends NamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl { - - public OpenShiftNamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl(Client client, Object item) { - super(client, item); - } - - public OpenShiftNamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl(OperationContext context) { - super(context); - } - - @Override - protected List asHasMetadata(Object item) { - if (item instanceof Template) { - return processTemplateList((Template) item, true); - } - return super.asHasMetadata(item); - } - - private static List processTemplate(Template template, Boolean failOnMissing) { - List parameters = template != null ? template.getParameters() : null; - List objects = template != null ? template.getObjects() : Collections.emptyList(); - KubernetesList list = new KubernetesListBuilder() - .withItems(objects) - .build(); - - try { - String json = OBJECT_MAPPER.writeValueAsString(list); - if (parameters != null && !parameters.isEmpty()) { - // lets make a few passes in case there's expressions in values - for (int i = 0; i < 5; i++) { - for (Parameter parameter : parameters) { - String name = parameter.getName(); - String regex = "${" + name + "}"; - String value; - if (Utils.isNotNullOrEmpty(parameter.getValue())) { - value = parameter.getValue(); - } else if (EXPRESSION.equals(parameter.getGenerate())) { - Generex generex = new Generex(parameter.getFrom()); - value = generex.random(); - } else if (Boolean.TRUE.equals(failOnMissing)) { - throw new IllegalArgumentException("No value available for parameter name: " + name); - } else { - value = ""; - } - json = json.replace(regex, value); - } - } - } - - list = OBJECT_MAPPER.readValue(json, KubernetesList.class); - } catch (IOException e) { - throw KubernetesClientException.launderThrowable(e); - } - return list.getItems(); - } - - private static List processTemplateList(Template item, Boolean enableProccessing) { - List result = new ArrayList<>(); - if (Boolean.FALSE.equals(enableProccessing)) { - result.addAll(item.getObjects()); - } else { - result.addAll(processTemplate(item, false)); - } - return result; - } - - @Override - public NamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl newInstance(OperationContext context) { - return new OpenShiftNamespaceVisitFromServerGetWatchDeleteRecreateWaitApplicableListImpl(context); - } -} 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());