package cli
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"runtime"
|
|
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
// RunWithArgs executes the given command with the specified command line args
|
|
// and environmental variables set. It returns any error returned from cmd.Execute()
|
|
//
|
|
// This is only used in testing.
|
|
func RunWithArgs(ctx context.Context, cmd *cobra.Command, args []string, env map[string]string) error {
|
|
oargs := os.Args
|
|
oenv := map[string]string{}
|
|
// defer returns the environment back to normal
|
|
defer func() {
|
|
os.Args = oargs
|
|
for k, v := range oenv {
|
|
os.Setenv(k, v)
|
|
}
|
|
}()
|
|
|
|
// set the args and env how we want them
|
|
os.Args = args
|
|
for k, v := range env {
|
|
// backup old value if there, to restore at end
|
|
oenv[k] = os.Getenv(k)
|
|
err := os.Setenv(k, v)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// and finally run the command
|
|
return RunWithTrace(ctx, cmd)
|
|
}
|
|
|
|
func RunWithTrace(ctx context.Context, cmd *cobra.Command) error {
|
|
cmd.SilenceUsage = true
|
|
cmd.SilenceErrors = true
|
|
|
|
if err := cmd.ExecuteContext(ctx); err != nil {
|
|
if viper.GetBool(TraceFlag) {
|
|
const size = 64 << 10
|
|
buf := make([]byte, size)
|
|
buf = buf[:runtime.Stack(buf, false)]
|
|
fmt.Fprintf(os.Stderr, "ERROR: %v\n%s\n", err, buf)
|
|
} else {
|
|
fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
|
|
}
|
|
|
|
return err
|
|
}
|
|
return nil
|
|
}
|