Release/1.14 (#12)

* Removed extra = in newVersion. Added target to release action to use the correct branch (#7)

Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>

* Feature/update workflows (#11)

* Removed extra = in newVersion. Added target to release action to use the correct branch

Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>

* Downgraded grpc to same version as the used springboot starter. Added javadoc. Removed componentscan since it's bad practie

Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>

---------

Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>

---------

Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
This commit is contained in:
Knut-Erik Johnsen 2024-06-26 11:50:28 +02:00 committed by GitHub
parent 22907e78a0
commit f25bf16b83
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 195 additions and 80 deletions

View File

@ -1,9 +1,48 @@
package io.crossplane.compositefunctions.starter.config;
import io.crossplane.compositefunctions.starter.conversion.CrossplaneExtraResourcesService;
import io.crossplane.compositefunctions.starter.conversion.CrossplaneObservableService;
import io.crossplane.compositefunctions.starter.conversion.CrossplaneResourceService;
import org.checkerframework.checker.units.qual.C;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
/**
* Autoconfiguration for the crossplane services.
*/
@AutoConfiguration
@ComponentScan(basePackages = {"io.crossplane.compositefunctions.starter.conversion"})
public class CrossplaneServiceConfiguration {
/**
* Set up services for working with extra resources
* @return the crossplaneExtraResourcesService
* @since 1.15
*/
@Bean
public CrossplaneExtraResourcesService crossplaneExtraResourcesService() {
return new CrossplaneExtraResourcesService();
}
/**
* Set up services for working with observed resources
* @return the crossplaneObservableService
* @since 1.14
*/
@Bean
public CrossplaneObservableService crossplaneObservableService() {
return new CrossplaneObservableService();
}
/**
* Set up services for working with default resources
* @return the crossplaneResourceService
* @since 1.15
*/
@Bean
public CrossplaneResourceService crossplaneResourceService() {
return new CrossplaneResourceService();
}
}

View File

@ -10,15 +10,20 @@ import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.client.utils.Serialization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Component
/**
* Class that helps with the extra resources map and also to create ResourceSelector in order to get extra resources
* to the function
*
* Commented out in 1.14
*
* @since 1.15
*/
public class CrossplaneExtraResourcesService {
private static final Logger logger = LoggerFactory.getLogger(CrossplaneExtraResourcesService.class);

View File

@ -8,16 +8,25 @@ import io.crossplane.compositefunctions.starter.exception.CrossplaneUnmarshallEx
import io.fabric8.kubernetes.client.utils.Serialization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
/**
* Class with helper methods for observable resources.
*/
public class CrossplaneObservableService {
private static final Logger logger = LoggerFactory.getLogger(CrossplaneObservableService.class);
private final JsonFormat.Printer printer = JsonFormat.printer();
/**
* Retrieve a resource from the observedstate and convert in into class T
* @param resourceName The resource name to find in the observed state
* @param observedState The observed state from the crossplane input
* @param clazz The class/type to create
* @return An instance of class T from the observed state
* @param <T> The class/type to create
*/
public <T> Optional<T> getObservableResource(String resourceName, State observedState, Class<T> clazz) {
Resource observedResource = observedState.getResourcesOrDefault(resourceName, null);
Optional<T> result = Optional.empty();

View File

@ -4,15 +4,23 @@ import com.google.protobuf.util.JsonFormat;
import io.crossplane.compositefunctions.protobuf.State;
import io.crossplane.compositefunctions.starter.exception.CrossplaneUnmarshallException;
import io.fabric8.kubernetes.client.utils.Serialization;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
/**
* Class with helper methods for default resources.
*/
public class CrossplaneResourceService {
final JsonFormat.Printer printer = JsonFormat.printer();
/**
* Converts the incoming Composite to instance of class T
* @param observedState The observed state from the crossplane input
* @param clazz The class/type to create
* @return An instance of class T from the observed state
* @param <T> The class/type to create
*/
public <T> Optional<T> getResource(State observedState, Class<T> clazz) {
try {
String resource = printer.print(observedState.getComposite().getResource());

View File

@ -1,11 +1,23 @@
package io.crossplane.compositefunctions.starter.exception;
/**
* Exception for unexpected items encountered when converting
*/
public class CrossplaneUnexpectedItemsException extends RuntimeException {
/**
* Constructor with message
* @param message The exception message
*/
public CrossplaneUnexpectedItemsException(String message) {
super(message);
}
/**
* Constructor with message and cause
* @param message The exception message
* @param cause The throwable that caused the exception
*/
public CrossplaneUnexpectedItemsException(String message, Throwable cause) {
super(message, cause);
}

View File

@ -1,11 +1,23 @@
package io.crossplane.compositefunctions.starter.exception;
/**
* Exception for errors when unmarhsalling
*/
public class CrossplaneUnmarshallException extends RuntimeException {
/**
* Constructor with message
* @param message The exception message
*/
public CrossplaneUnmarshallException(String message) {
super(message);
}
/**
* Constructor with message and cause
* @param message The exception message
* @param cause The throwable that caused the exception
*/
public CrossplaneUnmarshallException(String message, Throwable cause) {
super(message, cause);
}

View File

@ -3,6 +3,10 @@ package io.crossplane.compositefunctions.starter.registration;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.fabric8.kubernetes.api.model.ObjectMeta;
/**
* Class to aid in setting up autoregistration. Used to ignore the default
* fields when creating the openapiv3schema
*/
public abstract class CrossplaneCompositeResourceMixin {
@JsonIgnore

View File

@ -19,22 +19,33 @@ import io.fabric8.kubernetes.client.dsl.Resource;
import java.util.ArrayList;
import java.util.List;
import static io.crossplane.compositefunctions.starter.registration.CrossplanJsonSchemaGenerator.getOpenAPIV3Schema;
import static io.crossplane.compositefunctions.starter.registration.CrossplaneJsonSchemaGenerator.getOpenAPIV3Schema;
/**
* Service that can register the composite resource together with a function,
* which can also add other function to the pipeline definition
*/
public class CrossplaneCompositeResourceService {
public static <T extends CustomResource<?, Void>> void registerOrUpdateCompositeResource(String functionName,
List<String> additionalFunctions,
T functionDefinition,
/**
* Register or update the composite resource definition using the provided client.
* The client needs access to register the types
*
* @param pipelineFunctions A list of functionnames to add to the composition pipeline
* @param compositionDefinition The object that has the composition definiton
* @param kubernetesClient The client to use to register the definition
* @param <T> Must extend CustomResource
*/
public static <T extends CustomResource<?, Void>> void registerOrUpdateCompositeResource(List<String> pipelineFunctions,
T compositionDefinition,
KubernetesClient kubernetesClient) {
CompositeResourceDefinition compositeResourceDefinition = createCompositeResourceDefinition(functionDefinition);
CompositeResourceDefinition compositeResourceDefinition = createCompositeResourceDefinition(compositionDefinition);
registerOrUpdateCompositeResourceDefinition(compositeResourceDefinition, kubernetesClient);
Composition composition = createCompositionDefinition(functionName, additionalFunctions, functionDefinition);
Composition composition = createCompositionDefinition(pipelineFunctions, compositionDefinition);
registerOrUpdateCompositeResourceDefinition(composition, kubernetesClient);
@ -52,41 +63,49 @@ public class CrossplaneCompositeResourceService {
}
}
public static <T extends CustomResource<?, Void>> CompositeResourceDefinition createCompositeResourceDefinition(T functionDefinition) { //}, Class functionMixin) {
/**
* Create a CompositeResourceDefinition based on the provided CustomResource
* If Namespaced, ClaimNames will be added in addition to Names.
*
* @param compositionDefinition The composition definition
* @return A CompositeResourceDefintion based on the provided CustomResource
* @param <T> Must extend CustomResource
*/
public static <T extends CustomResource<?, Void>> CompositeResourceDefinition createCompositeResourceDefinition(T compositionDefinition) { //}, Class functionMixin) {
CompositeResourceDefinition compositeResourceDefinition = new CompositeResourceDefinition();
compositeResourceDefinition.setMetadata(CrossplaneMetadataBuilder.createMetadata(functionDefinition.getCRDName()));
compositeResourceDefinition.setMetadata(CrossplaneMetadataBuilder.createMetadata(compositionDefinition.getCRDName()));
CompositeResourceDefinitionSpec spec = new CompositeResourceDefinitionSpec();
spec.setGroup(functionDefinition.getGroup());
spec.setGroup(compositionDefinition.getGroup());
String namePrefix = "";
if (functionDefinition instanceof Namespaced) {
if (compositionDefinition instanceof Namespaced) {
ClaimNames claimNames = new ClaimNames();
claimNames.setKind(functionDefinition.getKind());
claimNames.setPlural(functionDefinition.getPlural());
claimNames.setSingular(functionDefinition.getSingular());
claimNames.setKind(compositionDefinition.getKind());
claimNames.setPlural(compositionDefinition.getPlural());
claimNames.setSingular(compositionDefinition.getSingular());
spec.setClaimNames(claimNames);
namePrefix = "x";
}
Names names = new Names();
names.setKind(namePrefix + functionDefinition.getKind());
names.setPlural(namePrefix + functionDefinition.getPlural());
names.setSingular(namePrefix + functionDefinition.getSingular());
names.setKind(namePrefix + compositionDefinition.getKind());
names.setPlural(namePrefix + compositionDefinition.getPlural());
names.setSingular(namePrefix + compositionDefinition.getSingular());
spec.setNames(names);
Versions versions = new Versions();
versions.setName(functionDefinition.getVersion());
versions.setName(compositionDefinition.getVersion());
// This is not 100%. isStorage vs referencable. Need to check the crossplan docs
versions.setReferenceable(functionDefinition.isStorage());
versions.setServed(functionDefinition.isServed());
versions.setReferenceable(compositionDefinition.isStorage());
versions.setServed(compositionDefinition.isServed());
Schema schema = new Schema();
schema.setOpenAPIV3Schema(getOpenAPIV3Schema(functionDefinition.getClass(), CrossplaneCompositeResourceMixin.class));
schema.setOpenAPIV3Schema(getOpenAPIV3Schema(compositionDefinition.getClass(), CrossplaneCompositeResourceMixin.class));
versions.setSchema(schema);
spec.setVersions(List.of(versions));
@ -108,26 +127,23 @@ public class CrossplaneCompositeResourceService {
}
private static <T extends CustomResource<?, Void>> Composition createCompositionDefinition(
String functionName, List<String> additionalFunctions,
T functionDefinition) {
List<String> pipelineFunctions, T compositionDefinition) {
Composition composition = new Composition();
composition.setMetadata(CrossplaneMetadataBuilder.createMetadata(functionDefinition.getKind().toLowerCase() + "-composition"));
composition.setMetadata(CrossplaneMetadataBuilder.createMetadata(compositionDefinition.getKind().toLowerCase() + "-composition"));
CompositionSpec compositionSpec = new CompositionSpec();
CompositeTypeRef compositeTypeRef = new CompositeTypeRef();
compositeTypeRef.setKind(functionDefinition.getKind());
compositeTypeRef.setApiVersion(functionDefinition.getApiVersion());
compositeTypeRef.setKind(compositionDefinition.getKind());
compositeTypeRef.setApiVersion(compositionDefinition.getApiVersion());
compositionSpec.setCompositeTypeRef(compositeTypeRef);
compositionSpec.setMode(CompositionSpec.Mode.PIPELINE);
List<Pipeline> pipelineList = new ArrayList<>();
pipelineList.add(createPipeline(functionName));
additionalFunctions.forEach(s -> pipelineList.add(createPipeline(s)));
pipelineFunctions.forEach(s -> pipelineList.add(createPipeline(s)));
compositionSpec.setPipeline(pipelineList);
composition.setSpec(compositionSpec);

View File

@ -12,8 +12,17 @@ import io.fabric8.kubernetes.api.model.apiextensions.v1.JSONSchemaProps;
import java.io.IOException;
import java.util.stream.Stream;
public class CrossplanJsonSchemaGenerator {
/**
* Generator of OpenApiV3Schema used when creating CompositeResourceDefinition
*/
public class CrossplaneJsonSchemaGenerator {
/**
* Create the OpenApiV3Schema
* @param clazz The class to create the schema from
* @param mixin A mixin to use when Jackson maps the class
* @return A OpenAPIV3Schema based on the given class
*/
public static OpenAPIV3Schema getOpenAPIV3Schema(Class clazz, Class mixin) {
try {
ObjectMapper mapper = new ObjectMapper();
@ -52,6 +61,11 @@ public class CrossplanJsonSchemaGenerator {
}
/**
* Get the JSONSchemaProps from the class
* @param clazz The class to get the schema from
* @return The schemaprops based on the provided class
*/
public static JSONSchemaProps getJsonSchema(Class clazz) {
try {
ObjectMapper mapper = new ObjectMapper();
@ -73,7 +87,9 @@ public class CrossplanJsonSchemaGenerator {
}
/**
* Class just use to ignore the ID property that automatically gets added.
*/
private abstract class IdIgnorer {
@JsonIgnore

View File

@ -6,24 +6,51 @@ import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Convinience methods to create the Metadata object in any kubernetes resource
*/
public class CrossplaneMetadataBuilder {
private CrossplaneMetadataBuilder() {
}
/**
* Create metadata with name
* @param name The name of the resource
* @return The metdata object based on the input
*/
public static ObjectMeta createMetadata(String name) {
return createMetadata(name, null);
}
/**
* Create metadata with name and namespace
* @param name The name of the resource
* @param namespace The namespace of the resource
* @return The metdata object based on the input
*/
public static ObjectMeta createMetadata(String name, String namespace) {
return createMetadata(name, namespace, null);
}
/**
* Create metadata with name, namespace and annotations
* @param name The name of the resource
* @param namespace The namespace of the resource
* @param annotations Annotations to add to the metadata
* @return The metdata object based on the input
*/
public static ObjectMeta createMetadata(String name, String namespace, Map<String, String> annotations) {
return new ObjectMetaBuilder().withName(name).withNamespace(namespace).withAnnotations(annotations).build();
}
public static ObjectMeta createMetadata(String name) {
return createMetadata(name, null);
}
/**
* Add extra metadata to a Metadata object
* @param annotations The extra metadata to add
* @param objectMeta The metadata object to add it to
* @return The metadata with the added annotations
*/
public static ObjectMeta addAnnotations(Map<String, String> annotations, ObjectMeta objectMeta) {
Map<String, String> existingAnnotations = objectMeta.getAnnotations();

41
pom.xml
View File

@ -29,7 +29,7 @@
<kubernetes-client.version>6.13.0</kubernetes-client.version>
<os-maven-plugin.version>1.7.1</os-maven-plugin.version>
<protobuf.version>3.25.1</protobuf.version>
<grpc.version>1.64.0</grpc.version>
<grpc.version>1.63.0</grpc.version>
<jakarta-annotation.version>1.3.5</jakarta-annotation.version>
<slf4j.version>2.0.13</slf4j.version>
<jackson-databind.version>2.17.1</jackson-databind.version>
@ -100,43 +100,10 @@
<!-- Protobuf -->
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-core</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-api</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-util</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-services</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-inprocess</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<artifactId>grpc-bom</artifactId>
<version>${grpc.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>