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  }