refact "cscli dashboard" (#2803)

This commit is contained in:
mmetc 2024-02-01 17:27:15 +01:00 committed by GitHub
parent 45c669fb65
commit f5fbe4a200
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 65 additions and 51 deletions

View file

@ -43,14 +43,17 @@ var (
// information needed to set up a random password on user's behalf // information needed to set up a random password on user's behalf
) )
type cliDashboard struct{} type cliDashboard struct{
cfg configGetter
func NewCLIDashboard() *cliDashboard {
return &cliDashboard{}
} }
func (cli cliDashboard) NewCommand() *cobra.Command { func NewCLIDashboard(getconfig configGetter) *cliDashboard {
/* ---- UPDATE COMMAND */ return &cliDashboard{
cfg: getconfig,
}
}
func (cli *cliDashboard) NewCommand() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "dashboard [command]", Use: "dashboard [command]",
Short: "Manage your metabase dashboard container [requires local API]", Short: "Manage your metabase dashboard container [requires local API]",
@ -65,8 +68,9 @@ cscli dashboard start
cscli dashboard stop cscli dashboard stop
cscli dashboard remove cscli dashboard remove
`, `,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error { PersistentPreRunE: func(_ *cobra.Command, _ []string) error {
if err := require.LAPI(csConfig); err != nil { cfg := cli.cfg()
if err := require.LAPI(cfg); err != nil {
return err return err
} }
@ -74,13 +78,13 @@ cscli dashboard remove
return err return err
} }
metabaseConfigFolderPath := filepath.Join(csConfig.ConfigPaths.ConfigDir, metabaseConfigFolder) metabaseConfigFolderPath := filepath.Join(cfg.ConfigPaths.ConfigDir, metabaseConfigFolder)
metabaseConfigPath = filepath.Join(metabaseConfigFolderPath, metabaseConfigFile) metabaseConfigPath = filepath.Join(metabaseConfigFolderPath, metabaseConfigFile)
if err := os.MkdirAll(metabaseConfigFolderPath, os.ModePerm); err != nil { if err := os.MkdirAll(metabaseConfigFolderPath, os.ModePerm); err != nil {
return err return err
} }
if err := require.DB(csConfig); err != nil { if err := require.DB(cfg); err != nil {
return err return err
} }
@ -99,16 +103,16 @@ cscli dashboard remove
}, },
} }
cmd.AddCommand(cli.NewSetupCmd()) cmd.AddCommand(cli.newSetupCmd())
cmd.AddCommand(cli.NewStartCmd()) cmd.AddCommand(cli.newStartCmd())
cmd.AddCommand(cli.NewStopCmd()) cmd.AddCommand(cli.newStopCmd())
cmd.AddCommand(cli.NewShowPasswordCmd()) cmd.AddCommand(cli.newShowPasswordCmd())
cmd.AddCommand(cli.NewRemoveCmd()) cmd.AddCommand(cli.newRemoveCmd())
return cmd return cmd
} }
func (cli cliDashboard) NewSetupCmd() *cobra.Command { func (cli *cliDashboard) newSetupCmd() *cobra.Command {
var force bool var force bool
cmd := &cobra.Command{ cmd := &cobra.Command{
@ -122,9 +126,9 @@ cscli dashboard setup
cscli dashboard setup --listen 0.0.0.0 cscli dashboard setup --listen 0.0.0.0
cscli dashboard setup -l 0.0.0.0 -p 443 --password <password> cscli dashboard setup -l 0.0.0.0 -p 443 --password <password>
`, `,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, _ []string) error {
if metabaseDbPath == "" { if metabaseDbPath == "" {
metabaseDbPath = csConfig.ConfigPaths.DataDir metabaseDbPath = cli.cfg().ConfigPaths.DataDir
} }
if metabasePassword == "" { if metabasePassword == "" {
@ -145,10 +149,10 @@ cscli dashboard setup -l 0.0.0.0 -p 443 --password <password>
if err != nil { if err != nil {
return err return err
} }
if err = chownDatabase(dockerGroup.Gid); err != nil { if err = cli.chownDatabase(dockerGroup.Gid); err != nil {
return err return err
} }
mb, err := metabase.SetupMetabase(csConfig.API.Server.DbConfig, metabaseListenAddress, metabaseListenPort, metabaseUser, metabasePassword, metabaseDbPath, dockerGroup.Gid, metabaseContainerID, metabaseImage) mb, err := metabase.SetupMetabase(cli.cfg().API.Server.DbConfig, metabaseListenAddress, metabaseListenPort, metabaseUser, metabasePassword, metabaseDbPath, dockerGroup.Gid, metabaseContainerID, metabaseImage)
if err != nil { if err != nil {
return err return err
} }
@ -164,26 +168,28 @@ cscli dashboard setup -l 0.0.0.0 -p 443 --password <password>
return nil return nil
}, },
} }
cmd.Flags().BoolVarP(&force, "force", "f", false, "Force setup : override existing files")
cmd.Flags().StringVarP(&metabaseDbPath, "dir", "d", "", "Shared directory with metabase container") flags := cmd.Flags()
cmd.Flags().StringVarP(&metabaseListenAddress, "listen", "l", metabaseListenAddress, "Listen address of container") flags.BoolVarP(&force, "force", "f", false, "Force setup : override existing files")
cmd.Flags().StringVar(&metabaseImage, "metabase-image", metabaseImage, "Metabase image to use") flags.StringVarP(&metabaseDbPath, "dir", "d", "", "Shared directory with metabase container")
cmd.Flags().StringVarP(&metabaseListenPort, "port", "p", metabaseListenPort, "Listen port of container") flags.StringVarP(&metabaseListenAddress, "listen", "l", metabaseListenAddress, "Listen address of container")
cmd.Flags().BoolVarP(&forceYes, "yes", "y", false, "force yes") flags.StringVar(&metabaseImage, "metabase-image", metabaseImage, "Metabase image to use")
//cmd.Flags().StringVarP(&metabaseUser, "user", "u", "crowdsec@crowdsec.net", "metabase user") flags.StringVarP(&metabaseListenPort, "port", "p", metabaseListenPort, "Listen port of container")
cmd.Flags().StringVar(&metabasePassword, "password", "", "metabase password") flags.BoolVarP(&forceYes, "yes", "y", false, "force yes")
//flags.StringVarP(&metabaseUser, "user", "u", "crowdsec@crowdsec.net", "metabase user")
flags.StringVar(&metabasePassword, "password", "", "metabase password")
return cmd return cmd
} }
func (cli cliDashboard) NewStartCmd() *cobra.Command { func (cli *cliDashboard) newStartCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "start", Use: "start",
Short: "Start the metabase container.", Short: "Start the metabase container.",
Long: `Stats the metabase container using docker.`, Long: `Stats the metabase container using docker.`,
Args: cobra.ExactArgs(0), Args: cobra.ExactArgs(0),
DisableAutoGenTag: true, DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, _ []string) error {
mb, err := metabase.NewMetabase(metabaseConfigPath, metabaseContainerID) mb, err := metabase.NewMetabase(metabaseConfigPath, metabaseContainerID)
if err != nil { if err != nil {
return err return err
@ -200,19 +206,20 @@ func (cli cliDashboard) NewStartCmd() *cobra.Command {
return nil return nil
}, },
} }
cmd.Flags().BoolVarP(&forceYes, "yes", "y", false, "force yes") cmd.Flags().BoolVarP(&forceYes, "yes", "y", false, "force yes")
return cmd return cmd
} }
func (cli cliDashboard) NewStopCmd() *cobra.Command { func (cli *cliDashboard) newStopCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "stop", Use: "stop",
Short: "Stops the metabase container.", Short: "Stops the metabase container.",
Long: `Stops the metabase container using docker.`, Long: `Stops the metabase container using docker.`,
Args: cobra.ExactArgs(0), Args: cobra.ExactArgs(0),
DisableAutoGenTag: true, DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, _ []string) error {
if err := metabase.StopContainer(metabaseContainerID); err != nil { if err := metabase.StopContainer(metabaseContainerID); err != nil {
return fmt.Errorf("unable to stop container '%s': %s", metabaseContainerID, err) return fmt.Errorf("unable to stop container '%s': %s", metabaseContainerID, err)
} }
@ -223,12 +230,12 @@ func (cli cliDashboard) NewStopCmd() *cobra.Command {
return cmd return cmd
} }
func (cli cliDashboard) NewShowPasswordCmd() *cobra.Command { func (cli *cliDashboard) newShowPasswordCmd() *cobra.Command {
cmd := &cobra.Command{Use: "show-password", cmd := &cobra.Command{Use: "show-password",
Short: "displays password of metabase.", Short: "displays password of metabase.",
Args: cobra.ExactArgs(0), Args: cobra.ExactArgs(0),
DisableAutoGenTag: true, DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, _ []string) error {
m := metabase.Metabase{} m := metabase.Metabase{}
if err := m.LoadConfig(metabaseConfigPath); err != nil { if err := m.LoadConfig(metabaseConfigPath); err != nil {
return err return err
@ -241,7 +248,7 @@ func (cli cliDashboard) NewShowPasswordCmd() *cobra.Command {
return cmd return cmd
} }
func (cli cliDashboard) NewRemoveCmd() *cobra.Command { func (cli *cliDashboard) newRemoveCmd() *cobra.Command {
var force bool var force bool
cmd := &cobra.Command{ cmd := &cobra.Command{
@ -254,7 +261,7 @@ func (cli cliDashboard) NewRemoveCmd() *cobra.Command {
cscli dashboard remove cscli dashboard remove
cscli dashboard remove --force cscli dashboard remove --force
`, `,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(_ *cobra.Command, _ []string) error {
if !forceYes { if !forceYes {
var answer bool var answer bool
prompt := &survey.Confirm{ prompt := &survey.Confirm{
@ -291,8 +298,8 @@ cscli dashboard remove --force
} }
log.Infof("container %s stopped & removed", metabaseContainerID) log.Infof("container %s stopped & removed", metabaseContainerID)
} }
log.Debugf("Removing metabase db %s", csConfig.ConfigPaths.DataDir) log.Debugf("Removing metabase db %s", cli.cfg().ConfigPaths.DataDir)
if err := metabase.RemoveDatabase(csConfig.ConfigPaths.DataDir); err != nil { if err := metabase.RemoveDatabase(cli.cfg().ConfigPaths.DataDir); err != nil {
log.Warnf("failed to remove metabase internal db : %s", err) log.Warnf("failed to remove metabase internal db : %s", err)
} }
if force { if force {
@ -309,8 +316,10 @@ cscli dashboard remove --force
return nil return nil
}, },
} }
cmd.Flags().BoolVarP(&force, "force", "f", false, "Remove also the metabase image")
cmd.Flags().BoolVarP(&forceYes, "yes", "y", false, "force yes") flags := cmd.Flags()
flags.BoolVarP(&force, "force", "f", false, "Remove also the metabase image")
flags.BoolVarP(&forceYes, "yes", "y", false, "force yes")
return cmd return cmd
} }
@ -431,22 +440,23 @@ func checkGroups(forceYes *bool) (*user.Group, error) {
return user.LookupGroup(crowdsecGroup) return user.LookupGroup(crowdsecGroup)
} }
func chownDatabase(gid string) error { func (cli *cliDashboard) chownDatabase(gid string) error {
cfg := cli.cfg()
intID, err := strconv.Atoi(gid) intID, err := strconv.Atoi(gid)
if err != nil { if err != nil {
return fmt.Errorf("unable to convert group ID to int: %s", err) return fmt.Errorf("unable to convert group ID to int: %s", err)
} }
if stat, err := os.Stat(csConfig.DbConfig.DbPath); !os.IsNotExist(err) { if stat, err := os.Stat(cfg.DbConfig.DbPath); !os.IsNotExist(err) {
info := stat.Sys() info := stat.Sys()
if err := os.Chown(csConfig.DbConfig.DbPath, int(info.(*syscall.Stat_t).Uid), intID); err != nil { if err := os.Chown(cfg.DbConfig.DbPath, int(info.(*syscall.Stat_t).Uid), intID); err != nil {
return fmt.Errorf("unable to chown sqlite db file '%s': %s", csConfig.DbConfig.DbPath, err) return fmt.Errorf("unable to chown sqlite db file '%s': %s", cfg.DbConfig.DbPath, err)
} }
} }
if csConfig.DbConfig.Type == "sqlite" && csConfig.DbConfig.UseWal != nil && *csConfig.DbConfig.UseWal { if cfg.DbConfig.Type == "sqlite" && cfg.DbConfig.UseWal != nil && *cfg.DbConfig.UseWal {
for _, ext := range []string{"-wal", "-shm"} { for _, ext := range []string{"-wal", "-shm"} {
file := csConfig.DbConfig.DbPath + ext file := cfg.DbConfig.DbPath + ext
if stat, err := os.Stat(file); !os.IsNotExist(err) { if stat, err := os.Stat(file); !os.IsNotExist(err) {
info := stat.Sys() info := stat.Sys()
if err := os.Chown(file, int(info.(*syscall.Stat_t).Uid), intID); err != nil { if err := os.Chown(file, int(info.(*syscall.Stat_t).Uid), intID); err != nil {

View file

@ -9,17 +9,21 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
type cliDashboard struct{} type cliDashboard struct{
cfg configGetter
}
func NewCLIDashboard() *cliDashboard { func NewCLIDashboard(getconfig configGetter) *cliDashboard {
return &cliDashboard{} return &cliDashboard{
cfg: getconfig,
}
} }
func (cli cliDashboard) NewCommand() *cobra.Command { func (cli cliDashboard) NewCommand() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "dashboard", Use: "dashboard",
DisableAutoGenTag: true, DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) { Run: func(_ *cobra.Command, _ []string) {
log.Infof("Dashboard command is disabled on %s", runtime.GOOS) log.Infof("Dashboard command is disabled on %s", runtime.GOOS)
}, },
} }

View file

@ -196,7 +196,7 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall
cmd.AddCommand(NewConfigCmd()) cmd.AddCommand(NewConfigCmd())
cmd.AddCommand(NewCLIHub(getconfig).NewCommand()) cmd.AddCommand(NewCLIHub(getconfig).NewCommand())
cmd.AddCommand(NewMetricsCmd()) cmd.AddCommand(NewMetricsCmd())
cmd.AddCommand(NewCLIDashboard().NewCommand()) cmd.AddCommand(NewCLIDashboard(getconfig).NewCommand())
cmd.AddCommand(NewCLIDecisions().NewCommand()) cmd.AddCommand(NewCLIDecisions().NewCommand())
cmd.AddCommand(NewCLIAlerts().NewCommand()) cmd.AddCommand(NewCLIAlerts().NewCommand())
cmd.AddCommand(NewCLISimulation(getconfig).NewCommand()) cmd.AddCommand(NewCLISimulation(getconfig).NewCommand())