Skip to content
This repository has been archived by the owner on Dec 13, 2021. It is now read-only.

Commit

Permalink
add support for both attach mode and detach mode (#158)
Browse files Browse the repository at this point in the history
* add support for both attach mode and detach mode

* fix: detach flag was parsed incorrectly
  • Loading branch information
v01dstar authored and AkihiroSuda committed Jun 27, 2016
1 parent 4919228 commit a8e405b
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 28 deletions.
12 changes: 8 additions & 4 deletions nmz/cli/container/run/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
"github.com/osrg/namazu/nmz/util/config"
)

func prepare(args []string) (dockerOpt *docker.CreateContainerOptions, removeOnExit bool, nmzCfg config.Config, err error) {
func prepare(args []string) (dockerOpt *docker.CreateContainerOptions, removeOnExit bool, detach bool, nmzCfg config.Config, err error) {
if len(args) < 3 {
// FIXME
err = fmt.Errorf("bad argument: %s", args)
Expand All @@ -39,6 +39,7 @@ func prepare(args []string) (dockerOpt *docker.CreateContainerOptions, removeOnE
return
}
removeOnExit = flagSet.IsSet("-rm")
detach = flagSet.IsSet("d") || flag.IsSet("-detach")

nmzCfgPath := flagSet.Lookup("-nmz-autopilot").Value.String()
nmzCfg, err = newConfig(nmzCfgPath)
Expand All @@ -61,12 +62,15 @@ func help() string {
Run a command in a new Namazu Container
Docker-compatible options:
-d, --detach [NOT SUPPORTED] Run container in background and print container ID
-d, --detach Run container in background and print container ID
-i, --interactive Keep STDIN open even if not attached
-p Publish a container's port(s) to the host
--name Assign a name to the container
--rm Automatically remove the container when it exits
-t, --tty Allocate a pseudo-TTY
-v, --volume=[] Bind mount a volume
--volumes-from Mount volumes from the specified container(s)
--privileged Give extended privileges to this container
Namazu-specific options:
-nmz-autopilot Namazu configuration file
Expand All @@ -77,7 +81,7 @@ NOTE: Unlike docker, COMMAND is mandatory at the moment.
}

func Run(args []string) int {
dockerOpt, removeOnExit, nmzCfg, err := prepare(args)
dockerOpt, removeOnExit, detach, nmzCfg, err := prepare(args)
if err != nil {
// do not panic here
fmt.Fprintf(os.Stderr, "%s\n", err)
Expand All @@ -91,7 +95,7 @@ func Run(args []string) int {
}

containerExitStatusChan := make(chan error)
c, err := ns.Boot(client, dockerOpt, containerExitStatusChan)
c, err := ns.Boot(client, dockerOpt, detach, containerExitStatusChan)
if err == docker.ErrNoSuchImage {
log.Critical(err)
// TODO: pull the image automatically
Expand Down
96 changes: 74 additions & 22 deletions nmz/cli/container/run/runflag.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,56 +20,108 @@ import (
// FIXME: we should not rely on internal docker packages..
"github.com/docker/docker/opts"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/go-connections/nat"
docker "github.com/fsouza/go-dockerclient"
)

// TODO: we should support more options..
func parseRun(cmd *flag.FlagSet, args []string) (*docker.CreateContainerOptions, error) {
var (
flStdin = cmd.Bool([]string{"i", "-interactive"}, false, "Keep STDIN open even if not attached")
flTty = cmd.Bool([]string{"t", "-tty"}, false, "Allocate a pseudo-TTY")
flDetach = cmd.Bool([]string{"d", "-detach"}, false, "[NOT SUPPORTED] Run container in background and print container ID")
attachStdin = true
attachStdout = true
attachStderr = true
stdinOnce = true

flVolumes = opts.NewListOpts(nil)
flVolumesFrom = opts.NewListOpts(nil)
flPublish = opts.NewListOpts(nil)

flStdin = cmd.Bool([]string{"i", "-interactive"}, false, "Keep STDIN open even if not attached")
flTty = cmd.Bool([]string{"t", "-tty"}, false, "Allocate a pseudo-TTY")
flPrivileged = cmd.Bool([]string{"-privileged"}, false, "Give extended privileges to this container")
flDetach = cmd.Bool([]string{"d", "-detach"}, false, "Run container in background and print container ID")
flAutoRemove = cmd.Bool([]string{"-rm"}, false, "Automatically remove the container when it exits")

flName = cmd.String([]string{"-name"}, "", "Assign a name to the container")
flVolumes = opts.NewListOpts(nil)
// the caller should handle "-rm" with cmd.IsSet()
_ = cmd.Bool([]string{"-rm"}, false, "Automatically remove the container when it exits")
flNetMode = cmd.String([]string{"-net"}, "default", "Connect a container to a network")

// the caller should handle "-nmz-autopilot"
_ = cmd.String([]string{"-nmz-autopilot"}, "", "Namazu configuration file")
)
cmd.Var(&flVolumes, []string{"v", "-volume"}, "Bind mount a volume")
cmd.Var(&flPublish, []string{"p"}, "Publish a container's port(s) to the host")
cmd.Var(&flVolumesFrom, []string{"-volumes-from"}, "Mount volumes from the specified container(s)")

if err := cmd.Parse(args); err != nil {
return nil, err
}
if !*flStdin {
return nil, fmt.Errorf("--interactive is expected.")
}
if !*flTty {
return nil, fmt.Errorf("--tty is expected.")
}
if *flDetach {
return nil, fmt.Errorf("Currently, --detach is not supported.")
}

parsedArgs := cmd.Args()
if len(parsedArgs) < 2 {
return nil, fmt.Errorf("requires a minimum of 2 arguments")

if !*flDetach {
if !*flStdin {
return nil, fmt.Errorf("--interactive is expected in attach mode.")
}
if !*flTty {
return nil, fmt.Errorf("--tty is expected in attach mode.")
}
if len(parsedArgs) < 2 {
return nil, fmt.Errorf("requires a minimum of 2 arguments in attach mode.")
}
} else {
if *flAutoRemove {
return nil, fmt.Errorf("--rm is not availible in detach mode.")
}
attachStdin = false
attachStdout = false
attachStderr = false
stdinOnce = false
}

image := parsedArgs[0]
execCmd := parsedArgs[1:]

// FIXME: we should implement this parse function ourselves..
_, portMap, err := nat.ParsePortSpecs(flPublish.GetAll())
if err != nil {
return nil, err
}

// Transform nat.PortMap to docker.PortMap(map[string][]PortBindings).
portBindings := make(map[docker.Port][]docker.PortBinding)
for port, bindings := range portMap {
for _, binding := range bindings {
// nat.Port string
bindingSlice, exists := portBindings[docker.Port(port)]
if !exists {
bindingSlice = []docker.PortBinding{}
}

portBindings[docker.Port(port)] = append(bindingSlice, docker.PortBinding{
HostIP: binding.HostIP,
HostPort: binding.HostPort,
})
}
}

dockerOpt := docker.CreateContainerOptions{
Name: *flName,
Config: &docker.Config{
Image: image,
Cmd: execCmd,
OpenStdin: *flStdin,
StdinOnce: true,
AttachStdin: true,
AttachStdout: true,
AttachStderr: true,
StdinOnce: stdinOnce,
AttachStdin: attachStdin,
AttachStdout: attachStdout,
AttachStderr: attachStderr,
Tty: *flTty,
},
HostConfig: &docker.HostConfig{
Binds: flVolumes.GetAllOrEmpty(),
Binds: flVolumes.GetAllOrEmpty(),
Privileged: *flPrivileged,
PortBindings: portBindings,
NetworkMode: *flNetMode,
VolumesFrom: flVolumesFrom.GetAllOrEmpty(),
},
}
return &dockerOpt, nil
Expand Down
12 changes: 10 additions & 2 deletions nmz/container/ns/boot.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
docker "github.com/fsouza/go-dockerclient"
)

func Boot(client *docker.Client, opt *docker.CreateContainerOptions,
func Boot(client *docker.Client, opt *docker.CreateContainerOptions, detach bool,
exitCh chan error) (*docker.Container, error) {
log.Debugf("Creating container for image %s", opt.Config.Image)
container, err := client.CreateContainer(*opt)
Expand All @@ -34,7 +34,15 @@ func Boot(client *docker.Client, opt *docker.CreateContainerOptions,

log.Debugf("Starting container %s", container.ID)
go func() {
exitCh <- dockerpty.Start(client, container, opt.HostConfig)
if detach {
err = client.StartContainer(container.ID, opt.HostConfig)
if err == nil {
_, err = client.WaitContainer(container.ID)
}
exitCh <- err
} else {
exitCh <- dockerpty.Start(client, container, opt.HostConfig)
}
}()

trial := 0
Expand Down

0 comments on commit a8e405b

Please sign in to comment.