浏览代码

cscli refact - encapsulation with types (#2643)

* refactor type cliHub, cliBouncers, cliMachines, cliPapi, cliNotifications, cliSupport, type cliExplain
mmetc 1 年之前
父节点
当前提交
3e86f52250

+ 57 - 51
cmd/crowdsec-cli/bouncers.go

@@ -60,8 +60,46 @@ func getBouncers(out io.Writer, dbClient *database.Client) error {
 	return nil
 }
 
-func NewBouncersListCmd() *cobra.Command {
-	cmdBouncersList := &cobra.Command{
+type cliBouncers struct {}
+
+func NewCLIBouncers() *cliBouncers {
+	return &cliBouncers{}
+}
+
+func (cli cliBouncers) NewCommand() *cobra.Command {
+	cmd := &cobra.Command{
+		Use:   "bouncers [action]",
+		Short: "Manage bouncers [requires local API]",
+		Long: `To list/add/delete/prune bouncers.
+Note: This command requires database direct access, so is intended to be run on Local API/master.
+`,
+		Args:              cobra.MinimumNArgs(1),
+		Aliases:           []string{"bouncer"},
+		DisableAutoGenTag: true,
+		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
+			var err error
+			if err = require.LAPI(csConfig); err != nil {
+				return err
+			}
+
+			dbClient, err = database.NewClient(csConfig.DbConfig)
+			if err != nil {
+				return fmt.Errorf("unable to create new database client: %s", err)
+			}
+			return nil
+		},
+	}
+
+	cmd.AddCommand(cli.NewListCmd())
+	cmd.AddCommand(cli.NewAddCmd())
+	cmd.AddCommand(cli.NewDeleteCmd())
+	cmd.AddCommand(cli.NewPruneCmd())
+
+	return cmd
+}
+
+func (cli cliBouncers) NewListCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:               "list",
 		Short:             "list all bouncers within the database",
 		Example:           `cscli bouncers list`,
@@ -76,10 +114,10 @@ func NewBouncersListCmd() *cobra.Command {
 		},
 	}
 
-	return cmdBouncersList
+	return cmd
 }
 
-func runBouncersAdd(cmd *cobra.Command, args []string) error {
+func (cli cliBouncers) add(cmd *cobra.Command, args []string) error {
 	keyLength := 32
 
 	flags := cmd.Flags()
@@ -125,26 +163,26 @@ func runBouncersAdd(cmd *cobra.Command, args []string) error {
 	return nil
 }
 
-func NewBouncersAddCmd() *cobra.Command {
-	cmdBouncersAdd := &cobra.Command{
+func (cli cliBouncers) NewAddCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:   "add MyBouncerName",
 		Short: "add a single bouncer to the database",
 		Example: `cscli bouncers add MyBouncerName
 cscli bouncers add MyBouncerName --key <random-key>`,
 		Args:              cobra.ExactArgs(1),
 		DisableAutoGenTag: true,
-		RunE:              runBouncersAdd,
+		RunE:              cli.add,
 	}
 
-	flags := cmdBouncersAdd.Flags()
+	flags := cmd.Flags()
 	flags.StringP("length", "l", "", "length of the api key")
 	flags.MarkDeprecated("length", "use --key instead")
 	flags.StringP("key", "k", "", "api key for the bouncer")
 
-	return cmdBouncersAdd
+	return cmd
 }
 
-func runBouncersDelete(cmd *cobra.Command, args []string) error {
+func (cli cliBouncers) delete(cmd *cobra.Command, args []string) error {
 	for _, bouncerID := range args {
 		err := dbClient.DeleteBouncer(bouncerID)
 		if err != nil {
@@ -156,8 +194,8 @@ func runBouncersDelete(cmd *cobra.Command, args []string) error {
 	return nil
 }
 
-func NewBouncersDeleteCmd() *cobra.Command {
-	cmdBouncersDelete := &cobra.Command{
+func (cli cliBouncers) NewDeleteCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:               "delete MyBouncerName",
 		Short:             "delete bouncer(s) from the database",
 		Args:              cobra.MinimumNArgs(1),
@@ -182,15 +220,15 @@ func NewBouncersDeleteCmd() *cobra.Command {
 			}
 			return ret, cobra.ShellCompDirectiveNoFileComp
 		},
-		RunE: runBouncersDelete,
+		RunE: cli.delete,
 	}
 
-	return cmdBouncersDelete
+	return cmd
 }
 
-func NewBouncersPruneCmd() *cobra.Command {
+func (cli cliBouncers) NewPruneCmd() *cobra.Command {
 	var parsedDuration time.Duration
-	cmdBouncersPrune := &cobra.Command{
+	cmd := &cobra.Command{
 		Use:               "prune",
 		Short:             "prune multiple bouncers from the database",
 		Args:              cobra.NoArgs,
@@ -253,39 +291,7 @@ cscli bouncers prune -d 60m --force`,
 			return nil
 		},
 	}
-	cmdBouncersPrune.Flags().StringP("duration", "d", "60m", "duration of time since last pull")
-	cmdBouncersPrune.Flags().Bool("force", false, "force prune without asking for confirmation")
-	return cmdBouncersPrune
-}
-
-func NewBouncersCmd() *cobra.Command {
-	var cmdBouncers = &cobra.Command{
-		Use:   "bouncers [action]",
-		Short: "Manage bouncers [requires local API]",
-		Long: `To list/add/delete/prune bouncers.
-Note: This command requires database direct access, so is intended to be run on Local API/master.
-`,
-		Args:              cobra.MinimumNArgs(1),
-		Aliases:           []string{"bouncer"},
-		DisableAutoGenTag: true,
-		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
-			var err error
-			if err = require.LAPI(csConfig); err != nil {
-				return err
-			}
-
-			dbClient, err = database.NewClient(csConfig.DbConfig)
-			if err != nil {
-				return fmt.Errorf("unable to create new database client: %s", err)
-			}
-			return nil
-		},
-	}
-
-	cmdBouncers.AddCommand(NewBouncersListCmd())
-	cmdBouncers.AddCommand(NewBouncersAddCmd())
-	cmdBouncers.AddCommand(NewBouncersDeleteCmd())
-	cmdBouncers.AddCommand(NewBouncersPruneCmd())
-
-	return cmdBouncers
+	cmd.Flags().StringP("duration", "d", "60m", "duration of time since last pull")
+	cmd.Flags().Bool("force", false, "force prune without asking for confirmation")
+	return cmd
 }

+ 79 - 73
cmd/crowdsec-cli/explain.go

@@ -34,7 +34,85 @@ func GetLineCountForFile(filepath string) (int, error) {
 	return lc, nil
 }
 
-func runExplain(cmd *cobra.Command, args []string) error {
+type cliExplain struct {}
+
+func NewCLIExplain() *cliExplain {
+	return &cliExplain{}
+}
+
+func (cli cliExplain) NewCommand() *cobra.Command {
+	cmd := &cobra.Command{
+		Use:   "explain",
+		Short: "Explain log pipeline",
+		Long: `
+Explain log pipeline 
+		`,
+		Example: `
+cscli explain --file ./myfile.log --type nginx 
+cscli explain --log "Sep 19 18:33:22 scw-d95986 sshd[24347]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=1.2.3.4" --type syslog
+cscli explain --dsn "file://myfile.log" --type nginx
+tail -n 5 myfile.log | cscli explain --type nginx -f -
+		`,
+		Args:              cobra.ExactArgs(0),
+		DisableAutoGenTag: true,
+		RunE:              cli.run,
+		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
+			flags := cmd.Flags()
+
+			logFile, err := flags.GetString("file")
+			if err != nil {
+				return err
+			}
+
+			dsn, err := flags.GetString("dsn")
+			if err != nil {
+				return err
+			}
+
+			logLine, err := flags.GetString("log")
+			if err != nil {
+				return err
+			}
+
+			logType, err := flags.GetString("type")
+			if err != nil {
+				return err
+			}
+
+			if logLine == "" && logFile == "" && dsn == "" {
+				printHelp(cmd)
+				fmt.Println()
+				return fmt.Errorf("please provide --log, --file or --dsn flag")
+			}
+			if logType == "" {
+				printHelp(cmd)
+				fmt.Println()
+				return fmt.Errorf("please provide --type flag")
+			}
+			fileInfo, _ := os.Stdin.Stat()
+			if logFile == "-" && ((fileInfo.Mode() & os.ModeCharDevice) == os.ModeCharDevice) {
+				return fmt.Errorf("the option -f - is intended to work with pipes")
+			}
+			return nil
+		},
+	}
+
+	flags := cmd.Flags()
+
+	flags.StringP("file", "f", "", "Log file to test")
+	flags.StringP("dsn", "d", "", "DSN to test")
+	flags.StringP("log", "l", "", "Log line to test")
+	flags.StringP("type", "t", "", "Type of the acquisition to test")
+	flags.String("labels", "", "Additional labels to add to the acquisition format (key:value,key2:value2)")
+	flags.BoolP("verbose", "v", false, "Display individual changes")
+	flags.Bool("failures", false, "Only show failed lines")
+	flags.Bool("only-successful-parsers", false, "Only show successful parsers")
+	flags.String("crowdsec", "crowdsec", "Path to crowdsec")
+
+	return cmd
+}
+
+func (cli cliExplain) run(cmd *cobra.Command, args []string) error {
 	flags := cmd.Flags()
 
 	logFile, err := flags.GetString("file")
@@ -189,75 +267,3 @@ func runExplain(cmd *cobra.Command, args []string) error {
 
 	return nil
 }
-
-func NewExplainCmd() *cobra.Command {
-	cmdExplain := &cobra.Command{
-		Use:   "explain",
-		Short: "Explain log pipeline",
-		Long: `
-Explain log pipeline 
-		`,
-		Example: `
-cscli explain --file ./myfile.log --type nginx 
-cscli explain --log "Sep 19 18:33:22 scw-d95986 sshd[24347]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=1.2.3.4" --type syslog
-cscli explain --dsn "file://myfile.log" --type nginx
-tail -n 5 myfile.log | cscli explain --type nginx -f -
-		`,
-		Args:              cobra.ExactArgs(0),
-		DisableAutoGenTag: true,
-		RunE:              runExplain,
-		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
-			flags := cmd.Flags()
-
-			logFile, err := flags.GetString("file")
-			if err != nil {
-				return err
-			}
-
-			dsn, err := flags.GetString("dsn")
-			if err != nil {
-				return err
-			}
-
-			logLine, err := flags.GetString("log")
-			if err != nil {
-				return err
-			}
-
-			logType, err := flags.GetString("type")
-			if err != nil {
-				return err
-			}
-
-			if logLine == "" && logFile == "" && dsn == "" {
-				printHelp(cmd)
-				fmt.Println()
-				return fmt.Errorf("please provide --log, --file or --dsn flag")
-			}
-			if logType == "" {
-				printHelp(cmd)
-				fmt.Println()
-				return fmt.Errorf("please provide --type flag")
-			}
-			fileInfo, _ := os.Stdin.Stat()
-			if logFile == "-" && ((fileInfo.Mode() & os.ModeCharDevice) == os.ModeCharDevice) {
-				return fmt.Errorf("the option -f - is intended to work with pipes")
-			}
-			return nil
-		},
-	}
-
-	flags := cmdExplain.Flags()
-
-	flags.StringP("file", "f", "", "Log file to test")
-	flags.StringP("dsn", "d", "", "DSN to test")
-	flags.StringP("log", "l", "", "Log line to test")
-	flags.StringP("type", "t", "", "Type of the acquisition to test")
-	flags.String("labels", "", "Additional labels to add to the acquisition format (key:value,key2:value2)")
-	flags.BoolP("verbose", "v", false, "Display individual changes")
-	flags.Bool("failures", false, "Only show failed lines")
-	flags.Bool("only-successful-parsers", false, "Only show successful parsers")
-	flags.String("crowdsec", "crowdsec", "Path to crowdsec")
-
-	return cmdExplain
-}

+ 35 - 29
cmd/crowdsec-cli/hub.go

@@ -13,8 +13,14 @@ import (
 	"github.com/crowdsecurity/crowdsec/pkg/cwhub"
 )
 
-func NewHubCmd() *cobra.Command {
-	cmdHub := &cobra.Command{
+type cliHub struct{}
+
+func NewCLIHub() *cliHub {
+	return &cliHub{}
+}
+
+func (cli cliHub) NewCommand() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:   "hub [action]",
 		Short: "Manage hub index",
 		Long: `Hub management
@@ -28,15 +34,15 @@ cscli hub upgrade`,
 		DisableAutoGenTag: true,
 	}
 
-	cmdHub.AddCommand(NewHubListCmd())
-	cmdHub.AddCommand(NewHubUpdateCmd())
-	cmdHub.AddCommand(NewHubUpgradeCmd())
-	cmdHub.AddCommand(NewHubTypesCmd())
+	cmd.AddCommand(cli.NewListCmd())
+	cmd.AddCommand(cli.NewUpdateCmd())
+	cmd.AddCommand(cli.NewUpgradeCmd())
+	cmd.AddCommand(cli.NewTypesCmd())
 
-	return cmdHub
+	return cmd
 }
 
-func runHubList(cmd *cobra.Command, args []string) error {
+func (cli cliHub) list(cmd *cobra.Command, args []string) error {
 	flags := cmd.Flags()
 
 	all, err := flags.GetBool("all")
@@ -74,22 +80,22 @@ func runHubList(cmd *cobra.Command, args []string) error {
 	return nil
 }
 
-func NewHubListCmd() *cobra.Command {
-	cmdHubList := &cobra.Command{
+func (cli cliHub) NewListCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:               "list [-a]",
 		Short:             "List all installed configurations",
 		Args:              cobra.ExactArgs(0),
 		DisableAutoGenTag: true,
-		RunE:              runHubList,
+		RunE:              cli.list,
 	}
 
-	flags := cmdHubList.Flags()
+	flags := cmd.Flags()
 	flags.BoolP("all", "a", false, "List disabled items as well")
 
-	return cmdHubList
+	return cmd
 }
 
-func runHubUpdate(cmd *cobra.Command, args []string) error {
+func (cli cliHub) update(cmd *cobra.Command, args []string) error {
 	local := csConfig.Hub
 	remote := require.RemoteHub(csConfig)
 
@@ -106,8 +112,8 @@ func runHubUpdate(cmd *cobra.Command, args []string) error {
 	return nil
 }
 
-func NewHubUpdateCmd() *cobra.Command {
-	cmdHubUpdate := &cobra.Command{
+func (cli cliHub) NewUpdateCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:   "update",
 		Short: "Download the latest index (catalog of available configurations)",
 		Long: `
@@ -115,13 +121,13 @@ Fetches the .index.json file from the hub, containing the list of available conf
 `,
 		Args:              cobra.ExactArgs(0),
 		DisableAutoGenTag: true,
-		RunE:              runHubUpdate,
+		RunE:              cli.update,
 	}
 
-	return cmdHubUpdate
+	return cmd
 }
 
-func runHubUpgrade(cmd *cobra.Command, args []string) error {
+func (cli cliHub) upgrade(cmd *cobra.Command, args []string) error {
 	flags := cmd.Flags()
 
 	force, err := flags.GetBool("force")
@@ -158,8 +164,8 @@ func runHubUpgrade(cmd *cobra.Command, args []string) error {
 	return nil
 }
 
-func NewHubUpgradeCmd() *cobra.Command {
-	cmdHubUpgrade := &cobra.Command{
+func (cli cliHub) NewUpgradeCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:   "upgrade",
 		Short: "Upgrade all configurations to their latest version",
 		Long: `
@@ -167,16 +173,16 @@ Upgrade all configs installed from Crowdsec Hub. Run 'sudo cscli hub update' if
 `,
 		Args:              cobra.ExactArgs(0),
 		DisableAutoGenTag: true,
-		RunE:              runHubUpgrade,
+		RunE:              cli.upgrade,
 	}
 
-	flags := cmdHubUpgrade.Flags()
+	flags := cmd.Flags()
 	flags.Bool("force", false, "Force upgrade: overwrite tainted and outdated files")
 
-	return cmdHubUpgrade
+	return cmd
 }
 
-func runHubTypes(cmd *cobra.Command, args []string) error {
+func (cli cliHub) types(cmd *cobra.Command, args []string) error {
 	switch csConfig.Cscli.Output {
 	case "human":
 		s, err := yaml.Marshal(cwhub.ItemTypes)
@@ -198,8 +204,8 @@ func runHubTypes(cmd *cobra.Command, args []string) error {
 	return nil
 }
 
-func NewHubTypesCmd() *cobra.Command {
-	cmdHubTypes := &cobra.Command{
+func (cli cliHub) NewTypesCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:   "types",
 		Short: "List supported item types",
 		Long: `
@@ -207,8 +213,8 @@ List the types of supported hub items.
 `,
 		Args:              cobra.ExactArgs(0),
 		DisableAutoGenTag: true,
-		RunE:              runHubTypes,
+		RunE:              cli.types,
 	}
 
-	return cmdHubTypes
+	return cmd
 }

+ 61 - 57
cmd/crowdsec-cli/machines.go

@@ -142,8 +142,46 @@ func getAgents(out io.Writer, dbClient *database.Client) error {
 	return nil
 }
 
-func NewMachinesListCmd() *cobra.Command {
-	cmdMachinesList := &cobra.Command{
+type cliMachines struct {}
+
+func NewCLIMachines() *cliMachines {
+	return &cliMachines{}
+}
+
+func (cli cliMachines) NewCommand() *cobra.Command {
+	cmd := &cobra.Command{
+		Use:   "machines [action]",
+		Short: "Manage local API machines [requires local API]",
+		Long: `To list/add/delete/validate/prune machines.
+Note: This command requires database direct access, so is intended to be run on the local API machine.
+`,
+		Example:           `cscli machines [action]`,
+		DisableAutoGenTag: true,
+		Aliases:           []string{"machine"},
+		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
+			var err error
+			if err := require.LAPI(csConfig); err != nil {
+				return err
+			}
+			dbClient, err = database.NewClient(csConfig.DbConfig)
+			if err != nil {
+				return fmt.Errorf("unable to create new database client: %s", err)
+			}
+			return nil
+		},
+	}
+
+	cmd.AddCommand(cli.NewListCmd())
+	cmd.AddCommand(cli.NewAddCmd())
+	cmd.AddCommand(cli.NewDeleteCmd())
+	cmd.AddCommand(cli.NewValidateCmd())
+	cmd.AddCommand(cli.NewPruneCmd())
+
+	return cmd
+}
+
+func (cli cliMachines) NewListCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:               "list",
 		Short:             "list all machines in the database",
 		Long:              `list all machines in the database with their status and last heartbeat`,
@@ -160,11 +198,11 @@ func NewMachinesListCmd() *cobra.Command {
 		},
 	}
 
-	return cmdMachinesList
+	return cmd
 }
 
-func NewMachinesAddCmd() *cobra.Command {
-	cmdMachinesAdd := &cobra.Command{
+func (cli cliMachines) NewAddCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:               "add",
 		Short:             "add a single machine to the database",
 		DisableAutoGenTag: true,
@@ -174,10 +212,10 @@ cscli machines add --auto
 cscli machines add MyTestMachine --auto
 cscli machines add MyTestMachine --password MyPassword
 `,
-		RunE: runMachinesAdd,
+		RunE: cli.add,
 	}
 
-	flags := cmdMachinesAdd.Flags()
+	flags := cmd.Flags()
 	flags.StringP("password", "p", "", "machine password to login to the API")
 	flags.StringP("file", "f", "", "output file destination (defaults to "+csconfig.DefaultConfigPath("local_api_credentials.yaml")+")")
 	flags.StringP("url", "u", "", "URL of the local API")
@@ -185,12 +223,10 @@ cscli machines add MyTestMachine --password MyPassword
 	flags.BoolP("auto", "a", false, "automatically generate password (and username if not provided)")
 	flags.Bool("force", false, "will force add the machine if it already exist")
 
-	return cmdMachinesAdd
+	return cmd
 }
 
-func runMachinesAdd(cmd *cobra.Command, args []string) error {
-	var err error
-
+func (cli cliMachines) add(cmd *cobra.Command, args []string) error {
 	flags := cmd.Flags()
 
 	machinePassword, err := flags.GetString("password")
@@ -308,8 +344,8 @@ func runMachinesAdd(cmd *cobra.Command, args []string) error {
 	return nil
 }
 
-func NewMachinesDeleteCmd() *cobra.Command {
-	cmdMachinesDelete := &cobra.Command{
+func (cli cliMachines) NewDeleteCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:               "delete [machine_name]...",
 		Short:             "delete machine(s) by name",
 		Example:           `cscli machines delete "machine1" "machine2"`,
@@ -329,13 +365,13 @@ func NewMachinesDeleteCmd() *cobra.Command {
 			}
 			return ret, cobra.ShellCompDirectiveNoFileComp
 		},
-		RunE: runMachinesDelete,
+		RunE: cli.delete,
 	}
 
-	return cmdMachinesDelete
+	return cmd
 }
 
-func runMachinesDelete(cmd *cobra.Command, args []string) error {
+func (cli cliMachines) delete(cmd *cobra.Command, args []string) error {
 	for _, machineID := range args {
 		err := dbClient.DeleteWatcher(machineID)
 		if err != nil {
@@ -348,9 +384,9 @@ func runMachinesDelete(cmd *cobra.Command, args []string) error {
 	return nil
 }
 
-func NewMachinesPruneCmd() *cobra.Command {
+func (cli cliMachines) NewPruneCmd() *cobra.Command {
 	var parsedDuration time.Duration
-	cmdMachinesPrune := &cobra.Command{
+	cmd := &cobra.Command{
 		Use:   "prune",
 		Short: "prune multiple machines from the database",
 		Long:  `prune multiple machines that are not validated or have not connected to the local API in a given duration.`,
@@ -421,15 +457,15 @@ cscli machines prune --not-validated-only --force`,
 			return nil
 		},
 	}
-	cmdMachinesPrune.Flags().StringP("duration", "d", "10m", "duration of time since validated machine last heartbeat")
-	cmdMachinesPrune.Flags().Bool("not-validated-only", false, "only prune machines that are not validated")
-	cmdMachinesPrune.Flags().Bool("force", false, "force prune without asking for confirmation")
+	cmd.Flags().StringP("duration", "d", "10m", "duration of time since validated machine last heartbeat")
+	cmd.Flags().Bool("not-validated-only", false, "only prune machines that are not validated")
+	cmd.Flags().Bool("force", false, "force prune without asking for confirmation")
 
-	return cmdMachinesPrune
+	return cmd
 }
 
-func NewMachinesValidateCmd() *cobra.Command {
-	cmdMachinesValidate := &cobra.Command{
+func (cli cliMachines) NewValidateCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:               "validate",
 		Short:             "validate a machine to access the local API",
 		Long:              `validate a machine to access the local API.`,
@@ -447,37 +483,5 @@ func NewMachinesValidateCmd() *cobra.Command {
 		},
 	}
 
-	return cmdMachinesValidate
-}
-
-func NewMachinesCmd() *cobra.Command {
-	var cmdMachines = &cobra.Command{
-		Use:   "machines [action]",
-		Short: "Manage local API machines [requires local API]",
-		Long: `To list/add/delete/validate/prune machines.
-Note: This command requires database direct access, so is intended to be run on the local API machine.
-`,
-		Example:           `cscli machines [action]`,
-		DisableAutoGenTag: true,
-		Aliases:           []string{"machine"},
-		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
-			var err error
-			if err := require.LAPI(csConfig); err != nil {
-				return err
-			}
-			dbClient, err = database.NewClient(csConfig.DbConfig)
-			if err != nil {
-				return fmt.Errorf("unable to create new database client: %s", err)
-			}
-			return nil
-		},
-	}
-
-	cmdMachines.AddCommand(NewMachinesListCmd())
-	cmdMachines.AddCommand(NewMachinesAddCmd())
-	cmdMachines.AddCommand(NewMachinesDeleteCmd())
-	cmdMachines.AddCommand(NewMachinesValidateCmd())
-	cmdMachines.AddCommand(NewMachinesPruneCmd())
-
-	return cmdMachines
+	return cmd
 }

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

@@ -225,22 +225,22 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall
 	rootCmd.PersistentFlags().SortFlags = false
 
 	rootCmd.AddCommand(NewConfigCmd())
-	rootCmd.AddCommand(NewHubCmd())
+	rootCmd.AddCommand(NewCLIHub().NewCommand())
 	rootCmd.AddCommand(NewMetricsCmd())
 	rootCmd.AddCommand(NewDashboardCmd())
 	rootCmd.AddCommand(NewDecisionsCmd())
 	rootCmd.AddCommand(NewAlertsCmd())
 	rootCmd.AddCommand(NewSimulationCmds())
-	rootCmd.AddCommand(NewBouncersCmd())
-	rootCmd.AddCommand(NewMachinesCmd())
+	rootCmd.AddCommand(NewCLIBouncers().NewCommand())
+	rootCmd.AddCommand(NewCLIMachines().NewCommand())
 	rootCmd.AddCommand(NewCapiCmd())
 	rootCmd.AddCommand(NewLapiCmd())
 	rootCmd.AddCommand(NewCompletionCmd())
 	rootCmd.AddCommand(NewConsoleCmd())
-	rootCmd.AddCommand(NewExplainCmd())
+	rootCmd.AddCommand(NewCLIExplain().NewCommand())
 	rootCmd.AddCommand(NewHubTestCmd())
-	rootCmd.AddCommand(NewNotificationsCmd())
-	rootCmd.AddCommand(NewSupportCmd())
+	rootCmd.AddCommand(NewCLINotifications().NewCommand())
+	rootCmd.AddCommand(NewCLISupport().NewCommand())
 
 	rootCmd.AddCommand(NewCollectionCLI().NewCommand())
 	rootCmd.AddCommand(NewParserCLI().NewCommand())
@@ -254,7 +254,7 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall
 	}
 
 	if fflag.PapiClient.IsEnabled() {
-		rootCmd.AddCommand(NewPapiCmd())
+		rootCmd.AddCommand(NewCLIPapi().NewCommand())
 	}
 
 	if err := rootCmd.Execute(); err != nil {

+ 28 - 21
cmd/crowdsec-cli/notifications.go

@@ -39,8 +39,15 @@ type NotificationsCfg struct {
 	ids      []uint
 }
 
-func NewNotificationsCmd() *cobra.Command {
-	var cmdNotifications = &cobra.Command{
+
+type cliNotifications struct {}
+
+func NewCLINotifications() *cliNotifications {
+	return &cliNotifications{}
+}
+
+func (cli cliNotifications) NewCommand() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:               "notifications [action]",
 		Short:             "Helper for notification plugin configuration",
 		Long:              "To list/inspect/test notification template",
@@ -62,12 +69,12 @@ func NewNotificationsCmd() *cobra.Command {
 		},
 	}
 
-	cmdNotifications.AddCommand(NewNotificationsListCmd())
-	cmdNotifications.AddCommand(NewNotificationsInspectCmd())
-	cmdNotifications.AddCommand(NewNotificationsReinjectCmd())
-	cmdNotifications.AddCommand(NewNotificationsTestCmd())
+	cmd.AddCommand(cli.NewListCmd())
+	cmd.AddCommand(cli.NewInspectCmd())
+	cmd.AddCommand(cli.NewReinjectCmd())
+	cmd.AddCommand(cli.NewTestCmd())
 
-	return cmdNotifications
+	return cmd
 }
 
 func getPluginConfigs() (map[string]csplugin.PluginConfig, error) {
@@ -141,8 +148,8 @@ func getProfilesConfigs() (map[string]NotificationsCfg, error) {
 	return ncfgs, nil
 }
 
-func NewNotificationsListCmd() *cobra.Command {
-	var cmdNotificationsList = &cobra.Command{
+func (cli cliNotifications) NewListCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:               "list",
 		Short:             "list active notifications plugins",
 		Long:              `list active notifications plugins`,
@@ -185,11 +192,11 @@ func NewNotificationsListCmd() *cobra.Command {
 		},
 	}
 
-	return cmdNotificationsList
+	return cmd
 }
 
-func NewNotificationsInspectCmd() *cobra.Command {
-	var cmdNotificationsInspect = &cobra.Command{
+func (cli cliNotifications) NewInspectCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:               "inspect",
 		Short:             "Inspect active notifications plugin configuration",
 		Long:              `Inspect active notifications plugin and show configuration`,
@@ -230,16 +237,16 @@ func NewNotificationsInspectCmd() *cobra.Command {
 		},
 	}
 
-	return cmdNotificationsInspect
+	return cmd
 }
 
-func NewNotificationsTestCmd() *cobra.Command {
+func (cli cliNotifications) NewTestCmd() *cobra.Command {
 	var (
 		pluginBroker  csplugin.PluginBroker
 		pluginTomb    tomb.Tomb
 		alertOverride string
 	)
-	var cmdNotificationsTest = &cobra.Command{
+	cmd := &cobra.Command{
 		Use:               "test [plugin name]",
 		Short:             "send a generic test alert to notification plugin",
 		Long:              `send a generic test alert to a notification plugin to test configuration even if is not active`,
@@ -313,16 +320,16 @@ func NewNotificationsTestCmd() *cobra.Command {
 			return nil
 		},
 	}
-	cmdNotificationsTest.Flags().StringVarP(&alertOverride, "alert", "a", "", "JSON string used to override alert fields in the generic alert (see crowdsec/pkg/models/alert.go in the source tree for the full definition of the object)")
+	cmd.Flags().StringVarP(&alertOverride, "alert", "a", "", "JSON string used to override alert fields in the generic alert (see crowdsec/pkg/models/alert.go in the source tree for the full definition of the object)")
 
-	return cmdNotificationsTest
+	return cmd
 }
 
-func NewNotificationsReinjectCmd() *cobra.Command {
+func (cli cliNotifications) NewReinjectCmd() *cobra.Command {
 	var alertOverride string
 	var alert *models.Alert
 
-	var cmdNotificationsReinject = &cobra.Command{
+	cmd := &cobra.Command{
 		Use:   "reinject",
 		Short: "reinject an alert into profiles to trigger notifications",
 		Long:  `reinject an alert into profiles to be evaluated by the filter and sent to matched notifications plugins`,
@@ -401,9 +408,9 @@ cscli notifications reinject <alert_id> -a '{"remediation": true,"scenario":"not
 			return nil
 		},
 	}
-	cmdNotificationsReinject.Flags().StringVarP(&alertOverride, "alert", "a", "", "JSON string used to override alert fields in the reinjected alert (see crowdsec/pkg/models/alert.go in the source tree for the full definition of the object)")
+	cmd.Flags().StringVarP(&alertOverride, "alert", "a", "", "JSON string used to override alert fields in the reinjected alert (see crowdsec/pkg/models/alert.go in the source tree for the full definition of the object)")
 
-	return cmdNotificationsReinject
+	return cmd
 }
 
 func FetchAlertFromArgString(toParse string) (*models.Alert, error) {

+ 17 - 11
cmd/crowdsec-cli/papi.go

@@ -15,8 +15,14 @@ import (
 	"github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require"
 )
 
-func NewPapiCmd() *cobra.Command {
-	var cmdLapi = &cobra.Command{
+type cliPapi struct {}
+
+func NewCLIPapi() *cliPapi {
+	return &cliPapi{}
+}
+
+func (cli cliPapi) NewCommand() *cobra.Command {
+	var cmd = &cobra.Command{
 		Use:               "papi [action]",
 		Short:             "Manage interaction with Polling API (PAPI)",
 		Args:              cobra.MinimumNArgs(1),
@@ -35,14 +41,14 @@ func NewPapiCmd() *cobra.Command {
 		},
 	}
 
-	cmdLapi.AddCommand(NewPapiStatusCmd())
-	cmdLapi.AddCommand(NewPapiSyncCmd())
+	cmd.AddCommand(cli.NewStatusCmd())
+	cmd.AddCommand(cli.NewSyncCmd())
 
-	return cmdLapi
+	return cmd
 }
 
-func NewPapiStatusCmd() *cobra.Command {
-	cmdCapiStatus := &cobra.Command{
+func (cli cliPapi) NewStatusCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:               "status",
 		Short:             "Get status of the Polling API",
 		Args:              cobra.MinimumNArgs(0),
@@ -87,11 +93,11 @@ func NewPapiStatusCmd() *cobra.Command {
 		},
 	}
 
-	return cmdCapiStatus
+	return cmd
 }
 
-func NewPapiSyncCmd() *cobra.Command {
-	cmdCapiSync := &cobra.Command{
+func (cli cliPapi) NewSyncCmd() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:               "sync",
 		Short:             "Sync with the Polling API, pulling all non-expired orders for the instance",
 		Args:              cobra.MinimumNArgs(0),
@@ -135,5 +141,5 @@ func NewPapiSyncCmd() *cobra.Command {
 		},
 	}
 
-	return cmdCapiSync
+	return cmd
 }

+ 18 - 6
cmd/crowdsec-cli/support.go

@@ -237,8 +237,14 @@ func collectAcquisitionConfig() map[string][]byte {
 	return ret
 }
 
-func NewSupportCmd() *cobra.Command {
-	var cmdSupport = &cobra.Command{
+type cliSupport struct {}
+
+func NewCLISupport() *cliSupport {
+	return &cliSupport{}
+}
+
+func (cli cliSupport) NewCommand() *cobra.Command {
+	cmd := &cobra.Command{
 		Use:               "support [action]",
 		Short:             "Provide commands to help during support",
 		Args:              cobra.MinimumNArgs(1),
@@ -248,9 +254,15 @@ func NewSupportCmd() *cobra.Command {
 		},
 	}
 
+	cmd.AddCommand(cli.NewDumpCmd())
+
+	return cmd
+}
+
+func (cli cliSupport) NewDumpCmd() *cobra.Command {
 	var outFile string
 
-	cmdDump := &cobra.Command{
+	cmd := &cobra.Command{
 		Use:   "dump",
 		Short: "Dump all your configuration to a zip file for easier support",
 		Long: `Dump the following informations:
@@ -415,8 +427,8 @@ cscli support dump -f /tmp/crowdsec-support.zip
 			log.Infof("Written zip file to %s", outFile)
 		},
 	}
-	cmdDump.Flags().StringVarP(&outFile, "outFile", "f", "", "File to dump the information to")
-	cmdSupport.AddCommand(cmdDump)
 
-	return cmdSupport
+	cmd.Flags().StringVarP(&outFile, "outFile", "f", "", "File to dump the information to")
+
+	return cmd
 }