瀏覽代碼

refact "cscli config", remove flag "cscli restore --old-backup" (#2832)

* refact "cscli config show"
* refact "cscli config backup"
* refact "cscli confgi show-yaml"
* refact "cscli config restore"
* refact "cscli config feature-flags"
* cscli restore: remove 'old-backup' option
* lint (whitespace, wrapped errors)
mmetc 1 年之前
父節點
當前提交
3e3df5e4c6

+ 18 - 8
cmd/crowdsec-cli/config.go

@@ -4,19 +4,29 @@ import (
 	"github.com/spf13/cobra"
 )
 
-func NewConfigCmd() *cobra.Command {
-	cmdConfig := &cobra.Command{
+type cliConfig struct {
+	cfg configGetter
+}
+
+func NewCLIConfig(cfg configGetter) *cliConfig {
+	return &cliConfig{
+		cfg: cfg,
+	}
+}
+
+func (cli *cliConfig) NewCommand() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:               "config [command]",
 		Short:             "Allows to view current config",
 		Args:              cobra.ExactArgs(0),
 		DisableAutoGenTag: true,
 	}
 
-	cmdConfig.AddCommand(NewConfigShowCmd())
-	cmdConfig.AddCommand(NewConfigShowYAMLCmd())
-	cmdConfig.AddCommand(NewConfigBackupCmd())
-	cmdConfig.AddCommand(NewConfigRestoreCmd())
-	cmdConfig.AddCommand(NewConfigFeatureFlagsCmd())
+	cmd.AddCommand(cli.newShowCmd())
+	cmd.AddCommand(cli.newShowYAMLCmd())
+	cmd.AddCommand(cli.newBackupCmd())
+	cmd.AddCommand(cli.newRestoreCmd())
+	cmd.AddCommand(cli.newFeatureFlagsCmd())
 
-	return cmdConfig
+	return cmd
 }

+ 50 - 49
cmd/crowdsec-cli/config_backup.go

@@ -2,6 +2,7 @@ package main
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
 	"os"
 	"path/filepath"
@@ -13,8 +14,8 @@ import (
 	"github.com/crowdsecurity/crowdsec/pkg/cwhub"
 )
 
-func backupHub(dirPath string) error {
-	hub, err := require.Hub(csConfig, nil, nil)
+func (cli *cliConfig) backupHub(dirPath string) error {
+	hub, err := require.Hub(cli.cfg(), nil, nil)
 	if err != nil {
 		return err
 	}
@@ -32,7 +33,7 @@ func backupHub(dirPath string) error {
 
 		itemDirectory := fmt.Sprintf("%s/%s/", dirPath, itemType)
 		if err = os.MkdirAll(itemDirectory, os.ModePerm); err != nil {
-			return fmt.Errorf("error while creating %s : %s", itemDirectory, err)
+			return fmt.Errorf("error while creating %s: %w", itemDirectory, err)
 		}
 
 		upstreamParsers := []string{}
@@ -41,18 +42,18 @@ func backupHub(dirPath string) error {
 			clog = clog.WithFields(log.Fields{
 				"file": v.Name,
 			})
-			if !v.State.Installed { //only backup installed ones
-				clog.Debugf("[%s] : not installed", k)
+			if !v.State.Installed { // only backup installed ones
+				clog.Debugf("[%s]: not installed", k)
 				continue
 			}
 
-			//for the local/tainted ones, we back up the full file
+			// for the local/tainted ones, we back up the full file
 			if v.State.Tainted || v.State.IsLocal() || !v.State.UpToDate {
-				//we need to backup stages for parsers
+				// we need to backup stages for parsers
 				if itemType == cwhub.PARSERS || itemType == cwhub.POSTOVERFLOWS {
 					fstagedir := fmt.Sprintf("%s%s", itemDirectory, v.Stage)
 					if err = os.MkdirAll(fstagedir, os.ModePerm); err != nil {
-						return fmt.Errorf("error while creating stage dir %s : %s", fstagedir, err)
+						return fmt.Errorf("error while creating stage dir %s: %w", fstagedir, err)
 					}
 				}
 
@@ -60,7 +61,7 @@ func backupHub(dirPath string) error {
 
 				tfile := fmt.Sprintf("%s%s/%s", itemDirectory, v.Stage, v.FileName)
 				if err = CopyFile(v.State.LocalPath, tfile); err != nil {
-					return fmt.Errorf("failed copy %s %s to %s : %s", itemType, v.State.LocalPath, tfile, err)
+					return fmt.Errorf("failed copy %s %s to %s: %w", itemType, v.State.LocalPath, tfile, err)
 				}
 
 				clog.Infof("local/tainted saved %s to %s", v.State.LocalPath, tfile)
@@ -68,21 +69,21 @@ func backupHub(dirPath string) error {
 				continue
 			}
 
-			clog.Debugf("[%s] : from hub, just backup name (up-to-date:%t)", k, v.State.UpToDate)
+			clog.Debugf("[%s]: from hub, just backup name (up-to-date:%t)", k, v.State.UpToDate)
 			clog.Infof("saving, version:%s, up-to-date:%t", v.Version, v.State.UpToDate)
 			upstreamParsers = append(upstreamParsers, v.Name)
 		}
-		//write the upstream items
+		// write the upstream items
 		upstreamParsersFname := fmt.Sprintf("%s/upstream-%s.json", itemDirectory, itemType)
 
 		upstreamParsersContent, err := json.MarshalIndent(upstreamParsers, "", " ")
 		if err != nil {
-			return fmt.Errorf("failed marshaling upstream parsers : %s", err)
+			return fmt.Errorf("failed marshaling upstream parsers: %w", err)
 		}
 
 		err = os.WriteFile(upstreamParsersFname, upstreamParsersContent, 0o644)
 		if err != nil {
-			return fmt.Errorf("unable to write to %s %s : %s", itemType, upstreamParsersFname, err)
+			return fmt.Errorf("unable to write to %s %s: %w", itemType, upstreamParsersFname, err)
 		}
 
 		clog.Infof("Wrote %d entries for %s to %s", len(upstreamParsers), itemType, upstreamParsersFname)
@@ -102,11 +103,13 @@ func backupHub(dirPath string) error {
 - Tainted/local/out-of-date scenarios, parsers, postoverflows and collections
 - Acquisition files (acquis.yaml, acquis.d/*.yaml)
 */
-func backupConfigToDirectory(dirPath string) error {
+func (cli *cliConfig) backup(dirPath string) error {
 	var err error
 
+	cfg := cli.cfg()
+
 	if dirPath == "" {
-		return fmt.Errorf("directory path can't be empty")
+		return errors.New("directory path can't be empty")
 	}
 
 	log.Infof("Starting configuration backup")
@@ -121,10 +124,10 @@ func backupConfigToDirectory(dirPath string) error {
 		return fmt.Errorf("while creating %s: %w", dirPath, err)
 	}
 
-	if csConfig.ConfigPaths.SimulationFilePath != "" {
+	if cfg.ConfigPaths.SimulationFilePath != "" {
 		backupSimulation := filepath.Join(dirPath, "simulation.yaml")
-		if err = CopyFile(csConfig.ConfigPaths.SimulationFilePath, backupSimulation); err != nil {
-			return fmt.Errorf("failed copy %s to %s: %w", csConfig.ConfigPaths.SimulationFilePath, backupSimulation, err)
+		if err = CopyFile(cfg.ConfigPaths.SimulationFilePath, backupSimulation); err != nil {
+			return fmt.Errorf("failed copy %s to %s: %w", cfg.ConfigPaths.SimulationFilePath, backupSimulation, err)
 		}
 
 		log.Infof("Saved simulation to %s", backupSimulation)
@@ -134,22 +137,22 @@ func backupConfigToDirectory(dirPath string) error {
 	   - backup AcquisitionFilePath
 	   - backup the other files of acquisition directory
 	*/
-	if csConfig.Crowdsec != nil && csConfig.Crowdsec.AcquisitionFilePath != "" {
+	if cfg.Crowdsec != nil && cfg.Crowdsec.AcquisitionFilePath != "" {
 		backupAcquisition := filepath.Join(dirPath, "acquis.yaml")
-		if err = CopyFile(csConfig.Crowdsec.AcquisitionFilePath, backupAcquisition); err != nil {
-			return fmt.Errorf("failed copy %s to %s: %s", csConfig.Crowdsec.AcquisitionFilePath, backupAcquisition, err)
+		if err = CopyFile(cfg.Crowdsec.AcquisitionFilePath, backupAcquisition); err != nil {
+			return fmt.Errorf("failed copy %s to %s: %w", cfg.Crowdsec.AcquisitionFilePath, backupAcquisition, err)
 		}
 	}
 
 	acquisBackupDir := filepath.Join(dirPath, "acquis")
 	if err = os.Mkdir(acquisBackupDir, 0o700); err != nil {
-		return fmt.Errorf("error while creating %s: %s", acquisBackupDir, err)
+		return fmt.Errorf("error while creating %s: %w", acquisBackupDir, err)
 	}
 
-	if csConfig.Crowdsec != nil && len(csConfig.Crowdsec.AcquisitionFiles) > 0 {
-		for _, acquisFile := range csConfig.Crowdsec.AcquisitionFiles {
+	if cfg.Crowdsec != nil && len(cfg.Crowdsec.AcquisitionFiles) > 0 {
+		for _, acquisFile := range cfg.Crowdsec.AcquisitionFiles {
 			/*if it was the default one, it was already backup'ed*/
-			if csConfig.Crowdsec.AcquisitionFilePath == acquisFile {
+			if cfg.Crowdsec.AcquisitionFilePath == acquisFile {
 				continue
 			}
 
@@ -169,56 +172,48 @@ func backupConfigToDirectory(dirPath string) error {
 	if ConfigFilePath != "" {
 		backupMain := fmt.Sprintf("%s/config.yaml", dirPath)
 		if err = CopyFile(ConfigFilePath, backupMain); err != nil {
-			return fmt.Errorf("failed copy %s to %s: %s", ConfigFilePath, backupMain, err)
+			return fmt.Errorf("failed copy %s to %s: %w", ConfigFilePath, backupMain, err)
 		}
 
 		log.Infof("Saved default yaml to %s", backupMain)
 	}
 
-	if csConfig.API != nil && csConfig.API.Server != nil && csConfig.API.Server.OnlineClient != nil && csConfig.API.Server.OnlineClient.CredentialsFilePath != "" {
+	if cfg.API != nil && cfg.API.Server != nil && cfg.API.Server.OnlineClient != nil && cfg.API.Server.OnlineClient.CredentialsFilePath != "" {
 		backupCAPICreds := fmt.Sprintf("%s/online_api_credentials.yaml", dirPath)
-		if err = CopyFile(csConfig.API.Server.OnlineClient.CredentialsFilePath, backupCAPICreds); err != nil {
-			return fmt.Errorf("failed copy %s to %s: %s", csConfig.API.Server.OnlineClient.CredentialsFilePath, backupCAPICreds, err)
+		if err = CopyFile(cfg.API.Server.OnlineClient.CredentialsFilePath, backupCAPICreds); err != nil {
+			return fmt.Errorf("failed copy %s to %s: %w", cfg.API.Server.OnlineClient.CredentialsFilePath, backupCAPICreds, err)
 		}
 
 		log.Infof("Saved online API credentials to %s", backupCAPICreds)
 	}
 
-	if csConfig.API != nil && csConfig.API.Client != nil && csConfig.API.Client.CredentialsFilePath != "" {
+	if cfg.API != nil && cfg.API.Client != nil && cfg.API.Client.CredentialsFilePath != "" {
 		backupLAPICreds := fmt.Sprintf("%s/local_api_credentials.yaml", dirPath)
-		if err = CopyFile(csConfig.API.Client.CredentialsFilePath, backupLAPICreds); err != nil {
-			return fmt.Errorf("failed copy %s to %s: %s", csConfig.API.Client.CredentialsFilePath, backupLAPICreds, err)
+		if err = CopyFile(cfg.API.Client.CredentialsFilePath, backupLAPICreds); err != nil {
+			return fmt.Errorf("failed copy %s to %s: %w", cfg.API.Client.CredentialsFilePath, backupLAPICreds, err)
 		}
 
 		log.Infof("Saved local API credentials to %s", backupLAPICreds)
 	}
 
-	if csConfig.API != nil && csConfig.API.Server != nil && csConfig.API.Server.ProfilesPath != "" {
+	if cfg.API != nil && cfg.API.Server != nil && cfg.API.Server.ProfilesPath != "" {
 		backupProfiles := fmt.Sprintf("%s/profiles.yaml", dirPath)
-		if err = CopyFile(csConfig.API.Server.ProfilesPath, backupProfiles); err != nil {
-			return fmt.Errorf("failed copy %s to %s: %s", csConfig.API.Server.ProfilesPath, backupProfiles, err)
+		if err = CopyFile(cfg.API.Server.ProfilesPath, backupProfiles); err != nil {
+			return fmt.Errorf("failed copy %s to %s: %w", cfg.API.Server.ProfilesPath, backupProfiles, err)
 		}
 
 		log.Infof("Saved profiles to %s", backupProfiles)
 	}
 
-	if err = backupHub(dirPath); err != nil {
-		return fmt.Errorf("failed to backup hub config: %s", err)
-	}
-
-	return nil
-}
-
-func runConfigBackup(cmd *cobra.Command, args []string) error {
-	if err := backupConfigToDirectory(args[0]); err != nil {
-		return fmt.Errorf("failed to backup config: %w", err)
+	if err = cli.backupHub(dirPath); err != nil {
+		return fmt.Errorf("failed to backup hub config: %w", err)
 	}
 
 	return nil
 }
 
-func NewConfigBackupCmd() *cobra.Command {
-	cmdConfigBackup := &cobra.Command{
+func (cli *cliConfig) newBackupCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:   `backup "directory"`,
 		Short: "Backup current config",
 		Long: `Backup the current crowdsec configuration including :
@@ -232,8 +227,14 @@ func NewConfigBackupCmd() *cobra.Command {
 		Example:           `cscli config backup ./my-backup`,
 		Args:              cobra.ExactArgs(1),
 		DisableAutoGenTag: true,
-		RunE:              runConfigBackup,
+		RunE: func(_ *cobra.Command, args []string) error {
+			if err := cli.backup(args[0]); err != nil {
+				return fmt.Errorf("failed to backup config: %w", err)
+			}
+
+			return nil
+		},
 	}
 
-	return cmdConfigBackup
+	return cmd
 }

+ 11 - 14
cmd/crowdsec-cli/config_feature_flags.go

@@ -11,14 +11,7 @@ import (
 	"github.com/crowdsecurity/crowdsec/pkg/fflag"
 )
 
-func runConfigFeatureFlags(cmd *cobra.Command, args []string) error {
-	flags := cmd.Flags()
-
-	showRetired, err := flags.GetBool("retired")
-	if err != nil {
-		return err
-	}
-
+func (cli *cliConfig) featureFlags(showRetired bool) error {
 	green := color.New(color.FgGreen).SprintFunc()
 	red := color.New(color.FgRed).SprintFunc()
 	yellow := color.New(color.FgYellow).SprintFunc()
@@ -121,18 +114,22 @@ func runConfigFeatureFlags(cmd *cobra.Command, args []string) error {
 	return nil
 }
 
-func NewConfigFeatureFlagsCmd() *cobra.Command {
-	cmdConfigFeatureFlags := &cobra.Command{
+func (cli *cliConfig) newFeatureFlagsCmd() *cobra.Command {
+	var showRetired bool
+
+	cmd := &cobra.Command{
 		Use:               "feature-flags",
 		Short:             "Displays feature flag status",
 		Long:              `Displays the supported feature flags and their current status.`,
 		Args:              cobra.ExactArgs(0),
 		DisableAutoGenTag: true,
-		RunE:              runConfigFeatureFlags,
+		RunE: func(_ *cobra.Command, _ []string) error {
+			return cli.featureFlags(showRetired)
+		},
 	}
 
-	flags := cmdConfigFeatureFlags.Flags()
-	flags.Bool("retired", false, "Show retired features")
+	flags := cmd.Flags()
+	flags.BoolVar(&showRetired, "retired", false, "Show retired features")
 
-	return cmdConfigFeatureFlags
+	return cmd
 }

+ 62 - 113
cmd/crowdsec-cli/config_restore.go

@@ -3,25 +3,17 @@ package main
 import (
 	"encoding/json"
 	"fmt"
-	"io"
 	"os"
 	"path/filepath"
 
 	log "github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
-	"gopkg.in/yaml.v2"
 
 	"github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require"
-	"github.com/crowdsecurity/crowdsec/pkg/csconfig"
 	"github.com/crowdsecurity/crowdsec/pkg/cwhub"
 )
 
-type OldAPICfg struct {
-	MachineID string `json:"machine_id"`
-	Password  string `json:"password"`
-}
-
-func restoreHub(dirPath string) error {
+func (cli *cliConfig) restoreHub(dirPath string) error {
 	hub, err := require.Hub(csConfig, require.RemoteHub(csConfig), nil)
 	if err != nil {
 		return err
@@ -38,14 +30,14 @@ func restoreHub(dirPath string) error {
 
 		file, err := os.ReadFile(upstreamListFN)
 		if err != nil {
-			return fmt.Errorf("error while opening %s : %s", upstreamListFN, err)
+			return fmt.Errorf("error while opening %s: %w", upstreamListFN, err)
 		}
 
 		var upstreamList []string
 
 		err = json.Unmarshal(file, &upstreamList)
 		if err != nil {
-			return fmt.Errorf("error unmarshaling %s : %s", upstreamListFN, err)
+			return fmt.Errorf("error unmarshaling %s: %w", upstreamListFN, err)
 		}
 
 		for _, toinstall := range upstreamList {
@@ -55,8 +47,7 @@ func restoreHub(dirPath string) error {
 				continue
 			}
 
-			err := item.Install(false, false)
-			if err != nil {
+			if err = item.Install(false, false); err != nil {
 				log.Errorf("Error while installing %s : %s", toinstall, err)
 			}
 		}
@@ -64,17 +55,17 @@ func restoreHub(dirPath string) error {
 		/*restore the local and tainted items*/
 		files, err := os.ReadDir(itemDirectory)
 		if err != nil {
-			return fmt.Errorf("failed enumerating files of %s : %s", itemDirectory, err)
+			return fmt.Errorf("failed enumerating files of %s: %w", itemDirectory, err)
 		}
 
 		for _, file := range files {
-			//this was the upstream data
+			// this was the upstream data
 			if file.Name() == fmt.Sprintf("upstream-%s.json", itype) {
 				continue
 			}
 
 			if itype == cwhub.PARSERS || itype == cwhub.POSTOVERFLOWS {
-				//we expect a stage here
+				// we expect a stage here
 				if !file.IsDir() {
 					continue
 				}
@@ -84,22 +75,23 @@ func restoreHub(dirPath string) error {
 				log.Debugf("Found stage %s in %s, target directory : %s", stage, itype, stagedir)
 
 				if err = os.MkdirAll(stagedir, os.ModePerm); err != nil {
-					return fmt.Errorf("error while creating stage directory %s : %s", stagedir, err)
+					return fmt.Errorf("error while creating stage directory %s: %w", stagedir, err)
 				}
 
 				// find items
 				ifiles, err := os.ReadDir(itemDirectory + "/" + stage + "/")
 				if err != nil {
-					return fmt.Errorf("failed enumerating files of %s : %s", itemDirectory+"/"+stage, err)
+					return fmt.Errorf("failed enumerating files of %s: %w", itemDirectory+"/"+stage, err)
 				}
-				//finally copy item
+
+				// finally copy item
 				for _, tfile := range ifiles {
 					log.Infof("Going to restore local/tainted [%s]", tfile.Name())
 					sourceFile := fmt.Sprintf("%s/%s/%s", itemDirectory, stage, tfile.Name())
 
 					destinationFile := fmt.Sprintf("%s%s", stagedir, tfile.Name())
 					if err = CopyFile(sourceFile, destinationFile); err != nil {
-						return fmt.Errorf("failed copy %s %s to %s : %s", itype, sourceFile, destinationFile, err)
+						return fmt.Errorf("failed copy %s %s to %s: %w", itype, sourceFile, destinationFile, err)
 					}
 
 					log.Infof("restored %s to %s", sourceFile, destinationFile)
@@ -108,9 +100,11 @@ func restoreHub(dirPath string) error {
 				log.Infof("Going to restore local/tainted [%s]", file.Name())
 				sourceFile := fmt.Sprintf("%s/%s", itemDirectory, file.Name())
 				destinationFile := fmt.Sprintf("%s/%s/%s", csConfig.ConfigPaths.ConfigDir, itype, file.Name())
+
 				if err = CopyFile(sourceFile, destinationFile); err != nil {
-					return fmt.Errorf("failed copy %s %s to %s : %s", itype, sourceFile, destinationFile, err)
+					return fmt.Errorf("failed copy %s %s to %s: %w", itype, sourceFile, destinationFile, err)
 				}
+
 				log.Infof("restored %s to %s", sourceFile, destinationFile)
 			}
 		}
@@ -130,95 +124,60 @@ func restoreHub(dirPath string) error {
 - Tainted/local/out-of-date scenarios, parsers, postoverflows and collections
 - Acquisition files (acquis.yaml, acquis.d/*.yaml)
 */
-func restoreConfigFromDirectory(dirPath string, oldBackup bool) error {
+func (cli *cliConfig) restore(dirPath string) error {
 	var err error
 
-	if !oldBackup {
-		backupMain := fmt.Sprintf("%s/config.yaml", dirPath)
-		if _, err = os.Stat(backupMain); err == nil {
-			if csConfig.ConfigPaths != nil && csConfig.ConfigPaths.ConfigDir != "" {
-				if err = CopyFile(backupMain, fmt.Sprintf("%s/config.yaml", csConfig.ConfigPaths.ConfigDir)); err != nil {
-					return fmt.Errorf("failed copy %s to %s : %s", backupMain, csConfig.ConfigPaths.ConfigDir, err)
-				}
+	backupMain := fmt.Sprintf("%s/config.yaml", dirPath)
+	if _, err = os.Stat(backupMain); err == nil {
+		if csConfig.ConfigPaths != nil && csConfig.ConfigPaths.ConfigDir != "" {
+			if err = CopyFile(backupMain, fmt.Sprintf("%s/config.yaml", csConfig.ConfigPaths.ConfigDir)); err != nil {
+				return fmt.Errorf("failed copy %s to %s: %w", backupMain, csConfig.ConfigPaths.ConfigDir, err)
 			}
 		}
+	}
 
-		// Now we have config.yaml, we should regenerate config struct to have rights paths etc
-		ConfigFilePath = fmt.Sprintf("%s/config.yaml", csConfig.ConfigPaths.ConfigDir)
-
-		log.Debug("Reloading configuration")
+	// Now we have config.yaml, we should regenerate config struct to have rights paths etc
+	ConfigFilePath = fmt.Sprintf("%s/config.yaml", csConfig.ConfigPaths.ConfigDir)
 
-		csConfig, _, err = loadConfigFor("config")
-		if err != nil {
-			return fmt.Errorf("failed to reload configuration: %s", err)
-		}
+	log.Debug("Reloading configuration")
 
-		backupCAPICreds := fmt.Sprintf("%s/online_api_credentials.yaml", dirPath)
-		if _, err = os.Stat(backupCAPICreds); err == nil {
-			if err = CopyFile(backupCAPICreds, csConfig.API.Server.OnlineClient.CredentialsFilePath); err != nil {
-				return fmt.Errorf("failed copy %s to %s : %s", backupCAPICreds, csConfig.API.Server.OnlineClient.CredentialsFilePath, err)
-			}
-		}
+	csConfig, _, err = loadConfigFor("config")
+	if err != nil {
+		return fmt.Errorf("failed to reload configuration: %w", err)
+	}
 
-		backupLAPICreds := fmt.Sprintf("%s/local_api_credentials.yaml", dirPath)
-		if _, err = os.Stat(backupLAPICreds); err == nil {
-			if err = CopyFile(backupLAPICreds, csConfig.API.Client.CredentialsFilePath); err != nil {
-				return fmt.Errorf("failed copy %s to %s : %s", backupLAPICreds, csConfig.API.Client.CredentialsFilePath, err)
-			}
+	backupCAPICreds := fmt.Sprintf("%s/online_api_credentials.yaml", dirPath)
+	if _, err = os.Stat(backupCAPICreds); err == nil {
+		if err = CopyFile(backupCAPICreds, csConfig.API.Server.OnlineClient.CredentialsFilePath); err != nil {
+			return fmt.Errorf("failed copy %s to %s: %w", backupCAPICreds, csConfig.API.Server.OnlineClient.CredentialsFilePath, err)
 		}
+	}
 
-		backupProfiles := fmt.Sprintf("%s/profiles.yaml", dirPath)
-		if _, err = os.Stat(backupProfiles); err == nil {
-			if err = CopyFile(backupProfiles, csConfig.API.Server.ProfilesPath); err != nil {
-				return fmt.Errorf("failed copy %s to %s : %s", backupProfiles, csConfig.API.Server.ProfilesPath, err)
-			}
+	backupLAPICreds := fmt.Sprintf("%s/local_api_credentials.yaml", dirPath)
+	if _, err = os.Stat(backupLAPICreds); err == nil {
+		if err = CopyFile(backupLAPICreds, csConfig.API.Client.CredentialsFilePath); err != nil {
+			return fmt.Errorf("failed copy %s to %s: %w", backupLAPICreds, csConfig.API.Client.CredentialsFilePath, err)
 		}
-	} else {
-		var oldAPICfg OldAPICfg
-		backupOldAPICfg := fmt.Sprintf("%s/api_creds.json", dirPath)
-
-		jsonFile, err := os.Open(backupOldAPICfg)
-		if err != nil {
-			log.Warningf("failed to open %s : %s", backupOldAPICfg, err)
-		} else {
-			byteValue, _ := io.ReadAll(jsonFile)
-			err = json.Unmarshal(byteValue, &oldAPICfg)
-			if err != nil {
-				return fmt.Errorf("failed to load json file %s : %s", backupOldAPICfg, err)
-			}
+	}
 
-			apiCfg := csconfig.ApiCredentialsCfg{
-				Login:    oldAPICfg.MachineID,
-				Password: oldAPICfg.Password,
-				URL:      CAPIBaseURL,
-			}
-			apiConfigDump, err := yaml.Marshal(apiCfg)
-			if err != nil {
-				return fmt.Errorf("unable to dump api credentials: %s", err)
-			}
-			apiConfigDumpFile := fmt.Sprintf("%s/online_api_credentials.yaml", csConfig.ConfigPaths.ConfigDir)
-			if csConfig.API.Server.OnlineClient != nil && csConfig.API.Server.OnlineClient.CredentialsFilePath != "" {
-				apiConfigDumpFile = csConfig.API.Server.OnlineClient.CredentialsFilePath
-			}
-			err = os.WriteFile(apiConfigDumpFile, apiConfigDump, 0o600)
-			if err != nil {
-				return fmt.Errorf("write api credentials in '%s' failed: %s", apiConfigDumpFile, err)
-			}
-			log.Infof("Saved API credentials to %s", apiConfigDumpFile)
+	backupProfiles := fmt.Sprintf("%s/profiles.yaml", dirPath)
+	if _, err = os.Stat(backupProfiles); err == nil {
+		if err = CopyFile(backupProfiles, csConfig.API.Server.ProfilesPath); err != nil {
+			return fmt.Errorf("failed copy %s to %s: %w", backupProfiles, csConfig.API.Server.ProfilesPath, err)
 		}
 	}
 
 	backupSimulation := fmt.Sprintf("%s/simulation.yaml", dirPath)
 	if _, err = os.Stat(backupSimulation); err == nil {
 		if err = CopyFile(backupSimulation, csConfig.ConfigPaths.SimulationFilePath); err != nil {
-			return fmt.Errorf("failed copy %s to %s : %s", backupSimulation, csConfig.ConfigPaths.SimulationFilePath, err)
+			return fmt.Errorf("failed copy %s to %s: %w", backupSimulation, csConfig.ConfigPaths.SimulationFilePath, err)
 		}
 	}
 
 	/*if there is a acquisition dir, restore its content*/
 	if csConfig.Crowdsec.AcquisitionDirPath != "" {
 		if err = os.MkdirAll(csConfig.Crowdsec.AcquisitionDirPath, 0o700); err != nil {
-			return fmt.Errorf("error while creating %s : %s", csConfig.Crowdsec.AcquisitionDirPath, err)
+			return fmt.Errorf("error while creating %s: %w", csConfig.Crowdsec.AcquisitionDirPath, err)
 		}
 	}
 
@@ -228,7 +187,7 @@ func restoreConfigFromDirectory(dirPath string, oldBackup bool) error {
 		log.Debugf("restoring backup'ed %s", backupAcquisition)
 
 		if err = CopyFile(backupAcquisition, csConfig.Crowdsec.AcquisitionFilePath); err != nil {
-			return fmt.Errorf("failed copy %s to %s : %s", backupAcquisition, csConfig.Crowdsec.AcquisitionFilePath, err)
+			return fmt.Errorf("failed copy %s to %s: %w", backupAcquisition, csConfig.Crowdsec.AcquisitionFilePath, err)
 		}
 	}
 
@@ -244,7 +203,7 @@ func restoreConfigFromDirectory(dirPath string, oldBackup bool) error {
 			log.Debugf("restoring %s to %s", acquisFile, targetFname)
 
 			if err = CopyFile(acquisFile, targetFname); err != nil {
-				return fmt.Errorf("failed copy %s to %s : %s", acquisFile, targetFname, err)
+				return fmt.Errorf("failed copy %s to %s: %w", acquisFile, targetFname, err)
 			}
 		}
 	}
@@ -265,37 +224,22 @@ func restoreConfigFromDirectory(dirPath string, oldBackup bool) error {
 			}
 
 			if err = CopyFile(acquisFile, targetFname); err != nil {
-				return fmt.Errorf("failed copy %s to %s : %s", acquisFile, targetFname, err)
+				return fmt.Errorf("failed copy %s to %s: %w", acquisFile, targetFname, err)
 			}
 
 			log.Infof("Saved acquis %s to %s", acquisFile, targetFname)
 		}
 	}
 
-	if err = restoreHub(dirPath); err != nil {
-		return fmt.Errorf("failed to restore hub config : %s", err)
+	if err = cli.restoreHub(dirPath); err != nil {
+		return fmt.Errorf("failed to restore hub config: %w", err)
 	}
 
 	return nil
 }
 
-func runConfigRestore(cmd *cobra.Command, args []string) error {
-	flags := cmd.Flags()
-
-	oldBackup, err := flags.GetBool("old-backup")
-	if err != nil {
-		return err
-	}
-
-	if err := restoreConfigFromDirectory(args[0], oldBackup); err != nil {
-		return fmt.Errorf("failed to restore config from %s: %w", args[0], err)
-	}
-
-	return nil
-}
-
-func NewConfigRestoreCmd() *cobra.Command {
-	cmdConfigRestore := &cobra.Command{
+func (cli *cliConfig) newRestoreCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:   `restore "directory"`,
 		Short: `Restore config in backup "directory"`,
 		Long: `Restore the crowdsec configuration from specified backup "directory" including:
@@ -308,11 +252,16 @@ func NewConfigRestoreCmd() *cobra.Command {
 - Backup of API credentials (local API and online API)`,
 		Args:              cobra.ExactArgs(1),
 		DisableAutoGenTag: true,
-		RunE:              runConfigRestore,
-	}
+		RunE: func(_ *cobra.Command, args []string) error {
+			dirPath := args[0]
 
-	flags := cmdConfigRestore.Flags()
-	flags.BoolP("old-backup", "", false, "To use when you are upgrading crowdsec v0.X to v1.X and you need to restore backup from v0.X")
+			if err := cli.restore(dirPath); err != nil {
+				return fmt.Errorf("failed to restore config from %s: %w", dirPath, err)
+			}
+
+			return nil
+		},
+	}
 
-	return cmdConfigRestore
+	return cmd
 }

+ 18 - 19
cmd/crowdsec-cli/config_show.go

@@ -182,31 +182,26 @@ Central API:
 {{- end }}
 `
 
-func runConfigShow(cmd *cobra.Command, args []string) error {
-	flags := cmd.Flags()
+func (cli *cliConfig) show(key string) error {
+	cfg := cli.cfg()
 
-	if err := csConfig.LoadAPIClient(); err != nil {
+	if err := cfg.LoadAPIClient(); err != nil {
 		log.Errorf("failed to load API client configuration: %s", err)
 		// don't return, we can still show the configuration
 	}
 
-	key, err := flags.GetString("key")
-	if err != nil {
-		return err
-	}
-
 	if key != "" {
 		return showConfigKey(key)
 	}
 
-	switch csConfig.Cscli.Output {
+	switch cfg.Cscli.Output {
 	case "human":
 		// The tests on .Enable look funny because the option has a true default which has
 		// not been set yet (we don't really load the LAPI) and go templates don't dereference
 		// pointers in boolean tests. Prefix notation is the cherry on top.
 		funcs := template.FuncMap{
 			// can't use generics here
-			"ValueBool": func(b *bool) bool { return b!=nil && *b },
+			"ValueBool": func(b *bool) bool { return b != nil && *b },
 		}
 
 		tmp, err := template.New("config").Funcs(funcs).Parse(configShowTemplate)
@@ -214,19 +209,19 @@ func runConfigShow(cmd *cobra.Command, args []string) error {
 			return err
 		}
 
-		err = tmp.Execute(os.Stdout, csConfig)
+		err = tmp.Execute(os.Stdout, cfg)
 		if err != nil {
 			return err
 		}
 	case "json":
-		data, err := json.MarshalIndent(csConfig, "", "  ")
+		data, err := json.MarshalIndent(cfg, "", "  ")
 		if err != nil {
 			return fmt.Errorf("failed to marshal configuration: %w", err)
 		}
 
 		fmt.Printf("%s\n", string(data))
 	case "raw":
-		data, err := yaml.Marshal(csConfig)
+		data, err := yaml.Marshal(cfg)
 		if err != nil {
 			return fmt.Errorf("failed to marshal configuration: %w", err)
 		}
@@ -237,18 +232,22 @@ func runConfigShow(cmd *cobra.Command, args []string) error {
 	return nil
 }
 
-func NewConfigShowCmd() *cobra.Command {
-	cmdConfigShow := &cobra.Command{
+func (cli *cliConfig) newShowCmd() *cobra.Command {
+	var key string
+
+	cmd := &cobra.Command{
 		Use:               "show",
 		Short:             "Displays current config",
 		Long:              `Displays the current cli configuration.`,
 		Args:              cobra.ExactArgs(0),
 		DisableAutoGenTag: true,
-		RunE:              runConfigShow,
+		RunE: func(_ *cobra.Command, _ []string) error {
+			return cli.show(key)
+		},
 	}
 
-	flags := cmdConfigShow.Flags()
-	flags.StringP("key", "", "", "Display only this value (Config.API.Server.ListenURI)")
+	flags := cmd.Flags()
+	flags.StringVarP(&key, "key", "", "", "Display only this value (Config.API.Server.ListenURI)")
 
-	return cmdConfigShow
+	return cmd
 }

+ 7 - 5
cmd/crowdsec-cli/config_showyaml.go

@@ -6,19 +6,21 @@ import (
 	"github.com/spf13/cobra"
 )
 
-func runConfigShowYAML(cmd *cobra.Command, args []string) error {
+func (cli *cliConfig) showYAML() error {
 	fmt.Println(mergedConfig)
 	return nil
 }
 
-func NewConfigShowYAMLCmd() *cobra.Command {
-	cmdConfigShow := &cobra.Command{
+func (cli *cliConfig) newShowYAMLCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:               "show-yaml",
 		Short:             "Displays merged config.yaml + config.yaml.local",
 		Args:              cobra.ExactArgs(0),
 		DisableAutoGenTag: true,
-		RunE:              runConfigShowYAML,
+		RunE: func(_ *cobra.Command, _ []string) error {
+			return cli.showYAML()
+		},
 	}
 
-	return cmdConfigShow
+	return cmd
 }

+ 1 - 1
cmd/crowdsec-cli/main.go

@@ -231,7 +231,7 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall
 
 	cmd.AddCommand(NewCLIDoc().NewCommand(cmd))
 	cmd.AddCommand(NewCLIVersion().NewCommand())
-	cmd.AddCommand(NewConfigCmd())
+	cmd.AddCommand(NewCLIConfig(cli.cfg).NewCommand())
 	cmd.AddCommand(NewCLIHub(cli.cfg).NewCommand())
 	cmd.AddCommand(NewCLIMetrics(cli.cfg).NewCommand())
 	cmd.AddCommand(NewCLIDashboard(cli.cfg).NewCommand())