Added relese workflow, updated build. Added more javadoc, and updated javadoc parameters. Added fetch scripts for getting external resources

Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
This commit is contained in:
Knut-Erik Johnsen 2024-06-18 23:09:44 +02:00
parent 7a90e13943
commit 4f525fd3f6
15 changed files with 139 additions and 225 deletions

View File

@ -17,14 +17,5 @@ jobs:
java-version: '17' java-version: '17'
distribution: 'oracle' distribution: 'oracle'
cache: maven cache: maven
server-id: central
server-username: MAVEN_CENTRAL_USERNAME # env variable for username in deploy
server-password: MAVEN_CENTRAL_TOKEN # env variable for token in deploy
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import
gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
- name: Build with Maven - name: Build with Maven
run: mvn -B deploy --file pom.xml -Pdeploy run: mvn -B clean verify --file pom.xml
env:
MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}

43
.github/workflows/maven-release.yaml vendored Normal file
View File

@ -0,0 +1,43 @@
name: Java CI with Maven
on:
workflow_dispatch:
inputs:
releaseversion:
description: 'Version to reelase'
required: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'oracle'
cache: maven
server-id: central
server-username: MAVEN_CENTRAL_USERNAME # env variable for username in deploy
server-password: MAVEN_CENTRAL_TOKEN # env variable for token in deploy
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import
gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
- name: Set the revision property
run: mvn versions:set-property -Dproperty=revision "-DnewVersion==${{ github.event.inputs.releaseversion }}" -DgenerateBackupPoms=false
- name: Build with Maven
run: mvn -B deploy --file pom.xml -Pdeploy
env:
MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
- name: Create release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ github.ref_name }}
run: |
gh release create "$tag" \
--repo="$GITHUB_REPOSITORY" \
--title="${GITHUB_REPOSITORY#*/} ${tag#v}" \
--generate-notes

View File

@ -32,12 +32,9 @@ spec:
schema: schema:
openAPIV3Schema: openAPIV3Schema:
description: |- description: |-
A CompositeResourceDefinition defines the schema for a new custom Kubernetes A CompositeResourceDefinition defines a new kind of composite infrastructure
API. resource. The new resource is composed of other composite or managed
infrastructure resources.
Read the Crossplane documentation for
[more information about CustomResourceDefinitions](https://docs.crossplane.io/latest/concepts/composite-resource-definitions).
properties: properties:
apiVersion: apiVersion:
description: |- description: |-
@ -483,13 +480,6 @@ spec:
A Message containing details about this condition's last transition from A Message containing details about this condition's last transition from
one status to another, if any. one status to another, if any.
type: string type: string
observedGeneration:
description: |-
ObservedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
type: integer
reason: reason:
description: A Reason for this condition's last transition from description: A Reason for this condition's last transition from
one status to another. one status to another.
@ -560,4 +550,4 @@ spec:
served: true served: true
storage: true storage: true
subresources: subresources:
status: {} status: {}

View File

@ -34,12 +34,8 @@ spec:
schema: schema:
openAPIV3Schema: openAPIV3Schema:
description: |- description: |-
A CompositionRevision represents a revision of a Composition. Crossplane A CompositionRevision represents a revision in time of a Composition.
creates new revisions when there are changes to the Composition. Revisions are created by Crossplane; they should be treated as immutable.
Crossplane creates and manages CompositionRevisions. Don't directly edit
CompositionRevisions.
properties: properties:
apiVersion: apiVersion:
description: |- description: |-
@ -287,7 +283,7 @@ spec:
type: string type: string
mergeOptions: mergeOptions:
description: MergeOptions Specifies merge options on description: MergeOptions Specifies merge options on
a field path. a field path
properties: properties:
appendSlice: appendSlice:
description: Specifies that already existing elements description: Specifies that already existing elements
@ -701,7 +697,7 @@ spec:
type: string type: string
mergeOptions: mergeOptions:
description: MergeOptions Specifies merge options description: MergeOptions Specifies merge options
on a field path. on a field path
properties: properties:
appendSlice: appendSlice:
description: Specifies that already existing elements description: Specifies that already existing elements
@ -991,46 +987,6 @@ spec:
items: items:
description: A PipelineStep in a Composition Function pipeline. description: A PipelineStep in a Composition Function pipeline.
properties: properties:
credentials:
description: Credentials are optional credentials that the Composition
Function needs.
items:
description: |-
FunctionCredentials are optional credentials that a Composition Function
needs to run.
properties:
name:
description: Name of this set of credentials.
type: string
secretRef:
description: |-
A SecretRef is a reference to a secret containing credentials that should
be supplied to the function.
properties:
name:
description: Name of the secret.
type: string
namespace:
description: Namespace of the secret.
type: string
required:
- name
- namespace
type: object
source:
description: Source of the function credentials.
enum:
- None
- Secret
type: string
required:
- name
- source
type: object
type: array
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
functionRef: functionRef:
description: |- description: |-
FunctionRef is a reference to the Composition Function this step should FunctionRef is a reference to the Composition Function this step should
@ -1239,7 +1195,7 @@ spec:
type: string type: string
mergeOptions: mergeOptions:
description: MergeOptions Specifies merge options description: MergeOptions Specifies merge options
on a field path. on a field path
properties: properties:
appendSlice: appendSlice:
description: Specifies that already existing elements description: Specifies that already existing elements
@ -1521,7 +1477,7 @@ spec:
items: items:
description: |- description: |-
ReadinessCheck is used to indicate how to tell whether a resource is ready ReadinessCheck is used to indicate how to tell whether a resource is ready
for consumption. for consumption
properties: properties:
fieldPath: fieldPath:
description: FieldPath shows the path of the field whose description: FieldPath shows the path of the field whose
@ -1614,13 +1570,6 @@ spec:
A Message containing details about this condition's last transition from A Message containing details about this condition's last transition from
one status to another, if any. one status to another, if any.
type: string type: string
observedGeneration:
description: |-
ObservedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
type: integer
reason: reason:
description: A Reason for this condition's last transition from description: A Reason for this condition's last transition from
one status to another. one status to another.
@ -1667,12 +1616,8 @@ spec:
schema: schema:
openAPIV3Schema: openAPIV3Schema:
description: |- description: |-
A CompositionRevision represents a revision of a Composition. Crossplane A CompositionRevision represents a revision in time of a Composition.
creates new revisions when there are changes to the Composition. Revisions are created by Crossplane; they should be treated as immutable.
Crossplane creates and manages CompositionRevisions. Don't directly edit
CompositionRevisions.
properties: properties:
apiVersion: apiVersion:
description: |- description: |-
@ -1920,7 +1865,7 @@ spec:
type: string type: string
mergeOptions: mergeOptions:
description: MergeOptions Specifies merge options on description: MergeOptions Specifies merge options on
a field path. a field path
properties: properties:
appendSlice: appendSlice:
description: Specifies that already existing elements description: Specifies that already existing elements
@ -2334,7 +2279,7 @@ spec:
type: string type: string
mergeOptions: mergeOptions:
description: MergeOptions Specifies merge options description: MergeOptions Specifies merge options
on a field path. on a field path
properties: properties:
appendSlice: appendSlice:
description: Specifies that already existing elements description: Specifies that already existing elements
@ -2624,46 +2569,6 @@ spec:
items: items:
description: A PipelineStep in a Composition Function pipeline. description: A PipelineStep in a Composition Function pipeline.
properties: properties:
credentials:
description: Credentials are optional credentials that the Composition
Function needs.
items:
description: |-
FunctionCredentials are optional credentials that a Composition Function
needs to run.
properties:
name:
description: Name of this set of credentials.
type: string
secretRef:
description: |-
A SecretRef is a reference to a secret containing credentials that should
be supplied to the function.
properties:
name:
description: Name of the secret.
type: string
namespace:
description: Namespace of the secret.
type: string
required:
- name
- namespace
type: object
source:
description: Source of the function credentials.
enum:
- None
- Secret
type: string
required:
- name
- source
type: object
type: array
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
functionRef: functionRef:
description: |- description: |-
FunctionRef is a reference to the Composition Function this step should FunctionRef is a reference to the Composition Function this step should
@ -2872,7 +2777,7 @@ spec:
type: string type: string
mergeOptions: mergeOptions:
description: MergeOptions Specifies merge options description: MergeOptions Specifies merge options
on a field path. on a field path
properties: properties:
appendSlice: appendSlice:
description: Specifies that already existing elements description: Specifies that already existing elements
@ -3154,7 +3059,7 @@ spec:
items: items:
description: |- description: |-
ReadinessCheck is used to indicate how to tell whether a resource is ready ReadinessCheck is used to indicate how to tell whether a resource is ready
for consumption. for consumption
properties: properties:
fieldPath: fieldPath:
description: FieldPath shows the path of the field whose description: FieldPath shows the path of the field whose
@ -3247,13 +3152,6 @@ spec:
A Message containing details about this condition's last transition from A Message containing details about this condition's last transition from
one status to another, if any. one status to another, if any.
type: string type: string
observedGeneration:
description: |-
ObservedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
type: integer
reason: reason:
description: A Reason for this condition's last transition from description: A Reason for this condition's last transition from
one status to another. one status to another.
@ -3282,4 +3180,4 @@ spec:
served: true served: true
storage: false storage: false
subresources: subresources:
status: {} status: {}

View File

@ -30,13 +30,7 @@ spec:
name: v1 name: v1
schema: schema:
openAPIV3Schema: openAPIV3Schema:
description: |- description: A Composition specifies how a composite resource should be composed.
A Composition defines a collection of managed resources or functions that
Crossplane uses to create and manage new composite resources.
Read the Crossplane documentation for
[more information about Compositions](https://docs.crossplane.io/latest/concepts/compositions).
properties: properties:
apiVersion: apiVersion:
description: |- description: |-
@ -282,7 +276,7 @@ spec:
type: string type: string
mergeOptions: mergeOptions:
description: MergeOptions Specifies merge options on description: MergeOptions Specifies merge options on
a field path. a field path
properties: properties:
appendSlice: appendSlice:
description: Specifies that already existing elements description: Specifies that already existing elements
@ -696,7 +690,7 @@ spec:
type: string type: string
mergeOptions: mergeOptions:
description: MergeOptions Specifies merge options description: MergeOptions Specifies merge options
on a field path. on a field path
properties: properties:
appendSlice: appendSlice:
description: Specifies that already existing elements description: Specifies that already existing elements
@ -986,46 +980,6 @@ spec:
items: items:
description: A PipelineStep in a Composition Function pipeline. description: A PipelineStep in a Composition Function pipeline.
properties: properties:
credentials:
description: Credentials are optional credentials that the Composition
Function needs.
items:
description: |-
FunctionCredentials are optional credentials that a Composition Function
needs to run.
properties:
name:
description: Name of this set of credentials.
type: string
secretRef:
description: |-
A SecretRef is a reference to a secret containing credentials that should
be supplied to the function.
properties:
name:
description: Name of the secret.
type: string
namespace:
description: Namespace of the secret.
type: string
required:
- name
- namespace
type: object
source:
description: Source of the function credentials.
enum:
- None
- Secret
type: string
required:
- name
- source
type: object
type: array
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
functionRef: functionRef:
description: |- description: |-
FunctionRef is a reference to the Composition Function this step should FunctionRef is a reference to the Composition Function this step should
@ -1053,9 +1007,6 @@ spec:
- step - step
type: object type: object
type: array type: array
x-kubernetes-list-map-keys:
- step
x-kubernetes-list-type: map
publishConnectionDetailsWithStoreConfigRef: publishConnectionDetailsWithStoreConfigRef:
default: default:
name: default name: default
@ -1237,7 +1188,7 @@ spec:
type: string type: string
mergeOptions: mergeOptions:
description: MergeOptions Specifies merge options description: MergeOptions Specifies merge options
on a field path. on a field path
properties: properties:
appendSlice: appendSlice:
description: Specifies that already existing elements description: Specifies that already existing elements
@ -1519,7 +1470,7 @@ spec:
items: items:
description: |- description: |-
ReadinessCheck is used to indicate how to tell whether a resource is ready ReadinessCheck is used to indicate how to tell whether a resource is ready
for consumption. for consumption
properties: properties:
fieldPath: fieldPath:
description: FieldPath shows the path of the field whose description: FieldPath shows the path of the field whose
@ -1589,4 +1540,4 @@ spec:
type: object type: object
served: true served: true
storage: true storage: true
subresources: {} subresources: {}

View File

@ -24,13 +24,8 @@ spec:
name: v1alpha1 name: v1alpha1
schema: schema:
openAPIV3Schema: openAPIV3Schema:
description: |- description: A EnvironmentConfig contains a set of arbitrary, unstructured
An EnvironmentConfig contains user-defined unstructured values for values.
use in a Composition.
Read the Crossplane documentation for
[more information about EnvironmentConfigs](https://docs.crossplane.io/latest/concepts/environment-configs).
properties: properties:
apiVersion: apiVersion:
description: |- description: |-
@ -59,4 +54,4 @@ spec:
type: object type: object
served: true served: true
storage: true storage: true
subresources: {} subresources: {}

View File

@ -28,16 +28,8 @@ spec:
name: v1alpha1 name: v1alpha1
schema: schema:
openAPIV3Schema: openAPIV3Schema:
description: |- description: A Usage defines a deletion blocking relationship between two
A Usage defines a deletion blocking relationship between two resources. resources.
Usages prevent accidental deletion of a single resource or deletion of
resources with dependent resources.
Read the Crossplane documentation for
[more information about Compositions](https://docs.crossplane.io/latest/concepts/usages).
properties: properties:
apiVersion: apiVersion:
description: |- description: |-
@ -176,13 +168,6 @@ spec:
A Message containing details about this condition's last transition from A Message containing details about this condition's last transition from
one status to another, if any. one status to another, if any.
type: string type: string
observedGeneration:
description: |-
ObservedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
type: integer
reason: reason:
description: A Reason for this condition's last transition from description: A Reason for this condition's last transition from
one status to another. one status to another.
@ -213,4 +198,4 @@ spec:
served: true served: true
storage: true storage: true
subresources: subresources:
status: {} status: {}

View File

@ -0,0 +1,12 @@
#!/bin/bash
release="release-1.16"
apiextensions=$(gh api --jq '.[].name' "/repos/crossplane/crossplane/contents/cluster/crds?ref=${release}" | grep apiextensions)
for file in $apiextensions;
do
# output=$(echo $file | cut -d'_' -f2)
gh api -H "Accept: application/vnd.github.raw+json" "/repos/crossplane/crossplane/contents/cluster/crds/${file}?ref=${release}" > $file
done

View File

@ -7,6 +7,12 @@ import org.slf4j.LoggerFactory;
import java.util.Map; import java.util.Map;
/**
* The base class for a function to implement. Extend this class and implement the abstract runFunction method.
* This class adds any desired resources from a previously called function into the returned desired map.
* Any returned objects from the runFunction in the desiredresources map will be converted to protobuf resources,
* so the implemented method can work with the regular Java objects.
*/
public abstract class CrossplaneCompositeFunctionBase extends FunctionRunnerServiceGrpc.FunctionRunnerServiceImplBase { public abstract class CrossplaneCompositeFunctionBase extends FunctionRunnerServiceGrpc.FunctionRunnerServiceImplBase {
private static final Logger logger = LoggerFactory.getLogger(CrossplaneCompositeFunctionBase.class); private static final Logger logger = LoggerFactory.getLogger(CrossplaneCompositeFunctionBase.class);
@ -19,6 +25,7 @@ public abstract class CrossplaneCompositeFunctionBase extends FunctionRunnerServ
State desired = request.getDesired(); State desired = request.getDesired();
// Copy existing state into new desired state // Copy existing state into new desired state
// Should these be sent to the function? Probably?
desiredBuilder.putAllResources(desired.getResourcesMap()); desiredBuilder.putAllResources(desired.getResourcesMap());
CrossplaneFunctionRequest crossplaneFunctionRequest = new CrossplaneFunctionRequest(request.getObserved(), CrossplaneFunctionRequest crossplaneFunctionRequest = new CrossplaneFunctionRequest(request.getObserved(),
@ -52,6 +59,11 @@ public abstract class CrossplaneCompositeFunctionBase extends FunctionRunnerServ
} }
/**
* The main method where the logic should live.
* @param crossplaneFunctionRequest The request object with the inputs from Crossplane added to it
* @return The response with desired resources, resource selectors and function results
*/
public abstract CrossplaneFunctionResponse runFunction(CrossplaneFunctionRequest crossplaneFunctionRequest); public abstract CrossplaneFunctionResponse runFunction(CrossplaneFunctionRequest crossplaneFunctionRequest);
} }

View File

@ -6,6 +6,12 @@ import io.crossplane.compositefunctions.protobuf.State;
import java.util.Map; import java.util.Map;
/**
* Holder for the request from crossplane
* @param observedState The observedstate of the crossplane resources
* @param extraResourcesMap A map of any extra resources requested
* @param credentialsMap A map of credentials sent as input
*/
public record CrossplaneFunctionRequest(State observedState, public record CrossplaneFunctionRequest(State observedState,
Map<String, Resources> extraResourcesMap, Map<String, Resources> extraResourcesMap,
Map<String, Credentials> credentialsMap) { Map<String, Credentials> credentialsMap) {

View File

@ -8,11 +8,20 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
/**
* Holder for the response to Crossplane
* @param desiredResources Map of the desired resources
* @param resourceSelectors Map of the resource selectors for any extra resources
* @param results List of the results
*/
public record CrossplaneFunctionResponse(Map<String, Object> desiredResources, public record CrossplaneFunctionResponse(Map<String, Object> desiredResources,
Map<String, ResourceSelector> resourceSelectors, Map<String, ResourceSelector> resourceSelectors,
List<Result> results) { List<Result> results) {
/**
* Create an empty response with all fields initiated
*/
public CrossplaneFunctionResponse() { public CrossplaneFunctionResponse() {
this(new HashMap<>(), new HashMap<>(), new ArrayList<>()); this(new HashMap<>(), new HashMap<>(), new ArrayList<>());
} }

View File

@ -5,12 +5,19 @@ import com.google.protobuf.Struct;
import com.google.protobuf.util.JsonFormat; import com.google.protobuf.util.JsonFormat;
import io.crossplane.compositefunctions.protobuf.Resource; import io.crossplane.compositefunctions.protobuf.Resource;
/**
public class CrossplaneObjectToProtobufConverter { * Helper class for converting Java Objects into protobuf Structs within the Resource object
*/
public final class CrossplaneObjectToProtobufConverter {
private static final ObjectMapper objectMapper = new ObjectMapper(); private static final ObjectMapper objectMapper = new ObjectMapper();
private static final JsonFormat.Parser parser = JsonFormat.parser(); private static final JsonFormat.Parser parser = JsonFormat.parser();
/**
* Convert a java object to a resource
* @param object The object to convert
* @return The Resource with the object wrapped as a Struct
*/
public static Resource convertToResource(Object object) { public static Resource convertToResource(Object object) {
try { try {
Resource.Builder builder = Resource.newBuilder(); Resource.Builder builder = Resource.newBuilder();
@ -21,6 +28,11 @@ public class CrossplaneObjectToProtobufConverter {
} }
/**
* Convert a java object to a struct
* @param object The object to convert
* @return The object as a protobuf struct
*/
public static Struct convertToStruct(Object object) { public static Struct convertToStruct(Object object) {
try { try {
Struct.Builder structBuilder = Struct.newBuilder(); Struct.Builder structBuilder = Struct.newBuilder();

View File

@ -0,0 +1,7 @@
#!/bin/bash
release="release-1.16"
file="run_function.proto"
gh api -H "Accept: application/vnd.github.raw+json" "/repos/crossplane/crossplane/contents/apis/apiextensions/fn/proto/v1beta1/${file}?ref=${release}" > $file
sed -i '/option go_package/a\option java_package = "io.crossplane.compositefunctions.protobuf";\noption java_multiple_files = true;' $file

View File

@ -25,7 +25,6 @@ option go_package = "github.com/crossplane/crossplane/apis/apiextensions/fn/prot
option java_package = "io.crossplane.compositefunctions.protobuf"; option java_package = "io.crossplane.compositefunctions.protobuf";
option java_multiple_files = true; option java_multiple_files = true;
// A FunctionRunnerService is a Composition Function. // A FunctionRunnerService is a Composition Function.
service FunctionRunnerService { service FunctionRunnerService {
// RunFunction runs the Composition Function. // RunFunction runs the Composition Function.
@ -204,7 +203,7 @@ message Resource {
google.protobuf.Struct resource = 1; google.protobuf.Struct resource = 1;
// The resource's connection details. // The resource's connection details.
// //
// * Crossplane will set this field in a RunFunctionRequest to communicate the // * Crossplane will set this field in a RunFunctionRequest to communicate the
// the observed connection details of a composite or composed resource. // the observed connection details of a composite or composed resource.
// //
@ -217,7 +216,7 @@ message Resource {
map<string, bytes> connection_details = 2; map<string, bytes> connection_details = 2;
// Ready indicates whether the resource should be considered ready. // Ready indicates whether the resource should be considered ready.
// //
// * Crossplane will never set this field in a RunFunctionRequest. // * Crossplane will never set this field in a RunFunctionRequest.
// //
// * A Function should set this field to READY_TRUE in a RunFunctionResponse // * A Function should set this field to READY_TRUE in a RunFunctionResponse

View File

@ -179,6 +179,10 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>${maven-javadoc-plugin.version}</version> <version>${maven-javadoc-plugin.version}</version>
<configuration>
<doclint>all,missing</doclint>
<excludePackageNames>io.crossplane.compositefunctions.protobuf:io.crossplane.apiextensions.*</excludePackageNames>
</configuration>
<executions> <executions>
<execution> <execution>
<id>attach-javadocs</id> <id>attach-javadocs</id>