github.com/kubewharf/katalyst-core@v0.5.3/pkg/util/resource-recommend/resource/k8s_resource_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 resource 18 19 import ( 20 "context" 21 "reflect" 22 "testing" 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/apimachinery/pkg/types" 28 "sigs.k8s.io/controller-runtime/pkg/client" 29 "sigs.k8s.io/controller-runtime/pkg/client/fake" 30 31 "github.com/kubewharf/katalyst-api/pkg/apis/recommendation/v1alpha1" 32 ) 33 34 func TestConvertAndGetResource(t *testing.T) { 35 type args struct { 36 ctx context.Context 37 client client.Client 38 namespace string 39 targetRef v1alpha1.CrossVersionObjectReference 40 } 41 type env struct { 42 namespace string 43 kind string 44 name string 45 apiVersion string 46 } 47 tests := []struct { 48 name string 49 args args 50 env env 51 want *unstructured.Unstructured 52 wantErr bool 53 }{ 54 { 55 name: "Get resource failed", 56 args: args{ 57 ctx: context.TODO(), 58 client: fake.NewClientBuilder().Build(), 59 namespace: "fakeNamespace", 60 targetRef: v1alpha1.CrossVersionObjectReference{ 61 Kind: "Deployment", 62 Name: "mockResourceName", 63 APIVersion: "apps/v1", 64 }, 65 }, 66 env: env{ 67 namespace: "fakeNamespace", 68 kind: "Deployment", 69 name: "mockResourceName1", 70 apiVersion: "apps/v1", 71 }, 72 wantErr: true, 73 }, 74 { 75 name: "Get resource failed", 76 args: args{ 77 ctx: context.TODO(), 78 client: fake.NewClientBuilder().Build(), 79 namespace: "fakeNamespace", 80 targetRef: v1alpha1.CrossVersionObjectReference{ 81 Kind: "Deployment", 82 Name: "mockResourceName", 83 APIVersion: "apps/v1", 84 }, 85 }, 86 env: env{ 87 namespace: "fakeNamespace", 88 kind: "Deployment", 89 name: "mockResourceName", 90 apiVersion: "apps/v1", 91 }, 92 wantErr: false, 93 }, 94 } 95 for _, tt := range tests { 96 t.Run(tt.name, func(t *testing.T) { 97 CreateMockUnstructured(nil, nil, tt.env.name, tt.env.namespace, tt.env.apiVersion, tt.env.kind, tt.args.client) 98 _, err := ConvertAndGetResource(tt.args.ctx, tt.args.client, tt.args.namespace, tt.args.targetRef) 99 if (err != nil) != tt.wantErr { 100 t.Errorf("ConvertAndGetResource() error = %v, wantErr %v", err, tt.wantErr) 101 return 102 } 103 }) 104 } 105 } 106 107 func TestGetAllClaimedContainers(t *testing.T) { 108 type args struct { 109 controller *unstructured.Unstructured 110 } 111 type env struct { 112 needCreate bool 113 unstructuredTemplateSpec map[string]interface{} 114 } 115 tests := []struct { 116 name string 117 args args 118 env env 119 want []string 120 wantErr bool 121 }{ 122 { 123 name: "spec.template.spec not found", 124 args: args{ 125 controller: &unstructured.Unstructured{}, 126 }, 127 env: env{ 128 needCreate: false, 129 unstructuredTemplateSpec: map[string]interface{}{}, 130 }, 131 want: nil, 132 wantErr: true, 133 }, 134 { 135 name: "nestedMap failed", 136 args: args{ 137 controller: &unstructured.Unstructured{}, 138 }, 139 env: env{ 140 needCreate: true, 141 unstructuredTemplateSpec: map[string]interface{}{ 142 "container": []interface{}{ 143 map[string]interface{}{ 144 "name": "container-1", 145 "image": "image:latest", 146 }, 147 map[string]interface{}{ 148 "name": "container-2", 149 "image": "image:latest", 150 }, 151 }, 152 }, 153 }, 154 want: nil, 155 wantErr: true, 156 }, 157 { 158 name: "container name not found", 159 args: args{ 160 controller: &unstructured.Unstructured{}, 161 }, 162 env: env{ 163 needCreate: true, 164 unstructuredTemplateSpec: map[string]interface{}{ 165 "containers": []interface{}{ 166 map[string]interface{}{ 167 "image": "image:latest", 168 }, 169 map[string]interface{}{ 170 "image": "image:latest", 171 }, 172 }, 173 }, 174 }, 175 want: []string{}, 176 wantErr: false, 177 }, 178 { 179 name: "all right", 180 args: args{ 181 controller: &unstructured.Unstructured{}, 182 }, 183 env: env{ 184 needCreate: true, 185 unstructuredTemplateSpec: map[string]interface{}{ 186 "containers": []interface{}{ 187 map[string]interface{}{ 188 "name": "container-1", 189 "image": "image:latest", 190 }, 191 map[string]interface{}{ 192 "name": "container-2", 193 "image": "image:latest", 194 }, 195 }, 196 }, 197 }, 198 want: []string{"container-1", "container-2"}, 199 wantErr: false, 200 }, 201 } 202 for _, tt := range tests { 203 t.Run(tt.name, func(t *testing.T) { 204 if tt.env.needCreate { 205 tt.args.controller.SetName("mockName") 206 unstructured.SetNestedMap(tt.args.controller.Object, tt.env.unstructuredTemplateSpec, "spec", "template", "spec") 207 } 208 got, err := GetAllClaimedContainers(tt.args.controller) 209 if (err != nil) != tt.wantErr { 210 t.Errorf("GetAllClaimedContainers() error = %v, wantErr %v", err, tt.wantErr) 211 return 212 } 213 if !reflect.DeepEqual(got, tt.want) { 214 t.Errorf("GetAllClaimedContainers() got = %v, want %v", got, tt.want) 215 } 216 }) 217 } 218 } 219 220 func TestPatchUpdateResourceRecommend(t *testing.T) { 221 type args struct { 222 client client.Client 223 namespaceName types.NamespacedName 224 resourceRecommend *v1alpha1.ResourceRecommend 225 } 226 tests := []struct { 227 name string 228 args args 229 wantErr bool 230 wantResourceRecommend *v1alpha1.ResourceRecommend 231 }{ 232 { 233 name: "all right 1", 234 args: args{ 235 client: fake.NewClientBuilder().Build(), 236 namespaceName: types.NamespacedName{ 237 Name: "mockName", 238 Namespace: "mockNamespace", 239 }, 240 resourceRecommend: &v1alpha1.ResourceRecommend{ 241 TypeMeta: metav1.TypeMeta{ 242 Kind: "ResourceRecommend", 243 APIVersion: "autoscaling.katalyst.kubewharf.io/v1alpha1", 244 }, 245 ObjectMeta: metav1.ObjectMeta{ 246 Name: "mockName", 247 Namespace: "mockNamespace", 248 }, 249 Status: v1alpha1.ResourceRecommendStatus{}, 250 }, 251 }, 252 wantResourceRecommend: &v1alpha1.ResourceRecommend{ 253 Status: v1alpha1.ResourceRecommendStatus{ 254 RecommendResources: &v1alpha1.RecommendResources{ 255 ContainerRecommendations: []v1alpha1.ContainerResources{ 256 { 257 ContainerName: "ContainerName1", 258 Requests: &v1alpha1.ContainerResourceList{}, 259 }, 260 { 261 ContainerName: "ContainerName2", 262 Requests: &v1alpha1.ContainerResourceList{}, 263 }, 264 { 265 ContainerName: "ContainerName3", 266 Requests: &v1alpha1.ContainerResourceList{}, 267 }, 268 { 269 ContainerName: "ContainerName4", 270 Requests: &v1alpha1.ContainerResourceList{}, 271 }, 272 }, 273 }, 274 Conditions: []v1alpha1.ResourceRecommendCondition{ 275 { 276 Type: v1alpha1.Validated, 277 Reason: "reason1", 278 Status: v1.ConditionTrue, 279 Message: "Message", 280 }, 281 { 282 Type: v1alpha1.Validated, 283 Reason: "reason2", 284 Status: v1.ConditionTrue, 285 Message: "Message", 286 }, 287 { 288 Type: v1alpha1.Validated, 289 Reason: "reason3", 290 Status: v1.ConditionTrue, 291 Message: "Message", 292 }, 293 { 294 Type: v1alpha1.Validated, 295 Reason: "reason4", 296 Status: v1.ConditionTrue, 297 Message: "Message", 298 }, 299 }, 300 }, 301 }, 302 wantErr: false, 303 }, 304 { 305 name: "all right 2", 306 args: args{ 307 client: fake.NewClientBuilder().Build(), 308 namespaceName: types.NamespacedName{ 309 Name: "mockName", 310 Namespace: "mockNamespace", 311 }, 312 resourceRecommend: &v1alpha1.ResourceRecommend{ 313 TypeMeta: metav1.TypeMeta{ 314 Kind: "ResourceRecommend", 315 APIVersion: "autoscaling.katalyst.kubewharf.io/v1alpha1", 316 }, 317 ObjectMeta: metav1.ObjectMeta{ 318 Name: "mockName", 319 Namespace: "mockNamespace", 320 }, 321 Status: v1alpha1.ResourceRecommendStatus{ 322 RecommendResources: &v1alpha1.RecommendResources{ 323 ContainerRecommendations: []v1alpha1.ContainerResources{ 324 { 325 ContainerName: "ContainerName0", 326 }, 327 { 328 ContainerName: "ContainerName1", 329 }, 330 { 331 ContainerName: "ContainerName2", 332 }, 333 { 334 ContainerName: "ContainerName3", 335 }, 336 }, 337 }, 338 Conditions: []v1alpha1.ResourceRecommendCondition{ 339 { 340 Type: v1alpha1.Validated, 341 Reason: "reason0", 342 Status: v1.ConditionTrue, 343 Message: "Message", 344 }, 345 { 346 Type: v1alpha1.Validated, 347 Reason: "reason1", 348 Status: v1.ConditionTrue, 349 Message: "Message", 350 }, 351 { 352 Type: v1alpha1.Validated, 353 Reason: "reason2", 354 Status: v1.ConditionTrue, 355 Message: "Message", 356 }, 357 { 358 Type: v1alpha1.Validated, 359 Reason: "reason3", 360 Status: v1.ConditionTrue, 361 Message: "Message", 362 }, 363 }, 364 }, 365 }, 366 }, 367 wantResourceRecommend: &v1alpha1.ResourceRecommend{ 368 Status: v1alpha1.ResourceRecommendStatus{ 369 RecommendResources: &v1alpha1.RecommendResources{ 370 ContainerRecommendations: []v1alpha1.ContainerResources{ 371 { 372 ContainerName: "ContainerName1", 373 Requests: &v1alpha1.ContainerResourceList{}, 374 }, 375 { 376 ContainerName: "ContainerName2", 377 Requests: &v1alpha1.ContainerResourceList{}, 378 }, 379 { 380 ContainerName: "ContainerName3", 381 Requests: &v1alpha1.ContainerResourceList{}, 382 }, 383 { 384 ContainerName: "ContainerName4", 385 Requests: &v1alpha1.ContainerResourceList{}, 386 }, 387 }, 388 }, 389 Conditions: []v1alpha1.ResourceRecommendCondition{ 390 { 391 Type: v1alpha1.Validated, 392 Reason: "reason1", 393 Status: v1.ConditionTrue, 394 Message: "Message", 395 }, 396 { 397 Type: v1alpha1.Validated, 398 Reason: "reason2", 399 Status: v1.ConditionTrue, 400 Message: "Message", 401 }, 402 { 403 Type: v1alpha1.Validated, 404 Reason: "reason3", 405 Status: v1.ConditionTrue, 406 Message: "Message", 407 }, 408 { 409 Type: v1alpha1.Validated, 410 Reason: "reason4", 411 Status: v1.ConditionTrue, 412 Message: "Message", 413 }, 414 }, 415 }, 416 }, 417 wantErr: false, 418 }, 419 } 420 for _, tt := range tests { 421 t.Run(tt.name, func(t *testing.T) { 422 v1alpha1.AddToScheme(tt.args.client.Scheme()) 423 tt.args.client.Create(context.TODO(), tt.args.resourceRecommend) 424 if err := PatchUpdateResourceRecommend(tt.args.client, tt.args.namespaceName, tt.args.resourceRecommend); (err != nil) != tt.wantErr { 425 t.Errorf("PatchUpdateResourceRecommend() error = %v, wantErr %v", err, tt.wantErr) 426 } 427 if err := PatchUpdateResourceRecommend(tt.args.client, tt.args.namespaceName, tt.wantResourceRecommend); (err != nil) != tt.wantErr { 428 t.Errorf("PatchUpdateResourceRecommend() error = %v, wantErr %v", err, tt.wantErr) 429 } 430 gotResourceRecommend := &v1alpha1.ResourceRecommend{} 431 tt.args.client.Get(context.TODO(), client.ObjectKey{ 432 Name: tt.args.namespaceName.Name, 433 Namespace: tt.args.namespaceName.Namespace, 434 }, gotResourceRecommend) 435 if !reflect.DeepEqual(gotResourceRecommend.Status, tt.wantResourceRecommend.Status) { 436 t.Errorf("PatchUpdateResourceRecommend() gotResourceRecommend.Status = %v, wantResourceRecommend.Status = %v", 437 gotResourceRecommend.Status, tt.wantResourceRecommend.Status) 438 } 439 }) 440 } 441 }