Skip to content
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
51 changes: 46 additions & 5 deletions cmd/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import (
"io/ioutil"
"os"
"os/exec"
"os/signal"
"strconv"
"strings"

"github.com/Sirupsen/logrus"
"github.com/rancher/go-rancher/client"
Expand All @@ -19,7 +22,13 @@ func DockerCommand() cli.Command {
Usage: "Run docker CLI on a host",
Description: "\nUses the $RANCHER_DOCKER_HOST to run docker commands. Use `--host <hostID>` or `--host <hostName>` to select a different host.\n\nExample:\n\t$ rancher --host 1h1 docker ps\n",
Action: hostDocker,
Flags: []cli.Flag{},
Flags: []cli.Flag{
cli.BoolFlag{
Name: "help-docker",
Usage: "Display the 'docker --help'",
},
},
SkipFlagParsing: true,
}
}

Expand All @@ -28,8 +37,16 @@ func hostDocker(ctx *cli.Context) error {
}

func doDocker(ctx *cli.Context) error {
hostname := ctx.GlobalString("host")
args := ctx.Args()
if len(args) > 0 && (args[0] == "-h" || args[0] == "--help") {
return cli.ShowCommandHelp(ctx, "docker")
}

if len(args) > 0 && args[0] == "--help-docker" {
return runDockerHelp("")
}

hostname := ctx.GlobalString("host")
if hostname == "" {
return fmt.Errorf("--host is required")
}
Expand All @@ -39,7 +56,7 @@ func doDocker(ctx *cli.Context) error {
return err
}

return runDocker(hostname, c, ctx.Args())
return runDocker(hostname, c, args)
}

func runDockerCommand(hostname string, c *client.RancherClient, command string, args []string) error {
Expand All @@ -50,6 +67,20 @@ func runDocker(hostname string, c *client.RancherClient, args []string) error {
return runDockerWithOutput(hostname, c, args, os.Stdout, os.Stderr)
}

func determineApiVersion(host *client.Host) string {
version := host.Labels["io.rancher.host.docker_version"]
parts := strings.Split(fmt.Sprint(version), ".")
if len(parts) != 2 {
return ""
}
num, err := strconv.Atoi(parts[1])
if err != nil {
return ""
}

return fmt.Sprintf("1.%d", num+12)
}

func runDockerWithOutput(hostname string, c *client.RancherClient, args []string,
out, outErr io.Writer) error {
resource, err := Lookup(c, hostname, "host")
Expand All @@ -67,6 +98,8 @@ func runDockerWithOutput(hostname string, c *client.RancherClient, args []string
return fmt.Errorf("Can not contact host %s in state %s", hostname, state)
}

apiVersion := determineApiVersion(host)

tempfile, err := ioutil.TempFile("", "docker-sock")
if err != nil {
return err
Expand All @@ -88,18 +121,26 @@ func runDockerWithOutput(hostname string, c *client.RancherClient, args []string
}()

var cmd *exec.Cmd
if len(args) == 1 && args[0] == "--" {
cmd = exec.Command(os.Getenv("SHELL"), args[1:]...)
if len(args) > 0 && args[0] == "--" {
if len(args) > 1 {
cmd = exec.Command(args[1], args[2:]...)
} else {
cmd = exec.Command(os.Getenv("SHELL"))
}
cmd.Env = append(os.Environ(), "debian_chroot=docker:"+hostname)
} else {
cmd = exec.Command("docker", args...)
cmd.Env = os.Environ()
}

cmd.Env = append(cmd.Env, "DOCKER_HOST="+dockerHost)
if apiVersion != "" {
cmd.Env = append(cmd.Env, "DOCKER_API_VERSION="+apiVersion)
}
cmd.Stdin = os.Stdin
cmd.Stdout = out
cmd.Stderr = outErr

signal.Ignore(os.Interrupt)
return cmd.Run()
}
26 changes: 19 additions & 7 deletions cmd/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ import (

func ExecCommand() cli.Command {
return cli.Command{
Name: "exec",
Usage: "Run a command on a container",
Description: "\nThe command will find the container on the host and use `docker exec` to access the container. Any options that `docker exec` uses can be passed as an option for `rancher exec`.\n\nExample:\n\t$ rancher exec -i -t 1i1\n",
Action: execCommand,
Name: "exec",
Usage: "Run a command on a container",
Description: "\nThe command will find the container on the host and use `docker exec` to access the container. Any options that `docker exec` uses can be passed as an option for `rancher exec`.\n\nExample:\n\t$ rancher exec -i -t 1i1\n",
Action: execCommand,
SkipFlagParsing: true,
Flags: []cli.Flag{
cli.BoolFlag{
Name: "help-docker",
Expand All @@ -32,7 +33,12 @@ func execCommand(ctx *cli.Context) error {
}

func execCommandInternal(ctx *cli.Context) error {
if ctx.Bool("help-docker") {
args := ctx.Args()
if len(args) > 0 && (args[0] == "-h" || args[0] == "--help") {
return cli.ShowCommandHelp(ctx, "exec")
}

if len(args) > 0 && args[0] == "--help-docker" {
return runDockerHelp("exec")
}

Expand All @@ -46,12 +52,14 @@ func execCommandInternal(ctx *cli.Context) error {
return err
}

// this is a massive hack. Need to fix the real issue
args = append([]string{"-i"}, args...)
return runDockerCommand(hostID, c, "exec", args)
}

func isHelp(args []string) bool {
for _, i := range args {
if i == "--help" {
if i == "--help" || i == "-h" {
return true
}
}
Expand Down Expand Up @@ -175,7 +183,11 @@ func getHostnameAndContainerID(c *client.RancherClient, containerID string) (str
}

func runDockerHelp(subcommand string) error {
cmd := exec.Command("docker", subcommand, "--help")
args := []string{"--help"}
if subcommand != "" {
args = []string{subcommand, "--help"}
}
cmd := exec.Command("docker", args...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
Expand Down