From abdc5bfc66719c632dcfb78e88d081c59edaf2b9 Mon Sep 17 00:00:00 2001 From: Gustavo Diaz Date: Thu, 13 Aug 2026 16:35:23 +0000 Subject: [PATCH 1/2] chore: Regenerate with code-generator v0.62.1 Picks up code-generator v0.62.1, which adds ACKGenerateVersion and ACKGenerateBuildDate to pkg/version/version.go and a debug-level build details line to cmd/controller/main.go (code-generator #728). This controller had not been regenerated since that release, so the churn is unrelated to any functional change and is separated out to keep the following commit reviewable. --- apis/v1alpha1/ack-generate-metadata.yaml | 8 +++---- cmd/controller/main.go | 28 ++++++++++++++++++++++++ pkg/version/version.go | 10 +++++++++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/apis/v1alpha1/ack-generate-metadata.yaml b/apis/v1alpha1/ack-generate-metadata.yaml index 4173fbe..66ac388 100755 --- a/apis/v1alpha1/ack-generate-metadata.yaml +++ b/apis/v1alpha1/ack-generate-metadata.yaml @@ -1,8 +1,8 @@ ack_generate_info: - build_date: "2026-08-04T17:35:56Z" - build_hash: db232581a560896c2dc461a244f96d5bf3191ec6 - go_version: go1.26.5 - version: v0.62.0 + build_date: "2026-08-13T16:33:00Z" + build_hash: 65d45b2e6c9efd6aca20e0d36826d1e18e4ba2b7 + go_version: go1.26.0 + version: v0.62.1 api_directory_checksum: 8f60eb5c2efd66afac68b6306bc19ac59b55bf39 api_version: v1alpha1 aws_sdk_go_version: v1.32.6 diff --git a/cmd/controller/main.go b/cmd/controller/main.go index fc175b5..d4ef701 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -18,6 +18,8 @@ package main import ( "context" "os" + goruntime "runtime" + "runtime/debug" kmsapitypes "github.com/aws-controllers-k8s/kms-controller/apis/v1alpha1" ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" @@ -53,6 +55,21 @@ var ( setupLog = ctrlrt.Log.WithName("setup") ) +// depVersion returns the module version of the given dependency import path, +// as recorded in the binary's build info, or "unknown" if it cannot be found. +func depVersion(path string) string { + info, ok := debug.ReadBuildInfo() + if !ok { + return "unknown" + } + for _, dep := range info.Deps { + if dep.Path == path { + return dep.Version + } + } + return "unknown" +} + func init() { _ = clientgoscheme.AddToScheme(scheme) @@ -146,6 +163,17 @@ func main() { setupLog.Info( "initializing service controller", "aws.service", awsServiceAlias, + "version", version.GitVersion, + ) + setupLog.V(1).Info( + "build details", + "aws.service", awsServiceAlias, + "gitCommit", version.GitCommit, + "buildDate", version.BuildDate, + "goVersion", goruntime.Version(), + "ackGenerateVersion", version.ACKGenerateVersion, + "ackRuntimeVersion", depVersion("github.com/aws-controllers-k8s/runtime"), + "awsSDKGoV2Version", depVersion("github.com/aws/aws-sdk-go-v2"), ) sc := ackrt.NewServiceController( awsServiceAlias, awsServiceAPIGroup, diff --git a/pkg/version/version.go b/pkg/version/version.go index de0f243..23573c0 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -15,8 +15,18 @@ package version +// GitVersion, GitCommit, and BuildDate describe the service controller build +// and are injected at controller build time via -ldflags. var ( GitVersion string GitCommit string BuildDate string ) + +// ACKGenerateVersion and ACKGenerateBuildDate identify the ack-generate build +// that generated this controller's code. They are baked in at code-generation +// time and are immutable for the life of the generated code. +const ( + ACKGenerateVersion = "v0.62.1" + ACKGenerateBuildDate = "2026-08-13T16:33:00Z" +) From 250f37a1cd7a4df6080cb0c9d31c2d65fed1376c Mon Sep 17 00:00:00 2001 From: Gustavo Diaz Date: Thu, 13 Aug 2026 16:42:00 +0000 Subject: [PATCH 2/2] feat(table): Add Keyspace reference for keyspaceName Table.keyspaceName names the Keyspace the table is created in, a Kind this same controller manages, so a user previously had to hardcode a value that does not exist until the Keyspace is created. Path is Spec.KeyspaceName rather than an ARN: the field's pattern (^[a-zA-Z0-9][a-zA-Z0-9_]{0,47}$) admits no arn: prefix, GetTable echoes the bare name back, and Keyspace exposes no name in its status. service_name is omitted because the target is same-service. Generates keyspaceRef, resolveReferenceForKeyspaceName, and relaxes keyspaceName out of the CRD required list. --- apis/v1alpha1/ack-generate-metadata.yaml | 6 +- apis/v1alpha1/generator.yaml | 4 + apis/v1alpha1/table.go | 4 +- apis/v1alpha1/zz_generated.deepcopy.go | 5 + .../keyspaces.services.k8s.aws_tables.yaml | 18 ++- generator.yaml | 4 + .../keyspaces.services.k8s.aws_tables.yaml | 18 ++- pkg/resource/table/delta.go | 3 + pkg/resource/table/references.go | 108 ++++++++++++++++++ pkg/version/version.go | 2 +- 10 files changed, 164 insertions(+), 8 deletions(-) diff --git a/apis/v1alpha1/ack-generate-metadata.yaml b/apis/v1alpha1/ack-generate-metadata.yaml index 66ac388..35decc7 100755 --- a/apis/v1alpha1/ack-generate-metadata.yaml +++ b/apis/v1alpha1/ack-generate-metadata.yaml @@ -1,13 +1,13 @@ ack_generate_info: - build_date: "2026-08-13T16:33:00Z" + build_date: "2026-08-13T16:35:38Z" build_hash: 65d45b2e6c9efd6aca20e0d36826d1e18e4ba2b7 go_version: go1.26.0 version: v0.62.1 -api_directory_checksum: 8f60eb5c2efd66afac68b6306bc19ac59b55bf39 +api_directory_checksum: 612ddccaa3ba3133720cfa4e7e91e56215b9f111 api_version: v1alpha1 aws_sdk_go_version: v1.32.6 generator_config_info: - file_checksum: 5bcee3b30b5b81b3f66396527ee0f5696e413cfb + file_checksum: 4acee79f10d3c8f7ecb876ab1894bf99fcef78bf original_file_name: generator.yaml last_modification: reason: API generation diff --git a/apis/v1alpha1/generator.yaml b/apis/v1alpha1/generator.yaml index 3dcd172..2889e9e 100644 --- a/apis/v1alpha1/generator.yaml +++ b/apis/v1alpha1/generator.yaml @@ -25,6 +25,10 @@ resources: Status: type: string is_read_only: true + KeyspaceName: + references: + resource: Keyspace + path: Spec.KeyspaceName EncryptionSpecification.KMSKeyIdentifier: references: resource: Key diff --git a/apis/v1alpha1/table.go b/apis/v1alpha1/table.go index 4b0004e..61c6d07 100644 --- a/apis/v1alpha1/table.go +++ b/apis/v1alpha1/table.go @@ -68,8 +68,8 @@ type TableSpec struct { // The name of the keyspace that the table is going to be created in. // // Regex Pattern: `^[a-zA-Z0-9][a-zA-Z0-9_]{0,47}$` - // +kubebuilder:validation:Required - KeyspaceName *string `json:"keyspaceName"` + KeyspaceName *string `json:"keyspaceName,omitempty"` + KeyspaceRef *ackv1alpha1.AWSResourceReferenceWrapper `json:"keyspaceRef,omitempty"` // Specifies if pointInTimeRecovery is enabled or disabled for the table. The // options are: // diff --git a/apis/v1alpha1/zz_generated.deepcopy.go b/apis/v1alpha1/zz_generated.deepcopy.go index 0f554da..5db2dd3 100644 --- a/apis/v1alpha1/zz_generated.deepcopy.go +++ b/apis/v1alpha1/zz_generated.deepcopy.go @@ -866,6 +866,11 @@ func (in *TableSpec) DeepCopyInto(out *TableSpec) { *out = new(string) **out = **in } + if in.KeyspaceRef != nil { + in, out := &in.KeyspaceRef, &out.KeyspaceRef + *out = new(corev1alpha1.AWSResourceReferenceWrapper) + (*in).DeepCopyInto(*out) + } if in.PointInTimeRecovery != nil { in, out := &in.PointInTimeRecovery, &out.PointInTimeRecovery *out = new(PointInTimeRecovery) diff --git a/config/crd/bases/keyspaces.services.k8s.aws_tables.yaml b/config/crd/bases/keyspaces.services.k8s.aws_tables.yaml index f9bc0cf..8b1c83e 100644 --- a/config/crd/bases/keyspaces.services.k8s.aws_tables.yaml +++ b/config/crd/bases/keyspaces.services.k8s.aws_tables.yaml @@ -131,6 +131,23 @@ spec: Regex Pattern: `^[a-zA-Z0-9][a-zA-Z0-9_]{0,47}$` type: string + keyspaceRef: + description: "AWSResourceReferenceWrapper provides a wrapper around + *AWSResourceReference\ntype to provide more user friendly syntax + for references using 'from' field\nEx:\nAPIIDRef:\n\n\tfrom:\n\t + \ name: my-api" + properties: + from: + description: |- + AWSResourceReference provides all the values necessary to reference another + k8s resource for finding the identifier(Id/ARN/Name) + properties: + name: + type: string + namespace: + type: string + type: object + type: object pointInTimeRecovery: description: |- Specifies if pointInTimeRecovery is enabled or disabled for the table. The @@ -279,7 +296,6 @@ spec: type: string type: object required: - - keyspaceName - schemaDefinition - tableName type: object diff --git a/generator.yaml b/generator.yaml index 3dcd172..2889e9e 100644 --- a/generator.yaml +++ b/generator.yaml @@ -25,6 +25,10 @@ resources: Status: type: string is_read_only: true + KeyspaceName: + references: + resource: Keyspace + path: Spec.KeyspaceName EncryptionSpecification.KMSKeyIdentifier: references: resource: Key diff --git a/helm/crds/keyspaces.services.k8s.aws_tables.yaml b/helm/crds/keyspaces.services.k8s.aws_tables.yaml index c57d00f..58ec407 100644 --- a/helm/crds/keyspaces.services.k8s.aws_tables.yaml +++ b/helm/crds/keyspaces.services.k8s.aws_tables.yaml @@ -131,6 +131,23 @@ spec: Regex Pattern: `^[a-zA-Z0-9][a-zA-Z0-9_]{0,47}$` type: string + keyspaceRef: + description: "AWSResourceReferenceWrapper provides a wrapper around + *AWSResourceReference\ntype to provide more user friendly syntax + for references using 'from' field\nEx:\nAPIIDRef:\n\n\tfrom:\n\t + \ name: my-api" + properties: + from: + description: |- + AWSResourceReference provides all the values necessary to reference another + k8s resource for finding the identifier(Id/ARN/Name) + properties: + name: + type: string + namespace: + type: string + type: object + type: object pointInTimeRecovery: description: |- Specifies if pointInTimeRecovery is enabled or disabled for the table. The @@ -279,7 +296,6 @@ spec: type: string type: object required: - - keyspaceName - schemaDefinition - tableName type: object diff --git a/pkg/resource/table/delta.go b/pkg/resource/table/delta.go index 8103706..9c3b5d1 100644 --- a/pkg/resource/table/delta.go +++ b/pkg/resource/table/delta.go @@ -121,6 +121,9 @@ func newResourceDelta( delta.Add("Spec.KeyspaceName", a.ko.Spec.KeyspaceName, b.ko.Spec.KeyspaceName) } } + if !equality.Semantic.Equalities.DeepEqual(a.ko.Spec.KeyspaceRef, b.ko.Spec.KeyspaceRef) { + delta.Add("Spec.KeyspaceRef", a.ko.Spec.KeyspaceRef, b.ko.Spec.KeyspaceRef) + } if ackcompare.HasNilDifference(a.ko.Spec.PointInTimeRecovery, b.ko.Spec.PointInTimeRecovery) { delta.Add("Spec.PointInTimeRecovery", a.ko.Spec.PointInTimeRecovery, b.ko.Spec.PointInTimeRecovery) } else if a.ko.Spec.PointInTimeRecovery != nil && b.ko.Spec.PointInTimeRecovery != nil { diff --git a/pkg/resource/table/references.go b/pkg/resource/table/references.go index 150684e..4cda0b8 100644 --- a/pkg/resource/table/references.go +++ b/pkg/resource/table/references.go @@ -48,6 +48,10 @@ func (rm *resourceManager) ClearResolvedReferences(res acktypes.AWSResource) ack } } + if ko.Spec.KeyspaceRef != nil { + ko.Spec.KeyspaceName = nil + } + return &resource{ko} } @@ -73,6 +77,12 @@ func (rm *resourceManager) ResolveReferences( resourceHasReferences = resourceHasReferences || fieldHasReferences } + if fieldHasReferences, err := rm.resolveReferenceForKeyspaceName(ctx, apiReader, ko); err != nil { + return &resource{ko}, (resourceHasReferences || fieldHasReferences), err + } else { + resourceHasReferences = resourceHasReferences || fieldHasReferences + } + return &resource{ko}, resourceHasReferences, err } @@ -85,6 +95,13 @@ func validateReferenceFields(ko *svcapitypes.Table) error { return ackerr.ResourceReferenceAndIDNotSupportedFor("EncryptionSpecification.KMSKeyIdentifier", "EncryptionSpecification.KMSKeyIdentifierRef") } } + + if ko.Spec.KeyspaceRef != nil && ko.Spec.KeyspaceName != nil { + return ackerr.ResourceReferenceAndIDNotSupportedFor("KeyspaceName", "KeyspaceRef") + } + if ko.Spec.KeyspaceRef == nil && ko.Spec.KeyspaceName == nil { + return ackerr.ResourceReferenceOrIDRequiredFor("KeyspaceName", "KeyspaceRef") + } return nil } @@ -180,3 +197,94 @@ func getReferencedResourceState_Key( } return nil } + +// resolveReferenceForKeyspaceName reads the resource referenced +// from KeyspaceRef field and sets the KeyspaceName +// from referenced resource. Returns a boolean indicating whether a reference +// contains references, or an error +func (rm *resourceManager) resolveReferenceForKeyspaceName( + ctx context.Context, + apiReader client.Reader, + ko *svcapitypes.Table, +) (hasReferences bool, err error) { + if ko.Spec.KeyspaceRef != nil && ko.Spec.KeyspaceRef.From != nil { + hasReferences = true + arr := ko.Spec.KeyspaceRef.From + if arr.Name == nil || *arr.Name == "" { + return hasReferences, fmt.Errorf("provided resource reference is nil or empty: KeyspaceRef") + } + namespace, err := ackrt.ResolveCrossNamespaceReference( + ctx, + rm.cfg.EnableCrossNamespace, + &ko.Status.Conditions, + ackrt.CrossNamespaceRefKindResource, + ko.ObjectMeta.GetNamespace(), + arr.Namespace, + *arr.Name, + ) + if err != nil { + return hasReferences, err + } + obj := &svcapitypes.Keyspace{} + if err := getReferencedResourceState_Keyspace(ctx, apiReader, obj, *arr.Name, namespace); err != nil { + return hasReferences, err + } + ko.Spec.KeyspaceName = (*string)(obj.Spec.KeyspaceName) + } + + return hasReferences, nil +} + +// getReferencedResourceState_Keyspace looks up whether a referenced resource +// exists and is in a ACK.ResourceSynced=True state. If the referenced resource does exist and is +// in a Synced state, returns nil, otherwise returns `ackerr.ResourceReferenceTerminalFor` or +// `ResourceReferenceNotSyncedFor` depending on if the resource is in a Terminal state. +func getReferencedResourceState_Keyspace( + ctx context.Context, + apiReader client.Reader, + obj *svcapitypes.Keyspace, + name string, // the Kubernetes name of the referenced resource + namespace string, // the Kubernetes namespace of the referenced resource +) error { + namespacedName := types.NamespacedName{ + Namespace: namespace, + Name: name, + } + err := apiReader.Get(ctx, namespacedName, obj) + if err != nil { + return err + } + var refResourceTerminal bool + for _, cond := range obj.Status.Conditions { + if cond.Type == ackv1alpha1.ConditionTypeTerminal && + cond.Status == corev1.ConditionTrue { + return ackerr.ResourceReferenceTerminalFor( + "Keyspace", + namespace, name) + } + } + if refResourceTerminal { + return ackerr.ResourceReferenceTerminalFor( + "Keyspace", + namespace, name) + } + var refResourceSynced bool + for _, cond := range obj.Status.Conditions { + if cond.Type == ackv1alpha1.ConditionTypeResourceSynced && + cond.Status == corev1.ConditionTrue { + refResourceSynced = true + } + } + if !refResourceSynced { + return ackerr.ResourceReferenceNotSyncedFor( + "Keyspace", + namespace, name) + } + if obj.Spec.KeyspaceName == nil { + return ackerr.ResourceReferenceMissingTargetFieldFor( + "Keyspace", + namespace, name, + "Spec.KeyspaceName") + } + return nil +} diff --git a/pkg/version/version.go b/pkg/version/version.go index 23573c0..535a4f2 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -28,5 +28,5 @@ var ( // time and are immutable for the life of the generated code. const ( ACKGenerateVersion = "v0.62.1" - ACKGenerateBuildDate = "2026-08-13T16:33:00Z" + ACKGenerateBuildDate = "2026-08-13T16:35:38Z" )