Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add consistent field support for cidrFunc (this is a breaking change,…
Browse files Browse the repository at this point in the history
… but used for consistency reasons: use cidrFuncField instead of cidrFunc now)

add output field
add possibiltiy to set fully qualified field references (e.g. desired.composite.resource., observed.composite.resource. or context.)

Signed-off-by: anessi <[email protected]>
anessi committed Jul 1, 2024

Verified

This commit was signed with the committer’s verified signature.
hakimifr Hakimi
1 parent fe95f53 commit c8360f0
Showing 16 changed files with 495 additions and 107 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -23,4 +23,5 @@ go.work
.golangci.yml
*.xpkg
function-cidr
.vscode
.vscode
*__debug_bin*
18 changes: 18 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
generate:
go generate ./...

build:
docker build . --quiet --platform=linux/amd64 --tag runtime-amd64
crossplane xpkg build --package-root=package --embed-runtime-image=runtime-amd64 --package-file=function-amd64.xpkg

render:
@for file in examples/xr-*.yaml; do \
echo "Rendering $$file..."; \
@@ -6,3 +13,14 @@ render:
apis/composition.yaml \
examples/functions.yaml; \
done

render-pipeline:
crossplane beta render examples/xr-cidrsubnet.yaml \
apis/composition-pipeline.yaml \
examples/functions.yaml

render-pipeline-context:
crossplane beta render examples/xr-cidrsubnet.yaml \
apis/composition-pipeline-context.yaml \
examples/functions-pipeline-context.yaml \
--extra-resources=examples/extraResources.yaml
25 changes: 14 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -54,21 +54,24 @@ Valid values are as follows:
- cidrsubnets
- cidrsubnetloop
```
Specify a custom `outputfield` in the function input parameters
Specify a custom `outputField` in the function input parameters
when the output should appear at a different path
than the respective `status.atFunction.cidr` sub field default path.

All `cidrfunc` IP Network Functions require a CIDR `prefix` as input.
Provide the `prefix` directly in the
function input or specify a `prefixfield` in the XR where
function input or specify a `prefixField` in the XR where
the function shall pick up the `prefix` value.

Function input field names ending in `field` indicate that
the function shall read the field path value from the specified
field path in the XR.
Function input field names ending in `Field` indicate that
the function shall read the field path value from the specified field path in the XR.
You can also provide `desired.composite.resource.` and `observed.composite.resource.` in the `prefixField` value to reference
the resource attribute from where to read the prefix value. See [apis/composition-pipeline.yaml](apis/composition-pipeline.yaml).
In addition, referencing the pipeline `context` is supported. You can use [gjson](https://github.com/tidwall/gjson)
for selecting context values. See [apis/composition-pipeline-context.yaml](apis/composition-pipeline-context.yaml).

### cidrhost
The `cidrhost cidrfunc` requires a `hostnum` or `hostnumfield` as
The `cidrhost cidrfunc` requires a `hostnum` or `hostnumField` as
function input. `hostnum` is an integer.

### cidrnetmask
@@ -78,8 +81,8 @@ when the `prefixField` path is specified in the function input
instead of a `prefix` value.

### cidrsubnet
The `cidrhost cidrsubnet` reauires a `netnum` or `netnumfield`,
and a `newbits` or `newbitsfield` as function input.
The `cidrhost cidrsubnet` reauires a `netnum` or `netnumField`,
and a `newbits` or `newbitsField` as function input.

`netNum` is an integer.
`newBits` is one integer in an array of integers.
@@ -95,7 +98,7 @@ The `cidrhost cidrsubnetloop` reauires the following input fields.
- `newBits` (integer array) or `newBitsField`
- `netNumCount` (integer) or `netNumCountField`
- `netNumItems` (string array) or `netNumItemsField`
- `offset` or `offsetfield`
- `offset` or `offsetField`
** netNumCount and netNumItems are mutually exclusive **

The `cidrsubnetloop` wrapper calculates `cidrsubnet` CIDRs using
@@ -107,5 +110,5 @@ or their respective values from their XR field references.

## Testing The Function
Clone the repo. Run `make debug` and in a second terminal run `make render`
and examine the output. Corresponding compositions and XR yaml can be
found in the `examples` folder.
or `make render-pipeline` and examine the output.
Corresponding compositions and XR yaml can be found in the `examples` folder.
100 changes: 100 additions & 0 deletions apis/composition-pipeline-context.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: xcidrs.platform.upbound.io
spec:
compositeTypeRef:
apiVersion: platform.upbound.io/v1alpha1
kind: XCIDR
mode: Pipeline
pipeline:
- step: pull-extra-resources
functionRef:
name: function-extra-resources
input:
apiVersion: extra-resources.fn.crossplane.io/v1beta1
kind: Input
spec:
extraResources:
- kind: XCluster
into: XCluster
apiVersion: example.crossplane.io/v1
type: Selector
selector:
maxMatch: 2
minMatch: 1
matchLabels:
- key: type
type: Value
value: cluster
- step: debug-context
functionRef:
name: function-go-templating
input:
apiVersion: gotemplate.fn.crossplane.io/v1beta1
kind: GoTemplate
source: Inline
inline:
template: |
apiVersion: test.my-domain.com/v1alpha1
kind: DebugContext
metadata:
annotations:
gotemplating.fn.crossplane.io/composition-resource-name: debug-context
debug:
{{ . | toYaml | nindent 2 }}
- step: cidr-subnets-partitions
functionRef:
name: upbound-function-cidr
input:
apiVersion: cidr.fn.crossplane.io/v1beta1
kind: Parameters
cidrFunc: cidrsubnets
prefixField: context.apiextensions\.crossplane\.io/extra-resources.XCluster.0.spec.cidrBlock
newBits:
- 1
- 1
output: status.atFunction.cidr.partitions
- step: cidr-subnets-private
functionRef:
name: upbound-function-cidr
input:
apiVersion: cidr.fn.crossplane.io/v1beta1
kind: Parameters
cidrFunc: cidrsubnets
prefixField: desired.composite.resource.status.atFunction.cidr.partitions[0]
newBits:
- 1
- 1
output: status.atFunction.cidr.private.subnets
- step: cidr-subnets-public
functionRef:
name: upbound-function-cidr
input:
apiVersion: cidr.fn.crossplane.io/v1beta1
kind: Parameters
cidrFunc: cidrsubnets
prefixField: desired.composite.resource.status.atFunction.cidr.partitions[1]
newBits:
- 1
- 1
output: status.atFunction.cidr.public.subnets
# To debug the pipeline output you can generate a new resource which contains all attribues. Make sure to add function-go-templating to functions.yaml.
- step: render-templates
functionRef:
name: function-go-templating
input:
apiVersion: gotemplate.fn.crossplane.io/v1beta1
kind: GoTemplate
source: Inline
inline:
template: |
apiVersion: test.my-domain.com/v1alpha1
kind: DebugResource
metadata:
annotations:
gotemplating.fn.crossplane.io/composition-resource-name: debug
debug:
{{ . | toYaml | nindent 2 }}
debugValue:
{{ index .desired.composite.resource.status.atFunction.cidr.public.subnets 0 | nindent 2 }}
65 changes: 65 additions & 0 deletions apis/composition-pipeline.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: xcidrs.platform.upbound.io
spec:
compositeTypeRef:
apiVersion: platform.upbound.io/v1alpha1
kind: XCIDR
mode: Pipeline
pipeline:
- step: cidr-subnets-partitions
functionRef:
name: upbound-function-cidr
input:
apiVersion: cidr.fn.crossplane.io/v1beta1
kind: Parameters
cidrFunc: cidrsubnets
prefixField: spec.parameters.cidrBlock
newBits:
- 1
- 1
output: status.atFunction.cidr.partitions
- step: cidr-subnets-private
functionRef:
name: upbound-function-cidr
input:
apiVersion: cidr.fn.crossplane.io/v1beta1
kind: Parameters
cidrFunc: cidrsubnets
prefixField: desired.composite.resource.status.atFunction.cidr.partitions[0]
newBits:
- 1
- 1
output: status.atFunction.cidr.private.subnets
- step: cidr-subnets-public
functionRef:
name: upbound-function-cidr
input:
apiVersion: cidr.fn.crossplane.io/v1beta1
kind: Parameters
cidrFunc: cidrsubnets
prefixField: desired.composite.resource.status.atFunction.cidr.partitions[1]
newBits:
- 1
- 1
output: status.atFunction.cidr.public.subnets
## To debug the pipeline output you can generate a new resource which contains all attribues. Make sure to add function-go-templating to functions.yaml.
# - step: render-templates
# functionRef:
# name: function-go-templating
# input:
# apiVersion: gotemplate.fn.crossplane.io/v1beta1
# kind: GoTemplate
# source: Inline
# inline:
# template: |
# apiVersion: test.my-domain.com/v1alpha1
# kind: DebugResource
# metadata:
# annotations:
# gotemplating.fn.crossplane.io/composition-resource-name: debug
# debug:
# {{ . | toYaml | nindent 2 }}
# debugValue:
# {{ index .desired.composite.resource.status.atFunction.cidr.public.subnets 0 | nindent 2 }}
2 changes: 1 addition & 1 deletion apis/composition.yaml
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ spec:
input:
apiVersion: cidr.fn.crossplane.io/v1beta1
kind: Parameters
cidrFunc: spec.parameters.cidrFunc
cidrFuncField: spec.parameters.cidrFunc
prefixField: spec.parameters.cidrBlock
newBitsField: spec.parameters.newBits
netNumItemsField: spec.parameters.azs
8 changes: 8 additions & 0 deletions examples/extraResources.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: example.crossplane.io/v1
kind: XCluster
metadata:
name: net-staging-blue
labels:
type: cluster
spec:
cidrBlock: 10.0.0.0/20
30 changes: 30 additions & 0 deletions examples/functions-pipeline-context.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
apiVersion: pkg.crossplane.io/v1beta1
kind: Function
metadata:
name: upbound-function-cidr
annotations:
render.crossplane.io/runtime: Development

# spec:
# package: xpkg.upbound.io/upbound/function-cidr:v0.3.0
---
apiVersion: pkg.crossplane.io/v1beta1
kind: Function
metadata:
name: function-go-templating
annotations:
render.crossplane.io/runtime-docker-cleanup: "Orphan"
spec:
package: xpkg.upbound.io/crossplane-contrib/function-go-templating:v0.4.1
---
apiVersion: pkg.crossplane.io/v1beta1
kind: Function
metadata:
name: function-extra-resources
annotations:
render.crossplane.io/runtime-docker-cleanup: "Orphan"
# 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-extra-resources:v0.0.3
1 change: 1 addition & 0 deletions examples/xr-cidrsubnetloop.yaml
Original file line number Diff line number Diff line change
@@ -13,3 +13,4 @@ spec:
- us-west-2
- us-west-3
offset: 48
output: status.atFunction.cidr.subnetloops
1 change: 1 addition & 0 deletions examples/xr-cidrsubnets.yaml
Original file line number Diff line number Diff line change
@@ -10,3 +10,4 @@ spec:
- 8
- 4
- 2
output: status.atFunction.cidr.subnets
86 changes: 60 additions & 26 deletions fn.go
Original file line number Diff line number Diff line change
@@ -35,7 +35,12 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ
response.Fatal(rsp, errors.Wrapf(err, "cannot get observed composite resource from %T", req))
return rsp, nil
}
if err := ValidateParameters(input, oxr); err != nil {
dxr, err := request.GetDesiredCompositeResource(req)
if err != nil {
response.Fatal(rsp, errors.Wrap(err, "cannot get desired composite resource"))
return rsp, nil
}
if err := ValidateParameters(input, oxr, req); err != nil {
response.Fatal(rsp, errors.Wrap(err, "invalid Function input"))
return rsp, nil
}
@@ -46,12 +51,6 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ
"oxr-name", oxr.Resource.GetName(),
)

dxr, err := request.GetDesiredCompositeResource(req)
if err != nil {
response.Fatal(rsp, errors.Wrap(err, "cannot get desired composite resource"))
return rsp, nil
}

dxr.Resource.SetAPIVersion(oxr.Resource.GetAPIVersion())
if err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot set ApiVersion %s for %s", oxr.Resource.GetAPIVersion(), oxr.Resource.GetKind()))
@@ -65,18 +64,18 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ

prefix := input.Prefix
if len(input.PrefixField) > 0 {
prefix, err = oxr.Resource.GetString(input.PrefixField)
prefix, err = GetPrefixField(input.PrefixField, oxr, req)
if err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot get prefix from field %s for %s", input.PrefixField, oxr.Resource.GetKind()))
return rsp, nil
}
}

cidrFunc := input.CidrFunc
if len(input.CidrFunc) > 0 {
cidrFunc, err = oxr.Resource.GetString(input.CidrFunc)
if len(input.CidrFuncField) > 0 {
cidrFunc, err = oxr.Resource.GetString(input.CidrFuncField)
if err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot get cidrFunc from field %s for %s", input.CidrFunc, oxr.Resource.GetKind()))
response.Fatal(rsp, errors.Wrapf(err, "cannot get cidrFunc from field %s for %s", input.CidrFuncField, oxr.Resource.GetKind()))
return rsp, nil
}
}
@@ -99,9 +98,16 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ
return rsp, nil
}

field, err := oxr.Resource.GetString(input.OutputField)
if err != nil {
field = "status.atFunction.cidr.host"
field := "status.atFunction.cidr.host"
if input.Output != "" {
field = input.Output
} else if input.OutputField != "" {
oxrField, err := oxr.Resource.GetString(input.OutputField)
if err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot get output from field %s for %s", input.OutputField, oxr.Resource.GetKind()))
return rsp, nil
}
field = oxrField
}

err = dxr.Resource.SetString(field, host)
@@ -118,9 +124,16 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ
response.Fatal(rsp, errors.Wrapf(err, "cannot calculate CIDR netmask for %s", oxr.Resource.GetKind()))
return rsp, nil
}
field, err := oxr.Resource.GetString(input.OutputField)
if err != nil {
field = "status.atFunction.cidr.netmask"
field := "status.atFunction.cidr.netmask"
if input.Output != "" {
field = input.Output
} else if input.OutputField != "" {
oxrField, err := oxr.Resource.GetString(input.OutputField)
if err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot get output from field %s for %s", input.OutputField, oxr.Resource.GetKind()))
return rsp, nil
}
field = oxrField
}
err = dxr.Resource.SetString(field, netmask)
if err != nil {
@@ -154,9 +167,16 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ
response.Fatal(rsp, errors.Wrapf(err, "cannot calculate subnet CIDR for %s", oxr.Resource.GetKind()))
return rsp, nil
}
field, err := oxr.Resource.GetString(input.OutputField)
if err != nil {
field = "status.atFunction.cidr.subnet"
field := "status.atFunction.cidr.subnet"
if input.Output != "" {
field = input.Output
} else if input.OutputField != "" {
oxrField, err := oxr.Resource.GetString(input.OutputField)
if err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot get output from field %s for %s", input.OutputField, oxr.Resource.GetKind()))
return rsp, nil
}
field = oxrField
}
err = dxr.Resource.SetString(field, string(cidr))
if err != nil {
@@ -187,9 +207,16 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ
for _, cidr := range cidrs {
cidrSubnetsStringArray = append(cidrSubnetsStringArray, string(cidr))
}
field, err := oxr.Resource.GetString(input.OutputField)
if err != nil {
field = "status.atFunction.cidr.subnets"
field := "status.atFunction.cidr.subnets"
if input.Output != "" {
field = input.Output
} else if input.OutputField != "" {
oxrField, err := oxr.Resource.GetString(input.OutputField)
if err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot get output from field %s for %s", input.OutputField, oxr.Resource.GetKind()))
return rsp, nil
}
field = oxrField
}
err = dxr.Resource.SetValue(field, cidrSubnetsStringArray)
if err != nil {
@@ -252,9 +279,16 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ
}
cidrSubnetLoopStringArray = append(cidrSubnetLoopStringArray, string(cidr))
}
field, err := oxr.Resource.GetString(input.OutputField)
if err != nil {
field = "status.atFunction.cidr.subnets"
field := "status.atFunction.cidr.subnets"
if input.Output != "" {
field = input.Output
} else if input.OutputField != "" {
oxrField, err := oxr.Resource.GetString(input.OutputField)
if err != nil {
response.Fatal(rsp, errors.Wrapf(err, "cannot get output from field %s for %s", input.OutputField, oxr.Resource.GetKind()))
return rsp, nil
}
field = oxrField
}
err = dxr.Resource.SetValue(field, cidrSubnetLoopStringArray)
if err != nil {
28 changes: 16 additions & 12 deletions go.mod
Original file line number Diff line number Diff line change
@@ -9,9 +9,10 @@ require (
github.com/crossplane/function-sdk-go v0.2.0
github.com/google/go-cmp v0.6.0
github.com/pkg/errors v0.9.1
github.com/tidwall/gjson v1.17.1
google.golang.org/protobuf v1.33.0
k8s.io/apimachinery v0.29.3
sigs.k8s.io/controller-tools v0.14.0
k8s.io/apimachinery v0.30.0
sigs.k8s.io/controller-tools v0.15.0
)

require (
@@ -44,27 +45,30 @@ require (
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cobra v1.8.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.26.0 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/oauth2 v0.15.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/term v0.16.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/term v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.17.0 // indirect
golang.org/x/tools v0.20.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect
google.golang.org/grpc v1.61.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.29.1 // indirect
k8s.io/apiextensions-apiserver v0.29.1 // indirect
k8s.io/client-go v0.29.1 // indirect
k8s.io/klog/v2 v2.110.1 // indirect
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
k8s.io/api v0.30.0 // indirect
k8s.io/apiextensions-apiserver v0.30.0 // indirect
k8s.io/client-go v0.30.0 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
k8s.io/utils v0.0.0-20240102154912-e7106e64919e // indirect
sigs.k8s.io/controller-runtime v0.17.0 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
71 changes: 38 additions & 33 deletions go.sum
Original file line number Diff line number Diff line change
@@ -45,7 +45,6 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/go-json-experiment/json v0.0.0-20231013223334-54c864be5b8d h1:zqfo2jECgX5eYQseB/X+uV4Y5ocGOG/vG/LTztUCyPA=
github.com/go-json-experiment/json v0.0.0-20231013223334-54c864be5b8d/go.mod h1:6daplAwHHGbUGib4990V3Il26O0OC4aRyvewaaAihaA=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
@@ -157,10 +156,10 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY=
github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw=
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
github.com/onsi/gomega v1.33.0 h1:snPCflnZrpMsy94p4lXVEkHo12lmPnc3vY5XBbreexE=
github.com/onsi/gomega v1.33.0/go.mod h1:+925n5YtiFsLzzafLUHzVMBpvvRAzrydIBiSIxjX3wY=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -191,6 +190,12 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tmccombs/hcl2json v0.3.3 h1:+DLNYqpWE0CsOQiEZu+OZm5ZBImake3wtITYxQ8uLFQ=
github.com/tmccombs/hcl2json v0.3.3/go.mod h1:Y2chtz2x9bAeRTvSibVRVgbLJhLJXKlUeIvjeVdnm4w=
github.com/upbound/provider-aws v0.47.1 h1:Z+eAy9Ut4suVrx79pkzhsYTC6uvxNW2jkwAQCUVbq3g=
@@ -222,24 +227,24 @@ golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/i
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -249,12 +254,12 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
@@ -268,8 +273,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -299,26 +304,26 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.29.1 h1:DAjwWX/9YT7NQD4INu49ROJuZAAAP/Ijki48GUPzxqw=
k8s.io/api v0.29.1/go.mod h1:7Kl10vBRUXhnQQI8YR/R327zXC8eJ7887/+Ybta+RoQ=
k8s.io/apiextensions-apiserver v0.29.1 h1:S9xOtyk9M3Sk1tIpQMu9wXHm5O2MX6Y1kIpPMimZBZw=
k8s.io/apiextensions-apiserver v0.29.1/go.mod h1:zZECpujY5yTW58co8V2EQR4BD6A9pktVgHhvc0uLfeU=
k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU=
k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU=
k8s.io/client-go v0.29.1 h1:19B/+2NGEwnFLzt0uB5kNJnfTsbV8w6TgQRz9l7ti7A=
k8s.io/client-go v0.29.1/go.mod h1:TDG/psL9hdet0TI9mGyHJSgRkW3H9JZk2dNEUS7bRks=
k8s.io/component-base v0.29.1 h1:MUimqJPCRnnHsskTTjKD+IC1EHBbRCVyi37IoFBrkYw=
k8s.io/component-base v0.29.1/go.mod h1:fP9GFjxYrLERq1GcWWZAE3bqbNcDKDytn2srWuHTtKc=
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
k8s.io/api v0.30.0 h1:siWhRq7cNjy2iHssOB9SCGNCl2spiF1dO3dABqZ8niA=
k8s.io/api v0.30.0/go.mod h1:OPlaYhoHs8EQ1ql0R/TsUgaRPhpKNxIMrKQfWUp8QSE=
k8s.io/apiextensions-apiserver v0.30.0 h1:jcZFKMqnICJfRxTgnC4E+Hpcq8UEhT8B2lhBcQ+6uAs=
k8s.io/apiextensions-apiserver v0.30.0/go.mod h1:N9ogQFGcrbWqAY9p2mUAL5mGxsLqwgtUce127VtRX5Y=
k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA=
k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ=
k8s.io/client-go v0.30.0/go.mod h1:g7li5O5256qe6TYdAMyX/otJqMhIiGgTapdLchhmOaY=
k8s.io/component-base v0.30.0 h1:cj6bp38g0ainlfYtaOQuRELh5KSYjhKxM+io7AUIk4o=
k8s.io/component-base v0.30.0/go.mod h1:V9x/0ePFNaKeKYA3bOvIbrNoluTSG+fSJKjLdjOoeXQ=
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ=
k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/controller-runtime v0.17.0 h1:fjJQf8Ukya+VjogLO6/bNX9HE6Y2xpsO5+fyS26ur/s=
sigs.k8s.io/controller-runtime v0.17.0/go.mod h1:+MngTvIQQQhfXtwfdGw/UOQ/aIaqsYywfCINOtwMO/s=
sigs.k8s.io/controller-tools v0.14.0 h1:rnNoCC5wSXlrNoBKKzL70LNJKIQKEzT6lloG6/LF73A=
sigs.k8s.io/controller-tools v0.14.0/go.mod h1:TV7uOtNNnnR72SpzhStvPkoS/U5ir0nMudrkrC4M9Sc=
sigs.k8s.io/controller-tools v0.15.0 h1:4dxdABXGDhIa68Fiwaif0vcu32xfwmgQ+w8p+5CxoAI=
sigs.k8s.io/controller-tools v0.15.0/go.mod h1:8zUSS2T8Hx0APCNRhJWbS3CAQEbIxLa07khzh7pZmXM=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
10 changes: 8 additions & 2 deletions input/v1beta1/parameters.go
Original file line number Diff line number Diff line change
@@ -19,8 +19,11 @@ type Parameters struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

// cidrfunc is one of cidrhost, cidrnetmast, cidesubnet, cidrsubnets, cidrsubnetloop
CidrFunc string `json:"cidrFunc"`
// cidrFuncField field
CidrFuncField string `json:"cidrFuncField,omitempty"`

// cidrfunc is one of cidrhost, cidrnetmask, cidrsubnet, cidrsubnets, cidrsubnetloop
CidrFunc string `json:"cidrFunc,omitempty"`

// prefix field
PrefixField string `json:"prefixField,omitempty"`
@@ -66,4 +69,7 @@ type Parameters struct {

// output field
OutputField string `json:"outputField,omitempty"`

// output
Output string `json:"output,omitempty"`
}
28 changes: 19 additions & 9 deletions package/input/cidr.fn.crossplane.io_parameters.yaml
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.13.0
controller-gen.kubebuilder.io/version: v0.15.0
name: parameters.cidr.fn.crossplane.io
spec:
group: cidr.fn.crossplane.io
@@ -22,24 +22,32 @@ spec:
description: Parameters can be used to provide input to this Function.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
cidrFunc:
description: cidrfunc is one of cidrhost, cidrnetmast, cidesubnet, cidrsubnets,
description: cidrfunc is one of cidrhost, cidrnetmask, cidrsubnet, cidrsubnets,
cidrsubnetloop
type: string
cidrFuncField:
description: cidrFuncField field
type: string
hostNum:
description: hostnum
type: integer
hostNumField:
description: hostnum field
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
@@ -79,6 +87,9 @@ spec:
offsetField:
description: offset field
type: string
output:
description: output
type: string
outputField:
description: output field
type: string
@@ -89,7 +100,6 @@ spec:
description: prefix field
type: string
required:
- cidrFunc
- prefix
type: object
served: true
126 changes: 114 additions & 12 deletions validate.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,125 @@
package main

import (
"encoding/json"
"fmt"
"net"
"strings"

"github.com/pkg/errors"

"github.com/tidwall/gjson"

"k8s.io/apimachinery/pkg/util/validation/field"

fnv1beta1 "github.com/crossplane/function-sdk-go/proto/v1beta1"
"github.com/crossplane/function-sdk-go/request"
"github.com/crossplane/function-sdk-go/resource"

"github.com/upbound/function-cidr/input/v1beta1"
)

// ExtractKeys extracts keys from a dotted list of keys while considering quoted strings a single value.
func ExtractKeys(input string) []string {
var keys []string
var keyBuilder strings.Builder
inQuotes := false

for i := 0; i < len(input); i++ {
char := input[i]

if char == '\'' {
inQuotes = !inQuotes
} else if char == '.' && !inQuotes {
keys = append(keys, keyBuilder.String())
keyBuilder.Reset()
} else {
keyBuilder.WriteByte(char)
}
}

if keyBuilder.Len() > 0 {
keys = append(keys, keyBuilder.String())
}

return keys
}

// GetPrefixField returns the prefix value from the defined field
func GetPrefixField(prefixField string, oxr *resource.Composite, req *fnv1beta1.RunFunctionRequest) (string, error) {
prefix := ""
if strings.HasPrefix(prefixField, "observed.") {
oxrPrefix, err := oxr.Resource.GetString(strings.Replace(prefixField, "observed.", "", 1))
prefix = oxrPrefix
if err != nil {
return "", errors.Wrapf(err, "cannot get prefix from field %s for %s", prefixField, oxr.Resource.GetKind())
}
} else if strings.HasPrefix(prefixField, "desired.") {
if strings.HasPrefix(prefixField, "desired.composite.") {
dxr, err := request.GetDesiredCompositeResource(req)
if err != nil {
return "", errors.Wrapf(err, "cannot get desired composite resource. Field %s for %s", prefixField, dxr.Resource.GetKind())
}
dxrPrefix, err := dxr.Resource.GetString(strings.Replace(prefixField, "desired.composite.resource.", "", 1))
prefix = dxrPrefix
if err != nil {
return "", errors.Wrapf(err, "cannot get prefix from field %s for %s", prefixField, dxr.Resource.GetKind())
}
} else if strings.HasPrefix(prefixField, "desired.resources.") {
properties := ExtractKeys(strings.Replace(prefixField, "desired.resources.", "", 1))
resourceName := resource.Name(properties[0])
dxr, err := request.GetDesiredComposedResources(req)
if err != nil {
return "", errors.Wrapf(err, "cannot get desired composed resource from %s", prefixField)
}
if val, ok := dxr[resourceName]; ok {
dxrPrefix, err := val.Resource.GetString(strings.Replace(prefixField, "desired.resources."+properties[0]+".resource.", "", 1))
prefix = dxrPrefix
if err != nil {
return "", errors.Wrapf(err, "cannot get prefix for resource with name %s from field %s", resourceName, prefixField)
}
} else {
return "", errors.New(fmt.Sprintf("No composed resource with name %s found for field %s", resourceName, prefixField))
}
}
} else if strings.HasPrefix(prefixField, "context.") {
ctxField := strings.Replace(prefixField, "context.", "", 1)
ctx := req.Context
if ctx == nil {
return "", errors.New("No context available")
}
json, err := json.Marshal(ctx)
if err != nil {
return "", errors.Wrapf(err, "failed to marshall context to json for extraction of field %s", prefixField)
}
prefixValue := gjson.GetBytes(json, ctxField)
if !prefixValue.Exists() {
return "", errors.New(fmt.Sprintf("Failed to extract value for %s from json context %s", ctxField, json))
}
prefix = prefixValue.Str
} else {
prefixValue, err := oxr.Resource.GetString(prefixField)
prefix = prefixValue
if err != nil {
return "", errors.Wrapf(err, "cannot get prefix from field %s for %s", prefixField, oxr.Resource.GetKind())
}
}
return prefix, nil
}

// ValidatePrefixParameter validates prefix parameter
func ValidatePrefixParameter(prefix, prefixField string, oxr *resource.Composite) *field.Error {
func ValidatePrefixParameter(prefix, prefixField string, oxr *resource.Composite, req *fnv1beta1.RunFunctionRequest) *field.Error {
if len(prefix) > 0 && len(prefixField) > 0 {
return field.Required(field.NewPath("parameters"), "specify only one of prefix or prefixfield to avoid ambiguous function input")
return field.Required(field.NewPath("parameters"), "specify only one of prefix or prefixField to avoid ambiguous function input")
}
if prefix == "" {
if prefixField == "" {
return field.Required(field.NewPath("parameters"), "either prefix or prefixfield function input is required")
return field.Required(field.NewPath("parameters"), "either prefix or prefixField function input is required")
}
oxrPrefix, err := oxr.Resource.GetString(prefixField)
oxrPrefix, err := GetPrefixField(prefixField, oxr, req)
prefix = oxrPrefix
if err != nil {
return field.Required(field.NewPath("parameters"), "cannot get prefix at prefixfield "+prefixField)
return field.Required(field.NewPath("parameters"), errors.Wrapf(err, "cannot get prefix at prefixField "+prefixField).Error())
}
}

@@ -128,19 +226,23 @@ func ValidateCidrSubnetloopParameters(p *v1beta1.Parameters) *field.Error {
}

// ValidateParameters validates the Parameters object.
func ValidateParameters(p *v1beta1.Parameters, oxr *resource.Composite) *field.Error {
if p.CidrFunc == "" {
return field.Required(field.NewPath("parameters"), "cidrFunc is required")
func ValidateParameters(p *v1beta1.Parameters, oxr *resource.Composite, req *fnv1beta1.RunFunctionRequest) *field.Error {
if p.CidrFunc == "" && p.CidrFuncField == "" {
return field.Required(field.NewPath("parameters"), "cidrFunc or cidrFuncField is required")
}

fieldError := ValidatePrefixParameter(p.Prefix, p.PrefixField, oxr)
fieldError := ValidatePrefixParameter(p.Prefix, p.PrefixField, oxr, req)
if fieldError != nil {
return fieldError
}

cidrFunc, err := oxr.Resource.GetString(p.CidrFunc)
if err != nil {
return field.Required(field.NewPath("parameters"), "cidrFunc is required")
var cidrFunc = p.CidrFunc
if p.CidrFuncField != "" {
oxrCidrFunc, err := oxr.Resource.GetString(p.CidrFuncField)
cidrFunc = oxrCidrFunc
if err != nil {
return field.Required(field.NewPath("parameters"), "cidrFuncField could not be found")
}
}

switch cidrFunc {

0 comments on commit c8360f0

Please sign in to comment.