github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/offering/base/console/console_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 baseconsole_test
    20  
    21  import (
    22  	current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1"
    23  	cmocks "github.com/IBM-Blockchain/fabric-operator/controllers/mocks"
    24  	config "github.com/IBM-Blockchain/fabric-operator/operatorconfig"
    25  	consolev1 "github.com/IBM-Blockchain/fabric-operator/pkg/apis/console/v1"
    26  	managermocks "github.com/IBM-Blockchain/fabric-operator/pkg/manager/resources/mocks"
    27  	baseconsole "github.com/IBM-Blockchain/fabric-operator/pkg/offering/base/console"
    28  	"github.com/IBM-Blockchain/fabric-operator/pkg/offering/base/console/mocks"
    29  	"github.com/IBM-Blockchain/fabric-operator/version"
    30  	. "github.com/onsi/ginkgo/v2"
    31  	. "github.com/onsi/gomega"
    32  	"github.com/pkg/errors"
    33  	"k8s.io/apimachinery/pkg/runtime"
    34  	logf "sigs.k8s.io/controller-runtime/pkg/log"
    35  	"sigs.k8s.io/controller-runtime/pkg/log/zap"
    36  )
    37  
    38  var _ = Describe("Base Console", func() {
    39  	var (
    40  		console        *baseconsole.Console
    41  		instance       *current.IBPConsole
    42  		mockKubeClient *cmocks.Client
    43  
    44  		deploymentMgr        *managermocks.ResourceManager
    45  		serviceMgr           *managermocks.ResourceManager
    46  		deployerServiceMgr   *managermocks.ResourceManager
    47  		pvcMgr               *managermocks.ResourceManager
    48  		configMapMgr         *managermocks.ResourceManager
    49  		consoleConfigMapMgr  *managermocks.ResourceManager
    50  		deployerConfigMapMgr *managermocks.ResourceManager
    51  		roleMgr              *managermocks.ResourceManager
    52  		roleBindingMgr       *managermocks.ResourceManager
    53  		serviceAccountMgr    *managermocks.ResourceManager
    54  		update               *mocks.Update
    55  		restartMgr           *mocks.RestartManager
    56  	)
    57  
    58  	BeforeEach(func() {
    59  		logf.SetLogger(zap.New())
    60  		mockKubeClient = &cmocks.Client{}
    61  		update = &mocks.Update{}
    62  		restartMgr = &mocks.RestartManager{}
    63  
    64  		deploymentMgr = &managermocks.ResourceManager{}
    65  		serviceMgr = &managermocks.ResourceManager{}
    66  		deployerServiceMgr = &managermocks.ResourceManager{}
    67  		pvcMgr = &managermocks.ResourceManager{}
    68  		configMapMgr = &managermocks.ResourceManager{}
    69  		consoleConfigMapMgr = &managermocks.ResourceManager{}
    70  		deployerConfigMapMgr = &managermocks.ResourceManager{}
    71  		roleMgr = &managermocks.ResourceManager{}
    72  		roleBindingMgr = &managermocks.ResourceManager{}
    73  		serviceAccountMgr = &managermocks.ResourceManager{}
    74  
    75  		instance = &current.IBPConsole{
    76  			Spec: current.IBPConsoleSpec{
    77  				License: current.License{
    78  					Accept: true,
    79  				},
    80  				ServiceAccountName: "test",
    81  				AuthScheme:         "couchdb",
    82  				DeployerTimeout:    30000,
    83  				Components:         "athena-components",
    84  				Sessions:           "athena-sessions",
    85  				System:             "athena-system",
    86  				Service:            &current.Service{},
    87  				Email:              "xyz@ibm.com",
    88  				Password:           "cGFzc3dvcmQ=",
    89  				SystemChannel:      "testchainid",
    90  				ImagePullSecrets:   []string{"testsecret"},
    91  				RegistryURL:        "ghcr.io/ibm-blockchain/ibp-temp/",
    92  				Kubeconfig:         &[]byte{},
    93  				ConnectionString:   "https://localhost",
    94  				Images: &current.ConsoleImages{
    95  					ConsoleInitImage:   "fake-init-image",
    96  					ConsoleInitTag:     "1234",
    97  					CouchDBImage:       "fake-couchdb-image",
    98  					CouchDBTag:         "1234",
    99  					ConsoleImage:       "fake-console-image",
   100  					ConsoleTag:         "1234",
   101  					ConfigtxlatorImage: "fake-configtxlator-image",
   102  					ConfigtxlatorTag:   "1234",
   103  					DeployerImage:      "fake-deployer-image",
   104  					DeployerTag:        "1234",
   105  				},
   106  				NetworkInfo: &current.NetworkInfo{
   107  					Domain:      "test.domain",
   108  					ConsolePort: 31010,
   109  					ProxyPort:   31011,
   110  				},
   111  				TLSSecretName: "secret",
   112  				Resources:     &current.ConsoleResources{},
   113  				Storage: &current.ConsoleStorage{
   114  					Console: &current.StorageSpec{
   115  						Size:  "100m",
   116  						Class: "manual",
   117  					},
   118  				},
   119  				Versions:           &current.Versions{},
   120  				PasswordSecretName: "password",
   121  			},
   122  		}
   123  		instance.Kind = "IBPConsole"
   124  		instance.Status.Version = version.Operator
   125  
   126  		console = &baseconsole.Console{
   127  			Client: mockKubeClient,
   128  			Scheme: &runtime.Scheme{},
   129  			Config: &config.Config{},
   130  
   131  			DeploymentManager:        deploymentMgr,
   132  			ServiceManager:           serviceMgr,
   133  			DeployerServiceManager:   deployerServiceMgr,
   134  			PVCManager:               pvcMgr,
   135  			ConfigMapManager:         configMapMgr,
   136  			ConsoleConfigMapManager:  consoleConfigMapMgr,
   137  			DeployerConfigMapManager: deployerConfigMapMgr,
   138  			RoleManager:              roleMgr,
   139  			RoleBindingManager:       roleBindingMgr,
   140  			ServiceAccountManager:    serviceAccountMgr,
   141  			Restart:                  restartMgr,
   142  		}
   143  	})
   144  
   145  	Context("Reconciles", func() {
   146  		It("returns nil and request will be requeued if instance version is updated", func() {
   147  			instance.Status.Version = ""
   148  			_, err := console.Reconcile(instance, update)
   149  			Expect(err).NotTo(HaveOccurred())
   150  			Expect(mockKubeClient.PatchStatusCallCount()).To(Equal(1))
   151  		})
   152  		It("returns an error if pvc manager fails to reconcile", func() {
   153  			pvcMgr.ReconcileReturns(errors.New("failed to reconcile pvc"))
   154  			_, err := console.Reconcile(instance, update)
   155  			Expect(err).To(HaveOccurred())
   156  			Expect(err.Error()).To(Equal("failed to reconcile managers: failed PVC reconciliation: failed to reconcile pvc"))
   157  		})
   158  
   159  		It("returns an error if service manager fails to reconcile", func() {
   160  			serviceMgr.ReconcileReturns(errors.New("failed to reconcile service"))
   161  			_, err := console.Reconcile(instance, update)
   162  			Expect(err).To(HaveOccurred())
   163  			Expect(err.Error()).To(Equal("failed to reconcile managers: failed Service reconciliation: failed to reconcile service"))
   164  		})
   165  
   166  		It("returns no error if dev mode is disabled & deployer service manager fails to reconcile", func() {
   167  			deployerServiceMgr.ReconcileReturns(errors.New("failed to reconcile service"))
   168  			_, err := console.Reconcile(instance, update)
   169  			Expect(err).NotTo(HaveOccurred())
   170  		})
   171  
   172  		It("returns an error if deployer service manager fails to reconcile", func() {
   173  			instance.Spec.FeatureFlags = &consolev1.FeatureFlags{
   174  				DevMode: true,
   175  			}
   176  			deployerServiceMgr.ReconcileReturns(errors.New("failed to reconcile service"))
   177  			_, err := console.Reconcile(instance, update)
   178  			Expect(err).To(HaveOccurred())
   179  			Expect(err.Error()).To(Equal("failed to reconcile managers: failed Deployer Service reconciliation: failed to reconcile service"))
   180  		})
   181  
   182  		It("returns an error if deployment manager fails to reconcile", func() {
   183  			deploymentMgr.ReconcileReturns(errors.New("failed to reconcile deployment"))
   184  			_, err := console.Reconcile(instance, update)
   185  			Expect(err).To(HaveOccurred())
   186  			Expect(err.Error()).To(Equal("failed to reconcile managers: failed Deployment reconciliation: failed to reconcile deployment"))
   187  		})
   188  
   189  		It("returns an error if role manager fails to reconcile", func() {
   190  			roleMgr.ReconcileReturns(errors.New("failed to reconcile role"))
   191  			_, err := console.Reconcile(instance, update)
   192  			Expect(err).To(HaveOccurred())
   193  			Expect(err.Error()).To(Equal("failed to reconcile managers: failed RBAC reconciliation: failed to reconcile role"))
   194  		})
   195  
   196  		It("returns an error if role binding manager fails to reconcile", func() {
   197  			roleBindingMgr.ReconcileReturns(errors.New("failed to reconcile role binding"))
   198  			_, err := console.Reconcile(instance, update)
   199  			Expect(err).To(HaveOccurred())
   200  			Expect(err.Error()).To(Equal("failed to reconcile managers: failed RBAC reconciliation: failed to reconcile role binding"))
   201  		})
   202  
   203  		It("returns an error if service account binding manager fails to reconcile", func() {
   204  			serviceAccountMgr.ReconcileReturns(errors.New("failed to reconcile service account"))
   205  			_, err := console.Reconcile(instance, update)
   206  			Expect(err).To(HaveOccurred())
   207  			Expect(err.Error()).To(Equal("failed to reconcile managers: failed RBAC reconciliation: failed to reconcile service account"))
   208  		})
   209  
   210  		It("returns an error if config map manager fails to reconcile", func() {
   211  			configMapMgr.ReconcileReturns(errors.New("failed to reconcile config map"))
   212  			_, err := console.Reconcile(instance, update)
   213  			Expect(err).To(HaveOccurred())
   214  			Expect(err.Error()).To(Equal("failed to reconcile managers: failed ConfigMap reconciliation: failed to reconcile config map"))
   215  		})
   216  
   217  		It("returns an error if config map manager fails to reconcile", func() {
   218  			consoleConfigMapMgr.ReconcileReturns(errors.New("failed to reconcile config map"))
   219  			_, err := console.Reconcile(instance, update)
   220  			Expect(err).To(HaveOccurred())
   221  			Expect(err.Error()).To(Equal("failed to reconcile managers: failed Console ConfigMap reconciliation: failed to reconcile config map"))
   222  		})
   223  
   224  		It("returns an error if config map manager fails to reconcile", func() {
   225  			deployerConfigMapMgr.ReconcileReturns(errors.New("failed to reconcile config map"))
   226  			_, err := console.Reconcile(instance, update)
   227  			Expect(err).To(HaveOccurred())
   228  			Expect(err.Error()).To(Equal("failed to reconcile managers: failed Deployer ConfigMap reconciliation: failed to reconcile config map"))
   229  		})
   230  
   231  		It("restarts pods by deleting deployment", func() {
   232  			update.RestartNeededReturns(true)
   233  			_, err := console.Reconcile(instance, update)
   234  			Expect(err).NotTo(HaveOccurred())
   235  			Expect(mockKubeClient.PatchCallCount()).To(Equal(1))
   236  		})
   237  
   238  		It("returns error if trigger restart fails", func() {
   239  			restartMgr.TriggerIfNeededReturns(errors.New("failed to trigger restart"))
   240  			_, err := console.Reconcile(instance, update)
   241  			Expect(err).To(HaveOccurred())
   242  			Expect(err.Error()).To(Equal("failed to restart deployment: failed to trigger restart"))
   243  		})
   244  
   245  		It("does not return an error on a successful reconcile", func() {
   246  			_, err := console.Reconcile(instance, update)
   247  			Expect(err).NotTo(HaveOccurred())
   248  		})
   249  	})
   250  
   251  	Context("ValidateSpec", func() {
   252  		It("returns no error if valid spec is passed", func() {
   253  			err := console.ValidateSpec(instance)
   254  			Expect(err).NotTo(HaveOccurred())
   255  		})
   256  
   257  		It("returns error if license is not accepted", func() {
   258  			instance.Spec.License.Accept = false
   259  			err := console.ValidateSpec(instance)
   260  			Expect(err).To(HaveOccurred())
   261  			Expect(err.Error()).To(Equal("user must accept license before continuing"))
   262  		})
   263  
   264  		It("returns error if serviceaccountname is not passed", func() {
   265  			instance.Spec.ServiceAccountName = ""
   266  			err := console.ValidateSpec(instance)
   267  			Expect(err).To(HaveOccurred())
   268  			Expect(err.Error()).To(Equal("Service account name not provided"))
   269  		})
   270  
   271  		It("returns error if email is not passed", func() {
   272  			instance.Spec.Email = ""
   273  			err := console.ValidateSpec(instance)
   274  			Expect(err).To(HaveOccurred())
   275  			Expect(err.Error()).To(Equal("email not provided"))
   276  		})
   277  
   278  		It("returns error if password & passwordsecret are not passed", func() {
   279  			instance.Spec.PasswordSecretName = ""
   280  			instance.Spec.Password = ""
   281  			err := console.ValidateSpec(instance)
   282  			Expect(err).To(HaveOccurred())
   283  			Expect(err.Error()).To(Equal("password and passwordSecretName both not provided, at least one expected"))
   284  		})
   285  
   286  		It("should not return error if password & passwordsecret are not passed when authscheme is ibmid", func() {
   287  			instance.Spec.AuthScheme = "ibmid"
   288  			instance.Spec.PasswordSecretName = ""
   289  			instance.Spec.Password = ""
   290  			err := console.ValidateSpec(instance)
   291  			Expect(err).ToNot(HaveOccurred())
   292  		})
   293  
   294  		It("returns error if imagepullsecret is not passed", func() {
   295  			instance.Spec.ImagePullSecrets = []string{}
   296  			err := console.ValidateSpec(instance)
   297  			Expect(err).To(HaveOccurred())
   298  			Expect(err.Error()).To(Equal("imagepullsecrets required"))
   299  		})
   300  
   301  		It("returns error if ingress info are not passed", func() {
   302  			instance.Spec.NetworkInfo = nil
   303  			err := console.ValidateSpec(instance)
   304  			Expect(err).To(HaveOccurred())
   305  			Expect(err.Error()).To(Equal("network information not provided"))
   306  		})
   307  	})
   308  
   309  	Context("CreateCouchdbCredentials", func() {
   310  		It("does not update connectionstring if it is not blank", func() {
   311  			connectionString := "https://fake.url"
   312  			instance.Spec.ConnectionString = connectionString
   313  			updated := console.CreateCouchdbCredentials(instance)
   314  			Expect(updated).To(BeFalse())
   315  			Expect(instance.Spec.ConnectionString).To(Equal(connectionString))
   316  		})
   317  
   318  		It("does not update connectionstring if it is not blank & is https", func() {
   319  			connectionString := "https://localhost:5984"
   320  			instance.Spec.ConnectionString = connectionString
   321  			updated := console.CreateCouchdbCredentials(instance)
   322  			Expect(updated).To(BeFalse())
   323  			Expect(instance.Spec.ConnectionString).To(Equal(connectionString))
   324  		})
   325  
   326  		It("does update connectionstring if it is missing creds", func() {
   327  			connectionString := "http://localhost:5984"
   328  			instance.Spec.ConnectionString = connectionString
   329  			updated := console.CreateCouchdbCredentials(instance)
   330  			Expect(updated).To(BeTrue())
   331  			Expect(instance.Spec.ConnectionString).NotTo(Equal(connectionString))
   332  		})
   333  
   334  		It("does not update connectionstring if it is has creds already", func() {
   335  			connectionString := "http://user:pass@localhost:5984"
   336  			instance.Spec.ConnectionString = connectionString
   337  			updated := console.CreateCouchdbCredentials(instance)
   338  			Expect(updated).To(BeFalse())
   339  			Expect(instance.Spec.ConnectionString).To(Equal(connectionString))
   340  		})
   341  	})
   342  })