Skip to content

Commit 4975648

Browse files
Merge pull request #426 from fmount/topology_envtest
Improve topology testing coverage
2 parents 01d504d + 9fb967b commit 4975648

File tree

4 files changed

+219
-36
lines changed

4 files changed

+219
-36
lines changed

tests/functional/base_test.go

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232

3333
networkv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1"
3434
infranetworkv1 "github.com/openstack-k8s-operators/infra-operator/apis/network/v1beta1"
35+
topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1"
3536
condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition"
3637
"github.com/openstack-k8s-operators/lib-common/modules/common/tls"
3738
ovnv1 "github.com/openstack-k8s-operators/ovn-operator/api/v1beta1"
@@ -414,7 +415,7 @@ func GetSampleDaemonSetTopologySpec(selector string) map[string]interface{} {
414415

415416
// GetSampleTopologySpec - A sample (and opinionated) Topology Spec used to
416417
// test OVN components
417-
func GetSampleTopologySpec(selector string) map[string]interface{} {
418+
func GetSampleTopologySpec(label string) (map[string]interface{}, []corev1.TopologySpreadConstraint) {
418419
// Build the topology Spec
419420
topologySpec := map[string]interface{}{
420421
"topologySpreadConstraints": []map[string]interface{}{
@@ -424,17 +425,33 @@ func GetSampleTopologySpec(selector string) map[string]interface{} {
424425
"whenUnsatisfiable": "ScheduleAnyway",
425426
"labelSelector": map[string]interface{}{
426427
"matchLabels": map[string]interface{}{
427-
"service": selector,
428+
"service": label,
428429
},
429430
},
430431
},
431432
},
432433
}
433-
return topologySpec
434+
// Build the topologyObj representation
435+
topologySpecObj := []corev1.TopologySpreadConstraint{
436+
{
437+
MaxSkew: 1,
438+
TopologyKey: corev1.LabelHostname,
439+
WhenUnsatisfiable: corev1.ScheduleAnyway,
440+
LabelSelector: &metav1.LabelSelector{
441+
MatchLabels: map[string]string{
442+
"service": label,
443+
},
444+
},
445+
},
446+
}
447+
return topologySpec, topologySpecObj
434448
}
435449

436450
// CreateTopology - Creates a Topology CR based on the spec passed as input
437-
func CreateTopology(topology types.NamespacedName, spec map[string]interface{}) client.Object {
451+
func CreateTopology(
452+
topology types.NamespacedName,
453+
spec map[string]interface{},
454+
) (client.Object, topologyv1.TopoRef) {
438455
raw := map[string]interface{}{
439456
"apiVersion": "topology.openstack.org/v1beta1",
440457
"kind": "Topology",
@@ -444,5 +461,20 @@ func CreateTopology(topology types.NamespacedName, spec map[string]interface{})
444461
},
445462
"spec": spec,
446463
}
447-
return th.CreateUnstructured(raw)
464+
// other than creating the topology based on the raw spec, we return the
465+
// TopoRef that can be referenced
466+
topologyRef := topologyv1.TopoRef{
467+
Name: topology.Name,
468+
Namespace: topology.Namespace,
469+
}
470+
return th.CreateUnstructured(raw), topologyRef
471+
}
472+
473+
// GetTopology - Returns the referenced Topology
474+
func GetTopology(name types.NamespacedName) *topologyv1.Topology {
475+
instance := &topologyv1.Topology{}
476+
Eventually(func(g Gomega) {
477+
g.Expect(k8sClient.Get(ctx, name, instance)).Should(Succeed())
478+
}, timeout, interval).Should(Succeed())
479+
return instance
448480
}

tests/functional/ovncontroller_controller_test.go

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,6 +1256,7 @@ var _ = Describe("OVNController controller", func() {
12561256
var daemonSetName types.NamespacedName
12571257
var daemonSetNameOVS types.NamespacedName
12581258
var ovnTopologies []types.NamespacedName
1259+
var topologyRef, topologyRefAlt *topologyv1.TopoRef
12591260

12601261
BeforeEach(func() {
12611262
ovnControllerName = types.NamespacedName{
@@ -1273,22 +1274,28 @@ var _ = Describe("OVNController controller", func() {
12731274
Name: "ovn-topology-alt",
12741275
},
12751276
}
1276-
// Build the topology Spec
1277-
topologySpec := GetSampleTopologySpec(ovnControllerName.Name)
1277+
// Define the two topology references used in this test
1278+
topologyRef = &topologyv1.TopoRef{
1279+
Name: ovnTopologies[0].Name,
1280+
Namespace: ovnTopologies[0].Namespace,
1281+
}
1282+
topologyRefAlt = &topologyv1.TopoRef{
1283+
Name: ovnTopologies[1].Name,
1284+
Namespace: ovnTopologies[1].Namespace,
1285+
}
1286+
12781287
// Create Test Topology
12791288
for _, t := range ovnTopologies {
1289+
// Build the topology Spec
1290+
topologySpec, _ := GetSampleTopologySpec(ovnControllerName.Name)
12801291
CreateTopology(t, topologySpec)
12811292
}
12821293

12831294
dbs := CreateOVNDBClusters(namespace, map[string][]string{}, 1)
12841295
DeferCleanup(DeleteOVNDBClusters, dbs)
12851296

12861297
spec := GetDefaultOVNControllerSpec()
1287-
1288-
spec.TopologyRef = &topologyv1.TopoRef{
1289-
Name: ovnTopologies[0].Name,
1290-
Namespace: ovnTopologies[0].Namespace,
1291-
}
1298+
spec.TopologyRef = topologyRef
12921299

12931300
//ovn.CreateOVNControllerWithName("ovn-controller-0", namespace, spec)
12941301
ovn.CreateOVNController(&ovnControllerName.Name, namespace, spec)
@@ -1310,14 +1317,17 @@ var _ = Describe("OVNController controller", func() {
13101317

13111318
It("sets topologyref in both .Status CR and resources", func() {
13121319
Eventually(func(g Gomega) {
1320+
tp := GetTopology(types.NamespacedName{
1321+
Name: topologyRef.Name,
1322+
Namespace: topologyRef.Namespace,
1323+
})
1324+
finalizers := tp.GetFinalizers()
1325+
g.Expect(finalizers).To(HaveLen(1))
13131326
ovn := GetOVNController(ovnControllerName)
13141327
g.Expect(ovn.Status.LastAppliedTopology).NotTo(BeNil())
1315-
}, timeout, interval).Should(Succeed())
1316-
1317-
Eventually(func(g Gomega) {
1318-
ovn := GetOVNController(ovnControllerName)
1319-
g.Expect(ovn.Status.LastAppliedTopology).NotTo(BeNil())
1320-
g.Expect(ovn.Status.LastAppliedTopology.Name).To(Equal(ovnTopologies[0].Name))
1328+
g.Expect(ovn.Status.LastAppliedTopology).To(Equal(topologyRef))
1329+
g.Expect(finalizers).To(ContainElement(
1330+
fmt.Sprintf("openstack.org/ovncontroller-%s", ovnControllerName.Name)))
13211331
}, timeout, interval).Should(Succeed())
13221332

13231333
Eventually(func(g Gomega) {
@@ -1334,11 +1344,27 @@ var _ = Describe("OVNController controller", func() {
13341344
}, timeout, interval).Should(Succeed())
13351345

13361346
Eventually(func(g Gomega) {
1347+
tp := GetTopology(types.NamespacedName{
1348+
Name: topologyRefAlt.Name,
1349+
Namespace: topologyRefAlt.Namespace,
1350+
})
1351+
finalizers := tp.GetFinalizers()
1352+
g.Expect(finalizers).To(HaveLen(1))
13371353
ovn := GetOVNController(ovnControllerName)
13381354
g.Expect(ovn.Status.LastAppliedTopology).NotTo(BeNil())
1339-
g.Expect(ovn.Status.LastAppliedTopology.Name).To(Equal(ovnTopologies[1].Name))
1355+
g.Expect(ovn.Status.LastAppliedTopology).To(Equal(topologyRefAlt))
1356+
g.Expect(finalizers).To(ContainElement(
1357+
fmt.Sprintf("openstack.org/ovncontroller-%s", ovnControllerName.Name)))
13401358
g.Expect(GetDaemonSet(daemonSetName).Spec.Template.Spec.TopologySpreadConstraints).To(BeNil())
13411359
g.Expect(GetDaemonSet(daemonSetNameOVS).Spec.Template.Spec.Affinity).To(BeNil())
1360+
1361+
// Verify the previous referenced topology has no finalizers
1362+
tp = GetTopology(types.NamespacedName{
1363+
Name: topologyRef.Name,
1364+
Namespace: topologyRef.Namespace,
1365+
})
1366+
finalizers = tp.GetFinalizers()
1367+
g.Expect(finalizers).To(BeEmpty())
13421368
}, timeout, interval).Should(Succeed())
13431369
})
13441370
It("removes topologyRef from the spec", func() {
@@ -1358,6 +1384,18 @@ var _ = Describe("OVNController controller", func() {
13581384
g.Expect(GetDaemonSet(daemonSetName).Spec.Template.Spec.TopologySpreadConstraints).To(BeNil())
13591385
g.Expect(GetDaemonSet(daemonSetName).Spec.Template.Spec.Affinity).To(BeNil())
13601386
}, timeout, interval).Should(Succeed())
1387+
1388+
// Verify the existing topologies have no finalizer anymore
1389+
Eventually(func(g Gomega) {
1390+
for _, topology := range ovnTopologies {
1391+
tp := GetTopology(types.NamespacedName{
1392+
Name: topology.Name,
1393+
Namespace: topology.Namespace,
1394+
})
1395+
finalizers := tp.GetFinalizers()
1396+
g.Expect(finalizers).To(BeEmpty())
1397+
}
1398+
}, timeout, interval).Should(Succeed())
13611399
})
13621400
})
13631401
It("rejects a wrong topologyRef on a different namespace", func() {

tests/functional/ovndbcluster_controller_test.go

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,6 +1228,7 @@ var _ = Describe("OVNDBCluster controller", func() {
12281228
var OVNDBClusterName types.NamespacedName
12291229
var statefulSetName types.NamespacedName
12301230
var ovnTopologies []types.NamespacedName
1231+
var topologyRef, topologyRefAlt *topologyv1.TopoRef
12311232

12321233
BeforeEach(func() {
12331234
OVNDBClusterName = types.NamespacedName{
@@ -1244,18 +1245,25 @@ var _ = Describe("OVNDBCluster controller", func() {
12441245
Name: "ovn-topology-alt",
12451246
},
12461247
}
1247-
// Build the topology Spec
1248-
topologySpec := GetSampleTopologySpec(OVNDBClusterName.Name)
1248+
// Define the two topology references used in this test
1249+
topologyRef = &topologyv1.TopoRef{
1250+
Name: ovnTopologies[0].Name,
1251+
Namespace: ovnTopologies[0].Namespace,
1252+
}
1253+
topologyRefAlt = &topologyv1.TopoRef{
1254+
Name: ovnTopologies[1].Name,
1255+
Namespace: ovnTopologies[1].Namespace,
1256+
}
1257+
12491258
// Create Test Topology
12501259
for _, t := range ovnTopologies {
1260+
// Build the topology Spec
1261+
topologySpec, _ := GetSampleTopologySpec(OVNDBClusterName.Name)
12511262
CreateTopology(t, topologySpec)
12521263
}
12531264

12541265
spec := GetDefaultOVNDBClusterSpec()
1255-
spec.TopologyRef = &topologyv1.TopoRef{
1256-
Name: ovnTopologies[0].Name,
1257-
Namespace: ovnTopologies[0].Namespace,
1258-
}
1266+
spec.TopologyRef = topologyRef
12591267
ovn.CreateOVNDBCluster(&OVNDBClusterName.Name, OVNDBClusterName.Namespace, spec)
12601268

12611269
statefulSetName = types.NamespacedName{
@@ -1267,10 +1275,22 @@ var _ = Describe("OVNDBCluster controller", func() {
12671275

12681276
It("sets topologyref in both .Status CR and resources", func() {
12691277
Eventually(func(g Gomega) {
1278+
tp := GetTopology(types.NamespacedName{
1279+
Name: topologyRef.Name,
1280+
Namespace: topologyRef.Namespace,
1281+
})
1282+
finalizers := tp.GetFinalizers()
1283+
g.Expect(finalizers).To(HaveLen(1))
12701284
ovndb := GetOVNDBCluster(OVNDBClusterName)
12711285
g.Expect(ovndb.Status.LastAppliedTopology).NotTo(BeNil())
1272-
g.Expect(ovndb.Status.LastAppliedTopology.Name).To(Equal(ovnTopologies[0].Name))
1286+
g.Expect(ovndb.Status.LastAppliedTopology).To(Equal(topologyRef))
1287+
g.Expect(finalizers).To(ContainElement(
1288+
fmt.Sprintf("openstack.org/ovndbcluster-%s", OVNDBClusterName.Name)))
1289+
}, timeout, interval).Should(Succeed())
1290+
Eventually(func(g Gomega) {
1291+
_, topologySpecObj := GetSampleTopologySpec(OVNDBClusterName.Name)
12731292
g.Expect(th.GetStatefulSet(statefulSetName).Spec.Template.Spec.TopologySpreadConstraints).ToNot(BeNil())
1293+
g.Expect(th.GetStatefulSet(statefulSetName).Spec.Template.Spec.TopologySpreadConstraints).To(Equal(topologySpecObj))
12741294
g.Expect(th.GetStatefulSet(statefulSetName).Spec.Template.Spec.Affinity).To(BeNil())
12751295
}, timeout, interval).Should(Succeed())
12761296
})
@@ -1283,12 +1303,35 @@ var _ = Describe("OVNDBCluster controller", func() {
12831303
}, timeout, interval).Should(Succeed())
12841304

12851305
Eventually(func(g Gomega) {
1306+
tp := GetTopology(types.NamespacedName{
1307+
Name: topologyRefAlt.Name,
1308+
Namespace: topologyRefAlt.Namespace,
1309+
})
1310+
finalizers := tp.GetFinalizers()
1311+
g.Expect(finalizers).To(HaveLen(1))
12861312
ovndb := GetOVNDBCluster(OVNDBClusterName)
12871313
g.Expect(ovndb.Status.LastAppliedTopology).NotTo(BeNil())
1288-
g.Expect(ovndb.Status.LastAppliedTopology.Name).To(Equal(ovnTopologies[1].Name))
1314+
g.Expect(ovndb.Status.LastAppliedTopology).To(Equal(topologyRefAlt))
1315+
g.Expect(finalizers).To(ContainElement(
1316+
fmt.Sprintf("openstack.org/ovndbcluster-%s", OVNDBClusterName.Name)))
1317+
}, timeout, interval).Should(Succeed())
1318+
1319+
Eventually(func(g Gomega) {
1320+
_, topologySpecObj := GetSampleTopologySpec(OVNDBClusterName.Name)
12891321
g.Expect(th.GetStatefulSet(statefulSetName).Spec.Template.Spec.TopologySpreadConstraints).ToNot(BeNil())
1322+
g.Expect(th.GetStatefulSet(statefulSetName).Spec.Template.Spec.TopologySpreadConstraints).To(Equal(topologySpecObj))
12901323
g.Expect(th.GetStatefulSet(statefulSetName).Spec.Template.Spec.Affinity).To(BeNil())
12911324
}, timeout, interval).Should(Succeed())
1325+
1326+
Eventually(func(g Gomega) {
1327+
// Verify the previous referenced topology has no finalizers
1328+
tp := GetTopology(types.NamespacedName{
1329+
Name: topologyRef.Name,
1330+
Namespace: topologyRef.Namespace,
1331+
})
1332+
finalizers := tp.GetFinalizers()
1333+
g.Expect(finalizers).To(BeEmpty())
1334+
}, timeout, interval).Should(Succeed())
12921335
})
12931336
It("removes topologyRef from the spec", func() {
12941337
Eventually(func(g Gomega) {
@@ -1307,6 +1350,18 @@ var _ = Describe("OVNDBCluster controller", func() {
13071350
g.Expect(th.GetStatefulSet(statefulSetName).Spec.Template.Spec.TopologySpreadConstraints).To(BeNil())
13081351
g.Expect(th.GetStatefulSet(statefulSetName).Spec.Template.Spec.Affinity).ToNot(BeNil())
13091352
}, timeout, interval).Should(Succeed())
1353+
1354+
// Verify the existing topologies have no finalizer anymore
1355+
Eventually(func(g Gomega) {
1356+
for _, topology := range ovnTopologies {
1357+
tp := GetTopology(types.NamespacedName{
1358+
Name: topology.Name,
1359+
Namespace: topology.Namespace,
1360+
})
1361+
finalizers := tp.GetFinalizers()
1362+
g.Expect(finalizers).To(BeEmpty())
1363+
}
1364+
}, timeout, interval).Should(Succeed())
13101365
})
13111366

13121367
It("rejects a wrong topologyRef on a different namespace", func() {

0 commit comments

Comments
 (0)