github.com/IBM-Blockchain/fabric-operator@v1.0.4/integration/operatorrestart/operatorrestart_suite_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 operatorrestart_test 20 21 import ( 22 "encoding/base64" 23 "fmt" 24 "io/ioutil" 25 "net/url" 26 "os" 27 "path/filepath" 28 "strings" 29 "testing" 30 "time" 31 32 . "github.com/onsi/ginkgo/v2" 33 . "github.com/onsi/gomega" 34 "github.com/onsi/gomega/gexec" 35 36 current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1" 37 "github.com/IBM-Blockchain/fabric-operator/integration" 38 "github.com/IBM-Blockchain/fabric-operator/integration/helper" 39 v1 "github.com/IBM-Blockchain/fabric-operator/pkg/apis/ca/v1" 40 ibpclient "github.com/IBM-Blockchain/fabric-operator/pkg/client" 41 "github.com/IBM-Blockchain/fabric-operator/pkg/command" 42 baseorderer "github.com/IBM-Blockchain/fabric-operator/pkg/offering/base/orderer" 43 "github.com/IBM-Blockchain/fabric-operator/pkg/util" 44 "github.com/IBM-Blockchain/fabric-operator/pkg/util/pointer" 45 46 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 47 "k8s.io/apimachinery/pkg/runtime" 48 "k8s.io/client-go/kubernetes" 49 ) 50 51 func TestOperatorrestart(t *testing.T) { 52 RegisterFailHandler(Fail) 53 RunSpecs(t, "Operatorrestart Suite") 54 } 55 56 const ( 57 ccTarFile = "gocc.tar.gz" 58 59 FabricBinaryVersion = "2.2.3" 60 FabricCABinaryVersion = "1.5.1" 61 62 peerAdminUsername = "peer-admin" 63 peerUsername = "peer" 64 ordererUsername = "orderer" 65 66 IBPCAS = "ibpcas" 67 IBPPEERS = "ibppeers" 68 IBPORDERERS = "ibporderers" 69 ) 70 71 var ( 72 wd string // Working directory of test 73 namespace string 74 domain string 75 kclient *kubernetes.Clientset 76 ibpCRClient *ibpclient.IBPClient 77 colorIndex uint 78 testFailed bool 79 caHost string 80 tlsBytes []byte 81 82 org1ca *helper.CA 83 org1peer *helper.Peer 84 orderer *helper.Orderer 85 ) 86 87 var _ = BeforeSuite(func() { 88 SetDefaultEventuallyTimeout(420 * time.Second) 89 SetDefaultEventuallyPollingInterval(time.Second) 90 91 var err error 92 93 domain = os.Getenv("DOMAIN") 94 if domain == "" { 95 domain = integration.TestAutomation1IngressDomain 96 } 97 98 wd, err = os.Getwd() 99 Expect(err).NotTo(HaveOccurred()) 100 fmt.Fprintf(GinkgoWriter, "Working directory: %s\n", wd) 101 102 cleanupFiles() 103 104 cfg := &integration.Config{ 105 OperatorServiceAccount: "../../config/rbac/service_account.yaml", 106 OperatorRole: "../../config/rbac/role.yaml", 107 OperatorRoleBinding: "../../config/rbac/role_binding.yaml", 108 OperatorDeployment: "../../testdata/deploy/operator.yaml", 109 OrdererSecret: "../../testdata/deploy/orderer/secret.yaml", 110 PeerSecret: "../../testdata/deploy/peer/secret.yaml", 111 ConsoleTLSSecret: "../../testdata/deploy/console/tlssecret.yaml", 112 } 113 114 namespace, kclient, ibpCRClient, err = integration.Setup(GinkgoWriter, cfg, "operatorrestart", "") 115 116 Expect(err).NotTo(HaveOccurred()) 117 118 downloadBinaries() 119 120 CreateNetwork() 121 }) 122 123 var _ = AfterSuite(func() { 124 125 if strings.ToLower(os.Getenv("SAVE_TEST")) == "true" { 126 return 127 } 128 129 integration.Cleanup(GinkgoWriter, kclient, namespace) 130 131 cleanupFiles() 132 }) 133 134 func CreateNetwork() { 135 By("starting CA pod", func() { 136 org1ca = Org1CA() 137 helper.CreateCA(ibpCRClient, org1ca.CR) 138 139 Eventually(org1ca.PodIsRunning).Should((Equal(true))) 140 }) 141 142 profile, err := org1ca.ConnectionProfile() 143 Expect(err).NotTo(HaveOccurred()) 144 145 tlsBytes, err = util.Base64ToBytes(profile.TLS.Cert) 146 Expect(err).NotTo(HaveOccurred()) 147 148 By("performing CA health check", func() { 149 Eventually(func() bool { 150 url := fmt.Sprintf("https://%s/cainfo", org1ca.Address()) 151 fmt.Fprintf(GinkgoWriter, "Waiting for CA health check to pass for '%s' at url: %s\n", org1ca.Name, url) 152 return org1ca.HealthCheck(url, tlsBytes) 153 }).Should(Equal(true)) 154 }) 155 156 org1ca.TLSToFile(tlsBytes) 157 158 caURL, err := url.Parse(profile.Endpoints.API) 159 Expect(err).NotTo(HaveOccurred()) 160 caHost = strings.Split(caURL.Host, ":")[0] 161 162 By("enrolling ca admin", func() { 163 os.Setenv("FABRIC_CA_CLIENT_HOME", filepath.Join(wd, org1ca.Name, "org1ca-admin")) 164 sess, err := helper.StartSession(org1ca.Enroll("admin", "adminpw"), "Enroll CA Admin") 165 Expect(err).NotTo(HaveOccurred()) 166 Eventually(sess).Should(gexec.Exit(0)) 167 }) 168 169 By("registering peer identity", func() { 170 os.Setenv("FABRIC_CA_CLIENT_HOME", filepath.Join(wd, org1ca.Name, "org1ca-admin")) 171 sess, err := helper.StartSession(org1ca.Register(peerUsername, "peerpw", "peer"), "Register User") 172 Expect(err).NotTo(HaveOccurred()) 173 Eventually(sess).Should(gexec.Exit(0)) 174 }) 175 176 By("registering and enrolling peer admin", func() { 177 os.Setenv("FABRIC_CA_CLIENT_HOME", filepath.Join(wd, org1ca.Name, "org1ca-admin")) 178 sess, err := helper.StartSession(org1ca.Register(peerAdminUsername, "peer-adminpw", "admin"), "Register Peer Admin") 179 Expect(err).NotTo(HaveOccurred()) 180 Eventually(sess).Should(gexec.Exit(0)) 181 182 os.Setenv("FABRIC_CA_CLIENT_HOME", filepath.Join(wd, "org1peer", peerAdminUsername)) 183 sess, err = helper.StartSession(org1ca.Enroll(peerAdminUsername, "peer-adminpw"), "Enroll Peer Admin") 184 Expect(err).NotTo(HaveOccurred()) 185 Eventually(sess).Should(gexec.Exit(0)) 186 }) 187 188 By("registering orderer identity", func() { 189 os.Setenv("FABRIC_CA_CLIENT_HOME", filepath.Join(wd, org1ca.Name, "org1ca-admin")) 190 sess, err := helper.StartSession(org1ca.Register(ordererUsername, "ordererpw", "orderer"), "Register Orderer Identity") 191 Expect(err).NotTo(HaveOccurred()) 192 Eventually(sess).Should(gexec.Exit(0)) 193 194 os.Setenv("FABRIC_CA_CLIENT_HOME", filepath.Join(wd, org1ca.Name, "org1ca-admin")) 195 sess, err = helper.StartSession(org1ca.Register("orderer2", "ordererpw2", "orderer"), "Register Orderer Identity") 196 Expect(err).NotTo(HaveOccurred()) 197 Eventually(sess).Should(gexec.Exit(0)) 198 }) 199 200 adminCertBytes, err := ioutil.ReadFile( 201 filepath.Join( 202 wd, 203 "org1peer", 204 peerAdminUsername, 205 "msp", 206 "signcerts", 207 "cert.pem", 208 ), 209 ) 210 Expect(err).NotTo(HaveOccurred()) 211 adminCertB64 := base64.StdEncoding.EncodeToString(adminCertBytes) 212 tlsCert := base64.StdEncoding.EncodeToString(tlsBytes) 213 214 By("starting Peer pod", func() { 215 org1peer = Org1Peer(tlsCert, caHost, adminCertB64) 216 err = helper.CreatePeer(ibpCRClient, org1peer.CR) 217 Expect(err).NotTo(HaveOccurred()) 218 }) 219 220 By("starting Orderer pod", func() { 221 orderer = GetOrderer(tlsCert, caHost) 222 err = helper.CreateOrderer(ibpCRClient, orderer.CR) 223 Expect(err).NotTo(HaveOccurred()) 224 }) 225 226 Eventually(org1peer.PodIsRunning).Should((Equal(true))) 227 Eventually(orderer.Nodes[0].PodIsRunning).Should((Equal(true))) 228 } 229 230 func downloadBinaries() { 231 os.Setenv("FABRIC_VERSION", FabricBinaryVersion) 232 os.Setenv("FABRIC_CA_VERSION", FabricCABinaryVersion) 233 sess, err := helper.StartSession( 234 helper.GetCommand(helper.AbsPath(wd, "../../scripts/download_binaries.sh")), 235 "Download Binaries", 236 ) 237 Expect(err).NotTo(HaveOccurred()) 238 Eventually(sess).Should(gexec.Exit(0)) 239 } 240 241 func cleanupFiles() { 242 os.RemoveAll(filepath.Join(wd, Org1CA().Name)) 243 } 244 245 func RestartOperator() { 246 fmt.Fprintf(GinkgoWriter, "Restarting operator\n") 247 integration.ShutdownOperator(GinkgoWriter) 248 249 fmt.Fprintf(GinkgoWriter, "Operator stopped\n") 250 251 // Currently triggering restart by closing channel results in following error on operator restart: 252 // {"level":"error","ts":1600966252.5380569,"logger":"controller-runtime.metrics","msg":"failed to register metric","name":"workqueue_retries_total","queue":"ibpconsole-controller","error":"duplicate metrics collector registration attempted" 253 // 254 // This error is not a breaking error, it can be ignored for testing purposes 255 256 fmt.Fprintf(GinkgoWriter, "Starting operator\n") 257 err := command.OperatorWithSignal(integration.OperatorCfg(), integration.SetupSignalHandler(), false, true) 258 Expect(err).NotTo(HaveOccurred()) 259 } 260 261 func Org1CA() *helper.CA { 262 caOverrides := &v1.ServerConfig{ 263 Debug: pointer.True(), 264 CAConfig: v1.CAConfig{ 265 Affiliations: map[string]interface{}{ 266 "org1": []string{"department1"}, 267 }, 268 DB: &v1.CAConfigDB{ 269 Type: "sqlite3", 270 }, 271 }, 272 } 273 caJson, err := util.ConvertToJsonMessage(caOverrides) 274 Expect(err).NotTo(HaveOccurred()) 275 276 name := "ibpca1" 277 cr := ¤t.IBPCA{ 278 ObjectMeta: metav1.ObjectMeta{ 279 Name: name, 280 Namespace: namespace, 281 }, 282 Spec: current.IBPCASpec{ 283 License: current.License{ 284 Accept: true, 285 }, 286 ImagePullSecrets: []string{"regcred"}, 287 Domain: domain, 288 Images: ¤t.CAImages{ 289 CAImage: integration.CaImage, 290 CATag: integration.CaTag, 291 CAInitImage: integration.InitImage, 292 CAInitTag: integration.InitTag, 293 }, 294 ConfigOverride: ¤t.ConfigOverride{ 295 CA: &runtime.RawExtension{Raw: *caJson}, 296 TLSCA: &runtime.RawExtension{Raw: *caJson}, 297 }, 298 FabricVersion: integration.FabricCAVersion, 299 }, 300 } 301 302 return &helper.CA{ 303 Domain: domain, 304 Name: cr.Name, 305 Namespace: namespace, 306 WorkingDir: wd, 307 CR: cr, 308 CRClient: ibpCRClient, 309 KClient: kclient, 310 NativeResourcePoller: integration.NativeResourcePoller{ 311 Name: cr.Name, 312 Namespace: namespace, 313 Client: kclient, 314 }, 315 } 316 } 317 318 func Org1Peer(tlsCert, caHost, adminCert string) *helper.Peer { 319 cr, err := helper.Org1PeerCR(namespace, domain, peerUsername, tlsCert, caHost, adminCert) 320 Expect(err).NotTo(HaveOccurred()) 321 322 return &helper.Peer{ 323 Domain: domain, 324 Name: cr.Name, 325 Namespace: namespace, 326 WorkingDir: wd, 327 CR: cr, 328 CRClient: ibpCRClient, 329 KClient: kclient, 330 NativeResourcePoller: integration.NativeResourcePoller{ 331 Name: cr.Name, 332 Namespace: namespace, 333 Client: kclient, 334 }, 335 } 336 } 337 338 func GetOrderer(tlsCert, caHost string) *helper.Orderer { 339 cr, err := helper.OrdererCR(namespace, domain, ordererUsername, tlsCert, caHost) 340 Expect(err).NotTo(HaveOccurred()) 341 342 nodes := []helper.Orderer{ 343 helper.Orderer{ 344 Name: cr.Name + "node1", 345 Namespace: namespace, 346 CR: cr.DeepCopy(), 347 NodeName: fmt.Sprintf("%s%s%d", cr.Name, baseorderer.NODE, 1), 348 NativeResourcePoller: integration.NativeResourcePoller{ 349 Name: cr.Name + "node1", 350 Namespace: namespace, 351 Client: kclient, 352 }, 353 }, 354 } 355 356 nodes[0].CR.ObjectMeta.Name = cr.Name + "node1" 357 358 return &helper.Orderer{ 359 Name: cr.Name, 360 Namespace: namespace, 361 CR: cr, 362 NodeName: fmt.Sprintf("%s-%s%d", cr.Name, baseorderer.NODE, 1), 363 NativeResourcePoller: integration.NativeResourcePoller{ 364 Name: cr.Name, 365 Namespace: namespace, 366 Client: kclient, 367 }, 368 Nodes: nodes, 369 } 370 }