github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/offering/k8s/peer/peer_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 k8speer_test
    20  
    21  import (
    22  	"context"
    23  
    24  	current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1"
    25  	cmocks "github.com/IBM-Blockchain/fabric-operator/controllers/mocks"
    26  	config "github.com/IBM-Blockchain/fabric-operator/operatorconfig"
    27  	"github.com/IBM-Blockchain/fabric-operator/pkg/initializer/common/enroller"
    28  	peerinit "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/peer"
    29  	managermocks "github.com/IBM-Blockchain/fabric-operator/pkg/manager/resources/mocks"
    30  	basepeer "github.com/IBM-Blockchain/fabric-operator/pkg/offering/base/peer"
    31  	"github.com/IBM-Blockchain/fabric-operator/pkg/offering/base/peer/mocks"
    32  	k8speer "github.com/IBM-Blockchain/fabric-operator/pkg/offering/k8s/peer"
    33  	"github.com/IBM-Blockchain/fabric-operator/pkg/operatorerrors"
    34  	"github.com/IBM-Blockchain/fabric-operator/version"
    35  	. "github.com/onsi/ginkgo/v2"
    36  	. "github.com/onsi/gomega"
    37  	"github.com/pkg/errors"
    38  	corev1 "k8s.io/api/core/v1"
    39  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    40  	"k8s.io/apimachinery/pkg/runtime"
    41  	"k8s.io/apimachinery/pkg/types"
    42  	"k8s.io/apimachinery/pkg/util/intstr"
    43  	"sigs.k8s.io/controller-runtime/pkg/client"
    44  )
    45  
    46  var _ = Describe("K8s Peer", func() {
    47  	var (
    48  		peer           *k8speer.Peer
    49  		instance       *current.IBPPeer
    50  		mockKubeClient *cmocks.Client
    51  		cfg            *config.Config
    52  
    53  		deploymentMgr     *mocks.DeploymentManager
    54  		serviceMgr        *managermocks.ResourceManager
    55  		pvcMgr            *managermocks.ResourceManager
    56  		couchPvcMgr       *managermocks.ResourceManager
    57  		configMapMgr      *managermocks.ResourceManager
    58  		roleMgr           *managermocks.ResourceManager
    59  		roleBindingMgr    *managermocks.ResourceManager
    60  		serviceAccountMgr *managermocks.ResourceManager
    61  		ingressMgr        *managermocks.ResourceManager
    62  		update            *mocks.Update
    63  		certificateMgr    *mocks.CertificateManager
    64  	)
    65  
    66  	BeforeEach(func() {
    67  		mockKubeClient = &cmocks.Client{}
    68  		update = &mocks.Update{}
    69  
    70  		replicas := int32(1)
    71  		instance = &current.IBPPeer{
    72  			TypeMeta: metav1.TypeMeta{
    73  				Kind: "IBPPeer",
    74  			},
    75  			ObjectMeta: metav1.ObjectMeta{
    76  				Name:      "peer1",
    77  				Namespace: "random",
    78  			},
    79  			Spec: current.IBPPeerSpec{
    80  				PeerExternalEndpoint: "address",
    81  				Domain:               "domain",
    82  				StateDb:              "couchdb",
    83  				Replicas:             &replicas,
    84  				Images:               &current.PeerImages{},
    85  				FabricVersion:        "1.4.9",
    86  			},
    87  			Status: current.IBPPeerStatus{
    88  				CRStatus: current.CRStatus{
    89  					Version: version.Operator,
    90  				},
    91  			},
    92  		}
    93  
    94  		mockKubeClient.GetStub = func(ctx context.Context, types types.NamespacedName, obj client.Object) error {
    95  			switch obj.(type) {
    96  			case *current.IBPPeer:
    97  				o := obj.(*current.IBPPeer)
    98  				o.Kind = "IBPPeer"
    99  				instance = o
   100  			case *corev1.Service:
   101  				o := obj.(*corev1.Service)
   102  				o.Spec.Type = corev1.ServiceTypeNodePort
   103  				o.Spec.Ports = append(o.Spec.Ports, corev1.ServicePort{
   104  					Name: "peer-api",
   105  					TargetPort: intstr.IntOrString{
   106  						IntVal: 7051,
   107  					},
   108  					NodePort: int32(7051),
   109  				})
   110  			case *corev1.Secret:
   111  				o := obj.(*corev1.Secret)
   112  				switch types.Name {
   113  				case "ecert-" + instance.Name + "-cacerts":
   114  					o.Name = "tls-" + instance.Name + "-signcert"
   115  					o.Namespace = instance.Namespace
   116  					o.Data = map[string][]byte{"cacert-0.pem": []byte("")}
   117  				default:
   118  					o.Name = "tls-" + instance.Name + "-signcert"
   119  					o.Namespace = instance.Namespace
   120  					o.Data = map[string][]byte{"cert.pem": []byte("LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNwVENDQWtxZ0F3SUJBZ0lSQU1FeVZVcDRMdlYydEFUREhlWklldDh3Q2dZSUtvWkl6ajBFQXdJd2daVXgKQ3pBSkJnTlZCQVlUQWxWVE1SY3dGUVlEVlFRSUV3NU9iM0owYUNCRFlYSnZiR2x1WVRFUE1BMEdBMVVFQnhNRwpSSFZ5YUdGdE1Rd3dDZ1lEVlFRS0V3TkpRazB4RXpBUkJnTlZCQXNUQ2tKc2IyTnJZMmhoYVc0eE9UQTNCZ05WCkJBTVRNR3BoYmpJeUxXOXlaR1Z5WlhKdmNtZGpZUzFqWVM1aGNIQnpMbkIxYldGekxtOXpMbVo1Y21VdWFXSnQKTG1OdmJUQWVGdzB5TURBeE1qSXhPREExTURCYUZ3MHpNREF4TVRreE9EQTFNREJhTUlHVk1Rc3dDUVlEVlFRRwpFd0pWVXpFWE1CVUdBMVVFQ0JNT1RtOXlkR2dnUTJGeWIyeHBibUV4RHpBTkJnTlZCQWNUQmtSMWNtaGhiVEVNCk1Bb0dBMVVFQ2hNRFNVSk5NUk13RVFZRFZRUUxFd3BDYkc5amEyTm9ZV2x1TVRrd053WURWUVFERXpCcVlXNHkKTWkxdmNtUmxjbVZ5YjNKblkyRXRZMkV1WVhCd2N5NXdkVzFoY3k1dmN5NW1lWEpsTG1saWJTNWpiMjB3V1RBVApCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFTR0lHUFkvZC9tQVhMejM4SlROR3F5bldpOTJXUVB6cnN0Cm5vdEFWZlh0dHZ5QWJXdTRNbWNUMEh6UnBTWjNDcGdxYUNXcTg1MUwyV09LcnZ6L0JPREpvM2t3ZHpCMUJnTlYKSFJFRWJqQnNnakJxWVc0eU1pMXZjbVJsY21WeWIzSm5ZMkV0WTJFdVlYQndjeTV3ZFcxaGN5NXZjeTVtZVhKbApMbWxpYlM1amIyMkNPR3BoYmpJeUxXOXlaR1Z5WlhKdmNtZGpZUzF2Y0dWeVlYUnBiMjV6TG1Gd2NITXVjSFZ0CllYTXViM011Wm5seVpTNXBZbTB1WTI5dE1Bb0dDQ3FHU000OUJBTUNBMGtBTUVZQ0lRQzM3Y1pkNFY2RThPQ1IKaDloQXEyK0dyR21FVTFQU0I1eHo5RkdEWThkODZRSWhBT1crM3Urb2d4bFNWNUoyR3ZYbHRaQmpXRkpvYnJxeApwVVQ4cW4yMDA1b0wKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo")}
   121  				}
   122  			}
   123  			return nil
   124  		}
   125  		instance.Status.Version = version.Operator
   126  
   127  		deploymentMgr = &mocks.DeploymentManager{}
   128  		serviceMgr = &managermocks.ResourceManager{}
   129  		pvcMgr = &managermocks.ResourceManager{}
   130  		couchPvcMgr = &managermocks.ResourceManager{}
   131  		configMapMgr = &managermocks.ResourceManager{}
   132  		roleMgr = &managermocks.ResourceManager{}
   133  		roleBindingMgr = &managermocks.ResourceManager{}
   134  		serviceAccountMgr = &managermocks.ResourceManager{}
   135  		ingressMgr = &managermocks.ResourceManager{}
   136  		certificateMgr = &mocks.CertificateManager{}
   137  		restartMgr := &mocks.RestartManager{}
   138  
   139  		scheme := &runtime.Scheme{}
   140  		cfg = &config.Config{
   141  			PeerInitConfig: &peerinit.Config{
   142  				OUFile:       "../../../../defaultconfig/peer/ouconfig.yaml",
   143  				CorePeerFile: "../../../../defaultconfig/peer/core.yaml",
   144  			},
   145  		}
   146  		initializer := &mocks.InitializeIBPPeer{}
   147  		initializer.GetInitPeerReturns(&peerinit.Peer{}, nil)
   148  		peer = &k8speer.Peer{
   149  			Peer: &basepeer.Peer{
   150  				Client: mockKubeClient,
   151  				Scheme: scheme,
   152  				Config: cfg,
   153  
   154  				DeploymentManager:       deploymentMgr,
   155  				ServiceManager:          serviceMgr,
   156  				PVCManager:              pvcMgr,
   157  				StateDBPVCManager:       couchPvcMgr,
   158  				FluentDConfigMapManager: configMapMgr,
   159  				RoleManager:             roleMgr,
   160  				RoleBindingManager:      roleBindingMgr,
   161  				ServiceAccountManager:   serviceAccountMgr,
   162  				Initializer:             initializer,
   163  				CertificateManager:      certificateMgr,
   164  				Restart:                 restartMgr,
   165  			},
   166  			IngressManager: ingressMgr,
   167  		}
   168  	})
   169  
   170  	Context("Reconciles", func() {
   171  		It("returns an error if pvc manager fails to reconcile", func() {
   172  			pvcMgr.ReconcileReturns(errors.New("failed to reconcile pvc"))
   173  			_, err := peer.Reconcile(instance, update)
   174  			Expect(err).To(HaveOccurred())
   175  			Expect(err.Error()).To(Equal("failed to reconcile managers: failed PVC reconciliation: failed to reconcile pvc"))
   176  		})
   177  
   178  		It("returns an error if couch pvc manager fails to reconcile", func() {
   179  			couchPvcMgr.ReconcileReturns(errors.New("failed to reconcile couch pvc"))
   180  			_, err := peer.Reconcile(instance, update)
   181  			Expect(err).To(HaveOccurred())
   182  			Expect(err.Error()).To(Equal("failed to reconcile managers: failed CouchDB PVC reconciliation: failed to reconcile couch pvc"))
   183  		})
   184  
   185  		It("returns an error if service manager fails to reconcile", func() {
   186  			serviceMgr.ReconcileReturns(errors.New("failed to reconcile service"))
   187  			_, err := peer.Reconcile(instance, update)
   188  			Expect(err).To(HaveOccurred())
   189  			Expect(err.Error()).To(Equal("failed to reconcile managers: failed Service reconciliation: failed to reconcile service"))
   190  		})
   191  
   192  		It("returns an error if deployment manager fails to reconcile", func() {
   193  			deploymentMgr.ReconcileReturns(errors.New("failed to reconcile deployment"))
   194  			_, err := peer.Reconcile(instance, update)
   195  			Expect(err).To(HaveOccurred())
   196  			Expect(err.Error()).To(Equal("failed to reconcile managers: failed Deployment reconciliation: failed to reconcile deployment"))
   197  		})
   198  
   199  		It("returns an error if role manager fails to reconcile", func() {
   200  			roleMgr.ReconcileReturns(errors.New("failed to reconcile role"))
   201  			_, err := peer.Reconcile(instance, update)
   202  			Expect(err).To(HaveOccurred())
   203  			Expect(err.Error()).To(ContainSubstring("failed to reconcile role"))
   204  		})
   205  
   206  		It("returns an error if role binding manager fails to reconcile", func() {
   207  			roleBindingMgr.ReconcileReturns(errors.New("failed to reconcile role binding"))
   208  			_, err := peer.Reconcile(instance, update)
   209  			Expect(err).To(HaveOccurred())
   210  			Expect(err.Error()).To(ContainSubstring("failed to reconcile role binding"))
   211  		})
   212  
   213  		It("returns an error if service account binding manager fails to reconcile", func() {
   214  			serviceAccountMgr.ReconcileReturns(errors.New("failed to reconcile service account"))
   215  			_, err := peer.Reconcile(instance, update)
   216  			Expect(err).To(HaveOccurred())
   217  			Expect(err.Error()).To(ContainSubstring("failed to reconcile service account"))
   218  		})
   219  
   220  		It("returns an error if config map manager fails to reconcile", func() {
   221  			configMapMgr.ReconcileReturns(errors.New("failed to reconcile config map"))
   222  			_, err := peer.Reconcile(instance, update)
   223  			Expect(err).To(HaveOccurred())
   224  			Expect(err.Error()).To(Equal("failed to reconcile managers: failed FluentD ConfigMap reconciliation: failed to reconcile config map"))
   225  		})
   226  
   227  		It("returns a breaking error if initialization fails", func() {
   228  			cfg.PeerInitConfig.CorePeerFile = "../../../../../defaultconfig/peer/badfile.yaml"
   229  			peer.Initializer = peerinit.New(cfg.PeerInitConfig, nil, nil, nil, nil, enroller.HSMEnrollJobTimeouts{})
   230  			_, err := peer.Reconcile(instance, update)
   231  			Expect(err).To(HaveOccurred())
   232  			Expect(err.Error()).To(ContainSubstring("Code: 22 - failed to initialize peer: open"))
   233  			Expect(operatorerrors.IsBreakingError(err, "msg", nil)).NotTo(HaveOccurred())
   234  		})
   235  
   236  		It("does not return an error on a successful reconcile", func() {
   237  			_, err := peer.Reconcile(instance, update)
   238  			Expect(err).NotTo(HaveOccurred())
   239  		})
   240  	})
   241  
   242  	Context("ExternalEndpoint", func() {
   243  		It("Updates the external endpoint, When external endpoint is not defined", func() {
   244  			instance.Namespace = "namespace"
   245  			instance.Name = "name"
   246  			instance.Spec.PeerExternalEndpoint = ""
   247  			instance.Spec.Domain = "1.2.3.4"
   248  
   249  			updated := peer.UpdateExternalEndpoint(instance)
   250  			Expect(updated).To(Equal(true))
   251  			Expect(instance.Spec.PeerExternalEndpoint).To(Equal("namespace-name-peer.1.2.3.4:443"))
   252  		})
   253  	})
   254  })