986 lines
39 KiB
Go
986 lines
39 KiB
Go
/*
|
|
Copyright IBM Corp All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package e2e
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"context"
|
|
"crypto/sha256"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
|
|
docker "github.com/fsouza/go-dockerclient"
|
|
"github.com/golang/protobuf/proto"
|
|
"github.com/hyperledger/fabric-lib-go/healthz"
|
|
"github.com/hyperledger/fabric-protos-go/orderer/etcdraft"
|
|
"github.com/hyperledger/fabric/integration/channelparticipation"
|
|
"github.com/hyperledger/fabric/integration/nwo"
|
|
"github.com/hyperledger/fabric/integration/nwo/commands"
|
|
"github.com/hyperledger/fabric/integration/nwo/fabricconfig"
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
"github.com/onsi/gomega/gbytes"
|
|
"github.com/onsi/gomega/gexec"
|
|
"github.com/tedsuo/ifrit"
|
|
ginkgomon "github.com/tedsuo/ifrit/ginkgomon_v2"
|
|
)
|
|
|
|
var _ = Describe("EndToEnd", func() {
|
|
var (
|
|
testDir string
|
|
client *docker.Client
|
|
network *nwo.Network
|
|
chaincode nwo.Chaincode
|
|
ordererRunner *ginkgomon.Runner
|
|
ordererProcess, peerProcess ifrit.Process
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
var err error
|
|
testDir, err = ioutil.TempDir("", "e2e")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
client, err = docker.NewClientFromEnv()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
chaincode = nwo.Chaincode{
|
|
Name: "mycc",
|
|
Version: "0.0",
|
|
Path: components.Build("github.com/hyperledger/fabric/integration/chaincode/simple/cmd"),
|
|
Lang: "binary",
|
|
PackageFile: filepath.Join(testDir, "simplecc.tar.gz"),
|
|
Ctor: `{"Args":["init","a","100","b","200"]}`,
|
|
SignaturePolicy: `AND ('Org1MSP.member','Org2MSP.member')`,
|
|
Sequence: "1",
|
|
InitRequired: true,
|
|
Label: "my_prebuilt_chaincode",
|
|
}
|
|
})
|
|
|
|
AfterEach(func() {
|
|
if ordererProcess != nil {
|
|
ordererProcess.Signal(syscall.SIGTERM)
|
|
Eventually(ordererProcess.Wait(), network.EventuallyTimeout).Should(Receive())
|
|
}
|
|
|
|
if peerProcess != nil {
|
|
peerProcess.Signal(syscall.SIGTERM)
|
|
Eventually(peerProcess.Wait(), network.EventuallyTimeout).Should(Receive())
|
|
}
|
|
|
|
if network != nil {
|
|
network.Cleanup()
|
|
}
|
|
os.RemoveAll(testDir)
|
|
})
|
|
|
|
Describe("basic etcdraft network with 2 orgs and no docker", func() {
|
|
var (
|
|
metricsReader *MetricsReader
|
|
runArtifactsFilePath string
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
metricsReader = NewMetricsReader()
|
|
go metricsReader.Start()
|
|
|
|
network = nwo.New(nwo.BasicEtcdRaft(), testDir, nil, StartPort(), components)
|
|
network.MetricsProvider = "statsd"
|
|
network.StatsdEndpoint = metricsReader.Address()
|
|
network.Channels = append(network.Channels, &nwo.Channel{
|
|
Name: "another-testchannel",
|
|
Profile: "TwoOrgsAppChannelEtcdRaft",
|
|
})
|
|
|
|
runArtifactsFilePath = filepath.Join(testDir, "run-artifacts.txt")
|
|
os.Setenv("RUN_ARTIFACTS_FILE", runArtifactsFilePath)
|
|
for i, e := range network.ExternalBuilders {
|
|
e.PropagateEnvironment = append(e.PropagateEnvironment, "RUN_ARTIFACTS_FILE")
|
|
network.ExternalBuilders[i] = e
|
|
}
|
|
|
|
network.GenerateConfigTree()
|
|
for _, peer := range network.PeersWithChannel("testchannel") {
|
|
core := network.ReadPeerConfig(peer)
|
|
core.VM = nil
|
|
network.WritePeerConfig(peer, core)
|
|
}
|
|
|
|
network.Bootstrap()
|
|
|
|
// Start all the fabric processes
|
|
ordererRunner, ordererProcess, peerProcess = network.StartSingleOrdererNetwork("orderer")
|
|
})
|
|
|
|
AfterEach(func() {
|
|
if metricsReader != nil {
|
|
metricsReader.Close()
|
|
}
|
|
|
|
// Terminate the processes but defer the network cleanup to the outer
|
|
// AfterEach.
|
|
if ordererProcess != nil {
|
|
ordererProcess.Signal(syscall.SIGTERM)
|
|
Eventually(ordererProcess.Wait(), network.EventuallyTimeout).Should(Receive())
|
|
}
|
|
|
|
if peerProcess != nil {
|
|
peerProcess.Signal(syscall.SIGTERM)
|
|
Eventually(peerProcess.Wait(), network.EventuallyTimeout).Should(Receive())
|
|
}
|
|
|
|
// Ensure that the temporary directories generated by launched external
|
|
// chaincodes have been cleaned up. This must be done after the peers
|
|
// have been terminated.
|
|
contents, err := ioutil.ReadFile(runArtifactsFilePath)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
scanner := bufio.NewScanner(bytes.NewBuffer(contents))
|
|
for scanner.Scan() {
|
|
Expect(scanner.Text()).NotTo(BeAnExistingFile())
|
|
}
|
|
})
|
|
|
|
It("executes a basic etcdraft network with 2 orgs and no docker", func() {
|
|
By("getting the orderer by name")
|
|
orderer := network.Orderer("orderer")
|
|
|
|
By("listing channels with osnadmin, no channels yet")
|
|
tlsdir := network.OrdererLocalTLSDir(orderer)
|
|
sess, err := network.Osnadmin(commands.ChannelList{
|
|
OrdererAddress: network.OrdererAddress(orderer, nwo.AdminPort),
|
|
CAFile: filepath.Join(tlsdir, "ca.crt"),
|
|
ClientCert: filepath.Join(tlsdir, "server.crt"),
|
|
ClientKey: filepath.Join(tlsdir, "server.key"),
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess).Should(gexec.Exit(0))
|
|
var channelList channelparticipation.ChannelList
|
|
err = json.Unmarshal(sess.Out.Contents(), &channelList)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(channelList).To(Equal(channelparticipation.ChannelList{}))
|
|
|
|
By("setting up the channel")
|
|
channelparticipation.JoinOrdererJoinPeersAppChannel(network, "testchannel", orderer, ordererRunner)
|
|
|
|
By("listing channels with osnadmin")
|
|
sess, err = network.Osnadmin(commands.ChannelList{
|
|
OrdererAddress: network.OrdererAddress(orderer, nwo.AdminPort),
|
|
CAFile: filepath.Join(tlsdir, "ca.crt"),
|
|
ClientCert: filepath.Join(tlsdir, "server.crt"),
|
|
ClientKey: filepath.Join(tlsdir, "server.key"),
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess).Should(gexec.Exit(0))
|
|
err = json.Unmarshal(sess.Out.Contents(), &channelList)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(channelList).To(Equal(channelparticipation.ChannelList{
|
|
Channels: []channelparticipation.ChannelInfoShort{{
|
|
Name: "testchannel",
|
|
URL: "/participation/v1/channels/testchannel",
|
|
}},
|
|
}))
|
|
|
|
By("enabling capabilities V2_5")
|
|
nwo.EnableCapabilities(network, "testchannel", "Application", "V2_5", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
|
|
|
|
By("attempting to install unsupported chaincode without docker")
|
|
badCC := chaincode
|
|
badCC.Lang = "unsupported-type"
|
|
badCC.Label = "chaincode-label"
|
|
badCC.PackageFile = filepath.Join(testDir, "unsupported-type.tar.gz")
|
|
nwo.PackageChaincodeBinary(badCC)
|
|
badCC.SetPackageIDFromPackageFile()
|
|
sess, err = network.PeerAdminSession(
|
|
network.Peer("Org1", "peer0"),
|
|
commands.ChaincodeInstall{
|
|
PackageFile: badCC.PackageFile,
|
|
ClientAuth: network.ClientAuthRequired,
|
|
},
|
|
)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1))
|
|
Expect(sess.Err).To(gbytes.Say("docker build is disabled"))
|
|
|
|
By("deploying the chaincode")
|
|
nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
|
|
|
|
By("ensuring external cc run artifacts exist after deploying")
|
|
contents, err := ioutil.ReadFile(runArtifactsFilePath)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
scanner := bufio.NewScanner(bytes.NewBuffer(contents))
|
|
for scanner.Scan() {
|
|
Expect(scanner.Text()).To(BeADirectory())
|
|
}
|
|
|
|
By("getting the client peer by name")
|
|
peer := network.Peer("Org1", "peer0")
|
|
|
|
RunQueryInvokeQuery(network, orderer, peer, "testchannel")
|
|
RunRespondWith(network, orderer, peer, "testchannel")
|
|
|
|
By("evaluating statsd metrics")
|
|
metricsWriteInterval := 5 * time.Second
|
|
CheckPeerStatsdStreamMetrics(metricsReader, 2*metricsWriteInterval)
|
|
CheckPeerStatsdMetrics("org1_peer0", metricsReader, 2*metricsWriteInterval)
|
|
CheckPeerStatsdMetrics("org2_peer0", metricsReader, 2*metricsWriteInterval)
|
|
|
|
By("checking for orderer metrics")
|
|
CheckOrdererStatsdMetrics("ordererorg_orderer", metricsReader, 2*metricsWriteInterval)
|
|
|
|
By("setting up another channel from a the same profile")
|
|
channelparticipation.JoinOrdererJoinPeersAppChannel(network, "another-testchannel", orderer, ordererRunner)
|
|
|
|
By("listing channels with osnadmin")
|
|
sess, err = network.Osnadmin(commands.ChannelList{
|
|
OrdererAddress: network.OrdererAddress(orderer, nwo.AdminPort),
|
|
CAFile: filepath.Join(tlsdir, "ca.crt"),
|
|
ClientCert: filepath.Join(tlsdir, "server.crt"),
|
|
ClientKey: filepath.Join(tlsdir, "server.key"),
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess).Should(gexec.Exit(0))
|
|
err = json.Unmarshal(sess.Out.Contents(), &channelList)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
sort.Slice(channelList.Channels, func(i, j int) bool {
|
|
return channelList.Channels[i].Name < channelList.Channels[j].Name
|
|
})
|
|
Expect(channelList).To(Equal(channelparticipation.ChannelList{
|
|
Channels: []channelparticipation.ChannelInfoShort{
|
|
{
|
|
Name: "another-testchannel",
|
|
URL: "/participation/v1/channels/another-testchannel",
|
|
},
|
|
{
|
|
Name: "testchannel",
|
|
URL: "/participation/v1/channels/testchannel",
|
|
},
|
|
},
|
|
}))
|
|
})
|
|
})
|
|
|
|
Describe("basic etcdraft network with docker chaincode builds", func() {
|
|
BeforeEach(func() {
|
|
network = nwo.New(nwo.BasicEtcdRaft(), testDir, client, StartPort(), components)
|
|
network.MetricsProvider = "prometheus"
|
|
network.GenerateConfigTree()
|
|
network.Bootstrap()
|
|
|
|
// Start all the fabric processes
|
|
ordererRunner, ordererProcess, peerProcess = network.StartSingleOrdererNetwork("orderer")
|
|
})
|
|
|
|
It("builds and executes transactions with docker chaincode", func() {
|
|
chaincodePath, err := filepath.Abs("../chaincode/module")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
// use these two variants of the same chaincode to ensure we test
|
|
// the golang docker build for both module and gopath chaincode
|
|
chaincode := nwo.Chaincode{
|
|
Name: "mycc",
|
|
Version: "0.0",
|
|
Path: chaincodePath,
|
|
Lang: "golang",
|
|
PackageFile: filepath.Join(testDir, "modulecc.tar.gz"),
|
|
Ctor: `{"Args":["init","a","100","b","200"]}`,
|
|
SignaturePolicy: `AND ('Org1MSP.member','Org2MSP.member')`,
|
|
Sequence: "1",
|
|
InitRequired: true,
|
|
Label: "my_module_chaincode",
|
|
}
|
|
|
|
gopathChaincode := nwo.Chaincode{
|
|
Name: "mycc",
|
|
Version: "0.0",
|
|
Path: "github.com/hyperledger/fabric/integration/chaincode/simple/cmd",
|
|
Lang: "golang",
|
|
PackageFile: filepath.Join(testDir, "simplecc.tar.gz"),
|
|
Ctor: `{"Args":["init","a","100","b","200"]}`,
|
|
SignaturePolicy: `AND ('Org1MSP.member','Org2MSP.member')`,
|
|
Sequence: "1",
|
|
InitRequired: true,
|
|
Label: "my_simple_chaincode",
|
|
}
|
|
|
|
orderer := network.Orderer("orderer")
|
|
|
|
By("setting up the channel")
|
|
channelparticipation.JoinOrdererJoinPeersAppChannel(network, "testchannel", orderer, ordererRunner)
|
|
|
|
cl := channelparticipation.List(network, orderer)
|
|
channelparticipation.ChannelListMatcher(cl, []string{"testchannel"})
|
|
|
|
nwo.EnableCapabilities(network, "testchannel", "Application", "V2_5", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
|
|
|
|
// package, install, and approve by org1 - module chaincode
|
|
packageInstallApproveChaincode(network, "testchannel", orderer, chaincode, network.Peer("Org1", "peer0"))
|
|
|
|
// package, install, and approve by org2 - gopath chaincode, same logic
|
|
packageInstallApproveChaincode(network, "testchannel", orderer, gopathChaincode, network.Peer("Org2", "peer0"))
|
|
|
|
testPeers := network.PeersWithChannel("testchannel")
|
|
nwo.CheckCommitReadinessUntilReady(network, "testchannel", chaincode, network.PeerOrgs(), testPeers...)
|
|
nwo.CommitChaincode(network, "testchannel", orderer, chaincode, testPeers[0], testPeers...)
|
|
nwo.InitChaincode(network, "testchannel", orderer, chaincode, testPeers...)
|
|
|
|
By("listing the containers after committing the chaincode definition")
|
|
initialContainerFilter := map[string][]string{
|
|
"name": {
|
|
chaincodeContainerNameFilter(network, chaincode),
|
|
chaincodeContainerNameFilter(network, gopathChaincode),
|
|
},
|
|
}
|
|
|
|
containers, err := client.ListContainers(docker.ListContainersOptions{Filters: initialContainerFilter})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(containers).To(HaveLen(2))
|
|
|
|
RunQueryInvokeQuery(network, orderer, network.Peer("Org1", "peer0"), "testchannel")
|
|
|
|
By("evaluating the operations endpoint and prometheus metrics")
|
|
CheckPeerOperationEndpoints(network, network.Peer("Org2", "peer0"))
|
|
CheckOrdererOperationEndpoints(network, orderer)
|
|
|
|
// upgrade chaincode to v2.0 with different label
|
|
chaincode.Version = "1.0"
|
|
chaincode.Sequence = "2"
|
|
chaincode.Label = "my_module_chaincode_updated"
|
|
gopathChaincode.Version = "1.0"
|
|
gopathChaincode.Sequence = "2"
|
|
gopathChaincode.Label = "my_simple_chaincode_updated"
|
|
|
|
// package, install, and approve by org1 - module chaincode
|
|
packageInstallApproveChaincode(network, "testchannel", orderer, chaincode, network.Peer("Org1", "peer0"))
|
|
|
|
// package, install, and approve by org2 - gopath chaincode, same logic
|
|
packageInstallApproveChaincode(network, "testchannel", orderer, gopathChaincode, network.Peer("Org2", "peer0"))
|
|
|
|
nwo.CheckCommitReadinessUntilReady(network, "testchannel", chaincode, network.PeerOrgs(), testPeers...)
|
|
nwo.CommitChaincode(network, "testchannel", orderer, chaincode, testPeers[0], testPeers...)
|
|
nwo.InitChaincode(network, "testchannel", orderer, chaincode, testPeers...)
|
|
|
|
By("listing the containers after updating the chaincode definition")
|
|
// expect the containers for the previous package id to be stopped
|
|
containers, err = client.ListContainers(docker.ListContainersOptions{Filters: initialContainerFilter})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(containers).To(HaveLen(0))
|
|
updatedContainerFilter := map[string][]string{
|
|
"name": {
|
|
chaincodeContainerNameFilter(network, chaincode),
|
|
chaincodeContainerNameFilter(network, gopathChaincode),
|
|
},
|
|
}
|
|
containers, err = client.ListContainers(docker.ListContainersOptions{Filters: updatedContainerFilter})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(containers).To(HaveLen(2))
|
|
|
|
RunQueryInvokeQuery(network, orderer, network.Peer("Org1", "peer0"), "testchannel")
|
|
|
|
By("retrieving the local mspid of the peer via simple chaincode")
|
|
sess, err := network.PeerUserSession(network.Peer("Org2", "peer0"), "User1", commands.ChaincodeQuery{
|
|
ChannelID: "testchannel",
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["mspid"]}`,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
|
|
Expect(sess).To(gbytes.Say("Org2MSP"))
|
|
})
|
|
})
|
|
|
|
Describe("basic single node etcdraft network with static leader", func() {
|
|
var (
|
|
peerRunners []*ginkgomon.Runner
|
|
processes map[string]ifrit.Process
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
network = nwo.New(nwo.MultiChannelEtcdRaft(), testDir, client, StartPort(), components)
|
|
network.GenerateConfigTree()
|
|
for _, peer := range network.Peers {
|
|
core := network.ReadPeerConfig(peer)
|
|
core.Peer.Gossip.UseLeaderElection = false
|
|
core.Peer.Gossip.OrgLeader = true
|
|
core.Peer.Deliveryclient.ReconnectTotalTimeThreshold = time.Second
|
|
network.WritePeerConfig(peer, core)
|
|
}
|
|
network.Bootstrap()
|
|
|
|
ordererRunner = network.OrdererRunner(network.Orderer("orderer"))
|
|
ordererProcess = ifrit.Invoke(ordererRunner)
|
|
Eventually(ordererProcess.Ready(), network.EventuallyTimeout).Should(BeClosed())
|
|
|
|
peerRunners = make([]*ginkgomon.Runner, len(network.Peers))
|
|
processes = map[string]ifrit.Process{}
|
|
for i, peer := range network.Peers {
|
|
pr := network.PeerRunner(peer)
|
|
peerRunners[i] = pr
|
|
p := ifrit.Invoke(pr)
|
|
processes[peer.ID()] = p
|
|
Eventually(p.Ready(), network.EventuallyTimeout).Should(BeClosed())
|
|
}
|
|
})
|
|
|
|
AfterEach(func() {
|
|
for _, p := range processes {
|
|
p.Signal(syscall.SIGTERM)
|
|
Eventually(p.Wait(), network.EventuallyTimeout).Should(Receive())
|
|
}
|
|
})
|
|
|
|
It("creates two channels with two orgs trying to reconfigure and update metadata", func() {
|
|
orderer := network.Orderer("orderer")
|
|
|
|
By("Create first channel and deploy the chaincode")
|
|
channelparticipation.JoinOrdererJoinPeersAppChannel(network, "testchannel", orderer, ordererRunner)
|
|
|
|
nwo.EnableCapabilities(network, "testchannel", "Application", "V2_5", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
|
|
nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
|
|
peer := network.Peer("Org1", "peer0")
|
|
RunQueryInvokeQuery(network, orderer, peer, "testchannel")
|
|
|
|
By("Create second channel and deploy chaincode")
|
|
channelparticipation.JoinOrdererJoinPeersAppChannel(network, "testchannel2", orderer, ordererRunner)
|
|
|
|
cl := channelparticipation.List(network, orderer)
|
|
channelparticipation.ChannelListMatcher(cl, []string{"testchannel", "testchannel2"})
|
|
|
|
nwo.EnableCapabilities(network, "testchannel2", "Application", "V2_5", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
|
|
peers := network.PeersWithChannel("testchannel2")
|
|
nwo.ApproveChaincodeForMyOrg(network, "testchannel2", orderer, chaincode, peers...)
|
|
nwo.CheckCommitReadinessUntilReady(network, "testchannel2", chaincode, network.PeerOrgs(), peers...)
|
|
nwo.CommitChaincode(network, "testchannel2", orderer, chaincode, peers[0], peers...)
|
|
nwo.InitChaincode(network, "testchannel2", orderer, chaincode, peers...)
|
|
RunQueryInvokeQuery(network, orderer, peer, "testchannel2")
|
|
|
|
By("Update consensus metadata to increase snapshot interval")
|
|
snapDir := path.Join(network.RootDir, "orderers", orderer.ID(), "etcdraft", "snapshot", "testchannel")
|
|
files, err := ioutil.ReadDir(snapDir)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
numOfSnaps := len(files)
|
|
|
|
nwo.UpdateConsensusMetadata(network, peer, orderer, "testchannel", func(originalMetadata []byte) []byte {
|
|
metadata := &etcdraft.ConfigMetadata{}
|
|
err := proto.Unmarshal(originalMetadata, metadata)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
// update max in flight messages
|
|
metadata.Options.MaxInflightBlocks = 1000
|
|
metadata.Options.SnapshotIntervalSize = 10 * 1024 * 1024 // 10 MB
|
|
|
|
// write metadata back
|
|
newMetadata, err := proto.Marshal(metadata)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
return newMetadata
|
|
})
|
|
|
|
// assert that no new snapshot is taken because SnapshotIntervalSize has just enlarged
|
|
files, err = ioutil.ReadDir(snapDir)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(len(files)).To(Equal(numOfSnaps))
|
|
|
|
By("ensuring that static leaders do not give up on retrieving blocks after the orderer goes down")
|
|
ordererProcess.Signal(syscall.SIGTERM)
|
|
Eventually(ordererProcess.Wait(), network.EventuallyTimeout).Should(Receive())
|
|
for _, peerRunner := range peerRunners {
|
|
Eventually(peerRunner.Err(), network.EventuallyTimeout).Should(gbytes.Say("peer is a static leader, ignoring peer.deliveryclient.reconnectTotalTimeThreshold"))
|
|
}
|
|
})
|
|
})
|
|
|
|
Describe("single node etcdraft network with remapped orderer endpoints", func() {
|
|
BeforeEach(func() {
|
|
network = nwo.New(nwo.MinimalRaft(), testDir, client, StartPort(), components)
|
|
network.GenerateConfigTree()
|
|
|
|
configtxConfig := network.ReadConfigTxConfig()
|
|
ordererEndpoints := configtxConfig.Profiles["OneOrgChannelEtcdRaft"].Orderer.Organizations[0].OrdererEndpoints
|
|
correctOrdererEndpoint := ordererEndpoints[0]
|
|
ordererEndpoints[0] = "127.0.0.1:1"
|
|
network.WriteConfigTxConfig(configtxConfig)
|
|
|
|
peer := network.Peer("Org1", "peer0")
|
|
peerConfig := network.ReadPeerConfig(peer)
|
|
peerConfig.Peer.Deliveryclient.AddressOverrides = []*fabricconfig.AddressOverride{
|
|
{
|
|
From: "127.0.0.1:1",
|
|
To: correctOrdererEndpoint,
|
|
CACertsFile: network.CACertsBundlePath(),
|
|
},
|
|
}
|
|
network.WritePeerConfig(peer, peerConfig)
|
|
|
|
network.Bootstrap()
|
|
|
|
// Start all the fabric processes
|
|
ordererRunner, ordererProcess, peerProcess = network.StartSingleOrdererNetwork("orderer")
|
|
})
|
|
|
|
It("creates and updates channel", func() {
|
|
orderer := network.Orderer("orderer")
|
|
channelparticipation.JoinOrdererJoinPeersAppChannel(network, "testchannel", orderer, ordererRunner)
|
|
|
|
// The below call waits for the config update to commit on the peer, so
|
|
// it will fail if the orderer addresses are wrong.
|
|
nwo.EnableCapabilities(network, "testchannel", "Application", "V2_5", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
|
|
})
|
|
})
|
|
|
|
Describe("basic etcdraft network with containers being interrupted", func() {
|
|
BeforeEach(func() {
|
|
network = nwo.New(nwo.FullEtcdRaft(), testDir, client, StartPort(), components)
|
|
|
|
network.GenerateConfigTree()
|
|
network.Bootstrap()
|
|
|
|
// Start all the fabric processes
|
|
ordererRunner, ordererProcess, peerProcess = network.StartSingleOrdererNetwork("orderer")
|
|
})
|
|
|
|
It("recreates terminated chaincode containers", func() {
|
|
chaincode := nwo.Chaincode{
|
|
Name: "mycc",
|
|
Version: "0.0",
|
|
Path: "github.com/hyperledger/fabric/integration/chaincode/simple/cmd",
|
|
Lang: "golang",
|
|
PackageFile: filepath.Join(testDir, "simplecc.tar.gz"),
|
|
Ctor: `{"Args":["init","a","100","b","200"]}`,
|
|
SignaturePolicy: `OR ('Org1MSP.peer', 'Org2MSP.peer')`,
|
|
Sequence: "1",
|
|
InitRequired: true,
|
|
Label: "my_simple_chaincode",
|
|
}
|
|
|
|
orderer := network.Orderer("orderer")
|
|
|
|
By("creating and joining channels")
|
|
channelparticipation.JoinOrdererJoinPeersAppChannel(network, "testchannel", orderer, ordererRunner)
|
|
|
|
By("enabling new lifecycle capabilities")
|
|
nwo.EnableCapabilities(network, "testchannel", "Application", "V2_5", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
|
|
By("deploying the chaincode")
|
|
nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
|
|
|
|
By("querying and invoking chaincode")
|
|
peer := network.Peers[0]
|
|
RunQueryInvokeQuery(network, orderer, peer, "testchannel")
|
|
|
|
By("removing chaincode containers from all peers")
|
|
listChaincodeContainers := docker.ListContainersOptions{
|
|
Filters: map[string][]string{
|
|
"name": {chaincodeContainerNameFilter(network, chaincode)},
|
|
},
|
|
}
|
|
ctx := context.Background()
|
|
containers, err := client.ListContainers(listChaincodeContainers)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(containers).NotTo(BeEmpty())
|
|
|
|
var originalContainerIDs []string
|
|
for _, container := range containers {
|
|
originalContainerIDs = append(originalContainerIDs, container.ID)
|
|
err = client.RemoveContainer(docker.RemoveContainerOptions{
|
|
ID: container.ID,
|
|
RemoveVolumes: true,
|
|
Force: true,
|
|
Context: ctx,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
}
|
|
|
|
By("invoking chaincode against all peers in test channel")
|
|
for _, peer := range network.Peers {
|
|
sess, err := network.PeerUserSession(peer, "User1", commands.ChaincodeInvoke{
|
|
ChannelID: "testchannel",
|
|
Orderer: network.OrdererAddress(orderer, nwo.ListenPort),
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["invoke","a","b","10"]}`,
|
|
PeerAddresses: []string{
|
|
network.PeerAddress(peer, nwo.ListenPort),
|
|
},
|
|
WaitForEvent: true,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
|
|
Expect(sess.Err).To(gbytes.Say("Chaincode invoke successful. result: status:200"))
|
|
}
|
|
|
|
By("checking successful removals of all old chaincode containers")
|
|
newContainers, err := client.ListContainers(listChaincodeContainers)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(newContainers).To(HaveLen(len(containers)))
|
|
|
|
for _, container := range newContainers {
|
|
Expect(originalContainerIDs).NotTo(ContainElement(container.ID))
|
|
}
|
|
})
|
|
})
|
|
|
|
Describe("basic lifecycle operations for chaincode install and update", func() {
|
|
BeforeEach(func() {
|
|
network = nwo.New(nwo.BasicEtcdRaft(), testDir, client, StartPort(), components)
|
|
|
|
network.GenerateConfigTree()
|
|
network.Bootstrap()
|
|
|
|
// Start all the fabric processes
|
|
ordererRunner, ordererProcess, peerProcess = network.StartSingleOrdererNetwork("orderer")
|
|
})
|
|
|
|
It("approves chaincode for org and updates chaincode definition", func() {
|
|
chaincode := nwo.Chaincode{
|
|
Name: "mycc",
|
|
Version: "0.0",
|
|
Path: "github.com/hyperledger/fabric/integration/chaincode/simple/cmd",
|
|
Lang: "golang",
|
|
PackageFile: filepath.Join(testDir, "simplecc.tar.gz"),
|
|
Ctor: `{"Args":["init","a","100","b","200"]}`,
|
|
SignaturePolicy: `OR ('Org1MSP.peer', 'Org2MSP.peer')`,
|
|
Sequence: "1",
|
|
InitRequired: true,
|
|
Label: "my_simple_chaincode",
|
|
}
|
|
|
|
orderer := network.Orderer("orderer")
|
|
|
|
By("creating and joining channels")
|
|
channelparticipation.JoinOrdererJoinPeersAppChannel(network, "testchannel", orderer, ordererRunner)
|
|
|
|
By("enabling new lifecycle capabilities")
|
|
nwo.EnableCapabilities(network, "testchannel", "Application", "V2_5", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
|
|
By("deploying the chaincode")
|
|
peers := network.PeersWithChannel("testchannel")
|
|
nwo.PackageAndInstallChaincode(network, chaincode, peers...)
|
|
|
|
// approve for each org
|
|
nwo.ApproveChaincodeForMyOrg(network, "testchannel", orderer, chaincode, peers...)
|
|
// commit definition
|
|
nwo.CheckCommitReadinessUntilReady(network, "testchannel", chaincode, network.PeerOrgs(), peers...)
|
|
|
|
// update chaincode endorsement policy and commit again
|
|
By("update chaincode's endorsement policy")
|
|
chaincode.SignaturePolicy = `AND ('Org1MSP.peer', 'Org2MSP.peer')`
|
|
nwo.ApproveChaincodeForMyOrg(network, "testchannel", orderer, chaincode, peers...)
|
|
nwo.CheckCommitReadinessUntilReady(network, "testchannel", chaincode, network.PeerOrgs(), peers...)
|
|
|
|
// finall commit the chaincode
|
|
By("committing chaincode's definition")
|
|
nwo.CommitChaincode(network, "testchannel", orderer, chaincode, peers[0], peers...)
|
|
|
|
if chaincode.PackageID == "" {
|
|
chaincode.SetPackageIDFromPackageFile()
|
|
}
|
|
|
|
By("attempting to approve chaincode definition after commit")
|
|
sess, err := network.PeerAdminSession(peers[0], commands.ChaincodeApproveForMyOrg{
|
|
ChannelID: "testchannel",
|
|
Orderer: network.OrdererAddress(orderer, nwo.ListenPort),
|
|
Name: chaincode.Name,
|
|
Version: chaincode.Version,
|
|
PackageID: chaincode.PackageID,
|
|
Sequence: chaincode.Sequence,
|
|
EndorsementPlugin: chaincode.EndorsementPlugin,
|
|
ValidationPlugin: chaincode.ValidationPlugin,
|
|
SignaturePolicy: chaincode.SignaturePolicy,
|
|
ChannelConfigPolicy: chaincode.ChannelConfigPolicy,
|
|
InitRequired: chaincode.InitRequired,
|
|
CollectionsConfig: chaincode.CollectionsConfig,
|
|
ClientAuth: network.ClientAuthRequired,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess.Err, network.EventuallyTimeout).Should(gbytes.Say(`Error: proposal failed with status: 500`))
|
|
})
|
|
})
|
|
})
|
|
|
|
func RunQueryInvokeQuery(n *nwo.Network, orderer *nwo.Orderer, peer *nwo.Peer, channel string) {
|
|
By("querying the chaincode")
|
|
sess, err := n.PeerUserSession(peer, "User1", commands.ChaincodeQuery{
|
|
ChannelID: channel,
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["query","a"]}`,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
Expect(sess).To(gbytes.Say("100"))
|
|
|
|
sess, err = n.PeerUserSession(peer, "User1", commands.ChaincodeInvoke{
|
|
ChannelID: channel,
|
|
Orderer: n.OrdererAddress(orderer, nwo.ListenPort),
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["invoke","a","b","10"]}`,
|
|
PeerAddresses: []string{
|
|
n.PeerAddress(n.Peer("Org1", "peer0"), nwo.ListenPort),
|
|
n.PeerAddress(n.Peer("Org2", "peer0"), nwo.ListenPort),
|
|
},
|
|
WaitForEvent: true,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
Expect(sess.Err).To(gbytes.Say("Chaincode invoke successful. result: status:200"))
|
|
|
|
sess, err = n.PeerUserSession(peer, "User1", commands.ChaincodeQuery{
|
|
ChannelID: channel,
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["query","a"]}`,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
Expect(sess).To(gbytes.Say("90"))
|
|
}
|
|
|
|
func RunRespondWith(n *nwo.Network, orderer *nwo.Orderer, peer *nwo.Peer, channel string) {
|
|
By("responding with a 300")
|
|
sess, err := n.PeerUserSession(peer, "User1", commands.ChaincodeInvoke{
|
|
ChannelID: channel,
|
|
Orderer: n.OrdererAddress(orderer, nwo.ListenPort),
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["respond","300","response-message","response-payload"]}`,
|
|
PeerAddresses: []string{
|
|
n.PeerAddress(n.Peer("Org1", "peer0"), nwo.ListenPort),
|
|
n.PeerAddress(n.Peer("Org2", "peer0"), nwo.ListenPort),
|
|
},
|
|
WaitForEvent: true,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
|
|
Expect(sess.Err).To(gbytes.Say("Chaincode invoke successful. result: status:300"))
|
|
|
|
By("responding with a 400")
|
|
sess, err = n.PeerUserSession(peer, "User1", commands.ChaincodeInvoke{
|
|
ChannelID: channel,
|
|
Orderer: n.OrdererAddress(orderer, nwo.ListenPort),
|
|
Name: "mycc",
|
|
Ctor: `{"Args":["respond","400","response-message","response-payload"]}`,
|
|
PeerAddresses: []string{
|
|
n.PeerAddress(n.Peer("Org1", "peer0"), nwo.ListenPort),
|
|
n.PeerAddress(n.Peer("Org2", "peer0"), nwo.ListenPort),
|
|
},
|
|
WaitForEvent: true,
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(1))
|
|
Expect(sess.Err).To(gbytes.Say(`Error: endorsement failure during invoke.`))
|
|
}
|
|
|
|
func CheckPeerStatsdMetrics(prefix string, mr *MetricsReader, timeout time.Duration) {
|
|
By("checking for peer statsd metrics")
|
|
Eventually(mr.String, timeout).Should(SatisfyAll(
|
|
ContainSubstring(prefix+".logging.entries_checked.info:"),
|
|
ContainSubstring(prefix+".logging.entries_written.info:"),
|
|
ContainSubstring(prefix+".go.mem.gc_completed_count:"),
|
|
ContainSubstring(prefix+".grpc.server.unary_requests_received.protos_Endorser.ProcessProposal:"),
|
|
ContainSubstring(prefix+".grpc.server.unary_requests_completed.protos_Endorser.ProcessProposal.OK:"),
|
|
ContainSubstring(prefix+".grpc.server.unary_request_duration.protos_Endorser.ProcessProposal.OK:"),
|
|
ContainSubstring(prefix+".ledger.blockchain_height"),
|
|
ContainSubstring(prefix+".ledger.blockstorage_commit_time"),
|
|
ContainSubstring(prefix+".ledger.blockstorage_and_pvtdata_commit_time"),
|
|
))
|
|
}
|
|
|
|
func CheckPeerStatsdStreamMetrics(mr *MetricsReader, timeout time.Duration) {
|
|
By("checking for stream metrics")
|
|
Eventually(mr.String, timeout).Should(SatisfyAll(
|
|
ContainSubstring(".grpc.server.stream_requests_received.protos_Deliver.DeliverFiltered:"),
|
|
ContainSubstring(".grpc.server.stream_requests_completed.protos_Deliver.DeliverFiltered.Unknown:"),
|
|
ContainSubstring(".grpc.server.stream_request_duration.protos_Deliver.DeliverFiltered.Unknown:"),
|
|
ContainSubstring(".grpc.server.stream_messages_received.protos_Deliver.DeliverFiltered"),
|
|
ContainSubstring(".grpc.server.stream_messages_sent.protos_Deliver.DeliverFiltered"),
|
|
))
|
|
}
|
|
|
|
func CheckOrdererStatsdMetrics(prefix string, mr *MetricsReader, timeout time.Duration) {
|
|
Eventually(mr.String, timeout).Should(SatisfyAll(
|
|
ContainSubstring(prefix+".consensus.etcdraft.committed_block_number"),
|
|
ContainSubstring(prefix+".participation.consensus_relation"),
|
|
ContainSubstring(prefix+".grpc.server.stream_request_duration.orderer_AtomicBroadcast.Deliver."),
|
|
ContainSubstring(prefix+".logging.entries_checked.info:"),
|
|
ContainSubstring(prefix+".logging.entries_written.info:"),
|
|
ContainSubstring(prefix+".go.mem.gc_completed_count:"),
|
|
ContainSubstring(prefix+".grpc.server.stream_requests_received.orderer_AtomicBroadcast.Deliver:"),
|
|
ContainSubstring(prefix+".grpc.server.stream_requests_completed.orderer_AtomicBroadcast.Deliver."),
|
|
ContainSubstring(prefix+".grpc.server.stream_messages_received.orderer_AtomicBroadcast.Deliver"),
|
|
ContainSubstring(prefix+".grpc.server.stream_messages_sent.orderer_AtomicBroadcast.Deliver"),
|
|
ContainSubstring(prefix+".ledger.blockchain_height"),
|
|
ContainSubstring(prefix+".ledger.blockstorage_commit_time"),
|
|
))
|
|
}
|
|
|
|
func CheckPeerOperationEndpoints(network *nwo.Network, peer *nwo.Peer) {
|
|
metricsURL := fmt.Sprintf("https://127.0.0.1:%d/metrics", network.PeerPort(peer, nwo.OperationsPort))
|
|
logspecURL := fmt.Sprintf("https://127.0.0.1:%d/logspec", network.PeerPort(peer, nwo.OperationsPort))
|
|
healthURL := fmt.Sprintf("https://127.0.0.1:%d/healthz", network.PeerPort(peer, nwo.OperationsPort))
|
|
|
|
authClient, unauthClient := nwo.PeerOperationalClients(network, peer)
|
|
|
|
CheckPeerPrometheusMetrics(authClient, metricsURL)
|
|
CheckLogspecOperations(authClient, logspecURL)
|
|
CheckHealthEndpoint(authClient, healthURL)
|
|
|
|
By("getting the logspec without a client cert")
|
|
resp, err := unauthClient.Get(logspecURL)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(resp.StatusCode).To(Equal(http.StatusUnauthorized))
|
|
|
|
By("ensuring health checks do not require a client cert")
|
|
CheckHealthEndpoint(unauthClient, healthURL)
|
|
}
|
|
|
|
func CheckOrdererOperationEndpoints(network *nwo.Network, orderer *nwo.Orderer) {
|
|
metricsURL := fmt.Sprintf("https://127.0.0.1:%d/metrics", network.OrdererPort(orderer, nwo.OperationsPort))
|
|
logspecURL := fmt.Sprintf("https://127.0.0.1:%d/logspec", network.OrdererPort(orderer, nwo.OperationsPort))
|
|
healthURL := fmt.Sprintf("https://127.0.0.1:%d/healthz", network.OrdererPort(orderer, nwo.OperationsPort))
|
|
|
|
authClient, unauthClient := nwo.OrdererOperationalClients(network, orderer)
|
|
|
|
CheckOrdererPrometheusMetrics(authClient, metricsURL)
|
|
CheckLogspecOperations(authClient, logspecURL)
|
|
CheckHealthEndpoint(authClient, healthURL)
|
|
|
|
By("getting the logspec without a client cert")
|
|
resp, err := unauthClient.Get(logspecURL)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(resp.StatusCode).To(Equal(http.StatusUnauthorized))
|
|
|
|
By("ensuring health checks do not require a client cert")
|
|
CheckHealthEndpoint(unauthClient, healthURL)
|
|
}
|
|
|
|
func CheckPeerPrometheusMetrics(client *http.Client, url string) {
|
|
By("hitting the prometheus metrics endpoint")
|
|
resp, err := client.Get(url)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(resp.StatusCode).To(Equal(http.StatusOK))
|
|
resp.Body.Close()
|
|
|
|
Eventually(getBody(client, url)).Should(ContainSubstring(`# TYPE grpc_server_stream_request_duration histogram`))
|
|
|
|
By("checking for some expected metrics")
|
|
body := getBody(client, url)()
|
|
Expect(body).To(ContainSubstring(`# TYPE go_gc_duration_seconds summary`))
|
|
Expect(body).To(ContainSubstring(`# TYPE grpc_server_stream_request_duration histogram`))
|
|
Expect(body).To(ContainSubstring(`grpc_server_stream_request_duration_count{code="Unknown",method="DeliverFiltered",service="protos_Deliver"}`))
|
|
Expect(body).To(ContainSubstring(`grpc_server_stream_messages_received{method="DeliverFiltered",service="protos_Deliver"}`))
|
|
Expect(body).To(ContainSubstring(`grpc_server_stream_messages_sent{method="DeliverFiltered",service="protos_Deliver"}`))
|
|
Expect(body).To(ContainSubstring(`# TYPE grpc_comm_conn_closed counter`))
|
|
Expect(body).To(ContainSubstring(`# TYPE grpc_comm_conn_opened counter`))
|
|
Expect(body).To(ContainSubstring(`ledger_blockchain_height`))
|
|
Expect(body).To(ContainSubstring(`ledger_blockstorage_commit_time_bucket`))
|
|
Expect(body).To(ContainSubstring(`ledger_blockstorage_and_pvtdata_commit_time_bucket`))
|
|
}
|
|
|
|
func CheckOrdererPrometheusMetrics(client *http.Client, url string) {
|
|
By("hitting the prometheus metrics endpoint")
|
|
resp, err := client.Get(url)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(resp.StatusCode).To(Equal(http.StatusOK))
|
|
resp.Body.Close()
|
|
|
|
Eventually(getBody(client, url)).Should(ContainSubstring(`# TYPE grpc_server_stream_request_duration histogram`))
|
|
|
|
By("checking for some expected metrics")
|
|
body := getBody(client, url)()
|
|
Expect(body).To(ContainSubstring(`# TYPE go_gc_duration_seconds summary`))
|
|
Expect(body).To(ContainSubstring(`# TYPE grpc_server_stream_request_duration histogram`))
|
|
Expect(body).To(ContainSubstring(`consensus_etcdraft_committed_block_number`))
|
|
Expect(body).To(ContainSubstring(`participation_consensus_relation`))
|
|
Expect(body).To(ContainSubstring(`# TYPE grpc_comm_conn_closed counter`))
|
|
Expect(body).To(ContainSubstring(`# TYPE grpc_comm_conn_opened counter`))
|
|
Expect(body).To(ContainSubstring(`ledger_blockchain_height`))
|
|
Expect(body).To(ContainSubstring(`ledger_blockstorage_commit_time_bucket`))
|
|
}
|
|
|
|
func CheckLogspecOperations(client *http.Client, logspecURL string) {
|
|
By("getting the logspec")
|
|
resp, err := client.Get(logspecURL)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(resp.StatusCode).To(Equal(http.StatusOK))
|
|
bodyBytes, err := ioutil.ReadAll(resp.Body)
|
|
resp.Body.Close()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(string(bodyBytes)).To(MatchJSON(`{"spec":"info"}`))
|
|
|
|
updateReq, err := http.NewRequest(http.MethodPut, logspecURL, strings.NewReader(`{"spec":"debug"}`))
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
By("setting the logspec")
|
|
resp, err = client.Do(updateReq)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(resp.StatusCode).To(Equal(http.StatusNoContent))
|
|
resp.Body.Close()
|
|
|
|
resp, err = client.Get(logspecURL)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(resp.StatusCode).To(Equal(http.StatusOK))
|
|
bodyBytes, err = ioutil.ReadAll(resp.Body)
|
|
resp.Body.Close()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(string(bodyBytes)).To(MatchJSON(`{"spec":"debug"}`))
|
|
|
|
By("resetting the logspec")
|
|
updateReq, err = http.NewRequest(http.MethodPut, logspecURL, strings.NewReader(`{"spec":"info"}`))
|
|
Expect(err).NotTo(HaveOccurred())
|
|
resp, err = client.Do(updateReq)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(resp.StatusCode).To(Equal(http.StatusNoContent))
|
|
resp.Body.Close()
|
|
}
|
|
|
|
func CheckHealthEndpoint(client *http.Client, url string) {
|
|
body := getBody(client, url)()
|
|
|
|
var healthStatus healthz.HealthStatus
|
|
err := json.Unmarshal([]byte(body), &healthStatus)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(healthStatus.Status).To(Equal(healthz.StatusOK))
|
|
}
|
|
|
|
func getBody(client *http.Client, url string) func() string {
|
|
return func() string {
|
|
resp, err := client.Get(url)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(resp.StatusCode).To(Equal(http.StatusOK))
|
|
bodyBytes, err := ioutil.ReadAll(resp.Body)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
resp.Body.Close()
|
|
return string(bodyBytes)
|
|
}
|
|
}
|
|
|
|
func packageInstallApproveChaincode(network *nwo.Network, channel string, orderer *nwo.Orderer, chaincode nwo.Chaincode, peers ...*nwo.Peer) {
|
|
nwo.PackageChaincode(network, chaincode, peers[0])
|
|
nwo.InstallChaincode(network, chaincode, peers...)
|
|
nwo.ApproveChaincodeForMyOrg(network, channel, orderer, chaincode, peers...)
|
|
}
|
|
|
|
func hashFile(file string) string {
|
|
f, err := os.Open(file)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
defer f.Close()
|
|
|
|
h := sha256.New()
|
|
_, err = io.Copy(h, f)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
return fmt.Sprintf("%x", h.Sum(nil))
|
|
}
|
|
|
|
func chaincodeContainerNameFilter(n *nwo.Network, chaincode nwo.Chaincode) string {
|
|
return fmt.Sprintf("^/%s-.*-%s-%s$", n.NetworkID, chaincode.Label, hashFile(chaincode.PackageFile))
|
|
}
|