diff --git a/components/cli/appveyor.yml b/components/cli/appveyor.yml index 262021d8ab..bb1e7d47c5 100644 --- a/components/cli/appveyor.yml +++ b/components/cli/appveyor.yml @@ -4,7 +4,7 @@ clone_folder: c:\gopath\src\github.com\docker\cli environment: GOPATH: c:\gopath - GOVERSION: 1.10 + GOVERSION: 1.10.3 DEPVERSION: v0.4.1 install: diff --git a/components/cli/cli/command/commands/commands.go b/components/cli/cli/command/commands/commands.go index a0e3465845..8780830573 100644 --- a/components/cli/cli/command/commands/commands.go +++ b/components/cli/cli/command/commands/commands.go @@ -24,7 +24,7 @@ import ( ) // AddCommands adds all the commands from cli/command to the root command -func AddCommands(cmd *cobra.Command, dockerCli *command.DockerCli) { +func AddCommands(cmd *cobra.Command, dockerCli command.Cli) { cmd.AddCommand( // checkpoint checkpoint.NewCheckpointCommand(dockerCli), diff --git a/components/cli/cli/command/formatter/service.go b/components/cli/cli/command/formatter/service.go index 697d6be4c0..5dde8006d2 100644 --- a/components/cli/cli/command/formatter/service.go +++ b/components/cli/cli/command/formatter/service.go @@ -85,6 +85,9 @@ ContainerSpec: {{- if .ContainerWorkDir }} Dir: {{ .ContainerWorkDir }} {{- end -}} +{{- if .HasContainerInit }} + Init: {{ .ContainerInit }} +{{- end -}} {{- if .ContainerUser }} User: {{ .ContainerUser }} {{- end }} @@ -372,6 +375,14 @@ func (ctx *serviceInspectContext) ContainerUser() string { return ctx.Service.Spec.TaskTemplate.ContainerSpec.User } +func (ctx *serviceInspectContext) HasContainerInit() bool { + return ctx.Service.Spec.TaskTemplate.ContainerSpec.Init != nil +} + +func (ctx *serviceInspectContext) ContainerInit() bool { + return *ctx.Service.Spec.TaskTemplate.ContainerSpec.Init +} + func (ctx *serviceInspectContext) ContainerMounts() []mounttypes.Mount { return ctx.Service.Spec.TaskTemplate.ContainerSpec.Mounts } diff --git a/components/cli/cli/command/image/push.go b/components/cli/cli/command/image/push.go index f05e813360..de6c2ec34e 100644 --- a/components/cli/cli/command/image/push.go +++ b/components/cli/cli/command/image/push.go @@ -26,7 +26,7 @@ func NewPushCommand(dockerCli command.Cli) *cobra.Command { Args: cli.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { opts.remote = args[0] - return runPush(dockerCli, opts) + return RunPush(dockerCli, opts) }, } @@ -37,7 +37,8 @@ func NewPushCommand(dockerCli command.Cli) *cobra.Command { return cmd } -func runPush(dockerCli command.Cli, opts pushOptions) error { +// RunPush performs a push against the engine based on the specified options +func RunPush(dockerCli command.Cli, opts pushOptions) error { ref, err := reference.ParseNormalizedNamed(opts.remote) if err != nil { return err diff --git a/components/cli/cli/command/image/save.go b/components/cli/cli/command/image/save.go index daa0dd8f72..ef23ca1bb1 100644 --- a/components/cli/cli/command/image/save.go +++ b/components/cli/cli/command/image/save.go @@ -27,7 +27,7 @@ func NewSaveCommand(dockerCli command.Cli) *cobra.Command { Args: cli.RequiresMinArgs(1), RunE: func(cmd *cobra.Command, args []string) error { opts.images = args - return runSave(dockerCli, opts) + return RunSave(dockerCli, opts) }, } @@ -38,7 +38,8 @@ func NewSaveCommand(dockerCli command.Cli) *cobra.Command { return cmd } -func runSave(dockerCli command.Cli, opts saveOptions) error { +// RunSave performs a save against the engine based on the specified options +func RunSave(dockerCli command.Cli, opts saveOptions) error { if opts.output == "" && dockerCli.Out().IsTerminal() { return errors.New("cowardly refusing to save to a terminal. Use the -o flag or redirect") } diff --git a/components/cli/cli/command/service/create.go b/components/cli/cli/command/service/create.go index ca7aaba376..ec74eb43c3 100644 --- a/components/cli/cli/command/service/create.go +++ b/components/cli/cli/command/service/create.go @@ -58,6 +58,8 @@ func newCreateCommand(dockerCli command.Cli) *cobra.Command { flags.SetAnnotation(flagDNSSearch, "version", []string{"1.25"}) flags.Var(&opts.hosts, flagHost, "Set one or more custom host-to-IP mappings (host:ip)") flags.SetAnnotation(flagHost, "version", []string{"1.25"}) + flags.BoolVar(&opts.init, flagInit, false, "Use an init inside each service container to forward signals and reap processes") + flags.SetAnnotation(flagInit, "version", []string{"1.37"}) flags.Var(cliopts.NewListOptsRef(&opts.resources.resGenericResources, ValidateSingleGenericResource), "generic-resource", "User defined resources") flags.SetAnnotation(flagHostAdd, "version", []string{"1.32"}) diff --git a/components/cli/cli/command/service/opts.go b/components/cli/cli/command/service/opts.go index 6d42745156..6a9591abce 100644 --- a/components/cli/cli/command/service/opts.go +++ b/components/cli/cli/command/service/opts.go @@ -480,6 +480,7 @@ type serviceOptions struct { user string groups opts.ListOpts credentialSpec credentialSpecOpt + init bool stopSignal string tty bool readOnly bool @@ -624,6 +625,7 @@ func (options *serviceOptions) ToService(ctx context.Context, apiClient client.N TTY: options.tty, ReadOnly: options.readOnly, Mounts: options.mounts.Value(), + Init: &options.init, DNSConfig: &swarm.DNSConfig{ Nameservers: options.dns.GetAll(), Search: options.dnsSearch.GetAll(), @@ -875,6 +877,7 @@ const ( flagRollbackMonitor = "rollback-monitor" flagRollbackOrder = "rollback-order" flagRollbackParallelism = "rollback-parallelism" + flagInit = "init" flagStopGracePeriod = "stop-grace-period" flagStopSignal = "stop-signal" flagTTY = "tty" diff --git a/components/cli/cli/command/service/update.go b/components/cli/cli/command/service/update.go index 66494fdbb9..3e380db23e 100644 --- a/components/cli/cli/command/service/update.go +++ b/components/cli/cli/command/service/update.go @@ -94,6 +94,8 @@ func newUpdateCommand(dockerCli command.Cli) *cobra.Command { flags.SetAnnotation(flagDNSSearchAdd, "version", []string{"1.25"}) flags.Var(&options.hosts, flagHostAdd, "Add a custom host-to-IP mapping (host:ip)") flags.SetAnnotation(flagHostAdd, "version", []string{"1.25"}) + flags.BoolVar(&options.init, flagInit, false, "Use an init inside each service container to forward signals and reap processes") + flags.SetAnnotation(flagInit, "version", []string{"1.37"}) // Add needs parsing, Remove only needs the key flags.Var(newListOptsVar(), flagGenericResourcesRemove, "Remove a Generic resource") @@ -235,6 +237,12 @@ func runUpdate(dockerCli command.Cli, flags *pflag.FlagSet, options *serviceOpti // nolint: gocyclo func updateService(ctx context.Context, apiClient client.NetworkAPIClient, flags *pflag.FlagSet, spec *swarm.ServiceSpec) error { + updateBoolPtr := func(flag string, field **bool) { + if flags.Changed(flag) { + b, _ := flags.GetBool(flag) + *field = &b + } + } updateString := func(flag string, field *string) { if flags.Changed(flag) { *field, _ = flags.GetString(flag) @@ -306,6 +314,7 @@ func updateService(ctx context.Context, apiClient client.NetworkAPIClient, flags updateString(flagWorkdir, &cspec.Dir) updateString(flagUser, &cspec.User) updateString(flagHostname, &cspec.Hostname) + updateBoolPtr(flagInit, &cspec.Init) if err := updateIsolation(flagIsolation, &cspec.Isolation); err != nil { return err } diff --git a/components/cli/cli/command/service/update_test.go b/components/cli/cli/command/service/update_test.go index fa761ba08f..847b6ab128 100644 --- a/components/cli/cli/command/service/update_test.go +++ b/components/cli/cli/command/service/update_test.go @@ -547,6 +547,32 @@ func TestUpdateReadOnly(t *testing.T) { assert.Check(t, !cspec.ReadOnly) } +func TestUpdateInit(t *testing.T) { + spec := &swarm.ServiceSpec{ + TaskTemplate: swarm.TaskSpec{ + ContainerSpec: &swarm.ContainerSpec{}, + }, + } + cspec := spec.TaskTemplate.ContainerSpec + + // Update with --init=true + flags := newUpdateCommand(nil).Flags() + flags.Set("init", "true") + updateService(nil, nil, flags, spec) + assert.Check(t, is.Equal(true, *cspec.Init)) + + // Update without --init, no change + flags = newUpdateCommand(nil).Flags() + updateService(nil, nil, flags, spec) + assert.Check(t, is.Equal(true, *cspec.Init)) + + // Update with --init=false + flags = newUpdateCommand(nil).Flags() + flags.Set("init", "false") + updateService(nil, nil, flags, spec) + assert.Check(t, is.Equal(false, *cspec.Init)) +} + func TestUpdateStopSignal(t *testing.T) { spec := &swarm.ServiceSpec{ TaskTemplate: swarm.TaskSpec{ diff --git a/components/cli/cli/command/system/inspect.go b/components/cli/cli/command/system/inspect.go index 437cd702fb..b49b4b33d3 100644 --- a/components/cli/cli/command/system/inspect.go +++ b/components/cli/cli/command/system/inspect.go @@ -22,7 +22,7 @@ type inspectOptions struct { } // NewInspectCommand creates a new cobra.Command for `docker inspect` -func NewInspectCommand(dockerCli *command.DockerCli) *cobra.Command { +func NewInspectCommand(dockerCli command.Cli) *cobra.Command { var opts inspectOptions cmd := &cobra.Command{ @@ -43,7 +43,7 @@ func NewInspectCommand(dockerCli *command.DockerCli) *cobra.Command { return cmd } -func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error { +func runInspect(dockerCli command.Cli, opts inspectOptions) error { var elementSearcher inspect.GetRefFunc switch opts.inspectType { case "", "container", "image", "node", "network", "service", "volume", "task", "plugin", "secret": @@ -54,62 +54,62 @@ func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error { return inspect.Inspect(dockerCli.Out(), opts.ids, opts.format, elementSearcher) } -func inspectContainers(ctx context.Context, dockerCli *command.DockerCli, getSize bool) inspect.GetRefFunc { +func inspectContainers(ctx context.Context, dockerCli command.Cli, getSize bool) inspect.GetRefFunc { return func(ref string) (interface{}, []byte, error) { return dockerCli.Client().ContainerInspectWithRaw(ctx, ref, getSize) } } -func inspectImages(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { +func inspectImages(ctx context.Context, dockerCli command.Cli) inspect.GetRefFunc { return func(ref string) (interface{}, []byte, error) { return dockerCli.Client().ImageInspectWithRaw(ctx, ref) } } -func inspectNetwork(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { +func inspectNetwork(ctx context.Context, dockerCli command.Cli) inspect.GetRefFunc { return func(ref string) (interface{}, []byte, error) { return dockerCli.Client().NetworkInspectWithRaw(ctx, ref, types.NetworkInspectOptions{}) } } -func inspectNode(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { +func inspectNode(ctx context.Context, dockerCli command.Cli) inspect.GetRefFunc { return func(ref string) (interface{}, []byte, error) { return dockerCli.Client().NodeInspectWithRaw(ctx, ref) } } -func inspectService(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { +func inspectService(ctx context.Context, dockerCli command.Cli) inspect.GetRefFunc { return func(ref string) (interface{}, []byte, error) { // Service inspect shows defaults values in empty fields. return dockerCli.Client().ServiceInspectWithRaw(ctx, ref, types.ServiceInspectOptions{InsertDefaults: true}) } } -func inspectTasks(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { +func inspectTasks(ctx context.Context, dockerCli command.Cli) inspect.GetRefFunc { return func(ref string) (interface{}, []byte, error) { return dockerCli.Client().TaskInspectWithRaw(ctx, ref) } } -func inspectVolume(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { +func inspectVolume(ctx context.Context, dockerCli command.Cli) inspect.GetRefFunc { return func(ref string) (interface{}, []byte, error) { return dockerCli.Client().VolumeInspectWithRaw(ctx, ref) } } -func inspectPlugin(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { +func inspectPlugin(ctx context.Context, dockerCli command.Cli) inspect.GetRefFunc { return func(ref string) (interface{}, []byte, error) { return dockerCli.Client().PluginInspectWithRaw(ctx, ref) } } -func inspectSecret(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { +func inspectSecret(ctx context.Context, dockerCli command.Cli) inspect.GetRefFunc { return func(ref string) (interface{}, []byte, error) { return dockerCli.Client().SecretInspectWithRaw(ctx, ref) } } -func inspectAll(ctx context.Context, dockerCli *command.DockerCli, getSize bool, typeConstraint string) inspect.GetRefFunc { +func inspectAll(ctx context.Context, dockerCli command.Cli, getSize bool, typeConstraint string) inspect.GetRefFunc { var inspectAutodetect = []struct { objectType string isSizeSupported bool diff --git a/components/cli/dockerfiles/Dockerfile.binary-native b/components/cli/dockerfiles/Dockerfile.binary-native index ea76ce5fb5..d6fdf533b1 100644 --- a/components/cli/dockerfiles/Dockerfile.binary-native +++ b/components/cli/dockerfiles/Dockerfile.binary-native @@ -1,4 +1,4 @@ -FROM golang:1.10.2-alpine +FROM golang:1.10.3-alpine RUN apk add -U git bash coreutils gcc musl-dev diff --git a/components/cli/dockerfiles/Dockerfile.cross b/components/cli/dockerfiles/Dockerfile.cross index 8bc5c2ea4e..40a01b88a5 100644 --- a/components/cli/dockerfiles/Dockerfile.cross +++ b/components/cli/dockerfiles/Dockerfile.cross @@ -1,3 +1,3 @@ -FROM dockercore/golang-cross:1.10.2@sha256:297fa4bc113facd7a528699919f86009420a6b5bedbdc89da35c14f7fee047e1 +FROM dockercore/golang-cross:1.10.3@sha256:7671b4ed357fda50124e5679d36c4c3206ded4d43f1d2e0ff3d120a1e2bf94d7 ENV DISABLE_WARN_OUTSIDE_CONTAINER=1 WORKDIR /go/src/github.com/docker/cli diff --git a/components/cli/dockerfiles/Dockerfile.dev b/components/cli/dockerfiles/Dockerfile.dev index 3ff8ad4de8..1b87ad5bb1 100644 --- a/components/cli/dockerfiles/Dockerfile.dev +++ b/components/cli/dockerfiles/Dockerfile.dev @@ -1,5 +1,5 @@ -FROM golang:1.10.2-alpine +FROM golang:1.10.3-alpine RUN apk add -U git make bash coreutils ca-certificates curl diff --git a/components/cli/dockerfiles/Dockerfile.e2e b/components/cli/dockerfiles/Dockerfile.e2e index 4087fb83a5..167bbf0e1e 100644 --- a/components/cli/dockerfiles/Dockerfile.e2e +++ b/components/cli/dockerfiles/Dockerfile.e2e @@ -1,4 +1,4 @@ -ARG GO_VERSION=1.10.2 +ARG GO_VERSION=1.10.3 # Use Debian based image as docker-compose requires glibc. FROM golang:${GO_VERSION} diff --git a/components/cli/dockerfiles/Dockerfile.lint b/components/cli/dockerfiles/Dockerfile.lint index 7113062c65..9726eecb42 100644 --- a/components/cli/dockerfiles/Dockerfile.lint +++ b/components/cli/dockerfiles/Dockerfile.lint @@ -1,4 +1,4 @@ -FROM golang:1.10.2-alpine +FROM golang:1.10.3-alpine RUN apk add -U git diff --git a/components/cli/docs/reference/commandline/service_create.md b/components/cli/docs/reference/commandline/service_create.md index cdda1373ae..8fdb5297a1 100644 --- a/components/cli/docs/reference/commandline/service_create.md +++ b/components/cli/docs/reference/commandline/service_create.md @@ -43,6 +43,7 @@ Options: --help Print usage --host list Set one or more custom host-to-IP mappings (host:ip) --hostname string Container hostname + --init bool Use an init inside each service container to forward signals and reap processes --isolation string Service container isolation mode -l, --label list Service labels --limit-cpu decimal Limit CPUs diff --git a/components/cli/docs/reference/commandline/service_update.md b/components/cli/docs/reference/commandline/service_update.md index 5c43f02099..f3d70495b3 100644 --- a/components/cli/docs/reference/commandline/service_update.md +++ b/components/cli/docs/reference/commandline/service_update.md @@ -54,6 +54,7 @@ Options: --host-add list Add a custom host-to-IP mapping (host:ip) --host-rm list Remove a custom host-to-IP mapping (host:ip) --hostname string Container hostname + --init bool Use an init inside each service container to forward signals and reap processes --image string Service image tag --isolation string Service container isolation mode --label-add list Add or update a service label