blob: 68211e5a8925eda2375695113320792a318c8d45 [file] [log] [blame]
Jiri Simsad7616c92015-03-24 23:44:30 -07001// Copyright 2015 The Vanadium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Cosmos Nicolaou4e213d72014-10-26 22:21:52 -07005package flags
6
Cosmos Nicolaoud811b072014-10-28 17:46:27 -07007import (
8 "flag"
9 "fmt"
10 "os"
11 "strings"
Suharsh Sivakumar9d17e4a2015-02-02 22:42:16 -080012 "sync"
Asim Shankar95910b62014-10-31 22:02:29 -070013
Mike Burrows4d7b13b2015-03-31 18:15:21 -070014 "v.io/v23/verror"
Todd Wang8123b5e2015-05-14 18:44:43 -070015 "v.io/x/ref"
Cosmos Nicolaoud811b072014-10-28 17:46:27 -070016)
Cosmos Nicolaou4e213d72014-10-26 22:21:52 -070017
Mike Burrows4d7b13b2015-03-31 18:15:21 -070018const pkgPath = "v.io/x/ref/lib/flags"
19
20var (
21 errNotNameColonFile = verror.Register(pkgPath+".errNotNameColonFile", verror.NoRetry, "{1:}{2:} {3} is not in 'name:file' format{:_}")
22)
23
Cosmos Nicolaoud811b072014-10-28 17:46:27 -070024// FlagGroup is the type for identifying groups of related flags.
25type FlagGroup int
26
27const (
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -070028 // Runtime identifies the flags and associated environment variables
29 // used by the Vanadium process runtime. Namely:
Asim Shankarf32d24d2015-04-01 16:34:26 -070030 // --v23.namespace.root (which may be repeated to supply multiple values)
31 // --v23.credentials
32 // --v23.vtrace.sample-rate
33 // --v23.vtrace.dump-on-shutdown
34 // --v23.vtrace.cache-size
35 // --v23.vtrace.collect-regexp
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -070036 Runtime FlagGroup = iota
Cosmos Nicolaoud811b072014-10-28 17:46:27 -070037 // Listen identifies the flags typically required to configure
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070038 // rpc.ListenSpec. Namely:
Asim Shankarf32d24d2015-04-01 16:34:26 -070039 // --v23.tcp.protocol
40 // --v23.tcp.address
41 // --v23.proxy
42 // --v23.i18n-catalogue
Cosmos Nicolaoud811b072014-10-28 17:46:27 -070043 Listen
Asim Shankarf32d24d2015-04-01 16:34:26 -070044 // --v23.permissions.file (which may be repeated to supply multiple values)
45 // Permissions files are named - i.e. --v23.permissions.file=<name>:<file>
46 // with the name "runtime" reserved for use by the runtime. "file" is
47 // a JSON-encoded representation of the Permissions type defined in the
48 // VDL package v.io/v23/security/access
49 // -v23.permissions.literal
Adam Sadovskya4d4a692015-04-20 11:36:49 -070050 Permissions
Cosmos Nicolaoud811b072014-10-28 17:46:27 -070051)
52
Cosmos Nicolaou036c30c2015-03-24 10:05:20 -070053var (
Asim Shankar8196c1e2015-04-08 22:42:18 -070054 defaultNamespaceRoot = "/(dev.v.io/role/vprod/service/mounttabled)@ns.dev.v.io:8101" // GUARDED_BY namespaceMu
Cosmos Nicolaou036c30c2015-03-24 10:05:20 -070055 namespaceMu sync.Mutex
56
57 defaultProtocol = "wsh" // GUARDED_BY listenMu
58 defaultHostPort = ":0" // GUARDED_BY listenMu
59 listenMu sync.RWMutex
60)
Cosmos Nicolaoue497a4b2014-10-31 09:50:01 -070061
Cosmos Nicolaoud811b072014-10-28 17:46:27 -070062// Flags represents the set of flag groups created by a call to
63// CreateAndRegister.
Cosmos Nicolaou4e213d72014-10-26 22:21:52 -070064type Flags struct {
Cosmos Nicolaou4e213d72014-10-26 22:21:52 -070065 FlagSet *flag.FlagSet
Cosmos Nicolaoud811b072014-10-28 17:46:27 -070066 groups map[FlagGroup]interface{}
Cosmos Nicolaou4e213d72014-10-26 22:21:52 -070067}
68
Cosmos Nicolaoud811b072014-10-28 17:46:27 -070069type namespaceRootFlagVar struct {
Bogdan Capritabf356d72015-01-08 17:28:48 -080070 isSet bool // is true when a flag has been explicitly set.
Cosmos Nicolaou036c30c2015-03-24 10:05:20 -070071 // isDefault true when a flag has the default value and is needed in
72 // addition to isSet to distinguish between using a default value
73 // as opposed to one from an environment variable.
74 isDefault bool
75 roots []string
Cosmos Nicolaou4e213d72014-10-26 22:21:52 -070076}
77
Cosmos Nicolaoud811b072014-10-28 17:46:27 -070078func (nsr *namespaceRootFlagVar) String() string {
79 return fmt.Sprintf("%v", nsr.roots)
80}
81
82func (nsr *namespaceRootFlagVar) Set(v string) error {
Cosmos Nicolaou036c30c2015-03-24 10:05:20 -070083 nsr.isDefault = false
Cosmos Nicolaoue497a4b2014-10-31 09:50:01 -070084 if !nsr.isSet {
Cosmos Nicolaou78237372014-11-04 18:19:09 -080085 // override the default value
Cosmos Nicolaoue497a4b2014-10-31 09:50:01 -070086 nsr.isSet = true
87 nsr.roots = []string{}
88 }
Cosmos Nicolaou96fa9172014-12-16 12:57:18 -080089 for _, t := range nsr.roots {
90 if v == t {
91 return nil
92 }
93 }
Cosmos Nicolaoud811b072014-10-28 17:46:27 -070094 nsr.roots = append(nsr.roots, v)
95 return nil
96}
97
Adam Sadovskya4d4a692015-04-20 11:36:49 -070098type permsFlagVar struct {
Cosmos Nicolaou78237372014-11-04 18:19:09 -080099 isSet bool
100 files map[string]string
101}
102
Adam Sadovskya4d4a692015-04-20 11:36:49 -0700103func (permsf *permsFlagVar) String() string {
104 return fmt.Sprintf("%v", permsf.files)
Cosmos Nicolaou78237372014-11-04 18:19:09 -0800105}
106
Adam Sadovskya4d4a692015-04-20 11:36:49 -0700107func (permsf *permsFlagVar) Set(v string) error {
108 if !permsf.isSet {
Cosmos Nicolaou78237372014-11-04 18:19:09 -0800109 // override the default value
Adam Sadovskya4d4a692015-04-20 11:36:49 -0700110 permsf.isSet = true
111 permsf.files = make(map[string]string)
Cosmos Nicolaou78237372014-11-04 18:19:09 -0800112 }
113 parts := strings.SplitN(v, ":", 2)
114 if len(parts) != 2 {
Mike Burrows4d7b13b2015-03-31 18:15:21 -0700115 return verror.New(errNotNameColonFile, nil, v)
Cosmos Nicolaou78237372014-11-04 18:19:09 -0800116 }
117 name, file := parts[0], parts[1]
Adam Sadovskya4d4a692015-04-20 11:36:49 -0700118 permsf.files[name] = file
Cosmos Nicolaou78237372014-11-04 18:19:09 -0800119 return nil
120}
121
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700122// RuntimeFlags contains the values of the Runtime flag group.
123type RuntimeFlags struct {
Todd Wang8123b5e2015-05-14 18:44:43 -0700124 // NamespaceRoots may be initialized by ref.EnvNamespacePrefix* enivornment
Asim Shankarf32d24d2015-04-01 16:34:26 -0700125 // variables as well as --v23.namespace.root. The command line
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700126 // will override the environment.
Cosmos Nicolaou036c30c2015-03-24 10:05:20 -0700127 NamespaceRoots []string
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700128
Todd Wang8123b5e2015-05-14 18:44:43 -0700129 // Credentials may be initialized by the ref.EnvCredentials
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700130 // environment variable. The command line will override the environment.
131 Credentials string // TODO(cnicolaou): provide flag.Value impl
132
Todd Wang8123b5e2015-05-14 18:44:43 -0700133 // I18nCatalogue may be initialized by the ref.EnvI18nCatalogueFiles
Mike Burrows63214cb2014-12-22 14:46:42 -0800134 // environment variable. The command line will override the
135 // environment.
136 I18nCatalogue string
137
Matt Rosencrantz3e76f282014-11-10 09:38:57 -0800138 // Vtrace flags control various aspects of Vtrace.
139 Vtrace VtraceFlags
140
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700141 namespaceRootsFlag namespaceRootFlagVar
142}
143
Matt Rosencrantz3e76f282014-11-10 09:38:57 -0800144type VtraceFlags struct {
145 // VtraceSampleRate is the rate (from 0.0 - 1.0) at which
146 // vtrace traces started by this process are sampled for collection.
147 SampleRate float64
148
149 // VtraceDumpOnShutdown tells the runtime to dump all stored traces
150 // to Stderr at shutdown if true.
151 DumpOnShutdown bool
152
Matt Rosencrantz5f98d942015-01-08 13:48:30 -0800153 // VtraceCacheSize is the number of traces to cache in memory.
154 // TODO(mattr): Traces can be of widely varying size, we should have
155 // some better measurement then just number of traces.
Matt Rosencrantz3e76f282014-11-10 09:38:57 -0800156 CacheSize int
Matt Rosencrantzf7b00e22015-01-13 13:44:56 -0800157
158 // SpanRegexp matches a regular expression against span names and
159 // annotations and forces any trace matching trace to be collected.
160 CollectRegexp string
Matt Rosencrantz3e76f282014-11-10 09:38:57 -0800161}
162
Adam Sadovskya4d4a692015-04-20 11:36:49 -0700163// PermissionsFlags contains the values of the PermissionsFlags flag group.
164type PermissionsFlags struct {
165 // List of named Permissions files.
166 fileFlag permsFlagVar
Robert Kroeger5096c4b2014-12-10 15:08:45 -0800167
168 // Single json string, overrides everything.
169 literal string
Cosmos Nicolaou78237372014-11-04 18:19:09 -0800170}
171
Adam Sadovskya4d4a692015-04-20 11:36:49 -0700172// PermissionsFile returns the file which is presumed to contain Permissions
173// information associated with the supplied name parameter.
174func (af PermissionsFlags) PermissionsFile(name string) string {
Robert Kroeger5096c4b2014-12-10 15:08:45 -0800175 return af.fileFlag.files[name]
176}
177
Adam Sadovskya4d4a692015-04-20 11:36:49 -0700178func (af PermissionsFlags) PermissionsLiteral() string {
Robert Kroeger5096c4b2014-12-10 15:08:45 -0800179 return af.literal
Cosmos Nicolaou78237372014-11-04 18:19:09 -0800180}
181
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800182// ListenAddrs is the set of listen addresses captured from the command line.
Matt Rosencrantz94502cf2015-03-18 09:43:44 -0700183// ListenAddrs mirrors rpc.ListenAddrs.
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800184type ListenAddrs []struct {
185 Protocol, Address string
186}
187
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700188// ListenFlags contains the values of the Listen flag group.
189type ListenFlags struct {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800190 Addrs ListenAddrs
191 ListenProxy string
Cosmos Nicolaou036c30c2015-03-24 10:05:20 -0700192 protocol tcpProtocolFlagVar
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800193 addresses ipHostPortFlagVar
194}
195
Cosmos Nicolaou036c30c2015-03-24 10:05:20 -0700196type tcpProtocolFlagVar struct {
197 isSet bool
198 validator TCPProtocolFlag
199}
200
201// Implements flag.Value.Get
202func (proto tcpProtocolFlagVar) Get() interface{} {
203 return proto.validator.String()
204}
205
206func (proto tcpProtocolFlagVar) String() string {
207 return proto.validator.String()
208}
209
210// Implements flag.Value.Set
211func (proto *tcpProtocolFlagVar) Set(s string) error {
212 if err := proto.validator.Set(s); err != nil {
213 return err
214 }
215 proto.isSet = true
216 return nil
217}
218
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800219type ipHostPortFlagVar struct {
Cosmos Nicolaou036c30c2015-03-24 10:05:20 -0700220 isSet bool
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800221 validator IPHostPortFlag
222 flags *ListenFlags
223}
224
225// Implements flag.Value.Get
226func (ip ipHostPortFlagVar) Get() interface{} {
227 return ip.String()
228}
229
230// Implements flag.Value.Set
231func (ip *ipHostPortFlagVar) Set(s string) error {
232 if err := ip.validator.Set(s); err != nil {
233 return err
234 }
235 a := struct {
236 Protocol, Address string
237 }{
Cosmos Nicolaou036c30c2015-03-24 10:05:20 -0700238 ip.flags.protocol.validator.String(),
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800239 ip.validator.String(),
240 }
Cosmos Nicolaou96fa9172014-12-16 12:57:18 -0800241 for _, t := range ip.flags.Addrs {
242 if t.Protocol == a.Protocol && t.Address == a.Address {
243 return nil
244 }
245 }
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800246 ip.flags.Addrs = append(ip.flags.Addrs, a)
Cosmos Nicolaou036c30c2015-03-24 10:05:20 -0700247 ip.isSet = true
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800248 return nil
249}
250
251// Implements flag.Value.String
252func (ip ipHostPortFlagVar) String() string {
253 s := ""
254 for _, a := range ip.flags.Addrs {
255 s += fmt.Sprintf("(%s %s)", a.Protocol, a.Address)
256 }
257 return s
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700258}
259
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700260// createAndRegisterRuntimeFlags creates and registers the RuntimeFlags
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700261// group with the supplied flag.FlagSet.
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700262func createAndRegisterRuntimeFlags(fs *flag.FlagSet) *RuntimeFlags {
Asim Shankar59b8b692015-03-30 01:23:36 -0700263 var (
264 f = &RuntimeFlags{}
Todd Wang8123b5e2015-05-14 18:44:43 -0700265 _, roots = ref.EnvNamespaceRoots()
266 creds = os.Getenv(ref.EnvCredentials)
267 i18nCatalogue = os.Getenv(ref.EnvI18nCatalogueFiles)
Asim Shankar59b8b692015-03-30 01:23:36 -0700268 )
Cosmos Nicolaoue497a4b2014-10-31 09:50:01 -0700269 if len(roots) == 0 {
270 f.namespaceRootsFlag.roots = []string{defaultNamespaceRoot}
Cosmos Nicolaou036c30c2015-03-24 10:05:20 -0700271 f.namespaceRootsFlag.isDefault = true
Cosmos Nicolaoue497a4b2014-10-31 09:50:01 -0700272 } else {
273 f.namespaceRootsFlag.roots = roots
274 }
Cosmos Nicolaou78237372014-11-04 18:19:09 -0800275
Asim Shankarf32d24d2015-04-01 16:34:26 -0700276 fs.Var(&f.namespaceRootsFlag, "v23.namespace.root", "local namespace root; can be repeated to provided multiple roots")
277 fs.StringVar(&f.Credentials, "v23.credentials", creds, "directory to use for storing security credentials")
278 fs.StringVar(&f.I18nCatalogue, "v23.i18n-catalogue", i18nCatalogue, "18n catalogue files to load, comma separated")
279
280 fs.Float64Var(&f.Vtrace.SampleRate, "v23.vtrace.sample-rate", 0.0, "Rate (from 0.0 to 1.0) to sample vtrace traces.")
281 fs.BoolVar(&f.Vtrace.DumpOnShutdown, "v23.vtrace.dump-on-shutdown", true, "If true, dump all stored traces on runtime shutdown.")
282 fs.IntVar(&f.Vtrace.CacheSize, "v23.vtrace.cache-size", 1024, "The number of vtrace traces to store in memory.")
283 fs.StringVar(&f.Vtrace.CollectRegexp, "v23.vtrace.collect-regexp", "", "Spans and annotations that match this regular expression will trigger trace collection.")
284
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700285 return f
286}
287
Adam Sadovskya4d4a692015-04-20 11:36:49 -0700288func createAndRegisterPermissionsFlags(fs *flag.FlagSet) *PermissionsFlags {
289 f := &PermissionsFlags{}
290 fs.Var(&f.fileFlag, "v23.permissions.file", "specify a perms file as <name>:<permsfile>")
291 fs.StringVar(&f.literal, "v23.permissions.literal", "", "explicitly specify the runtime perms as a JSON-encoded access.Permissions. Overrides all --v23.permissions.file flags.")
Cosmos Nicolaou78237372014-11-04 18:19:09 -0800292 return f
293}
294
Asim Shankarf32d24d2015-04-01 16:34:26 -0700295// SetDefaultProtocol sets the default protocol used when --v23.tcp.protocol is
Suharsh Sivakumar9d17e4a2015-02-02 22:42:16 -0800296// not provided. It must be called before flags are parsed for it to take effect.
297func SetDefaultProtocol(protocol string) {
298 listenMu.Lock()
299 defaultProtocol = protocol
300 listenMu.Unlock()
301}
302
Asim Shankarf32d24d2015-04-01 16:34:26 -0700303// SetDefaultHostPort sets the default host and port used when --v23.tcp.address
Suharsh Sivakumar9d17e4a2015-02-02 22:42:16 -0800304// is not provided. It must be called before flags are parsed for it to take effect.
305func SetDefaultHostPort(s string) {
306 listenMu.Lock()
307 defaultHostPort = s
308 listenMu.Unlock()
309}
310
Asim Shankarf32d24d2015-04-01 16:34:26 -0700311// SetDefaultNamespaceRoot sets the default value for --v23.namespace.root
Cosmos Nicolaou036c30c2015-03-24 10:05:20 -0700312func SetDefaultNamespaceRoot(root string) {
313 namespaceMu.Lock()
314 defaultNamespaceRoot = root
315 namespaceMu.Unlock()
316}
317
Asim Shankar8196c1e2015-04-08 22:42:18 -0700318// DefaultNamespaceRoot gets the default value of --v23.namespace.root
319func DefaultNamespaceRoot() string {
320 namespaceMu.Lock()
321 defer namespaceMu.Unlock()
322 return defaultNamespaceRoot
323}
324
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700325// createAndRegisterListenFlags creates and registers the ListenFlags
326// group with the supplied flag.FlagSet.
327func createAndRegisterListenFlags(fs *flag.FlagSet) *ListenFlags {
Suharsh Sivakumar9d17e4a2015-02-02 22:42:16 -0800328 listenMu.RLock()
329 defer listenMu.RUnlock()
330 var ipHostPortFlag IPHostPortFlag
331 if err := ipHostPortFlag.Set(defaultHostPort); err != nil {
332 panic(err)
333 }
Cosmos Nicolaou036c30c2015-03-24 10:05:20 -0700334 var protocolFlag TCPProtocolFlag
335 if err := protocolFlag.Set(defaultProtocol); err != nil {
336 panic(err)
337 }
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800338 f := &ListenFlags{
Cosmos Nicolaou036c30c2015-03-24 10:05:20 -0700339 protocol: tcpProtocolFlagVar{validator: protocolFlag},
Suharsh Sivakumar9d17e4a2015-02-02 22:42:16 -0800340 addresses: ipHostPortFlagVar{validator: ipHostPortFlag},
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800341 }
342 f.addresses.flags = f
343
Asim Shankarf32d24d2015-04-01 16:34:26 -0700344 fs.Var(&f.protocol, "v23.tcp.protocol", "protocol to listen with")
345 fs.Var(&f.addresses, "v23.tcp.address", "address to listen on")
346 fs.StringVar(&f.ListenProxy, "v23.proxy", "", "object name of proxy service to use to export services across network boundaries")
347
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700348 return f
349}
350
351// CreateAndRegister creates a new set of flag groups as specified by the
352// supplied flag group parameters and registers them with the supplied
Bogdan Capritabf356d72015-01-08 17:28:48 -0800353// flag.FlagSet.
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700354func CreateAndRegister(fs *flag.FlagSet, groups ...FlagGroup) *Flags {
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700355 if len(groups) == 0 {
356 return nil
357 }
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700358 f := &Flags{FlagSet: fs, groups: make(map[FlagGroup]interface{})}
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700359 for _, g := range groups {
360 switch g {
361 case Runtime:
362 f.groups[Runtime] = createAndRegisterRuntimeFlags(fs)
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700363 case Listen:
364 f.groups[Listen] = createAndRegisterListenFlags(fs)
Adam Sadovskya4d4a692015-04-20 11:36:49 -0700365 case Permissions:
366 f.groups[Permissions] = createAndRegisterPermissionsFlags(fs)
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700367 }
368 }
369 return f
370}
371
Cosmos Nicolaou036c30c2015-03-24 10:05:20 -0700372func refreshDefaults(f *Flags) {
373 for _, g := range f.groups {
374 switch v := g.(type) {
375 case *RuntimeFlags:
376 if v.namespaceRootsFlag.isDefault {
377 v.namespaceRootsFlag.roots = []string{defaultNamespaceRoot}
378 v.NamespaceRoots = v.namespaceRootsFlag.roots
379 }
380 case *ListenFlags:
381 if !v.protocol.isSet {
382 v.protocol.validator.Set(defaultProtocol)
383 }
384 if !v.addresses.isSet {
385 v.addresses.validator.Set(defaultHostPort)
386 }
387 }
388 }
389}
390
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700391// RuntimeFlags returns the Runtime flag subset stored in its Flags
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700392// instance.
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700393func (f *Flags) RuntimeFlags() RuntimeFlags {
394 if p := f.groups[Runtime]; p == nil {
395 return RuntimeFlags{}
396 }
397 from := f.groups[Runtime].(*RuntimeFlags)
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700398 to := *from
399 to.NamespaceRoots = make([]string, len(from.NamespaceRoots))
400 copy(to.NamespaceRoots, from.NamespaceRoots)
401 return to
402}
403
404// ListenFlags returns a copy of the Listen flag group stored in Flags.
405// This copy will contain default values if the Listen flag group
406// was not specified when CreateAndRegister was called. The HasGroup
407// method can be used for testing to see if any given group was configured.
408func (f *Flags) ListenFlags() ListenFlags {
409 if p := f.groups[Listen]; p != nil {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800410 lf := p.(*ListenFlags)
411 n := *lf
412 if len(lf.Addrs) == 0 {
413 n.Addrs = ListenAddrs{{n.protocol.String(),
414 n.addresses.validator.String()}}
415 return n
416 }
417 n.Addrs = make(ListenAddrs, len(lf.Addrs))
418 copy(n.Addrs, lf.Addrs)
419 return n
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700420 }
421 return ListenFlags{}
422}
423
Adam Sadovskya4d4a692015-04-20 11:36:49 -0700424// PermissionsFlags returns a copy of the Permissions flag group stored in
425// Flags. This copy will contain default values if the Permissions flag group
426// was not specified when CreateAndRegister was called. The HasGroup method can
427// be used for testing to see if any given group was configured.
428func (f *Flags) PermissionsFlags() PermissionsFlags {
429 if p := f.groups[Permissions]; p != nil {
430 return *(p.(*PermissionsFlags))
Cosmos Nicolaou78237372014-11-04 18:19:09 -0800431 }
Adam Sadovskya4d4a692015-04-20 11:36:49 -0700432 return PermissionsFlags{}
Cosmos Nicolaou78237372014-11-04 18:19:09 -0800433}
434
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700435// HasGroup returns group if the supplied FlagGroup has been created
436// for these Flags.
437func (f *Flags) HasGroup(group FlagGroup) bool {
438 _, present := f.groups[group]
439 return present
440}
441
442// Args returns the unparsed args, as per flag.Args.
443func (f *Flags) Args() []string {
444 return f.FlagSet.Args()
445}
446
Bogdan Capritabf356d72015-01-08 17:28:48 -0800447// Parse parses the supplied args, as per flag.Parse. The config can optionally
448// specify flag overrides.
449func (f *Flags) Parse(args []string, cfg map[string]string) error {
Cosmos Nicolaou036c30c2015-03-24 10:05:20 -0700450 // Refresh any defaults that may have changed.
451 refreshDefaults(f)
452
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700453 // TODO(cnicolaou): implement a single env var 'VANADIUM_OPTS'
454 // that can be used to specify any command line.
455 if err := f.FlagSet.Parse(args); err != nil {
456 return err
457 }
Bogdan Capritabf356d72015-01-08 17:28:48 -0800458 for k, v := range cfg {
459 if f.FlagSet.Lookup(k) != nil {
460 f.FlagSet.Set(k, v)
461 }
462 }
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700463
Cosmos Nicolaoue497a4b2014-10-31 09:50:01 -0700464 hasrt := f.groups[Runtime] != nil
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700465 if hasrt {
466 runtime := f.groups[Runtime].(*RuntimeFlags)
Cosmos Nicolaoue497a4b2014-10-31 09:50:01 -0700467 if runtime.namespaceRootsFlag.isSet {
468 // command line overrides the environment.
Cosmos Nicolaoue5b41502014-10-29 22:55:09 -0700469 runtime.NamespaceRoots = runtime.namespaceRootsFlag.roots
Cosmos Nicolaoue497a4b2014-10-31 09:50:01 -0700470 } else {
471 // we have a default value for the command line, which
472 // is only used if the environment variables have not been
473 // supplied.
474 if len(runtime.NamespaceRoots) == 0 {
475 runtime.NamespaceRoots = runtime.namespaceRootsFlag.roots
476 }
Cosmos Nicolaou98960042014-10-31 00:05:51 -0700477 }
Cosmos Nicolaoud811b072014-10-28 17:46:27 -0700478 }
479 return nil
Cosmos Nicolaou4e213d72014-10-26 22:21:52 -0700480}