github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/peer/channel/channel.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package channel
    18  
    19  import (
    20  	"fmt"
    21  	"strings"
    22  
    23  	"github.com/hyperledger/fabric/common/flogging"
    24  	"github.com/hyperledger/fabric/msp"
    25  	"github.com/hyperledger/fabric/peer/common"
    26  	ab "github.com/hyperledger/fabric/protos/orderer"
    27  	pb "github.com/hyperledger/fabric/protos/peer"
    28  	"github.com/spf13/cobra"
    29  	"github.com/spf13/pflag"
    30  	"golang.org/x/net/context"
    31  	"google.golang.org/grpc"
    32  	"google.golang.org/grpc/credentials"
    33  )
    34  
    35  const (
    36  	channelFuncName = "channel"
    37  	shortDes        = "Operate a channel: create|fetch|join|list|update."
    38  	longDes         = "Operate a channel: create|fetch|join|list|update."
    39  )
    40  
    41  var logger = flogging.MustGetLogger("channelCmd")
    42  
    43  type OrdererRequirement bool
    44  type EndorserRequirement bool
    45  
    46  const (
    47  	EndorserRequired    EndorserRequirement = true
    48  	EndorserNotRequired EndorserRequirement = false
    49  	OrdererRequired     OrdererRequirement  = true
    50  	OrdererNotRequired  OrdererRequirement  = false
    51  )
    52  
    53  var (
    54  	// join related variables.
    55  	genesisBlockPath string
    56  
    57  	// create related variables
    58  	chainID          string
    59  	channelTxFile    string
    60  	orderingEndpoint string
    61  	tls              bool
    62  	caFile           string
    63  	timeout          int
    64  )
    65  
    66  // Cmd returns the cobra command for Node
    67  func Cmd(cf *ChannelCmdFactory) *cobra.Command {
    68  	AddFlags(channelCmd)
    69  
    70  	channelCmd.AddCommand(createCmd(cf))
    71  	channelCmd.AddCommand(fetchCmd(cf))
    72  	channelCmd.AddCommand(joinCmd(cf))
    73  	channelCmd.AddCommand(listCmd(cf))
    74  	channelCmd.AddCommand(updateCmd(cf))
    75  
    76  	return channelCmd
    77  }
    78  
    79  // AddFlags adds flags for create and join
    80  func AddFlags(cmd *cobra.Command) {
    81  	flags := cmd.PersistentFlags()
    82  
    83  	flags.StringVarP(&orderingEndpoint, "orderer", "o", "", "Ordering service endpoint")
    84  	flags.BoolVarP(&tls, "tls", "", false, "Use TLS when communicating with the orderer endpoint")
    85  	flags.StringVarP(&caFile, "cafile", "", "", "Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint")
    86  }
    87  
    88  var flags *pflag.FlagSet
    89  
    90  func init() {
    91  	resetFlags()
    92  }
    93  
    94  // Explicitly define a method to facilitate tests
    95  func resetFlags() {
    96  	flags = &pflag.FlagSet{}
    97  
    98  	flags.StringVarP(&genesisBlockPath, "blockpath", "b", common.UndefinedParamValue, "Path to file containing genesis block")
    99  	flags.StringVarP(&chainID, "channelID", "c", common.UndefinedParamValue, "In case of a newChain command, the channel ID to create.")
   100  	flags.StringVarP(&channelTxFile, "file", "f", "", "Configuration transaction file generated by a tool such as configtxgen for submitting to orderer")
   101  	flags.IntVarP(&timeout, "timeout", "t", 5, "Channel creation timeout")
   102  }
   103  
   104  func attachFlags(cmd *cobra.Command, names []string) {
   105  	cmdFlags := cmd.Flags()
   106  	for _, name := range names {
   107  		if flag := flags.Lookup(name); flag != nil {
   108  			cmdFlags.AddFlag(flag)
   109  		} else {
   110  			logger.Fatalf("Could not find flag '%s' to attach to commond '%s'", name, cmd.Name())
   111  		}
   112  	}
   113  }
   114  
   115  var channelCmd = &cobra.Command{
   116  	Use:   channelFuncName,
   117  	Short: fmt.Sprint(shortDes),
   118  	Long:  fmt.Sprint(longDes),
   119  }
   120  
   121  type BroadcastClientFactory func() (common.BroadcastClient, error)
   122  
   123  // ChannelCmdFactory holds the clients used by ChannelCmdFactory
   124  type ChannelCmdFactory struct {
   125  	EndorserClient   pb.EndorserClient
   126  	Signer           msp.SigningIdentity
   127  	BroadcastClient  common.BroadcastClient
   128  	DeliverClient    deliverClientIntf
   129  	BroadcastFactory BroadcastClientFactory
   130  }
   131  
   132  // InitCmdFactory init the ChannelCmdFactory with clients to endorser and orderer according to params
   133  func InitCmdFactory(isEndorserRequired EndorserRequirement, isOrdererRequired OrdererRequirement) (*ChannelCmdFactory, error) {
   134  	var err error
   135  
   136  	cmdFact := &ChannelCmdFactory{}
   137  
   138  	cmdFact.Signer, err = common.GetDefaultSignerFnc()
   139  	if err != nil {
   140  		return nil, fmt.Errorf("Error getting default signer: %s", err)
   141  	}
   142  
   143  	cmdFact.BroadcastFactory = func() (common.BroadcastClient, error) {
   144  		return common.GetBroadcastClientFnc(orderingEndpoint, tls, caFile)
   145  	}
   146  
   147  	//for join and list, we need the endorser as well
   148  	if isEndorserRequired {
   149  		cmdFact.EndorserClient, err = common.GetEndorserClientFnc()
   150  		if err != nil {
   151  			return nil, fmt.Errorf("Error getting endorser client %s: %s", channelFuncName, err)
   152  		}
   153  	}
   154  
   155  	//for create and fetch, we need the orderer as well
   156  	if isOrdererRequired {
   157  		if len(strings.Split(orderingEndpoint, ":")) != 2 {
   158  			return nil, fmt.Errorf("Ordering service endpoint %s is not valid or missing", orderingEndpoint)
   159  		}
   160  
   161  		var opts []grpc.DialOption
   162  		// check for TLS
   163  		if tls {
   164  			if caFile != "" {
   165  				creds, err := credentials.NewClientTLSFromFile(caFile, "")
   166  				if err != nil {
   167  					return nil, fmt.Errorf("Error connecting to %s due to %s", orderingEndpoint, err)
   168  				}
   169  				opts = append(opts, grpc.WithTransportCredentials(creds))
   170  			}
   171  		} else {
   172  			opts = append(opts, grpc.WithInsecure())
   173  		}
   174  		conn, err := grpc.Dial(orderingEndpoint, opts...)
   175  		if err != nil {
   176  			return nil, err
   177  		}
   178  
   179  		client, err := ab.NewAtomicBroadcastClient(conn).Deliver(context.TODO())
   180  		if err != nil {
   181  			return nil, fmt.Errorf("Error connecting due to  %s", err)
   182  		}
   183  
   184  		cmdFact.DeliverClient = newDeliverClient(conn, client, chainID)
   185  	}
   186  	logger.Infof("Endorser and orderer connections initialized")
   187  	return cmdFact, nil
   188  }