package docker_test import ( "context" "fmt" "net" "net/http" "path/filepath" "runtime" "strings" "testing" "time" "github.com/docker/docker/client" "knative.dev/func/pkg/docker" ) // Test that we are creating client in accordance // with the DOCKER_HOST environment variable func TestNewClient(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("TODO fix this test on Windows CI") // TODO fix this } ctx, cancel := context.WithTimeout(context.Background(), time.Minute*1) defer cancel() tmpDir := t.TempDir() sock := filepath.Join(tmpDir, "docker.sock") dockerHost := fmt.Sprintf("unix://%s", sock) startMockDaemonUnix(t, sock) t.Setenv("DOCKER_HOST", dockerHost) dockerClient, dockerHostInRemote, err := docker.NewClient(client.DefaultDockerHost) if err != nil { t.Error(err) } defer dockerClient.Close() if runtime.GOOS == "linux" && dockerHostInRemote != dockerHost { t.Errorf("unexpected dockerHostInRemote: expected %q, but got %q", dockerHost, dockerHostInRemote) } if runtime.GOOS == "darwin" && dockerHostInRemote != "" { t.Errorf("unexpected dockerHostInRemote: expected empty string, but got %q", dockerHostInRemote) } _, err = dockerClient.Ping(ctx) if err != nil { t.Error(err) } } func TestNewClient_DockerHost(t *testing.T) { tests := []struct { name string dockerHostEnvVar string expectedRemoteDockerHost map[string]string }{ { name: "tcp", dockerHostEnvVar: "tcp://10.0.0.1:1234", expectedRemoteDockerHost: map[string]string{"darwin": "", "windows": "", "linux": ""}, }, { name: "unix", dockerHostEnvVar: "unix:///some/path/docker.sock", expectedRemoteDockerHost: map[string]string{"darwin": "", "windows": "", "linux": "unix:///some/path/docker.sock"}, }, { name: "Docker Desktop", dockerHostEnvVar: "unix:///home/jdoe/.docker/desktop/docker.sock", expectedRemoteDockerHost: map[string]string{"darwin": "", "windows": "", "linux": ""}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if strings.HasPrefix(tt.dockerHostEnvVar, "unix") && runtime.GOOS == "windows" { t.Skip("Windows cannot handle Unix sockets") } t.Setenv("DOCKER_HOST", tt.dockerHostEnvVar) _, host, err := docker.NewClient(client.DefaultDockerHost) if err != nil { t.Fatal(err) } expectedRemoteDockerHost := tt.expectedRemoteDockerHost[runtime.GOOS] if host != expectedRemoteDockerHost { t.Errorf("expected docker host %q, but got %q", expectedRemoteDockerHost, host) } }) } } func startMockDaemon(t *testing.T, listener net.Listener) { server := http.Server{} // mimics /_ping endpoint server.Handler = http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { writer.Header().Add("Content-Type", "text/plain") writer.WriteHeader(200) _, _ = writer.Write([]byte("OK")) }) serErrChan := make(chan error) go func() { serErrChan <- server.Serve(listener) }() t.Cleanup(func() { err := server.Shutdown(context.Background()) if err != nil { t.Fatal(err) } err = <-serErrChan if err != nil && !strings.Contains(err.Error(), "Server closed") { t.Fatal(err) } }) } func startMockDaemonUnix(t *testing.T, sock string) { l, err := net.Listen("unix", sock) if err != nil { t.Fatal(err) } startMockDaemon(t, l) }