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 }