Skip to content

Commit

Permalink
fix fabric8io#3972 encapsulated / deprecated usage of static json/yam…
Browse files Browse the repository at this point in the history
…l mappers
  • Loading branch information
shawkins committed Dec 11, 2022
1 parent 2906d4f commit d8c7a84
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 70 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Expand Up @@ -35,7 +35,7 @@
* Fix #4597: remove the deprecated support for `javax.validation.constraints.NotNull` in the `crd-generator`, to mark a property as `required` it needs to be annotated with `io.fabric8.generator.annotation.Required`
* Fix #3973: removed support for Parameterizable - 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 #3973: openShiftClient.templates().load and openShiftClient.load will no longer automatically process / create templates. Use the method openshiftClient.templates().from to get a template from any stream.
* Fix #3973: deprecated Serialization methods that take parameters.
* Fix #3973: deprecated Serialization methods that take parameters and methods for the json and yaml mappers.

### 6.2.0 (2022-10-20)

Expand Down
Expand Up @@ -116,7 +116,7 @@ Object[] store(V value) {
if (value == null) {
return null;
}
Map<String, Object> raw = Serialization.jsonMapper().convertValue(value, Map.class);
Map<String, Object> raw = Serialization.convertValue(value, Map.class);
return fields.stream().map(f -> GenericKubernetesResource.get(raw, (Object[]) f)).toArray();
}

Expand All @@ -129,7 +129,7 @@ V restore(String key, Object[] values) {
String[] keyParts = this.keyState.keyFieldFunction.apply(key);
applyFields(keyParts, raw, this.keyState.keyFields);

return Serialization.jsonMapper().convertValue(raw, typeClass);
return Serialization.convertValue(raw, typeClass);
}

private static void applyFields(Object[] values, Map<String, Object> raw, List<String[]> fields) {
Expand Down
Expand Up @@ -15,7 +15,6 @@
*/
package io.fabric8.kubernetes.client.internal;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.fabric8.kubernetes.api.model.AuthInfo;
import io.fabric8.kubernetes.api.model.Cluster;
import io.fabric8.kubernetes.api.model.Config;
Expand All @@ -26,6 +25,8 @@
import io.fabric8.kubernetes.client.utils.Serialization;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;

Expand All @@ -39,13 +40,11 @@ private KubeConfigUtils() {
}

public static Config parseConfig(File file) throws IOException {
ObjectMapper mapper = Serialization.yamlMapper();
return mapper.readValue(file, Config.class);
return Serialization.unmarshal(new FileInputStream(file), Config.class);
}

public static Config parseConfigFromString(String contents) throws IOException {
ObjectMapper mapper = Serialization.yamlMapper();
return mapper.readValue(contents, Config.class);
return Serialization.unmarshal(contents, Config.class);
}

/**
Expand Down Expand Up @@ -158,6 +157,8 @@ public static int getNamedUserIndexFromConfig(Config config, String userName) {
* @throws IOException in case of failure while writing to file
*/
public static void persistKubeConfigIntoFile(Config kubeConfig, String kubeConfigPath) throws IOException {
Serialization.yamlMapper().writeValue(new File(kubeConfigPath), kubeConfig);
try (FileWriter writer = new FileWriter(kubeConfigPath)) {
writer.write(Serialization.asYaml(kubeConfig));
}
}
}
Expand Up @@ -64,6 +64,10 @@ private static void copy(Reader reader, Writer writer) throws IOException {
}
}

/**
* @deprecated to be removed in future versions
*/
@Deprecated
public static boolean isJSONValid(String json) {
try {
ObjectMapper objectMapper = Serialization.jsonMapper();
Expand All @@ -74,18 +78,15 @@ public static boolean isJSONValid(String json) {
return true;
}

/**
* @deprecated to be removed in future versions
*/
@Deprecated
public static String convertYamlToJson(String yaml) throws IOException {
ObjectMapper yamlReader = Serialization.yamlMapper();
Object obj = yamlReader.readValue(yaml, Object.class);

ObjectMapper jsonWriter = Serialization.jsonMapper();
return jsonWriter.writeValueAsString(obj);
return Serialization.asJson(Serialization.unmarshal(yaml, Object.class));
}

public static String convertToJson(String jsonOrYaml) throws IOException {
if (isJSONValid(jsonOrYaml)) {
return jsonOrYaml;
}
return convertYamlToJson(jsonOrYaml);
}

Expand Down
Expand Up @@ -27,6 +27,8 @@
import io.fabric8.kubernetes.client.KubernetesClientException;
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;
Expand Down Expand Up @@ -75,7 +77,10 @@ private Serialization() {
* n.b. the use of this module gives precedence to properties present in the additionalProperties Map present
* in most KubernetesResource instances. If a property is both defined in the Map and in the original field, the
* one from the additionalProperties Map will be serialized.
*
* @deprecated
*/
@Deprecated
public static ObjectMapper jsonMapper() {
return JSON_MAPPER;
}
Expand All @@ -92,7 +97,10 @@ public static ObjectMapper jsonMapper() {
* n.b. the use of this module gives precedence to properties present in the additionalProperties Map present
* in most KubernetesResource instances. If a property is both defined in the Map and in the original field, the
* one from the additionalProperties Map will be serialized.
*
* @deprecated will be removed in future versions
*/
@Deprecated
public static ObjectMapper yamlMapper() {
if (YAML_MAPPER == null) {
synchronized (Serialization.class) {
Expand All @@ -111,7 +119,10 @@ public static ObjectMapper yamlMapper() {
* This is useful because in a lot of cases the YAML mapper is only need at application startup
* when the client is created, so there is no reason to keep the very heavy (in terms of memory) mapper
* around indefinitely.
*
* @deprecated
*/
@Deprecated
public static void clearYamlMapper() {
YAML_MAPPER = null;
}
Expand Down Expand Up @@ -154,6 +165,15 @@ public static <T> String asYaml(T object) {
} catch (JsonProcessingException e) {
throw KubernetesClientException.launderThrowable(e);
}
/*
* TODO: this will bypass the need for a yamlMapper
* Yaml yaml = yaml();
* try {
* return yaml.dump(convertValue(object, Map.class));
* } catch (IllegalArgumentException e) {
* return yaml.dump(convertValue(convertValue(object, JsonNode.class), Object.class));
* }
*/
}

/**
Expand Down Expand Up @@ -254,13 +274,16 @@ private static <T> T unmarshal(InputStream is, ObjectMapper mapper, TypeReferenc

final T result;
if (intch != '{' && intch != '[') {
final Yaml yaml = new Yaml(new SafeConstructor(), new Representer(), new DumperOptions(),
new CustomYamlTagResolverWithLimit());
Yaml yaml = yaml();
final Object obj = yaml.load(bis);
if (obj instanceof Map) {
result = mapper.convertValue(obj, type);
} else {
result = mapper.convertValue(new RawExtension(obj), type);
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);
Expand All @@ -271,6 +294,16 @@ private static <T> T unmarshal(InputStream is, ObjectMapper mapper, TypeReferenc
}
}

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}
* <p>
Expand Down Expand Up @@ -452,4 +485,12 @@ public void addImplicitResolver(Tag tag, Pattern regexp, String first, int limit
super.addImplicitResolver(tag, regexp, first, limit);
}
}

public static <T> T convertValue(Object value, Class<T> type) {
return JSON_MAPPER.convertValue(value, type);
}

public static Type constructParametricType(Class<?> parameterizedClass, Class<?> parameterType) {
return JSON_MAPPER.getTypeFactory().constructParametricType(parameterizedClass, parameterType);
}
}
Expand Up @@ -72,7 +72,6 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.junit.jupiter.api.Assertions.assertEquals;

class SerializationTest {
Expand Down Expand Up @@ -253,8 +252,10 @@ void unmarshalWithInvalidYamlShouldReturnRawExtension() {

@Test
void unmarshalYamlArrayShouldThrowException() {
assertThatIllegalArgumentException()
assertThatExceptionOfType(KubernetesClientException.class)
.isThrownBy(() -> Serialization.unmarshal("- 1\n- 2"))
.withMessage("Could not convert from yaml to requested type")
.havingCause()
.withMessageStartingWith("Cannot parse a nested array containing non-object resource");
}

Expand Down
Expand Up @@ -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.jsonMapper().convertValue(resource, baseOperation.getType());
resource = Serialization.convertValue(resource, baseOperation.getType());
}
@SuppressWarnings("unchecked")
final T t = (T) resource;
Expand Down Expand Up @@ -234,14 +234,14 @@ private WatchEvent contextAwareWatchEventDeserializer(String messageSource)
try {
return Serialization.unmarshal(messageSource, WatchEvent.class);
} catch (Exception ex1) {
JsonNode json = Serialization.jsonMapper().readTree(messageSource);
JsonNode json = Serialization.unmarshal(messageSource, JsonNode.class);
JsonNode objectJson = null;
if (json instanceof ObjectNode && json.has("object")) {
objectJson = ((ObjectNode) json).remove("object");
}

WatchEvent watchEvent = Serialization.jsonMapper().treeToValue(json, WatchEvent.class);
KubernetesResource object = Serialization.jsonMapper().treeToValue(objectJson, baseOperation.getType());
WatchEvent watchEvent = Serialization.convertValue(json, WatchEvent.class);
KubernetesResource object = Serialization.convertValue(objectJson, baseOperation.getType());

watchEvent.setObject(object);
return watchEvent;
Expand Down
Expand Up @@ -249,7 +249,7 @@ public BaseOperation<T, L, R> inAnyNamespace() {

@Override
public R load(InputStream is) {
T unmarshal = unmarshal(is, type);
T unmarshal = Serialization.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
Expand Down Expand Up @@ -394,7 +394,7 @@ public CompletableFuture<L> submitList(ListOptions listOptions) {
URL fetchListUrl = fetchListUrl(getNamespacedUrl(), defaultListOptions(listOptions, null));
HttpRequest.Builder requestBuilder = httpClient.newHttpRequestBuilder().url(fetchListUrl);
Type refinedType = listType.equals(DefaultKubernetesResourceList.class)
? Serialization.jsonMapper().getTypeFactory().constructParametricType(listType, type)
? Serialization.constructParametricType(listType, type)
: listType;
TypeReference<L> listTypeReference = new TypeReference<L>() {
@Override
Expand Down Expand Up @@ -740,7 +740,7 @@ public <X> 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, JSON_MAPPER.writeValueAsString(payload));
requestBuilder.method(method, JSON, Serialization.asJson(payload));
}
return handleResponse(requestBuilder, responseType);
} catch (IOException e) {
Expand Down
Expand Up @@ -16,7 +16,6 @@
package io.fabric8.kubernetes.client.dsl.internal;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.fabric8.kubernetes.api.model.DeleteOptions;
import io.fabric8.kubernetes.api.model.DeletionPropagation;
import io.fabric8.kubernetes.api.model.HasMetadata;
Expand Down Expand Up @@ -44,7 +43,6 @@

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
Expand All @@ -53,7 +51,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
Expand All @@ -67,7 +64,6 @@ public class OperationSupport {
public static final String STRATEGIC_MERGE_JSON_PATCH = "application/strategic-merge-patch+json";
public static final String JSON_MERGE_PATCH = "application/merge-patch+json";

protected static final ObjectMapper JSON_MAPPER = Serialization.jsonMapper();
private static final Logger LOG = LoggerFactory.getLogger(OperationSupport.class);
private static final String CLIENT_STATUS_FLAG = "CLIENT_STATUS_FLAG";
private static final int MAX_RETRY_INTERVAL_EXPONENT = 5;
Expand Down Expand Up @@ -322,7 +318,7 @@ protected KubernetesResource handleDelete(URL requestUrl, long gracePeriodSecond
}

HttpRequest.Builder requestBuilder = httpClient.newHttpRequestBuilder()
.delete(JSON, JSON_MAPPER.writeValueAsString(deleteOptions)).url(requestUrl);
.delete(JSON, Serialization.asJson(deleteOptions)).url(requestUrl);

return handleResponse(requestBuilder, KubernetesResource.class);
}
Expand All @@ -342,7 +338,7 @@ protected KubernetesResource handleDelete(URL requestUrl, long gracePeriodSecond
protected <T, I> T handleCreate(I resource, Class<T> outputType) throws InterruptedException, IOException {
resource = correctNamespace(resource);
HttpRequest.Builder requestBuilder = httpClient.newHttpRequestBuilder()
.post(JSON, JSON_MAPPER.writeValueAsString(resource))
.post(JSON, Serialization.asJson(resource))
.url(getResourceURLForWriteOperation(getResourceUrl(checkNamespace(resource), null)));
return handleResponse(requestBuilder, outputType);
}
Expand All @@ -361,7 +357,7 @@ protected <T, I> T handleCreate(I resource, Class<T> outputType) throws Interrup
protected <T> T handleUpdate(T updated, Class<T> type, boolean status) throws IOException {
updated = correctNamespace(updated);
HttpRequest.Builder requestBuilder = httpClient.newHttpRequestBuilder()
.put(JSON, JSON_MAPPER.writeValueAsString(updated))
.put(JSON, Serialization.asJson(updated))
.url(getResourceURLForWriteOperation(getResourceUrl(checkNamespace(updated), checkName(updated), status)));
return handleResponse(requestBuilder, type);
}
Expand Down Expand Up @@ -451,7 +447,7 @@ protected <T> T handleGet(URL resourceUrl, Class<T> type) throws IOException {
protected <T extends HasMetadata> T handleApproveOrDeny(T csr, Class<T> type) throws IOException, InterruptedException {
String uri = URLUtils.join(getResourceUrl(null, csr.getMetadata().getName(), false).toString(), "approval");
HttpRequest.Builder requestBuilder = httpClient.newHttpRequestBuilder()
.put(JSON, JSON_MAPPER.writeValueAsString(csr)).uri(uri);
.put(JSON, Serialization.asJson(csr)).uri(uri);
return handleResponse(requestBuilder, type);
}

Expand Down Expand Up @@ -637,13 +633,13 @@ public static Status createStatus(HttpResponse<?> response) {
try {
String bodyString = response.bodyString();
if (Utils.isNotNullOrEmpty(bodyString)) {
Status status = JSON_MAPPER.readValue(bodyString, Status.class);
Status status = Serialization.unmarshal(bodyString, Status.class);
if (status.getCode() == null) {
status = new StatusBuilder(status).withCode(statusCode).build();
}
return status;
}
} catch (IOException e) {
} catch (IOException | KubernetesClientException e) {
// ignored
}
if (response.message() != null) {
Expand Down Expand Up @@ -703,23 +699,6 @@ public static KubernetesClientException requestException(HttpRequest request, Ex
return requestException(request, e, null);
}

protected static <T> T unmarshal(InputStream is) {
return Serialization.unmarshal(is);
}

protected static <T> T unmarshal(InputStream is, final Class<T> type) {
return Serialization.unmarshal(is, type);
}

protected static <T> T unmarshal(InputStream is, TypeReference<T> type) {
return Serialization.unmarshal(is, type);
}

protected static <T> Map<String, Object> getObjectValueAsMap(T object) {
return JSON_MAPPER.convertValue(object, new TypeReference<Map<String, Object>>() {
});
}

public Config getConfig() {
return config;
}
Expand Down

0 comments on commit d8c7a84

Please sign in to comment.