diff --git a/cli/root.go b/cli/root.go index aad229a86a..4c5451286f 100644 --- a/cli/root.go +++ b/cli/root.go @@ -52,6 +52,7 @@ var ( func initMatchersCompat(_ *kingpin.ParseContext) error { promslogConfig := &promslog.Config{Writer: os.Stdout} if verbose { + promslogConfig.Level = &promslog.AllowedLevel{} _ = promslogConfig.Level.Set("debug") } logger := promslog.New(promslogConfig) @@ -144,7 +145,7 @@ func NewAlertmanagerClient(amURL *url.URL) *client.AlertmanagerAPI { } // Execute is the main function for the amtool command. -func Execute() { +func Execute(args []string) { app := kingpin.New("amtool", helpRoot).UsageWriter(os.Stdout) format.InitFormatFlags(app) @@ -175,12 +176,12 @@ func Execute() { app.Action(initMatchersCompat) - err = resolver.Bind(app, os.Args[1:]) + err = resolver.Bind(app, args[1:]) if err != nil { kingpin.Fatalf("%v\n", err) } - _, err = app.Parse(os.Args[1:]) + _, err = app.Parse(args[1:]) if err != nil { kingpin.Fatalf("%v\n", err) } diff --git a/cmd/amtool/main.go b/cmd/amtool/main.go index 9e36fb9d39..c0cf35dfee 100644 --- a/cmd/amtool/main.go +++ b/cmd/amtool/main.go @@ -13,8 +13,16 @@ package main -import "github.com/prometheus/alertmanager/cli" +import ( + "os" + + "github.com/prometheus/alertmanager/cli" +) func main() { - cli.Execute() + run(os.Args) +} + +func run(args []string) { + cli.Execute(args) } diff --git a/cmd/amtool/main_test.go b/cmd/amtool/main_test.go new file mode 100644 index 0000000000..9abc767e38 --- /dev/null +++ b/cmd/amtool/main_test.go @@ -0,0 +1,103 @@ +// Copyright 2018 Prometheus Team +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "runtime" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestEmptyCommand(t *testing.T) { + for _, tc := range []struct { + name string + args []string + exitCode int + stdout string + stderr string + }{ + { + name: "help without command", + args: []string{}, + exitCode: 0, + stdout: `usage: amtool [] [ ...]`, + }, + { + name: "empty command", + args: []string{""}, + exitCode: 1, + stderr: `error: expected command but got ""`, + }, + { + name: "version", + args: []string{"--version"}, + stdout: fmt.Sprintf("amtool, version (branch: , revision: unknown)\n build user: \n build date: \n go version: %s\n platform: %s/%s\n tags: unknown\n", runtime.Version(), runtime.GOOS, runtime.GOARCH), + }, + // In this test, we a running a command that invokes the --verbose flag. + // The test expects that there is no running instance on port 1. + { + name: "verbose flag", + exitCode: 1, + args: []string{"--verbose", "alert", "add", "--alertmanager.url=http://localhost:1"}, + stderr: `error: Post "http://localhost:1/api/v2/alerts": dial tcp 127.0.0.1:1`, + }, + } { + t.Run(tc.name, func(t *testing.T) { + if os.Getenv("FORK") == "1" { + run(append([]string{"amtool"}, tc.args...)) + } + + stdout, stderr, err := RunForkTest(t) + + if tc.exitCode == 0 { + require.NoError(t, err, "STDOUT:\n%s\n\nSTDERR:\n%s", stdout, stderr) + } else { + require.EqualError(t, err, fmt.Sprintf("exit status %d", tc.exitCode), "STDOUT:\n%s\n\nSTDERR:\n%s", stdout, stderr) + } + + if tc.stderr == "" { + require.Empty(t, stderr) + } else { + require.Contains(t, stderr, tc.stderr) + } + + if tc.stdout == "" { + require.Empty(t, stdout) + } else { + require.Contains(t, stdout, tc.stdout) + } + }) + } +} + +func RunForkTest(t *testing.T) (string, string, error) { + t.Helper() + + cmd := exec.Command(os.Args[0], fmt.Sprintf("-test.run=%v", t.Name())) + cmd.Env = append(os.Environ(), "FORK=1") + + var stdoutB, stderrB bytes.Buffer + cmd.Stdin = nil + cmd.Stdout = &stdoutB + cmd.Stderr = &stderrB + + err := cmd.Run() + + return stdoutB.String(), stderrB.String(), err +}