Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

--isolation for setting swarm service isolation mode #426

Merged
merged 2 commits into from
Nov 17, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions cli/command/service/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,8 @@ type serviceOptions struct {
healthcheck healthCheckOptions
secrets opts.SecretOpt
configs opts.ConfigOpt

isolation string
}

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

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

const (
Expand Down Expand Up @@ -879,4 +884,5 @@ const (
flagConfig = "config"
flagConfigAdd = "config-add"
flagConfigRemove = "config-rm"
flagIsolation = "isolation"
)
11 changes: 11 additions & 0 deletions cli/command/service/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,14 @@ func updateService(ctx context.Context, apiClient client.NetworkAPIClient, flags
}
}

updateIsolation := func(flag string, field *container.Isolation) error {
if flags.Changed(flag) {
val, _ := flags.GetString(flag)
*field = container.Isolation(val)
}
return nil
}

cspec := spec.TaskTemplate.ContainerSpec
task := &spec.TaskTemplate

Expand All @@ -288,6 +296,9 @@ func updateService(ctx context.Context, apiClient client.NetworkAPIClient, flags
updateString(flagWorkdir, &cspec.Dir)
updateString(flagUser, &cspec.User)
updateString(flagHostname, &cspec.Hostname)
if err := updateIsolation(flagIsolation, &cspec.Isolation); err != nil {
return err
}
if err := updateMounts(flags, &cspec.Mounts); err != nil {
return err
}
Expand Down
29 changes: 29 additions & 0 deletions cli/command/service/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -518,3 +518,32 @@ func TestUpdateStopSignal(t *testing.T) {
updateService(nil, nil, flags, spec)
assert.Equal(t, "SIGWINCH", cspec.StopSignal)
}

func TestUpdateIsolationValid(t *testing.T) {
flags := newUpdateCommand(nil).Flags()
err := flags.Set("isolation", "process")
require.NoError(t, err)
spec := swarm.ServiceSpec{
TaskTemplate: swarm.TaskSpec{
ContainerSpec: &swarm.ContainerSpec{},
},
}
err = updateService(context.Background(), nil, flags, &spec)
require.NoError(t, err)
assert.Equal(t, container.IsolationProcess, spec.TaskTemplate.ContainerSpec.Isolation)
}

func TestUpdateIsolationInvalid(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this test needs to call updateService() otherwise it's only testing isolationOpt

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, makes sense, I'll remove the test as opts is already tested and updateService won't be called if flags parsing fails

// validation depends on daemon os / version so validation should be done on the daemon side
flags := newUpdateCommand(nil).Flags()
err := flags.Set("isolation", "test")
require.NoError(t, err)
spec := swarm.ServiceSpec{
TaskTemplate: swarm.TaskSpec{
ContainerSpec: &swarm.ContainerSpec{},
},
}
err = updateService(context.Background(), nil, flags, &spec)
require.NoError(t, err)
assert.Equal(t, container.Isolation("test"), spec.TaskTemplate.ContainerSpec.Isolation)
}
1 change: 1 addition & 0 deletions cli/compose/convert/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ func Service(
Configs: configs,
ReadOnly: service.ReadOnly,
Privileges: &privileges,
Isolation: container.Isolation(service.Isolation),
},
LogDriver: logDriver,
Resources: resources,
Expand Down
9 changes: 9 additions & 0 deletions cli/compose/convert/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,3 +424,12 @@ func TestConvertFileObjectDefaults(t *testing.T) {
}
assert.Equal(t, expected, swarmRef)
}

func TestServiceConvertsIsolation(t *testing.T) {
src := composetypes.ServiceConfig{
Isolation: "hyperv",
}
result, err := Service("1.35", Namespace{name: "foo"}, src, nil, nil, nil, nil)
require.NoError(t, err)
assert.Equal(t, container.IsolationHyperV, result.TaskTemplate.ContainerSpec.Isolation)
}
32 changes: 32 additions & 0 deletions cli/compose/loader/loader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1454,5 +1454,37 @@ func TestLoadVolumesWarnOnDeprecatedExternalNameVersion33(t *testing.T) {
}
assert.Equal(t, expected, volumes)
assert.Equal(t, "", buf.String())
}

func TestLoadV35(t *testing.T) {
actual, err := loadYAML(`
version: "3.5"
services:
foo:
image: busybox
isolation: process
configs:
super:
external: true
`)
require.NoError(t, err)
require.Len(t, actual.Services, 1)
assert.Equal(t, "process", actual.Services[0].Isolation)
}

func TestLoadV35InvalidIsolation(t *testing.T) {
// validation should be done only on the daemon side
actual, err := loadYAML(`
version: "3.5"
services:
foo:
image: busybox
isolation: invalid
configs:
super:
external: true
`)
require.NoError(t, err)
require.Len(t, actual.Services, 1)
assert.Equal(t, "invalid", actual.Services[0].Isolation)
}
23 changes: 23 additions & 0 deletions cli/compose/schema/bindata.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading