github.com/afbjorklund/moby@v20.10.5+incompatible/integration-cli/daemon/daemon_swarm.go (about)

     1  package daemon // import "github.com/docker/docker/integration-cli/daemon"
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/docker/docker/api/types"
    10  	"github.com/docker/docker/api/types/filters"
    11  	"github.com/docker/docker/api/types/swarm"
    12  	"github.com/docker/docker/client"
    13  	"gotest.tools/v3/assert"
    14  )
    15  
    16  // CheckServiceTasksInState returns the number of tasks with a matching state,
    17  // and optional message substring.
    18  func (d *Daemon) CheckServiceTasksInState(service string, state swarm.TaskState, message string) func(*testing.T) (interface{}, string) {
    19  	return func(c *testing.T) (interface{}, string) {
    20  		tasks := d.GetServiceTasks(c, service)
    21  		var count int
    22  		for _, task := range tasks {
    23  			if task.Status.State == state {
    24  				if message == "" || strings.Contains(task.Status.Message, message) {
    25  					count++
    26  				}
    27  			}
    28  		}
    29  		return count, ""
    30  	}
    31  }
    32  
    33  // CheckServiceTasksInStateWithError returns the number of tasks with a matching state,
    34  // and optional message substring.
    35  func (d *Daemon) CheckServiceTasksInStateWithError(service string, state swarm.TaskState, errorMessage string) func(*testing.T) (interface{}, string) {
    36  	return func(c *testing.T) (interface{}, string) {
    37  		tasks := d.GetServiceTasks(c, service)
    38  		var count int
    39  		for _, task := range tasks {
    40  			if task.Status.State == state {
    41  				if errorMessage == "" || strings.Contains(task.Status.Err, errorMessage) {
    42  					count++
    43  				}
    44  			}
    45  		}
    46  		return count, ""
    47  	}
    48  }
    49  
    50  // CheckServiceRunningTasks returns the number of running tasks for the specified service
    51  func (d *Daemon) CheckServiceRunningTasks(service string) func(*testing.T) (interface{}, string) {
    52  	return d.CheckServiceTasksInState(service, swarm.TaskStateRunning, "")
    53  }
    54  
    55  // CheckServiceUpdateState returns the current update state for the specified service
    56  func (d *Daemon) CheckServiceUpdateState(service string) func(*testing.T) (interface{}, string) {
    57  	return func(c *testing.T) (interface{}, string) {
    58  		service := d.GetService(c, service)
    59  		if service.UpdateStatus == nil {
    60  			return "", ""
    61  		}
    62  		return service.UpdateStatus.State, ""
    63  	}
    64  }
    65  
    66  // CheckPluginRunning returns the runtime state of the plugin
    67  func (d *Daemon) CheckPluginRunning(plugin string) func(c *testing.T) (interface{}, string) {
    68  	return func(c *testing.T) (interface{}, string) {
    69  		apiclient := d.NewClientT(c)
    70  		resp, _, err := apiclient.PluginInspectWithRaw(context.Background(), plugin)
    71  		if client.IsErrNotFound(err) {
    72  			return false, fmt.Sprintf("%v", err)
    73  		}
    74  		assert.NilError(c, err)
    75  		return resp.Enabled, fmt.Sprintf("%+v", resp)
    76  	}
    77  }
    78  
    79  // CheckPluginImage returns the runtime state of the plugin
    80  func (d *Daemon) CheckPluginImage(plugin string) func(c *testing.T) (interface{}, string) {
    81  	return func(c *testing.T) (interface{}, string) {
    82  		apiclient := d.NewClientT(c)
    83  		resp, _, err := apiclient.PluginInspectWithRaw(context.Background(), plugin)
    84  		if client.IsErrNotFound(err) {
    85  			return false, fmt.Sprintf("%v", err)
    86  		}
    87  		assert.NilError(c, err)
    88  		return resp.PluginReference, fmt.Sprintf("%+v", resp)
    89  	}
    90  }
    91  
    92  // CheckServiceTasks returns the number of tasks for the specified service
    93  func (d *Daemon) CheckServiceTasks(service string) func(*testing.T) (interface{}, string) {
    94  	return func(c *testing.T) (interface{}, string) {
    95  		tasks := d.GetServiceTasks(c, service)
    96  		return len(tasks), ""
    97  	}
    98  }
    99  
   100  // CheckRunningTaskNetworks returns the number of times each network is referenced from a task.
   101  func (d *Daemon) CheckRunningTaskNetworks(c *testing.T) (interface{}, string) {
   102  	cli := d.NewClientT(c)
   103  	defer cli.Close()
   104  
   105  	filterArgs := filters.NewArgs()
   106  	filterArgs.Add("desired-state", "running")
   107  
   108  	options := types.TaskListOptions{
   109  		Filters: filterArgs,
   110  	}
   111  
   112  	tasks, err := cli.TaskList(context.Background(), options)
   113  	assert.NilError(c, err)
   114  
   115  	result := make(map[string]int)
   116  	for _, task := range tasks {
   117  		for _, network := range task.Spec.Networks {
   118  			result[network.Target]++
   119  		}
   120  	}
   121  	return result, ""
   122  }
   123  
   124  // CheckRunningTaskImages returns the times each image is running as a task.
   125  func (d *Daemon) CheckRunningTaskImages(c *testing.T) (interface{}, string) {
   126  	cli := d.NewClientT(c)
   127  	defer cli.Close()
   128  
   129  	filterArgs := filters.NewArgs()
   130  	filterArgs.Add("desired-state", "running")
   131  
   132  	options := types.TaskListOptions{
   133  		Filters: filterArgs,
   134  	}
   135  
   136  	tasks, err := cli.TaskList(context.Background(), options)
   137  	assert.NilError(c, err)
   138  
   139  	result := make(map[string]int)
   140  	for _, task := range tasks {
   141  		if task.Status.State == swarm.TaskStateRunning && task.Spec.ContainerSpec != nil {
   142  			result[task.Spec.ContainerSpec.Image]++
   143  		}
   144  	}
   145  	return result, ""
   146  }
   147  
   148  // CheckNodeReadyCount returns the number of ready node on the swarm
   149  func (d *Daemon) CheckNodeReadyCount(c *testing.T) (interface{}, string) {
   150  	nodes := d.ListNodes(c)
   151  	var readyCount int
   152  	for _, node := range nodes {
   153  		if node.Status.State == swarm.NodeStateReady {
   154  			readyCount++
   155  		}
   156  	}
   157  	return readyCount, ""
   158  }
   159  
   160  // CheckLocalNodeState returns the current swarm node state
   161  func (d *Daemon) CheckLocalNodeState(c *testing.T) (interface{}, string) {
   162  	info := d.SwarmInfo(c)
   163  	return info.LocalNodeState, ""
   164  }
   165  
   166  // CheckControlAvailable returns the current swarm control available
   167  func (d *Daemon) CheckControlAvailable(c *testing.T) (interface{}, string) {
   168  	info := d.SwarmInfo(c)
   169  	assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive)
   170  	return info.ControlAvailable, ""
   171  }
   172  
   173  // CheckLeader returns whether there is a leader on the swarm or not
   174  func (d *Daemon) CheckLeader(c *testing.T) (interface{}, string) {
   175  	cli := d.NewClientT(c)
   176  	defer cli.Close()
   177  
   178  	errList := "could not get node list"
   179  
   180  	ls, err := cli.NodeList(context.Background(), types.NodeListOptions{})
   181  	if err != nil {
   182  		return err, errList
   183  	}
   184  
   185  	for _, node := range ls {
   186  		if node.ManagerStatus != nil && node.ManagerStatus.Leader {
   187  			return nil, ""
   188  		}
   189  	}
   190  	return fmt.Errorf("no leader"), "could not find leader"
   191  }
   192  
   193  // CmdRetryOutOfSequence tries the specified command against the current daemon
   194  // up to 10 times, retrying if it encounters an "update out of sequence" error.
   195  func (d *Daemon) CmdRetryOutOfSequence(args ...string) (string, error) {
   196  	var (
   197  		output string
   198  		err    error
   199  	)
   200  
   201  	for i := 0; i < 10; i++ {
   202  		output, err = d.Cmd(args...)
   203  		// error, no error, whatever. if we don't have "update out of
   204  		// sequence", we don't retry, we just return.
   205  		if !strings.Contains(output, "update out of sequence") {
   206  			return output, err
   207  		}
   208  	}
   209  
   210  	// otherwise, once all of our attempts have been exhausted, just return
   211  	// whatever the last values were.
   212  	return output, err
   213  }