Skip to content

Commit

Permalink
Merge pull request #586 from akgalwas/backup-restore-2
Browse files Browse the repository at this point in the history
Implement shoot restore
  • Loading branch information
kyma-bot authored Jan 7, 2025
2 parents 5d478d4 + 9093175 commit 81eff0e
Show file tree
Hide file tree
Showing 15 changed files with 370 additions and 53 deletions.
6 changes: 3 additions & 3 deletions hack/runtime-migrator/cmd/backup/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"fmt"
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/config"
"github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/initialisation"
"github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/shoot"
"github.com/kyma-project/infrastructure-manager/pkg/gardener/kubeconfig"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -23,10 +23,10 @@ type Backup struct {
kubeconfigProvider kubeconfig.Provider
outputWriter backup.OutputWriter
results backup.Results
cfg config.Config
cfg initialisation.Config
}

func NewBackup(cfg config.Config, kubeconfigProvider kubeconfig.Provider, shootClient gardener_types.ShootInterface) (Backup, error) {
func NewBackup(cfg initialisation.Config, kubeconfigProvider kubeconfig.Provider, shootClient gardener_types.ShootInterface) (Backup, error) {
outputWriter, err := backup.NewOutputWriter(cfg.OutputPath)
if err != nil {
return Backup{}, err
Expand Down
14 changes: 8 additions & 6 deletions hack/runtime-migrator/cmd/backup/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package main
import (
"context"
"fmt"
"github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/config"
"github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/initialisation"
"log/slog"
"os"
logf "sigs.k8s.io/controller-runtime/pkg/log"
Expand All @@ -12,7 +12,9 @@ import (

func main() {
slog.Info("Starting runtime-backuper")
cfg := config.NewConfig()
cfg := initialisation.NewConfig()

initialisation.PrintConfig(cfg)

opts := zap.Options{
Development: true,
Expand All @@ -22,13 +24,13 @@ func main() {

gardenerNamespace := fmt.Sprintf("garden-%s", cfg.GardenerProjectName)

kubeconfigProvider, err := config.SetupKubernetesKubeconfigProvider(cfg.GardenerKubeconfigPath, gardenerNamespace, expirationTime)
kubeconfigProvider, err := initialisation.SetupKubernetesKubeconfigProvider(cfg.GardenerKubeconfigPath, gardenerNamespace, expirationTime)
if err != nil {
slog.Error(fmt.Sprintf("Failed to create kubeconfig provider: %v", err))
os.Exit(1)
}

shootClient, err := config.SetupGardenerShootClient(cfg.GardenerKubeconfigPath, gardenerNamespace)
shootClient, _, err := initialisation.SetupGardenerShootClients(cfg.GardenerKubeconfigPath, gardenerNamespace)
if err != nil {
slog.Error("Failed to setup Gardener shoot client", slog.Any("error", err))
os.Exit(1)
Expand All @@ -41,15 +43,15 @@ func main() {
}

slog.Info("Reading runtimeIds from input file")
runtimeIds, err := config.GetRuntimeIDsFromInputFile(cfg)
runtimeIds, err := initialisation.GetRuntimeIDsFromInputFile(cfg)
if err != nil {
slog.Error("Failed to read runtime Ids from input", slog.Any("error", err))
os.Exit(1)
}

err = backup.Do(context.Background(), runtimeIds)
if err != nil {
slog.Error("Failed to read runtime Ids from input", slog.Any("error", err))
slog.Error("Failed to backup runtimes", slog.Any("error", err))
os.Exit(1)
}
}
14 changes: 8 additions & 6 deletions hack/runtime-migrator/cmd/migration/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"strings"
"time"

"github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/config"
"github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/initialisation"
kimConfig "github.com/kyma-project/infrastructure-manager/pkg/config"
v12 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
Expand All @@ -27,7 +27,9 @@ const (

func main() {
slog.Info("Starting runtime-migrator")
cfg := config.NewConfig()
cfg := initialisation.NewConfig()

initialisation.PrintConfig(cfg)

opts := zap.Options{
Development: true,
Expand All @@ -37,19 +39,19 @@ func main() {

gardenerNamespace := fmt.Sprintf("garden-%s", cfg.GardenerProjectName)

kubeconfigProvider, err := config.SetupKubernetesKubeconfigProvider(cfg.GardenerKubeconfigPath, gardenerNamespace, expirationTime)
kubeconfigProvider, err := initialisation.SetupKubernetesKubeconfigProvider(cfg.GardenerKubeconfigPath, gardenerNamespace, expirationTime)
if err != nil {
slog.Error(fmt.Sprintf("Failed to create kubeconfig provider: %v", err))
os.Exit(1)
}

kcpClient, err := config.CreateKcpClient(&cfg)
kcpClient, err := initialisation.CreateKcpClient(&cfg)
if err != nil {
slog.Error("Failed to create kcp client", slog.Any("error", err))
os.Exit(1)
}

gardenerShootClient, err := config.SetupGardenerShootClient(cfg.GardenerKubeconfigPath, gardenerNamespace)
gardenerShootClient, _, err := initialisation.SetupGardenerShootClients(cfg.GardenerKubeconfigPath, gardenerNamespace)
if err != nil {
slog.Error("Failed to setup Gardener shoot client", slog.Any("error", err))
os.Exit(1)
Expand All @@ -75,7 +77,7 @@ func main() {
}

slog.Info("Reading runtimeIds from input file")
runtimeIds, err := config.GetRuntimeIDsFromInputFile(cfg)
runtimeIds, err := initialisation.GetRuntimeIDsFromInputFile(cfg)
if err != nil {
slog.Error("Failed to read runtime Ids from input", slog.Any("error", err))
os.Exit(1)
Expand Down
8 changes: 4 additions & 4 deletions hack/runtime-migrator/cmd/migration/migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

gardener_types "github.com/gardener/gardener/pkg/client/core/clientset/versioned/typed/core/v1beta1"
runtimev1 "github.com/kyma-project/infrastructure-manager/api/v1"
config2 "github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/config"
"github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/initialisation"
"github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/migration"
"github.com/kyma-project/infrastructure-manager/pkg/config"
"github.com/kyma-project/infrastructure-manager/pkg/gardener/kubeconfig"
Expand All @@ -26,7 +26,7 @@ type Migration struct {
isDryRun bool
}

func NewMigration(migratorConfig config2.Config, converterConfig config.ConverterConfig, auditLogConfig auditlogs.Configuration, kubeconfigProvider kubeconfig.Provider, kcpClient client.Client, shootClient gardener_types.ShootInterface) (Migration, error) {
func NewMigration(migratorConfig initialisation.Config, converterConfig config.ConverterConfig, auditLogConfig auditlogs.Configuration, kubeconfigProvider kubeconfig.Provider, kcpClient client.Client, shootClient gardener_types.ShootInterface) (Migration, error) {

outputWriter, err := migration.NewOutputWriter(migratorConfig.OutputPath)
if err != nil {
Expand All @@ -44,7 +44,7 @@ func NewMigration(migratorConfig config2.Config, converterConfig config.Converte
}

func (m Migration) Do(ctx context.Context, runtimeIDs []string) error {
listCtx, cancel := context.WithTimeout(ctx, config2.TimeoutK8sOperation)
listCtx, cancel := context.WithTimeout(ctx, initialisation.TimeoutK8sOperation)
defer cancel()

shootList, err := m.shootClient.List(listCtx, v1.ListOptions{})
Expand Down Expand Up @@ -92,7 +92,7 @@ func (m Migration) Do(ctx context.Context, runtimeIDs []string) error {
return
}

migrationCtx, cancel := context.WithTimeout(ctx, config2.TimeoutK8sOperation)
migrationCtx, cancel := context.WithTimeout(ctx, initialisation.TimeoutK8sOperation)
defer cancel()

runtime, err := m.runtimeMigrator.Do(migrationCtx, *shootToMigrate)
Expand Down
35 changes: 27 additions & 8 deletions hack/runtime-migrator/cmd/restore/main.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
package main

import (
"context"
"fmt"
"github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/config"
"github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/initialisation"
"log/slog"
"os"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"time"
)

const expirationTime = 60 * time.Minute

func main() {
slog.Info("Starting runtime-restorer")
cfg := config.NewConfig()
cfg := initialisation.NewRestoreConfig()

initialisation.PrintRestoreConfig(cfg)

opts := zap.Options{
Development: true,
Expand All @@ -24,21 +24,40 @@ func main() {

gardenerNamespace := fmt.Sprintf("garden-%s", cfg.GardenerProjectName)

_, err := config.SetupKubernetesKubeconfigProvider(cfg.GardenerKubeconfigPath, gardenerNamespace, expirationTime)
kubeconfigProvider, 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 = config.CreateKcpClient(&cfg)
_, err = initialisation.CreateKcpClient(&cfg.Config)
if err != nil {
slog.Error("Failed to create kcp client", slog.Any("error", err))
os.Exit(1)
}

_, err = config.SetupGardenerShootClient(cfg.GardenerKubeconfigPath, gardenerNamespace)
shootClient, dynamicGardenerClient, err := initialisation.SetupGardenerShootClients(cfg.GardenerKubeconfigPath, gardenerNamespace)
if err != nil {
slog.Error("Failed to setup Gardener shoot client", slog.Any("error", err))
os.Exit(1)
}

restore, err := NewRestore(cfg, kubeconfigProvider, shootClient, dynamicGardenerClient)
if err != nil {
slog.Error("Failed to setup Gardener shoot client", slog.Any("error", err))
os.Exit(1)
}

slog.Info("Reading runtimeIds from input file")
runtimeIds, err := initialisation.GetRuntimeIDsFromInputFile(cfg.Config)
if err != nil {
slog.Error("Failed to read runtime Ids from input", slog.Any("error", err))
os.Exit(1)
}

err = restore.Do(context.Background(), runtimeIds)
if err != nil {
slog.Error("Failed to restore runtimes", slog.Any("error", err))
os.Exit(1)
}
}
128 changes: 128 additions & 0 deletions hack/runtime-migrator/cmd/restore/restore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package main

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"
"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"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
"log/slog"
"sigs.k8s.io/controller-runtime/pkg/client"
"time"
)

const (
timeoutK8sOperation = 20 * time.Second
expirationTime = 60 * time.Minute
)

type Restore struct {
shootClient gardener_types.ShootInterface
dynamicGardenerClient client.Client
kubeconfigProvider kubeconfig.Provider
outputWriter restore.OutputWriter
results restore.Results
cfg initialisation.RestoreConfig
}

const fieldManagerName = "kim"

func NewRestore(cfg initialisation.RestoreConfig, kubeconfigProvider kubeconfig.Provider, shootClient gardener_types.ShootInterface, dynamicGardenerClient client.Client) (Restore, error) {
outputWriter, err := restore.NewOutputWriter(cfg.OutputPath)
if err != nil {
return Restore{}, err
}

return Restore{
shootClient: shootClient,
dynamicGardenerClient: dynamicGardenerClient,
kubeconfigProvider: kubeconfigProvider,
outputWriter: outputWriter,
results: restore.NewRestoreResults(outputWriter.NewResultsDir),
cfg: cfg,
}, err
}

func (r Restore) Do(ctx context.Context, runtimeIDs []string) error {
listCtx, cancel := context.WithTimeout(ctx, timeoutK8sOperation)
defer cancel()

shootList, err := r.shootClient.List(listCtx, v1.ListOptions{})
if err != nil {
return err
}

restorer := restore.NewRestorer(r.cfg.BackupDir)

for _, runtimeID := range runtimeIDs {
currentShoot, err := shoot.Fetch(ctx, shootList, r.shootClient, runtimeID)
if err != nil {
errMsg := fmt.Sprintf("Failed to fetch shoot: %v", err)
r.results.ErrorOccurred(runtimeID, "", errMsg)
slog.Error(errMsg, "runtimeID", runtimeID)

continue
}

if shoot.IsBeingDeleted(currentShoot) {
errMsg := fmt.Sprintf("Shoot is being deleted: %v", err)
r.results.ErrorOccurred(runtimeID, currentShoot.Name, errMsg)
slog.Error(errMsg, "runtimeID", runtimeID)

continue
}

shootToRestore, 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)
slog.Error(errMsg, "runtimeID", runtimeID)

continue
}

if r.cfg.IsDryRun {
slog.Info("Runtime processed successfully (dry-run)", "runtimeID", runtimeID)
r.results.OperationSucceeded(runtimeID, currentShoot.Name)

continue
}

err = r.applyResources(ctx, shootToRestore)
if err != nil {
errMsg := fmt.Sprintf("Failed to restore runtime: %v", err)
r.results.ErrorOccurred(runtimeID, currentShoot.Name, errMsg)
slog.Error(errMsg, "runtimeID", runtimeID)

continue
}

slog.Info("Runtime restore performed successfully", "runtimeID", runtimeID)
r.results.OperationSucceeded(runtimeID, currentShoot.Name)
}

resultsFile, err := r.outputWriter.SaveRestoreResults(r.results)
if err != nil {
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 results saved in: %s", resultsFile))

return nil
}

func (r Restore) applyResources(ctx context.Context, shootToRestore v1beta1.Shoot) error {
patchCtx, cancel := context.WithTimeout(ctx, timeoutK8sOperation)
defer cancel()

return r.dynamicGardenerClient.Patch(patchCtx, &shootToRestore, client.Apply, &client.PatchOptions{
FieldManager: fieldManagerName,
Force: ptr.To(true),
})
}
4 changes: 2 additions & 2 deletions hack/runtime-migrator/internal/backup/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import (
"context"
"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/config"
"github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app/internal/initialisation"
"github.com/kyma-project/infrastructure-manager/pkg/gardener/kubeconfig"
rbacv1 "k8s.io/api/rbac/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type Backuper struct {
cfg config.Config
cfg initialisation.Config
isDryRun bool
kubeconfigProvider kubeconfig.Provider
}
Expand Down
9 changes: 4 additions & 5 deletions hack/runtime-migrator/internal/backup/results.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ type RuntimeResult struct {
}

type Results struct {
Results []RuntimeResult
Succeeded int
Failed int
DifferenceDetected int
OutputDirectory string
Results []RuntimeResult
Succeeded int
Failed int
OutputDirectory string
}

func NewBackupResults(outputDirectory string) Results {
Expand Down
Loading

0 comments on commit 81eff0e

Please sign in to comment.