github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/cli/command/service/update_test.go (about) 1 package service 2 3 import ( 4 "reflect" 5 "sort" 6 "testing" 7 "time" 8 9 "github.com/docker/docker/api/types/container" 10 mounttypes "github.com/docker/docker/api/types/mount" 11 "github.com/docker/docker/api/types/swarm" 12 "github.com/docker/docker/pkg/testutil/assert" 13 ) 14 15 func TestUpdateServiceArgs(t *testing.T) { 16 flags := newUpdateCommand(nil).Flags() 17 flags.Set("args", "the \"new args\"") 18 19 spec := &swarm.ServiceSpec{} 20 cspec := &spec.TaskTemplate.ContainerSpec 21 cspec.Args = []string{"old", "args"} 22 23 updateService(flags, spec) 24 assert.EqualStringSlice(t, cspec.Args, []string{"the", "new args"}) 25 } 26 27 func TestUpdateLabels(t *testing.T) { 28 flags := newUpdateCommand(nil).Flags() 29 flags.Set("label-add", "toadd=newlabel") 30 flags.Set("label-rm", "toremove") 31 32 labels := map[string]string{ 33 "toremove": "thelabeltoremove", 34 "tokeep": "value", 35 } 36 37 updateLabels(flags, &labels) 38 assert.Equal(t, len(labels), 2) 39 assert.Equal(t, labels["tokeep"], "value") 40 assert.Equal(t, labels["toadd"], "newlabel") 41 } 42 43 func TestUpdateLabelsRemoveALabelThatDoesNotExist(t *testing.T) { 44 flags := newUpdateCommand(nil).Flags() 45 flags.Set("label-rm", "dne") 46 47 labels := map[string]string{"foo": "theoldlabel"} 48 updateLabels(flags, &labels) 49 assert.Equal(t, len(labels), 1) 50 } 51 52 func TestUpdatePlacement(t *testing.T) { 53 flags := newUpdateCommand(nil).Flags() 54 flags.Set("constraint-add", "node=toadd") 55 flags.Set("constraint-rm", "node!=toremove") 56 57 placement := &swarm.Placement{ 58 Constraints: []string{"node!=toremove", "container=tokeep"}, 59 } 60 61 updatePlacement(flags, placement) 62 assert.Equal(t, len(placement.Constraints), 2) 63 assert.Equal(t, placement.Constraints[0], "container=tokeep") 64 assert.Equal(t, placement.Constraints[1], "node=toadd") 65 } 66 67 func TestUpdateEnvironment(t *testing.T) { 68 flags := newUpdateCommand(nil).Flags() 69 flags.Set("env-add", "toadd=newenv") 70 flags.Set("env-rm", "toremove") 71 72 envs := []string{"toremove=theenvtoremove", "tokeep=value"} 73 74 updateEnvironment(flags, &envs) 75 assert.Equal(t, len(envs), 2) 76 // Order has been removed in updateEnvironment (map) 77 sort.Strings(envs) 78 assert.Equal(t, envs[0], "toadd=newenv") 79 assert.Equal(t, envs[1], "tokeep=value") 80 } 81 82 func TestUpdateEnvironmentWithDuplicateValues(t *testing.T) { 83 flags := newUpdateCommand(nil).Flags() 84 flags.Set("env-add", "foo=newenv") 85 flags.Set("env-add", "foo=dupe") 86 flags.Set("env-rm", "foo") 87 88 envs := []string{"foo=value"} 89 90 updateEnvironment(flags, &envs) 91 assert.Equal(t, len(envs), 0) 92 } 93 94 func TestUpdateEnvironmentWithDuplicateKeys(t *testing.T) { 95 // Test case for #25404 96 flags := newUpdateCommand(nil).Flags() 97 flags.Set("env-add", "A=b") 98 99 envs := []string{"A=c"} 100 101 updateEnvironment(flags, &envs) 102 assert.Equal(t, len(envs), 1) 103 assert.Equal(t, envs[0], "A=b") 104 } 105 106 func TestUpdateGroups(t *testing.T) { 107 flags := newUpdateCommand(nil).Flags() 108 flags.Set("group-add", "wheel") 109 flags.Set("group-add", "docker") 110 flags.Set("group-rm", "root") 111 flags.Set("group-add", "foo") 112 flags.Set("group-rm", "docker") 113 114 groups := []string{"bar", "root"} 115 116 updateGroups(flags, &groups) 117 assert.Equal(t, len(groups), 3) 118 assert.Equal(t, groups[0], "bar") 119 assert.Equal(t, groups[1], "foo") 120 assert.Equal(t, groups[2], "wheel") 121 } 122 123 func TestUpdateDNSConfig(t *testing.T) { 124 flags := newUpdateCommand(nil).Flags() 125 126 // IPv4, with duplicates 127 flags.Set("dns-add", "1.1.1.1") 128 flags.Set("dns-add", "1.1.1.1") 129 flags.Set("dns-add", "2.2.2.2") 130 flags.Set("dns-rm", "3.3.3.3") 131 flags.Set("dns-rm", "2.2.2.2") 132 // IPv6 133 flags.Set("dns-add", "2001:db8:abc8::1") 134 // Invalid dns record 135 assert.Error(t, flags.Set("dns-add", "x.y.z.w"), "x.y.z.w is not an ip address") 136 137 // domains with duplicates 138 flags.Set("dns-search-add", "example.com") 139 flags.Set("dns-search-add", "example.com") 140 flags.Set("dns-search-add", "example.org") 141 flags.Set("dns-search-rm", "example.org") 142 // Invalid dns search domain 143 assert.Error(t, flags.Set("dns-search-add", "example$com"), "example$com is not a valid domain") 144 145 flags.Set("dns-option-add", "ndots:9") 146 flags.Set("dns-option-rm", "timeout:3") 147 148 config := &swarm.DNSConfig{ 149 Nameservers: []string{"3.3.3.3", "5.5.5.5"}, 150 Search: []string{"localdomain"}, 151 Options: []string{"timeout:3"}, 152 } 153 154 updateDNSConfig(flags, &config) 155 156 assert.Equal(t, len(config.Nameservers), 3) 157 assert.Equal(t, config.Nameservers[0], "1.1.1.1") 158 assert.Equal(t, config.Nameservers[1], "2001:db8:abc8::1") 159 assert.Equal(t, config.Nameservers[2], "5.5.5.5") 160 161 assert.Equal(t, len(config.Search), 2) 162 assert.Equal(t, config.Search[0], "example.com") 163 assert.Equal(t, config.Search[1], "localdomain") 164 165 assert.Equal(t, len(config.Options), 1) 166 assert.Equal(t, config.Options[0], "ndots:9") 167 } 168 169 func TestUpdateMounts(t *testing.T) { 170 flags := newUpdateCommand(nil).Flags() 171 flags.Set("mount-add", "type=volume,source=vol2,target=/toadd") 172 flags.Set("mount-rm", "/toremove") 173 174 mounts := []mounttypes.Mount{ 175 {Target: "/toremove", Source: "vol1", Type: mounttypes.TypeBind}, 176 {Target: "/tokeep", Source: "vol3", Type: mounttypes.TypeBind}, 177 } 178 179 updateMounts(flags, &mounts) 180 assert.Equal(t, len(mounts), 2) 181 assert.Equal(t, mounts[0].Target, "/toadd") 182 assert.Equal(t, mounts[1].Target, "/tokeep") 183 184 } 185 186 func TestUpdateMountsWithDuplicateMounts(t *testing.T) { 187 flags := newUpdateCommand(nil).Flags() 188 flags.Set("mount-add", "type=volume,source=vol4,target=/toadd") 189 190 mounts := []mounttypes.Mount{ 191 {Target: "/tokeep1", Source: "vol1", Type: mounttypes.TypeBind}, 192 {Target: "/toadd", Source: "vol2", Type: mounttypes.TypeBind}, 193 {Target: "/tokeep2", Source: "vol3", Type: mounttypes.TypeBind}, 194 } 195 196 updateMounts(flags, &mounts) 197 assert.Equal(t, len(mounts), 3) 198 assert.Equal(t, mounts[0].Target, "/tokeep1") 199 assert.Equal(t, mounts[1].Target, "/tokeep2") 200 assert.Equal(t, mounts[2].Target, "/toadd") 201 } 202 203 func TestUpdatePorts(t *testing.T) { 204 flags := newUpdateCommand(nil).Flags() 205 flags.Set("publish-add", "1000:1000") 206 flags.Set("publish-rm", "333/udp") 207 208 portConfigs := []swarm.PortConfig{ 209 {TargetPort: 333, Protocol: swarm.PortConfigProtocolUDP}, 210 {TargetPort: 555}, 211 } 212 213 err := updatePorts(flags, &portConfigs) 214 assert.Equal(t, err, nil) 215 assert.Equal(t, len(portConfigs), 2) 216 // Do a sort to have the order (might have changed by map) 217 targetPorts := []int{int(portConfigs[0].TargetPort), int(portConfigs[1].TargetPort)} 218 sort.Ints(targetPorts) 219 assert.Equal(t, targetPorts[0], 555) 220 assert.Equal(t, targetPorts[1], 1000) 221 } 222 223 func TestUpdatePortsDuplicateEntries(t *testing.T) { 224 // Test case for #25375 225 flags := newUpdateCommand(nil).Flags() 226 flags.Set("publish-add", "80:80") 227 228 portConfigs := []swarm.PortConfig{ 229 {TargetPort: 80, PublishedPort: 80}, 230 } 231 232 err := updatePorts(flags, &portConfigs) 233 assert.Equal(t, err, nil) 234 assert.Equal(t, len(portConfigs), 1) 235 assert.Equal(t, portConfigs[0].TargetPort, uint32(80)) 236 } 237 238 func TestUpdatePortsDuplicateKeys(t *testing.T) { 239 // Test case for #25375 240 flags := newUpdateCommand(nil).Flags() 241 flags.Set("publish-add", "80:80") 242 243 portConfigs := []swarm.PortConfig{ 244 {TargetPort: 80, PublishedPort: 80}, 245 } 246 247 err := updatePorts(flags, &portConfigs) 248 assert.Equal(t, err, nil) 249 assert.Equal(t, len(portConfigs), 1) 250 assert.Equal(t, portConfigs[0].TargetPort, uint32(80)) 251 } 252 253 func TestUpdateHealthcheckTable(t *testing.T) { 254 type test struct { 255 flags [][2]string 256 initial *container.HealthConfig 257 expected *container.HealthConfig 258 err string 259 } 260 testCases := []test{ 261 { 262 flags: [][2]string{{"no-healthcheck", "true"}}, 263 initial: &container.HealthConfig{Test: []string{"CMD-SHELL", "cmd1"}, Retries: 10}, 264 expected: &container.HealthConfig{Test: []string{"NONE"}}, 265 }, 266 { 267 flags: [][2]string{{"health-cmd", "cmd1"}}, 268 initial: &container.HealthConfig{Test: []string{"NONE"}}, 269 expected: &container.HealthConfig{Test: []string{"CMD-SHELL", "cmd1"}}, 270 }, 271 { 272 flags: [][2]string{{"health-retries", "10"}}, 273 initial: &container.HealthConfig{Test: []string{"NONE"}}, 274 expected: &container.HealthConfig{Retries: 10}, 275 }, 276 { 277 flags: [][2]string{{"health-retries", "10"}}, 278 initial: &container.HealthConfig{Test: []string{"CMD", "cmd1"}}, 279 expected: &container.HealthConfig{Test: []string{"CMD", "cmd1"}, Retries: 10}, 280 }, 281 { 282 flags: [][2]string{{"health-interval", "1m"}}, 283 initial: &container.HealthConfig{Test: []string{"CMD", "cmd1"}}, 284 expected: &container.HealthConfig{Test: []string{"CMD", "cmd1"}, Interval: time.Minute}, 285 }, 286 { 287 flags: [][2]string{{"health-cmd", ""}}, 288 initial: &container.HealthConfig{Test: []string{"CMD", "cmd1"}, Retries: 10}, 289 expected: &container.HealthConfig{Retries: 10}, 290 }, 291 { 292 flags: [][2]string{{"health-retries", "0"}}, 293 initial: &container.HealthConfig{Test: []string{"CMD", "cmd1"}, Retries: 10}, 294 expected: &container.HealthConfig{Test: []string{"CMD", "cmd1"}}, 295 }, 296 { 297 flags: [][2]string{{"health-cmd", "cmd1"}, {"no-healthcheck", "true"}}, 298 err: "--no-healthcheck conflicts with --health-* options", 299 }, 300 { 301 flags: [][2]string{{"health-interval", "10m"}, {"no-healthcheck", "true"}}, 302 err: "--no-healthcheck conflicts with --health-* options", 303 }, 304 { 305 flags: [][2]string{{"health-timeout", "1m"}, {"no-healthcheck", "true"}}, 306 err: "--no-healthcheck conflicts with --health-* options", 307 }, 308 } 309 for i, c := range testCases { 310 flags := newUpdateCommand(nil).Flags() 311 for _, flag := range c.flags { 312 flags.Set(flag[0], flag[1]) 313 } 314 cspec := &swarm.ContainerSpec{ 315 Healthcheck: c.initial, 316 } 317 err := updateHealthcheck(flags, cspec) 318 if c.err != "" { 319 assert.Error(t, err, c.err) 320 } else { 321 assert.NilError(t, err) 322 if !reflect.DeepEqual(cspec.Healthcheck, c.expected) { 323 t.Errorf("incorrect result for test %d, expected health config:\n\t%#v\ngot:\n\t%#v", i, c.expected, cspec.Healthcheck) 324 } 325 } 326 } 327 } 328 329 func TestUpdateHosts(t *testing.T) { 330 flags := newUpdateCommand(nil).Flags() 331 flags.Set("host-add", "example.net:2.2.2.2") 332 flags.Set("host-add", "ipv6.net:2001:db8:abc8::1") 333 // remove with ipv6 should work 334 flags.Set("host-rm", "example.net:2001:db8:abc8::1") 335 // just hostname should work as well 336 flags.Set("host-rm", "example.net") 337 // bad format error 338 assert.Error(t, flags.Set("host-add", "$example.com$"), "bad format for add-host:") 339 340 hosts := []string{"1.2.3.4 example.com", "4.3.2.1 example.org", "2001:db8:abc8::1 example.net"} 341 342 updateHosts(flags, &hosts) 343 assert.Equal(t, len(hosts), 3) 344 assert.Equal(t, hosts[0], "1.2.3.4 example.com") 345 assert.Equal(t, hosts[1], "2001:db8:abc8::1 ipv6.net") 346 assert.Equal(t, hosts[2], "4.3.2.1 example.org") 347 }