github.com/Augustu/go-micro/v2@v2.9.3/config/source/flag/flag.go (about) 1 package flag 2 3 import ( 4 "errors" 5 "flag" 6 "strings" 7 "time" 8 9 "github.com/Augustu/go-micro/v2/config/source" 10 "github.com/imdario/mergo" 11 ) 12 13 type flagsrc struct { 14 opts source.Options 15 } 16 17 func (fs *flagsrc) Read() (*source.ChangeSet, error) { 18 if !flag.Parsed() { 19 return nil, errors.New("flags not parsed") 20 } 21 22 var changes map[string]interface{} 23 24 visitFn := func(f *flag.Flag) { 25 n := strings.ToLower(f.Name) 26 keys := strings.FieldsFunc(n, split) 27 reverse(keys) 28 29 tmp := make(map[string]interface{}) 30 for i, k := range keys { 31 if i == 0 { 32 tmp[k] = f.Value 33 continue 34 } 35 36 tmp = map[string]interface{}{k: tmp} 37 } 38 39 mergo.Map(&changes, tmp) // need to sort error handling 40 return 41 } 42 43 unset, ok := fs.opts.Context.Value(includeUnsetKey{}).(bool) 44 if ok && unset { 45 flag.VisitAll(visitFn) 46 } else { 47 flag.Visit(visitFn) 48 } 49 50 b, err := fs.opts.Encoder.Encode(changes) 51 if err != nil { 52 return nil, err 53 } 54 55 cs := &source.ChangeSet{ 56 Format: fs.opts.Encoder.String(), 57 Data: b, 58 Timestamp: time.Now(), 59 Source: fs.String(), 60 } 61 cs.Checksum = cs.Sum() 62 63 return cs, nil 64 } 65 66 func split(r rune) bool { 67 return r == '-' || r == '_' 68 } 69 70 func reverse(ss []string) { 71 for i := len(ss)/2 - 1; i >= 0; i-- { 72 opp := len(ss) - 1 - i 73 ss[i], ss[opp] = ss[opp], ss[i] 74 } 75 } 76 77 func (fs *flagsrc) Watch() (source.Watcher, error) { 78 return source.NewNoopWatcher() 79 } 80 81 func (fs *flagsrc) Write(cs *source.ChangeSet) error { 82 return nil 83 } 84 85 func (fs *flagsrc) String() string { 86 return "flag" 87 } 88 89 // NewSource returns a config source for integrating parsed flags. 90 // Hyphens are delimiters for nesting, and all keys are lowercased. 91 // 92 // Example: 93 // dbhost := flag.String("database-host", "localhost", "the db host name") 94 // 95 // { 96 // "database": { 97 // "host": "localhost" 98 // } 99 // } 100 func NewSource(opts ...source.Option) source.Source { 101 return &flagsrc{opts: source.NewOptions(opts...)} 102 }