Skip to content

Commit 25fc4ca

Browse files
committed
setup ipv6 for nerdctl
Signed-off-by: fahed dorgaa <[email protected]>
1 parent 655eb5b commit 25fc4ca

File tree

3 files changed

+81
-37
lines changed

3 files changed

+81
-37
lines changed

pkg/portutil/portutil.go

+61-34
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,24 @@ import (
2525
"github.com/pkg/errors"
2626
)
2727

28-
func ParseFlagP(s string) (*gocni.PortMapping, error) {
28+
func splitParts(rawport string) (string, string, string) {
29+
parts := strings.Split(rawport, ":")
30+
n := len(parts)
31+
containerport := parts[n-1]
32+
33+
switch n {
34+
case 1:
35+
return "", "", containerport
36+
case 2:
37+
return "", parts[0], containerport
38+
case 3:
39+
return parts[0], parts[1], containerport
40+
default:
41+
return strings.Join(parts[:n-2], ":"), parts[n-2], containerport
42+
}
43+
}
44+
45+
func ParseFlagP(s string) ([]gocni.PortMapping, error) {
2946
proto := "tcp"
3047
splitBySlash := strings.Split(s, "/")
3148
switch len(splitBySlash) {
@@ -42,44 +59,54 @@ func ParseFlagP(s string) (*gocni.PortMapping, error) {
4259
return nil, errors.Errorf("failed to parse %q, unexpected slashes", s)
4360
}
4461

45-
res := &gocni.PortMapping{
62+
res := gocni.PortMapping{
4663
Protocol: proto,
47-
HostIP: "0.0.0.0",
4864
}
4965

50-
splitByColon := strings.Split(splitBySlash[0], ":")
51-
switch len(splitByColon) {
52-
case 1:
66+
multi_res := []gocni.PortMapping{}
67+
68+
ip, hostPort, containerPort := splitParts(splitBySlash[0])
69+
70+
if containerPort == "" {
71+
return nil, errors.Errorf("No port specified: %s<empty>", splitBySlash[0])
72+
}
73+
74+
if hostPort == "" {
5375
return nil, errors.Errorf("automatic host port assignment is not supported yet (FIXME)")
54-
case 2:
55-
i, err := strconv.Atoi(splitByColon[0])
56-
if err != nil {
57-
return nil, err
58-
}
59-
res.HostPort = int32(i)
60-
i, err = strconv.Atoi(splitByColon[1])
61-
if err != nil {
62-
return nil, err
63-
}
64-
res.ContainerPort = int32(i)
65-
return res, nil
66-
case 3:
67-
res.HostIP = splitByColon[0]
68-
if net.ParseIP(res.HostIP) == nil {
69-
return nil, errors.Errorf("invalid IP %q", res.HostIP)
70-
}
71-
i, err := strconv.Atoi(splitByColon[1])
72-
if err != nil {
73-
return nil, err
76+
}
77+
78+
i, err := strconv.Atoi(hostPort)
79+
if err != nil {
80+
return nil, err
81+
}
82+
res.HostPort = int32(i)
83+
84+
i, err = strconv.Atoi(containerPort)
85+
if err != nil {
86+
return nil, err
87+
}
88+
res.ContainerPort = int32(i)
89+
90+
if ip == "" {
91+
res.HostIP = "0.0.0.0"
92+
multi_res = append(multi_res, res)
93+
res.HostIP = "::"
94+
multi_res = append(multi_res, res)
95+
} else {
96+
if ip[0] == '[' {
97+
// Strip [] from IPV6 addresses
98+
rawIP, _, err := net.SplitHostPort(ip + ":")
99+
if err != nil {
100+
return nil, errors.Errorf("Invalid ip address %v: %s", ip, err)
101+
}
102+
ip = rawIP
74103
}
75-
res.HostPort = int32(i)
76-
i, err = strconv.Atoi(splitByColon[2])
77-
if err != nil {
78-
return nil, err
104+
105+
if net.ParseIP(ip) == nil {
106+
return nil, errors.Errorf("Invalid ip address: %s", ip)
79107
}
80-
res.ContainerPort = int32(i)
81-
return res, nil
82-
default:
83-
return nil, errors.Errorf("failed to parse %q, unexpected colons", s)
108+
res.HostIP = ip
109+
multi_res = append(multi_res, res)
84110
}
111+
return multi_res, nil
85112
}

run.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ func runAction(clicontext *cli.Context) error {
328328
portSlice := strutil.DedupeStrSlice(clicontext.StringSlice("p"))
329329
netSlice := strutil.DedupeStrSlice(clicontext.StringSlice("net"))
330330

331-
ports := make([]gocni.PortMapping, len(portSlice))
331+
ports := make([]gocni.PortMapping, 0)
332332
if len(netSlice) != 1 {
333333
return errors.New("currently, number of networks must be 1")
334334
}
@@ -369,12 +369,12 @@ func runAction(clicontext *cli.Context) error {
369369
return err
370370
}
371371
opts = append(opts, withCustomResolvConf(resolvConfPath), withCustomHosts(etcHostsPath))
372-
for i, p := range portSlice {
372+
for _, p := range portSlice {
373373
pm, err := portutil.ParseFlagP(p)
374374
if err != nil {
375375
return err
376376
}
377-
ports[i] = *pm
377+
ports = append(ports, pm...)
378378
}
379379
}
380380

run_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,20 @@ func TestRunExitCode(t *testing.T) {
137137
assert.Equal(base.T, "exited", inspect123.State.Status)
138138
assert.Equal(base.T, 123, inspect123.State.ExitCode)
139139
}
140+
141+
func TestRunPortMappingWithEmptyIP(t *testing.T) {
142+
base := testutil.NewBase(t)
143+
defer base.Cmd("rm", "-f", "testPortMappingWithEmptyIP").Run()
144+
const expected = `80/tcp -> 0.0.0.0:80
145+
80/tcp -> :::80`
146+
base.Cmd("run", "-d", "--name", "testPortMappingWithEmptyIP", "-p", "80:80", testutil.NginxAlpineImage).Run()
147+
base.Cmd("port", "testPortMappingWithEmptyIP").AssertOut(expected)
148+
}
149+
150+
func TestRunPortMappingWithIPv6(t *testing.T) {
151+
base := testutil.NewBase(t)
152+
defer base.Cmd("rm", "-f", "testPortMappingWithIPv6").Run()
153+
base.Cmd("run", "-d", "--name", "testPortMappingWithIPv6", "-p", ":::80:80", testutil.NginxAlpineImage).Run()
154+
const expected = `80/tcp -> :::80`
155+
base.Cmd("port", "testPortMappingWithIPv6").AssertOut(expected)
156+
}

0 commit comments

Comments
 (0)