github.com/jwhonce/docker@v0.6.7-0.20190327063223-da823cf3a5a3/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/swarm" 11 "gotest.tools/assert" 12 is "gotest.tools/assert/cmp" 13 "gotest.tools/poll" 14 "gotest.tools/skip" 15 ) 16 17 func TestServiceUpdateLabel(t *testing.T) { 18 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 19 defer setupTest(t)() 20 d := swarm.NewSwarm(t, testEnv) 21 defer d.Stop(t) 22 cli := d.NewClientT(t) 23 defer cli.Close() 24 25 ctx := context.Background() 26 serviceName := "TestService_" + t.Name() 27 serviceID := swarm.CreateService(t, d, swarm.ServiceWithName(serviceName)) 28 service := getService(t, cli, serviceID) 29 assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{})) 30 31 // add label to empty set 32 service.Spec.Labels["foo"] = "bar" 33 _, err := cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 34 assert.NilError(t, err) 35 poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) 36 service = getService(t, cli, serviceID) 37 assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar"})) 38 39 // add label to non-empty set 40 service.Spec.Labels["foo2"] = "bar" 41 _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 42 assert.NilError(t, err) 43 poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) 44 service = getService(t, cli, serviceID) 45 assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar", "foo2": "bar"})) 46 47 delete(service.Spec.Labels, "foo2") 48 _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 49 assert.NilError(t, err) 50 poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) 51 service = getService(t, cli, serviceID) 52 assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar"})) 53 54 delete(service.Spec.Labels, "foo") 55 _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 56 assert.NilError(t, err) 57 poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) 58 service = getService(t, cli, serviceID) 59 assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{})) 60 61 // now make sure we can add again 62 service.Spec.Labels["foo"] = "bar" 63 _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 64 assert.NilError(t, err) 65 poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) 66 service = getService(t, cli, serviceID) 67 assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar"})) 68 69 err = cli.ServiceRemove(context.Background(), serviceID) 70 assert.NilError(t, err) 71 } 72 73 func TestServiceUpdateSecrets(t *testing.T) { 74 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 75 defer setupTest(t)() 76 d := swarm.NewSwarm(t, testEnv) 77 defer d.Stop(t) 78 cli := d.NewClientT(t) 79 defer cli.Close() 80 81 ctx := context.Background() 82 secretName := "TestSecret_" + t.Name() 83 secretTarget := "targetName" 84 resp, err := cli.SecretCreate(ctx, swarmtypes.SecretSpec{ 85 Annotations: swarmtypes.Annotations{ 86 Name: secretName, 87 }, 88 Data: []byte("TESTINGDATA"), 89 }) 90 assert.NilError(t, err) 91 assert.Check(t, resp.ID != "") 92 93 serviceName := "TestService_" + t.Name() 94 serviceID := swarm.CreateService(t, d, swarm.ServiceWithName(serviceName)) 95 service := getService(t, cli, serviceID) 96 97 // add secret 98 service.Spec.TaskTemplate.ContainerSpec.Secrets = append(service.Spec.TaskTemplate.ContainerSpec.Secrets, 99 &swarmtypes.SecretReference{ 100 File: &swarmtypes.SecretReferenceFileTarget{ 101 Name: secretTarget, 102 UID: "0", 103 GID: "0", 104 Mode: 0600, 105 }, 106 SecretID: resp.ID, 107 SecretName: secretName, 108 }, 109 ) 110 _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 111 assert.NilError(t, err) 112 poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) 113 114 service = getService(t, cli, serviceID) 115 secrets := service.Spec.TaskTemplate.ContainerSpec.Secrets 116 assert.Assert(t, is.Equal(1, len(secrets))) 117 118 secret := *secrets[0] 119 assert.Check(t, is.Equal(secretName, secret.SecretName)) 120 assert.Check(t, nil != secret.File) 121 assert.Check(t, is.Equal(secretTarget, secret.File.Name)) 122 123 // remove 124 service.Spec.TaskTemplate.ContainerSpec.Secrets = []*swarmtypes.SecretReference{} 125 _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 126 assert.NilError(t, err) 127 poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) 128 service = getService(t, cli, serviceID) 129 assert.Check(t, is.Equal(0, len(service.Spec.TaskTemplate.ContainerSpec.Secrets))) 130 131 err = cli.ServiceRemove(context.Background(), serviceID) 132 assert.NilError(t, err) 133 } 134 135 func TestServiceUpdateConfigs(t *testing.T) { 136 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 137 defer setupTest(t)() 138 d := swarm.NewSwarm(t, testEnv) 139 defer d.Stop(t) 140 cli := d.NewClientT(t) 141 defer cli.Close() 142 143 ctx := context.Background() 144 configName := "TestConfig_" + t.Name() 145 configTarget := "targetName" 146 resp, err := cli.ConfigCreate(ctx, swarmtypes.ConfigSpec{ 147 Annotations: swarmtypes.Annotations{ 148 Name: configName, 149 }, 150 Data: []byte("TESTINGDATA"), 151 }) 152 assert.NilError(t, err) 153 assert.Check(t, resp.ID != "") 154 155 serviceName := "TestService_" + t.Name() 156 serviceID := swarm.CreateService(t, d, swarm.ServiceWithName(serviceName)) 157 service := getService(t, cli, serviceID) 158 159 // add config 160 service.Spec.TaskTemplate.ContainerSpec.Configs = append(service.Spec.TaskTemplate.ContainerSpec.Configs, 161 &swarmtypes.ConfigReference{ 162 File: &swarmtypes.ConfigReferenceFileTarget{ 163 Name: configTarget, 164 UID: "0", 165 GID: "0", 166 Mode: 0600, 167 }, 168 ConfigID: resp.ID, 169 ConfigName: configName, 170 }, 171 ) 172 _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 173 assert.NilError(t, err) 174 poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) 175 176 service = getService(t, cli, serviceID) 177 configs := service.Spec.TaskTemplate.ContainerSpec.Configs 178 assert.Assert(t, is.Equal(1, len(configs))) 179 180 config := *configs[0] 181 assert.Check(t, is.Equal(configName, config.ConfigName)) 182 assert.Check(t, nil != config.File) 183 assert.Check(t, is.Equal(configTarget, config.File.Name)) 184 185 // remove 186 service.Spec.TaskTemplate.ContainerSpec.Configs = []*swarmtypes.ConfigReference{} 187 _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) 188 assert.NilError(t, err) 189 poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) 190 service = getService(t, cli, serviceID) 191 assert.Check(t, is.Equal(0, len(service.Spec.TaskTemplate.ContainerSpec.Configs))) 192 193 err = cli.ServiceRemove(context.Background(), serviceID) 194 assert.NilError(t, err) 195 } 196 197 func getService(t *testing.T, cli client.ServiceAPIClient, serviceID string) swarmtypes.Service { 198 t.Helper() 199 service, _, err := cli.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{}) 200 assert.NilError(t, err) 201 return service 202 } 203 204 func serviceIsUpdated(client client.ServiceAPIClient, serviceID string) func(log poll.LogT) poll.Result { 205 return func(log poll.LogT) poll.Result { 206 service, _, err := client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{}) 207 switch { 208 case err != nil: 209 return poll.Error(err) 210 case service.UpdateStatus != nil && service.UpdateStatus.State == swarmtypes.UpdateStateCompleted: 211 return poll.Success() 212 default: 213 if service.UpdateStatus != nil { 214 return poll.Continue("waiting for service %s to be updated, state: %s, message: %s", serviceID, service.UpdateStatus.State, service.UpdateStatus.Message) 215 } 216 return poll.Continue("waiting for service %s to be updated", serviceID) 217 } 218 } 219 }