cscli tests + fix bouncer/machine prune (#2883)

* func tests: "cscli config feature-flags"
* func tests: "cscli bouncers list"
* func tests + fix: "cscli bouncers/machines prune"
* lint
This commit is contained in:
mmetc 2024-03-11 13:14:01 +01:00 committed by GitHub
parent 6daaab1789
commit 49e0735b53
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 72 additions and 20 deletions

View file

@ -259,7 +259,7 @@ func (cli *cliBouncers) prune(duration time.Duration, force bool) error {
}
}
bouncers, err := cli.db.QueryBouncersLastPulltimeLT(time.Now().UTC().Add(duration))
bouncers, err := cli.db.QueryBouncersLastPulltimeLT(time.Now().UTC().Add(-duration))
if err != nil {
return fmt.Errorf("unable to query bouncers: %w", err)
}

View file

@ -4,6 +4,7 @@ import (
saferand "crypto/rand"
"encoding/csv"
"encoding/json"
"errors"
"fmt"
"math/big"
"os"
@ -134,7 +135,7 @@ Note: This command requires database direct access, so is intended to be run on
}
cli.db, err = database.NewClient(cli.cfg().DbConfig)
if err != nil {
return fmt.Errorf("unable to create new database client: %s", err)
return fmt.Errorf("unable to create new database client: %w", err)
}
return nil
@ -155,7 +156,7 @@ func (cli *cliMachines) list() error {
machines, err := cli.db.ListMachines()
if err != nil {
return fmt.Errorf("unable to list machines: %s", err)
return fmt.Errorf("unable to list machines: %w", err)
}
switch cli.cfg().Cscli.Output {
@ -166,7 +167,7 @@ func (cli *cliMachines) list() error {
enc.SetIndent("", " ")
if err := enc.Encode(machines); err != nil {
return fmt.Errorf("failed to marshal")
return errors.New("failed to marshal")
}
return nil
@ -175,7 +176,7 @@ func (cli *cliMachines) list() error {
err := csvwriter.Write([]string{"machine_id", "ip_address", "updated_at", "validated", "version", "auth_type", "last_heartbeat"})
if err != nil {
return fmt.Errorf("failed to write header: %s", err)
return fmt.Errorf("failed to write header: %w", err)
}
for _, m := range machines {
@ -257,12 +258,12 @@ func (cli *cliMachines) add(args []string, machinePassword string, dumpFile stri
// create machineID if not specified by user
if len(args) == 0 {
if !autoAdd {
return fmt.Errorf("please specify a machine name to add, or use --auto")
return errors.New("please specify a machine name to add, or use --auto")
}
machineID, err = generateID("")
if err != nil {
return fmt.Errorf("unable to generate machine id: %s", err)
return fmt.Errorf("unable to generate machine id: %w", err)
}
} else {
machineID = args[0]
@ -281,20 +282,20 @@ func (cli *cliMachines) add(args []string, machinePassword string, dumpFile stri
case os.IsNotExist(err) || force:
dumpFile = credFile
case err != nil:
return fmt.Errorf("unable to stat '%s': %s", credFile, err)
return fmt.Errorf("unable to stat '%s': %w", credFile, err)
default:
return fmt.Errorf(`credentials file '%s' already exists: please remove it, use "--force" or specify a different file with "-f" ("-f -" for standard output)`, credFile)
}
}
if dumpFile == "" {
return fmt.Errorf(`please specify a file to dump credentials to, with -f ("-f -" for standard output)`)
return errors.New(`please specify a file to dump credentials to, with -f ("-f -" for standard output)`)
}
// create a password if it's not specified by user
if machinePassword == "" && !interactive {
if !autoAdd {
return fmt.Errorf("please specify a password with --password or use --auto")
return errors.New("please specify a password with --password or use --auto")
}
machinePassword = generatePassword(passwordLength)
@ -309,7 +310,7 @@ func (cli *cliMachines) add(args []string, machinePassword string, dumpFile stri
_, err = cli.db.CreateMachine(&machineID, &password, "", true, force, types.PasswordAuthType)
if err != nil {
return fmt.Errorf("unable to create machine: %s", err)
return fmt.Errorf("unable to create machine: %w", err)
}
fmt.Fprintf(os.Stderr, "Machine '%s' successfully added to the local API.\n", machineID)
@ -320,7 +321,7 @@ func (cli *cliMachines) add(args []string, machinePassword string, dumpFile stri
} else if serverCfg != nil && serverCfg.ListenURI != "" {
apiURL = "http://" + serverCfg.ListenURI
} else {
return fmt.Errorf("unable to dump an api URL. Please provide it in your configuration or with the -u parameter")
return errors.New("unable to dump an api URL. Please provide it in your configuration or with the -u parameter")
}
}
@ -332,12 +333,12 @@ func (cli *cliMachines) add(args []string, machinePassword string, dumpFile stri
apiConfigDump, err := yaml.Marshal(apiCfg)
if err != nil {
return fmt.Errorf("unable to marshal api credentials: %s", err)
return fmt.Errorf("unable to marshal api credentials: %w", err)
}
if dumpFile != "" && dumpFile != "-" {
if err = os.WriteFile(dumpFile, apiConfigDump, 0o600); err != nil {
return fmt.Errorf("write api credentials in '%s' failed: %s", dumpFile, err)
return fmt.Errorf("write api credentials in '%s' failed: %w", dumpFile, err)
}
fmt.Fprintf(os.Stderr, "API credentials written to '%s'.\n", dumpFile)
@ -413,13 +414,13 @@ func (cli *cliMachines) prune(duration time.Duration, notValidOnly bool, force b
}
if !notValidOnly {
if pending, err := cli.db.QueryLastValidatedHeartbeatLT(time.Now().UTC().Add(duration)); err == nil {
if pending, err := cli.db.QueryLastValidatedHeartbeatLT(time.Now().UTC().Add(-duration)); err == nil {
machines = append(machines, pending...)
}
}
if len(machines) == 0 {
fmt.Println("no machines to prune")
fmt.Println("No machines to prune.")
return nil
}
@ -438,7 +439,7 @@ func (cli *cliMachines) prune(duration time.Duration, notValidOnly bool, force b
deleted, err := cli.db.BulkDeleteWatchers(machines)
if err != nil {
return fmt.Errorf("unable to prune machines: %s", err)
return fmt.Errorf("unable to prune machines: %w", err)
}
fmt.Fprintf(os.Stderr, "successfully delete %d machines\n", deleted)
@ -479,7 +480,7 @@ cscli machines prune --not-validated-only --force`,
func (cli *cliMachines) validate(machineID string) error {
if err := cli.db.ValidateMachine(machineID); err != nil {
return fmt.Errorf("unable to validate machine '%s': %s", machineID, err)
return fmt.Errorf("unable to validate machine '%s': %w", machineID, err)
}
log.Infof("machine '%s' validated successfully", machineID)
@ -495,7 +496,7 @@ func (cli *cliMachines) newValidateCmd() *cobra.Command {
Example: `cscli machines validate "machine_name"`,
Args: cobra.ExactArgs(1),
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
RunE: func(_ *cobra.Command, args []string) error {
return cli.validate(args[0])
},
}

View file

@ -358,3 +358,24 @@ teardown() {
rune -0 cscli setup
assert_output --partial 'cscli setup [command]'
}
@test "cscli config feature-flags" {
# disabled
rune -0 cscli config feature-flags
assert_line '✗ cscli_setup: Enable cscli setup command (service detection)'
# enabled in feature.yaml
CONFIG_DIR=$(dirname "$CONFIG_YAML")
echo ' - cscli_setup' >> "$CONFIG_DIR"/feature.yaml
rune -0 cscli config feature-flags
assert_line '✓ cscli_setup: Enable cscli setup command (service detection)'
# enabled in environment
# shellcheck disable=SC2031
export CROWDSEC_FEATURE_CSCLI_SETUP="true"
rune -0 cscli config feature-flags
assert_line '✓ cscli_setup: Enable cscli setup command (service detection)'
# there are no retired features
rune -0 cscli config feature-flags --retired
}

View file

@ -25,7 +25,13 @@ teardown() {
@test "there are 0 bouncers" {
rune -0 cscli bouncers list -o json
assert_output "[]"
assert_json '[]'
rune -0 cscli bouncers list -o human
assert_output --partial "Name"
rune -0 cscli bouncers list -o raw
assert_output --partial 'name'
}
@test "we can add one bouncer, and delete it" {
@ -68,3 +74,13 @@ teardown() {
rune -1 cscli bouncers delete ciTestBouncer
rune -1 cscli bouncers delete foobarbaz
}
@test "cscli bouncers prune" {
rune -0 cscli bouncers prune
assert_output 'No bouncers to prune.'
rune -0 cscli bouncers add ciTestBouncer
rune -0 cscli bouncers prune
assert_output 'No bouncers to prune.'
}

View file

@ -90,3 +90,17 @@ teardown() {
rune -0 jq '. | length' <(output)
assert_output 1
}
@test "cscli machines prune" {
rune -0 cscli metrics
rune -0 cscli machines prune
assert_output 'No machines to prune.'
rune -0 cscli machines list -o json
rune -0 jq -r '.[-1].machineId' <(output)
rune -0 cscli machines delete "$output"
rune -0 cscli machines prune
assert_output 'No machines to prune.'
}