github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/offering/base/ca/ca_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 baseca_test 20 21 import ( 22 "context" 23 "encoding/base64" 24 "encoding/json" 25 "errors" 26 "fmt" 27 "os" 28 "path/filepath" 29 30 . "github.com/onsi/ginkgo/v2" 31 . "github.com/onsi/gomega" 32 corev1 "k8s.io/api/core/v1" 33 "k8s.io/apimachinery/pkg/runtime" 34 "k8s.io/apimachinery/pkg/types" 35 "sigs.k8s.io/controller-runtime/pkg/client" 36 "sigs.k8s.io/yaml" 37 38 current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1" 39 cmocks "github.com/IBM-Blockchain/fabric-operator/controllers/mocks" 40 config "github.com/IBM-Blockchain/fabric-operator/operatorconfig" 41 v1 "github.com/IBM-Blockchain/fabric-operator/pkg/apis/ca/v1" 42 "github.com/IBM-Blockchain/fabric-operator/pkg/apis/deployer" 43 initializer "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/ca" 44 commonconfig "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/common/config" 45 managermocks "github.com/IBM-Blockchain/fabric-operator/pkg/manager/resources/mocks" 46 baseca "github.com/IBM-Blockchain/fabric-operator/pkg/offering/base/ca" 47 "github.com/IBM-Blockchain/fabric-operator/pkg/offering/base/ca/mocks" 48 basecamocks "github.com/IBM-Blockchain/fabric-operator/pkg/offering/base/ca/mocks" 49 override "github.com/IBM-Blockchain/fabric-operator/pkg/offering/k8s/ca/override" 50 "github.com/IBM-Blockchain/fabric-operator/pkg/operatorerrors" 51 "github.com/IBM-Blockchain/fabric-operator/version" 52 ) 53 54 var _ = Describe("Base CA", func() { 55 const ( 56 defaultConfigs = "../../../../defaultconfig/ca" 57 testdataDir = "../../../../testdata" 58 59 keyBase64 = "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb2dJQkFBS0NBUUVBdFJBUDlMemUyZEc1cm1rbmcvdVVtREFZU0VwUElqRFdUUDhqUjMxcUJ5Yjc3YWUrCnk3UTRvRnZod1lDVUhsUWVTWjFKeTdUUHpEcitoUk5hdDJYNGdGYUpGYmVFbC9DSHJ3Rk1mNzNzQStWV1pHdnkKdXhtbjB2bEdYMW5zSEo5aUdIUS9qR2FvV1FJYzlVbnpHWi8yWStlZkpxOWd3cDBNemFzWWZkdXordXVBNlp4VAp5TTdDOWFlWmxYL2ZMYmVkSXVXTzVzaXhPSlZQeUVpcWpkd0RiY1AxYy9mRCtSMm1DbmM3VGovSnVLK1poTGxPCnhGcVlFRmtROHBmSi9LY1pabVF1QURZVFh6RGp6OENxcTRTRU5ySzI0b2hQQkN2SGgyanplWjhGdGR4MmpSSFQKaXdCZWZEYWlSWVBSOUM4enk4K1Z2Wmt6S0hQV3N5aENiNUMrN1FJREFRQUJBb0lCQUZROGhzL2IxdW9Mc3BFOApCdEJXaVVsTWh0K0xBc25yWXFncnd5UU5hdmlzNEdRdXVJdFk2MGRmdCtZb2hjQ2ViZ0RkbG1tWlUxdTJ6cGJtCjdEdUt5MVFaN21rV0dpLytEWUlUM3AxSHBMZ2pTRkFzRUorUFRnN1BQamc2UTZrRlZjUCt3Vm4yb0xmWVRkU28KZE5zbEdxSmNMaVQzVHRMNzhlcjFnTTE5RzN6T3J1ZndrSGJSYU1BRmtvZ1ExUlZLSWpnVGUvbmpIMHFHNW9JagoxNEJLeFFKTUZFTG1pQk50NUx5OVMxWWdxTDRjbmNtUDN5L1QyNEdodVhNckx0eTVOeVhnS0dFZ1pUTDMzZzZvCnYreDFFMFRURWRjMVQvWVBGWkdBSXhHdWRKNWZZZ2JtWU9LZ09mUHZFOE9TbEV6OW56aHNnckVZYjdQVThpZDUKTHFycVJRRUNnWUVBNjIyT3RIUmMxaVY1ZXQxdHQydTVTTTlTS2h2b0lPT3d2Q3NnTEI5dDJzNEhRUlRYN0RXcAo0VDNpUC9leEl5OXI3bTIxNFo5MEgzZlpVNElSUkdHSUxKUVMrYzRQNVA4cHJFTDcyd1dIWlpQTTM3QlZTQ1U3CkxOTXl4TkRjeVdjSUJIVFh4NUY2eXhLNVFXWTg5MVB0eDlDamJFSEcrNVJVdDA4UVlMWDlUQTBDZ1lFQXhPSmYKcXFjeThMOVZyYUFVZG9lbGdIU0NGSkJRR3hMRFNSQlJSTkRIOUJhaWlZOCtwZzd2TExTRXFMRFpsbkZPbFkrQQpiRENEQ0RtdHhwRXViY0x6b3FnOXhlQTZ0eXZZWkNWalY5dXVzNVh1Wmk1VDBBUHhCdm56OHNNa3dRY3RQWkRQCk8zQTN4WllkZzJBRmFrV1BmT1FFbjVaK3F4TU13SG9VZ1ZwQkptRUNnWUJ2Q2FjcTJVOEgrWGpJU0ROOU5TT1kKZ1ovaEdIUnRQcmFXcVVodFJ3MkxDMjFFZHM0NExEOUphdVNSQXdQYThuelhZWXROTk9XU0NmYkllaW9tdEZHRApwUHNtTXRnd1MyQ2VUS0Y0OWF5Y2JnOU0yVi8vdlAraDdxS2RUVjAwNkpGUmVNSms3K3FZYU9aVFFDTTFDN0swCmNXVUNwQ3R6Y014Y0FNQmF2THNRNlFLQmdHbXJMYmxEdjUxaXM3TmFKV0Z3Y0MwL1dzbDZvdVBFOERiNG9RV1UKSUowcXdOV2ZvZm95TGNBS3F1QjIrbkU2SXZrMmFiQ25ZTXc3V0w4b0VJa3NodUtYOVgrTVZ6Y1VPekdVdDNyaQpGeU9mcHJJRXowcm5zcWNSNUJJNUZqTGJqVFpyMEMyUWp2NW5FVFAvaHlpQWFRQ1l5THAyWlVtZ0Vjb0VPNWtwClBhcEJBb0dBZVV0WjE0SVp2cVorQnAxR1VqSG9PR0pQVnlJdzhSRUFETjRhZXRJTUlQRWFVaDdjZUtWdVN6VXMKci9WczA1Zjg0cFBVaStuUTUzaGo2ZFhhYTd1UE1aMFBnNFY4cS9UdzJMZ3BWWndVd0ltZUQrcXNsbldha3VWMQpMSnp3SkhOa3pOWE1OMmJWREFZTndSamNRSmhtbzF0V2xHYlpRQjNoSkEwR2thWGZPa2c9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==" 60 certBase64 = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURBekNDQWV1Z0F3SUJBZ0lKQU9xQ1VmaFNjcWtlTUEwR0NTcUdTSWIzRFFFQkJRVUFNQmd4RmpBVUJnTlYKQkFNTURYQnZjM1JuY21WekxuUmxjM1F3SGhjTk1Ua3dOekl6TVRrd09UVTRXaGNOTWprd056SXdNVGt3T1RVNApXakFZTVJZd0ZBWURWUVFEREExd2IzTjBaM0psY3k1MFpYTjBNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DCkFROEFNSUlCQ2dLQ0FRRUF0UkFQOUx6ZTJkRzVybWtuZy91VW1EQVlTRXBQSWpEV1RQOGpSMzFxQnliNzdhZSsKeTdRNG9Gdmh3WUNVSGxRZVNaMUp5N1RQekRyK2hSTmF0Mlg0Z0ZhSkZiZUVsL0NIcndGTWY3M3NBK1ZXWkd2eQp1eG1uMHZsR1gxbnNISjlpR0hRL2pHYW9XUUljOVVuekdaLzJZK2VmSnE5Z3dwME16YXNZZmR1eit1dUE2WnhUCnlNN0M5YWVabFgvZkxiZWRJdVdPNXNpeE9KVlB5RWlxamR3RGJjUDFjL2ZEK1IybUNuYzdUai9KdUsrWmhMbE8KeEZxWUVGa1E4cGZKL0tjWlptUXVBRFlUWHpEano4Q3FxNFNFTnJLMjRvaFBCQ3ZIaDJqemVaOEZ0ZHgyalJIVAppd0JlZkRhaVJZUFI5Qzh6eTgrVnZaa3pLSFBXc3loQ2I1Qys3UUlEQVFBQm8xQXdUakFkQmdOVkhRNEVGZ1FVCi9mZ01BcExIMXBvcFFoS25KTmgrVk04QUtQZ3dId1lEVlIwakJCZ3dGb0FVL2ZnTUFwTEgxcG9wUWhLbkpOaCsKVk04QUtQZ3dEQVlEVlIwVEJBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRVUZBQU9DQVFFQURjOUc4M05LaWw3ZQpoVFlvR1piejhFV1o4c0puVnY4azMwRDlydUY1OXFvT0ppZGorQUhNbzNHOWtud1lvbGFGbmJwb093cElOZ3g1CnYvL21aU3VldlFMZUZKRlN1UjBheVQ1WFYxcjljNUZGQ2JSaEp0cE4rOEdTT29tRUFSYTNBVGVFSG5WeVpaYkMKWkFQQUxMVXlVeUVrSDR3Q0RZUGtYa3dWQVVlR2FGVmNqZWR0eGJ3Z2k0dG0rSFZoTEt5Y0NoZ25YUVhxQ2srTwo2RHJIc0Z0STVTNWQvQlBPbE1Yc28vNUFielBGelpVVVg4OEhkVUhWSWlqM0luMXdUbWhtREtwdzZ6dmcvNjIxCjRhcGhDOWJ2bXAxeUVOUklzb0xiMGlMWVAzRSswU0ZkZC9IRnRhVXV3eUx6cnl4R2xrdG1BVUJWNVdYZEQxMkIKTU1mQnhvNFVYUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" 61 ) 62 63 AfterEach(func() { 64 err := os.RemoveAll("shared") 65 Expect(err).NotTo(HaveOccurred()) 66 }) 67 68 var ( 69 ca *baseca.CA 70 instance *current.IBPCA 71 mockKubeClient *cmocks.Client 72 73 deploymentMgr *managermocks.ResourceManager 74 serviceMgr *managermocks.ResourceManager 75 pvcMgr *managermocks.ResourceManager 76 roleMgr *managermocks.ResourceManager 77 roleBindingMgr *managermocks.ResourceManager 78 serviceAccountMgr *managermocks.ResourceManager 79 80 initMock *basecamocks.InitializeIBPCA 81 update *mocks.Update 82 restartMgr *basecamocks.RestartManager 83 certMgr *basecamocks.CertificateManager 84 ) 85 86 BeforeEach(func() { 87 mockKubeClient = &cmocks.Client{} 88 update = &mocks.Update{} 89 90 replicas := int32(1) 91 instance = ¤t.IBPCA{ 92 Status: current.IBPCAStatus{ 93 CRStatus: current.CRStatus{ 94 Version: version.Operator, 95 }, 96 }, 97 Spec: current.IBPCASpec{ 98 Domain: "domain", 99 HSM: ¤t.HSM{ 100 PKCS11Endpoint: "tcp://0.0.0.0:2345", 101 }, 102 Images: ¤t.CAImages{ 103 CAImage: "caimage", 104 CATag: "2.0.0", 105 CAInitImage: "cainitimage", 106 CAInitTag: "2.0.0", 107 }, 108 Replicas: &replicas, 109 FabricVersion: "1.4.9-0", 110 }, 111 } 112 instance.Kind = "IBPCA" 113 instance.Name = "ca1" 114 instance.Namespace = "test" 115 116 mockKubeClient.GetStub = func(ctx context.Context, types types.NamespacedName, obj client.Object) error { 117 switch obj.(type) { 118 case *corev1.Secret: 119 o := obj.(*corev1.Secret) 120 switch types.Name { 121 case instance.Name + "-ca-crypto": 122 o.Name = instance.Name + "-ca-crypto" 123 o.Namespace = instance.Namespace 124 o.Data = map[string][]byte{ 125 "tls-cert.pem": []byte(certBase64), 126 "cert.pem": []byte(certBase64), 127 "operations-cert.pem": []byte(certBase64), 128 } 129 case instance.Name + "-tlsca-crypto": 130 o.Name = instance.Name + "-tlsca-crypto" 131 o.Namespace = instance.Namespace 132 o.Data = map[string][]byte{ 133 "cert.pem": []byte(certBase64), 134 } 135 } 136 137 } 138 return nil 139 } 140 141 deploymentMgr = &managermocks.ResourceManager{} 142 serviceMgr = &managermocks.ResourceManager{} 143 pvcMgr = &managermocks.ResourceManager{} 144 roleMgr = &managermocks.ResourceManager{} 145 roleBindingMgr = &managermocks.ResourceManager{} 146 serviceAccountMgr = &managermocks.ResourceManager{} 147 initMock = &basecamocks.InitializeIBPCA{} 148 restartMgr = &basecamocks.RestartManager{} 149 certMgr = &basecamocks.CertificateManager{} 150 151 initMock.SyncDBConfigReturns(instance, nil) 152 153 config := &config.Config{ 154 CAInitConfig: &initializer.Config{ 155 CADefaultConfigPath: filepath.Join(defaultConfigs, "/ca.yaml"), 156 CAOverrideConfigPath: filepath.Join(testdataDir, "init/override.yaml"), 157 TLSCADefaultConfigPath: filepath.Join(defaultConfigs, "tlsca.yaml"), 158 TLSCAOverrideConfigPath: filepath.Join(testdataDir, "init/override.yaml"), 159 SharedPath: "shared", 160 }, 161 Operator: config.Operator{ 162 Versions: &deployer.Versions{ 163 CA: map[string]deployer.VersionCA{ 164 "1.4.9-0": { 165 Default: true, 166 Image: deployer.CAImages{ 167 CAImage: "caimage", 168 CATag: "1.4.9", 169 CAInitImage: "cainitimage", 170 CAInitTag: "1.4.9", 171 }, 172 }, 173 }, 174 }, 175 }, 176 } 177 178 deploymentMgr.ExistsReturns(true) 179 ca = &baseca.CA{ 180 DeploymentManager: deploymentMgr, 181 ServiceManager: serviceMgr, 182 PVCManager: pvcMgr, 183 RoleManager: roleMgr, 184 RoleBindingManager: roleBindingMgr, 185 ServiceAccountManager: serviceAccountMgr, 186 Client: mockKubeClient, 187 Scheme: &runtime.Scheme{}, 188 Override: &override.Override{}, 189 Config: config, 190 Initializer: initMock, 191 Restart: restartMgr, 192 CertificateManager: certMgr, 193 } 194 }) 195 196 Context("Reconciles", func() { 197 It("requeues request and returns nil if instance version is updated", func() { 198 instance.Status.CRStatus.Version = "" 199 _, err := ca.Reconcile(instance, update) 200 Expect(err).NotTo(HaveOccurred()) 201 Expect(mockKubeClient.PatchStatusCallCount()).To(Equal(1)) 202 }) 203 204 It("returns a breaking error if initialization fails", func() { 205 initMock.HandleEnrollmentCAInitReturns(nil, errors.New("failed to init")) 206 _, err := ca.Reconcile(instance, update) 207 Expect(err).To(HaveOccurred()) 208 Expect(err.Error()).To(ContainSubstring("Code: 20 - failed to initialize ca: failed to init")) 209 Expect(operatorerrors.IsBreakingError(err, "msg", nil)).NotTo(HaveOccurred()) 210 }) 211 212 It("returns an error for invalid HSM endpoint", func() { 213 instance.Spec.HSM.PKCS11Endpoint = "tcp://:2345" 214 _, err := ca.Reconcile(instance, update) 215 Expect(err).To(HaveOccurred()) 216 Expect(err.Error()).To(Equal(fmt.Sprintf("failed pre reconcile checks: invalid HSM endpoint for ca instance '%s': missing IP address", instance.Name))) 217 }) 218 219 It("returns an error domain is not set", func() { 220 instance.Spec.Domain = "" 221 _, err := ca.Reconcile(instance, update) 222 Expect(err).To(HaveOccurred()) 223 Expect(err.Error()).To(Equal(fmt.Sprintf("failed pre reconcile checks: domain not set for ca instance '%s'", instance.Name))) 224 }) 225 226 It("returns an error if pvc manager fails to reconcile", func() { 227 pvcMgr.ReconcileReturns(errors.New("failed to reconcile pvc")) 228 _, err := ca.Reconcile(instance, update) 229 Expect(err).To(HaveOccurred()) 230 Expect(err.Error()).To(Equal("failed to reconcile managers: failed PVC reconciliation: failed to reconcile pvc")) 231 }) 232 233 It("returns an error if service manager fails to reconcile", func() { 234 serviceMgr.ReconcileReturns(errors.New("failed to reconcile service")) 235 _, err := ca.Reconcile(instance, update) 236 Expect(err).To(HaveOccurred()) 237 Expect(err.Error()).To(Equal("failed to reconcile managers: failed Service reconciliation: failed to reconcile service")) 238 }) 239 240 It("returns an error if role manager fails to reconcile", func() { 241 roleMgr.ReconcileReturns(errors.New("failed to reconcile role")) 242 _, err := ca.Reconcile(instance, update) 243 Expect(err).To(HaveOccurred()) 244 Expect(err.Error()).To(ContainSubstring("failed to reconcile role")) 245 }) 246 247 It("returns an error if role binding manager fails to reconcile", func() { 248 roleBindingMgr.ReconcileReturns(errors.New("failed to reconcile role binding")) 249 _, err := ca.Reconcile(instance, update) 250 Expect(err).To(HaveOccurred()) 251 Expect(err.Error()).To(ContainSubstring("failed to reconcile role binding")) 252 }) 253 254 It("returns an error if service account manager fails to reconcile", func() { 255 serviceAccountMgr.ReconcileReturns(errors.New("failed to reconcile service account")) 256 _, err := ca.Reconcile(instance, update) 257 Expect(err).To(HaveOccurred()) 258 Expect(err.Error()).To(ContainSubstring("failed to reconcile service account")) 259 }) 260 261 It("returns an error if deployment manager fails to reconcile", func() { 262 deploymentMgr.ReconcileReturns(errors.New("failed to reconcile deployment")) 263 _, err := ca.Reconcile(instance, update) 264 Expect(err).To(HaveOccurred()) 265 Expect(err.Error()).To(Equal("failed to reconcile managers: failed Deployment reconciliation: failed to reconcile deployment")) 266 }) 267 268 It("returns an error if restart fails", func() { 269 update.RestartNeededReturns(true) 270 mockKubeClient.PatchReturns(errors.New("patch failed")) 271 _, err := ca.Reconcile(instance, update) 272 Expect(err).Should(MatchError(ContainSubstring("patch failed"))) 273 }) 274 275 It("reconciles IBPCA", func() { 276 _, err := ca.Reconcile(instance, update) 277 Expect(err).NotTo(HaveOccurred()) 278 }) 279 }) 280 281 Context("initialize", func() { 282 It("returns an error if enrollment ca init fails", func() { 283 msg := "failed to init enrollment ca" 284 initMock.HandleEnrollmentCAInitReturns(nil, errors.New(msg)) 285 err := ca.Initialize(instance, update) 286 Expect(err).To(HaveOccurred()) 287 Expect(err.Error()).To(Equal(msg)) 288 }) 289 290 It("returns an error if unable to create create config resources for enrollment ca", func() { 291 msg := "failed to create config resources for enrollment ca" 292 initMock.HandleEnrollmentCAInitReturns(&initializer.Response{}, nil) 293 initMock.HandleConfigResourcesReturns(errors.New(msg)) 294 err := ca.Initialize(instance, update) 295 Expect(err).To(HaveOccurred()) 296 Expect(err.Error()).To(Equal(msg)) 297 }) 298 299 It("returns an error if tls ca init fails", func() { 300 msg := "failed to init tls ca" 301 initMock.HandleTLSCAInitReturns(nil, errors.New(msg)) 302 err := ca.Initialize(instance, update) 303 Expect(err).To(HaveOccurred()) 304 Expect(err.Error()).To(Equal(msg)) 305 }) 306 307 It("returns an error if unable to create create config resources for tls ca", func() { 308 msg := "failed to create config resources for tls ca" 309 initMock.HandleEnrollmentCAInitReturns(&initializer.Response{Config: &v1.ServerConfig{}}, nil) 310 initMock.HandleTLSCAInitReturns(&initializer.Response{Config: &v1.ServerConfig{}}, nil) 311 initMock.HandleConfigResourcesReturnsOnCall(1, errors.New(msg)) 312 err := ca.Initialize(instance, update) 313 Expect(err).To(HaveOccurred()) 314 Expect(err.Error()).To(Equal(msg)) 315 }) 316 317 It("triggers deployment restart if deployment exists and overrides update detected", func() { 318 deploymentMgr.ExistsReturns(true) 319 update.ConfigOverridesUpdatedReturns(true) 320 321 err := ca.Initialize(instance, update) 322 Expect(err).NotTo(HaveOccurred()) 323 Expect(restartMgr.ForConfigOverrideCallCount()).To(Equal(1)) 324 }) 325 }) 326 327 Context("AddTLSCryptoIfMissing", func() { 328 It("adds tls crypto", func() { 329 mockKubeClient.GetReturns(errors.New("fake error")) 330 err := ca.AddTLSCryptoIfMissing(instance, ¤t.CAEndpoints{}) 331 Expect(err).NotTo(HaveOccurred()) 332 333 caOverrides := &v1.ServerConfig{} 334 err = json.Unmarshal(instance.Spec.ConfigOverride.CA.Raw, caOverrides) 335 Expect(err).NotTo(HaveOccurred()) 336 337 Expect(caOverrides.TLS.CertFile).NotTo(Equal("")) 338 Expect(caOverrides.TLS.KeyFile).NotTo(Equal("")) 339 }) 340 }) 341 342 Context("image overrides", func() { 343 var images *current.CAImages 344 345 Context("using registry url", func() { 346 BeforeEach(func() { 347 images = ¤t.CAImages{ 348 CAImage: "caimage", 349 CATag: "2.0.0", 350 CAInitImage: "cainitimage", 351 CAInitTag: "2.0.0", 352 } 353 }) 354 355 It("overrides images based with registry url and does not append more value on each call", func() { 356 images.Override(images, "ghcr.io/ibm-blockchain/", "amd64") 357 Expect(images.CAImage).To(Equal("ghcr.io/ibm-blockchain/caimage")) 358 Expect(images.CATag).To(Equal("2.0.0")) 359 Expect(images.CAInitImage).To(Equal("ghcr.io/ibm-blockchain/cainitimage")) 360 Expect(images.CAInitTag).To(Equal("2.0.0")) 361 }) 362 363 It("overrides images based with registry url and does not append more value on each call", func() { 364 images.Override(images, "ghcr.io/ibm-blockchain/images/", "s390x") 365 Expect(images.CAImage).To(Equal("ghcr.io/ibm-blockchain/images/caimage")) 366 Expect(images.CATag).To(Equal("2.0.0")) 367 Expect(images.CAInitImage).To(Equal("ghcr.io/ibm-blockchain/images/cainitimage")) 368 Expect(images.CAInitTag).To(Equal("2.0.0")) 369 370 }) 371 }) 372 373 Context("using fully qualified path", func() { 374 BeforeEach(func() { 375 images = ¤t.CAImages{ 376 CAImage: "ghcr.io/ibm-blockchain/caimage", 377 CATag: "2.0.0", 378 CAInitImage: "ghcr.io/ibm-blockchain/cainitimage", 379 CAInitTag: "2.0.0", 380 } 381 }) 382 383 It("keeps images and adds arch to tag", func() { 384 images.Override(images, "", "s390") 385 Expect(images.CAImage).To(Equal("ghcr.io/ibm-blockchain/caimage")) 386 Expect(images.CATag).To(Equal("2.0.0")) 387 Expect(images.CAInitImage).To(Equal("ghcr.io/ibm-blockchain/cainitimage")) 388 Expect(images.CAInitTag).To(Equal("2.0.0")) 389 }) 390 }) 391 }) 392 393 Context("pre reconcile checks", func() { 394 Context("version and images", func() { 395 Context("create CR", func() { 396 It("returns an error if fabric version is not set in spec", func() { 397 instance.Spec.FabricVersion = "" 398 _, err := ca.PreReconcileChecks(instance, update) 399 Expect(err).To(MatchError(ContainSubstring("fabric version is not set"))) 400 }) 401 402 Context("images section blank", func() { 403 BeforeEach(func() { 404 instance.Spec.Images = nil 405 }) 406 407 It("normalizes fabric version and requests a requeue", func() { 408 instance.Spec.FabricVersion = "1.4.9" 409 requeue, err := ca.PreReconcileChecks(instance, update) 410 Expect(err).NotTo(HaveOccurred()) 411 Expect(requeue).To(Equal(true)) 412 Expect(instance.Spec.FabricVersion).To(Equal("1.4.9-0")) 413 }) 414 415 It("returns an error if fabric version not supported", func() { 416 instance.Spec.FabricVersion = "0.0.1" 417 _, err := ca.PreReconcileChecks(instance, update) 418 Expect(err).To(MatchError(ContainSubstring("fabric version '0.0.1' is not supported"))) 419 }) 420 421 When("version is passed without hyphen", func() { 422 BeforeEach(func() { 423 instance.Spec.FabricVersion = "1.4.9" 424 }) 425 426 It("finds default version for release and updates images section", func() { 427 requeue, err := ca.PreReconcileChecks(instance, update) 428 Expect(err).NotTo(HaveOccurred()) 429 Expect(requeue).To(Equal(true)) 430 Expect(*instance.Spec.Images).To(Equal(current.CAImages{ 431 CAImage: "caimage", 432 CATag: "1.4.9", 433 CAInitImage: "cainitimage", 434 CAInitTag: "1.4.9", 435 })) 436 }) 437 }) 438 439 When("version is passed with hyphen", func() { 440 BeforeEach(func() { 441 instance.Spec.FabricVersion = "1.4.9-0" 442 }) 443 444 It("looks images and updates images section", func() { 445 requeue, err := ca.PreReconcileChecks(instance, update) 446 Expect(err).NotTo(HaveOccurred()) 447 Expect(requeue).To(Equal(true)) 448 Expect(*instance.Spec.Images).To(Equal(current.CAImages{ 449 CAImage: "caimage", 450 CATag: "1.4.9", 451 CAInitImage: "cainitimage", 452 CAInitTag: "1.4.9", 453 })) 454 }) 455 }) 456 }) 457 458 Context("images section passed", func() { 459 BeforeEach(func() { 460 instance.Spec.Images = ¤t.CAImages{ 461 CAImage: "ghcr.io/ibm-blockchain/caimage", 462 CATag: "2.0.0", 463 CAInitImage: "ghcr.io/ibm-blockchain/cainitimage", 464 CAInitTag: "2.0.0", 465 } 466 }) 467 468 When("version is not passed", func() { 469 BeforeEach(func() { 470 instance.Spec.FabricVersion = "" 471 }) 472 473 It("returns an error", func() { 474 _, err := ca.PreReconcileChecks(instance, update) 475 Expect(err).To(MatchError(ContainSubstring("fabric version is not set"))) 476 }) 477 }) 478 479 When("version is passed", func() { 480 BeforeEach(func() { 481 instance.Spec.FabricVersion = "2.0.0-8" 482 }) 483 484 It("persists current spec configuration", func() { 485 requeue, err := ca.PreReconcileChecks(instance, update) 486 Expect(err).NotTo(HaveOccurred()) 487 Expect(requeue).To(Equal(false)) 488 Expect(instance.Spec.FabricVersion).To(Equal("2.0.0-8")) 489 Expect(*instance.Spec.Images).To(Equal(current.CAImages{ 490 CAImage: "ghcr.io/ibm-blockchain/caimage", 491 CATag: "2.0.0", 492 CAInitImage: "ghcr.io/ibm-blockchain/cainitimage", 493 CAInitTag: "2.0.0", 494 })) 495 }) 496 }) 497 }) 498 }) 499 500 Context("update CR", func() { 501 BeforeEach(func() { 502 instance.Spec.FabricVersion = "2.0.1-0" 503 instance.Spec.Images = ¤t.CAImages{ 504 CAImage: "ghcr.io/ibm-blockchain/caimage", 505 CATag: "2.0.1", 506 CAInitImage: "ghcr.io/ibm-blockchain/cainitimage", 507 CAInitTag: "2.0.1", 508 } 509 }) 510 511 When("images updated", func() { 512 BeforeEach(func() { 513 update.ImagesUpdatedReturns(true) 514 instance.Spec.Images = ¤t.CAImages{ 515 CAImage: "ghcr.io/ibm-blockchain/caimage", 516 CATag: "2.0.8", 517 CAInitImage: "ghcr.io/ibm-blockchain/cainitimage", 518 CAInitTag: "2.0.8", 519 } 520 }) 521 522 Context("and version updated", func() { 523 BeforeEach(func() { 524 update.FabricVersionUpdatedReturns(true) 525 instance.Spec.FabricVersion = "2.0.1-8" 526 }) 527 528 It("persists current spec configuration", func() { 529 requeue, err := ca.PreReconcileChecks(instance, update) 530 Expect(err).NotTo(HaveOccurred()) 531 Expect(requeue).To(Equal(false)) 532 Expect(instance.Spec.FabricVersion).To(Equal("2.0.1-8")) 533 Expect(*instance.Spec.Images).To(Equal(current.CAImages{ 534 CAImage: "ghcr.io/ibm-blockchain/caimage", 535 CATag: "2.0.8", 536 CAInitImage: "ghcr.io/ibm-blockchain/cainitimage", 537 CAInitTag: "2.0.8", 538 })) 539 }) 540 }) 541 542 Context("and version not updated", func() { 543 It("persists current spec configuration", func() { 544 requeue, err := ca.PreReconcileChecks(instance, update) 545 Expect(err).NotTo(HaveOccurred()) 546 Expect(requeue).To(Equal(false)) 547 Expect(instance.Spec.FabricVersion).To(Equal("2.0.1-0")) 548 Expect(*instance.Spec.Images).To(Equal(current.CAImages{ 549 CAImage: "ghcr.io/ibm-blockchain/caimage", 550 CATag: "2.0.8", 551 CAInitImage: "ghcr.io/ibm-blockchain/cainitimage", 552 CAInitTag: "2.0.8", 553 })) 554 }) 555 }) 556 }) 557 558 When("images not updated", func() { 559 Context("and version updated during operator migration", func() { 560 BeforeEach(func() { 561 update.FabricVersionUpdatedReturns(true) 562 instance.Spec.FabricVersion = "unsupported" 563 }) 564 565 It("persists current spec configuration", func() { 566 requeue, err := ca.PreReconcileChecks(instance, update) 567 Expect(err).NotTo(HaveOccurred()) 568 Expect(requeue).To(Equal(false)) 569 Expect(instance.Spec.FabricVersion).To(Equal("unsupported")) 570 Expect(*instance.Spec.Images).To(Equal(current.CAImages{ 571 CAImage: "ghcr.io/ibm-blockchain/caimage", 572 CATag: "2.0.1", 573 CAInitImage: "ghcr.io/ibm-blockchain/cainitimage", 574 CAInitTag: "2.0.1", 575 })) 576 }) 577 }) 578 579 Context("and version updated (not during operator migration)", func() { 580 BeforeEach(func() { 581 update.FabricVersionUpdatedReturns(true) 582 }) 583 584 When("using non-hyphenated version", func() { 585 BeforeEach(func() { 586 instance.Spec.FabricVersion = "1.4.9" 587 }) 588 589 It("looks images and updates images section", func() { 590 requeue, err := ca.PreReconcileChecks(instance, update) 591 Expect(err).NotTo(HaveOccurred()) 592 Expect(requeue).To(Equal(true)) 593 Expect(instance.Spec.FabricVersion).To(Equal("1.4.9-0")) 594 Expect(*instance.Spec.Images).To(Equal(current.CAImages{ 595 CAImage: "caimage", 596 CATag: "1.4.9", 597 CAInitImage: "cainitimage", 598 CAInitTag: "1.4.9", 599 })) 600 }) 601 }) 602 603 When("using hyphenated version", func() { 604 BeforeEach(func() { 605 instance.Spec.FabricVersion = "1.4.9-0" 606 }) 607 608 It("looks images and updates images section", func() { 609 requeue, err := ca.PreReconcileChecks(instance, update) 610 Expect(err).NotTo(HaveOccurred()) 611 Expect(requeue).To(Equal(true)) 612 Expect(instance.Spec.FabricVersion).To(Equal("1.4.9-0")) 613 Expect(*instance.Spec.Images).To(Equal(current.CAImages{ 614 CAImage: "caimage", 615 CATag: "1.4.9", 616 CAInitImage: "cainitimage", 617 CAInitTag: "1.4.9", 618 })) 619 }) 620 }) 621 }) 622 }) 623 }) 624 }) 625 626 Context("hsm image updates", func() { 627 var ( 628 hsmConfig = &commonconfig.HSMConfig{ 629 Library: commonconfig.Library{ 630 Image: "ghcr.io/ibm-blockchain/hsmimage:1.0.0", 631 }, 632 } 633 ) 634 635 BeforeEach(func() { 636 mockKubeClient.GetStub = func(ctx context.Context, types types.NamespacedName, obj client.Object) error { 637 switch obj.(type) { 638 case *corev1.ConfigMap: 639 o := obj.(*corev1.ConfigMap) 640 641 bytes, err := yaml.Marshal(hsmConfig) 642 Expect(err).NotTo(HaveOccurred()) 643 644 o.Data = map[string]string{ 645 "ibp-hsm-config.yaml": string(bytes), 646 } 647 } 648 return nil 649 } 650 }) 651 652 It("updates hsm image and tag if passed through operator config", func() { 653 updated, err := ca.PreReconcileChecks(instance, update) 654 Expect(err).NotTo(HaveOccurred()) 655 Expect(updated).To(Equal(true)) 656 Expect(instance.Spec.Images.HSMImage).To(Equal("ghcr.io/ibm-blockchain/hsmimage")) 657 Expect(instance.Spec.Images.HSMTag).To(Equal("1.0.0")) 658 }) 659 660 It("doesn't update hsm image and tag if hsm update is disabled", func() { 661 hsmConfig.Library.AutoUpdateDisabled = true 662 663 updated, err := ca.PreReconcileChecks(instance, update) 664 Expect(err).NotTo(HaveOccurred()) 665 Expect(updated).To(Equal(false)) 666 Expect(instance.Spec.Images.HSMImage).To(Equal("")) 667 Expect(instance.Spec.Images.HSMTag).To(Equal("")) 668 }) 669 }) 670 }) 671 672 Context("update connection profile", func() { 673 It("returns error if fails to get cert", func() { 674 mockKubeClient.GetReturns(errors.New("get error")) 675 err := ca.UpdateConnectionProfile(instance) 676 Expect(err).To(HaveOccurred()) 677 Expect(err.Error()).To(ContainSubstring("get error")) 678 }) 679 680 It("updates connection profile cm", func() { 681 err := ca.UpdateConnectionProfile(instance) 682 Expect(err).NotTo(HaveOccurred()) 683 Expect(mockKubeClient.GetCallCount()).To(Equal(3)) 684 685 _, obj, _ := mockKubeClient.UpdateArgsForCall(0) 686 configmap := obj.(*corev1.ConfigMap) 687 connectionprofile := ¤t.CAConnectionProfile{} 688 err = json.Unmarshal(configmap.BinaryData["profile.json"], connectionprofile) 689 Expect(err).NotTo(HaveOccurred()) 690 691 certEncoded := base64.StdEncoding.EncodeToString([]byte(certBase64)) 692 Expect(connectionprofile.TLS.Cert).To(Equal(certEncoded)) 693 Expect(connectionprofile.CA.SignCerts).To(Equal(certEncoded)) 694 Expect(connectionprofile.TLSCA.SignCerts).To(Equal(certEncoded)) 695 }) 696 }) 697 })