Skip to content

Commit 851621a

Browse files
committed
fix #3972: refining the client to not use static deserialization logic
1 parent 90d8acc commit 851621a

File tree

55 files changed

+785
-356
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+785
-356
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@
126126
* Fix #4579: the implicit registration of resource and list types that happens when using the resource(class) methods has been removed. This makes the behavior of the client more predictable as that was an undocumented side-effect. If you expect to see instances of a custom type from an untyped api call - typically KubernetesClient.load, KubernetesClient.resourceList, KubernetesClient.resource(InputStream|String), then you must either create a META-INF/services/io.fabric8.kubernetes.api.model.KubernetesResource file (see above #3923), or make calls to KubernetesDeserializer.registerCustomKind - however since KubernetesDeserializer is an internal class that mechanism is not preferred.
127127
* 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`
128128
* Fix #4363: deprecated existing ResourceCompare methods such as compareKubernetesResource as they are not for general use
129+
* Fix #3973: deprecated Serialization methods that take parameters and methods for the json and yaml mappers.
129130

130131
### 6.2.0 (2022-10-20)
131132

kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/DefaultKubernetesClient.java

-11
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@
2121
import io.fabric8.kubernetes.client.http.HttpClient.Factory;
2222
import io.fabric8.kubernetes.client.http.StandardHttpClientBuilder;
2323
import io.fabric8.kubernetes.client.utils.HttpClientUtils;
24-
import io.fabric8.kubernetes.client.utils.Serialization;
25-
26-
import java.io.InputStream;
2724

2825
/**
2926
* Class for Default Kubernetes Client implementing KubernetesClient interface.
@@ -36,14 +33,6 @@ public class DefaultKubernetesClient extends NamespacedKubernetesClientAdapter<N
3633

3734
public static final String KUBERNETES_VERSION_ENDPOINT = "version";
3835

39-
public static DefaultKubernetesClient fromConfig(String config) {
40-
return new DefaultKubernetesClient(Serialization.unmarshal(config, Config.class));
41-
}
42-
43-
public static DefaultKubernetesClient fromConfig(InputStream is) {
44-
return new DefaultKubernetesClient(Serialization.unmarshal(is, Config.class));
45-
}
46-
4736
public DefaultKubernetesClient() {
4837
this(new ConfigBuilder().build());
4938
}

kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/KubernetesClient.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@
7777
import io.fabric8.kubernetes.client.dsl.NamespaceableResource;
7878
import io.fabric8.kubernetes.client.dsl.NetworkAPIGroupDSL;
7979
import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
80-
import io.fabric8.kubernetes.client.dsl.ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable;
8180
import io.fabric8.kubernetes.client.dsl.PodResource;
8281
import io.fabric8.kubernetes.client.dsl.PolicyAPIGroupDSL;
8382
import io.fabric8.kubernetes.client.dsl.RbacAPIGroupDSL;
@@ -300,15 +299,15 @@ MixedOperation<GenericKubernetesResource, GenericKubernetesResourceList, Resourc
300299
* @param is the input stream containing JSON/YAML content
301300
* @return an operation instance to work on the list of Kubernetes Resource objects
302301
*/
303-
ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable<HasMetadata> load(InputStream is);
302+
NamespaceListVisitFromServerGetDeleteRecreateWaitApplicable<HasMetadata> load(InputStream is);
304303

305304
/**
306305
* Load a Kubernetes list object
307306
*
308307
* @param s kubernetes list as string
309308
* @return an operation instance to work on the deserialized KubernetesList objects
310309
*/
311-
ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable<HasMetadata> resourceList(String s);
310+
NamespaceListVisitFromServerGetDeleteRecreateWaitApplicable<HasMetadata> resourceList(String s);
312311

313312
/**
314313
* KubernetesResourceList operations

kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/KubernetesClientBuilder.java

+10-3
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616

1717
package io.fabric8.kubernetes.client;
1818

19+
import com.fasterxml.jackson.databind.ObjectMapper;
1920
import io.fabric8.kubernetes.client.http.HttpClient;
2021
import io.fabric8.kubernetes.client.informers.ResourceEventHandler;
2122
import io.fabric8.kubernetes.client.utils.HttpClientUtils;
22-
import io.fabric8.kubernetes.client.utils.Serialization;
23+
import io.fabric8.kubernetes.client.utils.KubernetesSerialization;
2324

2425
import java.io.InputStream;
2526
import java.lang.reflect.InvocationTargetException;
@@ -47,6 +48,7 @@ default void onClose(Executor executor) {
4748
private Class<KubernetesClient> clazz;
4849
private ExecutorSupplier executorSupplier;
4950
private Consumer<HttpClient.Builder> builderConsumer;
51+
private KubernetesSerialization kubernetesSerialization = new KubernetesSerialization(new ObjectMapper());
5052

5153
public KubernetesClientBuilder() {
5254
// basically the same logic as in KubernetesResourceUtil for finding list types
@@ -96,13 +98,18 @@ public KubernetesClientBuilder withConfig(Config config) {
9698
return this;
9799
}
98100

101+
public KubernetesClientBuilder withKubernetesSerialization(KubernetesSerialization kubernetesSerialization) {
102+
this.kubernetesSerialization = kubernetesSerialization;
103+
return this;
104+
}
105+
99106
public KubernetesClientBuilder withConfig(String config) {
100-
this.config = Serialization.unmarshal(config, Config.class);
107+
this.config = kubernetesSerialization.unmarshal(config, Config.class);
101108
return this;
102109
}
103110

104111
public KubernetesClientBuilder withConfig(InputStream config) {
105-
this.config = Serialization.unmarshal(config, Config.class);
112+
this.config = kubernetesSerialization.unmarshal(config, Config.class);
106113
return this;
107114
}
108115

kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/NamespacedKubernetesClientAdapter.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@
7878
import io.fabric8.kubernetes.client.dsl.NamespaceableResource;
7979
import io.fabric8.kubernetes.client.dsl.NetworkAPIGroupDSL;
8080
import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
81-
import io.fabric8.kubernetes.client.dsl.ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable;
8281
import io.fabric8.kubernetes.client.dsl.PodResource;
8382
import io.fabric8.kubernetes.client.dsl.PolicyAPIGroupDSL;
8483
import io.fabric8.kubernetes.client.dsl.RbacAPIGroupDSL;
@@ -255,12 +254,12 @@ public NonNamespaceOperation<ComponentStatus, ComponentStatusList, Resource<Comp
255254
}
256255

257256
@Override
258-
public ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable<HasMetadata> load(InputStream is) {
257+
public NamespaceListVisitFromServerGetDeleteRecreateWaitApplicable<HasMetadata> load(InputStream is) {
259258
return getClient().load(is);
260259
}
261260

262261
@Override
263-
public ParameterNamespaceListVisitFromServerGetDeleteRecreateWaitApplicable<HasMetadata> resourceList(String s) {
262+
public NamespaceListVisitFromServerGetDeleteRecreateWaitApplicable<HasMetadata> resourceList(String s) {
264263
return getClient().resourceList(s);
265264
}
266265

kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/extended/leaderelection/resourcelock/ConfigMapLock.java

+9-14
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,11 @@
1515
*/
1616
package io.fabric8.kubernetes.client.extended.leaderelection.resourcelock;
1717

18-
import com.fasterxml.jackson.core.JsonProcessingException;
19-
import com.fasterxml.jackson.core.type.TypeReference;
20-
import com.fasterxml.jackson.databind.ObjectMapper;
2118
import io.fabric8.kubernetes.api.model.ConfigMap;
2219
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
2320
import io.fabric8.kubernetes.api.model.ObjectMeta;
2421
import io.fabric8.kubernetes.client.KubernetesClient;
22+
import io.fabric8.kubernetes.client.KubernetesClientException;
2523
import io.fabric8.kubernetes.client.utils.Serialization;
2624
import org.slf4j.Logger;
2725
import org.slf4j.LoggerFactory;
@@ -36,13 +34,11 @@ public class ConfigMapLock implements Lock {
3634
private final String configMapNamespace;
3735
private final String configMapName;
3836
private final String identity;
39-
private final ObjectMapper objectMapper;
4037

4138
public ConfigMapLock(String configMapNamespace, String configMapName, String identity) {
4239
this.configMapNamespace = Objects.requireNonNull(configMapNamespace, "configMapNamespace is required");
4340
this.configMapName = Objects.requireNonNull(configMapName, "configMapName is required");
4441
this.identity = Objects.requireNonNull(identity, "identity is required");
45-
objectMapper = Serialization.jsonMapper();
4642
}
4743

4844
/**
@@ -58,9 +54,8 @@ public LeaderElectionRecord get(KubernetesClient client) {
5854
.map(annotations -> annotations.get(LEADER_ELECTION_RECORD_ANNOTATION_KEY))
5955
.map(annotation -> {
6056
try {
61-
return objectMapper.readValue(annotation, new TypeReference<LeaderElectionRecord>() {
62-
});
63-
} catch (JsonProcessingException ex) {
57+
return Serialization.unmarshal(annotation, LeaderElectionRecord.class);
58+
} catch (KubernetesClientException ex) {
6459
LOGGER.error("Error deserializing LeaderElectionRecord from ConfigMap", ex);
6560
return null;
6661
}
@@ -80,11 +75,11 @@ public void create(
8075
KubernetesClient client, LeaderElectionRecord leaderElectionRecord) throws LockException {
8176

8277
try {
83-
client.configMaps().inNamespace(configMapNamespace).withName(configMapName).create(new ConfigMapBuilder()
78+
client.configMaps().inNamespace(configMapNamespace).resource(new ConfigMapBuilder()
8479
.editOrNewMetadata().withNamespace(configMapNamespace).withName(configMapName)
85-
.addToAnnotations(LEADER_ELECTION_RECORD_ANNOTATION_KEY, objectMapper.writeValueAsString(leaderElectionRecord))
80+
.addToAnnotations(LEADER_ELECTION_RECORD_ANNOTATION_KEY, Serialization.asJson(leaderElectionRecord))
8681
.endMetadata()
87-
.build());
82+
.build()).create();
8883
} catch (Exception e) {
8984
throw new LockException("Unable to create ConfigMapLock", e);
9085
}
@@ -100,11 +95,11 @@ public void update(
10095
try {
10196
final ConfigMap toReplace = client.configMaps().inNamespace(configMapNamespace).withName(configMapName).get();
10297
toReplace.getMetadata().getAnnotations()
103-
.put(LEADER_ELECTION_RECORD_ANNOTATION_KEY, objectMapper.writeValueAsString(leaderElectionRecord));
98+
.put(LEADER_ELECTION_RECORD_ANNOTATION_KEY, Serialization.asJson(leaderElectionRecord));
10499
// Use replace instead of edit to avoid concurrent modifications, resourceVersion is locked to original record version
105-
client.configMaps().inNamespace(configMapNamespace).withName(configMapName)
100+
client.configMaps().inNamespace(configMapNamespace).resource(toReplace)
106101
.lockResourceVersion((String) Objects.requireNonNull(leaderElectionRecord.getVersion()))
107-
.replace(toReplace);
102+
.replace();
108103
} catch (Exception e) {
109104
throw new LockException("Unable to update ConfigMapLock", e);
110105
}

kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/informers/cache/ReducedStateItemStore.java

+7-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import io.fabric8.kubernetes.api.model.GenericKubernetesResource;
2020
import io.fabric8.kubernetes.api.model.HasMetadata;
21+
import io.fabric8.kubernetes.client.utils.KubernetesSerialization;
2122
import io.fabric8.kubernetes.client.utils.Serialization;
2223

2324
import java.util.ArrayList;
@@ -42,6 +43,7 @@ public class ReducedStateItemStore<V extends HasMetadata> implements ItemStore<V
4243
private final List<String[]> fields = new ArrayList<>();
4344
private final Class<V> typeClass;
4445
private final KeyState keyState;
46+
private KubernetesSerialization serialization = Serialization.getKubernetesSerialization();
4547

4648
public static class KeyState {
4749

@@ -101,7 +103,8 @@ public KeyState(Function<HasMetadata, String> keyFunction, Function<String, Stri
101103
* @param typeClass the expected type
102104
* @param valueFields the additional fields to save
103105
*/
104-
public ReducedStateItemStore(KeyState keyState, Class<V> typeClass, String... valueFields) {
106+
public ReducedStateItemStore(KeyState keyState, Class<V> typeClass,
107+
String... valueFields) {
105108
this.keyState = keyState;
106109
fields.add(new String[] { METADATA, "resourceVersion" });
107110
if (valueFields != null) {
@@ -110,13 +113,14 @@ public ReducedStateItemStore(KeyState keyState, Class<V> typeClass, String... va
110113
}
111114
}
112115
this.typeClass = typeClass;
116+
this.serialization = serialization;
113117
}
114118

115119
Object[] store(V value) {
116120
if (value == null) {
117121
return null;
118122
}
119-
Map<String, Object> raw = Serialization.jsonMapper().convertValue(value, Map.class);
123+
Map<String, Object> raw = serialization.convertValue(value, Map.class);
120124
return fields.stream().map(f -> GenericKubernetesResource.get(raw, (Object[]) f)).toArray();
121125
}
122126

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

132-
return Serialization.jsonMapper().convertValue(raw, typeClass);
136+
return serialization.convertValue(raw, typeClass);
133137
}
134138

135139
private static void applyFields(Object[] values, Map<String, Object> raw, List<String[]> fields) {

kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/internal/KubeConfigUtils.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616
package io.fabric8.kubernetes.client.internal;
1717

18-
import com.fasterxml.jackson.databind.ObjectMapper;
1918
import io.fabric8.kubernetes.api.model.AuthInfo;
2019
import io.fabric8.kubernetes.api.model.Cluster;
2120
import io.fabric8.kubernetes.api.model.Config;
@@ -26,6 +25,8 @@
2625
import io.fabric8.kubernetes.client.utils.Serialization;
2726

2827
import java.io.File;
28+
import java.io.FileInputStream;
29+
import java.io.FileWriter;
2930
import java.io.IOException;
3031
import java.util.List;
3132

@@ -39,13 +40,11 @@ private KubeConfigUtils() {
3940
}
4041

4142
public static Config parseConfig(File file) throws IOException {
42-
ObjectMapper mapper = Serialization.yamlMapper();
43-
return mapper.readValue(file, Config.class);
43+
return Serialization.unmarshal(new FileInputStream(file), Config.class);
4444
}
4545

4646
public static Config parseConfigFromString(String contents) throws IOException {
47-
ObjectMapper mapper = Serialization.yamlMapper();
48-
return mapper.readValue(contents, Config.class);
47+
return Serialization.unmarshal(contents, Config.class);
4948
}
5049

5150
/**
@@ -158,6 +157,8 @@ public static int getNamedUserIndexFromConfig(Config config, String userName) {
158157
* @throws IOException in case of failure while writing to file
159158
*/
160159
public static void persistKubeConfigIntoFile(Config kubeConfig, String kubeConfigPath) throws IOException {
161-
Serialization.yamlMapper().writeValue(new File(kubeConfigPath), kubeConfig);
160+
try (FileWriter writer = new FileWriter(kubeConfigPath)) {
161+
writer.write(Serialization.asYaml(kubeConfig));
162+
}
162163
}
163164
}

kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/IOHelpers.java

+9-8
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ private static void copy(Reader reader, Writer writer) throws IOException {
6464
}
6565
}
6666

67+
/**
68+
* @deprecated to be removed in future versions
69+
*/
70+
@Deprecated
6771
public static boolean isJSONValid(String json) {
6872
try {
6973
ObjectMapper objectMapper = Serialization.jsonMapper();
@@ -74,18 +78,15 @@ public static boolean isJSONValid(String json) {
7478
return true;
7579
}
7680

81+
/**
82+
* @deprecated to be removed in future versions
83+
*/
84+
@Deprecated
7785
public static String convertYamlToJson(String yaml) throws IOException {
78-
ObjectMapper yamlReader = Serialization.yamlMapper();
79-
Object obj = yamlReader.readValue(yaml, Object.class);
80-
81-
ObjectMapper jsonWriter = Serialization.jsonMapper();
82-
return jsonWriter.writeValueAsString(obj);
86+
return Serialization.asJson(Serialization.unmarshal(yaml, Object.class));
8387
}
8488

8589
public static String convertToJson(String jsonOrYaml) throws IOException {
86-
if (isJSONValid(jsonOrYaml)) {
87-
return jsonOrYaml;
88-
}
8990
return convertYamlToJson(jsonOrYaml);
9091
}
9192

kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/utils/KubernetesResourceUtil.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ public static List<EnvVar> convertMapToEnvVarList(Map<String, String> envVarMap)
383383
* Check whether a Kubernetes resource is Ready or not. Applicable only to
384384
* Deployment, ReplicaSet, Pod, ReplicationController, Endpoints, Node and
385385
* StatefulSet
386-
*
386+
*
387387
* @param item item which needs to be checked
388388
* @return boolean value indicating it's status
389389
*/
@@ -393,7 +393,7 @@ public static boolean isResourceReady(HasMetadata item) {
393393

394394
/**
395395
* Calculates age of a kubernetes resource
396-
*
396+
*
397397
* @param kubernetesResource
398398
* @return a positive duration indicating age of the kubernetes resource
399399
*/
@@ -435,7 +435,7 @@ private static Class<?> loadRelated(Class<?> type, String suffix, Class<?> defau
435435
public static Secret createDockerRegistrySecret(String dockerServer, String username, String password)
436436
throws JsonProcessingException {
437437
Map<String, Object> dockerConfigMap = createDockerRegistryConfigMap(dockerServer, username, password);
438-
String dockerConfigAsStr = Serialization.jsonMapper().writeValueAsString(dockerConfigMap);
438+
String dockerConfigAsStr = Serialization.asJson(dockerConfigMap);
439439

440440
return createDockerSecret(DEFAULT_CONTAINER_IMAGE_REGISTRY_SECRET_NAME, dockerConfigAsStr);
441441
}
@@ -452,7 +452,7 @@ public static Secret createDockerRegistrySecret(String dockerServer, String user
452452
public static Secret createDockerRegistrySecret(String dockerServer, String username, String password, String secretName)
453453
throws JsonProcessingException {
454454
Map<String, Object> dockerConfigMap = createDockerRegistryConfigMap(dockerServer, username, password);
455-
String dockerConfigAsStr = Serialization.jsonMapper().writeValueAsString(dockerConfigMap);
455+
String dockerConfigAsStr = Serialization.asJson(dockerConfigMap);
456456

457457
return createDockerSecret(secretName, dockerConfigAsStr);
458458
}

0 commit comments

Comments
 (0)