Skip to content

Commit

Permalink
Add helper functions for retrieving composed and composite resources
Browse files Browse the repository at this point in the history
Signed-off-by: Jony Tucci <jony@Jonys-Mac-mini.local>
Signed-off-by: Jon Tucci <jonytucci01@gmail.com>
  • Loading branch information
jon-tucci authored and jtucci committed Mar 29, 2024
1 parent 1fbc444 commit dc62196
Show file tree
Hide file tree
Showing 13 changed files with 346 additions and 11 deletions.
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" }}
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

0 comments on commit dc62196

Please sign in to comment.