github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/integration-cli/daemon/daemon_swarm.go (about) 1 package daemon // import "github.com/Prakhar-Agarwal-byte/moby/integration-cli/daemon" 2 3 import ( 4 "context" 5 "fmt" 6 "strings" 7 "testing" 8 9 "github.com/Prakhar-Agarwal-byte/moby/api/types" 10 "github.com/Prakhar-Agarwal-byte/moby/api/types/filters" 11 "github.com/Prakhar-Agarwal-byte/moby/api/types/swarm" 12 "github.com/Prakhar-Agarwal-byte/moby/errdefs" 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(ctx context.Context, service string, state swarm.TaskState, message string) func(*testing.T) (interface{}, string) { 19 return func(c *testing.T) (interface{}, string) { 20 tasks := d.GetServiceTasks(ctx, 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(ctx context.Context, service string, state swarm.TaskState, errorMessage string) func(*testing.T) (interface{}, string) { 36 return func(c *testing.T) (interface{}, string) { 37 tasks := d.GetServiceTasks(ctx, 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(ctx context.Context, service string) func(*testing.T) (interface{}, string) { 52 return d.CheckServiceTasksInState(ctx, service, swarm.TaskStateRunning, "") 53 } 54 55 // CheckServiceUpdateState returns the current update state for the specified service 56 func (d *Daemon) CheckServiceUpdateState(ctx context.Context, service string) func(*testing.T) (interface{}, string) { 57 return func(c *testing.T) (interface{}, string) { 58 service := d.GetService(ctx, 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(ctx context.Context, 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(ctx, plugin) 71 if errdefs.IsNotFound(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(ctx context.Context, 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(ctx, plugin) 84 if errdefs.IsNotFound(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(ctx context.Context, service string) func(*testing.T) (interface{}, string) { 94 return func(c *testing.T) (interface{}, string) { 95 tasks := d.GetServiceTasks(ctx, 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(ctx context.Context) func(t *testing.T) (interface{}, string) { 102 return func(t *testing.T) (interface{}, string) { 103 cli := d.NewClientT(t) 104 defer cli.Close() 105 106 tasks, err := cli.TaskList(ctx, types.TaskListOptions{ 107 Filters: filters.NewArgs(filters.Arg("desired-state", "running")), 108 }) 109 assert.NilError(t, err) 110 111 result := make(map[string]int) 112 for _, task := range tasks { 113 for _, network := range task.Spec.Networks { 114 result[network.Target]++ 115 } 116 } 117 return result, "" 118 } 119 } 120 121 // CheckRunningTaskImages returns the times each image is running as a task. 122 func (d *Daemon) CheckRunningTaskImages(ctx context.Context) func(t *testing.T) (interface{}, string) { 123 return func(t *testing.T) (interface{}, string) { 124 cli := d.NewClientT(t) 125 defer cli.Close() 126 127 tasks, err := cli.TaskList(ctx, types.TaskListOptions{ 128 Filters: filters.NewArgs(filters.Arg("desired-state", "running")), 129 }) 130 assert.NilError(t, err) 131 132 result := make(map[string]int) 133 for _, task := range tasks { 134 if task.Status.State == swarm.TaskStateRunning && task.Spec.ContainerSpec != nil { 135 result[task.Spec.ContainerSpec.Image]++ 136 } 137 } 138 return result, "" 139 } 140 } 141 142 // CheckNodeReadyCount returns the number of ready node on the swarm 143 func (d *Daemon) CheckNodeReadyCount(ctx context.Context) func(t *testing.T) (interface{}, string) { 144 return func(t *testing.T) (interface{}, string) { 145 nodes := d.ListNodes(ctx, t) 146 var readyCount int 147 for _, node := range nodes { 148 if node.Status.State == swarm.NodeStateReady { 149 readyCount++ 150 } 151 } 152 return readyCount, "" 153 } 154 } 155 156 // CheckLocalNodeState returns the current swarm node state 157 func (d *Daemon) CheckLocalNodeState(ctx context.Context) func(t *testing.T) (interface{}, string) { 158 return func(t *testing.T) (interface{}, string) { 159 info := d.SwarmInfo(ctx, t) 160 return info.LocalNodeState, "" 161 } 162 } 163 164 // CheckControlAvailable returns the current swarm control available 165 func (d *Daemon) CheckControlAvailable(ctx context.Context) func(t *testing.T) (interface{}, string) { 166 return func(t *testing.T) (interface{}, string) { 167 info := d.SwarmInfo(ctx, t) 168 assert.Equal(t, info.LocalNodeState, swarm.LocalNodeStateActive) 169 return info.ControlAvailable, "" 170 } 171 } 172 173 // CheckLeader returns whether there is a leader on the swarm or not 174 func (d *Daemon) CheckLeader(ctx context.Context) func(t *testing.T) (interface{}, string) { 175 return func(t *testing.T) (interface{}, string) { 176 cli := d.NewClientT(t) 177 defer cli.Close() 178 179 errList := "could not get node list" 180 181 ls, err := cli.NodeList(ctx, types.NodeListOptions{}) 182 if err != nil { 183 return err, errList 184 } 185 186 for _, node := range ls { 187 if node.ManagerStatus != nil && node.ManagerStatus.Leader { 188 return nil, "" 189 } 190 } 191 return fmt.Errorf("no leader"), "could not find leader" 192 } 193 } 194 195 // CmdRetryOutOfSequence tries the specified command against the current daemon 196 // up to 10 times, retrying if it encounters an "update out of sequence" error. 197 func (d *Daemon) CmdRetryOutOfSequence(args ...string) (string, error) { 198 var ( 199 output string 200 err error 201 ) 202 203 for i := 0; i < 10; i++ { 204 output, err = d.Cmd(args...) 205 // error, no error, whatever. if we don't have "update out of 206 // sequence", we don't retry, we just return. 207 if !strings.Contains(output, "update out of sequence") { 208 return output, err 209 } 210 } 211 212 // otherwise, once all of our attempts have been exhausted, just return 213 // whatever the last values were. 214 return output, err 215 }