From 3f56a3d29112f729ac8cee5a88cc4600f91204ba Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Tue, 31 Dec 2024 14:09:57 +0100 Subject: [PATCH 01/19] Started implementing CRB backup --- hack/runtime-migrator/cmd/backup/backup.go | 16 ++++--- .../internal/backup/backup.go | 34 +++++++++++--- .../internal/initialisation/client.go | 44 +++++++++++++++++++ 3 files changed, 82 insertions(+), 12 deletions(-) diff --git a/hack/runtime-migrator/cmd/backup/backup.go b/hack/runtime-migrator/cmd/backup/backup.go index f4fa8d9d..9eb106c2 100644 --- a/hack/runtime-migrator/cmd/backup/backup.go +++ b/hack/runtime-migrator/cmd/backup/backup.go @@ -10,6 +10,7 @@ import ( "github.com/kyma-project/infrastructure-manager/pkg/gardener/kubeconfig" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "log/slog" + "sigs.k8s.io/controller-runtime/pkg/client" "time" ) @@ -21,23 +22,24 @@ const ( type Backup struct { shootClient gardener_types.ShootInterface kubeconfigProvider kubeconfig.Provider + kcpClient client.Client outputWriter backup.OutputWriter results backup.Results cfg initialisation.Config } -func NewBackup(cfg initialisation.Config, kubeconfigProvider kubeconfig.Provider, shootClient gardener_types.ShootInterface) (Backup, error) { +func NewBackup(cfg initialisation.Config, kcpClient client.Client, shootClient gardener_types.ShootInterface) (Backup, error) { outputWriter, err := backup.NewOutputWriter(cfg.OutputPath) if err != nil { return Backup{}, err } return Backup{ - shootClient: shootClient, - kubeconfigProvider: kubeconfigProvider, - outputWriter: outputWriter, - results: backup.NewBackupResults(outputWriter.NewResultsDir), - cfg: cfg, + shootClient: shootClient, + kcpClient: kcpClient, + outputWriter: outputWriter, + results: backup.NewBackupResults(outputWriter.NewResultsDir), + cfg: cfg, }, nil } @@ -50,7 +52,7 @@ func (b Backup) Do(ctx context.Context, runtimeIDs []string) error { return err } - backuper := backup.NewBackuper(b.cfg.IsDryRun, b.kubeconfigProvider) + backuper := backup.NewBackuper(b.cfg.IsDryRun, b.kcpClient) for _, runtimeID := range runtimeIDs { shootToBackup, err := shoot.Fetch(ctx, shootList, b.shootClient, runtimeID) diff --git a/hack/runtime-migrator/internal/backup/backup.go b/hack/runtime-migrator/internal/backup/backup.go index c94b1779..359de86c 100644 --- a/hack/runtime-migrator/internal/backup/backup.go +++ b/hack/runtime-migrator/internal/backup/backup.go @@ -8,18 +8,20 @@ import ( "github.com/kyma-project/infrastructure-manager/pkg/gardener/kubeconfig" rbacv1 "k8s.io/api/rbac/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" ) type Backuper struct { cfg initialisation.Config isDryRun bool kubeconfigProvider kubeconfig.Provider + kcpClient client.Client } -func NewBackuper(isDryRun bool, kubeconfigProvider kubeconfig.Provider) Backuper { +func NewBackuper(isDryRun bool, kcpClient client.Client) Backuper { return Backuper{ - isDryRun: isDryRun, - kubeconfigProvider: kubeconfigProvider, + isDryRun: isDryRun, + kcpClient: kcpClient, } } @@ -31,9 +33,15 @@ type RuntimeBackup struct { } func (b Backuper) Do(_ context.Context, shoot v1beta1.Shoot) (RuntimeBackup, error) { + crbs, err := b.getCRBs(shoot.Labels["kcp.provisioner.kyma-project.io/runtime-id"]) + if err != nil { + return RuntimeBackup{}, err + } + return RuntimeBackup{ - ShootToRestore: b.getShootToRestore(shoot), - OriginalShoot: shoot, + ShootToRestore: b.getShootToRestore(shoot), + OriginalShoot: shoot, + ClusterRoleBindings: crbs, }, nil } @@ -84,3 +92,19 @@ func (b Backuper) getShootToRestore(shootFromGardener v1beta1.Shoot) v1beta1.Sho }, } } + +func (b Backuper) getCRBs(runtimeID string) ([]rbacv1.ClusterRoleBinding, error) { + runtimeClient, err := initialisation.GetRuntimeClient(context.Background(), b.kcpClient, runtimeID) + if err != nil { + return nil, err + } + + var crbList rbacv1.ClusterRoleBindingList + err = runtimeClient.List(context.Background(), &crbList) + + if err != nil { + return nil, err + } + + return crbList.Items, nil +} diff --git a/hack/runtime-migrator/internal/initialisation/client.go b/hack/runtime-migrator/internal/initialisation/client.go index 2868f1b5..59844e6d 100644 --- a/hack/runtime-migrator/internal/initialisation/client.go +++ b/hack/runtime-migrator/internal/initialisation/client.go @@ -1,6 +1,7 @@ package initialisation import ( + "context" "fmt" "github.com/gardener/gardener/pkg/apis/core/v1beta1" gardener_types "github.com/gardener/gardener/pkg/client/core/clientset/versioned/typed/core/v1beta1" @@ -10,11 +11,16 @@ import ( "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/clientcmd" "sigs.k8s.io/controller-runtime/pkg/client" "time" ) +const ( + kubeconfigSecretKey = "config" +) + func addToScheme(s *runtime.Scheme) error { for _, add := range []func(s *runtime.Scheme) error{ corev1.AddToScheme, @@ -102,3 +108,41 @@ func SetupGardenerShootClients(kubeconfigPath, gardenerNamespace string) (garden return shootClient, dynamicClient, err } + +//nolint:gochecknoglobals +func GetRuntimeClient(ctx context.Context, kcpClient client.Client, runtimeID string) (client.Client, error) { + secret, err := getKubeconfigSecret(ctx, kcpClient, runtimeID, "kcp-system") + if err != nil { + return nil, err + } + + restConfig, err := clientcmd.RESTConfigFromKubeConfig(secret.Data[kubeconfigSecretKey]) + if err != nil { + return nil, err + } + + shootClientWithAdmin, err := client.New(restConfig, client.Options{}) + if err != nil { + return nil, err + } + + return shootClientWithAdmin, nil +} + +func getKubeconfigSecret(ctx context.Context, cnt client.Client, runtimeID, namespace string) (corev1.Secret, error) { + secretName := fmt.Sprintf("kubeconfig-%s", runtimeID) + + var kubeconfigSecret corev1.Secret + secretKey := types.NamespacedName{Name: secretName, Namespace: namespace} + + err := cnt.Get(ctx, secretKey, &kubeconfigSecret) + + if err != nil { + return corev1.Secret{}, err + } + + if kubeconfigSecret.Data == nil { + return corev1.Secret{}, fmt.Errorf("kubeconfig secret `%s` does not contain kubeconfig data", kubeconfigSecret.Name) + } + return kubeconfigSecret, nil +} From d53562879ea57d12b7dc31a60630a2b8cb743268 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Tue, 31 Dec 2024 14:39:23 +0100 Subject: [PATCH 02/19] CRB backup implemented --- .../runtime-migrator/internal/backup/output.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/hack/runtime-migrator/internal/backup/output.go b/hack/runtime-migrator/internal/backup/output.go index 452b0a05..e03f73c9 100644 --- a/hack/runtime-migrator/internal/backup/output.go +++ b/hack/runtime-migrator/internal/backup/output.go @@ -40,16 +40,30 @@ func NewOutputWriter(outputDir string) (OutputWriter, error) { } func (ow OutputWriter) Save(runtimeID string, runtimeBackup RuntimeBackup) error { - err := os.MkdirAll(fmt.Sprintf("%s/%s", ow.BackupDir, runtimeID), os.ModePerm) + runtimeDir := fmt.Sprintf("%s/%s", ow.BackupDir, runtimeID) + err := os.MkdirAll(runtimeDir, os.ModePerm) if err != nil { return err } - err = saveYaml(runtimeBackup.ShootToRestore, fmt.Sprintf("%s/%s/%s-to-restore.yaml", ow.BackupDir, runtimeID, runtimeBackup.ShootToRestore.Name)) + err = saveYaml(runtimeBackup.ShootToRestore, fmt.Sprintf("%s/%s-to-restore.yaml", runtimeDir, runtimeBackup.ShootToRestore.Name)) if err != nil { return err } + crbDir := fmt.Sprintf("%s/crb", runtimeDir) + err = os.MkdirAll(crbDir, os.ModePerm) + if err != nil { + return err + } + + for _, crb := range runtimeBackup.ClusterRoleBindings { + err = saveYaml(crb, fmt.Sprintf("%s/%s.yaml", crbDir, crb.Name)) + if err != nil { + return err + } + } + return saveYaml(runtimeBackup.OriginalShoot, fmt.Sprintf("%s/%s/%s-original.yaml", ow.BackupDir, runtimeID, runtimeBackup.OriginalShoot.Name)) } From 611150b43be2c806c0b11590c4e9cb7c4f0b578b Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Tue, 31 Dec 2024 15:05:10 +0100 Subject: [PATCH 03/19] Started implementing CRB backup --- .../internal/restore/restorer.go | 67 ++++++++++++++++--- 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/hack/runtime-migrator/internal/restore/restorer.go b/hack/runtime-migrator/internal/restore/restorer.go index 6ada323e..84c28f98 100644 --- a/hack/runtime-migrator/internal/restore/restorer.go +++ b/hack/runtime-migrator/internal/restore/restorer.go @@ -3,6 +3,8 @@ package restore import ( "fmt" "github.com/gardener/gardener/pkg/apis/core/v1beta1" + "github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/backup" + rbacv1 "k8s.io/api/rbac/v1" "os" "path" "sigs.k8s.io/yaml" @@ -18,23 +20,72 @@ func NewRestorer(backupDir string) Restorer { } } -func (r Restorer) Do(runtimeID string, shootName string) (v1beta1.Shoot, error) { - filePath := path.Join(r.backupDir, fmt.Sprintf("backup/%s/%s-to-restore.yaml", runtimeID, shootName)) +func (r Restorer) Do(runtimeID string, shootName string) (backup.RuntimeBackup, error) { + shoot, err := r.getShootToRestore(runtimeID, shootName) + if err != nil { + return backup.RuntimeBackup{}, err + } - fileBytes, err := os.ReadFile(filePath) + crbs, err := r.getCRBsToRestore(runtimeID) if err != nil { - return v1beta1.Shoot{}, err + return backup.RuntimeBackup{}, err } - var shoot v1beta1.Shoot + return backup.RuntimeBackup{ + ShootToRestore: shoot, + ClusterRoleBindings: crbs, + }, nil +} + +func (r Restorer) getShootToRestore(runtimeID string, shootName string) (v1beta1.Shoot, error) { + shootFilePath := path.Join(r.backupDir, fmt.Sprintf("backup/%s/%s-to-restore.yaml", runtimeID, shootName)) - err = yaml.Unmarshal(fileBytes, &shoot) + shoot, err := restoreFromFile[v1beta1.Shoot](shootFilePath) if err != nil { return v1beta1.Shoot{}, err } - shoot.Kind = "Shoot" shoot.APIVersion = "core.gardener.cloud/v1beta1" - return shoot, nil + return *shoot, nil +} + +func (r Restorer) getCRBsToRestore(runtimeID string) ([]rbacv1.ClusterRoleBinding, error) { + crbsDir := path.Join("%s/%s/crb", r.backupDir, runtimeID) + entries, err := os.ReadDir(crbsDir) + + if err != nil { + return nil, err + } + + crbs := make([]rbacv1.ClusterRoleBinding, 0) + + for _, entry := range entries { + crbFilePath := entry.Name() + + crb, err := restoreFromFile[rbacv1.ClusterRoleBinding](crbFilePath) + if err != nil { + return nil, err + } + + crbs = append(crbs, *crb) + } + + return crbs, nil +} + +func restoreFromFile[T any](filePath string) (*T, error) { + fileBytes, err := os.ReadFile(filePath) + if err != nil { + return nil, err + } + + var obj T + + err = yaml.Unmarshal(fileBytes, &obj) + if err != nil { + return nil, err + } + + return &obj, nil } From 57c21e142c387c7a1052dd129556d7d61384feda Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Tue, 31 Dec 2024 15:25:09 +0100 Subject: [PATCH 04/19] Fix in backup --- hack/runtime-migrator/cmd/backup/backup.go | 2 +- hack/runtime-migrator/cmd/backup/main.go | 10 +++++----- hack/runtime-migrator/internal/backup/backup.go | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hack/runtime-migrator/cmd/backup/backup.go b/hack/runtime-migrator/cmd/backup/backup.go index 9eb106c2..697f6e8d 100644 --- a/hack/runtime-migrator/cmd/backup/backup.go +++ b/hack/runtime-migrator/cmd/backup/backup.go @@ -71,7 +71,7 @@ func (b Backup) Do(ctx context.Context, runtimeIDs []string) error { continue } - runtimeBackup, err := backuper.Do(ctx, *shootToBackup) + runtimeBackup, err := backuper.Do(ctx, *shootToBackup, runtimeID) if err != nil { errMsg := fmt.Sprintf("Failed to backup runtime: %v", err) b.results.ErrorOccurred(runtimeID, shootToBackup.Name, errMsg) diff --git a/hack/runtime-migrator/cmd/backup/main.go b/hack/runtime-migrator/cmd/backup/main.go index 6ffdbb4d..e7af47b8 100644 --- a/hack/runtime-migrator/cmd/backup/main.go +++ b/hack/runtime-migrator/cmd/backup/main.go @@ -24,19 +24,19 @@ func main() { gardenerNamespace := fmt.Sprintf("garden-%s", cfg.GardenerProjectName) - kubeconfigProvider, err := initialisation.SetupKubernetesKubeconfigProvider(cfg.GardenerKubeconfigPath, gardenerNamespace, expirationTime) + shootClient, _, err := initialisation.SetupGardenerShootClients(cfg.GardenerKubeconfigPath, gardenerNamespace) if err != nil { - slog.Error(fmt.Sprintf("Failed to create kubeconfig provider: %v", err)) + slog.Error("Failed to setup Gardener shoot client", slog.Any("error", err)) os.Exit(1) } - shootClient, _, err := initialisation.SetupGardenerShootClients(cfg.GardenerKubeconfigPath, gardenerNamespace) + kcpClient, err := initialisation.CreateKcpClient(&cfg) if err != nil { - slog.Error("Failed to setup Gardener shoot client", slog.Any("error", err)) + slog.Error("Failed to create kcp client", slog.Any("error", err)) os.Exit(1) } - backup, err := NewBackup(cfg, kubeconfigProvider, shootClient) + backup, err := NewBackup(cfg, kcpClient, shootClient) if err != nil { slog.Error("Failed to initialize backup", slog.Any("error", err)) os.Exit(1) diff --git a/hack/runtime-migrator/internal/backup/backup.go b/hack/runtime-migrator/internal/backup/backup.go index 359de86c..f201ba31 100644 --- a/hack/runtime-migrator/internal/backup/backup.go +++ b/hack/runtime-migrator/internal/backup/backup.go @@ -32,8 +32,8 @@ type RuntimeBackup struct { OIDCConfig []authenticationv1alpha1.OpenIDConnect } -func (b Backuper) Do(_ context.Context, shoot v1beta1.Shoot) (RuntimeBackup, error) { - crbs, err := b.getCRBs(shoot.Labels["kcp.provisioner.kyma-project.io/runtime-id"]) +func (b Backuper) Do(_ context.Context, shoot v1beta1.Shoot, runtimeID string) (RuntimeBackup, error) { + crbs, err := b.getCRBs(runtimeID) if err != nil { return RuntimeBackup{}, err } From acab547c4043eff8636b9aaba60ba7341c6a1157 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Thu, 2 Jan 2025 11:43:12 +0100 Subject: [PATCH 05/19] Restore crbs implemented --- hack/runtime-migrator/cmd/restore/main.go | 6 +-- hack/runtime-migrator/cmd/restore/restore.go | 55 +++++++++++++++++--- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/hack/runtime-migrator/cmd/restore/main.go b/hack/runtime-migrator/cmd/restore/main.go index 0dd9cb63..b7140b24 100644 --- a/hack/runtime-migrator/cmd/restore/main.go +++ b/hack/runtime-migrator/cmd/restore/main.go @@ -24,13 +24,13 @@ func main() { gardenerNamespace := fmt.Sprintf("garden-%s", cfg.GardenerProjectName) - kubeconfigProvider, err := initialisation.SetupKubernetesKubeconfigProvider(cfg.GardenerKubeconfigPath, gardenerNamespace, expirationTime) + _, err := initialisation.SetupKubernetesKubeconfigProvider(cfg.GardenerKubeconfigPath, gardenerNamespace, expirationTime) if err != nil { slog.Error(fmt.Sprintf("Failed to create kubeconfig provider: %v", err)) os.Exit(1) } - _, err = initialisation.CreateKcpClient(&cfg.Config) + kcpClient, err := initialisation.CreateKcpClient(&cfg.Config) if err != nil { slog.Error("Failed to create kcp client", slog.Any("error", err)) os.Exit(1) @@ -42,7 +42,7 @@ func main() { os.Exit(1) } - restore, err := NewRestore(cfg, kubeconfigProvider, shootClient, dynamicGardenerClient) + restore, err := NewRestore(cfg, kcpClient, shootClient, dynamicGardenerClient) if err != nil { slog.Error("Failed to setup Gardener shoot client", slog.Any("error", err)) os.Exit(1) diff --git a/hack/runtime-migrator/cmd/restore/restore.go b/hack/runtime-migrator/cmd/restore/restore.go index 553aa675..87842c97 100644 --- a/hack/runtime-migrator/cmd/restore/restore.go +++ b/hack/runtime-migrator/cmd/restore/restore.go @@ -5,10 +5,11 @@ import ( "fmt" "github.com/gardener/gardener/pkg/apis/core/v1beta1" gardener_types "github.com/gardener/gardener/pkg/client/core/clientset/versioned/typed/core/v1beta1" + "github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/backup" "github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/initialisation" "github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/restore" "github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/shoot" - "github.com/kyma-project/infrastructure-manager/pkg/gardener/kubeconfig" + v12 "k8s.io/api/rbac/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" "log/slog" @@ -24,7 +25,7 @@ const ( type Restore struct { shootClient gardener_types.ShootInterface dynamicGardenerClient client.Client - kubeconfigProvider kubeconfig.Provider + kcpClient client.Client outputWriter restore.OutputWriter results restore.Results cfg initialisation.RestoreConfig @@ -32,7 +33,7 @@ type Restore struct { const fieldManagerName = "kim" -func NewRestore(cfg initialisation.RestoreConfig, kubeconfigProvider kubeconfig.Provider, shootClient gardener_types.ShootInterface, dynamicGardenerClient client.Client) (Restore, error) { +func NewRestore(cfg initialisation.RestoreConfig, kcpClient client.Client, shootClient gardener_types.ShootInterface, dynamicGardenerClient client.Client) (Restore, error) { outputWriter, err := restore.NewOutputWriter(cfg.OutputPath) if err != nil { return Restore{}, err @@ -41,7 +42,7 @@ func NewRestore(cfg initialisation.RestoreConfig, kubeconfigProvider kubeconfig. return Restore{ shootClient: shootClient, dynamicGardenerClient: dynamicGardenerClient, - kubeconfigProvider: kubeconfigProvider, + kcpClient: kcpClient, outputWriter: outputWriter, results: restore.NewRestoreResults(outputWriter.NewResultsDir), cfg: cfg, @@ -77,7 +78,7 @@ func (r Restore) Do(ctx context.Context, runtimeIDs []string) error { continue } - shootToRestore, err := restorer.Do(runtimeID, currentShoot.Name) + objectsToRestore, err := restorer.Do(runtimeID, currentShoot.Name) if err != nil { errMsg := fmt.Sprintf("Failed to restore runtime: %v", err) r.results.ErrorOccurred(runtimeID, currentShoot.Name, errMsg) @@ -93,7 +94,7 @@ func (r Restore) Do(ctx context.Context, runtimeIDs []string) error { continue } - err = r.applyResources(ctx, shootToRestore) + err = r.applyResources(ctx, objectsToRestore, runtimeID) if err != nil { errMsg := fmt.Sprintf("Failed to restore runtime: %v", err) r.results.ErrorOccurred(runtimeID, currentShoot.Name, errMsg) @@ -117,12 +118,50 @@ func (r Restore) Do(ctx context.Context, runtimeIDs []string) error { return nil } -func (r Restore) applyResources(ctx context.Context, shootToRestore v1beta1.Shoot) error { +func (r Restore) applyResources(ctx context.Context, objectsToRestore backup.RuntimeBackup, runtimeID string) error { + err := r.applyShoot(ctx, objectsToRestore.ShootToRestore) + if err != nil { + return err + } + + clusterClient, err := initialisation.GetRuntimeClient(ctx, r.kcpClient, runtimeID) + if err != nil { + return err + } + + err = r.applyCRBs(ctx, clusterClient, objectsToRestore.ClusterRoleBindings) + if err != nil { + return err + } + + return nil +} + +func (r Restore) applyShoot(ctx context.Context, shoot v1beta1.Shoot) error { patchCtx, cancel := context.WithTimeout(ctx, timeoutK8sOperation) defer cancel() - return r.dynamicGardenerClient.Patch(patchCtx, &shootToRestore, client.Apply, &client.PatchOptions{ + return r.dynamicGardenerClient.Patch(patchCtx, &shoot, client.Apply, &client.PatchOptions{ FieldManager: fieldManagerName, Force: ptr.To(true), }) } + +func (r Restore) applyCRBs(ctx context.Context, clusterClient client.Client, crbs []v12.ClusterRoleBinding) error { + for _, crb := range crbs { + if err := applyCRB(ctx, crb, clusterClient); err != nil { + return err + } + } + + return nil +} + +func applyCRB(ctx context.Context, object v12.ClusterRoleBinding, clusterClient client.Client) error { + ctx, cancel := context.WithTimeout(ctx, timeoutK8sOperation) + defer cancel() + + return clusterClient.Update(ctx, &object, &client.UpdateOptions{ + FieldManager: fieldManagerName, + }) +} From a3e36f7ab203042f2131079bf28f1bad854a4048 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Thu, 2 Jan 2025 12:55:57 +0100 Subject: [PATCH 06/19] Backup crbs that refer to cluster-admin ClusterRole only --- hack/runtime-migrator/cmd/backup/backup.go | 2 +- hack/runtime-migrator/internal/backup/backup.go | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/hack/runtime-migrator/cmd/backup/backup.go b/hack/runtime-migrator/cmd/backup/backup.go index 697f6e8d..0f6a0659 100644 --- a/hack/runtime-migrator/cmd/backup/backup.go +++ b/hack/runtime-migrator/cmd/backup/backup.go @@ -94,7 +94,7 @@ func (b Backup) Do(ctx context.Context, runtimeIDs []string) error { continue } - slog.Info("Runtime backup created successfully successfully", "runtimeID", runtimeID) + slog.Info("Runtime backup created successfully", "runtimeID", runtimeID) b.results.OperationSucceeded(runtimeID, shootToBackup.Name) } diff --git a/hack/runtime-migrator/internal/backup/backup.go b/hack/runtime-migrator/internal/backup/backup.go index f201ba31..a90a81b6 100644 --- a/hack/runtime-migrator/internal/backup/backup.go +++ b/hack/runtime-migrator/internal/backup/backup.go @@ -106,5 +106,13 @@ func (b Backuper) getCRBs(runtimeID string) ([]rbacv1.ClusterRoleBinding, error) return nil, err } - return crbList.Items, nil + crbsToBackup := make([]rbacv1.ClusterRoleBinding, 0) + + for _, crb := range crbList.Items { + if crb.RoleRef.Kind == "ClusterRole" && crb.RoleRef.Name == "cluster-admin" { + crbsToBackup = append(crbsToBackup, crb) + } + } + + return crbsToBackup, nil } From 4eff7bb8292c5ca8ce4537cef848037788e0735a Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Thu, 2 Jan 2025 14:19:33 +0100 Subject: [PATCH 07/19] OIDC backup restore implemented --- .../internal/backup/backup.go | 34 ++++++++++++++----- .../internal/backup/output.go | 13 +++++++ .../internal/restore/restorer.go | 31 +++++++++++++++++ 3 files changed, 70 insertions(+), 8 deletions(-) diff --git a/hack/runtime-migrator/internal/backup/backup.go b/hack/runtime-migrator/internal/backup/backup.go index a90a81b6..041fba07 100644 --- a/hack/runtime-migrator/internal/backup/backup.go +++ b/hack/runtime-migrator/internal/backup/backup.go @@ -33,7 +33,17 @@ type RuntimeBackup struct { } func (b Backuper) Do(_ context.Context, shoot v1beta1.Shoot, runtimeID string) (RuntimeBackup, error) { - crbs, err := b.getCRBs(runtimeID) + runtimeClient, err := initialisation.GetRuntimeClient(context.Background(), b.kcpClient, runtimeID) + if err != nil { + return RuntimeBackup{}, err + } + + crbs, err := b.getCRBs(runtimeClient) + if err != nil { + return RuntimeBackup{}, err + } + + oidcConfig, err := b.getOIDCConfig(runtimeClient) if err != nil { return RuntimeBackup{}, err } @@ -42,6 +52,7 @@ func (b Backuper) Do(_ context.Context, shoot v1beta1.Shoot, runtimeID string) ( ShootToRestore: b.getShootToRestore(shoot), OriginalShoot: shoot, ClusterRoleBindings: crbs, + OIDCConfig: oidcConfig, }, nil } @@ -93,14 +104,9 @@ func (b Backuper) getShootToRestore(shootFromGardener v1beta1.Shoot) v1beta1.Sho } } -func (b Backuper) getCRBs(runtimeID string) ([]rbacv1.ClusterRoleBinding, error) { - runtimeClient, err := initialisation.GetRuntimeClient(context.Background(), b.kcpClient, runtimeID) - if err != nil { - return nil, err - } - +func (b Backuper) getCRBs(runtimeClient client.Client) ([]rbacv1.ClusterRoleBinding, error) { var crbList rbacv1.ClusterRoleBindingList - err = runtimeClient.List(context.Background(), &crbList) + err := runtimeClient.List(context.Background(), &crbList) if err != nil { return nil, err @@ -116,3 +122,15 @@ func (b Backuper) getCRBs(runtimeID string) ([]rbacv1.ClusterRoleBinding, error) return crbsToBackup, nil } + +func (b Backuper) getOIDCConfig(runtimeClient client.Client) ([]authenticationv1alpha1.OpenIDConnect, error) { + var oidcConfigList authenticationv1alpha1.OpenIDConnectList + + err := runtimeClient.List(context.Background(), &oidcConfigList) + + if err != nil { + return nil, err + } + + return oidcConfigList.Items, nil +} diff --git a/hack/runtime-migrator/internal/backup/output.go b/hack/runtime-migrator/internal/backup/output.go index e03f73c9..5256c28a 100644 --- a/hack/runtime-migrator/internal/backup/output.go +++ b/hack/runtime-migrator/internal/backup/output.go @@ -64,6 +64,19 @@ func (ow OutputWriter) Save(runtimeID string, runtimeBackup RuntimeBackup) error } } + oidcDir := fmt.Sprintf("%s/oidc", runtimeDir) + err = os.MkdirAll(oidcDir, os.ModePerm) + if err != nil { + return err + } + + for _, oidcConfig := range runtimeBackup.OIDCConfig { + err = saveYaml(oidcConfig, fmt.Sprintf("%s/%s.yaml", crbDir, oidcConfig.Name)) + if err != nil { + return err + } + } + return saveYaml(runtimeBackup.OriginalShoot, fmt.Sprintf("%s/%s/%s-original.yaml", ow.BackupDir, runtimeID, runtimeBackup.OriginalShoot.Name)) } diff --git a/hack/runtime-migrator/internal/restore/restorer.go b/hack/runtime-migrator/internal/restore/restorer.go index 84c28f98..869fd251 100644 --- a/hack/runtime-migrator/internal/restore/restorer.go +++ b/hack/runtime-migrator/internal/restore/restorer.go @@ -3,6 +3,7 @@ package restore import ( "fmt" "github.com/gardener/gardener/pkg/apis/core/v1beta1" + authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" "github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/backup" rbacv1 "k8s.io/api/rbac/v1" "os" @@ -31,9 +32,15 @@ func (r Restorer) Do(runtimeID string, shootName string) (backup.RuntimeBackup, return backup.RuntimeBackup{}, err } + oidcConfig, err := r.getOIDCConfigToRestore(runtimeID) + if err != nil { + return backup.RuntimeBackup{}, err + } + return backup.RuntimeBackup{ ShootToRestore: shoot, ClusterRoleBindings: crbs, + OIDCConfig: oidcConfig, }, nil } @@ -74,6 +81,30 @@ func (r Restorer) getCRBsToRestore(runtimeID string) ([]rbacv1.ClusterRoleBindin return crbs, nil } +func (r Restorer) getOIDCConfigToRestore(runtimeID string) ([]authenticationv1alpha1.OpenIDConnect, error) { + crbsDir := path.Join("%s/%s/oidc", r.backupDir, runtimeID) + entries, err := os.ReadDir(crbsDir) + + if err != nil { + return nil, err + } + + crbs := make([]authenticationv1alpha1.OpenIDConnect, 0) + + for _, entry := range entries { + crbFilePath := entry.Name() + + crb, err := restoreFromFile[authenticationv1alpha1.OpenIDConnect](crbFilePath) + if err != nil { + return nil, err + } + + crbs = append(crbs, *crb) + } + + return crbs, nil +} + func restoreFromFile[T any](filePath string) (*T, error) { fileBytes, err := os.ReadFile(filePath) if err != nil { From 3f991d1669260e0f5d0a55d93543d27d57ed6615 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Thu, 2 Jan 2025 15:12:31 +0100 Subject: [PATCH 08/19] Added checks for shoot generation before restore --- hack/runtime-migrator/cmd/restore/restore.go | 16 +++++++++- .../internal/restore/results.go | 30 +++++++++++++++++-- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/hack/runtime-migrator/cmd/restore/restore.go b/hack/runtime-migrator/cmd/restore/restore.go index 87842c97..f5ab5603 100644 --- a/hack/runtime-migrator/cmd/restore/restore.go +++ b/hack/runtime-migrator/cmd/restore/restore.go @@ -87,6 +87,20 @@ func (r Restore) Do(ctx context.Context, runtimeIDs []string) error { continue } + if currentShoot.Generation == objectsToRestore.OriginalShoot.Generation { + slog.Warn("Verify the current state of the system. Shoot was not modified after backup was prepared. Skipping.", "runtimeID", runtimeID) + r.results.OperationSkipped(runtimeID, currentShoot.Name) + + continue + } + + if currentShoot.Generation > objectsToRestore.OriginalShoot.Generation+1 { + slog.Warn("Verify the current state of the system. Restore should be performed manually, as the backup may overwrite more that on change.", "runtimeID", runtimeID) + r.results.AutomaticRestoreImpossible(runtimeID, currentShoot.Name) + + continue + } + if r.cfg.IsDryRun { slog.Info("Runtime processed successfully (dry-run)", "runtimeID", runtimeID) r.results.OperationSucceeded(runtimeID, currentShoot.Name) @@ -112,7 +126,7 @@ func (r Restore) Do(ctx context.Context, runtimeIDs []string) error { return err } - slog.Info(fmt.Sprintf("Restore completed. Successfully restored backups: %d, Failed operations: %d", r.results.Succeeded, r.results.Failed)) + slog.Info(fmt.Sprintf("Restore completed. Successfully restored backups: %d, Failed operations: %d, Skipped backups: %d, ", r.results.Succeeded, r.results.Failed, r.results.Skipped)) slog.Info(fmt.Sprintf("Restore results saved in: %s", resultsFile)) return nil diff --git a/hack/runtime-migrator/internal/restore/results.go b/hack/runtime-migrator/internal/restore/results.go index 347fa569..252fa32d 100644 --- a/hack/runtime-migrator/internal/restore/results.go +++ b/hack/runtime-migrator/internal/restore/results.go @@ -3,8 +3,10 @@ package restore type StatusType string const ( - StatusSuccess StatusType = "Success" - StatusError StatusType = "Error" + StatusSuccess StatusType = "Success" + StatusError StatusType = "Error" + StatusRestoreSkipped = "Skipped" + StatusUpdateDetected = "UpdateDetected" ) type RuntimeResult struct { @@ -18,6 +20,8 @@ type Results struct { Results []RuntimeResult Succeeded int Failed int + Skipped int + UpdateDetected int OutputDirectory string } @@ -50,3 +54,25 @@ func (br *Results) OperationSucceeded(runtimeID string, shootName string) { br.Succeeded++ br.Results = append(br.Results, result) } + +func (br *Results) OperationSkipped(runtimeID string, shootName string) { + result := RuntimeResult{ + RuntimeID: runtimeID, + ShootName: shootName, + Status: StatusRestoreSkipped, + } + + br.Skipped++ + br.Results = append(br.Results, result) +} + +func (br *Results) AutomaticRestoreImpossible(runtimeID string, shootName string) { + result := RuntimeResult{ + RuntimeID: runtimeID, + ShootName: shootName, + Status: StatusUpdateDetected, + } + + br.UpdateDetected++ + br.Results = append(br.Results, result) +} From cc204ec1d4688dbdaf33af917a2702778a18a978 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Thu, 2 Jan 2025 15:55:43 +0100 Subject: [PATCH 09/19] Minor fixes --- hack/runtime-migrator/internal/backup/backup.go | 11 +++++------ hack/runtime-migrator/internal/backup/output.go | 2 +- .../internal/initialisation/client.go | 5 ++++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/hack/runtime-migrator/internal/backup/backup.go b/hack/runtime-migrator/internal/backup/backup.go index 041fba07..b0ad9217 100644 --- a/hack/runtime-migrator/internal/backup/backup.go +++ b/hack/runtime-migrator/internal/backup/backup.go @@ -6,6 +6,7 @@ import ( authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" "github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/initialisation" "github.com/kyma-project/infrastructure-manager/pkg/gardener/kubeconfig" + "github.com/pkg/errors" rbacv1 "k8s.io/api/rbac/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -32,20 +33,20 @@ type RuntimeBackup struct { OIDCConfig []authenticationv1alpha1.OpenIDConnect } -func (b Backuper) Do(_ context.Context, shoot v1beta1.Shoot, runtimeID string) (RuntimeBackup, error) { - runtimeClient, err := initialisation.GetRuntimeClient(context.Background(), b.kcpClient, runtimeID) +func (b Backuper) Do(ctx context.Context, shoot v1beta1.Shoot, runtimeID string) (RuntimeBackup, error) { + runtimeClient, err := initialisation.GetRuntimeClient(ctx, b.kcpClient, runtimeID) if err != nil { return RuntimeBackup{}, err } crbs, err := b.getCRBs(runtimeClient) if err != nil { - return RuntimeBackup{}, err + return RuntimeBackup{}, errors.Wrap(err, "failed to get Cluster Role Bindings") } oidcConfig, err := b.getOIDCConfig(runtimeClient) if err != nil { - return RuntimeBackup{}, err + return RuntimeBackup{}, errors.Wrap(err, "failed to get OIDC config") } return RuntimeBackup{ @@ -98,8 +99,6 @@ func (b Backuper) getShootToRestore(shootFromGardener v1beta1.Shoot) v1beta1.Sho Resources: shootFromGardener.Spec.Resources, SecretBindingName: shootFromGardener.Spec.SecretBindingName, SeedSelector: shootFromGardener.Spec.SeedSelector, - // Tolerations is not specified in patch - //Tolerations: shootFromGardener.Spec.Tolerations, }, } } diff --git a/hack/runtime-migrator/internal/backup/output.go b/hack/runtime-migrator/internal/backup/output.go index 5256c28a..cfe6dd45 100644 --- a/hack/runtime-migrator/internal/backup/output.go +++ b/hack/runtime-migrator/internal/backup/output.go @@ -71,7 +71,7 @@ func (ow OutputWriter) Save(runtimeID string, runtimeBackup RuntimeBackup) error } for _, oidcConfig := range runtimeBackup.OIDCConfig { - err = saveYaml(oidcConfig, fmt.Sprintf("%s/%s.yaml", crbDir, oidcConfig.Name)) + err = saveYaml(oidcConfig, fmt.Sprintf("%s/%s.yaml", oidcDir, oidcConfig.Name)) if err != nil { return err } diff --git a/hack/runtime-migrator/internal/initialisation/client.go b/hack/runtime-migrator/internal/initialisation/client.go index 59844e6d..1fad8c12 100644 --- a/hack/runtime-migrator/internal/initialisation/client.go +++ b/hack/runtime-migrator/internal/initialisation/client.go @@ -19,6 +19,7 @@ import ( const ( kubeconfigSecretKey = "config" + timeoutK8sOperation = 20 * time.Second ) func addToScheme(s *runtime.Scheme) error { @@ -134,8 +135,10 @@ func getKubeconfigSecret(ctx context.Context, cnt client.Client, runtimeID, name var kubeconfigSecret corev1.Secret secretKey := types.NamespacedName{Name: secretName, Namespace: namespace} + getCtx, cancel := context.WithTimeout(ctx, timeoutK8sOperation) + defer cancel() - err := cnt.Get(ctx, secretKey, &kubeconfigSecret) + err := cnt.Get(getCtx, secretKey, &kubeconfigSecret) if err != nil { return corev1.Secret{}, err From c90ff81d342b2769b6b0d1580c575e2494b95478 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Fri, 3 Jan 2025 14:10:38 +0100 Subject: [PATCH 10/19] Added checking if CRD exists --- .../internal/backup/backup.go | 34 ++++++++++++++++--- .../internal/initialisation/client.go | 23 ++++++++++++- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/hack/runtime-migrator/internal/backup/backup.go b/hack/runtime-migrator/internal/backup/backup.go index b0ad9217..78ea98bc 100644 --- a/hack/runtime-migrator/internal/backup/backup.go +++ b/hack/runtime-migrator/internal/backup/backup.go @@ -8,6 +8,7 @@ import ( "github.com/kyma-project/infrastructure-manager/pkg/gardener/kubeconfig" "github.com/pkg/errors" rbacv1 "k8s.io/api/rbac/v1" + crdv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -123,13 +124,38 @@ func (b Backuper) getCRBs(runtimeClient client.Client) ([]rbacv1.ClusterRoleBind } func (b Backuper) getOIDCConfig(runtimeClient client.Client) ([]authenticationv1alpha1.OpenIDConnect, error) { - var oidcConfigList authenticationv1alpha1.OpenIDConnectList + found, err := oidcCRDExists(runtimeClient) + if err != nil { + return nil, err + } + + if found { + var oidcConfigList authenticationv1alpha1.OpenIDConnectList + + err := runtimeClient.List(context.Background(), &oidcConfigList) + + if err != nil { + return nil, err + } - err := runtimeClient.List(context.Background(), &oidcConfigList) + return oidcConfigList.Items, nil + } + + return []authenticationv1alpha1.OpenIDConnect{}, nil +} +func oidcCRDExists(runtimeClient client.Client) (bool, error) { + var crdsList crdv1.CustomResourceDefinitionList + err := runtimeClient.List(context.Background(), &crdsList) if err != nil { - return nil, err + return false, err + } + + for _, crd := range crdsList.Items { + if crd.APIVersion == "authentication.gardener.cloud/v1alpha1" && crd.Kind == "OpenIDConnect" { + return true, nil + } } - return oidcConfigList.Items, nil + return false, nil } diff --git a/hack/runtime-migrator/internal/initialisation/client.go b/hack/runtime-migrator/internal/initialisation/client.go index 1fad8c12..2eb143f7 100644 --- a/hack/runtime-migrator/internal/initialisation/client.go +++ b/hack/runtime-migrator/internal/initialisation/client.go @@ -5,11 +5,14 @@ import ( "fmt" "github.com/gardener/gardener/pkg/apis/core/v1beta1" gardener_types "github.com/gardener/gardener/pkg/client/core/clientset/versioned/typed/core/v1beta1" + gardener_oidc "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" v1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/kyma-project/infrastructure-manager/pkg/gardener" "github.com/kyma-project/infrastructure-manager/pkg/gardener/kubeconfig" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + crdv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/clientcmd" @@ -122,7 +125,25 @@ func GetRuntimeClient(ctx context.Context, kcpClient client.Client, runtimeID st return nil, err } - shootClientWithAdmin, err := client.New(restConfig, client.Options{}) + scheme := runtime.NewScheme() + err = gardener_oidc.AddToScheme(scheme) + if err != nil { + return nil, err + } + + err = rbacv1.AddToScheme(scheme) + if err != nil { + return nil, err + } + + err = crdv1.AddToScheme(scheme) + if err != nil { + return nil, err + } + + shootClientWithAdmin, err := client.New(restConfig, client.Options{ + Scheme: scheme, + }) if err != nil { return nil, err } From 8c570cd37dd806d8e6d42e8bdb8d629a3ddd38d5 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Sat, 4 Jan 2025 14:20:19 +0100 Subject: [PATCH 11/19] Restore working --- .../internal/backup/backup.go | 2 +- .../internal/restore/restorer.go | 57 +++++++------------ 2 files changed, 21 insertions(+), 38 deletions(-) diff --git a/hack/runtime-migrator/internal/backup/backup.go b/hack/runtime-migrator/internal/backup/backup.go index 78ea98bc..df368edb 100644 --- a/hack/runtime-migrator/internal/backup/backup.go +++ b/hack/runtime-migrator/internal/backup/backup.go @@ -152,7 +152,7 @@ func oidcCRDExists(runtimeClient client.Client) (bool, error) { } for _, crd := range crdsList.Items { - if crd.APIVersion == "authentication.gardener.cloud/v1alpha1" && crd.Kind == "OpenIDConnect" { + if crd.Name == "openidconnects.authentication.gardener.cloud" { return true, nil } } diff --git a/hack/runtime-migrator/internal/restore/restorer.go b/hack/runtime-migrator/internal/restore/restorer.go index 869fd251..619eb19a 100644 --- a/hack/runtime-migrator/internal/restore/restorer.go +++ b/hack/runtime-migrator/internal/restore/restorer.go @@ -22,30 +22,38 @@ func NewRestorer(backupDir string) Restorer { } func (r Restorer) Do(runtimeID string, shootName string) (backup.RuntimeBackup, error) { - shoot, err := r.getShootToRestore(runtimeID, shootName) + shootToRestore, err := r.getShootToRestore(runtimeID, fmt.Sprintf("%s-to-restore", shootName)) if err != nil { return backup.RuntimeBackup{}, err } - crbs, err := r.getCRBsToRestore(runtimeID) + originalShoot, err := r.getShootToRestore(runtimeID, fmt.Sprintf("%s-original", shootName)) if err != nil { return backup.RuntimeBackup{}, err } - oidcConfig, err := r.getOIDCConfigToRestore(runtimeID) + crbsDir := path.Join(r.backupDir, fmt.Sprintf("backup/%s/crb", runtimeID)) + crbs, err := getObjectsFromToRestore[rbacv1.ClusterRoleBinding](crbsDir) + if err != nil { + return backup.RuntimeBackup{}, err + } + + oidcDir := path.Join(r.backupDir, fmt.Sprintf("backup/%s/oidc", runtimeID)) + oidcConfig, err := getObjectsFromToRestore[authenticationv1alpha1.OpenIDConnect](oidcDir) if err != nil { return backup.RuntimeBackup{}, err } return backup.RuntimeBackup{ - ShootToRestore: shoot, + ShootToRestore: shootToRestore, + OriginalShoot: originalShoot, ClusterRoleBindings: crbs, OIDCConfig: oidcConfig, }, nil } func (r Restorer) getShootToRestore(runtimeID string, shootName string) (v1beta1.Shoot, error) { - shootFilePath := path.Join(r.backupDir, fmt.Sprintf("backup/%s/%s-to-restore.yaml", runtimeID, shootName)) + shootFilePath := path.Join(r.backupDir, fmt.Sprintf("backup/%s/%s.yaml", runtimeID, shootName)) shoot, err := restoreFromFile[v1beta1.Shoot](shootFilePath) if err != nil { @@ -57,52 +65,27 @@ func (r Restorer) getShootToRestore(runtimeID string, shootName string) (v1beta1 return *shoot, nil } -func (r Restorer) getCRBsToRestore(runtimeID string) ([]rbacv1.ClusterRoleBinding, error) { - crbsDir := path.Join("%s/%s/crb", r.backupDir, runtimeID) - entries, err := os.ReadDir(crbsDir) - - if err != nil { - return nil, err - } - - crbs := make([]rbacv1.ClusterRoleBinding, 0) - - for _, entry := range entries { - crbFilePath := entry.Name() - - crb, err := restoreFromFile[rbacv1.ClusterRoleBinding](crbFilePath) - if err != nil { - return nil, err - } - - crbs = append(crbs, *crb) - } - - return crbs, nil -} - -func (r Restorer) getOIDCConfigToRestore(runtimeID string) ([]authenticationv1alpha1.OpenIDConnect, error) { - crbsDir := path.Join("%s/%s/oidc", r.backupDir, runtimeID) - entries, err := os.ReadDir(crbsDir) +func getObjectsFromToRestore[T any](dir string) ([]T, error) { + entries, err := os.ReadDir(dir) if err != nil { return nil, err } - crbs := make([]authenticationv1alpha1.OpenIDConnect, 0) + objects := make([]T, 0) for _, entry := range entries { - crbFilePath := entry.Name() + filePath := fmt.Sprintf("%s/%s", dir, entry.Name()) - crb, err := restoreFromFile[authenticationv1alpha1.OpenIDConnect](crbFilePath) + object, err := restoreFromFile[T](filePath) if err != nil { return nil, err } - crbs = append(crbs, *crb) + objects = append(objects, *object) } - return crbs, nil + return objects, nil } func restoreFromFile[T any](filePath string) (*T, error) { From f2deb7d57f683761ba7f53dda5ecbe9cd3a69e52 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Sat, 4 Jan 2025 17:05:20 +0100 Subject: [PATCH 12/19] Added restoring OIDC --- hack/runtime-migrator/cmd/restore/restore.go | 89 +++++++++++++++---- .../internal/restore/results.go | 59 ++++++++---- 2 files changed, 110 insertions(+), 38 deletions(-) diff --git a/hack/runtime-migrator/cmd/restore/restore.go b/hack/runtime-migrator/cmd/restore/restore.go index f5ab5603..ea685820 100644 --- a/hack/runtime-migrator/cmd/restore/restore.go +++ b/hack/runtime-migrator/cmd/restore/restore.go @@ -5,11 +5,13 @@ import ( "fmt" "github.com/gardener/gardener/pkg/apis/core/v1beta1" gardener_types "github.com/gardener/gardener/pkg/client/core/clientset/versioned/typed/core/v1beta1" + authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" "github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/backup" "github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/initialisation" "github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/restore" "github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/shoot" v12 "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/api/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" "log/slog" @@ -103,12 +105,12 @@ func (r Restore) Do(ctx context.Context, runtimeIDs []string) error { if r.cfg.IsDryRun { slog.Info("Runtime processed successfully (dry-run)", "runtimeID", runtimeID) - r.results.OperationSucceeded(runtimeID, currentShoot.Name) + r.results.OperationSucceeded(runtimeID, currentShoot.Name, nil, nil) continue } - err = r.applyResources(ctx, objectsToRestore, runtimeID) + appliedCRBs, appliedOIDC, err := r.applyResources(ctx, objectsToRestore, runtimeID) if err != nil { errMsg := fmt.Sprintf("Failed to restore runtime: %v", err) r.results.ErrorOccurred(runtimeID, currentShoot.Name, errMsg) @@ -118,7 +120,7 @@ func (r Restore) Do(ctx context.Context, runtimeIDs []string) error { } slog.Info("Runtime restore performed successfully", "runtimeID", runtimeID) - r.results.OperationSucceeded(runtimeID, currentShoot.Name) + r.results.OperationSucceeded(runtimeID, currentShoot.Name, appliedCRBs, appliedOIDC) } resultsFile, err := r.outputWriter.SaveRestoreResults(r.results) @@ -132,23 +134,28 @@ func (r Restore) Do(ctx context.Context, runtimeIDs []string) error { return nil } -func (r Restore) applyResources(ctx context.Context, objectsToRestore backup.RuntimeBackup, runtimeID string) error { +func (r Restore) applyResources(ctx context.Context, objectsToRestore backup.RuntimeBackup, runtimeID string) ([]v12.ClusterRoleBinding, []authenticationv1alpha1.OpenIDConnect, error) { err := r.applyShoot(ctx, objectsToRestore.ShootToRestore) if err != nil { - return err + return nil, nil, err } clusterClient, err := initialisation.GetRuntimeClient(ctx, r.kcpClient, runtimeID) if err != nil { - return err + return nil, nil, err } - err = r.applyCRBs(ctx, clusterClient, objectsToRestore.ClusterRoleBindings) + appliedCRBs, err := r.applyCRBs(ctx, clusterClient, objectsToRestore.ClusterRoleBindings) if err != nil { - return err + return nil, nil, err } - return nil + appliedOIDC, err := r.applyOIDC(ctx, clusterClient, objectsToRestore.OIDCConfig) + if err != nil { + return nil, nil, err + } + + return appliedCRBs, appliedOIDC, nil } func (r Restore) applyShoot(ctx context.Context, shoot v1beta1.Shoot) error { @@ -161,21 +168,65 @@ func (r Restore) applyShoot(ctx context.Context, shoot v1beta1.Shoot) error { }) } -func (r Restore) applyCRBs(ctx context.Context, clusterClient client.Client, crbs []v12.ClusterRoleBinding) error { +func (r Restore) applyCRBs(ctx context.Context, clusterClient client.Client, crbs []v12.ClusterRoleBinding) ([]v12.ClusterRoleBinding, error) { + appliedCRBs := make([]v12.ClusterRoleBinding, 0) + for _, crb := range crbs { - if err := applyCRB(ctx, crb, clusterClient); err != nil { - return err + key := client.ObjectKey{ + Name: crb.Name, + Namespace: crb.Namespace, + } + applied, err := applyIfDoesntExist[*v12.ClusterRoleBinding](ctx, key, &crb, clusterClient) + if err != nil { + return nil, err + } + + if applied { + appliedCRBs = append(appliedCRBs, crb) } } - return nil + return appliedCRBs, nil } -func applyCRB(ctx context.Context, object v12.ClusterRoleBinding, clusterClient client.Client) error { - ctx, cancel := context.WithTimeout(ctx, timeoutK8sOperation) - defer cancel() +func (r Restore) applyOIDC(ctx context.Context, clusterClient client.Client, oidcConfigs []authenticationv1alpha1.OpenIDConnect) ([]authenticationv1alpha1.OpenIDConnect, error) { + appliedOIDCs := make([]authenticationv1alpha1.OpenIDConnect, 0) - return clusterClient.Update(ctx, &object, &client.UpdateOptions{ - FieldManager: fieldManagerName, - }) + for _, oidc := range oidcConfigs { + key := client.ObjectKey{ + Name: oidc.Name, + Namespace: oidc.Namespace, + } + applied, err := applyIfDoesntExist[*authenticationv1alpha1.OpenIDConnect](ctx, key, &oidc, clusterClient) + if err != nil { + return nil, err + } + + if applied { + appliedOIDCs = append(appliedOIDCs, oidc) + } + } + + return appliedOIDCs, nil +} + +func applyIfDoesntExist[T client.Object](ctx context.Context, key client.ObjectKey, object T, clusterClient client.Client) (bool, error) { + getCtx, cancelGet := context.WithTimeout(ctx, timeoutK8sOperation) + defer cancelGet() + + var existentObject T + + err := clusterClient.Get(getCtx, key, existentObject, &client.GetOptions{}) + if err == nil { + return false, nil + } + + if err != nil && !errors.IsNotFound(err) { + return false, err + } + + createCtx, cancelCreate := context.WithTimeout(ctx, timeoutK8sOperation) + defer cancelCreate() + + return true, clusterClient.Create(createCtx, object, &client.CreateOptions{}) } diff --git a/hack/runtime-migrator/internal/restore/results.go b/hack/runtime-migrator/internal/restore/results.go index 252fa32d..5635266e 100644 --- a/hack/runtime-migrator/internal/restore/results.go +++ b/hack/runtime-migrator/internal/restore/results.go @@ -1,5 +1,11 @@ package restore +import ( + "fmt" + authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" + v12 "k8s.io/api/rbac/v1" +) + type StatusType string const ( @@ -10,10 +16,12 @@ const ( ) type RuntimeResult struct { - RuntimeID string `json:"runtimeId"` - ShootName string `json:"shootName"` - Status StatusType `json:"status"` - ErrorMessage string `json:"errorMessage,omitempty"` + RuntimeID string `json:"runtimeId"` + ShootName string `json:"shootName"` + Status StatusType `json:"status"` + ErrorMessage string `json:"errorMessage,omitempty"` + RestoredCRBs []string `json:"restoredCRBs"` + RestoredOIDCs []string `json:"restoredOIDCs"` } type Results struct { @@ -32,7 +40,7 @@ func NewRestoreResults(outputDirectory string) Results { } } -func (br *Results) ErrorOccurred(runtimeID, shootName string, errorMsg string) { +func (rr *Results) ErrorOccurred(runtimeID, shootName string, errorMsg string) { result := RuntimeResult{ RuntimeID: runtimeID, ShootName: shootName, @@ -40,39 +48,52 @@ func (br *Results) ErrorOccurred(runtimeID, shootName string, errorMsg string) { ErrorMessage: errorMsg, } - br.Failed++ - br.Results = append(br.Results, result) + rr.Failed++ + rr.Results = append(rr.Results, result) } -func (br *Results) OperationSucceeded(runtimeID string, shootName string) { +func (rr *Results) OperationSucceeded(runtimeID string, shootName string, appliedCRBs []v12.ClusterRoleBinding, appliedOIDCs []authenticationv1alpha1.OpenIDConnect) { + + appliedCRBsString := make([]string, 0) + for _, crb := range appliedCRBs { + appliedCRBsString = append(appliedCRBsString, fmt.Sprintf("%s:%s", crb.Namespace, crb.Name)) + } + + appliedOIDCsString := make([]string, 0) + for _, oidc := range appliedOIDCs { + appliedOIDCsString = append(appliedOIDCsString, fmt.Sprintf("%s:%s", oidc.Namespace, oidc.Name)) + } + result := RuntimeResult{ - RuntimeID: runtimeID, - ShootName: shootName, - Status: StatusSuccess, + RuntimeID: runtimeID, + ShootName: shootName, + Status: StatusSuccess, + RestoredCRBs: appliedCRBsString, + RestoredOIDCs: appliedOIDCsString, } - br.Succeeded++ - br.Results = append(br.Results, result) + rr.Succeeded++ + rr.Results = append(rr.Results, result) } -func (br *Results) OperationSkipped(runtimeID string, shootName string) { +func (rr *Results) OperationSkipped(runtimeID string, shootName string) { result := RuntimeResult{ RuntimeID: runtimeID, ShootName: shootName, Status: StatusRestoreSkipped, } - br.Skipped++ - br.Results = append(br.Results, result) + rr.Skipped++ + rr.Results = append(rr.Results, result) } -func (br *Results) AutomaticRestoreImpossible(runtimeID string, shootName string) { +func (rr *Results) AutomaticRestoreImpossible(runtimeID string, shootName string) { result := RuntimeResult{ RuntimeID: runtimeID, ShootName: shootName, Status: StatusUpdateDetected, } - br.UpdateDetected++ - br.Results = append(br.Results, result) + rr.UpdateDetected++ + rr.Results = append(rr.Results, result) } From 423b782fa6c11d850beef98d0eeccf1cf388c3db Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Sat, 4 Jan 2025 17:17:38 +0100 Subject: [PATCH 13/19] Added flags for including RBAC and OIDC --- .../internal/initialisation/params.go | 6 +++- .../internal/restore/restorer.go | 34 +++++++++++++------ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/hack/runtime-migrator/internal/initialisation/params.go b/hack/runtime-migrator/internal/initialisation/params.go index b03d0468..dc7850fd 100644 --- a/hack/runtime-migrator/internal/initialisation/params.go +++ b/hack/runtime-migrator/internal/initialisation/params.go @@ -82,7 +82,9 @@ func GetRuntimeIDsFromInputFile(cfg Config) ([]string, error) { type RestoreConfig struct { Config - BackupDir string + BackupDir string + RestoreCRB bool + RestoreOIDC bool } func NewRestoreConfig() RestoreConfig { @@ -96,6 +98,8 @@ func NewRestoreConfig() RestoreConfig { flag.StringVar(&restoreConfig.InputType, "input-type", InputTypeJSON, "Type of input to be used. Possible values: **txt** (see the example hack/runtime-migrator/input/runtimeids_sample.txt), and **json** (see the example hack/runtime-migrator/input/runtimeids_sample.json).") flag.StringVar(&restoreConfig.InputFilePath, "input-file-path", "/path/to/input/file", "Path to the input file containing RuntimeCRs to be migrated.") flag.StringVar(&restoreConfig.BackupDir, "backup-path", "/path/to/backup/dir", "Path to the directory containing backup.") + flag.BoolVar(&restoreConfig.RestoreCRB, "restore-crbs", true, "Flag determining whether CRBs should be restored") + flag.BoolVar(&restoreConfig.RestoreOIDC, "restore-oidcs", true, "Flag determining whether OIDCs should be restored") flag.Parse() return restoreConfig diff --git a/hack/runtime-migrator/internal/restore/restorer.go b/hack/runtime-migrator/internal/restore/restorer.go index 619eb19a..bade868d 100644 --- a/hack/runtime-migrator/internal/restore/restorer.go +++ b/hack/runtime-migrator/internal/restore/restorer.go @@ -12,12 +12,16 @@ import ( ) type Restorer struct { - backupDir string + backupDir string + restoreCRB bool + restoreOIDC bool } -func NewRestorer(backupDir string) Restorer { +func NewRestorer(backupDir string, restoreCRB, restoreOIDC bool) Restorer { return Restorer{ - backupDir: backupDir, + backupDir: backupDir, + restoreCRB: restoreCRB, + restoreOIDC: restoreOIDC, } } @@ -32,16 +36,24 @@ func (r Restorer) Do(runtimeID string, shootName string) (backup.RuntimeBackup, return backup.RuntimeBackup{}, err } - crbsDir := path.Join(r.backupDir, fmt.Sprintf("backup/%s/crb", runtimeID)) - crbs, err := getObjectsFromToRestore[rbacv1.ClusterRoleBinding](crbsDir) - if err != nil { - return backup.RuntimeBackup{}, err + var crbs []rbacv1.ClusterRoleBinding + + if r.restoreCRB { + crbsDir := path.Join(r.backupDir, fmt.Sprintf("backup/%s/crb", runtimeID)) + crbs, err = getObjectsFromToRestore[rbacv1.ClusterRoleBinding](crbsDir) + if err != nil { + return backup.RuntimeBackup{}, err + } } - oidcDir := path.Join(r.backupDir, fmt.Sprintf("backup/%s/oidc", runtimeID)) - oidcConfig, err := getObjectsFromToRestore[authenticationv1alpha1.OpenIDConnect](oidcDir) - if err != nil { - return backup.RuntimeBackup{}, err + var oidcConfig []authenticationv1alpha1.OpenIDConnect + + if r.restoreOIDC { + oidcDir := path.Join(r.backupDir, fmt.Sprintf("backup/%s/oidc", runtimeID)) + oidcConfig, err = getObjectsFromToRestore[authenticationv1alpha1.OpenIDConnect](oidcDir) + if err != nil { + return backup.RuntimeBackup{}, err + } } return backup.RuntimeBackup{ From 1eb5d5599bb4616d5440ec4f716f5b752f5abda8 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Tue, 7 Jan 2025 13:23:19 +0100 Subject: [PATCH 14/19] Fixes in the backup --- hack/runtime-migrator/cmd/backup/backup.go | 3 +- hack/runtime-migrator/cmd/restore/restore.go | 4 +- .../internal/backup/backup.go | 45 ++++++++++++------- .../internal/initialisation/client.go | 1 - .../internal/initialisation/params.go | 2 +- hack/runtime-migrator/internal/shoot/util.go | 5 ++- 6 files changed, 36 insertions(+), 24 deletions(-) diff --git a/hack/runtime-migrator/cmd/backup/backup.go b/hack/runtime-migrator/cmd/backup/backup.go index 0f6a0659..49871dc7 100644 --- a/hack/runtime-migrator/cmd/backup/backup.go +++ b/hack/runtime-migrator/cmd/backup/backup.go @@ -16,7 +16,6 @@ import ( const ( timeoutK8sOperation = 20 * time.Second - expirationTime = 60 * time.Minute ) type Backup struct { @@ -52,7 +51,7 @@ func (b Backup) Do(ctx context.Context, runtimeIDs []string) error { return err } - backuper := backup.NewBackuper(b.cfg.IsDryRun, b.kcpClient) + backuper := backup.NewBackuper(b.cfg.IsDryRun, b.kcpClient, timeoutK8sOperation) for _, runtimeID := range runtimeIDs { shootToBackup, err := shoot.Fetch(ctx, shootList, b.shootClient, runtimeID) diff --git a/hack/runtime-migrator/cmd/restore/restore.go b/hack/runtime-migrator/cmd/restore/restore.go index ea685820..fbf89358 100644 --- a/hack/runtime-migrator/cmd/restore/restore.go +++ b/hack/runtime-migrator/cmd/restore/restore.go @@ -33,7 +33,7 @@ type Restore struct { cfg initialisation.RestoreConfig } -const fieldManagerName = "kim" +const fieldManagerName = "kim-restore" func NewRestore(cfg initialisation.RestoreConfig, kcpClient client.Client, shootClient gardener_types.ShootInterface, dynamicGardenerClient client.Client) (Restore, error) { outputWriter, err := restore.NewOutputWriter(cfg.OutputPath) @@ -60,7 +60,7 @@ func (r Restore) Do(ctx context.Context, runtimeIDs []string) error { return err } - restorer := restore.NewRestorer(r.cfg.BackupDir) + restorer := restore.NewRestorer(r.cfg.BackupDir, r.cfg.RestoreCRB, r.cfg.RestoreOIDC) for _, runtimeID := range runtimeIDs { currentShoot, err := shoot.Fetch(ctx, shootList, r.shootClient, runtimeID) diff --git a/hack/runtime-migrator/internal/backup/backup.go b/hack/runtime-migrator/internal/backup/backup.go index df368edb..eb628bac 100644 --- a/hack/runtime-migrator/internal/backup/backup.go +++ b/hack/runtime-migrator/internal/backup/backup.go @@ -11,19 +11,22 @@ import ( crdv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" + "time" ) type Backuper struct { - cfg initialisation.Config - isDryRun bool - kubeconfigProvider kubeconfig.Provider - kcpClient client.Client + cfg initialisation.Config + isDryRun bool + kubeconfigProvider kubeconfig.Provider + kcpClient client.Client + timeoutK8sOperation time.Duration } -func NewBackuper(isDryRun bool, kcpClient client.Client) Backuper { +func NewBackuper(isDryRun bool, kcpClient client.Client, timeoutK8sOperation time.Duration) Backuper { return Backuper{ - isDryRun: isDryRun, - kcpClient: kcpClient, + isDryRun: isDryRun, + kcpClient: kcpClient, + timeoutK8sOperation: timeoutK8sOperation, } } @@ -40,12 +43,12 @@ func (b Backuper) Do(ctx context.Context, shoot v1beta1.Shoot, runtimeID string) return RuntimeBackup{}, err } - crbs, err := b.getCRBs(runtimeClient) + crbs, err := b.getCRBs(ctx, runtimeClient) if err != nil { return RuntimeBackup{}, errors.Wrap(err, "failed to get Cluster Role Bindings") } - oidcConfig, err := b.getOIDCConfig(runtimeClient) + oidcConfig, err := b.getOIDCConfig(ctx, runtimeClient) if err != nil { return RuntimeBackup{}, errors.Wrap(err, "failed to get OIDC config") } @@ -104,9 +107,13 @@ func (b Backuper) getShootToRestore(shootFromGardener v1beta1.Shoot) v1beta1.Sho } } -func (b Backuper) getCRBs(runtimeClient client.Client) ([]rbacv1.ClusterRoleBinding, error) { +func (b Backuper) getCRBs(ctx context.Context, runtimeClient client.Client) ([]rbacv1.ClusterRoleBinding, error) { var crbList rbacv1.ClusterRoleBindingList - err := runtimeClient.List(context.Background(), &crbList) + + listCtx, cancel := context.WithTimeout(ctx, b.timeoutK8sOperation) + defer cancel() + + err := runtimeClient.List(listCtx, &crbList) if err != nil { return nil, err @@ -123,8 +130,8 @@ func (b Backuper) getCRBs(runtimeClient client.Client) ([]rbacv1.ClusterRoleBind return crbsToBackup, nil } -func (b Backuper) getOIDCConfig(runtimeClient client.Client) ([]authenticationv1alpha1.OpenIDConnect, error) { - found, err := oidcCRDExists(runtimeClient) +func (b Backuper) getOIDCConfig(ctx context.Context, runtimeClient client.Client) ([]authenticationv1alpha1.OpenIDConnect, error) { + found, err := b.oidcCRDExists(ctx, runtimeClient) if err != nil { return nil, err } @@ -132,7 +139,10 @@ func (b Backuper) getOIDCConfig(runtimeClient client.Client) ([]authenticationv1 if found { var oidcConfigList authenticationv1alpha1.OpenIDConnectList - err := runtimeClient.List(context.Background(), &oidcConfigList) + listCtx, cancel := context.WithTimeout(ctx, b.timeoutK8sOperation) + defer cancel() + + err := runtimeClient.List(listCtx, &oidcConfigList) if err != nil { return nil, err @@ -144,9 +154,12 @@ func (b Backuper) getOIDCConfig(runtimeClient client.Client) ([]authenticationv1 return []authenticationv1alpha1.OpenIDConnect{}, nil } -func oidcCRDExists(runtimeClient client.Client) (bool, error) { +func (b Backuper) oidcCRDExists(ctx context.Context, runtimeClient client.Client) (bool, error) { var crdsList crdv1.CustomResourceDefinitionList - err := runtimeClient.List(context.Background(), &crdsList) + listCtx, cancel := context.WithTimeout(ctx, b.timeoutK8sOperation) + defer cancel() + + err := runtimeClient.List(listCtx, &crdsList) if err != nil { return false, err } diff --git a/hack/runtime-migrator/internal/initialisation/client.go b/hack/runtime-migrator/internal/initialisation/client.go index 2eb143f7..d55ae5c3 100644 --- a/hack/runtime-migrator/internal/initialisation/client.go +++ b/hack/runtime-migrator/internal/initialisation/client.go @@ -22,7 +22,6 @@ import ( const ( kubeconfigSecretKey = "config" - timeoutK8sOperation = 20 * time.Second ) func addToScheme(s *runtime.Scheme) error { diff --git a/hack/runtime-migrator/internal/initialisation/params.go b/hack/runtime-migrator/internal/initialisation/params.go index dc7850fd..cd98d955 100644 --- a/hack/runtime-migrator/internal/initialisation/params.go +++ b/hack/runtime-migrator/internal/initialisation/params.go @@ -23,7 +23,7 @@ type Config struct { const ( InputTypeTxt = "txt" InputTypeJSON = "json" - TimeoutK8sOperation = 20 * time.Second + timeoutK8sOperation = 20 * time.Second ) func PrintConfig(cfg Config) { diff --git a/hack/runtime-migrator/internal/shoot/util.go b/hack/runtime-migrator/internal/shoot/util.go index 48636880..9e24ff00 100644 --- a/hack/runtime-migrator/internal/shoot/util.go +++ b/hack/runtime-migrator/internal/shoot/util.go @@ -4,13 +4,14 @@ import ( "context" "github.com/gardener/gardener/pkg/apis/core/v1beta1" gardener_types "github.com/gardener/gardener/pkg/client/core/clientset/versioned/typed/core/v1beta1" - "github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/initialisation" "github.com/pkg/errors" k8serrors "k8s.io/apimachinery/pkg/api/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "time" ) const runtimeIDAnnotation = "kcp.provisioner.kyma-project.io/runtime-id" +const timeoutK8sOperation = 20 * time.Second func Fetch(ctx context.Context, shootList *v1beta1.ShootList, shootClient gardener_types.ShootInterface, runtimeID string) (*v1beta1.Shoot, error) { shoot := findShoot(runtimeID, shootList) @@ -18,7 +19,7 @@ func Fetch(ctx context.Context, shootList *v1beta1.ShootList, shootClient garden return nil, errors.New("shoot was deleted or the runtimeID is incorrect") } - getCtx, cancel := context.WithTimeout(ctx, initialisation.TimeoutK8sOperation) + getCtx, cancel := context.WithTimeout(ctx, timeoutK8sOperation) defer cancel() // We are fetching the shoot from the gardener to make sure the runtime didn't get deleted during the migration process From 3be3e0c13047e7b75bd84d91c06fd17d0d298ec1 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Tue, 7 Jan 2025 16:52:14 +0100 Subject: [PATCH 15/19] Fixes for restoring OIDC and CRBs --- hack/runtime-migrator/cmd/restore/restore.go | 43 ++++++++++++++----- .../internal/restore/restorer.go | 10 +++++ .../internal/restore/results.go | 5 +-- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/hack/runtime-migrator/cmd/restore/restore.go b/hack/runtime-migrator/cmd/restore/restore.go index fbf89358..c2438fc5 100644 --- a/hack/runtime-migrator/cmd/restore/restore.go +++ b/hack/runtime-migrator/cmd/restore/restore.go @@ -96,12 +96,12 @@ func (r Restore) Do(ctx context.Context, runtimeIDs []string) error { continue } - if currentShoot.Generation > objectsToRestore.OriginalShoot.Generation+1 { - slog.Warn("Verify the current state of the system. Restore should be performed manually, as the backup may overwrite more that on change.", "runtimeID", runtimeID) - r.results.AutomaticRestoreImpossible(runtimeID, currentShoot.Name) - - continue - } + //if currentShoot.Generation > objectsToRestore.OriginalShoot.Generation+1 { + // slog.Warn("Verify the current state of the system. Restore should be performed manually, as the backup may overwrite more that on change.", "runtimeID", runtimeID) + // r.results.AutomaticRestoreImpossible(runtimeID, currentShoot.Name) + // + // continue + //} if r.cfg.IsDryRun { slog.Info("Runtime processed successfully (dry-run)", "runtimeID", runtimeID) @@ -176,7 +176,7 @@ func (r Restore) applyCRBs(ctx context.Context, clusterClient client.Client, crb Name: crb.Name, Namespace: crb.Namespace, } - applied, err := applyIfDoesntExist[*v12.ClusterRoleBinding](ctx, key, &crb, clusterClient) + applied, err := applyCRBIfDoesntExist(ctx, key, &crb, clusterClient) if err != nil { return nil, err } @@ -197,7 +197,7 @@ func (r Restore) applyOIDC(ctx context.Context, clusterClient client.Client, oid Name: oidc.Name, Namespace: oidc.Namespace, } - applied, err := applyIfDoesntExist[*authenticationv1alpha1.OpenIDConnect](ctx, key, &oidc, clusterClient) + applied, err := applyOIDCIfDoesntExist(ctx, key, &oidc, clusterClient) if err != nil { return nil, err } @@ -210,13 +210,13 @@ func (r Restore) applyOIDC(ctx context.Context, clusterClient client.Client, oid return appliedOIDCs, nil } -func applyIfDoesntExist[T client.Object](ctx context.Context, key client.ObjectKey, object T, clusterClient client.Client) (bool, error) { +func applyCRBIfDoesntExist(ctx context.Context, key client.ObjectKey, object *v12.ClusterRoleBinding, clusterClient client.Client) (bool, error) { getCtx, cancelGet := context.WithTimeout(ctx, timeoutK8sOperation) defer cancelGet() - var existentObject T + var existingObject v12.ClusterRoleBinding - err := clusterClient.Get(getCtx, key, existentObject, &client.GetOptions{}) + err := clusterClient.Get(getCtx, key, &existingObject, &client.GetOptions{}) if err == nil { return false, nil } @@ -230,3 +230,24 @@ func applyIfDoesntExist[T client.Object](ctx context.Context, key client.ObjectK return true, clusterClient.Create(createCtx, object, &client.CreateOptions{}) } + +func applyOIDCIfDoesntExist(ctx context.Context, key client.ObjectKey, object *authenticationv1alpha1.OpenIDConnect, clusterClient client.Client) (bool, error) { + getCtx, cancelGet := context.WithTimeout(ctx, timeoutK8sOperation) + defer cancelGet() + + var existingObject authenticationv1alpha1.OpenIDConnect + + err := clusterClient.Get(getCtx, key, &existingObject, &client.GetOptions{}) + if err == nil { + return false, nil + } + slog.Error(err.Error()) + if err != nil && !errors.IsNotFound(err) { + return false, err + } + + createCtx, cancelCreate := context.WithTimeout(ctx, timeoutK8sOperation) + defer cancelCreate() + + return true, clusterClient.Create(createCtx, object, &client.CreateOptions{}) +} diff --git a/hack/runtime-migrator/internal/restore/restorer.go b/hack/runtime-migrator/internal/restore/restorer.go index bade868d..03c7cdd8 100644 --- a/hack/runtime-migrator/internal/restore/restorer.go +++ b/hack/runtime-migrator/internal/restore/restorer.go @@ -44,6 +44,11 @@ func (r Restorer) Do(runtimeID string, shootName string) (backup.RuntimeBackup, if err != nil { return backup.RuntimeBackup{}, err } + + for i := 0; i < len(crbs); i++ { + crbs[i].Generation = 0 + crbs[i].ResourceVersion = "" + } } var oidcConfig []authenticationv1alpha1.OpenIDConnect @@ -54,6 +59,11 @@ func (r Restorer) Do(runtimeID string, shootName string) (backup.RuntimeBackup, if err != nil { return backup.RuntimeBackup{}, err } + + for i := 0; i < len(oidcConfig); i++ { + oidcConfig[i].Generation = 0 + oidcConfig[i].ResourceVersion = "" + } } return backup.RuntimeBackup{ diff --git a/hack/runtime-migrator/internal/restore/results.go b/hack/runtime-migrator/internal/restore/results.go index 5635266e..7f00a91a 100644 --- a/hack/runtime-migrator/internal/restore/results.go +++ b/hack/runtime-migrator/internal/restore/results.go @@ -1,7 +1,6 @@ package restore import ( - "fmt" authenticationv1alpha1 "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" v12 "k8s.io/api/rbac/v1" ) @@ -56,12 +55,12 @@ func (rr *Results) OperationSucceeded(runtimeID string, shootName string, applie appliedCRBsString := make([]string, 0) for _, crb := range appliedCRBs { - appliedCRBsString = append(appliedCRBsString, fmt.Sprintf("%s:%s", crb.Namespace, crb.Name)) + appliedCRBsString = append(appliedCRBsString, crb.Name) } appliedOIDCsString := make([]string, 0) for _, oidc := range appliedOIDCs { - appliedOIDCsString = append(appliedOIDCsString, fmt.Sprintf("%s:%s", oidc.Namespace, oidc.Name)) + appliedOIDCsString = append(appliedOIDCsString, oidc.Name) } result := RuntimeResult{ From 11d55072930029b1f400c5c8f5c4c4223f10b55a Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Wed, 8 Jan 2025 07:42:23 +0100 Subject: [PATCH 16/19] Review remarks 1 --- hack/runtime-migrator/cmd/backup/backup.go | 1 + hack/runtime-migrator/cmd/restore/restore.go | 12 ++++++------ .../internal/initialisation/params.go | 8 +++++--- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/hack/runtime-migrator/cmd/backup/backup.go b/hack/runtime-migrator/cmd/backup/backup.go index 49871dc7..3532b6d3 100644 --- a/hack/runtime-migrator/cmd/backup/backup.go +++ b/hack/runtime-migrator/cmd/backup/backup.go @@ -81,6 +81,7 @@ func (b Backup) Do(ctx context.Context, runtimeIDs []string) error { if b.cfg.IsDryRun { slog.Info("Runtime processed successfully (dry-run)", "runtimeID", runtimeID) + b.results.OperationSucceeded(runtimeID, shootToBackup.Name) continue } diff --git a/hack/runtime-migrator/cmd/restore/restore.go b/hack/runtime-migrator/cmd/restore/restore.go index c2438fc5..1f2d348d 100644 --- a/hack/runtime-migrator/cmd/restore/restore.go +++ b/hack/runtime-migrator/cmd/restore/restore.go @@ -96,12 +96,12 @@ func (r Restore) Do(ctx context.Context, runtimeIDs []string) error { continue } - //if currentShoot.Generation > objectsToRestore.OriginalShoot.Generation+1 { - // slog.Warn("Verify the current state of the system. Restore should be performed manually, as the backup may overwrite more that on change.", "runtimeID", runtimeID) - // r.results.AutomaticRestoreImpossible(runtimeID, currentShoot.Name) - // - // continue - //} + if currentShoot.Generation > objectsToRestore.OriginalShoot.Generation+1 { + slog.Warn("Verify the current state of the system. Restore should be performed manually, as the backup may overwrite more that on change.", "runtimeID", runtimeID) + r.results.AutomaticRestoreImpossible(runtimeID, currentShoot.Name) + + continue + } if r.cfg.IsDryRun { slog.Info("Runtime processed successfully (dry-run)", "runtimeID", runtimeID) diff --git a/hack/runtime-migrator/internal/initialisation/params.go b/hack/runtime-migrator/internal/initialisation/params.go index cd98d955..1c503c87 100644 --- a/hack/runtime-migrator/internal/initialisation/params.go +++ b/hack/runtime-migrator/internal/initialisation/params.go @@ -98,14 +98,16 @@ func NewRestoreConfig() RestoreConfig { flag.StringVar(&restoreConfig.InputType, "input-type", InputTypeJSON, "Type of input to be used. Possible values: **txt** (see the example hack/runtime-migrator/input/runtimeids_sample.txt), and **json** (see the example hack/runtime-migrator/input/runtimeids_sample.json).") flag.StringVar(&restoreConfig.InputFilePath, "input-file-path", "/path/to/input/file", "Path to the input file containing RuntimeCRs to be migrated.") flag.StringVar(&restoreConfig.BackupDir, "backup-path", "/path/to/backup/dir", "Path to the directory containing backup.") - flag.BoolVar(&restoreConfig.RestoreCRB, "restore-crbs", true, "Flag determining whether CRBs should be restored") - flag.BoolVar(&restoreConfig.RestoreOIDC, "restore-oidcs", true, "Flag determining whether OIDCs should be restored") + flag.BoolVar(&restoreConfig.RestoreCRB, "restore-crb", true, "Flag determining whether CRBs should be restored") + flag.BoolVar(&restoreConfig.RestoreOIDC, "restore-oidc", true, "Flag determining whether OIDCs should be restored") flag.Parse() return restoreConfig } func PrintRestoreConfig(cfg RestoreConfig) { - log.Println("backup-path:", cfg.BackupDir) PrintConfig(cfg.Config) + log.Println("backup-path:", cfg.BackupDir) + log.Println("restore-crb:", cfg.RestoreCRB) + log.Println("restore-oidc:", cfg.RestoreOIDC) } From aadcb475fbb554010860ef47534df8469b6c86ad Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Wed, 8 Jan 2025 07:53:06 +0100 Subject: [PATCH 17/19] Review remarks 2 --- hack/runtime-migrator/cmd/restore/restore.go | 11 ++--------- hack/runtime-migrator/internal/restore/results.go | 13 ------------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/hack/runtime-migrator/cmd/restore/restore.go b/hack/runtime-migrator/cmd/restore/restore.go index 1f2d348d..2ab69e82 100644 --- a/hack/runtime-migrator/cmd/restore/restore.go +++ b/hack/runtime-migrator/cmd/restore/restore.go @@ -89,15 +89,8 @@ func (r Restore) Do(ctx context.Context, runtimeIDs []string) error { continue } - if currentShoot.Generation == objectsToRestore.OriginalShoot.Generation { - slog.Warn("Verify the current state of the system. Shoot was not modified after backup was prepared. Skipping.", "runtimeID", runtimeID) - r.results.OperationSkipped(runtimeID, currentShoot.Name) - - continue - } - if currentShoot.Generation > objectsToRestore.OriginalShoot.Generation+1 { - slog.Warn("Verify the current state of the system. Restore should be performed manually, as the backup may overwrite more that on change.", "runtimeID", runtimeID) + slog.Warn("Verify the current state of the system. Restore should be performed manually, as the backup may overwrite user's changes.", "runtimeID", runtimeID) r.results.AutomaticRestoreImpossible(runtimeID, currentShoot.Name) continue @@ -128,7 +121,7 @@ func (r Restore) Do(ctx context.Context, runtimeIDs []string) error { return err } - slog.Info(fmt.Sprintf("Restore completed. Successfully restored backups: %d, Failed operations: %d, Skipped backups: %d, ", r.results.Succeeded, r.results.Failed, r.results.Skipped)) + slog.Info(fmt.Sprintf("Restore completed. Successfully restored backups: %d, Failed operations: %d", r.results.Succeeded, r.results.Failed)) slog.Info(fmt.Sprintf("Restore results saved in: %s", resultsFile)) return nil diff --git a/hack/runtime-migrator/internal/restore/results.go b/hack/runtime-migrator/internal/restore/results.go index 7f00a91a..30479331 100644 --- a/hack/runtime-migrator/internal/restore/results.go +++ b/hack/runtime-migrator/internal/restore/results.go @@ -10,7 +10,6 @@ type StatusType string const ( StatusSuccess StatusType = "Success" StatusError StatusType = "Error" - StatusRestoreSkipped = "Skipped" StatusUpdateDetected = "UpdateDetected" ) @@ -27,7 +26,6 @@ type Results struct { Results []RuntimeResult Succeeded int Failed int - Skipped int UpdateDetected int OutputDirectory string } @@ -75,17 +73,6 @@ func (rr *Results) OperationSucceeded(runtimeID string, shootName string, applie rr.Results = append(rr.Results, result) } -func (rr *Results) OperationSkipped(runtimeID string, shootName string) { - result := RuntimeResult{ - RuntimeID: runtimeID, - ShootName: shootName, - Status: StatusRestoreSkipped, - } - - rr.Skipped++ - rr.Results = append(rr.Results, result) -} - func (rr *Results) AutomaticRestoreImpossible(runtimeID string, shootName string) { result := RuntimeResult{ RuntimeID: runtimeID, From 8711b87a90d97638d154d06bc79ed60bb4a94884 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Wed, 8 Jan 2025 08:23:18 +0100 Subject: [PATCH 18/19] Added audit log config for restore --- hack/runtime-migrator/internal/backup/backup.go | 1 + hack/runtime-migrator/internal/restore/restorer.go | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/hack/runtime-migrator/internal/backup/backup.go b/hack/runtime-migrator/internal/backup/backup.go index eb628bac..8bcad612 100644 --- a/hack/runtime-migrator/internal/backup/backup.go +++ b/hack/runtime-migrator/internal/backup/backup.go @@ -82,6 +82,7 @@ func (b Backuper) getShootToRestore(shootFromGardener v1beta1.Shoot) v1beta1.Sho Kubernetes: v1beta1.Kubernetes{ EnableStaticTokenKubeconfig: shootFromGardener.Spec.Kubernetes.EnableStaticTokenKubeconfig, KubeAPIServer: &v1beta1.KubeAPIServerConfig{ + AuditConfig: shootFromGardener.Spec.Kubernetes.KubeAPIServer.AuditConfig, // TODO: consider skipping ClientAuthentication OIDCConfig: shootFromGardener.Spec.Kubernetes.KubeAPIServer.OIDCConfig, }, diff --git a/hack/runtime-migrator/internal/restore/restorer.go b/hack/runtime-migrator/internal/restore/restorer.go index 03c7cdd8..05625649 100644 --- a/hack/runtime-migrator/internal/restore/restorer.go +++ b/hack/runtime-migrator/internal/restore/restorer.go @@ -40,7 +40,7 @@ func (r Restorer) Do(runtimeID string, shootName string) (backup.RuntimeBackup, if r.restoreCRB { crbsDir := path.Join(r.backupDir, fmt.Sprintf("backup/%s/crb", runtimeID)) - crbs, err = getObjectsFromToRestore[rbacv1.ClusterRoleBinding](crbsDir) + crbs, err = getObjectsFromBackup[rbacv1.ClusterRoleBinding](crbsDir) if err != nil { return backup.RuntimeBackup{}, err } @@ -55,7 +55,7 @@ func (r Restorer) Do(runtimeID string, shootName string) (backup.RuntimeBackup, if r.restoreOIDC { oidcDir := path.Join(r.backupDir, fmt.Sprintf("backup/%s/oidc", runtimeID)) - oidcConfig, err = getObjectsFromToRestore[authenticationv1alpha1.OpenIDConnect](oidcDir) + oidcConfig, err = getObjectsFromBackup[authenticationv1alpha1.OpenIDConnect](oidcDir) if err != nil { return backup.RuntimeBackup{}, err } @@ -77,7 +77,7 @@ func (r Restorer) Do(runtimeID string, shootName string) (backup.RuntimeBackup, func (r Restorer) getShootToRestore(runtimeID string, shootName string) (v1beta1.Shoot, error) { shootFilePath := path.Join(r.backupDir, fmt.Sprintf("backup/%s/%s.yaml", runtimeID, shootName)) - shoot, err := restoreFromFile[v1beta1.Shoot](shootFilePath) + shoot, err := readFromFile[v1beta1.Shoot](shootFilePath) if err != nil { return v1beta1.Shoot{}, err } @@ -87,7 +87,7 @@ func (r Restorer) getShootToRestore(runtimeID string, shootName string) (v1beta1 return *shoot, nil } -func getObjectsFromToRestore[T any](dir string) ([]T, error) { +func getObjectsFromBackup[T any](dir string) ([]T, error) { entries, err := os.ReadDir(dir) if err != nil { @@ -99,7 +99,7 @@ func getObjectsFromToRestore[T any](dir string) ([]T, error) { for _, entry := range entries { filePath := fmt.Sprintf("%s/%s", dir, entry.Name()) - object, err := restoreFromFile[T](filePath) + object, err := readFromFile[T](filePath) if err != nil { return nil, err } @@ -110,7 +110,7 @@ func getObjectsFromToRestore[T any](dir string) ([]T, error) { return objects, nil } -func restoreFromFile[T any](filePath string) (*T, error) { +func readFromFile[T any](filePath string) (*T, error) { fileBytes, err := os.ReadFile(filePath) if err != nil { return nil, err From f475a34f073c3a4fe8792a585206d89ac0daa539 Mon Sep 17 00:00:00 2001 From: Arkadiusz Galwas Date: Wed, 8 Jan 2025 09:40:18 +0100 Subject: [PATCH 19/19] Minor refactor --- hack/runtime-migrator/cmd/restore/restore.go | 8 ++++---- hack/runtime-migrator/internal/backup/backup.go | 6 +++--- hack/runtime-migrator/internal/backup/output.go | 2 +- .../restore/{restorer.go => backupreader.go} | 16 ++++++++-------- 4 files changed, 16 insertions(+), 16 deletions(-) rename hack/runtime-migrator/internal/restore/{restorer.go => backupreader.go} (82%) diff --git a/hack/runtime-migrator/cmd/restore/restore.go b/hack/runtime-migrator/cmd/restore/restore.go index 2ab69e82..d2f11347 100644 --- a/hack/runtime-migrator/cmd/restore/restore.go +++ b/hack/runtime-migrator/cmd/restore/restore.go @@ -60,7 +60,7 @@ func (r Restore) Do(ctx context.Context, runtimeIDs []string) error { return err } - restorer := restore.NewRestorer(r.cfg.BackupDir, r.cfg.RestoreCRB, r.cfg.RestoreOIDC) + restorer := restore.NewBackupReader(r.cfg.BackupDir, r.cfg.RestoreCRB, r.cfg.RestoreOIDC) for _, runtimeID := range runtimeIDs { currentShoot, err := shoot.Fetch(ctx, shootList, r.shootClient, runtimeID) @@ -82,7 +82,7 @@ func (r Restore) Do(ctx context.Context, runtimeIDs []string) error { objectsToRestore, err := restorer.Do(runtimeID, currentShoot.Name) if err != nil { - errMsg := fmt.Sprintf("Failed to restore runtime: %v", err) + errMsg := fmt.Sprintf("Failed to read runtime from backup directory: %v", err) r.results.ErrorOccurred(runtimeID, currentShoot.Name, errMsg) slog.Error(errMsg, "runtimeID", runtimeID) @@ -105,7 +105,7 @@ func (r Restore) Do(ctx context.Context, runtimeIDs []string) error { appliedCRBs, appliedOIDC, err := r.applyResources(ctx, objectsToRestore, runtimeID) if err != nil { - errMsg := fmt.Sprintf("Failed to restore runtime: %v", err) + errMsg := fmt.Sprintf("Failed to apply resources: %v", err) r.results.ErrorOccurred(runtimeID, currentShoot.Name, errMsg) slog.Error(errMsg, "runtimeID", runtimeID) @@ -128,7 +128,7 @@ func (r Restore) Do(ctx context.Context, runtimeIDs []string) error { } func (r Restore) applyResources(ctx context.Context, objectsToRestore backup.RuntimeBackup, runtimeID string) ([]v12.ClusterRoleBinding, []authenticationv1alpha1.OpenIDConnect, error) { - err := r.applyShoot(ctx, objectsToRestore.ShootToRestore) + err := r.applyShoot(ctx, objectsToRestore.ShootForPatch) if err != nil { return nil, nil, err } diff --git a/hack/runtime-migrator/internal/backup/backup.go b/hack/runtime-migrator/internal/backup/backup.go index 8bcad612..5d4fdafe 100644 --- a/hack/runtime-migrator/internal/backup/backup.go +++ b/hack/runtime-migrator/internal/backup/backup.go @@ -32,7 +32,7 @@ func NewBackuper(isDryRun bool, kcpClient client.Client, timeoutK8sOperation tim type RuntimeBackup struct { OriginalShoot v1beta1.Shoot - ShootToRestore v1beta1.Shoot + ShootForPatch v1beta1.Shoot ClusterRoleBindings []rbacv1.ClusterRoleBinding OIDCConfig []authenticationv1alpha1.OpenIDConnect } @@ -54,14 +54,14 @@ func (b Backuper) Do(ctx context.Context, shoot v1beta1.Shoot, runtimeID string) } return RuntimeBackup{ - ShootToRestore: b.getShootToRestore(shoot), + ShootForPatch: b.getShootForPatch(shoot), OriginalShoot: shoot, ClusterRoleBindings: crbs, OIDCConfig: oidcConfig, }, nil } -func (b Backuper) getShootToRestore(shootFromGardener v1beta1.Shoot) v1beta1.Shoot { +func (b Backuper) getShootForPatch(shootFromGardener v1beta1.Shoot) v1beta1.Shoot { return v1beta1.Shoot{ TypeMeta: v1.TypeMeta{ Kind: "Shoot", diff --git a/hack/runtime-migrator/internal/backup/output.go b/hack/runtime-migrator/internal/backup/output.go index cfe6dd45..54084a1d 100644 --- a/hack/runtime-migrator/internal/backup/output.go +++ b/hack/runtime-migrator/internal/backup/output.go @@ -46,7 +46,7 @@ func (ow OutputWriter) Save(runtimeID string, runtimeBackup RuntimeBackup) error return err } - err = saveYaml(runtimeBackup.ShootToRestore, fmt.Sprintf("%s/%s-to-restore.yaml", runtimeDir, runtimeBackup.ShootToRestore.Name)) + err = saveYaml(runtimeBackup.ShootForPatch, fmt.Sprintf("%s/%s-to-restore.yaml", runtimeDir, runtimeBackup.ShootForPatch.Name)) if err != nil { return err } diff --git a/hack/runtime-migrator/internal/restore/restorer.go b/hack/runtime-migrator/internal/restore/backupreader.go similarity index 82% rename from hack/runtime-migrator/internal/restore/restorer.go rename to hack/runtime-migrator/internal/restore/backupreader.go index 05625649..a72e772e 100644 --- a/hack/runtime-migrator/internal/restore/restorer.go +++ b/hack/runtime-migrator/internal/restore/backupreader.go @@ -11,27 +11,27 @@ import ( "sigs.k8s.io/yaml" ) -type Restorer struct { +type BackupReader struct { backupDir string restoreCRB bool restoreOIDC bool } -func NewRestorer(backupDir string, restoreCRB, restoreOIDC bool) Restorer { - return Restorer{ +func NewBackupReader(backupDir string, restoreCRB, restoreOIDC bool) BackupReader { + return BackupReader{ backupDir: backupDir, restoreCRB: restoreCRB, restoreOIDC: restoreOIDC, } } -func (r Restorer) Do(runtimeID string, shootName string) (backup.RuntimeBackup, error) { - shootToRestore, err := r.getShootToRestore(runtimeID, fmt.Sprintf("%s-to-restore", shootName)) +func (r BackupReader) Do(runtimeID string, shootName string) (backup.RuntimeBackup, error) { + shootForPatch, err := r.getShoot(runtimeID, fmt.Sprintf("%s-to-restore", shootName)) if err != nil { return backup.RuntimeBackup{}, err } - originalShoot, err := r.getShootToRestore(runtimeID, fmt.Sprintf("%s-original", shootName)) + originalShoot, err := r.getShoot(runtimeID, fmt.Sprintf("%s-original", shootName)) if err != nil { return backup.RuntimeBackup{}, err } @@ -67,14 +67,14 @@ func (r Restorer) Do(runtimeID string, shootName string) (backup.RuntimeBackup, } return backup.RuntimeBackup{ - ShootToRestore: shootToRestore, + ShootForPatch: shootForPatch, OriginalShoot: originalShoot, ClusterRoleBindings: crbs, OIDCConfig: oidcConfig, }, nil } -func (r Restorer) getShootToRestore(runtimeID string, shootName string) (v1beta1.Shoot, error) { +func (r BackupReader) getShoot(runtimeID string, shootName string) (v1beta1.Shoot, error) { shootFilePath := path.Join(r.backupDir, fmt.Sprintf("backup/%s/%s.yaml", runtimeID, shootName)) shoot, err := readFromFile[v1beta1.Shoot](shootFilePath)