123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950 |
- package libnetwork
- import (
- "bytes"
- "encoding/json"
- "fmt"
- "io/ioutil"
- "os"
- "path"
- "path/filepath"
- "sync"
- log "github.com/Sirupsen/logrus"
- "github.com/docker/docker/pkg/ioutils"
- "github.com/docker/libnetwork/datastore"
- "github.com/docker/libnetwork/etchosts"
- "github.com/docker/libnetwork/netlabel"
- "github.com/docker/libnetwork/resolvconf"
- "github.com/docker/libnetwork/sandbox"
- "github.com/docker/libnetwork/types"
- )
- // Endpoint represents a logical connection between a network and a sandbox.
- type Endpoint interface {
- // A system generated id for this endpoint.
- ID() string
- // Name returns the name of this endpoint.
- Name() string
- // Network returns the name of the network to which this endpoint is attached.
- Network() string
- // Join creates a new sandbox for the given container ID and populates the
- // network resources allocated for the endpoint and joins the sandbox to
- // the endpoint.
- Join(containerID string, options ...EndpointOption) error
- // Leave removes the sandbox associated with container ID and detaches
- // the network resources populated in the sandbox
- Leave(containerID string, options ...EndpointOption) error
- // Return certain operational data belonging to this endpoint
- Info() EndpointInfo
- // DriverInfo returns a collection of driver operational data related to this endpoint retrieved from the driver
- DriverInfo() (map[string]interface{}, error)
- // ContainerInfo returns the info available at the endpoint about the attached container
- ContainerInfo() ContainerInfo
- // Delete and detaches this endpoint from the network.
- Delete() error
- }
- // EndpointOption is a option setter function type used to pass varios options to Network
- // and Endpoint interfaces methods. The various setter functions of type EndpointOption are
- // provided by libnetwork, they look like <Create|Join|Leave>Option[...](...)
- type EndpointOption func(ep *endpoint)
- // ContainerData is a set of data returned when a container joins an endpoint.
- type ContainerData struct {
- SandboxKey string
- }
- // These are the container configs used to customize container /etc/hosts file.
- type hostsPathConfig struct {
- hostName string
- domainName string
- hostsPath string
- extraHosts []extraHost
- parentUpdates []parentUpdate
- }
- // These are the container configs used to customize container /etc/resolv.conf file.
- type resolvConfPathConfig struct {
- resolvConfPath string
- dnsList []string
- dnsSearchList []string
- }
- type containerConfig struct {
- hostsPathConfig
- resolvConfPathConfig
- generic map[string]interface{}
- useDefaultSandBox bool
- prio int // higher the value, more the priority
- }
- type extraHost struct {
- name string
- IP string
- }
- type parentUpdate struct {
- eid string
- name string
- ip string
- }
- type containerInfo struct {
- id string
- config containerConfig
- data ContainerData
- sync.Mutex
- }
- func (ci *containerInfo) ID() string {
- return ci.id
- }
- func (ci *containerInfo) Labels() map[string]interface{} {
- return ci.config.generic
- }
- type endpoint struct {
- name string
- id types.UUID
- network *network
- iFaces []*endpointInterface
- joinInfo *endpointJoinInfo
- container *containerInfo
- exposedPorts []types.TransportPort
- generic map[string]interface{}
- joinLeaveDone chan struct{}
- dbIndex uint64
- dbExists bool
- sync.Mutex
- }
- func (ci *containerInfo) MarshalJSON() ([]byte, error) {
- ci.Lock()
- defer ci.Unlock()
- // We are just interested in the container ID. This can be expanded to include all of containerInfo if there is a need
- return json.Marshal(ci.id)
- }
- func (ci *containerInfo) UnmarshalJSON(b []byte) (err error) {
- ci.Lock()
- defer ci.Unlock()
- var id string
- if err := json.Unmarshal(b, &id); err != nil {
- return err
- }
- ci.id = id
- return nil
- }
- func (ep *endpoint) MarshalJSON() ([]byte, error) {
- ep.Lock()
- defer ep.Unlock()
- epMap := make(map[string]interface{})
- epMap["name"] = ep.name
- epMap["id"] = string(ep.id)
- epMap["ep_iface"] = ep.iFaces
- epMap["exposed_ports"] = ep.exposedPorts
- epMap["generic"] = ep.generic
- if ep.container != nil {
- epMap["container"] = ep.container
- }
- return json.Marshal(epMap)
- }
- func (ep *endpoint) UnmarshalJSON(b []byte) (err error) {
- ep.Lock()
- defer ep.Unlock()
- var epMap map[string]interface{}
- if err := json.Unmarshal(b, &epMap); err != nil {
- return err
- }
- ep.name = epMap["name"].(string)
- ep.id = types.UUID(epMap["id"].(string))
- ib, _ := json.Marshal(epMap["ep_iface"])
- var ifaces []endpointInterface
- json.Unmarshal(ib, &ifaces)
- ep.iFaces = make([]*endpointInterface, 0)
- for _, iface := range ifaces {
- ep.iFaces = append(ep.iFaces, &iface)
- }
- tb, _ := json.Marshal(epMap["exposed_ports"])
- var tPorts []types.TransportPort
- json.Unmarshal(tb, &tPorts)
- ep.exposedPorts = tPorts
- epc, ok := epMap["container"]
- if ok {
- cb, _ := json.Marshal(epc)
- var cInfo containerInfo
- json.Unmarshal(cb, &cInfo)
- ep.container = &cInfo
- }
- if epMap["generic"] != nil {
- ep.generic = epMap["generic"].(map[string]interface{})
- }
- return nil
- }
- const defaultPrefix = "/var/lib/docker/network/files"
- func (ep *endpoint) ID() string {
- ep.Lock()
- defer ep.Unlock()
- return string(ep.id)
- }
- func (ep *endpoint) Name() string {
- ep.Lock()
- defer ep.Unlock()
- return ep.name
- }
- func (ep *endpoint) Network() string {
- ep.Lock()
- defer ep.Unlock()
- return ep.network.name
- }
- // endpoint Key structure : endpoint/network-id/endpoint-id
- func (ep *endpoint) Key() []string {
- ep.Lock()
- n := ep.network
- defer ep.Unlock()
- return []string{datastore.EndpointKeyPrefix, string(n.id), string(ep.id)}
- }
- func (ep *endpoint) KeyPrefix() []string {
- ep.Lock()
- n := ep.network
- defer ep.Unlock()
- return []string{datastore.EndpointKeyPrefix, string(n.id)}
- }
- func (ep *endpoint) networkIDFromKey(key []string) (types.UUID, error) {
- // endpoint Key structure : endpoint/network-id/endpoint-id
- // its an invalid key if the key doesnt have all the 3 key elements above
- if key == nil || len(key) < 3 || key[0] != datastore.EndpointKeyPrefix {
- return types.UUID(""), fmt.Errorf("invalid endpoint key : %v", key)
- }
- // network-id is placed at index=1. pls refer to endpoint.Key() method
- return types.UUID(key[1]), nil
- }
- func (ep *endpoint) Value() []byte {
- b, err := json.Marshal(ep)
- if err != nil {
- return nil
- }
- return b
- }
- func (ep *endpoint) SetValue(value []byte) error {
- return json.Unmarshal(value, ep)
- }
- func (ep *endpoint) Index() uint64 {
- ep.Lock()
- defer ep.Unlock()
- return ep.dbIndex
- }
- func (ep *endpoint) SetIndex(index uint64) {
- ep.Lock()
- defer ep.Unlock()
- ep.dbIndex = index
- ep.dbExists = true
- }
- func (ep *endpoint) Exists() bool {
- ep.Lock()
- defer ep.Unlock()
- return ep.dbExists
- }
- func (ep *endpoint) processOptions(options ...EndpointOption) {
- ep.Lock()
- defer ep.Unlock()
- for _, opt := range options {
- if opt != nil {
- opt(ep)
- }
- }
- }
- func createBasePath(dir string) error {
- err := os.MkdirAll(dir, 0644)
- if err != nil && !os.IsExist(err) {
- return err
- }
- return nil
- }
- func createFile(path string) error {
- var f *os.File
- dir, _ := filepath.Split(path)
- err := createBasePath(dir)
- if err != nil {
- return err
- }
- f, err = os.Create(path)
- if err == nil {
- f.Close()
- }
- return err
- }
- // joinLeaveStart waits to ensure there are no joins or leaves in progress and
- // marks this join/leave in progress without race
- func (ep *endpoint) joinLeaveStart() {
- ep.Lock()
- defer ep.Unlock()
- for ep.joinLeaveDone != nil {
- joinLeaveDone := ep.joinLeaveDone
- ep.Unlock()
- select {
- case <-joinLeaveDone:
- }
- ep.Lock()
- }
- ep.joinLeaveDone = make(chan struct{})
- }
- // joinLeaveEnd marks the end of this join/leave operation and
- // signals the same without race to other join and leave waiters
- func (ep *endpoint) joinLeaveEnd() {
- ep.Lock()
- defer ep.Unlock()
- if ep.joinLeaveDone != nil {
- close(ep.joinLeaveDone)
- ep.joinLeaveDone = nil
- }
- }
- func (ep *endpoint) Join(containerID string, options ...EndpointOption) error {
- var err error
- if containerID == "" {
- return InvalidContainerIDError(containerID)
- }
- ep.joinLeaveStart()
- defer func() {
- ep.joinLeaveEnd()
- }()
- ep.Lock()
- if ep.container != nil {
- ep.Unlock()
- return ErrInvalidJoin{}
- }
- ep.container = &containerInfo{
- id: containerID,
- config: containerConfig{
- hostsPathConfig: hostsPathConfig{
- extraHosts: []extraHost{},
- parentUpdates: []parentUpdate{},
- },
- }}
- ep.joinInfo = &endpointJoinInfo{}
- container := ep.container
- network := ep.network
- epid := ep.id
- ep.Unlock()
- defer func() {
- if err != nil {
- ep.Lock()
- ep.container = nil
- ep.Unlock()
- }
- }()
- network.Lock()
- driver := network.driver
- nid := network.id
- ctrlr := network.ctrlr
- network.Unlock()
- ep.processOptions(options...)
- sboxKey := sandbox.GenerateKey(containerID)
- if container.config.useDefaultSandBox {
- sboxKey = sandbox.GenerateKey("default")
- }
- err = driver.Join(nid, epid, sboxKey, ep, container.config.generic)
- if err != nil {
- return err
- }
- defer func() {
- if err != nil {
- if err = driver.Leave(nid, epid); err != nil {
- log.Warnf("driver leave failed while rolling back join: %v", err)
- }
- }
- }()
- err = ep.buildHostsFiles()
- if err != nil {
- return err
- }
- err = ep.updateParentHosts()
- if err != nil {
- return err
- }
- err = ep.setupDNS()
- if err != nil {
- return err
- }
- sb, err := ctrlr.sandboxAdd(sboxKey, !container.config.useDefaultSandBox, ep)
- if err != nil {
- return fmt.Errorf("failed sandbox add: %v", err)
- }
- defer func() {
- if err != nil {
- ctrlr.sandboxRm(sboxKey, ep)
- }
- }()
- if err := network.ctrlr.updateEndpointToStore(ep); err != nil {
- return err
- }
- container.data.SandboxKey = sb.Key()
- return nil
- }
- func (ep *endpoint) hasInterface(iName string) bool {
- ep.Lock()
- defer ep.Unlock()
- for _, iface := range ep.iFaces {
- if iface.srcName == iName {
- return true
- }
- }
- return false
- }
- func (ep *endpoint) Leave(containerID string, options ...EndpointOption) error {
- var err error
- ep.joinLeaveStart()
- defer ep.joinLeaveEnd()
- ep.processOptions(options...)
- ep.Lock()
- container := ep.container
- n := ep.network
- if container == nil || container.id == "" || container.data.SandboxKey == "" ||
- containerID == "" || container.id != containerID {
- if container == nil {
- err = ErrNoContainer{}
- } else {
- err = InvalidContainerIDError(containerID)
- }
- ep.Unlock()
- return err
- }
- ep.container = nil
- ep.Unlock()
- n.Lock()
- driver := n.driver
- ctrlr := n.ctrlr
- n.Unlock()
- if err := ctrlr.updateEndpointToStore(ep); err != nil {
- ep.Lock()
- ep.container = container
- ep.Unlock()
- return err
- }
- err = driver.Leave(n.id, ep.id)
- ctrlr.sandboxRm(container.data.SandboxKey, ep)
- return err
- }
- func (ep *endpoint) Delete() error {
- var err error
- ep.Lock()
- epid := ep.id
- name := ep.name
- n := ep.network
- if ep.container != nil {
- ep.Unlock()
- return &ActiveContainerError{name: name, id: string(epid)}
- }
- n.Lock()
- ctrlr := n.ctrlr
- n.Unlock()
- ep.Unlock()
- if err = ctrlr.deleteEndpointFromStore(ep); err != nil {
- return err
- }
- defer func() {
- if err != nil {
- ep.SetIndex(0)
- if e := ctrlr.updateEndpointToStore(ep); e != nil {
- log.Warnf("failed to recreate endpoint in store %s : %v", name, err)
- }
- }
- }()
- // Update the endpoint count in network and update it in the datastore
- n.DecEndpointCnt()
- if err = ctrlr.updateNetworkToStore(n); err != nil {
- return err
- }
- defer func() {
- if err != nil {
- n.IncEndpointCnt()
- if e := ctrlr.updateNetworkToStore(n); e != nil {
- log.Warnf("failed to update network %s : %v", n.name, e)
- }
- }
- }()
- if err = ep.deleteEndpoint(); err != nil {
- return err
- }
- return nil
- }
- func (ep *endpoint) deleteEndpoint() error {
- ep.Lock()
- n := ep.network
- name := ep.name
- epid := ep.id
- ep.Unlock()
- n.Lock()
- _, ok := n.endpoints[epid]
- if !ok {
- n.Unlock()
- return nil
- }
- nid := n.id
- driver := n.driver
- delete(n.endpoints, epid)
- n.Unlock()
- if err := driver.DeleteEndpoint(nid, epid); err != nil {
- if _, ok := err.(types.ForbiddenError); ok {
- n.Lock()
- n.endpoints[epid] = ep
- n.Unlock()
- return err
- }
- log.Warnf("driver error deleting endpoint %s : %v", name, err)
- }
- n.updateSvcRecord(ep, false)
- return nil
- }
- func (ep *endpoint) addHostEntries(recs []etchosts.Record) {
- ep.Lock()
- container := ep.container
- ep.Unlock()
- if container == nil {
- return
- }
- if err := etchosts.Add(container.config.hostsPath, recs); err != nil {
- log.Warnf("Failed adding service host entries to the running container: %v", err)
- }
- }
- func (ep *endpoint) deleteHostEntries(recs []etchosts.Record) {
- ep.Lock()
- container := ep.container
- ep.Unlock()
- if container == nil {
- return
- }
- if err := etchosts.Delete(container.config.hostsPath, recs); err != nil {
- log.Warnf("Failed deleting service host entries to the running container: %v", err)
- }
- }
- func (ep *endpoint) buildHostsFiles() error {
- var extraContent []etchosts.Record
- ep.Lock()
- container := ep.container
- joinInfo := ep.joinInfo
- ifaces := ep.iFaces
- n := ep.network
- ep.Unlock()
- if container == nil {
- return ErrNoContainer{}
- }
- if container.config.hostsPath == "" {
- container.config.hostsPath = defaultPrefix + "/" + container.id + "/hosts"
- }
- dir, _ := filepath.Split(container.config.hostsPath)
- err := createBasePath(dir)
- if err != nil {
- return err
- }
- if joinInfo != nil && joinInfo.hostsPath != "" {
- content, err := ioutil.ReadFile(joinInfo.hostsPath)
- if err != nil && !os.IsNotExist(err) {
- return err
- }
- if err == nil {
- return ioutil.WriteFile(container.config.hostsPath, content, 0644)
- }
- }
- for _, extraHost := range container.config.extraHosts {
- extraContent = append(extraContent,
- etchosts.Record{Hosts: extraHost.name, IP: extraHost.IP})
- }
- extraContent = append(extraContent, n.getSvcRecords()...)
- IP := ""
- if len(ifaces) != 0 && ifaces[0] != nil {
- IP = ifaces[0].addr.IP.String()
- }
- return etchosts.Build(container.config.hostsPath, IP, container.config.hostName,
- container.config.domainName, extraContent)
- }
- func (ep *endpoint) updateParentHosts() error {
- ep.Lock()
- container := ep.container
- network := ep.network
- ep.Unlock()
- if container == nil {
- return ErrNoContainer{}
- }
- for _, update := range container.config.parentUpdates {
- network.Lock()
- pep, ok := network.endpoints[types.UUID(update.eid)]
- if !ok {
- network.Unlock()
- continue
- }
- network.Unlock()
- pep.Lock()
- pContainer := pep.container
- pep.Unlock()
- if pContainer != nil {
- if err := etchosts.Update(pContainer.config.hostsPath, update.ip, update.name); err != nil {
- return err
- }
- }
- }
- return nil
- }
- func (ep *endpoint) updateDNS(resolvConf []byte) error {
- ep.Lock()
- container := ep.container
- network := ep.network
- ep.Unlock()
- if container == nil {
- return ErrNoContainer{}
- }
- oldHash := []byte{}
- hashFile := container.config.resolvConfPath + ".hash"
- resolvBytes, err := ioutil.ReadFile(container.config.resolvConfPath)
- if err != nil {
- if !os.IsNotExist(err) {
- return err
- }
- } else {
- oldHash, err = ioutil.ReadFile(hashFile)
- if err != nil {
- if !os.IsNotExist(err) {
- return err
- }
- oldHash = []byte{}
- }
- }
- curHash, err := ioutils.HashData(bytes.NewReader(resolvBytes))
- if err != nil {
- return err
- }
- if string(oldHash) != "" && curHash != string(oldHash) {
- // Seems the user has changed the container resolv.conf since the last time
- // we checked so return without doing anything.
- return nil
- }
- // replace any localhost/127.* and remove IPv6 nameservers if IPv6 disabled.
- resolvConf, _ = resolvconf.FilterResolvDNS(resolvConf, network.enableIPv6)
- newHash, err := ioutils.HashData(bytes.NewReader(resolvConf))
- if err != nil {
- return err
- }
- // for atomic updates to these files, use temporary files with os.Rename:
- dir := path.Dir(container.config.resolvConfPath)
- tmpHashFile, err := ioutil.TempFile(dir, "hash")
- if err != nil {
- return err
- }
- tmpResolvFile, err := ioutil.TempFile(dir, "resolv")
- if err != nil {
- return err
- }
- // Change the perms to 0644 since ioutil.TempFile creates it by default as 0600
- if err := os.Chmod(tmpResolvFile.Name(), 0644); err != nil {
- return err
- }
- // write the updates to the temp files
- if err = ioutil.WriteFile(tmpHashFile.Name(), []byte(newHash), 0644); err != nil {
- return err
- }
- if err = ioutil.WriteFile(tmpResolvFile.Name(), resolvConf, 0644); err != nil {
- return err
- }
- // rename the temp files for atomic replace
- if err = os.Rename(tmpHashFile.Name(), hashFile); err != nil {
- return err
- }
- return os.Rename(tmpResolvFile.Name(), container.config.resolvConfPath)
- }
- func (ep *endpoint) setupDNS() error {
- ep.Lock()
- container := ep.container
- ep.Unlock()
- if container == nil {
- return ErrNoContainer{}
- }
- if container.config.resolvConfPath == "" {
- container.config.resolvConfPath = defaultPrefix + "/" + container.id + "/resolv.conf"
- }
- dir, _ := filepath.Split(container.config.resolvConfPath)
- err := createBasePath(dir)
- if err != nil {
- return err
- }
- resolvConf, err := resolvconf.Get()
- if err != nil {
- return err
- }
- if len(container.config.dnsList) > 0 ||
- len(container.config.dnsSearchList) > 0 {
- var (
- dnsList = resolvconf.GetNameservers(resolvConf)
- dnsSearchList = resolvconf.GetSearchDomains(resolvConf)
- )
- if len(container.config.dnsList) > 0 {
- dnsList = container.config.dnsList
- }
- if len(container.config.dnsSearchList) > 0 {
- dnsSearchList = container.config.dnsSearchList
- }
- return resolvconf.Build(container.config.resolvConfPath, dnsList, dnsSearchList)
- }
- return ep.updateDNS(resolvConf)
- }
- // EndpointOptionGeneric function returns an option setter for a Generic option defined
- // in a Dictionary of Key-Value pair
- func EndpointOptionGeneric(generic map[string]interface{}) EndpointOption {
- return func(ep *endpoint) {
- for k, v := range generic {
- ep.generic[k] = v
- }
- }
- }
- // JoinOptionPriority function returns an option setter for priority option to
- // be passed to endpoint Join method.
- func JoinOptionPriority(prio int) EndpointOption {
- return func(ep *endpoint) {
- ep.container.config.prio = prio
- }
- }
- // JoinOptionHostname function returns an option setter for hostname option to
- // be passed to endpoint Join method.
- func JoinOptionHostname(name string) EndpointOption {
- return func(ep *endpoint) {
- ep.container.config.hostName = name
- }
- }
- // JoinOptionDomainname function returns an option setter for domainname option to
- // be passed to endpoint Join method.
- func JoinOptionDomainname(name string) EndpointOption {
- return func(ep *endpoint) {
- ep.container.config.domainName = name
- }
- }
- // JoinOptionHostsPath function returns an option setter for hostspath option to
- // be passed to endpoint Join method.
- func JoinOptionHostsPath(path string) EndpointOption {
- return func(ep *endpoint) {
- ep.container.config.hostsPath = path
- }
- }
- // JoinOptionExtraHost function returns an option setter for extra /etc/hosts options
- // which is a name and IP as strings.
- func JoinOptionExtraHost(name string, IP string) EndpointOption {
- return func(ep *endpoint) {
- ep.container.config.extraHosts = append(ep.container.config.extraHosts, extraHost{name: name, IP: IP})
- }
- }
- // JoinOptionParentUpdate function returns an option setter for parent container
- // which needs to update the IP address for the linked container.
- func JoinOptionParentUpdate(eid string, name, ip string) EndpointOption {
- return func(ep *endpoint) {
- ep.container.config.parentUpdates = append(ep.container.config.parentUpdates, parentUpdate{eid: eid, name: name, ip: ip})
- }
- }
- // JoinOptionResolvConfPath function returns an option setter for resolvconfpath option to
- // be passed to endpoint Join method.
- func JoinOptionResolvConfPath(path string) EndpointOption {
- return func(ep *endpoint) {
- ep.container.config.resolvConfPath = path
- }
- }
- // JoinOptionDNS function returns an option setter for dns entry option to
- // be passed to endpoint Join method.
- func JoinOptionDNS(dns string) EndpointOption {
- return func(ep *endpoint) {
- ep.container.config.dnsList = append(ep.container.config.dnsList, dns)
- }
- }
- // JoinOptionDNSSearch function returns an option setter for dns search entry option to
- // be passed to endpoint Join method.
- func JoinOptionDNSSearch(search string) EndpointOption {
- return func(ep *endpoint) {
- ep.container.config.dnsSearchList = append(ep.container.config.dnsSearchList, search)
- }
- }
- // JoinOptionUseDefaultSandbox function returns an option setter for using default sandbox to
- // be passed to endpoint Join method.
- func JoinOptionUseDefaultSandbox() EndpointOption {
- return func(ep *endpoint) {
- ep.container.config.useDefaultSandBox = true
- }
- }
- // CreateOptionExposedPorts function returns an option setter for the container exposed
- // ports option to be passed to network.CreateEndpoint() method.
- func CreateOptionExposedPorts(exposedPorts []types.TransportPort) EndpointOption {
- return func(ep *endpoint) {
- // Defensive copy
- eps := make([]types.TransportPort, len(exposedPorts))
- copy(eps, exposedPorts)
- // Store endpoint label and in generic because driver needs it
- ep.exposedPorts = eps
- ep.generic[netlabel.ExposedPorts] = eps
- }
- }
- // CreateOptionPortMapping function returns an option setter for the mapping
- // ports option to be passed to network.CreateEndpoint() method.
- func CreateOptionPortMapping(portBindings []types.PortBinding) EndpointOption {
- return func(ep *endpoint) {
- // Store a copy of the bindings as generic data to pass to the driver
- pbs := make([]types.PortBinding, len(portBindings))
- copy(pbs, portBindings)
- ep.generic[netlabel.PortMap] = pbs
- }
- }
- // JoinOptionGeneric function returns an option setter for Generic configuration
- // that is not managed by libNetwork but can be used by the Drivers during the call to
- // endpoint join method. Container Labels are a good example.
- func JoinOptionGeneric(generic map[string]interface{}) EndpointOption {
- return func(ep *endpoint) {
- ep.container.config.generic = generic
- }
- }
|