2018-02-05 16:05:59 -05:00
|
|
|
package daemon // import "github.com/docker/docker/integration-cli/daemon"
|
2016-06-13 22:54:20 -04:00
|
|
|
|
|
|
|
import (
|
2018-04-19 18:30:59 -04:00
|
|
|
"context"
|
2016-06-13 22:54:20 -04:00
|
|
|
"fmt"
|
|
|
|
"strings"
|
2019-09-09 17:06:12 -04:00
|
|
|
"testing"
|
2016-06-13 22:54:20 -04:00
|
|
|
|
2016-09-06 14:18:12 -04:00
|
|
|
"github.com/docker/docker/api/types"
|
|
|
|
"github.com/docker/docker/api/types/filters"
|
|
|
|
"github.com/docker/docker/api/types/swarm"
|
2017-09-19 16:12:29 -04:00
|
|
|
"github.com/docker/docker/client"
|
2020-02-07 08:39:24 -05:00
|
|
|
"gotest.tools/v3/assert"
|
2016-06-13 22:54:20 -04:00
|
|
|
)
|
|
|
|
|
2016-12-15 16:56:32 -05:00
|
|
|
// CheckServiceTasksInState returns the number of tasks with a matching state,
|
|
|
|
// and optional message substring.
|
2019-09-09 17:08:22 -04:00
|
|
|
func (d *Daemon) CheckServiceTasksInState(service string, state swarm.TaskState, message string) func(*testing.T) (interface{}, string) {
|
|
|
|
return func(c *testing.T) (interface{}, string) {
|
2016-12-09 04:17:53 -05:00
|
|
|
tasks := d.GetServiceTasks(c, service)
|
2016-12-15 16:56:32 -05:00
|
|
|
var count int
|
2016-07-20 22:16:19 -04:00
|
|
|
for _, task := range tasks {
|
2016-12-15 16:56:32 -05:00
|
|
|
if task.Status.State == state {
|
|
|
|
if message == "" || strings.Contains(task.Status.Message, message) {
|
|
|
|
count++
|
|
|
|
}
|
2016-07-20 22:16:19 -04:00
|
|
|
}
|
|
|
|
}
|
2019-09-09 17:09:27 -04:00
|
|
|
return count, ""
|
2016-07-20 22:16:19 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-07 10:07:17 -04:00
|
|
|
// CheckServiceTasksInStateWithError returns the number of tasks with a matching state,
|
|
|
|
// and optional message substring.
|
2019-09-09 17:08:22 -04:00
|
|
|
func (d *Daemon) CheckServiceTasksInStateWithError(service string, state swarm.TaskState, errorMessage string) func(*testing.T) (interface{}, string) {
|
|
|
|
return func(c *testing.T) (interface{}, string) {
|
2017-08-07 10:07:17 -04:00
|
|
|
tasks := d.GetServiceTasks(c, service)
|
|
|
|
var count int
|
|
|
|
for _, task := range tasks {
|
|
|
|
if task.Status.State == state {
|
|
|
|
if errorMessage == "" || strings.Contains(task.Status.Err, errorMessage) {
|
|
|
|
count++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-09-09 17:09:27 -04:00
|
|
|
return count, ""
|
2017-08-07 10:07:17 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-15 16:56:32 -05:00
|
|
|
// CheckServiceRunningTasks returns the number of running tasks for the specified service
|
2019-09-09 17:08:22 -04:00
|
|
|
func (d *Daemon) CheckServiceRunningTasks(service string) func(*testing.T) (interface{}, string) {
|
2016-12-15 16:56:32 -05:00
|
|
|
return d.CheckServiceTasksInState(service, swarm.TaskStateRunning, "")
|
|
|
|
}
|
|
|
|
|
2016-12-09 04:17:53 -05:00
|
|
|
// CheckServiceUpdateState returns the current update state for the specified service
|
2019-09-09 17:08:22 -04:00
|
|
|
func (d *Daemon) CheckServiceUpdateState(service string) func(*testing.T) (interface{}, string) {
|
|
|
|
return func(c *testing.T) (interface{}, string) {
|
2016-12-09 04:17:53 -05:00
|
|
|
service := d.GetService(c, service)
|
2016-12-01 17:08:06 -05:00
|
|
|
if service.UpdateStatus == nil {
|
2019-09-09 17:09:27 -04:00
|
|
|
return "", ""
|
2016-12-01 17:08:06 -05:00
|
|
|
}
|
2019-09-09 17:09:27 -04:00
|
|
|
return service.UpdateStatus.State, ""
|
2016-09-02 17:12:05 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-07 13:07:01 -04:00
|
|
|
// CheckPluginRunning returns the runtime state of the plugin
|
2019-09-09 17:08:22 -04:00
|
|
|
func (d *Daemon) CheckPluginRunning(plugin string) func(c *testing.T) (interface{}, string) {
|
|
|
|
return func(c *testing.T) (interface{}, string) {
|
2018-12-22 09:53:02 -05:00
|
|
|
apiclient := d.NewClientT(c)
|
2017-09-19 16:12:29 -04:00
|
|
|
resp, _, err := apiclient.PluginInspectWithRaw(context.Background(), plugin)
|
|
|
|
if client.IsErrNotFound(err) {
|
2019-09-09 17:08:22 -04:00
|
|
|
return false, fmt.Sprintf("%v", err)
|
2017-06-07 13:07:01 -04:00
|
|
|
}
|
2018-03-13 15:28:34 -04:00
|
|
|
assert.NilError(c, err)
|
2019-09-09 17:08:22 -04:00
|
|
|
return resp.Enabled, fmt.Sprintf("%+v", resp)
|
2017-06-07 13:07:01 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// CheckPluginImage returns the runtime state of the plugin
|
2019-09-09 17:08:22 -04:00
|
|
|
func (d *Daemon) CheckPluginImage(plugin string) func(c *testing.T) (interface{}, string) {
|
|
|
|
return func(c *testing.T) (interface{}, string) {
|
2018-12-22 09:53:02 -05:00
|
|
|
apiclient := d.NewClientT(c)
|
2017-09-19 16:12:29 -04:00
|
|
|
resp, _, err := apiclient.PluginInspectWithRaw(context.Background(), plugin)
|
|
|
|
if client.IsErrNotFound(err) {
|
2019-09-09 17:08:22 -04:00
|
|
|
return false, fmt.Sprintf("%v", err)
|
2017-06-07 13:07:01 -04:00
|
|
|
}
|
2018-03-13 15:28:34 -04:00
|
|
|
assert.NilError(c, err)
|
2019-09-09 17:08:22 -04:00
|
|
|
return resp.PluginReference, fmt.Sprintf("%+v", resp)
|
2017-06-07 13:07:01 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-09 04:17:53 -05:00
|
|
|
// CheckServiceTasks returns the number of tasks for the specified service
|
2019-09-09 17:08:22 -04:00
|
|
|
func (d *Daemon) CheckServiceTasks(service string) func(*testing.T) (interface{}, string) {
|
|
|
|
return func(c *testing.T) (interface{}, string) {
|
2016-12-09 04:17:53 -05:00
|
|
|
tasks := d.GetServiceTasks(c, service)
|
2019-09-09 17:09:27 -04:00
|
|
|
return len(tasks), ""
|
2016-07-20 22:16:19 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-23 20:51:57 -04:00
|
|
|
// CheckRunningTaskNetworks returns the number of times each network is referenced from a task.
|
2019-09-09 17:08:22 -04:00
|
|
|
func (d *Daemon) CheckRunningTaskNetworks(c *testing.T) (interface{}, string) {
|
2018-12-22 09:53:02 -05:00
|
|
|
cli := d.NewClientT(c)
|
2017-05-23 23:56:26 -04:00
|
|
|
defer cli.Close()
|
2017-03-23 20:51:57 -04:00
|
|
|
|
|
|
|
filterArgs := filters.NewArgs()
|
|
|
|
filterArgs.Add("desired-state", "running")
|
|
|
|
|
2017-05-23 23:56:26 -04:00
|
|
|
options := types.TaskListOptions{
|
|
|
|
Filters: filterArgs,
|
|
|
|
}
|
|
|
|
|
|
|
|
tasks, err := cli.TaskList(context.Background(), options)
|
2019-04-04 09:23:19 -04:00
|
|
|
assert.NilError(c, err)
|
2017-03-23 20:51:57 -04:00
|
|
|
|
|
|
|
result := make(map[string]int)
|
|
|
|
for _, task := range tasks {
|
|
|
|
for _, network := range task.Spec.Networks {
|
|
|
|
result[network.Target]++
|
|
|
|
}
|
|
|
|
}
|
2019-09-09 17:09:27 -04:00
|
|
|
return result, ""
|
2017-03-23 20:51:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// CheckRunningTaskImages returns the times each image is running as a task.
|
2019-09-09 17:08:22 -04:00
|
|
|
func (d *Daemon) CheckRunningTaskImages(c *testing.T) (interface{}, string) {
|
2018-12-22 09:53:02 -05:00
|
|
|
cli := d.NewClientT(c)
|
2017-05-23 23:56:26 -04:00
|
|
|
defer cli.Close()
|
2016-07-11 20:15:30 -04:00
|
|
|
|
|
|
|
filterArgs := filters.NewArgs()
|
|
|
|
filterArgs.Add("desired-state", "running")
|
|
|
|
|
2017-05-23 23:56:26 -04:00
|
|
|
options := types.TaskListOptions{
|
|
|
|
Filters: filterArgs,
|
|
|
|
}
|
|
|
|
|
|
|
|
tasks, err := cli.TaskList(context.Background(), options)
|
2019-04-04 09:23:19 -04:00
|
|
|
assert.NilError(c, err)
|
2016-07-11 20:15:30 -04:00
|
|
|
|
|
|
|
result := make(map[string]int)
|
|
|
|
for _, task := range tasks {
|
2017-06-07 13:07:01 -04:00
|
|
|
if task.Status.State == swarm.TaskStateRunning && task.Spec.ContainerSpec != nil {
|
2016-07-11 20:15:30 -04:00
|
|
|
result[task.Spec.ContainerSpec.Image]++
|
|
|
|
}
|
|
|
|
}
|
2019-09-09 17:09:27 -04:00
|
|
|
return result, ""
|
2016-07-11 20:15:30 -04:00
|
|
|
}
|
|
|
|
|
2016-12-09 04:17:53 -05:00
|
|
|
// CheckNodeReadyCount returns the number of ready node on the swarm
|
2019-09-09 17:08:22 -04:00
|
|
|
func (d *Daemon) CheckNodeReadyCount(c *testing.T) (interface{}, string) {
|
2016-12-09 04:17:53 -05:00
|
|
|
nodes := d.ListNodes(c)
|
2016-07-11 20:15:30 -04:00
|
|
|
var readyCount int
|
|
|
|
for _, node := range nodes {
|
|
|
|
if node.Status.State == swarm.NodeStateReady {
|
|
|
|
readyCount++
|
|
|
|
}
|
|
|
|
}
|
2019-09-09 17:09:27 -04:00
|
|
|
return readyCount, ""
|
2016-07-11 20:15:30 -04:00
|
|
|
}
|
|
|
|
|
2016-12-09 04:17:53 -05:00
|
|
|
// CheckLocalNodeState returns the current swarm node state
|
2019-09-09 17:08:22 -04:00
|
|
|
func (d *Daemon) CheckLocalNodeState(c *testing.T) (interface{}, string) {
|
2018-04-11 06:10:17 -04:00
|
|
|
info := d.SwarmInfo(c)
|
2019-09-09 17:09:27 -04:00
|
|
|
return info.LocalNodeState, ""
|
2016-07-08 17:17:32 -04:00
|
|
|
}
|
|
|
|
|
2016-12-09 04:17:53 -05:00
|
|
|
// CheckControlAvailable returns the current swarm control available
|
2019-09-09 17:08:22 -04:00
|
|
|
func (d *Daemon) CheckControlAvailable(c *testing.T) (interface{}, string) {
|
2018-04-11 06:10:17 -04:00
|
|
|
info := d.SwarmInfo(c)
|
2019-04-04 09:23:19 -04:00
|
|
|
assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive)
|
2019-09-09 17:09:27 -04:00
|
|
|
return info.ControlAvailable, ""
|
2016-07-08 17:17:32 -04:00
|
|
|
}
|
2016-07-26 21:32:56 -04:00
|
|
|
|
2016-12-09 04:17:53 -05:00
|
|
|
// CheckLeader returns whether there is a leader on the swarm or not
|
2019-09-09 17:08:22 -04:00
|
|
|
func (d *Daemon) CheckLeader(c *testing.T) (interface{}, string) {
|
2018-12-22 09:53:02 -05:00
|
|
|
cli := d.NewClientT(c)
|
2017-05-23 23:56:26 -04:00
|
|
|
defer cli.Close()
|
|
|
|
|
2019-09-09 17:08:22 -04:00
|
|
|
errList := "could not get node list"
|
2016-07-26 21:32:56 -04:00
|
|
|
|
2017-05-23 23:56:26 -04:00
|
|
|
ls, err := cli.NodeList(context.Background(), types.NodeListOptions{})
|
|
|
|
if err != nil {
|
2016-07-26 21:32:56 -04:00
|
|
|
return err, errList
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, node := range ls {
|
|
|
|
if node.ManagerStatus != nil && node.ManagerStatus.Leader {
|
2019-09-09 17:09:27 -04:00
|
|
|
return nil, ""
|
2016-07-26 21:32:56 -04:00
|
|
|
}
|
|
|
|
}
|
2019-09-09 17:08:22 -04:00
|
|
|
return fmt.Errorf("no leader"), "could not find leader"
|
2016-07-26 21:32:56 -04:00
|
|
|
}
|
2019-07-18 13:58:21 -04:00
|
|
|
|
|
|
|
// CmdRetryOutOfSequence tries the specified command against the current daemon
|
|
|
|
// up to 10 times, retrying if it encounters an "update out of sequence" error.
|
|
|
|
func (d *Daemon) CmdRetryOutOfSequence(args ...string) (string, error) {
|
|
|
|
var (
|
|
|
|
output string
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
|
|
|
|
for i := 0; i < 10; i++ {
|
|
|
|
output, err = d.Cmd(args...)
|
|
|
|
// error, no error, whatever. if we don't have "update out of
|
|
|
|
// sequence", we don't retry, we just return.
|
|
|
|
if !strings.Contains(output, "update out of sequence") {
|
|
|
|
return output, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// otherwise, once all of our attempts have been exhausted, just return
|
|
|
|
// whatever the last values were.
|
|
|
|
return output, err
|
|
|
|
}
|