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