From d8401a4d869449aa1ef4e624dffe2e1eed22ff51 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Mon, 12 Feb 2024 20:58:51 -0500 Subject: [PATCH] refactor: remove all calls to common.NewShellCmdWithArgs --- plugins/app-json/functions.go | 67 ++++++++++++----------------------- plugins/common/docker.go | 26 ++++++++++++++ plugins/common/exec.go | 12 +++++++ plugins/common/log.go | 27 ++++++++------ 4 files changed, 76 insertions(+), 56 deletions(-) diff --git a/plugins/app-json/functions.go b/plugins/app-json/functions.go index ee2a9e690..b5cf991b3 100644 --- a/plugins/app-json/functions.go +++ b/plugins/app-json/functions.go @@ -1,7 +1,6 @@ package appjson import ( - "bytes" "context" "encoding/json" "errors" @@ -332,13 +331,16 @@ func executeScript(appName string, image string, imageTag string, phase string) fmt.Sprintf("LABEL com.dokku.%s-phase=true", phase), }...) commitArgs = append(commitArgs, containerID, image) - containerCommitCmd := common.NewShellCmdWithArgs( - common.DockerBin(), - commitArgs..., - ) - containerCommitCmd.ShowOutput = false - containerCommitCmd.Command.Stderr = os.Stderr - if !containerCommitCmd.Execute() { + result, err := common.CallExecCommand(common.ExecCommandInput{ + Command: common.DockerBin(), + Args: commitArgs, + StreamStderr: true, + }) + if err != nil { + return fmt.Errorf("Commiting of '%s' to image failed: %w", phase, err) + } + + if result.ExitCode != 0 { return fmt.Errorf("Commiting of '%s' to image failed: %s", phase, command) } @@ -390,34 +392,11 @@ func getCommandFromImage(image string) (string, error) { } func waitForExecution(containerID string) bool { - containerStartCmd := common.NewShellCmdWithArgs( - common.DockerBin(), - "container", - "start", - containerID, - ) - containerStartCmd.ShowOutput = false - containerStartCmd.Command.Stderr = os.Stderr - if !containerStartCmd.Execute() { + if !common.ContainerStart(containerID) { return false } - containerWaitCmd := common.NewShellCmdWithArgs( - common.DockerBin(), - "container", - "wait", - containerID, - ) - - containerWaitCmd.ShowOutput = false - containerWaitCmd.Command.Stderr = os.Stderr - b, err := containerWaitCmd.Output() - if err != nil { - return false - } - - containerExitCode := strings.TrimSpace(string(b[:])) - return containerExitCode == "0" + return common.ContainerWait(containerID) } func createdContainerID(appName string, dockerArgs []string, image string, command []string, phase string) (string, error) { @@ -440,21 +419,19 @@ func createdContainerID(appName string, dockerArgs []string, image string, comma return "", err } - containerCreateCmd := common.NewShellCmdWithArgs( - common.DockerBin(), - arguments..., - ) - var stderr bytes.Buffer - containerCreateCmd.Env = env - containerCreateCmd.ShowOutput = false - containerCreateCmd.Command.Stderr = &stderr - - b, err = containerCreateCmd.Output() + result, err := common.CallExecCommand(common.ExecCommandInput{ + Command: common.DockerBin(), + Args: arguments, + Env: env, + }) if err != nil { - return "", errors.New(stderr.String()) + return "", err + } + if result.ExitCode != 0 { + return "", errors.New(result.StderrContents()) } - containerID := strings.TrimSpace(string(b)) + containerID := result.StdoutContents() err = common.PlugnTrigger("post-container-create", []string{"app", containerID, appName, phase}...) return containerID, err } diff --git a/plugins/common/docker.go b/plugins/common/docker.go index 354bb2405..def86cd61 100644 --- a/plugins/common/docker.go +++ b/plugins/common/docker.go @@ -18,6 +18,19 @@ func ContainerIsRunning(containerID string) bool { return strings.TrimSpace(string(b[:])) == "true" } +// ContainerStart runs 'docker container start' against an existing container +func ContainerStart(containerID string) bool { + result, err := CallExecCommand(ExecCommandInput{ + Command: DockerBin(), + Args: []string{"container", "start", containerID}, + StreamStderr: true, + }) + if err != nil { + return false + } + return result.ExitCode == 0 +} + // ContainerRemove runs 'docker container remove' against an existing container func ContainerRemove(containerID string) bool { result, err := CallExecCommand(ExecCommandInput{ @@ -43,6 +56,19 @@ func ContainerExists(containerID string) bool { return result.ExitCode == 0 } +// ContainerWait runs 'docker container wait' against an existing container +func ContainerWait(containerID string) bool { + result, err := CallExecCommand(ExecCommandInput{ + Command: DockerBin(), + Args: []string{"container", "wait", containerID}, + StreamStderr: true, + }) + if err != nil { + return false + } + return result.ExitCode == 0 +} + // ContainerWaitTilReady will wait timeout seconds and then check if a container is running // returning an error if it is not running at the end of the timeout func ContainerWaitTilReady(containerID string, timeout time.Duration) error { diff --git a/plugins/common/exec.go b/plugins/common/exec.go index c114f1d86..2db72046d 100644 --- a/plugins/common/exec.go +++ b/plugins/common/exec.go @@ -42,6 +42,12 @@ type ExecCommandInput struct { // StreamStderr prints stderr directly to os.Stderr as the command runs. StreamStderr bool + // StdoutWriter is the writer to write stdout to + StdoutWriter io.Writer + + // StderrWriter is the writer to write stderr to + StderrWriter io.Writer + // Sudo runs the command with sudo -n -u root Sudo bool } @@ -137,6 +143,12 @@ func CallExecCommandWithContext(ctx context.Context, input ExecCommandInput) (Ex if input.StreamStderr { cmd.StdErrWriter = os.Stderr } + if input.StdoutWriter != nil { + cmd.StdOutWriter = input.StdoutWriter + } + if input.StderrWriter != nil { + cmd.StdErrWriter = input.StderrWriter + } res, err := cmd.Execute(ctx) if err != nil { diff --git a/plugins/common/log.go b/plugins/common/log.go index 79401d958..50234a0fc 100644 --- a/plugins/common/log.go +++ b/plugins/common/log.go @@ -174,22 +174,27 @@ func LogVerboseQuietContainerLogsTail(containerID string, lines int, tail bool) args = append(args, "--follow") } - sc := NewShellCmdWithArgs(DockerBin(), args...) var mu sync.Mutex - sc.Command.Stdout = &writer{ - mu: &mu, - source: "stdout", - } - sc.Command.Stderr = &writer{ - mu: &mu, - source: "stderr", - } + result, err := CallExecCommand(ExecCommandInput{ + Command: DockerBin(), + Args: args, + DisableStdioBuffer: true, + StdoutWriter: &writer{ + mu: &mu, + source: "stdout", + }, + StderrWriter: &writer{ + mu: &mu, + source: "stderr", + }, + }) - if err := sc.Command.Start(); err != nil { + if err != nil { LogExclaim(fmt.Sprintf("Failed to fetch container logs: %s", containerID)) + return } - if err := sc.Command.Wait(); err != nil { + if !tail && result.ExitCode != 0 { LogExclaim(fmt.Sprintf("Failed to fetch container logs: %s", containerID)) } }