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 = &current.IBPPeer{
    61  			Spec: current.IBPPeerSpec{
    62  				Images: &current.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 = &current.IBPPeer{
   191  				ObjectMeta: metav1.ObjectMeta{
   192  					Name: instance.Name,
   193  				},
   194  				Spec: current.IBPPeerSpec{
   195  					Images: &current.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 = &current.IBPPeer{
   205  				ObjectMeta: metav1.ObjectMeta{
   206  					Name: instance.Name,
   207  				},
   208  				Spec: current.IBPPeerSpec{
   209  					Images: &current.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 = &current.IBPPeer{
   224  				ObjectMeta: metav1.ObjectMeta{
   225  					Name: instance.Name,
   226  				},
   227  				Spec: current.IBPPeerSpec{
   228  					Images: &current.PeerImages{
   229  						PeerTag: "1.4.6-20200101",
   230  					},
   231  					MSPID: "old-mspid",
   232  				},
   233  			}
   234  
   235  			newPeer = &current.IBPPeer{
   236  				ObjectMeta: metav1.ObjectMeta{
   237  					Name: instance.Name,
   238  				},
   239  				Spec: current.IBPPeerSpec{
   240  					Images: &current.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 = &current.IBPPeer{
   354  				ObjectMeta: metav1.ObjectMeta{
   355  					Name: instance.Name,
   356  				},
   357  				Spec: current.IBPPeerSpec{
   358  					Secret: &current.SecretSpec{
   359  						MSP: &current.MSPSpec{
   360  							Component: &current.MSP{
   361  								SignCerts: "testcert",
   362  							},
   363  						},
   364  					},
   365  				},
   366  			}
   367  
   368  			newPeer = &current.IBPPeer{
   369  				ObjectMeta: metav1.ObjectMeta{
   370  					Name: instance.Name,
   371  				},
   372  				Spec: current.IBPPeerSpec{
   373  					Secret: &current.SecretSpec{
   374  						MSP: &current.MSPSpec{
   375  							TLS: &current.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 = &current.IBPPeer{
   434  					ObjectMeta: metav1.ObjectMeta{
   435  						Name: instance.Name,
   436  					},
   437  					Spec: current.IBPPeerSpec{
   438  						NumSecondsWarningPeriod: 10,
   439  					},
   440  				}
   441  
   442  				newPeer = &current.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 = &current.IBPPeer{
   471  					ObjectMeta: metav1.ObjectMeta{
   472  						Name: instance.Name,
   473  					},
   474  				}
   475  
   476  				newPeer = &current.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 = &current.SecretSpec{
   496  						Enrollment: &current.EnrollmentSpec{
   497  							Component: &current.Enrollment{
   498  								EnrollID: "id1",
   499  							},
   500  						},
   501  					}
   502  					newPeer.Spec.Secret = &current.SecretSpec{
   503  						MSP: &current.MSPSpec{
   504  							Component: &current.MSP{},
   505  						},
   506  						Enrollment: &current.EnrollmentSpec{
   507  							Component: &current.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 = &current.SecretSpec{
   530  						Enrollment: &current.EnrollmentSpec{
   531  							Component: &current.Enrollment{
   532  								EnrollID: "id1",
   533  							},
   534  						},
   535  					}
   536  					newPeer.Spec.Secret = &current.SecretSpec{
   537  						MSP: &current.MSPSpec{
   538  							Component: &current.MSP{},
   539  						},
   540  						Enrollment: &current.EnrollmentSpec{
   541  							Component: &current.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 = &current.IBPPeer{
   560  					ObjectMeta: metav1.ObjectMeta{
   561  						Name: instance.Name,
   562  					},
   563  				}
   564  
   565  				newPeer = &current.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 = &current.SecretSpec{
   579  					MSP: &current.MSPSpec{
   580  						Component: &current.MSP{
   581  							AdminCerts: []string{"oldcert"},
   582  						},
   583  					},
   584  				}
   585  				newPeer.Spec.Secret = &current.SecretSpec{
   586  					MSP: &current.MSPSpec{
   587  						Component: &current.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 = &current.IBPPeer{
   600  					ObjectMeta: metav1.ObjectMeta{
   601  						Name: instance.Name,
   602  					},
   603  				}
   604  
   605  				newPeer = &current.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 = &current.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  })