Browse code

Make --publish-rm precedes --publish-add, so that add wins

`--publish-add 8081:81 --publish-add 8082:82 --publish-rm 80
--publish-rm 81/tcp --publish-rm 82/tcp` would thus result in 81 and
82 to be published.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>

Vincent Demeester authored on 2016/12/15 15:24:43
Showing 5 changed files
... ...
@@ -630,15 +630,7 @@ func (r byPortConfig) Less(i, j int) bool {
630 630
 
631 631
 func portConfigToString(portConfig *swarm.PortConfig) string {
632 632
 	protocol := portConfig.Protocol
633
-	if protocol == "" {
634
-		protocol = "tcp"
635
-	}
636
-
637 633
 	mode := portConfig.PublishMode
638
-	if mode == "" {
639
-		mode = "ingress"
640
-	}
641
-
642 634
 	return fmt.Sprintf("%v:%v/%s/%s", portConfig.PublishedPort, portConfig.TargetPort, protocol, mode)
643 635
 }
644 636
 
... ...
@@ -663,28 +655,18 @@ func validatePublishRemove(val string) (string, error) {
663 663
 func updatePorts(flags *pflag.FlagSet, portConfig *[]swarm.PortConfig) error {
664 664
 	// The key of the map is `port/protocol`, e.g., `80/tcp`
665 665
 	portSet := map[string]swarm.PortConfig{}
666
-	// Check to see if there are any conflict in flags.
667
-	if flags.Changed(flagPublishAdd) {
668
-		ports := flags.Lookup(flagPublishAdd).Value.(*opts.PortOpt).Value()
669 666
 
670
-		for _, port := range ports {
671
-			if v, ok := portSet[portConfigToString(&port)]; ok && v != port {
672
-				return fmt.Errorf("conflicting port mapping between %v:%v/%s and %v:%v/%s", port.PublishedPort, port.TargetPort, port.Protocol, v.PublishedPort, v.TargetPort, v.Protocol)
673
-			}
674
-			portSet[portConfigToString(&port)] = port
675
-		}
676
-	}
677
-
678
-	// Override previous PortConfig in service if there is any duplicate
667
+	// Build the current list of portConfig
679 668
 	for _, entry := range *portConfig {
680 669
 		if _, ok := portSet[portConfigToString(&entry)]; !ok {
681 670
 			portSet[portConfigToString(&entry)] = entry
682 671
 		}
683 672
 	}
684 673
 
685
-	toRemove := flags.Lookup(flagPublishRemove).Value.(*opts.PortOpt).Value()
686
-
687 674
 	newPorts := []swarm.PortConfig{}
675
+
676
+	// Clean current ports
677
+	toRemove := flags.Lookup(flagPublishRemove).Value.(*opts.PortOpt).Value()
688 678
 portLoop:
689 679
 	for _, port := range portSet {
690 680
 		for _, pConfig := range toRemove {
... ...
@@ -698,6 +680,23 @@ portLoop:
698 698
 		newPorts = append(newPorts, port)
699 699
 	}
700 700
 
701
+	// Check to see if there are any conflict in flags.
702
+	if flags.Changed(flagPublishAdd) {
703
+		ports := flags.Lookup(flagPublishAdd).Value.(*opts.PortOpt).Value()
704
+
705
+		for _, port := range ports {
706
+			if v, ok := portSet[portConfigToString(&port)]; ok {
707
+				if v != port {
708
+					fmt.Println("v", v)
709
+					return fmt.Errorf("conflicting port mapping between %v:%v/%s and %v:%v/%s", port.PublishedPort, port.TargetPort, port.Protocol, v.PublishedPort, v.TargetPort, v.Protocol)
710
+				}
711
+				continue
712
+			}
713
+			//portSet[portConfigToString(&port)] = port
714
+			newPorts = append(newPorts, port)
715
+		}
716
+	}
717
+
701 718
 	// Sort the PortConfig to avoid unnecessary updates
702 719
 	sort.Sort(byPortConfig(newPorts))
703 720
 	*portConfig = newPorts
... ...
@@ -220,28 +220,18 @@ func TestUpdatePorts(t *testing.T) {
220 220
 	assert.Equal(t, targetPorts[1], 1000)
221 221
 }
222 222
 
223
-func TestUpdatePortsDuplicateEntries(t *testing.T) {
223
+func TestUpdatePortsDuplicate(t *testing.T) {
224 224
 	// Test case for #25375
225 225
 	flags := newUpdateCommand(nil).Flags()
226 226
 	flags.Set("publish-add", "80:80")
227 227
 
228 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},
229
+		{
230
+			TargetPort:    80,
231
+			PublishedPort: 80,
232
+			Protocol:      swarm.PortConfigProtocolTCP,
233
+			PublishMode:   swarm.PortConfigPublishModeIngress,
234
+		},
245 235
 	}
246 236
 
247 237
 	err := updatePorts(flags, &portConfigs)
... ...
@@ -355,13 +345,19 @@ func TestUpdatePortsRmWithProtocol(t *testing.T) {
355 355
 	flags.Set("publish-rm", "82/udp")
356 356
 
357 357
 	portConfigs := []swarm.PortConfig{
358
-		{TargetPort: 80, PublishedPort: 8080, Protocol: swarm.PortConfigProtocolTCP},
358
+		{
359
+			TargetPort:    80,
360
+			PublishedPort: 8080,
361
+			Protocol:      swarm.PortConfigProtocolTCP,
362
+			PublishMode:   swarm.PortConfigPublishModeIngress,
363
+		},
359 364
 	}
360 365
 
361 366
 	err := updatePorts(flags, &portConfigs)
362 367
 	assert.Equal(t, err, nil)
363
-	assert.Equal(t, len(portConfigs), 1)
364
-	assert.Equal(t, portConfigs[0].TargetPort, uint32(82))
368
+	assert.Equal(t, len(portConfigs), 2)
369
+	assert.Equal(t, portConfigs[0].TargetPort, uint32(81))
370
+	assert.Equal(t, portConfigs[1].TargetPort, uint32(82))
365 371
 }
366 372
 
367 373
 // FIXME(vdemeester) port to opts.PortOpt
... ...
@@ -264,13 +264,13 @@ func (s *DockerSwarmSuite) TestSwarmPublishAdd(c *check.C) {
264 264
 		c.Assert(err, checker.IsNil, check.Commentf(out))
265 265
 		c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "")
266 266
 
267
-		out, err = d.CmdRetryOutOfSequence("service", "update", "--publish-add", tc.publishAdd[0], tc.name)
267
+		out, err = d.cmdRetryOutOfSequence("service", "update", "--publish-add", tc.publishAdd[0], tc.name)
268 268
 		c.Assert(err, checker.IsNil, check.Commentf(out))
269 269
 
270
-		out, err = d.CmdRetryOutOfSequence("service", "update", "--publish-add", tc.publishAdd[1], tc.name)
270
+		out, err = d.cmdRetryOutOfSequence("service", "update", "--publish-add", tc.publishAdd[1], tc.name)
271 271
 		c.Assert(err, checker.IsNil, check.Commentf(out))
272 272
 
273
-		out, err = d.CmdRetryOutOfSequence("service", "update", "--publish-add", tc.publishAdd[2], "--publish-add", tc.publishAdd[3], tc.name)
273
+		out, err = d.cmdRetryOutOfSequence("service", "update", "--publish-add", tc.publishAdd[2], "--publish-add", tc.publishAdd[3], tc.name)
274 274
 		c.Assert(err, checker.NotNil, check.Commentf(out))
275 275
 
276 276
 		out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.EndpointSpec.Ports }}", tc.name)
... ...
@@ -82,6 +82,14 @@ func (p *PortOpt) Set(value string) error {
82 82
 			return fmt.Errorf("missing mandatory field %q", portOptTargetPort)
83 83
 		}
84 84
 
85
+		if pConfig.PublishMode == "" {
86
+			pConfig.PublishMode = swarm.PortConfigPublishModeIngress
87
+		}
88
+
89
+		if pConfig.Protocol == "" {
90
+			pConfig.Protocol = swarm.PortConfigProtocolTCP
91
+		}
92
+
85 93
 		p.ports = append(p.ports, pConfig)
86 94
 	} else {
87 95
 		// short syntax
... ...
@@ -131,6 +139,7 @@ func ConvertPortToPortConfig(
131 131
 			Protocol:      swarm.PortConfigProtocol(strings.ToLower(port.Proto())),
132 132
 			TargetPort:    uint32(port.Int()),
133 133
 			PublishedPort: uint32(hostPort),
134
+			PublishMode:   swarm.PortConfigPublishModeIngress,
134 135
 		})
135 136
 	}
136 137
 	return ports
... ...
@@ -16,8 +16,9 @@ func TestPortOptValidSimpleSyntax(t *testing.T) {
16 16
 			value: "80",
17 17
 			expected: []swarm.PortConfig{
18 18
 				{
19
-					Protocol:   "tcp",
20
-					TargetPort: 80,
19
+					Protocol:    "tcp",
20
+					TargetPort:  80,
21
+					PublishMode: swarm.PortConfigPublishModeIngress,
21 22
 				},
22 23
 			},
23 24
 		},
... ...
@@ -28,6 +29,7 @@ func TestPortOptValidSimpleSyntax(t *testing.T) {
28 28
 					Protocol:      "tcp",
29 29
 					TargetPort:    8080,
30 30
 					PublishedPort: 80,
31
+					PublishMode:   swarm.PortConfigPublishModeIngress,
31 32
 				},
32 33
 			},
33 34
 		},
... ...
@@ -38,6 +40,7 @@ func TestPortOptValidSimpleSyntax(t *testing.T) {
38 38
 					Protocol:      "tcp",
39 39
 					TargetPort:    80,
40 40
 					PublishedPort: 8080,
41
+					PublishMode:   swarm.PortConfigPublishModeIngress,
41 42
 				},
42 43
 			},
43 44
 		},
... ...
@@ -48,6 +51,7 @@ func TestPortOptValidSimpleSyntax(t *testing.T) {
48 48
 					Protocol:      "udp",
49 49
 					TargetPort:    8080,
50 50
 					PublishedPort: 80,
51
+					PublishMode:   swarm.PortConfigPublishModeIngress,
51 52
 				},
52 53
 			},
53 54
 		},
... ...
@@ -58,11 +62,13 @@ func TestPortOptValidSimpleSyntax(t *testing.T) {
58 58
 					Protocol:      "tcp",
59 59
 					TargetPort:    8080,
60 60
 					PublishedPort: 80,
61
+					PublishMode:   swarm.PortConfigPublishModeIngress,
61 62
 				},
62 63
 				{
63 64
 					Protocol:      "tcp",
64 65
 					TargetPort:    8081,
65 66
 					PublishedPort: 81,
67
+					PublishMode:   swarm.PortConfigPublishModeIngress,
66 68
 				},
67 69
 			},
68 70
 		},
... ...
@@ -73,16 +79,19 @@ func TestPortOptValidSimpleSyntax(t *testing.T) {
73 73
 					Protocol:      "udp",
74 74
 					TargetPort:    8080,
75 75
 					PublishedPort: 80,
76
+					PublishMode:   swarm.PortConfigPublishModeIngress,
76 77
 				},
77 78
 				{
78 79
 					Protocol:      "udp",
79 80
 					TargetPort:    8081,
80 81
 					PublishedPort: 81,
82
+					PublishMode:   swarm.PortConfigPublishModeIngress,
81 83
 				},
82 84
 				{
83 85
 					Protocol:      "udp",
84 86
 					TargetPort:    8082,
85 87
 					PublishedPort: 82,
88
+					PublishMode:   swarm.PortConfigPublishModeIngress,
86 89
 				},
87 90
 			},
88 91
 		},
... ...
@@ -106,7 +115,9 @@ func TestPortOptValidComplexSyntax(t *testing.T) {
106 106
 			value: "target=80",
107 107
 			expected: []swarm.PortConfig{
108 108
 				{
109
-					TargetPort: 80,
109
+					TargetPort:  80,
110
+					Protocol:    "tcp",
111
+					PublishMode: swarm.PortConfigPublishModeIngress,
110 112
 				},
111 113
 			},
112 114
 		},
... ...
@@ -114,8 +125,9 @@ func TestPortOptValidComplexSyntax(t *testing.T) {
114 114
 			value: "target=80,protocol=tcp",
115 115
 			expected: []swarm.PortConfig{
116 116
 				{
117
-					Protocol:   "tcp",
118
-					TargetPort: 80,
117
+					Protocol:    "tcp",
118
+					TargetPort:  80,
119
+					PublishMode: swarm.PortConfigPublishModeIngress,
119 120
 				},
120 121
 			},
121 122
 		},
... ...
@@ -126,6 +138,7 @@ func TestPortOptValidComplexSyntax(t *testing.T) {
126 126
 					Protocol:      "tcp",
127 127
 					TargetPort:    80,
128 128
 					PublishedPort: 8080,
129
+					PublishMode:   swarm.PortConfigPublishModeIngress,
129 130
 				},
130 131
 			},
131 132
 		},
... ...
@@ -136,6 +149,7 @@ func TestPortOptValidComplexSyntax(t *testing.T) {
136 136
 					Protocol:      "tcp",
137 137
 					TargetPort:    8080,
138 138
 					PublishedPort: 80,
139
+					PublishMode:   swarm.PortConfigPublishModeIngress,
139 140
 				},
140 141
 			},
141 142
 		},
... ...
@@ -157,6 +171,7 @@ func TestPortOptValidComplexSyntax(t *testing.T) {
157 157
 					TargetPort:    80,
158 158
 					PublishedPort: 8080,
159 159
 					PublishMode:   "host",
160
+					Protocol:      "tcp",
160 161
 				},
161 162
 			},
162 163
 		},
... ...
@@ -167,6 +182,7 @@ func TestPortOptValidComplexSyntax(t *testing.T) {
167 167
 					TargetPort:    80,
168 168
 					PublishedPort: 8080,
169 169
 					PublishMode:   "ingress",
170
+					Protocol:      "tcp",
170 171
 				},
171 172
 			},
172 173
 		},