github.com/k8snetworkplumbingwg/sriov-network-operator@v1.2.1-0.20240408194816-2d2e5a45d453/test/util/util.go (about) 1 package util 2 3 import ( 4 goctx "context" 5 "encoding/json" 6 "fmt" 7 "reflect" 8 9 // "strings" 10 // "testing" 11 "time" 12 13 dptypes "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/types" 14 // "github.com/operator-framework/operator-sdk/pkg/test/e2eutil" 15 appsv1 "k8s.io/api/apps/v1" 16 // corev1 "k8s.io/api/core/v1" 17 "k8s.io/apimachinery/pkg/api/errors" 18 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 19 "k8s.io/apimachinery/pkg/types" 20 "k8s.io/apimachinery/pkg/util/wait" 21 client "sigs.k8s.io/controller-runtime/pkg/client" 22 23 // "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/apis" 24 sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1" 25 ) 26 27 var ( 28 RetryInterval = time.Second * 1 29 APITimeout = time.Second * 20 30 Timeout = time.Second * 60 31 CleanupRetryInterval = time.Second * 1 32 CleanupTimeout = time.Second * 5 33 ) 34 35 func WaitForSriovNetworkNodeStateReady(nodeState *sriovnetworkv1.SriovNetworkNodeState, client client.Client, namespace, name string, retryInterval, timeout time.Duration) error { 36 time.Sleep(30 * time.Second) 37 err := wait.PollImmediate(retryInterval, timeout, func() (done bool, err error) { 38 ctx, cancel := goctx.WithTimeout(goctx.Background(), APITimeout) 39 defer cancel() 40 err = client.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, nodeState) 41 if err != nil { 42 if errors.IsNotFound(err) { 43 return false, nil 44 } 45 return false, err 46 } 47 if nodeState.Status.SyncStatus != "Succeeded" { 48 return false, nil 49 } 50 return true, nil 51 }) 52 if err != nil { 53 fmt.Printf("failed to wait for ds %s/%s to be ready: %v", namespace, name, err) 54 return err 55 } 56 57 return nil 58 } 59 60 func WaitForDaemonSetReady(ds *appsv1.DaemonSet, client client.Client, namespace, name string, retryInterval, timeout time.Duration) error { 61 err := wait.PollImmediate(retryInterval, timeout, func() (done bool, err error) { 62 ctx, cancel := goctx.WithTimeout(goctx.Background(), APITimeout) 63 defer cancel() 64 err = client.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, ds) 65 if err != nil { 66 if errors.IsNotFound(err) { 67 return false, nil 68 } 69 return false, err 70 } 71 if ds.Status.DesiredNumberScheduled == ds.Status.NumberReady { 72 return true, nil 73 } else { 74 return false, nil 75 } 76 }) 77 if err != nil { 78 fmt.Printf("failed to wait for ds %s/%s to be ready: %v", namespace, name, err) 79 return err 80 } 81 82 return nil 83 } 84 85 func WaitForNamespacedObject(obj client.Object, client client.Client, namespace, name string, retryInterval, timeout time.Duration) error { 86 err := wait.PollImmediate(retryInterval, timeout, func() (done bool, err error) { 87 ctx, cancel := goctx.WithTimeout(goctx.Background(), APITimeout) 88 defer cancel() 89 err = client.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, obj) 90 if err != nil { 91 if errors.IsNotFound(err) { 92 return false, nil 93 } 94 return false, err 95 } 96 return true, nil 97 }) 98 if err != nil { 99 fmt.Printf("failed to wait for obj %s/%s to exist: %v", namespace, name, err) 100 return err 101 } 102 103 return nil 104 } 105 106 func WaitForNamespacedObjectDeleted(obj client.Object, client client.Client, namespace, name string, retryInterval, timeout time.Duration) error { 107 err := wait.PollImmediate(retryInterval, timeout, func() (done bool, err error) { 108 ctx, cancel := goctx.WithTimeout(goctx.Background(), APITimeout) 109 defer cancel() 110 err = client.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, obj) 111 if err != nil { 112 if errors.IsNotFound(err) { 113 return true, nil 114 } 115 return false, err 116 } 117 return false, nil 118 }) 119 if err != nil { 120 fmt.Printf("failed to wait for obj %s/%s to not exist: %v", namespace, name, err) 121 return err 122 } 123 124 return nil 125 } 126 127 func GenerateSriovNetworkCRs(namespace string, specs map[string]sriovnetworkv1.SriovNetworkSpec) map[string]sriovnetworkv1.SriovNetwork { 128 crs := make(map[string]sriovnetworkv1.SriovNetwork) 129 130 for k, v := range specs { 131 crs[k] = sriovnetworkv1.SriovNetwork{ 132 TypeMeta: metav1.TypeMeta{ 133 Kind: "SriovNetwork", 134 APIVersion: "sriovnetwork.openshift.io/v1", 135 }, 136 ObjectMeta: metav1.ObjectMeta{ 137 Name: k, 138 Namespace: namespace, 139 }, 140 Spec: v, 141 } 142 } 143 return crs 144 } 145 146 func GenerateSriovIBNetworkCRs(namespace string, specs map[string]sriovnetworkv1.SriovIBNetworkSpec) map[string]sriovnetworkv1.SriovIBNetwork { 147 crs := make(map[string]sriovnetworkv1.SriovIBNetwork) 148 149 for k, v := range specs { 150 crs[k] = sriovnetworkv1.SriovIBNetwork{ 151 TypeMeta: metav1.TypeMeta{ 152 Kind: "SriovIBNetwork", 153 APIVersion: "sriovnetwork.openshift.io/v1", 154 }, 155 ObjectMeta: metav1.ObjectMeta{ 156 Name: k, 157 Namespace: namespace, 158 }, 159 Spec: v, 160 } 161 } 162 return crs 163 } 164 165 func ValidateDevicePluginConfig(nps []*sriovnetworkv1.SriovNetworkNodePolicy, rawConfig string) error { 166 rcl := dptypes.ResourceConfList{} 167 168 if err := json.Unmarshal([]byte(rawConfig), &rcl); err != nil { 169 return err 170 } 171 172 if len(rcl.ResourceList) != 1 { 173 return fmt.Errorf("number of resources in config is incorrect: %d", len(rcl.ResourceList)) 174 } 175 176 for _, rc := range rcl.ResourceList { 177 for _, np := range nps { 178 if rc.ResourceName != np.Spec.ResourceName { 179 continue 180 } 181 182 netDeviceSelectors := &dptypes.NetDeviceSelectors{} 183 raw, err := rc.Selectors.MarshalJSON() 184 if err != nil { 185 return err 186 } 187 188 err = json.Unmarshal(raw, netDeviceSelectors) 189 if err != nil { 190 return err 191 } 192 193 if netDeviceSelectors.IsRdma != np.Spec.IsRdma || rc.ResourceName != np.Spec.ResourceName || !validateSelector(netDeviceSelectors, &np.Spec.NicSelector) { 194 return fmt.Errorf("content of config is incorrect") 195 } 196 } 197 } 198 return nil 199 } 200 201 func validateSelector(rc *dptypes.NetDeviceSelectors, ns *sriovnetworkv1.SriovNetworkNicSelector) bool { 202 if ns.DeviceID != "" { 203 if len(rc.Devices) != 1 || ns.DeviceID != rc.Devices[0] { 204 return false 205 } 206 } 207 if ns.Vendor != "" { 208 if len(rc.Vendors) != 1 || ns.Vendor != rc.Vendors[0] { 209 return false 210 } 211 } 212 if len(ns.PfNames) > 0 { 213 if !reflect.DeepEqual(ns.PfNames, rc.PfNames) { 214 return false 215 } 216 } 217 return true 218 }