Skip to content

Commit

Permalink
fix: adds an additional printer column annotation
Browse files Browse the repository at this point in the history
closes: #3069

Signed-off-by: Steve Hawkins <[email protected]>
  • Loading branch information
shawkins committed Sep 30, 2024
1 parent ac682f8 commit d8d7ec0
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* 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 #5264: Remove deprecated `Config.errorMessages` field
* Fix #6008: removing the optional dependency on bouncy castle
* Fix #6230: introduced Quantity.multiply(int) to allow for Quantity multiplication by an integer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package io.fabric8.crdv2.generator;

import io.fabric8.crd.generator.annotation.AdditionalPrinterColumn;
import io.fabric8.crd.generator.annotation.PrinterColumn;
import io.fabric8.crdv2.generator.AbstractJsonSchema.AnnotationMetadata;
import io.fabric8.kubernetes.api.model.HasMetadata;
Expand Down Expand Up @@ -44,26 +45,42 @@ void addPrinterColumn(String path, String column, String format,

protected void handlePrinterColumns(AbstractJsonSchema<?, ?> resolver, PrinterColumnHandler handler) {
TreeMap<String, AnnotationMetadata> sortedCols = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
resolver.getAdditionalPrinterColumns().forEach(apc -> sortedCols.put(apc.path(), new AnnotationMetadata(apc, null)));
sortedCols.putAll(resolver.getAllPaths(PrinterColumn.class));
sortedCols.forEach((path, property) -> {
PrinterColumn printerColumn = ((PrinterColumn) property.annotation);
String column = printerColumn.name();
String column;
String type;
String format;
int priority;
String description;
if (property.annotation instanceof AdditionalPrinterColumn) {
AdditionalPrinterColumn printerColumn = ((AdditionalPrinterColumn) property.annotation);
column = printerColumn.name();
format = printerColumn.format();
priority = printerColumn.priority();
type = printerColumn.getType();
description = printerColumn.getDescription();
} else {
PrinterColumn printerColumn = ((PrinterColumn) property.annotation);
column = printerColumn.name();
format = printerColumn.format();
priority = printerColumn.priority();
type = property.schema.getType();

// TODO: add description to the annotation? The previous logic considered the comments, which are not available here
description = property.schema.getDescription();
}

if (Utils.isNullOrEmpty(column)) {
column = path.substring(path.lastIndexOf(".") + 1).toUpperCase();
}
String format = printerColumn.format();
format = Utils.isNotNullOrEmpty(format) ? format : null;
int priority = printerColumn.priority();
String type = property.schema.getType();
if ("object".equals(type) || "array".equals(type)) {
LOGGER.warn("Printer column '{}' has a type '{}' that is not allowed, will use string intead", column, type);
type = "string";
} else if ("string".equals(type) && "date".equals(property.schema.getFormat())) {
type = "date";
}

// TODO: add description to the annotation? The previous logic considered the comments, which are not available here
String description = property.schema.getDescription();
description = Utils.isNotNullOrEmpty(description) ? description : null;

handler.addPrinterColumn(path, column, format, priority, type, description);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.fasterxml.jackson.module.jsonSchema.types.ReferenceSchema;
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.PreserveUnknownFields;
import io.fabric8.crd.generator.annotation.PrinterColumn;
import io.fabric8.crd.generator.annotation.SchemaFrom;
Expand Down Expand Up @@ -93,6 +94,7 @@ public abstract class AbstractJsonSchema<T extends KubernetesJSONSchemaProps, V
private ResolvingContext resolvingContext;
private T root;
private Set<String> dependentClasses = new HashSet<>();
private Set<AdditionalPrinterColumn> additionalPrinterColumns = new HashSet<>();

public static class AnnotationMetadata {
public final Annotation annotation;
Expand Down Expand Up @@ -141,6 +143,8 @@ public Map<String, AnnotationMetadata> getAllPaths(Class<PrinterColumn> clazz) {
private T resolveRoot(Class<?> definition) {
InternalSchemaSwaps schemaSwaps = new InternalSchemaSwaps();
JsonSchema schema = resolvingContext.toJsonSchema(definition);
consumeRepeatingAnnotation(definition, AdditionalPrinterColumn.class,
additionalPrinterColumns::add);
if (schema instanceof GeneratorObjectSchema) {
return resolveObject(new LinkedHashMap<>(), schemaSwaps, schema, "kind", "apiVersion", "metadata");
}
Expand Down Expand Up @@ -598,4 +602,8 @@ private static String mapNotEmpty(String s) {

protected abstract T raw();

public Set<AdditionalPrinterColumn> getAdditionalPrinterColumns() {
return additionalPrinterColumns;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package io.fabric8.crdv2.example.joke;

import io.fabric8.crd.generator.annotation.AdditionalPrinterColumn;
import io.fabric8.kubernetes.api.model.Namespaced;
import io.fabric8.kubernetes.client.CustomResource;
import io.fabric8.kubernetes.model.annotation.Group;
Expand All @@ -24,6 +25,7 @@
@Group("samples.javaoperatorsdk.io")
@Version("v1alpha1")
@ShortNames("jr")
@AdditionalPrinterColumn(name = "Age", path = ".metadata.creationTimestamp", getType = "date")
public class JokeRequest extends CustomResource<JokeRequestSpec, JokeRequestStatus> implements Namespaced {

}
Original file line number Diff line number Diff line change
Expand Up @@ -387,18 +387,23 @@ void jokerequestCRDShouldWork() {
// printer columns should be ordered in the alphabetical order of their json path
final List<CustomResourceColumnDefinition> printerColumns = version
.getAdditionalPrinterColumns();
assertEquals(3, printerColumns.size());
assertEquals(4, printerColumns.size());
CustomResourceColumnDefinition columnDefinition = printerColumns.get(0);
assertEquals("date", columnDefinition.getType());
assertEquals(".metadata.creationTimestamp", columnDefinition.getJsonPath());
assertEquals("Age", columnDefinition.getName());
assertEquals(0, columnDefinition.getPriority());
columnDefinition = printerColumns.get(1);
assertEquals("string", columnDefinition.getType());
assertEquals(".spec.category", columnDefinition.getJsonPath());
assertEquals("jokeCategory", columnDefinition.getName());
assertEquals(1, columnDefinition.getPriority());
columnDefinition = printerColumns.get(1);
columnDefinition = printerColumns.get(2);
assertEquals("string", columnDefinition.getType());
assertEquals(".spec.excluded", columnDefinition.getJsonPath());
assertEquals("excludedTopics", columnDefinition.getName());
assertEquals(0, columnDefinition.getPriority());
columnDefinition = printerColumns.get(2);
columnDefinition = printerColumns.get(3);
assertEquals("string", columnDefinition.getType());
assertEquals(".status.category", columnDefinition.getJsonPath());
assertEquals("jokeCategory", columnDefinition.getName());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* 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 an additional printer column. Must be placed at the root of the custom resource.
*/
@Repeatable(AdditionalPrinterColumns.class)
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface AdditionalPrinterColumn {

/**
* The name of the column.
* An empty column name implies the use of the last path element
*
* @return the column name, or empty string if the last path element should be used.
*/
String name() default "";

/**
* The printer column format.
*
* @return the format or empty string if no format is specified.
*/
String format() default "";

/**
* The printer column priority.
*
* @return the priority or 0 if no priority is specified.
*/
int priority() default 0;

/**
* The JSON Path to the field
*
* @return
*/
String path();

/**
* The type of the printer column
*
* @return the type
*/
String getType();

/**
* The description of the printer column
*
* @return the description
*/
String getDescription() default "";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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;

/**
* A container for multiple {@link AdditionalPrinterColumn}s
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface AdditionalPrinterColumns {
AdditionalPrinterColumn[] value();
}

0 comments on commit d8d7ec0

Please sign in to comment.