Files
argo-cd/util/exec/exec.go
2024-08-06 16:41:35 -04:00

91 lines
2.4 KiB
Go

package exec
import (
"fmt"
"os"
"os/exec"
"strconv"
"strings"
"time"
"unicode"
"github.com/argoproj/gitops-engine/pkg/utils/tracing"
argoexec "github.com/argoproj/pkg/exec"
"github.com/argoproj/argo-cd/v2/util/log"
)
var timeout time.Duration
type ExecRunOpts struct {
// Redactor redacts tokens from the output
Redactor func(text string) string
// TimeoutBehavior configures what to do in case of timeout
TimeoutBehavior argoexec.TimeoutBehavior
// SkipErrorLogging determines whether to skip logging of execution errors (rc > 0)
SkipErrorLogging bool
// CaptureStderr determines whether to capture stderr in addition to stdout
CaptureStderr bool
}
func init() {
initTimeout()
}
func initTimeout() {
var err error
timeout, err = time.ParseDuration(os.Getenv("ARGOCD_EXEC_TIMEOUT"))
if err != nil {
timeout = 90 * time.Second
}
}
func Run(cmd *exec.Cmd) (string, error) {
return RunWithRedactor(cmd, nil)
}
func RunWithRedactor(cmd *exec.Cmd, redactor func(text string) string) (string, error) {
opts := ExecRunOpts{Redactor: redactor}
return RunWithExecRunOpts(cmd, opts)
}
func RunWithExecRunOpts(cmd *exec.Cmd, opts ExecRunOpts) (string, error) {
cmdOpts := argoexec.CmdOpts{Timeout: timeout, Redactor: opts.Redactor, TimeoutBehavior: opts.TimeoutBehavior, SkipErrorLogging: opts.SkipErrorLogging}
span := tracing.NewLoggingTracer(log.NewLogrusLogger(log.NewWithCurrentConfig())).StartSpan(fmt.Sprintf("exec %v", cmd.Args[0]))
span.SetBaggageItem("dir", fmt.Sprintf("%v", cmd.Dir))
if cmdOpts.Redactor != nil {
span.SetBaggageItem("args", opts.Redactor(fmt.Sprintf("%v", cmd.Args)))
} else {
span.SetBaggageItem("args", fmt.Sprintf("%v", cmd.Args))
}
defer span.Finish()
return argoexec.RunCommandExt(cmd, cmdOpts)
}
// GetCommandArgsToLog represents the given command in a way that we can copy-and-paste into a terminal
func GetCommandArgsToLog(cmd *exec.Cmd) string {
var argsToLog []string
for _, arg := range cmd.Args {
if arg == "" {
argsToLog = append(argsToLog, `""`)
continue
}
containsSpace := false
for _, r := range arg {
if unicode.IsSpace(r) {
containsSpace = true
break
}
}
if containsSpace {
// add quotes and escape any internal quotes
argsToLog = append(argsToLog, strconv.Quote(arg))
} else {
argsToLog = append(argsToLog, arg)
}
}
args := strings.Join(argsToLog, " ")
return args
}