replace log.Fatal -> fmt.Errorf (#2058)

This commit is contained in:
mmetc 2023-02-20 15:05:42 +01:00 committed by GitHub
parent 8fce946850
commit b7d1e2c483
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 191 additions and 126 deletions

View file

@ -253,13 +253,13 @@ cscli alerts list --range 1.2.3.0/24
cscli alerts list -s crowdsecurity/ssh-bf
cscli alerts list --type ban`,
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
var err error
if err := manageCliDecisionAlerts(alertListFilter.IPEquals, alertListFilter.RangeEquals,
alertListFilter.ScopeEquals, alertListFilter.ValueEquals); err != nil {
printHelp(cmd)
log.Fatalf("%s", err)
return err
}
if limit != nil {
alertListFilter.Limit = limit
@ -273,7 +273,7 @@ cscli alerts list --type ban`,
days, err := strconv.Atoi(realDuration)
if err != nil {
printHelp(cmd)
log.Fatalf("Can't parse duration %s, valid durations format: 1d, 4h, 4h15m", *alertListFilter.Until)
return fmt.Errorf("can't parse duration %s, valid durations format: 1d, 4h, 4h15m", *alertListFilter.Until)
}
*alertListFilter.Until = fmt.Sprintf("%d%s", days*24, "h")
}
@ -285,7 +285,7 @@ cscli alerts list --type ban`,
days, err := strconv.Atoi(realDuration)
if err != nil {
printHelp(cmd)
log.Fatalf("Can't parse duration %s, valid durations format: 1d, 4h, 4h15m", *alertListFilter.Since)
return fmt.Errorf("can't parse duration %s, valid durations format: 1d, 4h, 4h15m", *alertListFilter.Since)
}
*alertListFilter.Since = fmt.Sprintf("%d%s", days*24, "h")
}
@ -323,13 +323,15 @@ cscli alerts list --type ban`,
alerts, _, err := Client.Alerts.List(context.Background(), alertListFilter)
if err != nil {
log.Fatalf("Unable to list alerts : %v", err)
return fmt.Errorf("unable to list alerts: %v", err)
}
err = AlertsToTable(alerts, printMachine)
if err != nil {
log.Fatalf("unable to list alerts : %v", err)
return fmt.Errorf("unable to list alerts: %v", err)
}
return nil
},
}
cmdAlertsList.Flags().SortFlags = false
@ -372,25 +374,27 @@ cscli alerts delete -s crowdsecurity/ssh-bf"`,
DisableAutoGenTag: true,
Aliases: []string{"remove"},
Args: cobra.ExactArgs(0),
PreRun: func(cmd *cobra.Command, args []string) {
PreRunE: func(cmd *cobra.Command, args []string) error {
if AlertDeleteAll {
return
return nil
}
if *alertDeleteFilter.ScopeEquals == "" && *alertDeleteFilter.ValueEquals == "" &&
*alertDeleteFilter.ScenarioEquals == "" && *alertDeleteFilter.IPEquals == "" &&
*alertDeleteFilter.RangeEquals == "" && delAlertByID == "" {
_ = cmd.Usage()
log.Fatalln("At least one filter or --all must be specified")
return fmt.Errorf("at least one filter or --all must be specified")
}
return nil
},
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
var err error
if !AlertDeleteAll {
if err := manageCliDecisionAlerts(alertDeleteFilter.IPEquals, alertDeleteFilter.RangeEquals,
alertDeleteFilter.ScopeEquals, alertDeleteFilter.ValueEquals); err != nil {
printHelp(cmd)
log.Fatalf("%s", err)
return err
}
if ActiveDecision != nil {
alertDeleteFilter.ActiveDecisionEquals = ActiveDecision
@ -425,15 +429,17 @@ cscli alerts delete -s crowdsecurity/ssh-bf"`,
if delAlertByID == "" {
alerts, _, err = Client.Alerts.Delete(context.Background(), alertDeleteFilter)
if err != nil {
log.Fatalf("Unable to delete alerts : %v", err)
return fmt.Errorf("unable to delete alerts : %v", err)
}
} else {
alerts, _, err = Client.Alerts.DeleteOne(context.Background(), delAlertByID)
if err != nil {
log.Fatalf("Unable to delete alert : %v", err)
return fmt.Errorf("unable to delete alert: %v", err)
}
}
log.Infof("%s alert(s) deleted", alerts.NbDeleted)
return nil
},
}
cmdAlertsDelete.Flags().SortFlags = false
@ -455,20 +461,19 @@ func NewAlertsInspectCmd() *cobra.Command {
Short: `Show info about an alert`,
Example: `cscli alerts inspect 123`,
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
printHelp(cmd)
return
return fmt.Errorf("missing alert_id")
}
for _, alertID := range args {
id, err := strconv.Atoi(alertID)
if err != nil {
log.Fatalf("bad alert id %s", alertID)
continue
return fmt.Errorf("bad alert id %s", alertID)
}
alert, _, err := Client.Alerts.GetByID(context.Background(), id)
if err != nil {
log.Fatalf("can't find alert with id %s: %s", alertID, err)
return fmt.Errorf("can't find alert with id %s: %s", alertID, err)
}
switch csConfig.Cscli.Output {
case "human":
@ -478,17 +483,19 @@ func NewAlertsInspectCmd() *cobra.Command {
case "json":
data, err := json.MarshalIndent(alert, "", " ")
if err != nil {
log.Fatalf("unable to marshal alert with id %s: %s", alertID, err)
return fmt.Errorf("unable to marshal alert with id %s: %s", alertID, err)
}
fmt.Printf("%s\n", string(data))
case "raw":
data, err := yaml.Marshal(alert)
if err != nil {
log.Fatalf("unable to marshal alert with id %s: %s", alertID, err)
return fmt.Errorf("unable to marshal alert with id %s: %s", alertID, err)
}
fmt.Printf("%s\n", string(data))
}
}
return nil
},
}
cmdAlertsInspect.Flags().SortFlags = false
@ -506,21 +513,23 @@ func NewAlertsFlushCmd() *cobra.Command {
/!\ This command can be used only on the same machine than the local API`,
Example: `cscli alerts flush --max-items 1000 --max-age 7d`,
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
var err error
if err := csConfig.LoadAPIServer(); err != nil || csConfig.DisableAPI {
log.Fatal("Local API is disabled, please run this command on the local API machine")
return fmt.Errorf("local API is disabled, please run this command on the local API machine")
}
dbClient, err = database.NewClient(csConfig.DbConfig)
if err != nil {
log.Fatalf("unable to create new database client: %s", err)
return fmt.Errorf("unable to create new database client: %s", err)
}
log.Info("Flushing alerts. !! This may take a long time !!")
err = dbClient.FlushAlerts(maxAge, maxItems)
if err != nil {
log.Fatalf("unable to flush alerts: %s", err)
return fmt.Errorf("unable to flush alerts: %s", err)
}
log.Info("Alerts flushed")
return nil
},
}

View file

@ -9,7 +9,6 @@ import (
"time"
"github.com/fatih/color"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@ -29,14 +28,14 @@ func getBouncers(out io.Writer, dbClient *database.Client) error {
enc := json.NewEncoder(out)
enc.SetIndent("", " ")
if err := enc.Encode(bouncers); err != nil {
return errors.Wrap(err, "failed to unmarshal")
return fmt.Errorf("failed to unmarshal: %w", err)
}
return nil
} else if csConfig.Cscli.Output == "raw" {
csvwriter := csv.NewWriter(out)
err := csvwriter.Write([]string{"name", "ip", "revoked", "last_pull", "type", "version", "auth_type"})
if err != nil {
return errors.Wrap(err, "failed to write raw header")
return fmt.Errorf("failed to write raw header: %w", err)
}
for _, b := range bouncers {
var revoked string
@ -47,7 +46,7 @@ func getBouncers(out io.Writer, dbClient *database.Client) error {
}
err := csvwriter.Write([]string{b.Name, b.IPAddress, revoked, b.LastPull.Format(time.RFC3339), b.Type, b.Version, b.AuthType})
if err != nil {
return errors.Wrap(err, "failed to write raw")
return fmt.Errorf("failed to write raw: %w", err)
}
}
csvwriter.Flush()
@ -63,11 +62,12 @@ func NewBouncersListCmd() *cobra.Command {
Example: `cscli bouncers list`,
Args: cobra.ExactArgs(0),
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, arg []string) {
RunE: func(cmd *cobra.Command, arg []string) error {
err := getBouncers(color.Output, dbClient)
if err != nil {
log.Fatalf("unable to list bouncers: %s", err)
return fmt.Errorf("unable to list bouncers: %s", err)
}
return nil
},
}
@ -91,18 +91,18 @@ func runBouncersAdd(cmd *cobra.Command, args []string) error {
var apiKey string
if keyName == "" {
log.Fatalf("Please provide a name for the api key")
return fmt.Errorf("please provide a name for the api key")
}
apiKey = key
if key == "" {
apiKey, err = middlewares.GenerateAPIKey(keyLength)
}
if err != nil {
log.Fatalf("unable to generate api key: %s", err)
return fmt.Errorf("unable to generate api key: %s", err)
}
_, err = dbClient.CreateBouncer(keyName, "", middlewares.HashSHA512(apiKey), types.ApiKeyAuthType)
if err != nil {
log.Fatalf("unable to create bouncer: %s", err)
return fmt.Errorf("unable to create bouncer: %s", err)
}
if csConfig.Cscli.Output == "human" {
@ -114,7 +114,7 @@ func runBouncersAdd(cmd *cobra.Command, args []string) error {
} else if csConfig.Cscli.Output == "json" {
j, err := json.Marshal(apiKey)
if err != nil {
log.Fatalf("unable to marshal api key")
return fmt.Errorf("unable to marshal api key")
}
fmt.Printf("%s", string(j))
}
@ -149,7 +149,7 @@ func runBouncersDelete(cmd *cobra.Command, args []string) error {
for _, bouncerID := range args {
err := dbClient.DeleteBouncer(bouncerID)
if err != nil {
log.Fatalf("unable to delete bouncer '%s': %s", bouncerID, err)
return fmt.Errorf("unable to delete bouncer '%s': %s", bouncerID, err)
}
log.Infof("bouncer '%s' deleted successfully", bouncerID)
}
@ -200,15 +200,16 @@ Note: This command requires database direct access, so is intended to be run on
Args: cobra.MinimumNArgs(1),
Aliases: []string{"bouncer"},
DisableAutoGenTag: true,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
var err error
if err := csConfig.LoadAPIServer(); err != nil || csConfig.DisableAPI {
log.Fatal("Local API is disabled, please run this command on the local API machine")
return fmt.Errorf("local API is disabled, please run this command on the local API machine")
}
dbClient, err = database.NewClient(csConfig.DbConfig)
if err != nil {
log.Fatalf("unable to create new database client: %s", err)
return fmt.Errorf("unable to create new database client: %s", err)
}
return nil
},
}

View file

@ -65,7 +65,7 @@ func runExplain(cmd *cobra.Command, args []string) error {
}
if logFile == "-" && ((fileInfo.Mode() & os.ModeCharDevice) == os.ModeCharDevice) {
log.Fatal("-f - is intended to work with pipes.")
return fmt.Errorf("the option -f - is intended to work with pipes")
}
var f *os.File
@ -77,13 +77,13 @@ func runExplain(cmd *cobra.Command, args []string) error {
tmpFile = filepath.Join(dir, "cscli_test_tmp.log")
f, err = os.Create(tmpFile)
if err != nil {
log.Fatal(err)
return err
}
if logLine != "" {
_, err = f.WriteString(logLine)
if err != nil {
log.Fatal(err)
return err
}
} else if logFile == "-" {
reader := bufio.NewReader(os.Stdin)
@ -110,7 +110,7 @@ func runExplain(cmd *cobra.Command, args []string) error {
if logFile != "" {
absolutePath, err := filepath.Abs(logFile)
if err != nil {
log.Fatalf("unable to get absolute path of '%s', exiting", logFile)
return fmt.Errorf("unable to get absolute path of '%s', exiting", logFile)
}
dsn = fmt.Sprintf("file://%s", absolutePath)
lineCount := types.GetLineCountForFile(absolutePath)
@ -120,7 +120,7 @@ func runExplain(cmd *cobra.Command, args []string) error {
}
if dsn == "" {
log.Fatal("no acquisition (--file or --dsn) provided, can't run cscli test.")
return fmt.Errorf("no acquisition (--file or --dsn) provided, can't run cscli test")
}
cmdArgs := []string{"-c", ConfigFilePath, "-type", logType, "-dsn", dsn, "-dump-data", "./", "-no-api"}
@ -129,13 +129,13 @@ func runExplain(cmd *cobra.Command, args []string) error {
output, err := crowdsecCmd.CombinedOutput()
if err != nil {
fmt.Println(string(output))
log.Fatalf("fail to run crowdsec for test: %v", err)
return fmt.Errorf("fail to run crowdsec for test: %v", err)
}
// rm the temporary log file if only a log line/stdin was provided
if tmpFile != "" {
if err := os.Remove(tmpFile); err != nil {
log.Fatalf("unable to remove tmp log file '%s': %+v", tmpFile, err)
return fmt.Errorf("unable to remove tmp log file '%s': %+v", tmpFile, err)
}
}
parserDumpFile := filepath.Join(dir, hubtest.ParserResultFileName)
@ -143,12 +143,12 @@ func runExplain(cmd *cobra.Command, args []string) error {
parserDump, err := hubtest.LoadParserDump(parserDumpFile)
if err != nil {
log.Fatalf("unable to load parser dump result: %s", err)
return fmt.Errorf("unable to load parser dump result: %s", err)
}
bucketStateDump, err := hubtest.LoadBucketPourDump(bucketStateDumpFile)
if err != nil {
log.Fatalf("unable to load bucket dump result: %s", err)
return fmt.Errorf("unable to load bucket dump result: %s", err)
}
hubtest.DumpTree(*parserDump, *bucketStateDump, opts)

View file

@ -33,12 +33,14 @@ func NewHubTestCmd() *cobra.Command {
Long: "Run functional tests on hub configurations (parsers, scenarios, collections...)",
Args: cobra.ExactArgs(0),
DisableAutoGenTag: true,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
var err error
HubTest, err = hubtest.NewHubTest(hubPath, crowdsecPath, cscliPath)
if err != nil {
log.Fatalf("unable to load hubtest: %+v", err)
return fmt.Errorf("unable to load hubtest: %+v", err)
}
return nil
},
}
cmdHubTest.PersistentFlags().StringVar(&hubPath, "hub", ".", "Path to hub folder")
@ -74,19 +76,19 @@ cscli hubtest create my-nginx-custom-test --type nginx
cscli hubtest create my-scenario-test --parsers crowdsecurity/nginx --scenarios crowdsecurity/http-probing`,
Args: cobra.ExactArgs(1),
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
testName := args[0]
testPath := filepath.Join(HubTest.HubTestPath, testName)
if _, err := os.Stat(testPath); os.IsExist(err) {
log.Fatalf("test '%s' already exists in '%s', exiting", testName, testPath)
return fmt.Errorf("test '%s' already exists in '%s', exiting", testName, testPath)
}
if logType == "" {
log.Fatalf("please provide a type (--type) for the test")
return fmt.Errorf("please provide a type (--type) for the test")
}
if err := os.MkdirAll(testPath, os.ModePerm); err != nil {
log.Fatalf("unable to create folder '%s': %+v", testPath, err)
return fmt.Errorf("unable to create folder '%s': %+v", testPath, err)
}
// create empty log file
@ -94,7 +96,7 @@ cscli hubtest create my-scenario-test --parsers crowdsecurity/nginx --scenarios
logFilePath := filepath.Join(testPath, logFileName)
logFile, err := os.Create(logFilePath)
if err != nil {
log.Fatal(err)
return err
}
logFile.Close()
@ -102,7 +104,7 @@ cscli hubtest create my-scenario-test --parsers crowdsecurity/nginx --scenarios
parserAssertFilePath := filepath.Join(testPath, hubtest.ParserAssertFileName)
parserAssertFile, err := os.Create(parserAssertFilePath)
if err != nil {
log.Fatal(err)
return err
}
parserAssertFile.Close()
@ -110,7 +112,7 @@ cscli hubtest create my-scenario-test --parsers crowdsecurity/nginx --scenarios
scenarioAssertFilePath := filepath.Join(testPath, hubtest.ScenarioAssertFileName)
scenarioAssertFile, err := os.Create(scenarioAssertFilePath)
if err != nil {
log.Fatal(err)
return err
}
scenarioAssertFile.Close()
@ -138,18 +140,18 @@ cscli hubtest create my-scenario-test --parsers crowdsecurity/nginx --scenarios
configFilePath := filepath.Join(testPath, "config.yaml")
fd, err := os.OpenFile(configFilePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
if err != nil {
log.Fatalf("open: %s", err)
return fmt.Errorf("open: %s", err)
}
data, err := yaml.Marshal(configFileData)
if err != nil {
log.Fatalf("marshal: %s", err)
return fmt.Errorf("marshal: %s", err)
}
_, err = fd.Write(data)
if err != nil {
log.Fatalf("write: %s", err)
return fmt.Errorf("write: %s", err)
}
if err := fd.Close(); err != nil {
log.Fatalf(" close: %s", err)
return fmt.Errorf("close: %s", err)
}
fmt.Println()
fmt.Printf(" Test name : %s\n", testName)
@ -159,6 +161,7 @@ cscli hubtest create my-scenario-test --parsers crowdsecurity/nginx --scenarios
fmt.Printf(" Scenario assertion file : %s (please fill it with assertion)\n", scenarioAssertFilePath)
fmt.Printf(" Configuration File : %s (please fill it with parsers, scenarios...)\n", configFilePath)
return nil
},
}
cmdHubTestCreate.PersistentFlags().StringVarP(&logType, "type", "t", "", "Log type of the test")
@ -180,22 +183,21 @@ func NewHubTestRunCmd() *cobra.Command {
Use: "run",
Short: "run [test_name]",
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
if !runAll && len(args) == 0 {
printHelp(cmd)
fmt.Println("Please provide test to run or --all flag")
os.Exit(1)
return fmt.Errorf("Please provide test to run or --all flag")
}
if runAll {
if err := HubTest.LoadAllTests(); err != nil {
log.Fatalf("unable to load all tests: %+v", err)
return fmt.Errorf("unable to load all tests: %+v", err)
}
} else {
for _, testName := range args {
_, err := HubTest.LoadTestItem(testName)
if err != nil {
log.Fatalf("unable to load test '%s': %s", testName, err)
return fmt.Errorf("unable to load test '%s': %s", testName, err)
}
}
}
@ -210,8 +212,9 @@ func NewHubTestRunCmd() *cobra.Command {
}
}
return nil
},
PersistentPostRun: func(cmd *cobra.Command, args []string) {
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
success := true
testResult := make(map[string]bool)
for _, test := range HubTest.Tests {
@ -228,7 +231,7 @@ func NewHubTestRunCmd() *cobra.Command {
}
if !noClean {
if err := test.Clean(); err != nil {
log.Fatalf("unable to clean test '%s' env: %s", test.Name, err)
return fmt.Errorf("unable to clean test '%s' env: %s", test.Name, err)
}
}
fmt.Printf("\nPlease fill your assert file(s) for test '%s', exiting\n", test.Name)
@ -241,7 +244,7 @@ func NewHubTestRunCmd() *cobra.Command {
}
if !noClean {
if err := test.Clean(); err != nil {
log.Fatalf("unable to clean test '%s' env: %s", test.Name, err)
return fmt.Errorf("unable to clean test '%s' env: %s", test.Name, err)
}
}
} else {
@ -278,14 +281,14 @@ func NewHubTestRunCmd() *cobra.Command {
Default: true,
}
if err := survey.AskOne(prompt, &cleanTestEnv); err != nil {
log.Fatalf("unable to ask to remove runtime folder: %s", err)
return fmt.Errorf("unable to ask to remove runtime folder: %s", err)
}
}
}
if cleanTestEnv || forceClean {
if err := test.Clean(); err != nil {
log.Fatalf("unable to clean test '%s' env: %s", test.Name, err)
return fmt.Errorf("unable to clean test '%s' env: %s", test.Name, err)
}
}
}
@ -305,7 +308,7 @@ func NewHubTestRunCmd() *cobra.Command {
}
jsonStr, err := json.Marshal(jsonResult)
if err != nil {
log.Fatalf("unable to json test result: %s", err)
return fmt.Errorf("unable to json test result: %s", err)
}
fmt.Println(string(jsonStr))
}
@ -313,6 +316,8 @@ func NewHubTestRunCmd() *cobra.Command {
if !success {
os.Exit(1)
}
return nil
},
}
cmdHubTestRun.Flags().BoolVar(&noClean, "no-clean", false, "Don't clean runtime environment if test succeed")
@ -329,16 +334,18 @@ func NewHubTestCleanCmd() *cobra.Command {
Short: "clean [test_name]",
Args: cobra.MinimumNArgs(1),
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
for _, testName := range args {
test, err := HubTest.LoadTestItem(testName)
if err != nil {
log.Fatalf("unable to load test '%s': %s", testName, err)
return fmt.Errorf("unable to load test '%s': %s", testName, err)
}
if err := test.Clean(); err != nil {
log.Fatalf("unable to clean test '%s' env: %s", test.Name, err)
return fmt.Errorf("unable to clean test '%s' env: %s", test.Name, err)
}
}
return nil
},
}
@ -352,11 +359,11 @@ func NewHubTestInfoCmd() *cobra.Command {
Short: "info [test_name]",
Args: cobra.MinimumNArgs(1),
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
for _, testName := range args {
test, err := HubTest.LoadTestItem(testName)
if err != nil {
log.Fatalf("unable to load test '%s': %s", testName, err)
return fmt.Errorf("unable to load test '%s': %s", testName, err)
}
fmt.Println()
fmt.Printf(" Test name : %s\n", test.Name)
@ -366,6 +373,8 @@ func NewHubTestInfoCmd() *cobra.Command {
fmt.Printf(" Scenario assertion file : %s\n", filepath.Join(test.Path, hubtest.ScenarioAssertFileName))
fmt.Printf(" Configuration File : %s\n", filepath.Join(test.Path, "config.yaml"))
}
return nil
},
}
@ -378,9 +387,9 @@ func NewHubTestListCmd() *cobra.Command {
Use: "list",
Short: "list",
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
if err := HubTest.LoadAllTests(); err != nil {
log.Fatalf("unable to load all tests: %+v", err)
return fmt.Errorf("unable to load all tests: %s", err)
}
switch csConfig.Cscli.Output {
@ -389,12 +398,14 @@ func NewHubTestListCmd() *cobra.Command {
case "json":
j, err := json.MarshalIndent(HubTest.Tests, " ", " ")
if err != nil {
log.Fatal(err)
return err
}
fmt.Println(string(j))
default:
log.Fatalf("only human/json output modes are supported")
return fmt.Errorf("only human/json output modes are supported")
}
return nil
},
}
@ -411,9 +422,9 @@ func NewHubTestCoverageCmd() *cobra.Command {
Use: "coverage",
Short: "coverage",
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
if err := HubTest.LoadAllTests(); err != nil {
log.Fatalf("unable to load all tests: %+v", err)
return fmt.Errorf("unable to load all tests: %+v", err)
}
var err error
scenarioCoverage := []hubtest.ScenarioCoverage{}
@ -427,7 +438,7 @@ func NewHubTestCoverageCmd() *cobra.Command {
if showParserCov || showAll {
parserCoverage, err = HubTest.GetParsersCoverage()
if err != nil {
log.Fatalf("while getting parser coverage : %s", err)
return fmt.Errorf("while getting parser coverage: %s", err)
}
parserTested := 0
for _, test := range parserCoverage {
@ -441,7 +452,7 @@ func NewHubTestCoverageCmd() *cobra.Command {
if showScenarioCov || showAll {
scenarioCoverage, err = HubTest.GetScenariosCoverage()
if err != nil {
log.Fatalf("while getting scenario coverage: %s", err)
return fmt.Errorf("while getting scenario coverage: %s", err)
}
scenarioTested := 0
for _, test := range scenarioCoverage {
@ -481,18 +492,19 @@ func NewHubTestCoverageCmd() *cobra.Command {
} else if csConfig.Cscli.Output == "json" {
dump, err := json.MarshalIndent(parserCoverage, "", " ")
if err != nil {
log.Fatal(err)
return err
}
fmt.Printf("%s", dump)
dump, err = json.MarshalIndent(scenarioCoverage, "", " ")
if err != nil {
log.Fatal(err)
return err
}
fmt.Printf("%s", dump)
} else {
log.Fatalf("only human/json output modes are supported")
return fmt.Errorf("only human/json output modes are supported")
}
return nil
},
}
cmdHubTestCoverage.PersistentFlags().BoolVar(&showOnlyPercent, "percent", false, "Show only percentages of coverage")
@ -510,22 +522,24 @@ func NewHubTestEvalCmd() *cobra.Command {
Short: "eval [test_name]",
Args: cobra.ExactArgs(1),
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
for _, testName := range args {
test, err := HubTest.LoadTestItem(testName)
if err != nil {
log.Fatalf("can't load test: %+v", err)
return fmt.Errorf("can't load test: %+v", err)
}
err = test.ParserAssert.LoadTest(test.ParserResultFile)
if err != nil {
log.Fatalf("can't load test results from '%s': %+v", test.ParserResultFile, err)
return fmt.Errorf("can't load test results from '%s': %+v", test.ParserResultFile, err)
}
output, err := test.ParserAssert.EvalExpression(evalExpression)
if err != nil {
log.Fatal(err)
return err
}
fmt.Print(output)
}
return nil
},
}
cmdHubTestEval.PersistentFlags().StringVarP(&evalExpression, "expr", "e", "", "Expression to eval")
@ -540,21 +554,21 @@ func NewHubTestExplainCmd() *cobra.Command {
Short: "explain [test_name]",
Args: cobra.ExactArgs(1),
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
for _, testName := range args {
test, err := HubTest.LoadTestItem(testName)
if err != nil {
log.Fatalf("can't load test: %+v", err)
return fmt.Errorf("can't load test: %+v", err)
}
err = test.ParserAssert.LoadTest(test.ParserResultFile)
if err != nil {
err := test.Run()
if err != nil {
log.Fatalf("running test '%s' failed: %+v", test.Name, err)
return fmt.Errorf("running test '%s' failed: %+v", test.Name, err)
}
err = test.ParserAssert.LoadTest(test.ParserResultFile)
if err != nil {
log.Fatalf("unable to load parser result after run: %s", err)
return fmt.Errorf("unable to load parser result after run: %s", err)
}
}
@ -562,16 +576,18 @@ func NewHubTestExplainCmd() *cobra.Command {
if err != nil {
err := test.Run()
if err != nil {
log.Fatalf("running test '%s' failed: %+v", test.Name, err)
return fmt.Errorf("running test '%s' failed: %+v", test.Name, err)
}
err = test.ScenarioAssert.LoadTest(test.ScenarioResultFile, test.BucketPourResultFile)
if err != nil {
log.Fatalf("unable to load scenario result after run: %s", err)
return fmt.Errorf("unable to load scenario result after run: %s", err)
}
}
opts := hubtest.DumpOpts{}
hubtest.DumpTree(*test.ParserAssert.TestData, *test.ScenarioAssert.PourData, opts)
}
return nil
},
}

View file

@ -16,7 +16,6 @@ import (
"github.com/fatih/color"
"github.com/go-openapi/strfmt"
"github.com/google/uuid"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
@ -67,7 +66,7 @@ func generateIDPrefix() (string, error) {
if err == nil {
return bId.String(), nil
}
return "", errors.Wrap(err, "generating machine id")
return "", fmt.Errorf("generating machine id: %w", err)
}
// Generate a unique identifier, composed by a prefix and a random suffix.
@ -114,14 +113,14 @@ func getAgents(out io.Writer, dbClient *database.Client) error {
enc := json.NewEncoder(out)
enc.SetIndent("", " ")
if err := enc.Encode(machines); err != nil {
log.Fatalf("failed to unmarshal")
return fmt.Errorf("failed to marshal")
}
return nil
} else if csConfig.Cscli.Output == "raw" {
csvwriter := csv.NewWriter(out)
err := csvwriter.Write([]string{"machine_id", "ip_address", "updated_at", "validated", "version", "auth_type", "last_heartbeat"})
if err != nil {
log.Fatalf("failed to write header: %s", err)
return fmt.Errorf("failed to write header: %s", err)
}
for _, m := range machines {
var validated string
@ -132,7 +131,7 @@ func getAgents(out io.Writer, dbClient *database.Client) error {
}
err := csvwriter.Write([]string{m.MachineId, m.IpAddress, m.UpdatedAt.Format(time.RFC3339), validated, m.Version, m.AuthType, displayLastHeartBeat(m, false)})
if err != nil {
log.Fatalf("failed to write raw output : %s", err)
return fmt.Errorf("failed to write raw output : %s", err)
}
}
csvwriter.Flush()
@ -150,18 +149,22 @@ func NewMachinesListCmd() *cobra.Command {
Example: `cscli machines list`,
Args: cobra.MaximumNArgs(1),
DisableAutoGenTag: true,
PreRun: func(cmd *cobra.Command, args []string) {
PreRunE: func(cmd *cobra.Command, args []string) error {
var err error
dbClient, err = database.NewClient(csConfig.DbConfig)
if err != nil {
log.Fatalf("unable to create new database client: %s", err)
return fmt.Errorf("unable to create new database client: %s", err)
}
return nil
},
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
err := getAgents(color.Output, dbClient)
if err != nil {
log.Fatalf("unable to list machines: %s", err)
return fmt.Errorf("unable to list machines: %s", err)
}
return nil
},
}
@ -179,12 +182,14 @@ cscli machines add --auto
cscli machines add MyTestMachine --auto
cscli machines add MyTestMachine --password MyPassword
`,
PreRun: func(cmd *cobra.Command, args []string) {
PreRunE: func(cmd *cobra.Command, args []string) error {
var err error
dbClient, err = database.NewClient(csConfig.DbConfig)
if err != nil {
log.Fatalf("unable to create new database client: %s", err)
return fmt.Errorf("unable to create new database client: %s", err)
}
return nil
},
RunE: runMachinesAdd,
}
@ -246,7 +251,7 @@ func runMachinesAdd(cmd *cobra.Command, args []string) error {
}
machineID, err = generateID("")
if err != nil {
log.Fatalf("unable to generate machine id : %s", err)
return fmt.Errorf("unable to generate machine id: %s", err)
}
} else {
machineID = args[0]
@ -275,7 +280,7 @@ func runMachinesAdd(cmd *cobra.Command, args []string) error {
password := strfmt.Password(machinePassword)
_, err = dbClient.CreateMachine(&machineID, &password, "", true, forceAdd, types.PasswordAuthType)
if err != nil {
log.Fatalf("unable to create machine: %s", err)
return fmt.Errorf("unable to create machine: %s", err)
}
log.Infof("Machine '%s' successfully added to the local API", machineID)
@ -285,7 +290,7 @@ func runMachinesAdd(cmd *cobra.Command, args []string) error {
} else if csConfig.API.Server != nil && csConfig.API.Server.ListenURI != "" {
apiURL = "http://" + csConfig.API.Server.ListenURI
} else {
log.Fatalf("unable to dump an api URL. Please provide it in your configuration or with the -u parameter")
return fmt.Errorf("unable to dump an api URL. Please provide it in your configuration or with the -u parameter")
}
}
apiCfg := csconfig.ApiCredentialsCfg{
@ -295,12 +300,12 @@ func runMachinesAdd(cmd *cobra.Command, args []string) error {
}
apiConfigDump, err := yaml.Marshal(apiCfg)
if err != nil {
log.Fatalf("unable to marshal api credentials: %s", err)
return fmt.Errorf("unable to marshal api credentials: %s", err)
}
if dumpFile != "" && dumpFile != "-" {
err = os.WriteFile(dumpFile, apiConfigDump, 0644)
if err != nil {
log.Fatalf("write api credentials in '%s' failed: %s", dumpFile, err)
return fmt.Errorf("write api credentials in '%s' failed: %s", dumpFile, err)
}
log.Printf("API credentials dumped to '%s'", dumpFile)
} else {
@ -318,12 +323,13 @@ func NewMachinesDeleteCmd() *cobra.Command {
Args: cobra.MinimumNArgs(1),
Aliases: []string{"remove"},
DisableAutoGenTag: true,
PreRun: func(cmd *cobra.Command, args []string) {
PreRunE: func(cmd *cobra.Command, args []string) error {
var err error
dbClient, err = database.NewClient(csConfig.DbConfig)
if err != nil {
log.Fatalf("unable to create new database client: %s", err)
return fmt.Errorf("unable to create new database client: %s", err)
}
return nil
},
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
var err error
@ -371,19 +377,23 @@ func NewMachinesValidateCmd() *cobra.Command {
Example: `cscli machines validate "machine_name"`,
Args: cobra.ExactArgs(1),
DisableAutoGenTag: true,
PreRun: func(cmd *cobra.Command, args []string) {
PreRunE: func(cmd *cobra.Command, args []string) error {
var err error
dbClient, err = database.NewClient(csConfig.DbConfig)
if err != nil {
log.Fatalf("unable to create new database client: %s", err)
return fmt.Errorf("unable to create new database client: %s", err)
}
return nil
},
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
machineID := args[0]
if err := dbClient.ValidateMachine(machineID); err != nil {
log.Fatalf("unable to validate machine '%s': %s", machineID, err)
return fmt.Errorf("unable to validate machine '%s': %s", machineID, err)
}
log.Infof("machine '%s' validated successfully", machineID)
return nil
},
}
@ -400,13 +410,15 @@ Note: This command requires database direct access, so is intended to be run on
Example: `cscli machines [action]`,
DisableAutoGenTag: true,
Aliases: []string{"machine"},
PersistentPreRun: func(cmd *cobra.Command, args []string) {
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
if err := csConfig.LoadAPIServer(); err != nil || csConfig.DisableAPI {
if err != nil {
log.Errorf("local api : %s", err)
}
log.Fatal("Local API is disabled, please run this command on the local API machine")
return fmt.Errorf("local API is disabled, please run this command on the local API machine")
}
return nil
},
}

View file

@ -178,10 +178,11 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall
Args: cobra.ExactArgs(0),
Hidden: true,
DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
if err := doc.GenMarkdownTreeCustom(rootCmd, "./doc/", prepender, linkHandler); err != nil {
log.Fatalf("Failed to generate cobra doc: %s", err)
return fmt.Errorf("Failed to generate cobra doc: %s", err)
}
return nil
},
}
rootCmd.AddCommand(cmdDocGen)

View file

@ -19,6 +19,7 @@ setup() {
}
teardown() {
cd "$TEST_DIR" || exit 1
./instance-crowdsec stop
}
@ -297,3 +298,25 @@ declare stderr
rune -0 cscli config show --key Config.DbConfig.Password
assert_output 'P@ssw0rd$'
}
@test "cscli doc" {
# generating documentation requires a directory named "doc"
cd "$BATS_TEST_TMPDIR"
rune -1 cscli doc
refute_output
assert_stderr --regexp 'Failed to generate cobra doc: open doc/.*: no such file or directory'
mkdir -p doc
rune -0 cscli doc
refute_output
refute_stderr
assert_file_exist "doc/cscli.md"
assert_file_not_exist "doc/cscli_setup.md"
# commands guarded by feature flags are not documented unless the feature flag is set
export CROWDSEC_FEATURE_CSCLI_SETUP="true"
rune -0 cscli doc
assert_file_exist "doc/cscli_setup.md"
}

View file

@ -75,7 +75,7 @@ teardown() {
config_disable_lapi
./instance-crowdsec start || true
run -1 --separate-stderr cscli machines list
assert_stderr --partial "Local API is disabled, please run this command on the local API machine"
assert_stderr --partial "local API is disabled, please run this command on the local API machine"
}
@test "cscli metrics" {
@ -87,5 +87,5 @@ teardown() {
assert_output --partial "/v1/watchers/login"
assert_stderr --partial "crowdsec local API is disabled"
assert_stderr --partial "Local API is disabled, please run this command on the local API machine"
assert_stderr --partial "local API is disabled, please run this command on the local API machine"
}

View file

@ -66,6 +66,9 @@ teardown() {
}
@test "cscli alerts inspect" {
rune -1 cscli alerts inspect
assert_stderr --partial 'missing alert_id'
run -0 cscli decisions add -i 10.20.30.40 -t ban
run -0 cscli alerts list -o raw <(output)
run -0 grep 10.20.30.40 <(output)
@ -143,7 +146,7 @@ teardown() {
# can't delete twice
run -1 --separate-stderr cscli alerts delete --id "$ALERT_ID"
refute_output
assert_stderr --partial "Unable to delete alert"
assert_stderr --partial "unable to delete alert"
assert_stderr --partial "API error: ent: alert not found"
}