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 }