github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+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 // Build the orderer binary 42 orderer, err := gexec.Build("github.com/hyperledger/fabric/cmd/orderer") 43 gt.Expect(err).NotTo(HaveOccurred()) 44 45 defer gexec.CleanupBuildArtifacts() 46 47 t.Run("Bad", func(t *testing.T) { 48 gt = NewGomegaWithT(t) 49 tempDir, err := ioutil.TempDir("", "etcdraft-orderer-launch") 50 gt.Expect(err).NotTo(HaveOccurred()) 51 defer os.RemoveAll(tempDir) 52 53 t.Run("Invalid bootstrap block", func(t *testing.T) { 54 testEtcdRaftOSNFailureInvalidBootstrapBlock(NewGomegaWithT(t), tempDir, orderer, fabricRootDir, configtxgen) 55 }) 56 57 t.Run("TLS disabled single listener", func(t *testing.T) { 58 testEtcdRaftOSNNoTLSSingleListener(NewGomegaWithT(t), tempDir, orderer, fabricRootDir, configtxgen) 59 }) 60 }) 61 62 t.Run("Good", func(t *testing.T) { 63 // tests in this suite actually launch process with success, hence we need to avoid 64 // conflicts in listening port, opening files. 65 t.Run("TLS disabled dual listener", func(t *testing.T) { 66 gt = NewGomegaWithT(t) 67 tempDir, err := ioutil.TempDir("", "etcdraft-orderer-launch") 68 gt.Expect(err).NotTo(HaveOccurred()) 69 defer os.RemoveAll(tempDir) 70 71 testEtcdRaftOSNNoTLSDualListener(gt, tempDir, orderer, fabricRootDir, configtxgen) 72 }) 73 74 t.Run("TLS enabled single listener", func(t *testing.T) { 75 gt = NewGomegaWithT(t) 76 tempDir, err := ioutil.TempDir("", "etcdraft-orderer-launch") 77 gt.Expect(err).NotTo(HaveOccurred()) 78 defer os.RemoveAll(tempDir) 79 80 testEtcdRaftOSNSuccess(gt, tempDir, configtxgen, orderer, fabricRootDir) 81 }) 82 }) 83 } 84 85 func createBootstrapBlock(gt *GomegaWithT, tempDir, configtxgen, channel, profile string) string { 86 // create a genesis block for the specified channel and profile 87 genesisBlockPath := filepath.Join(tempDir, "genesis.block") 88 cmd := exec.Command(configtxgen, "-channelID", channel, "-profile", profile, 89 "-outputBlock", genesisBlockPath) 90 cmd.Env = append(cmd.Env, "FABRIC_CFG_PATH=testdata") 91 configtxgenProcess, err := gexec.Start(cmd, nil, nil) 92 gt.Expect(err).NotTo(HaveOccurred()) 93 gt.Eventually(configtxgenProcess, time.Minute).Should(gexec.Exit(0)) 94 gt.Expect(configtxgenProcess.Err).To(gbytes.Say("Writing genesis block")) 95 96 return genesisBlockPath 97 } 98 99 func testEtcdRaftOSNSuccess(gt *GomegaWithT, tempDir, configtxgen, orderer, fabricRootDir string) { 100 genesisBlockPath := createBootstrapBlock(gt, tempDir, configtxgen, "system", "SampleEtcdRaftSystemChannel") 101 102 // Launch the OSN 103 ordererProcess := launchOrderer(gt, orderer, tempDir, genesisBlockPath, fabricRootDir) 104 defer ordererProcess.Kill() 105 // The following configuration parameters are not specified in the orderer.yaml, so let's ensure 106 // they are really configured autonomously via the localconfig code. 107 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.DialTimeout = 5s")) 108 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.RPCTimeout = 7s")) 109 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.ReplicationBufferSize = 20971520")) 110 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.ReplicationPullTimeout = 5s")) 111 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.ReplicationRetryTimeout = 5s")) 112 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.ReplicationBackgroundRefreshInterval = 5m0s")) 113 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.ReplicationMaxRetries = 12")) 114 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.SendBufferSize = 10")) 115 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("General.Cluster.CertExpirationWarningThreshold = 168h0m0s")) 116 117 // Consensus.EvictionSuspicion is not specified in orderer.yaml, so let's ensure 118 // it is really configured autonomously via the etcdraft chain itself. 119 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("EvictionSuspicion not set, defaulting to 10m")) 120 // Wait until the the node starts up and elects itself as a single leader in a single node cluster. 121 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("Beginning to serve requests")) 122 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("becomeLeader")) 123 } 124 125 func testEtcdRaftOSNFailureInvalidBootstrapBlock(gt *GomegaWithT, tempDir, orderer, fabricRootDir, configtxgen string) { 126 // create an application channel genesis block 127 genesisBlockPath := createBootstrapBlock(gt, tempDir, configtxgen, "mychannel", "SampleOrgChannel") 128 genesisBlockBytes, err := ioutil.ReadFile(genesisBlockPath) 129 gt.Expect(err).NotTo(HaveOccurred()) 130 131 // Copy it to the designated location in the temporary folder 132 genesisBlockPath = filepath.Join(tempDir, "genesis.block") 133 err = ioutil.WriteFile(genesisBlockPath, genesisBlockBytes, 0644) 134 gt.Expect(err).NotTo(HaveOccurred()) 135 136 // Launch the OSN 137 ordererProcess := launchOrderer(gt, orderer, tempDir, genesisBlockPath, fabricRootDir) 138 defer ordererProcess.Kill() 139 140 expectedErr := "Failed validating bootstrap block: the block isn't a system channel block because it lacks ConsortiumsConfig" 141 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say(expectedErr)) 142 } 143 144 func testEtcdRaftOSNNoTLSSingleListener(gt *GomegaWithT, tempDir, orderer, fabricRootDir string, configtxgen string) { 145 genesisBlockPath := createBootstrapBlock(gt, tempDir, configtxgen, "system", "SampleEtcdRaftSystemChannel") 146 147 cmd := exec.Command(orderer) 148 cmd.Env = []string{ 149 fmt.Sprintf("ORDERER_GENERAL_LISTENPORT=%d", nextPort()), 150 "ORDERER_GENERAL_BOOTSTRAPMETHOD=file", 151 "ORDERER_GENERAL_SYSTEMCHANNEL=system", 152 fmt.Sprintf("ORDERER_FILELEDGER_LOCATION=%s", filepath.Join(tempDir, "ledger")), 153 fmt.Sprintf("ORDERER_GENERAL_BOOTSTRAPFILE=%s", genesisBlockPath), 154 fmt.Sprintf("FABRIC_CFG_PATH=%s", filepath.Join(fabricRootDir, "sampleconfig")), 155 } 156 ordererProcess, err := gexec.Start(cmd, nil, nil) 157 gt.Expect(err).NotTo(HaveOccurred()) 158 defer ordererProcess.Kill() 159 160 expectedErr := "TLS is required for running ordering nodes of type etcdraft." 161 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say(expectedErr)) 162 } 163 164 func testEtcdRaftOSNNoTLSDualListener(gt *GomegaWithT, tempDir, orderer, fabricRootDir string, configtxgen string) { 165 cwd, err := os.Getwd() 166 gt.Expect(err).NotTo(HaveOccurred()) 167 168 genesisBlockPath := createBootstrapBlock(gt, tempDir, configtxgen, "system", "SampleEtcdRaftSystemChannel") 169 170 cmd := exec.Command(orderer) 171 cmd.Env = []string{ 172 fmt.Sprintf("ORDERER_GENERAL_LISTENPORT=%d", nextPort()), 173 "ORDERER_GENERAL_BOOTSTRAPMETHOD=file", 174 "ORDERER_GENERAL_SYSTEMCHANNEL=system", 175 "ORDERER_GENERAL_TLS_ENABLED=false", 176 "ORDERER_OPERATIONS_TLS_ENABLED=false", 177 fmt.Sprintf("ORDERER_FILELEDGER_LOCATION=%s", filepath.Join(tempDir, "ledger")), 178 fmt.Sprintf("ORDERER_GENERAL_BOOTSTRAPFILE=%s", genesisBlockPath), 179 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_LISTENPORT=%d", nextPort()), 180 "ORDERER_GENERAL_CLUSTER_LISTENADDRESS=127.0.0.1", 181 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERCERTIFICATE=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.crt")), 182 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERPRIVATEKEY=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.key")), 183 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.crt")), 184 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.key")), 185 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_ROOTCAS=[%s]", filepath.Join(cwd, "testdata", "example.com", "tls", "ca.crt")), 186 fmt.Sprintf("ORDERER_CONSENSUS_WALDIR=%s", filepath.Join(tempDir, "wal")), 187 fmt.Sprintf("ORDERER_CONSENSUS_SNAPDIR=%s", filepath.Join(tempDir, "snapshot")), 188 fmt.Sprintf("FABRIC_CFG_PATH=%s", filepath.Join(fabricRootDir, "sampleconfig")), 189 "ORDERER_OPERATIONS_LISTENADDRESS=127.0.0.1:0", 190 } 191 ordererProcess, err := gexec.Start(cmd, nil, nil) 192 gt.Expect(err).NotTo(HaveOccurred()) 193 defer ordererProcess.Kill() 194 195 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("Beginning to serve requests")) 196 gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("becomeLeader")) 197 } 198 199 func launchOrderer(gt *GomegaWithT, orderer, tempDir, genesisBlockPath, fabricRootDir string) *gexec.Session { 200 cwd, err := os.Getwd() 201 gt.Expect(err).NotTo(HaveOccurred()) 202 203 // Launch the orderer process 204 cmd := exec.Command(orderer) 205 cmd.Env = []string{ 206 fmt.Sprintf("ORDERER_GENERAL_LISTENPORT=%d", nextPort()), 207 "ORDERER_GENERAL_BOOTSTRAPMETHOD=file", 208 "ORDERER_GENERAL_SYSTEMCHANNEL=system", 209 "ORDERER_GENERAL_TLS_CLIENTAUTHREQUIRED=true", 210 "ORDERER_GENERAL_TLS_ENABLED=true", 211 "ORDERER_OPERATIONS_TLS_ENABLED=false", 212 fmt.Sprintf("ORDERER_FILELEDGER_LOCATION=%s", filepath.Join(tempDir, "ledger")), 213 fmt.Sprintf("ORDERER_GENERAL_BOOTSTRAPFILE=%s", genesisBlockPath), 214 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_LISTENPORT=%d", nextPort()), 215 "ORDERER_GENERAL_CLUSTER_LISTENADDRESS=127.0.0.1", 216 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERCERTIFICATE=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.crt")), 217 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERPRIVATEKEY=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.key")), 218 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.crt")), 219 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.key")), 220 fmt.Sprintf("ORDERER_GENERAL_CLUSTER_ROOTCAS=[%s]", filepath.Join(cwd, "testdata", "example.com", "tls", "ca.crt")), 221 fmt.Sprintf("ORDERER_GENERAL_TLS_ROOTCAS=[%s]", filepath.Join(cwd, "testdata", "example.com", "tls", "ca.crt")), 222 fmt.Sprintf("ORDERER_GENERAL_TLS_CERTIFICATE=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.crt")), 223 fmt.Sprintf("ORDERER_GENERAL_TLS_PRIVATEKEY=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.key")), 224 fmt.Sprintf("ORDERER_CONSENSUS_WALDIR=%s", filepath.Join(tempDir, "wal")), 225 fmt.Sprintf("ORDERER_CONSENSUS_SNAPDIR=%s", filepath.Join(tempDir, "snapshot")), 226 fmt.Sprintf("FABRIC_CFG_PATH=%s", filepath.Join(fabricRootDir, "sampleconfig")), 227 } 228 sess, err := gexec.Start(cmd, nil, nil) 229 gt.Expect(err).NotTo(HaveOccurred()) 230 return sess 231 }