Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit aecbf56

Browse files
committed
get bind mount socket path from docker endpoint
Signed-off-by: Nick Adcock <[email protected]>
1 parent 939b9a3 commit aecbf56

File tree

34 files changed

+164
-91
lines changed

34 files changed

+164
-91
lines changed

Gopkg.lock

Lines changed: 4 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

e2e/.docker/.buildNodeID

Lines changed: 0 additions & 1 deletion
This file was deleted.

e2e/commands_test.go

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -276,19 +276,21 @@ func TestBundle(t *testing.T) {
276276
assert.Assert(t, fs.Equal(tmpDir.Join("simple.dockerapp"), manifest))
277277
}
278278

279-
func TestDockerAppLifecycleWithBindMounts(t *testing.T) {
280-
testDockerAppLifecycle(t, true)
281-
}
282-
283-
func TestDockerAppLifecycleWithoutBindMounts(t *testing.T) {
284-
testDockerAppLifecycle(t, false)
279+
func TestDockerAppLifecycle(t *testing.T) {
280+
t.Run("withBindMounts", func(t *testing.T) {
281+
testDockerAppLifecycle(t, true)
282+
})
283+
t.Run("withoutBindMounts", func(t *testing.T) {
284+
testDockerAppLifecycle(t, false)
285+
})
285286
}
286287

287288
func testDockerAppLifecycle(t *testing.T, useBindMount bool) {
288289
cmd, cleanup := dockerCli.createTestCmd()
289290
defer cleanup()
291+
appName := strings.Replace(t.Name(), "/", "_", 1)
290292

291-
tmpDir := fs.NewDir(t, t.Name())
293+
tmpDir := fs.NewDir(t, appName)
292294
defer tmpDir.Remove()
293295

294296
cmd.Env = append(cmd.Env, "DUFFLE_HOME="+tmpDir.Path())
@@ -309,19 +311,19 @@ func testDockerAppLifecycle(t *testing.T, useBindMount bool) {
309311
cmd.Command = dockerCli.Command("context", "create", "swarm-context", "--docker", fmt.Sprintf(`"host=tcp://%s"`, swarm.GetAddress(t)), "--default-stack-orchestrator", "swarm")
310312
icmd.RunCmd(cmd).Assert(t, icmd.Success)
311313

312-
if useBindMount {
313-
// When creating a context on a Windows host we cannot use
314-
// the unix socket but it's needed inside the invocation image.
315-
// The workaround is to create a context with an empty host.
316-
// This host will default to the unix socket inside the
317-
// invocation image
318-
cmd.Command = dockerCli.Command("context", "create", "swarm-target-context", "--docker", "host=", "--default-stack-orchestrator", "swarm")
319-
icmd.RunCmd(cmd).Assert(t, icmd.Success)
320-
} else {
321-
cmd.Command = dockerCli.Command("context", "create", "swarm-target-context", "--docker", fmt.Sprintf(`"host=tcp://%s"`, swarm.GetPrivateAddress(t)), "--default-stack-orchestrator", "swarm")
322-
icmd.RunCmd(cmd).Assert(t, icmd.Success)
314+
// When creating a context on a Windows host we cannot use
315+
// the unix socket but it's needed inside the invocation image.
316+
// The workaround is to create a context with an empty host.
317+
// This host will default to the unix socket inside the
318+
// invocation image
319+
host := "host="
320+
if !useBindMount {
321+
host += fmt.Sprintf("tcp://%s", swarm.GetPrivateAddress(t))
323322
}
324323

324+
cmd.Command = dockerCli.Command("context", "create", "swarm-target-context", "--docker", host, "--default-stack-orchestrator", "swarm")
325+
icmd.RunCmd(cmd).Assert(t, icmd.Success)
326+
325327
// Initialize the swarm
326328
cmd.Env = append(cmd.Env, "DOCKER_CONTEXT=swarm-context")
327329
cmd.Command = dockerCli.Command("swarm", "init")
@@ -332,47 +334,47 @@ func testDockerAppLifecycle(t *testing.T, useBindMount bool) {
332334
icmd.RunCmd(cmd).Assert(t, icmd.Success)
333335

334336
// Install a Docker Application Package
335-
cmd.Command = dockerCli.Command("app", "install", "testdata/simple/simple.dockerapp", "--name", t.Name())
337+
cmd.Command = dockerCli.Command("app", "install", "testdata/simple/simple.dockerapp", "--name", appName)
336338
checkContains(t, icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined(),
337339
[]string{
338-
fmt.Sprintf("Creating network %s_back", t.Name()),
339-
fmt.Sprintf("Creating network %s_front", t.Name()),
340-
fmt.Sprintf("Creating service %s_db", t.Name()),
341-
fmt.Sprintf("Creating service %s_api", t.Name()),
342-
fmt.Sprintf("Creating service %s_web", t.Name()),
340+
fmt.Sprintf("Creating network %s_back", appName),
341+
fmt.Sprintf("Creating network %s_front", appName),
342+
fmt.Sprintf("Creating service %s_db", appName),
343+
fmt.Sprintf("Creating service %s_api", appName),
344+
fmt.Sprintf("Creating service %s_web", appName),
343345
})
344346

345347
// Query the application status
346-
cmd.Command = dockerCli.Command("app", "status", t.Name())
348+
cmd.Command = dockerCli.Command("app", "status", appName)
347349
checkContains(t, icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined(),
348350
[]string{
349-
fmt.Sprintf("[[:alnum:]]+ %s_db replicated [0-1]/1 postgres:9.3", t.Name()),
350-
fmt.Sprintf(`[[:alnum:]]+ %s_web replicated [0-1]/1 nginx:latest \*:8082->80/tcp`, t.Name()),
351-
fmt.Sprintf("[[:alnum:]]+ %s_api replicated [0-1]/1 python:3.6", t.Name()),
351+
fmt.Sprintf("[[:alnum:]]+ %s_db replicated [0-1]/1 postgres:9.3", appName),
352+
fmt.Sprintf(`[[:alnum:]]+ %s_web replicated [0-1]/1 nginx:latest \*:8082->80/tcp`, appName),
353+
fmt.Sprintf("[[:alnum:]]+ %s_api replicated [0-1]/1 python:3.6", appName),
352354
})
353355

354356
// Upgrade the application, changing the port
355-
cmd.Command = dockerCli.Command("app", "upgrade", t.Name(), "--set", "web_port=8081")
357+
cmd.Command = dockerCli.Command("app", "upgrade", appName, "--set", "web_port=8081")
356358
checkContains(t, icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined(),
357359
[]string{
358-
fmt.Sprintf("Updating service %s_db", t.Name()),
359-
fmt.Sprintf("Updating service %s_api", t.Name()),
360-
fmt.Sprintf("Updating service %s_web", t.Name()),
360+
fmt.Sprintf("Updating service %s_db", appName),
361+
fmt.Sprintf("Updating service %s_api", appName),
362+
fmt.Sprintf("Updating service %s_web", appName),
361363
})
362364

363365
// Query the application status again, the port should have change
364-
cmd.Command = dockerCli.Command("app", "status", t.Name())
366+
cmd.Command = dockerCli.Command("app", "status", appName)
365367
icmd.RunCmd(cmd).Assert(t, icmd.Expected{ExitCode: 0, Out: "8081"})
366368

367369
// Uninstall the application
368-
cmd.Command = dockerCli.Command("app", "uninstall", t.Name())
370+
cmd.Command = dockerCli.Command("app", "uninstall", appName)
369371
checkContains(t, icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined(),
370372
[]string{
371-
fmt.Sprintf("Removing service %s_api", t.Name()),
372-
fmt.Sprintf("Removing service %s_db", t.Name()),
373-
fmt.Sprintf("Removing service %s_web", t.Name()),
374-
fmt.Sprintf("Removing network %s_front", t.Name()),
375-
fmt.Sprintf("Removing network %s_back", t.Name()),
373+
fmt.Sprintf("Removing service %s_api", appName),
374+
fmt.Sprintf("Removing service %s_db", appName),
375+
fmt.Sprintf("Removing service %s_web", appName),
376+
fmt.Sprintf("Removing network %s_front", appName),
377+
fmt.Sprintf("Removing network %s_back", appName),
376378
})
377379
}
378380

internal/commands/cnab.go

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"strings"
99

1010
"github.com/deislabs/duffle/pkg/bundle"
11+
"github.com/deislabs/duffle/pkg/claim"
1112
"github.com/deislabs/duffle/pkg/credentials"
1213
"github.com/deislabs/duffle/pkg/driver"
1314
"github.com/deislabs/duffle/pkg/duffle/home"
@@ -16,7 +17,6 @@ import (
1617
"github.com/docker/app/internal/packager"
1718
bundlestore "github.com/docker/app/internal/store"
1819
"github.com/docker/cli/cli/command"
19-
"github.com/docker/cli/cli/context"
2020
"github.com/docker/cli/cli/context/docker"
2121
"github.com/docker/cli/cli/context/store"
2222
"github.com/docker/distribution/reference"
@@ -25,6 +25,13 @@ import (
2525
"github.com/pkg/errors"
2626
)
2727

28+
type bindMount struct {
29+
required bool
30+
endpoint string
31+
}
32+
33+
const defaultSocketPath string = "/var/run/docker.sock"
34+
2835
func prepareCredentialSet(contextName string, contextStore store.Store, b *bundle.Bundle, namedCredentialsets []string) (map[string]string, error) {
2936
creds := map[string]string{}
3037
for _, file := range namedCredentialsets {
@@ -80,21 +87,21 @@ func duffleHome() home.Home {
8087
}
8188

8289
// prepareDriver prepares a driver per the user's request.
83-
func prepareDriver(dockerCli command.Cli, bindLocalSocket bool) (driver.Driver, error) {
90+
func prepareDriver(dockerCli command.Cli, bindMount bindMount) (driver.Driver, error) {
8491
driverImpl, err := driver.Lookup("docker")
8592
if err != nil {
8693
return driverImpl, err
8794
}
8895
if d, ok := driverImpl.(*driver.DockerDriver); ok {
8996
d.SetDockerCli(dockerCli)
90-
if bindLocalSocket {
97+
if bindMount.required {
9198
d.AddConfigurationOptions(func(config *container.Config, hostConfig *container.HostConfig) error {
9299
config.User = "0:0"
93100
mounts := []mount.Mount{
94101
{
95102
Type: mount.TypeBind,
96-
Source: "/var/run/docker.sock",
97-
Target: "/var/run/docker.sock",
103+
Source: bindMount.endpoint,
104+
Target: bindMount.endpoint,
98105
},
99106
}
100107
hostConfig.Mounts = mounts
@@ -180,36 +187,53 @@ func resolveBundle(dockerCli command.Cli, name string, pullRef bool, insecureReg
180187
return nil, fmt.Errorf("could not resolve bundle %q", name)
181188
}
182189

183-
func requiresBindMount(targetContextName string, targetOrchestrator string, dockerCli command.Cli) (bool, error) {
190+
func requiredClaimBindMount(c claim.Claim, targetContextName string, dockerCli command.Cli) (bindMount, error) {
191+
var specifiedOrchestrator string
192+
if rawOrchestrator, ok := c.Parameters["docker.orchestrator"]; ok {
193+
specifiedOrchestrator = rawOrchestrator.(string)
194+
}
195+
196+
return requiredBindMount(targetContextName, specifiedOrchestrator, dockerCli)
197+
}
198+
199+
func requiredBindMount(targetContextName string, targetOrchestrator string, dockerCli command.Cli) (bindMount, error) {
184200
if targetOrchestrator == "kubernetes" {
185-
return false, nil
201+
return bindMount{}, nil
186202
}
187203

188204
// TODO:smarter handling of default context required
189205
if targetContextName == "" {
190-
return true, nil
206+
return bindMount{true, defaultSocketPath}, nil
191207
}
192208

193209
ctxMeta, err := dockerCli.ContextStore().GetContextMetadata(targetContextName)
194210
if err != nil {
195-
return false, err
211+
return bindMount{}, err
196212
}
197213
dockerCtx, err := command.GetDockerContext(ctxMeta)
198214
if err != nil {
199-
return false, err
215+
return bindMount{}, err
200216
}
201217
if dockerCtx.StackOrchestrator == command.OrchestratorKubernetes {
202-
return false, nil
218+
return bindMount{}, nil
203219
}
204220
dockerEndpoint, err := docker.EndpointFromContext(ctxMeta)
205221
if err != nil {
206-
return false, err
222+
return bindMount{}, err
207223
}
208224

209-
return isDockerHostLocal(dockerEndpoint), nil
225+
host := dockerEndpoint.Host
226+
return bindMount{isDockerHostLocal(host), socketPath(host)}, nil
210227
}
211228

212-
func isDockerHostLocal(dockerEndpoint context.EndpointMetaBase) bool {
213-
host := dockerEndpoint.Host
214-
return host == "" || host == "unix:///var/run/docker.sock" || host == "npipe:////./pipe/docker_engine"
229+
func socketPath(host string) string {
230+
if strings.HasPrefix(host, "unix://") {
231+
return strings.TrimPrefix(host, "unix://")
232+
}
233+
234+
return defaultSocketPath
235+
}
236+
237+
func isDockerHostLocal(host string) bool {
238+
return host == "" || strings.HasPrefix(host, "unix://") || strings.HasPrefix(host, "npipe://")
215239
}

internal/commands/cnab_test.go

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"testing"
55

66
"github.com/docker/cli/cli/command"
7-
"github.com/docker/cli/cli/context"
87
"gotest.tools/assert"
98
)
109

@@ -16,34 +15,38 @@ func TestRequiresBindMount(t *testing.T) {
1615
name string
1716
targetContextName string
1817
targetOrchestrator string
19-
expectedResult bool
18+
expectedRequired bool
19+
expectedEndpoint string
2020
expectedError string
2121
}{
2222
{
2323
name: "kubernetes-orchestrator",
2424
targetContextName: "target-context",
2525
targetOrchestrator: "kubernetes",
26-
expectedResult: false,
26+
expectedRequired: false,
27+
expectedEndpoint: "",
2728
expectedError: "",
2829
},
2930
{
3031
name: "no-context",
3132
targetContextName: "",
3233
targetOrchestrator: "swarm",
33-
expectedResult: true,
34+
expectedRequired: true,
35+
expectedEndpoint: "/var/run/docker.sock",
3436
expectedError: "",
3537
},
3638
}
3739

3840
for _, testCase := range testCases {
3941
t.Run(testCase.name, func(t *testing.T) {
40-
result, err := requiresBindMount(testCase.targetContextName, testCase.targetOrchestrator, dockerCli)
42+
result, err := requiredBindMount(testCase.targetContextName, testCase.targetOrchestrator, dockerCli)
4143
if testCase.expectedError == "" {
4244
assert.NilError(t, err)
4345
} else {
4446
assert.Error(t, err, testCase.expectedError)
4547
}
46-
assert.Equal(t, testCase.expectedResult, result)
48+
assert.Equal(t, testCase.expectedRequired, result.required)
49+
assert.Equal(t, testCase.expectedEndpoint, result.endpoint)
4750
})
4851
}
4952
}
@@ -78,8 +81,42 @@ func TestIsDockerHostLocal(t *testing.T) {
7881

7982
for _, testCase := range testCases {
8083
t.Run(testCase.name, func(t *testing.T) {
81-
dockerEndpoint := context.EndpointMetaBase{Host: testCase.host}
82-
assert.Equal(t, testCase.expected, isDockerHostLocal(dockerEndpoint))
84+
assert.Equal(t, testCase.expected, isDockerHostLocal(testCase.host))
85+
})
86+
}
87+
}
88+
89+
func TestSocketPath(t *testing.T) {
90+
testCases := []struct {
91+
name string
92+
host string
93+
expected string
94+
}{
95+
{
96+
name: "unixSocket",
97+
host: "unix:///my/socket.sock",
98+
expected: "/my/socket.sock",
99+
},
100+
{
101+
name: "namedPipe",
102+
host: "npipe:////./docker",
103+
expected: "/var/run/docker.sock",
104+
},
105+
{
106+
name: "emptyHost",
107+
host: "",
108+
expected: "/var/run/docker.sock",
109+
},
110+
{
111+
name: "tcpHost",
112+
host: "tcp://my/tcp/endpoint",
113+
expected: "/var/run/docker.sock",
114+
},
115+
}
116+
117+
for _, testCase := range testCases {
118+
t.Run(testCase.name, func(t *testing.T) {
119+
assert.Equal(t, testCase.expected, socketPath(testCase.host))
83120
})
84121
}
85122
}

0 commit comments

Comments
 (0)