github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/offering/base/ca/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 "context" 23 "encoding/json" 24 25 . "github.com/onsi/ginkgo/v2" 26 . "github.com/onsi/gomega" 27 28 appsv1 "k8s.io/api/apps/v1" 29 corev1 "k8s.io/api/core/v1" 30 "k8s.io/apimachinery/pkg/api/resource" 31 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 32 "k8s.io/apimachinery/pkg/runtime" 33 "k8s.io/apimachinery/pkg/types" 34 35 current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1" 36 "github.com/IBM-Blockchain/fabric-operator/controllers/mocks" 37 v1 "github.com/IBM-Blockchain/fabric-operator/pkg/apis/ca/v1" 38 "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/common/config" 39 "github.com/IBM-Blockchain/fabric-operator/pkg/manager/resources" 40 dep "github.com/IBM-Blockchain/fabric-operator/pkg/manager/resources/deployment" 41 "github.com/IBM-Blockchain/fabric-operator/pkg/offering/base/ca/override" 42 "github.com/IBM-Blockchain/fabric-operator/pkg/util" 43 44 "sigs.k8s.io/controller-runtime/pkg/client" 45 "sigs.k8s.io/yaml" 46 ) 47 48 var _ = Describe("Deployment Overrides", func() { 49 var ( 50 overrider *override.Override 51 instance *current.IBPCA 52 deployment *appsv1.Deployment 53 mockKubeClient *mocks.Client 54 ) 55 56 BeforeEach(func() { 57 var err error 58 59 mockKubeClient = &mocks.Client{} 60 mockKubeClient.GetStub = func(ctx context.Context, types types.NamespacedName, obj client.Object) error { 61 switch obj.(type) { 62 case *corev1.ConfigMap: 63 hsmConfig := &config.HSMConfig{ 64 Type: "hsm", 65 Version: "v1", 66 MountPaths: []config.MountPath{ 67 config.MountPath{ 68 Name: "hsmcrypto", 69 Secret: "hsmcrypto", 70 MountPath: "/hsm", 71 Paths: []config.Path{ 72 { 73 Key: "cafile.pem", 74 Path: "cafile.pem", 75 }, 76 { 77 Key: "cert.pem", 78 Path: "cert.pem", 79 }, 80 { 81 Key: "key.pem", 82 Path: "key.pem", 83 }, 84 { 85 Key: "server.pem", 86 Path: "server.pem", 87 }, 88 }, 89 }, 90 config.MountPath{ 91 Name: "hsmconfig", 92 Secret: "hsmcrypto", 93 MountPath: "/etc/Chrystoki.conf", 94 SubPath: "Chrystoki.conf", 95 Paths: []config.Path{ 96 { 97 Key: "Chrystoki.conf", 98 Path: "Chrystoki.conf", 99 }, 100 }, 101 }, 102 }, 103 Envs: []corev1.EnvVar{ 104 { 105 Name: "env1", 106 Value: "env1value", 107 }, 108 }, 109 } 110 111 configBytes, err := yaml.Marshal(hsmConfig) 112 if err != nil { 113 return err 114 } 115 o := obj.(*corev1.ConfigMap) 116 o.Data = map[string]string{"ibp-hsm-config.yaml": string(configBytes)} 117 } 118 return nil 119 } 120 121 overrider = &override.Override{ 122 Client: mockKubeClient, 123 } 124 deployment, err = util.GetDeploymentFromFile("../../../../../definitions/ca/deployment.yaml") 125 Expect(err).NotTo(HaveOccurred()) 126 deployment.Spec.Template.Spec.InitContainers[0].Image = "fake-init-image:1234" 127 deployment.Spec.Template.Spec.Containers[0].Image = "fake-ca-image:1234" 128 129 instance = ¤t.IBPCA{ 130 ObjectMeta: metav1.ObjectMeta{ 131 Name: "override1", 132 Namespace: "namespace1", 133 }, 134 Spec: current.IBPCASpec{ 135 License: current.License{ 136 Accept: true, 137 }, 138 Storage: ¤t.CAStorages{}, 139 Service: ¤t.Service{}, 140 Images: ¤t.CAImages{ 141 CAImage: "ca-image", 142 CAInitImage: "init-image", 143 }, 144 Arch: []string{"test-arch"}, 145 Zone: "dal", 146 Region: "us-south", 147 ImagePullSecrets: []string{"pullsecret"}, 148 Resources: ¤t.CAResources{ 149 CA: &corev1.ResourceRequirements{ 150 Requests: corev1.ResourceList{ 151 corev1.ResourceCPU: resource.MustParse("0.6m"), 152 corev1.ResourceMemory: resource.MustParse("0.4m"), 153 corev1.ResourceEphemeralStorage: resource.MustParse("100M"), 154 }, 155 Limits: corev1.ResourceList{ 156 corev1.ResourceCPU: resource.MustParse("0.7m"), 157 corev1.ResourceMemory: resource.MustParse("0.5m"), 158 corev1.ResourceEphemeralStorage: resource.MustParse("1G"), 159 }, 160 }, 161 }, 162 }, 163 } 164 }) 165 166 When("creating a new deployment", func() { 167 It("returns an error if license is not accepted", func() { 168 instance.Spec.License.Accept = false 169 err := overrider.Deployment(instance, deployment, resources.Create) 170 Expect(err).To(HaveOccurred()) 171 Expect(err.Error()).To(Equal("user must accept license before continuing")) 172 }) 173 174 It("overrides values in deployment based on CA's instance spec", func() { 175 err := overrider.Deployment(instance, deployment, resources.Create) 176 Expect(err).NotTo(HaveOccurred()) 177 178 By("setting service account name to be name of CA instance", func() { 179 Expect(deployment.Spec.Template.Spec.ServiceAccountName).To(Equal(instance.Name)) 180 }) 181 182 By("setting image pull secret", func() { 183 Expect(deployment.Spec.Template.Spec.ImagePullSecrets[0].Name).To(Equal(instance.Spec.ImagePullSecrets[0])) 184 }) 185 186 By("setting resources", func() { 187 updated, err := util.GetResourcePatch(&corev1.ResourceRequirements{}, instance.Spec.Resources.CA) 188 Expect(err).NotTo(HaveOccurred()) 189 Expect(deployment.Spec.Template.Spec.Containers[0].Resources).To(Equal(*updated)) 190 }) 191 192 By("setting affinity", func() { 193 affinity := corev1.Affinity{ 194 NodeAffinity: &corev1.NodeAffinity{ 195 RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ 196 NodeSelectorTerms: []corev1.NodeSelectorTerm{ 197 corev1.NodeSelectorTerm{ 198 MatchExpressions: []corev1.NodeSelectorRequirement{ 199 corev1.NodeSelectorRequirement{ 200 Key: "kubernetes.io/arch", 201 Operator: corev1.NodeSelectorOpIn, 202 Values: instance.Spec.Arch, 203 }, 204 corev1.NodeSelectorRequirement{ 205 Key: "topology.kubernetes.io/zone", 206 Operator: corev1.NodeSelectorOpIn, 207 Values: []string{instance.Spec.Zone}, 208 }, 209 corev1.NodeSelectorRequirement{ 210 Key: "topology.kubernetes.io/region", 211 Operator: corev1.NodeSelectorOpIn, 212 Values: []string{instance.Spec.Region}, 213 }, 214 }, 215 }, 216 corev1.NodeSelectorTerm{ 217 MatchExpressions: []corev1.NodeSelectorRequirement{ 218 corev1.NodeSelectorRequirement{ 219 Key: "failure-domain.beta.kubernetes.io/zone", 220 Operator: corev1.NodeSelectorOpIn, 221 Values: []string{instance.Spec.Zone}, 222 }, 223 corev1.NodeSelectorRequirement{ 224 Key: "failure-domain.beta.kubernetes.io/region", 225 Operator: corev1.NodeSelectorOpIn, 226 Values: []string{instance.Spec.Region}, 227 }, 228 }, 229 }, 230 }, 231 }, 232 }, 233 } 234 affinity.PodAntiAffinity = &corev1.PodAntiAffinity{ 235 PreferredDuringSchedulingIgnoredDuringExecution: []corev1.WeightedPodAffinityTerm{ 236 corev1.WeightedPodAffinityTerm{ 237 Weight: 100, 238 PodAffinityTerm: corev1.PodAffinityTerm{ 239 LabelSelector: &metav1.LabelSelector{ 240 MatchExpressions: []metav1.LabelSelectorRequirement{ 241 metav1.LabelSelectorRequirement{ 242 Key: "app", 243 Operator: metav1.LabelSelectorOpIn, 244 Values: []string{instance.Name}, 245 }, 246 }, 247 }, 248 TopologyKey: "topology.kubernetes.io/zone", 249 }, 250 }, 251 corev1.WeightedPodAffinityTerm{ 252 Weight: 100, 253 PodAffinityTerm: corev1.PodAffinityTerm{ 254 LabelSelector: &metav1.LabelSelector{ 255 MatchExpressions: []metav1.LabelSelectorRequirement{ 256 metav1.LabelSelectorRequirement{ 257 Key: "app", 258 Operator: metav1.LabelSelectorOpIn, 259 Values: []string{instance.Name}, 260 }, 261 }, 262 }, 263 TopologyKey: "failure-domain.beta.kubernetes.io/zone", 264 }, 265 }, 266 }, 267 } 268 Expect(*deployment.Spec.Template.Spec.Affinity).To(Equal(affinity)) 269 }) 270 271 By("volumes creating a ca crypto volume", func() { 272 volume := corev1.Volume{ 273 Name: "ca-crypto", 274 VolumeSource: corev1.VolumeSource{ 275 Secret: &corev1.SecretVolumeSource{ 276 SecretName: instance.Name + "-ca-crypto", 277 }, 278 }, 279 } 280 Expect(deployment.Spec.Template.Spec.Volumes).To(ContainElement(volume)) 281 }) 282 283 By("volumes creating a tlsca crypto volume", func() { 284 volume := corev1.Volume{ 285 Name: "tlsca-crypto", 286 VolumeSource: corev1.VolumeSource{ 287 Secret: &corev1.SecretVolumeSource{ 288 SecretName: instance.Name + "-tlsca-crypto", 289 }, 290 }, 291 } 292 Expect(deployment.Spec.Template.Spec.Volumes).To(ContainElement(volume)) 293 }) 294 295 By("volumes creating a ca config volume", func() { 296 volume := corev1.Volume{ 297 Name: "ca-config", 298 VolumeSource: corev1.VolumeSource{ 299 ConfigMap: &corev1.ConfigMapVolumeSource{ 300 LocalObjectReference: corev1.LocalObjectReference{ 301 Name: instance.Name + "-ca-config", 302 }, 303 }, 304 }, 305 } 306 Expect(deployment.Spec.Template.Spec.Volumes).To(ContainElement(volume)) 307 }) 308 309 By("volumes creating a tlsca config volume", func() { 310 volume := corev1.Volume{ 311 Name: "tlsca-config", 312 VolumeSource: corev1.VolumeSource{ 313 ConfigMap: &corev1.ConfigMapVolumeSource{ 314 LocalObjectReference: corev1.LocalObjectReference{ 315 Name: instance.Name + "-tlsca-config", 316 }, 317 }, 318 }, 319 } 320 Expect(deployment.Spec.Template.Spec.Volumes).To(ContainElement(volume)) 321 }) 322 }) 323 324 Context("images", func() { 325 When("no tag is passed", func() { 326 It("uses 'latest' for image tags", func() { 327 Expect(deployment.Spec.Template.Spec.InitContainers[0].Image).To(Equal("fake-init-image:1234")) 328 Expect(deployment.Spec.Template.Spec.Containers[0].Image).To(Equal("fake-ca-image:1234")) 329 330 err := overrider.Deployment(instance, deployment, resources.Create) 331 Expect(err).NotTo(HaveOccurred()) 332 Expect(deployment.Spec.Template.Spec.InitContainers[0].Image).To(Equal("init-image:latest")) 333 Expect(deployment.Spec.Template.Spec.Containers[0].Image).To(Equal("ca-image:latest")) 334 }) 335 }) 336 337 When("tag is passed", func() { 338 It("uses the passed in tag for image tags", func() { 339 instance.Spec.Images.CAInitTag = "2.0.0" 340 instance.Spec.Images.CATag = "1.0.0" 341 342 err := overrider.Deployment(instance, deployment, resources.Create) 343 Expect(err).NotTo(HaveOccurred()) 344 Expect(deployment.Spec.Template.Spec.InitContainers[0].Image).To(Equal("init-image:2.0.0")) 345 Expect(deployment.Spec.Template.Spec.Containers[0].Image).To(Equal("ca-image:1.0.0")) 346 }) 347 }) 348 }) 349 350 Context("database overrides", func() { 351 When("not using postgres", func() { 352 It("performs overrides", func() { 353 err := overrider.Deployment(instance, deployment, resources.Create) 354 Expect(err).NotTo(HaveOccurred()) 355 356 By("creating a PVC volume", func() { 357 volume := corev1.Volume{ 358 Name: "fabric-ca", 359 VolumeSource: corev1.VolumeSource{ 360 PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ 361 ClaimName: instance.Name + "-pvc", 362 }, 363 }, 364 } 365 Expect(deployment.Spec.Template.Spec.Volumes).To(ContainElement(volume)) 366 }) 367 368 By("creating a volume mount for both init and ca containers", func() { 369 volumeMount := corev1.VolumeMount{ 370 Name: "fabric-ca", 371 MountPath: "/data", 372 SubPath: "fabric-ca-server", 373 } 374 Expect(deployment.Spec.Template.Spec.InitContainers[0].VolumeMounts).To(ContainElement(volumeMount)) 375 Expect(deployment.Spec.Template.Spec.Containers[0].VolumeMounts).To(ContainElement(volumeMount)) 376 }) 377 }) 378 }) 379 380 When("using postgres", func() { 381 BeforeEach(func() { 382 instance.Spec.ConfigOverride = ¤t.ConfigOverride{ 383 CA: &runtime.RawExtension{}, 384 TLSCA: &runtime.RawExtension{}, 385 } 386 387 caConfig := &v1.ServerConfig{ 388 CAConfig: v1.CAConfig{ 389 DB: &v1.CAConfigDB{ 390 Type: "postgres", 391 }, 392 }, 393 } 394 395 caConfigJson, err := util.ConvertToJsonMessage(caConfig) 396 Expect(err).NotTo(HaveOccurred()) 397 instance.Spec.ConfigOverride.CA = &runtime.RawExtension{Raw: *caConfigJson} 398 }) 399 400 It("performs overrides", func() { 401 err := overrider.Deployment(instance, deployment, resources.Create) 402 Expect(err).NotTo(HaveOccurred()) 403 404 By("creating a volume mount for both init and ca containers", func() { 405 volumeMount := corev1.VolumeMount{ 406 Name: "shared", 407 MountPath: "/data", 408 } 409 Expect(deployment.Spec.Template.Spec.InitContainers[0].VolumeMounts).To(ContainElement(volumeMount)) 410 Expect(deployment.Spec.Template.Spec.Containers[0].VolumeMounts).To(ContainElement(volumeMount)) 411 }) 412 413 By("setting strategy to rolling update", func() { 414 Expect(deployment.Spec.Strategy.Type).To(Equal(appsv1.RollingUpdateDeploymentStrategyType)) 415 }) 416 }) 417 }) 418 }) 419 420 Context("replicas is greater than 1", func() { 421 BeforeEach(func() { 422 replicas := int32(2) 423 instance.Spec.Replicas = &replicas 424 }) 425 426 It("returns an error if db is not set in CA override", func() { 427 err := overrider.Deployment(instance, deployment, resources.Create) 428 Expect(err).To(HaveOccurred()) 429 Expect(err.Error()).To(Equal("Failed to provide override configuration to support greater than 1 replicas")) 430 431 }) 432 433 It("returns an error if db is set to not equal postgres in CA override", func() { 434 ca := &v1.ServerConfig{ 435 CAConfig: v1.CAConfig{ 436 DB: &v1.CAConfigDB{ 437 Type: "mysql", 438 }, 439 }, 440 } 441 caJson, err := util.ConvertToJsonMessage(ca) 442 Expect(err).NotTo(HaveOccurred()) 443 444 instance.Spec.ConfigOverride = ¤t.ConfigOverride{ 445 CA: &runtime.RawExtension{Raw: *caJson}, 446 } 447 err = overrider.Deployment(instance, deployment, resources.Create) 448 Expect(err).To(HaveOccurred()) 449 Expect(err.Error()).To(Equal("DB Type in CA config override should be `postgres` to allow replicas > 1")) 450 }) 451 452 It("returns an error if datasource is empty in CA override", func() { 453 ca := &v1.ServerConfig{ 454 CAConfig: v1.CAConfig{ 455 DB: &v1.CAConfigDB{ 456 Type: "postgres", 457 }, 458 }, 459 } 460 caJson, err := util.ConvertToJsonMessage(ca) 461 Expect(err).NotTo(HaveOccurred()) 462 463 instance.Spec.ConfigOverride = ¤t.ConfigOverride{ 464 CA: &runtime.RawExtension{Raw: *caJson}, 465 TLSCA: &runtime.RawExtension{Raw: *caJson}, 466 } 467 468 err = overrider.Deployment(instance, deployment, resources.Create) 469 Expect(err).To(HaveOccurred()) 470 Expect(err.Error()).To(Equal("Datasource in CA config override should not be empty to allow replicas > 1")) 471 }) 472 473 It("returns an error if db is not set in TLSCA override", func() { 474 ca := &v1.ServerConfig{ 475 CAConfig: v1.CAConfig{ 476 DB: &v1.CAConfigDB{ 477 Type: "postgres", 478 Datasource: "datasource", 479 }, 480 }, 481 } 482 caJson, err := util.ConvertToJsonMessage(ca) 483 Expect(err).NotTo(HaveOccurred()) 484 485 instance.Spec.ConfigOverride = ¤t.ConfigOverride{ 486 CA: &runtime.RawExtension{Raw: *caJson}, 487 } 488 489 err = overrider.Deployment(instance, deployment, resources.Create) 490 Expect(err).To(HaveOccurred()) 491 Expect(err.Error()).To(Equal("Failed to provide database configuration for TLSCA to support greater than 1 replicas")) 492 }) 493 494 It("returns an error if db is set to not equal postgres in TLSCA override", func() { 495 ca := &v1.ServerConfig{ 496 CAConfig: v1.CAConfig{ 497 DB: &v1.CAConfigDB{ 498 Type: "postgres", 499 Datasource: "fake", 500 }, 501 }, 502 } 503 caJson, err := util.ConvertToJsonMessage(ca) 504 Expect(err).NotTo(HaveOccurred()) 505 506 tlsca := &v1.ServerConfig{ 507 CAConfig: v1.CAConfig{ 508 DB: &v1.CAConfigDB{ 509 Type: "mysql", 510 }, 511 }, 512 } 513 tlscaJson, err := util.ConvertToJsonMessage(tlsca) 514 Expect(err).NotTo(HaveOccurred()) 515 516 instance.Spec.ConfigOverride = ¤t.ConfigOverride{ 517 CA: &runtime.RawExtension{Raw: *caJson}, 518 TLSCA: &runtime.RawExtension{Raw: *tlscaJson}, 519 } 520 err = overrider.Deployment(instance, deployment, resources.Create) 521 Expect(err).To(HaveOccurred()) 522 Expect(err.Error()).To(Equal("DB Type in TLSCA config override should be `postgres` to allow replicas > 1")) 523 }) 524 525 It("returns an error if datasource is empty in TLSCA override", func() { 526 ca := &v1.ServerConfig{ 527 CAConfig: v1.CAConfig{ 528 DB: &v1.CAConfigDB{ 529 Type: "postgres", 530 Datasource: "fake", 531 }, 532 }, 533 } 534 caJson, err := util.ConvertToJsonMessage(ca) 535 Expect(err).NotTo(HaveOccurred()) 536 537 tlsca := &v1.ServerConfig{ 538 CAConfig: v1.CAConfig{ 539 DB: &v1.CAConfigDB{ 540 Type: "postgres", 541 }, 542 }, 543 } 544 tlscaJson, err := util.ConvertToJsonMessage(tlsca) 545 Expect(err).NotTo(HaveOccurred()) 546 547 instance.Spec.ConfigOverride = ¤t.ConfigOverride{ 548 CA: &runtime.RawExtension{Raw: *caJson}, 549 TLSCA: &runtime.RawExtension{Raw: *tlscaJson}, 550 } 551 552 err = overrider.Deployment(instance, deployment, resources.Create) 553 Expect(err).To(HaveOccurred()) 554 Expect(err.Error()).To(Equal("Datasource in TLSCA config override should not be empty to allow replicas > 1")) 555 }) 556 557 It("returns no error if db is set to postgres", func() { 558 ca := &v1.ServerConfig{ 559 CAConfig: v1.CAConfig{ 560 DB: &v1.CAConfigDB{ 561 Type: "postgres", 562 Datasource: "fake", 563 }, 564 }, 565 } 566 caBytes, err := json.Marshal(ca) 567 Expect(err).NotTo(HaveOccurred()) 568 caJson := json.RawMessage(caBytes) 569 570 tlsca := &v1.ServerConfig{ 571 CAConfig: v1.CAConfig{ 572 DB: &v1.CAConfigDB{ 573 Type: "postgres", 574 Datasource: "fake", 575 }, 576 }, 577 } 578 tlscaBytes, err := json.Marshal(tlsca) 579 Expect(err).NotTo(HaveOccurred()) 580 tlscaJson := json.RawMessage(tlscaBytes) 581 582 instance.Spec.ConfigOverride = ¤t.ConfigOverride{ 583 CA: &runtime.RawExtension{Raw: caJson}, 584 TLSCA: &runtime.RawExtension{Raw: tlscaJson}, 585 } 586 587 err = overrider.Deployment(instance, deployment, resources.Create) 588 Expect(err).NotTo(HaveOccurred()) 589 Expect(deployment.Spec.Strategy.Type).To(Equal(appsv1.RollingUpdateDeploymentStrategyType)) 590 }) 591 }) 592 593 Context("Replicas is nil", func() { 594 It("returns success", func() { 595 instance.Spec.Replicas = nil 596 err := overrider.Deployment(instance, deployment, resources.Create) 597 Expect(err).NotTo(HaveOccurred()) 598 }) 599 }) 600 }) 601 602 When("updating a deployment", func() { 603 Context("images", func() { 604 var image *current.CAImages 605 606 BeforeEach(func() { 607 image = ¤t.CAImages{ 608 CAImage: "ca-image", 609 CAInitImage: "init-image", 610 } 611 instance.Spec.Images = image 612 }) 613 614 When("no tag is passed", func() { 615 It("uses 'latest' for image tags", func() { 616 Expect(deployment.Spec.Template.Spec.InitContainers[0].Image).To(Equal("fake-init-image:1234")) 617 Expect(deployment.Spec.Template.Spec.Containers[0].Image).To(Equal("fake-ca-image:1234")) 618 619 err := overrider.Deployment(instance, deployment, resources.Create) 620 Expect(err).NotTo(HaveOccurred()) 621 Expect(deployment.Spec.Template.Spec.InitContainers[0].Image).To(Equal("init-image:latest")) 622 Expect(deployment.Spec.Template.Spec.Containers[0].Image).To(Equal("ca-image:latest")) 623 }) 624 }) 625 626 When("tag is passed", func() { 627 It("uses the passed in tag for image tags", func() { 628 image.CATag = "1.0.0" 629 image.CAInitTag = "2.0.0" 630 631 err := overrider.Deployment(instance, deployment, resources.Update) 632 Expect(err).NotTo(HaveOccurred()) 633 Expect(deployment.Spec.Template.Spec.InitContainers[0].Image).To(Equal("init-image:2.0.0")) 634 Expect(deployment.Spec.Template.Spec.Containers[0].Image).To(Equal("ca-image:1.0.0")) 635 }) 636 }) 637 }) 638 }) 639 640 Context("replicas is greater than 1", func() { 641 BeforeEach(func() { 642 replicas := int32(2) 643 instance.Spec.Replicas = &replicas 644 }) 645 646 It("returns an error if db is not set in CA override", func() { 647 err := overrider.Deployment(instance, deployment, resources.Update) 648 Expect(err).To(HaveOccurred()) 649 Expect(err.Error()).To(Equal("Failed to provide override configuration to support greater than 1 replicas")) 650 651 }) 652 653 It("returns an error if db is set to not equal postgres in CA override", func() { 654 ca := &v1.ServerConfig{ 655 CAConfig: v1.CAConfig{ 656 DB: &v1.CAConfigDB{ 657 Type: "mysql", 658 }, 659 }, 660 } 661 caBytes, err := json.Marshal(ca) 662 Expect(err).NotTo(HaveOccurred()) 663 caJson := json.RawMessage(caBytes) 664 665 instance.Spec.ConfigOverride = ¤t.ConfigOverride{ 666 CA: &runtime.RawExtension{Raw: caJson}, 667 } 668 err = overrider.Deployment(instance, deployment, resources.Update) 669 Expect(err).To(HaveOccurred()) 670 Expect(err.Error()).To(Equal("DB Type in CA config override should be `postgres` to allow replicas > 1")) 671 }) 672 673 It("returns an error if datasource is empty in CA override", func() { 674 ca := &v1.ServerConfig{ 675 CAConfig: v1.CAConfig{ 676 DB: &v1.CAConfigDB{ 677 Type: "postgres", 678 }, 679 }, 680 } 681 caBytes, err := json.Marshal(ca) 682 Expect(err).NotTo(HaveOccurred()) 683 684 tlsca := &v1.ServerConfig{ 685 CAConfig: v1.CAConfig{ 686 DB: &v1.CAConfigDB{ 687 Type: "postgres", 688 }, 689 }, 690 } 691 tlscaBytes, err := json.Marshal(tlsca) 692 Expect(err).NotTo(HaveOccurred()) 693 694 instance.Spec.ConfigOverride = ¤t.ConfigOverride{ 695 CA: &runtime.RawExtension{Raw: caBytes}, 696 TLSCA: &runtime.RawExtension{Raw: tlscaBytes}, 697 } 698 699 err = overrider.Deployment(instance, deployment, resources.Update) 700 Expect(err).To(HaveOccurred()) 701 Expect(err.Error()).To(Equal("Datasource in CA config override should not be empty to allow replicas > 1")) 702 }) 703 704 It("returns an error if db is not set in TLSCA override", func() { 705 ca := &v1.ServerConfig{ 706 CAConfig: v1.CAConfig{ 707 DB: &v1.CAConfigDB{ 708 Type: "postgres", 709 Datasource: "datasource", 710 }, 711 }, 712 } 713 caBytes, err := json.Marshal(ca) 714 Expect(err).NotTo(HaveOccurred()) 715 716 instance.Spec.ConfigOverride = ¤t.ConfigOverride{ 717 CA: &runtime.RawExtension{Raw: caBytes}, 718 } 719 720 err = overrider.Deployment(instance, deployment, resources.Update) 721 Expect(err).To(HaveOccurred()) 722 Expect(err.Error()).To(Equal("Failed to provide database configuration for TLSCA to support greater than 1 replicas")) 723 }) 724 725 It("returns an error if db is set to not equal postgres in TLSCA override", func() { 726 ca := &v1.ServerConfig{ 727 CAConfig: v1.CAConfig{ 728 DB: &v1.CAConfigDB{ 729 Type: "postgres", 730 Datasource: "fake", 731 }, 732 }, 733 } 734 caBytes, err := json.Marshal(ca) 735 Expect(err).NotTo(HaveOccurred()) 736 737 tlsca := &v1.ServerConfig{ 738 CAConfig: v1.CAConfig{ 739 DB: &v1.CAConfigDB{ 740 Type: "mysql", 741 }, 742 }, 743 } 744 tlscaBytes, err := json.Marshal(tlsca) 745 Expect(err).NotTo(HaveOccurred()) 746 747 instance.Spec.ConfigOverride = ¤t.ConfigOverride{ 748 CA: &runtime.RawExtension{Raw: caBytes}, 749 TLSCA: &runtime.RawExtension{Raw: tlscaBytes}, 750 } 751 752 err = overrider.Deployment(instance, deployment, resources.Update) 753 Expect(err).To(HaveOccurred()) 754 Expect(err.Error()).To(Equal("DB Type in TLSCA config override should be `postgres` to allow replicas > 1")) 755 }) 756 757 It("returns an error if datasource is empty in TLSCA override", func() { 758 ca := &v1.ServerConfig{ 759 CAConfig: v1.CAConfig{ 760 DB: &v1.CAConfigDB{ 761 Type: "postgres", 762 Datasource: "fake", 763 }, 764 }, 765 } 766 caBytes, err := json.Marshal(ca) 767 Expect(err).NotTo(HaveOccurred()) 768 769 tlsca := &v1.ServerConfig{ 770 CAConfig: v1.CAConfig{ 771 DB: &v1.CAConfigDB{ 772 Type: "postgres", 773 }, 774 }, 775 } 776 tlscaBytes, err := json.Marshal(tlsca) 777 Expect(err).NotTo(HaveOccurred()) 778 779 instance.Spec.ConfigOverride = ¤t.ConfigOverride{ 780 CA: &runtime.RawExtension{Raw: caBytes}, 781 TLSCA: &runtime.RawExtension{Raw: tlscaBytes}, 782 } 783 784 err = overrider.Deployment(instance, deployment, resources.Update) 785 Expect(err).To(HaveOccurred()) 786 Expect(err.Error()).To(Equal("Datasource in TLSCA config override should not be empty to allow replicas > 1")) 787 }) 788 789 It("returns no error if db is set to postgres", func() { 790 ca := &v1.ServerConfig{ 791 CAConfig: v1.CAConfig{ 792 DB: &v1.CAConfigDB{ 793 Type: "postgres", 794 Datasource: "fake", 795 }, 796 }, 797 } 798 caJson, err := util.ConvertToJsonMessage(ca) 799 Expect(err).NotTo(HaveOccurred()) 800 801 tlsca := &v1.ServerConfig{ 802 CAConfig: v1.CAConfig{ 803 DB: &v1.CAConfigDB{ 804 Type: "postgres", 805 Datasource: "fake", 806 }, 807 }, 808 } 809 tlscaJson, err := util.ConvertToJsonMessage(tlsca) 810 Expect(err).NotTo(HaveOccurred()) 811 812 instance.Spec.ConfigOverride = ¤t.ConfigOverride{ 813 CA: &runtime.RawExtension{Raw: *caJson}, 814 TLSCA: &runtime.RawExtension{Raw: *tlscaJson}, 815 } 816 817 err = overrider.Deployment(instance, deployment, resources.Update) 818 Expect(err).NotTo(HaveOccurred()) 819 Expect(deployment.Spec.Strategy.Type).To(Equal(appsv1.RollingUpdateDeploymentStrategyType)) 820 }) 821 }) 822 823 Context("HSM", func() { 824 BeforeEach(func() { 825 ca := &v1.ServerConfig{ 826 CAConfig: v1.CAConfig{ 827 CSP: &v1.BCCSP{ 828 ProviderName: "PKCS11", 829 PKCS11: &v1.PKCS11Opts{ 830 Label: "partition1", 831 Pin: "B6T9Q7mGNG", 832 }, 833 }, 834 }, 835 } 836 caJson, err := util.ConvertToJsonMessage(ca) 837 Expect(err).NotTo(HaveOccurred()) 838 839 instance.Spec.ConfigOverride = ¤t.ConfigOverride{ 840 CA: &runtime.RawExtension{Raw: *caJson}, 841 } 842 }) 843 844 It("sets proxy env on ca container", func() { 845 instance.Spec.HSM = ¤t.HSM{PKCS11Endpoint: "1.2.3.4"} 846 err := overrider.Deployment(instance, deployment, resources.Create) 847 Expect(err).NotTo(HaveOccurred()) 848 849 d := dep.New(deployment) 850 Expect(d.MustGetContainer(override.CA).Env).To(ContainElement(corev1.EnvVar{ 851 Name: "PKCS11_PROXY_SOCKET", 852 Value: "1.2.3.4", 853 })) 854 }) 855 856 It("configures deployment to use HSM init image", func() { 857 err := overrider.Deployment(instance, deployment, resources.Create) 858 Expect(err).NotTo(HaveOccurred()) 859 860 d := dep.New(deployment) 861 By("setting volume mounts", func() { 862 Expect(d.MustGetContainer(override.CA).VolumeMounts).To(ContainElement(corev1.VolumeMount{ 863 Name: "shared", 864 MountPath: "/hsm/lib", 865 SubPath: "hsm", 866 })) 867 868 Expect(d.MustGetContainer(override.CA).VolumeMounts).To(ContainElement(corev1.VolumeMount{ 869 Name: "hsmconfig", 870 MountPath: "/etc/Chrystoki.conf", 871 SubPath: "Chrystoki.conf", 872 })) 873 }) 874 875 By("setting env vars", func() { 876 Expect(d.MustGetContainer(override.CA).Env).To(ContainElement(corev1.EnvVar{ 877 Name: "env1", 878 Value: "env1value", 879 })) 880 }) 881 882 By("creating HSM init container", func() { 883 Expect(d.ContainerExists("hsm-client")).To(Equal(true)) 884 }) 885 }) 886 }) 887 })