Skip to content

Commit

Permalink
feat: account for osx special case socket (#217)
Browse files Browse the repository at this point in the history
* fix: update docker client code to make exception for darwin socket

---------

Signed-off-by: Christopher Phillips <[email protected]>
Signed-off-by: Christopher Phillips <[email protected]>
Co-authored-by: Christopher Phillips <[email protected]>
  • Loading branch information
spiffcs and spiffcs authored Feb 1, 2024
1 parent db7a4be commit 37291e8
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 4 deletions.
50 changes: 46 additions & 4 deletions internal/docker/client.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package docker

import (
"context"
"fmt"
"net/http"
"os"
"runtime"
"strings"

"github.com/docker/cli/cli/connhelper"
"github.com/docker/docker/client"
"github.com/mitchellh/go-homedir"
)

func GetClient() (*client.Client, error) {
Expand All @@ -17,7 +20,6 @@ func GetClient() (*client.Client, error) {
}

host := os.Getenv("DOCKER_HOST")

if strings.HasPrefix(host, "ssh") {
var (
helper *connhelper.ConnectionHelper
Expand Down Expand Up @@ -48,10 +50,50 @@ func GetClient() (*client.Client, error) {
}
}

dockerClient, err := client.NewClientWithOpts(clientOpts...)
possibleSocketPaths := possibleSocketPaths(runtime.GOOS)
for _, socketPath := range possibleSocketPaths {
dockerClient, err := newClient(socketPath, clientOpts...)
if err == nil {
err := checkConnection(dockerClient)
if err == nil {
return dockerClient, nil // Successfully connected
}
}
}

// If both attempts failed
return nil, fmt.Errorf("failed to connect to Docker daemon. Ensure Docker is running and accessible")
}

func checkConnection(dockerClient *client.Client) error {
ctx := context.Background()
_, err := dockerClient.Ping(ctx)
if err != nil {
return nil, fmt.Errorf("failed create docker client: %w", err)
return fmt.Errorf("failed to ping Docker daemon: %w", err)
}
return nil
}

return dockerClient, nil
func newClient(socket string, opts ...client.Opt) (*client.Client, error) {
if socket == "" {
return client.NewClientWithOpts(opts...)
}
opts = append(opts, client.WithHost(socket))
return client.NewClientWithOpts(opts...)
}

func possibleSocketPaths(os string) []string {
switch os {
case "darwin":
hDir, err := homedir.Dir()
if err != nil {
return nil
}
return []string{
"", // try the client default first
fmt.Sprintf("unix://%s/Library/Containers/com.docker.docker/Data/docker.raw.sock", hDir),
}
default:
return []string{""} // try the client default first
}
}
84 changes: 84 additions & 0 deletions internal/docker/docker_client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package docker

import (
"os"
"strings"
"testing"

"github.com/docker/docker/client"
)

func Test_newClient(t *testing.T) {
cases := []struct {
name string
providedSocket string
expectedSocket string
setEnv func(t *testing.T)
}{
{
name: "Test newClient returns the correct default location",
providedSocket: "",
expectedSocket: "unix:///var/run/docker.sock",
},
{
name: "Test newClient with runtime specific path",
providedSocket: "",
setEnv: func(t *testing.T) {
os.Setenv("DOCKER_HOST", "unix:///var/CUSTOM/docker.sock")

},
expectedSocket: "unix:///var/CUSTOM/docker.sock",
},
{
name: "Test newClient with runtime specific path",
providedSocket: "unix:///var/NEWCUSTOM/docker.sock",
expectedSocket: "unix:///var/NEWCUSTOM/docker.sock",
},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
if c.setEnv != nil {
c.setEnv(t)
}
clientOpts := []client.Opt{
client.FromEnv,
client.WithAPIVersionNegotiation(),
}

client, err := newClient(c.providedSocket, clientOpts...)
if err != nil {
t.Errorf("newClient() error = %v", err)
return
}

if client.DaemonHost() != c.expectedSocket {
t.Errorf("newClient() = %v, want %v", client.DaemonHost(), c.expectedSocket)
}
})
}
}

func Test_possibleSocketPaths(t *testing.T) {
cases := []struct {
name string
provided string
expected []string
}{
{
name: "Test possibleSocketPaths returns the correct default location for darwin",
provided: "darwin",
expected: []string{"", "Library/Containers/com.docker.docker/Data/docker.raw.sock"},
},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
for i, socketPath := range possibleSocketPaths(c.provided) {
if !strings.HasSuffix(socketPath, c.expected[i]) {
t.Errorf("possibleSocketPaths() = %v, want %v", socketPath, c.expected[i])
}
}
})
}
}

0 comments on commit 37291e8

Please sign in to comment.