github.com/IBM-Blockchain/fabric-operator@v1.0.4/controllers/ibppeer/ibppeer_controller_test.go (about) 1 /* 2 * Copyright contributors to the Hyperledger Fabric Operator project 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package ibppeer 20 21 import ( 22 "context" 23 "errors" 24 "fmt" 25 "sync" 26 27 . "github.com/onsi/ginkgo/v2" 28 . "github.com/onsi/gomega" 29 "k8s.io/utils/pointer" 30 31 current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1" 32 peermocks "github.com/IBM-Blockchain/fabric-operator/controllers/ibppeer/mocks" 33 "github.com/IBM-Blockchain/fabric-operator/controllers/mocks" 34 "github.com/IBM-Blockchain/fabric-operator/pkg/offering/common" 35 "github.com/IBM-Blockchain/fabric-operator/pkg/operatorerrors" 36 corev1 "k8s.io/api/core/v1" 37 k8serror "k8s.io/apimachinery/pkg/api/errors" 38 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 39 "k8s.io/apimachinery/pkg/runtime" 40 "k8s.io/apimachinery/pkg/types" 41 "k8s.io/apimachinery/pkg/util/intstr" 42 "sigs.k8s.io/controller-runtime/pkg/client" 43 "sigs.k8s.io/controller-runtime/pkg/event" 44 "sigs.k8s.io/controller-runtime/pkg/reconcile" 45 "sigs.k8s.io/yaml" 46 ) 47 48 var _ = Describe("ReconcileIBPPeer", func() { 49 var ( 50 reconciler *ReconcileIBPPeer 51 request reconcile.Request 52 mockKubeClient *mocks.Client 53 mockPeerReconcile *peermocks.PeerReconcile 54 instance *current.IBPPeer 55 ) 56 57 BeforeEach(func() { 58 mockKubeClient = &mocks.Client{} 59 mockPeerReconcile = &peermocks.PeerReconcile{} 60 instance = ¤t.IBPPeer{ 61 Spec: current.IBPPeerSpec{ 62 Images: ¤t.PeerImages{ 63 PeerTag: "1.4.9-2511004", 64 }, 65 }, 66 } 67 instance.Name = "test-peer" 68 69 mockKubeClient.GetStub = func(ctx context.Context, types types.NamespacedName, obj client.Object) error { 70 switch obj.(type) { 71 case *current.IBPPeer: 72 o := obj.(*current.IBPPeer) 73 o.Kind = "IBPPeer" 74 o.Name = instance.Name 75 76 instance = o 77 case *corev1.Service: 78 o := obj.(*corev1.Service) 79 o.Spec.Type = corev1.ServiceTypeNodePort 80 o.Spec.Ports = append(o.Spec.Ports, corev1.ServicePort{ 81 Name: "peer-api", 82 TargetPort: intstr.IntOrString{ 83 IntVal: 7051, 84 }, 85 NodePort: int32(7051), 86 }) 87 } 88 return nil 89 } 90 91 mockKubeClient.UpdateStatusStub = func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { 92 switch obj.(type) { 93 case *current.IBPPeer: 94 o := obj.(*current.IBPPeer) 95 instance = o 96 } 97 return nil 98 } 99 100 mockKubeClient.ListStub = func(ctx context.Context, obj client.ObjectList, opts ...client.ListOption) error { 101 switch obj.(type) { 102 case *corev1.NodeList: 103 nodeList := obj.(*corev1.NodeList) 104 node := corev1.Node{} 105 node.Labels = map[string]string{} 106 node.Labels["topology.kubernetes.io/zone"] = "dal" 107 node.Labels["topology.kubernetes.io/region"] = "us-south" 108 nodeList.Items = append(nodeList.Items, node) 109 case *current.IBPPeerList: 110 peerList := obj.(*current.IBPPeerList) 111 p1 := current.IBPPeer{} 112 p1.Name = "test-peer1" 113 p2 := current.IBPPeer{} 114 p2.Name = "test-peer2" 115 p3 := current.IBPPeer{} 116 p3.Name = "test-peer2" 117 peerList.Items = []current.IBPPeer{p1, p2, p3} 118 } 119 return nil 120 } 121 122 reconciler = &ReconcileIBPPeer{ 123 Offering: mockPeerReconcile, 124 client: mockKubeClient, 125 scheme: &runtime.Scheme{}, 126 update: map[string][]Update{}, 127 mutex: &sync.Mutex{}, 128 } 129 request = reconcile.Request{ 130 NamespacedName: types.NamespacedName{ 131 Namespace: "test-namespace", 132 Name: "test", 133 }, 134 } 135 }) 136 137 Context("Reconciles", func() { 138 It("does not return an error if the custom resource is 'not found'", func() { 139 notFoundErr := &k8serror.StatusError{ 140 ErrStatus: metav1.Status{ 141 Reason: metav1.StatusReasonNotFound, 142 }, 143 } 144 mockKubeClient.GetReturns(notFoundErr) 145 _, err := reconciler.Reconcile(context.TODO(), request) 146 Expect(err).NotTo(HaveOccurred()) 147 }) 148 149 It("returns an error if the request to get custom resource return any other error besides 'not found'", func() { 150 alreadyExistsErr := &k8serror.StatusError{ 151 ErrStatus: metav1.Status{ 152 Message: "already exists", 153 Reason: metav1.StatusReasonAlreadyExists, 154 }, 155 } 156 mockKubeClient.GetReturns(alreadyExistsErr) 157 _, err := reconciler.Reconcile(context.TODO(), request) 158 Expect(err).To(HaveOccurred()) 159 Expect(err.Error()).To(Equal("already exists")) 160 }) 161 162 It("returns an error if it encountered a non-breaking error", func() { 163 errMsg := "failed to reconcile deployment encountered breaking error" 164 mockPeerReconcile.ReconcileReturns(common.Result{}, errors.New(errMsg)) 165 _, err := reconciler.Reconcile(context.TODO(), request) 166 Expect(err).To(HaveOccurred()) 167 Expect(err.Error()).To(Equal(fmt.Sprintf("Peer instance '%s' encountered error: %s", instance.Name, errMsg))) 168 }) 169 170 It("does not return an error if it encountered a breaking error", func() { 171 mockPeerReconcile.ReconcileReturns(common.Result{}, operatorerrors.New(operatorerrors.InvalidDeploymentCreateRequest, "failed to reconcile deployment encountered breaking error")) 172 _, err := reconciler.Reconcile(context.TODO(), request) 173 Expect(err).NotTo(HaveOccurred()) 174 }) 175 }) 176 177 Context("update reconcile", func() { 178 var ( 179 oldPeer *current.IBPPeer 180 newPeer *current.IBPPeer 181 oldSecret *corev1.Secret 182 newSecret *corev1.Secret 183 e event.UpdateEvent 184 ) 185 186 BeforeEach(func() { 187 188 configoverride := []byte(`{"peer": {"id": "peer1"} }`) 189 190 oldPeer = ¤t.IBPPeer{ 191 ObjectMeta: metav1.ObjectMeta{ 192 Name: instance.Name, 193 }, 194 Spec: current.IBPPeerSpec{ 195 Images: ¤t.PeerImages{ 196 PeerTag: "1.4.6-20200101", 197 }, 198 ConfigOverride: &runtime.RawExtension{Raw: configoverride}, 199 }, 200 } 201 202 configoverride2 := []byte(`{"peer": {"id": "peer2"} }`) 203 204 newPeer = ¤t.IBPPeer{ 205 ObjectMeta: metav1.ObjectMeta{ 206 Name: instance.Name, 207 }, 208 Spec: current.IBPPeerSpec{ 209 Images: ¤t.PeerImages{ 210 PeerTag: "1.4.9-2511004", 211 }, 212 ConfigOverride: &runtime.RawExtension{Raw: configoverride2}, 213 }, 214 } 215 216 e = event.UpdateEvent{ 217 ObjectOld: oldPeer, 218 ObjectNew: newPeer, 219 } 220 221 Expect(reconciler.UpdateFunc(e)).To(Equal(true)) 222 223 oldPeer = ¤t.IBPPeer{ 224 ObjectMeta: metav1.ObjectMeta{ 225 Name: instance.Name, 226 }, 227 Spec: current.IBPPeerSpec{ 228 Images: ¤t.PeerImages{ 229 PeerTag: "1.4.6-20200101", 230 }, 231 MSPID: "old-mspid", 232 }, 233 } 234 235 newPeer = ¤t.IBPPeer{ 236 ObjectMeta: metav1.ObjectMeta{ 237 Name: instance.Name, 238 }, 239 Spec: current.IBPPeerSpec{ 240 Images: ¤t.PeerImages{ 241 PeerTag: "1.4.9-2511004", 242 }, 243 MSPID: "new-mspid", 244 }, 245 } 246 247 e = event.UpdateEvent{ 248 ObjectOld: oldPeer, 249 ObjectNew: newPeer, 250 } 251 252 Expect(reconciler.UpdateFunc(e)).To(Equal(true)) 253 254 oldSecret = &corev1.Secret{ 255 ObjectMeta: metav1.ObjectMeta{ 256 Name: fmt.Sprintf("tls-%s-signcert", instance.Name), 257 OwnerReferences: []metav1.OwnerReference{ 258 { 259 Name: instance.Name, 260 Kind: "IBPPeer", 261 }, 262 }, 263 }, 264 } 265 266 newSecret = &corev1.Secret{ 267 ObjectMeta: metav1.ObjectMeta{ 268 Name: fmt.Sprintf("tls-%s-signcert", instance.Name), 269 OwnerReferences: []metav1.OwnerReference{ 270 { 271 Name: instance.Name, 272 Kind: "IBPPeer", 273 }, 274 }, 275 }, 276 } 277 278 e = event.UpdateEvent{ 279 ObjectOld: oldSecret, 280 ObjectNew: newSecret, 281 } 282 283 Expect(reconciler.UpdateFunc(e)).To(Equal(false)) 284 285 oldSecret = &corev1.Secret{ 286 ObjectMeta: metav1.ObjectMeta{ 287 Name: fmt.Sprintf("ecert-%s-signcert", instance.Name), 288 OwnerReferences: []metav1.OwnerReference{ 289 { 290 Name: instance.Name, 291 Kind: "IBPPeer", 292 }, 293 }, 294 }, 295 Data: map[string][]byte{ 296 "test": []byte("data"), 297 }, 298 } 299 300 newSecret = &corev1.Secret{ 301 ObjectMeta: metav1.ObjectMeta{ 302 Name: fmt.Sprintf("ecert-%s-signcert", instance.Name), 303 OwnerReferences: []metav1.OwnerReference{ 304 { 305 Name: instance.Name, 306 Kind: "IBPPeer", 307 }, 308 }, 309 }, 310 Data: map[string][]byte{ 311 "test": []byte("newdata"), 312 }, 313 } 314 315 e = event.UpdateEvent{ 316 ObjectOld: oldSecret, 317 ObjectNew: newSecret, 318 } 319 320 Expect(reconciler.UpdateFunc(e)).To(Equal(true)) 321 322 oldSecret = &corev1.Secret{ 323 ObjectMeta: metav1.ObjectMeta{ 324 Name: fmt.Sprintf("tls-%s-admincerts", instance.Name), 325 OwnerReferences: []metav1.OwnerReference{ 326 { 327 Name: instance.Name, 328 Kind: "IBPPeer", 329 }, 330 }, 331 }, 332 } 333 334 newSecret = &corev1.Secret{ 335 ObjectMeta: metav1.ObjectMeta{ 336 Name: fmt.Sprintf("tls-%s-admincerts", instance.Name), 337 OwnerReferences: []metav1.OwnerReference{ 338 { 339 Name: instance.Name, 340 Kind: "IBPPeer", 341 }, 342 }, 343 }, 344 } 345 346 e = event.UpdateEvent{ 347 ObjectOld: oldSecret, 348 ObjectNew: newSecret, 349 } 350 351 Expect(reconciler.UpdateFunc(e)).To(Equal(false)) 352 353 oldPeer = ¤t.IBPPeer{ 354 ObjectMeta: metav1.ObjectMeta{ 355 Name: instance.Name, 356 }, 357 Spec: current.IBPPeerSpec{ 358 Secret: ¤t.SecretSpec{ 359 MSP: ¤t.MSPSpec{ 360 Component: ¤t.MSP{ 361 SignCerts: "testcert", 362 }, 363 }, 364 }, 365 }, 366 } 367 368 newPeer = ¤t.IBPPeer{ 369 ObjectMeta: metav1.ObjectMeta{ 370 Name: instance.Name, 371 }, 372 Spec: current.IBPPeerSpec{ 373 Secret: ¤t.SecretSpec{ 374 MSP: ¤t.MSPSpec{ 375 TLS: ¤t.MSP{ 376 SignCerts: "testcert", 377 }, 378 }, 379 }, 380 }, 381 } 382 383 e = event.UpdateEvent{ 384 ObjectOld: oldPeer, 385 ObjectNew: newPeer, 386 } 387 388 Expect(reconciler.UpdateFunc(e)).To(Equal(true)) 389 }) 390 391 It("properly pops update flags from stack", func() { 392 By("popping first update - config overrides", func() { 393 Expect(reconciler.GetUpdateStatus(instance).overridesUpdated).To(Equal(true)) 394 Expect(reconciler.GetUpdateStatus(instance).peerTagUpdated).To(Equal(true)) 395 396 _, err := reconciler.Reconcile(context.TODO(), request) 397 Expect(err).NotTo(HaveOccurred()) 398 399 }) 400 401 By("popping second update - spec updated", func() { 402 Expect(reconciler.GetUpdateStatus(instance).overridesUpdated).To(Equal(false)) 403 Expect(reconciler.GetUpdateStatus(instance).specUpdated).To(Equal(true)) 404 405 _, err := reconciler.Reconcile(context.TODO(), request) 406 Expect(err).NotTo(HaveOccurred()) 407 }) 408 409 By("popping third update - ecert updated", func() { 410 Expect(reconciler.GetUpdateStatus(instance).tlsCertUpdated).To(Equal(false)) 411 Expect(reconciler.GetUpdateStatus(instance).ecertUpdated).To(Equal(true)) 412 413 _, err := reconciler.Reconcile(context.TODO(), request) 414 Expect(err).NotTo(HaveOccurred()) 415 }) 416 417 By("popping fourth update - msp updated", func() { 418 Expect(reconciler.GetUpdateStatus(instance).tlsCertUpdated).To(Equal(false)) 419 Expect(reconciler.GetUpdateStatus(instance).ecertUpdated).To(Equal(false)) 420 421 Expect(reconciler.GetUpdateStatus(instance).mspUpdated).To(Equal(true)) 422 423 _, err := reconciler.Reconcile(context.TODO(), request) 424 Expect(err).NotTo(HaveOccurred()) 425 426 Expect(reconciler.GetUpdateStatus(instance).mspUpdated).To(Equal(false)) 427 }) 428 429 }) 430 431 Context("num seconds warning period updated", func() { 432 BeforeEach(func() { 433 oldPeer = ¤t.IBPPeer{ 434 ObjectMeta: metav1.ObjectMeta{ 435 Name: instance.Name, 436 }, 437 Spec: current.IBPPeerSpec{ 438 NumSecondsWarningPeriod: 10, 439 }, 440 } 441 442 newPeer = ¤t.IBPPeer{ 443 ObjectMeta: metav1.ObjectMeta{ 444 Name: instance.Name, 445 }, 446 Spec: current.IBPPeerSpec{ 447 NumSecondsWarningPeriod: 20, 448 }, 449 } 450 451 e = event.UpdateEvent{ 452 ObjectOld: oldPeer, 453 ObjectNew: newPeer, 454 } 455 456 Expect(reconciler.UpdateFunc(e)).To(Equal(true)) 457 }) 458 459 It("returns true if numSecondsWarningPeriod changed", func() { 460 Expect(reconciler.GetUpdateStatusAtElement(instance, 4).TLSCertUpdated()).To(Equal(true)) 461 Expect(reconciler.GetUpdateStatusAtElement(instance, 4).EcertUpdated()).To(Equal(true)) 462 463 _, err := reconciler.Reconcile(context.TODO(), request) 464 Expect(err).NotTo(HaveOccurred()) 465 }) 466 }) 467 468 Context("enrollment information changes detection", func() { 469 BeforeEach(func() { 470 oldPeer = ¤t.IBPPeer{ 471 ObjectMeta: metav1.ObjectMeta{ 472 Name: instance.Name, 473 }, 474 } 475 476 newPeer = ¤t.IBPPeer{ 477 ObjectMeta: metav1.ObjectMeta{ 478 Name: instance.Name, 479 }, 480 } 481 482 e = event.UpdateEvent{ 483 ObjectOld: oldPeer, 484 ObjectNew: newPeer, 485 } 486 }) 487 488 Context("ecert", func() { 489 It("returns false if new secret is nil", func() { 490 Expect(reconciler.UpdateFunc(e)).To(Equal(false)) 491 Expect(reconciler.GetUpdateStatus(instance).EcertEnroll()).To(Equal(false)) 492 }) 493 494 It("returns false if new secret has ecert msp set along with enrollment inforamtion", func() { 495 oldPeer.Spec.Secret = ¤t.SecretSpec{ 496 Enrollment: ¤t.EnrollmentSpec{ 497 Component: ¤t.Enrollment{ 498 EnrollID: "id1", 499 }, 500 }, 501 } 502 newPeer.Spec.Secret = ¤t.SecretSpec{ 503 MSP: ¤t.MSPSpec{ 504 Component: ¤t.MSP{}, 505 }, 506 Enrollment: ¤t.EnrollmentSpec{ 507 Component: ¤t.Enrollment{ 508 EnrollID: "id2", 509 }, 510 }, 511 } 512 513 newPeer.Spec.Action = current.PeerAction{ 514 Restart: true, 515 } 516 517 reconciler.UpdateFunc(e) 518 Expect(reconciler.GetUpdateStatusAtElement(instance, 4).EcertEnroll()).To(Equal(false)) 519 }) 520 }) 521 522 Context("TLS", func() { 523 It("returns false if new secret is nil", func() { 524 Expect(reconciler.UpdateFunc(e)).To(Equal(false)) 525 Expect(reconciler.GetUpdateStatus(instance).EcertEnroll()).To(Equal(false)) 526 }) 527 528 It("returns false if new secret has TLS msp set along with enrollment inforamtion", func() { 529 oldPeer.Spec.Secret = ¤t.SecretSpec{ 530 Enrollment: ¤t.EnrollmentSpec{ 531 Component: ¤t.Enrollment{ 532 EnrollID: "id1", 533 }, 534 }, 535 } 536 newPeer.Spec.Secret = ¤t.SecretSpec{ 537 MSP: ¤t.MSPSpec{ 538 Component: ¤t.MSP{}, 539 }, 540 Enrollment: ¤t.EnrollmentSpec{ 541 Component: ¤t.Enrollment{ 542 EnrollID: "id2", 543 }, 544 }, 545 } 546 547 newPeer.Spec.Action = current.PeerAction{ 548 Restart: true, 549 } 550 551 reconciler.UpdateFunc(e) 552 Expect(reconciler.GetUpdateStatusAtElement(instance, 4).EcertEnroll()).To(Equal(false)) 553 }) 554 }) 555 }) 556 557 Context("detect MSP updates", func() { 558 BeforeEach(func() { 559 oldPeer = ¤t.IBPPeer{ 560 ObjectMeta: metav1.ObjectMeta{ 561 Name: instance.Name, 562 }, 563 } 564 565 newPeer = ¤t.IBPPeer{ 566 ObjectMeta: metav1.ObjectMeta{ 567 Name: instance.Name, 568 }, 569 } 570 571 e = event.UpdateEvent{ 572 ObjectOld: oldPeer, 573 ObjectNew: newPeer, 574 } 575 }) 576 577 It("returns false if only admin certs updated in new msp", func() { 578 oldPeer.Spec.Secret = ¤t.SecretSpec{ 579 MSP: ¤t.MSPSpec{ 580 Component: ¤t.MSP{ 581 AdminCerts: []string{"oldcert"}, 582 }, 583 }, 584 } 585 newPeer.Spec.Secret = ¤t.SecretSpec{ 586 MSP: ¤t.MSPSpec{ 587 Component: ¤t.MSP{ 588 AdminCerts: []string{"newcert"}, 589 }, 590 }, 591 } 592 reconciler.UpdateFunc(e) 593 Expect(reconciler.GetUpdateStatusAtElement(instance, 4).MSPUpdated()).To(Equal(false)) 594 }) 595 }) 596 597 Context("update node OU", func() { 598 BeforeEach(func() { 599 oldPeer = ¤t.IBPPeer{ 600 ObjectMeta: metav1.ObjectMeta{ 601 Name: instance.Name, 602 }, 603 } 604 605 newPeer = ¤t.IBPPeer{ 606 ObjectMeta: metav1.ObjectMeta{ 607 Name: instance.Name, 608 }, 609 } 610 newPeer.Spec.DisableNodeOU = pointer.Bool(true) 611 612 e = event.UpdateEvent{ 613 ObjectOld: oldPeer, 614 ObjectNew: newPeer, 615 } 616 }) 617 618 It("returns true if node ou updated in spec", func() { 619 reconciler.UpdateFunc(e) 620 Expect(reconciler.GetUpdateStatusAtElement(instance, 4).NodeOUUpdated()).To(Equal(true)) 621 }) 622 }) 623 }) 624 625 Context("set status", func() { 626 It("sets the status to error if error occured during IPBPPeer reconciliation", func() { 627 reconciler.SetStatus(instance, nil, errors.New("ibppeer error")) 628 Expect(instance.Status.Type).To(Equal(current.Error)) 629 Expect(instance.Status.Message).To(Equal("ibppeer error")) 630 }) 631 632 It("sets the status to deploying if pod is not yet running", func() { 633 mockKubeClient.ListStub = func(ctx context.Context, obj client.ObjectList, opts ...client.ListOption) error { 634 podList := obj.(*corev1.PodList) 635 pod := corev1.Pod{} 636 podList.Items = append(podList.Items, pod) 637 return nil 638 } 639 reconciler.SetStatus(instance, nil, nil) 640 Expect(instance.Status.Type).To(Equal(current.Deploying)) 641 }) 642 643 It("sets the status to deployed if pod is running", func() { 644 mockKubeClient.ListStub = func(ctx context.Context, obj client.ObjectList, opts ...client.ListOption) error { 645 podList := obj.(*corev1.PodList) 646 pod := corev1.Pod{ 647 Status: corev1.PodStatus{ 648 Phase: corev1.PodRunning, 649 }, 650 } 651 podList.Items = append(podList.Items, pod) 652 return nil 653 } 654 655 reconciler.SetStatus(instance, nil, nil) 656 Expect(instance.Status.Type).To(Equal(current.Deployed)) 657 }) 658 }) 659 660 Context("create func predicate", func() { 661 Context("case: peer", func() { 662 var ( 663 peer *current.IBPPeer 664 e event.CreateEvent 665 ) 666 667 BeforeEach(func() { 668 peer = ¤t.IBPPeer{ 669 ObjectMeta: metav1.ObjectMeta{ 670 Name: instance.GetName(), 671 }, 672 Status: current.IBPPeerStatus{ 673 CRStatus: current.CRStatus{ 674 Type: current.Deployed, 675 }, 676 }, 677 } 678 e = event.CreateEvent{ 679 Object: peer, 680 } 681 }) 682 683 It("sets update flags to false if instance has status type and a create event is detected but no spec changes are detected", func() { 684 create := reconciler.CreateFunc(e) 685 Expect(create).To(Equal(true)) 686 687 Expect(reconciler.GetUpdateStatus(instance)).To(Equal(&Update{ 688 specUpdated: false, 689 overridesUpdated: false, 690 dindArgsUpdated: false, 691 })) 692 }) 693 694 It("sets update flags to true if instance has status type and a create event is detected and spec changes detected", func() { 695 override := []byte("{}") 696 697 spec := current.IBPPeerSpec{ 698 ImagePullSecrets: []string{"pullsecret1"}, 699 ConfigOverride: &runtime.RawExtension{Raw: override}, 700 } 701 binaryData, err := yaml.Marshal(spec) 702 Expect(err).NotTo(HaveOccurred()) 703 704 mockKubeClient.GetStub = func(ctx context.Context, types types.NamespacedName, obj client.Object) error { 705 switch obj.(type) { 706 case *corev1.ConfigMap: 707 o := obj.(*corev1.ConfigMap) 708 o.BinaryData = map[string][]byte{ 709 "spec": binaryData, 710 } 711 } 712 return nil 713 } 714 create := reconciler.CreateFunc(e) 715 Expect(create).To(Equal(true)) 716 717 Expect(reconciler.GetUpdateStatus(instance)).To(Equal(&Update{ 718 specUpdated: true, 719 overridesUpdated: true, 720 })) 721 }) 722 723 It("does not trigger update if instance does not have status type and a create event is detected", func() { 724 peer.Status.Type = "" 725 726 create := reconciler.CreateFunc(e) 727 Expect(create).To(Equal(true)) 728 729 Expect(reconciler.GetUpdateStatus(instance)).To(Equal(&Update{})) 730 }) 731 732 It("returns true but doesn't trigger update if new instance's name is unique to one IBPPeer in the list of IBPPeers", func() { 733 peer.Status.Type = "" 734 peer.Name = "test-peer1" 735 736 create := reconciler.CreateFunc(e) 737 Expect(create).To(Equal(true)) 738 Expect(reconciler.GetUpdateStatus(instance)).To(Equal(&Update{})) 739 740 }) 741 742 It("returns false if new instance's name already exists for another IBPPeer custom resource", func() { 743 peer.Status.Type = "" 744 peer.Name = "test-peer2" 745 746 create := reconciler.CreateFunc(e) 747 Expect(create).To(Equal(false)) 748 Expect(peer.Status.Type).To(Equal(current.Error)) 749 }) 750 }) 751 752 Context("case: secret", func() { 753 var ( 754 cert *corev1.Secret 755 e event.CreateEvent 756 ) 757 758 BeforeEach(func() { 759 cert = &corev1.Secret{ 760 ObjectMeta: metav1.ObjectMeta{ 761 OwnerReferences: []metav1.OwnerReference{ 762 {Name: instance.Name, 763 Kind: "IBPPeer"}, 764 }, 765 }, 766 } 767 e = event.CreateEvent{} 768 }) 769 770 It("sets create flags to true if create event is detected for secret and secret is a TLS signcert", func() { 771 cert.Name = fmt.Sprintf("tls-%s-signcert", instance.Name) 772 e.Object = cert 773 create := reconciler.CreateFunc(e) 774 Expect(create).To(Equal(true)) 775 776 Expect(reconciler.GetUpdateStatus(instance)).To(Equal(&Update{ 777 tlsCertCreated: true, 778 })) 779 }) 780 781 It("sets update flags to true if create event is detected for secret and secret is an ecert signcert", func() { 782 cert.Name = fmt.Sprintf("ecert-%s-signcert", instance.Name) 783 e.Object = cert 784 create := reconciler.CreateFunc(e) 785 Expect(create).To(Equal(true)) 786 787 Expect(reconciler.GetUpdateStatus(instance)).To(Equal(&Update{ 788 ecertCreated: true, 789 })) 790 }) 791 792 It("does not set update flags and doesn't trigger create event if create event is detected for secret and secret is not a signcert", func() { 793 cert.Name = fmt.Sprintf("tls-%s-admincert", instance.Name) 794 e.Object = cert 795 create := reconciler.CreateFunc(e) 796 Expect(create).To(Equal(false)) 797 798 Expect(reconciler.GetUpdateStatus(instance)).To(Equal(&Update{})) 799 }) 800 801 It("does not set update flags and doesn't trigger create event if create event is detected for non-peer secret", func() { 802 cert.Name = "tls-orderer1-signcert" 803 cert.OwnerReferences = nil 804 e.Object = cert 805 create := reconciler.CreateFunc(e) 806 Expect(create).To(Equal(false)) 807 808 Expect(reconciler.GetUpdateStatus(instance)).To(Equal(&Update{})) 809 }) 810 811 It("does not set update flags if create event is detected for secret with non-peer owner", func() { 812 cert.Name = "tls-orderer1-signcert" 813 cert.OwnerReferences[0].Kind = "IBPOrderer" 814 e.Object = cert 815 create := reconciler.CreateFunc(e) 816 Expect(create).To(Equal(true)) 817 818 Expect(reconciler.GetUpdateStatus(instance)).To(Equal(&Update{ 819 tlsCertCreated: false, 820 })) 821 }) 822 }) 823 }) 824 825 Context("remove element", func() { 826 BeforeEach(func() { 827 reconciler.PushUpdate(instance.Name, Update{ 828 overridesUpdated: true, 829 }) 830 831 reconciler.PushUpdate(instance.Name, Update{ 832 specUpdated: true, 833 }) 834 835 Expect(reconciler.GetUpdateStatus(instance).ConfigOverridesUpdated()).To(Equal(true)) 836 Expect(reconciler.GetUpdateStatusAtElement(instance, 1).SpecUpdated()).To(Equal(true)) 837 }) 838 839 It("removes top element", func() { 840 reconciler.PopUpdate(instance.Name) 841 Expect(reconciler.GetUpdateStatus(instance).ConfigOverridesUpdated()).To(Equal(false)) 842 Expect(reconciler.GetUpdateStatus(instance).SpecUpdated()).To(Equal(true)) 843 }) 844 845 It("removing more elements than in slice should not panic", func() { 846 reconciler.PopUpdate(instance.Name) 847 reconciler.PopUpdate(instance.Name) 848 reconciler.PopUpdate(instance.Name) 849 Expect(reconciler.GetUpdateStatus(instance).SpecUpdated()).To(Equal(false)) 850 Expect(reconciler.GetUpdateStatus(instance).ConfigOverridesUpdated()).To(Equal(false)) 851 }) 852 }) 853 854 Context("append update if missing", func() { 855 It("appends update", func() { 856 updates := []Update{{tlsCertUpdated: true}} 857 updates = reconciler.AppendUpdateIfMissing(updates, Update{ecertUpdated: true}) 858 Expect(len(updates)).To(Equal(2)) 859 }) 860 861 It("doesn't append update that is already in stack", func() { 862 updates := []Update{{tlsCertUpdated: true}} 863 updates = reconciler.AppendUpdateIfMissing(updates, Update{tlsCertUpdated: true}) 864 Expect(len(updates)).To(Equal(1)) 865 }) 866 }) 867 868 Context("push update", func() { 869 It("pushes update only if missing from stack of updates", func() { 870 reconciler.PushUpdate(instance.Name, Update{specUpdated: true}) 871 Expect(len(reconciler.update[instance.Name])).To(Equal(1)) 872 reconciler.PushUpdate(instance.Name, Update{tlsCertUpdated: true}) 873 Expect(len(reconciler.update[instance.Name])).To(Equal(2)) 874 reconciler.PushUpdate(instance.Name, Update{ecertUpdated: true}) 875 Expect(len(reconciler.update[instance.Name])).To(Equal(3)) 876 reconciler.PushUpdate(instance.Name, Update{tlsCertUpdated: true}) 877 Expect(len(reconciler.update[instance.Name])).To(Equal(3)) 878 reconciler.PushUpdate(instance.Name, Update{tlsCertUpdated: true, specUpdated: true}) 879 Expect(len(reconciler.update[instance.Name])).To(Equal(4)) 880 }) 881 }) 882 883 Context("add owner reference to secret", func() { 884 var ( 885 secret *corev1.Secret 886 ) 887 888 BeforeEach(func() { 889 secret = &corev1.Secret{} 890 secret.Name = "ecert-test-peer1-signcert" 891 }) 892 893 It("returns error if fails to get list of peers", func() { 894 mockKubeClient.ListReturns(errors.New("list error")) 895 _, err := reconciler.AddOwnerReferenceToSecret(secret) 896 Expect(err).To(HaveOccurred()) 897 Expect(err.Error()).To(ContainSubstring("list error")) 898 }) 899 900 It("returns false if secret doesn't belong to any peers in list", func() { 901 secret.Name = "tls-orderer1-signcert" 902 added, err := reconciler.AddOwnerReferenceToSecret(secret) 903 Expect(err).NotTo(HaveOccurred()) 904 Expect(added).To(Equal(false)) 905 }) 906 907 It("returns true if owner references added to secret", func() { 908 added, err := reconciler.AddOwnerReferenceToSecret(secret) 909 Expect(err).NotTo(HaveOccurred()) 910 Expect(added).To(Equal(true)) 911 }) 912 913 It("returns true if owner references added to init-rootcert secret", func() { 914 secret.Name = "test-peer1-init-rootcert" 915 added, err := reconciler.AddOwnerReferenceToSecret(secret) 916 Expect(err).NotTo(HaveOccurred()) 917 Expect(added).To(Equal(true)) 918 }) 919 }) 920 })