github.com/anjalikarhana/fabric@v2.1.1+incompatible/orderer/common/server/etcdraft_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package server_test 8 9 import ( 10 "fmt" 11 "io/ioutil" 12 "os" 13 "os/exec" 14 "path/filepath" 15 "sync/atomic" 16 "testing" 17 "time" 18 19 . "github.com/onsi/gomega" 20 "github.com/onsi/gomega/gbytes" 21 "github.com/onsi/gomega/gexec" 22 ) 23 24 var basePort = int32(8000) 25 26 func nextPort() int32 { 27 return atomic.AddInt32(&basePort, 1) 28 } 29 30 func TestSpawnEtcdRaft(t *testing.T) { 31 gt := NewGomegaWithT(t) 32 33 // Set the fabric root folder for easy navigation to sampleconfig folder 34 fabricRootDir, err := filepath.Abs(filepath.Join("..", "..", "..")) 35 gt.Expect(err).NotTo(HaveOccurred()) 36 37 // Build the configtxgen binary 38 configtxgen, err := gexec.Build("github.com/hyperledger/fabric/cmd/configtxgen") 39 gt.Expect(err).NotTo(HaveOccurred()) 40 41 cryptogen, err := gexec.Build("github.com/hyperledger/fabric/cmd/cryptogen") 42 gt.Expect(err).NotTo(HaveOccurred()) 43 44 // Build the orderer binary 45 orderer, err := gexec.Build("github.com/hyperledger/fabric/cmd/orderer") 46 gt.Expect(err).NotTo(HaveOccurred()) 47 48 defer gexec.CleanupBuildArtifacts() 49 50 tempDir, err := ioutil.TempDir("", "etcdraft-test") 51 defer os.RemoveAll(tempDir) 52 53 copyYamlFiles(gt, "testdata", tempDir) 54 55 cryptoPath := generateCryptoMaterials(gt, cryptogen, tempDir) 56 57 t.Run("Bad", func(t *testing.T) { 58 t.Run("Invalid bootstrap block", func(t *testing.T) { 59 testEtcdRaftOSNFailureInvalidBootstrapBlock(NewGomegaWithT(t), tempDir, orderer, fabricRootDir, configtxgen, cryptoPath) 60 }) 61 62 t.Run("TLS disabled single listener", func(t *testing.T) { 63 testEtcdRaftOSNNoTLSSingleListener(NewGomegaWithT(t), tempDir, orderer, fabricRootDir, configtxgen, cryptoPath) 64 }) 65 }) 66 67 t.Run("Good", func(t *testing.T) { 68 // tests in this suite actually launch process with success, hence we need to avoid 69 // conflicts in listening port, opening files. 70 t.Run("TLS disabled dual listener", func(t *testing.T) { 71 testEtcdRaftOSNNoTLSDualListener(NewGomegaWithT(t), tempDir, orderer, fabricRootDir, configtxgen, cryptoPath) 72 }) 73 74 t.Run("TLS enabled single listener", func(t *testing.T) { 75 testEtcdRaftOSNSuccess(NewGomegaWithT(t), tempDir, configtxgen, orderer, fabricRootDir, cryptoPath) 76 }) 77 }) 78 } 79 80 func copyYamlFiles(gt *GomegaWithT, src, dst string) { 81 for _, file := range []string{"configtx.yaml", "examplecom-config.yaml", "orderer.yaml"} { 82 fileBytes, err := ioutil.ReadFile(filepath.Join(src, file)) 83 gt.Expect(err).NotTo(HaveOccurred()) 84 err = ioutil.WriteFile(filepath.Join(dst, file), fileBytes, 0644) 85 gt.Expect(err).NotTo(HaveOccurred()) 86 } 87 } 88 89 func generateBootstrapBlock(gt *GomegaWithT, tempDir, configtxgen, channel, profile string) string { 90 // create a genesis block for the specified channel and profile 91 genesisBlockPath := filepath.Join(tempDir, "genesis.block") 92 cmd := exec.Command( 93 configtxgen, 94 "-channelID", channel, 95 "-profile", profile, 96 "-outputBlock", genesisBlockPath, 97 "--configPath", tempDir, 98 ) 99 configtxgenProcess, err := gexec.Start(cmd, nil, nil) 100 gt.Expect(err).NotTo(HaveOccurred()) 101 gt.Eventually(configtxgenProcess, time.Minute).Should(gexec.Exit(0)) 102 gt.Expect(configtxgenProcess.Err).To(gbytes.Say("Writing genesis block")) 103 104 return genesisBlockPath 105 } 106 107 func generateCryptoMaterials(gt *GomegaWithT, cryptogen, path string) string { 108 cryptoPath := filepath.Join(path, "crypto") 109 110 cmd := exec.Command( 111 cryptogen, 112 "generate", 113 "--config", filepath.Join(path, "examplecom-config.yaml"), 114 "--output", cryptoPath, 115 ) 116 cryptogenProcess, err := gexec.Start(cmd, nil, nil) 117 gt.Expect(err).NotTo(HaveOccurred()) 118 gt.Eventually(cryptogenProcess, time.Minute).Should(gexec.Exit(0)) 119 120 return cryptoPath 121 } 122 123 func testEtcdRaftOSNSuccess(gt *GomegaWithT, tempDir, configtxgen, orderer, fabricRootDir, cryptoPath string) { 124 genesisBlockPath := generateBootstrapBlock(gt, tempDir, configtxgen, "system", "SampleEtcdRaftSystemChannel") 125 126 // Launch the OSN 127 ordererProcess := launchOrderer(gt, orderer, tempDir, genesisBlockPath, fabricRootDir, cryptoPath) 128 defer func() { gt.Eventually(ordererProcess.Kill(), time.Minute).Should(gexec.Exit()) }() 129 // The following configuration parameters are not specified in the orderer.yaml, so let's ensure 130 // they are really configured autonomously via the localconfig code. 131 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.DialTimeout = 5s")) 132 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.RPCTimeout = 7s")) 133 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.ReplicationBufferSize = 20971520")) 134 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.ReplicationPullTimeout = 5s")) 135 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.ReplicationRetryTimeout = 5s")) 136 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.ReplicationBackgroundRefreshInterval = 5m0s")) 137 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.ReplicationMaxRetries = 12")) 138 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.SendBufferSize = 10")) 139 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.CertExpirationWarningThreshold = 168h0m0s")) 140 141 // Consensus.EvictionSuspicion is not specified in orderer.yaml, so let's ensure 142 // it is really configured autonomously via the etcdraft chain itself. 143 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("EvictionSuspicion not set, defaulting to 10m")) 144 // Wait until the the node starts up and elects itself as a single leader in a single node cluster. 145 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("Beginning to serve requests")) 146 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("becomeLeader")) 147 } 148 149 func testEtcdRaftOSNFailureInvalidBootstrapBlock(gt *GomegaWithT, tempDir, orderer, fabricRootDir, configtxgen, cryptoPath string) { 150 // create an application channel genesis block 151 genesisBlockPath := generateBootstrapBlock(gt, tempDir, configtxgen, "mychannel", "SampleOrgChannel") 152 genesisBlockBytes, err := ioutil.ReadFile(genesisBlockPath) 153 gt.Expect(err).NotTo(HaveOccurred()) 154 155 // Copy it to the designated location in the temporary folder 156 genesisBlockPath = filepath.Join(tempDir, "genesis.block") 157 err = ioutil.WriteFile(genesisBlockPath, genesisBlockBytes, 0644) 158 gt.Expect(err).NotTo(HaveOccurred()) 159 160 // Launch the OSN 161 ordererProcess := launchOrderer(gt, orderer, tempDir, genesisBlockPath, fabricRootDir, cryptoPath) 162 defer func() { gt.Eventually(ordererProcess.Kill(), time.Minute).Should(gexec.Exit()) }() 163 164 expectedErr := "Failed validating bootstrap block: the block isn't a system channel block because it lacks ConsortiumsConfig" 165 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say(expectedErr)) 166 } 167 168 func testEtcdRaftOSNNoTLSSingleListener(gt *GomegaWithT, tempDir, orderer, fabricRootDir string, configtxgen, cryptoPath string) { 169 genesisBlockPath := generateBootstrapBlock(gt, tempDir, configtxgen, "system", "SampleEtcdRaftSystemChannel") 170 171 cmd := exec.Command(orderer) 172 cmd.Env = []string{ 173 fmt.Sprintf("ORDERER_GENERAL_LISTENPORT=%d", nextPort()), 174 "ORDERER_GENERAL_BOOTSTRAPMETHOD=file", 175 "ORDERER_GENERAL_SYSTEMCHANNEL=system", 176 fmt.Sprintf("ORDERER_FILELEDGER_LOCATION=%s", filepath.Join(tempDir, "ledger")), 177 fmt.Sprintf("ORDERER_GENERAL_BOOTSTRAPFILE=%s", genesisBlockPath), 178 fmt.Sprintf("FABRIC_CFG_PATH=%s", tempDir), 179 } 180 ordererProcess, err := gexec.Start(cmd, nil, nil) 181 gt.Expect(err).NotTo(HaveOccurred()) 182 defer func() { gt.Eventually(ordererProcess.Kill(), time.Minute).Should(gexec.Exit()) }() 183 184 expectedErr := "TLS is required for running ordering nodes of type etcdraft." 185 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say(expectedErr)) 186 } 187 188 func testEtcdRaftOSNNoTLSDualListener(gt *GomegaWithT, tempDir, orderer, fabricRootDir string, configtxgen, cryptoPath string) { 189 ordererTLSPath := filepath.Join(cryptoPath, "ordererOrganizations", "example.com", "orderers", "127.0.0.1.example.com", "tls") 190 genesisBlockPath := generateBootstrapBlock(gt, tempDir, configtxgen, "system", "SampleEtcdRaftSystemChannel") 191 192 cmd := exec.Command(orderer) 193 cmd.Env = []string{ 194 fmt.Sprintf("ORDERER_GENERAL_LISTENPORT=%d", nextPort()), 195 "ORDERER_GENERAL_BOOTSTRAPMETHOD=file", 196 "ORDERER_GENERAL_SYSTEMCHANNEL=system", 197 "ORDERER_GENERAL_TLS_ENABLED=false", 198 "ORDERER_OPERATIONS_TLS_ENABLED=false", 199 fmt.Sprintf("ORDERER_FILELEDGER_LOCATION=%s", filepath.Join(tempDir, "ledger")), 200 fmt.Sprintf("ORDERER_GENERAL_BOOTSTRAPFILE=%s", genesisBlockPath), 201 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_LISTENPORT=%d", nextPort()), 202 "ORDERER_GENERAL_CLUSTER_LISTENADDRESS=127.0.0.1", 203 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERCERTIFICATE=%s", filepath.Join(ordererTLSPath, "server.crt")), 204 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERPRIVATEKEY=%s", filepath.Join(ordererTLSPath, "server.key")), 205 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=%s", filepath.Join(ordererTLSPath, "server.crt")), 206 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=%s", filepath.Join(ordererTLSPath, "server.key")), 207 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_ROOTCAS=[%s]", filepath.Join(ordererTLSPath, "ca.crt")), 208 fmt.Sprintf("ORDERER_CONSENSUS_WALDIR=%s", filepath.Join(tempDir, "wal")), 209 fmt.Sprintf("ORDERER_CONSENSUS_SNAPDIR=%s", filepath.Join(tempDir, "snapshot")), 210 fmt.Sprintf("FABRIC_CFG_PATH=%s", tempDir), 211 "ORDERER_OPERATIONS_LISTENADDRESS=127.0.0.1:0", 212 } 213 ordererProcess, err := gexec.Start(cmd, nil, nil) 214 gt.Expect(err).NotTo(HaveOccurred()) 215 defer func() { gt.Eventually(ordererProcess.Kill(), time.Minute).Should(gexec.Exit()) }() 216 217 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("Beginning to serve requests")) 218 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("becomeLeader")) 219 } 220 221 func launchOrderer(gt *GomegaWithT, orderer, tempDir, genesisBlockPath, fabricRootDir, cryptoPath string) *gexec.Session { 222 ordererTLSPath := filepath.Join(cryptoPath, "ordererOrganizations", "example.com", "orderers", "127.0.0.1.example.com", "tls") 223 // Launch the orderer process 224 cmd := exec.Command(orderer) 225 cmd.Env = []string{ 226 fmt.Sprintf("ORDERER_GENERAL_LISTENPORT=%d", nextPort()), 227 "ORDERER_GENERAL_BOOTSTRAPMETHOD=file", 228 "ORDERER_GENERAL_SYSTEMCHANNEL=system", 229 "ORDERER_GENERAL_TLS_CLIENTAUTHREQUIRED=true", 230 "ORDERER_GENERAL_TLS_ENABLED=true", 231 "ORDERER_OPERATIONS_TLS_ENABLED=false", 232 fmt.Sprintf("ORDERER_FILELEDGER_LOCATION=%s", filepath.Join(tempDir, "ledger")), 233 fmt.Sprintf("ORDERER_GENERAL_BOOTSTRAPFILE=%s", genesisBlockPath), 234 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_LISTENPORT=%d", nextPort()), 235 "ORDERER_GENERAL_CLUSTER_LISTENADDRESS=127.0.0.1", 236 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERCERTIFICATE=%s", filepath.Join(ordererTLSPath, "server.crt")), 237 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERPRIVATEKEY=%s", filepath.Join(ordererTLSPath, "server.key")), 238 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=%s", filepath.Join(ordererTLSPath, "server.crt")), 239 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=%s", filepath.Join(ordererTLSPath, "server.key")), 240 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_ROOTCAS=[%s]", filepath.Join(ordererTLSPath, "ca.crt")), 241 fmt.Sprintf("ORDERER_GENERAL_TLS_ROOTCAS=[%s]", filepath.Join(ordererTLSPath, "ca.crt")), 242 fmt.Sprintf("ORDERER_GENERAL_TLS_CERTIFICATE=%s", filepath.Join(ordererTLSPath, "server.crt")), 243 fmt.Sprintf("ORDERER_GENERAL_TLS_PRIVATEKEY=%s", filepath.Join(ordererTLSPath, "server.key")), 244 fmt.Sprintf("ORDERER_CONSENSUS_WALDIR=%s", filepath.Join(tempDir, "wal")), 245 fmt.Sprintf("ORDERER_CONSENSUS_SNAPDIR=%s", filepath.Join(tempDir, "snapshot")), 246 fmt.Sprintf("FABRIC_CFG_PATH=%s", tempDir), 247 } 248 sess, err := gexec.Start(cmd, nil, nil) 249 gt.Expect(err).NotTo(HaveOccurred()) 250 return sess 251 }