diff --git a/cmd/crowdsec-cli/collections.go b/cmd/crowdsec-cli/collections.go index 6806d39a7..f81cf4690 100644 --- a/cmd/crowdsec-cli/collections.go +++ b/cmd/crowdsec-cli/collections.go @@ -12,11 +12,15 @@ import ( ) func NewCollectionsCmd() *cobra.Command { - var cmdCollections = &cobra.Command{ + cmdCollections := &cobra.Command{ Use: "collections [action]", - Short: "Manage collections from hub", - Long: `Install/Remove/Upgrade/Inspect collections from the CrowdSec Hub.`, - /*TBD fix help*/ + Short: "Install/Remove/Upgrade/Inspect collections from the CrowdSec Hub.", + Example: `cscli collections install crowdsec/xxx crowdsec/xyz +cscli collections inspect crowdsec/xxx crowdsec/xyz +cscli collections upgrade crowdsec/xxx crowdsec/xyz +cscli collections list +cscli collections remove crowdsec/xxx crowdsec/xyz +`, Args: cobra.MinimumNArgs(1), Aliases: []string{"collection"}, DisableAutoGenTag: true, @@ -35,42 +39,130 @@ func NewCollectionsCmd() *cobra.Command { }, } - var ignoreError bool + cmdCollections.AddCommand(NewCollectionsInstallCmd()) + cmdCollections.AddCommand(NewCollectionsRemoveCmd()) + cmdCollections.AddCommand(NewCollectionsUpgradeCmd()) + cmdCollections.AddCommand(NewCollectionsInspectCmd()) + cmdCollections.AddCommand(NewCollectionsListCmd()) - var cmdCollectionsInstall = &cobra.Command{ - Use: "install collection", - Short: "Install given collection(s)", - Long: `Fetch and install given collection(s) from hub`, - Example: `cscli collections install crowdsec/xxx crowdsec/xyz`, - Args: cobra.MinimumNArgs(1), + return cmdCollections +} + +func runCollectionsInstall(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + downloadOnly, err := flags.GetBool("download-only") + if err != nil { + return err + } + + force, err := flags.GetBool("force") + if err != nil { + return err + } + + ignoreError, err := flags.GetBool("ignore") + if err != nil { + return err + } + + for _, name := range args { + t := cwhub.GetItem(cwhub.COLLECTIONS, name) + if t == nil { + nearestItem, score := GetDistance(cwhub.COLLECTIONS, name) + Suggest(cwhub.COLLECTIONS, name, nearestItem.Name, score, ignoreError) + + continue + } + + if err := cwhub.InstallItem(csConfig, name, cwhub.COLLECTIONS, force, downloadOnly); err != nil { + if !ignoreError { + return fmt.Errorf("error while installing '%s': %w", name, err) + } + log.Errorf("Error while installing '%s': %s", name, err) + } + } + + return nil +} + +func NewCollectionsInstallCmd() *cobra.Command { + cmdCollectionsInstall := &cobra.Command{ + Use: "install collection", + Short: "Install given collection(s)", + Long: `Fetch and install given collection(s) from hub`, + Example: `cscli collections install crowdsec/xxx crowdsec/xyz`, + Args: cobra.MinimumNArgs(1), + DisableAutoGenTag: true, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return compAllItems(cwhub.COLLECTIONS, args, toComplete) }, - DisableAutoGenTag: true, - RunE: func(cmd *cobra.Command, args []string) error { - for _, name := range args { - t := cwhub.GetItem(cwhub.COLLECTIONS, name) - if t == nil { - nearestItem, score := GetDistance(cwhub.COLLECTIONS, name) - Suggest(cwhub.COLLECTIONS, name, nearestItem.Name, score, ignoreError) - continue - } - if err := cwhub.InstallItem(csConfig, name, cwhub.COLLECTIONS, forceAction, downloadOnly); err != nil { - if !ignoreError { - return fmt.Errorf("error while installing '%s': %w", name, err) - } - log.Errorf("Error while installing '%s': %s", name, err) - } - } - return nil - }, + RunE: runCollectionsInstall, } - cmdCollectionsInstall.PersistentFlags().BoolVarP(&downloadOnly, "download-only", "d", false, "Only download packages, don't enable") - cmdCollectionsInstall.PersistentFlags().BoolVar(&forceAction, "force", false, "Force install : Overwrite tainted and outdated files") - cmdCollectionsInstall.PersistentFlags().BoolVar(&ignoreError, "ignore", false, "Ignore errors when installing multiple collections") - cmdCollections.AddCommand(cmdCollectionsInstall) - var cmdCollectionsRemove = &cobra.Command{ + flags := cmdCollectionsInstall.Flags() + flags.BoolP("download-only", "d", false, "Only download packages, don't enable") + flags.Bool("force", false, "Force install : Overwrite tainted and outdated files") + flags.Bool("ignore", false, "Ignore errors when installing multiple collections") + + return cmdCollectionsInstall +} + +func runCollectionsRemove(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + purge, err := flags.GetBool("purge") + if err != nil { + return err + } + + force, err := flags.GetBool("force") + if err != nil { + return err + } + + all, err := flags.GetBool("all") + if err != nil { + return err + } + + if all { + err := cwhub.RemoveMany(csConfig, cwhub.COLLECTIONS, "", all, purge, force) + if err != nil { + return err + } + + return nil + } + + if len(args) == 0 { + return fmt.Errorf("specify at least one collection to remove or '--all'") + } + + for _, name := range args { + if !force { + item := cwhub.GetItem(cwhub.COLLECTIONS, name) + if item == nil { + return fmt.Errorf("unable to retrieve: %s", name) + } + if len(item.BelongsToCollections) > 0 { + log.Warningf("%s belongs to other collections :\n%s\n", name, item.BelongsToCollections) + log.Printf("Run 'sudo cscli collections remove %s --force' if you want to force remove this sub collection\n", name) + continue + } + } + + err := cwhub.RemoveMany(csConfig, cwhub.COLLECTIONS, name, all, purge, force) + if err != nil { + return err + } + } + + return nil +} + +func NewCollectionsRemoveCmd() *cobra.Command { + cmdCollectionsRemove := &cobra.Command{ Use: "remove collection", Short: "Remove given collection(s)", Long: `Remove given collection(s) from hub`, @@ -80,39 +172,48 @@ func NewCollectionsCmd() *cobra.Command { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return compInstalledItems(cwhub.COLLECTIONS, args, toComplete) }, - RunE: func(cmd *cobra.Command, args []string) error { - if all { - cwhub.RemoveMany(csConfig, cwhub.COLLECTIONS, "", all, purge, forceAction) - return nil - } - - if len(args) == 0 { - return fmt.Errorf("specify at least one collection to remove or '--all'") - } - - for _, name := range args { - if !forceAction { - item := cwhub.GetItem(cwhub.COLLECTIONS, name) - if item == nil { - return fmt.Errorf("unable to retrieve: %s", name) - } - if len(item.BelongsToCollections) > 0 { - log.Warningf("%s belongs to other collections :\n%s\n", name, item.BelongsToCollections) - log.Printf("Run 'sudo cscli collections remove %s --force' if you want to force remove this sub collection\n", name) - continue - } - } - cwhub.RemoveMany(csConfig, cwhub.COLLECTIONS, name, all, purge, forceAction) - } - return nil - }, + RunE: runCollectionsRemove, } - cmdCollectionsRemove.PersistentFlags().BoolVar(&purge, "purge", false, "Delete source file too") - cmdCollectionsRemove.PersistentFlags().BoolVar(&forceAction, "force", false, "Force remove : Remove tainted and outdated files") - cmdCollectionsRemove.PersistentFlags().BoolVar(&all, "all", false, "Delete all the collections") - cmdCollections.AddCommand(cmdCollectionsRemove) - var cmdCollectionsUpgrade = &cobra.Command{ + flags := cmdCollectionsRemove.Flags() + flags.Bool("purge", false, "Delete source file too") + flags.Bool("force", false, "Force remove : Remove tainted and outdated files") + flags.Bool("all", false, "Delete all the collections") + + return cmdCollectionsRemove +} + +func runCollectionsUpgrade(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + force, err := flags.GetBool("force") + if err != nil { + return err + } + + all, err := flags.GetBool("all") + if err != nil { + return err + } + + if all { + cwhub.UpgradeConfig(csConfig, cwhub.COLLECTIONS, "", force) + return nil + } + + if len(args) == 0 { + return fmt.Errorf("specify at least one collection to upgrade or '--all'") + } + + for _, name := range args { + cwhub.UpgradeConfig(csConfig, cwhub.COLLECTIONS, name, force) + } + + return nil +} + +func NewCollectionsUpgradeCmd() *cobra.Command { + cmdCollectionsUpgrade := &cobra.Command{ Use: "upgrade collection", Short: "Upgrade given collection(s)", Long: `Fetch and upgrade given collection(s) from hub`, @@ -121,25 +222,35 @@ func NewCollectionsCmd() *cobra.Command { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return compInstalledItems(cwhub.COLLECTIONS, args, toComplete) }, - RunE: func(cmd *cobra.Command, args []string) error { - if all { - cwhub.UpgradeConfig(csConfig, cwhub.COLLECTIONS, "", forceAction) - } else { - if len(args) == 0 { - return fmt.Errorf("specify at least one collection to upgrade or '--all'") - } - for _, name := range args { - cwhub.UpgradeConfig(csConfig, cwhub.COLLECTIONS, name, forceAction) - } - } - return nil - }, + RunE: runCollectionsUpgrade, } - cmdCollectionsUpgrade.PersistentFlags().BoolVarP(&all, "all", "a", false, "Upgrade all the collections") - cmdCollectionsUpgrade.PersistentFlags().BoolVar(&forceAction, "force", false, "Force upgrade : Overwrite tainted and outdated files") - cmdCollections.AddCommand(cmdCollectionsUpgrade) - var cmdCollectionsInspect = &cobra.Command{ + flags := cmdCollectionsUpgrade.Flags() + flags.BoolP("all", "a", false, "Upgrade all the collections") + flags.Bool("force", false, "Force upgrade : Overwrite tainted and outdated files") + + return cmdCollectionsUpgrade +} + +func runCollectionsInspect(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + var err error + // XXX: set global + prometheusURL, err = flags.GetString("url") + if err != nil { + return err + } + + for _, name := range args { + InspectItem(name, cwhub.COLLECTIONS) + } + + return nil +} + +func NewCollectionsInspectCmd() *cobra.Command { + cmdCollectionsInspect := &cobra.Command{ Use: "inspect collection", Short: "Inspect given collection", Long: `Inspect given collection`, @@ -149,28 +260,42 @@ func NewCollectionsCmd() *cobra.Command { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return compInstalledItems(cwhub.COLLECTIONS, args, toComplete) }, - Run: func(cmd *cobra.Command, args []string) { - for _, name := range args { - InspectItem(name, cwhub.COLLECTIONS) - } - }, + RunE: runCollectionsInspect, } - cmdCollectionsInspect.PersistentFlags().StringVarP(&prometheusURL, "url", "u", "", "Prometheus url") - cmdCollections.AddCommand(cmdCollectionsInspect) - var cmdCollectionsList = &cobra.Command{ + flags := cmdCollectionsInspect.Flags() + flags.StringP("url", "u", "", "Prometheus url") + + return cmdCollectionsInspect +} + +func runCollectionsList(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + all, err := flags.GetBool("all") + if err != nil { + return err + } + + // XXX: will happily ignore missing collections + ListItems(color.Output, []string{cwhub.COLLECTIONS}, args, false, true, all) + + return nil +} + +func NewCollectionsListCmd() *cobra.Command { + cmdCollectionsList := &cobra.Command{ Use: "list collection [-a]", Short: "List all collections", Long: `List all collections`, Example: `cscli collections list`, Args: cobra.ExactArgs(0), DisableAutoGenTag: true, - Run: func(cmd *cobra.Command, args []string) { - ListItems(color.Output, []string{cwhub.COLLECTIONS}, args, false, true, all) - }, + RunE: runCollectionsList, } - cmdCollectionsList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List disabled items as well") - cmdCollections.AddCommand(cmdCollectionsList) - return cmdCollections + flags := cmdCollectionsList.Flags() + flags.BoolP("all", "a", false, "List disabled items as well") + + return cmdCollectionsList } diff --git a/cmd/crowdsec-cli/config_restore.go b/cmd/crowdsec-cli/config_restore.go index 395e943bc..a528372ef 100644 --- a/cmd/crowdsec-cli/config_restore.go +++ b/cmd/crowdsec-cli/config_restore.go @@ -27,10 +27,7 @@ func silentInstallItem(name string, obtype string) (string, error) { if item == nil { return "", fmt.Errorf("error retrieving item") } - if downloadOnly && item.Downloaded && item.UpToDate { - return fmt.Sprintf("%s is already downloaded and up-to-date", item.Name), nil - } - err := cwhub.DownloadLatest(csConfig.Hub, item, forceAction, false) + err := cwhub.DownloadLatest(csConfig.Hub, item, false, false) if err != nil { return "", fmt.Errorf("error while downloading %s : %v", item.Name, err) } @@ -38,9 +35,6 @@ func silentInstallItem(name string, obtype string) (string, error) { return "", err } - if downloadOnly { - return fmt.Sprintf("Downloaded %s to %s", item.Name, csConfig.Cscli.HubDir+"/"+item.RemotePath), nil - } err = cwhub.EnableItem(csConfig.Hub, item) if err != nil { return "", fmt.Errorf("error while enabling %s : %v", item.Name, err) diff --git a/cmd/crowdsec-cli/hub.go b/cmd/crowdsec-cli/hub.go index 7bdfd5162..c9ca62d67 100644 --- a/cmd/crowdsec-cli/hub.go +++ b/cmd/crowdsec-cli/hub.go @@ -45,35 +45,73 @@ cscli hub update # Download list of available configurations from the hub return cmdHub } +func runHubList(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + all, err := flags.GetBool("all") + if err != nil { + return err + } + + if err := require.Hub(csConfig); err != nil { + return err + } + + // use LocalSync to get warnings about tainted / outdated items + warn, _ := cwhub.LocalSync(csConfig.Hub) + for _, v := range warn { + log.Info(v) + } + + cwhub.DisplaySummary() + + ListItems(color.Output, []string{ + cwhub.COLLECTIONS, cwhub.PARSERS, cwhub.SCENARIOS, cwhub.PARSERS_OVFLW, + }, args, true, false, all) + + return nil +} + func NewHubListCmd() *cobra.Command { var cmdHubList = &cobra.Command{ Use: "list [-a]", Short: "List installed configs", Args: cobra.ExactArgs(0), DisableAutoGenTag: true, - RunE: func(cmd *cobra.Command, args []string) error { - if err := require.Hub(csConfig); err != nil { - return err - } - - // use LocalSync to get warnings about tainted / outdated items - warn, _ := cwhub.LocalSync(csConfig.Hub) - for _, v := range warn { - log.Info(v) - } - cwhub.DisplaySummary() - ListItems(color.Output, []string{ - cwhub.COLLECTIONS, cwhub.PARSERS, cwhub.SCENARIOS, cwhub.PARSERS_OVFLW, - }, args, true, false, all) - - return nil - }, + RunE: runHubList, } - cmdHubList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List disabled items as well") + + flags := cmdHubList.Flags() + flags.BoolP("all", "a", false, "List disabled items as well") return cmdHubList } +func runHubUpdate(cmd *cobra.Command, args []string) error { + if err := csConfig.LoadHub(); err != nil { + return err + } + + if err := cwhub.UpdateHubIdx(csConfig.Hub); err != nil { + if !errors.Is(err, cwhub.ErrIndexNotFound) { + return fmt.Errorf("failed to get Hub index : %w", err) + } + log.Warnf("Could not find index file for branch '%s', using 'master'", cwhub.HubBranch) + cwhub.HubBranch = "master" + if err := cwhub.UpdateHubIdx(csConfig.Hub); err != nil { + return fmt.Errorf("failed to get Hub index after retry: %w", err) + } + } + + // use LocalSync to get warnings about tainted / outdated items + warn, _ := cwhub.LocalSync(csConfig.Hub) + for _, v := range warn { + log.Info(v) + } + + return nil +} + func NewHubUpdateCmd() *cobra.Command { var cmdHubUpdate = &cobra.Command{ Use: "update", @@ -92,33 +130,36 @@ Fetches the [.index.json](https://github.com/crowdsecurity/hub/blob/master/.inde return nil }, - RunE: func(cmd *cobra.Command, args []string) error { - if err := csConfig.LoadHub(); err != nil { - return err - } - if err := cwhub.UpdateHubIdx(csConfig.Hub); err != nil { - if !errors.Is(err, cwhub.ErrIndexNotFound) { - return fmt.Errorf("failed to get Hub index : %w", err) - } - log.Warnf("Could not find index file for branch '%s', using 'master'", cwhub.HubBranch) - cwhub.HubBranch = "master" - if err := cwhub.UpdateHubIdx(csConfig.Hub); err != nil { - return fmt.Errorf("failed to get Hub index after retry: %w", err) - } - } - // use LocalSync to get warnings about tainted / outdated items - warn, _ := cwhub.LocalSync(csConfig.Hub) - for _, v := range warn { - log.Info(v) - } - - return nil - }, + RunE: runHubUpdate, } return cmdHubUpdate } +func runHubUpgrade(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + force, err := flags.GetBool("force") + if err != nil { + return err + } + + if err := require.Hub(csConfig); err != nil { + return err + } + + log.Infof("Upgrading collections") + cwhub.UpgradeConfig(csConfig, cwhub.COLLECTIONS, "", force) + log.Infof("Upgrading parsers") + cwhub.UpgradeConfig(csConfig, cwhub.PARSERS, "", force) + log.Infof("Upgrading scenarios") + cwhub.UpgradeConfig(csConfig, cwhub.SCENARIOS, "", force) + log.Infof("Upgrading postoverflows") + cwhub.UpgradeConfig(csConfig, cwhub.PARSERS_OVFLW, "", force) + + return nil +} + func NewHubUpgradeCmd() *cobra.Command { var cmdHubUpgrade = &cobra.Command{ Use: "upgrade", @@ -137,24 +178,11 @@ Upgrade all configs installed from Crowdsec Hub. Run 'sudo cscli hub update' if return nil }, - RunE: func(cmd *cobra.Command, args []string) error { - if err := require.Hub(csConfig); err != nil { - return err - } - - log.Infof("Upgrading collections") - cwhub.UpgradeConfig(csConfig, cwhub.COLLECTIONS, "", forceAction) - log.Infof("Upgrading parsers") - cwhub.UpgradeConfig(csConfig, cwhub.PARSERS, "", forceAction) - log.Infof("Upgrading scenarios") - cwhub.UpgradeConfig(csConfig, cwhub.SCENARIOS, "", forceAction) - log.Infof("Upgrading postoverflows") - cwhub.UpgradeConfig(csConfig, cwhub.PARSERS_OVFLW, "", forceAction) - - return nil - }, + RunE: runHubUpgrade, } - cmdHubUpgrade.PersistentFlags().BoolVar(&forceAction, "force", false, "Force upgrade : Overwrite tainted and outdated files") + + flags := cmdHubUpgrade.Flags() + flags.Bool("force", false, "Force upgrade : Overwrite tainted and outdated files") return cmdHubUpgrade } diff --git a/cmd/crowdsec-cli/main.go b/cmd/crowdsec-cli/main.go index e99fd53ab..d0320ac36 100644 --- a/cmd/crowdsec-cli/main.go +++ b/cmd/crowdsec-cli/main.go @@ -29,11 +29,6 @@ var dbClient *database.Client var OutputFormat string var OutputColor string -var downloadOnly bool -var forceAction bool -var purge bool -var all bool - var prometheusURL string var mergedConfig string diff --git a/cmd/crowdsec-cli/parsers.go b/cmd/crowdsec-cli/parsers.go index d97b070db..c1f33e804 100644 --- a/cmd/crowdsec-cli/parsers.go +++ b/cmd/crowdsec-cli/parsers.go @@ -12,7 +12,7 @@ import ( ) func NewParsersCmd() *cobra.Command { - var cmdParsers = &cobra.Command{ + cmdParsers := &cobra.Command{ Use: "parsers [action] [config]", Short: "Install/Remove/Upgrade/Inspect parser(s) from hub", Example: `cscli parsers install crowdsecurity/sshd-logs @@ -48,10 +48,46 @@ cscli parsers remove crowdsecurity/sshd-logs return cmdParsers } -func NewParsersInstallCmd() *cobra.Command { - var ignoreError bool +func runParsersInstall(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() - var cmdParsersInstall = &cobra.Command{ + downloadOnly, err := flags.GetBool("download-only") + if err != nil { + return err + } + + force, err := flags.GetBool("force") + if err != nil { + return err + } + + ignoreError, err := flags.GetBool("ignore") + if err != nil { + return err + } + + for _, name := range args { + t := cwhub.GetItem(cwhub.PARSERS, name) + if t == nil { + nearestItem, score := GetDistance(cwhub.PARSERS, name) + Suggest(cwhub.PARSERS, name, nearestItem.Name, score, ignoreError) + + continue + } + + if err := cwhub.InstallItem(csConfig, name, cwhub.PARSERS, force, downloadOnly); err != nil { + if !ignoreError { + return fmt.Errorf("error while installing '%s': %w", name, err) + } + log.Errorf("Error while installing '%s': %s", name, err) + } + } + + return nil +} + +func NewParsersInstallCmd() *cobra.Command { + cmdParsersInstall := &cobra.Command{ Use: "install [config]", Short: "Install given parser(s)", Long: `Fetch and install given parser(s) from hub`, @@ -61,32 +97,58 @@ func NewParsersInstallCmd() *cobra.Command { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return compAllItems(cwhub.PARSERS, args, toComplete) }, - RunE: func(cmd *cobra.Command, args []string) error { - for _, name := range args { - t := cwhub.GetItem(cwhub.PARSERS, name) - if t == nil { - nearestItem, score := GetDistance(cwhub.PARSERS, name) - Suggest(cwhub.PARSERS, name, nearestItem.Name, score, ignoreError) - continue - } - if err := cwhub.InstallItem(csConfig, name, cwhub.PARSERS, forceAction, downloadOnly); err != nil { - if !ignoreError { - return fmt.Errorf("error while installing '%s': %w", name, err) - } - log.Errorf("Error while installing '%s': %s", name, err) - } - } - return nil - }, + RunE: runParsersInstall, } - cmdParsersInstall.PersistentFlags().BoolVarP(&downloadOnly, "download-only", "d", false, "Only download packages, don't enable") - cmdParsersInstall.PersistentFlags().BoolVar(&forceAction, "force", false, "Force install : Overwrite tainted and outdated files") - cmdParsersInstall.PersistentFlags().BoolVar(&ignoreError, "ignore", false, "Ignore errors when installing multiple parsers") + flags := cmdParsersInstall.Flags() + flags.BoolP("download-only", "d", false, "Only download packages, don't enable") + flags.Bool("force", false, "Force install: Overwrite tainted and outdated files") + flags.Bool("ignore", false, "Ignore errors when installing multiple parsers") return cmdParsersInstall } +func runParsersRemove(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + purge, err := flags.GetBool("purge") + if err != nil { + return err + } + + force, err := flags.GetBool("force") + if err != nil { + return err + } + + all, err := flags.GetBool("all") + if err != nil { + return err + } + + if all { + err := cwhub.RemoveMany(csConfig, cwhub.PARSERS, "", all, purge, force) + if err != nil { + return err + } + + return nil + } + + if len(args) == 0 { + return fmt.Errorf("specify at least one parser to remove or '--all'") + } + + for _, name := range args { + err := cwhub.RemoveMany(csConfig, cwhub.PARSERS, name, all, purge, force) + if err != nil { + return err + } + } + + return nil +} + func NewParsersRemoveCmd() *cobra.Command { cmdParsersRemove := &cobra.Command{ Use: "remove [config]", @@ -98,31 +160,46 @@ func NewParsersRemoveCmd() *cobra.Command { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return compInstalledItems(cwhub.PARSERS, args, toComplete) }, - RunE: func(cmd *cobra.Command, args []string) error { - if all { - cwhub.RemoveMany(csConfig, cwhub.PARSERS, "", all, purge, forceAction) - return nil - } - - if len(args) == 0 { - return fmt.Errorf("specify at least one parser to remove or '--all'") - } - - for _, name := range args { - cwhub.RemoveMany(csConfig, cwhub.PARSERS, name, all, purge, forceAction) - } - - return nil - }, + RunE: runParsersRemove, } - cmdParsersRemove.PersistentFlags().BoolVar(&purge, "purge", false, "Delete source file too") - cmdParsersRemove.PersistentFlags().BoolVar(&forceAction, "force", false, "Force remove : Remove tainted and outdated files") - cmdParsersRemove.PersistentFlags().BoolVar(&all, "all", false, "Delete all the parsers") + flags := cmdParsersRemove.Flags() + flags.Bool("purge", false, "Delete source file too") + flags.Bool("force", false, "Force remove: Remove tainted and outdated files") + flags.Bool("all", false, "Delete all the parsers") return cmdParsersRemove } +func runParsersUpgrade(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + force, err := flags.GetBool("force") + if err != nil { + return err + } + + all, err := flags.GetBool("all") + if err != nil { + return err + } + + if all { + cwhub.UpgradeConfig(csConfig, cwhub.PARSERS, "", force) + return nil + } + + if len(args) == 0 { + return fmt.Errorf("specify at least one parser to upgrade or '--all'") + } + + for _, name := range args { + cwhub.UpgradeConfig(csConfig, cwhub.PARSERS, name, force) + } + + return nil +} + func NewParsersUpgradeCmd() *cobra.Command { cmdParsersUpgrade := &cobra.Command{ Use: "upgrade [config]", @@ -133,62 +210,78 @@ func NewParsersUpgradeCmd() *cobra.Command { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return compInstalledItems(cwhub.PARSERS, args, toComplete) }, - RunE: func(cmd *cobra.Command, args []string) error { - if all { - cwhub.UpgradeConfig(csConfig, cwhub.PARSERS, "", forceAction) - } else { - if len(args) == 0 { - return fmt.Errorf("specify at least one parser to upgrade or '--all'") - } - for _, name := range args { - cwhub.UpgradeConfig(csConfig, cwhub.PARSERS, name, forceAction) - } - } - return nil - }, + RunE: runParsersUpgrade, } - cmdParsersUpgrade.PersistentFlags().BoolVar(&all, "all", false, "Upgrade all the parsers") - cmdParsersUpgrade.PersistentFlags().BoolVar(&forceAction, "force", false, "Force upgrade : Overwrite tainted and outdated files") + flags := cmdParsersUpgrade.Flags() + flags.Bool("all", false, "Upgrade all the parsers") + flags.Bool("force", false, "Force upgrade : Overwrite tainted and outdated files") return cmdParsersUpgrade } +func runParsersInspect(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + var err error + // XXX: set global + prometheusURL, err = flags.GetString("url") + if err != nil { + return err + } + + InspectItem(args[0], cwhub.PARSERS) + + return nil +} + func NewParsersInspectCmd() *cobra.Command { - var cmdParsersInspect = &cobra.Command{ + cmdParsersInspect := &cobra.Command{ Use: "inspect [name]", Short: "Inspect given parser", Long: `Inspect given parser`, Example: `cscli parsers inspect crowdsec/xxx`, - DisableAutoGenTag: true, Args: cobra.MinimumNArgs(1), + DisableAutoGenTag: true, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return compInstalledItems(cwhub.PARSERS, args, toComplete) }, - Run: func(cmd *cobra.Command, args []string) { - InspectItem(args[0], cwhub.PARSERS) - }, + RunE: runParsersInspect, } - cmdParsersInspect.PersistentFlags().StringVarP(&prometheusURL, "url", "u", "", "Prometheus url") + flags := cmdParsersInspect.Flags() + flags.StringP("url", "u", "", "Prometheus url") return cmdParsersInspect } +func runParsersList(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + all, err := flags.GetBool("all") + if err != nil { + return err + } + + // XXX: will happily ignore missing parsers + ListItems(color.Output, []string{cwhub.PARSERS}, args, false, true, all) + + return nil +} + func NewParsersListCmd() *cobra.Command { - var cmdParsersList = &cobra.Command{ + cmdParsersList := &cobra.Command{ Use: "list [name]", Short: "List all parsers or given one", Long: `List all parsers or given one`, Example: `cscli parsers list cscli parser list crowdsecurity/xxx`, DisableAutoGenTag: true, - Run: func(cmd *cobra.Command, args []string) { - ListItems(color.Output, []string{cwhub.PARSERS}, args, false, true, all) - }, + RunE: runParsersList, } - cmdParsersList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List disabled items as well") + flags := cmdParsersList.Flags() + flags.BoolP("all", "a", false, "List disabled items as well") return cmdParsersList } diff --git a/cmd/crowdsec-cli/postoverflows.go b/cmd/crowdsec-cli/postoverflows.go index f4db0a79e..6c3aa6c80 100644 --- a/cmd/crowdsec-cli/postoverflows.go +++ b/cmd/crowdsec-cli/postoverflows.go @@ -16,10 +16,11 @@ func NewPostOverflowsCmd() *cobra.Command { Use: "postoverflows [action] [config]", Short: "Install/Remove/Upgrade/Inspect postoverflow(s) from hub", Example: `cscli postoverflows install crowdsecurity/cdn-whitelist - cscli postoverflows inspect crowdsecurity/cdn-whitelist - cscli postoverflows upgrade crowdsecurity/cdn-whitelist - cscli postoverflows list - cscli postoverflows remove crowdsecurity/cdn-whitelist`, +cscli postoverflows inspect crowdsecurity/cdn-whitelist +cscli postoverflows upgrade crowdsecurity/cdn-whitelist +cscli postoverflows list +cscli postoverflows remove crowdsecurity/cdn-whitelist +`, Args: cobra.MinimumNArgs(1), Aliases: []string{"postoverflow"}, DisableAutoGenTag: true, @@ -47,9 +48,45 @@ func NewPostOverflowsCmd() *cobra.Command { return cmdPostOverflows } -func NewPostOverflowsInstallCmd() *cobra.Command { - var ignoreError bool +func runPostOverflowsInstall(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + downloadOnly, err := flags.GetBool("download-only") + if err != nil { + return err + } + + force, err := flags.GetBool("force") + if err != nil { + return err + } + + ignoreError, err := flags.GetBool("ignore") + if err != nil { + return err + } + + for _, name := range args { + t := cwhub.GetItem(cwhub.PARSERS_OVFLW, name) + if t == nil { + nearestItem, score := GetDistance(cwhub.PARSERS_OVFLW, name) + Suggest(cwhub.PARSERS_OVFLW, name, nearestItem.Name, score, ignoreError) + + continue + } + + if err := cwhub.InstallItem(csConfig, name, cwhub.PARSERS_OVFLW, force, downloadOnly); err != nil { + if !ignoreError { + return fmt.Errorf("error while installing '%s': %w", name, err) + } + log.Errorf("Error while installing '%s': %s", name, err) + } + } + + return nil +} + +func NewPostOverflowsInstallCmd() *cobra.Command { cmdPostOverflowsInstall := &cobra.Command{ Use: "install [config]", Short: "Install given postoverflow(s)", @@ -60,32 +97,58 @@ func NewPostOverflowsInstallCmd() *cobra.Command { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return compAllItems(cwhub.PARSERS_OVFLW, args, toComplete) }, - RunE: func(cmd *cobra.Command, args []string) error { - for _, name := range args { - t := cwhub.GetItem(cwhub.PARSERS_OVFLW, name) - if t == nil { - nearestItem, score := GetDistance(cwhub.PARSERS_OVFLW, name) - Suggest(cwhub.PARSERS_OVFLW, name, nearestItem.Name, score, ignoreError) - continue - } - if err := cwhub.InstallItem(csConfig, name, cwhub.PARSERS_OVFLW, forceAction, downloadOnly); err != nil { - if !ignoreError { - return fmt.Errorf("error while installing '%s': %w", name, err) - } - log.Errorf("Error while installing '%s': %s", name, err) - } - } - return nil - }, + RunE: runPostOverflowsInstall, } - cmdPostOverflowsInstall.PersistentFlags().BoolVarP(&downloadOnly, "download-only", "d", false, "Only download packages, don't enable") - cmdPostOverflowsInstall.PersistentFlags().BoolVar(&forceAction, "force", false, "Force install : Overwrite tainted and outdated files") - cmdPostOverflowsInstall.PersistentFlags().BoolVar(&ignoreError, "ignore", false, "Ignore errors when installing multiple postoverflows") + flags := cmdPostOverflowsInstall.Flags() + flags.BoolP("download-only", "d", false, "Only download packages, don't enable") + flags.Bool("force", false, "Force install : Overwrite tainted and outdated files") + flags.Bool("ignore", false, "Ignore errors when installing multiple postoverflows") return cmdPostOverflowsInstall } +func runPostOverflowsRemove(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + purge, err := flags.GetBool("purge") + if err != nil { + return err + } + + force, err := flags.GetBool("force") + if err != nil { + return err + } + + all, err := flags.GetBool("all") + if err != nil { + return err + } + + if all { + err := cwhub.RemoveMany(csConfig, cwhub.PARSERS_OVFLW, "", all, purge, force) + if err != nil { + return err + } + + return nil + } + + if len(args) == 0 { + return fmt.Errorf("specify at least one postoverflow to remove or '--all'") + } + + for _, name := range args { + err := cwhub.RemoveMany(csConfig, cwhub.PARSERS_OVFLW, name, all, purge, force) + if err != nil { + return err + } + } + + return nil +} + func NewPostOverflowsRemoveCmd() *cobra.Command { cmdPostOverflowsRemove := &cobra.Command{ Use: "remove [config]", @@ -97,31 +160,46 @@ func NewPostOverflowsRemoveCmd() *cobra.Command { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return compInstalledItems(cwhub.PARSERS_OVFLW, args, toComplete) }, - RunE: func(cmd *cobra.Command, args []string) error { - if all { - cwhub.RemoveMany(csConfig, cwhub.PARSERS_OVFLW, "", all, purge, forceAction) - return nil - } - - if len(args) == 0 { - return fmt.Errorf("specify at least one postoverflow to remove or '--all'") - } - - for _, name := range args { - cwhub.RemoveMany(csConfig, cwhub.PARSERS_OVFLW, name, all, purge, forceAction) - } - - return nil - }, + RunE: runPostOverflowsRemove, } - cmdPostOverflowsRemove.PersistentFlags().BoolVar(&purge, "purge", false, "Delete source file too") - cmdPostOverflowsRemove.PersistentFlags().BoolVar(&forceAction, "force", false, "Force remove : Remove tainted and outdated files") - cmdPostOverflowsRemove.PersistentFlags().BoolVar(&all, "all", false, "Delete all the postoverflows") + flags := cmdPostOverflowsRemove.Flags() + flags.Bool("purge", false, "Delete source file too") + flags.Bool("force", false, "Force remove : Remove tainted and outdated files") + flags.Bool("all", false, "Delete all the postoverflows") return cmdPostOverflowsRemove } +func runPostOverflowUpgrade(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + force, err := flags.GetBool("force") + if err != nil { + return err + } + + all, err := flags.GetBool("all") + if err != nil { + return err + } + + if all { + cwhub.UpgradeConfig(csConfig, cwhub.PARSERS_OVFLW, "", force) + return nil + } + + if len(args) == 0 { + return fmt.Errorf("specify at least one postoverflow to upgrade or '--all'") + } + + for _, name := range args { + cwhub.UpgradeConfig(csConfig, cwhub.PARSERS_OVFLW, name, force) + } + + return nil +} + func NewPostOverflowsUpgradeCmd() *cobra.Command { cmdPostOverflowsUpgrade := &cobra.Command{ Use: "upgrade [config]", @@ -132,46 +210,66 @@ func NewPostOverflowsUpgradeCmd() *cobra.Command { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return compInstalledItems(cwhub.PARSERS_OVFLW, args, toComplete) }, - RunE: func(cmd *cobra.Command, args []string) error { - if all { - cwhub.UpgradeConfig(csConfig, cwhub.PARSERS_OVFLW, "", forceAction) - } else { - if len(args) == 0 { - return fmt.Errorf("specify at least one postoverflow to upgrade or '--all'") - } - for _, name := range args { - cwhub.UpgradeConfig(csConfig, cwhub.PARSERS_OVFLW, name, forceAction) - } - } - return nil - }, + RunE: runPostOverflowUpgrade, } - cmdPostOverflowsUpgrade.PersistentFlags().BoolVarP(&all, "all", "a", false, "Upgrade all the postoverflows") - cmdPostOverflowsUpgrade.PersistentFlags().BoolVar(&forceAction, "force", false, "Force upgrade : Overwrite tainted and outdated files") + flags := cmdPostOverflowsUpgrade.Flags() + flags.BoolP("all", "a", false, "Upgrade all the postoverflows") + flags.Bool("force", false, "Force upgrade : Overwrite tainted and outdated files") return cmdPostOverflowsUpgrade } +func runPostOverflowsInspect(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + var err error + // XXX: set global + prometheusURL, err = flags.GetString("url") + if err != nil { + return err + } + + InspectItem(args[0], cwhub.PARSERS_OVFLW) + + return nil +} + func NewPostOverflowsInspectCmd() *cobra.Command { cmdPostOverflowsInspect := &cobra.Command{ Use: "inspect [config]", Short: "Inspect given postoverflow", Long: `Inspect given postoverflow`, Example: `cscli postoverflows inspect crowdsec/xxx crowdsec/xyz`, - DisableAutoGenTag: true, Args: cobra.MinimumNArgs(1), + DisableAutoGenTag: true, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return compInstalledItems(cwhub.PARSERS_OVFLW, args, toComplete) }, - Run: func(cmd *cobra.Command, args []string) { - InspectItem(args[0], cwhub.PARSERS_OVFLW) - }, + RunE: runPostOverflowsInspect, } + flags := cmdPostOverflowsInspect.Flags() + // XXX: is this needed for postoverflows? + flags.StringP("url", "u", "", "Prometheus url") + return cmdPostOverflowsInspect } +func runPostOverflowsList(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + all, err := flags.GetBool("all") + if err != nil { + return err + } + + // XXX: will happily ignore missing postoverflows + ListItems(color.Output, []string{cwhub.PARSERS_OVFLW}, args, false, true, all) + + return nil +} + func NewPostOverflowsListCmd() *cobra.Command { cmdPostOverflowsList := &cobra.Command{ Use: "list [config]", @@ -180,12 +278,11 @@ func NewPostOverflowsListCmd() *cobra.Command { Example: `cscli postoverflows list cscli postoverflows list crowdsecurity/xxx`, DisableAutoGenTag: true, - Run: func(cmd *cobra.Command, args []string) { - ListItems(color.Output, []string{cwhub.PARSERS_OVFLW}, args, false, true, all) - }, + RunE: runPostOverflowsList, } - cmdPostOverflowsList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List disabled items as well") + flags := cmdPostOverflowsList.Flags() + flags.BoolP("all", "a", false, "List disabled items as well") return cmdPostOverflowsList } diff --git a/cmd/crowdsec-cli/scenarios.go b/cmd/crowdsec-cli/scenarios.go index 01e0b02dc..553ffa472 100644 --- a/cmd/crowdsec-cli/scenarios.go +++ b/cmd/crowdsec-cli/scenarios.go @@ -12,7 +12,7 @@ import ( ) func NewScenariosCmd() *cobra.Command { - var cmdScenarios = &cobra.Command{ + cmdScenarios := &cobra.Command{ Use: "scenarios [action] [config]", Short: "Install/Remove/Upgrade/Inspect scenario(s) from hub", Example: `cscli scenarios list [-a] @@ -48,141 +48,240 @@ cscli scenarios remove crowdsecurity/ssh-bf return cmdScenarios } -func NewCmdScenariosInstall() *cobra.Command { - var ignoreError bool +func runScenariosInstall(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() - var cmdScenariosInstall = &cobra.Command{ - Use: "install [config]", - Short: "Install given scenario(s)", - Long: `Fetch and install given scenario(s) from hub`, - Example: `cscli scenarios install crowdsec/xxx crowdsec/xyz`, - Args: cobra.MinimumNArgs(1), + downloadOnly, err := flags.GetBool("download-only") + if err != nil { + return err + } + + force, err := flags.GetBool("force") + if err != nil { + return err + } + + ignoreError, err := flags.GetBool("ignore") + if err != nil { + return err + } + + for _, name := range args { + t := cwhub.GetItem(cwhub.SCENARIOS, name) + if t == nil { + nearestItem, score := GetDistance(cwhub.SCENARIOS, name) + Suggest(cwhub.SCENARIOS, name, nearestItem.Name, score, ignoreError) + + continue + } + + if err := cwhub.InstallItem(csConfig, name, cwhub.SCENARIOS, force, downloadOnly); err != nil { + if !ignoreError { + return fmt.Errorf("error while installing '%s': %w", name, err) + } + log.Errorf("Error while installing '%s': %s", name, err) + } + } + + return nil +} + +func NewCmdScenariosInstall() *cobra.Command { + cmdScenariosInstall := &cobra.Command{ + Use: "install [config]", + Short: "Install given scenario(s)", + Long: `Fetch and install given scenario(s) from hub`, + Example: `cscli scenarios install crowdsec/xxx crowdsec/xyz`, + Args: cobra.MinimumNArgs(1), + DisableAutoGenTag: true, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return compAllItems(cwhub.SCENARIOS, args, toComplete) }, - DisableAutoGenTag: true, - RunE: func(cmd *cobra.Command, args []string) error { - for _, name := range args { - t := cwhub.GetItem(cwhub.SCENARIOS, name) - if t == nil { - nearestItem, score := GetDistance(cwhub.SCENARIOS, name) - Suggest(cwhub.SCENARIOS, name, nearestItem.Name, score, ignoreError) - continue - } - if err := cwhub.InstallItem(csConfig, name, cwhub.SCENARIOS, forceAction, downloadOnly); err != nil { - if !ignoreError { - return fmt.Errorf("error while installing '%s': %w", name, err) - } - log.Errorf("Error while installing '%s': %s", name, err) - } - } - return nil - }, + RunE: runScenariosInstall, } - cmdScenariosInstall.PersistentFlags().BoolVarP(&downloadOnly, "download-only", "d", false, "Only download packages, don't enable") - cmdScenariosInstall.PersistentFlags().BoolVar(&forceAction, "force", false, "Force install : Overwrite tainted and outdated files") - cmdScenariosInstall.PersistentFlags().BoolVar(&ignoreError, "ignore", false, "Ignore errors when installing multiple scenarios") + + flags := cmdScenariosInstall.Flags() + flags.BoolP("download-only", "d", false, "Only download packages, don't enable") + flags.Bool("force", false, "Force install : Overwrite tainted and outdated files") + flags.Bool("ignore", false, "Ignore errors when installing multiple scenarios") return cmdScenariosInstall } +func runScenariosRemove(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + purge, err := flags.GetBool("purge") + if err != nil { + return err + } + + force, err := flags.GetBool("force") + if err != nil { + return err + } + + all, err := flags.GetBool("all") + if err != nil { + return err + } + + if all { + err := cwhub.RemoveMany(csConfig, cwhub.SCENARIOS, "", all, purge, force) + if err != nil { + return err + } + + return nil + } + + if len(args) == 0 { + return fmt.Errorf("specify at least one scenario to remove or '--all'") + } + + for _, name := range args { + err := cwhub.RemoveMany(csConfig, cwhub.SCENARIOS, name, all, purge, force) + if err != nil { + return err + } + } + + return nil +} + func NewCmdScenariosRemove() *cobra.Command { - var cmdScenariosRemove = &cobra.Command{ - Use: "remove [config]", - Short: "Remove given scenario(s)", - Long: `remove given scenario(s)`, - Example: `cscli scenarios remove crowdsec/xxx crowdsec/xyz`, - Aliases: []string{"delete"}, + cmdScenariosRemove := &cobra.Command{ + Use: "remove [config]", + Short: "Remove given scenario(s)", + Long: `remove given scenario(s)`, + Example: `cscli scenarios remove crowdsec/xxx crowdsec/xyz`, + Aliases: []string{"delete"}, + DisableAutoGenTag: true, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return compInstalledItems(cwhub.SCENARIOS, args, toComplete) }, - DisableAutoGenTag: true, - RunE: func(cmd *cobra.Command, args []string) error { - if all { - cwhub.RemoveMany(csConfig, cwhub.SCENARIOS, "", all, purge, forceAction) - return nil - } - - if len(args) == 0 { - return fmt.Errorf("specify at least one scenario to remove or '--all'") - } - - for _, name := range args { - cwhub.RemoveMany(csConfig, cwhub.SCENARIOS, name, all, purge, forceAction) - } - return nil - }, + RunE: runScenariosRemove, } - cmdScenariosRemove.PersistentFlags().BoolVar(&purge, "purge", false, "Delete source file too") - cmdScenariosRemove.PersistentFlags().BoolVar(&forceAction, "force", false, "Force remove : Remove tainted and outdated files") - cmdScenariosRemove.PersistentFlags().BoolVar(&all, "all", false, "Delete all the scenarios") + + flags := cmdScenariosRemove.Flags() + flags.Bool("purge", false, "Delete source file too") + flags.Bool("force", false, "Force remove: Remove tainted and outdated files") + flags.Bool("all", false, "Delete all the scenarios") return cmdScenariosRemove } +func runScenariosUpgrade(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + force, err := flags.GetBool("force") + if err != nil { + return err + } + + all, err := flags.GetBool("all") + if err != nil { + return err + } + + if all { + cwhub.UpgradeConfig(csConfig, cwhub.SCENARIOS, "", force) + return nil + } + + if len(args) == 0 { + return fmt.Errorf("specify at least one scenario to upgrade or '--all'") + } + + for _, name := range args { + cwhub.UpgradeConfig(csConfig, cwhub.SCENARIOS, name, force) + } + + return nil +} + func NewCmdScenariosUpgrade() *cobra.Command { - var cmdScenariosUpgrade = &cobra.Command{ - Use: "upgrade [config]", - Short: "Upgrade given scenario(s)", - Long: `Fetch and Upgrade given scenario(s) from hub`, - Example: `cscli scenarios upgrade crowdsec/xxx crowdsec/xyz`, + cmdScenariosUpgrade := &cobra.Command{ + Use: "upgrade [config]", + Short: "Upgrade given scenario(s)", + Long: `Fetch and Upgrade given scenario(s) from hub`, + Example: `cscli scenarios upgrade crowdsec/xxx crowdsec/xyz`, + DisableAutoGenTag: true, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return compInstalledItems(cwhub.SCENARIOS, args, toComplete) }, - DisableAutoGenTag: true, - RunE: func(cmd *cobra.Command, args []string) error { - if all { - cwhub.UpgradeConfig(csConfig, cwhub.SCENARIOS, "", forceAction) - } else { - if len(args) == 0 { - return fmt.Errorf("specify at least one scenario to upgrade or '--all'") - } - for _, name := range args { - cwhub.UpgradeConfig(csConfig, cwhub.SCENARIOS, name, forceAction) - } - } - return nil - }, + RunE: runScenariosUpgrade, } - cmdScenariosUpgrade.PersistentFlags().BoolVarP(&all, "all", "a", false, "Upgrade all the scenarios") - cmdScenariosUpgrade.PersistentFlags().BoolVar(&forceAction, "force", false, "Force upgrade : Overwrite tainted and outdated files") + + flags := cmdScenariosUpgrade.Flags() + flags.BoolP("all", "a", false, "Upgrade all the scenarios") + flags.Bool("force", false, "Force upgrade : Overwrite tainted and outdated files") return cmdScenariosUpgrade } +func runScenariosInspect(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + var err error + // XXX: set global + prometheusURL, err = flags.GetString("url") + if err != nil { + return err + } + + InspectItem(args[0], cwhub.SCENARIOS) + + return nil +} + func NewCmdScenariosInspect() *cobra.Command { - var cmdScenariosInspect = &cobra.Command{ - Use: "inspect [config]", - Short: "Inspect given scenario", - Long: `Inspect given scenario`, - Example: `cscli scenarios inspect crowdsec/xxx`, - Args: cobra.MinimumNArgs(1), + cmdScenariosInspect := &cobra.Command{ + Use: "inspect [config]", + Short: "Inspect given scenario", + Long: `Inspect given scenario`, + Example: `cscli scenarios inspect crowdsec/xxx`, + Args: cobra.MinimumNArgs(1), + DisableAutoGenTag: true, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return compInstalledItems(cwhub.SCENARIOS, args, toComplete) }, - DisableAutoGenTag: true, - Run: func(cmd *cobra.Command, args []string) { - InspectItem(args[0], cwhub.SCENARIOS) - }, + RunE: runScenariosInspect, } - cmdScenariosInspect.PersistentFlags().StringVarP(&prometheusURL, "url", "u", "", "Prometheus url") + + flags := cmdScenariosInspect.Flags() + flags.StringP("url", "u", "", "Prometheus url") return cmdScenariosInspect } +func runScenariosList(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + + all, err := flags.GetBool("all") + if err != nil { + return err + } + + // XXX: will happily ignore missing scenarios + ListItems(color.Output, []string{cwhub.SCENARIOS}, args, false, true, all) + + return nil +} + func NewCmdScenariosList() *cobra.Command { - var cmdScenariosList = &cobra.Command{ + cmdScenariosList := &cobra.Command{ Use: "list [config]", Short: "List all scenario(s) or given one", Long: `List all scenario(s) or given one`, Example: `cscli scenarios list cscli scenarios list crowdsecurity/xxx`, DisableAutoGenTag: true, - Run: func(cmd *cobra.Command, args []string) { - ListItems(color.Output, []string{cwhub.SCENARIOS}, args, false, true, all) - }, + RunE: runScenariosList, } - cmdScenariosList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List disabled items as well") + + flags := cmdScenariosList.Flags() + flags.BoolP("all", "a", false, "List disabled items as well") return cmdScenariosList } diff --git a/cmd/crowdsec-cli/support.go b/cmd/crowdsec-cli/support.go index e5a4c36ab..7d80d6471 100644 --- a/cmd/crowdsec-cli/support.go +++ b/cmd/crowdsec-cli/support.go @@ -135,7 +135,7 @@ func collectOSInfo() ([]byte, error) { func collectHubItems(itemType string) []byte { out := bytes.NewBuffer(nil) log.Infof("Collecting %s list", itemType) - ListItems(out, []string{itemType}, []string{}, false, true, all) + ListItems(out, []string{itemType}, []string{}, false, true, false) return out.Bytes() } diff --git a/pkg/cwhub/helpers.go b/pkg/cwhub/helpers.go index c17e6758d..8ffeaa541 100644 --- a/pkg/cwhub/helpers.go +++ b/pkg/cwhub/helpers.go @@ -103,29 +103,28 @@ func InstallItem(csConfig *csconfig.Config, name string, obtype string, force bo return nil } -// XXX this must return errors instead of log.Fatal -func RemoveMany(csConfig *csconfig.Config, itemType string, name string, all bool, purge bool, forceAction bool) { +func RemoveMany(csConfig *csconfig.Config, itemType string, name string, all bool, purge bool, forceAction bool) error { if name != "" { item := GetItem(itemType, name) if item == nil { - log.Fatalf("unable to retrieve: %s", name) + return fmt.Errorf("unable to retrieve: %s", name) } err := DisableItem(csConfig.Hub, item, purge, forceAction) if err != nil { - log.Fatalf("unable to disable %s : %v", item.Name, err) + return fmt.Errorf("unable to disable %s: %w", item.Name, err) } if err = AddItem(itemType, *item); err != nil { - log.Fatalf("unable to add %s: %v", item.Name, err) + return fmt.Errorf("unable to add %s: %w", item.Name, err) } - return + return nil } if !all { - log.Fatal("removing item: no item specified") + return fmt.Errorf("removing item: no item specified") } disabled := 0 @@ -138,16 +137,18 @@ func RemoveMany(csConfig *csconfig.Config, itemType string, name string, all boo err := DisableItem(csConfig.Hub, &v, purge, forceAction) if err != nil { - log.Fatalf("unable to disable %s : %v", v.Name, err) + return fmt.Errorf("unable to disable %s: %w", v.Name, err) } if err := AddItem(itemType, v); err != nil { - log.Fatalf("unable to add %s: %v", v.Name, err) + return fmt.Errorf("unable to add %s: %w", v.Name, err) } disabled++ } log.Infof("Disabled %d items", disabled) + + return nil } func UpgradeConfig(csConfig *csconfig.Config, itemType string, name string, force bool) { diff --git a/pkg/cwhub/helpers_test.go b/pkg/cwhub/helpers_test.go index c8bb28c36..522dead05 100644 --- a/pkg/cwhub/helpers_test.go +++ b/pkg/cwhub/helpers_test.go @@ -74,7 +74,9 @@ func TestUpgradeConfigInDisabledScenarioShouldNotBeInstalled(t *testing.T) { require.True(t, hubIdx[SCENARIOS]["crowdsecurity/foobar_scenario"].Installed) assertCollectionDepsInstalled(t, "crowdsecurity/test_collection") - RemoveMany(cfg, SCENARIOS, "crowdsecurity/foobar_scenario", false, false, false) + err := RemoveMany(cfg, SCENARIOS, "crowdsecurity/foobar_scenario", false, false, false) + require.NoError(t, err) + getHubIdxOrFail(t) // scenario referenced by collection was deleted hence, collection should be tainted require.False(t, hubIdx[SCENARIOS]["crowdsecurity/foobar_scenario"].Installed) @@ -122,7 +124,9 @@ func TestUpgradeConfigNewScenarioIsInstalledWhenReferencedScenarioIsDisabled(t * require.True(t, hubIdx[SCENARIOS]["crowdsecurity/foobar_scenario"].Installed) assertCollectionDepsInstalled(t, "crowdsecurity/test_collection") - RemoveMany(cfg, SCENARIOS, "crowdsecurity/foobar_scenario", false, false, false) + err := RemoveMany(cfg, SCENARIOS, "crowdsecurity/foobar_scenario", false, false, false) + require.NoError(t, err) + getHubIdxOrFail(t) // scenario referenced by collection was deleted hence, collection should be tainted require.False(t, hubIdx[SCENARIOS]["crowdsecurity/foobar_scenario"].Installed) diff --git a/pkg/cwhub/loader.go b/pkg/cwhub/loader.go index 3c4566493..8b470148c 100644 --- a/pkg/cwhub/loader.go +++ b/pkg/cwhub/loader.go @@ -98,7 +98,7 @@ func (w Walker) getItemInfo(path string) (itemFileInfo, bool, error) { //.../hub/scenarios/crowdsec/ssh_bf.yaml //.../hub/profiles/crowdsec/linux.yaml if len(subs) < 4 { - log.Fatalf("path is too short : %s (%d)", path, len(subs)) + return itemFileInfo{}, false, fmt.Errorf("path is too short : %s (%d)", path, len(subs)) } ret.fname = subs[len(subs)-1] @@ -108,7 +108,7 @@ func (w Walker) getItemInfo(path string) (itemFileInfo, bool, error) { } else if strings.HasPrefix(path, w.installdir) { // we're in install /etc/crowdsec//... log.Tracef("in install dir") if len(subs) < 3 { - log.Fatalf("path is too short : %s (%d)", path, len(subs)) + return itemFileInfo{}, false, fmt.Errorf("path is too short: %s (%d)", path, len(subs)) } ///.../config/parser/stage/file.yaml ///.../config/postoverflow/stage/file.yaml @@ -352,7 +352,7 @@ func CollecDepsCheck(v *Item) error { for _, subName := range itemSlice { subItem, ok := hubIdx[sliceType][subName] if !ok { - log.Fatalf("Referred %s %s in collection %s doesn't exist.", sliceType, subName, v.Name) + return fmt.Errorf("referred %s %s in collection %s doesn't exist", sliceType, subName, v.Name) } log.Tracef("check %s installed:%t", subItem.Name, subItem.Installed)