Example #1
0
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
}
Example #2
0
// 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
}