Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions examples/selector_with_transforms/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Example manifests

You can run your function locally and test it using `crossplane beta render`
with these example manifests.

This example demonstrates four different transform types on label selectors,
each pulling from different fields of the composite resource:

1. **Regexp group extract** — `spec.region` (`us-east-1-abc`) → capture group 1
→ `us-east-1`
2. **Regexp replace with backreferences** —
`metadata.labels[crossplane.io/claim-namespace]` (`team-alpha`) →
`${1}-environment-config` → `alpha-environment-config`
3. **Map transform** — `spec.tier` (`production`) → mapped to `prod`
4. **Convert to lowercase** — `spec.priority` (`CRITICAL`) → `critical`

Together they select the EnvironmentConfig labeled `region: us-east-1`,
`config: alpha-environment-config`, `tier: prod`, `priority: critical`.

```shell
# Run the function locally
$ go run . --insecure --debug
```

```shell
# Then, in another terminal, call it with these example manifests
$ crossplane render \
--extra-resources selector_with_transforms/environmentConfigs.yaml \
--include-context \
selector_with_transforms/xr.yaml selector_with_transforms/composition.yaml selector_with_transforms/functions.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: https://us-east-1.example.com
team: alpha
---
apiVersion: render.crossplane.io/v1beta1
fields:
apiextensions.crossplane.io/environment:
apiVersion: internal.crossplane.io/v1alpha1
kind: Environment
region:
endpoint: https://us-east-1.example.com
name: us-east-1
team: alpha
kind: Context
```
81 changes: 81 additions & 0 deletions examples/selector_with_transforms/composition.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: function-environment-configs
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: Selector
selector:
mode: Single
matchLabels:
# 1. Regexp group extract:
# "us-east-1-abc" → extract group 1 → "us-east-1"
- key: region
valueFromFieldPath: spec.region
transforms:
- type: string
string:
type: Regexp
regexp:
match: "^([^-]+-[^-]+-[0-9]+)"
group: 1

# 2. Regexp replace with backreferences:
# "team-alpha" → "${1}-environment-config" → "alpha-environment-config"
- key: config
valueFromFieldPath: "metadata.labels[crossplane.io/claim-namespace]"
transforms:
- type: string
string:
type: Regexp
regexp:
match: "^team-(.+)$"
replace: "${1}-environment-config"

# 3. Map transform:
# "production" → "prod"
- key: tier
valueFromFieldPath: spec.tier
transforms:
- type: map
map:
production: "prod"
staging: "stage"
development: "dev"

# 4. Convert to lowercase:
# "CRITICAL" → "critical"
- key: priority
valueFromFieldPath: spec.priority
transforms:
- type: string
string:
type: Convert
convert: ToLower
- 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" "region" "endpoint" }}
team: {{ index .context "apiextensions.crossplane.io/environment" "team" }}
45 changes: 45 additions & 0 deletions examples/selector_with_transforms/environmentConfigs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
apiVersion: apiextensions.crossplane.io/v1beta1
kind: EnvironmentConfig
metadata:
name: env-us-east-1-alpha-prod-critical
labels:
region: "us-east-1"
config: "alpha-environment-config"
tier: "prod"
priority: "critical"
data:
region:
name: us-east-1
endpoint: https://us-east-1.example.com
team: alpha
---
apiVersion: apiextensions.crossplane.io/v1beta1
kind: EnvironmentConfig
metadata:
name: env-us-east-1-beta-prod-critical
labels:
region: "us-east-1"
config: "beta-environment-config"
tier: "prod"
priority: "critical"
data:
region:
name: us-east-1
endpoint: https://us-east-1.example.com
team: beta
---
apiVersion: apiextensions.crossplane.io/v1beta1
kind: EnvironmentConfig
metadata:
name: env-eu-west-1-alpha-stage-low
labels:
region: "eu-west-1"
config: "alpha-environment-config"
tier: "stage"
priority: "low"
data:
region:
name: eu-west-1
endpoint: https://eu-west-1.example.com
team: alpha
18 changes: 18 additions & 0 deletions examples/selector_with_transforms/functions.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
apiVersion: pkg.crossplane.io/v1beta1
kind: Function
metadata:
name: function-environment-configs
annotations:
# This tells crossplane beta render to connect to the function locally.
render.crossplane.io/runtime: Development
spec:
# This is ignored when using the Development runtime.
package: xpkg.upbound.io/crossplane-contrib/function-environment-configs:v0.4.0
---
apiVersion: pkg.crossplane.io/v1beta1
kind: Function
metadata:
name: function-go-templating
spec:
package: xpkg.upbound.io/crossplane-contrib/function-go-templating:v0.10.0
8 changes: 8 additions & 0 deletions examples/selector_with_transforms/provider.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-nop
spec:
package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.4.0
ignoreCrossplaneConstraints: true
10 changes: 10 additions & 0 deletions examples/selector_with_transforms/xr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: example.crossplane.io/v1
kind: XR
metadata:
name: example-xr
labels:
crossplane.io/claim-namespace: team-alpha
spec:
region: us-east-1-abc
tier: production
priority: CRITICAL
36 changes: 36 additions & 0 deletions examples/selector_with_transforms/xrd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xrs.example.crossplane.io
spec:
group: example.crossplane.io
names:
kind: XR
plural: xrs
connectionSecretKeys:
- test
versions:
- name: v1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
region:
type: string
tier:
type: string
priority:
type: string
status:
type: object
properties:
fromEnv:
type: string
team:
type: string
24 changes: 15 additions & 9 deletions fn.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,18 @@ import (
"reflect"
"sort"

"google.golang.org/protobuf/types/known/structpb"
extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"

"github.com/crossplane-contrib/function-environment-configs/input/v1beta1"
"github.com/crossplane/crossplane-runtime/pkg/errors"
"github.com/crossplane/crossplane-runtime/pkg/fieldpath"
"github.com/crossplane/crossplane-runtime/pkg/logging"
fnv1 "github.com/crossplane/function-sdk-go/proto/v1"
"github.com/crossplane/function-sdk-go/request"
"github.com/crossplane/function-sdk-go/resource"
"github.com/crossplane/function-sdk-go/response"

"github.com/crossplane-contrib/function-environment-configs/input/v1beta1"
"google.golang.org/protobuf/types/known/structpb"
extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
)

const (
Expand Down Expand Up @@ -304,14 +302,22 @@ func buildRequirements(in *v1beta1.Input, xr *resource.Composite) (*fnv1.Require
// TODO validate value not to be nil
matchLabels[selector.Key] = *selector.Value
case v1beta1.EnvironmentSourceSelectorLabelMatcherTypeFromCompositeFieldPath:
value, err := fieldpath.Pave(xr.Resource.Object).GetString(*selector.ValueFromFieldPath)
val, err := fieldpath.Pave(xr.Resource.Object).GetValue(*selector.ValueFromFieldPath)
if err != nil {
if !selector.FromFieldPathIsOptional() {
return nil, errors.Wrapf(err, "cannot get value from field path %q", *selector.ValueFromFieldPath)
}
continue
}
matchLabels[selector.Key] = value
// Apply transforms if any are specified.
if len(selector.Transforms) > 0 {
val, err = ResolveTransforms(selector.Transforms, val)
if err != nil {
return nil, errors.Wrapf(err, "cannot apply transforms for label %q from field path %q", selector.Key, *selector.ValueFromFieldPath)
}
}
// Labels are always strings.
matchLabels[selector.Key] = fmt.Sprintf("%v", val)
}
}
if len(matchLabels) == 0 {
Expand Down
Loading