github.com/moby/docker@v26.1.3+incompatible/integration/service/list_test.go (about)

     1  package service // import "github.com/docker/docker/integration/service"
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/docker/docker/api/types"
     8  	"github.com/docker/docker/api/types/filters"
     9  	swarmtypes "github.com/docker/docker/api/types/swarm"
    10  	"github.com/docker/docker/integration/internal/swarm"
    11  	"gotest.tools/v3/assert"
    12  	is "gotest.tools/v3/assert/cmp"
    13  	"gotest.tools/v3/poll"
    14  	"gotest.tools/v3/skip"
    15  )
    16  
    17  // TestServiceListWithStatuses tests that performing a ServiceList operation
    18  // correctly uses the Status parameter, and that the resulting response
    19  // contains correct service statuses.
    20  //
    21  // NOTE(dperny): because it's a pain to elicit the behavior of an unconverged
    22  // service reliably, I'm not testing that an unconverged service returns X
    23  // running and Y desired tasks. Instead, I'm just going to trust that I can
    24  // successfully assign a value to another value without screwing it up. The
    25  // logic for computing service statuses is in swarmkit anyway, not in the
    26  // engine, and is well-tested there, so this test just needs to make sure that
    27  // statuses get correctly associated with the right services.
    28  func TestServiceListWithStatuses(t *testing.T) {
    29  	skip.If(t, testEnv.IsRemoteDaemon)
    30  	skip.If(t, testEnv.DaemonInfo.OSType == "windows")
    31  
    32  	ctx := setupTest(t)
    33  
    34  	d := swarm.NewSwarm(ctx, t, testEnv)
    35  	defer d.Stop(t)
    36  	client := d.NewClientT(t)
    37  	defer client.Close()
    38  
    39  	serviceCount := 3
    40  	// create some services.
    41  	for i := 0; i < serviceCount; i++ {
    42  		spec := fullSwarmServiceSpec(fmt.Sprintf("test-list-%d", i), uint64(i+1))
    43  		// for whatever reason, the args "-u root", when included, cause these
    44  		// tasks to fail and exit. instead, we'll just pass no args, which
    45  		// works.
    46  		spec.TaskTemplate.ContainerSpec.Args = []string{}
    47  		resp, err := client.ServiceCreate(ctx, spec, types.ServiceCreateOptions{
    48  			QueryRegistry: false,
    49  		})
    50  		assert.NilError(t, err)
    51  		id := resp.ID
    52  		// we need to wait specifically for the tasks to be running, which the
    53  		// serviceContainerCount function does not do. instead, we'll use a
    54  		// bespoke closure right here.
    55  		poll.WaitOn(t, func(log poll.LogT) poll.Result {
    56  			tasks, err := client.TaskList(ctx, types.TaskListOptions{
    57  				Filters: filters.NewArgs(filters.Arg("service", id)),
    58  			})
    59  
    60  			running := 0
    61  			for _, task := range tasks {
    62  				if task.Status.State == swarmtypes.TaskStateRunning {
    63  					running++
    64  				}
    65  			}
    66  
    67  			switch {
    68  			case err != nil:
    69  				return poll.Error(err)
    70  			case running == i+1:
    71  				return poll.Success()
    72  			default:
    73  				return poll.Continue(
    74  					"running task count %d (%d total), waiting for %d",
    75  					running, len(tasks), i+1,
    76  				)
    77  			}
    78  		})
    79  	}
    80  
    81  	// now, let's do the list operation with no status arg set.
    82  	resp, err := client.ServiceList(ctx, types.ServiceListOptions{})
    83  	assert.NilError(t, err)
    84  	assert.Check(t, is.Len(resp, serviceCount))
    85  	for _, service := range resp {
    86  		assert.Check(t, is.Nil(service.ServiceStatus))
    87  	}
    88  
    89  	// now try again, but with Status: true. This time, we should have statuses
    90  	resp, err = client.ServiceList(ctx, types.ServiceListOptions{Status: true})
    91  	assert.NilError(t, err)
    92  	assert.Check(t, is.Len(resp, serviceCount))
    93  	for _, service := range resp {
    94  		replicas := *service.Spec.Mode.Replicated.Replicas
    95  
    96  		assert.Assert(t, service.ServiceStatus != nil)
    97  		// Use assert.Check to not fail out of the test if this fails
    98  		assert.Check(t, is.Equal(service.ServiceStatus.DesiredTasks, replicas))
    99  		assert.Check(t, is.Equal(service.ServiceStatus.RunningTasks, replicas))
   100  	}
   101  }