From 987e96f2bc2c00b193b3ea5794d94fffa17bae54 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Nov 2023 05:11:30 +0000 Subject: [PATCH 1/9] Update module github.com/crossplane/crossplane-runtime to v1.14.2 --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 4b2ffac..b198a8f 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ toolchain go1.21.3 require ( github.com/alecthomas/kong v0.8.1 - github.com/crossplane/crossplane-runtime v1.14.1 + github.com/crossplane/crossplane-runtime v1.14.2 github.com/crossplane/function-sdk-go v0.1.0 github.com/google/go-cmp v0.6.0 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 154f53e..8495ff8 100644 --- a/go.sum +++ b/go.sum @@ -65,6 +65,8 @@ github.com/crossplane/crossplane-runtime v1.14.0 h1:MFo93iOJLvYaMCaCoyH2vFWsHebd github.com/crossplane/crossplane-runtime v1.14.0/go.mod h1:aOP+5W2wKpvthVs3pFNbVOe1jwrKYbJho0ThGNCVz9o= github.com/crossplane/crossplane-runtime v1.14.1 h1:TCa7R1N4bDGHjsLhiRxR/mUhwmistlMACHm0kiiYKck= github.com/crossplane/crossplane-runtime v1.14.1/go.mod h1:aOP+5W2wKpvthVs3pFNbVOe1jwrKYbJho0ThGNCVz9o= +github.com/crossplane/crossplane-runtime v1.14.2 h1:pV5JMzyzi/kcbeVBVPCat5MHH8zS94MBUapAyGx/Ry0= +github.com/crossplane/crossplane-runtime v1.14.2/go.mod h1:aOP+5W2wKpvthVs3pFNbVOe1jwrKYbJho0ThGNCVz9o= github.com/crossplane/function-sdk-go v0.0.0-20231016233407-0a4b30c5dacc h1:hhupaJGj8I4LXhWr9lCm5MZLeeTAiuFF+/mesGi1y/8= github.com/crossplane/function-sdk-go v0.0.0-20231016233407-0a4b30c5dacc/go.mod h1:U3UsQAVOCrsUUQAYAyF25PlbSFR2WaLl89dLq58/b2s= github.com/crossplane/function-sdk-go v0.1.0 h1:WN3CUSaj6wgDqQPZZP1whMVIkTAZtN3HVCS67pTMzd8= From 2431b1148eab750bd45bfc52980e8fc334590cf7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Nov 2023 17:23:20 +0000 Subject: [PATCH 2/9] Update k8s.io/utils digest to cf03d44 --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 4b2ffac..07be828 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( k8s.io/api v0.28.3 k8s.io/apiextensions-apiserver v0.28.3 k8s.io/apimachinery v0.28.3 - k8s.io/utils v0.0.0-20230726121419-3b25d923346b + k8s.io/utils v0.0.0-20231121161247-cf03d44ff3cf sigs.k8s.io/controller-tools v0.13.0 ) diff --git a/go.sum b/go.sum index 154f53e..3df4870 100644 --- a/go.sum +++ b/go.sum @@ -653,6 +653,8 @@ k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5Ohx k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20231121161247-cf03d44ff3cf h1:iTzha1p7Fi83476ypNSz8nV9iR9932jIIs26F7gNLsU= +k8s.io/utils v0.0.0-20231121161247-cf03d44ff3cf/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= From adb7dabbc429b23a0357987246357df42d114b1d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Nov 2023 03:08:28 +0000 Subject: [PATCH 3/9] Update kubernetes packages to v0.28.4 --- go.mod | 10 +++++----- go.sum | 10 ++++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 07be828..7149f8b 100644 --- a/go.mod +++ b/go.mod @@ -11,9 +11,9 @@ require ( github.com/google/go-cmp v0.6.0 github.com/pkg/errors v0.9.1 google.golang.org/protobuf v1.31.0 - k8s.io/api v0.28.3 - k8s.io/apiextensions-apiserver v0.28.3 - k8s.io/apimachinery v0.28.3 + k8s.io/api v0.28.4 + k8s.io/apiextensions-apiserver v0.28.4 + k8s.io/apimachinery v0.28.4 k8s.io/utils v0.0.0-20231121161247-cf03d44ff3cf sigs.k8s.io/controller-tools v0.13.0 ) @@ -76,8 +76,8 @@ require ( 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/client-go v0.28.3 // indirect - k8s.io/component-base v0.28.3 // indirect + k8s.io/client-go v0.28.4 // indirect + k8s.io/component-base v0.28.4 // indirect k8s.io/klog/v2 v2.100.1 // indirect k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect sigs.k8s.io/controller-runtime v0.16.3 // indirect diff --git a/go.sum b/go.sum index 3df4870..a4bf477 100644 --- a/go.sum +++ b/go.sum @@ -639,14 +639,24 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.28.3 h1:Gj1HtbSdB4P08C8rs9AR94MfSGpRhJgsS+GF9V26xMM= k8s.io/api v0.28.3/go.mod h1:MRCV/jr1dW87/qJnZ57U5Pak65LGmQVkKTzf3AtKFHc= +k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY= +k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0= k8s.io/apiextensions-apiserver v0.28.3 h1:Od7DEnhXHnHPZG+W9I97/fSQkVpVPQx2diy+2EtmY08= k8s.io/apiextensions-apiserver v0.28.3/go.mod h1:NE1XJZ4On0hS11aWWJUTNkmVB03j9LM7gJSisbRt8Lc= +k8s.io/apiextensions-apiserver v0.28.4 h1:AZpKY/7wQ8n+ZYDtNHbAJBb+N4AXXJvyZx6ww6yAJvU= +k8s.io/apiextensions-apiserver v0.28.4/go.mod h1:pgQIZ1U8eJSMQcENew/0ShUTlePcSGFq6dxSxf2mwPM= k8s.io/apimachinery v0.28.3 h1:B1wYx8txOaCQG0HmYF6nbpU8dg6HvA06x5tEffvOe7A= k8s.io/apimachinery v0.28.3/go.mod h1:uQTKmIqs+rAYaq+DFaoD2X7pcjLOqbQX2AOiO0nIpb8= +k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8= +k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg= k8s.io/client-go v0.28.3 h1:2OqNb72ZuTZPKCl+4gTKvqao0AMOl9f3o2ijbAj3LI4= k8s.io/client-go v0.28.3/go.mod h1:LTykbBp9gsA7SwqirlCXBWtK0guzfhpoW4qSm7i9dxo= +k8s.io/client-go v0.28.4 h1:Np5ocjlZcTrkyRJ3+T3PkXDpe4UpatQxj85+xjaD2wY= +k8s.io/client-go v0.28.4/go.mod h1:0VDZFpgoZfelyP5Wqu0/r/TRYcLYuJ2U1KEeoaPa1N4= k8s.io/component-base v0.28.3 h1:rDy68eHKxq/80RiMb2Ld/tbH8uAE75JdCqJyi6lXMzI= k8s.io/component-base v0.28.3/go.mod h1:fDJ6vpVNSk6cRo5wmDa6eKIG7UlIQkaFmZN2fYgIUD8= +k8s.io/component-base v0.28.4 h1:c/iQLWPdUgI90O+T9TeECg8o7N3YJTiuz2sKxILYcYo= +k8s.io/component-base v0.28.4/go.mod h1:m9hR0uvqXDybiGL2nf/3Lf0MerAfQXzkfWhUY58JUbU= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= From 873f26b034a9934de34cb6674e4a44bf0ac6442b Mon Sep 17 00:00:00 2001 From: Philippe Scorsolini Date: Thu, 23 Nov 2023 10:28:04 +0100 Subject: [PATCH 4/9] fix: run patches in order for composed resources Signed-off-by: Philippe Scorsolini --- fn.go | 55 ++++++------------------------------------ fn_test.go | 2 +- render.go | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 48 deletions(-) diff --git a/fn.go b/fn.go index 7161787..0bc758f 100644 --- a/fn.go +++ b/fn.go @@ -196,58 +196,19 @@ func (f *Function) RunFunction(ctx context.Context, req *fnv1beta1.RunFunctionRe log.Debug("Found corresponding observed resource", "ready", ready, "name", ocd.Resource.GetName()) - - // TODO(negz): Should failures to patch the XR be terminal? It could - // indicate a required patch failed. A required patch means roughly - // "this patch has to succeed before you mutate the resource". This - // is useful to make sure we never create a composed resource in the - // wrong state. It's less clear how useful it is for the XR, given - // we'll only ever be updating it, not creating it. - - // We want to patch the XR from observed composed resources, not - // from desired state. This is because folks will typically be - // patching from a field that is set once the observed resource is - // applied such as its status. - if err := RenderToCompositePatches(dxr.Resource, ocd.Resource, t.Patches); err != nil { - response.Warning(rsp, errors.Wrapf(err, "cannot render ToComposite patches for composed resource %q", t.Name)) - log.Info("Cannot render ToComposite patches for composed resource", "warning", err) - warnings++ - } - - // TODO(negz): Same as above, but for the Environment. What does it - // mean for a required patch to the environment to fail? Should it - // be terminal? - - // Run all patches that are from the (observed) composed resource to - // the environment. - if err := RenderToEnvironmentPatches(env, ocd.Resource, t.Patches); err != nil { - response.Warning(rsp, errors.Wrapf(err, "cannot render ToEnvironment patches for composed resource %q", t.Name)) - log.Info("Cannot render ToEnvironment patches for composed resource", "warning", err) - warnings++ - } } - // If either of the below renderings return an error, most likely a - // required FromComposite or FromEnvironment patch failed. A required - // patch means roughly "this patch has to succeed before you mutate the - // resource." This is useful to make sure we never create a composed - // resource in the wrong state. To that end, we don't want to add this - // resource to our accumulated desired state. - if err := RenderFromCompositePatches(dcd.Resource, oxr.Resource, t.Patches); err != nil { - response.Warning(rsp, errors.Wrapf(err, "cannot render FromComposite patches for composed resource %q", t.Name)) - log.Info("Cannot render FromComposite patches for composed resource", "warning", err) + errs, store := RenderComposedPatches(ocd.Resource, dcd.Resource, oxr.Resource, dxr.Resource, env, t.Patches) + for _, err := range errs { + response.Warning(rsp, errors.Wrapf(err, "cannot render patches for composed resource %q", t.Name)) + log.Info("Cannot render patches for composed resource", "warning", err) warnings++ - continue - } - if err := RenderFromEnvironmentPatches(dcd.Resource, env, t.Patches); err != nil { - response.Warning(rsp, errors.Wrapf(err, "cannot render FromEnvironment patches for composed resource %q", t.Name)) - log.Info("Cannot render FromEnvironment patches for composed resource", "warning", err) - warnings++ - continue } - // Add or replace our desired resource. - desired[resource.Name(t.Name)] = dcd + if store { + // Add or replace our desired resource. + desired[resource.Name(t.Name)] = dcd + } } if err := response.SetDesiredCompositeResource(rsp, dxr); err != nil { diff --git a/fn_test.go b/fn_test.go index ea1fa3e..78a25d1 100644 --- a/fn_test.go +++ b/fn_test.go @@ -447,7 +447,7 @@ func TestRunFunction(t *testing.T) { Results: []*fnv1beta1.Result{ { Severity: fnv1beta1.Severity_SEVERITY_WARNING, - Message: fmt.Sprintf("cannot render FromComposite patches for composed resource %q: cannot apply the %q patch at index 1: spec.doesNotExist: no such field", "cool-resource", "FromCompositeFieldPath"), + Message: fmt.Sprintf("cannot render patches for composed resource %q: cannot apply the %q patch at index 1: spec.doesNotExist: no such field", "cool-resource", "FromCompositeFieldPath"), }, }, Context: &structpb.Struct{Fields: map[string]*structpb.Value{fncontext.KeyEnvironment: structpb.NewStructValue(nil)}}, diff --git a/render.go b/render.go index e1669b2..56a5c74 100644 --- a/render.go +++ b/render.go @@ -9,6 +9,9 @@ import ( "github.com/crossplane/crossplane-runtime/pkg/errors" "github.com/crossplane/crossplane-runtime/pkg/resource" + "github.com/crossplane/function-sdk-go/resource/composed" + "github.com/crossplane/function-sdk-go/resource/composite" + "github.com/crossplane-contrib/function-patch-and-transform/input/v1beta1" ) @@ -102,3 +105,71 @@ func RenderToEnvironmentPatches(env *unstructured.Unstructured, o runtime.Object } return nil } + +// RenderComposedPatches renders the supplied composed resource by applying all +// patches that are to or from the supplied composite resource and environment +// in the order they were defined. Properly selecting the right source or +// destination between observed and desired resources. +func RenderComposedPatches( //nolint:gocyclo // just a switch + ocd *composed.Unstructured, + dcd *composed.Unstructured, + oxr *composite.Unstructured, + dxr *composite.Unstructured, + env *unstructured.Unstructured, + ps []v1beta1.Patch, +) (errs []error, store bool) { + for i, p := range ps { + switch t := p.Type; t { + case v1beta1.PatchTypeToCompositeFieldPath, v1beta1.PatchTypeCombineToComposite: + // TODO(negz): Should failures to patch the XR be terminal? It could + // indicate a required patch failed. A required patch means roughly + // "this patch has to succeed before you mutate the resource". This + // is useful to make sure we never create a composed resource in the + // wrong state. It's less clear how useful it is for the XR, given + // we'll only ever be updating it, not creating it. + + // We want to patch the XR from observed composed resources, not + // from desired state. This is because folks will typically be + // patching from a field that is set once the observed resource is + // applied such as its status. + if ocd == nil { + continue + } + if err := ApplyToObjects(p, dxr, ocd); err != nil { + errs = append(errs, errors.Wrapf(err, errFmtPatch, t, i)) + } + case v1beta1.PatchTypeToEnvironmentFieldPath, v1beta1.PatchTypeCombineToEnvironment: + // TODO(negz): Same as above, but for the Environment. What does it + // mean for a required patch to the environment to fail? Should it + // be terminal? + + // Run all patches that are from the (observed) composed resource to + // the environment. + if ocd == nil { + continue + } + if err := ApplyToObjects(p, env, ocd); err != nil { + errs = append(errs, errors.Wrapf(err, errFmtPatch, t, i)) + } + // If either of the below renderings return an error, most likely a + // required FromComposite or FromEnvironment patch failed. A required + // patch means roughly "this patch has to succeed before you mutate the + // resource." This is useful to make sure we never create a composed + // resource in the wrong state. To that end, we don't want to add this + // resource to our accumulated desired state. + case v1beta1.PatchTypeFromCompositeFieldPath, v1beta1.PatchTypeCombineFromComposite: + if err := ApplyToObjects(p, oxr, dcd); err != nil { + errs = append(errs, errors.Wrapf(err, errFmtPatch, t, i)) + return errs, false + } + case v1beta1.PatchTypeFromEnvironmentFieldPath, v1beta1.PatchTypeCombineFromEnvironment: + if err := ApplyToObjects(p, env, dcd); err != nil { + errs = append(errs, errors.Wrapf(err, errFmtPatch, t, i)) + return errs, false + } + case v1beta1.PatchTypePatchSet: + // Already resolved - nothing to do. + } + } + return errs, true +} From 7fb1c722974c1ac8e7f1077a119f8c2a2f6069f9 Mon Sep 17 00:00:00 2001 From: Philippe Scorsolini Date: Thu, 23 Nov 2023 16:54:46 +0100 Subject: [PATCH 5/9] refactor: run environment patches in order Signed-off-by: Philippe Scorsolini --- fn.go | 10 +---- go.sum | 129 +++++++++++++++++++++++++++++++++++------------------- render.go | 57 +++++++----------------- 3 files changed, 101 insertions(+), 95 deletions(-) diff --git a/fn.go b/fn.go index 0bc758f..81727e2 100644 --- a/fn.go +++ b/fn.go @@ -114,17 +114,11 @@ func (f *Function) RunFunction(ctx context.Context, req *fnv1beta1.RunFunctionRe } if input.Environment != nil { - // Run all patches that are from the (observed) XR to the environment. - if err := RenderToEnvironmentPatches(env, oxr.Resource, input.Environment.Patches); err != nil { + // Run all patches that are from the (observed) XR to the environment or from the environment to the (desired) XR. + if err := RenderEnvironmentPatches(env, oxr.Resource, dxr.Resource, input.Environment.Patches); err != nil { response.Fatal(rsp, errors.Wrapf(err, "cannot render ToEnvironment patches from the composite resource")) return rsp, nil } - - // Run all patches that are from the environment to the (desired) XR. - if err := RenderFromEnvironmentPatches(dxr.Resource, env, input.Environment.Patches); err != nil { - response.Fatal(rsp, errors.Wrapf(err, "cannot render FromEnvironment patches to the composite resource")) - return rsp, nil - } } // Increment this if you emit a warning result. diff --git a/go.sum b/go.sum index 6c5ccd7..5c8071d 100644 --- a/go.sum +++ b/go.sum @@ -40,10 +40,20 @@ dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= +github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2ojoH/0= +github.com/alecthomas/assert/v2 v2.1.0/go.mod h1:b/+1DI2Q6NckYi+3mXyH3wFb8qG37K/DuK80n7WefXA= github.com/alecthomas/kong v0.8.1 h1:acZdn3m4lLRobeh3Zi2S2EpnXTd1mOL6U7xVml+vfkY= github.com/alecthomas/kong v0.8.1/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U= github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE= +github.com/alecthomas/repr v0.1.0/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= +github.com/antchfx/htmlquery v1.2.4 h1:qLteofCMe/KGovBI6SQgmou2QNyedFUW+pE+BpeZ494= +github.com/antchfx/htmlquery v1.2.4/go.mod h1:2xO6iu3EVWs7R2JYqBbp8YzG50gj/ofqs5/0VZoDZLc= +github.com/antchfx/xpath v1.2.0 h1:mbwv7co+x0RwgeGAOHdrKy89GvHaGvxxBtPK0uF9Zr8= +github.com/antchfx/xpath v1.2.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= +github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= +github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -59,23 +69,15 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/crossplane/crossplane-runtime v1.13.0 h1:EumInUbS8mXV7otwoI3xa0rPczexJOky4XLVlHxxjO0= -github.com/crossplane/crossplane-runtime v1.13.0/go.mod h1:FuKIC8Mg8hE2gIAMyf2wCPkxkFPz+VnMQiYWBq1/p5A= -github.com/crossplane/crossplane-runtime v1.14.0 h1:MFo93iOJLvYaMCaCoyH2vFWsHebdA1kv3QdOm7hcm5k= -github.com/crossplane/crossplane-runtime v1.14.0/go.mod h1:aOP+5W2wKpvthVs3pFNbVOe1jwrKYbJho0ThGNCVz9o= -github.com/crossplane/crossplane-runtime v1.14.1 h1:TCa7R1N4bDGHjsLhiRxR/mUhwmistlMACHm0kiiYKck= -github.com/crossplane/crossplane-runtime v1.14.1/go.mod h1:aOP+5W2wKpvthVs3pFNbVOe1jwrKYbJho0ThGNCVz9o= github.com/crossplane/crossplane-runtime v1.14.2 h1:pV5JMzyzi/kcbeVBVPCat5MHH8zS94MBUapAyGx/Ry0= github.com/crossplane/crossplane-runtime v1.14.2/go.mod h1:aOP+5W2wKpvthVs3pFNbVOe1jwrKYbJho0ThGNCVz9o= -github.com/crossplane/function-sdk-go v0.0.0-20231016233407-0a4b30c5dacc h1:hhupaJGj8I4LXhWr9lCm5MZLeeTAiuFF+/mesGi1y/8= -github.com/crossplane/function-sdk-go v0.0.0-20231016233407-0a4b30c5dacc/go.mod h1:U3UsQAVOCrsUUQAYAyF25PlbSFR2WaLl89dLq58/b2s= github.com/crossplane/function-sdk-go v0.1.0 h1:WN3CUSaj6wgDqQPZZP1whMVIkTAZtN3HVCS67pTMzd8= github.com/crossplane/function-sdk-go v0.1.0/go.mod h1:oRqHZ6RufpfZJ1N8aT4EfkP+5KpkhOKpWz7SeUDwwcw= +github.com/crossplane/upjet v0.11.0-rc.0.0.20231012093706-c4a76d2a7505 h1:eCmYgfRopVn6r8RM1Ra4XQAPwVsjTGfktBj2Dk7yy+Y= +github.com/crossplane/upjet v0.11.0-rc.0.0.20231012093706-c4a76d2a7505/go.mod h1:Ov+eoYS2n0Zge/E50zm65meOTYbAHnU6jPt27fQrpbc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE= -github.com/emicklei/go-restful/v3 v3.10.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -84,9 +86,12 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= +github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= @@ -97,7 +102,6 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 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.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -110,6 +114,7 @@ github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA= github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -178,21 +183,48 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 h1:pUa4ghanp6q4IJHwE9RwLgmVFfReJN+KbQ8ExNEUUoQ= +github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI= +github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= +github.com/hashicorp/go-hclog v1.2.1 h1:YQsLlGDJgwhXFpucSPyVbCBviQtjlHv3jLTlp8YmtEw= +github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl/v2 v2.14.1 h1:x0BpjfZ+CYdbiz+8yZTQ+gdLO7IXvOut7Da+XJayx34= +github.com/hashicorp/hcl/v2 v2.14.1/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0= +github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/terraform-json v0.14.0 h1:sh9iZ1Y8IFJLx+xQiKHGud6/TSUCM0N8e17dKDpqV7s= +github.com/hashicorp/terraform-json v0.14.0/go.mod h1:5A9HIWPkk4e5aeeXIBbkcOvaZbIYnAIkEyqP2pNSckM= +github.com/hashicorp/terraform-plugin-go v0.14.0 h1:ttnSlS8bz3ZPYbMb84DpcPhY4F5DsQtcAS7cHo8uvP4= +github.com/hashicorp/terraform-plugin-go v0.14.0/go.mod h1:2nNCBeRLaenyQEi78xrGrs9hMbulveqG/zDMQSvVJTE= +github.com/hashicorp/terraform-plugin-log v0.7.0 h1:SDxJUyT8TwN4l5b5/VkiTIaQgY6R+Y2BQ0sRZftGKQs= +github.com/hashicorp/terraform-plugin-log v0.7.0/go.mod h1:p4R1jWBXRTvL4odmEkFfDdhUjHf9zcs/BCoNHAc7IK4= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0 h1:FtCLTiTcykdsURXPt/ku7fYXm3y19nbzbZcUxHx9RbI= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0/go.mod h1:80wf5oad1tW+oLnbXS4UTYmDCrl7BuN1Q+IA91X1a4Y= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= +github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -208,6 +240,7 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -221,6 +254,16 @@ github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPn github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -229,9 +272,13 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 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/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -249,9 +296,8 @@ github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+Pymzi github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= @@ -270,11 +316,25 @@ 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/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.43.0 h1:ycb6ybc1Dauy0DKiuXShbcjuh7GmPJRBjNngd5dluz8= +github.com/upbound/provider-aws v0.43.0/go.mod h1:m7hoCp3D469sk1vaRh8u4hC8SmpPBJO70JrZS9p2H/U= +github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= +github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U= +github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= +github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY= +github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zclconf/go-cty v1.11.0 h1:726SxLdi2SDnjY+BStqB9J1hNp4+2WlzyXLuimibIe0= +github.com/zclconf/go-cty v1.11.0/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -284,6 +344,7 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -333,8 +394,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -380,8 +440,6 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= -golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU= golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -395,7 +453,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -505,15 +564,12 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= 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= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.3.0 h1:8NFhfS6gzxNqjLIYnZxg319wZ5Qjnx4m/CcX+Klzazc= -gomodules.xyz/jsonpatch/v2 v2.3.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -579,8 +635,6 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -599,8 +653,6 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= -google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -625,6 +677,7 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -639,39 +692,25 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.28.3 h1:Gj1HtbSdB4P08C8rs9AR94MfSGpRhJgsS+GF9V26xMM= -k8s.io/api v0.28.3/go.mod h1:MRCV/jr1dW87/qJnZ57U5Pak65LGmQVkKTzf3AtKFHc= k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY= k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0= -k8s.io/apiextensions-apiserver v0.28.3 h1:Od7DEnhXHnHPZG+W9I97/fSQkVpVPQx2diy+2EtmY08= -k8s.io/apiextensions-apiserver v0.28.3/go.mod h1:NE1XJZ4On0hS11aWWJUTNkmVB03j9LM7gJSisbRt8Lc= k8s.io/apiextensions-apiserver v0.28.4 h1:AZpKY/7wQ8n+ZYDtNHbAJBb+N4AXXJvyZx6ww6yAJvU= k8s.io/apiextensions-apiserver v0.28.4/go.mod h1:pgQIZ1U8eJSMQcENew/0ShUTlePcSGFq6dxSxf2mwPM= -k8s.io/apimachinery v0.28.3 h1:B1wYx8txOaCQG0HmYF6nbpU8dg6HvA06x5tEffvOe7A= -k8s.io/apimachinery v0.28.3/go.mod h1:uQTKmIqs+rAYaq+DFaoD2X7pcjLOqbQX2AOiO0nIpb8= k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8= k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg= -k8s.io/client-go v0.28.3 h1:2OqNb72ZuTZPKCl+4gTKvqao0AMOl9f3o2ijbAj3LI4= -k8s.io/client-go v0.28.3/go.mod h1:LTykbBp9gsA7SwqirlCXBWtK0guzfhpoW4qSm7i9dxo= k8s.io/client-go v0.28.4 h1:Np5ocjlZcTrkyRJ3+T3PkXDpe4UpatQxj85+xjaD2wY= k8s.io/client-go v0.28.4/go.mod h1:0VDZFpgoZfelyP5Wqu0/r/TRYcLYuJ2U1KEeoaPa1N4= -k8s.io/component-base v0.28.3 h1:rDy68eHKxq/80RiMb2Ld/tbH8uAE75JdCqJyi6lXMzI= -k8s.io/component-base v0.28.3/go.mod h1:fDJ6vpVNSk6cRo5wmDa6eKIG7UlIQkaFmZN2fYgIUD8= k8s.io/component-base v0.28.4 h1:c/iQLWPdUgI90O+T9TeECg8o7N3YJTiuz2sKxILYcYo= k8s.io/component-base v0.28.4/go.mod h1:m9hR0uvqXDybiGL2nf/3Lf0MerAfQXzkfWhUY58JUbU= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20231121161247-cf03d44ff3cf h1:iTzha1p7Fi83476ypNSz8nV9iR9932jIIs26F7gNLsU= k8s.io/utils v0.0.0-20231121161247-cf03d44ff3cf/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/controller-runtime v0.15.0 h1:ML+5Adt3qZnMSYxZ7gAverBLNPSMQEibtzAgp0UPojU= -sigs.k8s.io/controller-runtime v0.15.0/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4= sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0= sigs.k8s.io/controller-tools v0.13.0 h1:NfrvuZ4bxyolhDBt/rCZhDnx3M2hzlhgo5n3Iv2RykI= @@ -680,7 +719,5 @@ sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMm sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/render.go b/render.go index 56a5c74..44da046 100644 --- a/render.go +++ b/render.go @@ -2,7 +2,6 @@ package main import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/json" @@ -61,46 +60,22 @@ func RenderFromJSON(o resource.Object, data []byte) error { return nil } -// RenderFromCompositePatches renders the supplied composed resource by applying -// all patches that are _from_ the supplied composite resource. -func RenderFromCompositePatches(cd resource.Composed, xr resource.Composite, p []v1beta1.Patch) error { - for i := range p { - if err := Apply(p[i], xr, cd, v1beta1.PatchTypeFromCompositeFieldPath, v1beta1.PatchTypeCombineFromComposite); err != nil { - return errors.Wrapf(err, errFmtPatch, p[i].GetType(), i) - } - } - return nil -} - -// RenderToCompositePatches renders the supplied composite resource by applying -// all patches that are _from_ the supplied composed resource. -func RenderToCompositePatches(xr resource.Composite, cd resource.Composed, p []v1beta1.Patch) error { - for i := range p { - if err := Apply(p[i], xr, cd, v1beta1.PatchTypeToCompositeFieldPath, v1beta1.PatchTypeCombineToComposite); err != nil { - return errors.Wrapf(err, errFmtPatch, p[i].GetType(), i) - } - } - return nil -} - -// RenderFromEnvironmentPatches renders the supplied object (an XR or composed -// resource) by applying all patches that are from the supplied environment. -func RenderFromEnvironmentPatches(o runtime.Object, env *unstructured.Unstructured, p []v1beta1.Patch) error { - for i := range p { - if err := ApplyToObjects(p[i], env, o, v1beta1.PatchTypeFromEnvironmentFieldPath, v1beta1.PatchTypeCombineFromEnvironment); err != nil { - return errors.Wrapf(err, errFmtPatch, p[i].Type, i) - } - } - return nil -} - -// RenderToEnvironmentPatches renders the supplied environment by applying all -// patches that are to the environment, from the supplied object (an XR or -// composed resource). -func RenderToEnvironmentPatches(env *unstructured.Unstructured, o runtime.Object, p []v1beta1.Patch) error { - for i := range p { - if err := ApplyToObjects(p[i], env, o, v1beta1.PatchTypeToEnvironmentFieldPath, v1beta1.PatchTypeCombineToEnvironment); err != nil { - return errors.Wrapf(err, errFmtPatch, p[i].Type, i) +// RenderEnvironmentPatches renders the supplied environment by applying all +// patches that are to the environment, from the supplied XR. +func RenderEnvironmentPatches(env *unstructured.Unstructured, oxr, dxr *composite.Unstructured, ps []v1beta1.Patch) error { + for i, p := range ps { + p := p + switch p.Type { + case v1beta1.PatchTypeToEnvironmentFieldPath, v1beta1.PatchTypeCombineToEnvironment: + if err := ApplyToObjects(p, env, oxr); err != nil { + return errors.Wrapf(err, errFmtPatch, p.Type, i) + } + case v1beta1.PatchTypeFromEnvironmentFieldPath, v1beta1.PatchTypeCombineFromEnvironment: + if err := ApplyToObjects(p, env, dxr); err != nil { + return errors.Wrapf(err, errFmtPatch, p.Type, i) + } + case v1beta1.PatchTypePatchSet, v1beta1.PatchTypeFromCompositeFieldPath, v1beta1.PatchTypeCombineFromComposite, v1beta1.PatchTypeToCompositeFieldPath, v1beta1.PatchTypeCombineToComposite: + // nothing to do } } return nil From 74aefe60226e630e8d71d5f034a215e008b58abb Mon Sep 17 00:00:00 2001 From: Philippe Scorsolini Date: Thu, 23 Nov 2023 17:04:17 +0100 Subject: [PATCH 6/9] fix: correct patches in input CRD Signed-off-by: Philippe Scorsolini --- fn_test.go | 134 ++++--- input/v1beta1/resources_common.go | 16 +- input/v1beta1/resources_patches.go | 110 +++++- input/v1beta1/zz_generated.deepcopy.go | 64 ++- .../input/pt.fn.crossplane.io_resources.yaml | 48 ++- patches.go | 82 ++-- patches_test.go | 365 +++++++++++------- render.go | 17 +- validate.go | 37 +- validate_test.go | 62 +-- 10 files changed, 586 insertions(+), 349 deletions(-) diff --git a/fn_test.go b/fn_test.go index 78a25d1..806038e 100644 --- a/fn_test.go +++ b/fn_test.go @@ -156,23 +156,25 @@ func TestRunFunction(t *testing.T) { { Name: "cool-resource", Base: &runtime.RawExtension{Raw: []byte(`{"apiVersion":"example.org/v1","kind":"CD"}`)}, - Patches: []v1beta1.Patch{ + Patches: []v1beta1.ComposedPatch{ { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("spec.widgets"), - ToFieldPath: ptr.To[string]("spec.watchers"), - Transforms: []v1beta1.Transform{ - { - Type: v1beta1.TransformTypeConvert, - Convert: &v1beta1.ConvertTransform{ - ToType: v1beta1.TransformIOTypeInt64, + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("spec.widgets"), + ToFieldPath: ptr.To[string]("spec.watchers"), + Transforms: []v1beta1.Transform{ + { + Type: v1beta1.TransformTypeConvert, + Convert: &v1beta1.ConvertTransform{ + ToType: v1beta1.TransformIOTypeInt64, + }, }, - }, - { - Type: v1beta1.TransformTypeMath, - Math: &v1beta1.MathTransform{ - Type: v1beta1.MathTransformTypeMultiply, - Multiply: ptr.To[int64](3), + { + Type: v1beta1.TransformTypeMath, + Math: &v1beta1.MathTransform{ + Type: v1beta1.MathTransformTypeMultiply, + Multiply: ptr.To[int64](3), + }, }, }, }, @@ -221,23 +223,25 @@ func TestRunFunction(t *testing.T) { // patch the resource named "cool-resource" in // the desired resources array. Name: "cool-resource", - Patches: []v1beta1.Patch{ + Patches: []v1beta1.ComposedPatch{ { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("spec.widgets"), - ToFieldPath: ptr.To[string]("spec.watchers"), - Transforms: []v1beta1.Transform{ - { - Type: v1beta1.TransformTypeConvert, - Convert: &v1beta1.ConvertTransform{ - ToType: v1beta1.TransformIOTypeInt64, + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("spec.widgets"), + ToFieldPath: ptr.To[string]("spec.watchers"), + Transforms: []v1beta1.Transform{ + { + Type: v1beta1.TransformTypeConvert, + Convert: &v1beta1.ConvertTransform{ + ToType: v1beta1.TransformIOTypeInt64, + }, }, - }, - { - Type: v1beta1.TransformTypeMath, - Math: &v1beta1.MathTransform{ - Type: v1beta1.MathTransformTypeMultiply, - Multiply: ptr.To[int64](3), + { + Type: v1beta1.TransformTypeMath, + Math: &v1beta1.MathTransform{ + Type: v1beta1.MathTransformTypeMultiply, + Multiply: ptr.To[int64](3), + }, }, }, }, @@ -291,11 +295,13 @@ func TestRunFunction(t *testing.T) { // patch the resource named "cool-resource" in // the desired resources array. Name: "cool-resource", - Patches: []v1beta1.Patch{ + Patches: []v1beta1.ComposedPatch{ { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("spec.widgets"), - ToFieldPath: ptr.To[string]("spec.watchers"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("spec.widgets"), + ToFieldPath: ptr.To[string]("spec.watchers"), + }, }, }, }, @@ -387,25 +393,29 @@ func TestRunFunction(t *testing.T) { // patch the resource named "cool-resource" in // the desired resources array. Name: "cool-resource", - Patches: []v1beta1.Patch{ + Patches: []v1beta1.ComposedPatch{ { // This patch should work. - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("spec.widgets"), - ToFieldPath: ptr.To[string]("spec.watchers"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("spec.widgets"), + ToFieldPath: ptr.To[string]("spec.watchers"), + }, }, { // This patch should return an error, // because the required path does not // exist. - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("spec.doesNotExist"), - ToFieldPath: ptr.To[string]("spec.explode"), - Policy: &v1beta1.PatchPolicy{ - FromFieldPath: func() *v1beta1.FromFieldPathPolicy { - r := v1beta1.FromFieldPathPolicyRequired - return &r - }(), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("spec.doesNotExist"), + ToFieldPath: ptr.To[string]("spec.explode"), + Policy: &v1beta1.PatchPolicy{ + FromFieldPath: func() *v1beta1.FromFieldPathPolicy { + r := v1beta1.FromFieldPathPolicyRequired + return &r + }(), + }, }, }, }, @@ -572,23 +582,25 @@ func TestRunFunction(t *testing.T) { { Name: "cool-resource", Base: &runtime.RawExtension{Raw: []byte(`{"apiVersion":"example.org/v1","kind":"CD"}`)}, - Patches: []v1beta1.Patch{ + Patches: []v1beta1.ComposedPatch{ { - Type: v1beta1.PatchTypeToCompositeFieldPath, - FromFieldPath: ptr.To[string]("spec.widgets"), - ToFieldPath: ptr.To[string]("spec.watchers"), - Transforms: []v1beta1.Transform{ - { - Type: v1beta1.TransformTypeConvert, - Convert: &v1beta1.ConvertTransform{ - ToType: v1beta1.TransformIOTypeInt64, + Type: v1beta1.PatchTypeToCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("spec.widgets"), + ToFieldPath: ptr.To[string]("spec.watchers"), + Transforms: []v1beta1.Transform{ + { + Type: v1beta1.TransformTypeConvert, + Convert: &v1beta1.ConvertTransform{ + ToType: v1beta1.TransformIOTypeInt64, + }, }, - }, - { - Type: v1beta1.TransformTypeMath, - Math: &v1beta1.MathTransform{ - Type: v1beta1.MathTransformTypeMultiply, - Multiply: ptr.To[int64](3), + { + Type: v1beta1.TransformTypeMath, + Math: &v1beta1.MathTransform{ + Type: v1beta1.MathTransformTypeMultiply, + Multiply: ptr.To[int64](3), + }, }, }, }, diff --git a/input/v1beta1/resources_common.go b/input/v1beta1/resources_common.go index abed367..c1d750b 100644 --- a/input/v1beta1/resources_common.go +++ b/input/v1beta1/resources_common.go @@ -28,7 +28,19 @@ type PatchSet struct { Name string `json:"name"` // Patches will be applied as an overlay to the base resource. - Patches []Patch `json:"patches"` + Patches []PatchSetPatch `json:"patches"` +} + +// GetComposedPatches returns the composed patches from the patch set. +func (ps *PatchSet) GetComposedPatches() []ComposedPatch { + out := make([]ComposedPatch, len(ps.Patches)) + for i, p := range ps.Patches { + out[i] = ComposedPatch{ + Type: p.GetType(), + Patch: p.Patch, + } + } + return out } // ComposedTemplate is used to provide information about how the composed @@ -49,7 +61,7 @@ type ComposedTemplate struct { // Patches to and from the composed resource. // +optional - Patches []Patch `json:"patches,omitempty"` + Patches []ComposedPatch `json:"patches,omitempty"` // ConnectionDetails lists the propagation secret keys from this composed // resource to the composition instance connection secret. diff --git a/input/v1beta1/resources_patches.go b/input/v1beta1/resources_patches.go index 8924362..9478a79 100644 --- a/input/v1beta1/resources_patches.go +++ b/input/v1beta1/resources_patches.go @@ -57,21 +57,91 @@ type Environment struct { // composition's resources are composed. These patches are between the XR // and the Environment. Either from the Environment to the XR, or vice // versa. - Patches []Patch `json:"patches,omitempty"` + Patches []EnvironmentPatch `json:"patches,omitempty"` } -// Patch objects are applied between composite and composed resources. Their -// behaviour depends on the Type selected. The default Type, -// FromCompositeFieldPath, copies a value from the composite resource to -// the composed resource, applying any defined transformers. -type Patch struct { +// EnvironmentPatch objects are applied between the composite resource and +// the environment. Their behaviour depends on the Type selected. The default +// Type, FromCompositeFieldPath, copies a value from the composite resource +// to the environment, applying any defined transformers. +type EnvironmentPatch struct { // Type sets the patching behaviour to be used. Each patch type may require // its own fields to be set on the Patch object. // +optional - // +kubebuilder:validation:Enum=FromCompositeFieldPath;PatchSet;ToCompositeFieldPath;CombineFromComposite;CombineToComposite + // +kubebuilder:validation:Enum=FromCompositeFieldPath;ToCompositeFieldPath;CombineFromComposite;CombineToComposite // +kubebuilder:default=FromCompositeFieldPath Type PatchType `json:"type,omitempty"` + Patch `json:",inline"` +} + +// GetType returns the patch type. If the type is not set, it returns the default type. +func (ep *EnvironmentPatch) GetType() PatchType { + if ep.Type == "" { + return PatchTypeFromCompositeFieldPath + } + return ep.Type +} + +// ComposedPatch objects are applied between composite and composed resources. +// Their behaviour depends on the Type selected. The default Type, +// FromCompositeFieldPath, copies a value from the composite resource to the +// composed resource, applying any defined transformers. +type ComposedPatch struct { + // Type sets the patching behaviour to be used. Each patch type may require + // its own fields to be set on the ComposedPatch object. + // +optional + // +kubebuilder:validation:Enum=FromCompositeFieldPath;PatchSet;ToCompositeFieldPath;CombineFromComposite;CombineToComposite;FromEnvironmentFieldPath;ToEnvironmentFieldPath;CombineFromEnvironment;CombineToEnvironment + // +kubebuilder:default=FromCompositeFieldPath + Type PatchType `json:"type,omitempty"` + + // PatchSetName to include patches from. Required when type is PatchSet. + // +optional + PatchSetName *string `json:"patchSetName,omitempty"` + + Patch `json:",inline"` +} + +// GetType returns the patch type. If the type is not set, it returns the default type. +func (p *ComposedPatch) GetType() PatchType { + if p.Type == "" { + return PatchTypeFromCompositeFieldPath + } + return p.Type +} + +// GetPatchSetName returns the PatchSetName for this ComposedPatch, or an empty +// string if it is nil. +func (p *ComposedPatch) GetPatchSetName() string { + if p.PatchSetName == nil { + return "" + } + return *p.PatchSetName +} + +// PatchSetPatch defines a set of Patches that can be referenced by name by +// other patches of type PatchSet. +type PatchSetPatch struct { + // Type sets the patching behaviour to be used. Each patch type may require + // its own fields to be set on the ComposedPatch object. + // +optional + // +kubebuilder:validation:Enum=FromCompositeFieldPath;ToCompositeFieldPath;CombineFromComposite;CombineToComposite;FromEnvironmentFieldPath;ToEnvironmentFieldPath;CombineFromEnvironment;CombineToEnvironment + // +kubebuilder:default=FromCompositeFieldPath + Type PatchType `json:"type,omitempty"` + + Patch `json:",inline"` +} + +// GetType returns the patch type. If the type is not set, it returns the default type. +func (psp *PatchSetPatch) GetType() PatchType { + if psp.Type == "" { + return PatchTypeFromCompositeFieldPath + } + return psp.Type +} + +// Patch defines a patch between a source and destination. +type Patch struct { // FromFieldPath is the path of the field on the resource whose value is // to be used as input. Required when type is FromCompositeFieldPath or // ToCompositeFieldPath. @@ -89,10 +159,6 @@ type Patch struct { // +optional ToFieldPath *string `json:"toFieldPath,omitempty"` - // PatchSetName to include patches from. Required when type is PatchSet. - // +optional - PatchSetName *string `json:"patchSetName,omitempty"` - // Transforms are the list of functions that are used as a FIFO pipe for the // input to be transformed. // +optional @@ -114,17 +180,25 @@ func (p *Patch) GetFromFieldPath() string { // GetToFieldPath returns the ToFieldPath for this Patch, or an empty string if it is nil. func (p *Patch) GetToFieldPath() string { if p.ToFieldPath == nil { - return "" + // Default to patching the same field on the composed resource. + return p.GetFromFieldPath() } return *p.ToFieldPath } -// GetType returns the patch type. If the type is not set, it returns the default type. -func (p *Patch) GetType() PatchType { - if p.Type == "" { - return PatchTypeFromCompositeFieldPath - } - return p.Type +// GetCombine returns the Combine for this ComposedPatch, or nil if it is nil. +func (p *Patch) GetCombine() *Combine { + return p.Combine +} + +// GetTransforms returns the Transforms for this ComposedPatch, or nil if it is nil. +func (p *Patch) GetTransforms() []Transform { + return p.Transforms +} + +// GetPolicy returns the PatchPolicy for this ComposedPatch, or nil if it is nil. +func (p *Patch) GetPolicy() *PatchPolicy { + return p.Policy } // A CombineVariable defines the source of a value that is combined with diff --git a/input/v1beta1/zz_generated.deepcopy.go b/input/v1beta1/zz_generated.deepcopy.go index fa224c5..5787099 100644 --- a/input/v1beta1/zz_generated.deepcopy.go +++ b/input/v1beta1/zz_generated.deepcopy.go @@ -49,6 +49,27 @@ func (in *CombineVariable) DeepCopy() *CombineVariable { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComposedPatch) DeepCopyInto(out *ComposedPatch) { + *out = *in + if in.PatchSetName != nil { + in, out := &in.PatchSetName, &out.PatchSetName + *out = new(string) + **out = **in + } + in.Patch.DeepCopyInto(&out.Patch) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComposedPatch. +func (in *ComposedPatch) DeepCopy() *ComposedPatch { + if in == nil { + return nil + } + out := new(ComposedPatch) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ComposedTemplate) DeepCopyInto(out *ComposedTemplate) { *out = *in @@ -59,7 +80,7 @@ func (in *ComposedTemplate) DeepCopyInto(out *ComposedTemplate) { } if in.Patches != nil { in, out := &in.Patches, &out.Patches - *out = make([]Patch, len(*in)) + *out = make([]ComposedPatch, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -145,7 +166,7 @@ func (in *Environment) DeepCopyInto(out *Environment) { *out = *in if in.Patches != nil { in, out := &in.Patches, &out.Patches - *out = make([]Patch, len(*in)) + *out = make([]EnvironmentPatch, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -162,6 +183,22 @@ func (in *Environment) DeepCopy() *Environment { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnvironmentPatch) DeepCopyInto(out *EnvironmentPatch) { + *out = *in + in.Patch.DeepCopyInto(&out.Patch) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvironmentPatch. +func (in *EnvironmentPatch) DeepCopy() *EnvironmentPatch { + if in == nil { + return nil + } + out := new(EnvironmentPatch) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MapTransform) DeepCopyInto(out *MapTransform) { *out = *in @@ -296,11 +333,6 @@ func (in *Patch) DeepCopyInto(out *Patch) { *out = new(string) **out = **in } - if in.PatchSetName != nil { - in, out := &in.PatchSetName, &out.PatchSetName - *out = new(string) - **out = **in - } if in.Transforms != nil { in, out := &in.Transforms, &out.Transforms *out = make([]Transform, len(*in)) @@ -350,7 +382,7 @@ func (in *PatchSet) DeepCopyInto(out *PatchSet) { *out = *in if in.Patches != nil { in, out := &in.Patches, &out.Patches - *out = make([]Patch, len(*in)) + *out = make([]PatchSetPatch, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -367,6 +399,22 @@ func (in *PatchSet) DeepCopy() *PatchSet { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PatchSetPatch) DeepCopyInto(out *PatchSetPatch) { + *out = *in + in.Patch.DeepCopyInto(&out.Patch) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PatchSetPatch. +func (in *PatchSetPatch) DeepCopy() *PatchSetPatch { + if in == nil { + return nil + } + out := new(PatchSetPatch) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ReadinessCheck) DeepCopyInto(out *ReadinessCheck) { *out = *in diff --git a/package/input/pt.fn.crossplane.io_resources.yaml b/package/input/pt.fn.crossplane.io_resources.yaml index 9751e43..1b68e97 100644 --- a/package/input/pt.fn.crossplane.io_resources.yaml +++ b/package/input/pt.fn.crossplane.io_resources.yaml @@ -37,10 +37,11 @@ spec: between the XR and the Environment. Either from the Environment to the XR, or vice versa. items: - description: Patch objects are applied between composite and composed - resources. Their behaviour depends on the Type selected. The default - Type, FromCompositeFieldPath, copies a value from the composite - resource to the composed resource, applying any defined transformers. + description: EnvironmentPatch objects are applied between the composite + resource and the environment. Their behaviour depends on the Type + selected. The default Type, FromCompositeFieldPath, copies a value + from the composite resource to the environment, applying any defined + transformers. properties: combine: description: Combine is the patch configuration for a CombineFromComposite, @@ -91,10 +92,6 @@ spec: whose value is to be used as input. Required when type is FromCompositeFieldPath or ToCompositeFieldPath. type: string - patchSetName: - description: PatchSetName to include patches from. Required - when type is PatchSet. - type: string policy: description: Policy configures the specifics of patching behaviour. properties: @@ -322,7 +319,6 @@ spec: object. enum: - FromCompositeFieldPath - - PatchSet - ToCompositeFieldPath - CombineFromComposite - CombineToComposite @@ -350,11 +346,8 @@ spec: patches: description: Patches will be applied as an overlay to the base resource. items: - description: Patch objects are applied between composite and composed - resources. Their behaviour depends on the Type selected. The - default Type, FromCompositeFieldPath, copies a value from the - composite resource to the composed resource, applying any defined - transformers. + description: PatchSetPatch defines a set of Patches that can be + referenced by name by other patches of type PatchSet. properties: combine: description: Combine is the patch configuration for a CombineFromComposite, @@ -406,10 +399,6 @@ spec: resource whose value is to be used as input. Required when type is FromCompositeFieldPath or ToCompositeFieldPath. type: string - patchSetName: - description: PatchSetName to include patches from. Required - when type is PatchSet. - type: string policy: description: Policy configures the specifics of patching behaviour. properties: @@ -638,13 +627,16 @@ spec: default: FromCompositeFieldPath description: Type sets the patching behaviour to be used. Each patch type may require its own fields to be set on - the Patch object. + the ComposedPatch object. enum: - FromCompositeFieldPath - - PatchSet - ToCompositeFieldPath - CombineFromComposite - CombineToComposite + - FromEnvironmentFieldPath + - ToEnvironmentFieldPath + - CombineFromEnvironment + - CombineToEnvironment type: string type: object type: array @@ -720,11 +712,11 @@ spec: patches: description: Patches to and from the composed resource. items: - description: Patch objects are applied between composite and composed - resources. Their behaviour depends on the Type selected. The - default Type, FromCompositeFieldPath, copies a value from the - composite resource to the composed resource, applying any defined - transformers. + description: ComposedPatch objects are applied between composite + and composed resources. Their behaviour depends on the Type + selected. The default Type, FromCompositeFieldPath, copies a + value from the composite resource to the composed resource, + applying any defined transformers. properties: combine: description: Combine is the patch configuration for a CombineFromComposite, @@ -1008,13 +1000,17 @@ spec: default: FromCompositeFieldPath description: Type sets the patching behaviour to be used. Each patch type may require its own fields to be set on - the Patch object. + the ComposedPatch object. enum: - FromCompositeFieldPath - PatchSet - ToCompositeFieldPath - CombineFromComposite - CombineToComposite + - FromEnvironmentFieldPath + - ToEnvironmentFieldPath + - CombineFromEnvironment + - CombineToEnvironment type: string type: object type: array diff --git a/patches.go b/patches.go index 3ac372f..efe1056 100644 --- a/patches.go +++ b/patches.go @@ -25,16 +25,32 @@ const ( errFmtExpandingArrayFieldPaths = "cannot expand ToFieldPath %s" ) +// A PatchInterface is a patch that can be applied between resources. +type PatchInterface interface { + GetType() v1beta1.PatchType + GetFromFieldPath() string + GetToFieldPath() string + GetCombine() *v1beta1.Combine + GetTransforms() []v1beta1.Transform + GetPolicy() *v1beta1.PatchPolicy +} + +// PatchWithPatchSetName is a PatchInterface that has a PatchSetName field. +type PatchWithPatchSetName interface { + PatchInterface + GetPatchSetName() string +} + // Apply executes a patching operation between the from and to resources. // Applies all patch types unless an 'only' filter is supplied. -func Apply(p v1beta1.Patch, xr resource.Composite, cd resource.Composed, only ...v1beta1.PatchType) error { +func Apply(p PatchInterface, xr resource.Composite, cd resource.Composed, only ...v1beta1.PatchType) error { return ApplyToObjects(p, xr, cd, only...) } // ApplyToObjects works like Apply but accepts any kind of runtime.Object. It // might be vulnerable to conversion panics (see // https://github.com/crossplane/crossplane/pull/3394 for details). -func ApplyToObjects(p v1beta1.Patch, a, b runtime.Object, only ...v1beta1.PatchType) error { +func ApplyToObjects(p PatchInterface, a, b runtime.Object, only ...v1beta1.PatchType) error { if filterPatch(p, only...) { return nil } @@ -51,11 +67,11 @@ func ApplyToObjects(p v1beta1.Patch, a, b runtime.Object, only ...v1beta1.PatchT case v1beta1.PatchTypePatchSet: // Already resolved - nothing to do. } - return errors.Errorf(errFmtInvalidPatchType, p.Type) + return errors.Errorf(errFmtInvalidPatchType, p.GetType()) } // filterPatch returns true if patch should be filtered (not applied) -func filterPatch(p v1beta1.Patch, only ...v1beta1.PatchType) bool { +func filterPatch(p PatchInterface, only ...v1beta1.PatchType) bool { // filter does not apply if not set if len(only) == 0 { return false @@ -70,9 +86,9 @@ func filterPatch(p v1beta1.Patch, only ...v1beta1.PatchType) bool { } // ResolveTransforms applies a list of transforms to a patch value. -func ResolveTransforms(c v1beta1.Patch, input any) (any, error) { +func ResolveTransforms(ts []v1beta1.Transform, input any) (any, error) { var err error - for i, t := range c.Transforms { + for i, t := range ts { if input, err = Resolve(t, input); err != nil { // TODO(negz): Including the type might help find the offending transform faster. return nil, errors.Wrapf(err, errFmtTransformAtIndex, i) @@ -84,14 +100,9 @@ func ResolveTransforms(c v1beta1.Patch, input any) (any, error) { // ApplyFromFieldPathPatch patches the "to" resource, using a source field // on the "from" resource. Values may be transformed if any are defined on // the patch. -func ApplyFromFieldPathPatch(p v1beta1.Patch, from, to runtime.Object) error { - if p.FromFieldPath == nil { - return errors.Errorf(errFmtRequiredField, "FromFieldPath", p.Type) - } - - // Default to patching the same field on the composed resource. - if p.ToFieldPath == nil { - p.ToFieldPath = p.FromFieldPath +func ApplyFromFieldPathPatch(p PatchInterface, from, to runtime.Object) error { + if p.GetFromFieldPath() == "" { + return errors.Errorf(errFmtRequiredField, "FromFieldPath", p.GetType()) } fromMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(from) @@ -99,8 +110,8 @@ func ApplyFromFieldPathPatch(p v1beta1.Patch, from, to runtime.Object) error { return err } - in, err := fieldpath.Pave(fromMap).GetValue(*p.FromFieldPath) - if IsOptionalFieldPathNotFound(err, p.Policy) { + in, err := fieldpath.Pave(fromMap).GetValue(p.GetFromFieldPath()) + if IsOptionalFieldPathNotFound(err, p.GetPolicy()) { return nil } if err != nil { @@ -108,35 +119,36 @@ func ApplyFromFieldPathPatch(p v1beta1.Patch, from, to runtime.Object) error { } // Apply transform pipeline - out, err := ResolveTransforms(p, in) + out, err := ResolveTransforms(p.GetTransforms(), in) if err != nil { return err } - // Patch all expanded fields if the ToFieldPath contains wildcards - if strings.Contains(*p.ToFieldPath, "[*]") { - return patchFieldValueToMultiple(*p.ToFieldPath, out, to) + // ComposedPatch all expanded fields if the ToFieldPath contains wildcards + if strings.Contains(p.GetToFieldPath(), "[*]") { + return patchFieldValueToMultiple(p.GetToFieldPath(), out, to) } - return errors.Wrap(patchFieldValueToObject(*p.ToFieldPath, out, to), "cannot patch to object") + return errors.Wrap(patchFieldValueToObject(p.GetToFieldPath(), out, to), "cannot patch to object") } // ApplyCombineFromVariablesPatch patches the "to" resource, taking a list of // input variables and combining them into a single output value. // The single output value may then be further transformed if they are defined // on the patch. -func ApplyCombineFromVariablesPatch(p v1beta1.Patch, from, to runtime.Object) error { +func ApplyCombineFromVariablesPatch(p PatchInterface, from, to runtime.Object) error { // Combine patch requires configuration - if p.Combine == nil { - return errors.Errorf(errFmtRequiredField, "Combine", p.Type) + if p.GetCombine() == nil { + return errors.Errorf(errFmtRequiredField, "Combine", p.GetType()) } // Destination field path is required since we can't default to multiple // fields. - if p.ToFieldPath == nil { - return errors.Errorf(errFmtRequiredField, "ToFieldPath", p.Type) + if p.GetToFieldPath() == "" { + return errors.Errorf(errFmtRequiredField, "ToFieldPath", p.GetType()) } - vl := len(p.Combine.Variables) + combine := p.GetCombine() + vl := len(combine.Variables) if vl < 1 { return errors.New(errCombineRequiresVariables) @@ -153,7 +165,7 @@ func ApplyCombineFromVariablesPatch(p v1beta1.Patch, from, to runtime.Object) er // NOTE: This currently assumes all variables define a 'fromFieldPath' // value. If we add new variable types, this may not be the case and // this code may be better served split out into a dedicated function. - for i, sp := range p.Combine.Variables { + for i, sp := range combine.Variables { iv, err := fieldpath.Pave(fromMap).GetValue(sp.FromFieldPath) // If any source field is not found, we will not @@ -162,7 +174,7 @@ func ApplyCombineFromVariablesPatch(p v1beta1.Patch, from, to runtime.Object) er // number of inputs (e.g. a string format // expecting 3 fields '%s-%s-%s' but only // receiving 2 values). - if IsOptionalFieldPathNotFound(err, p.Policy) { + if IsOptionalFieldPathNotFound(err, p.GetPolicy()) { return nil } if err != nil { @@ -172,18 +184,18 @@ func ApplyCombineFromVariablesPatch(p v1beta1.Patch, from, to runtime.Object) er } // Combine input values - cb, err := Combine(*p.Combine, in) + cb, err := Combine(*p.GetCombine(), in) if err != nil { return err } // Apply transform pipeline - out, err := ResolveTransforms(p, cb) + out, err := ResolveTransforms(p.GetTransforms(), cb) if err != nil { return err } - return errors.Wrap(patchFieldValueToObject(*p.ToFieldPath, out, to), "cannot patch to object") + return errors.Wrap(patchFieldValueToObject(p.GetToFieldPath(), out, to), "cannot patch to object") } // IsOptionalFieldPathNotFound returns true if the supplied error indicates a @@ -231,19 +243,19 @@ func CombineString(format string, vars []any) string { // ComposedTemplates returns the supplied composed resource templates with any // supplied patchsets dereferenced. func ComposedTemplates(pss []v1beta1.PatchSet, cts []v1beta1.ComposedTemplate) ([]v1beta1.ComposedTemplate, error) { - pn := make(map[string][]v1beta1.Patch) + pn := make(map[string][]v1beta1.ComposedPatch) for _, s := range pss { for _, p := range s.Patches { if p.Type == v1beta1.PatchTypePatchSet { return nil, errors.New(errPatchSetType) } } - pn[s.Name] = s.Patches + pn[s.Name] = s.GetComposedPatches() } ct := make([]v1beta1.ComposedTemplate, len(cts)) for i, r := range cts { - var po []v1beta1.Patch + var po []v1beta1.ComposedPatch for _, p := range r.Patches { if p.Type != v1beta1.PatchTypePatchSet { po = append(po, p) diff --git a/patches_test.go b/patches_test.go index b6f6986..a98f158 100644 --- a/patches_test.go +++ b/patches_test.go @@ -28,7 +28,7 @@ func TestPatchApply(t *testing.T) { } type args struct { - patch v1beta1.Patch + patch v1beta1.ComposedPatch xr *composite.Unstructured cd *composed.Unstructured only []v1beta1.PatchType @@ -47,7 +47,7 @@ func TestPatchApply(t *testing.T) { "InvalidCompositeFieldPathPatch": { reason: "Should return error when required fields not passed to applyFromFieldPathPatch", args: args{ - patch: v1beta1.Patch{ + patch: v1beta1.ComposedPatch{ Type: v1beta1.PatchTypeFromCompositeFieldPath, // This is missing fields. }, @@ -61,7 +61,7 @@ func TestPatchApply(t *testing.T) { "Invalidv1.PatchType": { reason: "Should return an error if an invalid patch type is specified", args: args{ - patch: v1beta1.Patch{ + patch: v1beta1.ComposedPatch{ Type: "invalid-patchtype", }, xr: &composite.Unstructured{}, @@ -74,10 +74,12 @@ func TestPatchApply(t *testing.T) { "ValidCompositeFieldPathPatch": { reason: "Should correctly apply a CompositeFieldPathPatch with valid settings", args: args{ - patch: v1beta1.Patch{ - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.labels"), - ToFieldPath: ptr.To[string]("metadata.labels"), + patch: v1beta1.ComposedPatch{ + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.labels"), + ToFieldPath: ptr.To[string]("metadata.labels"), + }, }, xr: &composite.Unstructured{ Unstructured: unstructured.Unstructured{Object: MustObject(`{ @@ -119,10 +121,12 @@ func TestPatchApply(t *testing.T) { "ValidCompositeFieldPathPatchWithWildcards": { reason: "When passed a wildcarded path, adds a field to each element of an array", args: args{ - patch: v1beta1.Patch{ - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.name"), - ToFieldPath: ptr.To[string]("metadata.ownerReferences[*].name"), + patch: v1beta1.ComposedPatch{ + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.name"), + ToFieldPath: ptr.To[string]("metadata.ownerReferences[*].name"), + }, }, xr: &composite.Unstructured{ Unstructured: unstructured.Unstructured{Object: MustObject(`{ @@ -172,10 +176,12 @@ func TestPatchApply(t *testing.T) { "InvalidCompositeFieldPathPatchWithWildcards": { reason: "When passed a wildcarded path, throws an error if ToFieldPath cannot be expanded", args: args{ - patch: v1beta1.Patch{ - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.name"), - ToFieldPath: ptr.To[string]("metadata.ownerReferences[*].badField"), + patch: v1beta1.ComposedPatch{ + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.name"), + ToFieldPath: ptr.To[string]("metadata.ownerReferences[*].badField"), + }, }, xr: &composite.Unstructured{ Unstructured: unstructured.Unstructured{Object: MustObject(`{ @@ -210,10 +216,12 @@ func TestPatchApply(t *testing.T) { "MissingOptionalFieldPath": { reason: "A FromFieldPath patch should be a no-op when an optional fromFieldPath doesn't exist", args: args{ - patch: v1beta1.Patch{ - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.labels"), - ToFieldPath: ptr.To[string]("metadata.labels"), + patch: v1beta1.ComposedPatch{ + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.labels"), + ToFieldPath: ptr.To[string]("metadata.labels"), + }, }, xr: &composite.Unstructured{ Unstructured: unstructured.Unstructured{Object: MustObject(`{ @@ -250,16 +258,18 @@ func TestPatchApply(t *testing.T) { "MissingRequiredFieldPath": { reason: "A FromFieldPath patch should return an error when a required fromFieldPath doesn't exist", args: args{ - patch: v1beta1.Patch{ - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("wat"), - Policy: &v1beta1.PatchPolicy{ - FromFieldPath: func() *v1beta1.FromFieldPathPolicy { - s := v1beta1.FromFieldPathPolicyRequired - return &s - }(), + patch: v1beta1.ComposedPatch{ + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("wat"), + Policy: &v1beta1.PatchPolicy{ + FromFieldPath: func() *v1beta1.FromFieldPathPolicy { + s := v1beta1.FromFieldPathPolicyRequired + return &s + }(), + }, + ToFieldPath: ptr.To[string]("wat"), }, - ToFieldPath: ptr.To[string]("wat"), }, xr: &composite.Unstructured{ Unstructured: unstructured.Unstructured{Object: MustObject(`{ @@ -296,10 +306,12 @@ func TestPatchApply(t *testing.T) { "FilterExcludeCompositeFieldPathPatch": { reason: "Should not apply the patch as the v1.PatchType is not present in filter.", args: args{ - patch: v1beta1.Patch{ - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.labels"), - ToFieldPath: ptr.To[string]("metadata.labels"), + patch: v1beta1.ComposedPatch{ + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.labels"), + ToFieldPath: ptr.To[string]("metadata.labels"), + }, }, xr: &composite.Unstructured{ Unstructured: unstructured.Unstructured{Object: MustObject(`{ @@ -323,10 +335,12 @@ func TestPatchApply(t *testing.T) { "FilterIncludeCompositeFieldPathPatch": { reason: "Should apply the patch as the v1.PatchType is present in filter.", args: args{ - patch: v1beta1.Patch{ - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.labels"), - ToFieldPath: ptr.To[string]("metadata.labels"), + patch: v1beta1.ComposedPatch{ + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.labels"), + ToFieldPath: ptr.To[string]("metadata.labels"), + }, }, xr: &composite.Unstructured{ Unstructured: unstructured.Unstructured{Object: MustObject(`{ @@ -365,9 +379,11 @@ func TestPatchApply(t *testing.T) { "DefaultToFieldCompositeFieldPathPatch": { reason: "Should correctly default the ToFieldPath value if not specified.", args: args{ - patch: v1beta1.Patch{ - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.labels"), + patch: v1beta1.ComposedPatch{ + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.labels"), + }, }, xr: &composite.Unstructured{ Unstructured: unstructured.Unstructured{Object: MustObject(`{ @@ -405,10 +421,12 @@ func TestPatchApply(t *testing.T) { "ValidToCompositeFieldPathPatch": { reason: "Should correctly apply a ToCompositeFieldPath patch with valid settings", args: args{ - patch: v1beta1.Patch{ - Type: v1beta1.PatchTypeToCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.labels"), - ToFieldPath: ptr.To[string]("metadata.labels"), + patch: v1beta1.ComposedPatch{ + Type: v1beta1.PatchTypeToCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.labels"), + ToFieldPath: ptr.To[string]("metadata.labels"), + }, }, xr: &composite.Unstructured{ Unstructured: unstructured.Unstructured{Object: MustObject(`{ @@ -446,10 +464,12 @@ func TestPatchApply(t *testing.T) { "ValidToCompositeFieldPathPatchWithWildcards": { reason: "When passed a wildcarded path, adds a field to each element of an array", args: args{ - patch: v1beta1.Patch{ - Type: v1beta1.PatchTypeToCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.name"), - ToFieldPath: ptr.To[string]("metadata.ownerReferences[*].name"), + patch: v1beta1.ComposedPatch{ + Type: v1beta1.PatchTypeToCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.name"), + ToFieldPath: ptr.To[string]("metadata.ownerReferences[*].name"), + }, }, xr: &composite.Unstructured{ Unstructured: unstructured.Unstructured{Object: MustObject(`{ @@ -499,10 +519,13 @@ func TestPatchApply(t *testing.T) { "MissingCombineFromCompositeConfig": { reason: "Should return an error if Combine config is not passed", args: args{ - patch: v1beta1.Patch{ - Type: v1beta1.PatchTypeCombineFromComposite, - ToFieldPath: ptr.To[string]("metadata.labels.destination"), - // Missing a Combine field + patch: v1beta1.ComposedPatch{ + Type: v1beta1.PatchTypeCombineFromComposite, + Patch: v1beta1.Patch{ + ToFieldPath: ptr.To[string]("metadata.labels.destination"), + // Missing a Combine field + Combine: nil, + }, }, xr: &composite.Unstructured{}, cd: &composed.Unstructured{}, @@ -516,17 +539,19 @@ func TestPatchApply(t *testing.T) { "MissingCombineStrategyFromCompositeConfig": { reason: "Should return an error if Combine strategy config is not passed", args: args{ - patch: v1beta1.Patch{ + patch: v1beta1.ComposedPatch{ Type: v1beta1.PatchTypeCombineFromComposite, - Combine: &v1beta1.Combine{ - Variables: []v1beta1.CombineVariable{ - {FromFieldPath: "metadata.labels.source1"}, - {FromFieldPath: "metadata.labels.source2"}, + Patch: v1beta1.Patch{ + Combine: &v1beta1.Combine{ + Variables: []v1beta1.CombineVariable{ + {FromFieldPath: "metadata.labels.source1"}, + {FromFieldPath: "metadata.labels.source2"}, + }, + Strategy: v1beta1.CombineStrategyString, + // Missing a String combine config. }, - Strategy: v1beta1.CombineStrategyString, - // Missing a String combine config. + ToFieldPath: ptr.To[string]("metadata.labels.destination"), }, - ToFieldPath: ptr.To[string]("metadata.labels.destination"), }, xr: &composite.Unstructured{ Unstructured: unstructured.Unstructured{Object: MustObject(`{ @@ -548,15 +573,17 @@ func TestPatchApply(t *testing.T) { "MissingCombineVariablesFromCompositeConfig": { reason: "Should return an error if no variables have been passed", args: args{ - patch: v1beta1.Patch{ + patch: v1beta1.ComposedPatch{ Type: v1beta1.PatchTypeCombineFromComposite, - Combine: &v1beta1.Combine{ - // This is empty. - Variables: []v1beta1.CombineVariable{}, - Strategy: v1beta1.CombineStrategyString, - String: &v1beta1.StringCombine{Format: "%s-%s"}, + Patch: v1beta1.Patch{ + Combine: &v1beta1.Combine{ + // This is empty. + Variables: []v1beta1.CombineVariable{}, + Strategy: v1beta1.CombineStrategyString, + String: &v1beta1.StringCombine{Format: "%s-%s"}, + }, + ToFieldPath: ptr.To[string]("objectMeta.labels.destination"), }, - ToFieldPath: ptr.To[string]("objectMeta.labels.destination"), }, }, want: want{ @@ -569,18 +596,20 @@ func TestPatchApply(t *testing.T) { // not available. reason: "Should return no error and not apply patch if an optional variable is missing", args: args{ - patch: v1beta1.Patch{ + patch: v1beta1.ComposedPatch{ Type: v1beta1.PatchTypeCombineFromComposite, - Combine: &v1beta1.Combine{ - Variables: []v1beta1.CombineVariable{ - {FromFieldPath: "metadata.labels.source1"}, - {FromFieldPath: "metadata.labels.source2"}, - {FromFieldPath: "metadata.labels.source3"}, + Patch: v1beta1.Patch{ + Combine: &v1beta1.Combine{ + Variables: []v1beta1.CombineVariable{ + {FromFieldPath: "metadata.labels.source1"}, + {FromFieldPath: "metadata.labels.source2"}, + {FromFieldPath: "metadata.labels.source3"}, + }, + Strategy: v1beta1.CombineStrategyString, + String: &v1beta1.StringCombine{Format: "%s-%s"}, }, - Strategy: v1beta1.CombineStrategyString, - String: &v1beta1.StringCombine{Format: "%s-%s"}, + ToFieldPath: ptr.To[string]("metadata.labels.destination"), }, - ToFieldPath: ptr.To[string]("metadata.labels.destination"), }, xr: &composite.Unstructured{ Unstructured: unstructured.Unstructured{Object: MustObject(`{ @@ -602,17 +631,19 @@ func TestPatchApply(t *testing.T) { "ValidCombineFromComposite": { reason: "Should correctly apply a CombineFromComposite patch with valid settings", args: args{ - patch: v1beta1.Patch{ + patch: v1beta1.ComposedPatch{ Type: v1beta1.PatchTypeCombineFromComposite, - Combine: &v1beta1.Combine{ - Variables: []v1beta1.CombineVariable{ - {FromFieldPath: "metadata.labels.source1"}, - {FromFieldPath: "metadata.labels.source2"}, + Patch: v1beta1.Patch{ + Combine: &v1beta1.Combine{ + Variables: []v1beta1.CombineVariable{ + {FromFieldPath: "metadata.labels.source1"}, + {FromFieldPath: "metadata.labels.source2"}, + }, + Strategy: v1beta1.CombineStrategyString, + String: &v1beta1.StringCombine{Format: "%s-%s"}, }, - Strategy: v1beta1.CombineStrategyString, - String: &v1beta1.StringCombine{Format: "%s-%s"}, + ToFieldPath: ptr.To[string]("metadata.labels.destination"), }, - ToFieldPath: ptr.To[string]("metadata.labels.destination"), }, xr: &composite.Unstructured{ Unstructured: unstructured.Unstructured{Object: MustObject(`{ @@ -657,17 +688,19 @@ func TestPatchApply(t *testing.T) { "ValidCombineToComposite": { reason: "Should correctly apply a CombineToComposite patch with valid settings", args: args{ - patch: v1beta1.Patch{ + patch: v1beta1.ComposedPatch{ Type: v1beta1.PatchTypeCombineToComposite, - Combine: &v1beta1.Combine{ - Variables: []v1beta1.CombineVariable{ - {FromFieldPath: "metadata.labels.source1"}, - {FromFieldPath: "metadata.labels.source2"}, + Patch: v1beta1.Patch{ + Combine: &v1beta1.Combine{ + Variables: []v1beta1.CombineVariable{ + {FromFieldPath: "metadata.labels.source1"}, + {FromFieldPath: "metadata.labels.source2"}, + }, + Strategy: v1beta1.CombineStrategyString, + String: &v1beta1.StringCombine{Format: "%s-%s"}, }, - Strategy: v1beta1.CombineStrategyString, - String: &v1beta1.StringCombine{Format: "%s-%s"}, + ToFieldPath: ptr.To[string]("metadata.labels.destination"), }, - ToFieldPath: ptr.To[string]("metadata.labels.destination"), }, xr: &composite.Unstructured{ Unstructured: unstructured.Unstructured{Object: MustObject(`{ @@ -713,7 +746,7 @@ func TestPatchApply(t *testing.T) { for name, tc := range cases { t.Run(name, func(t *testing.T) { ncp := tc.args.xr.DeepCopyObject().(resource.Composite) - err := Apply(tc.args.patch, ncp, tc.args.cd, tc.args.only...) + err := Apply(&tc.args.patch, ncp, tc.args.cd, tc.args.only...) if tc.want.xr != nil { if diff := cmp.Diff(tc.want.xr, ncp); diff != "" { @@ -851,14 +884,18 @@ func TestComposedTemplates(t *testing.T) { args: args{ cts: []v1beta1.ComposedTemplate{ { - Patches: []v1beta1.Patch{ + Patches: []v1beta1.ComposedPatch{ { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.name"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.name"), + }, }, { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.namespace"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.namespace"), + }, }, }, }, @@ -867,14 +904,18 @@ func TestComposedTemplates(t *testing.T) { want: want{ ct: []v1beta1.ComposedTemplate{ { - Patches: []v1beta1.Patch{ + Patches: []v1beta1.ComposedPatch{ { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.name"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.name"), + }, }, { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.namespace"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.namespace"), + }, }, }, }, @@ -885,7 +926,7 @@ func TestComposedTemplates(t *testing.T) { reason: "Should return error and not modify the patches field when referring to an undefined PatchSet", args: args{ cts: []v1beta1.ComposedTemplate{{ - Patches: []v1beta1.Patch{ + Patches: []v1beta1.ComposedPatch{ { Type: v1beta1.PatchTypePatchSet, PatchSetName: ptr.To[string]("patch-set-1"), @@ -905,50 +946,60 @@ func TestComposedTemplates(t *testing.T) { pss: []v1beta1.PatchSet{ { Name: "patch-set-1", - Patches: []v1beta1.Patch{ + Patches: []v1beta1.PatchSetPatch{ { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.namespace"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.namespace"), + }, }, { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("spec.parameters.test"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("spec.parameters.test"), + }, }, }, }, { Name: "patch-set-2", - Patches: []v1beta1.Patch{ + Patches: []v1beta1.PatchSetPatch{ { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.annotations.patch-test-1"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.annotations.patch-test-1"), + }, }, { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.annotations.patch-test-2"), - Transforms: []v1beta1.Transform{{ - Type: v1beta1.TransformTypeMap, - Map: &v1beta1.MapTransform{ - Pairs: map[string]extv1.JSON{ - "k-1": asJSON("v-1"), - "k-2": asJSON("v-2"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.annotations.patch-test-2"), + Transforms: []v1beta1.Transform{{ + Type: v1beta1.TransformTypeMap, + Map: &v1beta1.MapTransform{ + Pairs: map[string]extv1.JSON{ + "k-1": asJSON("v-1"), + "k-2": asJSON("v-2"), + }, }, - }, - }}, + }}, + }, }, }, }, }, cts: []v1beta1.ComposedTemplate{ { - Patches: []v1beta1.Patch{ + Patches: []v1beta1.ComposedPatch{ { Type: v1beta1.PatchTypePatchSet, PatchSetName: ptr.To[string]("patch-set-2"), }, { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.name"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.name"), + }, }, { Type: v1beta1.PatchTypePatchSet, @@ -957,7 +1008,7 @@ func TestComposedTemplates(t *testing.T) { }, }, { - Patches: []v1beta1.Patch{ + Patches: []v1beta1.ComposedPatch{ { Type: v1beta1.PatchTypePatchSet, PatchSetName: ptr.To[string]("patch-set-1"), @@ -970,47 +1021,61 @@ func TestComposedTemplates(t *testing.T) { err: nil, ct: []v1beta1.ComposedTemplate{ { - Patches: []v1beta1.Patch{ + Patches: []v1beta1.ComposedPatch{ { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.annotations.patch-test-1"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.annotations.patch-test-1"), + }, }, { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.annotations.patch-test-2"), - Transforms: []v1beta1.Transform{{ - Type: v1beta1.TransformTypeMap, - Map: &v1beta1.MapTransform{ - Pairs: map[string]extv1.JSON{ - "k-1": asJSON("v-1"), - "k-2": asJSON("v-2"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.annotations.patch-test-2"), + Transforms: []v1beta1.Transform{{ + Type: v1beta1.TransformTypeMap, + Map: &v1beta1.MapTransform{ + Pairs: map[string]extv1.JSON{ + "k-1": asJSON("v-1"), + "k-2": asJSON("v-2"), + }, }, - }, - }}, + }}, + }, }, { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.name"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.name"), + }, }, { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.namespace"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.namespace"), + }, }, { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("spec.parameters.test"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("spec.parameters.test"), + }, }, }, }, { - Patches: []v1beta1.Patch{ + Patches: []v1beta1.ComposedPatch{ { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("metadata.namespace"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("metadata.namespace"), + }, }, { - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("spec.parameters.test"), + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("spec.parameters.test"), + }, }, }, }, @@ -1114,7 +1179,7 @@ func TestResolveTransforms(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := ResolveTransforms(v1beta1.Patch{Transforms: tt.args.ts}, tt.args.input) + got, err := ResolveTransforms(tt.args.ts, tt.args.input) if diff := cmp.Diff(tt.want.err, err, test.EquateErrors()); diff != "" { t.Errorf("ResolveTransforms(...): -want error, +got error:\n%s", diff) } diff --git a/render.go b/render.go index 44da046..f29cab8 100644 --- a/render.go +++ b/render.go @@ -62,16 +62,16 @@ func RenderFromJSON(o resource.Object, data []byte) error { // RenderEnvironmentPatches renders the supplied environment by applying all // patches that are to the environment, from the supplied XR. -func RenderEnvironmentPatches(env *unstructured.Unstructured, oxr, dxr *composite.Unstructured, ps []v1beta1.Patch) error { +func RenderEnvironmentPatches(env *unstructured.Unstructured, oxr, dxr *composite.Unstructured, ps []v1beta1.EnvironmentPatch) error { for i, p := range ps { p := p switch p.Type { case v1beta1.PatchTypeToEnvironmentFieldPath, v1beta1.PatchTypeCombineToEnvironment: - if err := ApplyToObjects(p, env, oxr); err != nil { + if err := ApplyToObjects(&p, env, oxr); err != nil { return errors.Wrapf(err, errFmtPatch, p.Type, i) } case v1beta1.PatchTypeFromEnvironmentFieldPath, v1beta1.PatchTypeCombineFromEnvironment: - if err := ApplyToObjects(p, env, dxr); err != nil { + if err := ApplyToObjects(&p, env, dxr); err != nil { return errors.Wrapf(err, errFmtPatch, p.Type, i) } case v1beta1.PatchTypePatchSet, v1beta1.PatchTypeFromCompositeFieldPath, v1beta1.PatchTypeCombineFromComposite, v1beta1.PatchTypeToCompositeFieldPath, v1beta1.PatchTypeCombineToComposite: @@ -91,9 +91,10 @@ func RenderComposedPatches( //nolint:gocyclo // just a switch oxr *composite.Unstructured, dxr *composite.Unstructured, env *unstructured.Unstructured, - ps []v1beta1.Patch, + ps []v1beta1.ComposedPatch, ) (errs []error, store bool) { for i, p := range ps { + p := p switch t := p.Type; t { case v1beta1.PatchTypeToCompositeFieldPath, v1beta1.PatchTypeCombineToComposite: // TODO(negz): Should failures to patch the XR be terminal? It could @@ -110,7 +111,7 @@ func RenderComposedPatches( //nolint:gocyclo // just a switch if ocd == nil { continue } - if err := ApplyToObjects(p, dxr, ocd); err != nil { + if err := ApplyToObjects(&p, dxr, ocd); err != nil { errs = append(errs, errors.Wrapf(err, errFmtPatch, t, i)) } case v1beta1.PatchTypeToEnvironmentFieldPath, v1beta1.PatchTypeCombineToEnvironment: @@ -123,7 +124,7 @@ func RenderComposedPatches( //nolint:gocyclo // just a switch if ocd == nil { continue } - if err := ApplyToObjects(p, env, ocd); err != nil { + if err := ApplyToObjects(&p, env, ocd); err != nil { errs = append(errs, errors.Wrapf(err, errFmtPatch, t, i)) } // If either of the below renderings return an error, most likely a @@ -133,12 +134,12 @@ func RenderComposedPatches( //nolint:gocyclo // just a switch // resource in the wrong state. To that end, we don't want to add this // resource to our accumulated desired state. case v1beta1.PatchTypeFromCompositeFieldPath, v1beta1.PatchTypeCombineFromComposite: - if err := ApplyToObjects(p, oxr, dcd); err != nil { + if err := ApplyToObjects(&p, oxr, dcd); err != nil { errs = append(errs, errors.Wrapf(err, errFmtPatch, t, i)) return errs, false } case v1beta1.PatchTypeFromEnvironmentFieldPath, v1beta1.PatchTypeCombineFromEnvironment: - if err := ApplyToObjects(p, env, dcd); err != nil { + if err := ApplyToObjects(&p, env, dcd); err != nil { errs = append(errs, errors.Wrapf(err, errFmtPatch, t, i)) return errs, false } diff --git a/validate.go b/validate.go index 417a326..ff006e9 100644 --- a/validate.go +++ b/validate.go @@ -59,7 +59,8 @@ func ValidateComposedTemplate(t v1beta1.ComposedTemplate) *field.Error { return field.Required(field.NewPath("name"), "name is required") } for i, p := range t.Patches { - if err := ValidatePatch(p); err != nil { + p := p + if err := ValidatePatch(&p); err != nil { return WrapFieldError(err, field.NewPath("patches").Index(i)) } } @@ -82,7 +83,8 @@ func ValidatePatchSet(ps v1beta1.PatchSet) *field.Error { return field.Required(field.NewPath("name"), "name is required") } for i, p := range ps.Patches { - if err := ValidatePatch(p); err != nil { + p := p + if err := ValidatePatch(&p); err != nil { return WrapFieldError(err, field.NewPath("patches").Index(i)) } } @@ -95,6 +97,7 @@ func ValidateEnvironment(e *v1beta1.Environment) *field.Error { return nil } for i, p := range e.Patches { + p := p switch p.GetType() { //nolint:exhaustive // Intentionally targeting only environment patches. case v1beta1.PatchTypeCombineToEnvironment, v1beta1.PatchTypeCombineFromEnvironment, @@ -104,7 +107,7 @@ func ValidateEnvironment(e *v1beta1.Environment) *field.Error { return field.Invalid(field.NewPath("patches").Index(i).Key("type"), p.Type, "invalid environment patch type") } - if err := ValidatePatch(p); err != nil { + if err := ValidatePatch(&p); err != nil { return WrapFieldError(err, field.NewPath("patches").Index(i)) } } @@ -157,35 +160,39 @@ func ValidateMatchConditionReadinessCheck(m *v1beta1.MatchConditionReadinessChec return nil } -// ValidatePatch validates a Patch. -func ValidatePatch(p v1beta1.Patch) *field.Error { +// ValidatePatch validates a ComposedPatch. +func ValidatePatch(p PatchInterface) *field.Error { //nolint: gocyclo // This is a long but simple/same-y switch. switch p.GetType() { case v1beta1.PatchTypeFromCompositeFieldPath, v1beta1.PatchTypeToCompositeFieldPath, v1beta1.PatchTypeFromEnvironmentFieldPath, v1beta1.PatchTypeToEnvironmentFieldPath: - if p.FromFieldPath == nil { - return field.Required(field.NewPath("fromFieldPath"), fmt.Sprintf("fromFieldPath must be set for patch type %s", p.Type)) + if p.GetFromFieldPath() == "" { + return field.Required(field.NewPath("fromFieldPath"), fmt.Sprintf("fromFieldPath must be set for patch type %s", p.GetType())) } case v1beta1.PatchTypePatchSet: - if p.PatchSetName == nil { - return field.Required(field.NewPath("patchSetName"), fmt.Sprintf("patchSetName must be set for patch type %s", p.Type)) + ps, ok := p.(PatchWithPatchSetName) + if !ok { + return field.Invalid(field.NewPath("type"), p.GetType(), fmt.Sprintf("patch type %T does not support patch of type %s", p, p.GetType())) + } + if ps.GetPatchSetName() == "" { + return field.Required(field.NewPath("patchSetName"), fmt.Sprintf("patchSetName must be set for patch type %s", p.GetType())) } case v1beta1.PatchTypeCombineFromComposite, v1beta1.PatchTypeCombineToComposite, v1beta1.PatchTypeCombineFromEnvironment, v1beta1.PatchTypeCombineToEnvironment: - if p.Combine == nil { - return field.Required(field.NewPath("combine"), fmt.Sprintf("combine must be set for patch type %s", p.Type)) + if p.GetCombine() == nil { + return field.Required(field.NewPath("combine"), fmt.Sprintf("combine must be set for patch type %s", p.GetType())) } - if p.ToFieldPath == nil { - return field.Required(field.NewPath("toFieldPath"), fmt.Sprintf("toFieldPath must be set for patch type %s", p.Type)) + if p.GetToFieldPath() == "" { + return field.Required(field.NewPath("toFieldPath"), fmt.Sprintf("toFieldPath must be set for patch type %s", p.GetType())) } default: // Should never happen - return field.Invalid(field.NewPath("type"), p.Type, "unknown patch type") + return field.Invalid(field.NewPath("type"), p.GetType(), "unknown patch type") } - for i, t := range p.Transforms { + for i, t := range p.GetTransforms() { if err := ValidateTransform(t); err != nil { return WrapFieldError(err, field.NewPath("transforms").Index(i)) } diff --git a/validate_test.go b/validate_test.go index 69e7c52..dde1333 100644 --- a/validate_test.go +++ b/validate_test.go @@ -237,7 +237,7 @@ func TestValidateConnectionDetail(t *testing.T) { func TestValidatePatch(t *testing.T) { type args struct { - patch v1beta1.Patch + patch v1beta1.ComposedPatch } type want struct { @@ -252,22 +252,26 @@ func TestValidatePatch(t *testing.T) { "ValidFromCompositeFieldPath": { reason: "FromCompositeFieldPath patch with FromFieldPath set should be valid", args: args{ - patch: v1beta1.Patch{ - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("spec.forProvider.foo"), + patch: v1beta1.ComposedPatch{ + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("spec.forProvider.foo"), + }, }, }, }, "FromCompositeFieldPathWithInvalidTransforms": { reason: "FromCompositeFieldPath with invalid transforms should return error", args: args{ - patch: v1beta1.Patch{ - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: ptr.To[string]("spec.forProvider.foo"), - Transforms: []v1beta1.Transform{ - { - Type: v1beta1.TransformTypeMath, - Math: nil, + patch: v1beta1.ComposedPatch{ + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("spec.forProvider.foo"), + Transforms: []v1beta1.Transform{ + { + Type: v1beta1.TransformTypeMath, + Math: nil, + }, }, }, }, @@ -282,9 +286,11 @@ func TestValidatePatch(t *testing.T) { "InvalidFromCompositeFieldPathMissingFromFieldPath": { reason: "Invalid FromCompositeFieldPath missing FromFieldPath should return error", args: args{ - patch: v1beta1.Patch{ - Type: v1beta1.PatchTypeFromCompositeFieldPath, - FromFieldPath: nil, + patch: v1beta1.ComposedPatch{ + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: nil, + }, }, }, want: want{ @@ -297,9 +303,11 @@ func TestValidatePatch(t *testing.T) { "InvalidFromCompositeFieldPathMissingToFieldPath": { reason: "Invalid ToCompositeFieldPath missing ToFieldPath should return error", args: args{ - patch: v1beta1.Patch{ - Type: v1beta1.PatchTypeToCompositeFieldPath, - ToFieldPath: nil, + patch: v1beta1.ComposedPatch{ + Type: v1beta1.PatchTypeToCompositeFieldPath, + Patch: v1beta1.Patch{ + ToFieldPath: nil, + }, }, }, want: want{ @@ -312,7 +320,7 @@ func TestValidatePatch(t *testing.T) { "Invalidv1beta1.PatchSetMissingv1beta1.PatchSetName": { reason: "Invalid v1beta1.PatchSet missing v1beta1.PatchSetName should return error", args: args{ - patch: v1beta1.Patch{ + patch: v1beta1.ComposedPatch{ Type: v1beta1.PatchTypePatchSet, }, }, @@ -326,7 +334,7 @@ func TestValidatePatch(t *testing.T) { "InvalidCombineMissingCombine": { reason: "Invalid Combine missing Combine should return error", args: args{ - patch: v1beta1.Patch{ + patch: v1beta1.ComposedPatch{ Type: v1beta1.PatchTypeCombineToComposite, }, }, @@ -340,16 +348,18 @@ func TestValidatePatch(t *testing.T) { "InvalidCombineMissingToFieldPath": { reason: "Invalid Combine missing ToFieldPath should return error", args: args{ - patch: v1beta1.Patch{ + patch: v1beta1.ComposedPatch{ Type: v1beta1.PatchTypeCombineToComposite, - Combine: &v1beta1.Combine{ - Variables: []v1beta1.CombineVariable{ - { - FromFieldPath: "spec.forProvider.foo", + Patch: v1beta1.Patch{ + Combine: &v1beta1.Combine{ + Variables: []v1beta1.CombineVariable{ + { + FromFieldPath: "spec.forProvider.foo", + }, }, }, + ToFieldPath: nil, }, - ToFieldPath: nil, }, }, want: want{ @@ -362,7 +372,7 @@ func TestValidatePatch(t *testing.T) { } for name, tc := range cases { t.Run(name, func(t *testing.T) { - err := ValidatePatch(tc.args.patch) + err := ValidatePatch(&tc.args.patch) if diff := cmp.Diff(tc.want.err, err, cmpopts.IgnoreFields(field.Error{}, "Detail", "BadValue")); diff != "" { t.Errorf("%s\nValidatePatch(...): -want, +got:\n%s", tc.reason, diff) } From 11603643e3255812850f5ed6ba8a3ec52dbbdbec Mon Sep 17 00:00:00 2001 From: Philippe Scorsolini Date: Thu, 23 Nov 2023 22:13:24 +0100 Subject: [PATCH 7/9] tests: render with environment Signed-off-by: Philippe Scorsolini --- fn_test.go | 296 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 296 insertions(+) diff --git a/fn_test.go b/fn_test.go index 806038e..7462518 100644 --- a/fn_test.go +++ b/fn_test.go @@ -10,7 +10,9 @@ import ( "google.golang.org/protobuf/testing/protocmp" "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/structpb" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/utils/ptr" "github.com/crossplane/crossplane-runtime/pkg/logging" @@ -643,6 +645,279 @@ func TestRunFunction(t *testing.T) { }, }, }, + "PatchToCompositeWithEnvironmentPatches": { + reason: "A basic ToCompositeFieldPath patch should work with environment.patches.", + args: args{ + req: &fnv1beta1.RunFunctionRequest{ + Input: resource.MustStructObject(&v1beta1.Resources{ + Resources: []v1beta1.ComposedTemplate{ + { + Name: "cool-resource", + Base: &runtime.RawExtension{Raw: []byte(`{"apiVersion":"example.org/v1","kind":"CD"}`)}, + }}, + Environment: &v1beta1.Environment{ + Patches: []v1beta1.EnvironmentPatch{ + { + Type: v1beta1.PatchTypeFromEnvironmentFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("data.widgets"), + ToFieldPath: ptr.To[string]("spec.watchers"), + Transforms: []v1beta1.Transform{ + { + Type: v1beta1.TransformTypeConvert, + Convert: &v1beta1.ConvertTransform{ + ToType: v1beta1.TransformIOTypeInt64, + }, + }, + { + Type: v1beta1.TransformTypeMath, + Math: &v1beta1.MathTransform{ + Type: v1beta1.MathTransformTypeMultiply, + Multiply: ptr.To[int64](3), + }}}}}}}}), + Observed: &fnv1beta1.State{ + Composite: &fnv1beta1.Resource{ + Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD","spec":{}}`), + }, + Resources: map[string]*fnv1beta1.Resource{}, + }, + Context: contextWithEnvironment(map[string]interface{}{ + "widgets": "10", + })}, + }, + want: want{ + rsp: &fnv1beta1.RunFunctionResponse{ + Meta: &fnv1beta1.ResponseMeta{Ttl: durationpb.New(response.DefaultTTL)}, + Desired: &fnv1beta1.State{ + Composite: &fnv1beta1.Resource{ + // spec.watchers = 10 * 3 = 30 + Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD","spec":{"watchers":30}}`), + }, + Resources: map[string]*fnv1beta1.Resource{ + "cool-resource": { + Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD"}`), + }}}, + Context: contextWithEnvironment(map[string]interface{}{ + "widgets": "10", + })}}}, + "EnvironmentPatchToEnvironment": { + reason: "A basic ToEnvironment patch should work with environment.patches.", + args: args{ + req: &fnv1beta1.RunFunctionRequest{ + Input: resource.MustStructObject(&v1beta1.Resources{ + Resources: []v1beta1.ComposedTemplate{ + { + Name: "cool-resource", + Base: &runtime.RawExtension{Raw: []byte(`{"apiVersion":"example.org/v1","kind":"CD"}`)}, + }}, + Environment: &v1beta1.Environment{ + Patches: []v1beta1.EnvironmentPatch{ + { + Type: v1beta1.PatchTypeToEnvironmentFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("spec.watchers"), + ToFieldPath: ptr.To[string]("data.widgets"), + Transforms: []v1beta1.Transform{ + { + Type: v1beta1.TransformTypeMath, + Math: &v1beta1.MathTransform{ + Type: v1beta1.MathTransformTypeMultiply, + Multiply: ptr.To[int64](3), + }, + }, + { + Type: v1beta1.TransformTypeConvert, + Convert: &v1beta1.ConvertTransform{ + ToType: v1beta1.TransformIOTypeString, + }, + }}}}}}}), + Observed: &fnv1beta1.State{ + Composite: &fnv1beta1.Resource{ + Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD","spec":{"watchers":10}}`), + }, + Resources: map[string]*fnv1beta1.Resource{}, + }, + Context: contextWithEnvironment(nil)}, + }, + want: want{ + rsp: &fnv1beta1.RunFunctionResponse{ + Meta: &fnv1beta1.ResponseMeta{Ttl: durationpb.New(response.DefaultTTL)}, + Desired: &fnv1beta1.State{ + Composite: &fnv1beta1.Resource{ + Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD"}`), + }, + Resources: map[string]*fnv1beta1.Resource{ + "cool-resource": { + Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD"}`), + }}}, + Context: contextWithEnvironment(map[string]interface{}{ + "widgets": "30", + })}}}, + "PatchComposedResourceFromEnvironment": { + reason: "A basic FromEnvironmentPatch should work if defined at spec.resources[*].patches.", + args: args{ + req: &fnv1beta1.RunFunctionRequest{ + Input: resource.MustStructObject(&v1beta1.Resources{ + Resources: []v1beta1.ComposedTemplate{{ + Name: "cool-resource", + Base: &runtime.RawExtension{Raw: []byte(`{"apiVersion":"example.org/v1","kind":"CD"}`)}, + Patches: []v1beta1.ComposedPatch{{ + Type: v1beta1.PatchTypeFromEnvironmentFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("data.widgets"), + ToFieldPath: ptr.To[string]("spec.watchers"), + Transforms: []v1beta1.Transform{{ + Type: v1beta1.TransformTypeConvert, + Convert: &v1beta1.ConvertTransform{ + ToType: v1beta1.TransformIOTypeInt64, + }, + }, { + Type: v1beta1.TransformTypeMath, + Math: &v1beta1.MathTransform{ + Type: v1beta1.MathTransformTypeMultiply, + Multiply: ptr.To[int64](3), + }, + }}}}}, + }}}), + Observed: &fnv1beta1.State{ + Composite: &fnv1beta1.Resource{ + Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD","spec":{}}`), + }, + Resources: map[string]*fnv1beta1.Resource{}, + }, + Context: contextWithEnvironment(map[string]interface{}{ + "widgets": "10", + })}, + }, + want: want{ + rsp: &fnv1beta1.RunFunctionResponse{ + Meta: &fnv1beta1.ResponseMeta{Ttl: durationpb.New(response.DefaultTTL)}, + Desired: &fnv1beta1.State{ + Composite: &fnv1beta1.Resource{ + Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD"}`), + }, + Resources: map[string]*fnv1beta1.Resource{ + "cool-resource": { + // spec.watchers = 10 * 3 = 30 + Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD","spec":{"watchers":30}}`), + }}}, + Context: contextWithEnvironment(map[string]interface{}{ + "widgets": "10", + })}}}, + + "PatchComposedResourceFromEnvironmentShadowedNotSet": { + reason: "A basic FromEnvironmentPatch should work if defined at spec.resources[*].patches, even if a successive patch shadows it and its source is not set.", + args: args{ + req: &fnv1beta1.RunFunctionRequest{ + Input: resource.MustStructObject(&v1beta1.Resources{ + Resources: []v1beta1.ComposedTemplate{{ + Name: "cool-resource", + Base: &runtime.RawExtension{Raw: []byte(`{"apiVersion":"example.org/v1","kind":"CD"}`)}, + Patches: []v1beta1.ComposedPatch{{ + Type: v1beta1.PatchTypeFromEnvironmentFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("data.widgets"), + ToFieldPath: ptr.To[string]("spec.watchers"), + Transforms: []v1beta1.Transform{{ + Type: v1beta1.TransformTypeConvert, + Convert: &v1beta1.ConvertTransform{ + ToType: v1beta1.TransformIOTypeInt64, + }, + }, { + Type: v1beta1.TransformTypeMath, + Math: &v1beta1.MathTransform{ + Type: v1beta1.MathTransformTypeMultiply, + Multiply: ptr.To[int64](3), + }, + }}}}, + { + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("spec.watchers"), + ToFieldPath: ptr.To[string]("spec.watchers"), + }}}}}}), + Observed: &fnv1beta1.State{ + Composite: &fnv1beta1.Resource{ + Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD","spec":{}}`), + }, + Resources: map[string]*fnv1beta1.Resource{}, + }, + Context: contextWithEnvironment(map[string]interface{}{ + "widgets": "10", + })}, + }, + want: want{ + rsp: &fnv1beta1.RunFunctionResponse{ + Meta: &fnv1beta1.ResponseMeta{Ttl: durationpb.New(response.DefaultTTL)}, + Desired: &fnv1beta1.State{ + Composite: &fnv1beta1.Resource{ + Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD"}`), + }, + Resources: map[string]*fnv1beta1.Resource{ + "cool-resource": { + // spec.watchers = 10 * 3 = 30 + Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD","spec":{"watchers":30}}`), + }}}, + Context: contextWithEnvironment(map[string]interface{}{ + "widgets": "10", + })}}}, + "PatchComposedResourceFromEnvironmentShadowedSet": { + reason: "A basic FromEnvironmentPatch should work if defined at spec.resources[*].patches, even if a successive patch shadows it and its source is set.", + args: args{ + req: &fnv1beta1.RunFunctionRequest{ + Input: resource.MustStructObject(&v1beta1.Resources{ + Resources: []v1beta1.ComposedTemplate{{ + Name: "cool-resource", + Base: &runtime.RawExtension{Raw: []byte(`{"apiVersion":"example.org/v1","kind":"CD"}`)}, + Patches: []v1beta1.ComposedPatch{{ + Type: v1beta1.PatchTypeFromEnvironmentFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("data.widgets"), + ToFieldPath: ptr.To[string]("spec.watchers"), + Transforms: []v1beta1.Transform{{ + Type: v1beta1.TransformTypeConvert, + Convert: &v1beta1.ConvertTransform{ + ToType: v1beta1.TransformIOTypeInt64, + }, + }, { + Type: v1beta1.TransformTypeMath, + Math: &v1beta1.MathTransform{ + Type: v1beta1.MathTransformTypeMultiply, + Multiply: ptr.To[int64](3), + }, + }}}}, + { + Type: v1beta1.PatchTypeFromCompositeFieldPath, + Patch: v1beta1.Patch{ + FromFieldPath: ptr.To[string]("spec.watchers"), + ToFieldPath: ptr.To[string]("spec.watchers"), + }}}}}}), + Observed: &fnv1beta1.State{ + Composite: &fnv1beta1.Resource{ + // I want this in the environment, 42 + Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD","spec":{"watchers":42}}`), + }, + Resources: map[string]*fnv1beta1.Resource{}, + }, + Context: contextWithEnvironment(map[string]interface{}{ + "widgets": "10", + })}, + }, + want: want{ + rsp: &fnv1beta1.RunFunctionResponse{ + Meta: &fnv1beta1.ResponseMeta{Ttl: durationpb.New(response.DefaultTTL)}, + Desired: &fnv1beta1.State{ + Composite: &fnv1beta1.Resource{ + Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD"}`), + }, + Resources: map[string]*fnv1beta1.Resource{ + "cool-resource": { + // spec.watchers comes from the composite resource, 42 + Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD","spec":{"watchers":42}}`), + }}}, + Context: contextWithEnvironment(map[string]interface{}{ + "widgets": "10", + })}}}, } for name, tc := range cases { @@ -660,3 +935,24 @@ func TestRunFunction(t *testing.T) { }) } } + +// Crossplane sends as context a fake resource: +// { "apiVersion": "internal.crossplane.io/v1alpha1", "kind": "Environment", "data": {... the actual environment content ...} } +// See: https://github.com/crossplane/crossplane/blob/806f0d20d146f6f4f1735c5ec6a7dc78923814b3/internal/controller/apiextensions/composite/environment_fetcher.go#L85C1-L85C1 +// That's because the patching code expects a resource to be able to use +// runtime.DefaultUnstructuredConverter.FromUnstructured to convert it back to +// an object. This is also why all patches need to specify the full path from data. +func contextWithEnvironment(data map[string]interface{}) *structpb.Struct { + if data == nil { + data = map[string]interface{}{} + } + u := unstructured.Unstructured{Object: map[string]interface{}{ + "data": data, + }} + u.SetGroupVersionKind(schema.GroupVersionKind{Group: "internal.crossplane.io", Version: "v1alpha1", Kind: "Environment"}) + d, err := structpb.NewStruct(u.UnstructuredContent()) + if err != nil { + panic(err) + } + return &structpb.Struct{Fields: map[string]*structpb.Value{fncontext.KeyEnvironment: structpb.NewStructValue(d)}} +} From 1074aa01904b815a272528d9efc96569c278163f Mon Sep 17 00:00:00 2001 From: Steven Borrelli Date: Wed, 29 Nov 2023 20:00:25 -0600 Subject: [PATCH 8/9] update examples Signed-off-by: Steven Borrelli --- examples/conditional-resources/composition.yaml | 1 + examples/conditional-resources/functions.yaml | 4 +++- go.sum | 8 ++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/conditional-resources/composition.yaml b/examples/conditional-resources/composition.yaml index 2d3b277..7fc75ee 100644 --- a/examples/conditional-resources/composition.yaml +++ b/examples/conditional-resources/composition.yaml @@ -15,6 +15,7 @@ spec: input: apiVersion: conditional-pt.fn.crossplane.io/v1beta1 kind: Resources + condition: observed.composite.resource.spec.render == true resources: - name: blue-resource condition: observed.composite.resource.spec.deployment.blue == true diff --git a/examples/conditional-resources/functions.yaml b/examples/conditional-resources/functions.yaml index 20ff604..d41d492 100644 --- a/examples/conditional-resources/functions.yaml +++ b/examples/conditional-resources/functions.yaml @@ -2,6 +2,8 @@ apiVersion: pkg.crossplane.io/v1beta1 kind: Function metadata: name: function-conditional-patch-and-transform + annotations: + render.crossplane.io/runtime: Development spec: - package: xpkg.upbound.io/borrelli-org/function-conditional-patch-and-transform:v0.3.0 + package: xpkg.upbound.io/borrelli-org/function-conditional-patch-and-transform:v0.4.0 packagePullPolicy: Always diff --git a/go.sum b/go.sum index c7cad90..1217ae5 100644 --- a/go.sum +++ b/go.sum @@ -42,8 +42,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= -github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= -github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2ojoH/0= github.com/alecthomas/kong v0.8.1 h1:acZdn3m4lLRobeh3Zi2S2EpnXTd1mOL6U7xVml+vfkY= github.com/alecthomas/kong v0.8.1/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U= @@ -72,10 +70,10 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/stevendborrelli/function-conditional-patch-and-transform v0.2.1 h1:8CNU6BGXWO+lqQw7t+calDuM9JEjQ61YYVA9fM9yv+8= -github.com/stevendborrelli/function-conditional-patch-and-transform v0.2.1/go.mod h1:B9hSlytx1BSH/zezwsRkLhcnEG1NHDQJE7Q5P4zxJGI= github.com/crossplane/crossplane-runtime v1.14.1 h1:TCa7R1N4bDGHjsLhiRxR/mUhwmistlMACHm0kiiYKck= github.com/crossplane/crossplane-runtime v1.14.1/go.mod h1:aOP+5W2wKpvthVs3pFNbVOe1jwrKYbJho0ThGNCVz9o= +github.com/crossplane/crossplane-runtime v1.14.2 h1:pV5JMzyzi/kcbeVBVPCat5MHH8zS94MBUapAyGx/Ry0= +github.com/crossplane/crossplane-runtime v1.14.2/go.mod h1:aOP+5W2wKpvthVs3pFNbVOe1jwrKYbJho0ThGNCVz9o= github.com/crossplane/function-sdk-go v0.1.0 h1:WN3CUSaj6wgDqQPZZP1whMVIkTAZtN3HVCS67pTMzd8= github.com/crossplane/function-sdk-go v0.1.0/go.mod h1:oRqHZ6RufpfZJ1N8aT4EfkP+5KpkhOKpWz7SeUDwwcw= github.com/crossplane/upjet v0.11.0-rc.0.0.20231012093706-c4a76d2a7505 h1:eCmYgfRopVn6r8RM1Ra4XQAPwVsjTGfktBj2Dk7yy+Y= @@ -311,6 +309,8 @@ github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stevendborrelli/function-conditional-patch-and-transform v0.2.1 h1:8CNU6BGXWO+lqQw7t+calDuM9JEjQ61YYVA9fM9yv+8= +github.com/stevendborrelli/function-conditional-patch-and-transform v0.2.1/go.mod h1:B9hSlytx1BSH/zezwsRkLhcnEG1NHDQJE7Q5P4zxJGI= github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From 61e33723e2be1c213f149a75acdc58f1549a013f Mon Sep 17 00:00:00 2001 From: Steven Borrelli Date: Wed, 29 Nov 2023 20:11:41 -0600 Subject: [PATCH 9/9] update version Signed-off-by: Steven Borrelli --- README.md | 2 +- examples/conditional-rendering/functions.yaml | 2 +- examples/conditional-resources/functions.yaml | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6c0a44d..775cc79 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ metadata: annotations: render.crossplane.io/runtime: Development spec: - package: xpkg.upbound.io/borrelli-org/function-conditional-patch-and-transform:v0.3.0 + package: xpkg.upbound.io/borrelli-org/function-conditional-patch-and-transform:v0.4.0 ``` ## What this function does diff --git a/examples/conditional-rendering/functions.yaml b/examples/conditional-rendering/functions.yaml index 20ff604..b197224 100644 --- a/examples/conditional-rendering/functions.yaml +++ b/examples/conditional-rendering/functions.yaml @@ -3,5 +3,5 @@ kind: Function metadata: name: function-conditional-patch-and-transform spec: - package: xpkg.upbound.io/borrelli-org/function-conditional-patch-and-transform:v0.3.0 + package: xpkg.upbound.io/borrelli-org/function-conditional-patch-and-transform:v0.4.0 packagePullPolicy: Always diff --git a/examples/conditional-resources/functions.yaml b/examples/conditional-resources/functions.yaml index d41d492..b197224 100644 --- a/examples/conditional-resources/functions.yaml +++ b/examples/conditional-resources/functions.yaml @@ -2,8 +2,6 @@ apiVersion: pkg.crossplane.io/v1beta1 kind: Function metadata: name: function-conditional-patch-and-transform - annotations: - render.crossplane.io/runtime: Development spec: package: xpkg.upbound.io/borrelli-org/function-conditional-patch-and-transform:v0.4.0 packagePullPolicy: Always