From 250638ee3c2b6e248626da19f4bd525fb68c54fd Mon Sep 17 00:00:00 2001 From: Rohan Kumar Date: Wed, 17 Jul 2024 17:49:56 +0530 Subject: [PATCH 1/2] fix (kubernetes-model-generator) : Handle deserialization of `defaultMode` field in custom deserializers for VolumeSource types Add custom deserializers to handle correct octal deserialization for these types: - ConfigMapVolumeSource - SecretVolumeSource - DownwardAPIVolumeSource - ProjectedVolumeSource Signed-off-by: Rohan Kumar --- CHANGELOG.md | 1 + .../client/utils/SerializationTest.java | 35 +++++++++++ .../resources/serialization/cronjob-octal.yml | 44 ++++++++++++++ .../jackson/IntegerOctalHandlerUtil.java | 39 ++++++++++++ .../jackson/IntegerOctalHandlerUtilTest.java | 44 ++++++++++++++ .../cmd/generate/generate.go | 12 ++++ .../api/model/ConfigMapVolumeSource.java | 2 +- .../api/model/DownwardAPIVolumeSource.java | 2 +- .../api/model/ProjectedVolumeSource.java | 2 +- .../api/model/SecretVolumeSource.java | 2 +- .../ConfigMapVolumeSourceDeserializer.java | 60 +++++++++++++++++++ .../DownwardAPIVolumeSourceDeserializer.java | 55 +++++++++++++++++ .../ProjectedVolumeSourceDeserializer.java | 44 ++++++++++++++ .../model/SecretVolumeSourceDeserializer.java | 60 +++++++++++++++++++ .../main/resources/schema/kube-schema.json | 12 ++-- .../resources/schema/validation-schema.json | 12 ++-- .../api/model/ConfigMapVolumeSourceTest.java | 49 +++++++++++++++ .../model/DownwardAPIVolumeSourceTest.java | 48 +++++++++++++++ .../api/model/ProjectedVolumeSourceTest.java | 52 ++++++++++++++++ .../api/model/SecretVolumeSourceTest.java | 49 +++++++++++++++ .../test/resources/configmapvolumesource.json | 11 ++++ .../resources/downwardapivolumesource.json | 12 ++++ .../test/resources/projectedvolumesource.json | 16 +++++ .../test/resources/secretvolumesource.json | 11 ++++ 24 files changed, 662 insertions(+), 12 deletions(-) create mode 100644 kubernetes-client-api/src/test/resources/serialization/cronjob-octal.yml create mode 100644 kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/IntegerOctalHandlerUtil.java create mode 100644 kubernetes-model-generator/kubernetes-model-common/src/test/java/io/fabric8/kubernetes/model/jackson/IntegerOctalHandlerUtilTest.java create mode 100644 kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSourceDeserializer.java create mode 100644 kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSourceDeserializer.java create mode 100644 kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSourceDeserializer.java create mode 100644 kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/SecretVolumeSourceDeserializer.java create mode 100644 kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSourceTest.java create mode 100644 kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSourceTest.java create mode 100644 kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSourceTest.java create mode 100644 kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/SecretVolumeSourceTest.java create mode 100644 kubernetes-model-generator/kubernetes-model-core/src/test/resources/configmapvolumesource.json create mode 100644 kubernetes-model-generator/kubernetes-model-core/src/test/resources/downwardapivolumesource.json create mode 100644 kubernetes-model-generator/kubernetes-model-core/src/test/resources/projectedvolumesource.json create mode 100644 kubernetes-model-generator/kubernetes-model-core/src/test/resources/secretvolumesource.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dbbda1693e..6c2b2b65577 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ #### Improvements * Fix #6008: removing the optional dependency on bouncy castle * Fix #5264: Remove deprecated `Config.errorMessages` field +* Fix #6110: VolumeSource's Octal `defaultMode` notation in yaml not properly converted to json #### Dependency Upgrade * Fix #6052: Removed dependency on no longer maintained com.github.mifmif:generex diff --git a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/SerializationTest.java b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/SerializationTest.java index 206e21bdf38..c9fdf1fc287 100644 --- a/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/SerializationTest.java +++ b/kubernetes-client-api/src/test/java/io/fabric8/kubernetes/client/utils/SerializationTest.java @@ -27,7 +27,9 @@ import io.fabric8.kubernetes.api.model.AnyType; import io.fabric8.kubernetes.api.model.Config; import io.fabric8.kubernetes.api.model.ConfigMap; +import io.fabric8.kubernetes.api.model.ConfigMapVolumeSource; import io.fabric8.kubernetes.api.model.GenericKubernetesResource; +import io.fabric8.kubernetes.api.model.KeyToPath; import io.fabric8.kubernetes.api.model.KubernetesList; import io.fabric8.kubernetes.api.model.KubernetesResource; import io.fabric8.kubernetes.api.model.Namespace; @@ -35,12 +37,18 @@ import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.PodBuilder; import io.fabric8.kubernetes.api.model.PodSpec; +import io.fabric8.kubernetes.api.model.PodTemplateSpec; import io.fabric8.kubernetes.api.model.Quantity; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.Toleration; +import io.fabric8.kubernetes.api.model.Volume; import io.fabric8.kubernetes.api.model.apiextensions.v1beta1.CustomResourceDefinition; import io.fabric8.kubernetes.api.model.apiextensions.v1beta1.JSONSchemaProps; import io.fabric8.kubernetes.api.model.apps.Deployment; +import io.fabric8.kubernetes.api.model.batch.v1.CronJob; +import io.fabric8.kubernetes.api.model.batch.v1.CronJobSpec; +import io.fabric8.kubernetes.api.model.batch.v1.JobSpec; +import io.fabric8.kubernetes.api.model.batch.v1.JobTemplateSpec; import io.fabric8.kubernetes.api.model.coordination.v1.Lease; import io.fabric8.kubernetes.api.model.coordination.v1.LeaseSpec; import io.fabric8.kubernetes.api.model.runtime.RawExtension; @@ -310,6 +318,33 @@ void unmarshalWithValidListShouldReturnKubernetesList() { new Tuple(Pod.class, "v1", "Pod", "a-pod")); } + @Test + @DisplayName("unmarshal, when integer value has octal literal value, then octal literal value correctly parsed") + void unmarshal_whenIntegerValueHasOctalLiteralValue_thenCorrectlyDeserializeInteger() { + // When + final CronJob cronJob = Serialization.unmarshal(getClass().getResourceAsStream("/serialization/cronjob-octal.yml"), + CronJob.class); + // Then + assertThat(cronJob) + .extracting(CronJob::getSpec) + .extracting(CronJobSpec::getJobTemplate) + .extracting(JobTemplateSpec::getSpec) + .extracting(JobSpec::getTemplate) + .extracting(PodTemplateSpec::getSpec) + .extracting(PodSpec::getVolumes) + .asInstanceOf(InstanceOfAssertFactories.list(Volume.class)) + .singleElement() + .extracting(Volume::getConfigMap) + .hasFieldOrPropertyWithValue("defaultMode", Integer.valueOf("0555", 8)) + .hasFieldOrPropertyWithValue("name", "conf") + .extracting(ConfigMapVolumeSource::getItems) + .asInstanceOf(InstanceOfAssertFactories.list(KeyToPath.class)) + .singleElement() + .hasFieldOrPropertyWithValue("key", "key1") + .hasFieldOrPropertyWithValue("path", "target") + .hasFieldOrPropertyWithValue("mode", Integer.valueOf("0555", 8)); + } + @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type") @JsonSubTypes(@JsonSubTypes.Type(value = Typed.class, name = "x")) public interface Typeable { diff --git a/kubernetes-client-api/src/test/resources/serialization/cronjob-octal.yml b/kubernetes-client-api/src/test/resources/serialization/cronjob-octal.yml new file mode 100644 index 00000000000..21927d77e15 --- /dev/null +++ b/kubernetes-client-api/src/test/resources/serialization/cronjob-octal.yml @@ -0,0 +1,44 @@ +# +# 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. +# + +apiVersion: batch/v1beta1 +kind: CronJob +metadata: + name: update-db +spec: + schedule: "*/1 * * * *" + jobTemplate: + spec: + template: + spec: + containers: + - name: update-fingerprints + image: python:3.6.2-slim + command: ["/bin/bash"] + args: ["-c", "python /client/test.py"] + volumeMounts: + - name: application-code + mountPath: /where/ever + restartPolicy: OnFailure + volumes: + - name: application-code + configMap: + name: conf + defaultMode: 0555 + items: + - key: key1 + path: target + mode: 0555 diff --git a/kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/IntegerOctalHandlerUtil.java b/kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/IntegerOctalHandlerUtil.java new file mode 100644 index 00000000000..29dd6b17fa1 --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/IntegerOctalHandlerUtil.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fabric8.kubernetes.model.jackson; + +import com.fasterxml.jackson.databind.JsonNode; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class IntegerOctalHandlerUtil { + private static final Pattern OCTAL_NUMBER = Pattern.compile("(0[oO]?)[0-7]+"); + + private IntegerOctalHandlerUtil() { + } + + public static Integer createIntegerValue(JsonNode node) { + String textValue = node.textValue(); + if (textValue != null) { + Matcher octalNumberMatcher = OCTAL_NUMBER.matcher(textValue); + if (octalNumberMatcher.matches()) { + return Integer.valueOf(textValue.substring(octalNumberMatcher.group(1).length()), 8); + } + } + return node.intValue(); + } +} diff --git a/kubernetes-model-generator/kubernetes-model-common/src/test/java/io/fabric8/kubernetes/model/jackson/IntegerOctalHandlerUtilTest.java b/kubernetes-model-generator/kubernetes-model-common/src/test/java/io/fabric8/kubernetes/model/jackson/IntegerOctalHandlerUtilTest.java new file mode 100644 index 00000000000..6fb1d7373bd --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-common/src/test/java/io/fabric8/kubernetes/model/jackson/IntegerOctalHandlerUtilTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fabric8.kubernetes.model.jackson; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +class IntegerOctalHandlerUtilTest { + private final ObjectMapper objectMapper = new ObjectMapper(); + + private static Stream shouldParseOctalNumbersCorrectly() { + return Stream.of( + Arguments.of("\"012\"", Integer.valueOf("012", 8)), + Arguments.of("\"0o12\"", Integer.valueOf("012", 8)), + Arguments.of("\"0O12\"", Integer.valueOf("012", 8))); + } + + @ParameterizedTest + @MethodSource + void shouldParseOctalNumbersCorrectly(String input, Integer expectedValue) throws JsonProcessingException { + assertThat(IntegerOctalHandlerUtil.createIntegerValue(objectMapper.readTree(input))) + .isEqualTo(expectedValue); + } +} diff --git a/kubernetes-model-generator/kubernetes-model-core/cmd/generate/generate.go b/kubernetes-model-generator/kubernetes-model-core/cmd/generate/generate.go index 80b6baee55f..69e4d7a6af8 100644 --- a/kubernetes-model-generator/kubernetes-model-core/cmd/generate/generate.go +++ b/kubernetes-model-generator/kubernetes-model-core/cmd/generate/generate.go @@ -152,6 +152,18 @@ func main() { Serializer: "io.fabric8.kubernetes.api.model.MicroTimeSerDes.Serializer.class", Deserializer: "io.fabric8.kubernetes.api.model.MicroTimeSerDes.Deserializer.class", }, + "kubernetes_core_ConfigMapVolumeSource": &schemagen.JavaSerDeDescriptor{ + Deserializer: "io.fabric8.kubernetes.api.model.ConfigMapVolumeSourceDeserializer.class", + }, + "kubernetes_core_SecretVolumeSource": &schemagen.JavaSerDeDescriptor{ + Deserializer: "io.fabric8.kubernetes.api.model.SecretVolumeSourceDeserializer.class", + }, + "kubernetes_core_DownwardAPIVolumeSource": &schemagen.JavaSerDeDescriptor{ + Deserializer: "io.fabric8.kubernetes.api.model.DownwardAPIVolumeSourceDeserializer.class", + }, + "kubernetes_core_ProjectedVolumeSource": &schemagen.JavaSerDeDescriptor{ + Deserializer: "io.fabric8.kubernetes.api.model.ProjectedVolumeSourceDeserializer.class", + }, } for definitionKey, descriptor := range serdes { diff --git a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSource.java b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSource.java index d24b9065776..64f3b25230f 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSource.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSource.java @@ -19,7 +19,7 @@ import lombok.ToString; import lombok.experimental.Accessors; -@JsonDeserialize(using = com.fasterxml.jackson.databind.JsonDeserializer.None.class) +@JsonDeserialize(using = io.fabric8.kubernetes.api.model.ConfigMapVolumeSourceDeserializer.class) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "defaultMode", diff --git a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSource.java b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSource.java index 6fadacbdb71..bfb4369674e 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSource.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSource.java @@ -19,7 +19,7 @@ import lombok.ToString; import lombok.experimental.Accessors; -@JsonDeserialize(using = com.fasterxml.jackson.databind.JsonDeserializer.None.class) +@JsonDeserialize(using = io.fabric8.kubernetes.api.model.DownwardAPIVolumeSourceDeserializer.class) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "defaultMode", diff --git a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSource.java b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSource.java index 1fa31c7e860..f74ea0d947f 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSource.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSource.java @@ -19,7 +19,7 @@ import lombok.ToString; import lombok.experimental.Accessors; -@JsonDeserialize(using = com.fasterxml.jackson.databind.JsonDeserializer.None.class) +@JsonDeserialize(using = io.fabric8.kubernetes.api.model.ProjectedVolumeSourceDeserializer.class) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "defaultMode", diff --git a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/SecretVolumeSource.java b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/SecretVolumeSource.java index 14c1ddc75f4..62e4d88fbfa 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/SecretVolumeSource.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/SecretVolumeSource.java @@ -19,7 +19,7 @@ import lombok.ToString; import lombok.experimental.Accessors; -@JsonDeserialize(using = com.fasterxml.jackson.databind.JsonDeserializer.None.class) +@JsonDeserialize(using = io.fabric8.kubernetes.api.model.SecretVolumeSourceDeserializer.class) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "defaultMode", diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSourceDeserializer.java b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSourceDeserializer.java new file mode 100644 index 00000000000..7ba928e0565 --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSourceDeserializer.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fabric8.kubernetes.api.model; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; + +import java.io.IOException; + +import static io.fabric8.kubernetes.model.jackson.IntegerOctalHandlerUtil.createIntegerValue; + +public class ConfigMapVolumeSourceDeserializer extends JsonDeserializer { + + @Override + public ConfigMapVolumeSource deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) + throws IOException { + JsonNode node = jsonParser.getCodec().readTree(jsonParser); + ConfigMapVolumeSourceBuilder builder = new ConfigMapVolumeSourceBuilder(); + if (node.get("items") != null) { + for (final JsonNode keyToPathNode : node.get("items")) { + builder.addToItems(createKeyToPath(keyToPathNode, jsonParser)); + } + } + if (node.get("name") != null) { + builder.withName(node.get("name").textValue()); + } + if (node.get("optional") != null) { + builder.withOptional(node.get("optional").booleanValue()); + } + if (node.get("defaultMode") != null) { + builder.withDefaultMode(createIntegerValue(node.get("defaultMode"))); + } + return builder.build(); + } + + private KeyToPath createKeyToPath(JsonNode node, JsonParser jsonParser) throws JsonProcessingException { + KeyToPath keyToPath = jsonParser.getCodec().treeToValue(node, KeyToPath.class); + KeyToPathBuilder keyToPathBuilder = new KeyToPathBuilder(keyToPath); + if (node.get("mode") != null) { + keyToPathBuilder.withMode(createIntegerValue(node.get("mode"))); + } + return keyToPathBuilder.build(); + } +} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSourceDeserializer.java b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSourceDeserializer.java new file mode 100644 index 00000000000..f950e120d23 --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSourceDeserializer.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fabric8.kubernetes.api.model; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; + +import java.io.IOException; + +import static io.fabric8.kubernetes.model.jackson.IntegerOctalHandlerUtil.createIntegerValue; + +public class DownwardAPIVolumeSourceDeserializer extends JsonDeserializer { + + @Override + public DownwardAPIVolumeSource deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) + throws IOException { + JsonNode node = jsonParser.getCodec().readTree(jsonParser); + DownwardAPIVolumeSourceBuilder builder = new DownwardAPIVolumeSourceBuilder(); + if (node.get("items") != null) { + for (final JsonNode keyToPathNode : node.get("items")) { + builder.addToItems(createDownwardAPIVolumeFile(keyToPathNode, jsonParser)); + } + } + if (node.get("defaultMode") != null) { + builder.withDefaultMode(createIntegerValue(node.get("defaultMode"))); + } + return builder.build(); + } + + private DownwardAPIVolumeFile createDownwardAPIVolumeFile(JsonNode node, JsonParser jsonParser) + throws JsonProcessingException { + DownwardAPIVolumeFile downwardAPIVolumeFile = jsonParser.getCodec().treeToValue(node, DownwardAPIVolumeFile.class); + DownwardAPIVolumeFileBuilder downwardAPIVolumeFileBuilder = new DownwardAPIVolumeFileBuilder(downwardAPIVolumeFile); + if (node.get("mode") != null) { + downwardAPIVolumeFileBuilder.withMode(createIntegerValue(node.get("mode"))); + } + return downwardAPIVolumeFileBuilder.build(); + } +} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSourceDeserializer.java b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSourceDeserializer.java new file mode 100644 index 00000000000..9af8b0a5fcb --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSourceDeserializer.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fabric8.kubernetes.api.model; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; + +import java.io.IOException; + +import static io.fabric8.kubernetes.model.jackson.IntegerOctalHandlerUtil.createIntegerValue; + +public class ProjectedVolumeSourceDeserializer extends JsonDeserializer { + + @Override + public ProjectedVolumeSource deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) + throws IOException { + JsonNode node = jsonParser.getCodec().readTree(jsonParser); + ProjectedVolumeSourceBuilder builder = new ProjectedVolumeSourceBuilder(); + if (node.get("sources") != null) { + for (final JsonNode sourceNode : node.get("sources")) { + builder.addToSources(jsonParser.getCodec().treeToValue(sourceNode, VolumeProjection.class)); + } + } + if (node.get("defaultMode") != null) { + builder.withDefaultMode(createIntegerValue(node.get("defaultMode"))); + } + return builder.build(); + } +} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/SecretVolumeSourceDeserializer.java b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/SecretVolumeSourceDeserializer.java new file mode 100644 index 00000000000..3a130bec5fc --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/SecretVolumeSourceDeserializer.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fabric8.kubernetes.api.model; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; + +import java.io.IOException; + +import static io.fabric8.kubernetes.model.jackson.IntegerOctalHandlerUtil.createIntegerValue; + +public class SecretVolumeSourceDeserializer extends JsonDeserializer { + + @Override + public SecretVolumeSource deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) + throws IOException { + JsonNode node = jsonParser.getCodec().readTree(jsonParser); + SecretVolumeSourceBuilder builder = new SecretVolumeSourceBuilder(); + if (node.get("items") != null) { + for (final JsonNode keyToPathNode : node.get("items")) { + builder.addToItems(createKeyToPath(keyToPathNode, jsonParser)); + } + } + if (node.get("secretName") != null) { + builder.withSecretName(node.get("secretName").textValue()); + } + if (node.get("optional") != null) { + builder.withOptional(node.get("optional").booleanValue()); + } + if (node.get("defaultMode") != null) { + builder.withDefaultMode(createIntegerValue(node.get("defaultMode"))); + } + return builder.build(); + } + + private KeyToPath createKeyToPath(JsonNode node, JsonParser jsonParser) throws JsonProcessingException { + KeyToPath keyToPath = jsonParser.getCodec().treeToValue(node, KeyToPath.class); + KeyToPathBuilder keyToPathBuilder = new KeyToPathBuilder(keyToPath); + if (node.get("mode") != null) { + keyToPathBuilder.withMode(createIntegerValue(node.get("mode"))); + } + return keyToPathBuilder.build(); + } +} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/kube-schema.json b/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/kube-schema.json index 59da900f808..521c84b552e 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/kube-schema.json +++ b/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/kube-schema.json @@ -2237,7 +2237,8 @@ "javaType": "io.fabric8.kubernetes.api.model.ConfigMapVolumeSource", "javaInterfaces": [ "io.fabric8.kubernetes.api.model.KubernetesResource" - ] + ], + "deserializer": "io.fabric8.kubernetes.api.model.ConfigMapVolumeSourceDeserializer.class" }, "kubernetes_core_Container": { "type": "object", @@ -2647,7 +2648,8 @@ "javaType": "io.fabric8.kubernetes.api.model.DownwardAPIVolumeSource", "javaInterfaces": [ "io.fabric8.kubernetes.api.model.KubernetesResource" - ] + ], + "deserializer": "io.fabric8.kubernetes.api.model.DownwardAPIVolumeSourceDeserializer.class" }, "kubernetes_core_EmptyDirVolumeSource": { "type": "object", @@ -6130,7 +6132,8 @@ "javaType": "io.fabric8.kubernetes.api.model.ProjectedVolumeSource", "javaInterfaces": [ "io.fabric8.kubernetes.api.model.KubernetesResource" - ] + ], + "deserializer": "io.fabric8.kubernetes.api.model.ProjectedVolumeSourceDeserializer.class" }, "kubernetes_core_QuobyteVolumeSource": { "type": "object", @@ -6912,7 +6915,8 @@ "javaType": "io.fabric8.kubernetes.api.model.SecretVolumeSource", "javaInterfaces": [ "io.fabric8.kubernetes.api.model.KubernetesResource" - ] + ], + "deserializer": "io.fabric8.kubernetes.api.model.SecretVolumeSourceDeserializer.class" }, "kubernetes_core_SecurityContext": { "type": "object", diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/validation-schema.json b/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/validation-schema.json index 9e0a4d9c6c2..0b23998a896 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/validation-schema.json +++ b/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/validation-schema.json @@ -2237,7 +2237,8 @@ "javaType": "io.fabric8.kubernetes.api.model.ConfigMapVolumeSource", "javaInterfaces": [ "io.fabric8.kubernetes.api.model.KubernetesResource" - ] + ], + "deserializer": "io.fabric8.kubernetes.api.model.ConfigMapVolumeSourceDeserializer.class" }, "kubernetes_core_Container": { "type": "object", @@ -2647,7 +2648,8 @@ "javaType": "io.fabric8.kubernetes.api.model.DownwardAPIVolumeSource", "javaInterfaces": [ "io.fabric8.kubernetes.api.model.KubernetesResource" - ] + ], + "deserializer": "io.fabric8.kubernetes.api.model.DownwardAPIVolumeSourceDeserializer.class" }, "kubernetes_core_EmptyDirVolumeSource": { "type": "object", @@ -6130,7 +6132,8 @@ "javaType": "io.fabric8.kubernetes.api.model.ProjectedVolumeSource", "javaInterfaces": [ "io.fabric8.kubernetes.api.model.KubernetesResource" - ] + ], + "deserializer": "io.fabric8.kubernetes.api.model.ProjectedVolumeSourceDeserializer.class" }, "kubernetes_core_QuobyteVolumeSource": { "type": "object", @@ -6912,7 +6915,8 @@ "javaType": "io.fabric8.kubernetes.api.model.SecretVolumeSource", "javaInterfaces": [ "io.fabric8.kubernetes.api.model.KubernetesResource" - ] + ], + "deserializer": "io.fabric8.kubernetes.api.model.SecretVolumeSourceDeserializer.class" }, "kubernetes_core_SecurityContext": { "type": "object", diff --git a/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSourceTest.java b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSourceTest.java new file mode 100644 index 00000000000..dc0063b1f4e --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSourceTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fabric8.kubernetes.api.model; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.assertj.core.api.InstanceOfAssertFactories; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStream; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +class ConfigMapVolumeSourceTest { + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + void deserializationWithOctalValueShouldWorkAsExpected() throws IOException { + // Given + InputStream inputStream = getClass().getResourceAsStream("/configmapvolumesource.json"); + + // When + ConfigMapVolumeSource configMapVolumeSource = objectMapper.readValue(inputStream, ConfigMapVolumeSource.class); + + // Then + assertThat(configMapVolumeSource) + .hasFieldOrPropertyWithValue("defaultMode", Integer.valueOf("0555", 8)) + .hasFieldOrPropertyWithValue("name", "conf") + .extracting(ConfigMapVolumeSource::getItems) + .asInstanceOf(InstanceOfAssertFactories.list(KeyToPath.class)) + .singleElement() + .hasFieldOrPropertyWithValue("key", "key1") + .hasFieldOrPropertyWithValue("path", "target") + .hasFieldOrPropertyWithValue("mode", Integer.valueOf("0555", 8)); + } +} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSourceTest.java b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSourceTest.java new file mode 100644 index 00000000000..085a36e2acc --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSourceTest.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fabric8.kubernetes.api.model; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.assertj.core.api.InstanceOfAssertFactories; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStream; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +class DownwardAPIVolumeSourceTest { + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + void deserializationWithOctalValueShouldWorkAsExpected() throws IOException { + // Given + InputStream inputStream = getClass().getResourceAsStream("/downwardapivolumesource.json"); + + // When + DownwardAPIVolumeSource downwardAPIVolumeSource = objectMapper.readValue(inputStream, DownwardAPIVolumeSource.class); + + // Then + assertThat(downwardAPIVolumeSource) + .hasFieldOrPropertyWithValue("defaultMode", Integer.valueOf("0555", 8)) + .extracting(DownwardAPIVolumeSource::getItems) + .asInstanceOf(InstanceOfAssertFactories.list(DownwardAPIVolumeFile.class)) + .singleElement() + .hasFieldOrPropertyWithValue("path", "labels") + .hasFieldOrPropertyWithValue("fieldRef.fieldPath", "metadata.labels") + .hasFieldOrPropertyWithValue("mode", Integer.valueOf("0555", 8)); + } +} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSourceTest.java b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSourceTest.java new file mode 100644 index 00000000000..9cb419793f5 --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSourceTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fabric8.kubernetes.api.model; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.assertj.core.api.InstanceOfAssertFactories; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStream; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +class ProjectedVolumeSourceTest { + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + void deserializationWithOctalValueShouldWorkAsExpected() throws IOException { + // Given + InputStream inputStream = getClass().getResourceAsStream("/projectedvolumesource.json"); + + // When + ProjectedVolumeSource projectedVolumeSource = objectMapper.readValue(inputStream, ProjectedVolumeSource.class); + + // Then + assertThat(projectedVolumeSource) + .hasFieldOrPropertyWithValue("defaultMode", Integer.valueOf("0555", 8)) + .extracting(ProjectedVolumeSource::getSources) + .asInstanceOf(InstanceOfAssertFactories.list(VolumeProjection.class)) + .singleElement() + .extracting(VolumeProjection::getSecret) + .hasFieldOrPropertyWithValue("name", "mysecret") + .extracting(SecretProjection::getItems) + .asInstanceOf(InstanceOfAssertFactories.list(KeyToPath.class)) + .singleElement() + .hasFieldOrPropertyWithValue("key", "username") + .hasFieldOrPropertyWithValue("path", "my-group/my-username"); + } +} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/SecretVolumeSourceTest.java b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/SecretVolumeSourceTest.java new file mode 100644 index 00000000000..b51ab420bfd --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/SecretVolumeSourceTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fabric8.kubernetes.api.model; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.assertj.core.api.InstanceOfAssertFactories; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStream; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +class SecretVolumeSourceTest { + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + void deserializationWithOctalValueShouldWorkAsExpected() throws IOException { + // Given + InputStream inputStream = getClass().getResourceAsStream("/secretvolumesource.json"); + + // When + SecretVolumeSource secretVolumeSource = objectMapper.readValue(inputStream, SecretVolumeSource.class); + + // Then + assertThat(secretVolumeSource) + .hasFieldOrPropertyWithValue("defaultMode", Integer.valueOf("0555", 8)) + .hasFieldOrPropertyWithValue("secretName", "conf") + .extracting(SecretVolumeSource::getItems) + .asInstanceOf(InstanceOfAssertFactories.list(KeyToPath.class)) + .singleElement() + .hasFieldOrPropertyWithValue("key", "key1") + .hasFieldOrPropertyWithValue("path", "target") + .hasFieldOrPropertyWithValue("mode", Integer.valueOf("0555", 8)); + } +} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/test/resources/configmapvolumesource.json b/kubernetes-model-generator/kubernetes-model-core/src/test/resources/configmapvolumesource.json new file mode 100644 index 00000000000..efbaaafe280 --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-core/src/test/resources/configmapvolumesource.json @@ -0,0 +1,11 @@ +{ + "name": "conf", + "defaultMode": "0555", + "items": [ + { + "key": "key1", + "path": "target", + "mode": "0555" + } + ] +} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/test/resources/downwardapivolumesource.json b/kubernetes-model-generator/kubernetes-model-core/src/test/resources/downwardapivolumesource.json new file mode 100644 index 00000000000..be5ca3f7ec1 --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-core/src/test/resources/downwardapivolumesource.json @@ -0,0 +1,12 @@ +{ + "defaultMode": "0555", + "items": [ + { + "path": "labels", + "fieldRef": { + "fieldPath": "metadata.labels" + }, + "mode": "0555" + } + ] +} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/test/resources/projectedvolumesource.json b/kubernetes-model-generator/kubernetes-model-core/src/test/resources/projectedvolumesource.json new file mode 100644 index 00000000000..0cf95a4296c --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-core/src/test/resources/projectedvolumesource.json @@ -0,0 +1,16 @@ +{ + "defaultMode": "0555", + "sources": [ + { + "secret": { + "name": "mysecret", + "items": [ + { + "key": "username", + "path": "my-group/my-username" + } + ] + } + } + ] +} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/test/resources/secretvolumesource.json b/kubernetes-model-generator/kubernetes-model-core/src/test/resources/secretvolumesource.json new file mode 100644 index 00000000000..d3cccae075e --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-core/src/test/resources/secretvolumesource.json @@ -0,0 +1,11 @@ +{ + "secretName": "conf", + "defaultMode": "0555", + "items": [ + { + "key": "key1", + "path": "target", + "mode": "0555" + } + ] +} From 03bb3dd13072fca9f1d5439e7bc7b3b52703a902 Mon Sep 17 00:00:00 2001 From: Marc Nuri Date: Thu, 18 Jul 2024 12:42:02 +0200 Subject: [PATCH 2/2] feat: Jackson module to handle Go (de)serialization nuances Signed-off-by: Marc Nuri --- CHANGELOG.md | 2 +- .../client/utils/KubernetesSerialization.java | 3 +- .../client/utils/Serialization.java | 3 +- .../resources/serialization/cronjob-octal.yml | 2 +- ...erUtil.java => GoCompatibilityModule.java} | 22 +--- .../model/jackson/GoIntegerDeserializer.java | 71 ++++++++++++ .../jackson/GoIntegerDeserializerTest.java | 101 ++++++++++++++++++ .../jackson/IntegerOctalHandlerUtilTest.java | 44 -------- .../cmd/generate/generate.go | 12 --- .../api/model/ConfigMapVolumeSource.java | 2 +- .../api/model/DownwardAPIVolumeSource.java | 2 +- .../api/model/ProjectedVolumeSource.java | 2 +- .../api/model/SecretVolumeSource.java | 2 +- .../ConfigMapVolumeSourceDeserializer.java | 60 ----------- .../DownwardAPIVolumeSourceDeserializer.java | 55 ---------- .../ProjectedVolumeSourceDeserializer.java | 44 -------- .../model/SecretVolumeSourceDeserializer.java | 60 ----------- .../main/resources/schema/kube-schema.json | 12 +-- .../resources/schema/validation-schema.json | 12 +-- .../api/model/ConfigMapVolumeSourceTest.java | 11 +- .../model/DownwardAPIVolumeSourceTest.java | 11 +- .../api/model/ProjectedVolumeSourceTest.java | 11 +- .../api/model/SecretVolumeSourceTest.java | 11 +- .../test/resources/configmapvolumesource.json | 2 +- 24 files changed, 235 insertions(+), 322 deletions(-) rename kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/{IntegerOctalHandlerUtil.java => GoCompatibilityModule.java} (50%) create mode 100644 kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/GoIntegerDeserializer.java create mode 100644 kubernetes-model-generator/kubernetes-model-common/src/test/java/io/fabric8/kubernetes/model/jackson/GoIntegerDeserializerTest.java delete mode 100644 kubernetes-model-generator/kubernetes-model-common/src/test/java/io/fabric8/kubernetes/model/jackson/IntegerOctalHandlerUtilTest.java delete mode 100644 kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSourceDeserializer.java delete mode 100644 kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSourceDeserializer.java delete mode 100644 kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSourceDeserializer.java delete mode 100644 kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/SecretVolumeSourceDeserializer.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c2b2b65577..309f5e5de70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,11 @@ #### Bugs * Fix #6038: Support for Gradle configuration cache +* Fix #6110: VolumeSource (and other file mode fields) in Octal are correctly interpreted #### Improvements * Fix #6008: removing the optional dependency on bouncy castle * Fix #5264: Remove deprecated `Config.errorMessages` field -* Fix #6110: VolumeSource's Octal `defaultMode` notation in yaml not properly converted to json #### Dependency Upgrade * Fix #6052: Removed dependency on no longer maintained com.github.mifmif:generex 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 index db04df0247c..7f7bb505178 100644 --- 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 @@ -39,6 +39,7 @@ 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.GoCompatibilityModule; import io.fabric8.kubernetes.model.jackson.UnmatchedFieldTypeModule; import org.snakeyaml.engine.v2.api.Dump; import org.snakeyaml.engine.v2.api.DumpSettings; @@ -89,7 +90,7 @@ public KubernetesSerialization(ObjectMapper mapper, boolean searchClassloaders) } protected void configureMapper(ObjectMapper mapper) { - mapper.registerModules(new JavaTimeModule(), unmatchedFieldTypeModule); + mapper.registerModules(new JavaTimeModule(), new GoCompatibilityModule(), unmatchedFieldTypeModule); mapper.disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); mapper.disable(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS); 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 5dde896af5a..0fc3970f90c 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 @@ -20,6 +20,7 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; import io.fabric8.kubernetes.api.model.KubernetesResource; +import io.fabric8.kubernetes.model.jackson.GoCompatibilityModule; import io.fabric8.kubernetes.model.jackson.UnmatchedFieldTypeModule; import java.io.InputStream; @@ -88,7 +89,7 @@ public static ObjectMapper yamlMapper() { if (YAML_MAPPER == null) { YAML_MAPPER = new ObjectMapper( new YAMLFactory().disable(YAMLGenerator.Feature.USE_NATIVE_TYPE_ID)); - YAML_MAPPER.registerModules(UNMATCHED_FIELD_TYPE_MODULE); + YAML_MAPPER.registerModules(new GoCompatibilityModule(), UNMATCHED_FIELD_TYPE_MODULE); } } } diff --git a/kubernetes-client-api/src/test/resources/serialization/cronjob-octal.yml b/kubernetes-client-api/src/test/resources/serialization/cronjob-octal.yml index 21927d77e15..5123000578e 100644 --- a/kubernetes-client-api/src/test/resources/serialization/cronjob-octal.yml +++ b/kubernetes-client-api/src/test/resources/serialization/cronjob-octal.yml @@ -37,7 +37,7 @@ spec: - name: application-code configMap: name: conf - defaultMode: 0555 + defaultMode: 0o555 items: - key: key1 path: target diff --git a/kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/IntegerOctalHandlerUtil.java b/kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/GoCompatibilityModule.java similarity index 50% rename from kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/IntegerOctalHandlerUtil.java rename to kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/GoCompatibilityModule.java index 29dd6b17fa1..3da432b9019 100644 --- a/kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/IntegerOctalHandlerUtil.java +++ b/kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/GoCompatibilityModule.java @@ -15,25 +15,11 @@ */ package io.fabric8.kubernetes.model.jackson; -import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.module.SimpleModule; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +public class GoCompatibilityModule extends SimpleModule { -public class IntegerOctalHandlerUtil { - private static final Pattern OCTAL_NUMBER = Pattern.compile("(0[oO]?)[0-7]+"); - - private IntegerOctalHandlerUtil() { - } - - public static Integer createIntegerValue(JsonNode node) { - String textValue = node.textValue(); - if (textValue != null) { - Matcher octalNumberMatcher = OCTAL_NUMBER.matcher(textValue); - if (octalNumberMatcher.matches()) { - return Integer.valueOf(textValue.substring(octalNumberMatcher.group(1).length()), 8); - } - } - return node.intValue(); + public GoCompatibilityModule() { + addDeserializer(Integer.class, new GoIntegerDeserializer()); } } diff --git a/kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/GoIntegerDeserializer.java b/kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/GoIntegerDeserializer.java new file mode 100644 index 00000000000..7bc012103f1 --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-common/src/main/java/io/fabric8/kubernetes/model/jackson/GoIntegerDeserializer.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fabric8.kubernetes.model.jackson; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.BeanProperty; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.deser.ContextualDeserializer; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class GoIntegerDeserializer extends StdDeserializer implements ContextualDeserializer { + + private static final Pattern OCTAL = Pattern.compile("(0[oO]?)([0-7]+)"); + private static final GoIntegerDeserializer APPLICABLE_INSTANCE = new GoIntegerDeserializer(true); + private static final Set APPLICABLE_FIELDS = new HashSet<>(Arrays.asList("mode", "defaultMode")); + + private final boolean applicable; + + protected GoIntegerDeserializer() { + this(false); + } + + private GoIntegerDeserializer(boolean applicable) { + super(Integer.class); + this.applicable = applicable; + } + + @Override + public Integer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + final String value = p.getText(); + if (value == null) { + return null; + } + if (applicable) { + final Matcher matcher = OCTAL.matcher(value); + if (matcher.find()) { + return Integer.valueOf(matcher.group(2), 8); + } + } + return _parseInteger(ctxt, value); + } + + @Override + public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) { + if (property != null && APPLICABLE_FIELDS.contains(property.getName())) { + return APPLICABLE_INSTANCE; + } + return this; + } +} diff --git a/kubernetes-model-generator/kubernetes-model-common/src/test/java/io/fabric8/kubernetes/model/jackson/GoIntegerDeserializerTest.java b/kubernetes-model-generator/kubernetes-model-common/src/test/java/io/fabric8/kubernetes/model/jackson/GoIntegerDeserializerTest.java new file mode 100644 index 00000000000..d7a3a564f68 --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-common/src/test/java/io/fabric8/kubernetes/model/jackson/GoIntegerDeserializerTest.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fabric8.kubernetes.model.jackson; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.exc.InvalidFormatException; +import lombok.Data; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; + +class GoIntegerDeserializerTest { + + private ObjectMapper context; + + @BeforeEach + void setUp() { + context = new ObjectMapper(); + context.registerModule(new GoCompatibilityModule()); + } + + @Nested + @TestInstance(PER_CLASS) + class Applicable { + + @ParameterizedTest(name = "{index}: with '{'\"{0}\": {1}'}' parses as {2}") + @MethodSource + void parsesOctals(String fieldName, String content, Integer expected) throws Exception { + final IntegerFieldsContainer result = context + .readValue(String.format("{\"%s\": %s}", fieldName, content), IntegerFieldsContainer.class); + assertThat(result).hasFieldOrPropertyWithValue(fieldName, expected); + } + + private Stream parsesOctals() { + return Stream.of("mode", "defaultMode") + .flatMap(field -> Stream.of( + Arguments.of(field, "null", null), + Arguments.of(field, "\"0555\"", 365), + Arguments.of(field, "\"0o555\"", 365), + Arguments.of(field, "\"0O555\"", 365), + Arguments.of(field, "\"555\"", 555), + Arguments.of(field, "\"0888\"", 888), + Arguments.of(field, "\"0o12\"", 10), + Arguments.of(field, "\"0O12\"", 10))); + } + } + + // + @Nested + class NotApplicable { + + @Test + void parsesOctalsAsDecimal() throws Exception { + final IntegerFieldsContainer result = context + .readValue("{\"notApplicable\": \"0555\"}", IntegerFieldsContainer.class); + assertThat(result).hasFieldOrPropertyWithValue("notApplicable", 555); + } + + @Test + void throwsExceptionForInvalidOctal() { + assertThatThrownBy(() -> context.readValue("{\"mode\": \"0o955\"}", IntegerFieldsContainer.class)) + .isInstanceOf(InvalidFormatException.class); + } + + @Test + void throwsExceptionForOctalWithSeparator() { + assertThatThrownBy(() -> context.readValue("{\"notApplicable\": \"0o555\"}", IntegerFieldsContainer.class)) + .isInstanceOf(InvalidFormatException.class); + } + } + + @Data + private static final class IntegerFieldsContainer { + private Integer mode; + private Integer defaultMode; + private Integer notApplicable; + } +} diff --git a/kubernetes-model-generator/kubernetes-model-common/src/test/java/io/fabric8/kubernetes/model/jackson/IntegerOctalHandlerUtilTest.java b/kubernetes-model-generator/kubernetes-model-common/src/test/java/io/fabric8/kubernetes/model/jackson/IntegerOctalHandlerUtilTest.java deleted file mode 100644 index 6fb1d7373bd..00000000000 --- a/kubernetes-model-generator/kubernetes-model-common/src/test/java/io/fabric8/kubernetes/model/jackson/IntegerOctalHandlerUtilTest.java +++ /dev/null @@ -1,44 +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.kubernetes.model.jackson; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.stream.Stream; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -class IntegerOctalHandlerUtilTest { - private final ObjectMapper objectMapper = new ObjectMapper(); - - private static Stream shouldParseOctalNumbersCorrectly() { - return Stream.of( - Arguments.of("\"012\"", Integer.valueOf("012", 8)), - Arguments.of("\"0o12\"", Integer.valueOf("012", 8)), - Arguments.of("\"0O12\"", Integer.valueOf("012", 8))); - } - - @ParameterizedTest - @MethodSource - void shouldParseOctalNumbersCorrectly(String input, Integer expectedValue) throws JsonProcessingException { - assertThat(IntegerOctalHandlerUtil.createIntegerValue(objectMapper.readTree(input))) - .isEqualTo(expectedValue); - } -} diff --git a/kubernetes-model-generator/kubernetes-model-core/cmd/generate/generate.go b/kubernetes-model-generator/kubernetes-model-core/cmd/generate/generate.go index 69e4d7a6af8..80b6baee55f 100644 --- a/kubernetes-model-generator/kubernetes-model-core/cmd/generate/generate.go +++ b/kubernetes-model-generator/kubernetes-model-core/cmd/generate/generate.go @@ -152,18 +152,6 @@ func main() { Serializer: "io.fabric8.kubernetes.api.model.MicroTimeSerDes.Serializer.class", Deserializer: "io.fabric8.kubernetes.api.model.MicroTimeSerDes.Deserializer.class", }, - "kubernetes_core_ConfigMapVolumeSource": &schemagen.JavaSerDeDescriptor{ - Deserializer: "io.fabric8.kubernetes.api.model.ConfigMapVolumeSourceDeserializer.class", - }, - "kubernetes_core_SecretVolumeSource": &schemagen.JavaSerDeDescriptor{ - Deserializer: "io.fabric8.kubernetes.api.model.SecretVolumeSourceDeserializer.class", - }, - "kubernetes_core_DownwardAPIVolumeSource": &schemagen.JavaSerDeDescriptor{ - Deserializer: "io.fabric8.kubernetes.api.model.DownwardAPIVolumeSourceDeserializer.class", - }, - "kubernetes_core_ProjectedVolumeSource": &schemagen.JavaSerDeDescriptor{ - Deserializer: "io.fabric8.kubernetes.api.model.ProjectedVolumeSourceDeserializer.class", - }, } for definitionKey, descriptor := range serdes { diff --git a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSource.java b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSource.java index 64f3b25230f..d24b9065776 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSource.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSource.java @@ -19,7 +19,7 @@ import lombok.ToString; import lombok.experimental.Accessors; -@JsonDeserialize(using = io.fabric8.kubernetes.api.model.ConfigMapVolumeSourceDeserializer.class) +@JsonDeserialize(using = com.fasterxml.jackson.databind.JsonDeserializer.None.class) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "defaultMode", diff --git a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSource.java b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSource.java index bfb4369674e..6fadacbdb71 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSource.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSource.java @@ -19,7 +19,7 @@ import lombok.ToString; import lombok.experimental.Accessors; -@JsonDeserialize(using = io.fabric8.kubernetes.api.model.DownwardAPIVolumeSourceDeserializer.class) +@JsonDeserialize(using = com.fasterxml.jackson.databind.JsonDeserializer.None.class) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "defaultMode", diff --git a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSource.java b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSource.java index f74ea0d947f..1fa31c7e860 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSource.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSource.java @@ -19,7 +19,7 @@ import lombok.ToString; import lombok.experimental.Accessors; -@JsonDeserialize(using = io.fabric8.kubernetes.api.model.ProjectedVolumeSourceDeserializer.class) +@JsonDeserialize(using = com.fasterxml.jackson.databind.JsonDeserializer.None.class) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "defaultMode", diff --git a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/SecretVolumeSource.java b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/SecretVolumeSource.java index 62e4d88fbfa..14c1ddc75f4 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/SecretVolumeSource.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/generated/java/io/fabric8/kubernetes/api/model/SecretVolumeSource.java @@ -19,7 +19,7 @@ import lombok.ToString; import lombok.experimental.Accessors; -@JsonDeserialize(using = io.fabric8.kubernetes.api.model.SecretVolumeSourceDeserializer.class) +@JsonDeserialize(using = com.fasterxml.jackson.databind.JsonDeserializer.None.class) @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "defaultMode", diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSourceDeserializer.java b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSourceDeserializer.java deleted file mode 100644 index 7ba928e0565..00000000000 --- a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSourceDeserializer.java +++ /dev/null @@ -1,60 +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.kubernetes.api.model; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; - -import java.io.IOException; - -import static io.fabric8.kubernetes.model.jackson.IntegerOctalHandlerUtil.createIntegerValue; - -public class ConfigMapVolumeSourceDeserializer extends JsonDeserializer { - - @Override - public ConfigMapVolumeSource deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) - throws IOException { - JsonNode node = jsonParser.getCodec().readTree(jsonParser); - ConfigMapVolumeSourceBuilder builder = new ConfigMapVolumeSourceBuilder(); - if (node.get("items") != null) { - for (final JsonNode keyToPathNode : node.get("items")) { - builder.addToItems(createKeyToPath(keyToPathNode, jsonParser)); - } - } - if (node.get("name") != null) { - builder.withName(node.get("name").textValue()); - } - if (node.get("optional") != null) { - builder.withOptional(node.get("optional").booleanValue()); - } - if (node.get("defaultMode") != null) { - builder.withDefaultMode(createIntegerValue(node.get("defaultMode"))); - } - return builder.build(); - } - - private KeyToPath createKeyToPath(JsonNode node, JsonParser jsonParser) throws JsonProcessingException { - KeyToPath keyToPath = jsonParser.getCodec().treeToValue(node, KeyToPath.class); - KeyToPathBuilder keyToPathBuilder = new KeyToPathBuilder(keyToPath); - if (node.get("mode") != null) { - keyToPathBuilder.withMode(createIntegerValue(node.get("mode"))); - } - return keyToPathBuilder.build(); - } -} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSourceDeserializer.java b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSourceDeserializer.java deleted file mode 100644 index f950e120d23..00000000000 --- a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSourceDeserializer.java +++ /dev/null @@ -1,55 +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.kubernetes.api.model; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; - -import java.io.IOException; - -import static io.fabric8.kubernetes.model.jackson.IntegerOctalHandlerUtil.createIntegerValue; - -public class DownwardAPIVolumeSourceDeserializer extends JsonDeserializer { - - @Override - public DownwardAPIVolumeSource deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) - throws IOException { - JsonNode node = jsonParser.getCodec().readTree(jsonParser); - DownwardAPIVolumeSourceBuilder builder = new DownwardAPIVolumeSourceBuilder(); - if (node.get("items") != null) { - for (final JsonNode keyToPathNode : node.get("items")) { - builder.addToItems(createDownwardAPIVolumeFile(keyToPathNode, jsonParser)); - } - } - if (node.get("defaultMode") != null) { - builder.withDefaultMode(createIntegerValue(node.get("defaultMode"))); - } - return builder.build(); - } - - private DownwardAPIVolumeFile createDownwardAPIVolumeFile(JsonNode node, JsonParser jsonParser) - throws JsonProcessingException { - DownwardAPIVolumeFile downwardAPIVolumeFile = jsonParser.getCodec().treeToValue(node, DownwardAPIVolumeFile.class); - DownwardAPIVolumeFileBuilder downwardAPIVolumeFileBuilder = new DownwardAPIVolumeFileBuilder(downwardAPIVolumeFile); - if (node.get("mode") != null) { - downwardAPIVolumeFileBuilder.withMode(createIntegerValue(node.get("mode"))); - } - return downwardAPIVolumeFileBuilder.build(); - } -} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSourceDeserializer.java b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSourceDeserializer.java deleted file mode 100644 index 9af8b0a5fcb..00000000000 --- a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSourceDeserializer.java +++ /dev/null @@ -1,44 +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.kubernetes.api.model; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; - -import java.io.IOException; - -import static io.fabric8.kubernetes.model.jackson.IntegerOctalHandlerUtil.createIntegerValue; - -public class ProjectedVolumeSourceDeserializer extends JsonDeserializer { - - @Override - public ProjectedVolumeSource deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) - throws IOException { - JsonNode node = jsonParser.getCodec().readTree(jsonParser); - ProjectedVolumeSourceBuilder builder = new ProjectedVolumeSourceBuilder(); - if (node.get("sources") != null) { - for (final JsonNode sourceNode : node.get("sources")) { - builder.addToSources(jsonParser.getCodec().treeToValue(sourceNode, VolumeProjection.class)); - } - } - if (node.get("defaultMode") != null) { - builder.withDefaultMode(createIntegerValue(node.get("defaultMode"))); - } - return builder.build(); - } -} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/SecretVolumeSourceDeserializer.java b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/SecretVolumeSourceDeserializer.java deleted file mode 100644 index 3a130bec5fc..00000000000 --- a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/SecretVolumeSourceDeserializer.java +++ /dev/null @@ -1,60 +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.kubernetes.api.model; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; - -import java.io.IOException; - -import static io.fabric8.kubernetes.model.jackson.IntegerOctalHandlerUtil.createIntegerValue; - -public class SecretVolumeSourceDeserializer extends JsonDeserializer { - - @Override - public SecretVolumeSource deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) - throws IOException { - JsonNode node = jsonParser.getCodec().readTree(jsonParser); - SecretVolumeSourceBuilder builder = new SecretVolumeSourceBuilder(); - if (node.get("items") != null) { - for (final JsonNode keyToPathNode : node.get("items")) { - builder.addToItems(createKeyToPath(keyToPathNode, jsonParser)); - } - } - if (node.get("secretName") != null) { - builder.withSecretName(node.get("secretName").textValue()); - } - if (node.get("optional") != null) { - builder.withOptional(node.get("optional").booleanValue()); - } - if (node.get("defaultMode") != null) { - builder.withDefaultMode(createIntegerValue(node.get("defaultMode"))); - } - return builder.build(); - } - - private KeyToPath createKeyToPath(JsonNode node, JsonParser jsonParser) throws JsonProcessingException { - KeyToPath keyToPath = jsonParser.getCodec().treeToValue(node, KeyToPath.class); - KeyToPathBuilder keyToPathBuilder = new KeyToPathBuilder(keyToPath); - if (node.get("mode") != null) { - keyToPathBuilder.withMode(createIntegerValue(node.get("mode"))); - } - return keyToPathBuilder.build(); - } -} diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/kube-schema.json b/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/kube-schema.json index 521c84b552e..59da900f808 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/kube-schema.json +++ b/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/kube-schema.json @@ -2237,8 +2237,7 @@ "javaType": "io.fabric8.kubernetes.api.model.ConfigMapVolumeSource", "javaInterfaces": [ "io.fabric8.kubernetes.api.model.KubernetesResource" - ], - "deserializer": "io.fabric8.kubernetes.api.model.ConfigMapVolumeSourceDeserializer.class" + ] }, "kubernetes_core_Container": { "type": "object", @@ -2648,8 +2647,7 @@ "javaType": "io.fabric8.kubernetes.api.model.DownwardAPIVolumeSource", "javaInterfaces": [ "io.fabric8.kubernetes.api.model.KubernetesResource" - ], - "deserializer": "io.fabric8.kubernetes.api.model.DownwardAPIVolumeSourceDeserializer.class" + ] }, "kubernetes_core_EmptyDirVolumeSource": { "type": "object", @@ -6132,8 +6130,7 @@ "javaType": "io.fabric8.kubernetes.api.model.ProjectedVolumeSource", "javaInterfaces": [ "io.fabric8.kubernetes.api.model.KubernetesResource" - ], - "deserializer": "io.fabric8.kubernetes.api.model.ProjectedVolumeSourceDeserializer.class" + ] }, "kubernetes_core_QuobyteVolumeSource": { "type": "object", @@ -6915,8 +6912,7 @@ "javaType": "io.fabric8.kubernetes.api.model.SecretVolumeSource", "javaInterfaces": [ "io.fabric8.kubernetes.api.model.KubernetesResource" - ], - "deserializer": "io.fabric8.kubernetes.api.model.SecretVolumeSourceDeserializer.class" + ] }, "kubernetes_core_SecurityContext": { "type": "object", diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/validation-schema.json b/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/validation-schema.json index 0b23998a896..9e0a4d9c6c2 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/validation-schema.json +++ b/kubernetes-model-generator/kubernetes-model-core/src/main/resources/schema/validation-schema.json @@ -2237,8 +2237,7 @@ "javaType": "io.fabric8.kubernetes.api.model.ConfigMapVolumeSource", "javaInterfaces": [ "io.fabric8.kubernetes.api.model.KubernetesResource" - ], - "deserializer": "io.fabric8.kubernetes.api.model.ConfigMapVolumeSourceDeserializer.class" + ] }, "kubernetes_core_Container": { "type": "object", @@ -2648,8 +2647,7 @@ "javaType": "io.fabric8.kubernetes.api.model.DownwardAPIVolumeSource", "javaInterfaces": [ "io.fabric8.kubernetes.api.model.KubernetesResource" - ], - "deserializer": "io.fabric8.kubernetes.api.model.DownwardAPIVolumeSourceDeserializer.class" + ] }, "kubernetes_core_EmptyDirVolumeSource": { "type": "object", @@ -6132,8 +6130,7 @@ "javaType": "io.fabric8.kubernetes.api.model.ProjectedVolumeSource", "javaInterfaces": [ "io.fabric8.kubernetes.api.model.KubernetesResource" - ], - "deserializer": "io.fabric8.kubernetes.api.model.ProjectedVolumeSourceDeserializer.class" + ] }, "kubernetes_core_QuobyteVolumeSource": { "type": "object", @@ -6915,8 +6912,7 @@ "javaType": "io.fabric8.kubernetes.api.model.SecretVolumeSource", "javaInterfaces": [ "io.fabric8.kubernetes.api.model.KubernetesResource" - ], - "deserializer": "io.fabric8.kubernetes.api.model.SecretVolumeSourceDeserializer.class" + ] }, "kubernetes_core_SecurityContext": { "type": "object", diff --git a/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSourceTest.java b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSourceTest.java index dc0063b1f4e..e977f932f87 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSourceTest.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/ConfigMapVolumeSourceTest.java @@ -16,7 +16,9 @@ package io.fabric8.kubernetes.api.model; import com.fasterxml.jackson.databind.ObjectMapper; +import io.fabric8.kubernetes.model.jackson.GoCompatibilityModule; import org.assertj.core.api.InstanceOfAssertFactories; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.io.IOException; @@ -25,7 +27,14 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; class ConfigMapVolumeSourceTest { - private final ObjectMapper objectMapper = new ObjectMapper(); + + private ObjectMapper objectMapper; + + @BeforeEach + void setUp() { + objectMapper = new ObjectMapper(); + objectMapper.registerModule(new GoCompatibilityModule()); + } @Test void deserializationWithOctalValueShouldWorkAsExpected() throws IOException { diff --git a/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSourceTest.java b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSourceTest.java index 085a36e2acc..9da8b8bb2df 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSourceTest.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/DownwardAPIVolumeSourceTest.java @@ -16,7 +16,9 @@ package io.fabric8.kubernetes.api.model; import com.fasterxml.jackson.databind.ObjectMapper; +import io.fabric8.kubernetes.model.jackson.GoCompatibilityModule; import org.assertj.core.api.InstanceOfAssertFactories; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.io.IOException; @@ -25,7 +27,14 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; class DownwardAPIVolumeSourceTest { - private final ObjectMapper objectMapper = new ObjectMapper(); + + private ObjectMapper objectMapper; + + @BeforeEach + void setUp() { + objectMapper = new ObjectMapper(); + objectMapper.registerModule(new GoCompatibilityModule()); + } @Test void deserializationWithOctalValueShouldWorkAsExpected() throws IOException { diff --git a/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSourceTest.java b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSourceTest.java index 9cb419793f5..00388fa2fdd 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSourceTest.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/ProjectedVolumeSourceTest.java @@ -16,7 +16,9 @@ package io.fabric8.kubernetes.api.model; import com.fasterxml.jackson.databind.ObjectMapper; +import io.fabric8.kubernetes.model.jackson.GoCompatibilityModule; import org.assertj.core.api.InstanceOfAssertFactories; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.io.IOException; @@ -25,7 +27,14 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; class ProjectedVolumeSourceTest { - private final ObjectMapper objectMapper = new ObjectMapper(); + + private ObjectMapper objectMapper; + + @BeforeEach + void setUp() { + objectMapper = new ObjectMapper(); + objectMapper.registerModule(new GoCompatibilityModule()); + } @Test void deserializationWithOctalValueShouldWorkAsExpected() throws IOException { diff --git a/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/SecretVolumeSourceTest.java b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/SecretVolumeSourceTest.java index b51ab420bfd..c998975793d 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/SecretVolumeSourceTest.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/test/java/io/fabric8/kubernetes/api/model/SecretVolumeSourceTest.java @@ -16,7 +16,9 @@ package io.fabric8.kubernetes.api.model; import com.fasterxml.jackson.databind.ObjectMapper; +import io.fabric8.kubernetes.model.jackson.GoCompatibilityModule; import org.assertj.core.api.InstanceOfAssertFactories; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.io.IOException; @@ -25,7 +27,14 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; class SecretVolumeSourceTest { - private final ObjectMapper objectMapper = new ObjectMapper(); + + private ObjectMapper objectMapper; + + @BeforeEach + void setUp() { + objectMapper = new ObjectMapper(); + objectMapper.registerModule(new GoCompatibilityModule()); + } @Test void deserializationWithOctalValueShouldWorkAsExpected() throws IOException { diff --git a/kubernetes-model-generator/kubernetes-model-core/src/test/resources/configmapvolumesource.json b/kubernetes-model-generator/kubernetes-model-core/src/test/resources/configmapvolumesource.json index efbaaafe280..5e84791039d 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/test/resources/configmapvolumesource.json +++ b/kubernetes-model-generator/kubernetes-model-core/src/test/resources/configmapvolumesource.json @@ -5,7 +5,7 @@ { "key": "key1", "path": "target", - "mode": "0555" + "mode": "0O555" } ] }