databricks-cli/libs/process/background.go

60 lines
1.3 KiB
Go
Raw Normal View History

package process
import (
"bytes"
"context"
"fmt"
"os/exec"
"strings"
"github.com/databricks/cli/libs/env"
"github.com/databricks/cli/libs/log"
)
type ProcessError struct {
Command string
Err error
Stdout string
Stderr string
}
func (perr *ProcessError) Unwrap() error {
return perr.Err
}
func (perr *ProcessError) Error() string {
return fmt.Sprintf("%s: %s", perr.Command, perr.Err)
}
func Background(ctx context.Context, args []string, opts ...execOption) (string, error) {
commandStr := strings.Join(args, " ")
log.Debugf(ctx, "running: %s", commandStr)
cmd := exec.CommandContext(ctx, args[0], args[1:]...)
stdout := bytes.Buffer{}
stderr := bytes.Buffer{}
// For background processes, there's no standard input
cmd.Stdin = nil
cmd.Stdout = &stdout
cmd.Stderr = &stderr
// we pull the env through lib/env such that we can run
// parallel tests with anything using libs/process.
for k, v := range env.All(ctx) {
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", k, v))
}
for _, o := range opts {
err := o(ctx, cmd)
if err != nil {
return "", err
}
}
if err := cmd.Run(); err != nil {
return stdout.String(), &ProcessError{
Err: err,
Command: commandStr,
Stdout: stdout.String(),
Stderr: stderr.String(),
}
}
return stdout.String(), nil
}