azure-container-networking/ipam/manager_test.go

374 строки
9.8 KiB
Go

// Copyright 2017 Microsoft. All rights reserved.
// MIT License
package ipam
import (
"fmt"
"net"
"testing"
"github.com/Azure/azure-container-networking/common"
)
var (
anyInterface = "any"
anyPriority = 42
// Pools and addresses used by tests.
subnet1 = net.IPNet{IP: net.IPv4(10, 0, 1, 0), Mask: net.IPv4Mask(255, 255, 255, 0)}
addr11 = net.IPv4(10, 0, 1, 1)
addr12 = net.IPv4(10, 0, 1, 2)
addr13 = net.IPv4(10, 0, 1, 3)
subnet2 = net.IPNet{IP: net.IPv4(10, 0, 2, 0), Mask: net.IPv4Mask(255, 255, 255, 0)}
addr21 = net.IPv4(10, 0, 2, 1)
addr22 = net.IPv4(10, 0, 2, 2)
addr23 = net.IPv4(10, 0, 2, 3)
subnet3 = net.IPNet{IP: net.IPv4(10, 0, 3, 0), Mask: net.IPv4Mask(255, 255, 255, 0)}
addr31 = net.IPv4(10, 0, 3, 1)
addr32 = net.IPv4(10, 0, 3, 2)
addr33 = net.IPv4(10, 0, 3, 3)
)
// createAddressManager creates an address manager with a simple test configuration.
func createAddressManager() (AddressManager, error) {
var config common.PluginConfig
var options map[string]interface{}
am, err := NewAddressManager()
if err != nil {
return nil, err
}
err = am.Initialize(&config, options)
if err != nil {
return nil, err
}
err = setupTestAddressSpace(am)
if err != nil {
return nil, err
}
return am, nil
}
// dumpAddressManager dumps the contents of an address manager.
func dumpAddressManager(am AddressManager) {
amImpl := am.(*addressManager)
fmt.Printf("AddressManager:%+v\n", amImpl)
for sk, sv := range amImpl.AddrSpaces {
fmt.Printf("AddressSpace %v:%+v\n", sk, sv)
for pk, pv := range sv.Pools {
fmt.Printf("\tPool %v:%+v\n", pk, pv)
for ak, av := range pv.Addresses {
fmt.Printf("\t\tAddress %v:%+v\n", ak, av)
}
}
}
}
// setupTestAddressSpace creates a simple address space used by various tests.
func setupTestAddressSpace(am AddressManager) error {
var anyInterface = "any"
var anyPriority = 42
amImpl := am.(*addressManager)
// Configure an empty global address space.
globalAs, err := amImpl.newAddressSpace(GlobalDefaultAddressSpaceId, GlobalScope)
if err != nil {
return err
}
err = amImpl.setAddressSpace(globalAs)
if err != nil {
return err
}
// Configure a local address space.
localAs, err := amImpl.newAddressSpace(LocalDefaultAddressSpaceId, LocalScope)
if err != nil {
return err
}
// Add subnet1 with addresses addr11 and addr12.
ap, err := localAs.newAddressPool(anyInterface, anyPriority, &subnet1)
ap.newAddressRecord(&addr11)
ap.newAddressRecord(&addr12)
// Add subnet2 with addr21.
ap, err = localAs.newAddressPool(anyInterface, anyPriority, &subnet2)
ap.newAddressRecord(&addr21)
amImpl.setAddressSpace(localAs)
return nil
}
// cleanupTestAddressSpace deletes any existing address spaces.
func cleanupTestAddressSpace(am AddressManager) error {
amImpl := am.(*addressManager)
// Configure an empty local address space.
localAs, err := amImpl.newAddressSpace(LocalDefaultAddressSpaceId, LocalScope)
if err != nil {
return err
}
err = amImpl.setAddressSpace(localAs)
if err != nil {
return err
}
// Configure an empty global address space.
globalAs, err := amImpl.newAddressSpace(GlobalDefaultAddressSpaceId, GlobalScope)
if err != nil {
return err
}
err = amImpl.setAddressSpace(globalAs)
if err != nil {
return err
}
return nil
}
//
// Address manager tests.
//
// Tests address spaces are created and queried correctly.
func TestAddressSpaceCreateAndGet(t *testing.T) {
// Start with the test address space.
am, err := createAddressManager()
if err != nil {
t.Fatalf("createAddressManager failed, err:%+v.", err)
}
// Test if the address spaces are returned correctly.
local, global := am.GetDefaultAddressSpaces()
if local != LocalDefaultAddressSpaceId {
t.Errorf("GetDefaultAddressSpaces returned invalid local address space.")
}
if global != GlobalDefaultAddressSpaceId {
t.Errorf("GetDefaultAddressSpaces returned invalid global address space.")
}
}
// Tests updating an existing address space adds new resources and removes stale ones.
func TestAddressSpaceUpdate(t *testing.T) {
// Start with the test address space.
am, err := createAddressManager()
if err != nil {
t.Fatalf("createAddressManager failed, err:%+v.", err)
}
amImpl := am.(*addressManager)
// Create a new local address space to update the existing one.
localAs, err := amImpl.newAddressSpace(LocalDefaultAddressSpaceId, LocalScope)
if err != nil {
t.Errorf("newAddressSpace failed, err:%+v.", err)
}
// Remove addr12 and add addr13 in subnet1.
ap, err := localAs.newAddressPool(anyInterface, anyPriority, &subnet1)
ap.newAddressRecord(&addr11)
ap.newAddressRecord(&addr13)
// Remove subnet2.
// Add subnet3 with addr31.
ap, err = localAs.newAddressPool(anyInterface, anyPriority, &subnet3)
ap.newAddressRecord(&addr31)
err = amImpl.setAddressSpace(localAs)
if err != nil {
t.Errorf("setAddressSpace failed, err:%+v.", err)
}
// Test that the address space was updated correctly.
localAs, err = amImpl.getAddressSpace(LocalDefaultAddressSpaceId)
if err != nil {
t.Errorf("getAddressSpace failed, err:%+v.", err)
}
// Subnet1 should have addr11 and addr13, but not addr12.
ap, err = localAs.getAddressPool(subnet1.String())
if err != nil {
t.Errorf("Cannot find subnet1, err:%+v.", err)
}
_, err = ap.requestAddress(addr11.String(), nil)
if err != nil {
t.Errorf("Cannot find addr11, err:%+v.", err)
}
_, err = ap.requestAddress(addr12.String(), nil)
if err == nil {
t.Errorf("Found addr12.")
}
_, err = ap.requestAddress(addr13.String(), nil)
if err != nil {
t.Errorf("Cannot find addr13, err:%+v.", err)
}
// Subnet2 should not exist.
ap, err = localAs.getAddressPool(subnet2.String())
if err == nil {
t.Errorf("Found subnet2.")
}
// Subnet3 should have addr31 only.
ap, err = localAs.getAddressPool(subnet3.String())
if err != nil {
t.Errorf("Cannot find subnet3, err:%+v.", err)
}
_, err = ap.requestAddress(addr31.String(), nil)
if err != nil {
t.Errorf("Cannot find addr31, err:%+v.", err)
}
_, err = ap.requestAddress(addr32.String(), nil)
if err == nil {
t.Errorf("Found addr32.")
}
}
// Tests multiple wildcard address pool requests return separate pools.
func TestAddressPoolRequestsForSeparatePools(t *testing.T) {
// Start with the test address space.
am, err := createAddressManager()
if err != nil {
t.Fatalf("createAddressManager failed, err:%+v.", err)
}
// Request two separate address pools.
poolId1, subnet1, err := am.RequestPool(LocalDefaultAddressSpaceId, "", "", nil, false)
if err != nil {
t.Errorf("RequestPool failed, err:%v", err)
}
poolId2, subnet2, err := am.RequestPool(LocalDefaultAddressSpaceId, "", "", nil, false)
if err != nil {
t.Errorf("RequestPool failed, err:%v", err)
}
// Test the poolIds and subnets do not match.
if poolId1 == poolId2 || subnet1 == subnet2 {
t.Errorf("Pool requests returned the same pool.")
}
// Release the address pools.
err = am.ReleasePool(LocalDefaultAddressSpaceId, poolId1)
if err != nil {
t.Errorf("ReleasePool failed, err:%v", err)
}
err = am.ReleasePool(LocalDefaultAddressSpaceId, poolId2)
if err != nil {
t.Errorf("ReleasePool failed, err:%v", err)
}
}
// Tests multiple identical address pool requests return the same pool and pools are referenced correctly.
func TestAddressPoolRequestsForSamePool(t *testing.T) {
// Start with the test address space.
am, err := createAddressManager()
if err != nil {
t.Fatalf("createAddressManager failed, err:%+v.", err)
}
// Request the same address pool twice.
poolId1, subnet1, err := am.RequestPool(LocalDefaultAddressSpaceId, "", "", nil, false)
if err != nil {
t.Errorf("RequestPool failed, err:%v", err)
}
poolId2, subnet2, err := am.RequestPool(LocalDefaultAddressSpaceId, poolId1, "", nil, false)
if err != nil {
t.Errorf("RequestPool failed, err:%v", err)
}
// Test the subnets do not match.
if poolId1 != poolId2 || subnet1 != subnet2 {
t.Errorf("Pool requests returned different pools.")
}
// Release the address pools.
err = am.ReleasePool(LocalDefaultAddressSpaceId, poolId1)
if err != nil {
t.Errorf("ReleasePool failed, err:%v", err)
}
err = am.ReleasePool(LocalDefaultAddressSpaceId, poolId2)
if err != nil {
t.Errorf("ReleasePool failed, err:%v", err)
}
// Third release should fail.
err = am.ReleasePool(LocalDefaultAddressSpaceId, poolId1)
if err == nil {
t.Errorf("ReleasePool succeeded extra, err:%v", err)
}
}
// Tests address requests from the same pool return separate addresses and releases work correctly.
func TestAddressRequestsFromTheSamePool(t *testing.T) {
// Start with the test address space.
am, err := createAddressManager()
if err != nil {
t.Fatalf("createAddressManager failed, err:%+v.", err)
}
// Request a pool.
poolId, _, err := am.RequestPool(LocalDefaultAddressSpaceId, "", "", nil, false)
if err != nil {
t.Errorf("RequestPool failed, err:%v", err)
}
// Request two addresses from the pool.
address1, err := am.RequestAddress(LocalDefaultAddressSpaceId, poolId, "", nil)
if err != nil {
t.Errorf("RequestAddress failed, err:%v", err)
}
addr, _, _ := net.ParseCIDR(address1)
address1 = addr.String()
address2, err := am.RequestAddress(LocalDefaultAddressSpaceId, poolId, "", nil)
if err != nil {
t.Errorf("RequestAddress failed, err:%v", err)
}
addr, _, _ = net.ParseCIDR(address2)
address2 = addr.String()
// Test the addresses do not match.
if address1 == address2 {
t.Errorf("Address requests returned the same address %v.", address1)
}
// Release addresses and the pool.
err = am.ReleaseAddress(LocalDefaultAddressSpaceId, poolId, address1)
if err != nil {
t.Errorf("ReleaseAddress failed, err:%v", err)
}
err = am.ReleaseAddress(LocalDefaultAddressSpaceId, poolId, address2)
if err != nil {
t.Errorf("ReleaseAddress failed, err:%v", err)
}
err = am.ReleasePool(LocalDefaultAddressSpaceId, poolId)
if err != nil {
t.Errorf("ReleasePool failed, err:%v", err)
}
}