1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #28076 from yongtang/25644-docker-service-tty

Add `--tty` to `docker service create/update`
This commit is contained in:
Daniel Nephin 2016-11-07 22:15:27 -05:00 committed by GitHub
commit 69efb4652c
9 changed files with 96 additions and 2 deletions

View file

@ -294,6 +294,7 @@ type serviceOptions struct {
workdir string workdir string
user string user string
groups []string groups []string
tty bool
mounts opts.MountOpt mounts opts.MountOpt
resources resourceOptions resources resourceOptions
@ -365,6 +366,7 @@ func (opts *serviceOptions) ToService() (swarm.ServiceSpec, error) {
Dir: opts.workdir, Dir: opts.workdir,
User: opts.user, User: opts.user,
Groups: opts.groups, Groups: opts.groups,
TTY: opts.tty,
Mounts: opts.mounts.Value(), Mounts: opts.mounts.Value(),
StopGracePeriod: opts.stopGrace.Value(), StopGracePeriod: opts.stopGrace.Value(),
}, },
@ -450,6 +452,8 @@ func addServiceFlags(cmd *cobra.Command, opts *serviceOptions) {
flags.Var(&opts.healthcheck.timeout, flagHealthTimeout, "Maximum time to allow one check to run") flags.Var(&opts.healthcheck.timeout, flagHealthTimeout, "Maximum time to allow one check to run")
flags.IntVar(&opts.healthcheck.retries, flagHealthRetries, 0, "Consecutive failures needed to report unhealthy") flags.IntVar(&opts.healthcheck.retries, flagHealthRetries, 0, "Consecutive failures needed to report unhealthy")
flags.BoolVar(&opts.healthcheck.noHealthcheck, flagNoHealthcheck, false, "Disable any container-specified HEALTHCHECK") flags.BoolVar(&opts.healthcheck.noHealthcheck, flagNoHealthcheck, false, "Disable any container-specified HEALTHCHECK")
flags.BoolVarP(&opts.tty, flagTTY, "t", false, "Allocate a pseudo-TTY")
} }
const ( const (
@ -490,6 +494,7 @@ const (
flagRestartMaxAttempts = "restart-max-attempts" flagRestartMaxAttempts = "restart-max-attempts"
flagRestartWindow = "restart-window" flagRestartWindow = "restart-window"
flagStopGracePeriod = "stop-grace-period" flagStopGracePeriod = "stop-grace-period"
flagTTY = "tty"
flagUpdateDelay = "update-delay" flagUpdateDelay = "update-delay"
flagUpdateFailureAction = "update-failure-action" flagUpdateFailureAction = "update-failure-action"
flagUpdateMaxFailureRatio = "update-max-failure-ratio" flagUpdateMaxFailureRatio = "update-max-failure-ratio"

View file

@ -274,6 +274,14 @@ func updateService(flags *pflag.FlagSet, spec *swarm.ServiceSpec) error {
return err return err
} }
if flags.Changed(flagTTY) {
tty, err := flags.GetBool(flagTTY)
if err != nil {
return err
}
cspec.TTY = tty
}
return nil return nil
} }

View file

@ -22,6 +22,7 @@ func containerSpecFromGRPC(c *swarmapi.ContainerSpec) types.ContainerSpec {
Dir: c.Dir, Dir: c.Dir,
User: c.User, User: c.User,
Groups: c.Groups, Groups: c.Groups,
TTY: c.TTY,
} }
// Mounts // Mounts
@ -77,6 +78,7 @@ func containerToGRPC(c types.ContainerSpec) (*swarmapi.ContainerSpec, error) {
Dir: c.Dir, Dir: c.Dir,
User: c.User, User: c.User,
Groups: c.Groups, Groups: c.Groups,
TTY: c.TTY,
} }
if c.StopGracePeriod != nil { if c.StopGracePeriod != nil {

View file

@ -127,6 +127,7 @@ func (c *containerConfig) image() string {
func (c *containerConfig) config() *enginecontainer.Config { func (c *containerConfig) config() *enginecontainer.Config {
config := &enginecontainer.Config{ config := &enginecontainer.Config{
Labels: c.labels(), Labels: c.labels(),
Tty: c.spec().TTY,
User: c.spec().User, User: c.spec().User,
Hostname: c.spec().Hostname, Hostname: c.spec().Hostname,
Env: c.spec().Env, Env: c.spec().Env,

View file

@ -167,6 +167,7 @@ This section lists each version from latest to oldest. Each listing includes a
* The `HostConfig` field now includes `NanoCPUs` that represents CPU quota in units of 10<sup>-9</sup> CPUs. * The `HostConfig` field now includes `NanoCPUs` that represents CPU quota in units of 10<sup>-9</sup> CPUs.
* `GET /info` now returns more structured information about security options. * `GET /info` now returns more structured information about security options.
* The `HostConfig` field now includes `CpuCount` that represents the number of CPUs available for execution by the container. Windows daemon only. * The `HostConfig` field now includes `CpuCount` that represents the number of CPUs available for execution by the container. Windows daemon only.
* `POST /services/create` and `POST /services/(id or name)/update` now accept the `TTY` parameter, which allocate a pseudo-TTY in container.
### v1.24 API changes ### v1.24 API changes

View file

@ -5112,7 +5112,8 @@ image](#create-an-image) section for more details.
} }
} }
], ],
"User": "33" "User": "33",
"TTY": false
}, },
"LogDriver": { "LogDriver": {
"Name": "json-file", "Name": "json-file",
@ -5189,6 +5190,7 @@ image](#create-an-image) section for more details.
- **User** A string value specifying the user inside the container. - **User** A string value specifying the user inside the container.
- **Labels** A map of labels to associate with the service (e.g., - **Labels** A map of labels to associate with the service (e.g.,
`{"key":"value", "key2":"value2"}`). `{"key":"value", "key2":"value2"}`).
- **TTY** A boolean indicating whether a pseudo-TTY should be allocated.
- **Mounts** Specification for mounts to be added to containers - **Mounts** Specification for mounts to be added to containers
created as part of the service. created as part of the service.
- **Target** Container path. - **Target** Container path.
@ -5390,7 +5392,8 @@ image](#create-an-image) section for more details.
"Image": "busybox", "Image": "busybox",
"Args": [ "Args": [
"top" "top"
] ],
"TTY": true
}, },
"Resources": { "Resources": {
"Limits": {}, "Limits": {},
@ -5438,6 +5441,7 @@ image](#create-an-image) section for more details.
- **User** A string value specifying the user inside the container. - **User** A string value specifying the user inside the container.
- **Labels** A map of labels to associate with the service (e.g., - **Labels** A map of labels to associate with the service (e.g.,
`{"key":"value", "key2":"value2"}`). `{"key":"value", "key2":"value2"}`).
- **TTY** A boolean indicating whether a pseudo-TTY should be allocated.
- **Mounts** Specification for mounts to be added to containers created as part of the new - **Mounts** Specification for mounts to be added to containers created as part of the new
service. service.
- **Target** Container path. - **Target** Container path.

View file

@ -52,6 +52,7 @@ Options:
--restart-max-attempts value Maximum number of restarts before giving up (default none) --restart-max-attempts value Maximum number of restarts before giving up (default none)
--restart-window value Window used to evaluate the restart policy (default none) --restart-window value Window used to evaluate the restart policy (default none)
--stop-grace-period value Time to wait before force killing a container (default none) --stop-grace-period value Time to wait before force killing a container (default none)
-t, --tty Allocate a pseudo-TTY
--update-delay duration Delay between updates --update-delay duration Delay between updates
--update-failure-action string Action on update failure (pause|continue) (default "pause") --update-failure-action string Action on update failure (pause|continue) (default "pause")
--update-max-failure-ratio value Failure rate to tolerate during an update --update-max-failure-ratio value Failure rate to tolerate during an update

View file

@ -58,6 +58,7 @@ Options:
--restart-window value Window used to evaluate the restart policy (default none) --restart-window value Window used to evaluate the restart policy (default none)
--rollback Rollback to previous specification --rollback Rollback to previous specification
--stop-grace-period value Time to wait before force killing a container (default none) --stop-grace-period value Time to wait before force killing a container (default none)
-t, --tty Allocate a pseudo-TTY
--update-delay duration Delay between updates --update-delay duration Delay between updates
--update-failure-action string Action on update failure (pause|continue) (default "pause") --update-failure-action string Action on update failure (pause|continue) (default "pause")
--update-max-failure-ratio value Failure rate to tolerate during an update --update-max-failure-ratio value Failure rate to tolerate during an update

View file

@ -718,3 +718,74 @@ func (s *DockerSwarmSuite) TestSwarmServiceEnvFile(c *check.C) {
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, "[VAR1=C VAR2]") c.Assert(out, checker.Contains, "[VAR1=C VAR2]")
} }
func (s *DockerSwarmSuite) TestSwarmServiceTTY(c *check.C) {
d := s.AddDaemon(c, true, true)
name := "top"
ttyCheck := "if [ -t 0 ]; then echo TTY > /status && top; else echo none > /status && top; fi"
// Without --tty
expectedOutput := "none"
out, err := d.Cmd("service", "create", "--name", name, "busybox", "sh", "-c", ttyCheck)
c.Assert(err, checker.IsNil)
// Make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, 1)
// We need to get the container id.
out, err = d.Cmd("ps", "-a", "-q", "--no-trunc")
c.Assert(err, checker.IsNil)
id := strings.TrimSpace(out)
out, err = d.Cmd("exec", id, "cat", "/status")
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, expectedOutput, check.Commentf("Expected '%s', but got %q", expectedOutput, out))
// Remove service
out, err = d.Cmd("service", "rm", name)
c.Assert(err, checker.IsNil)
// Make sure container has been destroyed.
waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, 0)
// With --tty
expectedOutput = "TTY"
out, err = d.Cmd("service", "create", "--name", name, "--tty", "busybox", "sh", "-c", ttyCheck)
c.Assert(err, checker.IsNil)
// Make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, 1)
// We need to get the container id.
out, err = d.Cmd("ps", "-a", "-q", "--no-trunc")
c.Assert(err, checker.IsNil)
id = strings.TrimSpace(out)
out, err = d.Cmd("exec", id, "cat", "/status")
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, expectedOutput, check.Commentf("Expected '%s', but got %q", expectedOutput, out))
}
func (s *DockerSwarmSuite) TestSwarmServiceTTYUpdate(c *check.C) {
d := s.AddDaemon(c, true, true)
// Create a service
name := "top"
_, err := d.Cmd("service", "create", "--name", name, "busybox", "top")
c.Assert(err, checker.IsNil)
// Make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, 1)
out, err := d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate.ContainerSpec.TTY }}", name)
c.Assert(err, checker.IsNil)
c.Assert(strings.TrimSpace(out), checker.Equals, "false")
_, err = d.Cmd("service", "update", "--tty", name)
c.Assert(err, checker.IsNil)
out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate.ContainerSpec.TTY }}", name)
c.Assert(err, checker.IsNil)
c.Assert(strings.TrimSpace(out), checker.Equals, "true")
}