--- title: Environment Configurations weight: 90 state: alpha alphaVersion: "1.11" description: "Environment Configurations or EnvironmentConfigs are an in-memory datastore used in patching Compositions" --- A Crossplane EnvironmentConfig is a cluster scoped [ConfigMap](https://kubernetes.io/docs/concepts/configuration/configmap/)-like resource used by Compositions. Compositions can use the environment to store information from individual resources or to apply [patches]({{}}). Crossplane supports multiple EnvironmentConfigs, each acting as a unique data store. When Crossplane creates a composite resource, Crossplane merges all the EnvironmentConfigs referenced in the associated Composition and creates a unique in-memory environment for that composite resource. The composite resource can read and write data to their unique in-memory environment. {{}} The in-memory environment is unique to each composite resource. A composite resource can't read data in another composite resource's environment. {{< /hint >}} ## Enable EnvironmentConfigs EnvironmentConfigs are an alpha feature. Alpha features aren't enabled by default. Enable EnvironmentConfig support by [changing the Crossplane pod setting]({{}}) and enabling {{}}--enable-environment-configs{{}} argument. ```yaml {label="deployment",copy-lines="12"} $ kubectl edit deployment crossplane --namespace crossplane-system apiVersion: apps/v1 kind: Deployment spec: # Removed for brevity template: spec: containers: - args: - core - start - --enable-environment-configs ``` {{}} The [Crossplane install guide]({{}}) describes enabling feature flags like {{}}--enable-environment-configs{{}} with Helm. {{< /hint >}} ## Create an EnvironmentConfig An {{}}EnvironmentConfig{{}} has a single object field, {{}}data{{}}. An EnvironmentConfig supports any data inside the {{}}data{{}} field. Here an example {{}}EnvironmentConfig{{}}. ```yaml {label="env1"} apiVersion: apiextensions.crossplane.io/v1alpha1 kind: EnvironmentConfig metadata: name: example-environment data: locations: us: us-east-2 eu: eu-north-1 key1: value1 key2: value2 key3: - item1 - item2 ``` ## Select an EnvironmentConfig Select the EnvironmentConfigs to use inside a Composition's {{}}environment{{}} field. The {{}}environmentConfigs{{}} field is a list of environments this Composition can use. Select an environment by {{}}Reference{{}} or by {{}}Selector{{}}. A {{}}Reference{{}} selects an environment by {{}}name{{}}. The {{}}Selector{{}} selects an environment based on the {{}}Labels{{}} applied to the environment. ```yaml {label="comp",copy-lines="none"} apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: name: example-composition spec: environment: environmentConfigs: - type: Reference ref: name: example-environment - type: Selector selector: matchLabels: # Removed for brevity ``` If a Composition uses multiple {{}}environmentConfigs{{}} Crossplane merges them together in the order they're listed. {{}} If multiple {{}}environmentConfigs{{}} use the same key, the Composition uses the value of the last environment listed. {{}} ### Select by name Select an environment by name with {{}}type: Reference{{}}. Define the {{}}ref{{}} object and the {{}}name{{}} matching the exact name of the environment. For example, select the {{}}environmentConfig{{}} named {{}}example-environment{{}} ```yaml {label="byName",copy-lines="all"} apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: name: example-composition spec: environment: environmentConfigs: - type: Reference ref: name: example-environment ``` ### Select by label Select an environment by labels with a {{}}type: Selector{{}}. Define the {{}}selector{{}} object. The {{}}matchLabels{{}} object contains a list of labels to match on. Selecting a label requires matching both the label {{}}key{{}} and the value of key. When matching the label's value, provide an exact value with a {{}}type: Value{{}} and provide the value to match in the {{}}value{{}} field. Crossplane can also match a label's value based on an input in the composite resource. Use {{}}type: FromCompositeFieldPath{{}} and provide the field to match in the {{}}valueFromFieldPath{{}} field. ```yaml {label="byLabel",copy-lines="all"} apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: name: example-composition spec: environment: environmentConfigs: - type: Selector selector: matchLabels: - key: my-label-key type: Value value: my-label-value - key: my-label-key type: FromCompositeFieldPath valueFromFieldPath: spec.parameters.deploy resources: # Removed for brevity ``` #### Manage selector results Selecting environments by labels may return more than one environment. The Composition sorts all the results by the name of the environments and only uses the first environment in the sorted list. Set the {{}}mode{{}} as {{}}mode: Multiple{{}} to return all matched environments. Use {{}}mode: Single{{}} to return a single environment. {{}} Sorting and the selection {{}}mode{{}} only applies to a single {{}}type: Selector{{}}. This doesn't change how Compositions merge multiple {{}}environmentConfigs{{}}. {{< /hint >}} ```yaml {label="selectResults"} apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: name: example-composition spec: environment: environmentConfigs: - type: Selector selector: mode: Multiple matchLabels: - key: my-label-key type: Value value: my-label-value - key: my-label-key type: FromCompositeFieldPath valueFromFieldPath: spec.parameters.deploy - type: Selector selector: mode: Single matchLabels: - key: my-other-label-key type: Value value: my-other-label-value - key: my-other-label-key type: FromCompositeFieldPath valueFromFieldPath: spec.parameters.deploy ``` When using {{}}mode: Multiple{{}} limit the number of returned environments with {{}}maxMatch{{}} and define the maximum number of environments returned. The Composition sorts the returned environments alphabetically by name. Sort the environments on a different field with {{}}sortByFieldPath{{}} and define the field to sort by. ```yaml {label="maxMatch"} apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: name: example-composition spec: environment: environmentConfigs: - type: Selector selector: mode: Multiple maxMatch: 4 sortByFieldPath: metadata.annotations[sort.by/weight] matchLabels: - key: my-label-key type: Value value: my-label-value - key: my-label-key type: FromCompositeFieldPath valueFromFieldPath: spec.parameters.deploy ``` The environments selected by {{}}matchLabels{{}} are then merged into any other environments listed in the {{}}environmentConfigs{{}}. #### Optional selector labels By default, Crossplane issues an error if a {{}}valueFromFieldPath{{}} field doesn't exist in the composite resource. Add {{}}fromFieldPathPolicy{{}} as {{}}Optional{{}} to ignore a field if it doesn't exist. ```yaml {label="byLabelOptional",copy-lines="all"} apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: name: example-composition spec: environment: environmentConfigs: - type: Selector selector: matchLabels: - key: my-first-label-key type: Value value: my-first-label-value - key: my-second-label-key type: FromCompositeFieldPath valueFromFieldPath: spec.parameters.deploy fromFieldPathPolicy: Optional resources: # Removed for brevity ``` Set a default value for an optional label by setting the default {{}}value{{}} for the {{}}key{{}} first, then define the {{}}Optional{{}} label. For example, this Composition defines {{}}value: my-default-value{{}} for the key {{}}my-second-label-key{{}}. If the label {{}}my-second-label-key{{}} exists, Crossplane uses the value from the label instead. ```yaml {label="byLabelOptionalDefault",copy-lines="all"} apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: name: example-composition spec: environment: environmentConfigs: - type: Selector selector: matchLabels: - key: my-first-label-key type: Value value: my-label-value - key: my-second-label-key type: Value value: my-default-value - key: my-second-label-key type: FromCompositeFieldPath valueFromFieldPath: spec.parameters.deploy fromFieldPathPolicy: Optional resources: # Removed for brevity ``` {{}} Crossplane applies values in order. The value of the last key defined always takes precedence. Defining the default value _after_ the label always overwrites the label value. {{< /hint >}} ## Patching with EnvironmentConfigs When Crossplane creates or updates a composite resource, Crossplane merges all the specified EnvironmentConfigs into an in-memory environment. The composite resource can read or write data between the EnvironmentConfig and composite resource or between the EnvironmentConfig and individual resources defined inside the composite resource. {{}} Read about EnvironmentConfig patch types in the [Patch and Transform]({{}}) documentation. {{< /hint >}} ### Patch a composite resource To patch the composite resource use {{< hover label="xrpatch" line="7">}}patches{{}} inside of the {{< hover label="xrpatch" line="5">}}environment{{}}. Use the {{< hover label="xrpatch" line="5">}}ToCompositeFieldPath{{}} to copy data from the in-memory environment to the composite resource. Use the {{< hover label="xrpatch" line="5">}}FromCompositeFieldPath{{}} to copy data from the composite resource to the in-memory environment. ```yaml {label="xrpatch",copy-lines="none"} apiVersion: apiextensions.crossplane.io/v1 kind: Composition # Removed for Brevity spec: environment: # Removed for Brevity patches: - type: ToCompositeFieldPath fromFieldPath: tags toFieldPath: metadata.labels[envTag] - type: FromCompositeFieldPath fromFieldPath: metadata.name toFieldPath: newEnvironmentKey ``` Individual resources can use any data written to the in-memory environment. ### Patch an individual resource To patch an individual resource, inside the {{}}patches{{}} of the resource, use {{}}ToEnvironmentFieldPath{{}} to copy data from the resource to the in-memory environment. Use {{}}FromEnvironmentFieldPath{{}} to copy data to the resource from the in-memory environment. ```yaml {label="envpatch",copy-lines="none"} apiVersion: apiextensions.crossplane.io/v1 kind: Composition # Removed for Brevity spec: environment: # Removed for Brevity resources: # Removed for Brevity - name: vpc base: apiVersion: ec2.aws.upbound.io/v1beta1 kind: VPC spec: forProvider: cidrBlock: 172.16.0.0/16 patches: - type: ToEnvironmentFieldPath fromFieldPath: status.atProvider.id toFieldPath: vpcId - type: FromEnvironmentFieldPath fromFieldPath: tags toFieldPath: spec.forProvider.tags ``` The [Patch and Transform]({{}}) documentation has more information on patching individual resources.