github.com/zhouyu0/docker-note@v0.0.0-20190722021225-b8d3825084db/integration/service/update_test.go (about) 1 package service // import "github.com/docker/docker/integration/service" 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/docker/docker/api/types" 8 swarmtypes "github.com/docker/docker/api/types/swarm" 9 "github.com/docker/docker/client" 10 "github.com/docker/docker/integration/internal/network" 11 "github.com/docker/docker/integration/internal/swarm" 12 "gotest.tools/assert" 13 is "gotest.tools/assert/cmp" 14 "gotest.tools/poll" 15 "gotest.tools/skip" 16 ) 17 18 func TestServiceUpdateLabel(t *testing.T) { 19 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 20 defer setupTest(t)() 21 d := swarm.NewSwarm(t, testEnv) 22 defer d.Stop(t) 23 cli := d.NewClientT(t) 24 defer cli.Close() 25 26 ctx := context.Background() 27 serviceName := "TestService_" + t.Name() 28 serviceID := swarm.CreateService(t, d, swarm.ServiceWithName(serviceName)) 29 service := getService(t, cli, serviceID) 30 assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{})) 31 32 // add label to empty set 33 service.Spec.Labels["foo"] = "bar" 34 _, err := cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 35 assert.NilError(t, err) 36 poll.WaitOn(t, serviceSpecIsUpdated(cli, serviceID, service.Version.Index), swarm.ServicePoll) 37 service = getService(t, cli, serviceID) 38 assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar"})) 39 40 // add label to non-empty set 41 service.Spec.Labels["foo2"] = "bar" 42 _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 43 assert.NilError(t, err) 44 poll.WaitOn(t, serviceSpecIsUpdated(cli, serviceID, service.Version.Index), swarm.ServicePoll) 45 service = getService(t, cli, serviceID) 46 assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar", "foo2": "bar"})) 47 48 delete(service.Spec.Labels, "foo2") 49 _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 50 assert.NilError(t, err) 51 poll.WaitOn(t, serviceSpecIsUpdated(cli, serviceID, service.Version.Index), swarm.ServicePoll) 52 service = getService(t, cli, serviceID) 53 assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar"})) 54 55 delete(service.Spec.Labels, "foo") 56 _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 57 assert.NilError(t, err) 58 poll.WaitOn(t, serviceSpecIsUpdated(cli, serviceID, service.Version.Index), swarm.ServicePoll) 59 service = getService(t, cli, serviceID) 60 assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{})) 61 62 // now make sure we can add again 63 service.Spec.Labels["foo"] = "bar" 64 _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 65 assert.NilError(t, err) 66 poll.WaitOn(t, serviceSpecIsUpdated(cli, serviceID, service.Version.Index), swarm.ServicePoll) 67 service = getService(t, cli, serviceID) 68 assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar"})) 69 70 err = cli.ServiceRemove(context.Background(), serviceID) 71 assert.NilError(t, err) 72 } 73 74 func TestServiceUpdateSecrets(t *testing.T) { 75 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 76 defer setupTest(t)() 77 d := swarm.NewSwarm(t, testEnv) 78 defer d.Stop(t) 79 cli := d.NewClientT(t) 80 defer cli.Close() 81 82 ctx := context.Background() 83 secretName := "TestSecret_" + t.Name() 84 secretTarget := "targetName" 85 resp, err := cli.SecretCreate(ctx, swarmtypes.SecretSpec{ 86 Annotations: swarmtypes.Annotations{ 87 Name: secretName, 88 }, 89 Data: []byte("TESTINGDATA"), 90 }) 91 assert.NilError(t, err) 92 assert.Check(t, resp.ID != "") 93 94 serviceName := "TestService_" + t.Name() 95 serviceID := swarm.CreateService(t, d, swarm.ServiceWithName(serviceName)) 96 service := getService(t, cli, serviceID) 97 98 // add secret 99 service.Spec.TaskTemplate.ContainerSpec.Secrets = append(service.Spec.TaskTemplate.ContainerSpec.Secrets, 100 &swarmtypes.SecretReference{ 101 File: &swarmtypes.SecretReferenceFileTarget{ 102 Name: secretTarget, 103 UID: "0", 104 GID: "0", 105 Mode: 0600, 106 }, 107 SecretID: resp.ID, 108 SecretName: secretName, 109 }, 110 ) 111 _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 112 assert.NilError(t, err) 113 poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) 114 115 service = getService(t, cli, serviceID) 116 secrets := service.Spec.TaskTemplate.ContainerSpec.Secrets 117 assert.Assert(t, is.Equal(1, len(secrets))) 118 119 secret := *secrets[0] 120 assert.Check(t, is.Equal(secretName, secret.SecretName)) 121 assert.Check(t, nil != secret.File) 122 assert.Check(t, is.Equal(secretTarget, secret.File.Name)) 123 124 // remove 125 service.Spec.TaskTemplate.ContainerSpec.Secrets = []*swarmtypes.SecretReference{} 126 _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 127 assert.NilError(t, err) 128 poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) 129 service = getService(t, cli, serviceID) 130 assert.Check(t, is.Equal(0, len(service.Spec.TaskTemplate.ContainerSpec.Secrets))) 131 132 err = cli.ServiceRemove(context.Background(), serviceID) 133 assert.NilError(t, err) 134 } 135 136 func TestServiceUpdateConfigs(t *testing.T) { 137 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 138 defer setupTest(t)() 139 d := swarm.NewSwarm(t, testEnv) 140 defer d.Stop(t) 141 cli := d.NewClientT(t) 142 defer cli.Close() 143 144 ctx := context.Background() 145 configName := "TestConfig_" + t.Name() 146 configTarget := "targetName" 147 resp, err := cli.ConfigCreate(ctx, swarmtypes.ConfigSpec{ 148 Annotations: swarmtypes.Annotations{ 149 Name: configName, 150 }, 151 Data: []byte("TESTINGDATA"), 152 }) 153 assert.NilError(t, err) 154 assert.Check(t, resp.ID != "") 155 156 serviceName := "TestService_" + t.Name() 157 serviceID := swarm.CreateService(t, d, swarm.ServiceWithName(serviceName)) 158 service := getService(t, cli, serviceID) 159 160 // add config 161 service.Spec.TaskTemplate.ContainerSpec.Configs = append(service.Spec.TaskTemplate.ContainerSpec.Configs, 162 &swarmtypes.ConfigReference{ 163 File: &swarmtypes.ConfigReferenceFileTarget{ 164 Name: configTarget, 165 UID: "0", 166 GID: "0", 167 Mode: 0600, 168 }, 169 ConfigID: resp.ID, 170 ConfigName: configName, 171 }, 172 ) 173 _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 174 assert.NilError(t, err) 175 poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) 176 177 service = getService(t, cli, serviceID) 178 configs := service.Spec.TaskTemplate.ContainerSpec.Configs 179 assert.Assert(t, is.Equal(1, len(configs))) 180 181 config := *configs[0] 182 assert.Check(t, is.Equal(configName, config.ConfigName)) 183 assert.Check(t, nil != config.File) 184 assert.Check(t, is.Equal(configTarget, config.File.Name)) 185 186 // remove 187 service.Spec.TaskTemplate.ContainerSpec.Configs = []*swarmtypes.ConfigReference{} 188 _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 189 assert.NilError(t, err) 190 poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) 191 service = getService(t, cli, serviceID) 192 assert.Check(t, is.Equal(0, len(service.Spec.TaskTemplate.ContainerSpec.Configs))) 193 194 err = cli.ServiceRemove(context.Background(), serviceID) 195 assert.NilError(t, err) 196 } 197 198 func TestServiceUpdateNetwork(t *testing.T) { 199 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 200 defer setupTest(t)() 201 d := swarm.NewSwarm(t, testEnv) 202 defer d.Stop(t) 203 cli := d.NewClientT(t) 204 defer cli.Close() 205 206 ctx := context.Background() 207 208 // Create a overlay network 209 testNet := "testNet" + t.Name() 210 overlayID := network.CreateNoError(t, ctx, cli, testNet, 211 network.WithDriver("overlay")) 212 213 var instances uint64 = 1 214 // Create service with the overlay network 215 serviceName := "TestServiceUpdateNetworkRM_" + t.Name() 216 serviceID := swarm.CreateService(t, d, 217 swarm.ServiceWithReplicas(instances), 218 swarm.ServiceWithName(serviceName), 219 swarm.ServiceWithNetwork(testNet)) 220 221 poll.WaitOn(t, swarm.RunningTasksCount(cli, serviceID, instances), swarm.ServicePoll) 222 service := getService(t, cli, serviceID) 223 netInfo, err := cli.NetworkInspect(ctx, testNet, types.NetworkInspectOptions{ 224 Verbose: true, 225 Scope: "swarm", 226 }) 227 assert.NilError(t, err) 228 assert.Assert(t, len(netInfo.Containers) == 2, "Expected 2 endpoints, one for container and one for LB Sandbox") 229 230 //Remove network from service 231 service.Spec.TaskTemplate.Networks = []swarmtypes.NetworkAttachmentConfig{} 232 _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 233 assert.NilError(t, err) 234 poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) 235 236 netInfo, err = cli.NetworkInspect(ctx, testNet, types.NetworkInspectOptions{ 237 Verbose: true, 238 Scope: "swarm", 239 }) 240 241 assert.NilError(t, err) 242 assert.Assert(t, len(netInfo.Containers) == 0, "Load balancing endpoint still exists in network") 243 244 err = cli.NetworkRemove(ctx, overlayID) 245 assert.NilError(t, err) 246 247 err = cli.ServiceRemove(ctx, serviceID) 248 assert.NilError(t, err) 249 } 250 251 func getService(t *testing.T, cli client.ServiceAPIClient, serviceID string) swarmtypes.Service { 252 t.Helper() 253 service, _, err := cli.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{}) 254 assert.NilError(t, err) 255 return service 256 } 257 258 func serviceIsUpdated(client client.ServiceAPIClient, serviceID string) func(log poll.LogT) poll.Result { 259 return func(log poll.LogT) poll.Result { 260 service, _, err := client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{}) 261 switch { 262 case err != nil: 263 return poll.Error(err) 264 case service.UpdateStatus != nil && service.UpdateStatus.State == swarmtypes.UpdateStateCompleted: 265 return poll.Success() 266 default: 267 if service.UpdateStatus != nil { 268 return poll.Continue("waiting for service %s to be updated, state: %s, message: %s", serviceID, service.UpdateStatus.State, service.UpdateStatus.Message) 269 } 270 return poll.Continue("waiting for service %s to be updated", serviceID) 271 } 272 } 273 } 274 275 func serviceSpecIsUpdated(client client.ServiceAPIClient, serviceID string, serviceOldVersion uint64) func(log poll.LogT) poll.Result { 276 return func(log poll.LogT) poll.Result { 277 service, _, err := client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{}) 278 switch { 279 case err != nil: 280 return poll.Error(err) 281 case service.Version.Index > serviceOldVersion: 282 return poll.Success() 283 default: 284 return poll.Continue("waiting for service %s to be updated", serviceID) 285 } 286 } 287 }