@@ -20,11 +20,11 @@ import (
2020 nadapi "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1"
2121 nadclient "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/client/clientset/versioned/typed/k8s.cni.cncf.io/v1"
2222
23- exutil "github.com/openshift/origin/test/extended/util"
2423 kubeauthorizationv1 "k8s.io/api/authorization/v1"
2524 v1 "k8s.io/api/core/v1"
2625 kerrors "k8s.io/apimachinery/pkg/api/errors"
2726 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27+ "k8s.io/apimachinery/pkg/types"
2828 "k8s.io/apimachinery/pkg/util/intstr"
2929 "k8s.io/apimachinery/pkg/util/rand"
3030 clientset "k8s.io/client-go/kubernetes"
@@ -34,6 +34,9 @@ import (
3434 frameworkpod "k8s.io/kubernetes/test/e2e/framework/pod"
3535 admissionapi "k8s.io/pod-security-admission/api"
3636 utilnet "k8s.io/utils/net"
37+ "k8s.io/utils/pointer"
38+
39+ exutil "github.com/openshift/origin/test/extended/util"
3740)
3841
3942const openDefaultPortsAnnotation = "k8s.ovn.org/open-default-ports"
@@ -689,6 +692,15 @@ var _ = Describe("[sig-network][OCPFeatureGate:NetworkSegmentation][Feature:User
689692 Eventually (userDefinedNetworkReadyFunc (oc .AdminDynamicClient (), f .Namespace .Name , testUdnName ), udnCrReadyTimeout , time .Second ).Should (Succeed ())
690693 })
691694
695+ It ("should create NetworkAttachmentDefinition according to spec" , func () {
696+ udnUidRaw , err := e2ekubectl .RunKubectl (f .Namespace .Name , "get" , userDefinedNetworkResource , testUdnName , "-o" , "jsonpath='{.metadata.uid}'" )
697+ Expect (err ).NotTo (HaveOccurred (), "should get the UserDefinedNetwork UID" )
698+ testUdnUID := strings .Trim (udnUidRaw , "'" )
699+
700+ By ("verify a NetworkAttachmentDefinition is created according to spec" )
701+ assertNetAttachDefManifest (nadClient , f .Namespace .Name , testUdnName , testUdnUID )
702+ })
703+
692704 It ("should delete NetworkAttachmentDefinition when UserDefinedNetwork is deleted" , func () {
693705 By ("delete UserDefinedNetwork" )
694706 _ , err := e2ekubectl .RunKubectl (f .Namespace .Name , "delete" , userDefinedNetworkResource , testUdnName )
@@ -883,6 +895,21 @@ var _ = Describe("[sig-network][OCPFeatureGate:NetworkSegmentation][Feature:User
883895 Eventually (clusterUserDefinedNetworkReadyFunc (oc .AdminDynamicClient (), testClusterUdnName ), udnCrReadyTimeout , time .Second ).Should (Succeed ())
884896 })
885897
898+ It ("should create NAD according to spec in each target namespace and report active namespaces" , func () {
899+ Eventually (
900+ validateClusterUDNStatusReportsActiveNamespacesFunc (oc .AdminDynamicClient (), testClusterUdnName , testTenantNamespaces ... ),
901+ 1 * time .Minute , 3 * time .Second ).Should (Succeed ())
902+
903+ udnUidRaw , err := e2ekubectl .RunKubectl ("" , "get" , clusterUserDefinedNetworkResource , testClusterUdnName , "-o" , "jsonpath='{.metadata.uid}'" )
904+ Expect (err ).NotTo (HaveOccurred (), "should get the ClsuterUserDefinedNetwork UID" )
905+ testUdnUID := strings .Trim (udnUidRaw , "'" )
906+
907+ By ("verify a NetworkAttachmentDefinition is created according to spec" )
908+ for _ , testNsName := range testTenantNamespaces {
909+ assertClusterNADManifest (nadClient , testNsName , testClusterUdnName , testUdnUID )
910+ }
911+ })
912+
886913 It ("when CR is deleted, should delete all managed NAD in each target namespace" , func () {
887914 By ("delete test CR" )
888915 _ , err := e2ekubectl .RunKubectl ("" , "delete" , clusterUserDefinedNetworkResource , testClusterUdnName )
@@ -898,7 +925,77 @@ var _ = Describe("[sig-network][OCPFeatureGate:NetworkSegmentation][Feature:User
898925 }
899926 })
900927
928+ It ("should create NAD in new created namespaces that apply to namespace-selector" , func () {
929+ testNewNs := f .Namespace .Name + "green"
930+
931+ By ("add new target namespace to CR namespace-selector" )
932+ patch := fmt .Sprintf (`[{"op": "add", "path": "./spec/namespaceSelector/matchExpressions/0/values/-", "value": "%s"}]` , testNewNs )
933+ _ , err := e2ekubectl .RunKubectl ("" , "patch" , clusterUserDefinedNetworkResource , testClusterUdnName , "--type=json" , "-p=" + patch )
934+ Expect (err ).NotTo (HaveOccurred ())
935+ Eventually (clusterUserDefinedNetworkReadyFunc (oc .AdminDynamicClient (), testClusterUdnName ), udnCrReadyTimeout , time .Second ).Should (Succeed ())
936+ Eventually (
937+ validateClusterUDNStatusReportsActiveNamespacesFunc (oc .AdminDynamicClient (), testClusterUdnName , testTenantNamespaces ... ),
938+ 1 * time .Minute , 3 * time .Second ).Should (Succeed ())
939+
940+ By ("create the new target namespace" )
941+ _ , err = cs .CoreV1 ().Namespaces ().Create (context .Background (), & v1.Namespace {
942+ ObjectMeta : metav1.ObjectMeta {
943+ Name : testNewNs ,
944+ Labels : map [string ]string {RequiredUDNNamespaceLabel : "" },
945+ }}, metav1.CreateOptions {})
946+ Expect (err ).NotTo (HaveOccurred ())
947+ DeferCleanup (func () error {
948+ err := cs .CoreV1 ().Namespaces ().Delete (context .Background (), testNewNs , metav1.DeleteOptions {})
949+ return err
950+ })
951+
952+ expectedActiveNamespaces := append (testTenantNamespaces , testNewNs )
953+ Eventually (
954+ validateClusterUDNStatusReportsActiveNamespacesFunc (oc .AdminDynamicClient (), testClusterUdnName , expectedActiveNamespaces ... ),
955+ 1 * time .Minute , 3 * time .Second ).Should (Succeed ())
956+
957+ udnUidRaw , err := e2ekubectl .RunKubectl ("" , "get" , clusterUserDefinedNetworkResource , testClusterUdnName , "-o" , "jsonpath='{.metadata.uid}'" )
958+ Expect (err ).NotTo (HaveOccurred (), "should get the ClsuterUserDefinedNetwork UID" )
959+ testUdnUID := strings .Trim (udnUidRaw , "'" )
960+
961+ By ("verify a NAD exist in new namespace according to spec" )
962+ assertClusterNADManifest (nadClient , testNewNs , testClusterUdnName , testUdnUID )
963+ })
964+
901965 When ("namespace-selector is mutated" , func () {
966+ It ("should create NAD in namespaces that apply to mutated namespace-selector" , func () {
967+ testNewNs := f .Namespace .Name + "green"
968+
969+ By ("create new namespace" )
970+ _ , err := cs .CoreV1 ().Namespaces ().Create (context .Background (), & v1.Namespace {
971+ ObjectMeta : metav1.ObjectMeta {
972+ Name : testNewNs ,
973+ Labels : map [string ]string {RequiredUDNNamespaceLabel : "" },
974+ }}, metav1.CreateOptions {})
975+ Expect (err ).NotTo (HaveOccurred ())
976+ DeferCleanup (func () error {
977+ err := cs .CoreV1 ().Namespaces ().Delete (context .Background (), testNewNs , metav1.DeleteOptions {})
978+ return err
979+ })
980+
981+ By ("add new namespace to CR namespace-selector" )
982+ patch := fmt .Sprintf (`[{"op": "add", "path": "./spec/namespaceSelector/matchExpressions/0/values/-", "value": "%s"}]` , testNewNs )
983+ _ , err = e2ekubectl .RunKubectl ("" , "patch" , clusterUserDefinedNetworkResource , testClusterUdnName , "--type=json" , "-p=" + patch )
984+ Expect (err ).NotTo (HaveOccurred ())
985+
986+ By ("verify status reports the new added namespace as active" )
987+ expectedActiveNs := append (testTenantNamespaces , testNewNs )
988+ Eventually (
989+ validateClusterUDNStatusReportsActiveNamespacesFunc (oc .AdminDynamicClient (), testClusterUdnName , expectedActiveNs ... ),
990+ 1 * time .Minute , 3 * time .Second ).Should (Succeed ())
991+
992+ By ("verify a NAD is created in new target namespace according to spec" )
993+ udnUidRaw , err := e2ekubectl .RunKubectl ("" , "get" , clusterUserDefinedNetworkResource , testClusterUdnName , "-o" , "jsonpath='{.metadata.uid}'" )
994+ Expect (err ).NotTo (HaveOccurred (), "should get the ClusterUserDefinedNetwork UID" )
995+ testUdnUID := strings .Trim (udnUidRaw , "'" )
996+ assertClusterNADManifest (nadClient , testNewNs , testClusterUdnName , testUdnUID )
997+ })
998+
902999 It ("should delete managed NAD in namespaces that no longer apply to namespace-selector" , func () {
9031000 By ("remove one active namespace from CR namespace-selector" )
9041001 activeTenantNs := testTenantNamespaces [1 ]
@@ -1427,6 +1524,45 @@ spec:
14271524`
14281525}
14291526
1527+ func assertNetAttachDefManifest (nadClient nadclient.K8sCniCncfIoV1Interface , namespace , udnName , udnUID string ) {
1528+ nad , err := nadClient .NetworkAttachmentDefinitions (namespace ).Get (context .Background (), udnName , metav1.GetOptions {})
1529+ Expect (err ).NotTo (HaveOccurred ())
1530+
1531+ ExpectWithOffset (1 , nad .Name ).To (Equal (udnName ))
1532+ ExpectWithOffset (1 , nad .Namespace ).To (Equal (namespace ))
1533+ ExpectWithOffset (1 , nad .OwnerReferences ).To (Equal ([]metav1.OwnerReference {{
1534+ APIVersion : "k8s.ovn.org/v1" ,
1535+ Kind : "UserDefinedNetwork" ,
1536+ Name : "test-net" ,
1537+ UID : types .UID (udnUID ),
1538+ BlockOwnerDeletion : pointer .Bool (true ),
1539+ Controller : pointer .Bool (true ),
1540+ }}))
1541+
1542+ jsonTemplate := `{
1543+ "cniVersion":"1.1.0",
1544+ "type": "ovn-k8s-cni-overlay",
1545+ "name": "%s",
1546+ "netAttachDefName": "%s",
1547+ "topology": "layer2",
1548+ "role": "secondary",
1549+ "subnets": "10.100.0.0/16"
1550+ }`
1551+
1552+ // REMOVEME(trozet): after network name has been updated to use underscores in OVNK
1553+ expectedLegacyNetworkName := namespace + "." + udnName
1554+ expectedNetworkName := namespace + "_" + udnName
1555+ expectedNadName := namespace + "/" + udnName
1556+
1557+ nadJSONLegacy := fmt .Sprintf (jsonTemplate , expectedLegacyNetworkName , expectedNadName )
1558+ nadJSON := fmt .Sprintf (jsonTemplate , expectedNetworkName , expectedNadName )
1559+
1560+ ExpectWithOffset (1 , nad .Spec .Config ).To (SatisfyAny (
1561+ MatchJSON (nadJSONLegacy ),
1562+ MatchJSON (nadJSON ),
1563+ ))
1564+ }
1565+
14301566func validateUDNStatusReportsConsumers (client dynamic.Interface , udnNamesapce , udnName , expectedPodName string ) error {
14311567 udn , err := client .Resource (udnGVR ).Namespace (udnNamesapce ).Get (context .Background (), udnName , metav1.GetOptions {})
14321568 if err != nil {
@@ -1467,6 +1603,48 @@ func normalizeConditions(conditions []metav1.Condition) []metav1.Condition {
14671603 return conditions
14681604}
14691605
1606+ func assertClusterNADManifest (nadClient nadclient.K8sCniCncfIoV1Interface , namespace , udnName , udnUID string ) {
1607+ nad , err := nadClient .NetworkAttachmentDefinitions (namespace ).Get (context .Background (), udnName , metav1.GetOptions {})
1608+ Expect (err ).NotTo (HaveOccurred ())
1609+
1610+ ExpectWithOffset (1 , nad .Name ).To (Equal (udnName ))
1611+ ExpectWithOffset (1 , nad .Namespace ).To (Equal (namespace ))
1612+ ExpectWithOffset (1 , nad .OwnerReferences ).To (Equal ([]metav1.OwnerReference {{
1613+ APIVersion : "k8s.ovn.org/v1" ,
1614+ Kind : "ClusterUserDefinedNetwork" ,
1615+ Name : udnName ,
1616+ UID : types .UID (udnUID ),
1617+ BlockOwnerDeletion : pointer .Bool (true ),
1618+ Controller : pointer .Bool (true ),
1619+ }}))
1620+ ExpectWithOffset (1 , nad .Labels ).To (Equal (map [string ]string {"k8s.ovn.org/user-defined-network" : "" }))
1621+ ExpectWithOffset (1 , nad .Finalizers ).To (Equal ([]string {"k8s.ovn.org/user-defined-network-protection" }))
1622+
1623+ // REMOVEME(trozet): after network name has been updated to use underscores in OVNK
1624+ expectedLegacyNetworkName := "cluster.udn." + udnName
1625+
1626+ expectedNetworkName := "cluster_udn_" + udnName
1627+ expectedNadName := namespace + "/" + udnName
1628+
1629+ jsonTemplate := `{
1630+ "cniVersion":"1.1.0",
1631+ "type": "ovn-k8s-cni-overlay",
1632+ "name": "%s",
1633+ "netAttachDefName": "%s",
1634+ "topology": "layer2",
1635+ "role": "secondary",
1636+ "subnets": "10.100.0.0/16"
1637+ }`
1638+
1639+ nadJSONLegacy := fmt .Sprintf (jsonTemplate , expectedLegacyNetworkName , expectedNadName )
1640+ nadJSON := fmt .Sprintf (jsonTemplate , expectedNetworkName , expectedNadName )
1641+
1642+ ExpectWithOffset (1 , nad .Spec .Config ).To (SatisfyAny (
1643+ MatchJSON (nadJSONLegacy ),
1644+ MatchJSON (nadJSON ),
1645+ ))
1646+ }
1647+
14701648func validateClusterUDNStatusReportsActiveNamespacesFunc (client dynamic.Interface , cUDNName string , expectedActiveNsNames ... string ) func () error {
14711649 return func () error {
14721650 cUDN , err := client .Resource (clusterUDNGVR ).Get (context .Background (), cUDNName , metav1.GetOptions {})
0 commit comments