Skip to content

Commit fad13bf

Browse files
committed
unit test
1 parent e225064 commit fad13bf

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed

pkg/controller/topology_test.go

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121
"fmt"
2222
"slices"
23+
"strings"
2324
"testing"
2425

2526
"github.com/container-storage-interface/spec/lib/go/csi"
@@ -1794,6 +1795,136 @@ func TestProvisionWithDeletedNodeFromCache(t *testing.T) {
17941795
}
17951796
}
17961797

1798+
func TestNodeTopologyLabelFallback(t *testing.T) {
1799+
// When the Node initially has incomplete topology labels, provisioning is expected to fail.
1800+
// Once those labels are added, provisioning should succeed.
1801+
topologyKeys := []string{
1802+
"com.example.csi/zone",
1803+
"com.example.csi/rack",
1804+
"com.example.csi/region",
1805+
"com.example.csi/compute-type",
1806+
}
1807+
incompleteNodeLabels := map[string]string{
1808+
"com.example.csi/zone": "zone1",
1809+
"com.example.csi/rack": "rackA",
1810+
"com.example.csi/region": "us-west",
1811+
}
1812+
completeNodeLabels := map[string]string{
1813+
"com.example.csi/zone": "zone1",
1814+
"com.example.csi/rack": "rackA",
1815+
"com.example.csi/region": "us-west",
1816+
"com.example.csi/compute-type": "standard",
1817+
}
1818+
1819+
// originally the node has incomplete topology labels
1820+
node := &v1.Node{
1821+
ObjectMeta: metav1.ObjectMeta{
1822+
Name: "test-node",
1823+
Labels: incompleteNodeLabels,
1824+
},
1825+
}
1826+
csiNode := &storagev1.CSINode{
1827+
ObjectMeta: metav1.ObjectMeta{
1828+
Name: "test-node",
1829+
},
1830+
Spec: storagev1.CSINodeSpec{
1831+
Drivers: []storagev1.CSINodeDriver{
1832+
{
1833+
Name: testDriverName,
1834+
NodeID: "test-node",
1835+
TopologyKeys: topologyKeys,
1836+
},
1837+
},
1838+
},
1839+
}
1840+
pvc := &v1.PersistentVolumeClaim{
1841+
ObjectMeta: metav1.ObjectMeta{
1842+
Name: "test-pvc",
1843+
Namespace: "default",
1844+
UID: "test-pvc-uid",
1845+
},
1846+
}
1847+
kubeClient := fakeclientset.NewSimpleClientset(node, csiNode, pvc)
1848+
_, csiNodeLister, nodeLister, _, _, stopChan := listers(kubeClient)
1849+
defer close(stopChan)
1850+
pvcNodeStore := NewInMemoryStore()
1851+
1852+
t.Run("first provisioning attempt should fail because incomplete node labels", func(t *testing.T) {
1853+
_, err := GenerateAccessibilityRequirements(
1854+
kubeClient,
1855+
testDriverName,
1856+
pvc.UID,
1857+
pvc.Name,
1858+
nil,
1859+
"test-node",
1860+
false,
1861+
false,
1862+
csiNodeLister,
1863+
nodeLister,
1864+
pvcNodeStore,
1865+
)
1866+
if err == nil {
1867+
t.Fatal("expected error due to missing topology label, got nil")
1868+
}
1869+
expectedError := "topology labels from selected node"
1870+
if !strings.Contains(err.Error(), expectedError) {
1871+
t.Errorf("expected error containing %q, got: %v", expectedError, err)
1872+
}
1873+
})
1874+
1875+
// update the Node with the missing label
1876+
node.Labels = completeNodeLabels
1877+
_, err := kubeClient.CoreV1().Nodes().Update(context.TODO(), node, metav1.UpdateOptions{})
1878+
if err != nil {
1879+
t.Fatalf("failed to update node: %v", err)
1880+
}
1881+
_, csiNodeLister2, nodeLister2, _, _, stopChan2 := listers(kubeClient)
1882+
defer close(stopChan2)
1883+
1884+
t.Run("second provisioning attempt should succeed after labels added", func(t *testing.T) {
1885+
requirements, err := GenerateAccessibilityRequirements(
1886+
kubeClient,
1887+
testDriverName,
1888+
pvc.UID,
1889+
pvc.Name,
1890+
nil,
1891+
"test-node",
1892+
false,
1893+
false,
1894+
csiNodeLister2,
1895+
nodeLister2,
1896+
pvcNodeStore,
1897+
)
1898+
if err != nil {
1899+
t.Fatalf("expected success after fallback, got error: %v", err)
1900+
}
1901+
if requirements == nil {
1902+
t.Fatal("expected requirements to be generated, got nil")
1903+
}
1904+
1905+
expectedTopology := &csi.Topology{
1906+
Segments: map[string]string{
1907+
"com.example.csi/zone": "zone1",
1908+
"com.example.csi/rack": "rackA",
1909+
"com.example.csi/region": "us-west",
1910+
"com.example.csi/compute-type": "standard",
1911+
},
1912+
}
1913+
if len(requirements.Requisite) != 1 {
1914+
t.Errorf("expected 1 requisite topology, got %d", len(requirements.Requisite))
1915+
} else if !cmp.Equal(requirements.Requisite[0], expectedTopology, protocmp.Transform()) {
1916+
t.Errorf("requisite topology mismatch.\nExpected: %v\nGot: %v",
1917+
expectedTopology, requirements.Requisite[0])
1918+
}
1919+
if len(requirements.Preferred) != 1 {
1920+
t.Errorf("expected 1 preferred topology, got %d", len(requirements.Preferred))
1921+
} else if !cmp.Equal(requirements.Preferred[0], expectedTopology, protocmp.Transform()) {
1922+
t.Errorf("preferred topology mismatch.\nExpected: %v\nGot: %v",
1923+
expectedTopology, requirements.Preferred[0])
1924+
}
1925+
})
1926+
}
1927+
17971928
func BenchmarkDedupAndSortZone(b *testing.B) {
17981929
terms := make([]topologyTerm, 0, 3000)
17991930
for range 1000 {

0 commit comments

Comments
 (0)