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 +}