github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/integration/service/list_test.go (about)

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