Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add helper functions for retrieving composed and composite resources #81

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@
go.work

# Binaries
function-go-templating
function-go-templating

# IDE
.idea
.idea/**
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,16 @@ about `crossplane beta render`.

## Additional functions

| Name | Description |
|------------------------------------------------------------------| --------------------------------------------------- |
| [`randomChoice`](example/inline) | Randomly selects one of a given strings |
| [`toYaml`](example/functions/toYaml) | Marshals any object into a YAML string |
| [`fromYaml`](example/functions/fromYaml) | Unmarshals a YAML string into an object |
| [`getResourceCondition`](example/functions/getResourceCondition) | Helper function to retreive conditions of resources |
| Name | Description |
|------------------------------------------------------------------|--------------------------------------------------------------|
| [`randomChoice`](example/inline) | Randomly selects one of a given strings |
| [`toYaml`](example/functions/toYaml) | Marshals any object into a YAML string |
| [`fromYaml`](example/functions/fromYaml) | Unmarshals a YAML string into an object |
| [`getResourceCondition`](example/functions/getResourceCondition) | Helper function to retreive conditions of resources |
| [`getComposedResouce`](example/functions/getComposedResource) | Helper function to retrieve observed composed resources |
| [`getCompositeResource`](example/functions/getCompositeResource) | Helper function to retreive the observed composite resource |
| [`setResourceNameAnnotation`](example/inline) | Returns the special resource-name annotation with given name |
| [`include`](example/functions/include) | Outputs template as a string |
| [`include`](example/functions/include) | Outputs template as a string |

## Developing this function

Expand Down
16 changes: 16 additions & 0 deletions example/functions/getComposedResource/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# getComposedResource
The getComposedResource function is a utility function used to facilitate the retrieval of composed resources within templated configurations, specifically targeting observed resources. By accepting a function request map and a resource name, it navigates the complex structure of a request to fetch the specified composed resource, making it easier and more user-friendly to access nested data. If the resource is found, it returns a map containing the resource's manifest; if not, it returns nil, indicating the resource does not exist or is inaccessible through the given path.
## Usage


Examples:

```golang
// 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" }}


```
49 changes: 49 additions & 0 deletions example/functions/getComposedResource/composition.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: example-function-get-composed-resource
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: |
---
# Create an initial composed resource for which we will retrieve a value
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
---
# Use getComposedResource to retrieve the observed resource named "flexServer"
{{ $flexServer := getComposedResource . "flexServer" }}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the resource was named flexserver all lowercase instead of flexServer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed :)

apiVersion: dbforpostgresql.azure.upbound.io/v1beta1
kind: FlexibleServerConfiguration
metadata:
annotations:
{{ setResourceNameAnnotation "flexServerConfig" }}
gotemplating.fn.crossplane.io/ready: "False"
spec:
forProvider:
# Populate the field using the observed status of the retrieved resource
serverId: {{ get $flexServer.status "id" }}
providerConfigRef:
name: my-provider-cfg
6 changes: 6 additions & 0 deletions example/functions/getComposedResource/functions.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: pkg.crossplane.io/v1beta1
kind: Function
metadata:
name: function-go-templating
spec:
package: xpkg.upbound.io/crossplane-contrib/function-go-templating:v0.4.1
20 changes: 20 additions & 0 deletions example/functions/getComposedResource/observed.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: dbforpostgresql.azure.upbound.io/v1beta1
kind: FlexibleServer
metadata:
annotations:
crossplane.io/composition-resource-name: flexServer
labels:
crossplane.io/composite: example
spec:
forProvider:
storageMb: 32768
providerConfigRef:
name: my-provider-cfg
status:
atProvider:
id: abcdef
conditions:
- type: Ready
status: "True"
reason: "foo"
lastTransitionTime: "2023-11-03T09:07:31Z"
6 changes: 6 additions & 0 deletions example/functions/getComposedResource/xr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: example.crossplane.io/v1beta1
kind: XR
metadata:
name: example
spec: {}

30 changes: 30 additions & 0 deletions example/functions/getCompositeResource/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# getCompositeResource
The getCompositeResource function is a utility function used to facilitate the retrieval of a composite resources (XR) within templated configurations. Upon successful retrieval, the function returns a map containing the observed composite resource's manifest. If the resource cannot be located or is unreachable, it returns nil, indicating the absence or inaccessibility of the composite resource.
## Usage


Examples:
Given the following XR spec
```yaml
apiVersion: example.crossplane.io/v1beta1
kind: XR
metadata:
name: example
spec:
name: "example"
location: "eastus"

```
```golang
// 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" }}

```
35 changes: 35 additions & 0 deletions example/functions/getCompositeResource/composition.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: example-function-get-composite-resource
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: |
---
# Use a getCompositeResource to retrieve the XR
{{ $xr := getCompositeResource . }}
apiVersion: dbforpostgresql.azure.upbound.io/v1beta1
kind: FlexibleServer
metadata:
annotations:
{{ setResourceNameAnnotation "flexserver" }}
gotemplating.fn.crossplane.io/ready: "False"
spec:
forProvider:
# Use the XR object to set values
adminLogin: {{ get $xr.spec "adminLogin" }}
location: {{ get $xr.spec "location" }}
6 changes: 6 additions & 0 deletions example/functions/getCompositeResource/functions.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: pkg.crossplane.io/v1beta1
kind: Function
metadata:
name: function-go-templating
spec:
package: xpkg.upbound.io/crossplane-contrib/function-go-templating:v0.4.1
7 changes: 7 additions & 0 deletions example/functions/getCompositeResource/xr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: example.crossplane.io/v1beta1
kind: XR
metadata:
name: example
spec:
adminLogin: "admin"
location: "eastus"
29 changes: 26 additions & 3 deletions function_maps.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import (
"gopkg.in/yaml.v3"

sprig "github.com/Masterminds/sprig/v3"
"github.com/crossplane-contrib/function-go-templating/input/v1beta1"
xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
"github.com/crossplane/crossplane-runtime/pkg/fieldpath"
"github.com/crossplane/function-sdk-go/errors"

"github.com/crossplane-contrib/function-go-templating/input/v1beta1"
)

const recursionMaxNums = 1000
Expand All @@ -25,6 +26,8 @@ var funcMaps = []template.FuncMap{
"fromYaml": fromYaml,
"getResourceCondition": getResourceCondition,
"setResourceNameAnnotation": setResourceNameAnnotation,
"getComposedResource": getComposedResource,
"getCompositeResource": getCompositeResource,
},
}

Expand All @@ -41,7 +44,7 @@ func GetNewTemplateWithFunctionMaps(delims *v1beta1.Delims) *template.Template {
tpl.Funcs(f)
}
tpl.Funcs(template.FuncMap{
"include": initInclude(tpl),
"include": initInclude(tpl),
})
tpl.Funcs(sprig.FuncMap())

Expand Down Expand Up @@ -103,4 +106,24 @@ func initInclude(t *template.Template) func(string, interface{}) (string, error)
return buf.String(), err
}

}
}

func getComposedResource(req map[string]any, name string) map[string]any {
var cr map[string]any
path := fmt.Sprintf("observed.resources.%s.resource", name)
if err := fieldpath.Pave(req).GetValueInto(path, &cr); err != nil {
return nil
}

return cr
}

func getCompositeResource(req map[string]any) map[string]any {
var cr map[string]any
path := fmt.Sprintf("observed.composite.resource")
if err := fieldpath.Pave(req).GetValueInto(path, &cr); err != nil {
return nil
}

return cr
}
Loading