From 4beec6259060fd4adffcf8c9dca90bd6101c9dee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernhard=20Str=C3=A4hle?= Date: Wed, 20 Nov 2024 18:27:56 +0100 Subject: [PATCH] feat(crd-generator): added support for selectable fields (6540) feat(crd-generator): Add support for selectable fields (#6392) --- Include selectable field in unit test --- Add docs about `@AdditionalPrinterColumn` annotation --- Add docs about `@SelectableField` and `@AdditionalSelectableField` annotation --- Add changelog --- CHANGELOG.md | 3 +- .../AbstractCustomResourceHandler.java | 13 +++ .../crdv2/generator/AbstractJsonSchema.java | 19 +++- .../generator/v1/CustomResourceHandler.java | 4 + .../crdv2/example/joke/JokeRequestSpec.java | 2 + .../crdv2/generator/CRDGeneratorTest.java | 1 + .../CRDGeneratorApprovalTest.java | 2 + .../selectablefield/SelectableField.java | 27 +++++ .../selectablefield/SelectableFieldSpec.java | 46 ++++++++ ...lefields.sample.fabric8.io.v1.approved.yml | 44 ++++++++ doc/CRD-generator.md | 106 ++++++++++++++---- .../annotation/AdditionalSelectableField.java | 44 ++++++++ .../AdditionalSelectableFields.java | 27 +++++ .../generator/annotation/SelectableField.java | 33 ++++++ 14 files changed, 345 insertions(+), 26 deletions(-) create mode 100644 crd-generator/test/src/test/java/io/fabric8/crd/generator/approvaltests/selectablefield/SelectableField.java create mode 100644 crd-generator/test/src/test/java/io/fabric8/crd/generator/approvaltests/selectablefield/SelectableFieldSpec.java create mode 100644 crd-generator/test/src/test/resources/io/fabric8/crd/generator/approvaltests/CRDGeneratorApprovalTest.approvalTest.selectablefields.sample.fabric8.io.v1.approved.yml create mode 100644 generator-annotations/src/main/java/io/fabric8/crd/generator/annotation/AdditionalSelectableField.java create mode 100644 generator-annotations/src/main/java/io/fabric8/crd/generator/annotation/AdditionalSelectableFields.java create mode 100644 generator-annotations/src/main/java/io/fabric8/crd/generator/annotation/SelectableField.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 68a7b48968d..9205cd867b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ * Fix #6214: Java generator does not recognize fields in CRDs other than metadata, spec, and status #### Improvements -* Fix #3069: added AdditionalPrinterColumn type annotation to completely specify additional printer columns +* Fix #3069: (crd-generator) Add `@AdditionalPrinterColumn` to specify a printer column by JSON path. +* Fix #6392: (crd-generator) Add `@AdditionalSelectableField` and `@SelectableField` to specify selectable fields. * Fix #5264: Remove deprecated `Config.errorMessages` field * Fix #6008: removing the optional dependency on bouncy castle * Fix #6407: sundrio builder-annotations is not available via bom import diff --git a/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/AbstractCustomResourceHandler.java b/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/AbstractCustomResourceHandler.java index b5b73fc98c1..24d408130d2 100644 --- a/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/AbstractCustomResourceHandler.java +++ b/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/AbstractCustomResourceHandler.java @@ -18,6 +18,7 @@ import io.fabric8.crd.generator.annotation.AdditionalPrinterColumn; import io.fabric8.crd.generator.annotation.AdditionalPrinterColumn.Format; import io.fabric8.crd.generator.annotation.PrinterColumn; +import io.fabric8.crd.generator.annotation.SelectableField; import io.fabric8.crdv2.generator.AbstractJsonSchema.AnnotationMetadata; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.client.utils.Utils; @@ -44,6 +45,10 @@ void addPrinterColumn(String path, String column, String format, int priority, String type, String description); } + public interface SelectableFieldHandler { + void addSelectableField(String jsonPath); + } + protected void handlePrinterColumns(AbstractJsonSchema resolver, PrinterColumnHandler handler) { TreeMap sortedCols = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); resolver.getAdditionalPrinterColumns().forEach(apc -> sortedCols.put(apc.jsonPath(), new AnnotationMetadata(apc, null))); @@ -78,6 +83,14 @@ protected void handlePrinterColumns(AbstractJsonSchema resolver, PrinterCo }); } + protected void handleSelectableField(AbstractJsonSchema resolver, SelectableFieldHandler handler) { + TreeMap sortedCols = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + resolver.getAdditionalSelectableFields() + .forEach(apc -> sortedCols.put(apc.jsonPath(), new AnnotationMetadata(apc, null))); + sortedCols.putAll(resolver.getAllPaths(SelectableField.class)); + sortedCols.forEach((jsonPath, property) -> handler.addSelectableField(jsonPath)); + } + public abstract Stream>> finish(); } diff --git a/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/AbstractJsonSchema.java b/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/AbstractJsonSchema.java index 670e5a7c207..473f45ff5bc 100644 --- a/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/AbstractJsonSchema.java +++ b/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/AbstractJsonSchema.java @@ -29,10 +29,12 @@ import com.fasterxml.jackson.module.jsonSchema.types.StringSchema; import com.fasterxml.jackson.module.jsonSchema.types.ValueTypeSchema; import io.fabric8.crd.generator.annotation.AdditionalPrinterColumn; +import io.fabric8.crd.generator.annotation.AdditionalSelectableField; import io.fabric8.crd.generator.annotation.PreserveUnknownFields; import io.fabric8.crd.generator.annotation.PrinterColumn; import io.fabric8.crd.generator.annotation.SchemaFrom; import io.fabric8.crd.generator.annotation.SchemaSwap; +import io.fabric8.crd.generator.annotation.SelectableField; import io.fabric8.crdv2.generator.InternalSchemaSwaps.SwapResult; import io.fabric8.crdv2.generator.ResolvingContext.GeneratorObjectSchema; import io.fabric8.generator.annotation.Default; @@ -95,6 +97,7 @@ public abstract class AbstractJsonSchema dependentClasses = new HashSet<>(); private Set additionalPrinterColumns = new HashSet<>(); + private Set additionalSelectableFields = new HashSet<>(); public static class AnnotationMetadata { public final Annotation annotation; @@ -111,8 +114,12 @@ public AnnotationMetadata(Annotation annotation, KubernetesJSONSchemaProps schem public AbstractJsonSchema(ResolvingContext resolvingContext, Class def) { this.resolvingContext = resolvingContext; // TODO: could make this configurable, and could stop looking for single valued ones - or warn - Stream.of(SpecReplicas.class, StatusReplicas.class, LabelSelector.class, PrinterColumn.class) - .forEach(clazz -> pathMetadata.put(clazz, new LinkedHashMap<>())); + Stream.of( + SpecReplicas.class, + StatusReplicas.class, + LabelSelector.class, + PrinterColumn.class, + SelectableField.class).forEach(clazz -> pathMetadata.put(clazz, new LinkedHashMap<>())); this.root = resolveRoot(def); } @@ -129,7 +136,7 @@ public Optional getSinglePath(Class clazz) { return ofNullable(pathMetadata.get(clazz)).flatMap(m -> m.keySet().stream().findFirst()); } - public Map getAllPaths(Class clazz) { + public Map getAllPaths(Class clazz) { return ofNullable(pathMetadata.get(clazz)).orElse(new LinkedHashMap<>()); } @@ -145,6 +152,8 @@ private T resolveRoot(Class definition) { JsonSchema schema = resolvingContext.toJsonSchema(definition); consumeRepeatingAnnotation(definition, AdditionalPrinterColumn.class, additionalPrinterColumns::add); + consumeRepeatingAnnotation(definition, AdditionalSelectableField.class, + additionalSelectableFields::add); if (schema instanceof GeneratorObjectSchema) { return resolveObject(new LinkedHashMap<>(), schemaSwaps, schema, "kind", "apiVersion", "metadata"); } @@ -606,4 +615,8 @@ public Set getAdditionalPrinterColumns() { return additionalPrinterColumns; } + public Set getAdditionalSelectableFields() { + return additionalSelectableFields; + } + } diff --git a/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/v1/CustomResourceHandler.java b/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/v1/CustomResourceHandler.java index b55ee48564b..9ea7f87562a 100644 --- a/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/v1/CustomResourceHandler.java +++ b/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/v1/CustomResourceHandler.java @@ -85,6 +85,10 @@ public void addPrinterColumn(String path, String column, String format, int prio } }); + handleSelectableField(resolver, jsonPath -> builder.addNewSelectableField() + .withJsonPath(jsonPath) + .endSelectableField()); + resolver.getSinglePath(SpecReplicas.class).ifPresent(path -> { builder.editOrNewSubresources().editOrNewScale().withSpecReplicasPath(path).endScale().endSubresources(); }); diff --git a/crd-generator/api-v2/src/test/java/io/fabric8/crdv2/example/joke/JokeRequestSpec.java b/crd-generator/api-v2/src/test/java/io/fabric8/crdv2/example/joke/JokeRequestSpec.java index d8ed0f6e134..bdc7a96ef18 100644 --- a/crd-generator/api-v2/src/test/java/io/fabric8/crdv2/example/joke/JokeRequestSpec.java +++ b/crd-generator/api-v2/src/test/java/io/fabric8/crdv2/example/joke/JokeRequestSpec.java @@ -17,6 +17,7 @@ import com.fasterxml.jackson.annotation.JsonPropertyDescription; import io.fabric8.crd.generator.annotation.PrinterColumn; +import io.fabric8.crd.generator.annotation.SelectableField; public class JokeRequestSpec { @@ -39,6 +40,7 @@ public enum ExcludedTopic { explicit } + @SelectableField @PrinterColumn(name = "jokeCategory", priority = 1) @JsonPropertyDescription("category-description") private Category category = Category.Any; diff --git a/crd-generator/api-v2/src/test/java/io/fabric8/crdv2/generator/CRDGeneratorTest.java b/crd-generator/api-v2/src/test/java/io/fabric8/crdv2/generator/CRDGeneratorTest.java index 17084f18efe..582f0a7de4d 100644 --- a/crd-generator/api-v2/src/test/java/io/fabric8/crdv2/generator/CRDGeneratorTest.java +++ b/crd-generator/api-v2/src/test/java/io/fabric8/crdv2/generator/CRDGeneratorTest.java @@ -408,6 +408,7 @@ void jokerequestCRDShouldWork() { assertEquals(".status.category", columnDefinition.getJsonPath()); assertEquals("jokeCategory", columnDefinition.getName()); assertEquals(0, columnDefinition.getPriority()); + assertEquals(".spec.category", version.getSelectableFields().get(0).getJsonPath()); CustomResourceValidation schema = version.getSchema(); assertNotNull(schema); Map properties = schema.getOpenAPIV3Schema().getProperties(); diff --git a/crd-generator/test/src/test/java/io/fabric8/crd/generator/approvaltests/CRDGeneratorApprovalTest.java b/crd-generator/test/src/test/java/io/fabric8/crd/generator/approvaltests/CRDGeneratorApprovalTest.java index 4056d242379..458330908ac 100644 --- a/crd-generator/test/src/test/java/io/fabric8/crd/generator/approvaltests/CRDGeneratorApprovalTest.java +++ b/crd-generator/test/src/test/java/io/fabric8/crd/generator/approvaltests/CRDGeneratorApprovalTest.java @@ -29,6 +29,7 @@ import io.fabric8.crd.generator.approvaltests.nocyclic.NoCyclic; import io.fabric8.crd.generator.approvaltests.printercolum.PrinterColumn; import io.fabric8.crd.generator.approvaltests.replica.Replica; +import io.fabric8.crd.generator.approvaltests.selectablefield.SelectableField; import io.fabric8.kubernetes.client.CustomResource; import io.sundr.utils.Strings; import org.approvaltests.Approvals; @@ -181,6 +182,7 @@ static Stream crdApprovalCasesApiV2(String crdVersion) { final List cases = new ArrayList<>(); for (boolean parallel : new boolean[] { false, true }) { cases.add(new TestCase("printercolumns.sample.fabric8.io", crdVersion, parallel, PrinterColumn.class)); + cases.add(new TestCase("selectablefields.sample.fabric8.io", crdVersion, parallel, SelectableField.class)); } return cases.stream(); } diff --git a/crd-generator/test/src/test/java/io/fabric8/crd/generator/approvaltests/selectablefield/SelectableField.java b/crd-generator/test/src/test/java/io/fabric8/crd/generator/approvaltests/selectablefield/SelectableField.java new file mode 100644 index 00000000000..921a7eac678 --- /dev/null +++ b/crd-generator/test/src/test/java/io/fabric8/crd/generator/approvaltests/selectablefield/SelectableField.java @@ -0,0 +1,27 @@ +/* + * 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.crd.generator.approvaltests.selectablefield; + +import io.fabric8.crd.generator.annotation.AdditionalSelectableField; +import io.fabric8.kubernetes.client.CustomResource; +import io.fabric8.kubernetes.model.annotation.Group; +import io.fabric8.kubernetes.model.annotation.Version; + +@Version("v1alpha1") +@Group("sample.fabric8.io") +@AdditionalSelectableField(jsonPath = ".spec.deepLevel1.name") +public class SelectableField extends CustomResource { +} diff --git a/crd-generator/test/src/test/java/io/fabric8/crd/generator/approvaltests/selectablefield/SelectableFieldSpec.java b/crd-generator/test/src/test/java/io/fabric8/crd/generator/approvaltests/selectablefield/SelectableFieldSpec.java new file mode 100644 index 00000000000..927f51b41bc --- /dev/null +++ b/crd-generator/test/src/test/java/io/fabric8/crd/generator/approvaltests/selectablefield/SelectableFieldSpec.java @@ -0,0 +1,46 @@ +/* + * 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.crd.generator.approvaltests.selectablefield; + +import io.fabric8.crd.generator.annotation.SelectableField; +import lombok.Data; + +@Data +public class SelectableFieldSpec { + + @SelectableField + private String id; + + private DeepLevel1 deepLevel1; + + @Data + static class DeepLevel1 { + // targeted from @AdditionalSelectableField + private String name; + + @SelectableField + private Integer fromLevel1; + + private DeepLevel2 deepLevel2; + } + + @Data + static class DeepLevel2 { + @SelectableField + private Boolean fromLevel2; + } + +} diff --git a/crd-generator/test/src/test/resources/io/fabric8/crd/generator/approvaltests/CRDGeneratorApprovalTest.approvalTest.selectablefields.sample.fabric8.io.v1.approved.yml b/crd-generator/test/src/test/resources/io/fabric8/crd/generator/approvaltests/CRDGeneratorApprovalTest.approvalTest.selectablefields.sample.fabric8.io.v1.approved.yml new file mode 100644 index 00000000000..c3ac0aaa709 --- /dev/null +++ b/crd-generator/test/src/test/resources/io/fabric8/crd/generator/approvaltests/CRDGeneratorApprovalTest.approvalTest.selectablefields.sample.fabric8.io.v1.approved.yml @@ -0,0 +1,44 @@ +# Generated by Fabric8 CRDGenerator, manual edits might get overwritten! +apiVersion: "apiextensions.k8s.io/v1" +kind: "CustomResourceDefinition" +metadata: + name: "selectablefields.sample.fabric8.io" +spec: + group: "sample.fabric8.io" + names: + kind: "SelectableField" + plural: "selectablefields" + singular: "selectablefield" + scope: "Cluster" + versions: + - name: "v1alpha1" + schema: + openAPIV3Schema: + properties: + spec: + properties: + deepLevel1: + properties: + deepLevel2: + properties: + fromLevel2: + type: "boolean" + type: "object" + fromLevel1: + type: "integer" + name: + type: "string" + type: "object" + id: + type: "string" + type: "object" + status: + type: "object" + type: "object" + selectableFields: + - jsonPath: ".spec.deepLevel1.deepLevel2.fromLevel2" + - jsonPath: ".spec.deepLevel1.fromLevel1" + - jsonPath: ".spec.deepLevel1.name" + - jsonPath: ".spec.id" + served: true + storage: true diff --git a/doc/CRD-generator.md b/doc/CRD-generator.md index a63a821ecb0..672c5e9a480 100644 --- a/doc/CRD-generator.md +++ b/doc/CRD-generator.md @@ -371,6 +371,65 @@ The CRD generator will customize columns shown by the `kubectl get` command. Abo priority: 1 ``` +### io.fabric8.crd.generator.annotation.AdditionalPrinterColumn + +_since kubernetes-client 7.0.0 (crd-generator/api-v2)_ + +If a custom resource class is annotated with `io.fabric8.crd.generator.annotation.AdditionalPrinterColumn` + +```java +@AdditionalPrinterColumn(name = "Age", jsonPath = ".metadata.creationTimestamp", type = Type.DATE) +public class Example extends CustomResource {} +``` + +The CRD generator will add `additionalPrinterColumns`: + +```yaml + - additionalPrinterColumns: + - jsonPath: ".metadata.creationTimestamp" + name: "Age" + priority: 0 + type: "date" +``` + +### io.fabric8.crd.generator.annotation.SelectableField + +_since kubernetes-client 7.0.0 (crd-generator/api-v2)_ + +If a field or one of its accessors is annotated with `io.fabric8.crd.generator.annotation.SelectableField` + +```java +public class ExampleSpec { + @SelectableField + String category; +} +``` + +The CRD generator will add `selectableFields`: + +```yaml + - selectableFields: + - jsonPath: .spec.category +``` + +### io.fabric8.crd.generator.annotation.AdditionalSelectableField + +_since kubernetes-client 7.0.0 (crd-generator/api-v2)_ + +If a custom resource class is annotated with `io.fabric8.crd.generator.annotation.AdditionalSelectableField` + +```java +@AdditionalSelectableField(jsonPath = ".spec.category") +public class Example extends CustomResource {} +``` + +The CRD generator will add `selectableFields`: + +```yaml + - selectableFields: + - jsonPath: .spec.category +``` + ### io.fabric8.crd.generator.annotation.SchemaFrom If a field or one of its accessors is annotated with `io.fabric8.crd.generator.annotation.SchemaFrom` @@ -668,28 +727,31 @@ spec: ## Features cheatsheet -| Annotation | Description | -|-------------------------------------------------------------|---------------------------------------------------------------------------------------| -| `com.fasterxml.jackson.annotation.JsonProperty` | The field is named after the provided value instead of looking up the java field name | -| `com.fasterxml.jackson.annotation.JsonPropertyDescription` | The provided text is be embedded in the `description` of the field | -| `com.fasterxml.jackson.annotation.JsonIgnore` | The field is ignored | -| `io.fabric8.crd.generator.annotation.PreserveUnknownFields` | The field have `x-kubernetes-preserve-unknown-fields: true` defined | -| `com.fasterxml.jackson.annotation.JsonAnyGetter` | The corresponding object have `x-kubernetes-preserve-unknown-fields: true` defined | -| `com.fasterxml.jackson.annotation.JsonAnySetter` | The corresponding object have `x-kubernetes-preserve-unknown-fields: true` defined | -| `io.fabric8.generator.annotation.Min` | The field defines a validation `min` | -| `io.fabric8.generator.annotation.Max` | The field defines a validation `max` | -| `io.fabric8.generator.annotation.Pattern` | The field defines a validation `pattern` | -| `io.fabric8.generator.annotation.Nullable` | The field is marked as `nullable` | -| `io.fabric8.generator.annotation.Required` | The field is marked as `required` | -| `io.fabric8.generator.annotation.ValidationRule` | The field or object is validated by a CEL rule | -| `io.fabric8.crd.generator.annotation.SchemaFrom` | The field type for the generation is the one coming from the annotation | -| `io.fabric8.crd.generator.annotation.SchemaSwap` | Similar to SchemaFrom, but can be applied at any point in the class hierarchy | -| `io.fabric8.crd.generator.annotation.Annotations` | Additional `annotations` in `metadata` | -| `io.fabric8.crd.generator.annotation.Labels` | Additional `labels` in `metadata` | -| `io.fabric8.crd.generator.annotation.PrinterColumn` | Customize columns shown by the `kubectl get` command | -| `io.fabric8.kubernetes.model.annotation.SpecReplicas` | The field is used in scale subresource as `specReplicaPath` | -| `io.fabric8.kubernetes.model.annotation.StatusReplicas` | The field is used in scale subresource as `statusReplicaPath` | -| `io.fabric8.kubernetes.model.annotation.LabelSelector` | The field is used in scale subresource as `labelSelectorPath` | +| Annotation | Description | +|-----------------------------------------------------------------|---------------------------------------------------------------------------------------------| +| `com.fasterxml.jackson.annotation.JsonProperty` | The field is named after the provided value instead of looking up the java field name | +| `com.fasterxml.jackson.annotation.JsonPropertyDescription` | The provided text is be embedded in the `description` of the field | +| `com.fasterxml.jackson.annotation.JsonIgnore` | The field is ignored | +| `io.fabric8.crd.generator.annotation.PreserveUnknownFields` | The field have `x-kubernetes-preserve-unknown-fields: true` defined | +| `com.fasterxml.jackson.annotation.JsonAnyGetter` | The corresponding object have `x-kubernetes-preserve-unknown-fields: true` defined | +| `com.fasterxml.jackson.annotation.JsonAnySetter` | The corresponding object have `x-kubernetes-preserve-unknown-fields: true` defined | +| `io.fabric8.generator.annotation.Min` | The field defines a validation `min` | +| `io.fabric8.generator.annotation.Max` | The field defines a validation `max` | +| `io.fabric8.generator.annotation.Pattern` | The field defines a validation `pattern` | +| `io.fabric8.generator.annotation.Nullable` | The field is marked as `nullable` | +| `io.fabric8.generator.annotation.Required` | The field is marked as `required` | +| `io.fabric8.generator.annotation.ValidationRule` | The field or object is validated by a CEL rule | +| `io.fabric8.crd.generator.annotation.SchemaFrom` | The field type for the generation is the one coming from the annotation | +| `io.fabric8.crd.generator.annotation.SchemaSwap` | Similar to SchemaFrom, but can be applied at any point in the class hierarchy | +| `io.fabric8.crd.generator.annotation.Annotations` | Additional `annotations` in `metadata` | +| `io.fabric8.crd.generator.annotation.Labels` | Additional `labels` in `metadata` | +| `io.fabric8.crd.generator.annotation.PrinterColumn` | Define the field as PrinterColumn, so that it will be shown by the `kubectl get` command. | +| `io.fabric8.crd.generator.annotation.AdditionalPrinterColumn` | Define a PrinterColumn by JSON path, so that it will be shown by the `kubectl get` command. | +| `io.fabric8.crd.generator.annotation.SelectableField` | Define the field as selectable, so that it can be used for filtering. | +| `io.fabric8.crd.generator.annotation.AdditionalSelectableField` | Define a SelectableField by JSON path, so that it can be used for filtering. | +| `io.fabric8.kubernetes.model.annotation.SpecReplicas` | The field is used in scale subresource as `specReplicaPath` | +| `io.fabric8.kubernetes.model.annotation.StatusReplicas` | The field is used in scale subresource as `statusReplicaPath` | +| `io.fabric8.kubernetes.model.annotation.LabelSelector` | The field is used in scale subresource as `labelSelectorPath` | A field of type `com.fasterxml.jackson.databind.JsonNode` is encoded as an empty object with `x-kubernetes-preserve-unknown-fields: true` defined. diff --git a/generator-annotations/src/main/java/io/fabric8/crd/generator/annotation/AdditionalSelectableField.java b/generator-annotations/src/main/java/io/fabric8/crd/generator/annotation/AdditionalSelectableField.java new file mode 100644 index 00000000000..8459407bb5a --- /dev/null +++ b/generator-annotations/src/main/java/io/fabric8/crd/generator/annotation/AdditionalSelectableField.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.crd.generator.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Defines a selectable field. Must be placed at the root of the + * custom resource. + * + * @see Kubernetes + * Docs - Field Selectors + */ +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Repeatable(AdditionalSelectableFields.class) +public @interface AdditionalSelectableField { + + /** + * The JSON Path to the field. + * + * @return the JSON path + */ + String jsonPath(); + +} diff --git a/generator-annotations/src/main/java/io/fabric8/crd/generator/annotation/AdditionalSelectableFields.java b/generator-annotations/src/main/java/io/fabric8/crd/generator/annotation/AdditionalSelectableFields.java new file mode 100644 index 00000000000..90c43189ee4 --- /dev/null +++ b/generator-annotations/src/main/java/io/fabric8/crd/generator/annotation/AdditionalSelectableFields.java @@ -0,0 +1,27 @@ +/* + * 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.crd.generator.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface AdditionalSelectableFields { + AdditionalSelectableField[] value(); +} diff --git a/generator-annotations/src/main/java/io/fabric8/crd/generator/annotation/SelectableField.java b/generator-annotations/src/main/java/io/fabric8/crd/generator/annotation/SelectableField.java new file mode 100644 index 00000000000..9515495ea60 --- /dev/null +++ b/generator-annotations/src/main/java/io/fabric8/crd/generator/annotation/SelectableField.java @@ -0,0 +1,33 @@ +/* + * 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.crd.generator.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marks a field as selectable. + * + * @see Kubernetes + * Docs - Field Selectors + */ +@Target({ ElementType.FIELD, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface SelectableField { +}