Merge pull request #110 from aboch/ed

Provide API to retrieve Endpoint operational data
This commit is contained in:
Madhu Venugopal 2015-05-04 16:50:11 -07:00
commit def2a1192f
9 changed files with 193 additions and 0 deletions

View File

@ -61,6 +61,17 @@ There are many networking solutions available to suit a broad range of use-cases
if err != nil {
return
}
// libentwork client can check the endpoint's operational data via the Info() API
epInfo, err := ep.Info()
mapData, ok := epInfo[options.PortMap]
if ok {
portMapping, ok := mapData.([]netutils.PortBinding)
if ok {
fmt.Printf("Current port mapping for endpoint %s: %v", ep.Name(), portMapping)
}
}
```
## Future

View File

@ -1,7 +1,10 @@
package main
import (
"fmt"
"github.com/docker/libnetwork"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/pkg/options"
)
@ -46,4 +49,14 @@ func main() {
if err != nil {
return
}
// libentwork client can check the endpoint's operational data via the Info() API
epInfo, err := ep.Info()
mapData, ok := epInfo[options.PortMap]
if ok {
portMapping, ok := mapData.([]netutils.PortBinding)
if ok {
fmt.Printf("Current port mapping for endpoint %s: %v", ep.Name(), portMapping)
}
}
}

View File

@ -40,6 +40,9 @@ type Driver interface {
// passing the network id and endpoint id.
DeleteEndpoint(nid, eid types.UUID) error
// EndpointInfo retrieves from the driver the operational data related to the specified endpoint
EndpointInfo(nid, eid types.UUID) (map[string]interface{}, error)
// Join method is invoked when a Sandbox is attached to an endpoint.
Join(nid, eid types.UUID, sboxKey string, options map[string]interface{}) error

View File

@ -573,6 +573,46 @@ func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
return nil
}
func (d *driver) EndpointInfo(nid, eid types.UUID) (map[string]interface{}, error) {
// Get the network handler and make sure it exists
d.Lock()
n := d.network
d.Unlock()
if n == nil {
return nil, driverapi.ErrNoNetwork
}
// Sanity check
n.Lock()
if n.id != nid {
n.Unlock()
return nil, InvalidNetworkIDError(nid)
}
n.Unlock()
// Check if endpoint id is good and retrieve correspondent endpoint
ep, err := n.getEndpoint(eid)
if err != nil {
return nil, err
}
if ep == nil {
return nil, driverapi.ErrNoEndpoint
}
m := make(map[string]interface{})
if ep.portMapping != nil {
// Return a copy of the operational data
pmc := make([]netutils.PortBinding, 0, len(ep.portMapping))
for _, pm := range ep.portMapping {
pmc = append(pmc, pm.GetCopy())
}
m[options.PortMap] = pmc
}
return m, nil
}
// Join method is invoked when a Sandbox is attached to an endpoint.
func (d *driver) Join(nid, eid types.UUID, sboxKey string, options map[string]interface{}) error {
var err error

View File

@ -72,6 +72,68 @@ func TestCreateFullOptions(t *testing.T) {
t.Fatalf("Failed to create bridge: %v", err)
}
}
func TestQueryEndpointInfo(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
_, d := New()
config := &Configuration{
BridgeName: DefaultBridgeName,
EnableIPTables: true,
EnableICC: false,
}
genericOption := make(map[string]interface{})
genericOption[options.GenericData] = config
if err := d.Config(genericOption); err != nil {
t.Fatalf("Failed to setup driver config: %v", err)
}
err := d.CreateNetwork("net1", nil)
if err != nil {
t.Fatalf("Failed to create bridge: %v", err)
}
portMappings := getPortMapping()
epOptions := make(map[string]interface{})
epOptions[options.PortMap] = portMappings
_, err = d.CreateEndpoint("net1", "ep1", epOptions)
if err != nil {
t.Fatalf("Failed to create an endpoint : %s", err.Error())
}
dd := d.(*driver)
ep, _ := dd.network.endpoints["ep1"]
data, err := d.EndpointInfo(dd.network.id, ep.id)
if err != nil {
t.Fatalf("Failed to ask for endpoint operational data: %v", err)
}
pmd, ok := data[options.PortMap]
if !ok {
t.Fatalf("Endpoint operational data does not contain port mapping data")
}
pm, ok := pmd.([]netutils.PortBinding)
if !ok {
t.Fatalf("Unexpected format for port mapping in endpoint operational data")
}
if len(ep.portMapping) != len(pm) {
t.Fatalf("Incomplete data for port mapping in endpoint operational data")
}
for i, pb := range ep.portMapping {
if !pb.Equal(&pm[i]) {
t.Fatalf("Unexpected data for port mapping in endpoint operational data")
}
}
// Cleanup as host ports are there
err = releasePorts(ep)
if err != nil {
t.Fatalf("Failed to release mapped ports: %v", err)
}
}
func TestCreateLinkWithOptions(t *testing.T) {
defer netutils.SetupTestNetNS(t)()

View File

@ -35,6 +35,10 @@ func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
return nil
}
func (d *driver) EndpointInfo(nid, eid types.UUID) (map[string]interface{}, error) {
return make(map[string]interface{}, 0), nil
}
// Join method is invoked when a Sandbox is attached to an endpoint.
func (d *driver) Join(nid, eid types.UUID, sboxKey string, options map[string]interface{}) error {
return nil

View File

@ -34,6 +34,9 @@ type Endpoint interface {
// SandboxInfo returns the sandbox information for this endpoint.
SandboxInfo() *sandbox.Info
// Info returns a collection of operational data related to this endpoint retrieved from the driver
Info() (map[string]interface{}, error)
// Delete and detaches this endpoint from the network.
Delete() error
}
@ -94,6 +97,10 @@ func (ep *endpoint) SandboxInfo() *sandbox.Info {
return ep.sandboxInfo.GetCopy()
}
func (ep *endpoint) Info() (map[string]interface{}, error) {
return ep.network.driver.EndpointInfo(ep.network.id, ep.id)
}
func (ep *endpoint) processOptions(options ...EndpointOption) {
for _, opt := range options {
if opt != nil {

View File

@ -131,6 +131,22 @@ func TestBridge(t *testing.T) {
t.Fatal(err)
}
epInfo, err := ep.Info()
if err != nil {
t.Fatal(err)
}
pmd, ok := epInfo[options.PortMap]
if !ok {
t.Fatalf("Could not find expected info in endpoint data")
}
pm, ok := pmd.([]netutils.PortBinding)
if !ok {
t.Fatalf("Unexpected format for port mapping in endpoint operational data")
}
if len(pm) != 3 {
t.Fatalf("Incomplete data for port mapping in endpoint operational data")
}
if err := ep.Delete(); err != nil {
t.Fatal(err)
}

View File

@ -83,6 +83,43 @@ func (p *PortBinding) GetCopy() PortBinding {
}
}
// Equal checks if this instance of PortBinding is equal to the passed one
func (p *PortBinding) Equal(o *PortBinding) bool {
if p == o {
return true
}
if o == nil {
return false
}
if p.Proto != o.Proto || p.Port != o.Port || p.HostPort != o.HostPort {
return false
}
if p.IP != nil {
if !p.IP.Equal(o.IP) {
return false
}
} else {
if o.IP != nil {
return false
}
}
if p.HostIP != nil {
if !p.HostIP.Equal(o.HostIP) {
return false
}
} else {
if o.HostIP != nil {
return false
}
}
return true
}
const (
// ICMP is for the ICMP ip protocol
ICMP = 1