github.com/k8snetworkplumbingwg/sriov-network-operator@v1.2.1-0.20240408194816-2d2e5a45d453/test/util/namespaces/namespaces.go (about) 1 package namespaces 2 3 import ( 4 "context" 5 "fmt" 6 "strings" 7 "time" 8 9 k8sv1 "k8s.io/api/core/v1" 10 k8serrors "k8s.io/apimachinery/pkg/api/errors" 11 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 12 "k8s.io/apimachinery/pkg/util/wait" 13 "k8s.io/utils/pointer" 14 runtimeclient "sigs.k8s.io/controller-runtime/pkg/client" 15 16 sriovv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" 17 testclient "github.com/k8snetworkplumbingwg/sriov-network-operator/test/util/client" 18 ) 19 20 // Test is the namespace to be use for testing 21 const Test = "sriov-conformance-testing" 22 23 var inhibitSecurityAdmissionLabels = map[string]string{ 24 "pod-security.kubernetes.io/audit": "privileged", 25 "pod-security.kubernetes.io/enforce": "privileged", 26 "pod-security.kubernetes.io/warn": "privileged", 27 "security.openshift.io/scc.podSecurityLabelSync": "false", 28 } 29 30 // WaitForDeletion waits until the namespace will be removed from the cluster 31 func WaitForDeletion(cs *testclient.ClientSet, nsName string, timeout time.Duration) error { 32 return wait.PollImmediate(time.Second, timeout, func() (bool, error) { 33 _, err := cs.Namespaces().Get(context.Background(), nsName, metav1.GetOptions{}) 34 if k8serrors.IsNotFound(err) { 35 return true, nil 36 } 37 return false, nil 38 }) 39 } 40 41 // Create creates a new namespace with the given name. 42 // If the namespace exists, it returns. 43 func Create(namespace string, cs *testclient.ClientSet) error { 44 _, err := cs.Namespaces().Create(context.Background(), &k8sv1.Namespace{ 45 ObjectMeta: metav1.ObjectMeta{ 46 Name: namespace, 47 Labels: inhibitSecurityAdmissionLabels, 48 }}, metav1.CreateOptions{}) 49 50 if k8serrors.IsAlreadyExists(err) { 51 return nil 52 } 53 return err 54 } 55 56 // DeleteAndWait deletes a namespace and waits until it is deleted 57 func DeleteAndWait(cs *testclient.ClientSet, namespace string, timeout time.Duration) error { 58 err := cs.Namespaces().Delete(context.Background(), namespace, metav1.DeleteOptions{}) 59 if k8serrors.IsNotFound(err) { 60 return nil 61 } 62 63 if err != nil { 64 return fmt.Errorf("failed to delete namespace [%s]: %w", namespace, err) 65 } 66 67 return WaitForDeletion(cs, namespace, timeout) 68 } 69 70 // Exists tells whether the given namespace exists 71 func Exists(namespace string, cs *testclient.ClientSet) bool { 72 _, err := cs.Namespaces().Get(context.Background(), namespace, metav1.GetOptions{}) 73 return err == nil || !k8serrors.IsNotFound(err) 74 } 75 76 // CleanPods deletes all pods in namespace 77 func CleanPods(namespace string, cs *testclient.ClientSet) error { 78 if !Exists(namespace, cs) { 79 return nil 80 } 81 err := cs.Pods(namespace).DeleteCollection(context.Background(), metav1.DeleteOptions{ 82 GracePeriodSeconds: pointer.Int64Ptr(0), 83 }, metav1.ListOptions{}) 84 if err != nil { 85 return fmt.Errorf("failed to delete pods %v", err) 86 } 87 return err 88 } 89 90 // CleanPolicies deletes all SriovNetworkNodePolicies in operatorNamespace 91 func CleanPolicies(operatorNamespace string, cs *testclient.ClientSet) error { 92 policies := sriovv1.SriovNetworkNodePolicyList{} 93 err := cs.List(context.Background(), 94 &policies, 95 runtimeclient.InNamespace(operatorNamespace), 96 ) 97 if err != nil { 98 return err 99 } 100 for _, p := range policies.Items { 101 if p.Name != "default" && strings.HasPrefix(p.Name, "test-") { 102 err := cs.Delete(context.Background(), &p) 103 if err != nil { 104 return fmt.Errorf("failed to delete policy %v", err) 105 } 106 } 107 } 108 return err 109 } 110 111 // CleanNetworks deletes all network in operatorNamespace 112 func CleanNetworks(operatorNamespace string, cs *testclient.ClientSet) error { 113 networks := sriovv1.SriovNetworkList{} 114 err := cs.List(context.Background(), 115 &networks, 116 runtimeclient.InNamespace(operatorNamespace)) 117 if err != nil { 118 return err 119 } 120 for _, n := range networks.Items { 121 if strings.HasPrefix(n.Name, "test-") { 122 err := cs.Delete(context.Background(), &n) 123 if err != nil { 124 return fmt.Errorf("failed to delete network %v", err) 125 } 126 } 127 } 128 return waitForSriovNetworkDeletion(operatorNamespace, cs, 15*time.Second) 129 } 130 131 func waitForSriovNetworkDeletion(operatorNamespace string, cs *testclient.ClientSet, timeout time.Duration) error { 132 return wait.PollImmediate(time.Second, timeout, func() (bool, error) { 133 networks := sriovv1.SriovNetworkList{} 134 err := cs.List(context.Background(), 135 &networks, 136 runtimeclient.InNamespace(operatorNamespace)) 137 if err != nil { 138 return false, err 139 } 140 for _, network := range networks.Items { 141 if strings.HasPrefix(network.Name, "test-") { 142 return false, nil 143 } 144 } 145 return true, nil 146 }) 147 } 148 149 // Clean cleans all dangling objects from the given namespace. 150 func Clean(operatorNamespace, namespace string, cs *testclient.ClientSet, discoveryEnabled bool) error { 151 err := CleanPods(namespace, cs) 152 if err != nil { 153 return err 154 } 155 err = CleanNetworks(operatorNamespace, cs) 156 if err != nil { 157 return err 158 } 159 if discoveryEnabled { 160 return nil 161 } 162 err = CleanPolicies(operatorNamespace, cs) 163 if err != nil { 164 return err 165 } 166 return nil 167 }