diff --git a/cmd/migrate/cmd.go b/cmd/migrate/cmd.go index a508b8a..66f980a 100644 --- a/cmd/migrate/cmd.go +++ b/cmd/migrate/cmd.go @@ -22,9 +22,10 @@ import ( func NewCmd(scheme *runtime.Scheme) *cobra.Command { // CLI flags var ( - tenantControlPlane string - targetDataStore string - timeout time.Duration + tenantControlPlane string + targetDataStore string + cleanupPriorMigration bool + timeout time.Duration ) cmd := &cobra.Command{ @@ -95,6 +96,20 @@ func NewCmd(scheme *runtime.Scheme) *cobra.Command { return err } defer targetConnection.Close() + + if cleanupPriorMigration { + log.Info("Checking if target DataStore should be clean-up prior migration") + + if exists, _ := targetConnection.DBExists(ctx, tcp.Status.Storage.Setup.Schema); exists { + log.Info("A colliding schema on target DataStore is present, cleaning up") + + if dErr := targetConnection.DeleteDB(ctx, tcp.Status.Storage.Setup.Schema); dErr != nil { + return fmt.Errorf("error cleaning up prior migration: %s", dErr.Error()) + } + + log.Info("Cleaning up prior migration has been completed") + } + } // Start migrating from the old Datastore to the new one log.Info("migration from origin to target started") @@ -110,6 +125,7 @@ func NewCmd(scheme *runtime.Scheme) *cobra.Command { cmd.Flags().StringVar(&tenantControlPlane, "tenant-control-plane", "", "Namespaced-name of the TenantControlPlane that must be migrated (e.g.: default/test)") cmd.Flags().StringVar(&targetDataStore, "target-datastore", "", "Name of the Datastore to which the TenantControlPlane will be migrated") + cmd.Flags().BoolVar(&cleanupPriorMigration, "cleanup-prior-migration", false, "When set to true, migration job will drop existing data in the target DataStore: useful to avoid stale data when migrating back and forth between DataStores.") cmd.Flags().DurationVar(&timeout, "timeout", 5*time.Minute, "Amount of time for the context timeout") _ = cmd.MarkFlagRequired("tenant-control-plane") diff --git a/docs/content/guides/datastore-migration.md b/docs/content/guides/datastore-migration.md index 7edb978..d533423 100644 --- a/docs/content/guides/datastore-migration.md +++ b/docs/content/guides/datastore-migration.md @@ -172,6 +172,11 @@ After a while, depending on the amount of data to migrate, the Tenant Control Pl !!! info "Leftover" Please, note the datastore migration leaves the data on the default datastore, so you have to remove it manually. +!!! info "Avoiding stale DataStore content" + When migrating `TenantControlPlane` across DataStore, a collision with the __schema__ name could happen, + leading to unexpected results such as old data still available. + The annotation `kamaji.clastix.io/cleanup-prior-migration=true` allows to enforce the clean-up of the target `DataStore` schema in case of collision. + ## Post migration After migrating data to the new datastore, complete the migration procedure by restarting the `kubelet.service` on all the tenant worker nodes. diff --git a/internal/resources/datastore/datastore_migrate.go b/internal/resources/datastore/datastore_migrate.go index 81ef538..f82f6fb 100644 --- a/internal/resources/datastore/datastore_migrate.go +++ b/internal/resources/datastore/datastore_migrate.go @@ -6,6 +6,7 @@ package datastore import ( "context" "fmt" + "strconv" "github.com/prometheus/client_golang/prometheus" batchv1 "k8s.io/api/batch/v1" @@ -122,6 +123,11 @@ func (d *Migrate) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamaji fmt.Sprintf("--target-datastore=%s", tenantControlPlane.Spec.DataStore), } + if tenantControlPlane.GetAnnotations() != nil { + v, _ := strconv.ParseBool(tenantControlPlane.GetAnnotations()["kamaji.clastix.io/cleanup-prior-migration"]) + d.job.Spec.Template.Spec.Containers[0].Args = append(d.job.Spec.Template.Spec.Containers[0].Args, fmt.Sprintf("--cleanup-prior-migration=%t", v)) + } + return nil }) if err != nil {