Skip to content

Commit

Permalink
EVEREST-1819 [CLI] Get rid of spf13/viper lib for parsing CLI params (#…
Browse files Browse the repository at this point in the history
…1015)

* EVEREST-1819 [CLI] Get rid of spf13/viper lib for parsing CLI params

- Use spf13/cobra lib only for parsing CLI params
- Parse global flags (--verbose, --json, --kubeconfig) on root level
- Extend examples

* EVEREST-1819 Fix formatting

* EVEREST-1819 Update dev helm chart

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Percona Platform Robot <61465387+percona-robot@users.noreply.github.com>
  • Loading branch information
3 people authored Jan 23, 2025
1 parent d0ec34f commit 14e8fd2
Show file tree
Hide file tree
Showing 39 changed files with 1,289 additions and 1,238 deletions.
16 changes: 3 additions & 13 deletions cmd/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,15 @@
package main

import (
"fmt"
"os"

"github.com/go-logr/zapr"
ctrlruntimelog "sigs.k8s.io/controller-runtime/pkg/log"

"github.com/percona/everest/commands"
"github.com/percona/everest/pkg/logger"
)

func main() {
l := logger.MustInitLogger(false)

// This is required because controller-runtime requires a logger
// to be set within 30 seconds of the program initialization.
log := zapr.NewLogger(l)
ctrlruntimelog.SetLogger(log)

rootCmd := commands.NewRootCmd(l.Sugar())
if err := rootCmd.Execute(); err != nil {
if err := commands.Execute(); err != nil {
_, _ = fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
2 changes: 1 addition & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const (
)

func main() {
logger := logger.MustInitLogger(true)
logger := logger.MustInitLogger(true, "everest")
defer logger.Sync() //nolint:errcheck
l := logger.Sugar()

Expand Down
29 changes: 15 additions & 14 deletions commands/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,25 @@ package commands

import (
"github.com/spf13/cobra"
"go.uber.org/zap"

"github.com/percona/everest/commands/accounts"
)

func newAccountsCmd(l *zap.SugaredLogger) *cobra.Command {
cmd := &cobra.Command{
Use: "accounts",
Long: "Manage Everest accounts",
Short: "Manage Everest accounts",
}
var accountsCmd = &cobra.Command{
Use: "accounts <command> [flags]",
Args: cobra.ExactArgs(1),
Long: "Manage Everest accounts",
Short: "Manage Everest accounts",
Run: func(_ *cobra.Command, _ []string) {},
}

cmd.AddCommand(accounts.NewCreateCmd(l))
cmd.AddCommand(accounts.NewListCmd(l))
cmd.AddCommand(accounts.NewDeleteCmd(l))
cmd.AddCommand(accounts.NewSetPwCommand(l))
cmd.AddCommand(accounts.NewResetJWTKeysCommand(l))
cmd.AddCommand(accounts.NewInitialAdminPasswdCommand(l))
func init() {
rootCmd.AddCommand(accountsCmd)

return cmd
accountsCmd.AddCommand(accounts.GetCreateCmd())
accountsCmd.AddCommand(accounts.GetListCmd())
accountsCmd.AddCommand(accounts.GetDeleteCmd())
accountsCmd.AddCommand(accounts.GetSetPasswordCmd())
accountsCmd.AddCommand(accounts.GetResetJWTKeysCmd())
accountsCmd.AddCommand(accounts.GetInitAdminPasswordCmd())
}
76 changes: 34 additions & 42 deletions commands/accounts/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,64 +19,56 @@
package accounts

import (
"context"
"errors"
"net/url"
"os"

"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.uber.org/zap"

accountscli "github.com/percona/everest/pkg/accounts/cli"
"github.com/percona/everest/pkg/kubernetes"
"github.com/percona/everest/pkg/cli"
"github.com/percona/everest/pkg/logger"
)

// NewCreateCmd returns a new create command.
func NewCreateCmd(l *zap.SugaredLogger) *cobra.Command {
cmd := &cobra.Command{
Use: "create",
var (
accountsCreateCmd = &cobra.Command{
Use: "create [flags]",
Args: cobra.NoArgs,
Example: "everestctl accounts create --username user1 --password $USER_PASS",
Short: "Create a new Everest user account",
Long: "Create a new Everest user account",
Run: func(cmd *cobra.Command, args []string) { //nolint:revive
initCreateViperFlags(cmd)
PreRun: accountsCreatePreRun,
Run: accountsCreateRun,
}

kubeconfigPath := viper.GetString("kubeconfig")
username := viper.GetString("username")
password := viper.GetString("password")
accountsCreateCfg = &accountscli.Config{}
accountsCreateOpts = &accountscli.CreateOptions{}
)

k, err := kubernetes.New(kubeconfigPath, l)
if err != nil {
var u *url.Error
if errors.As(err, &u) {
l.Error("Could not connect to Kubernetes. " +
"Make sure Kubernetes is running and is accessible from this computer/server.")
}
os.Exit(0)
}
func init() {
// local command flags
accountsCreateCmd.Flags().StringVarP(&accountsCreateOpts.Username, cli.FlagAccountsUsername, "u", "", "Username of the account")
accountsCreateCmd.Flags().StringVarP(&accountsCreateOpts.Password, cli.FlagAccountsCreatePassword, "p", "", "Password of the account")
}

cli := accountscli.New(l)
cli.WithAccountManager(k.Accounts())
func accountsCreatePreRun(cmd *cobra.Command, _ []string) { //nolint:revive
// Copy global flags to config
accountsCreateCfg.Pretty = !(cmd.Flag(cli.FlagVerbose).Changed || cmd.Flag(cli.FlagJSON).Changed)
accountsCreateCfg.KubeconfigPath = cmd.Flag(cli.FlagKubeconfig).Value.String()
}

if err := cli.Create(context.Background(), username, password); err != nil {
l.Error(err)
os.Exit(1)
}
},
func accountsCreateRun(cmd *cobra.Command, _ []string) { //nolint:revive
cliA, err := accountscli.NewAccounts(*accountsCreateCfg, logger.GetLogger())
if err != nil {
logger.GetLogger().Error(err)
os.Exit(1)
}
initCreateFlags(cmd)
return cmd
}

func initCreateFlags(cmd *cobra.Command) {
cmd.Flags().StringP("username", "u", "", "Username of the account")
cmd.Flags().StringP("password", "p", "", "Password of the account")
if err := cliA.Create(cmd.Context(), *accountsCreateOpts); err != nil {
logger.GetLogger().Error(err)
os.Exit(1)
}
}

func initCreateViperFlags(cmd *cobra.Command) {
viper.BindPFlag("username", cmd.Flags().Lookup("username")) //nolint:errcheck,gosec
viper.BindPFlag("password", cmd.Flags().Lookup("password")) //nolint:errcheck,gosec
viper.BindEnv("kubeconfig") //nolint:errcheck,gosec
viper.BindPFlag("kubeconfig", cmd.Flags().Lookup("kubeconfig")) //nolint:errcheck,gosec
// GetCreateCmd returns the command to create a new user account.
func GetCreateCmd() *cobra.Command {
return accountsCreateCmd
}
73 changes: 33 additions & 40 deletions commands/accounts/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,61 +17,54 @@
package accounts

import (
"context"
"errors"
"net/url"
"os"

"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.uber.org/zap"

accountscli "github.com/percona/everest/pkg/accounts/cli"
"github.com/percona/everest/pkg/kubernetes"
"github.com/percona/everest/pkg/cli"
"github.com/percona/everest/pkg/logger"
)

// NewDeleteCmd returns a new delete command.
func NewDeleteCmd(l *zap.SugaredLogger) *cobra.Command {
cmd := &cobra.Command{
Use: "delete",
var (
accountsDeleteCmd = &cobra.Command{
Use: "delete [flags]",
Args: cobra.NoArgs,
Example: "everestctl accounts delete --username user1",
Short: "Delete an existing Everest user account",
Long: "Delete an existing Everest user account",
Run: func(cmd *cobra.Command, args []string) { //nolint:revive
initDeleteViperFlags(cmd)

kubeconfigPath := viper.GetString("kubeconfig")
username := viper.GetString("username")
PreRun: accountsDeletePreRun,
Run: accountsDeleteRun,
}
accountsDeleteCfg = &accountscli.Config{}
accountsDeleteUsername string
)

k, err := kubernetes.New(kubeconfigPath, l)
if err != nil {
var u *url.Error
if errors.As(err, &u) {
l.Error("Could not connect to Kubernetes. " +
"Make sure Kubernetes is running and is accessible from this computer/server.")
}
os.Exit(0)
}
func init() {
// local command flags
accountsDeleteCmd.Flags().StringVarP(&accountsDeleteUsername, cli.FlagAccountsUsername, "u", "", "Username of the account")
}

cli := accountscli.New(l)
cli.WithAccountManager(k.Accounts())
func accountsDeletePreRun(cmd *cobra.Command, _ []string) { //nolint:revive
// Copy global flags to config
accountsDeleteCfg.Pretty = !(cmd.Flag(cli.FlagVerbose).Changed || cmd.Flag(cli.FlagJSON).Changed)
accountsDeleteCfg.KubeconfigPath = cmd.Flag(cli.FlagKubeconfig).Value.String()
}

if err := cli.Delete(context.Background(), username); err != nil {
l.Error(err)
os.Exit(1)
}
},
func accountsDeleteRun(cmd *cobra.Command, _ []string) { //nolint:revive
cliA, err := accountscli.NewAccounts(*accountsDeleteCfg, logger.GetLogger())
if err != nil {
logger.GetLogger().Error(err)
os.Exit(1)
}
initDeleteFlags(cmd)
return cmd
}

func initDeleteFlags(cmd *cobra.Command) {
cmd.Flags().StringP("username", "u", "", "Username of the account")
if err := cliA.Delete(cmd.Context(), accountsDeleteUsername); err != nil {
logger.GetLogger().Error(err)
os.Exit(1)
}
}

func initDeleteViperFlags(cmd *cobra.Command) {
viper.BindPFlag("username", cmd.Flags().Lookup("username")) //nolint:errcheck,gosec
viper.BindEnv("kubeconfig") //nolint:errcheck,gosec
viper.BindPFlag("kubeconfig", cmd.Flags().Lookup("kubeconfig")) //nolint:errcheck,gosec
// GetDeleteCmd returns the command to delete account.
func GetDeleteCmd() *cobra.Command {
return accountsDeleteCmd
}
97 changes: 52 additions & 45 deletions commands/accounts/initial_admin_password.go
Original file line number Diff line number Diff line change
@@ -1,61 +1,68 @@
// everest
// Copyright (C) 2023 Percona LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package accounts holds commands for accounts command.
package accounts

import (
"context"
"errors"
"fmt"
"net/url"
"os"

"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.uber.org/zap"

"github.com/percona/everest/pkg/common"
"github.com/percona/everest/pkg/kubernetes"
accountscli "github.com/percona/everest/pkg/accounts/cli"
"github.com/percona/everest/pkg/cli"
"github.com/percona/everest/pkg/logger"
)

// NewInitialAdminPasswdCommand returns a new initial-admin-passwd command.
func NewInitialAdminPasswdCommand(l *zap.SugaredLogger) *cobra.Command {
cmd := &cobra.Command{
Use: "initial-admin-password",
var (
accountsInitAdminPasswdCmd = &cobra.Command{
Use: "initial-admin-password [flags]",
Args: cobra.NoArgs,
Example: "everestctl accounts initial-admin-password",
Long: "Get the initial admin password for Everest",
Short: "Get the initial admin password for Everest",
Run: func(cmd *cobra.Command, args []string) { //nolint:revive
viper.BindEnv("kubeconfig") //nolint:errcheck,gosec
viper.BindPFlag("kubeconfig", cmd.Flags().Lookup("kubeconfig")) //nolint:errcheck,gosec
kubeconfigPath := viper.GetString("kubeconfig")

k, err := kubernetes.New(kubeconfigPath, l)
if err != nil {
var u *url.Error
l.Error("Could not connect to Kubernetes. " +
"Make sure Kubernetes is running and is accessible from this computer/server.")
if !errors.As(err, &u) {
l.Error(err)
}
os.Exit(1)
}

ctx := context.Background()
secure, err := k.Accounts().IsSecure(ctx, common.EverestAdminUser)
if err != nil {
l.Error(err)
os.Exit(1)
}
if secure {
l.Error("Cannot retrieve admin password after it has been updated.")
os.Exit(1)
}
admin, err := k.Accounts().Get(ctx, common.EverestAdminUser)
if err != nil {
l.Error(err)
os.Exit(1)
}
fmt.Fprint(os.Stdout, admin.PasswordHash+"\n")
},
PreRun: accountsInitAdminPasswdPreRun,
Run: accountsInitAdminPasswdRun,
}
accountsInitAdminPasswdCfg = &accountscli.Config{}
)

func accountsInitAdminPasswdPreRun(cmd *cobra.Command, _ []string) { //nolint:revive
// Copy global flags to config
accountsInitAdminPasswdCfg.Pretty = !(cmd.Flag(cli.FlagVerbose).Changed || cmd.Flag(cli.FlagJSON).Changed)
accountsInitAdminPasswdCfg.KubeconfigPath = cmd.Flag(cli.FlagKubeconfig).Value.String()
}

func accountsInitAdminPasswdRun(cmd *cobra.Command, _ []string) { //nolint:revive
cliA, err := accountscli.NewAccounts(*accountsInitAdminPasswdCfg, logger.GetLogger())
if err != nil {
logger.GetLogger().Error(err)
os.Exit(1)
}
return cmd

passwordHash, err := cliA.GetInitAdminPassword(cmd.Context())
if err != nil {
logger.GetLogger().Error(err)
os.Exit(1)
}

_, _ = fmt.Fprint(os.Stdout, passwordHash+"\n")
}

// GetInitAdminPasswordCmd returns the command to get the initial admin password.
func GetInitAdminPasswordCmd() *cobra.Command {
return accountsInitAdminPasswdCmd
}
Loading

0 comments on commit 14e8fd2

Please sign in to comment.