gitee.com/zhaochuninhefei/fabric-ca-gm@v0.0.2/cmd/fabric-ca-server/servercmd.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 main
    18  
    19  import (
    20  	"fmt"
    21  	"path/filepath"
    22  	"strings"
    23  
    24  	"gitee.com/zhaochuninhefei/fabric-ca-gm/internal/pkg/util"
    25  	"gitee.com/zhaochuninhefei/fabric-ca-gm/lib"
    26  	"gitee.com/zhaochuninhefei/fabric-ca-gm/lib/metadata"
    27  	log "gitee.com/zhaochuninhefei/zcgolog/zclog"
    28  	"github.com/pkg/errors"
    29  	"github.com/spf13/cobra"
    30  	"github.com/spf13/viper"
    31  )
    32  
    33  const (
    34  	extraArgsError = "Unrecognized arguments found: %v\n\n%s"
    35  )
    36  
    37  // ServerCmd encapsulates cobra command that provides command line interface
    38  // for the Fabric CA server and the configuration used by the Fabric CA server
    39  type ServerCmd struct {
    40  	// name of the fabric-ca-server command (init, start, version)
    41  	name string
    42  	// rootCmd is the cobra command
    43  	rootCmd *cobra.Command
    44  	// My viper instance
    45  	myViper *viper.Viper
    46  	// blockingStart indicates whether to block after starting the server or not
    47  	blockingStart bool
    48  	// cfgFileName is the name of the configuration file
    49  	cfgFileName string
    50  	// homeDirectory is the location of the server's home directory
    51  	homeDirectory string
    52  	// serverCfg is the server's configuration
    53  	cfg *lib.ServerConfig
    54  }
    55  
    56  // NewCommand returns new ServerCmd ready for running
    57  func NewCommand(name string, blockingStart bool) *ServerCmd {
    58  	s := &ServerCmd{
    59  		name:          name,
    60  		blockingStart: blockingStart,
    61  		myViper:       viper.New(),
    62  	}
    63  	s.init()
    64  	return s
    65  }
    66  
    67  // Execute runs this ServerCmd
    68  func (s *ServerCmd) Execute() error {
    69  	return s.rootCmd.Execute()
    70  }
    71  
    72  // init initializes the ServerCmd instance
    73  // It initializes the cobra root and sub commands and
    74  // registers command flgs with viper
    75  func (s *ServerCmd) init() {
    76  	// root command
    77  	rootCmd := &cobra.Command{
    78  		Use:   cmdName,
    79  		Short: longName,
    80  		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
    81  			err := s.configInit()
    82  			if err != nil {
    83  				return err
    84  			}
    85  			cmd.SilenceUsage = true
    86  			util.CmdRunBegin(s.myViper)
    87  			return nil
    88  		},
    89  	}
    90  	s.rootCmd = rootCmd
    91  
    92  	// initCmd represents the server init command
    93  	initCmd := &cobra.Command{
    94  		Use:   "init",
    95  		Short: fmt.Sprintf("Initialize the %s", shortName),
    96  		Long:  "Generate the key material needed by the server if it doesn't already exist",
    97  	}
    98  	initCmd.RunE = func(cmd *cobra.Command, args []string) error {
    99  		if len(args) > 0 {
   100  			return errors.Errorf(extraArgsError, args, initCmd.UsageString())
   101  		}
   102  		err := s.getServer().Init(false)
   103  		if err != nil {
   104  			util.Fatal("Initialization failure: %s", err)
   105  		}
   106  		log.Info("Initialization was successful")
   107  		return nil
   108  	}
   109  	s.rootCmd.AddCommand(initCmd)
   110  
   111  	// startCmd represents the server start command
   112  	startCmd := &cobra.Command{
   113  		Use:   "start",
   114  		Short: fmt.Sprintf("Start the %s", shortName),
   115  	}
   116  
   117  	startCmd.RunE = func(cmd *cobra.Command, args []string) error {
   118  		if len(args) > 0 {
   119  			return errors.Errorf(extraArgsError, args, startCmd.UsageString())
   120  		}
   121  		err := s.getServer().Start()
   122  		if err != nil {
   123  			return err
   124  		}
   125  		return nil
   126  	}
   127  	s.rootCmd.AddCommand(startCmd)
   128  
   129  	var versionCmd = &cobra.Command{
   130  		Use:   "version",
   131  		Short: "Prints Fabric CA Server version",
   132  		Run: func(cmd *cobra.Command, args []string) {
   133  			fmt.Print(metadata.GetVersionInfo(cmdName))
   134  		},
   135  	}
   136  	s.rootCmd.AddCommand(versionCmd)
   137  	s.registerFlags()
   138  }
   139  
   140  // registerFlags registers command flags with viper
   141  func (s *ServerCmd) registerFlags() {
   142  	// Get the default config file path
   143  	cfg := util.GetDefaultConfigFile(cmdName)
   144  
   145  	// All env variables must be prefixed
   146  	s.myViper.SetEnvPrefix(envVarPrefix)
   147  	s.myViper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
   148  
   149  	// Set specific global flags used by all commands
   150  	pflags := s.rootCmd.PersistentFlags()
   151  	pflags.StringVarP(&s.cfgFileName, "config", "c", "", "Configuration file")
   152  	pflags.MarkHidden("config")
   153  	// Don't want to use the default parameter for StringVarP. Need to be able to identify if home directory was explicitly set
   154  	pflags.StringVarP(&s.homeDirectory, "home", "H", "", fmt.Sprintf("Server's home directory (default \"%s\")", filepath.Dir(cfg)))
   155  	util.FlagString(s.myViper, pflags, "boot", "b", "",
   156  		"The user:pass for bootstrap admin which is required to build default config file")
   157  
   158  	// Register flags for all tagged and exported fields in the config
   159  	s.cfg = &lib.ServerConfig{}
   160  	tags := map[string]string{
   161  		"help.csr.cn":           "The common name field of the certificate signing request to a parent fabric-ca-server",
   162  		"help.csr.serialnumber": "The serial number in a certificate signing request to a parent fabric-ca-server",
   163  		"help.csr.hosts":        "A list of comma-separated host names in a certificate signing request to a parent fabric-ca-server",
   164  	}
   165  	err := util.RegisterFlags(s.myViper, pflags, s.cfg, nil)
   166  	if err != nil {
   167  		panic(err)
   168  	}
   169  	caCfg := &lib.CAConfig{}
   170  	err = util.RegisterFlags(s.myViper, pflags, caCfg, tags)
   171  	if err != nil {
   172  		panic(err)
   173  	}
   174  }
   175  
   176  // Configuration file is not required for some commands like version
   177  func (s *ServerCmd) configRequired() bool {
   178  	return s.name != "version"
   179  }
   180  
   181  // getServer returns a lib.Server for the init and start commands
   182  func (s *ServerCmd) getServer() *lib.Server {
   183  	return &lib.Server{
   184  		HomeDir:       s.homeDirectory,
   185  		Config:        s.cfg,
   186  		BlockingStart: s.blockingStart,
   187  		CA: lib.CA{
   188  			Config:         &s.cfg.CAcfg,
   189  			ConfigFilePath: s.cfgFileName,
   190  		},
   191  	}
   192  }