Skip to content

Commit

Permalink
docker: use docker API for executor
Browse files Browse the repository at this point in the history
  • Loading branch information
andrestc committed Mar 29, 2018
1 parent 6772dfd commit 5d14433
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 20 deletions.
47 changes: 37 additions & 10 deletions internal/docker/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,50 @@
package docker

import (
"fmt"

"github.com/fsouza/go-dockerclient"
"github.com/tsuru/tsuru/exec"
)

const dockerBinary = "/usr/local/bin/docker"

// Executor uses docker exec to execute a command in a running docker container
type Executor struct {
containerID string
executor exec.Executor
ContainerID string
Client *Client
}

func (d *Executor) Execute(opts exec.ExecuteOptions) error {
// TODO: use the exec API to properly configure workdir etc...
if d.executor == nil {
d.executor = &exec.OsExecutor{}
cmd := append([]string{opts.Cmd}, opts.Args...)
if opts.Dir != "" {
cmd = append([]string{"cd", opts.Dir, "&&"}, cmd...)
}
// TODO: Envs for API pre v1.25
e, err := d.Client.api.CreateExec(docker.CreateExecOptions{
Container: d.ContainerID,
Cmd: cmd,
AttachStdin: opts.Stdin != nil,
AttachStdout: opts.Stdout != nil,
AttachStderr: opts.Stderr != nil,
})
if err != nil {
return err
}
err = d.Client.api.StartExec(e.ID, docker.StartExecOptions{
OutputStream: opts.Stdout,
InputStream: opts.Stdin,
ErrorStream: opts.Stderr,
Tty: true,
RawTerminal: true,
})
if err != nil {
return err
}
execData, err := d.Client.api.InspectExec(e.ID)
if err != nil {
return err
}
if execData.ExitCode != 0 {
return fmt.Errorf("container exited with error: %v", execData.ExitCode)
}
opts.Args = append([]string{"exec", "-t", d.containerID, opts.Cmd}, opts.Args...)
opts.Cmd = dockerBinary
return d.executor.Execute(opts)
return nil
}
46 changes: 36 additions & 10 deletions internal/docker/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,46 @@
package docker

import (
"bytes"

"github.com/fsouza/go-dockerclient"

"github.com/fsouza/go-dockerclient/testing"
"github.com/tsuru/tsuru/exec"
"github.com/tsuru/tsuru/exec/exectest"
"gopkg.in/check.v1"
)

func (s *S) TestExecutor(c *check.C) {
fake := &exectest.FakeExecutor{}
e := Executor{containerID: "dd5e0fbf6d3c", executor: fake}
e.Execute(exec.ExecuteOptions{
Cmd: "/bin/ps",
server, err := testing.NewServer("127.0.0.1:0", nil, nil)
c.Assert(err, check.IsNil)
defer server.Stop()
client, err := NewClient(server.URL())
c.Assert(err, check.IsNil)

err = client.api.PullImage(docker.PullImageOptions{Repository: "my-img"}, docker.AuthConfiguration{})
c.Assert(err, check.IsNil)
cont, err := client.api.CreateContainer(docker.CreateContainerOptions{
Name: "my-container",
Config: &docker.Config{Image: "my-img"},
})
c.Assert(err, check.IsNil)
err = client.api.StartContainer(cont.ID, nil)
c.Assert(err, check.IsNil)

var executed bool
server.PrepareExec("*", func() {
executed = true
})

e := Executor{ContainerID: cont.ID, Client: client}
out := new(bytes.Buffer)
err = e.Execute(exec.ExecuteOptions{
Dir: "/home/",
Cmd: "/bin/ps",
Args: []string{"aux"},
Envs: []string{"A=B"},
Stdout: out,
})
executedCmds := fake.GetCommands(dockerBinary)
c.Assert(len(executedCmds), check.Equals, 1)
args := executedCmds[0].GetArgs()
expectedArgs := []string{"exec", "-t", "dd5e0fbf6d3c", "/bin/ps"}
c.Assert(args, check.DeepEquals, expectedArgs)
c.Assert(err, check.IsNil)
c.Assert(executed, check.Equals, true)
}

0 comments on commit 5d14433

Please sign in to comment.