Skip to content

Commit aa4ecd1

Browse files
committedFeb 7, 2017
Make sure we validate simple syntax on service commands
We ignored errors for simple syntax in `PortOpt` (missed that in the previous migration of this code). This make sure we don't ignore `nat.Parse` errors. Test has been migrate too (errors are not exactly the same as before though -_-) Signed-off-by: Vincent Demeester <[email protected]>
1 parent 191719e commit aa4ecd1

File tree

5 files changed

+48
-56
lines changed

5 files changed

+48
-56
lines changed
 

‎cli/command/service/opts.go

-12
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"github.com/docker/docker/api/types/swarm"
1111
"github.com/docker/docker/opts"
1212
runconfigopts "github.com/docker/docker/runconfig/opts"
13-
"github.com/docker/go-connections/nat"
1413
"github.com/spf13/cobra"
1514
)
1615

@@ -244,17 +243,6 @@ func (opts *healthCheckOptions) toHealthConfig() (*container.HealthConfig, error
244243
return healthConfig, nil
245244
}
246245

247-
// ValidatePort validates a string is in the expected format for a port definition
248-
func ValidatePort(value string) (string, error) {
249-
portMappings, err := nat.ParsePortSpec(value)
250-
for _, portMapping := range portMappings {
251-
if portMapping.Binding.HostIP != "" {
252-
return "", fmt.Errorf("HostIP is not supported by a service.")
253-
}
254-
}
255-
return value, err
256-
}
257-
258246
// convertExtraHostsToSwarmHosts converts an array of extra hosts in cli
259247
// <host>:<ip>
260248
// into a swarmkit host format:

‎cli/command/service/update.go

-18
Original file line numberDiff line numberDiff line change
@@ -663,24 +663,6 @@ func portConfigToString(portConfig *swarm.PortConfig) string {
663663
return fmt.Sprintf("%v:%v/%s/%s", portConfig.PublishedPort, portConfig.TargetPort, protocol, mode)
664664
}
665665

666-
// FIXME(vdemeester) port to opts.PortOpt
667-
// This validation is only used for `--publish-rm`.
668-
// The `--publish-rm` takes:
669-
// <TargetPort>[/<Protocol>] (e.g., 80, 80/tcp, 53/udp)
670-
func validatePublishRemove(val string) (string, error) {
671-
proto, port := nat.SplitProtoPort(val)
672-
if proto != "tcp" && proto != "udp" {
673-
return "", fmt.Errorf("invalid protocol '%s' for %s", proto, val)
674-
}
675-
if strings.Contains(port, ":") {
676-
return "", fmt.Errorf("invalid port format: '%s', should be <TargetPort>[/<Protocol>] (e.g., 80, 80/tcp, 53/udp)", port)
677-
}
678-
if _, err := nat.ParsePort(port); err != nil {
679-
return "", err
680-
}
681-
return val, nil
682-
}
683-
684666
func updatePorts(flags *pflag.FlagSet, portConfig *[]swarm.PortConfig) error {
685667
// The key of the map is `port/protocol`, e.g., `80/tcp`
686668
portSet := map[string]swarm.PortConfig{}

‎cli/command/service/update_test.go

-23
Original file line numberDiff line numberDiff line change
@@ -362,29 +362,6 @@ func TestUpdatePortsRmWithProtocol(t *testing.T) {
362362
assert.Equal(t, portConfigs[1].TargetPort, uint32(82))
363363
}
364364

365-
// FIXME(vdemeester) port to opts.PortOpt
366-
func TestValidatePort(t *testing.T) {
367-
validPorts := []string{"80/tcp", "80", "80/udp"}
368-
invalidPorts := map[string]string{
369-
"9999999": "out of range",
370-
"80:80/tcp": "invalid port format",
371-
"53:53/udp": "invalid port format",
372-
"80:80": "invalid port format",
373-
"80/xyz": "invalid protocol",
374-
"tcp": "invalid syntax",
375-
"udp": "invalid syntax",
376-
"": "invalid protocol",
377-
}
378-
for _, port := range validPorts {
379-
_, err := validatePublishRemove(port)
380-
assert.Equal(t, err, nil)
381-
}
382-
for port, e := range invalidPorts {
383-
_, err := validatePublishRemove(port)
384-
assert.Error(t, err, e)
385-
}
386-
}
387-
388365
type secretAPIClientMock struct {
389366
listResult []swarm.Secret
390367
}

‎opts/port.go

+12-3
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,20 @@ func (p *PortOpt) Set(value string) error {
9494
} else {
9595
// short syntax
9696
portConfigs := []swarm.PortConfig{}
97-
// We can ignore errors because the format was already validated by ValidatePort
98-
ports, portBindings, _ := nat.ParsePortSpecs([]string{value})
97+
ports, portBindingMap, err := nat.ParsePortSpecs([]string{value})
98+
if err != nil {
99+
return err
100+
}
101+
for _, portBindings := range portBindingMap {
102+
for _, portBinding := range portBindings {
103+
if portBinding.HostIP != "" {
104+
return fmt.Errorf("HostIP is not supported.")
105+
}
106+
}
107+
}
99108

100109
for port := range ports {
101-
portConfig, err := ConvertPortToPortConfig(port, portBindings)
110+
portConfig, err := ConvertPortToPortConfig(port, portBindingMap)
102111
if err != nil {
103112
return err
104113
}

‎opts/port_test.go

+36
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,42 @@ func TestPortOptInvalidComplexSyntax(t *testing.T) {
245245
}
246246
}
247247

248+
func TestPortOptInvalidSimpleSyntax(t *testing.T) {
249+
testCases := []struct {
250+
value string
251+
expectedError string
252+
}{
253+
{
254+
value: "9999999",
255+
expectedError: "Invalid containerPort: 9999999",
256+
},
257+
{
258+
value: "80/xyz",
259+
expectedError: "Invalid proto: xyz",
260+
},
261+
{
262+
value: "tcp",
263+
expectedError: "Invalid containerPort: tcp",
264+
},
265+
{
266+
value: "udp",
267+
expectedError: "Invalid containerPort: udp",
268+
},
269+
{
270+
value: "",
271+
expectedError: "No port specified",
272+
},
273+
{
274+
value: "1.1.1.1:80:80",
275+
expectedError: "HostIP is not supported",
276+
},
277+
}
278+
for _, tc := range testCases {
279+
var port PortOpt
280+
assert.Error(t, port.Set(tc.value), tc.expectedError)
281+
}
282+
}
283+
248284
func assertContains(t *testing.T, portConfigs []swarm.PortConfig, expected swarm.PortConfig) {
249285
var contains = false
250286
for _, portConfig := range portConfigs {

0 commit comments

Comments
 (0)