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>
(cherry picked from commit e5ec575b32
)
Signed-off-by: Tibor Vass <tibor@docker.com>
This commit is contained in:
parent
3bf23479cf
commit
85aefec45a
4 changed files with 102 additions and 4 deletions
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
20
integration-cli/daemon_swarm_hack.go
Normal file
20
integration-cli/daemon_swarm_hack.go
Normal 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...)
|
||||
}
|
45
integration-cli/docker_cli_service_create_hack_test.go
Normal file
45
integration-cli/docker_cli_service_create_hack_test.go
Normal 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)
|
||||
}
|
Loading…
Reference in a new issue