Signed-off-by: Daniel Nephin <dnephin@docker.com>
| ... | ... |
@@ -103,13 +103,6 @@ func updateService(flags *pflag.FlagSet, spec *swarm.ServiceSpec) error {
|
| 103 | 103 |
} |
| 104 | 104 |
} |
| 105 | 105 |
|
| 106 |
- updateListOpts := func(flag string, field *[]string) {
|
|
| 107 |
- if flags.Changed(flag) {
|
|
| 108 |
- value := flags.Lookup(flag).Value.(*opts.ListOpts) |
|
| 109 |
- *field = value.GetAll() |
|
| 110 |
- } |
|
| 111 |
- } |
|
| 112 |
- |
|
| 113 | 106 |
updateInt64Value := func(flag string, field *int64) {
|
| 114 | 107 |
if flags.Changed(flag) {
|
| 115 | 108 |
*field = flags.Lookup(flag).Value.(int64Value).Value() |
| ... | ... |
@@ -243,15 +236,10 @@ func anyChanged(flags *pflag.FlagSet, fields ...string) bool {
|
| 243 | 243 |
|
| 244 | 244 |
func updatePlacement(flags *pflag.FlagSet, placement *swarm.Placement) {
|
| 245 | 245 |
field, _ := flags.GetStringSlice(flagConstraintAdd) |
| 246 |
- constraints := &placement.Constraints |
|
| 247 | 246 |
placement.Constraints = append(placement.Constraints, field...) |
| 248 | 247 |
|
| 249 | 248 |
toRemove := buildToRemoveSet(flags, flagConstraintRemove) |
| 250 |
- for i, constraint := range placement.Constraints {
|
|
| 251 |
- if _, exists := toRemove[constraint]; exists {
|
|
| 252 |
- *constraints = append((*constraints)[:i], (*constraints)[i+1:]...) |
|
| 253 |
- } |
|
| 254 |
- } |
|
| 249 |
+ placement.Constraints = removeItems(placement.Constraints, toRemove, itemKey) |
|
| 255 | 250 |
} |
| 256 | 251 |
|
| 257 | 252 |
func updateLabels(flags *pflag.FlagSet, field *map[string]string) {
|
| ... | ... |
@@ -280,12 +268,7 @@ func updateEnvironment(flags *pflag.FlagSet, field *[]string) {
|
| 280 | 280 |
*field = append(*field, value.GetAll()...) |
| 281 | 281 |
} |
| 282 | 282 |
toRemove := buildToRemoveSet(flags, flagEnvRemove) |
| 283 |
- for i, env := range *field {
|
|
| 284 |
- key := envKey(env) |
|
| 285 |
- if _, exists := toRemove[key]; exists {
|
|
| 286 |
- *field = append((*field)[:i], (*field)[i+1:]...) |
|
| 287 |
- } |
|
| 288 |
- } |
|
| 283 |
+ *field = removeItems(*field, toRemove, envKey) |
|
| 289 | 284 |
} |
| 290 | 285 |
|
| 291 | 286 |
func envKey(value string) string {
|
| ... | ... |
@@ -293,6 +276,10 @@ func envKey(value string) string {
|
| 293 | 293 |
return kv[0] |
| 294 | 294 |
} |
| 295 | 295 |
|
| 296 |
+func itemKey(value string) string {
|
|
| 297 |
+ return value |
|
| 298 |
+} |
|
| 299 |
+ |
|
| 296 | 300 |
func buildToRemoveSet(flags *pflag.FlagSet, flag string) map[string]struct{} {
|
| 297 | 301 |
var empty struct{}
|
| 298 | 302 |
toRemove := make(map[string]struct{})
|
| ... | ... |
@@ -308,17 +295,34 @@ func buildToRemoveSet(flags *pflag.FlagSet, flag string) map[string]struct{} {
|
| 308 | 308 |
return toRemove |
| 309 | 309 |
} |
| 310 | 310 |
|
| 311 |
+func removeItems( |
|
| 312 |
+ seq []string, |
|
| 313 |
+ toRemove map[string]struct{},
|
|
| 314 |
+ keyFunc func(string) string, |
|
| 315 |
+) []string {
|
|
| 316 |
+ newSeq := []string{}
|
|
| 317 |
+ for _, item := range seq {
|
|
| 318 |
+ if _, exists := toRemove[keyFunc(item)]; !exists {
|
|
| 319 |
+ newSeq = append(newSeq, item) |
|
| 320 |
+ } |
|
| 321 |
+ } |
|
| 322 |
+ return newSeq |
|
| 323 |
+} |
|
| 324 |
+ |
|
| 311 | 325 |
func updateMounts(flags *pflag.FlagSet, mounts *[]swarm.Mount) {
|
| 312 | 326 |
if flags.Changed(flagMountAdd) {
|
| 313 | 327 |
values := flags.Lookup(flagMountAdd).Value.(*MountOpt).Value() |
| 314 | 328 |
*mounts = append(*mounts, values...) |
| 315 | 329 |
} |
| 316 | 330 |
toRemove := buildToRemoveSet(flags, flagMountRemove) |
| 317 |
- for i, mount := range *mounts {
|
|
| 318 |
- if _, exists := toRemove[mount.Target]; exists {
|
|
| 319 |
- *mounts = append((*mounts)[:i], (*mounts)[i+1:]...) |
|
| 331 |
+ |
|
| 332 |
+ newMounts := []swarm.Mount{}
|
|
| 333 |
+ for _, mount := range *mounts {
|
|
| 334 |
+ if _, exists := toRemove[mount.Target]; !exists {
|
|
| 335 |
+ newMounts = append(newMounts, mount) |
|
| 320 | 336 |
} |
| 321 | 337 |
} |
| 338 |
+ *mounts = newMounts |
|
| 322 | 339 |
} |
| 323 | 340 |
|
| 324 | 341 |
func updatePorts(flags *pflag.FlagSet, portConfig *[]swarm.PortConfig) {
|
| ... | ... |
@@ -331,19 +335,27 @@ func updatePorts(flags *pflag.FlagSet, portConfig *[]swarm.PortConfig) {
|
| 331 | 331 |
} |
| 332 | 332 |
} |
| 333 | 333 |
|
| 334 |
- if flags.Changed(flagPublishRemove) {
|
|
| 335 |
- toRemove := flags.Lookup(flagPublishRemove).Value.(*opts.ListOpts).GetAll() |
|
| 334 |
+ if !flags.Changed(flagPublishRemove) {
|
|
| 335 |
+ return |
|
| 336 |
+ } |
|
| 337 |
+ toRemove := flags.Lookup(flagPublishRemove).Value.(*opts.ListOpts).GetAll() |
|
| 338 |
+ newPorts := []swarm.PortConfig{}
|
|
| 339 |
+portLoop: |
|
| 340 |
+ for _, port := range *portConfig {
|
|
| 336 | 341 |
for _, rawTargetPort := range toRemove {
|
| 337 | 342 |
targetPort := nat.Port(rawTargetPort) |
| 338 |
- for i, port := range *portConfig {
|
|
| 339 |
- if string(port.Protocol) == targetPort.Proto() && |
|
| 340 |
- port.TargetPort == uint32(targetPort.Int()) {
|
|
| 341 |
- *portConfig = append((*portConfig)[:i], (*portConfig)[i+1:]...) |
|
| 342 |
- break |
|
| 343 |
- } |
|
| 343 |
+ if equalPort(targetPort, port) {
|
|
| 344 |
+ continue portLoop |
|
| 344 | 345 |
} |
| 345 | 346 |
} |
| 347 |
+ newPorts = append(newPorts, port) |
|
| 346 | 348 |
} |
| 349 |
+ *portConfig = newPorts |
|
| 350 |
+} |
|
| 351 |
+ |
|
| 352 |
+func equalPort(targetPort nat.Port, port swarm.PortConfig) bool {
|
|
| 353 |
+ return (string(port.Protocol) == targetPort.Proto() && |
|
| 354 |
+ port.TargetPort == uint32(targetPort.Int())) |
|
| 347 | 355 |
} |
| 348 | 356 |
|
| 349 | 357 |
func updateNetworks(flags *pflag.FlagSet, attachments *[]swarm.NetworkAttachmentConfig) {
|
| ... | ... |
@@ -354,11 +366,13 @@ func updateNetworks(flags *pflag.FlagSet, attachments *[]swarm.NetworkAttachment |
| 354 | 354 |
} |
| 355 | 355 |
} |
| 356 | 356 |
toRemove := buildToRemoveSet(flags, flagNetworkRemove) |
| 357 |
- for i, network := range *attachments {
|
|
| 358 |
- if _, exists := toRemove[network.Target]; exists {
|
|
| 359 |
- *attachments = append((*attachments)[:i], (*attachments)[i+1:]...) |
|
| 357 |
+ newNetworks := []swarm.NetworkAttachmentConfig{}
|
|
| 358 |
+ for _, network := range *attachments {
|
|
| 359 |
+ if _, exists := toRemove[network.Target]; !exists {
|
|
| 360 |
+ newNetworks = append(newNetworks, network) |
|
| 360 | 361 |
} |
| 361 | 362 |
} |
| 363 |
+ *attachments = newNetworks |
|
| 362 | 364 |
} |
| 363 | 365 |
|
| 364 | 366 |
func updateReplicas(flags *pflag.FlagSet, serviceMode *swarm.ServiceMode) error {
|
| ... | ... |
@@ -35,6 +35,15 @@ func TestUpdateLabels(t *testing.T) {
|
| 35 | 35 |
assert.Equal(t, labels["toadd"], "newlabel") |
| 36 | 36 |
} |
| 37 | 37 |
|
| 38 |
+func TestUpdateLabelsRemoveALabelThatDoesNotExist(t *testing.T) {
|
|
| 39 |
+ flags := newUpdateCommand(nil).Flags() |
|
| 40 |
+ flags.Set("label-rm", "dne")
|
|
| 41 |
+ |
|
| 42 |
+ labels := map[string]string{"foo": "theoldlabel"}
|
|
| 43 |
+ updateLabels(flags, &labels) |
|
| 44 |
+ assert.Equal(t, len(labels), 1) |
|
| 45 |
+} |
|
| 46 |
+ |
|
| 38 | 47 |
func TestUpdatePlacement(t *testing.T) {
|
| 39 | 48 |
flags := newUpdateCommand(nil).Flags() |
| 40 | 49 |
flags.Set("constraint-add", "node=toadd")
|
| ... | ... |
@@ -63,6 +72,18 @@ func TestUpdateEnvironment(t *testing.T) {
|
| 63 | 63 |
assert.Equal(t, envs[1], "toadd=newenv") |
| 64 | 64 |
} |
| 65 | 65 |
|
| 66 |
+func TestUpdateEnvironmentWithDuplicateValues(t *testing.T) {
|
|
| 67 |
+ flags := newUpdateCommand(nil).Flags() |
|
| 68 |
+ flags.Set("env-add", "foo=newenv")
|
|
| 69 |
+ flags.Set("env-add", "foo=dupe")
|
|
| 70 |
+ flags.Set("env-rm", "foo")
|
|
| 71 |
+ |
|
| 72 |
+ envs := []string{"foo=value"}
|
|
| 73 |
+ |
|
| 74 |
+ updateEnvironment(flags, &envs) |
|
| 75 |
+ assert.Equal(t, len(envs), 0) |
|
| 76 |
+} |
|
| 77 |
+ |
|
| 66 | 78 |
func TestUpdateMounts(t *testing.T) {
|
| 67 | 79 |
flags := newUpdateCommand(nil).Flags() |
| 68 | 80 |
flags.Set("mount-add", "type=volume,target=/toadd")
|