Skip to content

Commit

Permalink
Merge branch 'main' into custom-template-delims
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewChubatiuk authored Nov 16, 2023
2 parents c6f0915 + cfda8ce commit d5fc53c
Show file tree
Hide file tree
Showing 19 changed files with 434 additions and 44 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@

# Go workspace file
go.work

# Binaries
function-go-templating
65 changes: 37 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# function-go-templating

[![CI](https://github.com/crossplane-contrib/function-go-templating/actions/workflows/ci.yml/badge.svg)](https://github.com/crossplane-contrib/function-go-templating/actions/workflows/ci.yml) ![GitHub release (latest SemVer)](https://img.shields.io/github/release/crossplane-contrib/function-go-templating)

This [composition function][docs-functions] allows you to compose Crossplane
resources using [Go templates][go-templates]. If you've written a [Helm
chart][helm-chart] before, using this function will be a familiar experience.
chart][helm-chart] before, using this function will be a familiar experience.

Here's an example:

Expand All @@ -18,29 +19,28 @@ spec:
kind: XR
mode: Pipeline
pipeline:
- step: create-a-bucket
functionRef:
name: function-go-templating
input:
apiVersion: gotemplating.fn.crossplane.io/v1beta1
kind: GoTemplate
source: Inline
inline:
template: |
apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
metadata:
annotations:
gotemplating.fn.crossplane.io/composition-resource-name: bucket
spec:
forProvider:
region: {{ .observed.composite.resource.spec.region }}
- step: automatically-detect-ready-composed-resources
functionRef:
name: function-auto-ready
- step: create-a-bucket
functionRef:
name: function-go-templating
input:
apiVersion: gotemplating.fn.crossplane.io/v1beta1
kind: GoTemplate
source: Inline
inline:
template: |
apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
metadata:
annotations:
gotemplating.fn.crossplane.io/composition-resource-name: bucket
spec:
forProvider:
region: {{ .observed.composite.resource.spec.region }}
- step: automatically-detect-ready-composed-resources
functionRef:
name: function-auto-ready
```
## Using this function
This function can load templates from two sources: `Inline` and `FileSystem`.
Expand All @@ -55,15 +55,15 @@ The templates are passed a [`RunFunctionRequest`][bsr] as data. This means that
you can access the composite resource, any composed resources, and the function
pipeline context using notation like:

* `{{ .observed.composite.resource.metadata.name }}`
* `{{ .desired.composite.resource.status.widgets }}`
* `{{ (index .desired.composed.resource "resource-name").spec.widgets }}`
* `{{ index .context "apiextensions.crossplane.io/environment" }}`
- `{{ .observed.composite.resource.metadata.name }}`
- `{{ .desired.composite.resource.status.widgets }}`
- `{{ (index .desired.composed "resource-name").resource.spec.widgets }}`
- `{{ index .context "apiextensions.crossplane.io/environment" }}`

This function supports all of Go's [built-in template functions][builtin]. The
above examples use the `index` function to access keys like `resource-name` that
contain periods, hyphens and other special characters. Like Helm, this function
also supports [Sprig template functions][sprig].
also supports [Sprig template functions][sprig] as well as [additional functions](#additional-functions).

To return desired composite resource connection details, include a template that
produces the special `CompositeConnectionDetails` resource:
Expand Down Expand Up @@ -98,6 +98,15 @@ $ crossplane beta render xr.yaml composition.yaml functions.yaml
See the [composition functions documentation][docs-functions] to learn more
about `crossplane beta render`.

## Additional functions

| Name | Description |
| ---------------------------------------------------------------- | --------------------------------------------------- |
| [`randomChoice`](example/functions/randomChoice) | Randomly selects one of a given strings |
| [`toYaml`](example/functions/toYaml) | Marshals any object into a YAML string |
| [`fromYaml`](example/functions/fromYaml) | Unmarshals a YAML string into an object |
| [`getResourceCondition`](example/functions/getResourceCondition) | Helper function to retreive conditions of resources |

## Developing this function

This function uses [Go][go], [Docker][docker], and the [Crossplane CLI][cli] to
Expand Down Expand Up @@ -125,4 +134,4 @@ $ crossplane xpkg build -f package --embed-runtime-image=runtime
[sprig]: http://masterminds.github.io/sprig/
[go]: https://go.dev
[docker]: https://www.docker.com
[cli]: https://docs.crossplane.io/latest/cli
[cli]: https://docs.crossplane.io/latest/cli
13 changes: 13 additions & 0 deletions example/.dev/functions.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
# Use this function yaml when developing and executing the function directly instead of in a container
# E.g. `go run . --insecure --debug --address=":9443"`

apiVersion: pkg.crossplane.io/v1beta1
kind: Function
metadata:
name: function-go-templating
annotations:
render.crossplane.io/runtime: Development
render.crossplane.io/runtime-development-target: localhost:9443
spec:
package: xpkg.upbound.io/crossplane-contrib/function-go-templating:latest # ignored
25 changes: 25 additions & 0 deletions example/functions/fromYaml/composition.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: example-function-from-yaml
spec:
compositeTypeRef:
apiVersion: example.crossplane.io/v1beta1
kind: XR
mode: Pipeline
pipeline:
- step: render-templates
functionRef:
name: function-go-templating
input:
apiVersion: gotemplating.fn.crossplane.io/v1beta1
kind: GoTemplate
source: Inline
inline:
template: |
---
apiVersion: {{ .observed.composite.resource.apiVersion }}
kind: {{ .observed.composite.resource.kind }}
status:
# Extract single value from encoded yaml string
dummy: {{ (.observed.composite.resource.spec.yamlBlob | fromYaml).key2 }}
6 changes: 6 additions & 0 deletions example/functions/fromYaml/functions.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: pkg.crossplane.io/v1beta1
kind: Function
metadata:
name: function-go-templating
spec:
package: xpkg.upbound.io/crossplane-contrib/function-go-templating:latest
9 changes: 9 additions & 0 deletions example/functions/fromYaml/xr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: example.crossplane.io/v1beta1
kind: XR
metadata:
name: example
spec:
yamlBlob: |
key1: value1
key2: value2
key3: value3
44 changes: 44 additions & 0 deletions example/functions/getResourceCondition/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# getResourceCondition

## Usage

```golang
{{ getResourceCondition $conditionType $resource }}
{{ $resource | getResourceCondition $conditionType }}
```

Examples:

```golang
// Print whole condition
{{ .observed.resources.project | getResourceCondition "Ready" | toYaml }}

// Check status
{{ if eq (.observed.resources.project | getResourceCondition "Ready").Status "True" }}
// do something
{{ end }}
```

See example composition for more usage examples

## Example Outputs

Requested resource does not exist or does not have the requested condition

´´´yaml
lasttransitiontime: "0001-01-01T00:00:00Z"
message: ""
reason: ""
status: Unknown
type: Ready
´´´

Requested resource does have the requested condition

´´´yaml
lasttransitiontime: "2023-11-03T10:07:31+01:00"
message: "custom message"
reason: foo
status: "True"
type: Ready
´´´
47 changes: 47 additions & 0 deletions example/functions/getResourceCondition/composition.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: example-function-get-resource-condition
spec:
compositeTypeRef:
apiVersion: example.crossplane.io/v1beta1
kind: XR
mode: Pipeline
pipeline:
- step: render-templates
functionRef:
name: function-go-templating
input:
apiVersion: gotemplating.fn.crossplane.io/v1beta1
kind: GoTemplate
source: Inline
inline:
template: |
---
apiVersion: {{ .observed.composite.resource.apiVersion }}
kind: {{ .observed.composite.resource.kind }}
status:
# Retreive condition of XR
compositeCondition:
{{ getResourceCondition "Ready" .observed.composite | toYaml | nindent 4 }}
# Retreive non existing condition of a resource just returns an Unknown condition
compositeConditionNotFound:
{{ getResourceCondition "Other" .observed.composite | toYaml | nindent 4 }}
# You can also retreive conditions of composed resources the same way
composedCondition:
{{ getResourceCondition "Ready" .observed.resources.project | toYaml | nindent 4 }}
# Use a getResourceCondition to render conditional blocks in templates
{{ if eq (getResourceCondition "Ready" .observed.resources.project).Status "True" }}
projectId: {{ .observed.resources.project.resource.status.atProvider.id | quote }}
{{ end }}
# Alternative syntax using pipelines
pipeline:
{{ .observed.resources.project | getResourceCondition "Ready" | toYaml | nindent 4 }}
# Non object
nonResource:
{{ .observed.whatever | getResourceCondition "Ready" | toYaml | nindent 4 }}
6 changes: 6 additions & 0 deletions example/functions/getResourceCondition/functions.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: pkg.crossplane.io/v1beta1
kind: Function
metadata:
name: function-go-templating
spec:
package: xpkg.upbound.io/crossplane-contrib/function-go-templating:latest
21 changes: 21 additions & 0 deletions example/functions/getResourceCondition/observed.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
apiVersion: identity.openstack.upbound.io/v1alpha1
kind: ProjectV3
metadata:
annotations:
crossplane.io/composition-resource-name: project
labels:
crossplane.io/composite: myproject
name: myproject
spec:
forProvider:
name: myproject
providerConfigRef:
name: myprovider
status:
atProvider:
id: abcdef
conditions:
- type: Ready
status: "True"
reason: "foo"
lastTransitionTime: "2023-11-03T09:07:31Z"
12 changes: 12 additions & 0 deletions example/functions/getResourceCondition/xr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: example.crossplane.io/v1beta1
kind: XR
metadata:
name: example
spec:
key: value
status:
conditions:
- type: Ready
status: "True"
reason: "xr foo"
lastTransitionTime: "2023-11-03T09:07:31Z"
25 changes: 25 additions & 0 deletions example/functions/toYaml/composition.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: example-function-to-yaml
spec:
compositeTypeRef:
apiVersion: example.crossplane.io/v1beta1
kind: XR
mode: Pipeline
pipeline:
- step: render-templates
functionRef:
name: function-go-templating
input:
apiVersion: gotemplating.fn.crossplane.io/v1beta1
kind: GoTemplate
source: Inline
inline:
template: |
---
apiVersion: {{ .observed.composite.resource.apiVersion }}
kind: {{ .observed.composite.resource.kind }}
status:
# Copy the whole 'complexDictionary' as is by fomatting it as yaml
dummy: {{ .observed.composite.resource.spec.complexDictionary | toYaml | nindent 7 }}
6 changes: 6 additions & 0 deletions example/functions/toYaml/functions.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: pkg.crossplane.io/v1beta1
kind: Function
metadata:
name: function-go-templating
spec:
package: xpkg.upbound.io/crossplane-contrib/function-go-templating:latest
12 changes: 12 additions & 0 deletions example/functions/toYaml/xr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: example.crossplane.io/v1beta1
kind: XR
metadata:
name: example
spec:
complexDictionary:
scalar1: true
scalar2: text
scalar3: 123
list:
- abc
- def
Loading

0 comments on commit d5fc53c

Please sign in to comment.