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 = ¤t.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: ¤t.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: ¤t.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: ¤t.NetworkInfo{ 107 Domain: "test.domain", 108 ConsolePort: 31010, 109 ProxyPort: 31011, 110 }, 111 TLSSecretName: "secret", 112 Resources: ¤t.ConsoleResources{}, 113 Storage: ¤t.ConsoleStorage{ 114 Console: ¤t.StorageSpec{ 115 Size: "100m", 116 Class: "manual", 117 }, 118 }, 119 Versions: ¤t.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 })