k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/cmd/kubeadm/app/util/apiclient/idempotency_test.go (about) 1 /* 2 Copyright 2018 The Kubernetes 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 apiclient 18 19 import ( 20 "context" 21 "os" 22 "testing" 23 "time" 24 25 "github.com/google/go-cmp/cmp" 26 "github.com/pkg/errors" 27 28 apps "k8s.io/api/apps/v1" 29 v1 "k8s.io/api/core/v1" 30 rbac "k8s.io/api/rbac/v1" 31 apierrors "k8s.io/apimachinery/pkg/api/errors" 32 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 33 "k8s.io/apimachinery/pkg/runtime" 34 "k8s.io/apimachinery/pkg/runtime/schema" 35 clientsetfake "k8s.io/client-go/kubernetes/fake" 36 clientgotesting "k8s.io/client-go/testing" 37 38 kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" 39 ) 40 41 func TestMain(m *testing.M) { 42 // Override the default interval and timeouts during tests 43 defaultRetryInterval := apiCallRetryInterval 44 apiCallRetryInterval = time.Millisecond * 50 45 46 defaultTimeouts := kubeadmapi.GetActiveTimeouts() 47 defaultAPICallTimeout := defaultTimeouts.KubernetesAPICall 48 defaultTimeouts.KubernetesAPICall = &metav1.Duration{Duration: apiCallRetryInterval} 49 50 exitVal := m.Run() 51 52 // Restore the default interval and timeouts 53 apiCallRetryInterval = defaultRetryInterval 54 defaultTimeouts.KubernetesAPICall = defaultAPICallTimeout 55 56 os.Exit(exitVal) 57 } 58 59 func TestCreateOrUpdateConfigMap(t *testing.T) { 60 tests := []struct { 61 name string 62 setupClient func(*clientsetfake.Clientset) 63 expectedError bool 64 }{ 65 { 66 name: "create configmap success", 67 setupClient: func(client *clientsetfake.Clientset) { 68 client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 69 return true, nil, nil 70 }) 71 }, 72 expectedError: false, 73 }, 74 { 75 name: "create configmap returns error", 76 setupClient: func(client *clientsetfake.Clientset) { 77 client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 78 return true, nil, errors.New("unknown error") 79 }) 80 }, 81 expectedError: true, 82 }, 83 { 84 name: "configmap exists, update it", 85 setupClient: func(client *clientsetfake.Clientset) { 86 client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 87 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 88 }) 89 client.PrependReactor("update", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 90 return true, nil, nil 91 }) 92 }, 93 expectedError: false, 94 }, 95 { 96 name: "configmap exists, update error", 97 setupClient: func(client *clientsetfake.Clientset) { 98 client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 99 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 100 }) 101 client.PrependReactor("update", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 102 return true, nil, errors.New("") 103 }) 104 }, 105 expectedError: true, 106 }, 107 } 108 109 for _, tc := range tests { 110 t.Run(tc.name, func(t *testing.T) { 111 client := clientsetfake.NewSimpleClientset() 112 tc.setupClient(client) 113 err := CreateOrUpdateConfigMap(client, &v1.ConfigMap{}) 114 if (err != nil) != tc.expectedError { 115 t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err) 116 } 117 }) 118 } 119 } 120 121 func TestCreateOrMutateConfigMap(t *testing.T) { 122 tests := []struct { 123 name string 124 setupClient func(*clientsetfake.Clientset) 125 mutator func(*v1.ConfigMap) error 126 expectedError bool 127 }{ 128 { 129 name: "create configmap", 130 setupClient: func(client *clientsetfake.Clientset) { 131 client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 132 return true, nil, nil 133 }) 134 client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 135 return true, nil, nil 136 }) 137 client.PrependReactor("update", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 138 return true, nil, nil 139 }) 140 }, 141 expectedError: false, 142 }, 143 { 144 name: "create configmap error", 145 setupClient: func(client *clientsetfake.Clientset) { 146 client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 147 return true, nil, errors.New("") 148 }) 149 }, 150 expectedError: true, 151 }, 152 { 153 name: "configmap exists, mutate returns error", 154 setupClient: func(client *clientsetfake.Clientset) { 155 client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 156 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 157 }) 158 client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 159 return true, &v1.ConfigMap{}, nil 160 }) 161 }, 162 mutator: func(*v1.ConfigMap) error { return errors.New("") }, 163 expectedError: true, 164 }, 165 { 166 name: "configmap exists, get returns error", 167 setupClient: func(client *clientsetfake.Clientset) { 168 client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 169 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 170 }) 171 client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 172 return true, nil, errors.New("") 173 }) 174 }, 175 expectedError: true, 176 }, 177 { 178 name: "configmap exists, mutate returns error", 179 setupClient: func(client *clientsetfake.Clientset) { 180 client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 181 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 182 }) 183 client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 184 return true, &v1.ConfigMap{}, nil 185 }) 186 client.PrependReactor("update", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 187 return true, nil, errors.New("") 188 }) 189 }, 190 mutator: func(*v1.ConfigMap) error { return nil }, 191 expectedError: true, 192 }, 193 } 194 195 for _, tc := range tests { 196 t.Run(tc.name, func(t *testing.T) { 197 client := clientsetfake.NewSimpleClientset() 198 tc.setupClient(client) 199 err := CreateOrMutateConfigMap(client, &v1.ConfigMap{}, tc.mutator) 200 if (err != nil) != tc.expectedError { 201 t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err) 202 } 203 }) 204 } 205 } 206 207 func TestCreateOrRetainConfigMap(t *testing.T) { 208 tests := []struct { 209 name string 210 setupClient func(*clientsetfake.Clientset) 211 expectedError bool 212 }{ 213 { 214 name: "configmap exists", 215 setupClient: func(client *clientsetfake.Clientset) { 216 client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 217 return true, &v1.ConfigMap{}, nil 218 }) 219 }, 220 expectedError: false, 221 }, 222 { 223 name: "configmap get returns an error", 224 setupClient: func(client *clientsetfake.Clientset) { 225 client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 226 return true, nil, errors.New("") 227 }) 228 }, 229 expectedError: true, 230 }, 231 { 232 name: "configmap is not found, create it", 233 setupClient: func(client *clientsetfake.Clientset) { 234 client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 235 return true, nil, apierrors.NewNotFound(schema.GroupResource{}, "name") 236 }) 237 client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 238 return true, nil, nil 239 }) 240 }, 241 expectedError: false, 242 }, 243 { 244 name: "configmap is not found, create returns an error", 245 setupClient: func(client *clientsetfake.Clientset) { 246 client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 247 return true, nil, apierrors.NewNotFound(schema.GroupResource{}, "name") 248 }) 249 client.PrependReactor("create", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 250 return true, nil, errors.New("") 251 }) 252 }, 253 expectedError: true, 254 }, 255 } 256 257 for _, tc := range tests { 258 t.Run(tc.name, func(t *testing.T) { 259 client := clientsetfake.NewSimpleClientset() 260 tc.setupClient(client) 261 err := CreateOrRetainConfigMap(client, &v1.ConfigMap{}, "some-cm") 262 if (err != nil) != tc.expectedError { 263 t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err) 264 } 265 }) 266 } 267 } 268 269 func TestCreateOrUpdateSecret(t *testing.T) { 270 tests := []struct { 271 name string 272 setupClient func(*clientsetfake.Clientset) 273 expectedError bool 274 }{ 275 { 276 name: "create secret success", 277 setupClient: func(client *clientsetfake.Clientset) { 278 client.PrependReactor("create", "secrets", func(clientgotesting.Action) (bool, runtime.Object, error) { 279 return true, nil, nil 280 }) 281 }, 282 expectedError: false, 283 }, 284 { 285 name: "create secret returns error", 286 setupClient: func(client *clientsetfake.Clientset) { 287 client.PrependReactor("create", "secrets", func(clientgotesting.Action) (bool, runtime.Object, error) { 288 return true, nil, errors.New("unknown error") 289 }) 290 }, 291 expectedError: true, 292 }, 293 { 294 name: "secret exists, update it", 295 setupClient: func(client *clientsetfake.Clientset) { 296 client.PrependReactor("create", "secrets", func(clientgotesting.Action) (bool, runtime.Object, error) { 297 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 298 }) 299 client.PrependReactor("update", "secrets", func(clientgotesting.Action) (bool, runtime.Object, error) { 300 return true, nil, nil 301 }) 302 }, 303 expectedError: false, 304 }, 305 { 306 name: "secret exists, update error", 307 setupClient: func(client *clientsetfake.Clientset) { 308 client.PrependReactor("create", "secrets", func(clientgotesting.Action) (bool, runtime.Object, error) { 309 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 310 }) 311 client.PrependReactor("update", "secrets", func(clientgotesting.Action) (bool, runtime.Object, error) { 312 return true, nil, errors.New("") 313 }) 314 }, 315 expectedError: true, 316 }, 317 } 318 319 for _, tc := range tests { 320 t.Run(tc.name, func(t *testing.T) { 321 client := clientsetfake.NewSimpleClientset() 322 tc.setupClient(client) 323 err := CreateOrUpdateSecret(client, &v1.Secret{}) 324 if (err != nil) != tc.expectedError { 325 t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err) 326 } 327 }) 328 } 329 } 330 331 func TestCreateOrUpdateServiceAccount(t *testing.T) { 332 tests := []struct { 333 name string 334 setupClient func(*clientsetfake.Clientset) 335 expectedError bool 336 }{ 337 { 338 name: "create serviceaccount success", 339 setupClient: func(client *clientsetfake.Clientset) { 340 client.PrependReactor("create", "serviceaccounts", func(clientgotesting.Action) (bool, runtime.Object, error) { 341 return true, nil, nil 342 }) 343 }, 344 expectedError: false, 345 }, 346 { 347 name: "create serviceaccount returns error", 348 setupClient: func(client *clientsetfake.Clientset) { 349 client.PrependReactor("create", "serviceaccounts", func(clientgotesting.Action) (bool, runtime.Object, error) { 350 return true, nil, errors.New("unknown error") 351 }) 352 }, 353 expectedError: true, 354 }, 355 { 356 name: "serviceaccount exists, update it", 357 setupClient: func(client *clientsetfake.Clientset) { 358 client.PrependReactor("create", "serviceaccounts", func(clientgotesting.Action) (bool, runtime.Object, error) { 359 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 360 }) 361 client.PrependReactor("update", "serviceaccounts", func(clientgotesting.Action) (bool, runtime.Object, error) { 362 return true, nil, nil 363 }) 364 }, 365 expectedError: false, 366 }, 367 { 368 name: "serviceaccount exists, update error", 369 setupClient: func(client *clientsetfake.Clientset) { 370 client.PrependReactor("create", "serviceaccounts", func(clientgotesting.Action) (bool, runtime.Object, error) { 371 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 372 }) 373 client.PrependReactor("update", "serviceaccounts", func(clientgotesting.Action) (bool, runtime.Object, error) { 374 return true, nil, errors.New("") 375 }) 376 }, 377 expectedError: true, 378 }, 379 } 380 381 for _, tc := range tests { 382 t.Run(tc.name, func(t *testing.T) { 383 client := clientsetfake.NewSimpleClientset() 384 tc.setupClient(client) 385 err := CreateOrUpdateServiceAccount(client, &v1.ServiceAccount{}) 386 if (err != nil) != tc.expectedError { 387 t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err) 388 } 389 }) 390 } 391 } 392 393 func TestCreateOrUpdateDeployment(t *testing.T) { 394 tests := []struct { 395 name string 396 setupClient func(*clientsetfake.Clientset) 397 expectedError bool 398 }{ 399 { 400 name: "create deployment success", 401 setupClient: func(client *clientsetfake.Clientset) { 402 client.PrependReactor("create", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) { 403 return true, nil, nil 404 }) 405 }, 406 expectedError: false, 407 }, 408 { 409 name: "create deployment returns error", 410 setupClient: func(client *clientsetfake.Clientset) { 411 client.PrependReactor("create", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) { 412 return true, nil, errors.New("unknown error") 413 }) 414 }, 415 expectedError: true, 416 }, 417 { 418 name: "deployment exists, update it", 419 setupClient: func(client *clientsetfake.Clientset) { 420 client.PrependReactor("create", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) { 421 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 422 }) 423 client.PrependReactor("update", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) { 424 return true, nil, nil 425 }) 426 }, 427 expectedError: false, 428 }, 429 { 430 name: "deployment exists, update error", 431 setupClient: func(client *clientsetfake.Clientset) { 432 client.PrependReactor("create", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) { 433 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 434 }) 435 client.PrependReactor("update", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) { 436 return true, nil, errors.New("") 437 }) 438 }, 439 expectedError: true, 440 }, 441 } 442 443 for _, tc := range tests { 444 t.Run(tc.name, func(t *testing.T) { 445 client := clientsetfake.NewSimpleClientset() 446 tc.setupClient(client) 447 err := CreateOrUpdateDeployment(client, &apps.Deployment{}) 448 if (err != nil) != tc.expectedError { 449 t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err) 450 } 451 }) 452 } 453 } 454 455 func TestCreateOrRetainDeployment(t *testing.T) { 456 tests := []struct { 457 name string 458 setupClient func(*clientsetfake.Clientset) 459 expectedError bool 460 }{ 461 { 462 name: "deployment exists", 463 setupClient: func(client *clientsetfake.Clientset) { 464 client.PrependReactor("get", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) { 465 return true, &apps.Deployment{}, nil 466 }) 467 }, 468 expectedError: false, 469 }, 470 { 471 name: "deployment get returns an error", 472 setupClient: func(client *clientsetfake.Clientset) { 473 client.PrependReactor("get", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) { 474 return true, nil, errors.New("") 475 }) 476 }, 477 expectedError: true, 478 }, 479 { 480 name: "deployment is not found, create it", 481 setupClient: func(client *clientsetfake.Clientset) { 482 client.PrependReactor("get", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) { 483 return true, nil, apierrors.NewNotFound(schema.GroupResource{}, "name") 484 }) 485 client.PrependReactor("create", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) { 486 return true, nil, nil 487 }) 488 }, 489 expectedError: false, 490 }, 491 { 492 name: "deployment is not found, create returns an error", 493 setupClient: func(client *clientsetfake.Clientset) { 494 client.PrependReactor("get", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) { 495 return true, nil, apierrors.NewNotFound(schema.GroupResource{}, "name") 496 }) 497 client.PrependReactor("create", "deployments", func(clientgotesting.Action) (bool, runtime.Object, error) { 498 return true, nil, errors.New("") 499 }) 500 }, 501 expectedError: true, 502 }, 503 } 504 505 for _, tc := range tests { 506 t.Run(tc.name, func(t *testing.T) { 507 client := clientsetfake.NewSimpleClientset() 508 tc.setupClient(client) 509 err := CreateOrRetainDeployment(client, &apps.Deployment{}, "some-deployment") 510 if (err != nil) != tc.expectedError { 511 t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err) 512 } 513 }) 514 } 515 } 516 517 func TestCreateOrUpdateDaemonSet(t *testing.T) { 518 tests := []struct { 519 name string 520 setupClient func(*clientsetfake.Clientset) 521 expectedError bool 522 }{ 523 { 524 name: "create daemonset success", 525 setupClient: func(client *clientsetfake.Clientset) { 526 client.PrependReactor("create", "daemonsets", func(clientgotesting.Action) (bool, runtime.Object, error) { 527 return true, nil, nil 528 }) 529 }, 530 expectedError: false, 531 }, 532 { 533 name: "create daemonset returns error", 534 setupClient: func(client *clientsetfake.Clientset) { 535 client.PrependReactor("create", "daemonsets", func(clientgotesting.Action) (bool, runtime.Object, error) { 536 return true, nil, errors.New("unknown error") 537 }) 538 }, 539 expectedError: true, 540 }, 541 { 542 name: "daemonset exists, update it", 543 setupClient: func(client *clientsetfake.Clientset) { 544 client.PrependReactor("create", "daemonsets", func(clientgotesting.Action) (bool, runtime.Object, error) { 545 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 546 }) 547 client.PrependReactor("update", "daemonsets", func(clientgotesting.Action) (bool, runtime.Object, error) { 548 return true, nil, nil 549 }) 550 }, 551 expectedError: false, 552 }, 553 { 554 name: "daemonset exists, update error", 555 setupClient: func(client *clientsetfake.Clientset) { 556 client.PrependReactor("create", "daemonsets", func(clientgotesting.Action) (bool, runtime.Object, error) { 557 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 558 }) 559 client.PrependReactor("update", "daemonsets", func(clientgotesting.Action) (bool, runtime.Object, error) { 560 return true, nil, errors.New("") 561 }) 562 }, 563 expectedError: true, 564 }, 565 } 566 567 for _, tc := range tests { 568 t.Run(tc.name, func(t *testing.T) { 569 client := clientsetfake.NewSimpleClientset() 570 tc.setupClient(client) 571 err := CreateOrUpdateDaemonSet(client, &apps.DaemonSet{}) 572 if (err != nil) != tc.expectedError { 573 t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err) 574 } 575 }) 576 } 577 } 578 579 func TestCreateOrUpdateRole(t *testing.T) { 580 tests := []struct { 581 name string 582 setupClient func(*clientsetfake.Clientset) 583 expectedError bool 584 }{ 585 { 586 name: "create role success", 587 setupClient: func(client *clientsetfake.Clientset) { 588 client.PrependReactor("create", "roles", func(clientgotesting.Action) (bool, runtime.Object, error) { 589 return true, nil, nil 590 }) 591 }, 592 expectedError: false, 593 }, 594 { 595 name: "create role returns error", 596 setupClient: func(client *clientsetfake.Clientset) { 597 client.PrependReactor("create", "roles", func(clientgotesting.Action) (bool, runtime.Object, error) { 598 return true, nil, errors.New("unknown error") 599 }) 600 }, 601 expectedError: true, 602 }, 603 { 604 name: "role exists, update it", 605 setupClient: func(client *clientsetfake.Clientset) { 606 client.PrependReactor("create", "roles", func(clientgotesting.Action) (bool, runtime.Object, error) { 607 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 608 }) 609 client.PrependReactor("update", "roles", func(clientgotesting.Action) (bool, runtime.Object, error) { 610 return true, nil, nil 611 }) 612 }, 613 expectedError: false, 614 }, 615 { 616 name: "role exists, update error", 617 setupClient: func(client *clientsetfake.Clientset) { 618 client.PrependReactor("create", "roles", func(clientgotesting.Action) (bool, runtime.Object, error) { 619 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 620 }) 621 client.PrependReactor("update", "roles", func(clientgotesting.Action) (bool, runtime.Object, error) { 622 return true, nil, errors.New("") 623 }) 624 }, 625 expectedError: true, 626 }, 627 } 628 629 for _, tc := range tests { 630 t.Run(tc.name, func(t *testing.T) { 631 client := clientsetfake.NewSimpleClientset() 632 tc.setupClient(client) 633 err := CreateOrUpdateRole(client, &rbac.Role{}) 634 if (err != nil) != tc.expectedError { 635 t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err) 636 } 637 }) 638 } 639 } 640 641 func TestCreateOrUpdateRoleBindings(t *testing.T) { 642 tests := []struct { 643 name string 644 setupClient func(*clientsetfake.Clientset) 645 expectedError bool 646 }{ 647 { 648 name: "create rolebinding success", 649 setupClient: func(client *clientsetfake.Clientset) { 650 client.PrependReactor("create", "rolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) { 651 return true, nil, nil 652 }) 653 }, 654 expectedError: false, 655 }, 656 { 657 name: "create rolebinding returns error", 658 setupClient: func(client *clientsetfake.Clientset) { 659 client.PrependReactor("create", "rolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) { 660 return true, nil, errors.New("unknown error") 661 }) 662 }, 663 expectedError: true, 664 }, 665 { 666 name: "rolebinding exists, update it", 667 setupClient: func(client *clientsetfake.Clientset) { 668 client.PrependReactor("create", "rolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) { 669 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 670 }) 671 client.PrependReactor("update", "rolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) { 672 return true, nil, nil 673 }) 674 }, 675 expectedError: false, 676 }, 677 { 678 name: "rolebinding exists, update error", 679 setupClient: func(client *clientsetfake.Clientset) { 680 client.PrependReactor("create", "rolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) { 681 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 682 }) 683 client.PrependReactor("update", "rolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) { 684 return true, nil, errors.New("") 685 }) 686 }, 687 expectedError: true, 688 }, 689 } 690 691 for _, tc := range tests { 692 t.Run(tc.name, func(t *testing.T) { 693 client := clientsetfake.NewSimpleClientset() 694 tc.setupClient(client) 695 err := CreateOrUpdateRoleBinding(client, &rbac.RoleBinding{}) 696 if (err != nil) != tc.expectedError { 697 t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err) 698 } 699 }) 700 } 701 } 702 703 func TestCreateOrUpdateClusterRole(t *testing.T) { 704 tests := []struct { 705 name string 706 setupClient func(*clientsetfake.Clientset) 707 expectedError bool 708 }{ 709 { 710 name: "create clusterrole success", 711 setupClient: func(client *clientsetfake.Clientset) { 712 client.PrependReactor("create", "clusterroles", func(clientgotesting.Action) (bool, runtime.Object, error) { 713 return true, nil, nil 714 }) 715 }, 716 expectedError: false, 717 }, 718 { 719 name: "create clusterrole returns error", 720 setupClient: func(client *clientsetfake.Clientset) { 721 client.PrependReactor("create", "clusterroles", func(clientgotesting.Action) (bool, runtime.Object, error) { 722 return true, nil, errors.New("unknown error") 723 }) 724 }, 725 expectedError: true, 726 }, 727 { 728 name: "clusterrole exists, update it", 729 setupClient: func(client *clientsetfake.Clientset) { 730 client.PrependReactor("create", "clusterroles", func(clientgotesting.Action) (bool, runtime.Object, error) { 731 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 732 }) 733 client.PrependReactor("update", "clusterroles", func(clientgotesting.Action) (bool, runtime.Object, error) { 734 return true, nil, nil 735 }) 736 }, 737 expectedError: false, 738 }, 739 { 740 name: "clusterrole exists, update error", 741 setupClient: func(client *clientsetfake.Clientset) { 742 client.PrependReactor("create", "clusterroles", func(clientgotesting.Action) (bool, runtime.Object, error) { 743 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 744 }) 745 client.PrependReactor("update", "clusterroles", func(clientgotesting.Action) (bool, runtime.Object, error) { 746 return true, nil, errors.New("") 747 }) 748 }, 749 expectedError: true, 750 }, 751 } 752 753 for _, tc := range tests { 754 t.Run(tc.name, func(t *testing.T) { 755 client := clientsetfake.NewSimpleClientset() 756 tc.setupClient(client) 757 err := CreateOrUpdateClusterRole(client, &rbac.ClusterRole{}) 758 if (err != nil) != tc.expectedError { 759 t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err) 760 } 761 }) 762 } 763 } 764 765 func TestCreateOrUpdateClusterRoleBindings(t *testing.T) { 766 tests := []struct { 767 name string 768 setupClient func(*clientsetfake.Clientset) 769 expectedError bool 770 }{ 771 { 772 name: "create clusterrolebinding success", 773 setupClient: func(client *clientsetfake.Clientset) { 774 client.PrependReactor("create", "clusterrolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) { 775 return true, nil, nil 776 }) 777 }, 778 expectedError: false, 779 }, 780 { 781 name: "create clusterrolebinding returns error", 782 setupClient: func(client *clientsetfake.Clientset) { 783 client.PrependReactor("create", "clusterrolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) { 784 return true, nil, errors.New("unknown error") 785 }) 786 }, 787 expectedError: true, 788 }, 789 { 790 name: "clusterrolebinding exists, update it", 791 setupClient: func(client *clientsetfake.Clientset) { 792 client.PrependReactor("create", "clusterrolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) { 793 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 794 }) 795 client.PrependReactor("update", "clusterrolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) { 796 return true, nil, nil 797 }) 798 }, 799 expectedError: false, 800 }, 801 { 802 name: "clusterrolebinding exists, update error", 803 setupClient: func(client *clientsetfake.Clientset) { 804 client.PrependReactor("create", "clusterrolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) { 805 return true, nil, apierrors.NewAlreadyExists(schema.GroupResource{}, "name") 806 }) 807 client.PrependReactor("update", "clusterrolebindings", func(clientgotesting.Action) (bool, runtime.Object, error) { 808 return true, nil, errors.New("") 809 }) 810 }, 811 expectedError: true, 812 }, 813 } 814 815 for _, tc := range tests { 816 t.Run(tc.name, func(t *testing.T) { 817 client := clientsetfake.NewSimpleClientset() 818 tc.setupClient(client) 819 err := CreateOrUpdateClusterRoleBinding(client, &rbac.ClusterRoleBinding{}) 820 if (err != nil) != tc.expectedError { 821 t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err) 822 } 823 }) 824 } 825 } 826 827 func TestPatchNodeOnce(t *testing.T) { 828 testcases := []struct { 829 name string 830 lookupName string 831 node v1.Node 832 success bool 833 fakeError error 834 }{ 835 { 836 name: "simple update", 837 lookupName: "testnode", 838 node: v1.Node{ 839 ObjectMeta: metav1.ObjectMeta{ 840 Name: "testnode", 841 Labels: map[string]string{v1.LabelHostname: ""}, 842 }, 843 }, 844 success: true, 845 }, 846 { 847 name: "node does not exist", 848 lookupName: "whale", 849 success: false, 850 }, 851 { 852 name: "node not labelled yet", 853 lookupName: "robin", 854 node: v1.Node{ 855 ObjectMeta: metav1.ObjectMeta{ 856 Name: "robin", 857 }, 858 }, 859 success: false, 860 }, 861 { 862 name: "patch node when timeout", 863 lookupName: "testnode", 864 node: v1.Node{ 865 ObjectMeta: metav1.ObjectMeta{ 866 Name: "testnode", 867 Labels: map[string]string{v1.LabelHostname: ""}, 868 }, 869 }, 870 success: false, 871 fakeError: apierrors.NewTimeoutError("fake timeout", -1), 872 }, 873 { 874 name: "patch node when conflict", 875 lookupName: "testnode", 876 node: v1.Node{ 877 ObjectMeta: metav1.ObjectMeta{ 878 Name: "testnode", 879 Labels: map[string]string{v1.LabelHostname: ""}, 880 }, 881 }, 882 success: false, 883 fakeError: apierrors.NewConflict(schema.GroupResource{}, "fake conflict", nil), 884 }, 885 { 886 name: "patch node when there is a server timeout", 887 lookupName: "testnode", 888 node: v1.Node{ 889 ObjectMeta: metav1.ObjectMeta{ 890 Name: "testnode", 891 Labels: map[string]string{v1.LabelHostname: ""}, 892 }, 893 }, 894 success: false, 895 fakeError: apierrors.NewServerTimeout(schema.GroupResource{}, "fake server timeout", 1), 896 }, 897 { 898 name: "patch node when the service is unavailable", 899 lookupName: "testnode", 900 node: v1.Node{ 901 ObjectMeta: metav1.ObjectMeta{ 902 Name: "testnode", 903 Labels: map[string]string{v1.LabelHostname: ""}, 904 }, 905 }, 906 success: false, 907 fakeError: apierrors.NewServiceUnavailable("fake service unavailable"), 908 }, 909 { 910 name: "patch node failed with unknown error", 911 lookupName: "testnode", 912 node: v1.Node{ 913 ObjectMeta: metav1.ObjectMeta{ 914 Name: "testnode", 915 Labels: map[string]string{v1.LabelHostname: ""}, 916 }, 917 }, 918 success: false, 919 fakeError: errors.New("unknown error"), 920 }, 921 } 922 923 for _, tc := range testcases { 924 t.Run(tc.name, func(t *testing.T) { 925 client := clientsetfake.NewSimpleClientset() 926 _, err := client.CoreV1().Nodes().Create(context.Background(), &tc.node, metav1.CreateOptions{}) 927 if err != nil { 928 t.Fatalf("failed to create node to fake client: %v", err) 929 } 930 if tc.fakeError != nil { 931 client.PrependReactor("patch", "nodes", func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) { 932 return true, nil, tc.fakeError 933 }) 934 } 935 var lastError error 936 conditionFunction := PatchNodeOnce(client, tc.lookupName, func(node *v1.Node) { 937 node.Annotations = map[string]string{ 938 "updatedBy": "test", 939 } 940 }, &lastError) 941 success, err := conditionFunction(context.Background()) 942 if err != nil && tc.success { 943 t.Fatalf("did not expect error: %v", err) 944 } 945 if success != tc.success { 946 t.Fatalf("expected %v got %v", tc.success, success) 947 } 948 }) 949 } 950 } 951 952 func TestPatchNode(t *testing.T) { 953 tests := []struct { 954 name string 955 setupClient func(*clientsetfake.Clientset) 956 expectedError bool 957 }{ 958 { 959 name: "success", 960 setupClient: func(client *clientsetfake.Clientset) { 961 client.PrependReactor("get", "nodes", func(clientgotesting.Action) (bool, runtime.Object, error) { 962 return true, &v1.Node{ 963 ObjectMeta: metav1.ObjectMeta{ 964 Name: "some-node", 965 Labels: map[string]string{v1.LabelHostname: ""}, 966 }, 967 }, nil 968 }) 969 client.PrependReactor("patch", "nodes", func(clientgotesting.Action) (bool, runtime.Object, error) { 970 return true, nil, nil 971 }) 972 }, 973 expectedError: false, 974 }, 975 { 976 name: "error", 977 setupClient: func(client *clientsetfake.Clientset) { 978 client.PrependReactor("get", "nodes", func(clientgotesting.Action) (bool, runtime.Object, error) { 979 return true, nil, errors.New("unknown error") 980 }) 981 }, 982 expectedError: true, 983 }, 984 } 985 986 for _, tc := range tests { 987 t.Run(tc.name, func(t *testing.T) { 988 client := clientsetfake.NewSimpleClientset() 989 tc.setupClient(client) 990 patchFn := func(*v1.Node) {} 991 err := PatchNode(client, "some-node", patchFn) 992 if (err != nil) != tc.expectedError { 993 t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err) 994 } 995 }) 996 } 997 } 998 999 func TestGetConfigMapWithShortRetry(t *testing.T) { 1000 expectedConfigMap := &v1.ConfigMap{ 1001 ObjectMeta: metav1.ObjectMeta{ 1002 Namespace: "ns", 1003 Name: "some-cm", 1004 }, 1005 } 1006 tests := []struct { 1007 name string 1008 setupClient func(*clientsetfake.Clientset) 1009 expectedConfigMap *v1.ConfigMap 1010 expectedError bool 1011 }{ 1012 { 1013 name: "configmap exists", 1014 setupClient: func(client *clientsetfake.Clientset) { 1015 client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 1016 return true, expectedConfigMap, nil 1017 }) 1018 }, 1019 expectedConfigMap: expectedConfigMap, 1020 expectedError: false, 1021 }, 1022 { 1023 name: "configmap get returns an error", 1024 setupClient: func(client *clientsetfake.Clientset) { 1025 client.PrependReactor("get", "configmaps", func(clientgotesting.Action) (bool, runtime.Object, error) { 1026 return true, nil, errors.New("") 1027 }) 1028 }, 1029 expectedError: true, 1030 }, 1031 } 1032 1033 for _, tc := range tests { 1034 t.Run(tc.name, func(t *testing.T) { 1035 client := clientsetfake.NewSimpleClientset() 1036 tc.setupClient(client) 1037 actual, err := GetConfigMapWithShortRetry(client, "ns", "some-cm") 1038 if (err != nil) != tc.expectedError { 1039 t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err) 1040 } 1041 if err != nil { 1042 return 1043 } 1044 diff := cmp.Diff(tc.expectedConfigMap, actual) 1045 if len(diff) > 0 { 1046 t.Fatalf("got a diff with the expected config (-want,+got):\n%s", diff) 1047 } 1048 }) 1049 } 1050 }