Skip to content

Commit a016151

Browse files
committed
test: ipam sync routine unit tests
1 parent ea7f48c commit a016151

File tree

2 files changed

+218
-0
lines changed

2 files changed

+218
-0
lines changed

pkg/ipam/ipam_suite_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2019-2024 The Liqo Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package ipam
16+
17+
import (
18+
"testing"
19+
20+
. "github.com/onsi/ginkgo/v2"
21+
. "github.com/onsi/gomega"
22+
corev1 "k8s.io/api/core/v1"
23+
"k8s.io/client-go/kubernetes/scheme"
24+
25+
liqov1beta1 "github.com/liqotech/liqo/apis/core/v1beta1"
26+
ipamv1alpha1 "github.com/liqotech/liqo/apis/ipam/v1alpha1"
27+
networkingv1beta1 "github.com/liqotech/liqo/apis/networking/v1beta1"
28+
"github.com/liqotech/liqo/pkg/utils/testutil"
29+
)
30+
31+
func TestIpam(t *testing.T) {
32+
RegisterFailHandler(Fail)
33+
RunSpecs(t, "Ipam Suite")
34+
}
35+
36+
var _ = BeforeSuite(func() {
37+
testutil.LogsToGinkgoWriter()
38+
39+
Expect(corev1.AddToScheme(scheme.Scheme)).To(Succeed())
40+
Expect(liqov1beta1.AddToScheme(scheme.Scheme)).To(Succeed())
41+
Expect(networkingv1beta1.AddToScheme(scheme.Scheme)).To(Succeed())
42+
Expect(ipamv1alpha1.AddToScheme(scheme.Scheme)).To(Succeed())
43+
})

pkg/ipam/sync_test.go

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// Copyright 2019-2024 The Liqo Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package ipam
16+
17+
import (
18+
"context"
19+
"time"
20+
21+
. "github.com/onsi/ginkgo/v2"
22+
. "github.com/onsi/gomega"
23+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24+
"k8s.io/client-go/kubernetes/scheme"
25+
"k8s.io/utils/ptr"
26+
"sigs.k8s.io/controller-runtime/pkg/client/fake"
27+
28+
ipamv1alpha1 "github.com/liqotech/liqo/apis/ipam/v1alpha1"
29+
networkingv1beta1 "github.com/liqotech/liqo/apis/networking/v1beta1"
30+
)
31+
32+
var _ = Describe("Sync routine tests", func() {
33+
const (
34+
syncFrequency = 3 * time.Second
35+
testNamespace = "test"
36+
)
37+
38+
var (
39+
ctx context.Context
40+
fakeClientBuilder *fake.ClientBuilder
41+
now time.Time
42+
expiredThreshold time.Time
43+
expired time.Time
44+
45+
fakeIpamServer *LiqoIPAM
46+
47+
addNetowrkToCache = func(ipamServer *LiqoIPAM, cidr string, creationTimestamp time.Time) {
48+
ipamServer.cacheNetworks[cidr] = networkInfo{
49+
cidr: cidr,
50+
creationTimestamp: creationTimestamp,
51+
}
52+
}
53+
54+
addIPToCache = func(ipamServer *LiqoIPAM, ip, cidr string, creationTimestamp time.Time) {
55+
ipC := ipCidr{ip: ip, cidr: cidr}
56+
ipamServer.cacheIPs[ipC.String()] = ipInfo{
57+
ipCidr: ipC,
58+
creationTimestamp: creationTimestamp,
59+
}
60+
}
61+
62+
newNetwork = func(name, cidr string) *ipamv1alpha1.Network {
63+
return &ipamv1alpha1.Network{
64+
ObjectMeta: metav1.ObjectMeta{
65+
Name: name,
66+
Namespace: testNamespace,
67+
},
68+
Spec: ipamv1alpha1.NetworkSpec{
69+
CIDR: networkingv1beta1.CIDR(cidr),
70+
},
71+
Status: ipamv1alpha1.NetworkStatus{
72+
CIDR: networkingv1beta1.CIDR(cidr),
73+
},
74+
}
75+
}
76+
77+
newIP = func(name, ip, cidr string) *ipamv1alpha1.IP {
78+
return &ipamv1alpha1.IP{
79+
ObjectMeta: metav1.ObjectMeta{
80+
Name: name,
81+
Namespace: testNamespace,
82+
},
83+
Spec: ipamv1alpha1.IPSpec{
84+
IP: networkingv1beta1.IP(ip),
85+
CIDR: ptr.To(networkingv1beta1.CIDR(cidr)),
86+
},
87+
Status: ipamv1alpha1.IPStatus{
88+
IP: networkingv1beta1.IP(ip),
89+
CIDR: networkingv1beta1.CIDR(cidr),
90+
},
91+
}
92+
}
93+
)
94+
95+
BeforeEach(func() {
96+
ctx = context.Background()
97+
fakeClientBuilder = fake.NewClientBuilder().WithScheme(scheme.Scheme)
98+
now = time.Now()
99+
expiredThreshold = now.Add(-syncFrequency)
100+
expired = now.Add(-2 * syncFrequency)
101+
})
102+
103+
Describe("Testing the sync routine", func() {
104+
Context("Sync Networks", func() {
105+
BeforeEach(func() {
106+
// Add in-cluster networks
107+
client := fakeClientBuilder.WithObjects(
108+
newNetwork("net1", "10.0.0.0/16"),
109+
newNetwork("net2", "10.1.0.0/16"),
110+
newNetwork("net3", "10.2.0.0/16"),
111+
).Build()
112+
113+
// Populate the cache
114+
fakeIpamServer = &LiqoIPAM{
115+
Client: client,
116+
cacheNetworks: make(map[string]networkInfo),
117+
}
118+
addNetowrkToCache(fakeIpamServer, "10.0.0.0/16", now)
119+
addNetowrkToCache(fakeIpamServer, "10.1.0.0/16", expired)
120+
addNetowrkToCache(fakeIpamServer, "10.3.0.0/16", expired)
121+
addNetowrkToCache(fakeIpamServer, "10.4.0.0/16", now)
122+
})
123+
124+
It("should remove networks from cache if they are not present in the cluster", func() {
125+
// Run sync
126+
Expect(fakeIpamServer.syncNetworks(ctx, expiredThreshold)).To(Succeed())
127+
128+
// Check the cache
129+
Expect(fakeIpamServer.cacheNetworks).To(HaveKey("10.0.0.0/16")) // network in cluster and cache
130+
Expect(fakeIpamServer.cacheNetworks).To(HaveKey("10.1.0.0/16")) // network in cluster and cache before expired threshold
131+
Expect(fakeIpamServer.cacheNetworks).NotTo(HaveKey("10.2.0.0/16")) // network in cluster but not in cache
132+
Expect(fakeIpamServer.cacheNetworks).NotTo(HaveKey("10.3.0.0/16")) // network not in cluster but in cache before expired threshold
133+
Expect(fakeIpamServer.cacheNetworks).To(HaveKey("10.4.0.0/16")) // network not in cluster but in cache after expired threshold
134+
})
135+
})
136+
137+
Context("Sync IPs", func() {
138+
BeforeEach(func() {
139+
// Add in-cluster IPs
140+
client := fakeClientBuilder.WithObjects(
141+
newIP("ip1", "10.0.0.0", "10.0.0.0/24"),
142+
newIP("ip2", "10.0.0.1", "10.0.0.0/24"),
143+
newIP("ip3", "10.0.0.2", "10.0.0.0/24"),
144+
).Build()
145+
146+
// Populate the cache
147+
fakeIpamServer = &LiqoIPAM{
148+
Client: client,
149+
cacheIPs: make(map[string]ipInfo),
150+
}
151+
addIPToCache(fakeIpamServer, "10.0.0.0", "10.0.0.0/24", now)
152+
addIPToCache(fakeIpamServer, "10.0.0.1", "10.0.0.0/24", expired)
153+
addIPToCache(fakeIpamServer, "10.0.0.3", "10.0.0.0/24", expired)
154+
addIPToCache(fakeIpamServer, "10.0.0.4", "10.0.0.0/24", now)
155+
})
156+
157+
It("should remove IPs from cache if they are not present in the cluster", func() {
158+
// Run sync
159+
Expect(fakeIpamServer.syncIPs(ctx, expiredThreshold)).To(Succeed())
160+
161+
// Check the cache
162+
Expect(fakeIpamServer.cacheIPs).To(HaveKey(
163+
ipCidr{ip: "10.0.0.0", cidr: "10.0.0.0/24"}.String())) // IP in cluster and cache
164+
Expect(fakeIpamServer.cacheIPs).To(HaveKey(
165+
ipCidr{ip: "10.0.0.1", cidr: "10.0.0.0/24"}.String())) // IP in cluster and cache before expired threshold
166+
Expect(fakeIpamServer.cacheIPs).NotTo(HaveKey(
167+
ipCidr{ip: "10.0.0.2", cidr: "10.0.0.0/24"}.String())) // IP in cluster but not in cache
168+
Expect(fakeIpamServer.cacheIPs).NotTo(HaveKey(
169+
ipCidr{ip: "10.0.0.3", cidr: "10.0.0.0/24"}.String())) // IP not in cluster but in cache before expired threshold
170+
Expect(fakeIpamServer.cacheIPs).To(HaveKey(
171+
ipCidr{ip: "10.0.0.4", cidr: "10.0.0.0/24"}.String())) // IP not in cluster but in cache after expired threshold
172+
})
173+
})
174+
})
175+
})

0 commit comments

Comments
 (0)