blob: b329b9c47537a065881b3d6dcc5662de45cda1af [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
Todd Wang338f90c2015-05-07 19:42:46 -07005// The following enables go generate to generate the doc.go file.
6//go:generate go run $V23_ROOT/release/go/src/v.io/x/lib/cmdline/testdata/gendoc.go .
7
Robin Thellend18205cf2014-10-21 13:53:59 -07008package main
Robin Thellend4f5f5052014-07-01 15:43:10 -07009
10import (
Asim Shankar94117172015-04-09 00:20:51 -070011 "encoding/json"
Robin Thellend4f5f5052014-07-01 15:43:10 -070012 "fmt"
Asim Shankar94117172015-04-09 00:20:51 -070013 "os"
Todd Wang1624bf92015-04-22 16:53:57 -070014 "regexp"
Robin Thellendc300a952015-04-08 15:14:43 -070015 "sort"
Robin Thellend4f5f5052014-07-01 15:43:10 -070016 "time"
17
Jiri Simsa6ac95222015-02-23 16:11:49 -080018 "v.io/v23"
19 "v.io/v23/context"
Jiri Simsa6ac95222015-02-23 16:11:49 -080020 "v.io/v23/naming"
21 "v.io/v23/options"
Asim Shankar94117172015-04-09 00:20:51 -070022 "v.io/v23/security/access"
23 "v.io/v23/verror"
Todd Wang338f90c2015-05-07 19:42:46 -070024 "v.io/x/lib/cmdline2"
Jiri Simsa337af232015-02-27 14:36:46 -080025 "v.io/x/lib/vlog"
Todd Wang338f90c2015-05-07 19:42:46 -070026 "v.io/x/ref/lib/v23cmd"
Suharsh Sivakumardcc11d72015-05-11 12:19:20 -070027 _ "v.io/x/ref/runtime/factories/generic"
Robin Thellend4f5f5052014-07-01 15:43:10 -070028)
29
Todd Wang338f90c2015-05-07 19:42:46 -070030func main() {
31 cmdline2.HideGlobalFlagsExcept(regexp.MustCompile(`^v23\.namespace\.root$`))
32 cmdline2.Main(cmdRoot)
Todd Wang1624bf92015-04-22 16:53:57 -070033}
34
Asim Shankarb2cc1292015-02-23 15:22:45 -080035var (
Robin Thellendc300a952015-04-08 15:14:43 -070036 flagLongGlob bool
Asim Shankarb2cc1292015-02-23 15:22:45 -080037 flagInsecureResolve bool
38 flagInsecureResolveToMT bool
Nicolas Lacasse0dc334e2015-04-10 10:19:41 -070039 flagDeleteSubtree bool
Asim Shankarb2cc1292015-02-23 15:22:45 -080040)
41
Todd Wang338f90c2015-05-07 19:42:46 -070042func init() {
43 cmdGlob.Flags.BoolVar(&flagLongGlob, "l", false, "Long listing format.")
44 cmdResolve.Flags.BoolVar(&flagInsecureResolve, "insecure", false, "Insecure mode: May return results from untrusted servers and invoke Resolve on untrusted mounttables")
45 cmdResolveToMT.Flags.BoolVar(&flagInsecureResolveToMT, "insecure", false, "Insecure mode: May return results from untrusted servers and invoke Resolve on untrusted mounttables")
46 cmdDelete.Flags.BoolVar(&flagDeleteSubtree, "r", false, "Delete all children of the name in addition to the name itself.")
47}
48
49var cmdGlob = &cmdline2.Command{
50 Runner: v23cmd.RunnerFunc(runGlob),
Robin Thellend4f5f5052014-07-01 15:43:10 -070051 Name: "glob",
52 Short: "Returns all matching entries from the namespace",
53 Long: "Returns all matching entries from the namespace.",
54 ArgsName: "<pattern>",
55 ArgsLong: `
56<pattern> is a glob pattern that is matched against all the names below the
57specified mount name.
58`,
59}
60
Todd Wang338f90c2015-05-07 19:42:46 -070061func runGlob(ctx *context.T, env *cmdline2.Env, args []string) error {
Robin Thellend4f5f5052014-07-01 15:43:10 -070062 if expected, got := 1, len(args); expected != got {
Todd Wang338f90c2015-05-07 19:42:46 -070063 return env.UsageErrorf("glob: incorrect number of arguments, expected %d, got %d", expected, got)
Robin Thellend4f5f5052014-07-01 15:43:10 -070064 }
65 pattern := args[0]
Matt Rosencrantzd599e382015-01-12 11:13:32 -080066
Todd Wang338f90c2015-05-07 19:42:46 -070067 ctx, cancel := context.WithTimeout(ctx, time.Minute)
Matt Rosencrantz137b8d22014-08-18 09:56:15 -070068 defer cancel()
Matt Rosencrantzd599e382015-01-12 11:13:32 -080069
Jiri Simsa6ac95222015-02-23 16:11:49 -080070 ns := v23.GetNamespace(ctx)
Matt Rosencrantzd599e382015-01-12 11:13:32 -080071
Matt Rosencrantz137b8d22014-08-18 09:56:15 -070072 c, err := ns.Glob(ctx, pattern)
Robin Thellend4f5f5052014-07-01 15:43:10 -070073 if err != nil {
74 vlog.Infof("ns.Glob(%q) failed: %v", pattern, err)
75 return err
76 }
Robin Thellendc300a952015-04-08 15:14:43 -070077 if flagLongGlob {
78 // Show all the information we received.
79 for res := range c {
80 switch v := res.(type) {
James Ringc971dca2015-04-09 09:51:20 -070081 case *naming.GlobReplyEntry:
Todd Wang338f90c2015-05-07 19:42:46 -070082 fmt.Fprint(env.Stdout, v.Value.Name)
James Ringc971dca2015-04-09 09:51:20 -070083 for _, s := range v.Value.Servers {
Robin Thellendc300a952015-04-08 15:14:43 -070084 delta := s.Deadline.Time.Sub(time.Now())
Todd Wang338f90c2015-05-07 19:42:46 -070085 fmt.Fprintf(env.Stdout, " %s (Expires in %d sec)", s.Server, int(delta.Seconds()))
Robin Thellendc300a952015-04-08 15:14:43 -070086 }
Todd Wang338f90c2015-05-07 19:42:46 -070087 fmt.Fprintln(env.Stdout)
James Ringc971dca2015-04-09 09:51:20 -070088 case *naming.GlobReplyError:
Todd Wang338f90c2015-05-07 19:42:46 -070089 fmt.Fprintf(env.Stderr, "Error: %s: %v\n", v.Value.Name, v.Value.Error)
Robin Thellendc300a952015-04-08 15:14:43 -070090 }
91 }
92 return nil
93 }
94 // Show a sorted list of unique names, and any errors.
95 resultSet := make(map[string]struct{})
96 errors := []*naming.GlobError{}
Robin Thellend4f5f5052014-07-01 15:43:10 -070097 for res := range c {
David Why Use Two When One Will Do Presotto03c34d62015-02-10 01:38:58 -080098 switch v := res.(type) {
James Ringc971dca2015-04-09 09:51:20 -070099 case *naming.GlobReplyEntry:
100 if v.Value.Name != "" {
101 resultSet[v.Value.Name] = struct{}{}
David Why Use Two When One Will Do Presotto03c34d62015-02-10 01:38:58 -0800102 }
James Ringc971dca2015-04-09 09:51:20 -0700103 case *naming.GlobReplyError:
104 errors = append(errors, &v.Value)
Robin Thellend20732e52015-02-08 10:34:01 -0800105 }
Robin Thellend4f5f5052014-07-01 15:43:10 -0700106 }
Robin Thellendc300a952015-04-08 15:14:43 -0700107 results := []string{}
108 for r := range resultSet {
109 results = append(results, r)
110 }
111 sort.Strings(results)
112 for _, result := range results {
Todd Wang338f90c2015-05-07 19:42:46 -0700113 fmt.Fprintln(env.Stdout, result)
Robin Thellendc300a952015-04-08 15:14:43 -0700114 }
115 for _, err := range errors {
Todd Wang338f90c2015-05-07 19:42:46 -0700116 fmt.Fprintf(env.Stderr, "Error: %s: %v\n", err.Name, err.Error)
Robin Thellendc300a952015-04-08 15:14:43 -0700117 }
Robin Thellend4f5f5052014-07-01 15:43:10 -0700118 return nil
119}
120
Todd Wang338f90c2015-05-07 19:42:46 -0700121var cmdMount = &cmdline2.Command{
122 Runner: v23cmd.RunnerFunc(runMount),
Robin Thellend4f5f5052014-07-01 15:43:10 -0700123 Name: "mount",
124 Short: "Adds a server to the namespace",
125 Long: "Adds server <server> to the namespace with name <name>.",
126 ArgsName: "<name> <server> <ttl>",
127 ArgsLong: `
128<name> is the name to add to the namespace.
129<server> is the object address of the server to add.
130<ttl> is the TTL of the new entry. It is a decimal number followed by a unit
131suffix (s, m, h). A value of 0s represents an infinite duration.
132`,
133}
134
Todd Wang338f90c2015-05-07 19:42:46 -0700135func runMount(ctx *context.T, env *cmdline2.Env, args []string) error {
Robin Thellend4f5f5052014-07-01 15:43:10 -0700136 if expected, got := 3, len(args); expected != got {
Todd Wang338f90c2015-05-07 19:42:46 -0700137 return env.UsageErrorf("mount: incorrect number of arguments, expected %d, got %d", expected, got)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700138 }
139 name := args[0]
140 server := args[1]
141 ttlArg := args[2]
142
143 ttl, err := time.ParseDuration(ttlArg)
144 if err != nil {
145 return fmt.Errorf("TTL parse error: %v", err)
146 }
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800147
Todd Wang338f90c2015-05-07 19:42:46 -0700148 ctx, cancel := context.WithTimeout(ctx, time.Minute)
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700149 defer cancel()
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800150
Jiri Simsa6ac95222015-02-23 16:11:49 -0800151 ns := v23.GetNamespace(ctx)
Asim Shankar43d1f932015-03-24 20:57:56 -0700152 if err = ns.Mount(ctx, name, server, ttl); err != nil {
153 vlog.Infof("ns.Mount(%q, %q, %s) failed: %v", name, server, ttl, err)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700154 return err
155 }
Todd Wang338f90c2015-05-07 19:42:46 -0700156 fmt.Fprintln(env.Stdout, "Server mounted successfully.")
Robin Thellend4f5f5052014-07-01 15:43:10 -0700157 return nil
158}
159
Todd Wang338f90c2015-05-07 19:42:46 -0700160var cmdUnmount = &cmdline2.Command{
161 Runner: v23cmd.RunnerFunc(runUnmount),
Robin Thellend4f5f5052014-07-01 15:43:10 -0700162 Name: "unmount",
163 Short: "Removes a server from the namespace",
164 Long: "Removes server <server> with name <name> from the namespace.",
165 ArgsName: "<name> <server>",
166 ArgsLong: `
167<name> is the name to remove from the namespace.
168<server> is the object address of the server to remove.
169`,
170}
171
Todd Wang338f90c2015-05-07 19:42:46 -0700172func runUnmount(ctx *context.T, env *cmdline2.Env, args []string) error {
Robin Thellend4f5f5052014-07-01 15:43:10 -0700173 if expected, got := 2, len(args); expected != got {
Todd Wang338f90c2015-05-07 19:42:46 -0700174 return env.UsageErrorf("unmount: incorrect number of arguments, expected %d, got %d", expected, got)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700175 }
176 name := args[0]
177 server := args[1]
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800178
Todd Wang338f90c2015-05-07 19:42:46 -0700179 ctx, cancel := context.WithTimeout(ctx, time.Minute)
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700180 defer cancel()
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800181
Jiri Simsa6ac95222015-02-23 16:11:49 -0800182 ns := v23.GetNamespace(ctx)
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800183
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700184 if err := ns.Unmount(ctx, name, server); err != nil {
Robin Thellend4f5f5052014-07-01 15:43:10 -0700185 vlog.Infof("ns.Unmount(%q, %q) failed: %v", name, server, err)
186 return err
187 }
Todd Wang338f90c2015-05-07 19:42:46 -0700188 fmt.Fprintln(env.Stdout, "Server unmounted successfully.")
Robin Thellend4f5f5052014-07-01 15:43:10 -0700189 return nil
190}
191
Todd Wang338f90c2015-05-07 19:42:46 -0700192var cmdResolve = &cmdline2.Command{
193 Runner: v23cmd.RunnerFunc(runResolve),
Robin Thellend4f5f5052014-07-01 15:43:10 -0700194 Name: "resolve",
195 Short: "Translates a object name to its object address(es)",
196 Long: "Translates a object name to its object address(es).",
197 ArgsName: "<name>",
198 ArgsLong: "<name> is the name to resolve.",
199}
200
Todd Wang338f90c2015-05-07 19:42:46 -0700201func runResolve(ctx *context.T, env *cmdline2.Env, args []string) error {
Robin Thellend4f5f5052014-07-01 15:43:10 -0700202 if expected, got := 1, len(args); expected != got {
Todd Wang338f90c2015-05-07 19:42:46 -0700203 return env.UsageErrorf("resolve: incorrect number of arguments, expected %d, got %d", expected, got)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700204 }
205 name := args[0]
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800206
Todd Wang338f90c2015-05-07 19:42:46 -0700207 ctx, cancel := context.WithTimeout(ctx, time.Minute)
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700208 defer cancel()
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800209
Jiri Simsa6ac95222015-02-23 16:11:49 -0800210 ns := v23.GetNamespace(ctx)
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800211
David Why Use Two When One Will Do Presotto38788d42015-03-31 17:13:54 -0700212 var opts []naming.NamespaceOpt
Asim Shankarb2cc1292015-02-23 15:22:45 -0800213 if flagInsecureResolve {
Asim Shankar263c73b2015-03-19 18:31:26 -0700214 opts = append(opts, options.SkipServerEndpointAuthorization{})
Asim Shankarb2cc1292015-02-23 15:22:45 -0800215 }
216 me, err := ns.Resolve(ctx, name, opts...)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700217 if err != nil {
218 vlog.Infof("ns.Resolve(%q) failed: %v", name, err)
219 return err
220 }
Asim Shankar43d1f932015-03-24 20:57:56 -0700221 for _, n := range me.Names() {
Todd Wang338f90c2015-05-07 19:42:46 -0700222 fmt.Fprintln(env.Stdout, n)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700223 }
224 return nil
225}
226
Todd Wang338f90c2015-05-07 19:42:46 -0700227var cmdResolveToMT = &cmdline2.Command{
228 Runner: v23cmd.RunnerFunc(runResolveToMT),
Robin Thellend4f5f5052014-07-01 15:43:10 -0700229 Name: "resolvetomt",
230 Short: "Finds the address of the mounttable that holds an object name",
231 Long: "Finds the address of the mounttable that holds an object name.",
232 ArgsName: "<name>",
233 ArgsLong: "<name> is the name to resolve.",
234}
235
Todd Wang338f90c2015-05-07 19:42:46 -0700236func runResolveToMT(ctx *context.T, env *cmdline2.Env, args []string) error {
Robin Thellend4f5f5052014-07-01 15:43:10 -0700237 if expected, got := 1, len(args); expected != got {
Todd Wang338f90c2015-05-07 19:42:46 -0700238 return env.UsageErrorf("resolvetomt: incorrect number of arguments, expected %d, got %d", expected, got)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700239 }
240 name := args[0]
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800241
Todd Wang338f90c2015-05-07 19:42:46 -0700242 ctx, cancel := context.WithTimeout(ctx, time.Minute)
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700243 defer cancel()
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800244
Jiri Simsa6ac95222015-02-23 16:11:49 -0800245 ns := v23.GetNamespace(ctx)
David Why Use Two When One Will Do Presotto38788d42015-03-31 17:13:54 -0700246 var opts []naming.NamespaceOpt
Asim Shankarb2cc1292015-02-23 15:22:45 -0800247 if flagInsecureResolveToMT {
Asim Shankar263c73b2015-03-19 18:31:26 -0700248 opts = append(opts, options.SkipServerEndpointAuthorization{})
Asim Shankarb2cc1292015-02-23 15:22:45 -0800249 }
250 e, err := ns.ResolveToMountTable(ctx, name, opts...)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700251 if err != nil {
David Why Use Two When One Will Do Presotto8de85852015-01-21 11:05:09 -0800252 vlog.Infof("ns.ResolveToMountTable(%q) failed: %v", name, err)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700253 return err
254 }
Asim Shankar43d1f932015-03-24 20:57:56 -0700255 for _, s := range e.Servers {
Todd Wang338f90c2015-05-07 19:42:46 -0700256 fmt.Fprintln(env.Stdout, naming.JoinAddressName(s.Server, e.Name))
Robin Thellend4f5f5052014-07-01 15:43:10 -0700257 }
258 return nil
259}
260
Todd Wang338f90c2015-05-07 19:42:46 -0700261var cmdPermissions = &cmdline2.Command{
Asim Shankar94117172015-04-09 00:20:51 -0700262 Name: "permissions",
263 Short: "Manipulates permissions on an entry in the namespace",
264 Long: `
265Commands to get and set the permissions on a name - controlling the blessing
266names required to resolve the name.
267
268The permissions are provided as an JSON-encoded version of the Permissions type
269defined in v.io/v23/security/access/types.vdl.
270`,
Todd Wang338f90c2015-05-07 19:42:46 -0700271 Children: []*cmdline2.Command{cmdPermissionsGet, cmdPermissionsSet},
Asim Shankar94117172015-04-09 00:20:51 -0700272}
273
Todd Wang338f90c2015-05-07 19:42:46 -0700274var cmdPermissionsSet = &cmdline2.Command{
275 Runner: v23cmd.RunnerFunc(runPermissionsSet),
276 Name: "set",
277 Short: "Sets permissions on a mount name",
Asim Shankar94117172015-04-09 00:20:51 -0700278 Long: `
279Set replaces the permissions controlling usage of a mount name.
280`,
281 ArgsName: "<name> <permissions>",
282 ArgsLong: `
283<name> is the name on which permissions are to be set.
284
285<permissions> is the path to a file containing a JSON-encoded Permissions
286object (defined in v.io/v23/security/access/types.vdl), or "-" for STDIN.
287`,
288}
289
Todd Wang338f90c2015-05-07 19:42:46 -0700290func runPermissionsSet(ctx *context.T, env *cmdline2.Env, args []string) error {
Asim Shankar94117172015-04-09 00:20:51 -0700291 if expected, got := 2, len(args); expected != got {
Todd Wang338f90c2015-05-07 19:42:46 -0700292 return env.UsageErrorf("set: incorrect number of arguments, expected %d, got %d", expected, got)
Asim Shankar94117172015-04-09 00:20:51 -0700293 }
294 name := args[0]
295 var perms access.Permissions
296 file := os.Stdin
297 if args[1] != "-" {
298 var err error
299 if file, err = os.Open(args[1]); err != nil {
300 return err
301 }
302 defer file.Close()
303 }
304 if err := json.NewDecoder(file).Decode(&perms); err != nil {
305 return err
306 }
Todd Wang338f90c2015-05-07 19:42:46 -0700307 ctx, cancel := context.WithTimeout(ctx, time.Minute)
Asim Shankar94117172015-04-09 00:20:51 -0700308 defer cancel()
309 ns := v23.GetNamespace(ctx)
310 for {
311 _, etag, err := ns.GetPermissions(ctx, name)
Nicolas Lacassecc415562015-04-10 10:09:46 -0700312 if err != nil && verror.ErrorID(err) != naming.ErrNoSuchName.ID {
Asim Shankar94117172015-04-09 00:20:51 -0700313 return err
314 }
315 if err = ns.SetPermissions(ctx, name, perms, etag); verror.ErrorID(err) == verror.ErrBadVersion.ID {
316 vlog.Infof("SetPermissions(%q, %q) failed: %v, retrying...", name, etag, err)
317 continue
318 }
319 return err
320 }
321}
322
Todd Wang338f90c2015-05-07 19:42:46 -0700323var cmdPermissionsGet = &cmdline2.Command{
324 Runner: v23cmd.RunnerFunc(runPermissionsGet),
Asim Shankar94117172015-04-09 00:20:51 -0700325 Name: "get",
326 Short: "Gets permissions on a mount name",
327 ArgsName: "<name>",
328 ArgsLong: `
329<name> is a name in the namespace.
330`,
331 Long: `
332Get retrieves the permissions on the usage of a name.
333
334The output is a JSON-encoded Permissions object (defined in
335v.io/v23/security/access/types.vdl).
336`,
337}
338
Todd Wang338f90c2015-05-07 19:42:46 -0700339func runPermissionsGet(ctx *context.T, env *cmdline2.Env, args []string) error {
Asim Shankar94117172015-04-09 00:20:51 -0700340 if expected, got := 1, len(args); expected != got {
Todd Wang338f90c2015-05-07 19:42:46 -0700341 return env.UsageErrorf("get: incorrect number of arguments, expected %d, got %d", expected, got)
Asim Shankar94117172015-04-09 00:20:51 -0700342 }
343 name := args[0]
Todd Wang338f90c2015-05-07 19:42:46 -0700344 ctx, cancel := context.WithTimeout(ctx, time.Minute)
Asim Shankar94117172015-04-09 00:20:51 -0700345 defer cancel()
346
347 perms, _, err := v23.GetNamespace(ctx).GetPermissions(ctx, name)
348 if err != nil {
349 return err
350 }
Todd Wang338f90c2015-05-07 19:42:46 -0700351 return json.NewEncoder(env.Stdout).Encode(perms)
Asim Shankar94117172015-04-09 00:20:51 -0700352}
353
Todd Wang338f90c2015-05-07 19:42:46 -0700354var cmdDelete = &cmdline2.Command{
355 Runner: v23cmd.RunnerFunc(runDelete),
Nicolas Lacasse0dc334e2015-04-10 10:19:41 -0700356 Name: "delete",
357 Short: "Deletes a name from the namespace",
358 ArgsName: "<name>",
359 ArgsLong: "<name> is a name to delete.",
360 Long: "Deletes a name from the namespace.",
361}
362
Todd Wang338f90c2015-05-07 19:42:46 -0700363func runDelete(ctx *context.T, env *cmdline2.Env, args []string) error {
Nicolas Lacasse0dc334e2015-04-10 10:19:41 -0700364 if expected, got := 1, len(args); expected != got {
Todd Wang338f90c2015-05-07 19:42:46 -0700365 return env.UsageErrorf("delete: incorrect number of arguments, expected %d, got %d", expected, got)
Nicolas Lacasse0dc334e2015-04-10 10:19:41 -0700366 }
367 name := args[0]
Todd Wang338f90c2015-05-07 19:42:46 -0700368 ctx, cancel := context.WithTimeout(ctx, time.Minute)
Nicolas Lacasse0dc334e2015-04-10 10:19:41 -0700369 defer cancel()
370
371 return v23.GetNamespace(ctx).Delete(ctx, name, flagDeleteSubtree)
372}
373
Todd Wang338f90c2015-05-07 19:42:46 -0700374var cmdRoot = &cmdline2.Command{
375 Name: "namespace",
376 Short: "resolves and manages names in the Vanadium namespace",
377 Long: `
Todd Wang6ed3b6c2015-04-08 14:37:04 -0700378Command namespace resolves and manages names in the Vanadium namespace.
Robin Thellend4f5f5052014-07-01 15:43:10 -0700379
Asim Shankarf32d24d2015-04-01 16:34:26 -0700380The namespace roots are set from the command line via --v23.namespace.root
381command line option or from environment variables that have a name starting
382with V23_NAMESPACE, e.g. V23_NAMESPACE, V23_NAMESPACE_2, V23_NAMESPACE_GOOGLE,
383etc. The command line options override the environment.
Robin Thellend4f5f5052014-07-01 15:43:10 -0700384`,
Todd Wang338f90c2015-05-07 19:42:46 -0700385 Children: []*cmdline2.Command{cmdGlob, cmdMount, cmdUnmount, cmdResolve, cmdResolveToMT, cmdPermissions, cmdDelete},
Robin Thellend4f5f5052014-07-01 15:43:10 -0700386}