Refact cscli hub/item commands (#2536)
* log.Fatal -> fmt.Errorf * lint cmd/crowdsec-cli hub items and split collection commands * cscli collections: add examples * cscli parsers: avoid globals * cscli scenarios: avoid globals * cscli collections, postoverflows: avoid globals * cscli hub: avoid globals * remove unused globals
This commit is contained in:
parent
7db5bf8979
commit
734ba46e6a
11 changed files with 845 additions and 409 deletions
|
@ -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,54 +39,99 @@ func NewCollectionsCmd() *cobra.Command {
|
|||
},
|
||||
}
|
||||
|
||||
var ignoreError bool
|
||||
cmdCollections.AddCommand(NewCollectionsInstallCmd())
|
||||
cmdCollections.AddCommand(NewCollectionsRemoveCmd())
|
||||
cmdCollections.AddCommand(NewCollectionsUpgradeCmd())
|
||||
cmdCollections.AddCommand(NewCollectionsInspectCmd())
|
||||
cmdCollections.AddCommand(NewCollectionsListCmd())
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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),
|
||||
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 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
|
||||
},
|
||||
}
|
||||
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{
|
||||
Use: "remove collection",
|
||||
Short: "Remove given collection(s)",
|
||||
Long: `Remove given collection(s) from hub`,
|
||||
Example: `cscli collections remove crowdsec/xxx crowdsec/xyz`,
|
||||
Aliases: []string{"delete"},
|
||||
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 compInstalledItems(cwhub.COLLECTIONS, args, toComplete)
|
||||
return compAllItems(cwhub.COLLECTIONS, args, toComplete)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: runCollectionsInstall,
|
||||
}
|
||||
|
||||
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 {
|
||||
cwhub.RemoveMany(csConfig, cwhub.COLLECTIONS, "", all, purge, forceAction)
|
||||
err := cwhub.RemoveMany(csConfig, cwhub.COLLECTIONS, "", all, purge, force)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -91,7 +140,7 @@ func NewCollectionsCmd() *cobra.Command {
|
|||
}
|
||||
|
||||
for _, name := range args {
|
||||
if !forceAction {
|
||||
if !force {
|
||||
item := cwhub.GetItem(cwhub.COLLECTIONS, name)
|
||||
if item == nil {
|
||||
return fmt.Errorf("unable to retrieve: %s", name)
|
||||
|
@ -102,17 +151,69 @@ func NewCollectionsCmd() *cobra.Command {
|
|||
continue
|
||||
}
|
||||
}
|
||||
cwhub.RemoveMany(csConfig, cwhub.COLLECTIONS, name, all, purge, forceAction)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
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{
|
||||
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`,
|
||||
Example: `cscli collections 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.COLLECTIONS, args, toComplete)
|
||||
},
|
||||
RunE: runCollectionsRemove,
|
||||
}
|
||||
|
||||
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'")
|
||||
RunE: runCollectionsUpgrade,
|
||||
}
|
||||
for _, name := range args {
|
||||
cwhub.UpgradeConfig(csConfig, cwhub.COLLECTIONS, name, forceAction)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -45,13 +45,14 @@ cscli hub update # Download list of available configurations from the hub
|
|||
return cmdHub
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
@ -61,19 +62,56 @@ func NewHubListCmd() *cobra.Command {
|
|||
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
|
||||
},
|
||||
}
|
||||
cmdHubList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List disabled items as well")
|
||||
|
||||
func NewHubListCmd() *cobra.Command {
|
||||
var cmdHubList = &cobra.Command{
|
||||
Use: "list [-a]",
|
||||
Short: "List installed configs",
|
||||
Args: cobra.ExactArgs(0),
|
||||
DisableAutoGenTag: true,
|
||||
RunE: runHubList,
|
||||
}
|
||||
|
||||
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
|
||||
RunE: runHubUpgrade,
|
||||
}
|
||||
|
||||
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
|
||||
},
|
||||
}
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,29 +160,44 @@ 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 {
|
||||
RunE: runParsersRemove,
|
||||
}
|
||||
|
||||
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.RemoveMany(csConfig, cwhub.PARSERS, "", all, purge, forceAction)
|
||||
cwhub.UpgradeConfig(csConfig, cwhub.PARSERS, "", force)
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
return fmt.Errorf("specify at least one parser to remove or '--all'")
|
||||
return fmt.Errorf("specify at least one parser to upgrade or '--all'")
|
||||
}
|
||||
|
||||
for _, name := range args {
|
||||
cwhub.RemoveMany(csConfig, cwhub.PARSERS, name, all, purge, forceAction)
|
||||
cwhub.UpgradeConfig(csConfig, cwhub.PARSERS, name, force)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
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")
|
||||
|
||||
return cmdParsersRemove
|
||||
}
|
||||
|
||||
func NewParsersUpgradeCmd() *cobra.Command {
|
||||
|
@ -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
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@ func NewPostOverflowsCmd() *cobra.Command {
|
|||
cscli postoverflows inspect crowdsecurity/cdn-whitelist
|
||||
cscli postoverflows upgrade crowdsecurity/cdn-whitelist
|
||||
cscli postoverflows list
|
||||
cscli postoverflows remove crowdsecurity/cdn-whitelist`,
|
||||
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,29 +160,44 @@ 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 {
|
||||
RunE: runPostOverflowsRemove,
|
||||
}
|
||||
|
||||
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.RemoveMany(csConfig, cwhub.PARSERS_OVFLW, "", all, purge, forceAction)
|
||||
cwhub.UpgradeConfig(csConfig, cwhub.PARSERS_OVFLW, "", force)
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
return fmt.Errorf("specify at least one postoverflow to remove or '--all'")
|
||||
return fmt.Errorf("specify at least one postoverflow to upgrade or '--all'")
|
||||
}
|
||||
|
||||
for _, name := range args {
|
||||
cwhub.RemoveMany(csConfig, cwhub.PARSERS_OVFLW, name, all, purge, forceAction)
|
||||
cwhub.UpgradeConfig(csConfig, cwhub.PARSERS_OVFLW, name, force)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
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")
|
||||
|
||||
return cmdPostOverflowsRemove
|
||||
}
|
||||
|
||||
func NewPostOverflowsUpgradeCmd() *cobra.Command {
|
||||
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,58 +48,90 @@ 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()
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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),
|
||||
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 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
|
||||
},
|
||||
}
|
||||
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")
|
||||
|
||||
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)
|
||||
},
|
||||
RunE: runScenariosInstall,
|
||||
}
|
||||
|
||||
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 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"},
|
||||
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 {
|
||||
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 {
|
||||
cwhub.RemoveMany(csConfig, cwhub.SCENARIOS, "", all, purge, forceAction)
|
||||
err := cwhub.RemoveMany(csConfig, cwhub.SCENARIOS, "", all, purge, force)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -108,81 +140,148 @@ func NewCmdScenariosRemove() *cobra.Command {
|
|||
}
|
||||
|
||||
for _, name := range args {
|
||||
cwhub.RemoveMany(csConfig, cwhub.SCENARIOS, name, all, purge, forceAction)
|
||||
err := cwhub.RemoveMany(csConfig, cwhub.SCENARIOS, name, all, purge, force)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
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")
|
||||
|
||||
func NewCmdScenariosRemove() *cobra.Command {
|
||||
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)
|
||||
},
|
||||
RunE: runScenariosRemove,
|
||||
}
|
||||
|
||||
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{
|
||||
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'")
|
||||
RunE: runScenariosUpgrade,
|
||||
}
|
||||
for _, name := range args {
|
||||
cwhub.UpgradeConfig(csConfig, cwhub.SCENARIOS, name, forceAction)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
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{
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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/<type>/...
|
||||
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)
|
||||
|
|
Loading…
Reference in a new issue