github.com/hxx258456/fabric-ca-gm@v0.0.3-0.20221111064038-a268ad7e3a37/internal/pkg/util/flag.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package util 8 9 import ( 10 "fmt" 11 "reflect" 12 "strconv" 13 "time" 14 15 log "gitee.com/zhaochuninhefei/zcgolog/zclog" 16 logging "github.com/op/go-logging" 17 "github.com/pkg/errors" 18 "github.com/spf13/pflag" 19 "github.com/spf13/viper" 20 ) 21 22 const ( 23 // TagDefault is the tag name for a default value of a field as recognized 24 // by RegisterFlags. 25 TagDefault = "def" 26 // TagHelp is the tag name for a help message of a field as recognized 27 // by RegisterFlags. 28 TagHelp = "help" 29 // TagOpt is the tag name for a one character option of a field as recognized 30 // by RegisterFlags. For example, a value of "d" reserves "-d" for the 31 // command line argument. 32 TagOpt = "opt" 33 // TagSkip is the tag name which causes the field to be skipped by 34 // RegisterFlags. 35 TagSkip = "skip" 36 // TagHide is the tag name which causes the field to be hidden 37 TagHide = "hide" 38 ) 39 40 // RegisterFlags registers flags for all fields in an arbitrary 'config' object. 41 // This method recognizes the following field tags: 42 // "def" - the default value of the field; 43 // "opt" - the optional one character short name to use on the command line; 44 // "help" - the help message to display on the command line; 45 // "skip" - to skip the field. 46 func RegisterFlags(v *viper.Viper, flags *pflag.FlagSet, config interface{}, 47 tags map[string]string) error { 48 fr := &flagRegistrar{flags: flags, tags: tags, viper: v} 49 return ParseObj(config, fr.Register, tags) 50 } 51 52 type flagRegistrar struct { 53 flags *pflag.FlagSet 54 tags map[string]string 55 viper *viper.Viper 56 } 57 58 func (fr *flagRegistrar) Register(f *Field) (err error) { 59 // Don't register non-leaf fields 60 if !f.Leaf { 61 return nil 62 } 63 // Don't register fields with no address 64 if f.Addr == nil { 65 return errors.Errorf("Field is not addressable: %s", f.Path) 66 } 67 skip := fr.getTag(f, TagSkip) 68 if skip != "" { 69 return nil 70 } 71 72 help := fr.getTag(f, TagHelp) 73 opt := fr.getTag(f, TagOpt) 74 def := fr.getTag(f, TagDefault) 75 hide := fr.getHideBooleanTag(f) 76 switch f.Kind { 77 78 case reflect.String: 79 if help == "" && !hide { 80 return errors.Errorf("Field is missing a help tag: %s", f.Path) 81 } 82 fr.flags.StringVarP(f.Addr.(*string), f.Path, opt, def, help) 83 case reflect.Int: 84 if help == "" && !hide { 85 return errors.Errorf("Field is missing a help tag: %s", f.Path) 86 } 87 var intDef int 88 if def != "" { 89 intDef, err = strconv.Atoi(def) 90 if err != nil { 91 return errors.Errorf("Invalid integer value in 'def' tag of %s field", f.Path) 92 } 93 } 94 fr.flags.IntVarP(f.Addr.(*int), f.Path, opt, intDef, help) 95 case reflect.Int64: 96 if help == "" && !hide { 97 return errors.Errorf("Field is missing a help tag: %s", f.Path) 98 } 99 d, ok := f.Addr.(*time.Duration) 100 if !ok { 101 var intDef int64 102 if def != "" { 103 intDef, err = strconv.ParseInt(def, 10, 64) 104 if err != nil { 105 return errors.Errorf("Invalid int64 value in 'def' tag of %s field", f.Path) 106 } 107 } 108 fr.flags.Int64VarP(f.Addr.(*int64), f.Path, opt, intDef, help) 109 } else { 110 var intDef time.Duration 111 if def != "" { 112 intDef, err = time.ParseDuration(def) 113 if err != nil { 114 return errors.Errorf("Invalid duration value in 'def' tag of %s field", f.Path) 115 } 116 } 117 fr.flags.DurationVarP(d, f.Path, opt, intDef, help) 118 } 119 case reflect.Bool: 120 if help == "" && !hide { 121 return errors.Errorf("Field is missing a help tag: %s", f.Path) 122 } 123 var boolDef bool 124 if def != "" { 125 boolDef, err = strconv.ParseBool(def) 126 if err != nil { 127 return errors.Errorf("Invalid boolean value in 'def' tag of %s field", f.Path) 128 } 129 } 130 fr.flags.BoolVarP(f.Addr.(*bool), f.Path, opt, boolDef, help) 131 case reflect.Slice: 132 if f.Type.Elem().Kind() == reflect.String { 133 if help == "" && !hide { 134 return errors.Errorf("Field is missing a help tag: %s", f.Path) 135 } 136 fr.flags.StringSliceVarP(f.Addr.(*[]string), f.Path, opt, nil, help) 137 } else { 138 return nil 139 } 140 default: 141 log.Debugf("Not registering flag for '%s' because it is a currently unsupported type: %s", 142 f.Path, f.Kind) 143 return nil 144 } 145 if hide { 146 fr.flags.MarkHidden(f.Path) 147 } 148 bindFlag(fr.viper, fr.flags, f.Path) 149 return nil 150 } 151 152 func (fr *flagRegistrar) getTag(f *Field, tagName string) string { 153 var key, val string 154 key = fmt.Sprintf("%s.%s", tagName, f.Path) 155 if fr.tags != nil { 156 val = fr.tags[key] 157 } 158 if val == "" { 159 val = f.Tag.Get(tagName) 160 } 161 return val 162 } 163 164 func (fr *flagRegistrar) getHideBooleanTag(f *Field) bool { 165 boolVal, err := strconv.ParseBool(f.Hide) 166 if err != nil { 167 return false 168 } 169 return boolVal 170 } 171 172 // CmdRunBegin is called at the beginning of each cobra run function 173 func CmdRunBegin(v *viper.Viper) { 174 // If -d or --debug, set debug logging level 175 if v.GetBool("debug") { 176 log.Level = log.LOG_LEVEL_DEBUG 177 178 logging.SetLevel(logging.INFO, "bccsp") 179 logging.SetLevel(logging.INFO, "bccsp_p11") 180 logging.SetLevel(logging.INFO, "bccsp_sw") 181 } 182 } 183 184 // FlagString sets up a flag for a string, binding it to its name 185 func FlagString(v *viper.Viper, flags *pflag.FlagSet, name, short string, def string, desc string) { 186 flags.StringP(name, short, def, desc) 187 bindFlag(v, flags, name) 188 } 189 190 // common binding function 191 func bindFlag(v *viper.Viper, flags *pflag.FlagSet, name string) { 192 flag := flags.Lookup(name) 193 if flag == nil { 194 panic(fmt.Errorf("failed to lookup '%s'", name)) 195 } 196 v.BindPFlag(name, flag) 197 }