From a414772899ed12865cdd38d5b49956522bd95aa1 Mon Sep 17 00:00:00 2001 From: Julien Duchesne Date: Mon, 13 May 2024 07:43:56 -0400 Subject: [PATCH] Role: Do not set `version` if `autoIncrementVersion` is true (#139) In Terraform, the user would only set one of the two, but the Crossplane provider tries to set the value it reads back, preventing updates --- config/grafana/config.go | 3 + config/grafana/initializer_role.go | 58 +++++++++++++++++++ .../enterprise/role/zz_controller.go | 3 + 3 files changed, 64 insertions(+) create mode 100644 config/grafana/initializer_role.go diff --git a/config/grafana/config.go b/config/grafana/config.go index 989c087..1de8705 100644 --- a/config/grafana/config.go +++ b/config/grafana/config.go @@ -311,6 +311,9 @@ func Configure(p *ujconfig.Provider) { Extractor: optionalFieldExtractor("uid"), } }) + p.AddResourceConfigurator("grafana_role", func(r *ujconfig.Resource) { + r.InitializerFns = append(r.InitializerFns, createroleInitializer) + }) p.AddResourceConfigurator("grafana_role_assignment", func(r *ujconfig.Resource) { r.References["role_uid"] = ujconfig.Reference{ TerraformName: "grafana_role", diff --git a/config/grafana/initializer_role.go b/config/grafana/initializer_role.go new file mode 100644 index 0000000..2880d10 --- /dev/null +++ b/config/grafana/initializer_role.go @@ -0,0 +1,58 @@ +package grafana + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/crossplane/crossplane-runtime/pkg/fieldpath" + "github.com/crossplane/crossplane-runtime/pkg/reconciler/managed" + "github.com/crossplane/crossplane-runtime/pkg/resource" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func createroleInitializer(client client.Client) managed.Initializer { + return &roleInitializer{ + kube: client, + } +} + +// Based on the Tagger: https://github.com/crossplane/upjet/blob/v1.1.0/pkg/config/resource.go#L268 +type roleInitializer struct { + kube client.Client +} + +// If `autoIncrementVersion` is set to true, the `version` field will be set to the current value of `status.atProvider.version`. +// If the version field was never set, it will be deleted from the forProvider spec. +func (i *roleInitializer) Initialize(ctx context.Context, mg resource.Managed) error { + paved, err := fieldpath.PaveObject(mg) + if err != nil { + return err + } + v, err := paved.GetBool("spec.forProvider.autoIncrementVersion") + if err != nil { + return fmt.Errorf("could not get autoIncrementVersion: %w", err) + } + if !v { + return nil + } + atProviderValue, err := paved.GetValue("status.atProvider.version") + if err == nil { + if err := paved.SetValue("spec.forProvider.version", atProviderValue); err != nil { + return fmt.Errorf("could not set version: %w", err) + } + } else if err := paved.DeleteField("spec.forProvider.version"); err != nil { + return fmt.Errorf("could not delete version: %w", err) + } + pavedByte, err := paved.MarshalJSON() + if err != nil { + return fmt.Errorf("could not marshal modified role spec into JSON: %w", err) + } + if err := json.Unmarshal(pavedByte, mg); err != nil { + return fmt.Errorf("could not unmarshal modified role spec into managed resource interface: %w", err) + } + if err := i.kube.Update(ctx, mg); err != nil { + return fmt.Errorf("could not update managed resource: %w", err) + } + return nil +} diff --git a/internal/controller/enterprise/role/zz_controller.go b/internal/controller/enterprise/role/zz_controller.go index e87cb08..4128cf6 100755 --- a/internal/controller/enterprise/role/zz_controller.go +++ b/internal/controller/enterprise/role/zz_controller.go @@ -29,6 +29,9 @@ import ( func Setup(mgr ctrl.Manager, o tjcontroller.Options) error { name := managed.ControllerName(v1alpha1.Role_GroupVersionKind.String()) var initializers managed.InitializerChain + for _, i := range o.Provider.Resources["grafana_role"].InitializerFns { + initializers = append(initializers, i(mgr.GetClient())) + } cps := []managed.ConnectionPublisher{managed.NewAPISecretPublisher(mgr.GetClient(), mgr.GetScheme())} if o.SecretStoreConfigGVK != nil { cps = append(cps, connection.NewDetailsManager(mgr.GetClient(), *o.SecretStoreConfigGVK, connection.WithTLSConfig(o.ESSOptions.TLSConfig)))