Visitar URL original
Add isolation mode on service update/create and compose files · docker/cli@e8215fb · GitHub
Skip to content

Commit e8215fb

Browse files
committed
Add isolation mode on service update/create and compose files
Signed-off-by: Simon Ferquel <simon.ferquel@docker.com>
1 parent 47b1a8f commit e8215fb

14 files changed

Lines changed: 135 additions & 2 deletions

File tree

‎cli/command/service/opts.go‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,8 @@ type serviceOptions struct {
505505
healthcheck healthCheckOptions
506506
secrets opts.SecretOpt
507507
configs opts.ConfigOpt
508+
509+
isolation string
508510
}
509511

510512
func newServiceOptions() *serviceOptions {
@@ -614,6 +616,7 @@ func (options *serviceOptions) ToService(ctx context.Context, apiClient client.N
614616
Hosts: convertExtraHostsToSwarmHosts(options.hosts.GetAll()),
615617
StopGracePeriod: options.ToStopGracePeriod(flags),
616618
Healthcheck: healthConfig,
619+
Isolation: container.Isolation(options.isolation),
617620
},
618621
Networks: networks,
619622
Resources: options.resources.ToResourceRequirements(),
@@ -784,6 +787,8 @@ func addServiceFlags(flags *pflag.FlagSet, opts *serviceOptions, defaultFlagValu
784787

785788
flags.StringVar(&opts.stopSignal, flagStopSignal, "", "Signal to stop the container")
786789
flags.SetAnnotation(flagStopSignal, "version", []string{"1.28"})
790+
flags.StringVar(&opts.isolation, flagIsolation, "", "Service container isolation mode")
791+
flags.SetAnnotation(flagIsolation, "version", []string{"1.35"})
787792
}
788793

789794
const (
@@ -879,4 +884,5 @@ const (
879884
flagConfig = "config"
880885
flagConfigAdd = "config-add"
881886
flagConfigRemove = "config-rm"
887+
flagIsolation = "isolation"
882888
)

‎cli/command/service/update.go‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,14 @@ func updateService(ctx context.Context, apiClient client.NetworkAPIClient, flags
269269
}
270270
}
271271

272+
updateIsolation := func(flag string, field *container.Isolation) error {
273+
if flags.Changed(flag) {
274+
val, _ := flags.GetString(flag)
275+
*field = container.Isolation(val)
276+
}
277+
return nil
278+
}
279+
272280
cspec := spec.TaskTemplate.ContainerSpec
273281
task := &spec.TaskTemplate
274282

@@ -288,6 +296,9 @@ func updateService(ctx context.Context, apiClient client.NetworkAPIClient, flags
288296
updateString(flagWorkdir, &cspec.Dir)
289297
updateString(flagUser, &cspec.User)
290298
updateString(flagHostname, &cspec.Hostname)
299+
if err := updateIsolation(flagIsolation, &cspec.Isolation); err != nil {
300+
return err
301+
}
291302
if err := updateMounts(flags, &cspec.Mounts); err != nil {
292303
return err
293304
}

‎cli/command/service/update_test.go‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,3 +518,32 @@ func TestUpdateStopSignal(t *testing.T) {
518518
updateService(nil, nil, flags, spec)
519519
assert.Equal(t, "SIGWINCH", cspec.StopSignal)
520520
}
521+
522+
func TestUpdateIsolationValid(t *testing.T) {
523+
flags := newUpdateCommand(nil).Flags()
524+
err := flags.Set("isolation", "process")
525+
require.NoError(t, err)
526+
spec := swarm.ServiceSpec{
527+
TaskTemplate: swarm.TaskSpec{
528+
ContainerSpec: &swarm.ContainerSpec{},
529+
},
530+
}
531+
err = updateService(context.Background(), nil, flags, &spec)
532+
require.NoError(t, err)
533+
assert.Equal(t, container.IsolationProcess, spec.TaskTemplate.ContainerSpec.Isolation)
534+
}
535+
536+
func TestUpdateIsolationInvalid(t *testing.T) {
537+
// validation depends on daemon os / version so validation should be done on the daemon side
538+
flags := newUpdateCommand(nil).Flags()
539+
err := flags.Set("isolation", "test")
540+
require.NoError(t, err)
541+
spec := swarm.ServiceSpec{
542+
TaskTemplate: swarm.TaskSpec{
543+
ContainerSpec: &swarm.ContainerSpec{},
544+
},
545+
}
546+
err = updateService(context.Background(), nil, flags, &spec)
547+
require.NoError(t, err)
548+
assert.Equal(t, container.Isolation("test"), spec.TaskTemplate.ContainerSpec.Isolation)
549+
}

‎cli/compose/convert/service.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ func Service(
149149
Configs: configs,
150150
ReadOnly: service.ReadOnly,
151151
Privileges: &privileges,
152+
Isolation: container.Isolation(service.Isolation),
152153
},
153154
LogDriver: logDriver,
154155
Resources: resources,

‎cli/compose/convert/service_test.go‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,3 +424,12 @@ func TestConvertFileObjectDefaults(t *testing.T) {
424424
}
425425
assert.Equal(t, expected, swarmRef)
426426
}
427+
428+
func TestServiceConvertsIsolation(t *testing.T) {
429+
src := composetypes.ServiceConfig{
430+
Isolation: "hyperv",
431+
}
432+
result, err := Service("1.35", Namespace{name: "foo"}, src, nil, nil, nil, nil)
433+
require.NoError(t, err)
434+
assert.Equal(t, container.IsolationHyperV, result.TaskTemplate.ContainerSpec.Isolation)
435+
}

‎cli/compose/loader/loader_test.go‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1454,5 +1454,37 @@ func TestLoadVolumesWarnOnDeprecatedExternalNameVersion33(t *testing.T) {
14541454
}
14551455
assert.Equal(t, expected, volumes)
14561456
assert.Equal(t, "", buf.String())
1457+
}
14571458

1459+
func TestLoadV35(t *testing.T) {
1460+
actual, err := loadYAML(`
1461+
version: "3.5"
1462+
services:
1463+
foo:
1464+
image: busybox
1465+
isolation: process
1466+
configs:
1467+
super:
1468+
external: true
1469+
`)
1470+
require.NoError(t, err)
1471+
require.Len(t, actual.Services, 1)
1472+
assert.Equal(t, "process", actual.Services[0].Isolation)
1473+
}
1474+
1475+
func TestLoadV35InvalidIsolation(t *testing.T) {
1476+
// validation should be done only on the daemon side
1477+
actual, err := loadYAML(`
1478+
version: "3.5"
1479+
services:
1480+
foo:
1481+
image: busybox
1482+
isolation: invalid
1483+
configs:
1484+
super:
1485+
external: true
1486+
`)
1487+
require.NoError(t, err)
1488+
require.Len(t, actual.Services, 1)
1489+
assert.Equal(t, "invalid", actual.Services[0].Isolation)
14581490
}

‎cli/compose/schema/bindata.go‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎cli/compose/schema/data/config_schema_v3.5.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"$schema": "http://json-schema.org/draft-04/schema#",
3-
"id": "config_schema_v3.4.json",
3+
"id": "config_schema_v3.5.json",
44
"type": "object",
55
"required": ["version"],
66

@@ -154,6 +154,7 @@
154154
"hostname": {"type": "string"},
155155
"image": {"type": "string"},
156156
"ipc": {"type": "string"},
157+
"isolation": {"type": "string"},
157158
"labels": {"$ref": "#/definitions/list_or_dict"},
158159
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
159160

‎cli/compose/schema/schema_test.go‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,16 @@ func TestValidatePlacement(t *testing.T) {
8484

8585
assert.NoError(t, Validate(config, "3.3"))
8686
}
87+
88+
func TestValidateIsolation(t *testing.T) {
89+
config := dict{
90+
"version": "3.5",
91+
"services": dict{
92+
"foo": dict{
93+
"image": "busybox",
94+
"isolation": "some-isolation-value",
95+
},
96+
},
97+
}
98+
assert.NoError(t, Validate(config, "3.5"))
99+
}

‎cli/compose/types/types.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ type ServiceConfig struct {
126126
User string
127127
Volumes []ServiceVolumeConfig
128128
WorkingDir string `mapstructure:"working_dir"`
129+
Isolation string `mapstructure:"isolation"`
129130
}
130131

131132
// BuildConfig is a type for build

0 commit comments

Comments
 (0)