dotcloud/docker

View on GitHub
libnetwork/drvregistry/ipams.go

Summary

Maintainability
A
1 hr
Test Coverage
package drvregistry

import (
    "errors"
    "strings"
    "sync"

    "github.com/docker/docker/libnetwork/ipamapi"
    "github.com/docker/docker/libnetwork/types"
)

type ipamDriver struct {
    driver     ipamapi.Ipam
    capability *ipamapi.Capability
}

// IPAMs is a registry of IPAM drivers. The zero value is an empty IPAM driver
// registry, ready to use.
type IPAMs struct {
    mu      sync.Mutex
    drivers map[string]ipamDriver
}

var _ ipamapi.Registerer = (*IPAMs)(nil)

// IPAM returns the actual IPAM driver instance and its capability which registered with the passed name.
func (ir *IPAMs) IPAM(name string) (ipamapi.Ipam, *ipamapi.Capability) {
    ir.mu.Lock()
    defer ir.mu.Unlock()

    d := ir.drivers[name]
    return d.driver, d.capability
}

// RegisterIpamDriverWithCapabilities registers the IPAM driver discovered with specified capabilities.
func (ir *IPAMs) RegisterIpamDriverWithCapabilities(name string, driver ipamapi.Ipam, caps *ipamapi.Capability) error {
    if strings.TrimSpace(name) == "" {
        return errors.New("ipam driver name string cannot be empty")
    }

    ir.mu.Lock()
    defer ir.mu.Unlock()

    dd, ok := ir.drivers[name]
    if ok && dd.driver.IsBuiltIn() {
        return types.ForbiddenErrorf("ipam driver %q already registered", name)
    }

    if ir.drivers == nil {
        ir.drivers = make(map[string]ipamDriver)
    }
    ir.drivers[name] = ipamDriver{driver: driver, capability: caps}

    return nil
}

// RegisterIpamDriver registers the IPAM driver discovered with default capabilities.
func (ir *IPAMs) RegisterIpamDriver(name string, driver ipamapi.Ipam) error {
    return ir.RegisterIpamDriverWithCapabilities(name, driver, &ipamapi.Capability{})
}

// IPAMWalkFunc defines the IPAM driver table walker function signature.
type IPAMWalkFunc func(name string, driver ipamapi.Ipam, cap *ipamapi.Capability) bool

// WalkIPAMs walks the IPAM drivers registered in the registry and invokes the passed walk function and each one of them.
func (ir *IPAMs) WalkIPAMs(ifn IPAMWalkFunc) {
    type ipamVal struct {
        name string
        data ipamDriver
    }

    ir.mu.Lock()
    ivl := make([]ipamVal, 0, len(ir.drivers))
    for k, v := range ir.drivers {
        ivl = append(ivl, ipamVal{name: k, data: v})
    }
    ir.mu.Unlock()

    for _, iv := range ivl {
        if ifn(iv.name, iv.data.driver, iv.data.capability) {
            break
        }
    }
}