From f94363db4995969ec7ed5101cde0dab24d08e7a8 Mon Sep 17 00:00:00 2001 From: Gustavo Diaz Date: Wed, 2 Sep 2026 17:52:37 +0000 Subject: [PATCH] chore: regenerate references.go to show EnsureReferences output Demonstration only, not for merge. Shows what aws-controllers-k8s/code-generator#738 emits in the context of a full service controller. Regenerated with no other change, so the diff is exactly the generated EnsureReferences methods. go.mod is untouched: the method compiles against the current runtime and stays inert until aws-controllers-k8s/runtime#267 lands, which is what invokes it. lambda covers all three reference shapes, so the per-shape behaviour is visible in one controller: function struct-nested Code.S3BucketRef, VPCConfig.SecurityGroupRefs, VPCConfig.SubnetRefs -> emitted layer_version struct-nested emitted event_source_mapping list-nested -> nothing emitted alias, code_signing_config, function_url_config, version top-level only -> nothing emitted function is the shape reported in aws-controllers-k8s/community#2431. --- pkg/resource/function/references.go | 41 ++++++++++++++++++++++++ pkg/resource/layer_version/references.go | 35 ++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/pkg/resource/function/references.go b/pkg/resource/function/references.go index 4d292744..3dfbdabf 100644 --- a/pkg/resource/function/references.go +++ b/pkg/resource/function/references.go @@ -94,6 +94,47 @@ func (rm *resourceManager) ClearResolvedReferences(res acktypes.AWSResource) ack return &resource{ko} } +// EnsureReferences restores, onto a copy of `latest`, the cross-resource +// reference (*Ref) fields it is missing, taking them from `desired`. Only +// reference fields are written, so every concrete value on `latest` stands. +// +// A *Ref is a sibling of the concrete field it resolves into, so rebuilding the +// containing struct from an AWS API response drops it. That disables +// ClearResolvedReferences, which suppresses a resolved value only while the +// sibling *Ref is visible, so the spec patch deletes the declared *Ref and stores +// the resolved value in its place. +// +// Only references reached through structs are restored. A top-level *Ref needs no +// help, since every write path starts from a DeepCopy of the object it was handed. +// A *Ref reached through a list is not restored and remains subject to the above: +// it has no fixed address, and replacing the whole list instead would discard +// whatever the service populated inside it. +// +// `desired` must be the declared resource with its references resolved, and must +// not be an object that has been through a resource manager: managers may mutate +// the resource they are handed, and some write API response values into it. +func (rm *resourceManager) EnsureReferences( + desired acktypes.AWSResource, + latest acktypes.AWSResource, +) acktypes.AWSResource { + // Deep copy the source as well, so a reference handed over below does not + // alias the caller's declared object. + desiredKO := rm.concreteResource(desired).ko.DeepCopy() + latestKO := rm.concreteResource(latest).ko.DeepCopy() + + if desiredKO.Spec.Code != nil && latestKO.Spec.Code != nil && desiredKO.Spec.Code.S3BucketRef != nil && latestKO.Spec.Code.S3BucketRef == nil { + latestKO.Spec.Code.S3BucketRef = desiredKO.Spec.Code.S3BucketRef + } + if desiredKO.Spec.VPCConfig != nil && latestKO.Spec.VPCConfig != nil && len(desiredKO.Spec.VPCConfig.SecurityGroupRefs) > 0 && len(latestKO.Spec.VPCConfig.SecurityGroupRefs) == 0 { + latestKO.Spec.VPCConfig.SecurityGroupRefs = desiredKO.Spec.VPCConfig.SecurityGroupRefs + } + if desiredKO.Spec.VPCConfig != nil && latestKO.Spec.VPCConfig != nil && len(desiredKO.Spec.VPCConfig.SubnetRefs) > 0 && len(latestKO.Spec.VPCConfig.SubnetRefs) == 0 { + latestKO.Spec.VPCConfig.SubnetRefs = desiredKO.Spec.VPCConfig.SubnetRefs + } + + return &resource{latestKO} +} + // ResolveReferences finds if there are any Reference field(s) present // inside AWSResource passed in the parameter and attempts to resolve those // reference field(s) into their respective target field(s). It returns a diff --git a/pkg/resource/layer_version/references.go b/pkg/resource/layer_version/references.go index a3b10f59..b6eb3e33 100644 --- a/pkg/resource/layer_version/references.go +++ b/pkg/resource/layer_version/references.go @@ -51,6 +51,41 @@ func (rm *resourceManager) ClearResolvedReferences(res acktypes.AWSResource) ack return &resource{ko} } +// EnsureReferences restores, onto a copy of `latest`, the cross-resource +// reference (*Ref) fields it is missing, taking them from `desired`. Only +// reference fields are written, so every concrete value on `latest` stands. +// +// A *Ref is a sibling of the concrete field it resolves into, so rebuilding the +// containing struct from an AWS API response drops it. That disables +// ClearResolvedReferences, which suppresses a resolved value only while the +// sibling *Ref is visible, so the spec patch deletes the declared *Ref and stores +// the resolved value in its place. +// +// Only references reached through structs are restored. A top-level *Ref needs no +// help, since every write path starts from a DeepCopy of the object it was handed. +// A *Ref reached through a list is not restored and remains subject to the above: +// it has no fixed address, and replacing the whole list instead would discard +// whatever the service populated inside it. +// +// `desired` must be the declared resource with its references resolved, and must +// not be an object that has been through a resource manager: managers may mutate +// the resource they are handed, and some write API response values into it. +func (rm *resourceManager) EnsureReferences( + desired acktypes.AWSResource, + latest acktypes.AWSResource, +) acktypes.AWSResource { + // Deep copy the source as well, so a reference handed over below does not + // alias the caller's declared object. + desiredKO := rm.concreteResource(desired).ko.DeepCopy() + latestKO := rm.concreteResource(latest).ko.DeepCopy() + + if desiredKO.Spec.Content != nil && latestKO.Spec.Content != nil && desiredKO.Spec.Content.S3BucketRef != nil && latestKO.Spec.Content.S3BucketRef == nil { + latestKO.Spec.Content.S3BucketRef = desiredKO.Spec.Content.S3BucketRef + } + + return &resource{latestKO} +} + // ResolveReferences finds if there are any Reference field(s) present // inside AWSResource passed in the parameter and attempts to resolve those // reference field(s) into their respective target field(s). It returns a