181 lines
4.2 KiB
Go
181 lines
4.2 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package discovery
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
|
|
"github.com/golang/protobuf/proto"
|
|
"github.com/hyperledger/fabric-protos-go/msp"
|
|
"github.com/hyperledger/fabric/cmd/common"
|
|
discovery "github.com/hyperledger/fabric/discovery/client"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// NewPeerCmd creates a new PeerCmd with the given Stub and ResponseParser
|
|
func NewPeerCmd(stub Stub, parser ResponseParser) *PeerCmd {
|
|
return &PeerCmd{
|
|
stub: stub,
|
|
parser: parser,
|
|
}
|
|
}
|
|
|
|
// PeerCmd executes channelPeer listing command
|
|
type PeerCmd struct {
|
|
stub Stub
|
|
server *string
|
|
channel *string
|
|
parser ResponseParser
|
|
}
|
|
|
|
// SetServer sets the server of the PeerCmd
|
|
func (pc *PeerCmd) SetServer(server *string) {
|
|
pc.server = server
|
|
}
|
|
|
|
// SetChannel sets the channel of the PeerCmd
|
|
func (pc *PeerCmd) SetChannel(channel *string) {
|
|
pc.channel = channel
|
|
}
|
|
|
|
// Execute executes the command
|
|
func (pc *PeerCmd) Execute(conf common.Config) error {
|
|
channel := ""
|
|
|
|
if pc.channel != nil {
|
|
channel = *pc.channel
|
|
}
|
|
|
|
if pc.server == nil || *pc.server == "" {
|
|
return errors.New("no server specified")
|
|
}
|
|
|
|
server := *pc.server
|
|
|
|
req := discovery.NewRequest()
|
|
if channel != "" {
|
|
req = req.OfChannel(channel)
|
|
req = req.AddPeersQuery()
|
|
} else {
|
|
req = req.AddLocalPeersQuery()
|
|
}
|
|
res, err := pc.stub.Send(server, conf, req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return pc.parser.ParseResponse(channel, res)
|
|
}
|
|
|
|
// PeerResponseParser parses a channelPeer response
|
|
type PeerResponseParser struct {
|
|
io.Writer
|
|
}
|
|
|
|
// ParseResponse parses the given response about the given channel
|
|
func (parser *PeerResponseParser) ParseResponse(channel string, res ServiceResponse) error {
|
|
var listPeers peerLister
|
|
if channel == "" {
|
|
listPeers = res.ForLocal()
|
|
} else {
|
|
listPeers = &simpleChannelResponse{res.ForChannel(channel)}
|
|
}
|
|
peers, err := listPeers.Peers()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
channelState := channel != ""
|
|
b, _ := json.MarshalIndent(assemblePeers(peers, channelState), "", "\t")
|
|
fmt.Fprintln(parser.Writer, string(b))
|
|
return nil
|
|
}
|
|
|
|
func assemblePeers(peers []*discovery.Peer, withChannelState bool) interface{} {
|
|
if withChannelState {
|
|
var peerSlices []channelPeer
|
|
for _, p := range peers {
|
|
peerSlices = append(peerSlices, rawPeerToChannelPeer(p))
|
|
}
|
|
return peerSlices
|
|
}
|
|
var peerSlices []localPeer
|
|
for _, p := range peers {
|
|
peerSlices = append(peerSlices, rawPeerToLocalPeer(p))
|
|
}
|
|
return peerSlices
|
|
}
|
|
|
|
type channelPeer struct {
|
|
MSPID string
|
|
LedgerHeight uint64
|
|
Endpoint string
|
|
Identity string
|
|
Chaincodes []string
|
|
}
|
|
|
|
type localPeer struct {
|
|
MSPID string
|
|
Endpoint string
|
|
Identity string
|
|
}
|
|
|
|
type peerLister interface {
|
|
Peers() ([]*discovery.Peer, error)
|
|
}
|
|
|
|
type simpleChannelResponse struct {
|
|
discovery.ChannelResponse
|
|
}
|
|
|
|
func (scr *simpleChannelResponse) Peers() ([]*discovery.Peer, error) {
|
|
return scr.ChannelResponse.Peers()
|
|
}
|
|
|
|
func rawPeerToChannelPeer(p *discovery.Peer) channelPeer {
|
|
var ledgerHeight uint64
|
|
var ccs []string
|
|
if p.StateInfoMessage != nil && p.StateInfoMessage.GetStateInfo() != nil && p.StateInfoMessage.GetStateInfo().Properties != nil {
|
|
properties := p.StateInfoMessage.GetStateInfo().Properties
|
|
ledgerHeight = properties.LedgerHeight
|
|
for _, cc := range properties.Chaincodes {
|
|
if cc == nil {
|
|
continue
|
|
}
|
|
ccs = append(ccs, cc.Name)
|
|
}
|
|
}
|
|
var endpoint string
|
|
if p.AliveMessage != nil && p.AliveMessage.GetAliveMsg() != nil && p.AliveMessage.GetAliveMsg().Membership != nil {
|
|
endpoint = p.AliveMessage.GetAliveMsg().Membership.Endpoint
|
|
}
|
|
sID := &msp.SerializedIdentity{}
|
|
proto.Unmarshal(p.Identity, sID)
|
|
return channelPeer{
|
|
MSPID: p.MSPID,
|
|
Endpoint: endpoint,
|
|
LedgerHeight: ledgerHeight,
|
|
Identity: string(sID.IdBytes),
|
|
Chaincodes: ccs,
|
|
}
|
|
}
|
|
|
|
func rawPeerToLocalPeer(p *discovery.Peer) localPeer {
|
|
var endpoint string
|
|
if p.AliveMessage != nil && p.AliveMessage.GetAliveMsg() != nil && p.AliveMessage.GetAliveMsg().Membership != nil {
|
|
endpoint = p.AliveMessage.GetAliveMsg().Membership.Endpoint
|
|
}
|
|
sID := &msp.SerializedIdentity{}
|
|
proto.Unmarshal(p.Identity, sID)
|
|
return localPeer{
|
|
MSPID: p.MSPID,
|
|
Endpoint: endpoint,
|
|
Identity: string(sID.IdBytes),
|
|
}
|
|
}
|