github.com/IBM-Blockchain/fabric-operator@v1.0.4/integration/actions/peer/peer_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 peer_test 20 21 import ( 22 "bytes" 23 "context" 24 "encoding/base64" 25 "encoding/json" 26 "fmt" 27 28 . "github.com/onsi/ginkgo/v2" 29 . "github.com/onsi/gomega" 30 "sigs.k8s.io/controller-runtime/pkg/client" 31 32 current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1" 33 "github.com/IBM-Blockchain/fabric-operator/integration" 34 "github.com/IBM-Blockchain/fabric-operator/integration/helper" 35 "github.com/IBM-Blockchain/fabric-operator/pkg/offering/common" 36 37 k8serrors "k8s.io/apimachinery/pkg/api/errors" 38 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 39 ) 40 41 var _ = Describe("trigger peer actions", func() { 42 AfterEach(func() { 43 // Set flag if a test falls 44 if CurrentGinkgoTestDescription().Failed { 45 testFailed = true 46 } 47 }) 48 49 var ( 50 podName string 51 ibppeer *current.IBPPeer 52 ) 53 54 BeforeEach(func() { 55 Eventually(func() int { return len(org1peer.GetRunningPods()) }).Should(Equal(1)) 56 podName = org1peer.GetRunningPods()[0].Name 57 58 integration.ClearOperatorConfig(kclient, namespace) 59 }) 60 61 When("spec has restart flag set to true", func() { 62 It("performs restart action", func() { 63 patch := func(o client.Object) { 64 ibppeer = o.(*current.IBPPeer) 65 ibppeer.Spec.Action.Restart = true 66 } 67 68 err := integration.ResilientPatch(ibpCRClient, org1peer.Name, namespace, IBPPEERS, 3, ¤t.IBPPeer{}, patch) 69 Expect(err).NotTo(HaveOccurred()) 70 71 Eventually(org1peer.PodIsRunning).Should((Equal(true))) 72 73 By("restarting peer pods", func() { 74 Eventually(func() bool { 75 pods := org1peer.GetRunningPods() 76 if len(pods) == 0 { 77 return false 78 } 79 80 newPodName := pods[0].Name 81 if newPodName != podName { 82 return true 83 } 84 85 return false 86 }).Should(Equal(true)) 87 }) 88 89 By("setting restart flag back to false after restart", func() { 90 Eventually(func() bool { 91 result := ibpCRClient.Get().Namespace(namespace).Resource(IBPPEERS).Name(org1peer.Name).Do(context.TODO()) 92 ibppeer := ¤t.IBPPeer{} 93 result.Into(ibppeer) 94 95 return ibppeer.Spec.Action.Restart 96 }).Should(Equal(false)) 97 }) 98 }) 99 }) 100 101 When("spec has ecert reenroll flag set to true", func() { 102 var ( 103 ecert, ekey []byte 104 105 commonAssertions = func() { 106 By("restarting peer pods", func() { 107 Eventually(func() bool { 108 pods := org1peer.GetRunningPods() 109 if len(pods) == 0 { 110 return false 111 } 112 113 newPodName := pods[0].Name 114 if newPodName != podName { 115 return true 116 } 117 118 return false 119 }).Should(Equal(true)) 120 }) 121 122 By("backing up old signcert", func() { 123 backup := GetBackup("ecert", org1peer.Name) 124 Expect(len(backup.List)).NotTo(Equal(0)) 125 Expect(backup.List[len(backup.List)-1].SignCerts).To(Equal(base64.StdEncoding.EncodeToString(ecert))) 126 }) 127 128 By("updating ecert signcert secret", func() { 129 updatedEcertSecret, err := kclient.CoreV1().Secrets(namespace).Get(context.TODO(), fmt.Sprintf("ecert-%s-signcert", org1peer.Name), metav1.GetOptions{}) 130 Expect(err).NotTo(HaveOccurred()) 131 132 Expect(bytes.Equal(ecert, updatedEcertSecret.Data["cert.pem"])).To(Equal(false)) 133 }) 134 } 135 ) 136 137 BeforeEach(func() { 138 ecertSecret, err := kclient.CoreV1().Secrets(namespace). 139 Get(context.TODO(), fmt.Sprintf("ecert-%s-signcert", org1peer.Name), metav1.GetOptions{}) 140 Expect(err).NotTo(HaveOccurred()) 141 ecert = ecertSecret.Data["cert.pem"] 142 143 ecertSecret, err = kclient.CoreV1().Secrets(namespace). 144 Get(context.TODO(), fmt.Sprintf("ecert-%s-keystore", org1peer.Name), metav1.GetOptions{}) 145 Expect(err).NotTo(HaveOccurred()) 146 ekey = ecertSecret.Data["key.pem"] 147 }) 148 149 It("gets a new certificate and key", func() { 150 patch := func(o client.Object) { 151 ibppeer = o.(*current.IBPPeer) 152 ibppeer.Spec.Action.Reenroll.EcertNewKey = true 153 } 154 155 err := integration.ResilientPatch( 156 ibpCRClient, 157 org1peer.Name, 158 namespace, 159 IBPPEERS, 160 3, 161 ¤t.IBPPeer{}, 162 patch) 163 Expect(err).NotTo(HaveOccurred()) 164 165 commonAssertions() 166 167 By("generating a new key", func() { 168 updatedEcertKey, err := kclient.CoreV1().Secrets(namespace). 169 Get(context.TODO(), fmt.Sprintf("ecert-%s-keystore", org1peer.Name), metav1.GetOptions{}) 170 Expect(err).NotTo(HaveOccurred()) 171 Expect(bytes.Equal(ekey, updatedEcertKey.Data["key.pem"])).To(Equal(false)) 172 }) 173 174 By("setting reenroll flag back to false after restart", func() { 175 ibppeer := ¤t.IBPPeer{} 176 Eventually(func() bool { 177 result := ibpCRClient.Get().Namespace(namespace).Resource(IBPPEERS).Name(org1peer.Name).Do(context.TODO()) 178 result.Into(ibppeer) 179 180 return ibppeer.Spec.Action.Reenroll.EcertNewKey 181 }).Should(Equal(false)) 182 }) 183 }) 184 185 It("gets a new certificate", func() { 186 patch := func(o client.Object) { 187 ibppeer = o.(*current.IBPPeer) 188 ibppeer.Spec.Action.Reenroll.Ecert = true 189 } 190 191 err := integration.ResilientPatch( 192 ibpCRClient, 193 org1peer.Name, 194 namespace, 195 IBPPEERS, 196 3, 197 ¤t.IBPPeer{}, 198 patch) 199 Expect(err).NotTo(HaveOccurred()) 200 201 commonAssertions() 202 203 By("not generating a new key", func() { 204 updatedEcertKey, err := kclient.CoreV1().Secrets(namespace). 205 Get(context.TODO(), fmt.Sprintf("ecert-%s-keystore", org1peer.Name), metav1.GetOptions{}) 206 Expect(err).NotTo(HaveOccurred()) 207 Expect(bytes.Equal(ekey, updatedEcertKey.Data["key.pem"])).To(Equal(true)) 208 }) 209 210 By("setting reenroll flag back to false after restart", func() { 211 ibppeer := ¤t.IBPPeer{} 212 Eventually(func() bool { 213 result := ibpCRClient.Get().Namespace(namespace).Resource(IBPPEERS).Name(org1peer.Name).Do(context.TODO()) 214 result.Into(ibppeer) 215 216 return ibppeer.Spec.Action.Reenroll.Ecert 217 }).Should(Equal(false)) 218 }) 219 }) 220 }) 221 222 When("spec has TLS reenroll flag set to true", func() { 223 var ( 224 cert, key []byte 225 226 commonAssertions = func() { 227 By("restarting peer pods", func() { 228 Eventually(func() bool { 229 pods := org1peer.GetRunningPods() 230 if len(pods) == 0 { 231 return false 232 } 233 234 newPodName := pods[0].Name 235 if newPodName != podName { 236 return true 237 } 238 239 return false 240 }).Should(Equal(true)) 241 }) 242 243 By("backing up old signcert", func() { 244 backup := GetBackup("tls", org1peer.Name) 245 Expect(len(backup.List)).NotTo(Equal(0)) 246 Expect(backup.List[len(backup.List)-1].SignCerts).To(Equal(base64.StdEncoding.EncodeToString(cert))) 247 }) 248 249 By("updating tls signcert secret", func() { 250 updatedTLSSecret, err := kclient.CoreV1().Secrets(namespace).Get(context.TODO(), fmt.Sprintf("tls-%s-signcert", org1peer.Name), metav1.GetOptions{}) 251 Expect(err).NotTo(HaveOccurred()) 252 253 Expect(bytes.Equal(cert, updatedTLSSecret.Data["cert.pem"])).To(Equal(false)) 254 }) 255 } 256 ) 257 258 BeforeEach(func() { 259 tlsSecret, err := kclient.CoreV1().Secrets(namespace). 260 Get(context.TODO(), fmt.Sprintf("tls-%s-signcert", org1peer.Name), metav1.GetOptions{}) 261 Expect(err).NotTo(HaveOccurred()) 262 cert = tlsSecret.Data["cert.pem"] 263 264 tlsSecret, err = kclient.CoreV1().Secrets(namespace). 265 Get(context.TODO(), fmt.Sprintf("tls-%s-keystore", org1peer.Name), metav1.GetOptions{}) 266 Expect(err).NotTo(HaveOccurred()) 267 key = tlsSecret.Data["key.pem"] 268 }) 269 270 When("requesting a new key", func() { 271 It("gets a new key and certificate", func() { 272 patch := func(o client.Object) { 273 ibppeer = o.(*current.IBPPeer) 274 ibppeer.Spec.Action.Reenroll.TLSCertNewKey = true 275 } 276 277 err := integration.ResilientPatch( 278 ibpCRClient, 279 org1peer.Name, 280 namespace, 281 IBPPEERS, 282 3, 283 ¤t.IBPPeer{}, 284 patch) 285 Expect(err).NotTo(HaveOccurred()) 286 287 commonAssertions() 288 289 By("generating a new key", func() { 290 updatedKey, err := kclient.CoreV1().Secrets(namespace). 291 Get(context.TODO(), fmt.Sprintf("tls-%s-keystore", org1peer.Name), metav1.GetOptions{}) 292 Expect(err).NotTo(HaveOccurred()) 293 294 Expect(bytes.Equal(key, updatedKey.Data["key.pem"])).To(Equal(false)) 295 }) 296 297 By("setting reenroll flag back to false after restart", func() { 298 Eventually(func() bool { 299 result := ibpCRClient.Get().Namespace(namespace).Resource(IBPPEERS).Name(org1peer.Name).Do(context.TODO()) 300 ibppeer := ¤t.IBPPeer{} 301 result.Into(ibppeer) 302 303 return ibppeer.Spec.Action.Reenroll.TLSCertNewKey 304 }).Should(Equal(false)) 305 }) 306 }) 307 }) 308 309 When("reusing existing key", func() { 310 It("gets a new certificate", func() { 311 patch := func(o client.Object) { 312 ibppeer = o.(*current.IBPPeer) 313 ibppeer.Spec.Action.Reenroll.TLSCert = true 314 } 315 316 err := integration.ResilientPatch( 317 ibpCRClient, 318 org1peer.Name, 319 namespace, 320 IBPPEERS, 321 3, 322 ¤t.IBPPeer{}, 323 patch) 324 Expect(err).NotTo(HaveOccurred()) 325 326 commonAssertions() 327 328 By("not generating a new key", func() { 329 updatedKey, err := kclient.CoreV1().Secrets(namespace). 330 Get(context.TODO(), fmt.Sprintf("tls-%s-keystore", org1peer.Name), metav1.GetOptions{}) 331 Expect(err).NotTo(HaveOccurred()) 332 Expect(bytes.Equal(key, updatedKey.Data["key.pem"])).To(Equal(true)) 333 }) 334 335 By("setting reenroll flag back to false after restart", func() { 336 Eventually(func() bool { 337 result := ibpCRClient.Get().Namespace(namespace).Resource(IBPPEERS).Name(org1peer.Name).Do(context.TODO()) 338 ibppeer := ¤t.IBPPeer{} 339 result.Into(ibppeer) 340 341 return ibppeer.Spec.Action.Reenroll.TLSCert 342 }).Should(Equal(false)) 343 }) 344 }) 345 }) 346 }) 347 348 When("spec has ecert enroll flag set to true", func() { 349 var ( 350 ecert []byte 351 ecertKey []byte 352 ) 353 354 BeforeEach(func() { 355 ecertSecret, err := kclient.CoreV1(). 356 Secrets(namespace). 357 Get(context.TODO(), fmt.Sprintf("ecert-%s-signcert", org1peer.Name), metav1.GetOptions{}) 358 Expect(err).NotTo(HaveOccurred()) 359 360 ecertKeySecret, err := kclient.CoreV1(). 361 Secrets(namespace). 362 Get(context.TODO(), fmt.Sprintf("ecert-%s-keystore", org1peer.Name), metav1.GetOptions{}) 363 Expect(err).NotTo(HaveOccurred()) 364 365 ecert = ecertSecret.Data["cert.pem"] 366 ecertKey = ecertKeySecret.Data["key.pem"] 367 }) 368 369 It("generates new crypto", func() { 370 patch := func(o client.Object) { 371 ibppeer = o.(*current.IBPPeer) 372 ibppeer.Spec.Action.Enroll.Ecert = true 373 } 374 375 err := integration.ResilientPatch(ibpCRClient, org1peer.Name, namespace, IBPPEERS, 3, ¤t.IBPPeer{}, patch) 376 Expect(err).NotTo(HaveOccurred()) 377 378 By("backing up old crypto", func() { 379 Eventually(func() bool { 380 backup := GetBackup("ecert", org1peer.Name) 381 if len(backup.List) == 0 { 382 return false 383 } 384 385 return backup.List[len(backup.List)-1].SignCerts == base64.StdEncoding.EncodeToString(ecert) && 386 backup.List[len(backup.List)-1].KeyStore == base64.StdEncoding.EncodeToString(ecertKey) 387 }).Should(Equal(true)) 388 }) 389 390 By("updating ecert signcert secret", func() { 391 Eventually(func() bool { 392 updatedEcertSecret, err := kclient.CoreV1(). 393 Secrets(namespace). 394 Get(context.TODO(), fmt.Sprintf("ecert-%s-signcert", org1peer.Name), metav1.GetOptions{}) 395 Expect(err).NotTo(HaveOccurred()) 396 397 return bytes.Equal(ecert, updatedEcertSecret.Data["cert.pem"]) 398 }).Should(Equal(false)) 399 }) 400 401 By("updating ecert key secret", func() { 402 Eventually(func() bool { 403 updatedEcertSecret, err := kclient.CoreV1(). 404 Secrets(namespace). 405 Get(context.TODO(), fmt.Sprintf("ecert-%s-keystore", org1peer.Name), metav1.GetOptions{}) 406 Expect(err).NotTo(HaveOccurred()) 407 408 return bytes.Equal(ecertKey, updatedEcertSecret.Data["key.pem"]) 409 }).Should(Equal(false)) 410 }) 411 412 By("setting ecert action flag back to false in spec after completion", func() { 413 Eventually(func() bool { 414 result := ibpCRClient.Get().Namespace(namespace). 415 Resource(IBPPEERS). 416 Name(org1peer.Name). 417 Do(context.TODO()) 418 ibppeer := ¤t.IBPPeer{} 419 result.Into(ibppeer) 420 421 return ibppeer.Spec.Action.Enroll.Ecert 422 }).Should(Equal(false)) 423 }) 424 }) 425 }) 426 427 When("spec has tls enroll flag set to true", func() { 428 var ( 429 tlscert []byte 430 tlskey []byte 431 ) 432 433 BeforeEach(func() { 434 tlscertSecret, err := kclient.CoreV1(). 435 Secrets(namespace). 436 Get(context.TODO(), fmt.Sprintf("tls-%s-signcert", org1peer.Name), metav1.GetOptions{}) 437 Expect(err).NotTo(HaveOccurred()) 438 439 tlskeySecret, err := kclient.CoreV1(). 440 Secrets(namespace). 441 Get(context.TODO(), fmt.Sprintf("tls-%s-keystore", org1peer.Name), metav1.GetOptions{}) 442 Expect(err).NotTo(HaveOccurred()) 443 444 tlscert = tlscertSecret.Data["cert.pem"] 445 tlskey = tlskeySecret.Data["key.pem"] 446 }) 447 448 It("generates new crypto", func() { 449 patch := func(o client.Object) { 450 ibppeer = o.(*current.IBPPeer) 451 ibppeer.Spec.Action.Enroll.TLSCert = true 452 } 453 454 err := integration.ResilientPatch(ibpCRClient, org1peer.Name, namespace, IBPPEERS, 3, ¤t.IBPPeer{}, patch) 455 Expect(err).NotTo(HaveOccurred()) 456 457 By("backing up old crypto", func() { 458 Eventually(func() bool { 459 backup := GetBackup("tls", org1peer.Name) 460 Expect(len(backup.List)).NotTo(Equal(0)) 461 return backup.List[len(backup.List)-1].SignCerts == base64.StdEncoding.EncodeToString(tlscert) && 462 backup.List[len(backup.List)-1].KeyStore == base64.StdEncoding.EncodeToString(tlskey) 463 }).Should(Equal(true)) 464 }) 465 466 By("updating ecert signcert secret", func() { 467 Eventually(func() bool { 468 updatedTlscertSecret, err := kclient.CoreV1(). 469 Secrets(namespace). 470 Get(context.TODO(), fmt.Sprintf("tls-%s-signcert", org1peer.Name), metav1.GetOptions{}) 471 Expect(err).NotTo(HaveOccurred()) 472 473 return bytes.Equal(tlscert, updatedTlscertSecret.Data["cert.pem"]) 474 }).Should(Equal(false)) 475 }) 476 477 By("updating ecert key secret", func() { 478 Eventually(func() bool { 479 updatedTlskeySecret, err := kclient.CoreV1(). 480 Secrets(namespace). 481 Get(context.TODO(), fmt.Sprintf("tls-%s-keystore", org1peer.Name), metav1.GetOptions{}) 482 Expect(err).NotTo(HaveOccurred()) 483 484 return bytes.Equal(tlskey, updatedTlskeySecret.Data["key.pem"]) 485 }).Should(Equal(false)) 486 }) 487 488 By("setting TLS action flag back to false in spec after completion", func() { 489 Eventually(func() bool { 490 result := ibpCRClient.Get().Namespace(namespace). 491 Resource(IBPPEERS). 492 Name(org1peer.Name). 493 Do(context.TODO()) 494 ibppeer := ¤t.IBPPeer{} 495 result.Into(ibppeer) 496 497 return ibppeer.Spec.Action.Enroll.TLSCert 498 }).Should(Equal(false)) 499 }) 500 }) 501 }) 502 503 Context("upgrade dbs", func() { 504 var ( 505 migrationJobName string 506 err error 507 ) 508 509 It("performs db reset job", func() { 510 patch := func(o client.Object) { 511 ibppeer = o.(*current.IBPPeer) 512 ibppeer.Spec.Action.UpgradeDBs = true 513 } 514 515 err = integration.ResilientPatch(ibpCRClient, org1peer.Name, namespace, IBPPEERS, 3, ¤t.IBPPeer{}, patch) 516 Expect(err).NotTo(HaveOccurred()) 517 518 By("starting migration job", func() { 519 Eventually(func() bool { 520 migrationJobName, err = helper.GetJobID(kclient, namespace, fmt.Sprintf("%s-dbmigration", ibppeer.Name)) 521 if err != nil { 522 return false 523 } 524 525 _, err = kclient.BatchV1().Jobs(namespace). 526 Get(context.TODO(), migrationJobName, metav1.GetOptions{}) 527 if err != nil { 528 return false 529 } 530 return true 531 }).Should(Equal(true)) 532 }) 533 534 By("clearing out reset value after completion", func() { 535 Eventually(func() bool { 536 result := ibpCRClient.Get().Namespace(namespace). 537 Resource(IBPPEERS). 538 Name(org1peer.Name). 539 Do(context.TODO()) 540 541 Expect(result.Error()).NotTo(HaveOccurred()) 542 543 ibppeer = ¤t.IBPPeer{} 544 result.Into(ibppeer) 545 546 return ibppeer.Spec.Action.UpgradeDBs 547 }).Should(Equal(false)) 548 }) 549 550 By("removing migration job", func() { 551 Eventually(func() bool { 552 _, err := kclient.BatchV1().Jobs(namespace). 553 Get(context.TODO(), migrationJobName, metav1.GetOptions{}) 554 if err != nil { 555 return true 556 } 557 return false 558 }).Should(Equal(true)) 559 }) 560 561 By("removing migration pod", func() { 562 Eventually(func() bool { 563 podList, err := kclient.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{ 564 LabelSelector: fmt.Sprintf("job-name=%s-dbmigration", ibppeer.Name), 565 }) 566 if err != nil { 567 return true 568 } 569 570 if len(podList.Items) == 0 { 571 return true 572 } 573 574 return false 575 }).Should(Equal(true)) 576 }) 577 }) 578 }) 579 580 }) 581 582 func GetBackup(certType, name string) *common.Backup { 583 backupSecret, err := kclient.CoreV1().Secrets(namespace).Get(context.TODO(), fmt.Sprintf("%s-crypto-backup", name), metav1.GetOptions{}) 584 if err != nil { 585 Expect(k8serrors.IsNotFound(err)).To(Equal(true)) 586 return &common.Backup{} 587 } 588 589 backup := &common.Backup{} 590 key := fmt.Sprintf("%s-backup.json", certType) 591 err = json.Unmarshal(backupSecret.Data[key], backup) 592 Expect(err).NotTo(HaveOccurred()) 593 594 return backup 595 }