From b849aa6b95e14450c90657cfe9668dfd5704a464 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Sat, 14 Jan 2017 00:12:19 -0800 Subject: [PATCH] Add `--read-only` for `service create` and `service update` This fix tries to address the issue raised in 29972 where it was not possible to specify `--read-only` for `docker service create` and `docker service update`, in order to have the container's root file system to be read only. This fix adds `--read-only` and update the `ReadonlyRootfs` in `HostConfig` through `service create` and `service update`. Related docs has been updated. Integration test has been added. This fix fixes 29972. Signed-off-by: Yong Tang --- command/service/opts.go | 6 ++++++ command/service/update.go | 8 ++++++++ command/service/update_test.go | 22 ++++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/command/service/opts.go b/command/service/opts.go index 2218890aa3..dcd52ac7a3 100644 --- a/command/service/opts.go +++ b/command/service/opts.go @@ -303,6 +303,7 @@ type serviceOptions struct { user string groups opts.ListOpts tty bool + readOnly bool mounts opts.MountOpt dns opts.ListOpts dnsSearch opts.ListOpts @@ -384,6 +385,7 @@ func (opts *serviceOptions) ToService() (swarm.ServiceSpec, error) { User: opts.user, Groups: opts.groups.GetAll(), TTY: opts.tty, + ReadOnly: opts.readOnly, Mounts: opts.mounts.Value(), DNSConfig: &swarm.DNSConfig{ Nameservers: opts.dns.GetAll(), @@ -488,6 +490,9 @@ func addServiceFlags(cmd *cobra.Command, opts *serviceOptions) { flags.BoolVarP(&opts.tty, flagTTY, "t", false, "Allocate a pseudo-TTY") flags.SetAnnotation(flagTTY, "version", []string{"1.25"}) + + flags.BoolVar(&opts.readOnly, flagReadOnly, false, "Mount the container's root filesystem as read only") + flags.SetAnnotation(flagReadOnly, "version", []string{"1.26"}) } const ( @@ -532,6 +537,7 @@ const ( flagPublish = "publish" flagPublishRemove = "publish-rm" flagPublishAdd = "publish-add" + flagReadOnly = "read-only" flagReplicas = "replicas" flagReserveCPU = "reserve-cpu" flagReserveMemory = "reserve-memory" diff --git a/command/service/update.go b/command/service/update.go index 66002b69e0..57a4577f88 100644 --- a/command/service/update.go +++ b/command/service/update.go @@ -341,6 +341,14 @@ func updateService(flags *pflag.FlagSet, spec *swarm.ServiceSpec) error { cspec.TTY = tty } + if flags.Changed(flagReadOnly) { + readOnly, err := flags.GetBool(flagReadOnly) + if err != nil { + return err + } + cspec.ReadOnly = readOnly + } + return nil } diff --git a/command/service/update_test.go b/command/service/update_test.go index bb931929c0..992ae9ef3b 100644 --- a/command/service/update_test.go +++ b/command/service/update_test.go @@ -442,3 +442,25 @@ func TestUpdateSecretUpdateInPlace(t *testing.T) { assert.Equal(t, updatedSecrets[0].SecretName, "foo") assert.Equal(t, updatedSecrets[0].File.Name, "foo2") } + +func TestUpdateReadOnly(t *testing.T) { + spec := &swarm.ServiceSpec{} + cspec := &spec.TaskTemplate.ContainerSpec + + // Update with --read-only=true, changed to true + flags := newUpdateCommand(nil).Flags() + flags.Set("read-only", "true") + updateService(flags, spec) + assert.Equal(t, cspec.ReadOnly, true) + + // Update without --read-only, no change + flags = newUpdateCommand(nil).Flags() + updateService(flags, spec) + assert.Equal(t, cspec.ReadOnly, true) + + // Update with --read-only=false, changed to false + flags = newUpdateCommand(nil).Flags() + flags.Set("read-only", "false") + updateService(flags, spec) + assert.Equal(t, cspec.ReadOnly, false) +}