github.com/kaituanwang/hyperledger@v2.0.1+incompatible/integration/e2e/e2e_test.go (about)

     1  /*
     2  Copyright IBM Corp All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package e2e
     8  
     9  import (
    10  	"context"
    11  	"crypto/tls"
    12  	"crypto/x509"
    13  	"encoding/json"
    14  	"fmt"
    15  	"io/ioutil"
    16  	"net/http"
    17  	"os"
    18  	"path"
    19  	"path/filepath"
    20  	"strings"
    21  	"syscall"
    22  	"time"
    23  
    24  	docker "github.com/fsouza/go-dockerclient"
    25  	"github.com/golang/protobuf/proto"
    26  	"github.com/hyperledger/fabric-lib-go/healthz"
    27  	"github.com/hyperledger/fabric-protos-go/orderer/etcdraft"
    28  	"github.com/hyperledger/fabric/common/util"
    29  	"github.com/hyperledger/fabric/integration/nwo"
    30  	"github.com/hyperledger/fabric/integration/nwo/commands"
    31  	"github.com/hyperledger/fabric/integration/nwo/fabricconfig"
    32  	. "github.com/onsi/ginkgo"
    33  	. "github.com/onsi/gomega"
    34  	"github.com/onsi/gomega/gbytes"
    35  	"github.com/onsi/gomega/gexec"
    36  	"github.com/tedsuo/ifrit"
    37  	"github.com/tedsuo/ifrit/ginkgomon"
    38  )
    39  
    40  var _ = Describe("EndToEnd", func() {
    41  	var (
    42  		testDir   string
    43  		client    *docker.Client
    44  		network   *nwo.Network
    45  		chaincode nwo.Chaincode
    46  		process   ifrit.Process
    47  	)
    48  
    49  	BeforeEach(func() {
    50  		var err error
    51  		testDir, err = ioutil.TempDir("", "e2e")
    52  		Expect(err).NotTo(HaveOccurred())
    53  
    54  		client, err = docker.NewClientFromEnv()
    55  		Expect(err).NotTo(HaveOccurred())
    56  
    57  		chaincode = nwo.Chaincode{
    58  			Name:            "mycc",
    59  			Version:         "0.0",
    60  			Path:            components.Build("github.com/hyperledger/fabric/integration/chaincode/module"),
    61  			Lang:            "binary",
    62  			PackageFile:     filepath.Join(testDir, "modulecc.tar.gz"),
    63  			Ctor:            `{"Args":["init","a","100","b","200"]}`,
    64  			SignaturePolicy: `AND ('Org1MSP.member','Org2MSP.member')`,
    65  			Sequence:        "1",
    66  			InitRequired:    true,
    67  			Label:           "my_prebuilt_chaincode",
    68  		}
    69  	})
    70  
    71  	AfterEach(func() {
    72  		if process != nil {
    73  			process.Signal(syscall.SIGTERM)
    74  			Eventually(process.Wait(), network.EventuallyTimeout).Should(Receive())
    75  		}
    76  		if network != nil {
    77  			network.Cleanup()
    78  		}
    79  		os.RemoveAll(testDir)
    80  	})
    81  
    82  	Describe("basic solo network with 2 orgs and no docker", func() {
    83  		var datagramReader *DatagramReader
    84  
    85  		BeforeEach(func() {
    86  			datagramReader = NewDatagramReader()
    87  			go datagramReader.Start()
    88  
    89  			network = nwo.New(nwo.BasicSolo(), testDir, nil, StartPort(), components)
    90  			network.MetricsProvider = "statsd"
    91  			network.StatsdEndpoint = datagramReader.Address()
    92  			network.Profiles = append(network.Profiles, &nwo.Profile{
    93  				Name:          "TwoOrgsBaseProfileChannel",
    94  				Consortium:    "SampleConsortium",
    95  				Orderers:      []string{"orderer"},
    96  				Organizations: []string{"Org1", "Org2"},
    97  			})
    98  			network.Channels = append(network.Channels, &nwo.Channel{
    99  				Name:        "baseprofilechannel",
   100  				Profile:     "TwoOrgsBaseProfileChannel",
   101  				BaseProfile: "TwoOrgsOrdererGenesis",
   102  			})
   103  
   104  			network.GenerateConfigTree()
   105  			for _, peer := range network.PeersWithChannel("testchannel") {
   106  				core := network.ReadPeerConfig(peer)
   107  				core.VM = nil
   108  				network.WritePeerConfig(peer, core)
   109  			}
   110  			network.Bootstrap()
   111  
   112  			networkRunner := network.NetworkGroupRunner()
   113  			process = ifrit.Invoke(networkRunner)
   114  			Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed())
   115  		})
   116  
   117  		AfterEach(func() {
   118  			if datagramReader != nil {
   119  				datagramReader.Close()
   120  			}
   121  		})
   122  
   123  		It("executes a basic solo network with 2 orgs and no docker", func() {
   124  			By("getting the orderer by name")
   125  			orderer := network.Orderer("orderer")
   126  
   127  			By("setting up the channel")
   128  			network.CreateAndJoinChannel(orderer, "testchannel")
   129  			nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
   130  
   131  			By("deploying the chaincode")
   132  			nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
   133  
   134  			By("getting the client peer by name")
   135  			peer := network.Peer("Org1", "peer0")
   136  
   137  			RunQueryInvokeQuery(network, orderer, peer, "testchannel")
   138  			RunRespondWith(network, orderer, peer, "testchannel")
   139  
   140  			By("waiting for DeliverFiltered stats to be emitted")
   141  			metricsWriteInterval := 5 * time.Second
   142  			Eventually(datagramReader, 2*metricsWriteInterval).Should(gbytes.Say("stream_request_duration.protos_Deliver.DeliverFiltered."))
   143  
   144  			CheckPeerStatsdStreamMetrics(datagramReader.String())
   145  			CheckPeerStatsdMetrics(datagramReader.String(), "org1_peer0")
   146  			CheckPeerStatsdMetrics(datagramReader.String(), "org2_peer0")
   147  			CheckOrdererStatsdMetrics(datagramReader.String(), "ordererorg_orderer")
   148  
   149  			By("setting up a channel from a base profile")
   150  			additionalPeer := network.Peer("Org2", "peer0")
   151  			network.CreateChannel("baseprofilechannel", orderer, peer, additionalPeer)
   152  		})
   153  	})
   154  
   155  	Describe("basic kafka network with 2 orgs", func() {
   156  		BeforeEach(func() {
   157  			network = nwo.New(nwo.BasicKafka(), testDir, client, StartPort(), components)
   158  			network.MetricsProvider = "prometheus"
   159  			network.GenerateConfigTree()
   160  			network.Bootstrap()
   161  
   162  			networkRunner := network.NetworkGroupRunner()
   163  			process = ifrit.Invoke(networkRunner)
   164  			Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed())
   165  		})
   166  
   167  		It("executes a basic kafka network with 2 orgs (using docker chaincode builds)", func() {
   168  			chaincodePath, err := filepath.Abs("../chaincode/module")
   169  			Expect(err).NotTo(HaveOccurred())
   170  
   171  			// use these two variants of the same chaincode to ensure we test
   172  			// the golang docker build for both module and gopath chaincode
   173  			chaincode = nwo.Chaincode{
   174  				Name:            "mycc",
   175  				Version:         "0.0",
   176  				Path:            chaincodePath,
   177  				Lang:            "golang",
   178  				PackageFile:     filepath.Join(testDir, "modulecc.tar.gz"),
   179  				Ctor:            `{"Args":["init","a","100","b","200"]}`,
   180  				SignaturePolicy: `AND ('Org1MSP.member','Org2MSP.member')`,
   181  				Sequence:        "1",
   182  				InitRequired:    true,
   183  				Label:           "my_module_chaincode",
   184  			}
   185  
   186  			gopathChaincode := nwo.Chaincode{
   187  				Name:            "mycc",
   188  				Version:         "0.0",
   189  				Path:            "github.com/hyperledger/fabric/integration/chaincode/simple/cmd",
   190  				Lang:            "golang",
   191  				PackageFile:     filepath.Join(testDir, "simplecc.tar.gz"),
   192  				Ctor:            `{"Args":["init","a","100","b","200"]}`,
   193  				SignaturePolicy: `AND ('Org1MSP.member','Org2MSP.member')`,
   194  				Sequence:        "1",
   195  				InitRequired:    true,
   196  				Label:           "my_simple_chaincode",
   197  			}
   198  
   199  			orderer := network.Orderer("orderer")
   200  
   201  			network.CreateAndJoinChannel(orderer, "testchannel")
   202  			nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
   203  
   204  			// package, install, and approve by org1 - module chaincode
   205  			packageInstallApproveChaincode(network, "testchannel", orderer, chaincode, network.Peer("Org1", "peer0"))
   206  
   207  			// package, install, and approve by org2 - gopath chaincode, same logic
   208  			packageInstallApproveChaincode(network, "testchannel", orderer, gopathChaincode, network.Peer("Org2", "peer0"))
   209  
   210  			testPeers := network.PeersWithChannel("testchannel")
   211  			nwo.CheckCommitReadinessUntilReady(network, "testchannel", chaincode, network.PeerOrgs(), testPeers...)
   212  			nwo.CommitChaincode(network, "testchannel", orderer, chaincode, testPeers[0], testPeers...)
   213  			nwo.InitChaincode(network, "testchannel", orderer, chaincode, testPeers...)
   214  
   215  			By("listing the containers after committing the chaincode definition")
   216  			getPackageID := func(c nwo.Chaincode) string {
   217  				fileBytes, err := ioutil.ReadFile(c.PackageFile)
   218  				Expect(err).NotTo(HaveOccurred())
   219  				hashStr := fmt.Sprintf("%x", util.ComputeSHA256(fileBytes))
   220  				return hashStr
   221  			}
   222  
   223  			modulePkgID := getPackageID(chaincode)
   224  			gopathPkgID := getPackageID(gopathChaincode)
   225  			initialContainerFilter := map[string][]string{
   226  				"name": {modulePkgID, gopathPkgID},
   227  			}
   228  			containers, err := client.ListContainers(docker.ListContainersOptions{Filters: initialContainerFilter})
   229  			Expect(err).NotTo(HaveOccurred())
   230  			Expect(containers).To(HaveLen(2))
   231  
   232  			RunQueryInvokeQuery(network, orderer, network.Peer("Org1", "peer0"), "testchannel")
   233  
   234  			CheckPeerOperationEndpoints(network, network.Peer("Org2", "peer0"))
   235  			CheckOrdererOperationEndpoints(network, orderer)
   236  
   237  			// upgrade chaincode to v2.0 with different label
   238  			chaincode.Version = "1.0"
   239  			chaincode.Sequence = "2"
   240  			chaincode.Label = "my_module_chaincode_updated"
   241  			gopathChaincode.Version = "1.0"
   242  			gopathChaincode.Sequence = "2"
   243  			gopathChaincode.Label = "my_simple_chaincode_updated"
   244  
   245  			// package, install, and approve by org1 - module chaincode
   246  			packageInstallApproveChaincode(network, "testchannel", orderer, chaincode, network.Peer("Org1", "peer0"))
   247  
   248  			// package, install, and approve by org2 - gopath chaincode, same logic
   249  			packageInstallApproveChaincode(network, "testchannel", orderer, gopathChaincode, network.Peer("Org2", "peer0"))
   250  
   251  			nwo.CheckCommitReadinessUntilReady(network, "testchannel", chaincode, network.PeerOrgs(), testPeers...)
   252  			nwo.CommitChaincode(network, "testchannel", orderer, chaincode, testPeers[0], testPeers...)
   253  			nwo.InitChaincode(network, "testchannel", orderer, chaincode, testPeers...)
   254  
   255  			By("listing the containers after updating the chaincode definition")
   256  			// expect the containers for the previous package id to be stopped
   257  			containers, err = client.ListContainers(docker.ListContainersOptions{Filters: initialContainerFilter})
   258  			Expect(err).NotTo(HaveOccurred())
   259  			Expect(containers).To(HaveLen(0))
   260  			updatedModulePkgID := getPackageID(chaincode)
   261  			updatedGopathPkgID := getPackageID(gopathChaincode)
   262  			updatedContainerFilter := map[string][]string{
   263  				"name": {updatedModulePkgID, updatedGopathPkgID},
   264  			}
   265  			containers, err = client.ListContainers(docker.ListContainersOptions{Filters: updatedContainerFilter})
   266  			Expect(err).NotTo(HaveOccurred())
   267  			Expect(containers).To(HaveLen(2))
   268  
   269  			RunQueryInvokeQuery(network, orderer, network.Peer("Org1", "peer0"), "testchannel")
   270  
   271  			By("retrieving the local mspid of the peer via simple chaincode")
   272  			sess, err := network.PeerUserSession(network.Peer("Org2", "peer0"), "User1", commands.ChaincodeQuery{
   273  				ChannelID: "testchannel",
   274  				Name:      "mycc",
   275  				Ctor:      `{"Args":["mspid"]}`,
   276  			})
   277  			Expect(err).NotTo(HaveOccurred())
   278  			Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   279  			Expect(sess).To(gbytes.Say("Org2MSP"))
   280  		})
   281  	})
   282  
   283  	Describe("basic single node etcdraft network", func() {
   284  		var (
   285  			peerRunners    []*ginkgomon.Runner
   286  			processes      map[string]ifrit.Process
   287  			ordererProcess ifrit.Process
   288  		)
   289  
   290  		BeforeEach(func() {
   291  			network = nwo.New(nwo.MultiChannelEtcdRaft(), testDir, client, StartPort(), components)
   292  			network.GenerateConfigTree()
   293  			for _, peer := range network.Peers {
   294  				core := network.ReadPeerConfig(peer)
   295  				core.Peer.Gossip.UseLeaderElection = false
   296  				core.Peer.Gossip.OrgLeader = true
   297  				core.Peer.Deliveryclient.ReconnectTotalTimeThreshold = time.Duration(time.Second)
   298  				network.WritePeerConfig(peer, core)
   299  			}
   300  			network.Bootstrap()
   301  
   302  			ordererRunner := network.OrdererGroupRunner()
   303  			ordererProcess = ifrit.Invoke(ordererRunner)
   304  			Eventually(ordererProcess.Ready(), network.EventuallyTimeout).Should(BeClosed())
   305  
   306  			peerRunners = make([]*ginkgomon.Runner, len(network.Peers))
   307  			processes = map[string]ifrit.Process{}
   308  			for i, peer := range network.Peers {
   309  				pr := network.PeerRunner(peer)
   310  				peerRunners[i] = pr
   311  				p := ifrit.Invoke(pr)
   312  				processes[peer.ID()] = p
   313  				Eventually(p.Ready(), network.EventuallyTimeout).Should(BeClosed())
   314  			}
   315  		})
   316  
   317  		AfterEach(func() {
   318  			if ordererProcess != nil {
   319  				ordererProcess.Signal(syscall.SIGTERM)
   320  				Eventually(ordererProcess.Wait(), network.EventuallyTimeout).Should(Receive())
   321  			}
   322  			for _, p := range processes {
   323  				p.Signal(syscall.SIGTERM)
   324  				Eventually(p.Wait(), network.EventuallyTimeout).Should(Receive())
   325  			}
   326  		})
   327  
   328  		It("creates two channels with two orgs trying to reconfigure and update metadata", func() {
   329  			orderer := network.Orderer("orderer")
   330  			peer := network.Peer("Org1", "peer0")
   331  
   332  			By("Create first channel and deploy the chaincode")
   333  			network.CreateAndJoinChannel(orderer, "testchannel")
   334  			nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
   335  			nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
   336  			RunQueryInvokeQuery(network, orderer, peer, "testchannel")
   337  
   338  			By("Create second channel and deploy chaincode")
   339  			network.CreateAndJoinChannel(orderer, "testchannel2")
   340  			peers := network.PeersWithChannel("testchannel2")
   341  			nwo.EnableCapabilities(network, "testchannel2", "Application", "V2_0", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
   342  			nwo.ApproveChaincodeForMyOrg(network, "testchannel2", orderer, chaincode, peers...)
   343  			nwo.CheckCommitReadinessUntilReady(network, "testchannel2", chaincode, network.PeerOrgs(), peers...)
   344  			nwo.CommitChaincode(network, "testchannel2", orderer, chaincode, peers[0], peers...)
   345  			nwo.InitChaincode(network, "testchannel2", orderer, chaincode, peers...)
   346  			RunQueryInvokeQuery(network, orderer, peer, "testchannel2")
   347  
   348  			By("Update consensus metadata to increase snapshot interval")
   349  			snapDir := path.Join(network.RootDir, "orderers", orderer.ID(), "etcdraft", "snapshot", "testchannel")
   350  			files, err := ioutil.ReadDir(snapDir)
   351  			Expect(err).NotTo(HaveOccurred())
   352  			numOfSnaps := len(files)
   353  
   354  			nwo.UpdateConsensusMetadata(network, peer, orderer, "testchannel", func(originalMetadata []byte) []byte {
   355  				metadata := &etcdraft.ConfigMetadata{}
   356  				err := proto.Unmarshal(originalMetadata, metadata)
   357  				Expect(err).NotTo(HaveOccurred())
   358  
   359  				// update max in flight messages
   360  				metadata.Options.MaxInflightBlocks = 1000
   361  				metadata.Options.SnapshotIntervalSize = 10 * 1024 * 1024 // 10 MB
   362  
   363  				// write metadata back
   364  				newMetadata, err := proto.Marshal(metadata)
   365  				Expect(err).NotTo(HaveOccurred())
   366  				return newMetadata
   367  			})
   368  
   369  			// assert that no new snapshot is taken because SnapshotIntervalSize has just enlarged
   370  			files, err = ioutil.ReadDir(snapDir)
   371  			Expect(err).NotTo(HaveOccurred())
   372  			Expect(len(files)).To(Equal(numOfSnaps))
   373  
   374  			By("ensuring that static leaders do not give up on retrieving blocks after the orderer goes down")
   375  			ordererProcess.Signal(syscall.SIGTERM)
   376  			Eventually(ordererProcess.Wait(), network.EventuallyTimeout).Should(Receive())
   377  			for _, peerRunner := range peerRunners {
   378  				Eventually(peerRunner.Err(), network.EventuallyTimeout).Should(gbytes.Say("peer is a static leader, ignoring peer.deliveryclient.reconnectTotalTimeThreshold"))
   379  			}
   380  		})
   381  	})
   382  
   383  	Describe("single node etcdraft network with remapped orderer endpoints", func() {
   384  		BeforeEach(func() {
   385  			network = nwo.New(nwo.MinimalRaft(), testDir, client, StartPort(), components)
   386  			network.GenerateConfigTree()
   387  
   388  			configtxConfig := network.ReadConfigTxConfig()
   389  			ordererEndpoints := configtxConfig.Profiles["SampleDevModeEtcdRaft"].Orderer.Organizations[0].OrdererEndpoints
   390  			correctOrdererEndpoint := ordererEndpoints[0]
   391  			ordererEndpoints[0] = "127.0.0.1:1"
   392  			network.WriteConfigTxConfig(configtxConfig)
   393  
   394  			peer := network.Peer("Org1", "peer0")
   395  			peerConfig := network.ReadPeerConfig(peer)
   396  			peerConfig.Peer.Deliveryclient.AddressOverrides = []*fabricconfig.AddressOverride{
   397  				{
   398  					From:        "127.0.0.1:1",
   399  					To:          correctOrdererEndpoint,
   400  					CACertsFile: network.CACertsBundlePath(),
   401  				},
   402  			}
   403  			network.WritePeerConfig(peer, peerConfig)
   404  
   405  			network.Bootstrap()
   406  
   407  			networkRunner := network.NetworkGroupRunner()
   408  			process = ifrit.Invoke(networkRunner)
   409  			Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed())
   410  		})
   411  
   412  		It("creates and updates channel", func() {
   413  			orderer := network.Orderer("orderer")
   414  
   415  			network.CreateAndJoinChannel(orderer, "testchannel")
   416  
   417  			// The below call waits for the config update to commit on the peer, so
   418  			// it will fail if the orderer addresses are wrong.
   419  			nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
   420  		})
   421  	})
   422  
   423  	Describe("basic solo network without a system channel", func() {
   424  		var ordererProcess ifrit.Process
   425  		BeforeEach(func() {
   426  			soloConfig := nwo.BasicSolo()
   427  			network = nwo.New(soloConfig, testDir, client, StartPort(), components)
   428  			network.GenerateConfigTree()
   429  
   430  			orderer := network.Orderer("orderer")
   431  			ordererConfig := network.ReadOrdererConfig(orderer)
   432  			ordererConfig.General.BootstrapMethod = "none"
   433  			network.WriteOrdererConfig(orderer, ordererConfig)
   434  			network.Bootstrap()
   435  
   436  			ordererRunner := network.OrdererRunner(orderer)
   437  			ordererProcess = ifrit.Invoke(ordererRunner)
   438  			Eventually(ordererProcess.Ready, network.EventuallyTimeout).Should(BeClosed())
   439  			Eventually(ordererRunner.Err(), network.EventuallyTimeout).Should(gbytes.Say("registrar initializing without a system channel"))
   440  		})
   441  
   442  		AfterEach(func() {
   443  			if ordererProcess != nil {
   444  				ordererProcess.Signal(syscall.SIGTERM)
   445  				Eventually(ordererProcess.Wait(), network.EventuallyTimeout).Should(Receive())
   446  			}
   447  		})
   448  
   449  		It("starts the orderer but rejects channel creation requests", func() {
   450  			By("attempting to create a channel without a system channel defined")
   451  			sess, err := network.PeerAdminSession(network.Peer("Org1", "peer0"), commands.ChannelCreate{
   452  				ChannelID:   "testchannel",
   453  				Orderer:     network.OrdererAddress(network.Orderer("orderer"), nwo.ListenPort),
   454  				File:        network.CreateChannelTxPath("testchannel"),
   455  				OutputBlock: "/dev/null",
   456  				ClientAuth:  network.ClientAuthRequired,
   457  			})
   458  			Expect(err).NotTo(HaveOccurred())
   459  			Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1))
   460  			Eventually(sess.Err, network.EventuallyTimeout).Should(gbytes.Say("channel creation request not allowed because the orderer system channel is not yet defined"))
   461  		})
   462  	})
   463  
   464  	Describe("basic solo network with containers being interrupted", func() {
   465  		BeforeEach(func() {
   466  			network = nwo.New(nwo.FullSolo(), testDir, client, StartPort(), components)
   467  
   468  			network.GenerateConfigTree()
   469  			network.Bootstrap()
   470  
   471  			networkRunner := network.NetworkGroupRunner()
   472  			process = ifrit.Invoke(networkRunner)
   473  			Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed())
   474  		})
   475  
   476  		It("kills chaincode containers as unexpected", func() {
   477  			chaincode := nwo.Chaincode{
   478  				Name:            "mycc",
   479  				Version:         "0.0",
   480  				Path:            "github.com/hyperledger/fabric/integration/chaincode/simple/cmd",
   481  				Lang:            "golang",
   482  				PackageFile:     filepath.Join(testDir, "simplecc.tar.gz"),
   483  				Ctor:            `{"Args":["init","a","100","b","200"]}`,
   484  				SignaturePolicy: `OR ('Org1MSP.peer', 'Org2MSP.peer')`,
   485  				Sequence:        "1",
   486  				InitRequired:    true,
   487  				Label:           "my_simple_chaincode",
   488  			}
   489  
   490  			peer := network.Peers[0]
   491  			orderer := network.Orderer("orderer")
   492  
   493  			By("creating and joining channels")
   494  			network.CreateAndJoinChannels(orderer)
   495  
   496  			By("enabling new lifecycle capabilities")
   497  			nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
   498  			By("deploying the chaincode")
   499  			nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
   500  
   501  			By("querying and invoking chaincode")
   502  			RunQueryInvokeQuery(network, orderer, peer, "testchannel")
   503  
   504  			By("removing chaincode containers from all peers")
   505  			ctx := context.Background()
   506  			containers, err := client.ListContainers(docker.ListContainersOptions{})
   507  			Expect(err).NotTo(HaveOccurred())
   508  
   509  			originalContainerIDs := []string{}
   510  			for _, container := range containers {
   511  				if strings.Contains(container.Command, "chaincode") {
   512  					originalContainerIDs = append(originalContainerIDs, container.ID)
   513  					err = client.RemoveContainer(docker.RemoveContainerOptions{
   514  						ID:            container.ID,
   515  						RemoveVolumes: true,
   516  						Force:         true,
   517  						Context:       ctx,
   518  					})
   519  					Expect(err).NotTo(HaveOccurred())
   520  				}
   521  			}
   522  
   523  			By("invoking chaincode against all peers in test channel")
   524  			for _, peer := range network.Peers {
   525  				sess, err := network.PeerUserSession(peer, "User1", commands.ChaincodeInvoke{
   526  					ChannelID: "testchannel",
   527  					Orderer:   network.OrdererAddress(orderer, nwo.ListenPort),
   528  					Name:      "mycc",
   529  					Ctor:      `{"Args":["invoke","a","b","10"]}`,
   530  					PeerAddresses: []string{
   531  						network.PeerAddress(peer, nwo.ListenPort),
   532  					},
   533  					WaitForEvent: true,
   534  				})
   535  				Expect(err).NotTo(HaveOccurred())
   536  				Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   537  				Expect(sess.Err).To(gbytes.Say("Chaincode invoke successful. result: status:200"))
   538  			}
   539  
   540  			By("checking successful removals of all old chaincode containers")
   541  			newContainers, err := client.ListContainers(docker.ListContainersOptions{})
   542  			Expect(err).NotTo(HaveOccurred())
   543  			Expect(len(newContainers)).To(BeEquivalentTo(len(containers)))
   544  
   545  			for _, container := range newContainers {
   546  				Expect(originalContainerIDs).NotTo(ContainElement(container.ID))
   547  			}
   548  		})
   549  	})
   550  })
   551  
   552  func RunQueryInvokeQuery(n *nwo.Network, orderer *nwo.Orderer, peer *nwo.Peer, channel string) {
   553  	By("querying the chaincode")
   554  	sess, err := n.PeerUserSession(peer, "User1", commands.ChaincodeQuery{
   555  		ChannelID: channel,
   556  		Name:      "mycc",
   557  		Ctor:      `{"Args":["query","a"]}`,
   558  	})
   559  	Expect(err).NotTo(HaveOccurred())
   560  	Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
   561  	Expect(sess).To(gbytes.Say("100"))
   562  
   563  	sess, err = n.PeerUserSession(peer, "User1", commands.ChaincodeInvoke{
   564  		ChannelID: channel,
   565  		Orderer:   n.OrdererAddress(orderer, nwo.ListenPort),
   566  		Name:      "mycc",
   567  		Ctor:      `{"Args":["invoke","a","b","10"]}`,
   568  		PeerAddresses: []string{
   569  			n.PeerAddress(n.Peer("Org1", "peer0"), nwo.ListenPort),
   570  			n.PeerAddress(n.Peer("Org2", "peer0"), nwo.ListenPort),
   571  		},
   572  		WaitForEvent: true,
   573  	})
   574  	Expect(err).NotTo(HaveOccurred())
   575  	Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
   576  	Expect(sess.Err).To(gbytes.Say("Chaincode invoke successful. result: status:200"))
   577  
   578  	sess, err = n.PeerUserSession(peer, "User1", commands.ChaincodeQuery{
   579  		ChannelID: channel,
   580  		Name:      "mycc",
   581  		Ctor:      `{"Args":["query","a"]}`,
   582  	})
   583  	Expect(err).NotTo(HaveOccurred())
   584  	Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
   585  	Expect(sess).To(gbytes.Say("90"))
   586  }
   587  
   588  func RunRespondWith(n *nwo.Network, orderer *nwo.Orderer, peer *nwo.Peer, channel string) {
   589  	By("responding with a 300")
   590  	sess, err := n.PeerUserSession(peer, "User1", commands.ChaincodeInvoke{
   591  		ChannelID: channel,
   592  		Orderer:   n.OrdererAddress(orderer, nwo.ListenPort),
   593  		Name:      "mycc",
   594  		Ctor:      `{"Args":["respond","300","response-message","response-payload"]}`,
   595  		PeerAddresses: []string{
   596  			n.PeerAddress(n.Peer("Org1", "peer0"), nwo.ListenPort),
   597  			n.PeerAddress(n.Peer("Org2", "peer0"), nwo.ListenPort),
   598  		},
   599  		WaitForEvent: true,
   600  	})
   601  	Expect(err).NotTo(HaveOccurred())
   602  	Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
   603  	Expect(sess.Err).To(gbytes.Say("Chaincode invoke successful. result: status:300"))
   604  
   605  	By("responding with a 400")
   606  	sess, err = n.PeerUserSession(peer, "User1", commands.ChaincodeInvoke{
   607  		ChannelID: channel,
   608  		Orderer:   n.OrdererAddress(orderer, nwo.ListenPort),
   609  		Name:      "mycc",
   610  		Ctor:      `{"Args":["respond","400","response-message","response-payload"]}`,
   611  		PeerAddresses: []string{
   612  			n.PeerAddress(n.Peer("Org1", "peer0"), nwo.ListenPort),
   613  			n.PeerAddress(n.Peer("Org2", "peer0"), nwo.ListenPort),
   614  		},
   615  		WaitForEvent: true,
   616  	})
   617  	Expect(err).NotTo(HaveOccurred())
   618  	Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(1))
   619  	Expect(sess.Err).To(gbytes.Say(`Error: endorsement failure during invoke.`))
   620  }
   621  
   622  func CheckPeerStatsdMetrics(contents, prefix string) {
   623  	By("checking for peer statsd metrics")
   624  	Expect(contents).To(ContainSubstring(prefix + ".logging.entries_checked.info:"))
   625  	Expect(contents).To(ContainSubstring(prefix + ".logging.entries_written.info:"))
   626  	Expect(contents).To(ContainSubstring(prefix + ".go.mem.gc_completed_count:"))
   627  	Expect(contents).To(ContainSubstring(prefix + ".grpc.server.unary_requests_received.protos_Endorser.ProcessProposal:"))
   628  	Expect(contents).To(ContainSubstring(prefix + ".grpc.server.unary_requests_completed.protos_Endorser.ProcessProposal.OK:"))
   629  	Expect(contents).To(ContainSubstring(prefix + ".grpc.server.unary_request_duration.protos_Endorser.ProcessProposal.OK:"))
   630  	Expect(contents).To(ContainSubstring(prefix + ".ledger.blockchain_height"))
   631  	Expect(contents).To(ContainSubstring(prefix + ".ledger.blockstorage_commit_time"))
   632  	Expect(contents).To(ContainSubstring(prefix + ".ledger.blockstorage_and_pvtdata_commit_time"))
   633  }
   634  
   635  func CheckPeerStatsdStreamMetrics(contents string) {
   636  	By("checking for stream metrics")
   637  	Expect(contents).To(ContainSubstring(".grpc.server.stream_requests_received.protos_Deliver.DeliverFiltered:"))
   638  	Expect(contents).To(ContainSubstring(".grpc.server.stream_requests_completed.protos_Deliver.DeliverFiltered.Unknown:"))
   639  	Expect(contents).To(ContainSubstring(".grpc.server.stream_request_duration.protos_Deliver.DeliverFiltered.Unknown:"))
   640  	Expect(contents).To(ContainSubstring(".grpc.server.stream_messages_received.protos_Deliver.DeliverFiltered"))
   641  	Expect(contents).To(ContainSubstring(".grpc.server.stream_messages_sent.protos_Deliver.DeliverFiltered"))
   642  }
   643  
   644  func CheckOrdererStatsdMetrics(contents, prefix string) {
   645  	By("checking for AtomicBroadcast")
   646  	Expect(contents).To(ContainSubstring(prefix + ".grpc.server.stream_request_duration.orderer_AtomicBroadcast.Broadcast.OK"))
   647  	Expect(contents).To(ContainSubstring(prefix + ".grpc.server.stream_request_duration.orderer_AtomicBroadcast.Deliver."))
   648  
   649  	By("checking for orderer metrics")
   650  	Expect(contents).To(ContainSubstring(prefix + ".logging.entries_checked.info:"))
   651  	Expect(contents).To(ContainSubstring(prefix + ".logging.entries_written.info:"))
   652  	Expect(contents).To(ContainSubstring(prefix + ".go.mem.gc_completed_count:"))
   653  	Expect(contents).To(ContainSubstring(prefix + ".grpc.server.stream_requests_received.orderer_AtomicBroadcast.Deliver:"))
   654  	Expect(contents).To(ContainSubstring(prefix + ".grpc.server.stream_requests_completed.orderer_AtomicBroadcast.Deliver."))
   655  	Expect(contents).To(ContainSubstring(prefix + ".grpc.server.stream_messages_received.orderer_AtomicBroadcast.Deliver"))
   656  	Expect(contents).To(ContainSubstring(prefix + ".grpc.server.stream_messages_sent.orderer_AtomicBroadcast.Deliver"))
   657  	Expect(contents).To(ContainSubstring(prefix + ".ledger.blockchain_height"))
   658  	Expect(contents).To(ContainSubstring(prefix + ".ledger.blockstorage_commit_time"))
   659  }
   660  
   661  func OrdererOperationalClients(network *nwo.Network, orderer *nwo.Orderer) (authClient, unauthClient *http.Client) {
   662  	return operationalClients(network.OrdererLocalTLSDir(orderer))
   663  }
   664  
   665  func PeerOperationalClients(network *nwo.Network, peer *nwo.Peer) (authClient, unauthClient *http.Client) {
   666  	return operationalClients(network.PeerLocalTLSDir(peer))
   667  }
   668  
   669  func operationalClients(tlsDir string) (authClient, unauthClient *http.Client) {
   670  	clientCert, err := tls.LoadX509KeyPair(
   671  		filepath.Join(tlsDir, "server.crt"),
   672  		filepath.Join(tlsDir, "server.key"),
   673  	)
   674  	Expect(err).NotTo(HaveOccurred())
   675  
   676  	clientCertPool := x509.NewCertPool()
   677  	caCert, err := ioutil.ReadFile(filepath.Join(tlsDir, "ca.crt"))
   678  	Expect(err).NotTo(HaveOccurred())
   679  	clientCertPool.AppendCertsFromPEM(caCert)
   680  
   681  	authenticatedClient := &http.Client{
   682  		Transport: &http.Transport{
   683  			TLSClientConfig: &tls.Config{
   684  				Certificates: []tls.Certificate{clientCert},
   685  				RootCAs:      clientCertPool,
   686  			},
   687  		},
   688  	}
   689  	unauthenticatedClient := &http.Client{
   690  		Transport: &http.Transport{
   691  			TLSClientConfig: &tls.Config{RootCAs: clientCertPool},
   692  		},
   693  	}
   694  
   695  	return authenticatedClient, unauthenticatedClient
   696  }
   697  
   698  func CheckPeerOperationEndpoints(network *nwo.Network, peer *nwo.Peer) {
   699  	metricsURL := fmt.Sprintf("https://127.0.0.1:%d/metrics", network.PeerPort(peer, nwo.OperationsPort))
   700  	logspecURL := fmt.Sprintf("https://127.0.0.1:%d/logspec", network.PeerPort(peer, nwo.OperationsPort))
   701  	healthURL := fmt.Sprintf("https://127.0.0.1:%d/healthz", network.PeerPort(peer, nwo.OperationsPort))
   702  
   703  	authClient, unauthClient := PeerOperationalClients(network, peer)
   704  
   705  	CheckPeerPrometheusMetrics(authClient, metricsURL)
   706  	CheckLogspecOperations(authClient, logspecURL)
   707  	CheckHealthEndpoint(authClient, healthURL)
   708  
   709  	By("getting the logspec without a client cert")
   710  	resp, err := unauthClient.Get(logspecURL)
   711  	Expect(err).NotTo(HaveOccurred())
   712  	Expect(resp.StatusCode).To(Equal(http.StatusUnauthorized))
   713  
   714  	By("ensuring health checks do not require a client cert")
   715  	CheckHealthEndpoint(unauthClient, healthURL)
   716  }
   717  
   718  func CheckOrdererOperationEndpoints(network *nwo.Network, orderer *nwo.Orderer) {
   719  	metricsURL := fmt.Sprintf("https://127.0.0.1:%d/metrics", network.OrdererPort(orderer, nwo.OperationsPort))
   720  	logspecURL := fmt.Sprintf("https://127.0.0.1:%d/logspec", network.OrdererPort(orderer, nwo.OperationsPort))
   721  	healthURL := fmt.Sprintf("https://127.0.0.1:%d/healthz", network.OrdererPort(orderer, nwo.OperationsPort))
   722  
   723  	authClient, unauthClient := OrdererOperationalClients(network, orderer)
   724  
   725  	CheckOrdererPrometheusMetrics(authClient, metricsURL)
   726  	CheckLogspecOperations(authClient, logspecURL)
   727  	CheckHealthEndpoint(authClient, healthURL)
   728  
   729  	By("getting the logspec without a client cert")
   730  	resp, err := unauthClient.Get(logspecURL)
   731  	Expect(err).NotTo(HaveOccurred())
   732  	Expect(resp.StatusCode).To(Equal(http.StatusUnauthorized))
   733  
   734  	By("ensuring health checks do not require a client cert")
   735  	CheckHealthEndpoint(unauthClient, healthURL)
   736  }
   737  
   738  func CheckPeerPrometheusMetrics(client *http.Client, url string) {
   739  	By("hitting the prometheus metrics endpoint")
   740  	resp, err := client.Get(url)
   741  	Expect(err).NotTo(HaveOccurred())
   742  	Expect(resp.StatusCode).To(Equal(http.StatusOK))
   743  	resp.Body.Close()
   744  
   745  	Eventually(getBody(client, url)).Should(ContainSubstring(`# TYPE grpc_server_stream_request_duration histogram`))
   746  
   747  	By("checking for some expected metrics")
   748  	body := getBody(client, url)()
   749  	Expect(body).To(ContainSubstring(`# TYPE go_gc_duration_seconds summary`))
   750  	Expect(body).To(ContainSubstring(`# TYPE grpc_server_stream_request_duration histogram`))
   751  	Expect(body).To(ContainSubstring(`grpc_server_stream_request_duration_count{code="Unknown",method="DeliverFiltered",service="protos_Deliver"}`))
   752  	Expect(body).To(ContainSubstring(`grpc_server_stream_messages_received{method="DeliverFiltered",service="protos_Deliver"}`))
   753  	Expect(body).To(ContainSubstring(`grpc_server_stream_messages_sent{method="DeliverFiltered",service="protos_Deliver"}`))
   754  	Expect(body).To(ContainSubstring(`# TYPE grpc_comm_conn_closed counter`))
   755  	Expect(body).To(ContainSubstring(`# TYPE grpc_comm_conn_opened counter`))
   756  	Expect(body).To(ContainSubstring(`ledger_blockchain_height`))
   757  	Expect(body).To(ContainSubstring(`ledger_blockstorage_commit_time_bucket`))
   758  	Expect(body).To(ContainSubstring(`ledger_blockstorage_and_pvtdata_commit_time_bucket`))
   759  }
   760  
   761  func CheckOrdererPrometheusMetrics(client *http.Client, url string) {
   762  	By("hitting the prometheus metrics endpoint")
   763  	resp, err := client.Get(url)
   764  	Expect(err).NotTo(HaveOccurred())
   765  	Expect(resp.StatusCode).To(Equal(http.StatusOK))
   766  	resp.Body.Close()
   767  
   768  	Eventually(getBody(client, url)).Should(ContainSubstring(`# TYPE grpc_server_stream_request_duration histogram`))
   769  
   770  	By("checking for some expected metrics")
   771  	body := getBody(client, url)()
   772  	Expect(body).To(ContainSubstring(`# TYPE go_gc_duration_seconds summary`))
   773  	Expect(body).To(ContainSubstring(`# TYPE grpc_server_stream_request_duration histogram`))
   774  	Expect(body).To(ContainSubstring(`grpc_server_stream_request_duration_sum{code="OK",method="Deliver",service="orderer_AtomicBroadcast"`))
   775  	Expect(body).To(ContainSubstring(`grpc_server_stream_request_duration_sum{code="OK",method="Broadcast",service="orderer_AtomicBroadcast"`))
   776  	Expect(body).To(ContainSubstring(`# TYPE grpc_comm_conn_closed counter`))
   777  	Expect(body).To(ContainSubstring(`# TYPE grpc_comm_conn_opened counter`))
   778  	Expect(body).To(ContainSubstring(`ledger_blockchain_height`))
   779  	Expect(body).To(ContainSubstring(`ledger_blockstorage_commit_time_bucket`))
   780  }
   781  
   782  func CheckLogspecOperations(client *http.Client, logspecURL string) {
   783  	By("getting the logspec")
   784  	resp, err := client.Get(logspecURL)
   785  	Expect(err).NotTo(HaveOccurred())
   786  	Expect(resp.StatusCode).To(Equal(http.StatusOK))
   787  	bodyBytes, err := ioutil.ReadAll(resp.Body)
   788  	resp.Body.Close()
   789  	Expect(err).NotTo(HaveOccurred())
   790  	Expect(string(bodyBytes)).To(MatchJSON(`{"spec":"info"}`))
   791  
   792  	updateReq, err := http.NewRequest(http.MethodPut, logspecURL, strings.NewReader(`{"spec":"debug"}`))
   793  	Expect(err).NotTo(HaveOccurred())
   794  
   795  	By("setting the logspec")
   796  	resp, err = client.Do(updateReq)
   797  	Expect(err).NotTo(HaveOccurred())
   798  	Expect(resp.StatusCode).To(Equal(http.StatusNoContent))
   799  
   800  	resp, err = client.Get(logspecURL)
   801  	Expect(err).NotTo(HaveOccurred())
   802  	Expect(resp.StatusCode).To(Equal(http.StatusOK))
   803  	bodyBytes, err = ioutil.ReadAll(resp.Body)
   804  	resp.Body.Close()
   805  	Expect(err).NotTo(HaveOccurred())
   806  	Expect(string(bodyBytes)).To(MatchJSON(`{"spec":"debug"}`))
   807  }
   808  
   809  func CheckHealthEndpoint(client *http.Client, url string) {
   810  	body := getBody(client, url)()
   811  
   812  	var healthStatus healthz.HealthStatus
   813  	err := json.Unmarshal([]byte(body), &healthStatus)
   814  	Expect(err).NotTo(HaveOccurred())
   815  	Expect(healthStatus.Status).To(Equal(healthz.StatusOK))
   816  }
   817  
   818  func getBody(client *http.Client, url string) func() string {
   819  	return func() string {
   820  		resp, err := client.Get(url)
   821  		Expect(err).NotTo(HaveOccurred())
   822  		Expect(resp.StatusCode).To(Equal(http.StatusOK))
   823  		bodyBytes, err := ioutil.ReadAll(resp.Body)
   824  		Expect(err).NotTo(HaveOccurred())
   825  		resp.Body.Close()
   826  		return string(bodyBytes)
   827  	}
   828  }
   829  
   830  func packageInstallApproveChaincode(network *nwo.Network, channel string, orderer *nwo.Orderer, chaincode nwo.Chaincode, peers ...*nwo.Peer) {
   831  	nwo.PackageChaincode(network, chaincode, peers[0])
   832  	nwo.InstallChaincode(network, chaincode, peers...)
   833  	nwo.ApproveChaincodeForMyOrg(network, channel, orderer, chaincode, peers...)
   834  }