github.com/zhouyu0/docker-note@v0.0.0-20190722021225-b8d3825084db/integration/internal/swarm/service.go (about) 1 package swarm 2 3 import ( 4 "context" 5 "runtime" 6 "testing" 7 "time" 8 9 "github.com/docker/docker/api/types" 10 "github.com/docker/docker/api/types/filters" 11 swarmtypes "github.com/docker/docker/api/types/swarm" 12 "github.com/docker/docker/internal/test/daemon" 13 "github.com/docker/docker/internal/test/environment" 14 "gotest.tools/assert" 15 "gotest.tools/poll" 16 "gotest.tools/skip" 17 ) 18 19 // ServicePoll tweaks the pollSettings for `service` 20 func ServicePoll(config *poll.Settings) { 21 // Override the default pollSettings for `service` resource here ... 22 config.Timeout = 30 * time.Second 23 config.Delay = 100 * time.Millisecond 24 if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" { 25 config.Timeout = 90 * time.Second 26 } 27 } 28 29 // NetworkPoll tweaks the pollSettings for `network` 30 func NetworkPoll(config *poll.Settings) { 31 // Override the default pollSettings for `network` resource here ... 32 config.Timeout = 30 * time.Second 33 config.Delay = 100 * time.Millisecond 34 35 if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" { 36 config.Timeout = 50 * time.Second 37 } 38 } 39 40 // ContainerPoll tweaks the pollSettings for `container` 41 func ContainerPoll(config *poll.Settings) { 42 // Override the default pollSettings for `container` resource here ... 43 44 if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" { 45 config.Timeout = 30 * time.Second 46 config.Delay = 100 * time.Millisecond 47 } 48 } 49 50 // NewSwarm creates a swarm daemon for testing 51 func NewSwarm(t *testing.T, testEnv *environment.Execution, ops ...func(*daemon.Daemon)) *daemon.Daemon { 52 t.Helper() 53 skip.If(t, testEnv.IsRemoteDaemon) 54 skip.If(t, testEnv.DaemonInfo.OSType == "windows") 55 if testEnv.DaemonInfo.ExperimentalBuild { 56 ops = append(ops, daemon.WithExperimental) 57 } 58 d := daemon.New(t, ops...) 59 d.StartAndSwarmInit(t) 60 return d 61 } 62 63 // ServiceSpecOpt is used with `CreateService` to pass in service spec modifiers 64 type ServiceSpecOpt func(*swarmtypes.ServiceSpec) 65 66 // CreateService creates a service on the passed in swarm daemon. 67 func CreateService(t *testing.T, d *daemon.Daemon, opts ...ServiceSpecOpt) string { 68 t.Helper() 69 spec := defaultServiceSpec() 70 for _, o := range opts { 71 o(&spec) 72 } 73 74 client := d.NewClientT(t) 75 defer client.Close() 76 77 resp, err := client.ServiceCreate(context.Background(), spec, types.ServiceCreateOptions{}) 78 assert.NilError(t, err, "error creating service") 79 return resp.ID 80 } 81 82 func defaultServiceSpec() swarmtypes.ServiceSpec { 83 var spec swarmtypes.ServiceSpec 84 ServiceWithImage("busybox:latest")(&spec) 85 ServiceWithCommand([]string{"/bin/top"})(&spec) 86 ServiceWithReplicas(1)(&spec) 87 return spec 88 } 89 90 // ServiceWithInit sets whether the service should use init or not 91 func ServiceWithInit(b *bool) func(*swarmtypes.ServiceSpec) { 92 return func(spec *swarmtypes.ServiceSpec) { 93 ensureContainerSpec(spec) 94 spec.TaskTemplate.ContainerSpec.Init = b 95 } 96 } 97 98 // ServiceWithImage sets the image to use for the service 99 func ServiceWithImage(image string) func(*swarmtypes.ServiceSpec) { 100 return func(spec *swarmtypes.ServiceSpec) { 101 ensureContainerSpec(spec) 102 spec.TaskTemplate.ContainerSpec.Image = image 103 } 104 } 105 106 // ServiceWithCommand sets the command to use for the service 107 func ServiceWithCommand(cmd []string) ServiceSpecOpt { 108 return func(spec *swarmtypes.ServiceSpec) { 109 ensureContainerSpec(spec) 110 spec.TaskTemplate.ContainerSpec.Command = cmd 111 } 112 } 113 114 // ServiceWithConfig adds the config reference to the service 115 func ServiceWithConfig(configRef *swarmtypes.ConfigReference) ServiceSpecOpt { 116 return func(spec *swarmtypes.ServiceSpec) { 117 ensureContainerSpec(spec) 118 spec.TaskTemplate.ContainerSpec.Configs = append(spec.TaskTemplate.ContainerSpec.Configs, configRef) 119 } 120 } 121 122 // ServiceWithSecret adds the secret reference to the service 123 func ServiceWithSecret(secretRef *swarmtypes.SecretReference) ServiceSpecOpt { 124 return func(spec *swarmtypes.ServiceSpec) { 125 ensureContainerSpec(spec) 126 spec.TaskTemplate.ContainerSpec.Secrets = append(spec.TaskTemplate.ContainerSpec.Secrets, secretRef) 127 } 128 } 129 130 // ServiceWithReplicas sets the replicas for the service 131 func ServiceWithReplicas(n uint64) ServiceSpecOpt { 132 return func(spec *swarmtypes.ServiceSpec) { 133 spec.Mode = swarmtypes.ServiceMode{ 134 Replicated: &swarmtypes.ReplicatedService{ 135 Replicas: &n, 136 }, 137 } 138 } 139 } 140 141 // ServiceWithName sets the name of the service 142 func ServiceWithName(name string) ServiceSpecOpt { 143 return func(spec *swarmtypes.ServiceSpec) { 144 spec.Annotations.Name = name 145 } 146 } 147 148 // ServiceWithNetwork sets the network of the service 149 func ServiceWithNetwork(network string) ServiceSpecOpt { 150 return func(spec *swarmtypes.ServiceSpec) { 151 spec.TaskTemplate.Networks = append(spec.TaskTemplate.Networks, 152 swarmtypes.NetworkAttachmentConfig{Target: network}) 153 } 154 } 155 156 // ServiceWithEndpoint sets the Endpoint of the service 157 func ServiceWithEndpoint(endpoint *swarmtypes.EndpointSpec) ServiceSpecOpt { 158 return func(spec *swarmtypes.ServiceSpec) { 159 spec.EndpointSpec = endpoint 160 } 161 } 162 163 // GetRunningTasks gets the list of running tasks for a service 164 func GetRunningTasks(t *testing.T, d *daemon.Daemon, serviceID string) []swarmtypes.Task { 165 t.Helper() 166 client := d.NewClientT(t) 167 defer client.Close() 168 169 filterArgs := filters.NewArgs() 170 filterArgs.Add("desired-state", "running") 171 filterArgs.Add("service", serviceID) 172 173 options := types.TaskListOptions{ 174 Filters: filterArgs, 175 } 176 tasks, err := client.TaskList(context.Background(), options) 177 assert.NilError(t, err) 178 return tasks 179 } 180 181 // ExecTask runs the passed in exec config on the given task 182 func ExecTask(t *testing.T, d *daemon.Daemon, task swarmtypes.Task, config types.ExecConfig) types.HijackedResponse { 183 t.Helper() 184 client := d.NewClientT(t) 185 defer client.Close() 186 187 ctx := context.Background() 188 resp, err := client.ContainerExecCreate(ctx, task.Status.ContainerStatus.ContainerID, config) 189 assert.NilError(t, err, "error creating exec") 190 191 startCheck := types.ExecStartCheck{} 192 attach, err := client.ContainerExecAttach(ctx, resp.ID, startCheck) 193 assert.NilError(t, err, "error attaching to exec") 194 return attach 195 } 196 197 func ensureContainerSpec(spec *swarmtypes.ServiceSpec) { 198 if spec.TaskTemplate.ContainerSpec == nil { 199 spec.TaskTemplate.ContainerSpec = &swarmtypes.ContainerSpec{} 200 } 201 }