diff --git a/crd-generator/api/pom.xml b/crd-generator/api/pom.xml index bc8690b6778..f367dae7730 100644 --- a/crd-generator/api/pom.xml +++ b/crd-generator/api/pom.xml @@ -36,6 +36,11 @@ compile + + io.fabric8 + generator-annotations + + io.fabric8 kubernetes-model-common diff --git a/crd-generator/api/src/main/java/io/fabric8/crd/generator/AbstractJsonSchema.java b/crd-generator/api/src/main/java/io/fabric8/crd/generator/AbstractJsonSchema.java index 59fbfd70d6b..db16adf282b 100644 --- a/crd-generator/api/src/main/java/io/fabric8/crd/generator/AbstractJsonSchema.java +++ b/crd-generator/api/src/main/java/io/fabric8/crd/generator/AbstractJsonSchema.java @@ -17,7 +17,6 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import io.fabric8.crd.generator.annotation.SchemaSwap; import io.fabric8.crd.generator.utils.Types; import io.fabric8.kubernetes.api.model.Duration; import io.fabric8.kubernetes.api.model.IntOrString; @@ -78,6 +77,11 @@ public abstract class AbstractJsonSchema { public static final String ANNOTATION_JSON_IGNORE = "com.fasterxml.jackson.annotation.JsonIgnore"; public static final String ANNOTATION_JSON_ANY_GETTER = "com.fasterxml.jackson.annotation.JsonAnyGetter"; public static final String ANNOTATION_JSON_ANY_SETTER = "com.fasterxml.jackson.annotation.JsonAnySetter"; + public static final String ANNOTATION_MIN = "io.fabric8.generator.annotation.Min"; + public static final String ANNOTATION_MAX = "io.fabric8.generator.annotation.Max"; + public static final String ANNOTATION_PATTERN = "io.fabric8.generator.annotation.Pattern"; + public static final String ANNOTATION_NULLABLE = "io.fabric8.generator.annotation.Nullable"; + public static final String ANNOTATION_REQUIRED = "io.fabric8.generator.annotation.Required"; public static final String ANNOTATION_NOT_NULL = "javax.validation.constraints.NotNull"; public static final String ANNOTATION_SCHEMA_FROM = "io.fabric8.crd.generator.annotation.SchemaFrom"; public static final String ANNOTATION_SCHEMA_SWAP = "io.fabric8.crd.generator.annotation.SchemaSwap"; @@ -110,6 +114,51 @@ public static String getSchemaTypeFor(TypeRef typeRef) { return type; } + protected static class SchemaPropsOptions { + final Optional min; + final Optional max; + final Optional pattern; + final boolean nullable; + final boolean required; + + SchemaPropsOptions() { + min = Optional.empty(); + max = Optional.empty(); + pattern = Optional.empty(); + nullable = false; + required = false; + } + + public SchemaPropsOptions(Optional min, Optional max, Optional pattern, + boolean nullable, boolean required) { + this.min = min; + this.max = max; + this.pattern = pattern; + this.nullable = nullable; + this.required = required; + } + + public Optional getMin() { + return min; + } + + public Optional getMax() { + return max; + } + + public Optional getPattern() { + return pattern; + } + + public boolean isNullable() { + return nullable; + } + + public boolean getRequired() { + return nullable; + } + } + /** * Creates the JSON schema for the particular {@link TypeDef}. This is template method where * sub-classes are supposed to provide specific implementations of abstract methods. @@ -264,7 +313,15 @@ private T internalFromImpl(TypeDef definition, Set visited, List min; + private Optional max; + private Optional pattern; + private boolean nullable; private boolean required; private boolean ignored; private boolean preserveUnknownFields; @@ -297,6 +358,10 @@ private PropertyOrAccessor(Collection annotations, String name, S this.name = name; this.propertyName = propertyName; type = isMethod ? "accessor" : "field"; + + min = Optional.empty(); + max = Optional.empty(); + pattern = Optional.empty(); } static PropertyOrAccessor fromProperty(Property property) { @@ -310,7 +375,22 @@ static PropertyOrAccessor fromMethod(Method method, String propertyName) { public void process() { annotations.forEach(a -> { switch (a.getClassRef().getFullyQualifiedName()) { + case ANNOTATION_NULLABLE: + nullable = true; + break; + case ANNOTATION_MAX: + max = Optional.of((Double) a.getParameters().get("value")); + break; + case ANNOTATION_MIN: + min = Optional.of((Double) a.getParameters().get("value")); + break; + case ANNOTATION_PATTERN: + pattern = Optional.of((String) a.getParameters().get("value")); + break; case ANNOTATION_NOT_NULL: + LOGGER.warn("Annotation: {} on property: {} is deprecated. Please use: {} instead", ANNOTATION_NOT_NULL, name, + ANNOTATION_REQUIRED); + case ANNOTATION_REQUIRED: required = true; break; case ANNOTATION_JSON_PROPERTY: @@ -343,6 +423,22 @@ public String getRenamedTo() { return renamedTo; } + public boolean isNullable() { + return nullable; + } + + public Optional getMax() { + return max; + } + + public Optional getMin() { + return min; + } + + public Optional getPattern() { + return pattern; + } + public boolean isRequired() { return required; } @@ -387,6 +483,10 @@ private static class PropertyFacade { private final Set matchedSchemaSwaps; private String renamedTo; private String description; + private Optional min; + private Optional max; + private Optional pattern; + private boolean nullable; private boolean required; private boolean ignored; private boolean preserveUnknownFields; @@ -414,6 +514,9 @@ public PropertyFacade(Property property, Map potentialAccessors, if (method != null) { propertyOrAccessors.add(PropertyOrAccessor.fromMethod(method, name)); } + min = Optional.empty(); + max = Optional.empty(); + pattern = Optional.empty(); } public Property process() { @@ -450,6 +553,22 @@ public Property process() { } } + if (p.getMin().isPresent()) { + min = p.getMin(); + } + + if (p.getMax().isPresent()) { + max = p.getMax(); + } + + if (p.getPattern().isPresent()) { + pattern = p.getPattern(); + } + + if (p.isNullable()) { + nullable = true; + } + if (p.isRequired()) { required = true; } else if (p.isIgnored()) { @@ -527,7 +646,7 @@ private String extractUpdatedNameFromJacksonPropertyIfPresent(Property property) * @param builder the builder representing the schema being built * @param schema the built schema for the property being added */ - public abstract void addProperty(Property property, B builder, T schema); + public abstract void addProperty(Property property, B builder, T schema, SchemaPropsOptions options); /** * Finishes up the process by actually building the final JSON schema based on the provided diff --git a/crd-generator/api/src/main/java/io/fabric8/crd/generator/v1/JsonSchema.java b/crd-generator/api/src/main/java/io/fabric8/crd/generator/v1/JsonSchema.java index 9875c5b9f3a..01ab8882881 100644 --- a/crd-generator/api/src/main/java/io/fabric8/crd/generator/v1/JsonSchema.java +++ b/crd-generator/api/src/main/java/io/fabric8/crd/generator/v1/JsonSchema.java @@ -22,6 +22,7 @@ import io.sundr.model.Property; import io.sundr.model.TypeDef; import io.sundr.model.TypeRef; + import java.util.List; public class JsonSchema extends AbstractJsonSchema { @@ -29,11 +30,11 @@ public class JsonSchema extends AbstractJsonSchema requir @Override protected JSONSchemaProps arrayLikeProperty(JSONSchemaProps schema) { return new JSONSchemaPropsBuilder() - .withType("array") - .withNewItems() - .withSchema(schema) - .and() - .build(); + .withType("array") + .withNewItems() + .withSchema(schema) + .and() + .build(); } @Override protected JSONSchemaProps mapLikeProperty(JSONSchemaProps schema) { return new JSONSchemaPropsBuilder() - .withType("object") - .withNewAdditionalProperties() - .withSchema(schema) - .endAdditionalProperties() - .build(); + .withType("object") + .withNewAdditionalProperties() + .withSchema(schema) + .endAdditionalProperties() + .build(); } @Override @@ -108,7 +117,7 @@ protected JSONSchemaProps enumProperty(JsonNode... enumValues) { @Override protected JSONSchemaProps addDescription(JSONSchemaProps schema, String description) { return new JSONSchemaPropsBuilder(schema) - .withDescription(description) - .build(); + .withDescription(description) + .build(); } } diff --git a/crd-generator/api/src/main/java/io/fabric8/crd/generator/v1beta1/JsonSchema.java b/crd-generator/api/src/main/java/io/fabric8/crd/generator/v1beta1/JsonSchema.java index 06729c515ca..732a6514d54 100644 --- a/crd-generator/api/src/main/java/io/fabric8/crd/generator/v1beta1/JsonSchema.java +++ b/crd-generator/api/src/main/java/io/fabric8/crd/generator/v1beta1/JsonSchema.java @@ -22,6 +22,7 @@ import io.sundr.model.Property; import io.sundr.model.TypeDef; import io.sundr.model.TypeRef; + import java.util.List; public class JsonSchema extends AbstractJsonSchema { @@ -29,21 +30,21 @@ public class JsonSchema extends AbstractJsonSchema requir @Override protected JSONSchemaProps arrayLikeProperty(JSONSchemaProps schema) { return new JSONSchemaPropsBuilder() - .withType("array") - .withNewItems() - .withSchema(schema) - .and() - .build(); + .withType("array") + .withNewItems() + .withSchema(schema) + .and() + .build(); } @Override protected JSONSchemaProps mapLikeProperty(JSONSchemaProps schema) { return new JSONSchemaPropsBuilder() - .withType("object") - .withNewAdditionalProperties() - .withSchema(schema) - .endAdditionalProperties() - .build(); + .withType("object") + .withNewAdditionalProperties() + .withSchema(schema) + .endAdditionalProperties() + .build(); } @Override protected JSONSchemaProps singleProperty(String typeName) { return new JSONSchemaPropsBuilder() - .withType(typeName) - .build(); + .withType(typeName) + .build(); } @Override @@ -111,7 +120,7 @@ protected JSONSchemaProps enumProperty(JsonNode... enumValues) { @Override protected JSONSchemaProps addDescription(JSONSchemaProps schema, String description) { return new JSONSchemaPropsBuilder(schema) - .withDescription(description) - .build(); + .withDescription(description) + .build(); } } diff --git a/crd-generator/api/src/test/java/io/fabric8/crd/example/annotated/AnnotatedSpec.java b/crd-generator/api/src/test/java/io/fabric8/crd/example/annotated/AnnotatedSpec.java index a45c891f1b0..7ff0b398eda 100644 --- a/crd-generator/api/src/test/java/io/fabric8/crd/example/annotated/AnnotatedSpec.java +++ b/crd-generator/api/src/test/java/io/fabric8/crd/example/annotated/AnnotatedSpec.java @@ -18,8 +18,12 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import io.fabric8.generator.annotation.Max; +import io.fabric8.generator.annotation.Min; +import io.fabric8.generator.annotation.Nullable; +import io.fabric8.generator.annotation.Pattern; +import io.fabric8.generator.annotation.Required; -import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; public class AnnotatedSpec { @@ -29,10 +33,16 @@ public class AnnotatedSpec { private int foo; @JsonProperty private String unnamed; + private int min; + private int max; + private String singleDigit; + private String nullable; @NotNull private boolean emptySetter; + @Required + private boolean emptySetter2; private AnnotatedEnum anEnum; - @Min(0) // a non-string value attribute + @javax.validation.constraints.Min(0) // a non-string value attribute private int sizedField; @JsonIgnore @@ -56,11 +66,36 @@ public boolean getIgnoredBar() { return ignoredBar; } + @Max(5.0) + public int getMax() { + return 1; + } + + @Min(-5) + public int getMin() { + return 1; + } + + @Pattern("\\b[1-9]\\b") + public String getSingleDigit() { + return "1"; + } + + @Nullable + public String getNullable() { + return null; + } + @JsonProperty public void setEmptySetter(boolean emptySetter) { this.emptySetter = emptySetter; } + @JsonProperty + public void setEmptySetter2(boolean emptySetter2) { + this.emptySetter2 = emptySetter2; + } + public enum AnnotatedEnum { non, @JsonProperty("oui") diff --git a/crd-generator/api/src/test/java/io/fabric8/crd/generator/v1/JsonSchemaTest.java b/crd-generator/api/src/test/java/io/fabric8/crd/generator/v1/JsonSchemaTest.java index a0715d3cd44..1790fb63b3b 100644 --- a/crd-generator/api/src/test/java/io/fabric8/crd/generator/v1/JsonSchemaTest.java +++ b/crd-generator/api/src/test/java/io/fabric8/crd/generator/v1/JsonSchemaTest.java @@ -18,10 +18,10 @@ import com.fasterxml.jackson.databind.JsonNode; import io.fabric8.crd.example.annotated.Annotated; import io.fabric8.crd.example.basic.Basic; +import io.fabric8.crd.example.extraction.Extraction; import io.fabric8.crd.example.extraction.IncorrectExtraction; import io.fabric8.crd.example.extraction.IncorrectExtraction2; import io.fabric8.crd.example.json.ContainingJson; -import io.fabric8.crd.example.extraction.Extraction; import io.fabric8.crd.example.person.Person; import io.fabric8.crd.generator.utils.Types; import io.fabric8.kubernetes.api.model.apiextensions.v1.JSONSchemaProps; @@ -44,16 +44,16 @@ void shouldCreateJsonSchemaFromClass() { Map properties = schema.getProperties(); assertEquals(7, properties.size()); final List personTypes = properties.get("type").getEnum().stream().map(JsonNode::asText) - .collect(Collectors.toList()); + .collect(Collectors.toList()); assertEquals(2, personTypes.size()); assertTrue(personTypes.contains("crazy")); assertTrue(personTypes.contains("crazier")); final Map addressProperties = properties.get("addresses").getItems() - .getSchema().getProperties(); + .getSchema().getProperties(); assertEquals(5, addressProperties.size()); final List addressTypes = addressProperties.get("type").getEnum().stream() - .map(JsonNode::asText) - .collect(Collectors.toList()); + .map(JsonNode::asText) + .collect(Collectors.toList()); assertEquals(2, addressTypes.size()); assertTrue(addressTypes.contains("home")); assertTrue(addressTypes.contains("work")); @@ -80,7 +80,7 @@ void shouldAugmentPropertiesSchemaFromAnnotations() { assertEquals(2, properties.size()); final JSONSchemaProps specSchema = properties.get("spec"); Map spec = specSchema.getProperties(); - assertEquals(6, spec.size()); + assertEquals(11, spec.size()); // check descriptions are present assertTrue(spec.containsKey("from-field")); @@ -97,10 +97,35 @@ void shouldAugmentPropertiesSchemaFromAnnotations() { assertNull(spec.get("emptySetter").getDescription()); assertTrue(spec.containsKey("anEnum")); + final JSONSchemaProps min = spec.get("min"); + assertEquals(-5.0, min.getMinimum()); + assertNull(min.getMaximum()); + assertNull(min.getPattern()); + assertNull(min.getNullable()); + + final JSONSchemaProps max = spec.get("max"); + assertEquals(5.0, max.getMaximum()); + assertNull(max.getMinimum()); + assertNull(max.getPattern()); + assertNull(max.getNullable()); + + final JSONSchemaProps pattern = spec.get("singleDigit"); + assertEquals("\\b[1-9]\\b", pattern.getPattern()); + assertNull(pattern.getMinimum()); + assertNull(pattern.getMaximum()); + assertNull(pattern.getNullable()); + + final JSONSchemaProps nullable = spec.get("nullable"); + assertTrue(nullable.getNullable()); + assertNull(nullable.getMinimum()); + assertNull(nullable.getMaximum()); + assertNull(nullable.getPattern()); + // check required list, should register properties with their modified name if needed final List required = specSchema.getRequired(); - assertEquals(2, required.size()); + assertEquals(3, required.size()); assertTrue(required.contains("emptySetter")); + assertTrue(required.contains("emptySetter2")); assertTrue(required.contains("from-getter")); // check the enum values diff --git a/doc/CRD-generator.md b/doc/CRD-generator.md index 3a69a2fdcb7..4275c1ae3df 100644 --- a/doc/CRD-generator.md +++ b/doc/CRD-generator.md @@ -152,9 +152,107 @@ The field will be skipped in the generated CRD and will not appear in the schema type: object ``` -### javax.validation.constraints.NotNull +### io.fabric8.generator.annotation.Min -If a field or one of its accessors is annotated with `javax.validation.constraints.NotNull` +If a field or one of its accessors is annotated with `io.fabric8.generator.annotation.Min` + +```java +public class ExampleSpec { + @Min(-1) + int someValue; +} +``` + +The field will have the `minimum` property in the generated CRD, such as: + +```yaml + spec: + properties: + someValue: + minimum: -1.0 + type: integer + required: + - someValue + type: object +``` + +### io.fabric8.generator.annotation.Max + +If a field or one of its accessors is annotated with `io.fabric8.generator.annotation.Max` + +```java +public class ExampleSpec { + @Min(1) + int someValue; +} +``` + +The field will have the `maximum` property in the generated CRD, such as: + +```yaml + spec: + properties: + someValue: + maximum: 1.0 + type: integer + required: + - someValue + type: object +``` + +### io.fabric8.generator.annotation.Pattern + +If a field or one of its accessors is annotated with `io.fabric8.generator.annotation.Pattern` + +```java +public class ExampleSpec { + @Pattern("\\b[1-9]\\b") + String someValue; +} +``` + +The field will have the `pattern` property in the generated CRD, such as: + +```yaml + spec: + properties: + someValue: + maximum: "\\b[1-9]\\b" + type: string + required: + - someValue + type: object +``` + +### io.fabric8.generator.annotation.Nullable + +If a field or one of its accessors is annotated with `io.fabric8.generator.annotation.Nullable` + +```java +public class ExampleSpec { + @Nullable + String someValue; +} +``` + +The field will have the `nullable` property in the generated CRD, such as: + +```yaml + spec: + properties: + someValue: + nullable: true + type: string + required: + - someValue + type: object +``` + +### io.fabric8.generator.annotation.Required + +__DEPRECATED:__ `javax.validation.constraints.NotNull` + +If a field or one of its accessors is annotated with `io.fabric8.generator.annotation.Required` ```java public class ExampleSpec { @@ -268,7 +366,11 @@ Corresponding `x-kubernetes-preserve-unknown-fields: true` will be generated in | `com.fasterxml.jackson.annotation.JsonIgnore` | The field is ignored | | `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 | -| `javax.validation.constraints.NotNull` | The field is marked as `required` | +| `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.crd.generator.annotation.SchemaFrom` | The field type for the generation is the one coming from the annotation | | `io.fabric8.crd.generator.annotation.SchemaSwap` | Same as SchemaFrom, but can be applied at any point in the class hierarchy | diff --git a/generator-annotations/pom.xml b/generator-annotations/pom.xml new file mode 100644 index 00000000000..5ca98b912b2 --- /dev/null +++ b/generator-annotations/pom.xml @@ -0,0 +1,33 @@ + + + + 4.0.0 + + io.fabric8 + kubernetes-client-project + 6.1-SNAPSHOT + + + generator-annotations + jar + Fabric8 :: Generator Annotations + + diff --git a/generator-annotations/src/main/java/io/fabric8/generator/annotation/Max.java b/generator-annotations/src/main/java/io/fabric8/generator/annotation/Max.java new file mode 100644 index 00000000000..4f371db245a --- /dev/null +++ b/generator-annotations/src/main/java/io/fabric8/generator/annotation/Max.java @@ -0,0 +1,24 @@ +/** + * 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.generator.annotation; + +import java.lang.annotation.*; + +@Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface Max { + double value(); +} diff --git a/generator-annotations/src/main/java/io/fabric8/generator/annotation/Min.java b/generator-annotations/src/main/java/io/fabric8/generator/annotation/Min.java new file mode 100644 index 00000000000..3876efbab19 --- /dev/null +++ b/generator-annotations/src/main/java/io/fabric8/generator/annotation/Min.java @@ -0,0 +1,24 @@ +/** + * 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.generator.annotation; + +import java.lang.annotation.*; + +@Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface Min { + double value(); +} diff --git a/generator-annotations/src/main/java/io/fabric8/generator/annotation/Nullable.java b/generator-annotations/src/main/java/io/fabric8/generator/annotation/Nullable.java new file mode 100644 index 00000000000..88238c3cd9a --- /dev/null +++ b/generator-annotations/src/main/java/io/fabric8/generator/annotation/Nullable.java @@ -0,0 +1,23 @@ +/** + * 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.generator.annotation; + +import java.lang.annotation.*; + +@Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface Nullable { +} diff --git a/generator-annotations/src/main/java/io/fabric8/generator/annotation/Pattern.java b/generator-annotations/src/main/java/io/fabric8/generator/annotation/Pattern.java new file mode 100644 index 00000000000..e5c7c739281 --- /dev/null +++ b/generator-annotations/src/main/java/io/fabric8/generator/annotation/Pattern.java @@ -0,0 +1,24 @@ +/** + * 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.generator.annotation; + +import java.lang.annotation.*; + +@Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface Pattern { + String value(); +} diff --git a/generator-annotations/src/main/java/io/fabric8/generator/annotation/Required.java b/generator-annotations/src/main/java/io/fabric8/generator/annotation/Required.java new file mode 100644 index 00000000000..5d83c708f2e --- /dev/null +++ b/generator-annotations/src/main/java/io/fabric8/generator/annotation/Required.java @@ -0,0 +1,23 @@ +/** + * 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.generator.annotation; + +import java.lang.annotation.*; + +@Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface Required { +} diff --git a/pom.xml b/pom.xml index c6ab4d4b495..c9601f7e3c9 100644 --- a/pom.xml +++ b/pom.xml @@ -192,6 +192,7 @@ platforms kubernetes-tests uberjar + generator-annotations crd-generator java-generator httpclient-okhttp @@ -200,6 +201,11 @@ + + io.fabric8 + generator-annotations + ${project.version} + io.fabric8 java-generator-core