Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ test-all:
./ipam/ \
./log/ \
./netlink/ \
./network/ \
./store/ \
./telemetry/ \
./aitelemetry/ \
Expand Down
10 changes: 6 additions & 4 deletions cni/ipam/ipam_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ package ipam
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"testing"

cniSkel "github.com/containernetworking/cni/pkg/skel"
cniTypesCurr "github.com/containernetworking/cni/pkg/types/current"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"net/http"
"net/url"
"testing"
"time"

"github.com/Azure/azure-container-networking/common"
"github.com/Azure/azure-container-networking/platform"
Expand Down Expand Up @@ -70,6 +70,8 @@ var (
err error

_ = BeforeSuite(func() {
// TODO: Ensure that the other testAgent has bees released.
time.Sleep(1 * time.Second)
// Create a fake local agent to handle requests from IPAM plugin.
u, _ := url.Parse("tcp://" + ipamQueryUrl)
testAgent, err = common.NewListener(u)
Expand Down
157 changes: 106 additions & 51 deletions ipam/ipv6Ipam_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ package ipam
import (
"context"
"reflect"
"runtime"
"testing"

"github.com/Azure/azure-container-networking/common"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
testclient "k8s.io/client-go/kubernetes/fake"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

"github.com/Azure/azure-container-networking/common"
)

const (
Expand All @@ -36,59 +40,110 @@ func newKubernetesTestClient() kubernetes.Interface {
return client
}

func TestIPv6Ipam(t *testing.T) {
options := make(map[string]interface{})
options[common.OptEnvironment] = common.OptEnvironmentIPv6NodeIpam

client := newKubernetesTestClient()
node, _ := client.CoreV1().Nodes().Get(context.TODO(), testNodeName, metav1.GetOptions{})

testInterfaces, err := retrieveKubernetesPodIPs(node, testSubnetSize)
if err != nil {
t.Fatalf("Failed to carve addresses: %+v", err)
}
func TestIpv6Ipam(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Ipv6Ipam Suite")
}

correctInterfaces := &NetworkInterfaces{
Interfaces: []Interface{
{
IsPrimary: true,
IPSubnets: []IPSubnet{
{
Prefix: "ace:cab:deca:deed::/126",
IPAddresses: []IPAddress{
{Address: "ace:cab:deca:deed::2", IsPrimary: false},
{Address: "ace:cab:deca:deed::3", IsPrimary: false},
var (
_ = Describe("Test ipv6Ipam", func() {

Describe("Test newIPv6IpamSource", func() {

Context("When creating with current environment", func() {
It("Should create successfully", func() {
name := common.OptEnvironmentIPv6NodeIpam
options := map[string]interface{}{}
options[common.OptEnvironment] = name
kubeConfigPath := defaultLinuxKubeConfigFilePath
if runtime.GOOS == windows {
kubeConfigPath = defaultWindowsKubeConfigFilePath
}
isLoaded := true
ipv6IpamSource, err := newIPv6IpamSource(options, isLoaded)
Expect(err).NotTo(HaveOccurred())
Expect(ipv6IpamSource.name).To(Equal(name))
Expect(ipv6IpamSource.kubeConfigPath).To(Equal(kubeConfigPath))
Expect(ipv6IpamSource.isLoaded).To(Equal(isLoaded))
})
})
})

Describe("Test start and stop", func() {

source := &ipv6IpamSource{}

Context("Start the source with sink", func() {
It("Should set the sink of source", func() {
sink := &addressManagerMock{}
err := source.start(sink)
Expect(err).NotTo(HaveOccurred())
Expect(source.sink).NotTo(BeNil())
})
})

Context("Stop the source", func() {
It("Should remove the sink of source", func() {
source.stop()
Expect(source.sink).To(BeNil())
})
})
})

Describe("TestIPv6Ipam", func() {
Context("When node have IPv6 subnet", func() {
It("Carve addresses successfully and Network interface match", func() {
options := make(map[string]interface{})
options[common.OptEnvironment] = common.OptEnvironmentIPv6NodeIpam

client := newKubernetesTestClient()
node, _ := client.CoreV1().Nodes().Get(context.TODO(), testNodeName, metav1.GetOptions{})

testInterfaces, err := retrieveKubernetesPodIPs(node, testSubnetSize)
Expect(err).NotTo(HaveOccurred())

correctInterfaces := &NetworkInterfaces{
Interfaces: []Interface{
{
IsPrimary: true,
IPSubnets: []IPSubnet{
{
Prefix: "ace:cab:deca:deed::/126",
IPAddresses: []IPAddress{
{Address: "ace:cab:deca:deed::2", IsPrimary: false},
{Address: "ace:cab:deca:deed::3", IsPrimary: false},
},
},
},
},
},
},
},
},
},
}

equal := reflect.DeepEqual(testInterfaces, correctInterfaces)

if !equal {
t.Fatalf("Network interface mismatch, expected: %+v actual: %+v", correctInterfaces, testInterfaces)
}
}
}

func TestIPv6IpamWithoutIPv6SubnetAllocated(t *testing.T) {
options := make(map[string]interface{})
options[common.OptEnvironment] = common.OptEnvironmentIPv6NodeIpam
equal := reflect.DeepEqual(testInterfaces, correctInterfaces)
Expect(equal).To(BeTrue())
})
})

testnode := &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: testNodeName,
},
Spec: v1.NodeSpec{
PodCIDR: "10.0.0.1/24",
PodCIDRs: []string{"10.0.0.1/24"},
},
}
Context("When node doesn't have IPv6 subnet", func() {
It("Should fail to retrieve the IPv6 address", func() {
options := make(map[string]interface{})
options[common.OptEnvironment] = common.OptEnvironmentIPv6NodeIpam

_, err := retrieveKubernetesPodIPs(testnode, testSubnetSize)
testnode := &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: testNodeName,
},
Spec: v1.NodeSpec{
PodCIDR: "10.0.0.1/24",
PodCIDRs: []string{"10.0.0.1/24"},
},
}

_, err := retrieveKubernetesPodIPs(testnode, testSubnetSize)
Expect(err).To(HaveOccurred())
})
})
})
})
)

if err == nil {
t.Fatal("Expected to fail IPv6 IP retrieval when node doesn't have IPv6 subnet")
}
}
147 changes: 80 additions & 67 deletions ipam/manager_ipv6Ipam_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,25 @@ package ipam
import (
"testing"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

"github.com/Azure/azure-container-networking/common"
)

var (

// Pools and addresses used by tests.
ipv6subnet1 = "ace:cab:deca:deed::" + testSubnetSize
ipv6addr2 = "ace:cab:deca:deed::2"
ipv6addr3 = "ace:cab:deca:deed::3"
)

func TestManagerIpv6Ipam(t *testing.T) {
RegisterFailHandler(Fail)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where these functions are defined? can you add comment as well about these functions and what it does

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defined in pkg Gpmega. RegisterFailHandler connects Ginkgo to Gomega. When a matcher fails the fail handler passed into RegisterFailHandler is called.

RunSpecs(t, "Manager ipv6ipam Suite")
}


func createTestIpv6AddressManager() (AddressManager, error) {
var config common.PluginConfig
var options map[string]interface{}
Expand All @@ -43,69 +51,74 @@ func createTestIpv6AddressManager() (AddressManager, error) {
return am, nil
}

//
// Address manager tests.
//
// request pool, request address with no address specified, request address with address specified,
// release both addresses, release pool
func TestIPv6GetAddressPoolAndAddress(t *testing.T) {
// Start with the test address space.
am, err := createTestIpv6AddressManager()
if err != nil {
t.Fatalf("createAddressManager failed, err:%+v.", err)
}

// Test if the address spaces are returned correctly.
local, _ := am.GetDefaultAddressSpaces()

if local != LocalDefaultAddressSpaceId {
t.Errorf("GetDefaultAddressSpaces returned invalid local address space.")
}

// Request two separate address pools.
poolID1, subnet1, err := am.RequestPool(LocalDefaultAddressSpaceId, "", "", nil, true)
if err != nil {
t.Errorf("RequestPool failed, err:%v", err)
}

if subnet1 != ipv6subnet1 {
t.Errorf("Mismatched retrieved subnet, expected:%+v, actual %+v", ipv6subnet1, subnet1)
}

// test with a specified address
address2, err := am.RequestAddress(LocalDefaultAddressSpaceId, poolID1, ipv6addr2, nil)
if err != nil {
t.Errorf("RequestAddress failed, err:%v", err)
}

if address2 != ipv6addr2+testSubnetSize {
t.Errorf("RequestAddress failed, expected: %v, actual: %v", ipv6addr2+testSubnetSize, address2)
}

// test with a specified address
address3, err := am.RequestAddress(LocalDefaultAddressSpaceId, poolID1, "", nil)
if err != nil {
t.Errorf("RequestAddress failed, err:%v", err)
}

if address3 != ipv6addr3+testSubnetSize {
t.Errorf("RequestAddress failed, expected: %v, actual: %v", ipv6addr3+testSubnetSize, address3)
}

// Release addresses and the pool.
err = am.ReleaseAddress(LocalDefaultAddressSpaceId, poolID1, address2, nil)
if err != nil {
t.Errorf("ReleaseAddress failed, err:%v", err)
}

// Release addresses and the pool.
err = am.ReleaseAddress(LocalDefaultAddressSpaceId, poolID1, address3, nil)
if err != nil {
t.Errorf("ReleaseAddress failed, err:%v", err)
}

err = am.ReleasePool(LocalDefaultAddressSpaceId, poolID1)
if err != nil {
t.Errorf("ReleasePool failed, err:%v", err)
}
}
var (
_ = Describe("Test manager ipv6Ipam", func() {

Describe("Test IPv6 get address pool and address", func() {

var (
am AddressManager
err error
poolID1 string
subnet1 string
address2 string
address3 string
)

Context("Start with the test address space", func() {
It("Should create AddressManager successfully", func() {
am, err = createTestIpv6AddressManager()
Expect(err).NotTo(HaveOccurred())
})
})

Context("When test if the address spaces are returned correctly", func() {
It("GetDefaultAddressSpaces returned valid local address space", func() {
local, _ := am.GetDefaultAddressSpaces()
Expect(local).To(Equal(LocalDefaultAddressSpaceId))
})
})

Context("When request two separate address pools", func() {
It("Should request pool successfully and return subnet matched ipv6subnet1", func() {
poolID1, subnet1, err = am.RequestPool(LocalDefaultAddressSpaceId, "", "", nil, true)
Expect(err).NotTo(HaveOccurred())
Expect(subnet1).To(Equal(ipv6subnet1))

})
})

Context("When test with a specified address", func() {
It("Should request address successfully", func() {
address2, err := am.RequestAddress(LocalDefaultAddressSpaceId, poolID1, ipv6addr2, nil)
Expect(err).NotTo(HaveOccurred())
Expect(address2).To(Equal(ipv6addr2+testSubnetSize))
})
})

Context("When test without requesting address explicitly", func() {
It("Should request address successfully", func() {
address3, err := am.RequestAddress(LocalDefaultAddressSpaceId, poolID1, "", nil)
Expect(err).NotTo(HaveOccurred())
Expect(address3).To(Equal(ipv6addr3+testSubnetSize))
})
})

Context("When release address2", func() {
It("Should release successfully", func() {
err = am.ReleaseAddress(LocalDefaultAddressSpaceId, poolID1, address2, nil)
Expect(err).NotTo(HaveOccurred())
})
})

Context("When release address3 and the pool", func() {
It("Should release successfully", func() {
err = am.ReleaseAddress(LocalDefaultAddressSpaceId, poolID1, address3, nil)
Expect(err).NotTo(HaveOccurred())
err = am.ReleasePool(LocalDefaultAddressSpaceId, poolID1)
Expect(err).NotTo(HaveOccurred())
})
})
})
})
)
Loading