зеркало из https://github.com/microsoft/docker.git
Support `--link` for user-defined networks
This brings in the container-local alias functionality for containers connected to u ser-defined networks. Signed-off-by: Madhu Venugopal <madhu@docker.com>
This commit is contained in:
Родитель
c1582f20cc
Коммит
e221b8a3d6
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/docker/docker/opts"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
runconfigopts "github.com/docker/docker/runconfig/opts"
|
||||
"github.com/docker/engine-api/types"
|
||||
"github.com/docker/engine-api/types/filters"
|
||||
"github.com/docker/engine-api/types/network"
|
||||
|
@ -112,6 +113,8 @@ func (cli *DockerCli) CmdNetworkConnect(args ...string) error {
|
|||
cmd := Cli.Subcmd("network connect", []string{"NETWORK CONTAINER"}, "Connects a container to a network", false)
|
||||
flIPAddress := cmd.String([]string{"-ip"}, "", "IP Address")
|
||||
flIPv6Address := cmd.String([]string{"-ip6"}, "", "IPv6 Address")
|
||||
flLinks := opts.NewListOpts(runconfigopts.ValidateLink)
|
||||
cmd.Var(&flLinks, []string{"-link"}, "Add link to another container")
|
||||
cmd.Require(flag.Min, 2)
|
||||
if err := cmd.ParseFlags(args, true); err != nil {
|
||||
return err
|
||||
|
@ -121,6 +124,7 @@ func (cli *DockerCli) CmdNetworkConnect(args ...string) error {
|
|||
IPv4Address: *flIPAddress,
|
||||
IPv6Address: *flIPv6Address,
|
||||
},
|
||||
Links: flLinks.GetAll(),
|
||||
}
|
||||
return cli.client.NetworkConnect(cmd.Arg(0), cmd.Arg(1), epConfig)
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"github.com/docker/docker/pkg/chrootarchive"
|
||||
"github.com/docker/docker/pkg/symlink"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
runconfigopts "github.com/docker/docker/runconfig/opts"
|
||||
"github.com/docker/docker/utils"
|
||||
"github.com/docker/docker/volume"
|
||||
"github.com/docker/engine-api/types/container"
|
||||
|
@ -247,6 +248,21 @@ func (container *Container) UpdateSandboxNetworkSettings(sb libnetwork.Sandbox)
|
|||
return nil
|
||||
}
|
||||
|
||||
// BuildJoinOptions builds endpoint Join options from a given network.
|
||||
func (container *Container) BuildJoinOptions(n libnetwork.Network) ([]libnetwork.EndpointOption, error) {
|
||||
var joinOptions []libnetwork.EndpointOption
|
||||
if epConfig, ok := container.NetworkSettings.Networks[n.Name()]; ok {
|
||||
for _, str := range epConfig.Links {
|
||||
name, alias, err := runconfigopts.ParseLink(str)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
joinOptions = append(joinOptions, libnetwork.CreateOptionAlias(name, alias))
|
||||
}
|
||||
}
|
||||
return joinOptions, nil
|
||||
}
|
||||
|
||||
// BuildCreateEndpointOptions builds endpoint options from a given network.
|
||||
func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network) ([]libnetwork.EndpointOption, error) {
|
||||
var (
|
||||
|
|
|
@ -586,7 +586,7 @@ func (daemon *Daemon) updateContainerNetworkSettings(container *container.Contai
|
|||
if container.NetworkSettings == nil {
|
||||
container.NetworkSettings = &network.Settings{}
|
||||
}
|
||||
if endpointsConfig != nil {
|
||||
if len(endpointsConfig) > 0 {
|
||||
container.NetworkSettings.Networks = endpointsConfig
|
||||
}
|
||||
if container.NetworkSettings.Networks == nil {
|
||||
|
@ -816,7 +816,12 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName
|
|||
container.UpdateSandboxNetworkSettings(sb)
|
||||
}
|
||||
|
||||
if err := ep.Join(sb); err != nil {
|
||||
joinOptions, err := container.BuildJoinOptions(n)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ep.Join(sb, joinOptions...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -868,7 +868,7 @@ func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error
|
|||
|
||||
// registerLinks writes the links to a file.
|
||||
func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
||||
if hostConfig == nil {
|
||||
if hostConfig == nil || hostConfig.NetworkMode.IsUserDefined() {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1040,3 +1040,44 @@ func verifyIPAddresses(c *check.C, cName, nwname, ipv4, ipv6 string) {
|
|||
out, _ = dockerCmd(c, "inspect", fmt.Sprintf("--format='{{ .NetworkSettings.Networks.%s.GlobalIPv6Address }}'", nwname), cName)
|
||||
c.Assert(strings.TrimSpace(out), check.Equals, ipv6)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestUserDefinedNetworkConnectDisconnectLink(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "foo1")
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "foo2")
|
||||
|
||||
dockerCmd(c, "run", "-d", "--net=foo1", "--name=first", "busybox", "top")
|
||||
c.Assert(waitRun("first"), check.IsNil)
|
||||
|
||||
// run a container in user-defined network udlinkNet with a link for an existing container
|
||||
// and a link for a container that doesnt exist
|
||||
dockerCmd(c, "run", "-d", "--net=foo1", "--name=second", "--link=first:FirstInFoo1",
|
||||
"--link=third:bar", "busybox", "top")
|
||||
c.Assert(waitRun("second"), check.IsNil)
|
||||
|
||||
// ping to first and its alias FirstInFoo1 must succeed
|
||||
_, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
|
||||
c.Assert(err, check.IsNil)
|
||||
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo1")
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
// connect first container to foo2 network
|
||||
dockerCmd(c, "network", "connect", "foo2", "first")
|
||||
// connect second container to foo2 network with a different alias for first container
|
||||
dockerCmd(c, "network", "connect", "--link=first:FirstInFoo2", "foo2", "second")
|
||||
|
||||
// ping the new alias in network foo2
|
||||
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo2")
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
// disconnect first container from foo1 network
|
||||
dockerCmd(c, "network", "disconnect", "foo1", "first")
|
||||
|
||||
// link in foo1 network must fail
|
||||
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo1")
|
||||
c.Assert(err, check.NotNil)
|
||||
|
||||
// link in foo2 network must succeed
|
||||
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo2")
|
||||
c.Assert(err, check.IsNil)
|
||||
}
|
||||
|
|
|
@ -199,6 +199,80 @@ func (s *DockerSuite) TestRunLinksContainerWithContainerId(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestUserDefinedNetworkLinks(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "udlinkNet")
|
||||
|
||||
dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=first", "busybox", "top")
|
||||
c.Assert(waitRun("first"), check.IsNil)
|
||||
|
||||
// run a container in user-defined network udlinkNet with a link for an existing container
|
||||
// and a link for a container that doesnt exist
|
||||
dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=second", "--link=first:foo",
|
||||
"--link=third:bar", "busybox", "top")
|
||||
c.Assert(waitRun("second"), check.IsNil)
|
||||
|
||||
// ping to first and its alias foo must succeed
|
||||
_, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
|
||||
c.Assert(err, check.IsNil)
|
||||
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
// ping to third and its alias must fail
|
||||
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "third")
|
||||
c.Assert(err, check.NotNil)
|
||||
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar")
|
||||
c.Assert(err, check.NotNil)
|
||||
|
||||
// start third container now
|
||||
dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=third", "busybox", "top")
|
||||
c.Assert(waitRun("third"), check.IsNil)
|
||||
|
||||
// ping to third and its alias must succeed now
|
||||
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "third")
|
||||
c.Assert(err, check.IsNil)
|
||||
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar")
|
||||
c.Assert(err, check.IsNil)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestUserDefinedNetworkLinksWithRestart(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "udlinkNet")
|
||||
|
||||
dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=first", "busybox", "top")
|
||||
c.Assert(waitRun("first"), check.IsNil)
|
||||
|
||||
dockerCmd(c, "run", "-d", "--net=udlinkNet", "--name=second", "--link=first:foo",
|
||||
"busybox", "top")
|
||||
c.Assert(waitRun("second"), check.IsNil)
|
||||
|
||||
// ping to first and its alias foo must succeed
|
||||
_, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
|
||||
c.Assert(err, check.IsNil)
|
||||
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
// Restart first container
|
||||
dockerCmd(c, "restart", "first")
|
||||
c.Assert(waitRun("first"), check.IsNil)
|
||||
|
||||
// ping to first and its alias foo must still succeed
|
||||
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
|
||||
c.Assert(err, check.IsNil)
|
||||
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
// Restart second container
|
||||
dockerCmd(c, "restart", "second")
|
||||
c.Assert(waitRun("second"), check.IsNil)
|
||||
|
||||
// ping to first and its alias foo must still succeed
|
||||
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
|
||||
c.Assert(err, check.IsNil)
|
||||
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
|
||||
c.Assert(err, check.IsNil)
|
||||
}
|
||||
|
||||
// Issue 9677.
|
||||
func (s *DockerSuite) TestRunWithDaemonFlags(c *check.C) {
|
||||
out, _, err := dockerCmdWithError("--exec-opt", "foo=bar", "run", "-i", "busybox", "true")
|
||||
|
|
|
@ -48,10 +48,6 @@ func ValidateNetMode(c *container.Config, hc *container.HostConfig) error {
|
|||
return ErrConflictContainerNetworkAndLinks
|
||||
}
|
||||
|
||||
if hc.NetworkMode.IsUserDefined() && len(hc.Links) > 0 {
|
||||
return ErrConflictUserDefinedNetworkAndLinks
|
||||
}
|
||||
|
||||
if (hc.NetworkMode.IsHost() || hc.NetworkMode.IsContainer()) && len(hc.DNS) > 0 {
|
||||
return ErrConflictNetworkAndDNS
|
||||
}
|
||||
|
|
|
@ -409,11 +409,11 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
|
|||
config.StdinOnce = true
|
||||
}
|
||||
|
||||
var networkingConfig *networktypes.NetworkingConfig
|
||||
networkingConfig := &networktypes.NetworkingConfig{
|
||||
EndpointsConfig: make(map[string]*networktypes.EndpointSettings),
|
||||
}
|
||||
|
||||
if *flIPv4Address != "" || *flIPv6Address != "" {
|
||||
networkingConfig = &networktypes.NetworkingConfig{
|
||||
EndpointsConfig: make(map[string]*networktypes.EndpointSettings),
|
||||
}
|
||||
networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = &networktypes.EndpointSettings{
|
||||
IPAMConfig: &networktypes.EndpointIPAMConfig{
|
||||
IPv4Address: *flIPv4Address,
|
||||
|
@ -422,6 +422,16 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
|
|||
}
|
||||
}
|
||||
|
||||
if hostConfig.NetworkMode.IsUserDefined() && len(hostConfig.Links) > 0 {
|
||||
epConfig := networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)]
|
||||
if epConfig == nil {
|
||||
epConfig = &networktypes.EndpointSettings{}
|
||||
}
|
||||
epConfig.Links = make([]string, len(hostConfig.Links))
|
||||
copy(epConfig.Links, hostConfig.Links)
|
||||
networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = epConfig
|
||||
}
|
||||
|
||||
return config, hostConfig, networkingConfig, cmd, nil
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче