github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/offering/base/console/override/deployment_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 override_test 20 21 import ( 22 "encoding/json" 23 "fmt" 24 25 . "github.com/onsi/ginkgo/v2" 26 . "github.com/onsi/gomega" 27 28 current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1" 29 "github.com/IBM-Blockchain/fabric-operator/pkg/manager/resources" 30 "github.com/IBM-Blockchain/fabric-operator/pkg/offering/base/console/override" 31 "github.com/IBM-Blockchain/fabric-operator/pkg/util" 32 appsv1 "k8s.io/api/apps/v1" 33 corev1 "k8s.io/api/core/v1" 34 "k8s.io/apimachinery/pkg/runtime" 35 ) 36 37 var _ = Describe("Base Console Deployment Overrides", func() { 38 Context("Deployment", func() { 39 var ( 40 overrider *override.Override 41 instance, instanceWithTags *current.IBPConsole 42 deployment *appsv1.Deployment 43 err error 44 usetagsFlag bool 45 ) 46 47 BeforeEach(func() { 48 overrider = &override.Override{} 49 50 instance = ¤t.IBPConsole{ 51 Spec: current.IBPConsoleSpec{ 52 License: current.License{ 53 Accept: true, 54 }, 55 ServiceAccountName: "test", 56 AuthScheme: "couchdb", 57 DeployerTimeout: 30000, 58 Components: "athena-components", 59 Sessions: "athena-sessions", 60 System: "athena-system", 61 ConnectionString: "test.com", 62 Service: ¤t.Service{}, 63 Email: "xyz@ibm.com", 64 PasswordSecretName: "secret", 65 Password: "cGFzc3dvcmQ=", 66 KubeconfigSecretName: "kubeconfig-secret", 67 SystemChannel: "testchainid", 68 ImagePullSecrets: []string{"testsecret"}, 69 Images: ¤t.ConsoleImages{ 70 ConsoleInitImage: "fake-init-image", 71 ConsoleInitTag: "1234", 72 CouchDBImage: "fake-couchdb-image", 73 CouchDBTag: "1234", 74 ConsoleImage: "fake-console-image", 75 ConsoleTag: "1234", 76 ConfigtxlatorImage: "fake-configtxlator-image", 77 ConfigtxlatorTag: "1234", 78 DeployerImage: "fake-deployer-image", 79 DeployerTag: "1234", 80 }, 81 RegistryURL: "ghcr.io/ibm-blockchain/", 82 NetworkInfo: ¤t.NetworkInfo{ 83 Domain: "test.domain", 84 ConsolePort: 31010, 85 ProxyPort: 31011, 86 }, 87 TLSSecretName: "secret", 88 Resources: ¤t.ConsoleResources{}, 89 Storage: ¤t.ConsoleStorage{ 90 Console: ¤t.StorageSpec{ 91 Size: "100m", 92 Class: "manual", 93 }, 94 }, 95 }, 96 } 97 deployment, err = util.GetDeploymentFromFile("../../../../../definitions/console/deployment.yaml") 98 Expect(err).NotTo(HaveOccurred()) 99 usetagsFlag = true 100 instanceWithTags = ¤t.IBPConsole{ 101 Spec: current.IBPConsoleSpec{ 102 License: current.License{ 103 Accept: true, 104 }, 105 ServiceAccountName: "test", 106 AuthScheme: "couchdb", 107 DeployerTimeout: 30000, 108 Components: "athena-components", 109 Sessions: "athena-sessions", 110 System: "athena-system", 111 ConnectionString: "test.com", 112 Service: ¤t.Service{}, 113 Email: "xyz@ibm.com", 114 PasswordSecretName: "secret", 115 Password: "cGFzc3dvcmQ=", 116 KubeconfigSecretName: "kubeconfig-secret", 117 SystemChannel: "testchainid", 118 ImagePullSecrets: []string{"testsecret"}, 119 Images: ¤t.ConsoleImages{ 120 ConsoleInitImage: "fake-init-image", 121 ConsoleInitTag: "1234", 122 CouchDBImage: "fake-couchdb-image", 123 CouchDBTag: "1234", 124 ConsoleImage: "fake-console-image", 125 ConsoleTag: "1234", 126 ConfigtxlatorImage: "fake-configtxlator-image", 127 ConfigtxlatorTag: "1234", 128 DeployerImage: "fake-deployer-image", 129 DeployerTag: "1234", 130 MustgatherImage: "fake-mustgather-image", 131 MustgatherTag: "1234", 132 }, 133 RegistryURL: "ghcr.io/ibm-blockchain/", 134 NetworkInfo: ¤t.NetworkInfo{ 135 Domain: "test.domain", 136 ConsolePort: 31010, 137 ProxyPort: 31011, 138 }, 139 TLSSecretName: "secret", 140 Resources: ¤t.ConsoleResources{}, 141 Storage: ¤t.ConsoleStorage{ 142 Console: ¤t.StorageSpec{ 143 Size: "100m", 144 Class: "manual", 145 }, 146 }, 147 UseTags: &usetagsFlag, 148 }, 149 } 150 }) 151 152 Context("create", func() { 153 It("overrides values based on spec", func() { 154 err := overrider.Deployment(instanceWithTags, deployment, resources.Create) 155 Expect(err).NotTo(HaveOccurred()) 156 157 By("setting service account name", func() { 158 Expect(deployment.Spec.Template.Spec.ServiceAccountName).To(Equal(instanceWithTags.Name)) 159 }) 160 161 By("image pull secret", func() { 162 Expect(deployment.Spec.Template.Spec.ImagePullSecrets).To(Equal([]corev1.LocalObjectReference{ 163 corev1.LocalObjectReference{ 164 Name: instanceWithTags.Spec.ImagePullSecrets[0], 165 }, 166 })) 167 }) 168 169 By("setting DEFAULT_USER_PASSWORD_INITIAL env var", func() { 170 envVar := corev1.EnvVar{ 171 Name: "DEFAULT_USER_PASSWORD_INITIAL", 172 ValueFrom: &corev1.EnvVarSource{ 173 SecretKeyRef: &corev1.SecretKeySelector{ 174 LocalObjectReference: corev1.LocalObjectReference{ 175 Name: instanceWithTags.Spec.PasswordSecretName, 176 }, 177 Key: "password", 178 }, 179 }, 180 } 181 Expect(deployment.Spec.Template.Spec.Containers[0].Env).To(ContainElement(envVar)) 182 }) 183 184 By("setting TLS volume and volume mount if TLS secret name provided in spec", func() { 185 vm := corev1.VolumeMount{ 186 Name: "tls-certs", 187 MountPath: "/certs/tls", 188 } 189 Expect(deployment.Spec.Template.Spec.Containers[0].VolumeMounts).To(ContainElement(vm)) 190 191 v := corev1.Volume{ 192 Name: "tls-certs", 193 VolumeSource: corev1.VolumeSource{ 194 Secret: &corev1.SecretVolumeSource{ 195 SecretName: instanceWithTags.Spec.TLSSecretName, 196 }, 197 }, 198 } 199 Expect(deployment.Spec.Template.Spec.Volumes).To(ContainElement(v)) 200 }) 201 202 By("setting deployer volume", func() { 203 v := corev1.Volume{ 204 Name: "deployer-template", 205 VolumeSource: corev1.VolumeSource{ 206 ConfigMap: &corev1.ConfigMapVolumeSource{ 207 LocalObjectReference: corev1.LocalObjectReference{ 208 Name: instanceWithTags.Name + "-deployer", 209 }, 210 }, 211 }, 212 } 213 Expect(deployment.Spec.Template.Spec.Volumes).To(ContainElement(v)) 214 }) 215 216 By("setting console volume", func() { 217 v := corev1.Volume{ 218 Name: "template", 219 VolumeSource: corev1.VolumeSource{ 220 ConfigMap: &corev1.ConfigMapVolumeSource{ 221 LocalObjectReference: corev1.LocalObjectReference{ 222 Name: instanceWithTags.Name + "-console", 223 }, 224 }, 225 }, 226 } 227 Expect(deployment.Spec.Template.Spec.Volumes).To(ContainElement(v)) 228 }) 229 230 By("setting affinity", func() { 231 expectedAffinity := overrider.GetAffinity(instanceWithTags) 232 Expect(deployment.Spec.Template.Spec.Affinity).To(Equal(expectedAffinity)) 233 }) 234 235 ConsoleDeploymentCommonOverrides(instanceWithTags, deployment) 236 }) 237 238 Context("using couchdb", func() { 239 BeforeEach(func() { 240 instance.Spec.ConnectionString = "localhost" 241 }) 242 243 It("overrides values based on spec", func() { 244 err := overrider.Deployment(instance, deployment, resources.Create) 245 Expect(err).NotTo(HaveOccurred()) 246 247 By("setting couchdb TLS volume and volume mount", func() { 248 vm := corev1.VolumeMount{ 249 Name: "couchdb", 250 MountPath: "/opt/couchdb/data", 251 SubPath: "data", 252 } 253 Expect(deployment.Spec.Template.Spec.Containers[3].VolumeMounts).To(ContainElement(vm)) 254 Expect(deployment.Spec.Template.Spec.InitContainers[0].VolumeMounts).To(ContainElement(vm)) 255 }) 256 257 By("setting cert volume and volume mount", func() { 258 vm := corev1.VolumeMount{ 259 Name: "couchdb", 260 MountPath: "/certs/", 261 SubPath: "tls", 262 } 263 Expect(deployment.Spec.Template.Spec.Containers[0].VolumeMounts).To(ContainElement(vm)) 264 Expect(deployment.Spec.Template.Spec.InitContainers[0].VolumeMounts).To(ContainElement(vm)) 265 }) 266 }) 267 }) 268 269 Context("not using TLS secret name", func() { 270 BeforeEach(func() { 271 instance.Spec.TLSSecretName = "" 272 }) 273 274 It("overrides values based on spec", func() { 275 vm := corev1.VolumeMount{ 276 Name: "tls-certs", 277 MountPath: "/certs/tls", 278 } 279 Expect(deployment.Spec.Template.Spec.Containers[0].VolumeMounts).NotTo(ContainElement(vm)) 280 281 v := corev1.Volume{ 282 Name: "tls-certs", 283 VolumeSource: corev1.VolumeSource{ 284 Secret: &corev1.SecretVolumeSource{ 285 SecretName: instance.Spec.TLSSecretName, 286 }, 287 }, 288 } 289 Expect(deployment.Spec.Template.Spec.Volumes).NotTo(ContainElement(v)) 290 }) 291 }) 292 }) 293 294 Context("enabling activity tracker", func() { 295 It("overrides mounts based on spec overrides", func() { 296 consoleOverride := ¤t.ConsoleOverridesConsole{ 297 ActivityTrackerConsolePath: "fake/path", 298 ActivityTrackerHostPath: "host/path", 299 } 300 consoleBytes, err := json.Marshal(consoleOverride) 301 Expect(err).NotTo(HaveOccurred()) 302 instance.Spec.ConfigOverride = ¤t.ConsoleOverrides{ 303 Console: &runtime.RawExtension{Raw: consoleBytes}, 304 } 305 306 err = overrider.Deployment(instance, deployment, resources.Create) 307 Expect(err).NotTo(HaveOccurred()) 308 vm := corev1.VolumeMount{ 309 Name: "activity", 310 MountPath: "fake/path", 311 SubPath: "", 312 } 313 Expect(deployment.Spec.Template.Spec.Containers[0].VolumeMounts).To(ContainElement(vm)) 314 hostPathType := corev1.HostPathDirectoryOrCreate 315 v := corev1.Volume{ 316 Name: "activity", 317 VolumeSource: corev1.VolumeSource{ 318 HostPath: &corev1.HostPathVolumeSource{ 319 Path: "host/path", 320 Type: &hostPathType, 321 }, 322 }, 323 } 324 Expect(deployment.Spec.Template.Spec.Volumes).To(ContainElement(v)) 325 326 By("adding to init container command", func() { 327 Expect(deployment.Spec.Template.Spec.InitContainers[0].Command).To(Equal([]string{ 328 "sh", 329 "-c", 330 "chmod -R 775 fake/path && chown -R -H 1000:1000 fake/path", 331 })) 332 }) 333 }) 334 335 It("overrides mounts based on spec overrides when only console path provided", func() { 336 consoleOverride := ¤t.ConsoleOverridesConsole{ 337 ActivityTrackerConsolePath: "fake/path", 338 } 339 consoleBytes, err := json.Marshal(consoleOverride) 340 Expect(err).NotTo(HaveOccurred()) 341 instance.Spec.ConfigOverride = ¤t.ConsoleOverrides{ 342 Console: &runtime.RawExtension{Raw: consoleBytes}, 343 } 344 345 err = overrider.Deployment(instance, deployment, resources.Create) 346 Expect(err).NotTo(HaveOccurred()) 347 vm := corev1.VolumeMount{ 348 Name: "activity", 349 MountPath: "fake/path", 350 SubPath: "", 351 } 352 Expect(deployment.Spec.Template.Spec.Containers[0].VolumeMounts).To(ContainElement(vm)) 353 hostPathType := corev1.HostPathDirectoryOrCreate 354 v := corev1.Volume{ 355 Name: "activity", 356 VolumeSource: corev1.VolumeSource{ 357 HostPath: &corev1.HostPathVolumeSource{ 358 Path: "/var/log/at", 359 Type: &hostPathType, 360 }, 361 }, 362 } 363 Expect(deployment.Spec.Template.Spec.Volumes).To(ContainElement(v)) 364 }) 365 366 It("adds command to init container command correctly when not using remote DB", func() { 367 consoleOverride := ¤t.ConsoleOverridesConsole{ 368 ActivityTrackerConsolePath: "fake/path", 369 ActivityTrackerHostPath: "host/path", 370 } 371 consoleBytes, err := json.Marshal(consoleOverride) 372 Expect(err).NotTo(HaveOccurred()) 373 instance.Spec.ConfigOverride = ¤t.ConsoleOverrides{ 374 Console: &runtime.RawExtension{Raw: consoleBytes}, 375 } 376 instance.Spec.ConnectionString = "localhost" 377 378 err = overrider.Deployment(instance, deployment, resources.Create) 379 Expect(err).NotTo(HaveOccurred()) 380 381 By("appending to init container command", func() { 382 Expect(deployment.Spec.Template.Spec.InitContainers[0].Command).To(Equal([]string{ 383 "sh", 384 "-c", 385 "chmod -R 775 /opt/couchdb/data/ && chown -R -H 5984:5984 /opt/couchdb/data/ && chmod -R 775 /certs/ && chown -R -H 1000:1000 /certs/ && chmod -R 775 fake/path && chown -R -H 1000:1000 fake/path", 386 })) 387 }) 388 }) 389 }) 390 391 // TODO:OSS 392 // as both the console and deployer defaults are blank 393 // Context("update", func() { 394 // It("doesn't overrides images and tags values, when usetags flag is not set", func() { 395 // err := overrider.Deployment(instance, deployment, resources.Update) 396 // Expect(err).NotTo(HaveOccurred()) 397 // Expect(deployment.Spec.Template.Spec.Containers[0].Image).To(ContainSubstring("ghcr.io/ibm-blockchain/fake-console-image@sha256")) 398 // Expect(deployment.Spec.Template.Spec.InitContainers[0].Image).To(ContainSubstring("ghcr.io/ibm-blockchain/fake-init-image@sha256")) 399 // Expect(deployment.Spec.Template.Spec.Containers[1].Image).To(ContainSubstring("ghcr.io/ibm-blockchain/fake-deployer-image@sha256")) 400 // Expect(deployment.Spec.Template.Spec.Containers[2].Image).To(ContainSubstring("ghcr.io/ibm-blockchain/fake-configtxlator-image@sha256")) 401 // }) 402 // }) 403 404 Context("update when usetags set", func() { 405 It("overrides values based on spec, when usetags flag is set", func() { 406 err := overrider.Deployment(instanceWithTags, deployment, resources.Update) 407 Expect(err).NotTo(HaveOccurred()) 408 ConsoleDeploymentCommonOverrides(instanceWithTags, deployment) 409 }) 410 }) 411 412 Context("Replicas", func() { 413 When("using remote db", func() { 414 It("using replica value from spec", func() { 415 replicas := int32(2) 416 instance.Spec.Replicas = &replicas 417 err := overrider.Deployment(instance, deployment, resources.Create) 418 Expect(err).NotTo(HaveOccurred()) 419 Expect(*deployment.Spec.Replicas).To(Equal(replicas)) 420 }) 421 }) 422 423 When("Replicas is greater than 1", func() { 424 BeforeEach(func() { 425 instance.Spec.ConnectionString = "localhost" 426 }) 427 428 It("returns an error", func() { 429 replicas := int32(2) 430 instance.Spec.Replicas = &replicas 431 err := overrider.Deployment(instance, deployment, resources.Create) 432 Expect(err).To(HaveOccurred()) 433 Expect(err.Error()).To(Equal("replicas > 1 not allowed in IBPConsole")) 434 }) 435 }) 436 437 When("Replicas is equal to 1", func() { 438 It("returns success", func() { 439 replicas := int32(1) 440 instance.Spec.Replicas = &replicas 441 err := overrider.Deployment(instance, deployment, resources.Create) 442 Expect(err).NotTo(HaveOccurred()) 443 }) 444 }) 445 When("Replicas is equal to 0", func() { 446 It("returns success", func() { 447 replicas := int32(0) 448 instance.Spec.Replicas = &replicas 449 err := overrider.Deployment(instance, deployment, resources.Create) 450 Expect(err).NotTo(HaveOccurred()) 451 }) 452 }) 453 When("Replicas is nil", func() { 454 It("returns success", func() { 455 instance.Spec.Replicas = nil 456 err := overrider.Deployment(instance, deployment, resources.Create) 457 Expect(err).NotTo(HaveOccurred()) 458 }) 459 }) 460 }) 461 }) 462 }) 463 464 func ConsoleDeploymentCommonOverrides(instance *current.IBPConsole, dep *appsv1.Deployment) { 465 By("setting init image", func() { 466 Expect(dep.Spec.Template.Spec.InitContainers[0].Image).To(Equal(fmt.Sprintf("%s%s:%s", instance.Spec.RegistryURL, instance.Spec.Images.ConsoleInitImage, instance.Spec.Images.ConsoleInitTag))) 467 }) 468 469 By("setting console image", func() { 470 Expect(dep.Spec.Template.Spec.Containers[0].Image).To(Equal(fmt.Sprintf("%s%s:%s", instance.Spec.RegistryURL, instance.Spec.Images.ConsoleImage, instance.Spec.Images.ConsoleTag))) 471 }) 472 473 By("setting deployer image", func() { 474 Expect(dep.Spec.Template.Spec.Containers[1].Image).To(Equal(fmt.Sprintf("%s%s:%s", instance.Spec.RegistryURL, instance.Spec.Images.DeployerImage, instance.Spec.Images.DeployerTag))) 475 }) 476 477 By("setting configtxlator image", func() { 478 Expect(dep.Spec.Template.Spec.Containers[2].Image).To(Equal(fmt.Sprintf("%s%s:%s", instance.Spec.RegistryURL, instance.Spec.Images.ConfigtxlatorImage, instance.Spec.Images.ConfigtxlatorTag))) 479 }) 480 481 By("setting replicas", func() { 482 Expect(dep.Spec.Replicas).To(Equal(instance.Spec.Replicas)) 483 }) 484 485 By("setting KUBECONFIGPATH env var", func() { 486 envVar := corev1.EnvVar{ 487 Name: "KUBECONFIGPATH", 488 Value: "/kubeconfig/kubeconfig.yaml", 489 } 490 Expect(dep.Spec.Template.Spec.Containers[1].Env).To(ContainElement(envVar)) 491 }) 492 }