func (sc *sandboxCreate) parseOptions() []libnetwork.SandboxOption { var setFctList []libnetwork.SandboxOption if sc.HostName != "" { setFctList = append(setFctList, libnetwork.OptionHostname(sc.HostName)) } if sc.DomainName != "" { setFctList = append(setFctList, libnetwork.OptionDomainname(sc.DomainName)) } if sc.HostsPath != "" { setFctList = append(setFctList, libnetwork.OptionHostsPath(sc.HostsPath)) } if sc.ResolvConfPath != "" { setFctList = append(setFctList, libnetwork.OptionResolvConfPath(sc.ResolvConfPath)) } if sc.UseDefaultSandbox { setFctList = append(setFctList, libnetwork.OptionUseDefaultSandbox()) } if sc.UseExternalKey { setFctList = append(setFctList, libnetwork.OptionUseExternalKey()) } if sc.DNS != nil { for _, d := range sc.DNS { setFctList = append(setFctList, libnetwork.OptionDNS(d)) } } if sc.ExtraHosts != nil { for _, e := range sc.ExtraHosts { setFctList = append(setFctList, libnetwork.OptionExtraHost(e.Name, e.Address)) } } return setFctList }
func (daemon *Daemon) buildSandboxOptions(container *Container, n libnetwork.Network) ([]libnetwork.SandboxOption, error) { var ( sboxOptions []libnetwork.SandboxOption err error dns []string dnsSearch []string dnsOptions []string ) sboxOptions = append(sboxOptions, libnetwork.OptionHostname(container.Config.Hostname), libnetwork.OptionDomainname(container.Config.Domainname)) if container.hostConfig.NetworkMode.IsHost() { sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox()) sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts")) sboxOptions = append(sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf")) } else if daemon.execDriver.SupportsHooks() { // OptionUseExternalKey is mandatory for userns support. // But optional for non-userns support sboxOptions = append(sboxOptions, libnetwork.OptionUseExternalKey()) } container.HostsPath, err = container.getRootResourcePath("hosts") if err != nil { return nil, err } sboxOptions = append(sboxOptions, libnetwork.OptionHostsPath(container.HostsPath)) container.ResolvConfPath, err = container.getRootResourcePath("resolv.conf") if err != nil { return nil, err } sboxOptions = append(sboxOptions, libnetwork.OptionResolvConfPath(container.ResolvConfPath)) if len(container.hostConfig.DNS) > 0 { dns = container.hostConfig.DNS } else if len(daemon.configStore.DNS) > 0 { dns = daemon.configStore.DNS } for _, d := range dns { sboxOptions = append(sboxOptions, libnetwork.OptionDNS(d)) } if len(container.hostConfig.DNSSearch) > 0 { dnsSearch = container.hostConfig.DNSSearch } else if len(daemon.configStore.DNSSearch) > 0 { dnsSearch = daemon.configStore.DNSSearch } for _, ds := range dnsSearch { sboxOptions = append(sboxOptions, libnetwork.OptionDNSSearch(ds)) } if len(container.hostConfig.DNSOptions) > 0 { dnsOptions = container.hostConfig.DNSOptions } else if len(daemon.configStore.DNSOptions) > 0 { dnsOptions = daemon.configStore.DNSOptions } for _, ds := range dnsOptions { sboxOptions = append(sboxOptions, libnetwork.OptionDNSOptions(ds)) } if container.NetworkSettings.SecondaryIPAddresses != nil { name := container.Config.Hostname if container.Config.Domainname != "" { name = name + "." + container.Config.Domainname } for _, a := range container.NetworkSettings.SecondaryIPAddresses { sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(name, a.Addr)) } } for _, extraHost := range container.hostConfig.ExtraHosts { // allow IPv6 addresses in extra hosts; only split on first ":" parts := strings.SplitN(extraHost, ":", 2) sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(parts[0], parts[1])) } // Link feature is supported only for the default bridge network. // return if this call to build join options is not for default bridge network if n.Name() != "bridge" { return sboxOptions, nil } ep, _ := container.getEndpointInNetwork(n) if ep == nil { return sboxOptions, nil } var childEndpoints, parentEndpoints []string children, err := daemon.children(container.Name) if err != nil { return nil, err } for linkAlias, child := range children { if !isLinkable(child) { return nil, fmt.Errorf("Cannot link to %s, as it does not belong to the default network", child.Name) } _, alias := path.Split(linkAlias) // allow access to the linked container via the alias, real name, and container hostname aliasList := alias + " " + child.Config.Hostname // only add the name if alias isn't equal to the name if alias != child.Name[1:] { aliasList = aliasList + " " + child.Name[1:] } sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.Networks["bridge"].IPAddress)) cEndpoint, _ := child.getEndpointInNetwork(n) if cEndpoint != nil && cEndpoint.ID() != "" { childEndpoints = append(childEndpoints, cEndpoint.ID()) } } bridgeSettings := container.NetworkSettings.Networks["bridge"] refs := daemon.containerGraph().RefPaths(container.ID) for _, ref := range refs { if ref.ParentID == "0" { continue } c, err := daemon.Get(ref.ParentID) if err != nil { logrus.Error(err) } if c != nil && !daemon.configStore.DisableBridge && container.hostConfig.NetworkMode.IsPrivate() { logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", c.ID, ref.Name, bridgeSettings.IPAddress) sboxOptions = append(sboxOptions, libnetwork.OptionParentUpdate(c.ID, ref.Name, bridgeSettings.IPAddress)) if ep.ID() != "" { parentEndpoints = append(parentEndpoints, ep.ID()) } } } linkOptions := options.Generic{ netlabel.GenericData: options.Generic{ "ParentEndpoints": parentEndpoints, "ChildEndpoints": childEndpoints, }, } sboxOptions = append(sboxOptions, libnetwork.OptionGeneric(linkOptions)) return sboxOptions, nil }
func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libnetwork.Network) ([]libnetwork.SandboxOption, error) { var ( sboxOptions []libnetwork.SandboxOption err error dns []string dnsSearch []string dnsOptions []string bindings = make(nat.PortMap) pbList []types.PortBinding exposeList []types.TransportPort ) defaultNetName := runconfig.DefaultDaemonNetworkMode().NetworkName() sboxOptions = append(sboxOptions, libnetwork.OptionHostname(container.Config.Hostname), libnetwork.OptionDomainname(container.Config.Domainname)) if container.HostConfig.NetworkMode.IsHost() { sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox()) sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts")) sboxOptions = append(sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf")) } else if daemon.execDriver.SupportsHooks() { // OptionUseExternalKey is mandatory for userns support. // But optional for non-userns support sboxOptions = append(sboxOptions, libnetwork.OptionUseExternalKey()) } container.HostsPath, err = container.GetRootResourcePath("hosts") if err != nil { return nil, err } sboxOptions = append(sboxOptions, libnetwork.OptionHostsPath(container.HostsPath)) container.ResolvConfPath, err = container.GetRootResourcePath("resolv.conf") if err != nil { return nil, err } sboxOptions = append(sboxOptions, libnetwork.OptionResolvConfPath(container.ResolvConfPath)) if len(container.HostConfig.DNS) > 0 { dns = container.HostConfig.DNS } else if len(daemon.configStore.DNS) > 0 { dns = daemon.configStore.DNS } for _, d := range dns { sboxOptions = append(sboxOptions, libnetwork.OptionDNS(d)) } if len(container.HostConfig.DNSSearch) > 0 { dnsSearch = container.HostConfig.DNSSearch } else if len(daemon.configStore.DNSSearch) > 0 { dnsSearch = daemon.configStore.DNSSearch } for _, ds := range dnsSearch { sboxOptions = append(sboxOptions, libnetwork.OptionDNSSearch(ds)) } if len(container.HostConfig.DNSOptions) > 0 { dnsOptions = container.HostConfig.DNSOptions } else if len(daemon.configStore.DNSOptions) > 0 { dnsOptions = daemon.configStore.DNSOptions } for _, ds := range dnsOptions { sboxOptions = append(sboxOptions, libnetwork.OptionDNSOptions(ds)) } if container.NetworkSettings.SecondaryIPAddresses != nil { name := container.Config.Hostname if container.Config.Domainname != "" { name = name + "." + container.Config.Domainname } for _, a := range container.NetworkSettings.SecondaryIPAddresses { sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(name, a.Addr)) } } for _, extraHost := range container.HostConfig.ExtraHosts { // allow IPv6 addresses in extra hosts; only split on first ":" parts := strings.SplitN(extraHost, ":", 2) sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(parts[0], parts[1])) } if container.HostConfig.PortBindings != nil { for p, b := range container.HostConfig.PortBindings { bindings[p] = []nat.PortBinding{} for _, bb := range b { bindings[p] = append(bindings[p], nat.PortBinding{ HostIP: bb.HostIP, HostPort: bb.HostPort, }) } } } portSpecs := container.Config.ExposedPorts ports := make([]nat.Port, len(portSpecs)) var i int for p := range portSpecs { ports[i] = p i++ } nat.SortPortMap(ports, bindings) for _, port := range ports { expose := types.TransportPort{} expose.Proto = types.ParseProtocol(port.Proto()) expose.Port = uint16(port.Int()) exposeList = append(exposeList, expose) pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto} binding := bindings[port] for i := 0; i < len(binding); i++ { pbCopy := pb.GetCopy() newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort)) var portStart, portEnd int if err == nil { portStart, portEnd, err = newP.Range() } if err != nil { return nil, fmt.Errorf("Error parsing HostPort value(%s):%v", binding[i].HostPort, err) } pbCopy.HostPort = uint16(portStart) pbCopy.HostPortEnd = uint16(portEnd) pbCopy.HostIP = net.ParseIP(binding[i].HostIP) pbList = append(pbList, pbCopy) } if container.HostConfig.PublishAllPorts && len(binding) == 0 { pbList = append(pbList, pb) } } sboxOptions = append(sboxOptions, libnetwork.OptionPortMapping(pbList), libnetwork.OptionExposedPorts(exposeList)) // Link feature is supported only for the default bridge network. // return if this call to build join options is not for default bridge network if n.Name() != defaultNetName { return sboxOptions, nil } ep, _ := container.GetEndpointInNetwork(n) if ep == nil { return sboxOptions, nil } var childEndpoints, parentEndpoints []string children := daemon.children(container) for linkAlias, child := range children { if !isLinkable(child) { return nil, fmt.Errorf("Cannot link to %s, as it does not belong to the default network", child.Name) } _, alias := path.Split(linkAlias) // allow access to the linked container via the alias, real name, and container hostname aliasList := alias + " " + child.Config.Hostname // only add the name if alias isn't equal to the name if alias != child.Name[1:] { aliasList = aliasList + " " + child.Name[1:] } sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.Networks[defaultNetName].IPAddress)) cEndpoint, _ := child.GetEndpointInNetwork(n) if cEndpoint != nil && cEndpoint.ID() != "" { childEndpoints = append(childEndpoints, cEndpoint.ID()) } } bridgeSettings := container.NetworkSettings.Networks[defaultNetName] for alias, parent := range daemon.parents(container) { if daemon.configStore.DisableBridge || !container.HostConfig.NetworkMode.IsPrivate() { continue } _, alias = path.Split(alias) logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", parent.ID, alias, bridgeSettings.IPAddress) sboxOptions = append(sboxOptions, libnetwork.OptionParentUpdate( parent.ID, alias, bridgeSettings.IPAddress, )) if ep.ID() != "" { parentEndpoints = append(parentEndpoints, ep.ID()) } } linkOptions := options.Generic{ netlabel.GenericData: options.Generic{ "ParentEndpoints": parentEndpoints, "ChildEndpoints": childEndpoints, }, } sboxOptions = append(sboxOptions, libnetwork.OptionGeneric(linkOptions)) return sboxOptions, nil }
func externalKeyTest(t *testing.T, reexec bool) { if !testutils.IsRunningInContainer() { defer testutils.SetupTestOSContext(t)() } n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{ netlabel.GenericData: options.Generic{ "BridgeName": "testnetwork", }, }, nil, nil) if err != nil { t.Fatal(err) } defer func() { if err := n.Delete(); err != nil { t.Fatal(err) } }() ep, err := n.CreateEndpoint("ep1") if err != nil { t.Fatal(err) } defer func() { err = ep.Delete() if err != nil { t.Fatal(err) } }() ep2, err := n.CreateEndpoint("ep2") if err != nil { t.Fatal(err) } defer func() { err = ep2.Delete() if err != nil { t.Fatal(err) } }() cnt, err := controller.NewSandbox(containerID, libnetwork.OptionHostname("test"), libnetwork.OptionDomainname("docker.io"), libnetwork.OptionUseExternalKey(), libnetwork.OptionExtraHost("web", "192.168.0.1")) defer func() { if err := cnt.Delete(); err != nil { t.Fatal(err) } osl.GC() }() // Join endpoint to sandbox before SetKey err = ep.Join(cnt) runtime.LockOSThread() if err != nil { t.Fatal(err) } defer func() { err = ep.Leave(cnt) runtime.LockOSThread() if err != nil { t.Fatal(err) } }() sbox := ep.Info().Sandbox() if sbox == nil { t.Fatalf("Expected to have a valid Sandbox") } if reexec { err := reexecSetKey("this-must-fail", containerID, controller.ID()) if err == nil { t.Fatalf("SetExternalKey must fail if the corresponding namespace is not created") } } else { // Setting an non-existing key (namespace) must fail if err := sbox.SetKey("this-must-fail"); err == nil { t.Fatalf("Setkey must fail if the corresponding namespace is not created") } } // Create a new OS sandbox using the osl API before using it in SetKey if extOsBox, err := osl.NewSandbox("ValidKey", true); err != nil { t.Fatalf("Failed to create new osl sandbox") } else { defer func() { if err := extOsBox.Destroy(); err != nil { log.Warnf("Failed to remove os sandbox: %v", err) } }() } if reexec { err := reexecSetKey("ValidKey", containerID, controller.ID()) if err != nil { t.Fatalf("SetExternalKey failed with %v", err) } } else { if err := sbox.SetKey("ValidKey"); err != nil { t.Fatalf("Setkey failed with %v", err) } } // Join endpoint to sandbox after SetKey err = ep2.Join(sbox) if err != nil { t.Fatal(err) } runtime.LockOSThread() defer func() { err = ep2.Leave(sbox) runtime.LockOSThread() if err != nil { t.Fatal(err) } }() if ep.Info().Sandbox().Key() != ep2.Info().Sandbox().Key() { t.Fatalf("ep1 and ep2 returned different container sandbox key") } checkSandbox(t, ep.Info()) }