Cosmos Nicolaou | 4e213d7 | 2014-10-26 22:21:52 -0700 | [diff] [blame] | 1 | package flags |
| 2 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 3 | import ( |
| 4 | "flag" |
| 5 | "fmt" |
| 6 | "os" |
| 7 | "strings" |
Asim Shankar | 95910b6 | 2014-10-31 22:02:29 -0700 | [diff] [blame] | 8 | |
| 9 | "veyron.io/veyron/veyron/lib/flags/consts" |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 10 | ) |
Cosmos Nicolaou | 4e213d7 | 2014-10-26 22:21:52 -0700 | [diff] [blame] | 11 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 12 | // FlagGroup is the type for identifying groups of related flags. |
| 13 | type FlagGroup int |
| 14 | |
| 15 | const ( |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 16 | // Runtime identifies the flags and associated environment variables |
| 17 | // used by the Vanadium process runtime. Namely: |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 18 | // --veyron.namespace.root (which may be repeated to supply multiple values) |
| 19 | // --veyron.credentials |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 20 | Runtime FlagGroup = iota |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 21 | // Listen identifies the flags typically required to configure |
| 22 | // ipc.ListenSpec. Namely: |
| 23 | // --veyron.tcp.protocol |
| 24 | // --veyron.tcp.address |
| 25 | // --veyron.proxy |
| 26 | Listen |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 27 | // --veyron.acl (which may be repeated to supply multiple values) |
Cosmos Nicolaou | c7ddcf0 | 2014-11-05 16:26:56 -0800 | [diff] [blame] | 28 | // ACL files are named - i.e. --veyron.acl=<name>:<file> with the |
| 29 | // name <runtime> reserved for use by the runtime. |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 30 | ACL |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 31 | ) |
| 32 | |
Robin Thellend | 8fea01c | 2014-12-11 13:48:10 -0800 | [diff] [blame] | 33 | const defaultNamespaceRoot = "/ns.dev.v.io:8101" |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 34 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 35 | // Flags represents the set of flag groups created by a call to |
| 36 | // CreateAndRegister. |
Cosmos Nicolaou | 4e213d7 | 2014-10-26 22:21:52 -0700 | [diff] [blame] | 37 | type Flags struct { |
Cosmos Nicolaou | 4e213d7 | 2014-10-26 22:21:52 -0700 | [diff] [blame] | 38 | FlagSet *flag.FlagSet |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 39 | groups map[FlagGroup]interface{} |
Cosmos Nicolaou | 4e213d7 | 2014-10-26 22:21:52 -0700 | [diff] [blame] | 40 | } |
| 41 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 42 | type namespaceRootFlagVar struct { |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 43 | isSet bool // is true when a flag have has been explicitly set. |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 44 | roots []string |
Cosmos Nicolaou | 4e213d7 | 2014-10-26 22:21:52 -0700 | [diff] [blame] | 45 | } |
| 46 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 47 | func (nsr *namespaceRootFlagVar) String() string { |
| 48 | return fmt.Sprintf("%v", nsr.roots) |
| 49 | } |
| 50 | |
| 51 | func (nsr *namespaceRootFlagVar) Set(v string) error { |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 52 | if !nsr.isSet { |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 53 | // override the default value |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 54 | nsr.isSet = true |
| 55 | nsr.roots = []string{} |
| 56 | } |
Cosmos Nicolaou | 96fa917 | 2014-12-16 12:57:18 -0800 | [diff] [blame] | 57 | for _, t := range nsr.roots { |
| 58 | if v == t { |
| 59 | return nil |
| 60 | } |
| 61 | } |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 62 | nsr.roots = append(nsr.roots, v) |
| 63 | return nil |
| 64 | } |
| 65 | |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 66 | type aclFlagVar struct { |
| 67 | isSet bool |
| 68 | files map[string]string |
| 69 | } |
| 70 | |
| 71 | func (aclf *aclFlagVar) String() string { |
| 72 | return fmt.Sprintf("%v", aclf.files) |
| 73 | } |
| 74 | |
| 75 | func (aclf *aclFlagVar) Set(v string) error { |
| 76 | if !aclf.isSet { |
| 77 | // override the default value |
| 78 | aclf.isSet = true |
| 79 | aclf.files = make(map[string]string) |
| 80 | } |
| 81 | parts := strings.SplitN(v, ":", 2) |
| 82 | if len(parts) != 2 { |
| 83 | return fmt.Errorf("%q is not in 'name:file' format", v) |
| 84 | } |
| 85 | name, file := parts[0], parts[1] |
| 86 | aclf.files[name] = file |
| 87 | return nil |
| 88 | } |
| 89 | |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 90 | // RuntimeFlags contains the values of the Runtime flag group. |
| 91 | type RuntimeFlags struct { |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 92 | // NamespaceRoots may be initialized by NAMESPACE_ROOT* enivornment |
| 93 | // variables as well as --veyron.namespace.root. The command line |
| 94 | // will override the environment. |
| 95 | NamespaceRoots []string // TODO(cnicolaou): provide flag.Value impl |
| 96 | |
Mike Burrows | 63214cb | 2014-12-22 14:46:42 -0800 | [diff] [blame] | 97 | // Credentials may be initialized by the VEYRON_CREDENTIALS |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 98 | // environment variable. The command line will override the environment. |
| 99 | Credentials string // TODO(cnicolaou): provide flag.Value impl |
| 100 | |
Mike Burrows | 63214cb | 2014-12-22 14:46:42 -0800 | [diff] [blame] | 101 | // I18nCatalogue may be initialized by the VANADIUM_I18N_CATALOGUE |
| 102 | // environment variable. The command line will override the |
| 103 | // environment. |
| 104 | I18nCatalogue string |
| 105 | |
Matt Rosencrantz | 3e76f28 | 2014-11-10 09:38:57 -0800 | [diff] [blame] | 106 | // Vtrace flags control various aspects of Vtrace. |
| 107 | Vtrace VtraceFlags |
| 108 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 109 | namespaceRootsFlag namespaceRootFlagVar |
| 110 | } |
| 111 | |
Matt Rosencrantz | 3e76f28 | 2014-11-10 09:38:57 -0800 | [diff] [blame] | 112 | type VtraceFlags struct { |
| 113 | // VtraceSampleRate is the rate (from 0.0 - 1.0) at which |
| 114 | // vtrace traces started by this process are sampled for collection. |
| 115 | SampleRate float64 |
| 116 | |
| 117 | // VtraceDumpOnShutdown tells the runtime to dump all stored traces |
| 118 | // to Stderr at shutdown if true. |
| 119 | DumpOnShutdown bool |
| 120 | |
| 121 | // VtraceCacheSize the number of traces to cache in memory. |
| 122 | CacheSize int |
| 123 | } |
| 124 | |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 125 | // ACLFlags contains the values of the ACLFlags flag group. |
| 126 | type ACLFlags struct { |
| 127 | flag aclFlagVar |
| 128 | } |
| 129 | |
| 130 | // ACLFile returns the file which is presumed to contain ACL information |
| 131 | // associated with the supplied name parameter. |
| 132 | func (af ACLFlags) ACLFile(name string) string { |
| 133 | return af.flag.files[name] |
| 134 | } |
| 135 | |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 136 | // ListenAddrs is the set of listen addresses captured from the command line. |
| 137 | // ListenAddrs mirrors ipc.ListenAddrs. |
| 138 | type ListenAddrs []struct { |
| 139 | Protocol, Address string |
| 140 | } |
| 141 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 142 | // ListenFlags contains the values of the Listen flag group. |
| 143 | type ListenFlags struct { |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 144 | Addrs ListenAddrs |
| 145 | ListenProxy string |
| 146 | protocol TCPProtocolFlag |
| 147 | addresses ipHostPortFlagVar |
| 148 | } |
| 149 | |
| 150 | type ipHostPortFlagVar struct { |
| 151 | validator IPHostPortFlag |
| 152 | flags *ListenFlags |
| 153 | } |
| 154 | |
| 155 | // Implements flag.Value.Get |
| 156 | func (ip ipHostPortFlagVar) Get() interface{} { |
| 157 | return ip.String() |
| 158 | } |
| 159 | |
| 160 | // Implements flag.Value.Set |
| 161 | func (ip *ipHostPortFlagVar) Set(s string) error { |
| 162 | if err := ip.validator.Set(s); err != nil { |
| 163 | return err |
| 164 | } |
| 165 | a := struct { |
| 166 | Protocol, Address string |
| 167 | }{ |
| 168 | ip.flags.protocol.String(), |
| 169 | ip.validator.String(), |
| 170 | } |
Cosmos Nicolaou | 96fa917 | 2014-12-16 12:57:18 -0800 | [diff] [blame] | 171 | for _, t := range ip.flags.Addrs { |
| 172 | if t.Protocol == a.Protocol && t.Address == a.Address { |
| 173 | return nil |
| 174 | } |
| 175 | } |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 176 | ip.flags.Addrs = append(ip.flags.Addrs, a) |
| 177 | return nil |
| 178 | } |
| 179 | |
| 180 | // Implements flag.Value.String |
| 181 | func (ip ipHostPortFlagVar) String() string { |
| 182 | s := "" |
| 183 | for _, a := range ip.flags.Addrs { |
| 184 | s += fmt.Sprintf("(%s %s)", a.Protocol, a.Address) |
| 185 | } |
| 186 | return s |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 187 | } |
| 188 | |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 189 | // createAndRegisterRuntimeFlags creates and registers the RuntimeFlags |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 190 | // group with the supplied flag.FlagSet. |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 191 | func createAndRegisterRuntimeFlags(fs *flag.FlagSet) *RuntimeFlags { |
| 192 | f := &RuntimeFlags{} |
Mike Burrows | 63214cb | 2014-12-22 14:46:42 -0800 | [diff] [blame] | 193 | roots, creds, i18nCatalogue := readEnv() |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 194 | if len(roots) == 0 { |
| 195 | f.namespaceRootsFlag.roots = []string{defaultNamespaceRoot} |
| 196 | } else { |
| 197 | f.namespaceRootsFlag.roots = roots |
| 198 | } |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 199 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 200 | fs.Var(&f.namespaceRootsFlag, "veyron.namespace.root", "local namespace root; can be repeated to provided multiple roots") |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 201 | fs.StringVar(&f.Credentials, "veyron.credentials", creds, "directory to use for storing security credentials") |
Mike Burrows | 63214cb | 2014-12-22 14:46:42 -0800 | [diff] [blame] | 202 | fs.StringVar(&f.I18nCatalogue, "vanadium.i18n_catalogue", i18nCatalogue, "18n catalogue files to load, comma separated") |
Matt Rosencrantz | 3e76f28 | 2014-11-10 09:38:57 -0800 | [diff] [blame] | 203 | |
| 204 | fs.Float64Var(&f.Vtrace.SampleRate, "veyron.vtrace.sample_rate", 0.0, "Rate (from 0.0 to 1.0) to sample vtrace traces.") |
| 205 | fs.BoolVar(&f.Vtrace.DumpOnShutdown, "veyron.vtrace.dump_on_shutdown", false, "If true, dump all stored traces on runtime shutdown.") |
| 206 | fs.IntVar(&f.Vtrace.CacheSize, "veyron.vtrace.cache_size", 1024, "The number of vtrace traces to store in memory.") |
| 207 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 208 | return f |
| 209 | } |
| 210 | |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 211 | func createAndRegisterACLFlags(fs *flag.FlagSet) *ACLFlags { |
| 212 | f := &ACLFlags{} |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 213 | fs.Var(&f.flag, "veyron.acl", "specify an acl file as <name>:<aclfile>") |
| 214 | return f |
| 215 | } |
| 216 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 217 | // createAndRegisterListenFlags creates and registers the ListenFlags |
| 218 | // group with the supplied flag.FlagSet. |
| 219 | func createAndRegisterListenFlags(fs *flag.FlagSet) *ListenFlags { |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 220 | f := &ListenFlags{ |
| 221 | protocol: TCPProtocolFlag{"tcp"}, |
| 222 | addresses: ipHostPortFlagVar{validator: IPHostPortFlag{Port: "0"}}, |
| 223 | } |
| 224 | f.addresses.flags = f |
| 225 | |
| 226 | fs.Var(&f.protocol, "veyron.tcp.protocol", "protocol to listen with") |
| 227 | fs.Var(&f.addresses, "veyron.tcp.address", "address to listen on") |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 228 | fs.StringVar(&f.ListenProxy, "veyron.proxy", "", "object name of proxy service to use to export services across network boundaries") |
| 229 | return f |
| 230 | } |
| 231 | |
| 232 | // CreateAndRegister creates a new set of flag groups as specified by the |
| 233 | // supplied flag group parameters and registers them with the supplied |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 234 | // flag.Flagset. |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 235 | func CreateAndRegister(fs *flag.FlagSet, groups ...FlagGroup) *Flags { |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 236 | if len(groups) == 0 { |
| 237 | return nil |
| 238 | } |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 239 | f := &Flags{FlagSet: fs, groups: make(map[FlagGroup]interface{})} |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 240 | for _, g := range groups { |
| 241 | switch g { |
| 242 | case Runtime: |
| 243 | f.groups[Runtime] = createAndRegisterRuntimeFlags(fs) |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 244 | case Listen: |
| 245 | f.groups[Listen] = createAndRegisterListenFlags(fs) |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 246 | case ACL: |
| 247 | f.groups[ACL] = createAndRegisterACLFlags(fs) |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 248 | } |
| 249 | } |
| 250 | return f |
| 251 | } |
| 252 | |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 253 | // RuntimeFlags returns the Runtime flag subset stored in its Flags |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 254 | // instance. |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 255 | func (f *Flags) RuntimeFlags() RuntimeFlags { |
| 256 | if p := f.groups[Runtime]; p == nil { |
| 257 | return RuntimeFlags{} |
| 258 | } |
| 259 | from := f.groups[Runtime].(*RuntimeFlags) |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 260 | to := *from |
| 261 | to.NamespaceRoots = make([]string, len(from.NamespaceRoots)) |
| 262 | copy(to.NamespaceRoots, from.NamespaceRoots) |
| 263 | return to |
| 264 | } |
| 265 | |
| 266 | // ListenFlags returns a copy of the Listen flag group stored in Flags. |
| 267 | // This copy will contain default values if the Listen flag group |
| 268 | // was not specified when CreateAndRegister was called. The HasGroup |
| 269 | // method can be used for testing to see if any given group was configured. |
| 270 | func (f *Flags) ListenFlags() ListenFlags { |
| 271 | if p := f.groups[Listen]; p != nil { |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 272 | lf := p.(*ListenFlags) |
| 273 | n := *lf |
| 274 | if len(lf.Addrs) == 0 { |
| 275 | n.Addrs = ListenAddrs{{n.protocol.String(), |
| 276 | n.addresses.validator.String()}} |
| 277 | return n |
| 278 | } |
| 279 | n.Addrs = make(ListenAddrs, len(lf.Addrs)) |
| 280 | copy(n.Addrs, lf.Addrs) |
| 281 | return n |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 282 | } |
| 283 | return ListenFlags{} |
| 284 | } |
| 285 | |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 286 | // ACLFlags returns a copy of the ACL flag group stored in Flags. |
| 287 | // This copy will contain default values if the ACL flag group |
| 288 | // was not specified when CreateAndRegister was called. The HasGroup |
| 289 | // method can be used for testing to see if any given group was configured. |
| 290 | func (f *Flags) ACLFlags() ACLFlags { |
| 291 | if p := f.groups[ACL]; p != nil { |
| 292 | return *(p.(*ACLFlags)) |
| 293 | } |
| 294 | return ACLFlags{} |
| 295 | } |
| 296 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 297 | // HasGroup returns group if the supplied FlagGroup has been created |
| 298 | // for these Flags. |
| 299 | func (f *Flags) HasGroup(group FlagGroup) bool { |
| 300 | _, present := f.groups[group] |
| 301 | return present |
| 302 | } |
| 303 | |
| 304 | // Args returns the unparsed args, as per flag.Args. |
| 305 | func (f *Flags) Args() []string { |
| 306 | return f.FlagSet.Args() |
| 307 | } |
| 308 | |
Mike Burrows | 63214cb | 2014-12-22 14:46:42 -0800 | [diff] [blame] | 309 | // readEnv reads the legacy NAMESPACE_ROOT?, VEYRON_CREDENTIALS, |
| 310 | // and VANADIUM_I18N_CATALOGUE env vars. |
| 311 | func readEnv() ([]string, string, string) { |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 312 | roots := []string{} |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 313 | for _, ev := range os.Environ() { |
| 314 | p := strings.SplitN(ev, "=", 2) |
| 315 | if len(p) != 2 { |
| 316 | continue |
| 317 | } |
| 318 | k, v := p[0], p[1] |
Asim Shankar | 95910b6 | 2014-10-31 22:02:29 -0700 | [diff] [blame] | 319 | if strings.HasPrefix(k, consts.NamespaceRootPrefix) && len(v) > 0 { |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 320 | roots = append(roots, v) |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 321 | } |
| 322 | } |
Mike Burrows | 63214cb | 2014-12-22 14:46:42 -0800 | [diff] [blame] | 323 | return roots, os.Getenv(consts.VeyronCredentials), os.Getenv(consts.I18nCatalogueFiles) |
Cosmos Nicolaou | 4e213d7 | 2014-10-26 22:21:52 -0700 | [diff] [blame] | 324 | } |
| 325 | |
Cosmos Nicolaou | a025109 | 2014-11-09 22:04:37 -0800 | [diff] [blame] | 326 | // Parse parses the supplied args, as per flag.Parse. |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 327 | func (f *Flags) Parse(args []string) error { |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 328 | // TODO(cnicolaou): implement a single env var 'VANADIUM_OPTS' |
| 329 | // that can be used to specify any command line. |
| 330 | if err := f.FlagSet.Parse(args); err != nil { |
| 331 | return err |
| 332 | } |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 333 | |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 334 | hasrt := f.groups[Runtime] != nil |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 335 | if hasrt { |
| 336 | runtime := f.groups[Runtime].(*RuntimeFlags) |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 337 | if runtime.namespaceRootsFlag.isSet { |
| 338 | // command line overrides the environment. |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 339 | runtime.NamespaceRoots = runtime.namespaceRootsFlag.roots |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 340 | } else { |
| 341 | // we have a default value for the command line, which |
| 342 | // is only used if the environment variables have not been |
| 343 | // supplied. |
| 344 | if len(runtime.NamespaceRoots) == 0 { |
| 345 | runtime.NamespaceRoots = runtime.namespaceRootsFlag.roots |
| 346 | } |
Cosmos Nicolaou | 9896004 | 2014-10-31 00:05:51 -0700 | [diff] [blame] | 347 | } |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 348 | } |
| 349 | return nil |
Cosmos Nicolaou | 4e213d7 | 2014-10-26 22:21:52 -0700 | [diff] [blame] | 350 | } |