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 }