Implement service integration tests

This is done in a hacky way as currently there is no better way.
Uses known implementation details about how tasks are scheduled to be
able to operate on the underlying container.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
Brian Goff 2016-06-29 14:00:11 -04:00
parent 97aebe9a6c
commit e5ec575b32
4 changed files with 102 additions and 4 deletions

View file

@ -4,6 +4,7 @@ import (
"fmt"
"os"
"path/filepath"
"sync"
"testing"
"github.com/docker/docker/cliconfig"
@ -194,9 +195,10 @@ func init() {
}
type DockerSwarmSuite struct {
ds *DockerSuite
daemons []*SwarmDaemon
portIndex int
ds *DockerSuite
daemons []*SwarmDaemon
daemonsLock sync.Mutex // protect access to daemons
portIndex int
}
func (s *DockerSwarmSuite) SetUpTest(c *check.C) {
@ -227,19 +229,23 @@ func (s *DockerSwarmSuite) AddDaemon(c *check.C, joinSwarm, manager bool) *Swarm
}
s.portIndex++
s.daemonsLock.Lock()
s.daemons = append(s.daemons, d)
s.daemonsLock.Unlock()
return d
}
func (s *DockerSwarmSuite) TearDownTest(c *check.C) {
testRequires(c, DaemonIsLinux)
s.daemonsLock.Lock()
for _, d := range s.daemons {
d.Stop()
}
s.daemons = nil
s.portIndex = 0
s.daemonsLock.Unlock()
s.portIndex = 0
s.ds.TearDownTest(c)
}

View file

@ -9,6 +9,7 @@ import (
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/filters"
"github.com/docker/engine-api/types/swarm"
"github.com/go-check/check"
)
@ -131,6 +132,32 @@ func (d *SwarmDaemon) getService(c *check.C, id string) *swarm.Service {
return &service
}
func (d *SwarmDaemon) getServiceTasks(c *check.C, service string) []swarm.Task {
var tasks []swarm.Task
filterArgs := filters.NewArgs()
filterArgs.Add("desired-state", "running")
filterArgs.Add("service", service)
filters, err := filters.ToParam(filterArgs)
c.Assert(err, checker.IsNil)
status, out, err := d.SockRequest("GET", "/tasks?filters="+filters, nil)
c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out)))
c.Assert(err, checker.IsNil, check.Commentf(string(out)))
c.Assert(json.Unmarshal(out, &tasks), checker.IsNil)
return tasks
}
func (d *SwarmDaemon) getTask(c *check.C, id string) swarm.Task {
var task swarm.Task
status, out, err := d.SockRequest("GET", "/tasks/"+id, nil)
c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out)))
c.Assert(err, checker.IsNil, check.Commentf(string(out)))
c.Assert(json.Unmarshal(out, &task), checker.IsNil)
return task
}
func (d *SwarmDaemon) updateService(c *check.C, service *swarm.Service, f ...serviceConstructor) {
for _, fn := range f {
fn(service)

View file

@ -0,0 +1,20 @@
package main
import "github.com/go-check/check"
func (s *DockerSwarmSuite) getDaemon(c *check.C, nodeID string) *SwarmDaemon {
s.daemonsLock.Lock()
defer s.daemonsLock.Unlock()
for _, d := range s.daemons {
if d.NodeID == nodeID {
return d
}
}
c.Fatalf("could not find node with id: %s", nodeID)
return nil
}
// nodeCmd executes a command on a given node via the normal docker socket
func (s *DockerSwarmSuite) nodeCmd(c *check.C, id, cmd string, args ...string) (string, error) {
return s.getDaemon(c, id).Cmd(cmd, args...)
}

View file

@ -0,0 +1,45 @@
// +build !windows
package main
import (
"encoding/json"
"strings"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/swarm"
"github.com/go-check/check"
)
func (s *DockerSwarmSuite) TestServiceCreateMountVolume(c *check.C) {
d := s.AddDaemon(c, true, true)
out, err := d.Cmd("service", "create", "--mount", "type=volume,source=foo,target=/foo", "busybox", "top")
c.Assert(err, checker.IsNil, check.Commentf(out))
id := strings.TrimSpace(out)
var tasks []swarm.Task
waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
tasks = d.getServiceTasks(c, id)
return len(tasks) > 0, nil
}, checker.Equals, true)
task := tasks[0]
waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interface{}, check.CommentInterface) {
if task.NodeID == "" || task.Status.ContainerStatus.ContainerID == "" {
task = d.getTask(c, task.ID)
}
return task.NodeID != "" && task.Status.ContainerStatus.ContainerID != "", nil
}, checker.Equals, true)
out, err = s.nodeCmd(c, task.NodeID, "inspect", "--format", "{{json .Mounts}}", task.Status.ContainerStatus.ContainerID)
c.Assert(err, checker.IsNil, check.Commentf(out))
var mounts []types.MountPoint
c.Assert(json.Unmarshal([]byte(out), &mounts), checker.IsNil)
c.Assert(mounts, checker.HasLen, 1)
c.Assert(mounts[0].Name, checker.Equals, "foo")
c.Assert(mounts[0].Destination, checker.Equals, "/foo")
c.Assert(mounts[0].RW, checker.Equals, false)
}