Skip to content
This repository was archived by the owner on Nov 27, 2023. It is now read-only.

Commit d13bc95

Browse files
authored
Merge pull request #1463 from aiordache/ipc_support
Add IPC support
2 parents b24a3e1 + baeede2 commit d13bc95

File tree

3 files changed

+120
-33
lines changed

3 files changed

+120
-33
lines changed

local/compose/create.go

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func (s *composeService) Create(ctx context.Context, project *types.Project, opt
100100
}
101101
}
102102

103-
prepareNetworkMode(project)
103+
prepareServicesDependsOn(project)
104104

105105
return InDependencyOrder(ctx, project, func(c context.Context, service types.ServiceConfig) error {
106106
if utils.StringContains(opts.Services, service.Name) {
@@ -142,18 +142,20 @@ func prepareNetworks(project *types.Project) {
142142
}
143143
}
144144

145-
func prepareNetworkMode(p *types.Project) {
145+
func prepareServicesDependsOn(p *types.Project) {
146146
outLoop:
147147
for i := range p.Services {
148-
dependency := getDependentServiceByNetwork(p.Services[i].NetworkMode)
149-
if dependency == "" {
148+
networkDependency := getDependentServiceFromMode(p.Services[i].NetworkMode)
149+
ipcDependency := getDependentServiceFromMode(p.Services[i].Ipc)
150+
151+
if networkDependency == "" && ipcDependency == "" {
150152
continue
151153
}
152154
if p.Services[i].DependsOn == nil {
153155
p.Services[i].DependsOn = make(types.DependsOnConfig)
154156
}
155157
for _, service := range p.Services {
156-
if service.Name == dependency {
158+
if service.Name == networkDependency || service.Name == ipcDependency {
157159
p.Services[i].DependsOn[service.Name] = types.ServiceDependency{
158160
Condition: types.ServiceConditionStarted,
159161
}
@@ -269,7 +271,14 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
269271

270272
resources := getDeployResources(service)
271273

272-
networkMode, err := getNetworkMode(ctx, p, service)
274+
networkMode, err := getMode(ctx, service.Name, service.NetworkMode)
275+
if err != nil {
276+
return nil, nil, nil, err
277+
}
278+
if networkMode == "" {
279+
networkMode = getDefaultNetworkMode(p, service)
280+
}
281+
ipcmode, err := getMode(ctx, service.Name, service.Ipc)
273282
if err != nil {
274283
return nil, nil, nil, err
275284
}
@@ -305,8 +314,9 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
305314
Mounts: mounts,
306315
CapAdd: strslice.StrSlice(service.CapAdd),
307316
CapDrop: strslice.StrSlice(service.CapDrop),
308-
NetworkMode: networkMode,
317+
NetworkMode: container.NetworkMode(networkMode),
309318
Init: service.Init,
319+
IpcMode: container.IpcMode(ipcmode),
310320
ReadonlyRootfs: service.ReadOnly,
311321
RestartPolicy: getRestartPolicy(service),
312322
ShmSize: shmSize,
@@ -328,10 +338,21 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
328338
LogConfig: logConfig,
329339
}
330340

331-
networkConfig := buildDefaultNetworkConfig(service, networkMode, getContainerName(p.Name, service, number))
341+
networkConfig := buildDefaultNetworkConfig(service, container.NetworkMode(networkMode), getContainerName(p.Name, service, number))
332342
return &containerConfig, &hostConfig, networkConfig, nil
333343
}
334344

345+
func getDefaultNetworkMode(project *types.Project, service types.ServiceConfig) string {
346+
mode := "none"
347+
if len(project.Networks) > 0 {
348+
for name := range getNetworksForService(service) {
349+
mode = project.Networks[name].Name
350+
break
351+
}
352+
}
353+
return mode
354+
}
355+
335356
func getRestartPolicy(service types.ServiceConfig) container.RestartPolicy {
336357
var restart container.RestartPolicy
337358
if service.Restart != "" {
@@ -470,12 +491,11 @@ func getVolumesFrom(project *types.Project, volumesFrom []string) ([]string, []s
470491

471492
}
472493

473-
func getDependentServiceByNetwork(networkMode string) string {
474-
baseService := ""
475-
if strings.HasPrefix(networkMode, types.NetworkModeServicePrefix) {
476-
return networkMode[len(types.NetworkModeServicePrefix):]
494+
func getDependentServiceFromMode(mode string) string {
495+
if strings.HasPrefix(mode, types.NetworkModeServicePrefix) {
496+
return mode[len(types.NetworkModeServicePrefix):]
477497
}
478-
return baseService
498+
return ""
479499
}
480500

481501
func (s *composeService) buildContainerVolumes(ctx context.Context, p types.Project, service types.ServiceConfig,
@@ -745,33 +765,22 @@ func getAliases(s types.ServiceConfig, c *types.ServiceNetworkConfig) []string {
745765
return aliases
746766
}
747767

748-
func getNetworkMode(ctx context.Context, p *types.Project, service types.ServiceConfig) (container.NetworkMode, error) {
768+
func getMode(ctx context.Context, serviceName string, mode string) (string, error) {
749769
cState, err := GetContextContainerState(ctx)
750770
if err != nil {
751-
return container.NetworkMode("none"), nil
771+
return "", nil
752772
}
753773
observedState := cState.GetContainers()
754-
755-
mode := service.NetworkMode
756-
if mode == "" {
757-
if len(p.Networks) > 0 {
758-
for name := range getNetworksForService(service) {
759-
return container.NetworkMode(p.Networks[name].Name), nil
760-
}
761-
}
762-
return container.NetworkMode("none"), nil
763-
}
764-
depServiceNetworkMode := getDependentServiceByNetwork(service.NetworkMode)
765-
if depServiceNetworkMode != "" {
766-
depServiceContainers := observedState.filter(isService(depServiceNetworkMode))
774+
depService := getDependentServiceFromMode(mode)
775+
if depService != "" {
776+
depServiceContainers := observedState.filter(isService(depService))
767777
if len(depServiceContainers) > 0 {
768-
return container.NetworkMode(types.NetworkModeContainerPrefix + depServiceContainers[0].ID), nil
778+
return types.NetworkModeContainerPrefix + depServiceContainers[0].ID, nil
769779
}
770-
return container.NetworkMode("none"),
771-
fmt.Errorf(`no containers started for network_mode %q in service %q -> %v`,
772-
mode, service.Name, observedState)
780+
return "", fmt.Errorf(`no containers started for %q in service %q -> %v`,
781+
mode, serviceName, observedState)
773782
}
774-
return container.NetworkMode(mode), nil
783+
return mode, nil
775784
}
776785

777786
func getNetworksForService(s types.ServiceConfig) map[string]*types.ServiceNetworkConfig {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
services:
2+
service:
3+
image: busybox
4+
command: top
5+
ipc: "service:shareable"
6+
container:
7+
image: busybox
8+
command: top
9+
ipc: "container:ipc_mode_container"
10+
shareable:
11+
image: busybox
12+
command: top
13+
ipc: shareable

local/e2e/compose/ipc_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
Copyright 2020 Docker Compose CLI authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package e2e
18+
19+
import (
20+
"fmt"
21+
"strings"
22+
"testing"
23+
24+
"gotest.tools/v3/icmd"
25+
26+
. "github.com/docker/compose-cli/utils/e2e"
27+
)
28+
29+
func TestIPC(t *testing.T) {
30+
c := NewParallelE2eCLI(t, binDir)
31+
32+
const projectName = "ipc_e2e"
33+
var cid string
34+
t.Run("create ipc mode container", func(t *testing.T) {
35+
res := c.RunDockerCmd("run", "-d", "--rm", "--ipc=shareable", "--name", "ipc_mode_container", "busybox", "top")
36+
cid = strings.Trim(res.Stdout(), "\n")
37+
})
38+
39+
t.Run("up", func(t *testing.T) {
40+
c.RunDockerCmd("compose", "-f", "./fixtures/ipc-test/compose.yaml", "--project-name", projectName, "up", "-d")
41+
})
42+
43+
t.Run("check running project", func(t *testing.T) {
44+
res := c.RunDockerCmd("compose", "-p", projectName, "ps")
45+
res.Assert(t, icmd.Expected{Out: `shareable`})
46+
})
47+
48+
t.Run("check ipcmode in container inspect", func(t *testing.T) {
49+
res := c.RunDockerCmd("inspect", projectName+"_shareable_1")
50+
res.Assert(t, icmd.Expected{Out: `"IpcMode": "shareable",`})
51+
52+
res = c.RunDockerCmd("inspect", projectName+"_service_1")
53+
res.Assert(t, icmd.Expected{Out: `"IpcMode": "container:`})
54+
55+
res = c.RunDockerCmd("inspect", projectName+"_container_1")
56+
res.Assert(t, icmd.Expected{Out: fmt.Sprintf(`"IpcMode": "container:%s",`, cid)})
57+
})
58+
59+
t.Run("down", func(t *testing.T) {
60+
_ = c.RunDockerCmd("compose", "--project-name", projectName, "down")
61+
})
62+
t.Run("stop ipc mode container", func(t *testing.T) {
63+
_ = c.RunDockerCmd("stop", "ipc_mode_container")
64+
})
65+
}

0 commit comments

Comments
 (0)