From 6c241599c6a10a630fdd2fcaeef52893087758af Mon Sep 17 00:00:00 2001 From: Steve Hawkins Date: Wed, 18 May 2022 10:48:15 -0400 Subject: [PATCH] fix #3625: updating the default logic for maps and objectmetadata --- CHANGELOG.md | 1 + doc/MIGRATION-v6.md | 10 +++ .../kubernetes/client/CustomResource.java | 3 + .../api/model/GenericKubernetesResource.java | 6 +- .../jsonschema2pojo/Fabric8DefaultRule.java | 77 +++++++++++++++++++ .../jsonschema2pojo/Fabric8RuleFactory.java | 11 ++- 6 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 kubernetes-model-generator/kubernetes-model-jsonschema2pojo/src/main/java/io/fabric8/kubernetes/jsonschema2pojo/Fabric8DefaultRule.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 66fa4e00e8a..ffd63299b70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ #### Improvements * Remove `setIntVal`, `setStrVal`, `setKind` setters from `IntOrString` class to avoid invalid combinations +* Fix #3625: ObjectMetadata and its annotations and labels are non-null by default. * Fix #3852: Deserializing kamelets fails with UnrecognizedPropertyException * Fix #3889 : remove piped stream for file download * Fix #1285: removed references to manually calling registerCustomKind diff --git a/doc/MIGRATION-v6.md b/doc/MIGRATION-v6.md index d2eb06956f4..c7368a199e9 100644 --- a/doc/MIGRATION-v6.md +++ b/doc/MIGRATION-v6.md @@ -1,6 +1,7 @@ # Migration from 5.x to 6.x ## Contents: +- [ObjectMetadata](#objectmetadata) - [Backwards Compatibility Interceptor](#backwards-compatibility-interceptor) - [Namespace Changes](#namespace-changes) - [API/Impl split](#api-impl-split) @@ -19,6 +20,15 @@ - [Delete Behavior](#delete-behavior) - [Stream Changes](#stream-changes) +## ObjectMetadata + +ObjectMetadata will default to a non-null value. All Maps in the generated object models, including ObjectMetadata.annotations and labels will also be non-null by default. A small behavioral difference is that the default value will be omitted from serialization, previously if you did something like +``` +Pod p = new Pod(); +p.setMetadata(new ObjectMetadata()); +``` +p would serialize with "metadata: {}" - that will now be omitted. + ## Backwards Compatibility Interceptor kubernetes.backwardsCompatibilityInterceptor.disable now defaults to true, rather than false. If you need backwards compatibility support, please set this property to false. diff --git a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/CustomResource.java b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/CustomResource.java index 5a4d781a86b..21fce8de4b5 100644 --- a/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/CustomResource.java +++ b/kubernetes-client-api/src/main/java/io/fabric8/kubernetes/client/CustomResource.java @@ -76,6 +76,7 @@ public abstract class CustomResource implements HasMetadata { private static final Logger LOG = LoggerFactory.getLogger(CustomResource.class); + @JsonInclude(value = Include.CUSTOM, valueFilter = ObjectMeta.class) private ObjectMeta metadata = new ObjectMeta(); @JsonProperty("spec") @@ -190,6 +191,7 @@ public static String getPlural(Class clazz) { return HasMetadata.getPlural(clazz); } + @Override @JsonIgnore public String getPlural() { return plural; @@ -203,6 +205,7 @@ public static String getSingular(Class clazz) { return HasMetadata.getSingular(clazz); } + @Override @JsonIgnore public String getSingular() { return singular; diff --git a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/GenericKubernetesResource.java b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/GenericKubernetesResource.java index c4a16326d11..70da9fa91fc 100644 --- a/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/GenericKubernetesResource.java +++ b/kubernetes-model-generator/kubernetes-model-core/src/main/java/io/fabric8/kubernetes/api/model/GenericKubernetesResource.java @@ -21,6 +21,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @@ -56,7 +57,8 @@ public class GenericKubernetesResource implements HasMetadata { @JsonProperty("kind") private String kind; @JsonProperty("metadata") - private ObjectMeta metadata; + @JsonInclude(value = Include.CUSTOM, valueFilter = ObjectMeta.class) + private ObjectMeta metadata = new ObjectMeta(); @JsonIgnore private Map additionalProperties = new LinkedHashMap<>(); @@ -130,7 +132,7 @@ public T get(Object... path) { /** * The same as {@link #get(Object...)}, but starting at any root raw object - * + * * @param type of the returned object (Map, Collection, or value). * @param root starting object * @param path of the field to retrieve. diff --git a/kubernetes-model-generator/kubernetes-model-jsonschema2pojo/src/main/java/io/fabric8/kubernetes/jsonschema2pojo/Fabric8DefaultRule.java b/kubernetes-model-generator/kubernetes-model-jsonschema2pojo/src/main/java/io/fabric8/kubernetes/jsonschema2pojo/Fabric8DefaultRule.java new file mode 100644 index 00000000000..3f141acb19b --- /dev/null +++ b/kubernetes-model-generator/kubernetes-model-jsonschema2pojo/src/main/java/io/fabric8/kubernetes/jsonschema2pojo/Fabric8DefaultRule.java @@ -0,0 +1,77 @@ +/** + * 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.jsonschema2pojo; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.JsonNode; +import com.sun.codemodel.JClass; +import com.sun.codemodel.JExpr; +import com.sun.codemodel.JFieldVar; +import com.sun.codemodel.JType; +import org.jsonschema2pojo.Schema; +import org.jsonschema2pojo.rules.DefaultRule; +import org.jsonschema2pojo.rules.RuleFactory; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Adds default map and objectmeta handling + */ +public class Fabric8DefaultRule extends DefaultRule { + + public static final String OBJECTMETA = "io.fabric8.kubernetes.api.model.ObjectMeta"; + public static final String ANNOTATION_VALUE_FILTER = "valueFilter"; + + private final RuleFactory ruleFactory; + + public Fabric8DefaultRule(RuleFactory ruleFactory) { + super(ruleFactory); + this.ruleFactory = ruleFactory; + } + + @Override + public JFieldVar apply(String nodeName, JsonNode node, JsonNode parent, JFieldVar field, Schema currentSchema) { + JType fieldType = field.type(); + String fieldTypeName = fieldType.fullName(); + + if (node == null || node.asText() == null || node.asText().isEmpty()) { + if (ruleFactory.getGenerationConfig().isInitializeCollections() && fieldTypeName.startsWith(Map.class.getName())) { + JClass keyGenericType = ((JClass) fieldType).getTypeParameters().get(0); + JClass valueGenericType = ((JClass) fieldType).getTypeParameters().get(1); + + JClass mapImplClass = fieldType.owner().ref(LinkedHashMap.class); + mapImplClass = mapImplClass.narrow(keyGenericType, valueGenericType); + // maps are not marked as omitJavaEmpty - it's simplest to just add the annotation here, rather than updating the generator + field.annotate(JsonInclude.class).param(KubernetesCoreTypeAnnotator.ANNOTATION_VALUE, JsonInclude.Include.NON_EMPTY); + field.init(JExpr._new(mapImplClass)); + } + + if (fieldTypeName.equals(OBJECTMETA)) { + JClass implClass = fieldType.owner().ref(fieldTypeName); + // annotate to omit the default + field.annotate(JsonInclude.class).param(KubernetesCoreTypeAnnotator.ANNOTATION_VALUE, JsonInclude.Include.CUSTOM) + .param(ANNOTATION_VALUE_FILTER, implClass); + field.init(JExpr._new(implClass)); + } + + } + + return super.apply(nodeName, node, parent, field, currentSchema); + } + +} diff --git a/kubernetes-model-generator/kubernetes-model-jsonschema2pojo/src/main/java/io/fabric8/kubernetes/jsonschema2pojo/Fabric8RuleFactory.java b/kubernetes-model-generator/kubernetes-model-jsonschema2pojo/src/main/java/io/fabric8/kubernetes/jsonschema2pojo/Fabric8RuleFactory.java index 7daf1a8f499..dbd01248619 100644 --- a/kubernetes-model-generator/kubernetes-model-jsonschema2pojo/src/main/java/io/fabric8/kubernetes/jsonschema2pojo/Fabric8RuleFactory.java +++ b/kubernetes-model-generator/kubernetes-model-jsonschema2pojo/src/main/java/io/fabric8/kubernetes/jsonschema2pojo/Fabric8RuleFactory.java @@ -15,6 +15,9 @@ */ package io.fabric8.kubernetes.jsonschema2pojo; +import com.sun.codemodel.JFieldVar; +import com.sun.codemodel.JPackage; +import com.sun.codemodel.JType; import org.jsonschema2pojo.DefaultGenerationConfig; import org.jsonschema2pojo.Jackson2Annotator; import org.jsonschema2pojo.SchemaStore; @@ -23,9 +26,6 @@ import org.jsonschema2pojo.util.NameHelper; import org.jsonschema2pojo.util.ParcelableHelper; -import com.sun.codemodel.JPackage; -import com.sun.codemodel.JType; - public class Fabric8RuleFactory extends RuleFactory { private final Fabric8NameHelper nameHelper; @@ -44,4 +44,9 @@ public NameHelper getNameHelper() { public Rule getObjectRule() { return new Fabric8ObjectRule(this, new ParcelableHelper(), getReflectionHelper()); } + + @Override + public Rule getDefaultRule() { + return new Fabric8DefaultRule(this); + } }