func (container *Container) setupLinkedContainers() ([]string, error) { var ( env []string daemon = container.daemon ) children, err := daemon.Children(container.Name) if err != nil { return nil, err } if len(children) > 0 { container.activeLinks = make(map[string]*links.Link, len(children)) // If we encounter an error make sure that we rollback any network // config and ip table changes rollback := func() { for _, link := range container.activeLinks { link.Disable() } container.activeLinks = nil } for linkAlias, child := range children { if !child.State.IsRunning() { return nil, fmt.Errorf("Cannot link to a non running container: %s AS %s", child.Name, linkAlias) } link, err := links.NewLink( container.NetworkSettings.IPAddress, child.NetworkSettings.IPAddress, linkAlias, child.Config.Env, child.Config.ExposedPorts, daemon.eng) if err != nil { rollback() return nil, err } container.activeLinks[link.Alias()] = link if err := link.Enable(); err != nil { rollback() return nil, err } for _, envVar := range link.ToEnv() { env = append(env, envVar) } } } return env, nil }
// Support cross-host linking func (c *Cluster) processLinks(containerNode *node.Node, config *cluster.ContainerConfig) error { originalLinks := config.HostConfig.Links if originalLinks == nil || len(originalLinks) == 0 { return nil } containers := c.Containers() //Cache for the container info in linking cache := map[string](*dockerclient.ContainerInfo){} addr := containerNode.Addr var newLinks []string var newEnv []string var crossHostLinks []string for _, link := range originalLinks { //Parse the link info linkInfo := strings.Split(link, ":") name, alias := linkInfo[0], linkInfo[1] linkContainerName := "/" + name for _, target := range containers { if target.Info.Name == linkContainerName { if addr == target.Engine.Addr { log.Debug("No additional work for the container link on the same host") } else { //Update the link var err error targetInfo := cache[target.Id] if targetInfo == nil { targetInfo, err = target.Engine.InspectContainer(target.Id) if err != nil { log.Warningf("Failed to find the linked container %s: %v", target.Id, err) return err } cache[target.Id] = targetInfo } //Simulate link for container on other hosts ports := make(nat.PortSet) for p := range targetInfo.NetworkSettings.Ports { ports[nat.Port(p)] = struct{}{} } linkName := fmt.Sprintf("/%s/%s", name, alias) newLink, err := links.NewLink("", targetInfo.NetworkSettings.IPAddress, linkName, targetInfo.Config.Env, ports) //Add as cross-host links crossHostLinks = append(crossHostLinks, link) //Ignore this link from the host config link = "" env := newLink.ToEnv() newEnv = append(newEnv, env...) newHost := alias + ":" + targetInfo.NetworkSettings.IPAddress config.HostConfig.ExtraHosts = append(config.HostConfig.ExtraHosts, newHost) } break } } if link != "" { newLinks = append(newLinks, link) } } //Update the Links config.HostConfig.Links = newLinks //Update the Env config.Env = append(config.Env, newEnv...) //Add the Env CROSS_HOST_LINKS if crossHostLinks != nil { envCrossHostLinks := "CROSS_HOST_LINKS=" + strings.Join(crossHostLinks, ";") config.Env = append(config.Env, envCrossHostLinks) } return nil }