This facilitates the refactoring of commands.go
Docker-DCO-1.1-Signed-off-by: Solomon Hykes <solomon@docker.com> (github: shykes)
| ... | ... |
@@ -12,6 +12,7 @@ import ( |
| 12 | 12 |
"github.com/dotcloud/docker/archive" |
| 13 | 13 |
"github.com/dotcloud/docker/auth" |
| 14 | 14 |
"github.com/dotcloud/docker/engine" |
| 15 |
+ "github.com/dotcloud/docker/nat" |
|
| 15 | 16 |
flag "github.com/dotcloud/docker/pkg/mflag" |
| 16 | 17 |
"github.com/dotcloud/docker/pkg/sysinfo" |
| 17 | 18 |
"github.com/dotcloud/docker/pkg/term" |
| ... | ... |
@@ -799,7 +800,7 @@ func (cli *DockerCli) CmdPort(args ...string) error {
|
| 799 | 799 |
return err |
| 800 | 800 |
} |
| 801 | 801 |
|
| 802 |
- if frontends, exists := out.NetworkSettings.Ports[Port(port+"/"+proto)]; exists && frontends != nil {
|
|
| 802 |
+ if frontends, exists := out.NetworkSettings.Ports[nat.Port(port+"/"+proto)]; exists && frontends != nil {
|
|
| 803 | 803 |
for _, frontend := range frontends {
|
| 804 | 804 |
fmt.Fprintf(cli.out, "%s:%s\n", frontend.HostIp, frontend.HostPort) |
| 805 | 805 |
} |
| ... | ... |
@@ -1792,7 +1793,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf |
| 1792 | 1792 |
cmd.Var(&flLinks, []string{"#link", "-link"}, "Add link to another container (name:alias)")
|
| 1793 | 1793 |
cmd.Var(&flEnv, []string{"e", "-env"}, "Set environment variables")
|
| 1794 | 1794 |
|
| 1795 |
- cmd.Var(&flPublish, []string{"p", "-publish"}, fmt.Sprintf("Publish a container's port to the host (format: %s) (use 'docker port' to see the actual mapping)", PortSpecTemplateFormat))
|
|
| 1795 |
+ cmd.Var(&flPublish, []string{"p", "-publish"}, fmt.Sprintf("Publish a container's port to the host (format: %s) (use 'docker port' to see the actual mapping)", nat.PortSpecTemplateFormat))
|
|
| 1796 | 1796 |
cmd.Var(&flExpose, []string{"#expose", "-expose"}, "Expose a port from the container without publishing it to your host")
|
| 1797 | 1797 |
cmd.Var(&flDns, []string{"#dns", "-dns"}, "Set custom dns servers")
|
| 1798 | 1798 |
cmd.Var(&flVolumesFrom, []string{"#volumes-from", "-volumes-from"}, "Mount volumes from the specified container(s)")
|
| ... | ... |
@@ -1885,7 +1886,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf |
| 1885 | 1885 |
domainname = parts[1] |
| 1886 | 1886 |
} |
| 1887 | 1887 |
|
| 1888 |
- ports, portBindings, err := parsePortSpecs(flPublish.GetAll()) |
|
| 1888 |
+ ports, portBindings, err := nat.ParsePortSpecs(flPublish.GetAll()) |
|
| 1889 | 1889 |
if err != nil {
|
| 1890 | 1890 |
return nil, nil, cmd, err |
| 1891 | 1891 |
} |
| ... | ... |
@@ -1895,7 +1896,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf |
| 1895 | 1895 |
if strings.Contains(e, ":") {
|
| 1896 | 1896 |
return nil, nil, cmd, fmt.Errorf("Invalid port format for --expose: %s", e)
|
| 1897 | 1897 |
} |
| 1898 |
- p := NewPort(splitProtoPort(e)) |
|
| 1898 |
+ p := nat.NewPort(nat.SplitProtoPort(e)) |
|
| 1899 | 1899 |
if _, exists := ports[p]; !exists {
|
| 1900 | 1900 |
ports[p] = struct{}{}
|
| 1901 | 1901 |
} |
| ... | ... |
@@ -1,6 +1,7 @@ |
| 1 | 1 |
package docker |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "github.com/dotcloud/docker/nat" |
|
| 4 | 5 |
"testing" |
| 5 | 6 |
) |
| 6 | 7 |
|
| ... | ... |
@@ -125,7 +126,7 @@ func TestMergeConfig(t *testing.T) {
|
| 125 | 125 |
t.Fatalf("Expected VolumesFrom to be 1111, found %s", configUser.VolumesFrom)
|
| 126 | 126 |
} |
| 127 | 127 |
|
| 128 |
- ports, _, err := parsePortSpecs([]string{"0000"})
|
|
| 128 |
+ ports, _, err := nat.ParsePortSpecs([]string{"0000"})
|
|
| 129 | 129 |
if err != nil {
|
| 130 | 130 |
t.Error(err) |
| 131 | 131 |
} |
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
"github.com/dotcloud/docker/engine" |
| 9 | 9 |
"github.com/dotcloud/docker/execdriver" |
| 10 | 10 |
"github.com/dotcloud/docker/graphdriver" |
| 11 |
+ "github.com/dotcloud/docker/nat" |
|
| 11 | 12 |
"github.com/dotcloud/docker/pkg/mount" |
| 12 | 13 |
"github.com/dotcloud/docker/pkg/term" |
| 13 | 14 |
"github.com/dotcloud/docker/utils" |
| ... | ... |
@@ -86,7 +87,7 @@ type Config struct {
|
| 86 | 86 |
AttachStdout bool |
| 87 | 87 |
AttachStderr bool |
| 88 | 88 |
PortSpecs []string // Deprecated - Can be in the format of 8080/tcp |
| 89 |
- ExposedPorts map[Port]struct{}
|
|
| 89 |
+ ExposedPorts map[nat.Port]struct{}
|
|
| 90 | 90 |
Tty bool // Attach standard streams to a tty, including stdin if it is not closed. |
| 91 | 91 |
OpenStdin bool // Open stdin |
| 92 | 92 |
StdinOnce bool // If true, close stdin after the 1 attached client disconnects. |
| ... | ... |
@@ -147,7 +148,7 @@ type HostConfig struct {
|
| 147 | 147 |
ContainerIDFile string |
| 148 | 148 |
LxcConf []KeyValuePair |
| 149 | 149 |
Privileged bool |
| 150 |
- PortBindings map[Port][]PortBinding |
|
| 150 |
+ PortBindings nat.PortMap |
|
| 151 | 151 |
Links []string |
| 152 | 152 |
PublishAllPorts bool |
| 153 | 153 |
} |
| ... | ... |
@@ -189,38 +190,7 @@ type KeyValuePair struct {
|
| 189 | 189 |
Value string |
| 190 | 190 |
} |
| 191 | 191 |
|
| 192 |
-type PortBinding struct {
|
|
| 193 |
- HostIp string |
|
| 194 |
- HostPort string |
|
| 195 |
-} |
|
| 196 |
- |
|
| 197 |
-// 80/tcp |
|
| 198 |
-type Port string |
|
| 199 |
- |
|
| 200 |
-func (p Port) Proto() string {
|
|
| 201 |
- parts := strings.Split(string(p), "/") |
|
| 202 |
- if len(parts) == 1 {
|
|
| 203 |
- return "tcp" |
|
| 204 |
- } |
|
| 205 |
- return parts[1] |
|
| 206 |
-} |
|
| 207 |
- |
|
| 208 |
-func (p Port) Port() string {
|
|
| 209 |
- return strings.Split(string(p), "/")[0] |
|
| 210 |
-} |
|
| 211 |
- |
|
| 212 |
-func (p Port) Int() int {
|
|
| 213 |
- i, err := parsePort(p.Port()) |
|
| 214 |
- if err != nil {
|
|
| 215 |
- panic(err) |
|
| 216 |
- } |
|
| 217 |
- return i |
|
| 218 |
-} |
|
| 219 |
- |
|
| 220 |
-func NewPort(proto, port string) Port {
|
|
| 221 |
- return Port(fmt.Sprintf("%s/%s", port, proto))
|
|
| 222 |
-} |
|
| 223 |
- |
|
| 192 |
+// FIXME: move deprecated port stuff to nat to clean up the core. |
|
| 224 | 193 |
type PortMapping map[string]string // Deprecated |
| 225 | 194 |
|
| 226 | 195 |
type NetworkSettings struct {
|
| ... | ... |
@@ -229,13 +199,13 @@ type NetworkSettings struct {
|
| 229 | 229 |
Gateway string |
| 230 | 230 |
Bridge string |
| 231 | 231 |
PortMapping map[string]PortMapping // Deprecated |
| 232 |
- Ports map[Port][]PortBinding |
|
| 232 |
+ Ports nat.PortMap |
|
| 233 | 233 |
} |
| 234 | 234 |
|
| 235 | 235 |
func (settings *NetworkSettings) PortMappingAPI() *engine.Table {
|
| 236 | 236 |
var outs = engine.NewTable("", 0)
|
| 237 | 237 |
for port, bindings := range settings.Ports {
|
| 238 |
- p, _ := parsePort(port.Port()) |
|
| 238 |
+ p, _ := nat.ParsePort(port.Port()) |
|
| 239 | 239 |
if len(bindings) == 0 {
|
| 240 | 240 |
out := &engine.Env{}
|
| 241 | 241 |
out.SetInt("PublicPort", p)
|
| ... | ... |
@@ -245,7 +215,7 @@ func (settings *NetworkSettings) PortMappingAPI() *engine.Table {
|
| 245 | 245 |
} |
| 246 | 246 |
for _, binding := range bindings {
|
| 247 | 247 |
out := &engine.Env{}
|
| 248 |
- h, _ := parsePort(binding.HostPort) |
|
| 248 |
+ h, _ := nat.ParsePort(binding.HostPort) |
|
| 249 | 249 |
out.SetInt("PrivatePort", p)
|
| 250 | 250 |
out.SetInt("PublicPort", h)
|
| 251 | 251 |
out.Set("Type", port.Proto())
|
| ... | ... |
@@ -1152,8 +1122,8 @@ func (container *Container) allocateNetwork() error {
|
| 1152 | 1152 |
} |
| 1153 | 1153 |
|
| 1154 | 1154 |
var ( |
| 1155 |
- portSpecs = make(map[Port]struct{})
|
|
| 1156 |
- bindings = make(map[Port][]PortBinding) |
|
| 1155 |
+ portSpecs = make(nat.PortSet) |
|
| 1156 |
+ bindings = make(nat.PortMap) |
|
| 1157 | 1157 |
) |
| 1158 | 1158 |
|
| 1159 | 1159 |
if !container.State.IsGhost() {
|
| ... | ... |
@@ -1177,7 +1147,7 @@ func (container *Container) allocateNetwork() error {
|
| 1177 | 1177 |
for port := range portSpecs {
|
| 1178 | 1178 |
binding := bindings[port] |
| 1179 | 1179 |
if container.hostConfig.PublishAllPorts && len(binding) == 0 {
|
| 1180 |
- binding = append(binding, PortBinding{})
|
|
| 1180 |
+ binding = append(binding, nat.PortBinding{})
|
|
| 1181 | 1181 |
} |
| 1182 | 1182 |
|
| 1183 | 1183 |
for i := 0; i < len(binding); i++ {
|
| ... | ... |
@@ -1593,7 +1563,7 @@ func (container *Container) Copy(resource string) (archive.Archive, error) {
|
| 1593 | 1593 |
} |
| 1594 | 1594 |
|
| 1595 | 1595 |
// Returns true if the container exposes a certain port |
| 1596 |
-func (container *Container) Exposes(p Port) bool {
|
|
| 1596 |
+func (container *Container) Exposes(p nat.Port) bool {
|
|
| 1597 | 1597 |
_, exists := container.Config.ExposedPorts[p] |
| 1598 | 1598 |
return exists |
| 1599 | 1599 |
} |
| ... | ... |
@@ -1,6 +1,7 @@ |
| 1 | 1 |
package docker |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "github.com/dotcloud/docker/nat" |
|
| 4 | 5 |
"testing" |
| 5 | 6 |
) |
| 6 | 7 |
|
| ... | ... |
@@ -22,7 +23,7 @@ func TestParseLxcConfOpt(t *testing.T) {
|
| 22 | 22 |
} |
| 23 | 23 |
|
| 24 | 24 |
func TestParseNetworkOptsPrivateOnly(t *testing.T) {
|
| 25 |
- ports, bindings, err := parsePortSpecs([]string{"192.168.1.100::80"})
|
|
| 25 |
+ ports, bindings, err := nat.ParsePortSpecs([]string{"192.168.1.100::80"})
|
|
| 26 | 26 |
if err != nil {
|
| 27 | 27 |
t.Fatal(err) |
| 28 | 28 |
} |
| ... | ... |
@@ -64,7 +65,7 @@ func TestParseNetworkOptsPrivateOnly(t *testing.T) {
|
| 64 | 64 |
} |
| 65 | 65 |
|
| 66 | 66 |
func TestParseNetworkOptsPublic(t *testing.T) {
|
| 67 |
- ports, bindings, err := parsePortSpecs([]string{"192.168.1.100:8080:80"})
|
|
| 67 |
+ ports, bindings, err := nat.ParsePortSpecs([]string{"192.168.1.100:8080:80"})
|
|
| 68 | 68 |
if err != nil {
|
| 69 | 69 |
t.Fatal(err) |
| 70 | 70 |
} |
| ... | ... |
@@ -106,7 +107,7 @@ func TestParseNetworkOptsPublic(t *testing.T) {
|
| 106 | 106 |
} |
| 107 | 107 |
|
| 108 | 108 |
func TestParseNetworkOptsUdp(t *testing.T) {
|
| 109 |
- ports, bindings, err := parsePortSpecs([]string{"192.168.1.100::6000/udp"})
|
|
| 109 |
+ ports, bindings, err := nat.ParsePortSpecs([]string{"192.168.1.100::6000/udp"})
|
|
| 110 | 110 |
if err != nil {
|
| 111 | 111 |
t.Fatal(err) |
| 112 | 112 |
} |
| ... | ... |
@@ -5,6 +5,7 @@ import ( |
| 5 | 5 |
"fmt" |
| 6 | 6 |
"github.com/dotcloud/docker" |
| 7 | 7 |
"github.com/dotcloud/docker/engine" |
| 8 |
+ "github.com/dotcloud/docker/nat" |
|
| 8 | 9 |
"github.com/dotcloud/docker/sysinit" |
| 9 | 10 |
"github.com/dotcloud/docker/utils" |
| 10 | 11 |
"io" |
| ... | ... |
@@ -368,7 +369,7 @@ func startEchoServerContainer(t *testing.T, proto string) (*docker.Runtime, *doc |
| 368 | 368 |
eng = NewTestEngine(t) |
| 369 | 369 |
runtime = mkRuntimeFromEngine(eng, t) |
| 370 | 370 |
port = 5554 |
| 371 |
- p docker.Port |
|
| 371 |
+ p nat.Port |
|
| 372 | 372 |
) |
| 373 | 373 |
defer func() {
|
| 374 | 374 |
if err != nil {
|
| ... | ... |
@@ -387,8 +388,8 @@ func startEchoServerContainer(t *testing.T, proto string) (*docker.Runtime, *doc |
| 387 | 387 |
} else {
|
| 388 | 388 |
t.Fatal(fmt.Errorf("Unknown protocol %v", proto))
|
| 389 | 389 |
} |
| 390 |
- ep := make(map[docker.Port]struct{}, 1)
|
|
| 391 |
- p = docker.Port(fmt.Sprintf("%s/%s", strPort, proto))
|
|
| 390 |
+ ep := make(map[nat.Port]struct{}, 1)
|
|
| 391 |
+ p = nat.Port(fmt.Sprintf("%s/%s", strPort, proto))
|
|
| 392 | 392 |
ep[p] = struct{}{}
|
| 393 | 393 |
|
| 394 | 394 |
jobCreate := eng.Job("create")
|
| ... | ... |
@@ -411,8 +412,8 @@ func startEchoServerContainer(t *testing.T, proto string) (*docker.Runtime, *doc |
| 411 | 411 |
} |
| 412 | 412 |
|
| 413 | 413 |
jobStart := eng.Job("start", id)
|
| 414 |
- portBindings := make(map[docker.Port][]docker.PortBinding) |
|
| 415 |
- portBindings[p] = []docker.PortBinding{
|
|
| 414 |
+ portBindings := make(map[nat.Port][]nat.PortBinding) |
|
| 415 |
+ portBindings[p] = []nat.PortBinding{
|
|
| 416 | 416 |
{},
|
| 417 | 417 |
} |
| 418 | 418 |
if err := jobStart.SetenvJson("PortsBindings", portBindings); err != nil {
|
| ... | ... |
@@ -3,6 +3,7 @@ package docker |
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"github.com/dotcloud/docker/engine" |
| 6 |
+ "github.com/dotcloud/docker/nat" |
|
| 6 | 7 |
"path" |
| 7 | 8 |
"strings" |
| 8 | 9 |
) |
| ... | ... |
@@ -12,7 +13,7 @@ type Link struct {
|
| 12 | 12 |
ChildIP string |
| 13 | 13 |
Name string |
| 14 | 14 |
ChildEnvironment []string |
| 15 |
- Ports []Port |
|
| 15 |
+ Ports []nat.Port |
|
| 16 | 16 |
IsEnabled bool |
| 17 | 17 |
eng *engine.Engine |
| 18 | 18 |
} |
| ... | ... |
@@ -25,7 +26,7 @@ func NewLink(parent, child *Container, name string, eng *engine.Engine) (*Link, |
| 25 | 25 |
return nil, fmt.Errorf("Cannot link to a non running container: %s AS %s", child.Name, name)
|
| 26 | 26 |
} |
| 27 | 27 |
|
| 28 |
- ports := make([]Port, len(child.Config.ExposedPorts)) |
|
| 28 |
+ ports := make([]nat.Port, len(child.Config.ExposedPorts)) |
|
| 29 | 29 |
var i int |
| 30 | 30 |
for p := range child.Config.ExposedPorts {
|
| 31 | 31 |
ports[i] = p |
| ... | ... |
@@ -85,14 +86,14 @@ func (l *Link) ToEnv() []string {
|
| 85 | 85 |
} |
| 86 | 86 |
|
| 87 | 87 |
// Default port rules |
| 88 |
-func (l *Link) getDefaultPort() *Port {
|
|
| 89 |
- var p Port |
|
| 88 |
+func (l *Link) getDefaultPort() *nat.Port {
|
|
| 89 |
+ var p nat.Port |
|
| 90 | 90 |
i := len(l.Ports) |
| 91 | 91 |
|
| 92 | 92 |
if i == 0 {
|
| 93 | 93 |
return nil |
| 94 | 94 |
} else if i > 1 {
|
| 95 |
- sortPorts(l.Ports, func(ip, jp Port) bool {
|
|
| 95 |
+ nat.Sort(l.Ports, func(ip, jp nat.Port) bool {
|
|
| 96 | 96 |
// If the two ports have the same number, tcp takes priority |
| 97 | 97 |
// Sort in desc order |
| 98 | 98 |
return ip.Int() < jp.Int() || (ip.Int() == jp.Int() && strings.ToLower(ip.Proto()) == "tcp") |
| ... | ... |
@@ -1,6 +1,7 @@ |
| 1 | 1 |
package docker |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "github.com/dotcloud/docker/nat" |
|
| 4 | 5 |
"strings" |
| 5 | 6 |
"testing" |
| 6 | 7 |
) |
| ... | ... |
@@ -22,9 +23,9 @@ func TestLinkNew(t *testing.T) {
|
| 22 | 22 |
from := newMockLinkContainer(fromID, "172.0.17.2") |
| 23 | 23 |
from.Config.Env = []string{}
|
| 24 | 24 |
from.State = State{Running: true}
|
| 25 |
- ports := make(map[Port]struct{})
|
|
| 25 |
+ ports := make(nat.PortSet) |
|
| 26 | 26 |
|
| 27 |
- ports[Port("6379/tcp")] = struct{}{}
|
|
| 27 |
+ ports[nat.Port("6379/tcp")] = struct{}{}
|
|
| 28 | 28 |
|
| 29 | 29 |
from.Config.ExposedPorts = ports |
| 30 | 30 |
|
| ... | ... |
@@ -51,7 +52,7 @@ func TestLinkNew(t *testing.T) {
|
| 51 | 51 |
t.Fail() |
| 52 | 52 |
} |
| 53 | 53 |
for _, p := range link.Ports {
|
| 54 |
- if p != Port("6379/tcp") {
|
|
| 54 |
+ if p != nat.Port("6379/tcp") {
|
|
| 55 | 55 |
t.Fail() |
| 56 | 56 |
} |
| 57 | 57 |
} |
| ... | ... |
@@ -64,9 +65,9 @@ func TestLinkEnv(t *testing.T) {
|
| 64 | 64 |
from := newMockLinkContainer(fromID, "172.0.17.2") |
| 65 | 65 |
from.Config.Env = []string{"PASSWORD=gordon"}
|
| 66 | 66 |
from.State = State{Running: true}
|
| 67 |
- ports := make(map[Port]struct{})
|
|
| 67 |
+ ports := make(nat.PortSet) |
|
| 68 | 68 |
|
| 69 |
- ports[Port("6379/tcp")] = struct{}{}
|
|
| 69 |
+ ports[nat.Port("6379/tcp")] = struct{}{}
|
|
| 70 | 70 |
|
| 71 | 71 |
from.Config.ExposedPorts = ports |
| 72 | 72 |
|
| 73 | 73 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,133 @@ |
| 0 |
+package nat |
|
| 1 |
+ |
|
| 2 |
+// nat is a convenience package for docker's manipulation of strings describing |
|
| 3 |
+// network ports. |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "fmt" |
|
| 7 |
+ "github.com/dotcloud/docker/utils" |
|
| 8 |
+ "strconv" |
|
| 9 |
+ "strings" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+const ( |
|
| 13 |
+ PortSpecTemplate = "ip:hostPort:containerPort" |
|
| 14 |
+ PortSpecTemplateFormat = "ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort" |
|
| 15 |
+) |
|
| 16 |
+ |
|
| 17 |
+type PortBinding struct {
|
|
| 18 |
+ HostIp string |
|
| 19 |
+ HostPort string |
|
| 20 |
+} |
|
| 21 |
+ |
|
| 22 |
+type PortMap map[Port][]PortBinding |
|
| 23 |
+ |
|
| 24 |
+type PortSet map[Port]struct{}
|
|
| 25 |
+ |
|
| 26 |
+// 80/tcp |
|
| 27 |
+type Port string |
|
| 28 |
+ |
|
| 29 |
+func NewPort(proto, port string) Port {
|
|
| 30 |
+ return Port(fmt.Sprintf("%s/%s", port, proto))
|
|
| 31 |
+} |
|
| 32 |
+ |
|
| 33 |
+func ParsePort(rawPort string) (int, error) {
|
|
| 34 |
+ port, err := strconv.ParseUint(rawPort, 10, 16) |
|
| 35 |
+ if err != nil {
|
|
| 36 |
+ return 0, err |
|
| 37 |
+ } |
|
| 38 |
+ return int(port), nil |
|
| 39 |
+} |
|
| 40 |
+ |
|
| 41 |
+func (p Port) Proto() string {
|
|
| 42 |
+ parts := strings.Split(string(p), "/") |
|
| 43 |
+ if len(parts) == 1 {
|
|
| 44 |
+ return "tcp" |
|
| 45 |
+ } |
|
| 46 |
+ return parts[1] |
|
| 47 |
+} |
|
| 48 |
+ |
|
| 49 |
+func (p Port) Port() string {
|
|
| 50 |
+ return strings.Split(string(p), "/")[0] |
|
| 51 |
+} |
|
| 52 |
+ |
|
| 53 |
+func (p Port) Int() int {
|
|
| 54 |
+ i, err := ParsePort(p.Port()) |
|
| 55 |
+ if err != nil {
|
|
| 56 |
+ panic(err) |
|
| 57 |
+ } |
|
| 58 |
+ return i |
|
| 59 |
+} |
|
| 60 |
+ |
|
| 61 |
+// Splits a port in the format of port/proto |
|
| 62 |
+func SplitProtoPort(rawPort string) (string, string) {
|
|
| 63 |
+ parts := strings.Split(rawPort, "/") |
|
| 64 |
+ l := len(parts) |
|
| 65 |
+ if l == 0 {
|
|
| 66 |
+ return "", "" |
|
| 67 |
+ } |
|
| 68 |
+ if l == 1 {
|
|
| 69 |
+ return "tcp", rawPort |
|
| 70 |
+ } |
|
| 71 |
+ return parts[0], parts[1] |
|
| 72 |
+} |
|
| 73 |
+ |
|
| 74 |
+// We will receive port specs in the format of ip:public:private/proto and these need to be |
|
| 75 |
+// parsed in the internal types |
|
| 76 |
+func ParsePortSpecs(ports []string) (map[Port]struct{}, map[Port][]PortBinding, error) {
|
|
| 77 |
+ var ( |
|
| 78 |
+ exposedPorts = make(map[Port]struct{}, len(ports))
|
|
| 79 |
+ bindings = make(map[Port][]PortBinding) |
|
| 80 |
+ ) |
|
| 81 |
+ |
|
| 82 |
+ for _, rawPort := range ports {
|
|
| 83 |
+ proto := "tcp" |
|
| 84 |
+ |
|
| 85 |
+ if i := strings.LastIndex(rawPort, "/"); i != -1 {
|
|
| 86 |
+ proto = rawPort[i+1:] |
|
| 87 |
+ rawPort = rawPort[:i] |
|
| 88 |
+ } |
|
| 89 |
+ if !strings.Contains(rawPort, ":") {
|
|
| 90 |
+ rawPort = fmt.Sprintf("::%s", rawPort)
|
|
| 91 |
+ } else if len(strings.Split(rawPort, ":")) == 2 {
|
|
| 92 |
+ rawPort = fmt.Sprintf(":%s", rawPort)
|
|
| 93 |
+ } |
|
| 94 |
+ |
|
| 95 |
+ parts, err := utils.PartParser(PortSpecTemplate, rawPort) |
|
| 96 |
+ if err != nil {
|
|
| 97 |
+ return nil, nil, err |
|
| 98 |
+ } |
|
| 99 |
+ |
|
| 100 |
+ var ( |
|
| 101 |
+ containerPort = parts["containerPort"] |
|
| 102 |
+ rawIp = parts["ip"] |
|
| 103 |
+ hostPort = parts["hostPort"] |
|
| 104 |
+ ) |
|
| 105 |
+ |
|
| 106 |
+ if containerPort == "" {
|
|
| 107 |
+ return nil, nil, fmt.Errorf("No port specified: %s<empty>", rawPort)
|
|
| 108 |
+ } |
|
| 109 |
+ if _, err := strconv.ParseUint(containerPort, 10, 16); err != nil {
|
|
| 110 |
+ return nil, nil, fmt.Errorf("Invalid containerPort: %s", containerPort)
|
|
| 111 |
+ } |
|
| 112 |
+ if _, err := strconv.ParseUint(hostPort, 10, 16); hostPort != "" && err != nil {
|
|
| 113 |
+ return nil, nil, fmt.Errorf("Invalid hostPort: %s", hostPort)
|
|
| 114 |
+ } |
|
| 115 |
+ |
|
| 116 |
+ port := NewPort(proto, containerPort) |
|
| 117 |
+ if _, exists := exposedPorts[port]; !exists {
|
|
| 118 |
+ exposedPorts[port] = struct{}{}
|
|
| 119 |
+ } |
|
| 120 |
+ |
|
| 121 |
+ binding := PortBinding{
|
|
| 122 |
+ HostIp: rawIp, |
|
| 123 |
+ HostPort: hostPort, |
|
| 124 |
+ } |
|
| 125 |
+ bslice, exists := bindings[port] |
|
| 126 |
+ if !exists {
|
|
| 127 |
+ bslice = []PortBinding{}
|
|
| 128 |
+ } |
|
| 129 |
+ bindings[port] = append(bslice, binding) |
|
| 130 |
+ } |
|
| 131 |
+ return exposedPorts, bindings, nil |
|
| 132 |
+} |
| 0 | 133 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,28 @@ |
| 0 |
+package nat |
|
| 1 |
+ |
|
| 2 |
+import "sort" |
|
| 3 |
+ |
|
| 4 |
+type portSorter struct {
|
|
| 5 |
+ ports []Port |
|
| 6 |
+ by func(i, j Port) bool |
|
| 7 |
+} |
|
| 8 |
+ |
|
| 9 |
+func (s *portSorter) Len() int {
|
|
| 10 |
+ return len(s.ports) |
|
| 11 |
+} |
|
| 12 |
+ |
|
| 13 |
+func (s *portSorter) Swap(i, j int) {
|
|
| 14 |
+ s.ports[i], s.ports[j] = s.ports[j], s.ports[i] |
|
| 15 |
+} |
|
| 16 |
+ |
|
| 17 |
+func (s *portSorter) Less(i, j int) bool {
|
|
| 18 |
+ ip := s.ports[i] |
|
| 19 |
+ jp := s.ports[j] |
|
| 20 |
+ |
|
| 21 |
+ return s.by(ip, jp) |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 24 |
+func Sort(ports []Port, predicate func(i, j Port) bool) {
|
|
| 25 |
+ s := &portSorter{ports, predicate}
|
|
| 26 |
+ sort.Sort(s) |
|
| 27 |
+} |
| 0 | 28 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,41 @@ |
| 0 |
+package nat |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "testing" |
|
| 5 |
+) |
|
| 6 |
+ |
|
| 7 |
+func TestSortUniquePorts(t *testing.T) {
|
|
| 8 |
+ ports := []Port{
|
|
| 9 |
+ Port("6379/tcp"),
|
|
| 10 |
+ Port("22/tcp"),
|
|
| 11 |
+ } |
|
| 12 |
+ |
|
| 13 |
+ Sort(ports, func(ip, jp Port) bool {
|
|
| 14 |
+ return ip.Int() < jp.Int() || (ip.Int() == jp.Int() && ip.Proto() == "tcp") |
|
| 15 |
+ }) |
|
| 16 |
+ |
|
| 17 |
+ first := ports[0] |
|
| 18 |
+ if fmt.Sprint(first) != "22/tcp" {
|
|
| 19 |
+ t.Log(fmt.Sprint(first)) |
|
| 20 |
+ t.Fail() |
|
| 21 |
+ } |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 24 |
+func TestSortSamePortWithDifferentProto(t *testing.T) {
|
|
| 25 |
+ ports := []Port{
|
|
| 26 |
+ Port("8888/tcp"),
|
|
| 27 |
+ Port("8888/udp"),
|
|
| 28 |
+ Port("6379/tcp"),
|
|
| 29 |
+ Port("6379/udp"),
|
|
| 30 |
+ } |
|
| 31 |
+ |
|
| 32 |
+ Sort(ports, func(ip, jp Port) bool {
|
|
| 33 |
+ return ip.Int() < jp.Int() || (ip.Int() == jp.Int() && ip.Proto() == "tcp") |
|
| 34 |
+ }) |
|
| 35 |
+ |
|
| 36 |
+ first := ports[0] |
|
| 37 |
+ if fmt.Sprint(first) != "6379/tcp" {
|
|
| 38 |
+ t.Fail() |
|
| 39 |
+ } |
|
| 40 |
+} |
| ... | ... |
@@ -2,31 +2,6 @@ package docker |
| 2 | 2 |
|
| 3 | 3 |
import "sort" |
| 4 | 4 |
|
| 5 |
-type portSorter struct {
|
|
| 6 |
- ports []Port |
|
| 7 |
- by func(i, j Port) bool |
|
| 8 |
-} |
|
| 9 |
- |
|
| 10 |
-func (s *portSorter) Len() int {
|
|
| 11 |
- return len(s.ports) |
|
| 12 |
-} |
|
| 13 |
- |
|
| 14 |
-func (s *portSorter) Swap(i, j int) {
|
|
| 15 |
- s.ports[i], s.ports[j] = s.ports[j], s.ports[i] |
|
| 16 |
-} |
|
| 17 |
- |
|
| 18 |
-func (s *portSorter) Less(i, j int) bool {
|
|
| 19 |
- ip := s.ports[i] |
|
| 20 |
- jp := s.ports[j] |
|
| 21 |
- |
|
| 22 |
- return s.by(ip, jp) |
|
| 23 |
-} |
|
| 24 |
- |
|
| 25 |
-func sortPorts(ports []Port, predicate func(i, j Port) bool) {
|
|
| 26 |
- s := &portSorter{ports, predicate}
|
|
| 27 |
- sort.Sort(s) |
|
| 28 |
-} |
|
| 29 |
- |
|
| 30 | 5 |
type containerSorter struct {
|
| 31 | 6 |
containers []*Container |
| 32 | 7 |
by func(i, j *Container) bool |
| 33 | 8 |
deleted file mode 100644 |
| ... | ... |
@@ -1,41 +0,0 @@ |
| 1 |
-package docker |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "testing" |
|
| 6 |
-) |
|
| 7 |
- |
|
| 8 |
-func TestSortUniquePorts(t *testing.T) {
|
|
| 9 |
- ports := []Port{
|
|
| 10 |
- Port("6379/tcp"),
|
|
| 11 |
- Port("22/tcp"),
|
|
| 12 |
- } |
|
| 13 |
- |
|
| 14 |
- sortPorts(ports, func(ip, jp Port) bool {
|
|
| 15 |
- return ip.Int() < jp.Int() || (ip.Int() == jp.Int() && ip.Proto() == "tcp") |
|
| 16 |
- }) |
|
| 17 |
- |
|
| 18 |
- first := ports[0] |
|
| 19 |
- if fmt.Sprint(first) != "22/tcp" {
|
|
| 20 |
- t.Log(fmt.Sprint(first)) |
|
| 21 |
- t.Fail() |
|
| 22 |
- } |
|
| 23 |
-} |
|
| 24 |
- |
|
| 25 |
-func TestSortSamePortWithDifferentProto(t *testing.T) {
|
|
| 26 |
- ports := []Port{
|
|
| 27 |
- Port("8888/tcp"),
|
|
| 28 |
- Port("8888/udp"),
|
|
| 29 |
- Port("6379/tcp"),
|
|
| 30 |
- Port("6379/udp"),
|
|
| 31 |
- } |
|
| 32 |
- |
|
| 33 |
- sortPorts(ports, func(ip, jp Port) bool {
|
|
| 34 |
- return ip.Int() < jp.Int() || (ip.Int() == jp.Int() && ip.Proto() == "tcp") |
|
| 35 |
- }) |
|
| 36 |
- |
|
| 37 |
- first := ports[0] |
|
| 38 |
- if fmt.Sprint(first) != "6379/tcp" {
|
|
| 39 |
- t.Fail() |
|
| 40 |
- } |
|
| 41 |
-} |
| ... | ... |
@@ -3,10 +3,10 @@ package docker |
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"github.com/dotcloud/docker/archive" |
| 6 |
+ "github.com/dotcloud/docker/nat" |
|
| 6 | 7 |
"github.com/dotcloud/docker/pkg/namesgenerator" |
| 7 | 8 |
"github.com/dotcloud/docker/utils" |
| 8 | 9 |
"io" |
| 9 |
- "strconv" |
|
| 10 | 10 |
"strings" |
| 11 | 11 |
"sync/atomic" |
| 12 | 12 |
) |
| ... | ... |
@@ -98,7 +98,7 @@ func MergeConfig(userConf, imageConf *Config) error {
|
| 98 | 98 |
userConf.ExposedPorts = imageConf.ExposedPorts |
| 99 | 99 |
} else if imageConf.ExposedPorts != nil {
|
| 100 | 100 |
if userConf.ExposedPorts == nil {
|
| 101 |
- userConf.ExposedPorts = make(map[Port]struct{})
|
|
| 101 |
+ userConf.ExposedPorts = make(nat.PortSet) |
|
| 102 | 102 |
} |
| 103 | 103 |
for port := range imageConf.ExposedPorts {
|
| 104 | 104 |
if _, exists := userConf.ExposedPorts[port]; !exists {
|
| ... | ... |
@@ -109,9 +109,9 @@ func MergeConfig(userConf, imageConf *Config) error {
|
| 109 | 109 |
|
| 110 | 110 |
if userConf.PortSpecs != nil && len(userConf.PortSpecs) > 0 {
|
| 111 | 111 |
if userConf.ExposedPorts == nil {
|
| 112 |
- userConf.ExposedPorts = make(map[Port]struct{})
|
|
| 112 |
+ userConf.ExposedPorts = make(nat.PortSet) |
|
| 113 | 113 |
} |
| 114 |
- ports, _, err := parsePortSpecs(userConf.PortSpecs) |
|
| 114 |
+ ports, _, err := nat.ParsePortSpecs(userConf.PortSpecs) |
|
| 115 | 115 |
if err != nil {
|
| 116 | 116 |
return err |
| 117 | 117 |
} |
| ... | ... |
@@ -125,10 +125,10 @@ func MergeConfig(userConf, imageConf *Config) error {
|
| 125 | 125 |
if imageConf.PortSpecs != nil && len(imageConf.PortSpecs) > 0 {
|
| 126 | 126 |
utils.Debugf("Migrating image port specs to containter: %s", strings.Join(imageConf.PortSpecs, ", "))
|
| 127 | 127 |
if userConf.ExposedPorts == nil {
|
| 128 |
- userConf.ExposedPorts = make(map[Port]struct{})
|
|
| 128 |
+ userConf.ExposedPorts = make(nat.PortSet) |
|
| 129 | 129 |
} |
| 130 | 130 |
|
| 131 |
- ports, _, err := parsePortSpecs(imageConf.PortSpecs) |
|
| 131 |
+ ports, _, err := nat.ParsePortSpecs(imageConf.PortSpecs) |
|
| 132 | 132 |
if err != nil {
|
| 133 | 133 |
return err |
| 134 | 134 |
} |
| ... | ... |
@@ -212,96 +212,9 @@ func parseLxcOpt(opt string) (string, string, error) {
|
| 212 | 212 |
return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil |
| 213 | 213 |
} |
| 214 | 214 |
|
| 215 |
-// FIXME: network related stuff (including parsing) should be grouped in network file |
|
| 216 |
-const ( |
|
| 217 |
- PortSpecTemplate = "ip:hostPort:containerPort" |
|
| 218 |
- PortSpecTemplateFormat = "ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort" |
|
| 219 |
-) |
|
| 220 |
- |
|
| 221 |
-// We will receive port specs in the format of ip:public:private/proto and these need to be |
|
| 222 |
-// parsed in the internal types |
|
| 223 |
-func parsePortSpecs(ports []string) (map[Port]struct{}, map[Port][]PortBinding, error) {
|
|
| 224 |
- var ( |
|
| 225 |
- exposedPorts = make(map[Port]struct{}, len(ports))
|
|
| 226 |
- bindings = make(map[Port][]PortBinding) |
|
| 227 |
- ) |
|
| 228 |
- |
|
| 229 |
- for _, rawPort := range ports {
|
|
| 230 |
- proto := "tcp" |
|
| 231 |
- |
|
| 232 |
- if i := strings.LastIndex(rawPort, "/"); i != -1 {
|
|
| 233 |
- proto = rawPort[i+1:] |
|
| 234 |
- rawPort = rawPort[:i] |
|
| 235 |
- } |
|
| 236 |
- if !strings.Contains(rawPort, ":") {
|
|
| 237 |
- rawPort = fmt.Sprintf("::%s", rawPort)
|
|
| 238 |
- } else if len(strings.Split(rawPort, ":")) == 2 {
|
|
| 239 |
- rawPort = fmt.Sprintf(":%s", rawPort)
|
|
| 240 |
- } |
|
| 241 |
- |
|
| 242 |
- parts, err := utils.PartParser(PortSpecTemplate, rawPort) |
|
| 243 |
- if err != nil {
|
|
| 244 |
- return nil, nil, err |
|
| 245 |
- } |
|
| 246 |
- |
|
| 247 |
- var ( |
|
| 248 |
- containerPort = parts["containerPort"] |
|
| 249 |
- rawIp = parts["ip"] |
|
| 250 |
- hostPort = parts["hostPort"] |
|
| 251 |
- ) |
|
| 252 |
- |
|
| 253 |
- if containerPort == "" {
|
|
| 254 |
- return nil, nil, fmt.Errorf("No port specified: %s<empty>", rawPort)
|
|
| 255 |
- } |
|
| 256 |
- if _, err := strconv.ParseUint(containerPort, 10, 16); err != nil {
|
|
| 257 |
- return nil, nil, fmt.Errorf("Invalid containerPort: %s", containerPort)
|
|
| 258 |
- } |
|
| 259 |
- if _, err := strconv.ParseUint(hostPort, 10, 16); hostPort != "" && err != nil {
|
|
| 260 |
- return nil, nil, fmt.Errorf("Invalid hostPort: %s", hostPort)
|
|
| 261 |
- } |
|
| 262 |
- |
|
| 263 |
- port := NewPort(proto, containerPort) |
|
| 264 |
- if _, exists := exposedPorts[port]; !exists {
|
|
| 265 |
- exposedPorts[port] = struct{}{}
|
|
| 266 |
- } |
|
| 267 |
- |
|
| 268 |
- binding := PortBinding{
|
|
| 269 |
- HostIp: rawIp, |
|
| 270 |
- HostPort: hostPort, |
|
| 271 |
- } |
|
| 272 |
- bslice, exists := bindings[port] |
|
| 273 |
- if !exists {
|
|
| 274 |
- bslice = []PortBinding{}
|
|
| 275 |
- } |
|
| 276 |
- bindings[port] = append(bslice, binding) |
|
| 277 |
- } |
|
| 278 |
- return exposedPorts, bindings, nil |
|
| 279 |
-} |
|
| 280 |
- |
|
| 281 |
-// Splits a port in the format of port/proto |
|
| 282 |
-func splitProtoPort(rawPort string) (string, string) {
|
|
| 283 |
- parts := strings.Split(rawPort, "/") |
|
| 284 |
- l := len(parts) |
|
| 285 |
- if l == 0 {
|
|
| 286 |
- return "", "" |
|
| 287 |
- } |
|
| 288 |
- if l == 1 {
|
|
| 289 |
- return "tcp", rawPort |
|
| 290 |
- } |
|
| 291 |
- return parts[0], parts[1] |
|
| 292 |
-} |
|
| 293 |
- |
|
| 294 |
-func parsePort(rawPort string) (int, error) {
|
|
| 295 |
- port, err := strconv.ParseUint(rawPort, 10, 16) |
|
| 296 |
- if err != nil {
|
|
| 297 |
- return 0, err |
|
| 298 |
- } |
|
| 299 |
- return int(port), nil |
|
| 300 |
-} |
|
| 301 |
- |
|
| 302 | 215 |
func migratePortMappings(config *Config, hostConfig *HostConfig) error {
|
| 303 | 216 |
if config.PortSpecs != nil {
|
| 304 |
- ports, bindings, err := parsePortSpecs(config.PortSpecs) |
|
| 217 |
+ ports, bindings, err := nat.ParsePortSpecs(config.PortSpecs) |
|
| 305 | 218 |
if err != nil {
|
| 306 | 219 |
return err |
| 307 | 220 |
} |
| ... | ... |
@@ -314,7 +227,7 @@ func migratePortMappings(config *Config, hostConfig *HostConfig) error {
|
| 314 | 314 |
} |
| 315 | 315 |
|
| 316 | 316 |
if config.ExposedPorts == nil {
|
| 317 |
- config.ExposedPorts = make(map[Port]struct{}, len(ports))
|
|
| 317 |
+ config.ExposedPorts = make(nat.PortSet, len(ports)) |
|
| 318 | 318 |
} |
| 319 | 319 |
for k, v := range ports {
|
| 320 | 320 |
config.ExposedPorts[k] = v |