cscli: add option --ignore-missing to "bouncers delete", "machines delete" (#3177)

* cscli: add option --ignore-missing to "bouncers delete", "machines delete"

* lint
This commit is contained in:
mmetc 2024-08-13 16:49:27 +02:00 committed by GitHub
parent 71a253aea6
commit 48e3f51954
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 69 additions and 16 deletions

View file

@ -344,11 +344,15 @@ func (cli *cliBouncers) validBouncerID(cmd *cobra.Command, args []string, toComp
return ret, cobra.ShellCompDirectiveNoFileComp
}
func (cli *cliBouncers) delete(bouncers []string) error {
func (cli *cliBouncers) delete(bouncers []string, ignoreMissing bool) error {
for _, bouncerID := range bouncers {
err := cli.db.DeleteBouncer(bouncerID)
if err != nil {
return fmt.Errorf("unable to delete bouncer '%s': %w", bouncerID, err)
if err := cli.db.DeleteBouncer(bouncerID); err != nil {
var notFoundErr *database.BouncerNotFoundError
if ignoreMissing && errors.As(err, &notFoundErr) {
return nil
}
return fmt.Errorf("unable to delete bouncer: %w", err)
}
log.Infof("bouncer '%s' deleted successfully", bouncerID)
@ -358,18 +362,24 @@ func (cli *cliBouncers) delete(bouncers []string) error {
}
func (cli *cliBouncers) newDeleteCmd() *cobra.Command {
var ignoreMissing bool
cmd := &cobra.Command{
Use: "delete MyBouncerName",
Short: "delete bouncer(s) from the database",
Example: `cscli bouncers delete "bouncer1" "bouncer2"`,
Args: cobra.MinimumNArgs(1),
Aliases: []string{"remove"},
DisableAutoGenTag: true,
ValidArgsFunction: cli.validBouncerID,
RunE: func(_ *cobra.Command, args []string) error {
return cli.delete(args)
return cli.delete(args, ignoreMissing)
},
}
flags := cmd.Flags()
flags.BoolVar(&ignoreMissing, "ignore-missing", false, "don't print errors if one or more bouncers don't exist")
return cmd
}

View file

@ -488,10 +488,16 @@ func (cli *cliMachines) validMachineID(cmd *cobra.Command, args []string, toComp
return ret, cobra.ShellCompDirectiveNoFileComp
}
func (cli *cliMachines) delete(machines []string) error {
func (cli *cliMachines) delete(machines []string, ignoreMissing bool) error {
for _, machineID := range machines {
if err := cli.db.DeleteWatcher(machineID); err != nil {
log.Errorf("unable to delete machine '%s': %s", machineID, err)
var notFoundErr *database.MachineNotFoundError
if ignoreMissing && errors.As(err, &notFoundErr) {
return nil
}
log.Errorf("unable to delete machine: %s", err)
return nil
}
@ -502,6 +508,8 @@ func (cli *cliMachines) delete(machines []string) error {
}
func (cli *cliMachines) newDeleteCmd() *cobra.Command {
var ignoreMissing bool
cmd := &cobra.Command{
Use: "delete [machine_name]...",
Short: "delete machine(s) by name",
@ -511,10 +519,13 @@ func (cli *cliMachines) newDeleteCmd() *cobra.Command {
DisableAutoGenTag: true,
ValidArgsFunction: cli.validMachineID,
RunE: func(_ *cobra.Command, args []string) error {
return cli.delete(args)
return cli.delete(args, ignoreMissing)
},
}
flags := cmd.Flags()
flags.BoolVar(&ignoreMissing, "ignore-missing", false, "don't print errors if one or more machines don't exist")
return cmd
}

View file

@ -12,6 +12,14 @@ import (
"github.com/crowdsecurity/crowdsec/pkg/models"
)
type BouncerNotFoundError struct {
BouncerName string
}
func (e *BouncerNotFoundError) Error() string {
return fmt.Sprintf("'%s' does not exist", e.BouncerName)
}
func (c *Client) BouncerUpdateBaseMetrics(bouncerName string, bouncerType string, baseMetrics models.BaseMetrics) error {
os := baseMetrics.Os
features := strings.Join(baseMetrics.FeatureFlags, ",")
@ -88,7 +96,7 @@ func (c *Client) DeleteBouncer(name string) error {
}
if nbDeleted == 0 {
return errors.New("bouncer doesn't exist")
return &BouncerNotFoundError{BouncerName: name}
}
return nil

View file

@ -21,6 +21,14 @@ const (
CapiListsMachineID = types.ListOrigin
)
type MachineNotFoundError struct {
MachineID string
}
func (e *MachineNotFoundError) Error() string {
return fmt.Sprintf("'%s' does not exist", e.MachineID)
}
func (c *Client) MachineUpdateBaseMetrics(machineID string, baseMetrics models.BaseMetrics, hubItems models.HubItems, datasources map[string]int64) error {
os := baseMetrics.Os
features := strings.Join(baseMetrics.FeatureFlags, ",")
@ -168,7 +176,7 @@ func (c *Client) DeleteWatcher(name string) error {
}
if nbDeleted == 0 {
return errors.New("machine doesn't exist")
return &MachineNotFoundError{MachineID: name}
}
return nil
@ -197,8 +205,8 @@ func (c *Client) UpdateMachineLastHeartBeat(machineID string) error {
return nil
}
func (c *Client) UpdateMachineScenarios(scenarios string, ID int) error {
_, err := c.Ent.Machine.UpdateOneID(ID).
func (c *Client) UpdateMachineScenarios(scenarios string, id int) error {
_, err := c.Ent.Machine.UpdateOneID(id).
SetUpdatedAt(time.Now().UTC()).
SetScenarios(scenarios).
Save(c.CTX)
@ -209,8 +217,8 @@ func (c *Client) UpdateMachineScenarios(scenarios string, ID int) error {
return nil
}
func (c *Client) UpdateMachineIP(ipAddr string, ID int) error {
_, err := c.Ent.Machine.UpdateOneID(ID).
func (c *Client) UpdateMachineIP(ipAddr string, id int) error {
_, err := c.Ent.Machine.UpdateOneID(id).
SetIpAddress(ipAddr).
Save(c.CTX)
if err != nil {
@ -220,8 +228,8 @@ func (c *Client) UpdateMachineIP(ipAddr string, ID int) error {
return nil
}
func (c *Client) UpdateMachineVersion(ipAddr string, ID int) error {
_, err := c.Ent.Machine.UpdateOneID(ID).
func (c *Client) UpdateMachineVersion(ipAddr string, id int) error {
_, err := c.Ent.Machine.UpdateOneID(id).
SetVersion(ipAddr).
Save(c.CTX)
if err != nil {

View file

@ -60,6 +60,14 @@ teardown() {
assert_json '{message:"access forbidden"}'
}
@test "delete non-existent bouncer" {
# this is a fatal error, which is not consistent with "machines delete"
rune -1 cscli bouncers delete something
assert_stderr --partial "unable to delete bouncer: 'something' does not exist"
rune -0 cscli bouncers delete something --ignore-missing
refute_stderr
}
@test "bouncers delete has autocompletion" {
rune -0 cscli bouncers add foo1
rune -0 cscli bouncers add foo2

View file

@ -62,6 +62,14 @@ teardown() {
assert_output 1
}
@test "delete non-existent machine" {
# this is not a fatal error, won't halt a script with -e
rune -0 cscli machines delete something
assert_stderr --partial "unable to delete machine: 'something' does not exist"
rune -0 cscli machines delete something --ignore-missing
refute_stderr
}
@test "machines [delete|inspect] has autocompletion" {
rune -0 cscli machines add -a -f /dev/null foo1
rune -0 cscli machines add -a -f /dev/null foo2