diff --git a/cmd/zitadelctl/cmds/backup.go b/cmd/zitadelctl/cmds/backup.go index 90db39dd4..bab90acd3 100644 --- a/cmd/zitadelctl/cmds/backup.go +++ b/cmd/zitadelctl/cmds/backup.go @@ -1,13 +1,9 @@ package cmds import ( - "errors" - - "github.com/caos/orbos/pkg/git" - "github.com/caos/orbos/pkg/kubernetes/cli" + "github.com/caos/zitadel/pkg/databases" - "github.com/caos/zitadel/operator/crtlgitops" "github.com/spf13/cobra" ) @@ -36,25 +32,27 @@ func BackupCommand(getRv GetRootValues) *cobra.Command { monitor := rv.Monitor orbConfig := rv.OrbConfig gitClient := rv.GitClient - version := rv.Version - - if !rv.Gitops { - return errors.New("backup command is only supported with the --gitops flag yet") - } k8sClient, err := cli.Client(monitor, orbConfig, gitClient, rv.Kubeconfig, rv.Gitops, true) if err != nil { return err } - if gitClient.Exists(git.DatabaseFile) { + if rv.Gitops { + if err := databases.GitOpsInstantBackup( + monitor, + k8sClient, + gitClient, + backup, + ); err != nil { + return err + } - if err := crtlgitops.Backup( + } else { + if err := databases.CrdInstantBackup( monitor, - orbConfig.Path, k8sClient, backup, - &version, ); err != nil { return err } diff --git a/cmd/zitadelctl/cmds/backuplist.go b/cmd/zitadelctl/cmds/backuplist.go index 6b19e1400..ead2ce794 100644 --- a/cmd/zitadelctl/cmds/backuplist.go +++ b/cmd/zitadelctl/cmds/backuplist.go @@ -1,10 +1,11 @@ package cmds import ( - "errors" "fmt" "sort" + "github.com/caos/orbos/pkg/kubernetes/cli" + "github.com/caos/zitadel/pkg/databases" "github.com/spf13/cobra" ) @@ -31,24 +32,26 @@ func BackupListCommand(getRv GetRootValues) *cobra.Command { orbConfig := rv.OrbConfig gitClient := rv.GitClient - if !rv.Gitops { - return errors.New("backuplist command is only supported with the --gitops flag yet") - } - - if err := gitClient.Configure(orbConfig.URL, []byte(orbConfig.Repokey)); err != nil { - monitor.Error(err) - return nil - } - - if err := gitClient.Clone(); err != nil { - monitor.Error(err) - return nil - } - - backups, err := databases.ListBackups(monitor, gitClient) + backups := make([]string, 0) + k8sClient, err := cli.Client(monitor, orbConfig, rv.GitClient, rv.Kubeconfig, rv.Gitops, true) if err != nil { - monitor.Error(err) - return nil + return err + } + + if rv.Gitops { + backupsT, err := databases.GitOpsListBackups(monitor, gitClient, k8sClient) + if err != nil { + monitor.Error(err) + return nil + } + backups = backupsT + } else { + backupsT, err := databases.CrdListBackups(monitor, k8sClient) + if err != nil { + monitor.Error(err) + return nil + } + backups = backupsT } sort.Slice(backups, func(i, j int) bool { diff --git a/cmd/zitadelctl/cmds/destroy.go b/cmd/zitadelctl/cmds/destroy.go new file mode 100644 index 000000000..6621838d2 --- /dev/null +++ b/cmd/zitadelctl/cmds/destroy.go @@ -0,0 +1,165 @@ +package cmds + +import ( + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/git" + "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/kubernetes/cli" + "github.com/caos/zitadel/operator/crtlcrd" + "github.com/caos/zitadel/operator/crtlgitops" + orbdb "github.com/caos/zitadel/operator/database/kinds/orb" + orbzit "github.com/caos/zitadel/operator/zitadel/kinds/orb" + kuberneteszit "github.com/caos/zitadel/pkg/kubernetes" + "github.com/spf13/cobra" +) + +func TeardownCommand(getRv GetRootValues) *cobra.Command { + + var ( + cmd = &cobra.Command{ + Use: "teardown", + Short: "Tear down an Orb", + Long: "Destroys a whole Orb", + Aliases: []string{ + "shoot", + "destroy", + "devastate", + "annihilate", + "crush", + "bulldoze", + "total", + "smash", + "decimate", + "kill", + "trash", + "wipe-off-the-map", + "pulverize", + "take-apart", + "destruct", + "obliterate", + "disassemble", + "explode", + "blow-up", + }, + } + ) + + cmd.RunE = func(cmd *cobra.Command, args []string) (err error) { + + rv, err := getRv() + if err != nil { + return err + } + defer func() { + err = rv.ErrFunc(err) + }() + + monitor := rv.Monitor + orbConfig := rv.OrbConfig + gitClient := rv.GitClient + version := rv.Version + + k8sClient, err := cli.Client( + monitor, + orbConfig, + gitClient, + rv.Kubeconfig, + rv.Gitops, + true, + ) + if err != nil { + return err + } + + monitor.WithFields(map[string]interface{}{ + "version": version, + }).Info("Destroying Orb") + + if err := kuberneteszit.ScaleZitadelOperator(monitor, k8sClient, 0); err != nil { + return err + } + + if err := kuberneteszit.ScaleDatabaseOperator(monitor, k8sClient, 0); err != nil { + return err + } + + if rv.Gitops { + if err := crtlgitops.DestroyOperator(monitor, orbConfig.Path, k8sClient, &version, rv.Gitops); err != nil { + return err + } + + if err := crtlgitops.DestroyDatabase(monitor, orbConfig.Path, k8sClient, &version, rv.Gitops); err != nil { + return err + } + } else { + if err := crtlcrd.Destroy(monitor, k8sClient, version, "zitadel", "database"); err != nil { + return err + } + } + + if err := destroyOperator(monitor, gitClient, k8sClient, rv.Gitops); err != nil { + return err + } + + if err := destroyDatabase(monitor, gitClient, k8sClient, rv.Gitops); err != nil { + return err + } + + return nil + } + return cmd +} + +func destroyOperator(monitor mntr.Monitor, gitClient *git.Client, k8sClient kubernetes.ClientInt, gitops bool) error { + if gitops { + if gitClient.Exists(git.ZitadelFile) { + desiredTree, err := gitClient.ReadTree(git.ZitadelFile) + if err != nil { + return err + } + desired, err := orbzit.ParseDesiredV0(desiredTree) + if err != nil { + return err + } + spec := desired.Spec + + _, del := orbzit.Reconcile(monitor, spec, gitops) + if err := del(k8sClient); err != nil { + return err + } + } + } else { + _, del := orbzit.Reconcile(monitor, &orbzit.Spec{}, gitops) + if err := del(k8sClient); err != nil { + return err + } + } + return nil +} + +func destroyDatabase(monitor mntr.Monitor, gitClient *git.Client, k8sClient kubernetes.ClientInt, gitops bool) error { + if gitops { + if gitClient.Exists(git.DatabaseFile) { + desiredTree, err := gitClient.ReadTree(git.DatabaseFile) + if err != nil { + return err + } + desired, err := orbdb.ParseDesiredV0(desiredTree) + if err != nil { + return err + } + spec := desired.Spec + + _, del := orbdb.Reconcile(monitor, spec, gitops) + if err := del(k8sClient); err != nil { + return err + } + } + } else { + _, del := orbdb.Reconcile(monitor, &orbdb.Spec{}, gitops) + if err := del(k8sClient); err != nil { + return err + } + } + return nil +} diff --git a/cmd/zitadelctl/cmds/restore.go b/cmd/zitadelctl/cmds/restore.go index 55628d13b..3eaad26b1 100644 --- a/cmd/zitadelctl/cmds/restore.go +++ b/cmd/zitadelctl/cmds/restore.go @@ -2,10 +2,10 @@ package cmds import ( "errors" + "github.com/caos/zitadel/pkg/zitadel" "github.com/caos/orbos/pkg/kubernetes/cli" - "github.com/caos/zitadel/operator/crtlgitops" "github.com/caos/zitadel/pkg/databases" "github.com/manifoldco/promptui" "github.com/spf13/cobra" @@ -39,19 +39,26 @@ func RestoreCommand(getRv GetRootValues) *cobra.Command { gitClient := rv.GitClient version := rv.Version - if !rv.Gitops { - return errors.New("restore command is only supported with the --gitops flag yet") - } - k8sClient, err := cli.Client(monitor, orbConfig, gitClient, rv.Kubeconfig, rv.Gitops, true) if err != nil { return err } - list, err := databases.ListBackups(monitor, gitClient) - if err != nil { - monitor.Error(err) - return nil + list := make([]string, 0) + if rv.Gitops { + listT, err := databases.GitOpsListBackups(monitor, gitClient, k8sClient) + if err != nil { + monitor.Error(err) + return nil + } + list = listT + } else { + listT, err := databases.CrdListBackups(monitor, k8sClient) + if err != nil { + monitor.Error(err) + return nil + } + list = listT } if backup == "" { @@ -79,8 +86,17 @@ func RestoreCommand(getRv GetRootValues) *cobra.Command { return nil } - if err := crtlgitops.Restore(monitor, gitClient, orbConfig, k8sClient, backup, rv.Gitops, &version); err != nil { - monitor.Error(err) + if rv.Gitops { + if err := zitadel.GitOpsClearMigrateRestore(monitor, gitClient, orbConfig, k8sClient, backup, &version); err != nil { + monitor.Error(err) + return err + } + } else { + if err := zitadel.CrdClearMigrateRestore(monitor, k8sClient, backup, &version); err != nil { + monitor.Error(err) + return err + } + } return nil } diff --git a/cmd/zitadelctl/cmds/takeoff.go b/cmd/zitadelctl/cmds/takeoff.go index 589b55724..70a4f9e7c 100644 --- a/cmd/zitadelctl/cmds/takeoff.go +++ b/cmd/zitadelctl/cmds/takeoff.go @@ -106,7 +106,8 @@ func deployOperator(monitor mntr.Monitor, gitClient *git.Client, k8sClient kuber // at takeoff the artifacts have to be applied spec.SelfReconciling = true - if err := orbzit.Reconcile(monitor, spec, gitops)(k8sClient); err != nil { + rec, _ := orbzit.Reconcile(monitor, spec, gitops) + if err := rec(k8sClient); err != nil { return err } } @@ -117,7 +118,8 @@ func deployOperator(monitor mntr.Monitor, gitClient *git.Client, k8sClient kuber SelfReconciling: true, } - if err := orbzit.Reconcile(monitor, spec, gitops)(k8sClient); err != nil { + rec, _ := orbzit.Reconcile(monitor, spec, gitops) + if err := rec(k8sClient); err != nil { return err } } @@ -140,11 +142,8 @@ func deployDatabase(monitor mntr.Monitor, gitClient *git.Client, k8sClient kuber // at takeoff the artifacts have to be applied spec.SelfReconciling = true - if err := orbdb.Reconcile( - monitor, - spec, - gitops, - )(k8sClient); err != nil { + rec, _ := orbdb.Reconcile(monitor, desired.Spec, gitops) + if err := rec(k8sClient); err != nil { return err } } @@ -155,11 +154,8 @@ func deployDatabase(monitor mntr.Monitor, gitClient *git.Client, k8sClient kuber SelfReconciling: true, } - if err := orbdb.Reconcile( - monitor, - spec, - gitops, - )(k8sClient); err != nil { + rec, _ := orbdb.Reconcile(monitor, spec, gitops) + if err := rec(k8sClient); err != nil { return err } } diff --git a/cmd/zitadelctl/main.go b/cmd/zitadelctl/main.go index 782232ff4..bff74ea1c 100644 --- a/cmd/zitadelctl/main.go +++ b/cmd/zitadelctl/main.go @@ -27,6 +27,7 @@ func main() { cmds.BackupCommand(rootValues), cmds.StartDatabase(rootValues), cmds.ConfigCommand(rootValues, githubClientID, githubClientSecret), + cmds.TeardownCommand(rootValues), ) if err := rootCmd.Execute(); err != nil { diff --git a/internal/ui/login/handler/login.go b/internal/ui/login/handler/login.go index 8943ac498..e4c752020 100644 --- a/internal/ui/login/handler/login.go +++ b/internal/ui/login/handler/login.go @@ -19,8 +19,8 @@ import ( "github.com/caos/zitadel/internal/domain" "github.com/caos/zitadel/internal/form" "github.com/caos/zitadel/internal/id" - "github.com/caos/zitadel/internal/static" "github.com/caos/zitadel/internal/query" + "github.com/caos/zitadel/internal/static" _ "github.com/caos/zitadel/internal/ui/login/statik" usr_model "github.com/caos/zitadel/internal/user/model" "github.com/gorilla/csrf" diff --git a/operator/crtlcrd/backup.go b/operator/crtlcrd/backup.go new file mode 100644 index 000000000..b8d2854d5 --- /dev/null +++ b/operator/crtlcrd/backup.go @@ -0,0 +1,32 @@ +package crtlcrd + +import ( + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/tree" + "github.com/caos/zitadel/operator/api/database" + orbdb "github.com/caos/zitadel/operator/database/kinds/orb" +) + +func Restore(monitor mntr.Monitor, k8sClient *kubernetes.Client, backup string, binaryVersion *string) error { + desired, err := database.ReadCrd(k8sClient) + if err != nil { + return err + } + + query, _, _, _, _, _, err := orbdb.AdaptFunc(backup, binaryVersion, false, "restore")(monitor, desired, &tree.Tree{}) + if err != nil { + return err + } + + ensure, err := query(k8sClient, map[string]interface{}{}) + if err != nil { + return err + } + + if err := ensure(k8sClient); err != nil { + return err + } + + return nil +} diff --git a/operator/crtlcrd/database/destroy.go b/operator/crtlcrd/database/destroy.go new file mode 100644 index 000000000..2eaf94801 --- /dev/null +++ b/operator/crtlcrd/database/destroy.go @@ -0,0 +1,26 @@ +package database + +import ( + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/tree" + "github.com/caos/zitadel/operator/api/database" + orbdb "github.com/caos/zitadel/operator/database/kinds/orb" +) + +func Destroy(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, version string) error { + desired, err := database.ReadCrd(k8sClient) + if err != nil { + return err + } + + if desired != nil { + _, destroy, _, _, _, _, err := orbdb.AdaptFunc("", &version, false, "database")(monitor, desired, &tree.Tree{}) + if err != nil { + return err + } + + return destroy(k8sClient) + } + return nil +} diff --git a/operator/crtlcrd/destroy.go b/operator/crtlcrd/destroy.go new file mode 100644 index 000000000..857ff654e --- /dev/null +++ b/operator/crtlcrd/destroy.go @@ -0,0 +1,24 @@ +package crtlcrd + +import ( + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/zitadel/operator/crtlcrd/database" + "github.com/caos/zitadel/operator/crtlcrd/zitadel" +) + +func Destroy(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, version string, features ...string) error { + for _, feature := range features { + switch feature { + case Zitadel: + if err := zitadel.Destroy(monitor, k8sClient, version); err != nil { + return err + } + case Database: + if err := database.Destroy(monitor, k8sClient, version); err != nil { + return err + } + } + } + return nil +} diff --git a/operator/crtlcrd/zitadel/destroy.go b/operator/crtlcrd/zitadel/destroy.go new file mode 100644 index 000000000..7f4a44227 --- /dev/null +++ b/operator/crtlcrd/zitadel/destroy.go @@ -0,0 +1,26 @@ +package zitadel + +import ( + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/tree" + "github.com/caos/zitadel/operator/api/zitadel" + orbz "github.com/caos/zitadel/operator/zitadel/kinds/orb" +) + +func Destroy(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, version string) error { + desired, err := zitadel.ReadCrd(k8sClient) + if err != nil { + return err + } + + if desired != nil { + _, destroy, _, _, _, _, err := orbz.AdaptFunc(nil, "ensure", &version, false, []string{"operator", "iam"})(monitor, desired, &tree.Tree{}) + if err != nil { + return err + } + + return destroy(k8sClient) + } + return nil +} diff --git a/operator/crtlgitops/destroy.go b/operator/crtlgitops/destroy.go new file mode 100644 index 000000000..44c6ca3ba --- /dev/null +++ b/operator/crtlgitops/destroy.go @@ -0,0 +1,44 @@ +package crtlgitops + +import ( + "context" + + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/git" + "github.com/caos/orbos/pkg/kubernetes" + orbconfig "github.com/caos/orbos/pkg/orb" + "github.com/caos/zitadel/operator/database" + orbdb "github.com/caos/zitadel/operator/database/kinds/orb" + "github.com/caos/zitadel/operator/zitadel" + orbz "github.com/caos/zitadel/operator/zitadel/kinds/orb" +) + +func DestroyOperator(monitor mntr.Monitor, orbConfigPath string, k8sClient *kubernetes.Client, version *string, gitops bool) error { + + orbConfig, err := orbconfig.ParseOrbConfig(orbConfigPath) + if err != nil { + return err + } + + gitClient := git.New(context.Background(), monitor, "orbos", "orbos@caos.ch") + if err := gitClient.Configure(orbConfig.URL, []byte(orbConfig.Repokey)); err != nil { + return err + } + + return zitadel.Destroy(monitor, gitClient, orbz.AdaptFunc(orbConfig, "ensure", version, gitops, []string{"zitadel", "iam"}), k8sClient) +} + +func DestroyDatabase(monitor mntr.Monitor, orbConfigPath string, k8sClient *kubernetes.Client, version *string, gitops bool) error { + + orbConfig, err := orbconfig.ParseOrbConfig(orbConfigPath) + if err != nil { + return err + } + + gitClient := git.New(context.Background(), monitor, "orbos", "orbos@caos.ch") + if err := gitClient.Configure(orbConfig.URL, []byte(orbConfig.Repokey)); err != nil { + return err + } + + return database.Destroy(monitor, gitClient, orbdb.AdaptFunc("", version, gitops, "operator", "database", "backup"), k8sClient) +} diff --git a/operator/crtlgitops/start.go b/operator/crtlgitops/start.go index 986313b4d..456140388 100644 --- a/operator/crtlgitops/start.go +++ b/operator/crtlgitops/start.go @@ -13,8 +13,6 @@ import ( "github.com/caos/orbos/pkg/kubernetes" orbconfig "github.com/caos/orbos/pkg/orb" "github.com/caos/zitadel/operator/zitadel/kinds/orb" - "github.com/caos/zitadel/pkg/databases" - kubernetes2 "github.com/caos/zitadel/pkg/kubernetes" ) func Operator(monitor mntr.Monitor, orbConfigPath string, k8sClient *kubernetes.Client, version *string, gitops bool) error { @@ -54,61 +52,6 @@ func Operator(monitor mntr.Monitor, orbConfigPath string, k8sClient *kubernetes. return nil } -func Restore( - monitor mntr.Monitor, - gitClient *git.Client, - orbCfg *orbconfig.Orb, - k8sClient *kubernetes.Client, - backup string, - gitops bool, - version *string, -) error { - databasesList := []string{ - "notification", - "adminapi", - "auth", - "authz", - "eventstore", - "management", - } - - if err := kubernetes2.ScaleZitadelOperator(monitor, k8sClient, 0); err != nil { - return err - } - - if err := zitadel.Takeoff(monitor, gitClient, orb.AdaptFunc(orbCfg, "scaledown", version, gitops, []string{"scaledown"}), k8sClient)(); err != nil { - return err - } - - if err := databases.Clear(monitor, k8sClient, gitClient, databasesList); err != nil { - return err - } - - if err := zitadel.Takeoff(monitor, gitClient, orb.AdaptFunc(orbCfg, "migration", version, gitops, []string{"migration"}), k8sClient)(); err != nil { - return err - } - - if err := databases.Restore( - monitor, - k8sClient, - gitClient, - backup, - databasesList, - ); err != nil { - return err - } - - if err := zitadel.Takeoff(monitor, gitClient, orb.AdaptFunc(orbCfg, "scaleup", version, gitops, []string{"scaleup"}), k8sClient)(); err != nil { - return err - } - - if err := kubernetes2.ScaleZitadelOperator(monitor, k8sClient, 1); err != nil { - return err - } - - return nil -} - func Database(monitor mntr.Monitor, orbConfigPath string, k8sClient *kubernetes.Client, binaryVersion *string, gitops bool) error { takeoffChan := make(chan struct{}) go func() { @@ -145,20 +88,3 @@ func Database(monitor mntr.Monitor, orbConfigPath string, k8sClient *kubernetes. return nil } - -func Backup(monitor mntr.Monitor, orbConfigPath string, k8sClient *kubernetes.Client, backup string, binaryVersion *string) error { - orbConfig, err := orbconfig.ParseOrbConfig(orbConfigPath) - if err != nil { - monitor.Error(err) - return err - } - - gitClient := git.New(context.Background(), monitor, "orbos", "orbos@caos.ch") - if err := gitClient.Configure(orbConfig.URL, []byte(orbConfig.Repokey)); err != nil { - monitor.Error(err) - return err - } - - database.Takeoff(monitor, gitClient, orbdb.AdaptFunc(backup, binaryVersion, false, "instantbackup"), k8sClient)() - return nil -} diff --git a/operator/database/destroy.go b/operator/database/destroy.go new file mode 100644 index 000000000..cd65f6b6e --- /dev/null +++ b/operator/database/destroy.go @@ -0,0 +1,34 @@ +package database + +import ( + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/git" + "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/tree" + "github.com/caos/zitadel/operator" +) + +func Destroy( + monitor mntr.Monitor, + gitClient *git.Client, + adapt operator.AdaptFunc, + k8sClient *kubernetes.Client, +) error { + internalMonitor := monitor.WithField("operator", "database") + internalMonitor.Info("Destroy") + treeDesired, err := operator.Parse(gitClient, "database.yml") + if err != nil { + return err + } + treeCurrent := &tree.Tree{} + + _, destroy, _, _, _, _, err := adapt(internalMonitor, treeDesired, treeCurrent) + if err != nil { + return err + } + + if err := destroy(k8sClient); err != nil { + return err + } + return nil +} diff --git a/operator/database/kinds/backups/backups.go b/operator/database/kinds/backups/backups.go index cc74380c1..0a97ba70c 100644 --- a/operator/database/kinds/backups/backups.go +++ b/operator/database/kinds/backups/backups.go @@ -2,6 +2,7 @@ package backups import ( "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/kubernetes" "github.com/caos/orbos/pkg/labels" "github.com/caos/orbos/pkg/secret" "github.com/caos/orbos/pkg/tree" @@ -61,6 +62,7 @@ func Adapt( func GetBackupList( monitor mntr.Monitor, + k8sClient kubernetes.ClientInt, name string, desiredTree *tree.Tree, ) ( @@ -69,7 +71,7 @@ func GetBackupList( ) { switch desiredTree.Common.Kind { case "databases.caos.ch/BucketBackup": - return bucket.BackupList()(monitor, name, desiredTree) + return bucket.BackupList()(monitor, k8sClient, name, desiredTree) default: return nil, errors.Errorf("unknown database kind %s", desiredTree.Common.Kind) } diff --git a/operator/database/kinds/backups/bucket/adapt.go b/operator/database/kinds/backups/bucket/adapt.go index fd8b458ac..928bbbb06 100644 --- a/operator/database/kinds/backups/bucket/adapt.go +++ b/operator/database/kinds/backups/bucket/adapt.go @@ -116,6 +116,7 @@ func AdaptFunc( namespace, componentLabels, []string{}, + []string{}, nodeselector, tolerations, checkDBReady, @@ -162,6 +163,11 @@ func AdaptFunc( databases = []string{} } + users, err := currentDB.GetListUsersFunc()(k8sClient) + if err != nil { + users = []string{} + } + value, err := read.GetSecretValue(k8sClient, desiredKind.Spec.ServiceAccountJSON, desiredKind.Spec.ExistingServiceAccountJSON) if err != nil { return nil, err @@ -218,6 +224,7 @@ func AdaptFunc( namespace, componentLabels, databases, + users, nodeselector, tolerations, checkDBReady, diff --git a/operator/database/kinds/backups/bucket/adapt_test.go b/operator/database/kinds/backups/bucket/adapt_test.go index 8e4c874d5..17ee76aab 100644 --- a/operator/database/kinds/backups/bucket/adapt_test.go +++ b/operator/database/kinds/backups/bucket/adapt_test.go @@ -153,7 +153,7 @@ func TestBucket_AdaptBackup(t *testing.T) { assert.NoError(t, err) databases := []string{"test1", "test2"} - queried := SetQueriedForDatabases(databases) + queried := SetQueriedForDatabases(databases, []string{}) ensure, err := query(client, queried) assert.NoError(t, err) assert.NotNil(t, ensure) @@ -228,7 +228,7 @@ func TestBucket_AdaptInstantBackup(t *testing.T) { assert.NoError(t, err) databases := []string{"test1", "test2"} - queried := SetQueriedForDatabases(databases) + queried := SetQueriedForDatabases(databases, []string{}) ensure, err := query(client, queried) assert.NotNil(t, ensure) assert.NoError(t, err) @@ -304,7 +304,7 @@ func TestBucket_AdaptRestore(t *testing.T) { assert.NoError(t, err) databases := []string{"test1", "test2"} - queried := SetQueriedForDatabases(databases) + queried := SetQueriedForDatabases(databases, []string{}) ensure, err := query(client, queried) assert.NotNil(t, ensure) assert.NoError(t, err) @@ -380,7 +380,8 @@ func TestBucket_AdaptClean(t *testing.T) { assert.NoError(t, err) databases := []string{"test1", "test2"} - queried := SetQueriedForDatabases(databases) + users := []string{"test1", "test2"} + queried := SetQueriedForDatabases(databases, users) ensure, err := query(client, queried) assert.NotNil(t, ensure) assert.NoError(t, err) diff --git a/operator/database/kinds/backups/bucket/clean/adapt.go b/operator/database/kinds/backups/bucket/clean/adapt.go index c46b8d0c9..66b741afb 100644 --- a/operator/database/kinds/backups/bucket/clean/adapt.go +++ b/operator/database/kinds/backups/bucket/clean/adapt.go @@ -30,6 +30,7 @@ func AdaptFunc( namespace string, componentLabels *labels.Component, databases []string, + users []string, nodeselector map[string]string, tolerations []corev1.Toleration, checkDBReady operator.EnsureFunc, @@ -42,7 +43,7 @@ func AdaptFunc( err error, ) { - command := getCommand(databases) + command := getCommand(databases, users) jobDef := getJob( namespace, diff --git a/operator/database/kinds/backups/bucket/clean/adapt_test.go b/operator/database/kinds/backups/bucket/clean/adapt_test.go index 5c6ad8db9..7339e022d 100644 --- a/operator/database/kinds/backups/bucket/clean/adapt_test.go +++ b/operator/database/kinds/backups/bucket/clean/adapt_test.go @@ -20,6 +20,7 @@ func TestBackup_Adapt1(t *testing.T) { monitor := mntr.Monitor{} namespace := "testNs" databases := []string{"testDb"} + users := []string{"testUser"} nodeselector := map[string]string{"test": "test"} tolerations := []corev1.Toleration{ {Key: "testKey", Operator: "testOp"}} @@ -44,6 +45,7 @@ func TestBackup_Adapt1(t *testing.T) { secretKey, getCommand( databases, + users, ), image, ) @@ -57,6 +59,7 @@ func TestBackup_Adapt1(t *testing.T) { namespace, componentLabels, databases, + users, nodeselector, tolerations, checkDBReady, @@ -78,6 +81,7 @@ func TestBackup_Adapt2(t *testing.T) { monitor := mntr.Monitor{} namespace := "testNs2" databases := []string{"testDb1", "testDb2"} + users := []string{"testUser1", "testUser2"} nodeselector := map[string]string{"test2": "test2"} tolerations := []corev1.Toleration{ {Key: "testKey2", Operator: "testOp2"}} @@ -102,6 +106,7 @@ func TestBackup_Adapt2(t *testing.T) { secretKey, getCommand( databases, + users, ), image, ) @@ -115,6 +120,7 @@ func TestBackup_Adapt2(t *testing.T) { namespace, componentLabels, databases, + users, nodeselector, tolerations, checkDBReady, diff --git a/operator/database/kinds/backups/bucket/clean/command.go b/operator/database/kinds/backups/bucket/clean/command.go index 8b724f03f..bef9cf5a9 100644 --- a/operator/database/kinds/backups/bucket/clean/command.go +++ b/operator/database/kinds/backups/bucket/clean/command.go @@ -4,6 +4,7 @@ import "strings" func getCommand( databases []string, + users []string, ) string { backupCommands := make([]string, 0) for _, database := range databases { @@ -14,12 +15,12 @@ func getCommand( database, }, " ")) } - for _, database := range databases { + for _, user := range users { backupCommands = append(backupCommands, strings.Join([]string{ "/scripts/clean-user.sh", certPath, - database, + user, }, " ")) } backupCommands = append(backupCommands, diff --git a/operator/database/kinds/backups/bucket/clean/command_test.go b/operator/database/kinds/backups/bucket/clean/command_test.go index 34969c2aa..e79a3713f 100644 --- a/operator/database/kinds/backups/bucket/clean/command_test.go +++ b/operator/database/kinds/backups/bucket/clean/command_test.go @@ -7,8 +7,9 @@ import ( func TestClean_Command1(t *testing.T) { databases := []string{} + users := []string{} - cmd := getCommand(databases) + cmd := getCommand(databases, users) equals := "/scripts/clean-migration.sh " + certPath assert.Equal(t, equals, cmd) @@ -16,8 +17,9 @@ func TestClean_Command1(t *testing.T) { func TestClean_Command2(t *testing.T) { databases := []string{"test"} + users := []string{"test"} - cmd := getCommand(databases) + cmd := getCommand(databases, users) equals := "/scripts/clean-db.sh " + certPath + " test && /scripts/clean-user.sh " + certPath + " test && /scripts/clean-migration.sh " + certPath assert.Equal(t, equals, cmd) @@ -25,8 +27,9 @@ func TestClean_Command2(t *testing.T) { func TestClean_Command3(t *testing.T) { databases := []string{"test1", "test2", "test3"} + users := []string{"test1", "test2", "test3"} - cmd := getCommand(databases) + cmd := getCommand(databases, users) equals := "/scripts/clean-db.sh " + certPath + " test1 && /scripts/clean-db.sh " + certPath + " test2 && /scripts/clean-db.sh " + certPath + " test3 && " + "/scripts/clean-user.sh " + certPath + " test1 && /scripts/clean-user.sh " + certPath + " test2 && /scripts/clean-user.sh " + certPath + " test3 && " + "/scripts/clean-migration.sh " + certPath diff --git a/operator/database/kinds/backups/bucket/list.go b/operator/database/kinds/backups/bucket/list.go index da05d2ef7..7e2856f56 100644 --- a/operator/database/kinds/backups/bucket/list.go +++ b/operator/database/kinds/backups/bucket/list.go @@ -4,6 +4,8 @@ import ( "cloud.google.com/go/storage" "context" "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/secret/read" "github.com/caos/orbos/pkg/tree" "github.com/caos/zitadel/operator/database/kinds/backups/core" "github.com/pkg/errors" @@ -13,7 +15,7 @@ import ( ) func BackupList() core.BackupListFunc { - return func(monitor mntr.Monitor, name string, desired *tree.Tree) ([]string, error) { + return func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, name string, desired *tree.Tree) ([]string, error) { desiredKind, err := ParseDesiredV0(desired) if err != nil { return nil, errors.Wrap(err, "parsing desired state failed") @@ -24,7 +26,12 @@ func BackupList() core.BackupListFunc { monitor.Verbose() } - return listFilesWithFilter(desiredKind.Spec.ServiceAccountJSON.Value, desiredKind.Spec.Bucket, name) + value, err := read.GetSecretValue(k8sClient, desiredKind.Spec.ServiceAccountJSON, desiredKind.Spec.ExistingServiceAccountJSON) + if err != nil { + return nil, err + } + + return listFilesWithFilter(value, desiredKind.Spec.Bucket, name) } } diff --git a/operator/database/kinds/backups/bucket/mock.go b/operator/database/kinds/backups/bucket/mock.go index 4c05b2553..04fccc42c 100644 --- a/operator/database/kinds/backups/bucket/mock.go +++ b/operator/database/kinds/backups/bucket/mock.go @@ -13,9 +13,9 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" ) -func SetQueriedForDatabases(databases []string) map[string]interface{} { +func SetQueriedForDatabases(databases, users []string) map[string]interface{} { queried := map[string]interface{}{} - core.SetQueriedForDatabaseDBList(queried, databases) + core.SetQueriedForDatabaseDBList(queried, databases, users) return queried } diff --git a/operator/database/kinds/backups/core/list.go b/operator/database/kinds/backups/core/list.go index cff4b1391..4667ddcbe 100644 --- a/operator/database/kinds/backups/core/list.go +++ b/operator/database/kinds/backups/core/list.go @@ -2,7 +2,8 @@ package core import ( "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/kubernetes" "github.com/caos/orbos/pkg/tree" ) -type BackupListFunc func(monitor mntr.Monitor, name string, desired *tree.Tree) ([]string, error) +type BackupListFunc func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, name string, desired *tree.Tree) ([]string, error) diff --git a/operator/database/kinds/databases/core/current.go b/operator/database/kinds/databases/core/current.go index 46c825db3..801a51b9a 100644 --- a/operator/database/kinds/databases/core/current.go +++ b/operator/database/kinds/databases/core/current.go @@ -45,7 +45,7 @@ func SetQueriedForDatabase(queried map[string]interface{}, databaseCurrent *tree queried[queriedName] = databaseCurrent } -func SetQueriedForDatabaseDBList(queried map[string]interface{}, databases []string) { +func SetQueriedForDatabaseDBList(queried map[string]interface{}, databases, users []string) { currentDBList := &CurrentDBList{ Common: &tree.Common{ Kind: "DBList", @@ -53,6 +53,7 @@ func SetQueriedForDatabaseDBList(queried map[string]interface{}, databases []str }, Current: &DatabaseCurrentDBList{ Databases: databases, + Users: users, }, } diff --git a/operator/database/kinds/databases/core/dblist.go b/operator/database/kinds/databases/core/dblist.go index 8f29239d2..5bdfdad3f 100644 --- a/operator/database/kinds/databases/core/dblist.go +++ b/operator/database/kinds/databases/core/dblist.go @@ -16,6 +16,7 @@ type CurrentDBList struct { type DatabaseCurrentDBList struct { Databases []string + Users []string } func (c *CurrentDBList) GetURL() string { @@ -53,7 +54,9 @@ func (c *CurrentDBList) GetListDatabasesFunc() func(k8sClient kubernetes.ClientI } func (c *CurrentDBList) GetListUsersFunc() func(k8sClient kubernetes.ClientInt) ([]string, error) { - return nil + return func(k8sClient kubernetes.ClientInt) ([]string, error) { + return c.Current.Users, nil + } } func (c *CurrentDBList) GetAddUserFunc() func(user string) (operator.QueryFunc, error) { diff --git a/operator/database/kinds/databases/databases.go b/operator/database/kinds/databases/databases.go index 29a280ad5..79b4c866a 100644 --- a/operator/database/kinds/databases/databases.go +++ b/operator/database/kinds/databases/databases.go @@ -2,6 +2,7 @@ package databases import ( "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/kubernetes" "github.com/caos/orbos/pkg/labels" "github.com/caos/orbos/pkg/secret" "github.com/caos/orbos/pkg/tree" @@ -65,6 +66,7 @@ func Adapt( func GetBackupList( monitor mntr.Monitor, + k8sClient kubernetes.ClientInt, desiredTree *tree.Tree, ) ( []string, @@ -72,7 +74,7 @@ func GetBackupList( ) { switch desiredTree.Common.Kind { case "databases.caos.ch/CockroachDB": - return managed.BackupList()(monitor, desiredTree) + return managed.BackupList()(monitor, k8sClient, desiredTree) case "databases.caos.ch/ProvidedDatabse": return nil, errors.Errorf("no backups supported for database kind %s", desiredTree.Common.Kind) default: diff --git a/operator/database/kinds/databases/managed/adapt.go b/operator/database/kinds/databases/managed/adapt.go index c3d140c2d..82dbf2eff 100644 --- a/operator/database/kinds/databases/managed/adapt.go +++ b/operator/database/kinds/databases/managed/adapt.go @@ -142,22 +142,11 @@ func Adapter( cockroachHTTPPort, ) - //externalName := "cockroachdb-public." + namespaceStr + ".svc.cluster.local" - //queryES, destroyES, err := service.AdaptFunc("cockroachdb-public", "default", labels, []service.Port{}, "ExternalName", map[string]string{}, false, "", externalName) - //if err != nil { - // return nil, nil, err - //} - queryPDB, err := pdb.AdaptFuncToEnsure(namespace, labels.MustForName(componentLabels, pdbName), cockroachSelector, "1") if err != nil { return nil, nil, nil, nil, nil, false, err } - destroyPDB, err := pdb.AdaptFuncToDestroy(namespace, pdbName) - if err != nil { - return nil, nil, nil, nil, nil, false, err - } - currentDB := &Current{ Common: &tree.Common{ Kind: "databases.caos.ch/CockroachDB", @@ -188,7 +177,6 @@ func Adapter( if isFeatureDatabase { destroyers = append(destroyers, - operator.ResourceDestroyToZitadelDestroy(destroyPDB), destroyS, operator.ResourceDestroyToZitadelDestroy(destroySFS), destroyRBAC, diff --git a/operator/database/kinds/databases/managed/adapt_backup_test.go b/operator/database/kinds/databases/managed/adapt_backup_test.go index 276a5d3b2..20d64ab4f 100644 --- a/operator/database/kinds/databases/managed/adapt_backup_test.go +++ b/operator/database/kinds/databases/managed/adapt_backup_test.go @@ -88,7 +88,7 @@ func TestManaged_AdaptBucketBackup(t *testing.T) { assert.NoError(t, err) databases := []string{"test1", "test2"} - queried := bucket.SetQueriedForDatabases(databases) + queried := bucket.SetQueriedForDatabases(databases, []string{}) ensure, err := query(k8sClient, queried) assert.NoError(t, err) assert.NotNil(t, ensure) @@ -128,7 +128,7 @@ func TestManaged_AdaptBucketInstantBackup(t *testing.T) { assert.NoError(t, err) databases := []string{"test1", "test2"} - queried := bucket.SetQueriedForDatabases(databases) + queried := bucket.SetQueriedForDatabases(databases, []string{}) ensure, err := query(k8sClient, queried) assert.NoError(t, err) assert.NotNil(t, ensure) @@ -169,7 +169,8 @@ func TestManaged_AdaptBucketCleanAndRestore(t *testing.T) { assert.NoError(t, err) databases := []string{"test1", "test2"} - queried := bucket.SetQueriedForDatabases(databases) + users := []string{"test1", "test2"} + queried := bucket.SetQueriedForDatabases(databases, users) ensure, err := query(k8sClient, queried) assert.NoError(t, err) assert.NotNil(t, ensure) diff --git a/operator/database/kinds/databases/managed/listbackups.go b/operator/database/kinds/databases/managed/listbackups.go index 5a295db44..5ec5e698c 100644 --- a/operator/database/kinds/databases/managed/listbackups.go +++ b/operator/database/kinds/databases/managed/listbackups.go @@ -2,13 +2,14 @@ package managed import ( "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/kubernetes" "github.com/caos/orbos/pkg/tree" "github.com/caos/zitadel/operator/database/kinds/backups" "github.com/pkg/errors" ) -func BackupList() func(monitor mntr.Monitor, desired *tree.Tree) ([]string, error) { - return func(monitor mntr.Monitor, desired *tree.Tree) ([]string, error) { +func BackupList() func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, desired *tree.Tree) ([]string, error) { + return func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, desired *tree.Tree) ([]string, error) { desiredKind, err := parseDesiredV0(desired) if err != nil { return nil, errors.Wrap(err, "parsing desired state failed") @@ -22,7 +23,7 @@ func BackupList() func(monitor mntr.Monitor, desired *tree.Tree) ([]string, erro backuplists := make([]string, 0) if desiredKind.Spec.Backups != nil { for name, def := range desiredKind.Spec.Backups { - backuplist, err := backups.GetBackupList(monitor, name, def) + backuplist, err := backups.GetBackupList(monitor, k8sClient, name, def) if err != nil { return nil, err } diff --git a/operator/database/kinds/databases/managed/rbac/adapt.go b/operator/database/kinds/databases/managed/rbac/adapt.go index bee285b07..fad86b1a8 100644 --- a/operator/database/kinds/databases/managed/rbac/adapt.go +++ b/operator/database/kinds/databases/managed/rbac/adapt.go @@ -33,7 +33,7 @@ func AdaptFunc( return nil, nil, err } - destroyR, err := role.AdaptFuncToDestroy(namespace, roleLabels.Name()) + destroyR, err := role.AdaptFuncToDestroy(roleLabels.Name(), namespace) if err != nil { return nil, nil, err } diff --git a/operator/database/kinds/orb/adapt.go b/operator/database/kinds/orb/adapt.go index ebd33108a..0311f6683 100644 --- a/operator/database/kinds/orb/adapt.go +++ b/operator/database/kinds/orb/adapt.go @@ -91,22 +91,28 @@ func AdaptFunc( return nil, nil, nil, nil, nil, migrate, err } + rec, _ := Reconcile(monitor, desiredKind.Spec, gitops) + destroyers := make([]operator.DestroyFunc, 0) queriers := make([]operator.QueryFunc, 0) + dbOrBackup := false for _, feature := range features { switch feature { case "database", backup.Instant, backup.Normal, restore.Instant, clean.Instant: - queriers = append(queriers, - operator.ResourceQueryToZitadelQuery(queryNS), - queryDB, - ) - destroyers = append(destroyers, - destroyDB, - ) + if !dbOrBackup { + dbOrBackup = true + queriers = append(queriers, + operator.ResourceQueryToZitadelQuery(queryNS), + queryDB, + ) + destroyers = append(destroyers, + destroyDB, + ) + } case "operator": queriers = append(queriers, operator.ResourceQueryToZitadelQuery(queryNS), - operator.EnsureFuncToQueryFunc(Reconcile(monitor, desiredKind.Spec, gitops)), + operator.EnsureFuncToQueryFunc(rec), ) } } diff --git a/operator/database/kinds/orb/backups.go b/operator/database/kinds/orb/backups.go index 6dd1b03f6..07ffcbd0c 100644 --- a/operator/database/kinds/orb/backups.go +++ b/operator/database/kinds/orb/backups.go @@ -2,13 +2,14 @@ package orb import ( "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/kubernetes" "github.com/caos/orbos/pkg/tree" "github.com/caos/zitadel/operator/database/kinds/databases" "github.com/pkg/errors" ) -func BackupListFunc() func(monitor mntr.Monitor, desiredTree *tree.Tree) (strings []string, err error) { - return func(monitor mntr.Monitor, desiredTree *tree.Tree) (strings []string, err error) { +func BackupListFunc() func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, desiredTree *tree.Tree) (strings []string, err error) { + return func(monitor mntr.Monitor, k8sClient kubernetes.ClientInt, desiredTree *tree.Tree) (strings []string, err error) { desiredKind, err := ParseDesiredV0(desiredTree) if err != nil { return nil, errors.Wrap(err, "parsing desired state failed") @@ -19,6 +20,6 @@ func BackupListFunc() func(monitor mntr.Monitor, desiredTree *tree.Tree) (string monitor = monitor.Verbose() } - return databases.GetBackupList(monitor, desiredKind.Database) + return databases.GetBackupList(monitor, k8sClient, desiredKind.Database) } } diff --git a/operator/database/kinds/orb/reconcile.go b/operator/database/kinds/orb/reconcile.go index dd9a3f926..7345599f1 100644 --- a/operator/database/kinds/orb/reconcile.go +++ b/operator/database/kinds/orb/reconcile.go @@ -3,6 +3,7 @@ package orb import ( "github.com/caos/orbos/mntr" "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/labels" "github.com/caos/orbos/pkg/tree" "github.com/caos/orbos/pkg/treelabels" "github.com/caos/zitadel/operator" @@ -14,31 +15,39 @@ func Reconcile( monitor mntr.Monitor, spec *Spec, gitops bool, -) operator.EnsureFunc { +) ( + operator.EnsureFunc, + operator.DestroyFunc, +) { return func(k8sClient kubernetes.ClientInt) (err error) { - recMonitor := monitor.WithField("version", spec.Version) + recMonitor := monitor.WithField("version", spec.Version) - if spec.Version == "" { - err := errors.New("No version provided for self-reconciling") - recMonitor.Error(err) - return err - } - - if spec.SelfReconciling { - desiredTree := &tree.Tree{ - Common: &tree.Common{ - Kind: "databases.caos.ch/Orb", - Version: "v0", - }, - } - - if err := zitadelKubernetes.EnsureDatabaseArtifacts(monitor, treelabels.MustForAPI(desiredTree, mustDatabaseOperator(&spec.Version)), k8sClient, spec.Version, spec.NodeSelector, spec.Tolerations, spec.CustomImageRegistry, gitops); err != nil { - recMonitor.Error(errors.Wrap(err, "Failed to deploy database-operator into k8s-cluster")) + if spec.Version == "" { + err := errors.New("No version provided for self-reconciling") return err } - recMonitor.Info("Applied database-operator") - } - return nil - } + if spec.SelfReconciling { + desiredTree := &tree.Tree{ + Common: &tree.Common{ + Kind: "databases.caos.ch/Orb", + Version: "v0", + }, + } + + if err := zitadelKubernetes.EnsureDatabaseArtifacts(monitor, treelabels.MustForAPI(desiredTree, mustDatabaseOperator(&spec.Version)), k8sClient, spec.Version, spec.NodeSelector, spec.Tolerations, spec.CustomImageRegistry, gitops); err != nil { + recMonitor.Error(errors.Wrap(err, "Failed to deploy database-operator into k8s-cluster")) + return err + } + recMonitor.Info("Applied database-operator") + } + return nil + }, func(k8sClient kubernetes.ClientInt) error { + if err := zitadelKubernetes.DestroyDatabaseOperator(monitor, labels.MustForAPI(labels.NoopOperator("database-operator"), "database", "v0"), k8sClient, gitops); err != nil { + monitor.Error(errors.Wrap(err, "Failed to destroy database-operator in k8s-cluster")) + return err + } + monitor.Info("Destroyed database-operator") + return nil + } } diff --git a/operator/zitadel/destroy.go b/operator/zitadel/destroy.go new file mode 100644 index 000000000..870b60ebd --- /dev/null +++ b/operator/zitadel/destroy.go @@ -0,0 +1,34 @@ +package zitadel + +import ( + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/git" + "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/tree" + "github.com/caos/zitadel/operator" +) + +func Destroy( + monitor mntr.Monitor, + gitClient *git.Client, + adapt operator.AdaptFunc, + k8sClient *kubernetes.Client, +) error { + internalMonitor := monitor.WithField("operator", "zitadel") + internalMonitor.Info("Destroy") + treeDesired, err := operator.Parse(gitClient, "zitadel.yml") + if err != nil { + return err + } + treeCurrent := &tree.Tree{} + + _, destroy, _, _, _, _, err := adapt(internalMonitor, treeDesired, treeCurrent) + if err != nil { + return err + } + + if err := destroy(k8sClient); err != nil { + return err + } + return nil +} diff --git a/operator/zitadel/kinds/iam/zitadel/migration/adapt.go b/operator/zitadel/kinds/iam/zitadel/migration/adapt.go index 2da9e6db4..b34dca009 100644 --- a/operator/zitadel/kinds/iam/zitadel/migration/adapt.go +++ b/operator/zitadel/kinds/iam/zitadel/migration/adapt.go @@ -64,7 +64,7 @@ func AdaptFunc( return nil, nil, err } - destroyJ, err := job.AdaptFuncToDestroy(jobName, namespace) + destroyJ, err := job.AdaptFuncToDestroy(namespace, jobName) if err != nil { return nil, nil, err } diff --git a/operator/zitadel/kinds/iam/zitadel/setup/adapt.go b/operator/zitadel/kinds/iam/zitadel/setup/adapt.go index 25446a627..660bf8aad 100644 --- a/operator/zitadel/kinds/iam/zitadel/setup/adapt.go +++ b/operator/zitadel/kinds/iam/zitadel/setup/adapt.go @@ -51,7 +51,7 @@ func AdaptFunc( jobName := getJobName(reason) nameLabels := labels.MustForName(componentLabels, jobName) - destroyJ, err := job.AdaptFuncToDestroy(jobName, namespace) + destroyJ, err := job.AdaptFuncToDestroy(namespace, jobName) if err != nil { return nil, nil, err } diff --git a/operator/zitadel/kinds/orb/adapt.go b/operator/zitadel/kinds/orb/adapt.go index f385182df..91fa3165e 100644 --- a/operator/zitadel/kinds/orb/adapt.go +++ b/operator/zitadel/kinds/orb/adapt.go @@ -101,6 +101,8 @@ func AdaptFunc( migrate = migrate || migrateIAM secret.AppendSecrets("", allSecrets, zitadelSecrets, allExisting, zitadelExisting) + rec, _ := Reconcile(monitor, desiredKind.Spec, gitops) + destroyers := make([]operator.DestroyFunc, 0) queriers := make([]operator.QueryFunc, 0) for _, feature := range features { @@ -114,7 +116,7 @@ func AdaptFunc( case "operator": queriers = append(queriers, operator.ResourceQueryToZitadelQuery(queryNS), - operator.EnsureFuncToQueryFunc(Reconcile(monitor, desiredKind.Spec, gitops)), + operator.EnsureFuncToQueryFunc(rec), ) } } diff --git a/operator/zitadel/kinds/orb/reconcile.go b/operator/zitadel/kinds/orb/reconcile.go index 6c2e79c9c..e72280fa0 100644 --- a/operator/zitadel/kinds/orb/reconcile.go +++ b/operator/zitadel/kinds/orb/reconcile.go @@ -1,8 +1,10 @@ package orb import ( + "fmt" "github.com/caos/orbos/mntr" kubernetes2 "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/labels" "github.com/caos/orbos/pkg/tree" "github.com/caos/orbos/pkg/treelabels" "github.com/caos/zitadel/operator" @@ -14,31 +16,39 @@ func Reconcile( monitor mntr.Monitor, spec *Spec, gitops bool, -) operator.EnsureFunc { +) ( + operator.EnsureFunc, + operator.DestroyFunc, +) { return func(k8sClient kubernetes2.ClientInt) (err error) { - recMonitor := monitor.WithField("version", spec.Version) + recMonitor := monitor.WithField("version", spec.Version) - if spec.Version == "" { - err := errors.New("No version provided for self-reconciling") - recMonitor.Error(err) - return err - } - - if spec.SelfReconciling { - desiredTree := &tree.Tree{ - Common: &tree.Common{ - Kind: "zitadel.caos.ch/Orb", - Version: "v0", - }, - } - - if err := kubernetes.EnsureZitadelOperatorArtifacts(monitor, treelabels.MustForAPI(desiredTree, mustZITADELOperator(&spec.Version)), k8sClient, spec.Version, spec.NodeSelector, spec.Tolerations, spec.CustomImageRegistry, gitops); err != nil { - recMonitor.Error(errors.Wrap(err, "Failed to deploy zitadel-operator into k8s-cluster")) + if spec.Version == "" { + err := errors.New("No version provided for self-reconciling") + recMonitor.Error(err) return err } - recMonitor.Info("Applied zitadel-operator") - } - return nil - } + if spec.SelfReconciling { + desiredTree := &tree.Tree{ + Common: &tree.Common{ + Kind: "zitadel.caos.ch/Orb", + Version: "v0", + }, + } + + if err := kubernetes.EnsureZitadelOperatorArtifacts(monitor, treelabels.MustForAPI(desiredTree, mustZITADELOperator(&spec.Version)), k8sClient, spec.Version, spec.NodeSelector, spec.Tolerations, spec.CustomImageRegistry, gitops); err != nil { + return fmt.Errorf("failed to deploy zitadel-operator into k8s-cluster: %w", err) + } + recMonitor.Info("Applied zitadel-operator") + } + return nil + }, func(k8sClient kubernetes2.ClientInt) error { + if err := kubernetes.DestroyZitadelOperator(monitor, labels.MustForAPI(labels.NoopOperator("zitadel-operator"), "zitadel", "v0"), k8sClient, gitops); err != nil { + monitor.Error(errors.Wrap(err, "Failed to destroy zitadel-operator in k8s-cluster")) + return err + } + monitor.Info("Destroyed zitadel-operator") + return nil + } } diff --git a/pkg/databases/backup.go b/pkg/databases/backup.go index 9e0f7e790..e03875441 100644 --- a/pkg/databases/backup.go +++ b/pkg/databases/backup.go @@ -5,10 +5,11 @@ import ( "github.com/caos/orbos/pkg/git" "github.com/caos/orbos/pkg/kubernetes" "github.com/caos/orbos/pkg/tree" + "github.com/caos/zitadel/operator/api/database" orbdb "github.com/caos/zitadel/operator/database/kinds/orb" ) -func InstantBackup( +func GitOpsInstantBackup( monitor mntr.Monitor, k8sClient kubernetes.ClientInt, gitClient *git.Client, @@ -16,9 +17,29 @@ func InstantBackup( ) error { desired, err := gitClient.ReadTree(git.DatabaseFile) if err != nil { - monitor.Error(err) return err } + return instantBackup(monitor, k8sClient, desired, name) +} + +func CrdInstantBackup( + monitor mntr.Monitor, + k8sClient kubernetes.ClientInt, + name string, +) error { + desired, err := database.ReadCrd(k8sClient) + if err != nil { + return err + } + return instantBackup(monitor, k8sClient, desired, name) +} + +func instantBackup( + monitor mntr.Monitor, + k8sClient kubernetes.ClientInt, + desired *tree.Tree, + name string, +) error { current := &tree.Tree{} query, _, _, _, _, _, err := orbdb.AdaptFunc(name, nil, false, "instantbackup")(monitor, desired, current) @@ -40,25 +61,3 @@ func InstantBackup( } return nil } - -func ListBackups( - monitor mntr.Monitor, - gitClient *git.Client, -) ( - []string, - error, -) { - desired, err := gitClient.ReadTree(git.DatabaseFile) - if err != nil { - monitor.Error(err) - return nil, err - } - - backups, err := orbdb.BackupListFunc()(monitor, desired) - if err != nil { - monitor.Error(err) - return nil, err - } - - return backups, nil -} diff --git a/pkg/databases/backuplist.go b/pkg/databases/backuplist.go new file mode 100644 index 000000000..9ffedd953 --- /dev/null +++ b/pkg/databases/backuplist.go @@ -0,0 +1,57 @@ +package databases + +import ( + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/git" + "github.com/caos/orbos/pkg/kubernetes" + "github.com/caos/orbos/pkg/tree" + "github.com/caos/zitadel/operator/api/database" + orbdb "github.com/caos/zitadel/operator/database/kinds/orb" +) + +func GitOpsListBackups( + monitor mntr.Monitor, + gitClient *git.Client, + k8sClient kubernetes.ClientInt, +) ( + []string, + error, +) { + desired, err := gitClient.ReadTree(git.DatabaseFile) + if err != nil { + return nil, err + } + + return listBackups(monitor, k8sClient, desired) +} + +func CrdListBackups( + monitor mntr.Monitor, + k8sClient kubernetes.ClientInt, +) ( + []string, + error, +) { + desired, err := database.ReadCrd(k8sClient) + if err != nil { + return nil, err + } + + return listBackups(monitor, k8sClient, desired) +} + +func listBackups( + monitor mntr.Monitor, + k8sClient kubernetes.ClientInt, + desired *tree.Tree, +) ( + []string, + error, +) { + backups, err := orbdb.BackupListFunc()(monitor, k8sClient, desired) + if err != nil { + return nil, err + } + + return backups, nil +} diff --git a/pkg/databases/clear.go b/pkg/databases/clear.go index 8e3e7a7f6..6321da7ae 100644 --- a/pkg/databases/clear.go +++ b/pkg/databases/clear.go @@ -5,21 +5,47 @@ import ( "github.com/caos/orbos/pkg/git" "github.com/caos/orbos/pkg/kubernetes" "github.com/caos/orbos/pkg/tree" + "github.com/caos/zitadel/operator/api/database" "github.com/caos/zitadel/operator/database/kinds/databases/core" orbdb "github.com/caos/zitadel/operator/database/kinds/orb" ) -func Clear( +func GitOpsClear( monitor mntr.Monitor, k8sClient kubernetes.ClientInt, gitClient *git.Client, databases []string, + users []string, ) error { desired, err := gitClient.ReadTree(git.DatabaseFile) if err != nil { - monitor.Error(err) return err } + + return clear(monitor, k8sClient, databases, users, desired) +} + +func CrdClear( + monitor mntr.Monitor, + k8sClient kubernetes.ClientInt, + databases []string, + users []string, +) error { + desired, err := database.ReadCrd(k8sClient) + if err != nil { + return err + } + + return clear(monitor, k8sClient, databases, users, desired) +} + +func clear( + monitor mntr.Monitor, + k8sClient kubernetes.ClientInt, + databases []string, + users []string, + desired *tree.Tree, +) error { current := &tree.Tree{} query, _, _, _, _, _, err := orbdb.AdaptFunc("", nil, false, "clean")(monitor, desired, current) @@ -28,7 +54,7 @@ func Clear( return err } queried := map[string]interface{}{} - core.SetQueriedForDatabaseDBList(queried, databases) + core.SetQueriedForDatabaseDBList(queried, databases, users) ensure, err := query(k8sClient, queried) if err != nil { @@ -37,8 +63,8 @@ func Clear( } if err := ensure(k8sClient); err != nil { - monitor.Error(err) return err } + return nil } diff --git a/pkg/databases/connection.go b/pkg/databases/connection.go index 5c5fdc1bb..fae306930 100644 --- a/pkg/databases/connection.go +++ b/pkg/databases/connection.go @@ -19,7 +19,7 @@ func CrdGetConnectionInfo( return "", "", err } - return getConnectionInfo(monitor, k8sClient, desired) + return getConnectionInfo(monitor, k8sClient, desired, false) } func GitOpsGetConnectionInfo( @@ -33,17 +33,18 @@ func GitOpsGetConnectionInfo( return "", "", err } - return getConnectionInfo(monitor, k8sClient, desired) + return getConnectionInfo(monitor, k8sClient, desired, true) } func getConnectionInfo( monitor mntr.Monitor, k8sClient kubernetes.ClientInt, desired *tree.Tree, + gitOps bool, ) (string, string, error) { current := &tree.Tree{} - query, _, _, _, _, _, err := orbdb.AdaptFunc("", nil, false, "database")(monitor, desired, current) + query, _, _, _, _, _, err := orbdb.AdaptFunc("", nil, gitOps, "database")(monitor, desired, current) if err != nil { return "", "", err } diff --git a/pkg/databases/restore.go b/pkg/databases/restore.go index 50a9485ba..d18534598 100644 --- a/pkg/databases/restore.go +++ b/pkg/databases/restore.go @@ -5,11 +5,12 @@ import ( "github.com/caos/orbos/pkg/git" "github.com/caos/orbos/pkg/kubernetes" "github.com/caos/orbos/pkg/tree" + "github.com/caos/zitadel/operator/api/database" "github.com/caos/zitadel/operator/database/kinds/databases/core" orbdb "github.com/caos/zitadel/operator/database/kinds/orb" ) -func Restore( +func GitOpsRestore( monitor mntr.Monitor, k8sClient kubernetes.ClientInt, gitClient *git.Client, @@ -18,9 +19,31 @@ func Restore( ) error { desired, err := gitClient.ReadTree(git.DatabaseFile) if err != nil { - monitor.Error(err) return err } + return restore(monitor, k8sClient, desired, name, databases) +} + +func CrdRestore( + monitor mntr.Monitor, + k8sClient kubernetes.ClientInt, + name string, + databases []string, +) error { + desired, err := database.ReadCrd(k8sClient) + if err != nil { + return err + } + return restore(monitor, k8sClient, desired, name, databases) +} + +func restore( + monitor mntr.Monitor, + k8sClient kubernetes.ClientInt, + desired *tree.Tree, + name string, + databases []string, +) error { current := &tree.Tree{} query, _, _, _, _, _, err := orbdb.AdaptFunc(name, nil, false, "restore")(monitor, desired, current) @@ -29,7 +52,7 @@ func Restore( return err } queried := map[string]interface{}{} - core.SetQueriedForDatabaseDBList(queried, databases) + core.SetQueriedForDatabaseDBList(queried, databases, []string{}) ensure, err := query(k8sClient, queried) if err != nil { diff --git a/pkg/kubernetes/artifacts.go b/pkg/kubernetes/artifacts.go index f7ea5917f..b86b5600a 100644 --- a/pkg/kubernetes/artifacts.go +++ b/pkg/kubernetes/artifacts.go @@ -16,6 +16,14 @@ import ( mach "k8s.io/apimachinery/pkg/apis/meta/v1" ) +const ( + namespace = "caos-system" +) + +func getZitadelOperatorNameLabels(apiLabels *labels.API) *labels.Name { + return toNameLabels(apiLabels, "zitadel-operator") +} + func EnsureZitadelOperatorArtifacts( monitor mntr.Monitor, apiLabels *labels.API, @@ -31,7 +39,7 @@ func EnsureZitadelOperatorArtifacts( "zitadel": version, }).Debug("Ensuring zitadel artifacts") - nameLabels := labels.MustForName(labels.MustForComponent(apiLabels, "operator"), "zitadel-operator") + nameLabels := getZitadelOperatorNameLabels(apiLabels) k8sNameLabels := labels.MustK8sMap(nameLabels) k8sPodSelector := labels.MustK8sMap(labels.DeriveNameSelector(nameLabels, false)) @@ -42,7 +50,7 @@ func EnsureZitadelOperatorArtifacts( if err := client.ApplyServiceAccount(&core.ServiceAccount{ ObjectMeta: mach.ObjectMeta{ Name: nameLabels.Name(), - Namespace: "caos-system", + Namespace: namespace, }, }); err != nil { return err @@ -76,7 +84,7 @@ func EnsureZitadelOperatorArtifacts( Subjects: []rbac.Subject{{ Kind: "ServiceAccount", Name: nameLabels.Name(), - Namespace: "caos-system", + Namespace: namespace, }}, }); err != nil { return err @@ -251,7 +259,7 @@ status: deployment := &apps.Deployment{ ObjectMeta: mach.ObjectMeta{ Name: nameLabels.Name(), - Namespace: "caos-system", + Namespace: namespace, Labels: k8sNameLabels, }, Spec: apps.DeploymentSpec{ @@ -305,6 +313,40 @@ status: return nil } +func DestroyZitadelOperator( + monitor mntr.Monitor, + apiLabels *labels.API, + client kubernetes.ClientInt, + gitops bool, +) error { + nameLabels := getZitadelOperatorNameLabels(apiLabels) + + monitor.WithFields(map[string]interface{}{}).Debug("Destroying zitadel artifacts") + + if err := client.DeleteServiceAccount(namespace, nameLabels.Name()); err != nil { + return err + } + + if err := client.DeleteClusterRole(nameLabels.Name()); err != nil { + return err + } + + if err := client.DeleteClusterRoleBinding(nameLabels.Name()); err != nil { + return err + } + + if !gitops { + if err := client.DeleteCRDResource("apiextensions.k8s.io", "v1beta1", "CustomResourceDefinition", "zitadels.caos.ch"); err != nil { + return err + } + } + + if err := client.DeleteDeployment(namespace, nameLabels.Name()); err != nil { + return err + } + + return nil +} func ScaleZitadelOperator( monitor mntr.Monitor, @@ -312,7 +354,16 @@ func ScaleZitadelOperator( replicaCount int, ) error { monitor.Debug("Scaling zitadel-operator") - return client.ScaleDeployment("caos-system", "zitadel-operator", replicaCount) + return client.ScaleDeployment(namespace, "zitadel-operator", replicaCount) +} + +func ScaleDatabaseOperator( + monitor mntr.Monitor, + client *kubernetes.Client, + replicaCount int, +) error { + monitor.Debug("Scaling database-operator") + return client.ScaleDeployment(namespace, "database-operator", replicaCount) } func int32Ptr(i int32) *int32 { return &i } @@ -322,6 +373,10 @@ func toNameLabels(apiLabels *labels.API, operatorName string) *labels.Name { return labels.MustForName(labels.MustForComponent(apiLabels, "operator"), operatorName) } +func getDatabaseOperatorNameLabels(apiLabels *labels.API) *labels.Name { + return toNameLabels(apiLabels, "database-operator") +} + func EnsureDatabaseArtifacts( monitor mntr.Monitor, apiLabels *labels.API, @@ -345,8 +400,8 @@ func EnsureDatabaseArtifacts( if err := client.ApplyServiceAccount(&core.ServiceAccount{ ObjectMeta: mach.ObjectMeta{ - Name: "database-operator", - Namespace: "caos-system", + Name: nameLabels.Name(), + Namespace: namespace, Labels: k8sNameLabels, }, }); err != nil { @@ -355,7 +410,7 @@ func EnsureDatabaseArtifacts( if err := client.ApplyClusterRole(&rbac.ClusterRole{ ObjectMeta: mach.ObjectMeta{ - Name: "database-operator-clusterrole", + Name: nameLabels.Name(), Labels: k8sNameLabels, }, Rules: []rbac.PolicyRule{{ @@ -369,19 +424,19 @@ func EnsureDatabaseArtifacts( if err := client.ApplyClusterRoleBinding(&rbac.ClusterRoleBinding{ ObjectMeta: mach.ObjectMeta{ - Name: "database-operator-clusterrolebinding", + Name: nameLabels.Name(), Labels: k8sNameLabels, }, RoleRef: rbac.RoleRef{ APIGroup: "rbac.authorization.k8s.io", Kind: "ClusterRole", - Name: "database-operator-clusterrole", + Name: nameLabels.Name(), }, Subjects: []rbac.Subject{{ Kind: "ServiceAccount", - Name: "database-operator", - Namespace: "caos-system", + Name: nameLabels.Name(), + Namespace: namespace, }}, }); err != nil { return err @@ -548,8 +603,8 @@ status: deployment := &apps.Deployment{ ObjectMeta: mach.ObjectMeta{ - Name: "database-operator", - Namespace: "caos-system", + Name: nameLabels.Name(), + Namespace: namespace, Labels: k8sNameLabels, }, Spec: apps.DeploymentSpec{ @@ -562,7 +617,7 @@ status: Labels: labels.MustK8sMap(labels.AsSelectable(nameLabels)), }, Spec: core.PodSpec{ - ServiceAccountName: "database-operator", + ServiceAccountName: nameLabels.Name(), Containers: []core.Container{{ Name: "database", ImagePullPolicy: core.PullIfNotPresent, @@ -604,3 +659,38 @@ status: return nil } + +func DestroyDatabaseOperator( + monitor mntr.Monitor, + apiLabels *labels.API, + client kubernetes.ClientInt, + gitops bool, +) error { + nameLabels := getDatabaseOperatorNameLabels(apiLabels) + + monitor.WithFields(map[string]interface{}{}).Debug("Destroying database artifacts") + + if err := client.DeleteServiceAccount(namespace, nameLabels.Name()); err != nil { + return err + } + + if err := client.DeleteClusterRole(nameLabels.Name()); err != nil { + return err + } + + if err := client.DeleteClusterRoleBinding(nameLabels.Name()); err != nil { + return err + } + + if !gitops { + if err := client.DeleteCRDResource("apiextensions.k8s.io", "v1beta1", "CustomResourceDefinition", "databases.caos.ch"); err != nil { + return err + } + } + + if err := client.DeleteDeployment(namespace, nameLabels.Name()); err != nil { + return err + } + + return nil +} diff --git a/pkg/zitadel/clearmigraterestore.go b/pkg/zitadel/clearmigraterestore.go new file mode 100644 index 000000000..b6af6eba0 --- /dev/null +++ b/pkg/zitadel/clearmigraterestore.go @@ -0,0 +1,103 @@ +package zitadel + +import ( + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/git" + "github.com/caos/orbos/pkg/kubernetes" + orbconfig "github.com/caos/orbos/pkg/orb" + "github.com/caos/zitadel/pkg/databases" + kubernetes2 "github.com/caos/zitadel/pkg/kubernetes" + "time" +) + +var ( + databasesList = []string{ + "notification", + "adminapi", + "auth", + "authz", + "eventstore", + "management", + } + userList = []string{ + "notification", + "adminapi", + "auth", + "authz", + "eventstore", + "management", + "queries", + } +) + +func GitOpsClearMigrateRestore( + monitor mntr.Monitor, + gitClient *git.Client, + orbCfg *orbconfig.Orb, + k8sClient *kubernetes.Client, + backup string, + version *string, +) error { + + if err := kubernetes2.ScaleZitadelOperator(monitor, k8sClient, 0); err != nil { + return err + } + time.Sleep(5 * time.Second) + + if err := GitOpsScaleDown(monitor, orbCfg, gitClient, k8sClient, version); err != nil { + return err + } + + if err := databases.GitOpsClear(monitor, k8sClient, gitClient, databasesList, userList); err != nil { + return err + } + + if err := GitOpsMigrations(monitor, orbCfg, gitClient, k8sClient, version); err != nil { + return err + } + + if err := databases.GitOpsRestore(monitor, k8sClient, gitClient, backup, databasesList); err != nil { + return err + } + + if err := kubernetes2.ScaleZitadelOperator(monitor, k8sClient, 1); err != nil { + return err + } + + return nil +} + +func CrdClearMigrateRestore( + monitor mntr.Monitor, + k8sClient *kubernetes.Client, + backup string, + version *string, +) error { + + if err := kubernetes2.ScaleZitadelOperator(monitor, k8sClient, 0); err != nil { + return err + } + time.Sleep(5 * time.Second) + + if err := CrdScaleDown(monitor, k8sClient, version); err != nil { + return err + } + + if err := databases.CrdClear(monitor, k8sClient, databasesList, userList); err != nil { + return err + } + + if err := CrdMigrations(monitor, k8sClient, version); err != nil { + return err + } + + if err := databases.CrdRestore(monitor, k8sClient, backup, databasesList); err != nil { + return err + } + + if err := kubernetes2.ScaleZitadelOperator(monitor, k8sClient, 1); err != nil { + return err + } + + return nil +} diff --git a/pkg/zitadel/migration.go b/pkg/zitadel/migration.go new file mode 100644 index 000000000..674988290 --- /dev/null +++ b/pkg/zitadel/migration.go @@ -0,0 +1,67 @@ +package zitadel + +import ( + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/git" + "github.com/caos/orbos/pkg/kubernetes" + orbconfig "github.com/caos/orbos/pkg/orb" + "github.com/caos/orbos/pkg/tree" + "github.com/caos/zitadel/operator/api/zitadel" + "github.com/caos/zitadel/operator/zitadel/kinds/orb" +) + +//Take care! to use this function you have to include migration files into the binary +func CrdMigrations( + monitor mntr.Monitor, + k8sClient *kubernetes.Client, + version *string, +) error { + desired, err := zitadel.ReadCrd(k8sClient) + if err != nil { + return err + } + + return migrations(monitor, nil, k8sClient, false, version, desired) +} + +//Take care! to use this function you have to include migration files into the binary +func GitOpsMigrations( + monitor mntr.Monitor, + orbCfg *orbconfig.Orb, + gitClient *git.Client, + k8sClient *kubernetes.Client, + version *string, +) error { + desired, err := gitClient.ReadTree(git.ZitadelFile) + if err != nil { + return err + } + + return migrations(monitor, orbCfg, k8sClient, true, version, desired) +} + +//Take care! to use this function you have to include migration files into the binary +func migrations( + monitor mntr.Monitor, + orbCfg *orbconfig.Orb, + k8sClient *kubernetes.Client, + gitops bool, + version *string, + desired *tree.Tree, +) error { + current := &tree.Tree{} + query, _, _, _, _, _, err := orb.AdaptFunc(orbCfg, "migration", version, gitops, []string{"migration"})(monitor, desired, current) + if err != nil { + return err + } + + ensure, err := query(k8sClient, map[string]interface{}{}) + if err != nil { + return err + } + + if err := ensure(k8sClient); err != nil { + return err + } + return nil +} diff --git a/pkg/zitadel/zitadel.go b/pkg/zitadel/zitadel.go new file mode 100644 index 000000000..fc6c33984 --- /dev/null +++ b/pkg/zitadel/zitadel.go @@ -0,0 +1,65 @@ +package zitadel + +import ( + "github.com/caos/orbos/mntr" + "github.com/caos/orbos/pkg/git" + "github.com/caos/orbos/pkg/kubernetes" + orbconfig "github.com/caos/orbos/pkg/orb" + "github.com/caos/orbos/pkg/tree" + "github.com/caos/zitadel/operator/api/zitadel" + "github.com/caos/zitadel/operator/zitadel/kinds/orb" +) + +func CrdScaleDown( + monitor mntr.Monitor, + k8sClient *kubernetes.Client, + version *string, +) error { + desired, err := zitadel.ReadCrd(k8sClient) + if err != nil { + return err + } + + return scaleDown(monitor, nil, k8sClient, false, version, desired) +} + +func GitOpsScaleDown( + monitor mntr.Monitor, + orbCfg *orbconfig.Orb, + gitClient *git.Client, + k8sClient *kubernetes.Client, + version *string, +) error { + desired, err := gitClient.ReadTree(git.ZitadelFile) + if err != nil { + return err + } + + return scaleDown(monitor, orbCfg, k8sClient, true, version, desired) +} + +//Take care! to use this function you have to include migration files into the binary +func scaleDown( + monitor mntr.Monitor, + orbCfg *orbconfig.Orb, + k8sClient *kubernetes.Client, + gitops bool, + version *string, + desired *tree.Tree, +) error { + current := &tree.Tree{} + query, _, _, _, _, _, err := orb.AdaptFunc(orbCfg, "scaledown", version, gitops, []string{"scaledown"})(monitor, desired, current) + if err != nil { + return err + } + + ensure, err := query(k8sClient, map[string]interface{}{}) + if err != nil { + return err + } + + if err := ensure(k8sClient); err != nil { + return err + } + return nil +}