From 8da24cf37905ad9982d2ac405da3ae0d32762fce Mon Sep 17 00:00:00 2001 From: Amund Tenstad Date: Wed, 18 Feb 2026 09:15:18 +0100 Subject: [PATCH 1/2] refactor: avoid json marshal protojson unmarshal roundtrip Signed-off-by: Amund Tenstad --- fn.go | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/fn.go b/fn.go index f72ce1d..e7c933c 100644 --- a/fn.go +++ b/fn.go @@ -2,11 +2,9 @@ package main import ( "context" - "encoding/json" "reflect" "sort" - "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/types/known/structpb" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -88,25 +86,19 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1.RunFunctionRequest) return rsp, nil } - // For now cheaply convert to JSON for serializing. - // - // TODO(reedjosh): look into resources.AsStruct or simlar since unsturctured k8s objects are already almost json. - // structpb.NewList(v []interface{}) should create an array like. - // Combining this and similar structures from the structpb lib should should be done to create - // a map[string][object] container into which the found extra resources can be dumped. - // - // The found extra resources should then be directly marhsal-able via: - // obj := &unstructured.Unstructured{} - // obj.MarshalJSON() - b, err := json.Marshal(verifiedExtras) - if err != nil { - response.Fatal(rsp, errors.Errorf("cannot marshal %T: %w", verifiedExtras, err)) - return rsp, nil + // convert map[string][]unstructured.Unstructured to map[string]any + out := make(map[string]any, len(verifiedExtras)) + for k, us := range verifiedExtras { + li := make([]any, 0, len(us)) + for _, u := range us { + li = append(li, u.Object) + } + out[k] = li } - s := &structpb.Struct{} - err = protojson.Unmarshal(b, s) + + s, err := structpb.NewStruct(out) if err != nil { - response.Fatal(rsp, errors.Errorf("cannot unmarshal %T into %T: %w", extraResources, s, err)) + response.Fatal(rsp, errors.Wrapf(err, "cannot create new Struct from extra resources output")) return rsp, nil } response.SetContextKey(rsp, FunctionContextKeyExtraResources, structpb.NewStructValue(s)) From b36e026a8c3586f3e02339ca238831d42498ca21 Mon Sep 17 00:00:00 2001 From: Amund Tenstad Date: Wed, 18 Feb 2026 10:06:46 +0100 Subject: [PATCH 2/2] refactor: move any conversions into verifyAndSortExtras Signed-off-by: Amund Tenstad --- fn.go | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/fn.go b/fn.go index e7c933c..7e12bee 100644 --- a/fn.go +++ b/fn.go @@ -6,7 +6,6 @@ import ( "sort" "google.golang.org/protobuf/types/known/structpb" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "github.com/crossplane/crossplane-runtime/v2/pkg/errors" "github.com/crossplane/crossplane-runtime/v2/pkg/fieldpath" @@ -86,17 +85,7 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1.RunFunctionRequest) return rsp, nil } - // convert map[string][]unstructured.Unstructured to map[string]any - out := make(map[string]any, len(verifiedExtras)) - for k, us := range verifiedExtras { - li := make([]any, 0, len(us)) - for _, u := range us { - li = append(li, u.Object) - } - out[k] = li - } - - s, err := structpb.NewStruct(out) + s, err := structpb.NewStruct(verifiedExtras) if err != nil { response.Fatal(rsp, errors.Wrapf(err, "cannot create new Struct from extra resources output")) return rsp, nil @@ -163,8 +152,8 @@ func buildRequirements(in *v1beta1.Input, xr *resource.Composite) (*fnv1.Require // Verify Min/Max and sort extra resources by field path within a single kind. func verifyAndSortExtras(in *v1beta1.Input, extraResources map[string][]resource.Required, //nolint:gocyclo // TODO(reedjosh): refactor -) (cleanedExtras map[string][]unstructured.Unstructured, err error) { - cleanedExtras = make(map[string][]unstructured.Unstructured) +) (map[string]any, error) { + cleanedExtras := make(map[string]any) for _, extraResource := range in.Spec.ExtraResources { extraResName := extraResource.Into resources, ok := extraResources[extraResName] @@ -182,7 +171,6 @@ func verifyAndSortExtras(in *v1beta1.Input, extraResources map[string][]resource if len(resources) > 1 { return nil, errors.Errorf("expected exactly one extra resource %q, got %d", extraResName, len(resources)) } - cleanedExtras[extraResName] = append(cleanedExtras[extraResName], *resources[0].Resource) case v1beta1.ResourceSourceTypeSelector: selector := extraResource.Selector @@ -195,10 +183,13 @@ func verifyAndSortExtras(in *v1beta1.Input, extraResources map[string][]resource if selector.MaxMatch != nil && uint64(len(resources)) > *selector.MaxMatch { resources = resources[:*selector.MaxMatch] } - for _, r := range resources { - cleanedExtras[extraResName] = append(cleanedExtras[extraResName], *r.Resource) - } } + + objects := make([]any, 0, len(resources)) + for _, r := range resources { + objects = append(objects, r.Resource.Object) + } + cleanedExtras[extraResName] = objects } return cleanedExtras, nil }