Created
June 14, 2022 15:53
-
-
Save LiFeAiR/93cd7f9602b09047e66b95ed5d0560d6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package exechelper | |
import ( | |
"bytes" | |
"fmt" | |
"os/exec" | |
) | |
type DockerExecParams struct { | |
ContainerName string | |
Mounts map[string]string | |
CommandArgs []string | |
CmdImplementation execCmd | |
} | |
type execCmd interface { | |
Command(name string, arg ...string) *exec.Cmd | |
SetStdout(*bytes.Buffer) | |
SetStderr(*bytes.Buffer) | |
GetExitCode() int | |
Run() error | |
} | |
type ec struct { | |
*exec.Cmd | |
} | |
func (e *ec) Command(name string, arg ...string) *exec.Cmd { | |
e.Cmd = exec.Command(name, arg...) | |
return e.Cmd | |
} | |
func (e *ec) SetStdout(b *bytes.Buffer) { | |
e.Cmd.Stdout = b | |
} | |
func (e *ec) SetStderr(b *bytes.Buffer) { | |
e.Cmd.Stderr = b | |
} | |
func (e *ec) GetExitCode() int { | |
return e.Cmd.ProcessState.ExitCode() | |
} | |
func (e *ec) Run() error { | |
return e.Cmd.Run() | |
} | |
func dockerPullIfNotExists(params *DockerExecParams) error { | |
ci := params.CmdImplementation | |
ci.Command("docker", "image", "inspect", params.ContainerName) | |
var stdOutBytes, stdErrBytes bytes.Buffer | |
ci.SetStdout(&stdOutBytes) | |
ci.SetStderr(&stdErrBytes) | |
err := ci.Run() | |
if err != nil { | |
ci.Command("docker", "pull", params.ContainerName) | |
return ci.Run() | |
} | |
return nil | |
} | |
func DockerExec(params *DockerExecParams) (string, string, int, error) { | |
if params.CmdImplementation == nil { | |
params.CmdImplementation = &ec{} | |
} | |
err := dockerPullIfNotExists(params) | |
if err != nil { | |
return "", "", 1, fmt.Errorf("error pulling docker container %s: %w", params.ContainerName, err) | |
} | |
cmdArgs := []string{"run", "-i", "--rm"} | |
for mountPoint, mountPath := range params.Mounts { | |
cmdArgs = append(cmdArgs, "-v", mountPoint+":"+mountPath) | |
} | |
cmdArgs = append(cmdArgs, params.ContainerName) | |
cmdArgs = append(cmdArgs, params.CommandArgs...) | |
ci := params.CmdImplementation | |
ci.Command("docker", cmdArgs...) | |
var stdOutBytes, stdErrBytes bytes.Buffer | |
ci.SetStdout(&stdOutBytes) | |
ci.SetStderr(&stdErrBytes) | |
err = ci.Run() | |
return stdOutBytes.String(), stdErrBytes.String(), ci.GetExitCode(), err | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package exechelper | |
import ( | |
"bytes" | |
"os" | |
"os/exec" | |
"testing" | |
) | |
type mockCmdImplementation struct { | |
*exec.Cmd | |
} | |
func (e *mockCmdImplementation) Command(name string, arg ...string) *exec.Cmd { | |
e.Cmd = exec.Command(name, arg...) | |
return e.Cmd | |
} | |
func (e *mockCmdImplementation) SetStdout(b *bytes.Buffer) { | |
e.Cmd.Stdout = b | |
} | |
func (e *mockCmdImplementation) SetStderr(b *bytes.Buffer) { | |
e.Cmd.Stderr = b | |
} | |
func (e *mockCmdImplementation) GetExitCode() int { | |
return e.Cmd.ProcessState.ExitCode() | |
} | |
func (i *mockCmdImplementation) Run() error { | |
i.Cmd.ProcessState = &os.ProcessState{} | |
_, _ = i.Stdout.Write([]byte("hello")) | |
_, _ = i.Stdout.Write([]byte("")) | |
return nil | |
} | |
func NewMockCmdImplementation() *mockCmdImplementation { | |
return &mockCmdImplementation{} | |
} | |
func TestDockerExec(t *testing.T) { | |
type args struct { | |
params *DockerExecParams | |
} | |
tests := []struct { | |
name string | |
args args | |
want string | |
want1 string | |
want2 int | |
wantErr bool | |
}{ | |
{"HelloWorld", | |
args{&DockerExecParams{ | |
ContainerName: "hello-world", | |
CmdImplementation: &mockCmdImplementation{}, | |
}, | |
}, "hello", "", 0, false}, | |
} | |
for _, tt := range tests { | |
t.Run(tt.name, func(t *testing.T) { | |
got, got1, got2, err := DockerExec(tt.args.params) | |
if (err != nil) != tt.wantErr { | |
t.Errorf("DockerExec() error = %v, wantErr %v", err, tt.wantErr) | |
return | |
} | |
if got != tt.want { | |
t.Errorf("DockerExec() got = %v, want %v", got, tt.want) | |
} | |
if got1 != tt.want1 { | |
t.Errorf("DockerExec() got1 = %v, want %v", got1, tt.want1) | |
} | |
if got2 != tt.want2 { | |
t.Errorf("DockerExec() got2 = %v, want %v", got2, tt.want2) | |
} | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment