From a893d6a284b09e184f27e1eb05b8c0d74ae616cc Mon Sep 17 00:00:00 2001 From: Philippe Scorsolini Date: Wed, 9 Oct 2024 10:06:38 +0100 Subject: [PATCH] docs: migration from native composition environment Signed-off-by: Philippe Scorsolini --- README.md | 258 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 179 insertions(+), 79 deletions(-) diff --git a/README.md b/README.md index 35d77e3..fec8095 100644 --- a/README.md +++ b/README.md @@ -6,108 +6,206 @@ > This function relies on functionalities only available in Crossplane 1.15 and > later. It will not work with earlier versions. +> [!IMPORTANT] +> This function is meant to replace native Composition Environment +> (`--enable-environment-configs`), see +> [below](#migration-from-native-composition-environment) for more details. + This [composition function][docs-functions] allows you to request `EnvironmentConfigs`, merge them in the requested order and return inject the computed `environment` into the `Context` at a well-known key, `apiextensions.crossplane.io/environment`, so that other functions such as [function-patch-and-transform] can access it. -The following paths from native `Resource` Compositions can be just moved to the -input of this function: +## Examples + +See [example](./example/) folder. + +## Migration from native Composition Environment + +Crossplane 1.8 [dropped] native Composition Environment, meaning +`spec.environment` and `*Environment` patches were removed, while +`EnvironmentConfig` as a resource was promoted to `Beta`. + +`crossplane beta convert pipeline-composition` has been updated to +automatically migrate Compositions using those fields to this function. + +A manual migration can be performed moving the following fields from a +`Composition` spec to this function's `Input`: - `spec.environment.environmentConfigs` -> `spec.environmentConfigs` - `spec.environment.defaultData` -> `spec.defaultData` - `spec.environment.policy.resolution` -> `spec.policy.resolution` -`spec.environment.policy.resolve` is not supported yet, which results -effectively in the same behavior as `Always`. +`spec.environment.policy.resolve` is not configurable at the moment, defaulting +to policy `Always`. + +`spec.environment.patches` and resources' `*Environment` patches will have to +be moved to [function-patch-and-transform]'s input. -Here's an example using [function-go-templating](https://github.com/crossplane-contrib/function-go-templating): +The diagram below shows what part of the usual Composition is replaced by this +function and how it fits with other functions: + +![diagram.png](diagram.png) + +## Migration Example + +Given an example `Resource` Composition: ```yaml apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: - name: function-environment-configs + name: foo spec: compositeTypeRef: apiVersion: example.crossplane.io/v1 kind: XR - mode: Pipeline - pipeline: - - step: environmentConfigs - functionRef: - name: function-environment-configs - input: - apiVersion: environmentconfigs.fn.crossplane.io/v1beta1 - kind: Input - spec: - environmentConfigs: - - type: Reference - ref: - name: example-config - - step: go-templating - functionRef: - name: function-go-templating - input: - apiVersion: gotemplating.fn.crossplane.io/v1beta1 - kind: GoTemplate - source: Inline - inline: - template: | - --- - apiVersion: example.crossplane.io/v1 - kind: XR - status: - fromEnv: {{ index .context "apiextensions.crossplane.io/environment" "complex" "c" "d" }} + mode: Resources + environment: + environmentConfigs: + - type: Reference + ref: + name: example-config + patches: + # So you can then use it in all your patches: + # - Env -> XR + - type: ToCompositeFieldPath + fromFieldPath: "someFieldInTheEnvironment" + toFieldPath: "status.someFieldFromTheEnvironment" + # - XR -> Env + - type: FromCompositeFieldPath + fromFieldPath: "spec.someFieldInTheXR" + toFieldPath: "someFieldFromTheXR" + resources: + - name: bucket + base: + apiVersion: s3.aws.upbound.io/v1beta1 + kind: Bucket + spec: + forProvider: + region: us-east-2 + patches: + # - Env -> Resource + - type: FromEnvironmentFieldPath + fromFieldPath: "someFieldInTheEnvironment" + toFieldPath: "spec.forProvider.someFieldFromTheEnvironment" + # - Resource -> Env + - type: ToEnvironmentFieldPath + fromFieldPath: "status.someOtherFieldInTheResource" + toFieldPath: "someOtherFieldInTheEnvironment" + ``` -Here is another example using [function-patch-and-transform](https://github.com/crossplane-contrib/function-patch-and-transform): +The above can be converted to use this function and +[function-patch-and-transform] as follows: ```yaml -... same as above ... - - step: patch-and-transform - # function-patch-and-transform knows it has to look for the environment in the - # context at "apiextensions.crossplane.io/environment" - functionRef: - name: function-patch-and-transform - input: - apiVersion: pt.fn.crossplane.io/v1beta1 - kind: Resources - environment: - patches: - # So you can then use it in all your patches: - # - Env -> XR - - type: ToCompositeFieldPath - fromFieldPath: "someFieldInTheEnvironment" - toFieldPath: "status.someFieldFromTheEnvironment" - # - XR -> Env - - type: FromCompositeFieldPath - fromFieldPath: "spec.someFieldInTheXR" - toFieldPath: "someFieldFromTheXR" - resources: - - name: bucket - base: - apiVersion: s3.aws.upbound.io/v1beta1 - kind: Bucket - spec: - forProvider: - region: us-east-2 - patches: - # - Env -> Resource - - type: FromEnvironmentFieldPath - fromFieldPath: "someFieldInTheEnvironment" - toFieldPath: "spec.forProvider.someFieldFromTheEnvironment" - # - Resource -> Env - - type: ToEnvironmentFieldPath - fromFieldPath: "status.someOtherFieldInTheResource" - toFieldPath: "someOtherFieldInTheEnvironment" - # the environment will be passed to the next function in the pipeline - # as part of the context +apiVersion: apiextensions.crossplane.io/v1 +kind: Composition +metadata: + name: foo +spec: + compositeTypeRef: + apiVersion: example.crossplane.io/v1 + kind: XR + mode: Pipeline + pipeline: + - step: environmentConfigs + functionRef: + name: function-environment-configs + input: + apiVersion: environmentconfigs.fn.crossplane.io/v1beta1 + kind: Input + spec: + environmentConfigs: + - type: Reference + ref: + name: example-config + # the environment is be passed to the next function in the pipeline + # as part of the context + - step: patch-and-transform + # function-patch-and-transform knows it has to look for the environment in the + # context at "apiextensions.crossplane.io/environment" + functionRef: + name: function-patch-and-transform + input: + apiVersion: pt.fn.crossplane.io/v1beta1 + kind: Resources + environment: + patches: + # So you can then use it in all your patches: + # - Env -> XR + - type: ToCompositeFieldPath + fromFieldPath: "someFieldInTheEnvironment" + toFieldPath: "status.someFieldFromTheEnvironment" + # - XR -> Env + - type: FromCompositeFieldPath + fromFieldPath: "spec.someFieldInTheXR" + toFieldPath: "someFieldFromTheXR" + resources: + - name: bucket + base: + apiVersion: s3.aws.upbound.io/v1beta1 + kind: Bucket + spec: + forProvider: + region: us-east-2 + patches: + # - Env -> Resource + - type: FromEnvironmentFieldPath + fromFieldPath: "someFieldInTheEnvironment" + toFieldPath: "spec.forProvider.someFieldFromTheEnvironment" + # - Resource -> Env + - type: ToEnvironmentFieldPath + fromFieldPath: "status.someOtherFieldInTheResource" + toFieldPath: "someOtherFieldInTheEnvironment" ``` -This diagram shows what part of the usual Composition is replaced by this -function and how it fits with other functions: -![diagram.png](diagram.png) +## Consuming environment from Context-aware functions + +This function just merges selected `EnvironmentConfigs` into the `Context` at a well-known key, `apiextensions.crossplane.io/environment`, therefore any `Context`-aware function can access it. + +For example, using [function-go-templating]: + +```yaml +apiVersion: apiextensions.crossplane.io/v1 +kind: Composition +metadata: + name: foo +spec: + compositeTypeRef: + apiVersion: example.crossplane.io/v1 + kind: XR + mode: Pipeline + pipeline: + - step: environmentConfigs + functionRef: + name: function-environment-configs + input: + apiVersion: environmentconfigs.fn.crossplane.io/v1beta1 + kind: Input + spec: + environmentConfigs: + - type: Reference + ref: + name: example-config + # the environment is be passed to the next function in the pipeline + # as part of the context + - step: go-templating + functionRef: + name: function-go-templating + input: + apiVersion: gotemplating.fn.crossplane.io/v1beta1 + kind: GoTemplate + source: Inline + inline: + template: | + --- + apiVersion: example.crossplane.io/v1 + kind: XR + status: + fromEnv: {{ index .context "apiextensions.crossplane.io/environment" "complex" "c" "d" }} +``` ## Using this function @@ -151,9 +249,11 @@ $ docker build . --tag=runtime $ crossplane xpkg build -f package --embed-runtime-image=runtime ``` -[docs-functions]: https://docs.crossplane.io/v1.14/concepts/composition-functions/ [bsr]: https://buf.build/crossplane/crossplane/docs/main:apiextensions.fn.proto.v1beta1#apiextensions.fn.proto.v1beta1.RunFunctionRequest -[go]: https://go.dev -[docker]: https://www.docker.com [cli]: https://docs.crossplane.io/latest/cli +[docker]: https://www.docker.com +[docs-functions]: https://docs.crossplane.io/v1.14/concepts/composition-functions/ +[dropped]: https://github.com/crossplane/crossplane/pull/5938 +[function-go-templating]: https://github.com/crossplane-contrib/function-go-templating [function-patch-and-transform]: https://github.com/crossplane-contrib/function-patch-and-transform +[go]: https://go.dev