diff --git a/internal/pkg/docker/dockerengine/dockerengine.go b/internal/pkg/docker/dockerengine/dockerengine.go index 5f216a584b6..7bc919a80fb 100644 --- a/internal/pkg/docker/dockerengine/dockerengine.go +++ b/internal/pkg/docker/dockerengine/dockerengine.go @@ -15,6 +15,7 @@ import ( "os" osexec "os/exec" "path/filepath" + "regexp" "sort" "strings" "sync" @@ -437,8 +438,10 @@ func (d *DockerCmdClient) containerState(ctx context.Context, containerName stri if err := d.runner.RunWithContext(ctx, "docker", []string{"inspect", "--format", "{{json .State}}", containerID}, exec.Stdout(buf)); err != nil { return ContainerState{}, fmt.Errorf("run docker inspect: %w", err) } + // Make sure we unmarshal a valid json string. + out := regexp.MustCompile(`{(.|\n)*}`).FindString(buf.String()) var containerState ContainerState - if err := json.Unmarshal([]byte(strings.TrimSpace(buf.String())), &containerState); err != nil { + if err := json.Unmarshal([]byte(out), &containerState); err != nil { return ContainerState{}, fmt.Errorf("unmarshal state of container %q:%w", containerName, err) } return containerState, nil @@ -477,13 +480,12 @@ func (c DockerCmdClient) CheckDockerEngineRunning() error { return ErrDockerCommandNotFound } buf := &bytes.Buffer{} - err := c.runner.Run("docker", []string{"info", "-f", "'{{json .}}'"}, exec.Stdout(buf)) + err := c.runner.Run("docker", []string{"info", "-f", "json"}, exec.Stdout(buf)) if err != nil { return fmt.Errorf("get docker info: %w", err) } - // Trim redundant prefix and suffix. For example: '{"ServerErrors":["Cannot connect...}'\n returns - // {"ServerErrors":["Cannot connect...} - out := strings.TrimSuffix(strings.TrimPrefix(strings.TrimSpace(buf.String()), "'"), "'") + // Make sure we unmarshal a valid json string. + out := regexp.MustCompile(`{(.|\n)*}`).FindString(buf.String()) type dockerEngineNotRunningMsg struct { ServerErrors []string `json:"ServerErrors"` } @@ -510,7 +512,8 @@ func (c DockerCmdClient) GetPlatform() (os, arch string, err error) { return "", "", fmt.Errorf("run docker version: %w", err) } - out := strings.TrimSuffix(strings.TrimPrefix(strings.TrimSpace(buf.String()), "'"), "'") + // Make sure we unmarshal a valid json string. + out := regexp.MustCompile(`{(.|\n)*}`).FindString(buf.String()) type dockerServer struct { OS string `json:"Os"` Arch string `json:"Arch"` diff --git a/internal/pkg/docker/dockerengine/dockerengine_test.go b/internal/pkg/docker/dockerengine/dockerengine_test.go index a2c6d5609de..b444ec3bdc6 100644 --- a/internal/pkg/docker/dockerengine/dockerengine_test.go +++ b/internal/pkg/docker/dockerengine/dockerengine_test.go @@ -425,7 +425,7 @@ func TestDockerCommand_CheckDockerEngineRunning(t *testing.T) { "error running docker info": { setupMocks: func(controller *gomock.Controller) { mockCmd = NewMockCmd(controller) - mockCmd.EXPECT().Run("docker", []string{"info", "-f", "'{{json .}}'"}, gomock.Any()).Return(mockError) + mockCmd.EXPECT().Run("docker", []string{"info", "-f", "json"}, gomock.Any()).Return(mockError) }, wantedErr: fmt.Errorf("get docker info: some error"), @@ -433,11 +433,12 @@ func TestDockerCommand_CheckDockerEngineRunning(t *testing.T) { "return when docker engine is not started": { setupMocks: func(controller *gomock.Controller) { mockCmd = NewMockCmd(controller) - mockCmd.EXPECT().Run("docker", []string{"info", "-f", "'{{json .}}'"}, gomock.Any()). + mockCmd.EXPECT().Run("docker", []string{"info", "-f", "json"}, gomock.Any()). Do(func(_ string, _ []string, opt exec.CmdOption) { cmd := &osexec.Cmd{} opt(cmd) - _, _ = cmd.Stdout.Write([]byte(`'{"ServerErrors":["Cannot connect to the Docker daemon at unix:///var/run/docker.sock.", "Is the docker daemon running?"]}'`)) + _, _ = cmd.Stdout.Write([]byte(`Cannot connect to the Docker daemon at unix:///Users/penghaoh/.docker/run/docker.sock. Is the docker daemon running? +'{"ID":"","Containers":0,"ContainersRunning":0,"ServerErrors":["Cannot connect to the Docker daemon at unix:///var/run/docker.sock.", "Is the docker daemon running?"]}'`)) }).Return(nil) }, @@ -448,7 +449,7 @@ func TestDockerCommand_CheckDockerEngineRunning(t *testing.T) { "success": { setupMocks: func(controller *gomock.Controller) { mockCmd = NewMockCmd(controller) - mockCmd.EXPECT().Run("docker", []string{"info", "-f", "'{{json .}}'"}, gomock.Any()). + mockCmd.EXPECT().Run("docker", []string{"info", "-f", "json"}, gomock.Any()). Do(func(_ string, _ []string, opt exec.CmdOption) { cmd := &osexec.Cmd{} opt(cmd)