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