From d1997b76d9747323ba6eb1a2b443dbde8d96385d Mon Sep 17 00:00:00 2001 From: Matthew Christopher Date: Thu, 25 Jan 2024 19:39:56 -0800 Subject: [PATCH] Make Resolver generic in value parameter too (#3742) This is needed to support resolving a map[string]string for collections of secrets. --- .../genericarmclient/generic_client_test.go | 4 +-- .../reconcilers/azuresql/local_user.go | 2 +- v2/internal/reconcilers/mysql/local_user.go | 2 +- .../postgresql/postgresql_user_reconciler.go | 2 +- v2/internal/resolver/config_map_resolver.go | 10 +++---- v2/internal/resolver/resolver.go | 28 +++++++++---------- v2/internal/resolver/secret_resolver.go | 8 +++--- v2/pkg/genruntime/arm_transformer.go | 8 ++++-- v2/pkg/genruntime/configmaps.go | 2 +- v2/pkg/genruntime/resolved.go | 18 ++++++------ 10 files changed, 44 insertions(+), 40 deletions(-) diff --git a/v2/internal/genericarmclient/generic_client_test.go b/v2/internal/genericarmclient/generic_client_test.go index 9b429f959ff..c81dd2752c6 100644 --- a/v2/internal/genericarmclient/generic_client_test.go +++ b/v2/internal/genericarmclient/generic_client_test.go @@ -41,7 +41,7 @@ func Test_NewResourceGroup(t *testing.T) { resourceGroup := testContext.NewTestResourceGroup() resolved := genruntime.ConvertToARMResolvedDetails{ Name: resourceGroup.Name, - ResolvedReferences: genruntime.MakeResolved[genruntime.ResourceReference](nil), + ResolvedReferences: genruntime.MakeResolved[genruntime.ResourceReference, string](nil), } spec, err := resourceGroup.Spec.ConvertToARM(resolved) g.Expect(err).ToNot(HaveOccurred()) @@ -103,7 +103,7 @@ func Test_NewResourceGroup_Error(t *testing.T) { resolved := genruntime.ConvertToARMResolvedDetails{ Name: rgName, - ResolvedReferences: genruntime.MakeResolved[genruntime.ResourceReference](nil), + ResolvedReferences: genruntime.MakeResolved[genruntime.ResourceReference, string](nil), } spec, err := resourceGroup.Spec.ConvertToARM(resolved) g.Expect(err).ToNot(HaveOccurred()) diff --git a/v2/internal/reconcilers/azuresql/local_user.go b/v2/internal/reconcilers/azuresql/local_user.go index eaa79edb4bc..de423f57bde 100644 --- a/v2/internal/reconcilers/azuresql/local_user.go +++ b/v2/internal/reconcilers/azuresql/local_user.go @@ -112,7 +112,7 @@ func (u *localUser) Exists(ctx context.Context) (bool, error) { return exists, nil } -func (u *localUser) connectToDB(ctx context.Context, secrets genruntime.Resolved[genruntime.SecretReference]) (*sql.DB, error) { +func (u *localUser) connectToDB(ctx context.Context, secrets genruntime.Resolved[genruntime.SecretReference, string]) (*sql.DB, error) { details, err := getOwnerDetails(ctx, u.resourceResolver, u.user) if err != nil { return nil, err diff --git a/v2/internal/reconcilers/mysql/local_user.go b/v2/internal/reconcilers/mysql/local_user.go index be86f257eee..f56e8c6fa38 100644 --- a/v2/internal/reconcilers/mysql/local_user.go +++ b/v2/internal/reconcilers/mysql/local_user.go @@ -117,7 +117,7 @@ func (u *localUser) Exists(ctx context.Context) (bool, error) { return exists, nil } -func (u *localUser) connectToDB(ctx context.Context, secrets genruntime.Resolved[genruntime.SecretReference]) (*sql.DB, error) { +func (u *localUser) connectToDB(ctx context.Context, secrets genruntime.Resolved[genruntime.SecretReference, string]) (*sql.DB, error) { serverFQDN, err := getServerFQDN(ctx, u.resourceResolver, u.user) if err != nil { return nil, err diff --git a/v2/internal/reconcilers/postgresql/postgresql_user_reconciler.go b/v2/internal/reconcilers/postgresql/postgresql_user_reconciler.go index 071348fbca3..a777b33348b 100644 --- a/v2/internal/reconcilers/postgresql/postgresql_user_reconciler.go +++ b/v2/internal/reconcilers/postgresql/postgresql_user_reconciler.go @@ -222,7 +222,7 @@ func (r *PostgreSQLUserReconciler) UpdateStatus(ctx context.Context, log logr.Lo return nil } -func (r *PostgreSQLUserReconciler) connectToDB(ctx context.Context, _ logr.Logger, user *asopostgresql.User, secrets genruntime.Resolved[genruntime.SecretReference]) (*sql.DB, error) { +func (r *PostgreSQLUserReconciler) connectToDB(ctx context.Context, _ logr.Logger, user *asopostgresql.User, secrets genruntime.Resolved[genruntime.SecretReference, string]) (*sql.DB, error) { // Get the owner - at this point it must exist ownerDetails, err := r.ResourceResolver.ResolveOwner(ctx, user) if err != nil { diff --git a/v2/internal/resolver/config_map_resolver.go b/v2/internal/resolver/config_map_resolver.go index c3b937ab257..64d2641e03f 100644 --- a/v2/internal/resolver/config_map_resolver.go +++ b/v2/internal/resolver/config_map_resolver.go @@ -8,7 +8,6 @@ package resolver import ( "context" - "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/pkg/errors" v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -17,12 +16,13 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/set" "github.com/Azure/azure-service-operator/v2/internal/util/kubeclient" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" ) // ConfigMapResolver is a configmap resolver type ConfigMapResolver interface { ResolveConfigMapReference(ctx context.Context, ref genruntime.NamespacedConfigMapReference) (string, error) - ResolveConfigMapReferences(ctx context.Context, refs set.Set[genruntime.NamespacedConfigMapReference]) (genruntime.Resolved[genruntime.ConfigMapReference], error) + ResolveConfigMapReferences(ctx context.Context, refs set.Set[genruntime.NamespacedConfigMapReference]) (genruntime.Resolved[genruntime.ConfigMapReference, string], error) } // kubeConfigMapResolver resolves Kubernetes config maps @@ -66,16 +66,16 @@ func (r *kubeConfigMapResolver) ResolveConfigMapReference(ctx context.Context, r } // ResolveConfigMapReferences resolves all provided configmap references -func (r *kubeConfigMapResolver) ResolveConfigMapReferences(ctx context.Context, refs set.Set[genruntime.NamespacedConfigMapReference]) (genruntime.Resolved[genruntime.ConfigMapReference], error) { +func (r *kubeConfigMapResolver) ResolveConfigMapReferences(ctx context.Context, refs set.Set[genruntime.NamespacedConfigMapReference]) (genruntime.Resolved[genruntime.ConfigMapReference, string], error) { result := make(map[genruntime.ConfigMapReference]string, len(refs)) for ref := range refs { value, err := r.ResolveConfigMapReference(ctx, ref) if err != nil { - return genruntime.MakeResolved[genruntime.ConfigMapReference](nil), err + return genruntime.MakeResolved[genruntime.ConfigMapReference, string](nil), err } result[ref.ConfigMapReference] = value } - return genruntime.MakeResolved[genruntime.ConfigMapReference](result), nil + return genruntime.MakeResolved[genruntime.ConfigMapReference, string](result), nil } diff --git a/v2/internal/resolver/resolver.go b/v2/internal/resolver/resolver.go index d9d3dbf85c1..7b21fa66fa6 100644 --- a/v2/internal/resolver/resolver.go +++ b/v2/internal/resolver/resolver.go @@ -91,25 +91,25 @@ func (r *Resolver) ResolveReferenceToARMID(ctx context.Context, ref genruntime.N } // ResolveReferencesToARMIDs resolves all provided references to their ARM IDs. -func (r *Resolver) ResolveReferencesToARMIDs(ctx context.Context, refs map[genruntime.NamespacedResourceReference]struct{}) (genruntime.Resolved[genruntime.ResourceReference], error) { +func (r *Resolver) ResolveReferencesToARMIDs(ctx context.Context, refs map[genruntime.NamespacedResourceReference]struct{}) (genruntime.Resolved[genruntime.ResourceReference, string], error) { result := make(map[genruntime.ResourceReference]string, len(refs)) for ref := range refs { armID, err := r.ResolveReferenceToARMID(ctx, ref) if err != nil { - return genruntime.MakeResolved[genruntime.ResourceReference](nil), err + return genruntime.MakeResolved[genruntime.ResourceReference, string](nil), err } result[ref.ResourceReference] = armID } - return genruntime.MakeResolved[genruntime.ResourceReference](result), nil + return genruntime.MakeResolved[genruntime.ResourceReference, string](result), nil } // ResolveResourceReferences resolves every reference found on the specified genruntime.ARMMetaObject to its corresponding ARM ID. -func (r *Resolver) ResolveResourceReferences(ctx context.Context, metaObject genruntime.ARMMetaObject) (genruntime.Resolved[genruntime.ResourceReference], error) { +func (r *Resolver) ResolveResourceReferences(ctx context.Context, metaObject genruntime.ARMMetaObject) (genruntime.Resolved[genruntime.ResourceReference, string], error) { refs, err := reflecthelpers.FindResourceReferences(metaObject) if err != nil { - return genruntime.Resolved[genruntime.ResourceReference]{}, errors.Wrapf(err, "finding references on %q", metaObject.GetName()) + return genruntime.Resolved[genruntime.ResourceReference, string]{}, errors.Wrapf(err, "finding references on %q", metaObject.GetName()) } // Include the namespace @@ -121,7 +121,7 @@ func (r *Resolver) ResolveResourceReferences(ctx context.Context, metaObject gen // resolve them resolvedRefs, err := r.ResolveReferencesToARMIDs(ctx, namespacedRefs) if err != nil { - return genruntime.Resolved[genruntime.ResourceReference]{}, errors.Wrapf(err, "failed resolving ARM IDs for references") + return genruntime.Resolved[genruntime.ResourceReference, string]{}, errors.Wrapf(err, "failed resolving ARM IDs for references") } return resolvedRefs, nil @@ -288,15 +288,15 @@ func (r *Resolver) findGVK(ref genruntime.NamespacedResourceReference) (schema.G func (r *Resolver) ResolveSecretReferences( ctx context.Context, refs set.Set[genruntime.NamespacedSecretReference], -) (genruntime.Resolved[genruntime.SecretReference], error) { +) (genruntime.Resolved[genruntime.SecretReference, string], error) { return r.kubeSecretResolver.ResolveSecretReferences(ctx, refs) } // ResolveResourceSecretReferences resolves all of the specified genruntime.MetaObject's secret references. -func (r *Resolver) ResolveResourceSecretReferences(ctx context.Context, metaObject genruntime.MetaObject) (genruntime.Resolved[genruntime.SecretReference], error) { +func (r *Resolver) ResolveResourceSecretReferences(ctx context.Context, metaObject genruntime.MetaObject) (genruntime.Resolved[genruntime.SecretReference, string], error) { refs, err := reflecthelpers.FindSecretReferences(metaObject) if err != nil { - return genruntime.Resolved[genruntime.SecretReference]{}, errors.Wrapf(err, "finding secrets on %q", metaObject.GetName()) + return genruntime.Resolved[genruntime.SecretReference, string]{}, errors.Wrapf(err, "finding secrets on %q", metaObject.GetName()) } // Include the namespace @@ -308,7 +308,7 @@ func (r *Resolver) ResolveResourceSecretReferences(ctx context.Context, metaObje // resolve them resolvedSecrets, err := r.ResolveSecretReferences(ctx, namespacedSecretRefs) if err != nil { - return genruntime.Resolved[genruntime.SecretReference]{}, errors.Wrapf(err, "failed resolving secret references") + return genruntime.Resolved[genruntime.SecretReference, string]{}, errors.Wrapf(err, "failed resolving secret references") } return resolvedSecrets, nil @@ -318,15 +318,15 @@ func (r *Resolver) ResolveResourceSecretReferences(ctx context.Context, metaObje func (r *Resolver) ResolveConfigMapReferences( ctx context.Context, refs set.Set[genruntime.NamespacedConfigMapReference], -) (genruntime.Resolved[genruntime.ConfigMapReference], error) { +) (genruntime.Resolved[genruntime.ConfigMapReference, string], error) { return r.kubeConfigMapResolver.ResolveConfigMapReferences(ctx, refs) } // ResolveResourceConfigMapReferences resolves the specified genruntime.MetaObject's configmap references. -func (r *Resolver) ResolveResourceConfigMapReferences(ctx context.Context, metaObject genruntime.MetaObject) (genruntime.Resolved[genruntime.ConfigMapReference], error) { +func (r *Resolver) ResolveResourceConfigMapReferences(ctx context.Context, metaObject genruntime.MetaObject) (genruntime.Resolved[genruntime.ConfigMapReference, string], error) { refs, err := reflecthelpers.FindConfigMapReferences(metaObject) if err != nil { - return genruntime.Resolved[genruntime.ConfigMapReference]{}, errors.Wrapf(err, "finding config maps on %q", metaObject.GetName()) + return genruntime.Resolved[genruntime.ConfigMapReference, string]{}, errors.Wrapf(err, "finding config maps on %q", metaObject.GetName()) } // Include the namespace @@ -338,7 +338,7 @@ func (r *Resolver) ResolveResourceConfigMapReferences(ctx context.Context, metaO // resolve them resolvedConfigMaps, err := r.ResolveConfigMapReferences(ctx, namespacedConfigMapReferences) if err != nil { - return genruntime.Resolved[genruntime.ConfigMapReference]{}, errors.Wrapf(err, "failed resolving config map references") + return genruntime.Resolved[genruntime.ConfigMapReference, string]{}, errors.Wrapf(err, "failed resolving config map references") } return resolvedConfigMaps, nil diff --git a/v2/internal/resolver/secret_resolver.go b/v2/internal/resolver/secret_resolver.go index 9cdaeb47bc4..c849ce87fa0 100644 --- a/v2/internal/resolver/secret_resolver.go +++ b/v2/internal/resolver/secret_resolver.go @@ -22,7 +22,7 @@ import ( // SecretResolver is a secret resolver type SecretResolver interface { ResolveSecretReference(ctx context.Context, ref genruntime.NamespacedSecretReference) (string, error) - ResolveSecretReferences(ctx context.Context, refs set.Set[genruntime.NamespacedSecretReference]) (genruntime.Resolved[genruntime.SecretReference], error) + ResolveSecretReferences(ctx context.Context, refs set.Set[genruntime.NamespacedSecretReference]) (genruntime.Resolved[genruntime.SecretReference, string], error) } // kubeSecretResolver resolves Kubernetes secrets @@ -68,16 +68,16 @@ func (r *kubeSecretResolver) ResolveSecretReference(ctx context.Context, ref gen } // ResolveSecretReferences resolves all provided secret references -func (r *kubeSecretResolver) ResolveSecretReferences(ctx context.Context, refs set.Set[genruntime.NamespacedSecretReference]) (genruntime.Resolved[genruntime.SecretReference], error) { +func (r *kubeSecretResolver) ResolveSecretReferences(ctx context.Context, refs set.Set[genruntime.NamespacedSecretReference]) (genruntime.Resolved[genruntime.SecretReference, string], error) { result := make(map[genruntime.SecretReference]string, len(refs)) for ref := range refs { value, err := r.ResolveSecretReference(ctx, ref) if err != nil { - return genruntime.MakeResolved[genruntime.SecretReference](nil), err + return genruntime.MakeResolved[genruntime.SecretReference, string](nil), err } result[ref.SecretReference] = value } - return genruntime.MakeResolved[genruntime.SecretReference](result), nil + return genruntime.MakeResolved[genruntime.SecretReference, string](result), nil } diff --git a/v2/pkg/genruntime/arm_transformer.go b/v2/pkg/genruntime/arm_transformer.go index 295bb7945d5..2f42d93bc35 100644 --- a/v2/pkg/genruntime/arm_transformer.go +++ b/v2/pkg/genruntime/arm_transformer.go @@ -16,16 +16,18 @@ type ConvertToARMResolvedDetails struct { // TODO: We might be able to remove this in favor of using AzureName() everywhere in the future Name string + // TODO: We could collapse all of these Resolved[X, string] into a single Resolved[any, string], if we wanted to... + // ResolvedReferences is a set of references which have been resolved to their ARM IDs. - ResolvedReferences Resolved[ResourceReference] + ResolvedReferences Resolved[ResourceReference, string] // ResolvedSecrets is a set of secret references which have been resolved to the corresponding // secret value. - ResolvedSecrets Resolved[SecretReference] + ResolvedSecrets Resolved[SecretReference, string] // ResolvedConfigMaps is a set of config map references which have been resolved to the corresponding // config map value. - ResolvedConfigMaps Resolved[ConfigMapReference] + ResolvedConfigMaps Resolved[ConfigMapReference, string] } type ToARMConverter interface { diff --git a/v2/pkg/genruntime/configmaps.go b/v2/pkg/genruntime/configmaps.go index 635ee06fb86..19aa8833d68 100644 --- a/v2/pkg/genruntime/configmaps.go +++ b/v2/pkg/genruntime/configmaps.go @@ -120,7 +120,7 @@ func ValidateConfigMapDestinations(destinations []*ConfigMapDestination) (admiss } // LookupOptionalConfigMapReferenceValue looks up a ConfigMapReference if it's not nil, or else returns the provided value -func LookupOptionalConfigMapReferenceValue(resolved Resolved[ConfigMapReference], ref *ConfigMapReference, value *string) (string, error) { +func LookupOptionalConfigMapReferenceValue(resolved Resolved[ConfigMapReference, string], ref *ConfigMapReference, value *string) (string, error) { if ref == nil && value == nil { return "", errors.Errorf("ref and value are both nil") } diff --git a/v2/pkg/genruntime/resolved.go b/v2/pkg/genruntime/resolved.go index 8abc8d77983..574c7141fe8 100644 --- a/v2/pkg/genruntime/resolved.go +++ b/v2/pkg/genruntime/resolved.go @@ -17,32 +17,34 @@ type reference interface { } // Resolved is a set of references which have been resolved for a particular resource. -type Resolved[T reference] struct { +type Resolved[T reference, V any] struct { // resolved is a map of T to value. - resolved map[T]string + resolved map[T]V } // MakeResolved creates a Resolved -func MakeResolved[T reference](resolvedMap map[T]string) Resolved[T] { - return Resolved[T]{ +func MakeResolved[T reference, V any](resolvedMap map[T]V) Resolved[T, V] { + return Resolved[T, V]{ resolved: resolvedMap, } } // Lookup looks up the value for the given reference. If it cannot be found, an error is returned. -func (r Resolved[T]) Lookup(ref T) (string, error) { +func (r Resolved[T, V]) Lookup(ref T) (V, error) { result, ok := r.resolved[ref] if !ok { - return "", errors.Errorf("couldn't find resolved %T %s", ref, ref.String()) + var ret V + return ret, errors.Errorf("couldn't find resolved %T %s", ref, ref.String()) } return result, nil } // LookupFromPtr looks up the value for the given reference. If the reference is nil, an error is returned. // If the value cannot be found, an error is returned -func (r Resolved[T]) LookupFromPtr(ref *T) (string, error) { +func (r Resolved[T, V]) LookupFromPtr(ref *T) (V, error) { if ref == nil { - return "", errors.Errorf("cannot look up secret from nil SecretReference") + var ret V + return ret, errors.Errorf("cannot look up secret from nil SecretReference") } return r.Lookup(*ref)