### Include Template Example Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/functions/include/README.md Example of how to include a template named 'template-name' and indent its output. The second example shows capturing the included template's output into a variable. ```go // Print whole condition {{ include "template-name" . | nindent 4 }} {{ $output:= include "template-name" . }} ``` -------------------------------- ### Example Function Context Output Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/context/README.md This is an example of the output generated by `crossplane render` when the function writes to the context. ```yaml --- apiVersion: example.crossplane.io/v1 kind: XR metadata: name: example-xr status: conditions: - lastTransitionTime: "2024-01-01T00:00:00Z" reason: Available status: "True" type: Ready fromEnv: e --- apiVersion: render.crossplane.io/v1beta1 fields: apiextensions.crossplane.io/environment: apiVersion: internal.crossplane.io/v1alpha1 array: - "1" - "2" complex: a: b c: d: e f: "1" kind: Environment nestedEnvUpdate: hello: world update: environment newkey: hello: world other-context-key: complex: a: b c: d: e f: "1" kind: Context ``` -------------------------------- ### Get and Print Resource Condition Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/functions/getResourceCondition/README.md Retrieves the 'Ready' condition for a project resource and outputs its YAML representation. Ensure the resource and condition type are correctly specified. ```go-template // Print whole condition {{ .observed.resources.project | getResourceCondition "Ready" | toYaml }} ``` -------------------------------- ### Compose S3 Bucket with Go Template Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/README.md Example of using the GoTemplate function to create an S3 bucket. It demonstrates accessing composite resource spec properties for template values and setting template options. ```yaml apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: name: example spec: compositeTypeRef: apiVersion: example.crossplane.io/v1beta1 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: options: - missingkey=error 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 ``` -------------------------------- ### Example XR Output with Environment Data Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/environment/README.md This is an example output from `crossplane render` showing an XR with a status field populated from environment data. It demonstrates how environment variables are integrated into the rendered output. ```yaml --- apiversion: example.crossplane.io/v1 kind: XR metadata: name: example-xr status: conditions: - lastTransitionTime: "2024-01-01T00:00:00Z" reason: Available status: "True" type: Ready fromEnv: e --- apiversion: render.crossplane.io/v1beta1 fields: apiextensions.crossplane.io/environment: apiversion: internal.crossplane.io/v1alpha1 array: - "1" - "2" complex: a: b c: d: e f: "1" kind: Environment nestedEnvUpdate: hello: world template: | --- apiversion: meta.gotemplating.fn.crossplane.io/v1alpha1 kind: Context data: # update existing EnvironmentConfig by using the "apiextensions.crossplane.io/environment" key "apiextensions.crossplane.io/environment": kind: Environment apiversion: internal.crossplane.io/v1alpha1 update: environment nestedEnvUpdate: hello: world array: - "1" - "2" # read existing context and move it to another key "other-context-key": complex: {{ index .context "apiextensions.crossplane.io/environment" "complex" | toYaml | nindent 6 }} # Create a new Context key and populate it with data newkey: hello: world --- apiversion: example.crossplane.io/v1 kind: XR status: fromEnv: {{ index .context "apiextensions.crossplane.io/environment" "complex" "c" "d" }} update: environment newkey: hello: world other-context-key: complex: a: b c: d: e f: "1" ``` -------------------------------- ### Local Development and Testing with Crossplane CLI Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Use `crossplane beta render` to test Compositions locally before deployment. This command outputs desired composed resources to standard output. Ensure the Crossplane CLI is installed. ```shell # Install the Crossplane CLI curl -sL https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh | sh ``` ```shell # Render a Composition locally — outputs desired composed resources to stdout crossplane beta render xr.yaml composition.yaml functions.yaml ``` ```shell # Example with the inline example: crossplane beta render \ example/inline/xr.yaml \ example/inline/composition.yaml \ example/inline/functions.yaml ``` ```shell # Run unit tests for the function itself go test ./... ``` ```shell # Build the function container image docker build . --tag=runtime ``` ```shell # Build a Crossplane package (xpkg) for deployment crossplane xpkg build -f package --embed-runtime-image=runtime ``` -------------------------------- ### Render Composite Resources Locally Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/conditions/README.md Use `crossplane render` to test your function locally with example manifests. Ensure you have `xr.yaml`, `composition.yaml`, and `functions.yaml` prepared. ```shell crossplane render \ xr.yaml composition.yaml functions.yaml ``` -------------------------------- ### Build Function Package Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/README.md Builds a Crossplane function package, embedding the runtime image. This command requires the Crossplane CLI to be installed. ```shell crossplane xpkg build -f package --embed-runtime-image=runtime ``` -------------------------------- ### Inline Template Rendering in Composition Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Example of using an inline Go template within a Crossplane Composition to dynamically render multiple IAM User resources based on a count. It also demonstrates updating composite resource status. ```yaml apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: name: example-inline 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: | {{- range $i := until (.observed.composite.resource.spec.count | int) }} --- apiVersion: iam.aws.upbound.io/v1beta1 kind: User metadata: annotations: {{ setResourceNameAnnotation (print "user-" $i) }} labels: dummy: {{ dig "resources" (print "user-" $i) "resource" "metadata" "labels" "dummy" (randomChoice "foo" "bar" "baz") $.observed }} spec: forProvider: {} {{- end }} --- # Update composite resource status (no composition-resource-name annotation = status-only update) apiVersion: example.crossplane.io/v1beta1 kind: XR status: userCount: {{ .observed.composite.resource.spec.count }} ``` -------------------------------- ### Run Function Locally in Debug Mode Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/environment/README.md Execute the function locally using `go run . --insecure --debug` to enable debugging. This command starts the function process for local testing and log inspection. ```shell # Run the function locally $ go run . --insecure --debug ``` -------------------------------- ### Custom Delimiters for Go Templates Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Customize template delimiters from the default `{{ }}` to any string, which is useful when template content contains Go-style braces. This example uses `[[ ]]` as delimiters. ```yaml input: apiVersion: gotemplating.fn.crossplane.io/v1beta1 kind: GoTemplate delims: left: "[[" right: "]]" source: Inline inline: template: | [[- range $i := until (.observed.composite.resource.spec.count | int) ]] --- apiVersion: iam.aws.upbound.io/v1beta1 kind: User metadata: annotations: gotemplating.fn.crossplane.io/composition-resource-name: user-[[ $i ]] labels: dummy: [[ randomChoice "foo" "bar" "baz" ]] spec: forProvider: {} [[- end ]] --- # Raw JSON-like content with braces is safe because delimiters are [[/]] apiVersion: v1 kind: ConfigMap metadata: annotations: {{ setResourceNameAnnotation "raw-config" }} data: jsonValue: '{"key": "value", "nested": {"a": 1}}' ``` -------------------------------- ### Get Composed Resource Connection Details Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Retrieves connection details for a composed resource. Values are base64-encoded. Returns nil if the resource or its details are not yet observed. ```yaml inline: template: | --- apiVersion: iam.aws.m.upbound.io/v1beta1 kind: User metadata: annotations: {{ setResourceNameAnnotation "user" }} spec: forProvider: {} --- apiVersion: iam.aws.m.upbound.io/v1beta1 kind: AccessKey metadata: annotations: {{ setResourceNameAnnotation "accesskey-0" }} spec: forProvider: userSelector: matchControllerRef: true writeConnectionSecretToRef: name: {{ $.observed.composite.resource.metadata.name }}-secret --- apiVersion: v1 kind: Secret metadata: annotations: {{ setResourceNameAnnotation "connection-secret" }} {{ if eq $.observed.resources nil }} data: {} {{ else }} {{ $ak := getComposedConnectionDetails . "accesskey-0" }} data: username: {{ index $ak "username" }} password: {{ index $ak "password" }} {{ end }} ``` -------------------------------- ### Get Extra Resources from Cluster Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Retrieves extra resources fetched from the cluster under a given requirement key. Returns nil if resources are not yet retrieved. Use `default (list)` for safe nil handling. ```yaml inline: template: | --- apiVersion: meta.gotemplating.fn.crossplane.io/v1alpha1 kind: ExtraResources requirements: bucket: apiVersion: s3.aws.upbound.io/v1beta1 kind: Bucket matchName: "{{ .observed.composite.resource.spec.environment }}-bucket" {{ $buckets := getExtraResources . "bucket" }} {{- range $i, $item := default (list) $buckets }} --- apiVersion: kubernetes.crossplane.io/v1alpha1 kind: Object metadata: annotations: gotemplating.fn.crossplane.io/composition-resource-name: bucket-cm-{{ $i }} spec: forProvider: manifest: apiVersion: v1 kind: ConfigMap metadata: name: {{ $item.resource.metadata.name }}-info data: id: {{ $item.resource.status.atProvider.id }} {{- end }} ``` -------------------------------- ### Encode Connection Secret Value with b64enc Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/README.md Example showing how to use the `b64enc` Sprig function to base64 encode a connection secret value when it's not directly from a managed resource's connectionDetails field. ```yaml apiVersion: meta.gotemplating.fn.crossplane.io/v1alpha1 kind: CompositeConnectionDetails data: server-endpoint: {{ (index $.observed.resources "my-server").resource.status.atProvider.endpoint | b64enc }} ``` -------------------------------- ### Retrieve and Extract Composed Resource Data Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/functions/getComposedResource/README.md Use getComposedResource to fetch an observed resource by name from a function request. Then, use the get function to extract specific fields from the resource's status. ```go // Retrieve the observed resource named "flexServer" from the function request {{ $flexServer := getComposedResource . "flexServer" }} // Extract values from the observed resource {{ $flexServerID := get $flexServer.status.atProvider "id" }} ``` -------------------------------- ### Get Extra Resources from Pipeline Context Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Retrieves extra resources fetched and stored in the pipeline context by a previous step. This enables separating resource declaration and consumption into different `function-go-templating` steps. ```yaml # Step 1: declare requirements only - step: fetch-extra-resources functionRef: name: function-go-templating input: apiVersion: gotemplating.fn.crossplane.io/v1beta1 kind: GoTemplate source: Inline inline: template: | --- apiVersion: meta.gotemplating.fn.crossplane.io/v1alpha1 kind: ExtraResources requirements: bucket: apiVersion: s3.aws.upbound.io/v1beta1 kind: Bucket matchName: "{{ .observed.composite.resource.spec.environment }}-bucket" # Step 2: consume from context - step: render-templates functionRef: name: function-go-templating input: apiVersion: gotemplating.fn.crossplane.io/v1beta1 kind: GoTemplate source: Inline inline: template: | {{ $buckets := getExtraResourcesFromContext . "bucket" }} {{- range $i, $item := default (list) $buckets }} --- apiVersion: v1 kind: ConfigMap metadata: annotations: gotemplating.fn.crossplane.io/composition-resource-name: cm-{{ $i }} name: {{ $item.resource.metadata.name }}-info data: id: {{ $item.resource.status.atProvider.id }} {{- end }} ``` -------------------------------- ### Get Composed Resource Condition Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Retrieves a named condition from a composed resource's status. Returns an `xpv1.Condition` object or an empty condition with `Unknown` status if not found. ```yaml inline: template: | {{ $server := getComposedResource . "flexServer" }} {{ $readyCondition := getResourceCondition "Ready" $server }} --- apiVersion: example.crossplane.io/v1beta1 kind: XR status: serverReady: {{ $readyCondition.Status }} serverMessage: {{ $readyCondition.Message }} --- # Conditionally proceed only when the server is Ready=True {{ if eq (toString $readyCondition.Status) "True" }} apiVersion: dbforpostgresql.azure.upbound.io/v1beta1 kind: FlexibleServerConfiguration metadata: annotations: {{ setResourceNameAnnotation "serverConfig" }} spec: forProvider: serverId: {{ get $server.status "id" }} {{ end }} ``` -------------------------------- ### Include Function Syntax Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/functions/include/README.md This shows the basic syntax for using the include function. It requires the name of the template to include and the context to render it with. ```go {{ include $name $context }} ``` -------------------------------- ### Annotate Composed and Composite Resources for Readiness Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/README.md Apply the `gotemplating.fn.crossplane.io/ready` annotation to mark composed or composite resources as ready. Set the value to "True" for ready resources. ```yaml # Composed resource apiVersion: s3.aws.upbound.io/v1beta1 kind: Bucket metadata: annotations: gotemplating.fn.crossplane.io/composition-resource-name: bucket gotemplating.fn.crossplane.io/ready: "True" spec: {} # Composite resource apiVersion: example.crossplane.io/v1beta1 kind: XR metadata: annotations: gotemplating.fn.crossplane.io/ready: "True" status: {} ``` -------------------------------- ### Render Crossplane Compositions Locally Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/README.md Use the `crossplane beta render` command to render XR, Composition, and Function configurations locally. This is useful for testing and debugging. ```shell $ crossplane beta render xr.yaml composition.yaml functions.yaml ``` -------------------------------- ### Basic getResourceCondition Usage Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/functions/getResourceCondition/README.md Demonstrates the two primary ways to call the getResourceCondition function: directly with arguments or using the pipe operator. ```go-template {{ getResourceCondition $conditionType $resource }} ``` ```go-template {{ $resource | getResourceCondition $conditionType }} ``` -------------------------------- ### Configure Go Template Options Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Set template rendering options like `missingkey=error` to fail on missing keys. This is recommended for production to catch typos early. Options can also be set globally via CLI flags or environment variables. ```yaml input: apiVersion: gotemplating.fn.crossplane.io/v1beta1 kind: GoTemplate source: Inline options: - missingkey=error # fail on missing keys (instead of rendering "") inline: template: | apiVersion: s3.aws.upbound.io/v1beta1 kind: Bucket metadata: annotations: {{ setResourceNameAnnotation "bucket" }} spec: forProvider: region: {{ .observed.composite.resource.spec.region }} # If .spec.region is missing, the render fails immediately with a descriptive error ``` -------------------------------- ### Create ConfigMap with Templates Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/filesystem/README.md Use this command to create a ConfigMap named 'templates' in the 'crossplane-system' namespace, loading templates from the 'templates.tmpl' file. This ConfigMap will be mounted into the function pod. ```shell kubectl create configmap templates --from-file=templates.tmpl -n crossplane-system ``` -------------------------------- ### Run Tests Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/README.md Executes all tests for the function. Ensure tests are located in `fn_test.go` or similar test files. ```shell go test ./... ``` -------------------------------- ### Build Function Runtime Image Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/README.md Builds the function's runtime image using Docker. Ensure you are in the project root directory. ```shell docker build . --tag=runtime ``` -------------------------------- ### Load Templates from File System Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Configure the Go Template function to load templates from a specified directory within the function container. Hidden files and directories are ignored. ```yaml apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: name: xusers-filesystem spec: compositeTypeRef: apiVersion: aws.platformref.upbound.io/v1alpha1 kind: XUser mode: Pipeline pipeline: - step: render-templates functionRef: name: function-go-templating input: apiVersion: gotemplating.fn.crossplane.io/v1beta1 kind: GoTemplate source: FileSystem fileSystem: dirPath: /templates # directory inside the function's container image - step: ready functionRef: name: function-auto-ready ``` -------------------------------- ### Load Templates from Environment Context Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Dynamically load templates from an `EnvironmentConfig` by specifying the source as `Environment` and providing the key where the template is stored. This allows for runtime configuration. ```yaml apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: name: example-environment-source spec: compositeTypeRef: apiVersion: example.crossplane.io/v1 kind: XR mode: Pipeline pipeline: - step: environmentConfigs functionRef: name: crossplane-contrib-function-environment-configs input: apiVersion: environmentconfigs.fn.crossplane.io/v1beta1 kind: Input spec: environmentConfigs: - type: Reference ref: name: sampletemplate # EnvironmentConfig containing a "template" key - step: go-templating-from-env functionRef: name: crossplane-contrib-function-go-templating input: apiVersion: gotemplating.fn.crossplane.io/v1beta1 kind: GoTemplate source: Environment environment: key: template # key inside apiextensions.crossplane.io/environment ``` -------------------------------- ### GoTemplate Data Model for Templates Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Illustrates the data model available within Go templates, including observed and desired states, pipeline context, and extra resources. Access data using dot-notation or the `index` function. ```yaml # In a Composition pipeline step: inline: template: | # Access observed composite resource fields region: {{ .observed.composite.resource.spec.region }} name: {{ .observed.composite.resource.metadata.name }} # Access desired composite resource (set by earlier pipeline steps) widgets: {{ .desired.composite.resource.status.widgets }} # Access an observed composed resource by name (use index for names with hyphens/dots) serverId: {{ (index .observed.resources "my-server").resource.status.atProvider.id }} # Access the pipeline context (e.g. environment loaded by function-environment-configs) envValue: {{ index .context "apiextensions.crossplane.io/environment" "myKey" }} # Access extra resources fetched from the cluster bucketId: {{ (index (index .extraResources "my-bucket").items 0).resource.status.atProvider.id }} ``` -------------------------------- ### Return Composite Connection Details (Legacy) Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/README.md Illustrates how to return composite resource connection details for legacy v1 XRs using the CompositeConnectionDetails resource. The connection secret value must be base64 encoded. ```yaml apiVersion: meta.gotemplating.fn.crossplane.io/v1alpha1 kind: CompositeConnectionDetails data: connection-secret-key: connection-secret-value ``` -------------------------------- ### Control Readiness Signal Annotation Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt The `gotemplating.fn.crossplane.io/ready` annotation controls the readiness signal for composed or composite resources. Valid values are `True`, `False`, and `Unspecified`. This annotation is removed before the object is stored. ```yaml apiVersion: s3.aws.upbound.io/v1beta1 kind: Bucket metadata: annotations: gotemplating.fn.crossplane.io/composition-resource-name: my-bucket gotemplating.fn.crossplane.io/ready: "True" spec: forProvider: region: us-east-1 --- # Also works on the composite resource itself apiVersion: example.crossplane.io/v1beta1 kind: XR metadata: annotations: gotemplating.fn.crossplane.io/ready: "False" status: {} ``` -------------------------------- ### Multiple Templates via `templates` Slice Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Use the `templates` slice to define multiple Go templates inline. Each template in the slice will be rendered. ```yaml input: apiVersion: gotemplating.fn.crossplane.io/v1beta1 kind: GoTemplate source: Inline inline: templates: - | 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 }} - | apiVersion: example.crossplane.io/v1beta1 kind: XR status: bucketReady: true ``` -------------------------------- ### Run Code Generation Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/README.md Executes code generation scripts. This is typically the first step in the development process. ```shell go generate ./... ``` -------------------------------- ### Testing getCredentialData Locally with crossplane render Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/functions/getCredentialData/README.md Use the `crossplane render` command to test the getCredentialData function locally. This command requires XR, composition, and function definition YAML files, along with a function credentials file and context. ```shell crossplane render xr.yaml composition.yaml functions.yaml \ --function-credentials=credentials.yaml \ --include-context ``` ```yaml --- apiVersion: example.crossplane.io/v1beta1 kind: XR metadata: name: example status: conditions: - lastTransitionTime: "2024-01-01T00:00:00Z" reason: Available status: "True" type: Ready --- apiVersion: render.crossplane.io/v1beta1 fields: password: bar username: foo kind: Context ``` -------------------------------- ### Configure function-go-templating for Development Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/conditions/README.md Set the `render.crossplane.io/runtime: Development` annotation in your Function manifest to enable local development mode. This directs `crossplane render` to communicate with the locally running function. ```yaml apiVersion: pkg.crossplane.io/v1 kind: Function metadata: name: crossplane-contrib-function-go-templating annotations: render.crossplane.io/runtime: Development spec: package: xpkg.crossplane.io/crossplane-contrib/function-go-templating:v0.9.0 ``` -------------------------------- ### Create Composed Resources with Resource Name Annotation Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/README.md When the `gotemplating.fn.crossplane.io/composition-resource-name` annotation is set, this composition will create composed resources. Be cautious of infinite recursion and ensure a termination strategy. ```yaml apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: name: example-allow-recursion 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: example.crossplane.io/v1beta1 kind: XR metadata: annotations: {{ setResourceNameAnnotation "recursive-xr" }} spec: compositionRef: name: example-other # make sure to avoid infinite recursion ``` -------------------------------- ### Configure Function for Local Development Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/context/README.md Annotate the Function resource with `render.crossplane.io/runtime: Development` to direct `crossplane render` to communicate with the local process. ```yaml apiVersion: pkg.crossplane.io/v1 kind: Function metadata: name: crossplane-contrib-function-go-templating annotations: render.crossplane.io/runtime: Development spec: package: xpkg.crossplane.io/crossplane-contrib/function-go-templating:v0.6.0 ``` -------------------------------- ### Retrieve and Extract Composed Connection Details Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/functions/getComposedConnectionDetails/README.md Use this function to fetch connection details for specific observed resources by name. Access individual details like username or password using the index function. Connection details are only available in observed state. ```golang // Retrieve the connection details for observed resources named "accesskey-0" and "accesskey-1" {{ $accesskey0 := getComposedConnectionDetails . "accesskey-0" }} {{ $accesskey1 := getComposedConnectionDetails . "accesskey-1" }} // Extract values from the connection details {{ index $accesskey0 "username" }} {{ index $accesskey1 "password" }} ``` -------------------------------- ### Render Function with Environment Configs Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/environment/README.md Use `crossplane render` to test the function locally with specified environment configurations and manifests. This command includes context and processes multiple YAML files. ```shell crossplane render \ --extra-resources environmentConfigs.yaml \ --include-context \ xr.yaml composition.yaml functions.yaml ``` -------------------------------- ### Configure Function for Local Development Runtime Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/environment/README.md Apply this YAML configuration to a `Function` resource to set the `render.crossplane.io/runtime: Development` annotation. This directs `crossplane render` to communicate with the locally running function process. ```yaml apiversion: pkg.crossplane.io/v1 kind: Function metadata: name: crossplane-contrib-function-go-templating annotations: render.crossplane.io/runtime: Development spec: package: xpkg.crossplane.io/crossplane-contrib/function-go-templating:v0.6.0 ``` -------------------------------- ### Write Context Data with Meta Resource Context Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Use the Context meta resource to write arbitrary data into the Crossplane composition pipeline context. Subsequent pipeline steps can read these values. Existing keys are deep-merged with override semantics. ```yaml inline: template: | --- apiVersion: meta.gotemplating.fn.crossplane.io/v1alpha1 kind: Context data: # Create a new context key region: {{ .observed.composite.resource.spec.region }} # Update an existing EnvironmentConfig key (deep merge with override) "apiextensions.crossplane.io/environment": kind: Environment apiVersion: internal.crossplane.io/v1alpha1 dbEndpoint: {{ .observed.composite.resource.spec.dbHost }} nestedUpdate: hello: world # Copy and transform existing context data to a new key "derived-config": complex: {{ index .context "apiextensions.crossplane.io/environment" "complex" | toYaml | nindent 6 }} --- # Consume the context in the same step to update XR status apiVersion: example.crossplane.io/v1beta1 kind: XR status: fromEnv: {{ index .context "apiextensions.crossplane.io/environment" "complex" "c" "d" }} ``` -------------------------------- ### Generate CompositeConnectionDetails Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Use CompositeConnectionDetails to produce connection details for legacy v1 composite resources. Values must be base64-encoded. Not supported for v2 XRs. ```yaml inline: template: | --- apiVersion: meta.gotemplating.fn.crossplane.io/v1alpha1 kind: CompositeConnectionDetails data: # Already base64 if sourced from a managed resource's connectionDetails: endpoint: {{ (index $.observed.resources "my-server").connectionDetails.endpoint }} # Manually encode a static or computed value: url: {{ "http://internal.example.com" | b64enc }} # Encode a status field from an observed resource: server-ip: {{ (index $.observed.resources "my-server").resource.status.atProvider.endpoint | b64enc }} ``` -------------------------------- ### Write Data to Composition Context Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/README.md Use the `Context` resource to write data into the Composition pipeline context. This data can be accessed by subsequent pipeline steps. Existing keys can be updated. ```yaml --- apiVersion: meta.gotemplating.fn.crossplane.io/v1alpha1 kind: Context data: region: {{ $spec.region }} id: field array: - "1" - "2" ``` -------------------------------- ### Serialize Go Value to YAML with Indentation Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt The `toYaml` function serializes Go values into YAML strings. It's often paired with `nindent` for correct indentation in inline YAML blocks. Use this to embed complex data structures as YAML. ```yaml inline: template: | --- apiVersion: {{ .observed.composite.resource.apiVersion }} kind: {{ .observed.composite.resource.kind }} status: # Embed the entire complexDictionary spec field as YAML, indented 7 spaces config: {{ .observed.composite.resource.spec.complexDictionary | toYaml | nindent 7 }} # Embed a map of labels built dynamically labels: | {{ dict "app" "my-app" "tier" "backend" | toYaml | nindent 4 }} ``` -------------------------------- ### Define ExtraResources for Templating Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/README.md Configure `ExtraResources` to fetch additional Kubernetes resources from the cluster and make them available within your Go templates. Resources can be requested by name, label, or dynamically generated labels. ```yaml apiVersion: meta.gotemplating.fn.crossplane.io/v1alpha1 kind: ExtraResources requirements: some-foo-by-name: # Resources can be requested either by name apiVersion: example.com/v1beta1 kind: Foo matchName: "some-extra-foo" some-foo-by-labels: # Or by label. apiVersion: example.com/v1beta1 kind: Foo matchLabels: app: my-app some-bar-by-a-computed-label: # But you can also generate them dynamically using the template, for example: apiVersion: example.com/v1beta1 kind: Bar matchLabels: foo: {{ .observed.composite.resource.name }} ``` -------------------------------- ### Reuse Template Logic with include and nindent Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt The `include` function renders a named template, supporting reuse and indentation control with `nindent`/`indent`. It's preferred over the built-in `template` action when indentation is critical. Supports up to 1000 recursive calls. ```yaml inline: template: | {{- define "common-labels" -}} app: {{ .app }} tier: {{ .tier }} env: {{ .env }} {{- end }} --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx annotations: {{ setResourceNameAnnotation "nginx-deployment" }} labels: {{- include "common-labels" (dict "app" "nginx" "tier" "frontend" "env" .observed.composite.resource.spec.env) | nindent 4 }} spec: selector: matchLabels: {{- include "common-labels" (dict "app" "nginx" "tier" "frontend" "env" .observed.composite.resource.spec.env) | nindent 6 }} template: metadata: labels: app: nginx ``` -------------------------------- ### Recursive Composition with Composed XRs Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt When a resource matching the composite's GVK has the `composition-resource-name` annotation, it's created as a new composed resource (nested XR). Always terminate recursion by pointing to a different `compositionRef`. ```yaml # composition-wrapper.yaml — creates a nested XR inline: template: | apiVersion: example.crossplane.io/v1beta1 kind: XR metadata: annotations: {{ setResourceNameAnnotation "nested-xr" }} spec: compositionRef: name: example-recursive-real # a different composition to avoid infinite loop region: {{ .observed.composite.resource.spec.region }} ``` -------------------------------- ### Check Resource Condition Status Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/functions/getResourceCondition/README.md Conditionally executes a block of code based on the 'Status' field of the 'Ready' condition for a project resource. This is useful for implementing logic that depends on resource readiness. ```go-template // Check status {{ if eq (.observed.resources.project | getResourceCondition "Ready").Status "True" }} // do something {{ end }} ``` -------------------------------- ### Access ExtraResources in Go Templates Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/README.md Access retrieved extra resources within your Go templates using the `extraResources` key. Iterate over items for each requested resource type. ```yaml {{- $someExtraResources := index .extraResources "some-extra-resources-key" }} {{- range $i, $extraResource := $someExtraResources.items }} # # Do something for each retrieved extraResource # {{- end }} ``` -------------------------------- ### Retrieve Composite Resource (XR) - Go Templating Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/example/functions/getCompositeResource/README.md Use this snippet to retrieve the observed composite resource (XR) from the function request. It then patches values from the XR into the composed resource's spec. ```yaml apiVersion: example.crossplane.io/v1beta1 kind: XR metadata: name: example spec: name: "example" location: "eastus" ``` ```go // Retrieve the observed composite resource (XR) from the function request {{ $xr := getCompositeResource . }} apiVersion: example.crossplane.io/v1beta1 kind: ExampleResource // 'Patch' values from the composite resource into the composed resource spec: forProvider: name: {{ get $xr.spec "name" }} location: {{ get $xr.spec "location" }} ``` -------------------------------- ### GoTemplate Input API Definition Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Defines the GoTemplate input object for the function, specifying template source, delimiters, options, and TTL. Use this to configure how templates are loaded and rendered. ```yaml apiVersion: gotemplating.fn.crossplane.io/v1beta1 kind: GoTemplate # Custom template delimiters (optional, default: {{ and }}) delims: left: "||" right: "]]" # Source: Inline | FileSystem | Environment source: Inline # Template engine options (default: missingkey=default) options: - missingkey=error # Response cache TTL (default: 1m0s) ttl: "30s" inline: template: | apiVersion: s3.aws.upbound.io/v1beta1 kind: Bucket metadata: annotations: gotemplating.fn.crossplane.io/composition-resource-name: my-bucket spec: forProvider: region: [[ .observed.composite.resource.spec.region ]] ``` -------------------------------- ### Add Composition Resource Name Annotation Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Use `setResourceNameAnnotation` to add the `gotemplating.fn.crossplane.io/composition-resource-name` annotation. This is useful within `metadata.annotations` blocks to manage quoting and indentation. ```yaml inline: template: | apiVersion: s3.aws.upbound.io/v1beta1 kind: Bucket metadata: annotations: {{ setResourceNameAnnotation "primary-bucket" }} # Renders to: gotemplating.fn.crossplane.io/composition-resource-name: primary-bucket labels: env: {{ .observed.composite.resource.spec.env }} spec: forProvider: region: us-west-2 ``` -------------------------------- ### Retrieve Observed Composite Resource Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt The `getCompositeResource` function retrieves the observed composite resource as a map. It's functionally equivalent to `.observed.composite.resource` but provides a clearer intent in templates. Use it to access XR spec fields. ```yaml inline: template: | --- {{ $xr := getCompositeResource . }} apiVersion: dbforpostgresql.azure.upbound.io/v1beta1 kind: FlexibleServer metadata: annotations: {{ setResourceNameAnnotation "flexserver" }} gotemplating.fn.crossplane.io/ready: "False" spec: forProvider: adminLogin: {{ get $xr.spec "adminLogin" }} location: {{ get $xr.spec "location" }} version: {{ get $xr.spec "version" | default "14" }} ``` -------------------------------- ### Retrieve Observed Composed Resource Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Use `getComposedResource` to fetch an observed composed resource by its name. It returns the full resource object or `nil` if not yet observed. This allows chaining resources by using data from one resource's status in another. ```yaml inline: template: | --- apiVersion: dbforpostgresql.azure.upbound.io/v1beta1 kind: FlexibleServer metadata: annotations: {{ setResourceNameAnnotation "flexServer" }} gotemplating.fn.crossplane.io/ready: "False" spec: forProvider: storageMb: 32768 providerConfigRef: name: my-provider-cfg --- {{ $flexServer := getComposedResource . "flexServer" }} apiVersion: dbforpostgresql.azure.upbound.io/v1beta1 kind: FlexibleServerConfiguration metadata: annotations: {{ setResourceNameAnnotation "flexServerConfig" }} spec: forProvider: serverId: {{ if $flexServer }}{{ get $flexServer.status "id" }}{{ end }} providerConfigRef: name: my-provider-cfg ``` -------------------------------- ### Retrieve Credential Data with getCredentialData Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Use `getCredentialData` to fetch credentials from a named source within the function pipeline. Convert byte slices to strings using `toString` for template output. ```yaml apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: name: example-credentials spec: compositeTypeRef: apiVersion: example.crossplane.io/v1beta1 kind: XR mode: Pipeline pipeline: - step: render-templates functionRef: name: function-go-templating credentials: - name: foo-creds # credential name referenced in the template secretRef: name: foo-creds # Kubernetes Secret in the same namespace namespace: default source: Secret input: apiVersion: gotemplating.fn.crossplane.io/v1beta1 kind: GoTemplate source: Inline inline: template: | --- apiVersion: meta.gotemplating.fn.crossplane.io/v1alpha1 kind: Context data: username: {{ (getCredentialData . "foo-creds").username | toString }} password: {{ (getCredentialData . "foo-creds").password | toString }} ``` -------------------------------- ### Deserialize YAML String to Go Map/Slice Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Use `fromYaml` to parse YAML strings into Go maps or slices. This is helpful for processing YAML data stored in XR spec fields. It can be chained with other functions like `range` for iterating over lists. ```yaml inline: template: | --- apiVersion: {{ .observed.composite.resource.apiVersion }} kind: {{ .observed.composite.resource.kind }} status: # .spec.yamlBlob is a string like "key1: val1\nkey2: val2" extracted: {{ (.observed.composite.resource.spec.yamlBlob | fromYaml).key2 }} # Chain with range to iterate over a YAML list stored in a field: {{- $items := .observed.composite.resource.spec.listYaml | fromYaml }} {{- range $items }} - {{ . }} {{- end }} ``` -------------------------------- ### Utilize Sprig Functions in Go Templates Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Leverage Sprig template functions for string manipulation, encoding/decoding, date formatting, safe navigation, and list/dict operations. Note that `env` and `expandenv` are removed for security. ```yaml inline: template: | apiVersion: example.crossplane.io/v1beta1 kind: XR status: # String manipulation upper: {{ .observed.composite.resource.spec.name | upper }} trimmed: {{ .observed.composite.resource.spec.name | trim }} # Base64 (from Sprig) encoded: {{ "hello world" | b64enc }} decoded: {{ .observed.composite.resource.spec.encodedVal | b64dec }} # Date formatting timestamp: {{ now | date "2006-01-02" }} # Safe navigation — dig returns a default if any key is missing label: {{ dig "metadata" "labels" "app" "unknown" $.observed.composite.resource }} # List and dict operations count: {{ len .observed.composite.resource.spec.regions }} first: {{ first .observed.composite.resource.spec.regions }} # Ternary mode: {{ ternary "prod" "dev" (eq .observed.composite.resource.spec.env "production") }} ``` -------------------------------- ### Declare ExtraResources Requirements Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt Use ExtraResources to declare requirements for additional cluster resources. Supports matching by name or labels, and labels can reference template data. Retrieved resources are stored in the context. ```yaml inline: template: | --- apiVersion: meta.gotemplating.fn.crossplane.io/v1alpha1 kind: ExtraResources requirements: # Match by exact name (dynamic — built from XR spec) target-bucket: apiVersion: s3.aws.upbound.io/v1beta1 kind: Bucket matchName: "{{ .observed.composite.resource.spec.environment }}-bucket" # Match by labels app-buckets: apiVersion: s3.aws.upbound.io/v1beta1 kind: Bucket matchLabels: app: my-app # Namespace-scoped resource my-config: apiVersion: v1 kind: ConfigMap matchName: shared-config namespace: platform {{- with .extraResources }} {{- $bucket := index . "target-bucket" }} {{- range $i, $item := $bucket.items }} --- apiVersion: kubernetes.crossplane.io/v1alpha1 kind: Object metadata: annotations: gotemplating.fn.crossplane.io/composition-resource-name: bucket-cm-{{ $i }} spec: forProvider: manifest: apiVersion: v1 kind: ConfigMap metadata: name: {{ $item.resource.metadata.name }}-info data: bucket-id: {{ $item.resource.status.atProvider.id }} {{- end }} {{- end }} ``` -------------------------------- ### Update Existing Context Data Source: https://github.com/crossplane-contrib/function-go-templating/blob/main/README.md Match an existing context key, such as `apiextensions.crossplane.io/environment`, to update nested fields within the Composition context. This allows for merging and updating environment configurations. ```yaml --- apiVersion: meta.gotemplating.fn.crossplane.io/v1alpha1 kind: Context data: "apiextensions.crossplane.io/environment": kind: Environment apiVersion: internal.crossplane.io/v1alpha1 update: environment nestedEnvUpdate: hello: world otherContextData: test: field ``` -------------------------------- ### Randomly Select from a List Source: https://context7.com/crossplane-contrib/function-go-templating/llms.txt The `randomChoice` function selects a single string from a list of options. It's useful for distributing resources across different regions or availability zones, or for generating test data. ```yaml inline: template: | apiVersion: s3.aws.upbound.io/v1beta1 kind: Bucket metadata: annotations: {{ setResourceNameAnnotation "my-bucket" }} spec: forProvider: # Randomly assign one of three regions on first render; persists via observed state region: {{ dig "resources" "my-bucket" "resource" "spec" "forProvider" "region" (randomChoice "us-east-1" "us-west-2" "eu-west-1") $.observed }} ```