Browse Source

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>
Brian Goff 9 năm trước cách đây
mục cha
commit
e5ec575b32

+ 10 - 4
integration-cli/check_test.go

@@ -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)
 }
 

+ 27 - 0
integration-cli/daemon_swarm.go

@@ -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 - 0
integration-cli/daemon_swarm_hack.go

@@ -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 - 0
integration-cli/docker_cli_service_create_hack_test.go

@@ -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)
+}