github.com/rawahars/moby@v24.0.4+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 tasks, err := cli.TaskList(context.Background(), types.TaskListOptions{ 106 Filters: filters.NewArgs(filters.Arg("desired-state", "running")), 107 }) 108 assert.NilError(c, err) 109 110 result := make(map[string]int) 111 for _, task := range tasks { 112 for _, network := range task.Spec.Networks { 113 result[network.Target]++ 114 } 115 } 116 return result, "" 117 } 118 119 // CheckRunningTaskImages returns the times each image is running as a task. 120 func (d *Daemon) CheckRunningTaskImages(c *testing.T) (interface{}, string) { 121 cli := d.NewClientT(c) 122 defer cli.Close() 123 124 tasks, err := cli.TaskList(context.Background(), types.TaskListOptions{ 125 Filters: filters.NewArgs(filters.Arg("desired-state", "running")), 126 }) 127 assert.NilError(c, err) 128 129 result := make(map[string]int) 130 for _, task := range tasks { 131 if task.Status.State == swarm.TaskStateRunning && task.Spec.ContainerSpec != nil { 132 result[task.Spec.ContainerSpec.Image]++ 133 } 134 } 135 return result, "" 136 } 137 138 // CheckNodeReadyCount returns the number of ready node on the swarm 139 func (d *Daemon) CheckNodeReadyCount(c *testing.T) (interface{}, string) { 140 nodes := d.ListNodes(c) 141 var readyCount int 142 for _, node := range nodes { 143 if node.Status.State == swarm.NodeStateReady { 144 readyCount++ 145 } 146 } 147 return readyCount, "" 148 } 149 150 // CheckLocalNodeState returns the current swarm node state 151 func (d *Daemon) CheckLocalNodeState(c *testing.T) (interface{}, string) { 152 info := d.SwarmInfo(c) 153 return info.LocalNodeState, "" 154 } 155 156 // CheckControlAvailable returns the current swarm control available 157 func (d *Daemon) CheckControlAvailable(c *testing.T) (interface{}, string) { 158 info := d.SwarmInfo(c) 159 assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) 160 return info.ControlAvailable, "" 161 } 162 163 // CheckLeader returns whether there is a leader on the swarm or not 164 func (d *Daemon) CheckLeader(c *testing.T) (interface{}, string) { 165 cli := d.NewClientT(c) 166 defer cli.Close() 167 168 errList := "could not get node list" 169 170 ls, err := cli.NodeList(context.Background(), types.NodeListOptions{}) 171 if err != nil { 172 return err, errList 173 } 174 175 for _, node := range ls { 176 if node.ManagerStatus != nil && node.ManagerStatus.Leader { 177 return nil, "" 178 } 179 } 180 return fmt.Errorf("no leader"), "could not find leader" 181 } 182 183 // CmdRetryOutOfSequence tries the specified command against the current daemon 184 // up to 10 times, retrying if it encounters an "update out of sequence" error. 185 func (d *Daemon) CmdRetryOutOfSequence(args ...string) (string, error) { 186 var ( 187 output string 188 err error 189 ) 190 191 for i := 0; i < 10; i++ { 192 output, err = d.Cmd(args...) 193 // error, no error, whatever. if we don't have "update out of 194 // sequence", we don't retry, we just return. 195 if !strings.Contains(output, "update out of sequence") { 196 return output, err 197 } 198 } 199 200 // otherwise, once all of our attempts have been exhausted, just return 201 // whatever the last values were. 202 return output, err 203 }