123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- package daemon // import "github.com/docker/docker/integration-cli/daemon"
- import (
- "context"
- "fmt"
- "strings"
- "testing"
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/filters"
- "github.com/docker/docker/api/types/swarm"
- "github.com/docker/docker/errdefs"
- "gotest.tools/v3/assert"
- )
- // CheckServiceTasksInState returns the number of tasks with a matching state,
- // and optional message substring.
- func (d *Daemon) CheckServiceTasksInState(ctx context.Context, service string, state swarm.TaskState, message string) func(*testing.T) (interface{}, string) {
- return func(c *testing.T) (interface{}, string) {
- tasks := d.GetServiceTasks(ctx, c, service)
- var count int
- for _, task := range tasks {
- if task.Status.State == state {
- if message == "" || strings.Contains(task.Status.Message, message) {
- count++
- }
- }
- }
- return count, ""
- }
- }
- // CheckServiceTasksInStateWithError returns the number of tasks with a matching state,
- // and optional message substring.
- func (d *Daemon) CheckServiceTasksInStateWithError(ctx context.Context, service string, state swarm.TaskState, errorMessage string) func(*testing.T) (interface{}, string) {
- return func(c *testing.T) (interface{}, string) {
- tasks := d.GetServiceTasks(ctx, c, service)
- var count int
- for _, task := range tasks {
- if task.Status.State == state {
- if errorMessage == "" || strings.Contains(task.Status.Err, errorMessage) {
- count++
- }
- }
- }
- return count, ""
- }
- }
- // CheckServiceRunningTasks returns the number of running tasks for the specified service
- func (d *Daemon) CheckServiceRunningTasks(ctx context.Context, service string) func(*testing.T) (interface{}, string) {
- return d.CheckServiceTasksInState(ctx, service, swarm.TaskStateRunning, "")
- }
- // CheckServiceUpdateState returns the current update state for the specified service
- func (d *Daemon) CheckServiceUpdateState(ctx context.Context, service string) func(*testing.T) (interface{}, string) {
- return func(c *testing.T) (interface{}, string) {
- service := d.GetService(ctx, c, service)
- if service.UpdateStatus == nil {
- return "", ""
- }
- return service.UpdateStatus.State, ""
- }
- }
- // CheckPluginRunning returns the runtime state of the plugin
- func (d *Daemon) CheckPluginRunning(ctx context.Context, plugin string) func(c *testing.T) (interface{}, string) {
- return func(c *testing.T) (interface{}, string) {
- apiclient := d.NewClientT(c)
- resp, _, err := apiclient.PluginInspectWithRaw(ctx, plugin)
- if errdefs.IsNotFound(err) {
- return false, fmt.Sprintf("%v", err)
- }
- assert.NilError(c, err)
- return resp.Enabled, fmt.Sprintf("%+v", resp)
- }
- }
- // CheckPluginImage returns the runtime state of the plugin
- func (d *Daemon) CheckPluginImage(ctx context.Context, plugin string) func(c *testing.T) (interface{}, string) {
- return func(c *testing.T) (interface{}, string) {
- apiclient := d.NewClientT(c)
- resp, _, err := apiclient.PluginInspectWithRaw(ctx, plugin)
- if errdefs.IsNotFound(err) {
- return false, fmt.Sprintf("%v", err)
- }
- assert.NilError(c, err)
- return resp.PluginReference, fmt.Sprintf("%+v", resp)
- }
- }
- // CheckServiceTasks returns the number of tasks for the specified service
- func (d *Daemon) CheckServiceTasks(ctx context.Context, service string) func(*testing.T) (interface{}, string) {
- return func(c *testing.T) (interface{}, string) {
- tasks := d.GetServiceTasks(ctx, c, service)
- return len(tasks), ""
- }
- }
- // CheckRunningTaskNetworks returns the number of times each network is referenced from a task.
- func (d *Daemon) CheckRunningTaskNetworks(ctx context.Context) func(t *testing.T) (interface{}, string) {
- return func(t *testing.T) (interface{}, string) {
- cli := d.NewClientT(t)
- defer cli.Close()
- tasks, err := cli.TaskList(ctx, types.TaskListOptions{
- Filters: filters.NewArgs(filters.Arg("desired-state", "running")),
- })
- assert.NilError(t, err)
- result := make(map[string]int)
- for _, task := range tasks {
- for _, network := range task.Spec.Networks {
- result[network.Target]++
- }
- }
- return result, ""
- }
- }
- // CheckRunningTaskImages returns the times each image is running as a task.
- func (d *Daemon) CheckRunningTaskImages(ctx context.Context) func(t *testing.T) (interface{}, string) {
- return func(t *testing.T) (interface{}, string) {
- cli := d.NewClientT(t)
- defer cli.Close()
- tasks, err := cli.TaskList(ctx, types.TaskListOptions{
- Filters: filters.NewArgs(filters.Arg("desired-state", "running")),
- })
- assert.NilError(t, err)
- result := make(map[string]int)
- for _, task := range tasks {
- if task.Status.State == swarm.TaskStateRunning && task.Spec.ContainerSpec != nil {
- result[task.Spec.ContainerSpec.Image]++
- }
- }
- return result, ""
- }
- }
- // CheckNodeReadyCount returns the number of ready node on the swarm
- func (d *Daemon) CheckNodeReadyCount(ctx context.Context) func(t *testing.T) (interface{}, string) {
- return func(t *testing.T) (interface{}, string) {
- nodes := d.ListNodes(ctx, t)
- var readyCount int
- for _, node := range nodes {
- if node.Status.State == swarm.NodeStateReady {
- readyCount++
- }
- }
- return readyCount, ""
- }
- }
- // CheckLocalNodeState returns the current swarm node state
- func (d *Daemon) CheckLocalNodeState(ctx context.Context) func(t *testing.T) (interface{}, string) {
- return func(t *testing.T) (interface{}, string) {
- info := d.SwarmInfo(ctx, t)
- return info.LocalNodeState, ""
- }
- }
- // CheckControlAvailable returns the current swarm control available
- func (d *Daemon) CheckControlAvailable(ctx context.Context) func(t *testing.T) (interface{}, string) {
- return func(t *testing.T) (interface{}, string) {
- info := d.SwarmInfo(ctx, t)
- assert.Equal(t, info.LocalNodeState, swarm.LocalNodeStateActive)
- return info.ControlAvailable, ""
- }
- }
- // CheckLeader returns whether there is a leader on the swarm or not
- func (d *Daemon) CheckLeader(ctx context.Context) func(t *testing.T) (interface{}, string) {
- return func(t *testing.T) (interface{}, string) {
- cli := d.NewClientT(t)
- defer cli.Close()
- errList := "could not get node list"
- ls, err := cli.NodeList(ctx, types.NodeListOptions{})
- if err != nil {
- return err, errList
- }
- for _, node := range ls {
- if node.ManagerStatus != nil && node.ManagerStatus.Leader {
- return nil, ""
- }
- }
- return fmt.Errorf("no leader"), "could not find leader"
- }
- }
- // 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
- }
|