Merge pull request #2251 from thaJeztah/1962-fix-port-bug

Convert ports before parsing.
This commit is contained in:
Silvin Lubecki 2020-01-16 11:26:44 +01:00 committed by GitHub
commit 0ab564b1c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 58 additions and 31 deletions

View File

@ -379,23 +379,20 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
} }
publishOpts := copts.publish.GetAll() publishOpts := copts.publish.GetAll()
var ports map[nat.Port]struct{} var (
var portBindings map[nat.Port][]nat.PortBinding ports map[nat.Port]struct{}
portBindings map[nat.Port][]nat.PortBinding
convertedOpts []string
)
ports, portBindings, err = nat.ParsePortSpecs(publishOpts) convertedOpts, err = convertToStandardNotation(publishOpts)
// If simple port parsing fails try to parse as long format
if err != nil { if err != nil {
publishOpts, err = parsePortOpts(publishOpts) return nil, err
if err != nil { }
return nil, err
}
ports, portBindings, err = nat.ParsePortSpecs(publishOpts) ports, portBindings, err = nat.ParsePortSpecs(convertedOpts)
if err != nil {
if err != nil { return nil, err
return nil, err
}
} }
// Merge in exposed ports to the map of published ports // Merge in exposed ports to the map of published ports
@ -403,10 +400,11 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
if strings.Contains(e, ":") { if strings.Contains(e, ":") {
return nil, errors.Errorf("invalid port format for --expose: %s", e) return nil, errors.Errorf("invalid port format for --expose: %s", e)
} }
//support two formats for expose, original format <portnum>/[<proto>] or <startport-endport>/[<proto>] // support two formats for expose, original format <portnum>/[<proto>]
// or <startport-endport>/[<proto>]
proto, port := nat.SplitProtoPort(e) proto, port := nat.SplitProtoPort(e)
//parse the start and end port and create a sequence of ports to expose // parse the start and end port and create a sequence of ports to expose
//if expose a port, the start and end port are the same // if expose a port, the start and end port are the same
start, end, err := nat.ParsePortRange(port) start, end, err := nat.ParsePortRange(port)
if err != nil { if err != nil {
return nil, errors.Errorf("invalid range format for --expose: %s, error: %s", e, err) return nil, errors.Errorf("invalid range format for --expose: %s, error: %s", e, err)
@ -796,19 +794,23 @@ func parseNetworkAttachmentOpt(ep opts.NetworkAttachmentOpts) (*networktypes.End
return epConfig, nil return epConfig, nil
} }
func parsePortOpts(publishOpts []string) ([]string, error) { func convertToStandardNotation(ports []string) ([]string, error) {
optsList := []string{} optsList := []string{}
for _, publish := range publishOpts { for _, publish := range ports {
params := map[string]string{"protocol": "tcp"} if strings.Contains(publish, "=") {
for _, param := range strings.Split(publish, ",") { params := map[string]string{"protocol": "tcp"}
opt := strings.Split(param, "=") for _, param := range strings.Split(publish, ",") {
if len(opt) < 2 { opt := strings.Split(param, "=")
return optsList, errors.Errorf("invalid publish opts format (should be name=value but got '%s')", param) if len(opt) < 2 {
} return optsList, errors.Errorf("invalid publish opts format (should be name=value but got '%s')", param)
}
params[opt[0]] = opt[1] params[opt[0]] = opt[1]
}
optsList = append(optsList, fmt.Sprintf("%s:%s/%s", params["published"], params["target"], params["protocol"]))
} else {
optsList = append(optsList, publish)
} }
optsList = append(optsList, fmt.Sprintf("%s:%s/%s", params["published"], params["target"], params["protocol"]))
} }
return optsList, nil return optsList, nil
} }

View File

@ -873,8 +873,33 @@ func TestParseSystemPaths(t *testing.T) {
} }
} }
func TestParsePortOpts(t *testing.T) { func TestConvertToStandardNotation(t *testing.T) {
parsed, err := parsePortOpts([]string{"published=1500,target=200", "target=80,published=90"}) valid := map[string][]string{
assert.NilError(t, err) "20:10/tcp": {"target=10,published=20"},
assert.DeepEqual(t, []string{"1500:200/tcp", "90:80/tcp"}, parsed) "40:30": {"40:30"},
"20:20 80:4444": {"20:20", "80:4444"},
"1500:2500/tcp 1400:1300": {"target=2500,published=1500", "1400:1300"},
"1500:200/tcp 90:80/tcp": {"published=1500,target=200", "target=80,published=90"},
}
invalid := [][]string{
{"published=1500,target:444"},
{"published=1500,444"},
{"published=1500,target,444"},
}
for key, ports := range valid {
convertedPorts, err := convertToStandardNotation(ports)
if err != nil {
assert.NilError(t, err)
}
assert.DeepEqual(t, strings.Split(key, " "), convertedPorts)
}
for _, ports := range invalid {
if _, err := convertToStandardNotation(ports); err == nil {
t.Fatalf("ConvertToStandardNotation(`%q`) should have failed conversion", ports)
}
}
} }