generated from crossplane/function-template-go
-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #128 from stevendborrelli/write-context
Function Context support
- Loading branch information
Showing
11 changed files
with
462 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package main | ||
|
||
import ( | ||
"dario.cat/mergo" | ||
"github.com/crossplane/function-sdk-go/errors" | ||
fnv1beta1 "github.com/crossplane/function-sdk-go/proto/v1beta1" | ||
) | ||
|
||
// MergeContext merges existing Context with new values provided | ||
func (f *Function) MergeContext(req *fnv1beta1.RunFunctionRequest, val map[string]interface{}) (map[string]interface{}, error) { | ||
mergedContext := req.GetContext().AsMap() | ||
if len(val) == 0 { | ||
return mergedContext, nil | ||
} | ||
if err := mergo.Merge(&mergedContext, val, mergo.WithOverride); err != nil { | ||
return mergedContext, errors.Wrapf(err, "cannot merge data %T", req) | ||
} | ||
return mergedContext, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package main | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/crossplane/crossplane-runtime/pkg/logging" | ||
fnv1beta1 "github.com/crossplane/function-sdk-go/proto/v1beta1" | ||
"github.com/crossplane/function-sdk-go/resource" | ||
"github.com/google/go-cmp/cmp" | ||
"github.com/google/go-cmp/cmp/cmpopts" | ||
"google.golang.org/protobuf/testing/protocmp" | ||
) | ||
|
||
func TestMergeContext(t *testing.T) { | ||
type args struct { | ||
val map[string]interface{} | ||
req *fnv1beta1.RunFunctionRequest | ||
} | ||
type want struct { | ||
us map[string]any | ||
err error | ||
} | ||
|
||
cases := map[string]struct { | ||
reason string | ||
args args | ||
want want | ||
}{ | ||
"NoContextAtKey": { | ||
reason: "When there is no existing context data at the key to merge, return the value", | ||
args: args{ | ||
req: &fnv1beta1.RunFunctionRequest{ | ||
Context: nil, | ||
}, | ||
val: map[string]interface{}{"hello": "world"}, | ||
}, | ||
want: want{ | ||
us: map[string]interface{}{"hello": "world"}, | ||
err: nil, | ||
}, | ||
}, | ||
"SuccessfulMerge": { | ||
reason: "Confirm that keys are merged with source overwriting destination", | ||
args: args{ | ||
req: &fnv1beta1.RunFunctionRequest{ | ||
Context: resource.MustStructJSON(`{"apiextensions.crossplane.io/environment":{"complex":{"a":"b","c":{"d":"e","f":"1","overWrite": "fromContext"}}}}`), | ||
}, | ||
val: map[string]interface{}{ | ||
"newKey": "newValue", | ||
"apiextensions.crossplane.io/environment": map[string]any{ | ||
"complex": map[string]any{ | ||
"c": map[string]any{ | ||
"overWrite": "fromFunction", | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
want: want{ | ||
us: map[string]interface{}{ | ||
"apiextensions.crossplane.io/environment": map[string]any{ | ||
"complex": map[string]any{ | ||
"a": "b", | ||
"c": map[string]any{ | ||
"d": "e", | ||
"f": "1", | ||
"overWrite": "fromFunction", | ||
}, | ||
}, | ||
}, | ||
"newKey": "newValue"}, | ||
err: nil, | ||
}, | ||
}, | ||
} | ||
for name, tc := range cases { | ||
t.Run(name, func(t *testing.T) { | ||
f := &Function{ | ||
log: logging.NewNopLogger(), | ||
} | ||
rsp, err := f.MergeContext(tc.args.req, tc.args.val) | ||
|
||
if diff := cmp.Diff(tc.want.us, rsp, protocmp.Transform()); diff != "" { | ||
t.Errorf("%s\nf.MergeContext(...): -want rsp, +got rsp:\n%s", tc.reason, diff) | ||
} | ||
|
||
if diff := cmp.Diff(tc.want.err, err, cmpopts.EquateErrors()); diff != "" { | ||
t.Errorf("%s\nf.RunFunction(...): -want err, +got err:\n%s", tc.reason, diff) | ||
} | ||
}) | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# Writing to the Function Context | ||
|
||
function-go-templating can write to the Function Context | ||
|
||
## Testing This Function Locally | ||
|
||
You can run your function locally and test it using [`crossplane render`](https://docs.crossplane.io/latest/cli/command-reference/#render) | ||
with these example manifests. | ||
|
||
```shell | ||
crossplane render \ | ||
--extra-resources environmentConfigs.yaml \ | ||
--include-context \ | ||
xr.yaml composition.yaml functions.yaml | ||
``` | ||
|
||
Will produce an output like: | ||
|
||
```shell | ||
--- | ||
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 | ||
``` | ||
|
||
## Debugging This Function | ||
|
||
First we need to run the command in debug mode. In a terminal Window Run: | ||
|
||
```shell | ||
# Run the function locally | ||
$ go run . --insecure --debug | ||
``` | ||
|
||
Next, set the go-templating function `render.crossplane.io/runtime: Development` annotation so that | ||
`crossplane render` communicates with the local process instead of downloading an image: | ||
|
||
```yaml | ||
apiVersion: pkg.crossplane.io/v1beta1 | ||
kind: Function | ||
metadata: | ||
name: crossplane-contrib-function-go-templating | ||
annotations: | ||
render.crossplane.io/runtime: Development | ||
spec: | ||
package: xpkg.upbound.io/crossplane-contrib/function-go-templating:v0.6.0 | ||
``` | ||
While the function is running in one terminal, open another terminal window and run `crossplane render`. | ||
The function should output debug-level logs in the terminal. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
apiVersion: apiextensions.crossplane.io/v1 | ||
kind: Composition | ||
metadata: | ||
name: go-template-context.example.crossplane.io | ||
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: example-config | ||
- step: go-templating-update-context | ||
functionRef: | ||
name: crossplane-contrib-function-go-templating | ||
input: | ||
apiVersion: gotemplating.fn.crossplane.io/v1beta1 | ||
kind: GoTemplate | ||
source: Inline | ||
inline: | ||
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" }} | ||
- step: automatically-detect-ready-composed-resources | ||
functionRef: | ||
name: crossplane-contrib-function-auto-ready |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
apiVersion: apiextensions.crossplane.io/v1alpha1 | ||
kind: EnvironmentConfig | ||
metadata: | ||
name: example-config | ||
data: | ||
complex: | ||
a: b | ||
c: | ||
d: e | ||
f: "1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
--- | ||
apiVersion: pkg.crossplane.io/v1beta1 | ||
kind: Function | ||
metadata: | ||
name: crossplane-contrib-function-environment-configs | ||
spec: | ||
# This is ignored when using the Development runtime. | ||
package: xpkg.upbound.io/crossplane-contrib/function-environment-configs:v0.0.7 | ||
--- | ||
apiVersion: pkg.crossplane.io/v1beta1 | ||
kind: Function | ||
metadata: | ||
name: crossplane-contrib-function-go-templating | ||
annotations: | ||
# This tells crossplane beta render to connect to the function locally. | ||
render.crossplane.io/runtime: Development | ||
spec: | ||
package: xpkg.upbound.io/crossplane-contrib/function-go-templating:v0.6.0 | ||
--- | ||
apiVersion: pkg.crossplane.io/v1beta1 | ||
kind: Function | ||
metadata: | ||
name: crossplane-contrib-function-auto-ready | ||
spec: | ||
package: xpkg.upbound.io/crossplane-contrib/function-auto-ready:v0.2.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
apiVersion: example.crossplane.io/v1 | ||
kind: XR | ||
metadata: | ||
name: example-xr | ||
spec: {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
--- | ||
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: | ||
status: | ||
type: object | ||
properties: | ||
fromEnv: | ||
type: string |
Oops, something went wrong.