github.com/kubewharf/katalyst-core@v0.5.3/pkg/controller/kcc/util/kcct_test.go (about) 1 /* 2 Copyright 2022 The Katalyst Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package util 18 19 import ( 20 "reflect" 21 "testing" 22 "time" 23 24 v1 "k8s.io/api/core/v1" 25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 27 "k8s.io/klog/v2" 28 29 apisv1alpha1 "github.com/kubewharf/katalyst-api/pkg/apis/config/v1alpha1" 30 "github.com/kubewharf/katalyst-core/pkg/util/native" 31 ) 32 33 func toTestUnstructured(obj interface{}) *unstructured.Unstructured { 34 ret, err := native.ToUnstructured(obj) 35 if err != nil { 36 klog.Error(err) 37 } 38 return ret 39 } 40 41 func generateTestCNC(name string, labels map[string]string) *apisv1alpha1.CustomNodeConfig { 42 return &apisv1alpha1.CustomNodeConfig{ 43 ObjectMeta: metav1.ObjectMeta{ 44 Name: name, 45 Labels: labels, 46 }, 47 } 48 } 49 50 func generateTestTargetResource(name, labelSelector string, nodeNames []string) *unstructured.Unstructured { 51 return toTestUnstructured(&apisv1alpha1.AdminQoSConfiguration{ 52 ObjectMeta: metav1.ObjectMeta{ 53 Name: name, 54 }, 55 Spec: apisv1alpha1.AdminQoSConfigurationSpec{ 56 GenericConfigSpec: apisv1alpha1.GenericConfigSpec{ 57 NodeLabelSelector: labelSelector, 58 EphemeralSelector: apisv1alpha1.EphemeralSelector{ 59 NodeNames: nodeNames, 60 }, 61 }, 62 }, 63 Status: apisv1alpha1.GenericConfigStatus{}, 64 }) 65 } 66 67 func generateTestTargetResourceWithTimeout(name, labelSelector string, nodeNames []string) *unstructured.Unstructured { 68 return toTestUnstructured(&apisv1alpha1.AdminQoSConfiguration{ 69 ObjectMeta: metav1.ObjectMeta{ 70 Name: name, 71 CreationTimestamp: metav1.NewTime(time.Now().Add(-1 * time.Minute * 10)), 72 }, 73 Spec: apisv1alpha1.AdminQoSConfigurationSpec{ 74 GenericConfigSpec: apisv1alpha1.GenericConfigSpec{ 75 NodeLabelSelector: labelSelector, 76 EphemeralSelector: apisv1alpha1.EphemeralSelector{ 77 NodeNames: nodeNames, 78 LastDuration: &metav1.Duration{Duration: time.Minute}, 79 }, 80 }, 81 }, 82 Status: apisv1alpha1.GenericConfigStatus{}, 83 }) 84 } 85 86 func Test_findMatchedTargetConfig(t *testing.T) { 87 t.Parallel() 88 89 type args struct { 90 cnc *apisv1alpha1.CustomNodeConfig 91 configList []*unstructured.Unstructured 92 } 93 tests := []struct { 94 name string 95 args args 96 want []*unstructured.Unstructured 97 wantErr bool 98 }{ 99 { 100 name: "only nodeNames config", 101 args: args{ 102 cnc: generateTestCNC("node-1", map[string]string{ 103 "aa": "default", 104 }), 105 configList: []*unstructured.Unstructured{ 106 generateTestTargetResource("config-1", "", []string{"node-1"}), 107 generateTestTargetResource("config-2", "", []string{"node-2"}), 108 }, 109 }, 110 want: []*unstructured.Unstructured{ 111 generateTestTargetResource("config-1", "", []string{"node-1"}), 112 }, 113 }, 114 { 115 name: "nodeNames overlap", 116 args: args{ 117 cnc: generateTestCNC("node-1", map[string]string{ 118 "aa": "default", 119 }), 120 configList: []*unstructured.Unstructured{ 121 generateTestTargetResource("config-1", "", []string{"node-1"}), 122 generateTestTargetResource("config-2", "", []string{"node-1"}), 123 }, 124 }, 125 want: []*unstructured.Unstructured{ 126 generateTestTargetResource("config-1", "", []string{"node-1"}), 127 generateTestTargetResource("config-2", "", []string{"node-1"}), 128 }, 129 }, 130 { 131 name: "target config invalid", 132 args: args{ 133 cnc: generateTestCNC("node-1", map[string]string{ 134 "aa": "default", 135 }), 136 configList: []*unstructured.Unstructured{ 137 generateTestTargetResourceWithTimeout("config-1", "aa=default", []string{"node-1"}), 138 generateTestTargetResourceWithTimeout("config-2", "", nil), 139 }, 140 }, 141 want: []*unstructured.Unstructured{ 142 generateTestTargetResourceWithTimeout("config-1", "aa=default", []string{"node-1"}), 143 }, 144 }, 145 { 146 name: "nodeNames prior than labelSelector", 147 args: args{ 148 cnc: generateTestCNC("node-1", map[string]string{ 149 "aa": "default", 150 }), 151 configList: []*unstructured.Unstructured{ 152 generateTestTargetResource("config-1", "aa=default", nil), 153 generateTestTargetResource("config-2", "", []string{"node-1"}), 154 }, 155 }, 156 want: []*unstructured.Unstructured{ 157 generateTestTargetResource("config-2", "", []string{"node-1"}), 158 }, 159 }, 160 { 161 name: "labelSelector overlap", 162 args: args{ 163 cnc: generateTestCNC("node-1", map[string]string{ 164 "aa": "default", 165 }), 166 configList: []*unstructured.Unstructured{ 167 generateTestTargetResource("config-1", "aa=default", nil), 168 generateTestTargetResource("config-2", "", nil), 169 generateTestTargetResource("config-3", "aa in (default,non-standard)", nil), 170 }, 171 }, 172 want: []*unstructured.Unstructured{ 173 generateTestTargetResource("config-1", "aa=default", nil), 174 generateTestTargetResource("config-3", "aa in (default,non-standard)", nil), 175 }, 176 }, 177 { 178 name: "labelSelector overlap but nodeName valid", 179 args: args{ 180 cnc: generateTestCNC("node-1", map[string]string{ 181 "aa": "default", 182 }), 183 configList: []*unstructured.Unstructured{ 184 generateTestTargetResource("config-1", "aa=default", nil), 185 generateTestTargetResource("config-2", "", []string{"node-1"}), 186 generateTestTargetResource("config-3", "aa in (default,non-standard)", nil), 187 }, 188 }, 189 want: []*unstructured.Unstructured{ 190 generateTestTargetResource("config-2", "", []string{"node-1"}), 191 }, 192 }, 193 } 194 for _, tt := range tests { 195 tt := tt 196 t.Run(tt.name, func(t *testing.T) { 197 t.Parallel() 198 199 got, err := findMatchedKCCTargetConfigForNode(tt.args.cnc, tt.args.configList) 200 if (err != nil) != tt.wantErr { 201 t.Errorf("findMatchedKCCTargetConfigForNode() error = %v, wantErr %v", err, tt.wantErr) 202 return 203 } 204 if !reflect.DeepEqual(got, tt.want) { 205 t.Errorf("findMatchedKCCTargetConfigForNode() got = %v, want %v", got, tt.want) 206 } 207 }) 208 } 209 } 210 211 func TestUpdateKCCTGenericConditions(t *testing.T) { 212 t.Parallel() 213 214 type args struct { 215 status *apisv1alpha1.GenericConfigStatus 216 conditionType apisv1alpha1.ConfigConditionType 217 conditionStatus v1.ConditionStatus 218 reason string 219 message string 220 } 221 tests := []struct { 222 name string 223 args args 224 want bool 225 }{ 226 { 227 name: "test-1", 228 args: args{ 229 status: &apisv1alpha1.GenericConfigStatus{}, 230 conditionType: apisv1alpha1.ConfigConditionTypeValid, 231 conditionStatus: v1.ConditionTrue, 232 reason: "", 233 message: "", 234 }, 235 want: true, 236 }, 237 } 238 for _, tt := range tests { 239 tt := tt 240 t.Run(tt.name, func(t *testing.T) { 241 t.Parallel() 242 if got := UpdateKCCTGenericConditions(tt.args.status, tt.args.conditionType, tt.args.conditionStatus, tt.args.reason, tt.args.message); got != tt.want { 243 t.Errorf("UpdateKCCTGenericConditions() = %v, want %v", got, tt.want) 244 } 245 }) 246 } 247 }