Skip to content

Commit 99d3447

Browse files
committed
setup ipv6 for nerdctl
Signed-off-by: fahed dorgaa <[email protected]>
1 parent e93fc90 commit 99d3447

File tree

6 files changed

+115
-42
lines changed

6 files changed

+115
-42
lines changed

.github/workflows/test.yml

+5
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ jobs:
9898
- uses: actions/checkout@v2
9999
with:
100100
fetch-depth: 1
101+
- name: "Enable Ipv6 on Docker"
102+
run: |
103+
sudo apt-get --no-install-recommends install moreutils
104+
jq '. |= . + { "ipv6": true, "fixed-cidr-v6": "fd00::/64" }' /etc/docker/daemon.json | sudo sponge /etc/docker/daemon.json
105+
sudo systemctl restart docker.service
101106
- name: "Ensure that the test suite is compatible with Docker"
102107
run: go test -v -exec sudo -test.target=docker -test.kill-daemon .
103108

go.mod

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ require (
2828
github.com/rootless-containers/rootlesskit v0.14.1
2929
github.com/sirupsen/logrus v1.8.1
3030
github.com/urfave/cli/v2 v2.3.0
31-
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9
31+
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83
3232
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
33-
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
33+
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46
3434
gotest.tools/v3 v3.0.3
3535
)

go.sum

+4-3
Original file line numberDiff line numberDiff line change
@@ -640,8 +640,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
640640
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
641641
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
642642
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
643-
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9 h1:phUcVbl53swtrUN8kQEXFhUxPlIlWyBfKmidCu7P95o=
644-
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
643+
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
644+
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
645645
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
646646
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
647647
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -789,8 +789,9 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
789789
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
790790
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
791791
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
792-
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
793792
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
793+
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46 h1:V066+OYJ66oTjnhm4Yrn7SXIwSCiDQJxpBxmvqb1N1c=
794+
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
794795
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
795796
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
796797
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

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
}

port_test.go

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package main
18+
19+
import (
20+
"testing"
21+
22+
"github.com/containerd/nerdctl/pkg/testutil"
23+
)
24+
25+
func TestRunPortMappingWithEmptyIP(t *testing.T) {
26+
base := testutil.NewBase(t)
27+
defer base.Cmd("rm", "-f", "testPortMappingWithEmptyIP").Run()
28+
const expected = `80/tcp -> 0.0.0.0:80
29+
80/tcp -> :::80`
30+
base.Cmd("run", "-d", "--name", "testPortMappingWithEmptyIP", "-p", "80:80", testutil.NginxAlpineImage).Run()
31+
base.Cmd("port", "testPortMappingWithEmptyIP").AssertOut(expected)
32+
}
33+
34+
func TestRunPortMappingWithIPv6(t *testing.T) {
35+
base := testutil.NewBase(t)
36+
defer base.Cmd("rm", "-f", "testPortMappingWithIPv6").Run()
37+
base.Cmd("run", "-d", "--name", "testPortMappingWithIPv6", "-p", "[::]:80:80", testutil.NginxAlpineImage).Run()
38+
const expected = `80/tcp -> :::80`
39+
base.Cmd("port", "testPortMappingWithIPv6").AssertOut(expected)
40+
}

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

0 commit comments

Comments
 (0)