Service discovery
Add a minimal service discover support using service names or service names qualified with network name. This is achieved by populating the container's /etc/hosts file record with the appropriate entries Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
This commit is contained in:
parent
362568467d
commit
271bcd7ba1
3 changed files with 100 additions and 0 deletions
|
@ -284,6 +284,7 @@ func (c *controller) addNetwork(n *network) error {
|
|||
}
|
||||
|
||||
n.Lock()
|
||||
n.svcRecords = svcMap{}
|
||||
n.driver = dd.driver
|
||||
d := n.driver
|
||||
n.Unlock()
|
||||
|
|
|
@ -571,9 +571,39 @@ func (ep *endpoint) deleteEndpoint() error {
|
|||
}
|
||||
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
|
||||
|
||||
|
@ -581,6 +611,7 @@ func (ep *endpoint) buildHostsFiles() error {
|
|||
container := ep.container
|
||||
joinInfo := ep.joinInfo
|
||||
ifaces := ep.iFaces
|
||||
n := ep.network
|
||||
ep.Unlock()
|
||||
|
||||
if container == nil {
|
||||
|
@ -613,6 +644,8 @@ func (ep *endpoint) buildHostsFiles() error {
|
|||
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()
|
||||
|
|
|
@ -2,6 +2,7 @@ package libnetwork
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
|
@ -9,6 +10,7 @@ import (
|
|||
"github.com/docker/libnetwork/config"
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/etchosts"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/options"
|
||||
"github.com/docker/libnetwork/types"
|
||||
|
@ -51,6 +53,8 @@ type Network interface {
|
|||
// When the function returns true, the walk will stop.
|
||||
type EndpointWalker func(ep Endpoint) bool
|
||||
|
||||
type svcMap map[string]net.IP
|
||||
|
||||
type network struct {
|
||||
ctrlr *controller
|
||||
name string
|
||||
|
@ -62,6 +66,7 @@ type network struct {
|
|||
endpoints endpointTable
|
||||
generic options.Generic
|
||||
dbIndex uint64
|
||||
svcRecords svcMap
|
||||
stopWatchCh chan struct{}
|
||||
sync.Mutex
|
||||
}
|
||||
|
@ -272,6 +277,8 @@ func (n *network) addEndpoint(ep *endpoint) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n.updateSvcRecord(ep, true)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -384,3 +391,62 @@ func (n *network) isGlobalScoped() (bool, error) {
|
|||
n.Unlock()
|
||||
return c.isDriverGlobalScoped(n.networkType)
|
||||
}
|
||||
|
||||
func (n *network) updateSvcRecord(ep *endpoint, isAdd bool) {
|
||||
n.Lock()
|
||||
var recs []etchosts.Record
|
||||
for _, iface := range ep.InterfaceList() {
|
||||
if isAdd {
|
||||
n.svcRecords[ep.Name()] = iface.Address().IP
|
||||
n.svcRecords[ep.Name()+"."+n.name] = iface.Address().IP
|
||||
} else {
|
||||
delete(n.svcRecords, ep.Name())
|
||||
delete(n.svcRecords, ep.Name()+"."+n.name)
|
||||
}
|
||||
|
||||
recs = append(recs, etchosts.Record{
|
||||
Hosts: ep.Name(),
|
||||
IP: iface.Address().IP.String(),
|
||||
})
|
||||
|
||||
recs = append(recs, etchosts.Record{
|
||||
Hosts: ep.Name() + "." + n.name,
|
||||
IP: iface.Address().IP.String(),
|
||||
})
|
||||
}
|
||||
n.Unlock()
|
||||
|
||||
var epList []*endpoint
|
||||
n.WalkEndpoints(func(e Endpoint) bool {
|
||||
cEp := e.(*endpoint)
|
||||
cEp.Lock()
|
||||
if cEp.container != nil {
|
||||
epList = append(epList, cEp)
|
||||
}
|
||||
cEp.Unlock()
|
||||
return false
|
||||
})
|
||||
|
||||
for _, cEp := range epList {
|
||||
if isAdd {
|
||||
cEp.addHostEntries(recs)
|
||||
} else {
|
||||
cEp.deleteHostEntries(recs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (n *network) getSvcRecords() []etchosts.Record {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
var recs []etchosts.Record
|
||||
for h, ip := range n.svcRecords {
|
||||
recs = append(recs, etchosts.Record{
|
||||
Hosts: h,
|
||||
IP: ip.String(),
|
||||
})
|
||||
}
|
||||
|
||||
return recs
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue