Jiri Simsa | d7616c9 | 2015-03-24 23:44:30 -0700 | [diff] [blame] | 1 | // 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 Nicolaou | 4e213d7 | 2014-10-26 22:21:52 -0700 | [diff] [blame] | 5 | package flags |
| 6 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 7 | import ( |
| 8 | "flag" |
| 9 | "fmt" |
| 10 | "os" |
| 11 | "strings" |
Suharsh Sivakumar | 9d17e4a | 2015-02-02 22:42:16 -0800 | [diff] [blame] | 12 | "sync" |
Asim Shankar | 95910b6 | 2014-10-31 22:02:29 -0700 | [diff] [blame] | 13 | |
Mike Burrows | 4d7b13b | 2015-03-31 18:15:21 -0700 | [diff] [blame] | 14 | "v.io/v23/verror" |
Todd Wang | 8123b5e | 2015-05-14 18:44:43 -0700 | [diff] [blame] | 15 | "v.io/x/ref" |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 16 | ) |
Cosmos Nicolaou | 4e213d7 | 2014-10-26 22:21:52 -0700 | [diff] [blame] | 17 | |
Mike Burrows | 4d7b13b | 2015-03-31 18:15:21 -0700 | [diff] [blame] | 18 | const pkgPath = "v.io/x/ref/lib/flags" |
| 19 | |
| 20 | var ( |
| 21 | errNotNameColonFile = verror.Register(pkgPath+".errNotNameColonFile", verror.NoRetry, "{1:}{2:} {3} is not in 'name:file' format{:_}") |
| 22 | ) |
| 23 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 24 | // FlagGroup is the type for identifying groups of related flags. |
| 25 | type FlagGroup int |
| 26 | |
| 27 | const ( |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 28 | // Runtime identifies the flags and associated environment variables |
| 29 | // used by the Vanadium process runtime. Namely: |
Asim Shankar | f32d24d | 2015-04-01 16:34:26 -0700 | [diff] [blame] | 30 | // --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 Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 36 | Runtime FlagGroup = iota |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 37 | // Listen identifies the flags typically required to configure |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 38 | // rpc.ListenSpec. Namely: |
Asim Shankar | f32d24d | 2015-04-01 16:34:26 -0700 | [diff] [blame] | 39 | // --v23.tcp.protocol |
| 40 | // --v23.tcp.address |
| 41 | // --v23.proxy |
| 42 | // --v23.i18n-catalogue |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 43 | Listen |
Asim Shankar | f32d24d | 2015-04-01 16:34:26 -0700 | [diff] [blame] | 44 | // --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 Sadovsky | a4d4a69 | 2015-04-20 11:36:49 -0700 | [diff] [blame] | 50 | Permissions |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 51 | ) |
| 52 | |
Cosmos Nicolaou | 036c30c | 2015-03-24 10:05:20 -0700 | [diff] [blame] | 53 | var ( |
Asim Shankar | 8196c1e | 2015-04-08 22:42:18 -0700 | [diff] [blame] | 54 | defaultNamespaceRoot = "/(dev.v.io/role/vprod/service/mounttabled)@ns.dev.v.io:8101" // GUARDED_BY namespaceMu |
Cosmos Nicolaou | 036c30c | 2015-03-24 10:05:20 -0700 | [diff] [blame] | 55 | namespaceMu sync.Mutex |
| 56 | |
| 57 | defaultProtocol = "wsh" // GUARDED_BY listenMu |
| 58 | defaultHostPort = ":0" // GUARDED_BY listenMu |
| 59 | listenMu sync.RWMutex |
| 60 | ) |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 61 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 62 | // Flags represents the set of flag groups created by a call to |
| 63 | // CreateAndRegister. |
Cosmos Nicolaou | 4e213d7 | 2014-10-26 22:21:52 -0700 | [diff] [blame] | 64 | type Flags struct { |
Cosmos Nicolaou | 4e213d7 | 2014-10-26 22:21:52 -0700 | [diff] [blame] | 65 | FlagSet *flag.FlagSet |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 66 | groups map[FlagGroup]interface{} |
Cosmos Nicolaou | 4e213d7 | 2014-10-26 22:21:52 -0700 | [diff] [blame] | 67 | } |
| 68 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 69 | type namespaceRootFlagVar struct { |
Bogdan Caprita | bf356d7 | 2015-01-08 17:28:48 -0800 | [diff] [blame] | 70 | isSet bool // is true when a flag has been explicitly set. |
Cosmos Nicolaou | 036c30c | 2015-03-24 10:05:20 -0700 | [diff] [blame] | 71 | // 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 Nicolaou | 4e213d7 | 2014-10-26 22:21:52 -0700 | [diff] [blame] | 76 | } |
| 77 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 78 | func (nsr *namespaceRootFlagVar) String() string { |
| 79 | return fmt.Sprintf("%v", nsr.roots) |
| 80 | } |
| 81 | |
| 82 | func (nsr *namespaceRootFlagVar) Set(v string) error { |
Cosmos Nicolaou | 036c30c | 2015-03-24 10:05:20 -0700 | [diff] [blame] | 83 | nsr.isDefault = false |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 84 | if !nsr.isSet { |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 85 | // override the default value |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 86 | nsr.isSet = true |
| 87 | nsr.roots = []string{} |
| 88 | } |
Cosmos Nicolaou | 96fa917 | 2014-12-16 12:57:18 -0800 | [diff] [blame] | 89 | for _, t := range nsr.roots { |
| 90 | if v == t { |
| 91 | return nil |
| 92 | } |
| 93 | } |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 94 | nsr.roots = append(nsr.roots, v) |
| 95 | return nil |
| 96 | } |
| 97 | |
Adam Sadovsky | a4d4a69 | 2015-04-20 11:36:49 -0700 | [diff] [blame] | 98 | type permsFlagVar struct { |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 99 | isSet bool |
| 100 | files map[string]string |
| 101 | } |
| 102 | |
Adam Sadovsky | a4d4a69 | 2015-04-20 11:36:49 -0700 | [diff] [blame] | 103 | func (permsf *permsFlagVar) String() string { |
| 104 | return fmt.Sprintf("%v", permsf.files) |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 105 | } |
| 106 | |
Adam Sadovsky | a4d4a69 | 2015-04-20 11:36:49 -0700 | [diff] [blame] | 107 | func (permsf *permsFlagVar) Set(v string) error { |
| 108 | if !permsf.isSet { |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 109 | // override the default value |
Adam Sadovsky | a4d4a69 | 2015-04-20 11:36:49 -0700 | [diff] [blame] | 110 | permsf.isSet = true |
| 111 | permsf.files = make(map[string]string) |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 112 | } |
| 113 | parts := strings.SplitN(v, ":", 2) |
| 114 | if len(parts) != 2 { |
Mike Burrows | 4d7b13b | 2015-03-31 18:15:21 -0700 | [diff] [blame] | 115 | return verror.New(errNotNameColonFile, nil, v) |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 116 | } |
| 117 | name, file := parts[0], parts[1] |
Adam Sadovsky | a4d4a69 | 2015-04-20 11:36:49 -0700 | [diff] [blame] | 118 | permsf.files[name] = file |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 119 | return nil |
| 120 | } |
| 121 | |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 122 | // RuntimeFlags contains the values of the Runtime flag group. |
| 123 | type RuntimeFlags struct { |
Todd Wang | 8123b5e | 2015-05-14 18:44:43 -0700 | [diff] [blame] | 124 | // NamespaceRoots may be initialized by ref.EnvNamespacePrefix* enivornment |
Asim Shankar | f32d24d | 2015-04-01 16:34:26 -0700 | [diff] [blame] | 125 | // variables as well as --v23.namespace.root. The command line |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 126 | // will override the environment. |
Cosmos Nicolaou | 036c30c | 2015-03-24 10:05:20 -0700 | [diff] [blame] | 127 | NamespaceRoots []string |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 128 | |
Todd Wang | 8123b5e | 2015-05-14 18:44:43 -0700 | [diff] [blame] | 129 | // Credentials may be initialized by the ref.EnvCredentials |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 130 | // environment variable. The command line will override the environment. |
| 131 | Credentials string // TODO(cnicolaou): provide flag.Value impl |
| 132 | |
Todd Wang | 8123b5e | 2015-05-14 18:44:43 -0700 | [diff] [blame] | 133 | // I18nCatalogue may be initialized by the ref.EnvI18nCatalogueFiles |
Mike Burrows | 63214cb | 2014-12-22 14:46:42 -0800 | [diff] [blame] | 134 | // environment variable. The command line will override the |
| 135 | // environment. |
| 136 | I18nCatalogue string |
| 137 | |
Matt Rosencrantz | 3e76f28 | 2014-11-10 09:38:57 -0800 | [diff] [blame] | 138 | // Vtrace flags control various aspects of Vtrace. |
| 139 | Vtrace VtraceFlags |
| 140 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 141 | namespaceRootsFlag namespaceRootFlagVar |
| 142 | } |
| 143 | |
Matt Rosencrantz | 3e76f28 | 2014-11-10 09:38:57 -0800 | [diff] [blame] | 144 | type 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 Rosencrantz | 5f98d94 | 2015-01-08 13:48:30 -0800 | [diff] [blame] | 153 | // 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 Rosencrantz | 3e76f28 | 2014-11-10 09:38:57 -0800 | [diff] [blame] | 156 | CacheSize int |
Matt Rosencrantz | f7b00e2 | 2015-01-13 13:44:56 -0800 | [diff] [blame] | 157 | |
| 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 Rosencrantz | 3e76f28 | 2014-11-10 09:38:57 -0800 | [diff] [blame] | 161 | } |
| 162 | |
Adam Sadovsky | a4d4a69 | 2015-04-20 11:36:49 -0700 | [diff] [blame] | 163 | // PermissionsFlags contains the values of the PermissionsFlags flag group. |
| 164 | type PermissionsFlags struct { |
| 165 | // List of named Permissions files. |
| 166 | fileFlag permsFlagVar |
Robert Kroeger | 5096c4b | 2014-12-10 15:08:45 -0800 | [diff] [blame] | 167 | |
| 168 | // Single json string, overrides everything. |
| 169 | literal string |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 170 | } |
| 171 | |
Adam Sadovsky | a4d4a69 | 2015-04-20 11:36:49 -0700 | [diff] [blame] | 172 | // PermissionsFile returns the file which is presumed to contain Permissions |
| 173 | // information associated with the supplied name parameter. |
| 174 | func (af PermissionsFlags) PermissionsFile(name string) string { |
Robert Kroeger | 5096c4b | 2014-12-10 15:08:45 -0800 | [diff] [blame] | 175 | return af.fileFlag.files[name] |
| 176 | } |
| 177 | |
Adam Sadovsky | a4d4a69 | 2015-04-20 11:36:49 -0700 | [diff] [blame] | 178 | func (af PermissionsFlags) PermissionsLiteral() string { |
Robert Kroeger | 5096c4b | 2014-12-10 15:08:45 -0800 | [diff] [blame] | 179 | return af.literal |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 180 | } |
| 181 | |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 182 | // ListenAddrs is the set of listen addresses captured from the command line. |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 183 | // ListenAddrs mirrors rpc.ListenAddrs. |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 184 | type ListenAddrs []struct { |
| 185 | Protocol, Address string |
| 186 | } |
| 187 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 188 | // ListenFlags contains the values of the Listen flag group. |
| 189 | type ListenFlags struct { |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 190 | Addrs ListenAddrs |
| 191 | ListenProxy string |
Cosmos Nicolaou | 036c30c | 2015-03-24 10:05:20 -0700 | [diff] [blame] | 192 | protocol tcpProtocolFlagVar |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 193 | addresses ipHostPortFlagVar |
| 194 | } |
| 195 | |
Cosmos Nicolaou | 036c30c | 2015-03-24 10:05:20 -0700 | [diff] [blame] | 196 | type tcpProtocolFlagVar struct { |
| 197 | isSet bool |
| 198 | validator TCPProtocolFlag |
| 199 | } |
| 200 | |
| 201 | // Implements flag.Value.Get |
| 202 | func (proto tcpProtocolFlagVar) Get() interface{} { |
| 203 | return proto.validator.String() |
| 204 | } |
| 205 | |
| 206 | func (proto tcpProtocolFlagVar) String() string { |
| 207 | return proto.validator.String() |
| 208 | } |
| 209 | |
| 210 | // Implements flag.Value.Set |
| 211 | func (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 Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 219 | type ipHostPortFlagVar struct { |
Cosmos Nicolaou | 036c30c | 2015-03-24 10:05:20 -0700 | [diff] [blame] | 220 | isSet bool |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 221 | validator IPHostPortFlag |
| 222 | flags *ListenFlags |
| 223 | } |
| 224 | |
| 225 | // Implements flag.Value.Get |
| 226 | func (ip ipHostPortFlagVar) Get() interface{} { |
| 227 | return ip.String() |
| 228 | } |
| 229 | |
| 230 | // Implements flag.Value.Set |
| 231 | func (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 Nicolaou | 036c30c | 2015-03-24 10:05:20 -0700 | [diff] [blame] | 238 | ip.flags.protocol.validator.String(), |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 239 | ip.validator.String(), |
| 240 | } |
Cosmos Nicolaou | 96fa917 | 2014-12-16 12:57:18 -0800 | [diff] [blame] | 241 | for _, t := range ip.flags.Addrs { |
| 242 | if t.Protocol == a.Protocol && t.Address == a.Address { |
| 243 | return nil |
| 244 | } |
| 245 | } |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 246 | ip.flags.Addrs = append(ip.flags.Addrs, a) |
Cosmos Nicolaou | 036c30c | 2015-03-24 10:05:20 -0700 | [diff] [blame] | 247 | ip.isSet = true |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 248 | return nil |
| 249 | } |
| 250 | |
| 251 | // Implements flag.Value.String |
| 252 | func (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 Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 258 | } |
| 259 | |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 260 | // createAndRegisterRuntimeFlags creates and registers the RuntimeFlags |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 261 | // group with the supplied flag.FlagSet. |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 262 | func createAndRegisterRuntimeFlags(fs *flag.FlagSet) *RuntimeFlags { |
Asim Shankar | 59b8b69 | 2015-03-30 01:23:36 -0700 | [diff] [blame] | 263 | var ( |
| 264 | f = &RuntimeFlags{} |
Todd Wang | 8123b5e | 2015-05-14 18:44:43 -0700 | [diff] [blame] | 265 | _, roots = ref.EnvNamespaceRoots() |
| 266 | creds = os.Getenv(ref.EnvCredentials) |
| 267 | i18nCatalogue = os.Getenv(ref.EnvI18nCatalogueFiles) |
Asim Shankar | 59b8b69 | 2015-03-30 01:23:36 -0700 | [diff] [blame] | 268 | ) |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 269 | if len(roots) == 0 { |
| 270 | f.namespaceRootsFlag.roots = []string{defaultNamespaceRoot} |
Cosmos Nicolaou | 036c30c | 2015-03-24 10:05:20 -0700 | [diff] [blame] | 271 | f.namespaceRootsFlag.isDefault = true |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 272 | } else { |
| 273 | f.namespaceRootsFlag.roots = roots |
| 274 | } |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 275 | |
Asim Shankar | f32d24d | 2015-04-01 16:34:26 -0700 | [diff] [blame] | 276 | 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 Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 285 | return f |
| 286 | } |
| 287 | |
Adam Sadovsky | a4d4a69 | 2015-04-20 11:36:49 -0700 | [diff] [blame] | 288 | func 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 Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 292 | return f |
| 293 | } |
| 294 | |
Asim Shankar | f32d24d | 2015-04-01 16:34:26 -0700 | [diff] [blame] | 295 | // SetDefaultProtocol sets the default protocol used when --v23.tcp.protocol is |
Suharsh Sivakumar | 9d17e4a | 2015-02-02 22:42:16 -0800 | [diff] [blame] | 296 | // not provided. It must be called before flags are parsed for it to take effect. |
| 297 | func SetDefaultProtocol(protocol string) { |
| 298 | listenMu.Lock() |
| 299 | defaultProtocol = protocol |
| 300 | listenMu.Unlock() |
| 301 | } |
| 302 | |
Asim Shankar | f32d24d | 2015-04-01 16:34:26 -0700 | [diff] [blame] | 303 | // SetDefaultHostPort sets the default host and port used when --v23.tcp.address |
Suharsh Sivakumar | 9d17e4a | 2015-02-02 22:42:16 -0800 | [diff] [blame] | 304 | // is not provided. It must be called before flags are parsed for it to take effect. |
| 305 | func SetDefaultHostPort(s string) { |
| 306 | listenMu.Lock() |
| 307 | defaultHostPort = s |
| 308 | listenMu.Unlock() |
| 309 | } |
| 310 | |
Asim Shankar | f32d24d | 2015-04-01 16:34:26 -0700 | [diff] [blame] | 311 | // SetDefaultNamespaceRoot sets the default value for --v23.namespace.root |
Cosmos Nicolaou | 036c30c | 2015-03-24 10:05:20 -0700 | [diff] [blame] | 312 | func SetDefaultNamespaceRoot(root string) { |
| 313 | namespaceMu.Lock() |
| 314 | defaultNamespaceRoot = root |
| 315 | namespaceMu.Unlock() |
| 316 | } |
| 317 | |
Asim Shankar | 8196c1e | 2015-04-08 22:42:18 -0700 | [diff] [blame] | 318 | // DefaultNamespaceRoot gets the default value of --v23.namespace.root |
| 319 | func DefaultNamespaceRoot() string { |
| 320 | namespaceMu.Lock() |
| 321 | defer namespaceMu.Unlock() |
| 322 | return defaultNamespaceRoot |
| 323 | } |
| 324 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 325 | // createAndRegisterListenFlags creates and registers the ListenFlags |
| 326 | // group with the supplied flag.FlagSet. |
| 327 | func createAndRegisterListenFlags(fs *flag.FlagSet) *ListenFlags { |
Suharsh Sivakumar | 9d17e4a | 2015-02-02 22:42:16 -0800 | [diff] [blame] | 328 | listenMu.RLock() |
| 329 | defer listenMu.RUnlock() |
| 330 | var ipHostPortFlag IPHostPortFlag |
| 331 | if err := ipHostPortFlag.Set(defaultHostPort); err != nil { |
| 332 | panic(err) |
| 333 | } |
Cosmos Nicolaou | 036c30c | 2015-03-24 10:05:20 -0700 | [diff] [blame] | 334 | var protocolFlag TCPProtocolFlag |
| 335 | if err := protocolFlag.Set(defaultProtocol); err != nil { |
| 336 | panic(err) |
| 337 | } |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 338 | f := &ListenFlags{ |
Cosmos Nicolaou | 036c30c | 2015-03-24 10:05:20 -0700 | [diff] [blame] | 339 | protocol: tcpProtocolFlagVar{validator: protocolFlag}, |
Suharsh Sivakumar | 9d17e4a | 2015-02-02 22:42:16 -0800 | [diff] [blame] | 340 | addresses: ipHostPortFlagVar{validator: ipHostPortFlag}, |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 341 | } |
| 342 | f.addresses.flags = f |
| 343 | |
Asim Shankar | f32d24d | 2015-04-01 16:34:26 -0700 | [diff] [blame] | 344 | 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 Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 348 | 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 Caprita | bf356d7 | 2015-01-08 17:28:48 -0800 | [diff] [blame] | 353 | // flag.FlagSet. |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 354 | func CreateAndRegister(fs *flag.FlagSet, groups ...FlagGroup) *Flags { |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 355 | if len(groups) == 0 { |
| 356 | return nil |
| 357 | } |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 358 | f := &Flags{FlagSet: fs, groups: make(map[FlagGroup]interface{})} |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 359 | for _, g := range groups { |
| 360 | switch g { |
| 361 | case Runtime: |
| 362 | f.groups[Runtime] = createAndRegisterRuntimeFlags(fs) |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 363 | case Listen: |
| 364 | f.groups[Listen] = createAndRegisterListenFlags(fs) |
Adam Sadovsky | a4d4a69 | 2015-04-20 11:36:49 -0700 | [diff] [blame] | 365 | case Permissions: |
| 366 | f.groups[Permissions] = createAndRegisterPermissionsFlags(fs) |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 367 | } |
| 368 | } |
| 369 | return f |
| 370 | } |
| 371 | |
Cosmos Nicolaou | 036c30c | 2015-03-24 10:05:20 -0700 | [diff] [blame] | 372 | func 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 Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 391 | // RuntimeFlags returns the Runtime flag subset stored in its Flags |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 392 | // instance. |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 393 | func (f *Flags) RuntimeFlags() RuntimeFlags { |
| 394 | if p := f.groups[Runtime]; p == nil { |
| 395 | return RuntimeFlags{} |
| 396 | } |
| 397 | from := f.groups[Runtime].(*RuntimeFlags) |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 398 | 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. |
| 408 | func (f *Flags) ListenFlags() ListenFlags { |
| 409 | if p := f.groups[Listen]; p != nil { |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 410 | 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 Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 420 | } |
| 421 | return ListenFlags{} |
| 422 | } |
| 423 | |
Adam Sadovsky | a4d4a69 | 2015-04-20 11:36:49 -0700 | [diff] [blame] | 424 | // 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. |
| 428 | func (f *Flags) PermissionsFlags() PermissionsFlags { |
| 429 | if p := f.groups[Permissions]; p != nil { |
| 430 | return *(p.(*PermissionsFlags)) |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 431 | } |
Adam Sadovsky | a4d4a69 | 2015-04-20 11:36:49 -0700 | [diff] [blame] | 432 | return PermissionsFlags{} |
Cosmos Nicolaou | 7823737 | 2014-11-04 18:19:09 -0800 | [diff] [blame] | 433 | } |
| 434 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 435 | // HasGroup returns group if the supplied FlagGroup has been created |
| 436 | // for these Flags. |
| 437 | func (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. |
| 443 | func (f *Flags) Args() []string { |
| 444 | return f.FlagSet.Args() |
| 445 | } |
| 446 | |
Bogdan Caprita | bf356d7 | 2015-01-08 17:28:48 -0800 | [diff] [blame] | 447 | // Parse parses the supplied args, as per flag.Parse. The config can optionally |
| 448 | // specify flag overrides. |
| 449 | func (f *Flags) Parse(args []string, cfg map[string]string) error { |
Cosmos Nicolaou | 036c30c | 2015-03-24 10:05:20 -0700 | [diff] [blame] | 450 | // Refresh any defaults that may have changed. |
| 451 | refreshDefaults(f) |
| 452 | |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 453 | // 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 Caprita | bf356d7 | 2015-01-08 17:28:48 -0800 | [diff] [blame] | 458 | for k, v := range cfg { |
| 459 | if f.FlagSet.Lookup(k) != nil { |
| 460 | f.FlagSet.Set(k, v) |
| 461 | } |
| 462 | } |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 463 | |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 464 | hasrt := f.groups[Runtime] != nil |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 465 | if hasrt { |
| 466 | runtime := f.groups[Runtime].(*RuntimeFlags) |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 467 | if runtime.namespaceRootsFlag.isSet { |
| 468 | // command line overrides the environment. |
Cosmos Nicolaou | e5b4150 | 2014-10-29 22:55:09 -0700 | [diff] [blame] | 469 | runtime.NamespaceRoots = runtime.namespaceRootsFlag.roots |
Cosmos Nicolaou | e497a4b | 2014-10-31 09:50:01 -0700 | [diff] [blame] | 470 | } 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 Nicolaou | 9896004 | 2014-10-31 00:05:51 -0700 | [diff] [blame] | 477 | } |
Cosmos Nicolaou | d811b07 | 2014-10-28 17:46:27 -0700 | [diff] [blame] | 478 | } |
| 479 | return nil |
Cosmos Nicolaou | 4e213d7 | 2014-10-26 22:21:52 -0700 | [diff] [blame] | 480 | } |