mirror of
https://github.com/clearlinux/docker.git
synced 2026-08-21 05:07:22 +00:00
Add default port for link
Add links unit test file
This commit is contained in:
@@ -1122,6 +1122,11 @@ func (cli *DockerCli) CmdLinks(args ...string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.NArg() < 1 && !*flAll {
|
||||
cmd.Usage()
|
||||
return nil
|
||||
}
|
||||
|
||||
v := url.Values{}
|
||||
v.Set("name", cmd.Arg(0))
|
||||
|
||||
|
||||
@@ -125,6 +125,14 @@ func (p Port) Port() string {
|
||||
return strings.Split(string(p), "/")[0]
|
||||
}
|
||||
|
||||
func (p Port) Int() int {
|
||||
i, err := parsePort(p.Port())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
func NewPort(proto, port string) Port {
|
||||
return Port(fmt.Sprintf("%s/%s", port, proto))
|
||||
}
|
||||
@@ -830,6 +838,9 @@ func (container *Container) Start(hostConfig *HostConfig) error {
|
||||
return err
|
||||
}
|
||||
linkedContainer := runtime.Get(parts["id"])
|
||||
if linkedContainer == nil {
|
||||
return fmt.Errorf("Cannot find container: %s", parts["id"])
|
||||
}
|
||||
|
||||
link, err := runtime.links.NewLink(container, linkedContainer, runtime.networkManager.bridgeIface, parts["alias"])
|
||||
if err != nil {
|
||||
|
||||
@@ -26,6 +26,9 @@ type LinkRepository struct {
|
||||
}
|
||||
|
||||
func (r *LinkRepository) NewLink(to, from *Container, bridgeInterface string, alias string) (*Link, error) {
|
||||
if to.ID == from.ID {
|
||||
return nil, fmt.Errorf("Cannot link to self: %s == %s", to.ID, from.ID)
|
||||
}
|
||||
if !from.State.Running {
|
||||
return nil, fmt.Errorf("Cannot link to a non running container: %s AS %s", from.ID, alias)
|
||||
}
|
||||
@@ -39,7 +42,7 @@ func (r *LinkRepository) NewLink(to, from *Container, bridgeInterface string, al
|
||||
FromID: utils.TruncateID(from.ID),
|
||||
ToID: utils.TruncateID(to.ID),
|
||||
BridgeInterface: bridgeInterface,
|
||||
Alias: alias,
|
||||
Alias: strings.ToUpper(alias),
|
||||
FromIP: from.NetworkSettings.IPAddress,
|
||||
ToIP: to.NetworkSettings.IPAddress,
|
||||
FromEnvironment: from.Config.Env,
|
||||
@@ -57,25 +60,55 @@ func (l *Link) ID() string {
|
||||
|
||||
func (l *Link) ToEnv() []string {
|
||||
env := []string{}
|
||||
|
||||
if p := l.getDefaultPort(); p != nil {
|
||||
env = append(env, fmt.Sprintf("%s_PORT=%s://%s:%s", l.Alias, p.Proto(), l.FromIP, p.Port()))
|
||||
}
|
||||
|
||||
// Load exposed ports into the environment
|
||||
for _, p := range l.ports {
|
||||
env = append(env, fmt.Sprintf("%s_%s_ADDR=%s://%s:%s", strings.ToUpper(l.Alias), p.Port(), p.Proto(), l.FromIP, p.Port()))
|
||||
env = append(env, fmt.Sprintf("%s_PORT_%s_%s=%s://%s:%s", l.Alias, p.Port(), strings.ToUpper(p.Proto()), p.Proto(), l.FromIP, p.Port()))
|
||||
}
|
||||
|
||||
// Load the linked container's ID into the environment
|
||||
env = append(env, fmt.Sprintf("%s_ID=%s", l.Alias, l.FromID))
|
||||
|
||||
if l.FromEnvironment != nil {
|
||||
for _, v := range l.FromEnvironment {
|
||||
parts := strings.Split(v, "=")
|
||||
if len(parts) < 2 {
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
}
|
||||
env = append(env, fmt.Sprintf("%s_ENV_%s=%s", strings.ToUpper(l.Alias), parts[0], parts[1]))
|
||||
// Ignore a few variables that are added during docker build
|
||||
if parts[0] == "HOME" || parts[0] == "PATH" {
|
||||
continue
|
||||
}
|
||||
env = append(env, fmt.Sprintf("%s_ENV_%s=%s", l.Alias, parts[0], parts[1]))
|
||||
}
|
||||
}
|
||||
return env
|
||||
}
|
||||
|
||||
// Default port rules
|
||||
func (l *Link) getDefaultPort() *Port {
|
||||
var p Port
|
||||
i := len(l.ports)
|
||||
|
||||
if i == 0 {
|
||||
return nil
|
||||
} else if i > 1 {
|
||||
sortPorts(l.ports, func(ip, jp Port) bool {
|
||||
// If the two ports have the same number, tcp takes priority
|
||||
// Sort in desc order
|
||||
return ip.Int() < jp.Int() || (ip.Int() == jp.Int() && ip.Proto() == "tcp")
|
||||
})
|
||||
}
|
||||
p = l.ports[0]
|
||||
return &p
|
||||
}
|
||||
|
||||
func (l *Link) Enable() error {
|
||||
if err := l.toggle("-I"); err != nil {
|
||||
if err := l.toggle("-I", false); err != nil {
|
||||
return err
|
||||
}
|
||||
l.isEnabled = true
|
||||
@@ -85,12 +118,12 @@ func (l *Link) Enable() error {
|
||||
func (l *Link) Disable() {
|
||||
// We do not care about erros here because the link may not
|
||||
// exist in iptables
|
||||
l.toggle("-D")
|
||||
l.toggle("-D", true)
|
||||
|
||||
l.isEnabled = false
|
||||
}
|
||||
|
||||
func (l *Link) toggle(action string) error {
|
||||
func (l *Link) toggle(action string, ignoreErrors bool) error {
|
||||
for _, p := range l.ports {
|
||||
if err := iptables.Raw(action, "FORWARD",
|
||||
"-i", l.BridgeInterface, "-o", l.BridgeInterface,
|
||||
@@ -98,7 +131,7 @@ func (l *Link) toggle(action string) error {
|
||||
"-s", l.ToIP,
|
||||
"--dport", p.Port(),
|
||||
"-d", l.FromIP,
|
||||
"-j", "ACCEPT"); err != nil {
|
||||
"-j", "ACCEPT"); !ignoreErrors && err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -108,7 +141,7 @@ func (l *Link) toggle(action string) error {
|
||||
"-s", l.FromIP,
|
||||
"--sport", p.Port(),
|
||||
"-d", l.ToIP,
|
||||
"-j", "ACCEPT"); err != nil {
|
||||
"-j", "ACCEPT"); !ignoreErrors && err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func newTestLinkRepository(t *testing.T) *LinkRepository {
|
||||
r, err := NewLinkRepository("")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func newMockLinkContainer(id string, ip string) *Container {
|
||||
return &Container{
|
||||
Config: &Config{},
|
||||
ID: id,
|
||||
NetworkSettings: &NetworkSettings{
|
||||
IPAddress: ip,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinkNew(t *testing.T) {
|
||||
r := newTestLinkRepository(t)
|
||||
toID := GenerateID()
|
||||
fromID := GenerateID()
|
||||
|
||||
from := newMockLinkContainer(fromID, "172.0.17.2")
|
||||
from.Config.Env = []string{}
|
||||
from.State = State{Running: true}
|
||||
ports := make(map[Port]struct{})
|
||||
|
||||
ports[Port("6379/tcp")] = struct{}{}
|
||||
|
||||
from.Config.ExposedPorts = ports
|
||||
|
||||
to := newMockLinkContainer(toID, "172.0.17.3")
|
||||
|
||||
link, err := r.NewLink(to, from, "172.0.17.1", "docker")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if link == nil {
|
||||
t.FailNow()
|
||||
}
|
||||
if link.ID() != fmt.Sprintf("%s:%s", utils.TruncateID(to.ID), "DOCKER") {
|
||||
t.Fail()
|
||||
}
|
||||
if link.Alias != "DOCKER" {
|
||||
t.Fail()
|
||||
}
|
||||
if link.FromID != utils.TruncateID(from.ID) {
|
||||
t.Fail()
|
||||
}
|
||||
if link.ToID != utils.TruncateID(to.ID) {
|
||||
t.Fail()
|
||||
}
|
||||
if link.ToIP != "172.0.17.3" {
|
||||
t.Fail()
|
||||
}
|
||||
if link.FromIP != "172.0.17.2" {
|
||||
t.Fail()
|
||||
}
|
||||
if link.BridgeInterface != "172.0.17.1" {
|
||||
t.Fail()
|
||||
}
|
||||
for _, p := range link.ports {
|
||||
if p != Port("6379/tcp") {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinkEnv(t *testing.T) {
|
||||
r := newTestLinkRepository(t)
|
||||
toID := GenerateID()
|
||||
fromID := GenerateID()
|
||||
|
||||
from := newMockLinkContainer(fromID, "172.0.17.2")
|
||||
from.Config.Env = []string{"PASSWORD=gordon"}
|
||||
from.State = State{Running: true}
|
||||
ports := make(map[Port]struct{})
|
||||
|
||||
ports[Port("6379/tcp")] = struct{}{}
|
||||
|
||||
from.Config.ExposedPorts = ports
|
||||
|
||||
to := newMockLinkContainer(toID, "172.0.17.3")
|
||||
|
||||
link, err := r.NewLink(to, from, "172.0.17.1", "docker")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rawEnv := link.ToEnv()
|
||||
env := make(map[string]string, len(rawEnv))
|
||||
for _, e := range rawEnv {
|
||||
parts := strings.Split(e, "=")
|
||||
if len(parts) != 2 {
|
||||
t.FailNow()
|
||||
}
|
||||
env[parts[0]] = parts[1]
|
||||
}
|
||||
if env["DOCKER_PORT"] != "tcp://172.0.17.2:6379" {
|
||||
t.Fail()
|
||||
}
|
||||
if env["DOCKER_PORT_6379_TCP"] != "tcp://172.0.17.2:6379" {
|
||||
t.Fail()
|
||||
}
|
||||
if env["DOCKER_ID"] != utils.TruncateID(from.ID) {
|
||||
t.Fail()
|
||||
}
|
||||
if env["DOCKER_ENV_PASSWORD"] != "gordon" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
@@ -34,3 +34,28 @@ func sortImagesByCreationAndTag(images []APIImages) {
|
||||
|
||||
sort.Sort(sorter)
|
||||
}
|
||||
|
||||
type portSorter struct {
|
||||
ports []Port
|
||||
by func(i, j Port) bool
|
||||
}
|
||||
|
||||
func (s *portSorter) Len() int {
|
||||
return len(s.ports)
|
||||
}
|
||||
|
||||
func (s *portSorter) Swap(i, j int) {
|
||||
s.ports[i], s.ports[j] = s.ports[j], s.ports[i]
|
||||
}
|
||||
|
||||
func (s *portSorter) Less(i, j int) bool {
|
||||
ip := s.ports[i]
|
||||
jp := s.ports[j]
|
||||
|
||||
return s.by(ip, jp)
|
||||
}
|
||||
|
||||
func sortPorts(ports []Port, predicate func(i, j Port) bool) {
|
||||
s := &portSorter{ports, predicate}
|
||||
sort.Sort(s)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -55,3 +56,38 @@ func TestServerListOrderedImagesByCreationDateAndTag(t *testing.T) {
|
||||
t.Error("Expected []APIImges to be ordered by most recent creation date and tag name.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSortUniquePorts(t *testing.T) {
|
||||
ports := []Port{
|
||||
Port("6379/tcp"),
|
||||
Port("22/tcp"),
|
||||
}
|
||||
|
||||
sortPorts(ports, func(ip, jp Port) bool {
|
||||
return ip.Int() < jp.Int() || (ip.Int() == jp.Int() && ip.Proto() == "tcp")
|
||||
})
|
||||
|
||||
first := ports[0]
|
||||
if fmt.Sprint(first) != "22/tcp" {
|
||||
t.Log(fmt.Sprint(first))
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestSortSamePortWithDifferentProto(t *testing.T) {
|
||||
ports := []Port{
|
||||
Port("8888/tcp"),
|
||||
Port("8888/udp"),
|
||||
Port("6379/tcp"),
|
||||
Port("6379/udp"),
|
||||
}
|
||||
|
||||
sortPorts(ports, func(ip, jp Port) bool {
|
||||
return ip.Int() < jp.Int() || (ip.Int() == jp.Int() && ip.Proto() == "tcp")
|
||||
})
|
||||
|
||||
first := ports[0]
|
||||
if fmt.Sprint(first) != "6379/tcp" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user