github.com/zhouyu0/docker-note@v0.0.0-20190722021225-b8d3825084db/integration/service/inspect_test.go (about)

     1  package service // import "github.com/docker/docker/integration/service"
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/docker/docker/api/types"
     9  	"github.com/docker/docker/api/types/container"
    10  	"github.com/docker/docker/api/types/filters"
    11  	swarmtypes "github.com/docker/docker/api/types/swarm"
    12  	"github.com/docker/docker/client"
    13  	"github.com/docker/docker/integration/internal/swarm"
    14  	"github.com/google/go-cmp/cmp"
    15  	"gotest.tools/assert"
    16  	is "gotest.tools/assert/cmp"
    17  	"gotest.tools/poll"
    18  	"gotest.tools/skip"
    19  )
    20  
    21  func TestInspect(t *testing.T) {
    22  	skip.If(t, testEnv.IsRemoteDaemon)
    23  	skip.If(t, testEnv.DaemonInfo.OSType == "windows")
    24  	defer setupTest(t)()
    25  	d := swarm.NewSwarm(t, testEnv)
    26  	defer d.Stop(t)
    27  	client := d.NewClientT(t)
    28  	defer client.Close()
    29  
    30  	var now = time.Now()
    31  	var instances uint64 = 2
    32  	serviceSpec := fullSwarmServiceSpec("test-service-inspect", instances)
    33  
    34  	ctx := context.Background()
    35  	resp, err := client.ServiceCreate(ctx, serviceSpec, types.ServiceCreateOptions{
    36  		QueryRegistry: false,
    37  	})
    38  	assert.NilError(t, err)
    39  
    40  	id := resp.ID
    41  	poll.WaitOn(t, serviceContainerCount(client, id, instances))
    42  
    43  	service, _, err := client.ServiceInspectWithRaw(ctx, id, types.ServiceInspectOptions{})
    44  	assert.NilError(t, err)
    45  
    46  	expected := swarmtypes.Service{
    47  		ID:   id,
    48  		Spec: serviceSpec,
    49  		Meta: swarmtypes.Meta{
    50  			Version:   swarmtypes.Version{Index: uint64(11)},
    51  			CreatedAt: now,
    52  			UpdatedAt: now,
    53  		},
    54  	}
    55  	assert.Check(t, is.DeepEqual(service, expected, cmpServiceOpts()))
    56  }
    57  
    58  // TODO: use helpers from gotest.tools/assert/opt when available
    59  func cmpServiceOpts() cmp.Option {
    60  	const threshold = 20 * time.Second
    61  
    62  	metaTimeFields := func(path cmp.Path) bool {
    63  		switch path.String() {
    64  		case "Meta.CreatedAt", "Meta.UpdatedAt":
    65  			return true
    66  		}
    67  		return false
    68  	}
    69  	withinThreshold := cmp.Comparer(func(x, y time.Time) bool {
    70  		delta := x.Sub(y)
    71  		return delta < threshold && delta > -threshold
    72  	})
    73  
    74  	return cmp.FilterPath(metaTimeFields, withinThreshold)
    75  }
    76  
    77  func fullSwarmServiceSpec(name string, replicas uint64) swarmtypes.ServiceSpec {
    78  	restartDelay := 100 * time.Millisecond
    79  	maxAttempts := uint64(4)
    80  
    81  	return swarmtypes.ServiceSpec{
    82  		Annotations: swarmtypes.Annotations{
    83  			Name: name,
    84  			Labels: map[string]string{
    85  				"service-label": "service-label-value",
    86  			},
    87  		},
    88  		TaskTemplate: swarmtypes.TaskSpec{
    89  			ContainerSpec: &swarmtypes.ContainerSpec{
    90  				Image:           "busybox:latest",
    91  				Labels:          map[string]string{"container-label": "container-value"},
    92  				Command:         []string{"/bin/top"},
    93  				Args:            []string{"-u", "root"},
    94  				Hostname:        "hostname",
    95  				Env:             []string{"envvar=envvalue"},
    96  				Dir:             "/work",
    97  				User:            "root",
    98  				StopSignal:      "SIGINT",
    99  				StopGracePeriod: &restartDelay,
   100  				Hosts:           []string{"8.8.8.8  google"},
   101  				DNSConfig: &swarmtypes.DNSConfig{
   102  					Nameservers: []string{"8.8.8.8"},
   103  					Search:      []string{"somedomain"},
   104  				},
   105  				Isolation: container.IsolationDefault,
   106  			},
   107  			RestartPolicy: &swarmtypes.RestartPolicy{
   108  				Delay:       &restartDelay,
   109  				Condition:   swarmtypes.RestartPolicyConditionOnFailure,
   110  				MaxAttempts: &maxAttempts,
   111  			},
   112  			Runtime: swarmtypes.RuntimeContainer,
   113  		},
   114  		Mode: swarmtypes.ServiceMode{
   115  			Replicated: &swarmtypes.ReplicatedService{
   116  				Replicas: &replicas,
   117  			},
   118  		},
   119  		UpdateConfig: &swarmtypes.UpdateConfig{
   120  			Parallelism:     2,
   121  			Delay:           200 * time.Second,
   122  			FailureAction:   swarmtypes.UpdateFailureActionContinue,
   123  			Monitor:         2 * time.Second,
   124  			MaxFailureRatio: 0.2,
   125  			Order:           swarmtypes.UpdateOrderStopFirst,
   126  		},
   127  		RollbackConfig: &swarmtypes.UpdateConfig{
   128  			Parallelism:     3,
   129  			Delay:           300 * time.Second,
   130  			FailureAction:   swarmtypes.UpdateFailureActionPause,
   131  			Monitor:         3 * time.Second,
   132  			MaxFailureRatio: 0.3,
   133  			Order:           swarmtypes.UpdateOrderStartFirst,
   134  		},
   135  	}
   136  }
   137  
   138  func serviceContainerCount(client client.ServiceAPIClient, id string, count uint64) func(log poll.LogT) poll.Result {
   139  	return func(log poll.LogT) poll.Result {
   140  		filter := filters.NewArgs()
   141  		filter.Add("service", id)
   142  		tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
   143  			Filters: filter,
   144  		})
   145  		switch {
   146  		case err != nil:
   147  			return poll.Error(err)
   148  		case len(tasks) == int(count):
   149  			return poll.Success()
   150  		default:
   151  			return poll.Continue("task count at %d waiting for %d", len(tasks), count)
   152  		}
   153  	}
   154  }