Compare commits

...

29 Commits

Author SHA1 Message Date
Knut-Erik Johnsen 0f737991a8 Remove temporary naming fix for releases
Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-12-06 10:35:09 +01:00
Knut-Erik Johnsen 0568ba97c6 Upgrade maven-jar-plugin for providers. Temporary fix for releasing new version of providers
Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-11-15 07:39:34 +01:00
Knut-Erik Johnsen a7c2105af2 Add methods to extract connectiondetails both from extra resources and observable resources
Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-11-13 16:26:15 +01:00
Knut-Erik Johnsen 272e596c69 Update to 1.18 of crossplane
Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-11-08 23:23:29 +01:00
Knut-Erik Johnsen a2db617e7b Add kubernetes provider 2024-10-17 15:28:38 +02:00
Knut-Erik Johnsen 7bac463211 Add initial support for conditions 2024-10-17 15:07:49 +02:00
Knut-Erik Johnsen 4bebc4a60b Add provider kubernetes. Update to new parent. Add exclude on io.crossplane.* for javadocs 2024-10-17 14:59:41 +02:00
Knut-Erik Johnsen 88a9eadb8a Added provider models for GCP, AWS, Terraform and Github 2024-10-17 14:34:06 +02:00
Knut-Erik Johnsen 14076cd62e Fix tagname 2024-10-14 13:44:45 +02:00
Knut-Erik Johnsen 220068c09f Add interface to generate some doc out of
Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-10-11 16:23:09 +02:00
Knut-Erik Johnsen f15a317426 Add interface to generate some doc out of
Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-10-11 16:02:32 +02:00
Knut-Erik Johnsen 5e93e752f1 Remove the javadoc setting as the parent not no longer skips
Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-10-11 15:40:48 +02:00
Knut-Erik Johnsen 965cb66b5d Updated parent to 1.17-beta
Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-10-11 15:31:14 +02:00
Knut-Erik Johnsen 723d28bf7b Updated protobuf version
Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-10-11 15:22:43 +02:00
Knut-Erik Johnsen fa11c728c0 Update how we generate javadoc for provider models
Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-10-11 15:21:09 +02:00
Knut-Erik Johnsen f30d33fc30 Need to generate javadoc to be able to publish
Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-10-11 13:48:08 +02:00
Knut-Erik Johnsen a62e73a11b Fetch the correct version of files, and print if any error fetching the crd
Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-10-11 13:39:39 +02:00
Knut-Erik Johnsen 1a06a07237 Fetch the desired version from github. Release the correct version with version name
Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-10-11 13:11:02 +02:00
Knut-Erik Johnsen 9175c8fffc Run correct file 2024-10-11 12:30:48 +02:00
Knut-Erik Johnsen d88e3181da Run correct file 2024-10-11 12:28:31 +02:00
Knut-Erik Johnsen ebec9bc84c Rename the options 2024-10-11 12:25:56 +02:00
Knut-Erik Johnsen 3dc2e0bd8f Rename the options 2024-10-11 12:24:02 +02:00
Knut-Erik Johnsen d8a4f6b3c8 Rename the workflow 2024-10-11 12:22:32 +02:00
Knut-Erik Johnsen 81d0fa1d5a Started on adding support for 1.17 spec. Start on provider-models to ease java development
Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-10-11 12:18:59 +02:00
Knut-Erik Johnsen 57d4f1c270
Backports/1.17 custom (#23)
* Include namePrefix in CRD name of CompositionResourceDefinition as CRD name must match plural.group (#20)

Signed-off-by: Jesper Nylend <jesper.nylend@gmail.com>

* Wrap the generator to avoid refs in the generated schema

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

---------

Signed-off-by: Jesper Nylend <jesper.nylend@gmail.com>
Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
Co-authored-by: Jesper Nylend <jesper.nylend@gmail.com>
2024-10-07 16:00:47 +02:00
Knut-Erik Johnsen 4a23c6ba53
Feature/add size check for resources (#18)
* Removed extra = in newVersion. Added target to release action to use the correct branch (#7) (#8)

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

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

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

* 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>

* Release/1.15 (#13)

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

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

* 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>

---------

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

* Added range check for extra resources

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

---------

Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-06-27 14:42:40 +02:00
Knut-Erik Johnsen a41312e2c8
Release/1.16 (#14)
* Removed extra = in newVersion. Added target to release action to use the correct branch (#7) (#8) (#9)

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

* Release/1.15 (#13)

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

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

* 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>

---------

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

---------

Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-06-26 11:52:11 +02:00
Knut-Erik Johnsen 5e1827412b
Removed extra = in newVersion. Added target to release action to use the correct branch (#7) (#8) (#9) (#10)
Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-06-25 21:49:20 +02:00
Knut-Erik Johnsen fe64d75730
Upgrade to 1.16, adding the credentialmap and observedgeneration to the crossplane crds (#6)
Signed-off-by: Knut-Erik Johnsen <abstract@knut-erik.org>
2024-06-25 00:13:46 +02:00
48 changed files with 1633 additions and 1791 deletions

View File

@ -0,0 +1,68 @@
name: Release a new version of a provider model
on:
workflow_dispatch:
inputs:
releaseversion:
type: string
description: 'Version to release'
required: true
provider:
type: choice
description: 'Provider to release'
required: true
options:
- provider-upjet-azure
- provider-upjet-azuread
- provider-upjet-aws
- provider-upjet-gcp
- provider-upjet-github
- provider-terraform
- provider-kubernetes
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: Fetch crds
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
working-directory: "./provider-models/crossplane-${{ github.event.inputs.provider }}/src/main/resources/kubernetes"
run : ./fetch.sh "${{ github.event.inputs.releaseversion }}"
- name: List crds
working-directory: "./provider-models/crossplane-${{ github.event.inputs.provider }}/src/main/resources/kubernetes"
run : ls
- name: Set the revision property
working-directory: "./provider-models/crossplane-${{ github.event.inputs.provider }}"
run: mvn versions:set-property -Dproperty=modelrevision "-DnewVersion=${{ github.event.inputs.releaseversion }}" -DgenerateBackupPoms=false
- name: Build with Maven
working-directory: "./provider-models/crossplane-${{ github.event.inputs.provider }}"
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 }}
MAVEN_OPTS: "-Xmx2048m"
- name: Create release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
tag: "${{ github.event.inputs.releaseversion }}"
provider: "${{ github.event.inputs.provider }}"
run: |
gh release create "$provider-$tag" \
--repo="$GITHUB_REPOSITORY" \
--title="$provider-v${tag#v}" \
--target "$GITHUB_SHA"

View File

@ -5,7 +5,7 @@ on:
inputs:
releaseversion:
type: string
description: 'Version to reelase'
description: 'Version to release'
required: true
@ -26,7 +26,7 @@ jobs:
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
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:
@ -40,5 +40,6 @@ jobs:
run: |
gh release create "$tag" \
--repo="$GITHUB_REPOSITORY" \
--title="${tag#v}" \
--generate-notes
--title="v${tag#v}" \
--generate-notes \
--target "$GITHUB_SHA"

2
.gitignore vendored
View File

@ -28,3 +28,5 @@ replay_pid*
.idea/
target/
generated/
provider-models/**/src/main/resources/kubernetes/*.yaml

View File

@ -1,8 +1,9 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.14.0
controller-gen.kubebuilder.io/version: v0.16.5
name: compositeresourcedefinitions.apiextensions.crossplane.io
spec:
group: apiextensions.crossplane.io
@ -32,9 +33,11 @@ spec:
schema:
openAPIV3Schema:
description: |-
A CompositeResourceDefinition defines a new kind of composite infrastructure
resource. The new resource is composed of other composite or managed
infrastructure resources.
A CompositeResourceDefinition defines the schema for a new custom Kubernetes
API.
Read the Crossplane documentation for
[more information about CustomResourceDefinitions](https://docs.crossplane.io/latest/concepts/composite-resource-definitions).
properties:
apiVersion:
description: |-
@ -76,6 +79,7 @@ spec:
items:
type: string
type: array
x-kubernetes-list-type: atomic
kind:
description: |-
kind is the serialized kind of the resource. It is normally CamelCase and singular.
@ -100,6 +104,7 @@ spec:
items:
type: string
type: array
x-kubernetes-list-type: atomic
singular:
description: singular is the singular name of the resource. It
must be all lowercase. Defaults to lowercased `kind`.
@ -108,6 +113,9 @@ spec:
- kind
- plural
type: object
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
connectionSecretKeys:
description: |-
ConnectionSecretKeys is the list of keys that will be exposed to the end
@ -146,7 +154,6 @@ spec:
service is a reference to the service for this webhook. Either
service or url must be specified.
If the webhook is running within the cluster, then you should use `service`.
properties:
name:
@ -180,29 +187,24 @@ spec:
(`scheme://host:port/path`). Exactly one of `url` or `service`
must be specified.
The `host` should not refer to a service running in the cluster; use
the `service` field instead. The host might be resolved via external
DNS in some apiservers (e.g., `kube-apiserver` cannot resolve
in-cluster DNS as that would be a layering violation). `host` may
also be an IP address.
Please note that using `localhost` or `127.0.0.1` as a `host` is
risky unless you take great care to run this webhook on all hosts
which run an apiserver which might need to make calls to this
webhook. Such installs are likely to be non-portable, i.e., not easy
to turn up in a new cluster.
The scheme must be "https"; the URL must begin with "https://".
A path is optional, and if present may be any string permissible in
a URL. You may use the path to pass an arbitrary string to the
webhook, for example, a cluster identifier.
Attempting to use a user or basic auth e.g. "user:password@" is not
allowed. Fragments ("#...") and query parameters ("?...") are not
allowed, either.
@ -219,6 +221,7 @@ spec:
items:
type: string
type: array
x-kubernetes-list-type: atomic
required:
- conversionReviewVersions
type: object
@ -265,12 +268,18 @@ spec:
required:
- name
type: object
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
group:
description: |-
Group specifies the API group of the defined composite resource.
Composite resources are served under `/apis/<group>/...`. Must match the
name of the XRD (in the form `<names.plural>.<group>`).
type: string
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
metadata:
description: Metadata specifies the desired metadata for the defined
composite resource and claim CRD's.
@ -309,6 +318,7 @@ spec:
items:
type: string
type: array
x-kubernetes-list-type: atomic
kind:
description: |-
kind is the serialized kind of the resource. It is normally CamelCase and singular.
@ -333,6 +343,7 @@ spec:
items:
type: string
type: array
x-kubernetes-list-type: atomic
singular:
description: singular is the singular name of the resource. It
must be all lowercase. Defaults to lowercased `kind`.
@ -341,6 +352,9 @@ spec:
- kind
- plural
type: object
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
versions:
description: |-
Versions is the list of all API versions of the defined composite
@ -480,6 +494,13 @@ spec:
A Message containing details about this condition's last transition from
one status to another, if any.
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:
description: A Reason for this condition's last transition from
one status to another.

View File

@ -1,8 +1,9 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.14.0
controller-gen.kubebuilder.io/version: v0.16.5
name: compositions.apiextensions.crossplane.io
spec:
group: apiextensions.crossplane.io
@ -30,7 +31,12 @@ spec:
name: v1
schema:
openAPIV3Schema:
description: A Composition specifies how a composite resource should be composed.
description: |-
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:
apiVersion:
description: |-
@ -67,143 +73,57 @@ spec:
- apiVersion
- kind
type: object
environment:
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
mode:
default: Resources
description: |-
Environment configures the environment in which resources are rendered.
Mode controls what type or "mode" of Composition will be used.
"Pipeline" indicates that a Composition specifies a pipeline of
Composition Functions, each of which is responsible for producing
composed resources that Crossplane should create or update.
THIS IS AN ALPHA FIELD. Do not use it in production. It is not honored
unless the relevant Crossplane feature flag is enabled, and may be
changed or removed without notice.
properties:
defaultData:
additionalProperties:
x-kubernetes-preserve-unknown-fields: true
"Resources" indicates that a Composition uses what is commonly referred
to as "Patch & Transform" or P&T composition. This mode of Composition
uses an array of resources, each a template for a composed resource.
All Compositions should use Pipeline mode. Resources mode is deprecated.
Resources mode won't be removed in Crossplane 1.x, and will remain the
default to avoid breaking legacy Compositions. However, it's no longer
accepting new features, and only accepting security related bug fixes.
enum:
- Resources
- Pipeline
type: string
patchSets:
description: |-
DefaultData statically defines the initial state of the environment.
It has the same schema-less structure as the data field in
environment configs.
It is overwritten by the selected environment configs.
type: object
environmentConfigs:
description: |-
EnvironmentConfigs selects a list of `EnvironmentConfig`s. The resolved
resources are stored in the composite resource at
`spec.environmentConfigRefs` and is only updated if it is null.
PatchSets define a named set of patches that may be included by any
resource in this Composition. PatchSets cannot themselves refer to other
PatchSets.
PatchSets are only used by the "Resources" mode of Composition. They
are ignored by other modes.
The list of references is used to compute an in-memory environment at
compose time. The data of all object is merged in the order they are
listed, meaning the values of EnvironmentConfigs with a larger index take
priority over ones with smaller indices.
The computed environment can be accessed in a composition using
`FromEnvironmentFieldPath` and `CombineFromEnvironment` patches.
Deprecated: Use Composition Functions instead.
items:
description: EnvironmentSource selects a EnvironmentConfig resource.
properties:
ref:
description: |-
Ref is a named reference to a single EnvironmentConfig.
Either Ref or Selector is required.
A PatchSet is a set of patches that can be reused from all resources within
a Composition.
properties:
name:
description: The name of the object.
description: Name of this PatchSet.
type: string
required:
- name
type: object
selector:
description: Selector selects EnvironmentConfig(s) via labels.
properties:
matchLabels:
description: MatchLabels ensures an object with matching
labels is selected.
items:
description: |-
An EnvironmentSourceSelectorLabelMatcher acts like a k8s label selector but
can draw the label value from a different path.
properties:
fromFieldPathPolicy:
default: Required
description: |-
FromFieldPathPolicy specifies the policy for the valueFromFieldPath.
The default is Required, meaning that an error will be returned if the
field is not found in the composite resource.
Optional means that if the field is not found in the composite resource,
that label pair will just be skipped. N.B. other specified label
matchers will still be used to retrieve the desired
environment config, if any.
enum:
- Optional
- Required
type: string
key:
description: Key of the label to match.
type: string
type:
default: FromCompositeFieldPath
description: Type specifies where the value for
a label comes from.
enum:
- FromCompositeFieldPath
- Value
type: string
value:
description: Value specifies a literal label value.
type: string
valueFromFieldPath:
description: ValueFromFieldPath specifies the
field path to look for the label value.
type: string
required:
- key
type: object
type: array
maxMatch:
description: MaxMatch specifies the number of extracted
EnvironmentConfigs in Multiple mode, extracts all
if nil.
format: int64
type: integer
minMatch:
description: MinMatch specifies the required minimum
of extracted EnvironmentConfigs in Multiple mode.
format: int64
type: integer
mode:
default: Single
description: 'Mode specifies retrieval strategy: "Single"
or "Multiple".'
enum:
- Single
- Multiple
type: string
sortByFieldPath:
default: metadata.name
description: SortByFieldPath is the path to the field
based on which list of EnvironmentConfigs is alphabetically
sorted.
type: string
type: object
type:
default: Reference
description: |-
Type specifies the way the EnvironmentConfig is selected.
Default is `Reference`
enum:
- Reference
- Selector
type: string
type: object
type: array
patches:
description: |-
Patches is a list of environment patches that are executed before a
composition's resources are composed.
description: Patches will be applied as an overlay to the base
resource.
items:
description: EnvironmentPatch is a patch for a Composition environment.
description: |-
Patch objects are applied between composite and composed resources. Their
behaviour depends on the Type selected. The default Type,
FromCompositeFieldPath, copies a value from the composite resource to
the composed resource, applying any defined transformers.
properties:
combine:
description: |-
@ -260,416 +180,6 @@ spec:
to be used as input. Required when type is FromCompositeFieldPath or
ToCompositeFieldPath.
type: string
policy:
description: Policy configures the specifics of patching
behaviour.
properties:
fromFieldPath:
description: |-
FromFieldPath specifies how to patch from a field path. The default is
'Optional', which means the patch will be a no-op if the specified
fromFieldPath does not exist. Use 'Required' if the patch should fail if
the specified path does not exist.
enum:
- Optional
- Required
type: string
mergeOptions:
description: MergeOptions Specifies merge options on
a field path
properties:
appendSlice:
description: Specifies that already existing elements
in a merged slice should be preserved
type: boolean
keepMapValues:
description: Specifies that already existing values
in a merged map should be preserved
type: boolean
type: object
type: object
toFieldPath:
description: |-
ToFieldPath is the path of the field on the resource whose value will
be changed with the result of transforms. Leave empty if you'd like to
propagate to the same path as fromFieldPath.
type: string
transforms:
description: |-
Transforms are the list of functions that are used as a FIFO pipe for the
input to be transformed.
items:
description: |-
Transform is a unit of process whose input is transformed into an output with
the supplied configuration.
properties:
convert:
description: Convert is used to cast the input into
the given output type.
properties:
format:
description: |-
The expected input format.
* `quantity` - parses the input as a K8s [`resource.Quantity`](https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity).
Only used during `string -> float64` conversions.
* `json` - parses the input as a JSON string.
Only used during `string -> object` or `string -> list` conversions.
If this property is null, the default conversion is applied.
enum:
- none
- quantity
- json
type: string
toType:
description: ToType is the type of the output
of this transform.
enum:
- string
- int
- int64
- bool
- float64
- object
- array
type: string
required:
- toType
type: object
map:
additionalProperties:
x-kubernetes-preserve-unknown-fields: true
description: Map uses the input as a key in the given
map and returns the value.
type: object
match:
description: Match is a more complex version of Map
that matches a list of patterns.
properties:
fallbackTo:
default: Value
description: Determines to what value the transform
should fallback if no pattern matches.
enum:
- Value
- Input
type: string
fallbackValue:
description: |-
The fallback value that should be returned by the transform if now pattern
matches.
x-kubernetes-preserve-unknown-fields: true
patterns:
description: |-
The patterns that should be tested against the input string.
Patterns are tested in order. The value of the first match is used as
result of this transform.
items:
description: |-
MatchTransformPattern is a transform that returns the value that matches a
pattern.
properties:
literal:
description: |-
Literal exactly matches the input string (case sensitive).
Is required if `type` is `literal`.
type: string
regexp:
description: |-
Regexp to match against the input string.
Is required if `type` is `regexp`.
type: string
result:
description: The value that is used as result
of the transform if the pattern matches.
x-kubernetes-preserve-unknown-fields: true
type:
default: literal
description: |-
Type specifies how the pattern matches the input.
* `literal` - the pattern value has to exactly match (case sensitive) the
input string. This is the default.
* `regexp` - the pattern treated as a regular expression against
which the input string is tested. Crossplane will throw an error if the
key is not a valid regexp.
enum:
- literal
- regexp
type: string
required:
- result
- type
type: object
type: array
type: object
math:
description: |-
Math is used to transform the input via mathematical operations such as
multiplication.
properties:
clampMax:
description: ClampMax makes sure that the value
is not bigger than the given value.
format: int64
type: integer
clampMin:
description: ClampMin makes sure that the value
is not smaller than the given value.
format: int64
type: integer
multiply:
description: Multiply the value.
format: int64
type: integer
type:
default: Multiply
description: Type of the math transform to be
run.
enum:
- Multiply
- ClampMin
- ClampMax
type: string
type: object
string:
description: |-
String is used to transform the input into a string or a different kind
of string. Note that the input does not necessarily need to be a string.
properties:
convert:
description: |-
Optional conversion method to be specified.
`ToUpper` and `ToLower` change the letter case of the input string.
`ToBase64` and `FromBase64` perform a base64 conversion based on the input string.
`ToJson` converts any input value into its raw JSON representation.
`ToSha1`, `ToSha256` and `ToSha512` generate a hash value based on the input
converted to JSON.
`ToAdler32` generate a addler32 hash based on the input string.
enum:
- ToUpper
- ToLower
- ToBase64
- FromBase64
- ToJson
- ToSha1
- ToSha256
- ToSha512
- ToAdler32
type: string
fmt:
description: |-
Format the input using a Go format string. See
https://golang.org/pkg/fmt/ for details.
type: string
join:
description: Join defines parameters to join a
slice of values to a string.
properties:
separator:
description: |-
Separator defines the character that should separate the values from each
other in the joined string.
type: string
required:
- separator
type: object
regexp:
description: Extract a match from the input using
a regular expression.
properties:
group:
description: Group number to match. 0 (the
default) matches the entire expression.
type: integer
match:
description: |-
Match string. May optionally include submatches, aka capture groups.
See https://pkg.go.dev/regexp/ for details.
type: string
required:
- match
type: object
trim:
description: Trim the prefix or suffix from the
input
type: string
type:
default: Format
description: Type of the string transform to be
run.
enum:
- Format
- Convert
- TrimPrefix
- TrimSuffix
- Regexp
- Join
type: string
type: object
type:
description: Type of the transform to be run.
enum:
- map
- match
- math
- string
- convert
type: string
required:
- type
type: object
type: array
type:
default: FromCompositeFieldPath
description: |-
Type sets the patching behaviour to be used. Each patch type may require
its own fields to be set on the Patch object.
enum:
- FromCompositeFieldPath
- ToCompositeFieldPath
- CombineFromComposite
- CombineToComposite
type: string
type: object
type: array
policy:
description: |-
Policy represents the Resolve and Resolution policies which apply to
all EnvironmentSourceReferences in EnvironmentConfigs list.
properties:
resolution:
default: Required
description: |-
Resolution specifies whether resolution of this reference is required.
The default is 'Required', which means the reconcile will fail if the
reference cannot be resolved. 'Optional' means this reference will be
a no-op if it cannot be resolved.
enum:
- Required
- Optional
type: string
resolve:
description: |-
Resolve specifies when this reference should be resolved. The default
is 'IfNotPresent', which will attempt to resolve the reference only when
the corresponding field is not present. Use 'Always' to resolve the
reference on every reconcile.
enum:
- Always
- IfNotPresent
type: string
type: object
type: object
mode:
default: Resources
description: |-
Mode controls what type or "mode" of Composition will be used.
"Resources" (the default) indicates that a Composition uses what is
commonly referred to as "Patch & Transform" or P&T composition. This mode
of Composition uses an array of resources, each a template for a composed
resource.
"Pipeline" indicates that a Composition specifies a pipeline
of Composition Functions, each of which is responsible for producing
composed resources that Crossplane should create or update. THE PIPELINE
MODE IS A BETA FEATURE. It is not honored if the relevant Crossplane
feature flag is disabled.
enum:
- Resources
- Pipeline
type: string
patchSets:
description: |-
PatchSets define a named set of patches that may be included by any
resource in this Composition. PatchSets cannot themselves refer to other
PatchSets.
PatchSets are only used by the "Resources" mode of Composition. They
are ignored by other modes.
items:
description: |-
A PatchSet is a set of patches that can be reused from all resources within
a Composition.
properties:
name:
description: Name of this PatchSet.
type: string
patches:
description: Patches will be applied as an overlay to the base
resource.
items:
description: |-
Patch objects are applied between composite and composed resources. Their
behaviour depends on the Type selected. The default Type,
FromCompositeFieldPath, copies a value from the composite resource to
the composed resource, applying any defined transformers.
properties:
combine:
description: |-
Combine is the patch configuration for a CombineFromComposite,
CombineFromEnvironment, CombineToComposite or CombineToEnvironment patch.
properties:
strategy:
description: |-
Strategy defines the strategy to use to combine the input variable values.
Currently only string is supported.
enum:
- string
type: string
string:
description: |-
String declares that input variables should be combined into a single
string, using the relevant settings for formatting purposes.
properties:
fmt:
description: |-
Format the input using a Go format string. See
https://golang.org/pkg/fmt/ for details.
type: string
required:
- fmt
type: object
variables:
description: |-
Variables are the list of variables whose values will be retrieved and
combined.
items:
description: |-
A CombineVariable defines the source of a value that is combined with
others to form and patch an output value. Currently, this only supports
retrieving values from a field path.
properties:
fromFieldPath:
description: |-
FromFieldPath is the path of the field on the source whose value is
to be used as input.
type: string
required:
- fromFieldPath
type: object
minItems: 1
type: array
required:
- strategy
- variables
type: object
fromFieldPath:
description: |-
FromFieldPath is the path of the field on the resource whose value is
to be used as input. Required when type is FromCompositeFieldPath,
FromEnvironmentFieldPath, ToCompositeFieldPath, ToEnvironmentFieldPath.
type: string
patchSetName:
description: PatchSetName to include patches from. Required
when type is PatchSet.
@ -690,7 +200,7 @@ spec:
type: string
mergeOptions:
description: MergeOptions Specifies merge options
on a field path
on a field path.
properties:
appendSlice:
description: Specifies that already existing elements
@ -725,13 +235,11 @@ spec:
description: |-
The expected input format.
* `quantity` - parses the input as a K8s [`resource.Quantity`](https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity).
Only used during `string -> float64` conversions.
* `json` - parses the input as a JSON string.
Only used during `string -> object` or `string -> list` conversions.
If this property is null, the default conversion is applied.
enum:
- none
@ -806,11 +314,9 @@ spec:
description: |-
Type specifies how the pattern matches the input.
* `literal` - the pattern value has to exactly match (case sensitive) the
input string. This is the default.
* `regexp` - the pattern treated as a regular expression against
which the input string is tested. Crossplane will throw an error if the
key is not a valid regexp.
@ -948,14 +454,10 @@ spec:
its own fields to be set on the Patch object.
enum:
- FromCompositeFieldPath
- FromEnvironmentFieldPath
- PatchSet
- ToCompositeFieldPath
- ToEnvironmentFieldPath
- CombineFromEnvironment
- CombineFromComposite
- CombineToComposite
- CombineToEnvironment
type: string
type: object
type: array
@ -970,16 +472,51 @@ spec:
composite resource referring to this composition is created. One of
resources and pipeline must be specified - you cannot specify both.
The Pipeline is only used by the "Pipeline" mode of Composition. It is
ignored by other modes.
THIS IS A BETA FIELD. It is not honored if the relevant Crossplane
feature flag is disabled.
items:
description: A PipelineStep in a Composition Function pipeline.
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:
description: |-
FunctionRef is a reference to the Composition Function this step should
@ -1007,6 +544,9 @@ spec:
- step
type: object
type: array
x-kubernetes-list-map-keys:
- step
x-kubernetes-list-type: map
publishConnectionDetailsWithStoreConfigRef:
default:
name: default
@ -1015,7 +555,6 @@ spec:
with which the connection details of composite resources dynamically
provisioned using this composition will be published.
THIS IS AN ALPHA FIELD. Do not use it in production. It is not honored
unless the relevant Crossplane feature flag is enabled, and may be
changed or removed without notice.
@ -1031,9 +570,10 @@ spec:
Resources is a list of resource templates that will be used when a
composite resource referring to this composition is created.
Resources are only used by the "Resources" mode of Composition. They are
ignored by other modes.
Deprecated: Use Composition Functions instead.
items:
description: |-
ComposedTemplate is used to provide information about how the composed resource
@ -1115,8 +655,8 @@ spec:
properties:
combine:
description: |-
Combine is the patch configuration for a CombineFromComposite,
CombineFromEnvironment, CombineToComposite or CombineToEnvironment patch.
Combine is the patch configuration for a CombineFromComposite or
CombineToComposite patch.
properties:
strategy:
description: |-
@ -1165,8 +705,8 @@ spec:
fromFieldPath:
description: |-
FromFieldPath is the path of the field on the resource whose value is
to be used as input. Required when type is FromCompositeFieldPath,
FromEnvironmentFieldPath, ToCompositeFieldPath, ToEnvironmentFieldPath.
to be used as input. Required when type is FromCompositeFieldPath or
ToCompositeFieldPath.
type: string
patchSetName:
description: PatchSetName to include patches from. Required
@ -1188,7 +728,7 @@ spec:
type: string
mergeOptions:
description: MergeOptions Specifies merge options
on a field path
on a field path.
properties:
appendSlice:
description: Specifies that already existing elements
@ -1223,13 +763,11 @@ spec:
description: |-
The expected input format.
* `quantity` - parses the input as a K8s [`resource.Quantity`](https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity).
Only used during `string -> float64` conversions.
* `json` - parses the input as a JSON string.
Only used during `string -> object` or `string -> list` conversions.
If this property is null, the default conversion is applied.
enum:
- none
@ -1304,11 +842,9 @@ spec:
description: |-
Type specifies how the pattern matches the input.
* `literal` - the pattern value has to exactly match (case sensitive) the
input string. This is the default.
* `regexp` - the pattern treated as a regular expression against
which the input string is tested. Crossplane will throw an error if the
key is not a valid regexp.
@ -1446,14 +982,10 @@ spec:
its own fields to be set on the Patch object.
enum:
- FromCompositeFieldPath
- FromEnvironmentFieldPath
- PatchSet
- ToCompositeFieldPath
- ToEnvironmentFieldPath
- CombineFromEnvironment
- CombineFromComposite
- CombineToComposite
- CombineToEnvironment
type: string
type: object
type: array
@ -1470,7 +1002,7 @@ spec:
items:
description: |-
ReadinessCheck is used to indicate how to tell whether a resource is ready
for consumption
for consumption.
properties:
fieldPath:
description: FieldPath shows the path of the field whose

View File

@ -1,8 +1,9 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.14.0
controller-gen.kubebuilder.io/version: v0.16.5
name: environmentconfigs.apiextensions.crossplane.io
spec:
group: apiextensions.crossplane.io
@ -24,8 +25,54 @@ spec:
name: v1alpha1
schema:
openAPIV3Schema:
description: A EnvironmentConfig contains a set of arbitrary, unstructured
values.
description: |-
An EnvironmentConfig contains user-defined unstructured values for
use in a Composition.
Read the Crossplane documentation for
[more information about EnvironmentConfigs](https://docs.crossplane.io/latest/concepts/environment-configs).
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
data:
additionalProperties:
x-kubernetes-preserve-unknown-fields: true
description: |-
The data of this EnvironmentConfig.
This may contain any kind of structure that can be serialized into JSON.
type: object
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
type: object
served: true
storage: false
subresources: {}
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
name: v1beta1
schema:
openAPIV3Schema:
description: |-
An EnvironmentConfig contains user-defined unstructured values for
use in a Composition.
Read the Crossplane documentation for
[more information about EnvironmentConfigs](https://docs.crossplane.io/latest/concepts/environment-configs).
properties:
apiVersion:
description: |-

View File

@ -1,8 +1,9 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.14.0
controller-gen.kubebuilder.io/version: v0.16.5
name: usages.apiextensions.crossplane.io
spec:
group: apiextensions.crossplane.io
@ -28,8 +29,14 @@ spec:
name: v1alpha1
schema:
openAPIV3Schema:
description: A Usage defines a deletion blocking relationship between two
resources.
description: |-
A Usage defines a deletion blocking relationship between two 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:
apiVersion:
description: |-
@ -168,6 +175,13 @@ spec:
A Message containing details about this condition's last transition from
one status to another, if any.
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:
description: A Reason for this condition's last transition from
one status to another.

View File

@ -1,6 +1,6 @@
#!/bin/bash
release="release-1.15"
release="v1.18.0"
apiextensions=$(gh api --jq '.[].name' "/repos/crossplane/crossplane/contents/cluster/crds?ref=${release}" | grep apiextensions)

View File

@ -1,11 +1,11 @@
package io.crossplane.compositefunctions.base;
import io.crossplane.compositefunctions.protobuf.FunctionRunnerServiceGrpc;
import io.crossplane.compositefunctions.protobuf.Requirements;
import io.crossplane.compositefunctions.protobuf.RunFunctionRequest;
import io.crossplane.compositefunctions.protobuf.RunFunctionResponse;
import io.crossplane.compositefunctions.protobuf.State;
import io.crossplane.compositefunctions.protobuf.v1.FunctionRunnerServiceGrpc;
import io.crossplane.compositefunctions.protobuf.v1.Requirements;
import io.crossplane.compositefunctions.protobuf.v1.RunFunctionRequest;
import io.crossplane.compositefunctions.protobuf.v1.RunFunctionResponse;
import io.crossplane.compositefunctions.protobuf.v1.State;
import io.grpc.stub.StreamObserver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -33,9 +33,8 @@ public abstract class CrossplaneCompositeFunctionBase extends FunctionRunnerServ
desiredBuilder.putAllResources(desired.getResourcesMap());
CrossplaneFunctionRequest crossplaneFunctionRequest = new CrossplaneFunctionRequest(request.getObserved(),
request.getExtraResourcesMap(), request.getDesired());
request.getExtraResourcesMap(), request.getCredentialsMap(), request.getDesired());
// request.getCredentialsMap(),
logger.debug("Calling method with implemented logic");
CrossplaneFunctionResponse crossplaneFunctionResponse = runFunction(crossplaneFunctionRequest);
@ -55,11 +54,14 @@ public abstract class CrossplaneCompositeFunctionBase extends FunctionRunnerServ
responseBuilder.setRequirements(requirements);
}
if (! crossplaneFunctionResponse.results().isEmpty()) {
responseBuilder.addAllResults(crossplaneFunctionResponse.results());
}
if (! crossplaneFunctionResponse.conditions().isEmpty()) {
responseBuilder.addAllConditions(crossplaneFunctionResponse.conditions());
}
if (desiredBuilder.getResourcesCount() > 0) {
responseBuilder.setDesired(desiredBuilder.build());
}

View File

@ -1,7 +1,8 @@
package io.crossplane.compositefunctions.base;
import io.crossplane.compositefunctions.protobuf.Resources;
import io.crossplane.compositefunctions.protobuf.State;
import io.crossplane.compositefunctions.protobuf.v1.Credentials;
import io.crossplane.compositefunctions.protobuf.v1.Resources;
import io.crossplane.compositefunctions.protobuf.v1.State;
import java.util.Map;
@ -9,12 +10,10 @@ 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
* @param desiredState The sum of previously called functions state. To override, create a new resource with the same name in the response
*/
public record CrossplaneFunctionRequest(State observedState, Map<String, Resources> extraResourcesMap, State desiredState) {
public record CrossplaneFunctionRequest(State observedState, Map<String, Resources> extraResourcesMap,
Map<String, Credentials> credentialsMap, State desiredState) {
// *
// * @param credentialsMap A map of credentials sent as input
//
// Map<String, Credentials> credentialsMap
}

View File

@ -1,7 +1,8 @@
package io.crossplane.compositefunctions.base;
import io.crossplane.compositefunctions.protobuf.ResourceSelector;
import io.crossplane.compositefunctions.protobuf.Result;
import io.crossplane.compositefunctions.protobuf.v1.Condition;
import io.crossplane.compositefunctions.protobuf.v1.ResourceSelector;
import io.crossplane.compositefunctions.protobuf.v1.Result;
import java.util.ArrayList;
import java.util.HashMap;
@ -16,7 +17,7 @@ import java.util.Map;
*/
public record CrossplaneFunctionResponse(Map<String, Object> desiredResources,
Map<String, ResourceSelector> resourceSelectors,
List<Result> results) {
List<Result> results, List<Condition> conditions) {
//
//
@ -26,6 +27,6 @@ public record CrossplaneFunctionResponse(Map<String, Object> desiredResources,
* Create an empty response with all fields initiated
*/
public CrossplaneFunctionResponse() {
this(new HashMap<>(), new HashMap<>(), new ArrayList<>());
this(new HashMap<>(), new HashMap<>(), new ArrayList<>(), new ArrayList<>());
}
}

View File

@ -3,7 +3,7 @@ package io.crossplane.compositefunctions.base;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.protobuf.Struct;
import com.google.protobuf.util.JsonFormat;
import io.crossplane.compositefunctions.protobuf.Resource;
import io.crossplane.compositefunctions.protobuf.v1.Resource;
/**
* Helper class for converting Java Objects into protobuf Structs within the Resource object

View File

@ -1,9 +1,46 @@
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.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Bean;
/**
* 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

@ -2,23 +2,29 @@ package io.crossplane.compositefunctions.starter.conversion;
import com.google.protobuf.util.JsonFormat;
import io.crossplane.compositefunctions.protobuf.ResourceSelector;
import io.crossplane.compositefunctions.protobuf.Resources;
import io.crossplane.compositefunctions.starter.exception.CrossplaneUnexpectedItemsException;
import io.crossplane.compositefunctions.protobuf.v1.ResourceSelector;
import io.crossplane.compositefunctions.protobuf.v1.Resources;
import io.crossplane.compositefunctions.starter.exception.CrossplaneUnmarshallException;
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.HashMap;
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);
@ -26,17 +32,19 @@ public class CrossplaneExtraResourcesService {
public <T> Optional<T> getExtraResource(Map<String, Resources> extraResources, String resourceName, Class<T> clazz) {
return getExtraResources(extraResources, resourceName, 1, clazz).get(0);
List<Optional<T>> resources = getExtraResources(extraResources, resourceName, 1, clazz);
if (resources.isEmpty()) {
return Optional.empty();
}
return resources.get(0);
}
public <T> List<Optional<T>> getExtraResources(Map<String, Resources> extraResources, String resourceName, int expectedResources, Class<T> clazz) {
List<Optional<T>> result = new ArrayList<>();
Resources resources = extraResources.get(resourceName);
if (resources != null ) {
if (resources.getItemsCount() != expectedResources) {
throw new CrossplaneUnexpectedItemsException("Unexpected number of resources. Expected " + expectedResources + " but got " + resources.getItemsCount() + ".");
}
if (resources != null && resources.getItemsCount() == expectedResources) {
for (int i = 0; i < expectedResources; i++) {
try {
logger.debug("We have an extra resource " + clazz.getSimpleName());
@ -50,6 +58,39 @@ public class CrossplaneExtraResourcesService {
return result;
}
public Map<String, String> getConnectionDetails(Map<String, Resources> extraResources, String resourceName) {
List<Map<String, String>> resources = getConnectionDetails(extraResources, resourceName, 1);
if (resources.isEmpty()) {
return new HashMap<>();
}
return resources.get(0);
}
public List<Map<String, String>> getConnectionDetails(Map<String, Resources> extraResources, String resourceName, int expectedResources) {
List<Map<String, String>> result = new ArrayList<>();
Resources resources = extraResources.get(resourceName);
if (resources != null && resources.getItemsCount() == expectedResources) {
for (int i = 0; i < expectedResources; i++) {
try {
logger.debug("We have connectiondetails " + resourceName);
Map<String, String> currentDetails = new HashMap<>();
resources.getItems(i).getConnectionDetailsMap().forEach((key, value) ->
currentDetails.put(key, value.toStringUtf8())
);
result.add(currentDetails);
} catch (Exception e) {
throw new CrossplaneUnmarshallException("Error when unmarshalling the connectionDetails", e);
}
}
}
return result;
}
public Map<String, ResourceSelector> createExtraResourcesSelector(String resourceName, HasMetadata type) {
ResourceSelector resourceSelector = ResourceSelector.newBuilder()
.setApiVersion(type.getApiVersion())

View File

@ -2,22 +2,33 @@ package io.crossplane.compositefunctions.starter.conversion;
import com.google.protobuf.util.JsonFormat;
import io.crossplane.compositefunctions.protobuf.Resource;
import io.crossplane.compositefunctions.protobuf.State;
import io.crossplane.compositefunctions.protobuf.v1.Resource;
import io.crossplane.compositefunctions.protobuf.v1.State;
import io.crossplane.compositefunctions.starter.exception.CrossplaneUnmarshallException;
import io.fabric8.kubernetes.client.utils.Serialization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
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();
@ -33,4 +44,22 @@ public class CrossplaneObservableService {
return result;
}
public Map<String, String> getObservableConnectionDetails(String resourceName, State observedState) {
Resource observedResource = observedState.getResourcesOrDefault(resourceName, null);
Map<String, String> result = new HashMap<>();
if (observedResource != null) {
try {
logger.debug("We have an observed connectionDetails for " + resourceName);
observedResource.getConnectionDetailsMap().forEach((key, value) ->
result.put(key, value.toStringUtf8())
);
} catch (Exception e) {
throw new CrossplaneUnmarshallException("Error when unmarshalling the connectionDetails for " + resourceName, e);
}
}
return result;
}
}

View File

@ -1,18 +1,26 @@
package io.crossplane.compositefunctions.starter.conversion;
import com.google.protobuf.util.JsonFormat;
import io.crossplane.compositefunctions.protobuf.State;
import io.crossplane.compositefunctions.protobuf.v1.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()));
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());
// This is not 100%. isStorage vs referencable. Need to check the crossplane docs
versions.setReferenceable(compositionDefinition.isStorage());
versions.setServed(compositionDefinition.isServed());
compositeResourceDefinition.setMetadata(CrossplaneMetadataBuilder.createMetadata(namePrefix + compositionDefinition.getCRDName()));
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

@ -1,10 +1,13 @@
package io.crossplane.compositefunctions.starter.registration;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatTypes;
import com.fasterxml.jackson.module.jsonSchema.jakarta.JsonSchema;
import com.fasterxml.jackson.module.jsonSchema.jakarta.JsonSchemaGenerator;
import com.fasterxml.jackson.module.jsonSchema.jakarta.factories.SchemaFactoryWrapper;
import com.fasterxml.jackson.module.jsonSchema.jakarta.factories.VisitorContext;
import com.fasterxml.jackson.module.jsonSchema.jakarta.types.ArraySchema;
import io.crossplane.apiextensions.v1.compositeresourcedefinitionspec.versions.schema.OpenAPIV3Schema;
import io.fabric8.kubernetes.api.model.apiextensions.v1.JSONSchemaProps;
@ -12,15 +15,34 @@ 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();
//Add mixin class to ignore id field as OpenShift does not support it.
mapper.addMixIn(clazz, mixin);
// apper.addMixIn(ObjectMeta.class, MetadataIgnorer.class);
JsonSchemaGenerator generator = new JsonSchemaGenerator(mapper);
SchemaFactoryWrapper visitor = new SchemaFactoryWrapper();
visitor.setVisitorContext(new VisitorContext(){
@Override
public String addSeenSchemaUri(JavaType aSeenSchema) {
return javaTypeToUrn(aSeenSchema);
}
});
JsonSchemaGenerator generator = new JsonSchemaGenerator(mapper, visitor);
JsonSchema jsonSchema = generator.generateSchema(clazz);
removeIdField(jsonSchema);
@ -52,6 +74,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 +100,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();

View File

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

View File

@ -19,10 +19,10 @@ syntax = "proto3";
import "google/protobuf/struct.proto";
import "google/protobuf/duration.proto";
package apiextensions.fn.proto.v1beta1;
package apiextensions.fn.proto.v1;
option go_package = "github.com/crossplane/crossplane/apis/apiextensions/fn/proto/v1beta1";
option java_package = "io.crossplane.compositefunctions.protobuf";
option go_package = "github.com/crossplane/crossplane/apis/apiextensions/fn/proto/v1";
option java_package = "io.crossplane.compositefunctions.protobuf.v1";
option java_multiple_files = true;
// A FunctionRunnerService is a Composition Function.
@ -70,6 +70,24 @@ message RunFunctionRequest {
// did not exist, Crossplane sets the map key to an empty Resources message to
// indicate that it attempted to satisfy the request.
map<string, Resources> extra_resources = 6;
// Optional credentials that this Function may use to communicate with an
// external system.
map <string, Credentials> credentials = 7;
}
// Credentials that a Function may use to communicate with an external system.
message Credentials {
// Source of the credentials.
oneof source {
// Credential data loaded by Crossplane, for example from a Secret.
CredentialData credential_data = 1;
}
}
// CredentialData loaded by Crossplane, for example from a Secret.
message CredentialData {
map<string, bytes> data = 1;
}
// Resources represents the state of several Crossplane resources.
@ -105,6 +123,10 @@ message RunFunctionResponse {
// Requirements that must be satisfied for this Function to run successfully.
Requirements requirements = 5;
// Status conditions to be applied to the composite resource. Conditions may also
// optionally be applied to the composite resource's associated claim.
repeated Condition conditions = 6;
}
// RequestMeta contains metadata pertaining to a RunFunctionRequest.
@ -123,11 +145,18 @@ message Requirements {
// ResourceSelector selects a group of resources, either by name or by label.
message ResourceSelector {
// API version of resources to select.
string api_version = 1;
// Kind of resources to select.
string kind = 2;
// Resources to match.
oneof match {
// Match the resource with this name.
string match_name = 3;
// Match all resources with these labels.
MatchLabels match_labels = 4;
}
}
@ -197,8 +226,11 @@ message Resource {
// * A Function should set this field to READY_TRUE in a RunFunctionResponse
// to indicate that a desired composed resource is ready.
//
// * A Function should not set this field in a RunFunctionResponse to indicate
// that the desired composite resource is ready. This will be ignored.
// * A Function should set this field to READY_TRUE in a RunFunctionResponse
// to indicate that a desired composite resource is ready.
// This overwrites the standard readiness detection that determines the
// ready state of the composite by the ready state of the the
// composed resources.
Ready ready = 3;
}
@ -220,6 +252,13 @@ message Result {
// Human-readable details about the result.
string message = 2;
// Optional PascalCase, machine-readable reason for this result. If omitted,
// the value will be ComposeResources.
optional string reason = 3;
// The resources this result targets.
optional Target target = 4;
}
// Severity of Function results.
@ -240,3 +279,53 @@ enum Severity {
// with the composite resource.
SEVERITY_NORMAL = 3;
}
// Target of Function results and conditions.
enum Target {
// If the target is unspecified, the result targets the composite resource.
TARGET_UNSPECIFIED = 0;
// Target the composite resource. Results that target the composite resource
// should include detailed, advanced information.
TARGET_COMPOSITE = 1;
// Target the composite and the claim. Results that target the composite and
// the claim should include only end-user friendly information.
TARGET_COMPOSITE_AND_CLAIM = 2;
}
// Status condition to be applied to the composite resource. Condition may also
// optionally be applied to the composite resource's associated claim. For
// detailed information on proper usage of status conditions, please see
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties.
message Condition {
// Type of condition in PascalCase.
string type = 1;
// Status of the condition.
Status status = 2;
// Reason contains a programmatic identifier indicating the reason for the
// condition's last transition. Producers of specific condition types may
// define expected values and meanings for this field, and whether the values
// are considered a guaranteed API. The value should be a PascalCase string.
// This field may not be empty.
string reason = 3;
// Message is a human readable message indicating details about the
// transition. This may be an empty string.
optional string message = 4;
// The resources this condition targets.
optional Target target = 5;
}
enum Status {
STATUS_CONDITION_UNSPECIFIED = 0;
STATUS_CONDITION_UNKNOWN = 1;
STATUS_CONDITION_TRUE = 2;
STATUS_CONDITION_FALSE = 3;
}

View File

@ -0,0 +1,188 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.crossplane.providers</groupId>
<artifactId>crossplane-providers-parent</artifactId>
<version>${revision}</version>
<packaging>pom</packaging>
<url>https://crossplane.io/</url>
<description>Crossplane parent pom for provider models</description>
<properties>
<revision>1.0.0-SNAPSHOT</revision>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.target>17</maven.compiler.target>
<maven.compiler.source>17</maven.compiler.source>
<!-- Dependency versions -->
<spring-boot.version>3.3.3</spring-boot.version>
<kubernetes-client.version>6.13.3</kubernetes-client.version>
<jackson-databind.version>2.17.1</jackson-databind.version>
<!-- Plugin versions -->
<flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version>
<central-publishing-maven-plugin.version>0.4.0</central-publishing-maven-plugin.version>
<maven-source-plugin.version>3.3.1</maven-source-plugin.version>
<maven-javadoc-plugin.version>3.7.0</maven-javadoc-plugin.version>
<maven-jar-plugin.version>3.4.2</maven-jar-plugin.version>
<maven-gpg-plugin.version>3.2.4</maven-gpg-plugin.version>
<build-helper-maven-plugin.version>3.6.0</build-helper-maven-plugin.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-client-bom</artifactId>
<version>${kubernetes-client.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-databind.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<!-- To make the artifacts with ${revision} usable by maven, they have to be flattened -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>${flatten-maven-plugin.version}</version>
<configuration>
<updatePomFile>true</updatePomFile>
<flattenMode>resolveCiFriendliesOnly</flattenMode>
</configuration>
<executions>
<execution>
<id>flatten</id>
<phase>process-resources</phase>
<goals>
<goal>flatten</goal>
</goals>
</execution>
<execution>
<id>flatten.clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.central</groupId>
<artifactId>central-publishing-maven-plugin</artifactId>
<version>${central-publishing-maven-plugin.version}</version>
<extensions>true</extensions>
<configuration>
<publishingServerId>central</publishingServerId>
<tokenAuth>true</tokenAuth>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>${maven-source-plugin.version}</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven-javadoc-plugin.version}</version>
<configuration>
<doclint>all,missing</doclint>
<excludePackageNames>io.upbound.*,io.crossplane.*</excludePackageNames>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<licenses>
<license>
<name>The Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<developers>
<developer>
<name>Knut-Erik Johnsen</name>
<organization>Crossplane</organization>
<organizationUrl>https://crossplane.io</organizationUrl>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/crossplane/function-sdk-java.git</connection>
<developerConnection>scm:git:ssh://github.com:crossplane/function-sdk-java.git</developerConnection>
<url>https://github.com/crossplane/function-sdk-java/tree/main</url>
</scm>
<profiles>
<profile>
<id>deploy</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>${maven-gpg-plugin.version}</version>
<configuration>
<gpgArguments>
<arg>--pinentry-mode</arg>
<arg>loopback</arg>
</gpgArguments>
</configuration>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

50
pom.xml
View File

@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.1</version>
<version>3.3.3</version>
</parent>
<groupId>io.crossplane.compositefunctions</groupId>
@ -25,11 +25,11 @@
<maven.compiler.source>17</maven.compiler.source>
<!-- Dependency versions -->
<spring-boot.version>3.3.1</spring-boot.version>
<kubernetes-client.version>6.13.0</kubernetes-client.version>
<spring-boot.version>3.3.3</spring-boot.version>
<kubernetes-client.version>6.13.3</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>
<protobuf.version>3.25.5</protobuf.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>
@ -50,6 +50,7 @@
<module>crossplane-protobuf-model</module>
<module>crossplane-function-base</module>
<module>crossplane-function-springboot-starter</module>
<module>crossplane-providers-parent</module>
<module>crossplane-function-example</module>
</modules>
@ -100,43 +101,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>

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- PROJECT -->
<parent>
<groupId>io.crossplane.providers</groupId>
<artifactId>crossplane-providers-parent</artifactId>
<version>1.18.0-charlie</version>
</parent>
<artifactId>crossplane-provider-kubernetes-model</artifactId>
<description>Crossplane models for the Kubernetes provider</description>
<version>${modelrevision}</version>
<properties>
<modelrevision>1.0.0-SNAPSHOT</modelrevision>
</properties>
<!-- DEPENDENCIES -->
<dependencies>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-client</artifactId>
</dependency>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>generator-annotations</artifactId>
</dependency>
</dependencies>
<!-- BUILD -->
<build>
<!-- PLUGINS -->
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>java-generator-maven-plugin</artifactId>
<version>${kubernetes-client.version}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<source>src/main/resources/kubernetes</source>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,7 @@
package io.upbound;
/**
* This is the project for the Kubernetes Provider.
*/
public interface KubernetesProvider {
}

View File

@ -0,0 +1,27 @@
#!/bin/bash
release="v0.15.0"
repo="crossplane-contrib"
provider="provider-kubernetes"
if [ $# -eq 1 ]
then
release="v$1"
fi
echo "Fetching release: ${release}"
crds=$(gh api --jq '.[].name' "/repos/${repo}/${provider}/contents/package/crds?ref=${release}")
for crd in $crds;
do
# output=$(echo $file | cut -d'_' -f2)
gh api -H "Accept: application/vnd.github.raw+json" "/repos/${repo}/${provider}/contents/package/crds/${crd}?ref=${release}" > $crd
retVal=$?
if [ $retVal -ne 0 ]; then
echo "Failed to fetch ${crd}"
fi
done

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- PROJECT -->
<parent>
<groupId>io.crossplane.providers</groupId>
<artifactId>crossplane-providers-parent</artifactId>
<version>1.18.0-charlie</version>
</parent>
<artifactId>crossplane-provider-terraform-model</artifactId>
<description>Crossplane models for the Terraform provider</description>
<version>${modelrevision}</version>
<properties>
<modelrevision>1.0.0-SNAPSHOT</modelrevision>
</properties>
<!-- DEPENDENCIES -->
<dependencies>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-client</artifactId>
</dependency>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>generator-annotations</artifactId>
</dependency>
</dependencies>
<!-- BUILD -->
<build>
<!-- PLUGINS -->
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>java-generator-maven-plugin</artifactId>
<version>${kubernetes-client.version}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<source>src/main/resources/kubernetes</source>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,7 @@
package io.upbound;
/**
* This is the project for the Terraform Provider.
*/
public interface TerraformProvider {
}

View File

@ -0,0 +1,27 @@
#!/bin/bash
release="v0.18.0"
repo="upbound"
provider="provider-terraform"
if [ $# -eq 1 ]
then
release="v$1"
fi
echo "Fetching release: ${release}"
crds=$(gh api --jq '.[].name' "/repos/${repo}/${provider}/contents/package/crds?ref=${release}")
for crd in $crds;
do
# output=$(echo $file | cut -d'_' -f2)
gh api -H "Accept: application/vnd.github.raw+json" "/repos/${repo}/${provider}/contents/package/crds/${crd}?ref=${release}" > $crd
retVal=$?
if [ $retVal -ne 0 ]; then
echo "Failed to fetch ${crd}"
fi
done

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- PROJECT -->
<parent>
<groupId>io.crossplane.providers</groupId>
<artifactId>crossplane-providers-parent</artifactId>
<version>1.18.0-charlie</version>
</parent>
<artifactId>crossplane-provider-upjet-aws-model</artifactId>
<description>Crossplane models for the AWS provider</description>
<version>${modelrevision}</version>
<properties>
<modelrevision>1.0.0-SNAPSHOT</modelrevision>
</properties>
<!-- DEPENDENCIES -->
<dependencies>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-client</artifactId>
</dependency>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>generator-annotations</artifactId>
</dependency>
</dependencies>
<!-- BUILD -->
<build>
<!-- PLUGINS -->
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>java-generator-maven-plugin</artifactId>
<version>${kubernetes-client.version}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<source>src/main/resources/kubernetes</source>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,7 @@
package io.upbound;
/**
* This is the project for the AWS Provider.
*/
public interface AwsProvider {
}

View File

@ -0,0 +1,27 @@
#!/bin/bash
release="v1.15.0"
repo="crossplane-contrib"
provider="provider-upjet-aws"
if [ $# -eq 1 ]
then
release="v$1"
fi
echo "Fetching release: ${release}"
crds=$(gh api --jq '.[].name' "/repos/${repo}/${provider}/contents/package/crds?ref=${release}")
for crd in $crds;
do
# output=$(echo $file | cut -d'_' -f2)
gh api -H "Accept: application/vnd.github.raw+json" "/repos/${repo}/${provider}/contents/package/crds/${crd}?ref=${release}" > $crd
retVal=$?
if [ $retVal -ne 0 ]; then
echo "Failed to fetch ${crd}"
fi
done

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- PROJECT -->
<parent>
<groupId>io.crossplane.providers</groupId>
<artifactId>crossplane-providers-parent</artifactId>
<version>1.18.0-charlie</version>
</parent>
<artifactId>crossplane-provider-upjet-azure-model</artifactId>
<description>Crossplane models for the Azure upjet based provider</description>
<version>${modelrevision}</version>
<properties>
<modelrevision>1.0.0-SNAPSHOT</modelrevision>
</properties>
<!-- DEPENDENCIES -->
<dependencies>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-client</artifactId>
</dependency>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>generator-annotations</artifactId>
</dependency>
</dependencies>
<!-- BUILD -->
<build>
<!-- PLUGINS -->
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>java-generator-maven-plugin</artifactId>
<version>${kubernetes-client.version}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<source>src/main/resources/kubernetes</source>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,7 @@
package io.upbound;
/**
* This is the project for the upjet based Azure Provider.
*/
public interface AzureProvider {
}

View File

@ -0,0 +1,25 @@
#!/bin/bash
release="v1.0.1"
if [ $# -eq 1 ]
then
release="v$1"
fi
echo "Fetching release: ${release}"
crds=$(gh api --jq '.[].name' "/repos/crossplane-contrib/provider-upjet-azure/contents/package/crds?ref=${release}")
for crd in $crds;
do
# output=$(echo $file | cut -d'_' -f2)
gh api -H "Accept: application/vnd.github.raw+json" "/repos/crossplane-contrib/provider-upjet-azure/contents/package/crds/${crd}?ref=${release}" > $crd
retVal=$?
if [ $retVal -ne 0 ]; then
echo "Failed to fetch ${crd}"
fi
done

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- PROJECT -->
<parent>
<groupId>io.crossplane.providers</groupId>
<artifactId>crossplane-providers-parent</artifactId>
<version>1.18.0-charlie</version>
</parent>
<artifactId>crossplane-provider-upjet-azuread-model</artifactId>
<description>Crossplane models for the Azure AD upjet based provider</description>
<version>${modelrevision}</version>
<properties>
<modelrevision>1.0.0-SNAPSHOT</modelrevision>
</properties>
<!-- DEPENDENCIES -->
<dependencies>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-client</artifactId>
</dependency>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>generator-annotations</artifactId>
</dependency>
</dependencies>
<!-- BUILD -->
<build>
<!-- PLUGINS -->
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>java-generator-maven-plugin</artifactId>
<version>${kubernetes-client.version}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<source>src/main/resources/kubernetes</source>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,7 @@
package io.upbound;
/**
* This is the project for the upjet based Azure AD Provider.
*/
public interface AzureADProvider {
}

View File

@ -0,0 +1,24 @@
#!/bin/bash
release="v1.5.0"
if [ $# -eq 1 ]
then
release="v$1"
fi
echo "Fetching release: ${release}"
crds=$(gh api --jq '.[].name' "/repos/crossplane-contrib/provider-upjet-azuread/contents/package/crds?ref=${release}")
for crd in $crds;
do
# output=$(echo $file | cut -d'_' -f2)
gh api -H "Accept: application/vnd.github.raw+json" "/repos/crossplane-contrib/provider-upjet-azuread/contents/package/crds/${crd}?ref=${release}" > $crd
retVal=$?
if [ $retVal -ne 0 ]; then
echo "Failed to fetch ${crd}"
fi
done

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- PROJECT -->
<parent>
<groupId>io.crossplane.providers</groupId>
<artifactId>crossplane-providers-parent</artifactId>
<version>1.18.0-charlie</version>
</parent>
<artifactId>crossplane-provider-upjet-gcp-model</artifactId>
<description>Crossplane models for the GCP provider</description>
<version>${modelrevision}</version>
<properties>
<modelrevision>1.0.0-SNAPSHOT</modelrevision>
</properties>
<!-- DEPENDENCIES -->
<dependencies>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-client</artifactId>
</dependency>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>generator-annotations</artifactId>
</dependency>
</dependencies>
<!-- BUILD -->
<build>
<!-- PLUGINS -->
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>java-generator-maven-plugin</artifactId>
<version>${kubernetes-client.version}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<source>src/main/resources/kubernetes</source>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,7 @@
package io.upbound;
/**
* This is the project for the GCP Provider.
*/
public interface GcpProvider {
}

View File

@ -0,0 +1,27 @@
#!/bin/bash
release="v1.8.3"
repo="crossplane-contrib"
provider="provider-upjet-gcp"
if [ $# -eq 1 ]
then
release="v$1"
fi
echo "Fetching release: ${release}"
crds=$(gh api --jq '.[].name' "/repos/${repo}/${provider}/contents/package/crds?ref=${release}")
for crd in $crds;
do
# output=$(echo $file | cut -d'_' -f2)
gh api -H "Accept: application/vnd.github.raw+json" "/repos/${repo}/${provider}/contents/package/crds/${crd}?ref=${release}" > $crd
retVal=$?
if [ $retVal -ne 0 ]; then
echo "Failed to fetch ${crd}"
fi
done

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- PROJECT -->
<parent>
<groupId>io.crossplane.providers</groupId>
<artifactId>crossplane-providers-parent</artifactId>
<version>1.18.0-charlie</version>
</parent>
<artifactId>crossplane-provider-upjet-github-model</artifactId>
<description>Crossplane models for the Github provider</description>
<version>${modelrevision}</version>
<properties>
<modelrevision>1.0.0-SNAPSHOT</modelrevision>
</properties>
<!-- DEPENDENCIES -->
<dependencies>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-client</artifactId>
</dependency>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>generator-annotations</artifactId>
</dependency>
</dependencies>
<!-- BUILD -->
<build>
<!-- PLUGINS -->
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>java-generator-maven-plugin</artifactId>
<version>${kubernetes-client.version}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<source>src/main/resources/kubernetes</source>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,7 @@
package io.upbound;
/**
* This is the project for the Github Provider.
*/
public interface GithubProvider {
}

View File

@ -0,0 +1,27 @@
#!/bin/bash
release="v0.14.0"
repo="crossplane-contrib"
provider="provider-upjet-github"
if [ $# -eq 1 ]
then
release="v$1"
fi
echo "Fetching release: ${release}"
crds=$(gh api --jq '.[].name' "/repos/${repo}/${provider}/contents/package/crds?ref=${release}")
for crd in $crds;
do
# output=$(echo $file | cut -d'_' -f2)
gh api -H "Accept: application/vnd.github.raw+json" "/repos/${repo}/${provider}/contents/package/crds/${crd}?ref=${release}" > $crd
retVal=$?
if [ $retVal -ne 0 ]; then
echo "Failed to fetch ${crd}"
fi
done