From bafa71f49726cefbe6c3942d6c59d7368fe29357 Mon Sep 17 00:00:00 2001 From: Oksana Grishchenko Date: Wed, 14 Feb 2024 14:04:41 +0200 Subject: [PATCH 1/7] EVEREST-843 Comma-separated namespaces flag --- cli-tests/tests/flow/all-operators.spec.ts | 4 ++-- commands/install.go | 6 +++--- commands/upgrade.go | 4 ++-- install.sh | 2 +- pkg/install/install.go | 23 +++++++++++++--------- pkg/kubernetes/kubernetes.go | 2 +- pkg/upgrade/upgrade.go | 9 +++++++-- 7 files changed, 30 insertions(+), 20 deletions(-) diff --git a/cli-tests/tests/flow/all-operators.spec.ts b/cli-tests/tests/flow/all-operators.spec.ts index 54ef12d4..b0cc5de8 100644 --- a/cli-tests/tests/flow/all-operators.spec.ts +++ b/cli-tests/tests/flow/all-operators.spec.ts @@ -46,7 +46,7 @@ test.describe('Everest CLI install', async () => { await test.step('run everest install command', async () => { const out = await cli.everestExecSkipWizard( - `install --namespace=everest-all`, + `install --namespaces=everest-all`, ); await out.assertSuccess(); @@ -73,7 +73,7 @@ test.describe('Everest CLI install', async () => { await out.assertSuccess(); - out = await cli.everestExecSkipWizardWithEnv('upgrade --namespace=everest-all', 'DISABLE_TELEMETRY=true'); + out = await cli.everestExecSkipWizardWithEnv('upgrade --namespaces=everest-all', 'DISABLE_TELEMETRY=true'); await out.assertSuccess(); await out.outErrContainsNormalizedMany([ 'Subscriptions have been patched\t{"component": "upgrade"}', diff --git a/commands/install.go b/commands/install.go index cdc59bba..7c15ca0e 100644 --- a/commands/install.go +++ b/commands/install.go @@ -30,7 +30,7 @@ import ( func newInstallCmd(l *zap.SugaredLogger) *cobra.Command { cmd := &cobra.Command{ Use: "install", - Example: "everestctl install --namespace dev --namespace staging --namespace prod --operator.mongodb=true --operator.postgresql=true --operator.xtradb-cluster=true --skip-wizard", + Example: "everestctl install --namespaces dev,staging,prod --operator.mongodb=true --operator.postgresql=true --operator.xtradb-cluster=true --skip-wizard", Run: func(cmd *cobra.Command, args []string) { initInstallViperFlags(cmd) c := &install.Config{} @@ -58,7 +58,7 @@ func newInstallCmd(l *zap.SugaredLogger) *cobra.Command { func initInstallFlags(cmd *cobra.Command) { cmd.Flags().StringP("kubeconfig", "k", "~/.kube/config", "Path to a kubeconfig") - cmd.Flags().StringArray("namespace", []string{}, "Namespaces list Percona Everest can manage") + cmd.Flags().String("namespaces", "", "Comma-separated namespaces list Percona Everest can manage") cmd.Flags().Bool("skip-wizard", false, "Skip installation wizard") cmd.Flags().Bool("operator.mongodb", true, "Install MongoDB operator") @@ -71,7 +71,7 @@ func initInstallViperFlags(cmd *cobra.Command) { viper.BindEnv("kubeconfig") //nolint:errcheck,gosec viper.BindPFlag("kubeconfig", cmd.Flags().Lookup("kubeconfig")) //nolint:errcheck,gosec - viper.BindPFlag("namespace", cmd.Flags().Lookup("namespace")) //nolint:errcheck,gosec + viper.BindPFlag("namespaces", cmd.Flags().Lookup("namespaces")) //nolint:errcheck,gosec viper.BindPFlag("operator.mongodb", cmd.Flags().Lookup("operator.mongodb")) //nolint:errcheck,gosec viper.BindPFlag("operator.postgresql", cmd.Flags().Lookup("operator.postgresql")) //nolint:errcheck,gosec diff --git a/commands/upgrade.go b/commands/upgrade.go index 3c6f5f54..7380ddb1 100644 --- a/commands/upgrade.go +++ b/commands/upgrade.go @@ -59,7 +59,7 @@ func newUpgradeCmd(l *zap.SugaredLogger) *cobra.Command { func initUpgradeFlags(cmd *cobra.Command) { cmd.Flags().StringP("kubeconfig", "k", "~/.kube/config", "Path to a kubeconfig") - cmd.Flags().StringArray("namespace", []string{}, "Namespaces list Percona Everest can manage") + cmd.Flags().String("namespaces", "", "Comma-separated namespaces list Percona Everest can manage") cmd.Flags().Bool("upgrade-olm", false, "Upgrade OLM distribution") cmd.Flags().Bool("skip-wizard", false, "Skip installation wizard") } @@ -67,7 +67,7 @@ func initUpgradeFlags(cmd *cobra.Command) { func initUpgradeViperFlags(cmd *cobra.Command) { viper.BindEnv("kubeconfig") //nolint:errcheck,gosec viper.BindPFlag("kubeconfig", cmd.Flags().Lookup("kubeconfig")) //nolint:errcheck,gosec - viper.BindPFlag("namespace", cmd.Flags().Lookup("namespace")) //nolint:errcheck,gosec + viper.BindPFlag("namespaces", cmd.Flags().Lookup("namespaces")) //nolint:errcheck,gosec viper.BindPFlag("upgrade-olm", cmd.Flags().Lookup("upgrade-olm")) //nolint:errcheck,gosec viper.BindPFlag("skip-wizard", cmd.Flags().Lookup("skip-wizard")) //nolint:errcheck,gosec } diff --git a/install.sh b/install.sh index 9e5b24c8..cab215c4 100755 --- a/install.sh +++ b/install.sh @@ -35,7 +35,7 @@ fi echo "Provisioning Everest with monitoring disabled" echo "If you want to enable monitoring please refer to the everest installation documentation." echo "" -./everestctl install --namespace everest --operator.mongodb=true --operator.postgresql=true --operator.xtradb-cluster=true --skip-wizard +./everestctl install --namespaces everest --operator.mongodb=true --operator.postgresql=true --operator.xtradb-cluster=true --skip-wizard echo "Your provisioned Everest instance will be available at http://127.0.0.1:8080" echo "Exposing Everest using kubectl port-forwarding. You can expose it manually" diff --git a/pkg/install/install.go b/pkg/install/install.go index 850e291e..df2d42e1 100644 --- a/pkg/install/install.go +++ b/pkg/install/install.go @@ -91,7 +91,7 @@ type ( // Config stores configuration for the operators. Config struct { // Namespaces defines namespaces that everest can operate in. - Namespaces []string `mapstructure:"namespace"` + Namespaces string `mapstructure:"namespaces"` // SkipWizard skips wizard during installation. SkipWizard bool `mapstructure:"skip-wizard"` // KubeconfigPath is a path to a kubeconfig @@ -111,6 +111,10 @@ type ( } ) +func (c Config) NamespacesList() []string { + return strings.Split(c.Namespaces, ",") +} + // NewInstall returns a new Install struct. func NewInstall(c Config, l *zap.SugaredLogger) (*Install, error) { cli := &Install{ @@ -179,9 +183,10 @@ func (o *Install) populateConfig() error { } if len(o.config.Namespaces) == 0 { - return errors.New("namespace list is empty. Specify at least one namespace using the --namespace flag") + return errors.New("namespace list is empty. Specify the comma-separated list of namespaces using the --namespaces flag, at least one namespace is required") } - for _, ns := range o.config.Namespaces { + + for _, ns := range o.config.NamespacesList() { if ns == SystemNamespace || ns == monitoringNamespace { return fmt.Errorf("'%s' namespace is reserved for Everest internals. Please specify another namespace", ns) } @@ -239,7 +244,7 @@ func (o *Install) provisionEverestOperator(ctx context.Context) error { } o.l.Info("Creating operator group for everest") - if err := o.kubeClient.CreateOperatorGroup(ctx, systemOperatorGroup, SystemNamespace, o.config.Namespaces); err != nil { + if err := o.kubeClient.CreateOperatorGroup(ctx, systemOperatorGroup, SystemNamespace, o.config.NamespacesList()); err != nil { return err } @@ -277,7 +282,7 @@ func (o *Install) provisionEverest(ctx context.Context) error { } o.l.Info("Updating cluster role bindings for everest-admin") - if err := o.kubeClient.UpdateClusterRoleBinding(ctx, everestServiceAccountClusterRoleBinding, o.config.Namespaces); err != nil { + if err := o.kubeClient.UpdateClusterRoleBinding(ctx, everestServiceAccountClusterRoleBinding, o.config.NamespacesList()); err != nil { return err } @@ -285,7 +290,7 @@ func (o *Install) provisionEverest(ctx context.Context) error { } func (o *Install) provisionDBNamespaces(ctx context.Context) error { - for _, namespace := range o.config.Namespaces { + for _, namespace := range o.config.NamespacesList() { namespace := namespace if err := o.createNamespace(namespace); err != nil { return err @@ -349,7 +354,7 @@ func (o *Install) runEverestWizard() error { return fmt.Errorf("'%s' namespace is reserved for Everest internals. Please specify another namespace", ns) } - o.config.Namespaces = append(o.config.Namespaces, ns) + o.config.Namespaces += "," + ns } if len(o.config.Namespaces) == 0 { @@ -497,7 +502,7 @@ func (o *Install) installOperator(ctx context.Context, channel, operatorName, na }, } if operatorName == everestOperatorName { - params.TargetNamespaces = o.config.Namespaces + params.TargetNamespaces = o.config.NamespacesList() params.SubscriptionConfig.Env = append(params.SubscriptionConfig.Env, []corev1.EnvVar{ { Name: EverestMonitoringNamespaceEnvVar, @@ -505,7 +510,7 @@ func (o *Install) installOperator(ctx context.Context, channel, operatorName, na }, { Name: kubernetes.EverestDBNamespacesEnvVar, - Value: strings.Join(o.config.Namespaces, ","), + Value: o.config.Namespaces, }, }...) } diff --git a/pkg/kubernetes/kubernetes.go b/pkg/kubernetes/kubernetes.go index 081f60d2..f51d1917 100644 --- a/pkg/kubernetes/kubernetes.go +++ b/pkg/kubernetes/kubernetes.go @@ -631,7 +631,7 @@ type InstallOperatorRequest struct { func mergeNamespacesEnvVar(str1, str2 string) string { ns1 := strings.Split(str1, ",") ns2 := strings.Split(str2, ",") - nsMap := map[string]struct{}{} + nsMap := make(map[string]struct{}) for _, ns := range ns1 { if ns == "" { diff --git a/pkg/upgrade/upgrade.go b/pkg/upgrade/upgrade.go index 2c94f6f6..6007533d 100644 --- a/pkg/upgrade/upgrade.go +++ b/pkg/upgrade/upgrade.go @@ -22,6 +22,7 @@ import ( "fmt" "net/url" "os" + "strings" "github.com/AlecAivazis/survey/v2" goversion "github.com/hashicorp/go-version" @@ -37,7 +38,7 @@ type ( // Config defines configuration required for upgrade command. Config struct { // Namespaces defines namespaces that everest can operate in. - Namespaces []string `mapstructure:"namespace"` + Namespaces string `mapstructure:"namespaces"` // KubeconfigPath is a path to a kubeconfig KubeconfigPath string `mapstructure:"kubeconfig"` // UpgradeOLM defines do we need to upgrade OLM or not. @@ -54,6 +55,10 @@ type ( } ) +func (c Config) NamespacesList() []string { + return strings.Split(c.Namespaces, ",") +} + // NewUpgrade returns a new Upgrade struct. func NewUpgrade(c Config, l *zap.SugaredLogger) (*Upgrade, error) { cli := &Upgrade{ @@ -126,7 +131,7 @@ func (u *Upgrade) runEverestWizard(ctx context.Context) error { } func (u *Upgrade) patchSubscriptions(ctx context.Context) error { - for _, namespace := range u.config.Namespaces { + for _, namespace := range u.config.NamespacesList() { namespace := namespace subList, err := u.kubeClient.ListSubscriptions(ctx, namespace) if err != nil { From 4c129a3ee84385095e53e0f3972fcd1697b9faff Mon Sep 17 00:00:00 2001 From: Oksana Grishchenko Date: Wed, 14 Feb 2024 15:30:53 +0200 Subject: [PATCH 2/7] deps --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c74ab00d..7a99e1db 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/hashicorp/go-version v1.6.0 github.com/operator-framework/api v0.22.0 github.com/operator-framework/operator-lifecycle-manager v0.26.0 - github.com/percona/everest-operator v0.6.0-dev1.0.20240207193854-cdd70b8eb1e6 + github.com/percona/everest-operator v0.6.0-dev1.0.20240214112044-8f2dea595284 github.com/spf13/cobra v1.8.0 github.com/spf13/viper v1.18.2 github.com/stretchr/testify v1.8.4 diff --git a/go.sum b/go.sum index 97841180..cfd94bf4 100644 --- a/go.sum +++ b/go.sum @@ -525,8 +525,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= -github.com/percona/everest-operator v0.6.0-dev1.0.20240207193854-cdd70b8eb1e6 h1:leGa/XuWVstdYyj61r92xByjuT52jsbVroHB0fj4j7A= -github.com/percona/everest-operator v0.6.0-dev1.0.20240207193854-cdd70b8eb1e6/go.mod h1:45pGpvWrPy495qiQqxNuOJor4wif+vTTTJP4Qee8qZk= +github.com/percona/everest-operator v0.6.0-dev1.0.20240214112044-8f2dea595284 h1:5LKWEvGtaimDPVI3Rj9tFxO+g/zAjUJq0yFIzznQGfc= +github.com/percona/everest-operator v0.6.0-dev1.0.20240214112044-8f2dea595284/go.mod h1:45pGpvWrPy495qiQqxNuOJor4wif+vTTTJP4Qee8qZk= github.com/percona/percona-backup-mongodb v1.8.1-0.20230920143330-3b1c2e263901 h1:BDgsZRCjEuxl2/z4yWBqB0s8d20shuIDks7/RVdZiLs= github.com/percona/percona-backup-mongodb v1.8.1-0.20230920143330-3b1c2e263901/go.mod h1:fZRCMpUqkWlLVdRKqqaj001LoVP2eo6F0ZhoMPeXDng= github.com/percona/percona-postgresql-operator v0.0.0-20231220140959-ad5eef722609 h1:+UOK4gcHrRgqjo4smgfwT7/0apF6PhAJdQIdAV4ub/M= From 8bebd6b97833b443120ca3d90663156801aa9578 Mon Sep 17 00:00:00 2001 From: Oksana Grishchenko Date: Wed, 14 Feb 2024 15:32:29 +0200 Subject: [PATCH 3/7] tests --- cli-tests/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli-tests/Makefile b/cli-tests/Makefile index ccbb94b4..dc60c0e1 100644 --- a/cli-tests/Makefile +++ b/cli-tests/Makefile @@ -4,7 +4,7 @@ init: ## Install dependencies install-operators: ## Install operators to k8s ../bin/everest install \ - --namespace percona-everest-operators \ + --namespaces percona-everest-operators \ --skip-wizard \ test-cli: ## Run all tests From aa8ef9dbc88eb91ee835349e617afa8c65845ac9 Mon Sep 17 00:00:00 2001 From: Oksana Grishchenko Date: Wed, 14 Feb 2024 15:41:30 +0200 Subject: [PATCH 4/7] comments --- pkg/install/install.go | 3 ++- pkg/upgrade/upgrade.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/install/install.go b/pkg/install/install.go index df2d42e1..e8c29ef3 100644 --- a/pkg/install/install.go +++ b/pkg/install/install.go @@ -90,7 +90,7 @@ const ( type ( // Config stores configuration for the operators. Config struct { - // Namespaces defines namespaces that everest can operate in. + // Namespaces defines comma-separated list of namespaces that everest can operate in. Namespaces string `mapstructure:"namespaces"` // SkipWizard skips wizard during installation. SkipWizard bool `mapstructure:"skip-wizard"` @@ -111,6 +111,7 @@ type ( } ) +// NamespacesList returns list of the namespaces that everest can operate in. func (c Config) NamespacesList() []string { return strings.Split(c.Namespaces, ",") } diff --git a/pkg/upgrade/upgrade.go b/pkg/upgrade/upgrade.go index 6007533d..072fc6cd 100644 --- a/pkg/upgrade/upgrade.go +++ b/pkg/upgrade/upgrade.go @@ -37,7 +37,7 @@ import ( type ( // Config defines configuration required for upgrade command. Config struct { - // Namespaces defines namespaces that everest can operate in. + // Namespaces defines comma-separated list of namespaces that everest can operate in. Namespaces string `mapstructure:"namespaces"` // KubeconfigPath is a path to a kubeconfig KubeconfigPath string `mapstructure:"kubeconfig"` @@ -55,6 +55,7 @@ type ( } ) +// NamespacesList returns list of the namespaces that everest can operate in. func (c Config) NamespacesList() []string { return strings.Split(c.Namespaces, ",") } From 6e0f0e1951b7a3bf7b8b2e1721ca8dae2939d57b Mon Sep 17 00:00:00 2001 From: Oksana Grishchenko Date: Wed, 14 Feb 2024 15:45:38 +0200 Subject: [PATCH 5/7] linter, address comments --- pkg/install/install.go | 4 ++-- pkg/upgrade/upgrade.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/install/install.go b/pkg/install/install.go index e8c29ef3..d434a302 100644 --- a/pkg/install/install.go +++ b/pkg/install/install.go @@ -183,7 +183,7 @@ func (o *Install) populateConfig() error { } } - if len(o.config.Namespaces) == 0 { + if len(o.config.NamespacesList()) == 0 { return errors.New("namespace list is empty. Specify the comma-separated list of namespaces using the --namespaces flag, at least one namespace is required") } @@ -358,7 +358,7 @@ func (o *Install) runEverestWizard() error { o.config.Namespaces += "," + ns } - if len(o.config.Namespaces) == 0 { + if len(o.config.NamespacesList()) == 0 { return errors.New("namespace list is empty. Specify at least one namespace") } diff --git a/pkg/upgrade/upgrade.go b/pkg/upgrade/upgrade.go index 072fc6cd..4210fa4b 100644 --- a/pkg/upgrade/upgrade.go +++ b/pkg/upgrade/upgrade.go @@ -85,7 +85,7 @@ func (u *Upgrade) Run(ctx context.Context) error { if err := u.runEverestWizard(ctx); err != nil { return err } - if len(u.config.Namespaces) == 0 { + if len(u.config.NamespacesList()) == 0 { return errors.New("namespace list is empty. Specify at least one namespace") } if err := u.upgradeOLM(ctx); err != nil { From 7a96a797f2a0d9c9ee939f82cf1f997a348d272c Mon Sep 17 00:00:00 2001 From: Oksana Grishchenko Date: Wed, 14 Feb 2024 15:52:59 +0200 Subject: [PATCH 6/7] tests --- cli-tests/tests/flow/mongodb-operator.spec.ts | 2 +- cli-tests/tests/flow/pg-operator.spec.ts | 4 ++-- cli-tests/tests/flow/pxc-operator.spec.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cli-tests/tests/flow/mongodb-operator.spec.ts b/cli-tests/tests/flow/mongodb-operator.spec.ts index d217bc97..3f63bd13 100644 --- a/cli-tests/tests/flow/mongodb-operator.spec.ts +++ b/cli-tests/tests/flow/mongodb-operator.spec.ts @@ -49,7 +49,7 @@ test.describe('Everest CLI install', async () => { await test.step('run everest install command', async () => { const out = await cli.everestExecSkipWizard( - `install --operator.mongodb=true --operator.postgresql=false --operator.xtradb-cluster=false --namespace=everest-operators`, + `install --operator.mongodb=true --operator.postgresql=false --operator.xtradb-cluster=false --namespaces=everest-operators`, ); await out.assertSuccess(); diff --git a/cli-tests/tests/flow/pg-operator.spec.ts b/cli-tests/tests/flow/pg-operator.spec.ts index 6f7188b2..a86935a9 100644 --- a/cli-tests/tests/flow/pg-operator.spec.ts +++ b/cli-tests/tests/flow/pg-operator.spec.ts @@ -48,7 +48,7 @@ test.describe('Everest CLI install', async () => { await test.step('run everest install command', async () => { const out = await cli.everestExecSkipWizard( - `install --operator.mongodb=false --operator.postgresql=true --operator.xtradb-cluster=false --namespace=everest-operators`, + `install --operator.mongodb=false --operator.postgresql=true --operator.xtradb-cluster=false --namespaces=everest-operators`, ); await out.assertSuccess(); @@ -68,7 +68,7 @@ test.describe('Everest CLI install', async () => { await operator.assertSuccess(); const out = await cli.everestExecSkipWizard( - `install --operator.mongodb=false --operator.postgresql=true --operator.xtradb-cluster=true --namespace=everest-operators`, + `install --operator.mongodb=false --operator.postgresql=true --operator.xtradb-cluster=true --namespaces=everest-operators`, ); const restartedOperator = await cli.exec(`kubectl -n everest-system get po | grep everest|awk {'print $1'}`); await restartedOperator.assertSuccess(); diff --git a/cli-tests/tests/flow/pxc-operator.spec.ts b/cli-tests/tests/flow/pxc-operator.spec.ts index c8e2ea24..980c27f5 100644 --- a/cli-tests/tests/flow/pxc-operator.spec.ts +++ b/cli-tests/tests/flow/pxc-operator.spec.ts @@ -49,7 +49,7 @@ test.describe('Everest CLI install', async () => { await test.step('run everest install command', async () => { const out = await cli.everestExecSkipWizard( - `install --operator.mongodb=false --operator.postgresql=false --operator.xtradb-cluster=true --namespace=everest-operators`, + `install --operator.mongodb=false --operator.postgresql=false --operator.xtradb-cluster=true --namespaces=everest-operators`, ); await out.assertSuccess(); From b9919038843be93bfe3c91f6b7ceeafe192e5a7a Mon Sep 17 00:00:00 2001 From: Oksana Grishchenko Date: Wed, 14 Feb 2024 16:22:04 +0200 Subject: [PATCH 7/7] fix wizard --- pkg/install/install.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/install/install.go b/pkg/install/install.go index d434a302..5cc5a7d7 100644 --- a/pkg/install/install.go +++ b/pkg/install/install.go @@ -355,7 +355,11 @@ func (o *Install) runEverestWizard() error { return fmt.Errorf("'%s' namespace is reserved for Everest internals. Please specify another namespace", ns) } - o.config.Namespaces += "," + ns + if o.config.Namespaces != "" { + o.config.Namespaces += "," + } + + o.config.Namespaces += ns } if len(o.config.NamespacesList()) == 0 {