blob: 2d16cdc34ac03f980efbf51db43566516c2722b8 [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
Robin Thellend18205cf2014-10-21 13:53:59 -07005package main
Robin Thellend4f5f5052014-07-01 15:43:10 -07006
7import (
Asim Shankar94117172015-04-09 00:20:51 -07008 "encoding/json"
Robin Thellend4f5f5052014-07-01 15:43:10 -07009 "fmt"
Asim Shankar94117172015-04-09 00:20:51 -070010 "os"
Robin Thellendc300a952015-04-08 15:14:43 -070011 "sort"
Robin Thellend4f5f5052014-07-01 15:43:10 -070012 "time"
13
Jiri Simsa6ac95222015-02-23 16:11:49 -080014 "v.io/v23"
15 "v.io/v23/context"
Jiri Simsa6ac95222015-02-23 16:11:49 -080016 "v.io/v23/naming"
17 "v.io/v23/options"
Asim Shankar94117172015-04-09 00:20:51 -070018 "v.io/v23/security/access"
19 "v.io/v23/verror"
Jiri Simsa24a71552015-02-27 11:31:36 -080020 "v.io/x/lib/cmdline"
Jiri Simsa337af232015-02-27 14:36:46 -080021 "v.io/x/lib/vlog"
Robin Thellend4f5f5052014-07-01 15:43:10 -070022)
23
Asim Shankarb2cc1292015-02-23 15:22:45 -080024var (
Robin Thellendc300a952015-04-08 15:14:43 -070025 flagLongGlob bool
Asim Shankarb2cc1292015-02-23 15:22:45 -080026 flagInsecureResolve bool
27 flagInsecureResolveToMT bool
Nicolas Lacasse0dc334e2015-04-10 10:19:41 -070028 flagDeleteSubtree bool
Asim Shankarb2cc1292015-02-23 15:22:45 -080029)
30
Robin Thellend4f5f5052014-07-01 15:43:10 -070031var cmdGlob = &cmdline.Command{
32 Run: runGlob,
33 Name: "glob",
34 Short: "Returns all matching entries from the namespace",
35 Long: "Returns all matching entries from the namespace.",
36 ArgsName: "<pattern>",
37 ArgsLong: `
38<pattern> is a glob pattern that is matched against all the names below the
39specified mount name.
40`,
41}
42
43func runGlob(cmd *cmdline.Command, args []string) error {
44 if expected, got := 1, len(args); expected != got {
Todd Wanga615e4d2014-09-29 16:56:05 -070045 return cmd.UsageErrorf("glob: incorrect number of arguments, expected %d, got %d", expected, got)
Robin Thellend4f5f5052014-07-01 15:43:10 -070046 }
47 pattern := args[0]
Matt Rosencrantzd599e382015-01-12 11:13:32 -080048
Matt Rosencrantza5ad2722015-01-22 11:17:47 -080049 ctx, cancel := context.WithTimeout(gctx, time.Minute)
Matt Rosencrantz137b8d22014-08-18 09:56:15 -070050 defer cancel()
Matt Rosencrantzd599e382015-01-12 11:13:32 -080051
Jiri Simsa6ac95222015-02-23 16:11:49 -080052 ns := v23.GetNamespace(ctx)
Matt Rosencrantzd599e382015-01-12 11:13:32 -080053
Matt Rosencrantz137b8d22014-08-18 09:56:15 -070054 c, err := ns.Glob(ctx, pattern)
Robin Thellend4f5f5052014-07-01 15:43:10 -070055 if err != nil {
56 vlog.Infof("ns.Glob(%q) failed: %v", pattern, err)
57 return err
58 }
Robin Thellendc300a952015-04-08 15:14:43 -070059 if flagLongGlob {
60 // Show all the information we received.
61 for res := range c {
62 switch v := res.(type) {
James Ringc971dca2015-04-09 09:51:20 -070063 case *naming.GlobReplyEntry:
64 fmt.Fprint(cmd.Stdout(), v.Value.Name)
65 for _, s := range v.Value.Servers {
Robin Thellendc300a952015-04-08 15:14:43 -070066 delta := s.Deadline.Time.Sub(time.Now())
67 fmt.Fprintf(cmd.Stdout(), " %s (Expires in %d sec)", s.Server, int(delta.Seconds()))
68 }
69 fmt.Fprintln(cmd.Stdout())
James Ringc971dca2015-04-09 09:51:20 -070070 case *naming.GlobReplyError:
71 fmt.Fprintf(cmd.Stderr(), "Error: %s: %v\n", v.Value.Name, v.Value.Error)
Robin Thellendc300a952015-04-08 15:14:43 -070072 }
73 }
74 return nil
75 }
76 // Show a sorted list of unique names, and any errors.
77 resultSet := make(map[string]struct{})
78 errors := []*naming.GlobError{}
Robin Thellend4f5f5052014-07-01 15:43:10 -070079 for res := range c {
David Why Use Two When One Will Do Presotto03c34d62015-02-10 01:38:58 -080080 switch v := res.(type) {
James Ringc971dca2015-04-09 09:51:20 -070081 case *naming.GlobReplyEntry:
82 if v.Value.Name != "" {
83 resultSet[v.Value.Name] = struct{}{}
David Why Use Two When One Will Do Presotto03c34d62015-02-10 01:38:58 -080084 }
James Ringc971dca2015-04-09 09:51:20 -070085 case *naming.GlobReplyError:
86 errors = append(errors, &v.Value)
Robin Thellend20732e52015-02-08 10:34:01 -080087 }
Robin Thellend4f5f5052014-07-01 15:43:10 -070088 }
Robin Thellendc300a952015-04-08 15:14:43 -070089 results := []string{}
90 for r := range resultSet {
91 results = append(results, r)
92 }
93 sort.Strings(results)
94 for _, result := range results {
95 fmt.Fprintln(cmd.Stdout(), result)
96 }
97 for _, err := range errors {
98 fmt.Fprintf(cmd.Stderr(), "Error: %s: %v\n", err.Name, err.Error)
99 }
Robin Thellend4f5f5052014-07-01 15:43:10 -0700100 return nil
101}
102
103var cmdMount = &cmdline.Command{
104 Run: runMount,
105 Name: "mount",
106 Short: "Adds a server to the namespace",
107 Long: "Adds server <server> to the namespace with name <name>.",
108 ArgsName: "<name> <server> <ttl>",
109 ArgsLong: `
110<name> is the name to add to the namespace.
111<server> is the object address of the server to add.
112<ttl> is the TTL of the new entry. It is a decimal number followed by a unit
113suffix (s, m, h). A value of 0s represents an infinite duration.
114`,
115}
116
117func runMount(cmd *cmdline.Command, args []string) error {
118 if expected, got := 3, len(args); expected != got {
Todd Wanga615e4d2014-09-29 16:56:05 -0700119 return cmd.UsageErrorf("mount: incorrect number of arguments, expected %d, got %d", expected, got)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700120 }
121 name := args[0]
122 server := args[1]
123 ttlArg := args[2]
124
125 ttl, err := time.ParseDuration(ttlArg)
126 if err != nil {
127 return fmt.Errorf("TTL parse error: %v", err)
128 }
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800129
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800130 ctx, cancel := context.WithTimeout(gctx, time.Minute)
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700131 defer cancel()
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800132
Jiri Simsa6ac95222015-02-23 16:11:49 -0800133 ns := v23.GetNamespace(ctx)
Asim Shankar43d1f932015-03-24 20:57:56 -0700134 if err = ns.Mount(ctx, name, server, ttl); err != nil {
135 vlog.Infof("ns.Mount(%q, %q, %s) failed: %v", name, server, ttl, err)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700136 return err
137 }
138 fmt.Fprintln(cmd.Stdout(), "Server mounted successfully.")
139 return nil
140}
141
142var cmdUnmount = &cmdline.Command{
143 Run: runUnmount,
144 Name: "unmount",
145 Short: "Removes a server from the namespace",
146 Long: "Removes server <server> with name <name> from the namespace.",
147 ArgsName: "<name> <server>",
148 ArgsLong: `
149<name> is the name to remove from the namespace.
150<server> is the object address of the server to remove.
151`,
152}
153
154func runUnmount(cmd *cmdline.Command, args []string) error {
155 if expected, got := 2, len(args); expected != got {
Todd Wanga615e4d2014-09-29 16:56:05 -0700156 return cmd.UsageErrorf("unmount: incorrect number of arguments, expected %d, got %d", expected, got)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700157 }
158 name := args[0]
159 server := args[1]
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800160
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800161 ctx, cancel := context.WithTimeout(gctx, time.Minute)
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700162 defer cancel()
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800163
Jiri Simsa6ac95222015-02-23 16:11:49 -0800164 ns := v23.GetNamespace(ctx)
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800165
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700166 if err := ns.Unmount(ctx, name, server); err != nil {
Robin Thellend4f5f5052014-07-01 15:43:10 -0700167 vlog.Infof("ns.Unmount(%q, %q) failed: %v", name, server, err)
168 return err
169 }
170 fmt.Fprintln(cmd.Stdout(), "Server unmounted successfully.")
171 return nil
172}
173
174var cmdResolve = &cmdline.Command{
175 Run: runResolve,
176 Name: "resolve",
177 Short: "Translates a object name to its object address(es)",
178 Long: "Translates a object name to its object address(es).",
179 ArgsName: "<name>",
180 ArgsLong: "<name> is the name to resolve.",
181}
182
183func runResolve(cmd *cmdline.Command, args []string) error {
184 if expected, got := 1, len(args); expected != got {
Todd Wanga615e4d2014-09-29 16:56:05 -0700185 return cmd.UsageErrorf("resolve: incorrect number of arguments, expected %d, got %d", expected, got)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700186 }
187 name := args[0]
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800188
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800189 ctx, cancel := context.WithTimeout(gctx, time.Minute)
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700190 defer cancel()
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800191
Jiri Simsa6ac95222015-02-23 16:11:49 -0800192 ns := v23.GetNamespace(ctx)
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800193
David Why Use Two When One Will Do Presotto38788d42015-03-31 17:13:54 -0700194 var opts []naming.NamespaceOpt
Asim Shankarb2cc1292015-02-23 15:22:45 -0800195 if flagInsecureResolve {
Asim Shankar263c73b2015-03-19 18:31:26 -0700196 opts = append(opts, options.SkipServerEndpointAuthorization{})
Asim Shankarb2cc1292015-02-23 15:22:45 -0800197 }
198 me, err := ns.Resolve(ctx, name, opts...)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700199 if err != nil {
200 vlog.Infof("ns.Resolve(%q) failed: %v", name, err)
201 return err
202 }
Asim Shankar43d1f932015-03-24 20:57:56 -0700203 for _, n := range me.Names() {
204 fmt.Fprintln(cmd.Stdout(), n)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700205 }
206 return nil
207}
208
209var cmdResolveToMT = &cmdline.Command{
210 Run: runResolveToMT,
211 Name: "resolvetomt",
212 Short: "Finds the address of the mounttable that holds an object name",
213 Long: "Finds the address of the mounttable that holds an object name.",
214 ArgsName: "<name>",
215 ArgsLong: "<name> is the name to resolve.",
216}
217
218func runResolveToMT(cmd *cmdline.Command, args []string) error {
219 if expected, got := 1, len(args); expected != got {
Todd Wanga615e4d2014-09-29 16:56:05 -0700220 return cmd.UsageErrorf("resolvetomt: incorrect number of arguments, expected %d, got %d", expected, got)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700221 }
222 name := args[0]
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800223
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800224 ctx, cancel := context.WithTimeout(gctx, time.Minute)
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700225 defer cancel()
Matt Rosencrantzd599e382015-01-12 11:13:32 -0800226
Jiri Simsa6ac95222015-02-23 16:11:49 -0800227 ns := v23.GetNamespace(ctx)
David Why Use Two When One Will Do Presotto38788d42015-03-31 17:13:54 -0700228 var opts []naming.NamespaceOpt
Asim Shankarb2cc1292015-02-23 15:22:45 -0800229 if flagInsecureResolveToMT {
Asim Shankar263c73b2015-03-19 18:31:26 -0700230 opts = append(opts, options.SkipServerEndpointAuthorization{})
Asim Shankarb2cc1292015-02-23 15:22:45 -0800231 }
232 e, err := ns.ResolveToMountTable(ctx, name, opts...)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700233 if err != nil {
David Why Use Two When One Will Do Presotto8de85852015-01-21 11:05:09 -0800234 vlog.Infof("ns.ResolveToMountTable(%q) failed: %v", name, err)
Robin Thellend4f5f5052014-07-01 15:43:10 -0700235 return err
236 }
Asim Shankar43d1f932015-03-24 20:57:56 -0700237 for _, s := range e.Servers {
238 fmt.Fprintln(cmd.Stdout(), naming.JoinAddressName(s.Server, e.Name))
Robin Thellend4f5f5052014-07-01 15:43:10 -0700239 }
240 return nil
241}
242
Asim Shankar94117172015-04-09 00:20:51 -0700243var cmdPermissions = &cmdline.Command{
244 Name: "permissions",
245 Short: "Manipulates permissions on an entry in the namespace",
246 Long: `
247Commands to get and set the permissions on a name - controlling the blessing
248names required to resolve the name.
249
250The permissions are provided as an JSON-encoded version of the Permissions type
251defined in v.io/v23/security/access/types.vdl.
252`,
253 Children: []*cmdline.Command{cmdPermissionsGet, cmdPermissionsSet},
254}
255
256var cmdPermissionsSet = &cmdline.Command{
257 Run: runPermissionsSet,
258 Name: "set",
259 Short: "Sets permissions on a mount name",
260 Long: `
261Set replaces the permissions controlling usage of a mount name.
262`,
263 ArgsName: "<name> <permissions>",
264 ArgsLong: `
265<name> is the name on which permissions are to be set.
266
267<permissions> is the path to a file containing a JSON-encoded Permissions
268object (defined in v.io/v23/security/access/types.vdl), or "-" for STDIN.
269`,
270}
271
272func runPermissionsSet(cmd *cmdline.Command, args []string) error {
273 if expected, got := 2, len(args); expected != got {
274 return cmd.UsageErrorf("set: incorrect number of arguments, expected %d, got %d", expected, got)
275 }
276 name := args[0]
277 var perms access.Permissions
278 file := os.Stdin
279 if args[1] != "-" {
280 var err error
281 if file, err = os.Open(args[1]); err != nil {
282 return err
283 }
284 defer file.Close()
285 }
286 if err := json.NewDecoder(file).Decode(&perms); err != nil {
287 return err
288 }
289 ctx, cancel := context.WithTimeout(gctx, time.Minute)
290 defer cancel()
291 ns := v23.GetNamespace(ctx)
292 for {
293 _, etag, err := ns.GetPermissions(ctx, name)
294 if err != nil {
295 return err
296 }
297 if err = ns.SetPermissions(ctx, name, perms, etag); verror.ErrorID(err) == verror.ErrBadVersion.ID {
298 vlog.Infof("SetPermissions(%q, %q) failed: %v, retrying...", name, etag, err)
299 continue
300 }
301 return err
302 }
303}
304
305var cmdPermissionsGet = &cmdline.Command{
306 Run: runPermissionsGet,
307 Name: "get",
308 Short: "Gets permissions on a mount name",
309 ArgsName: "<name>",
310 ArgsLong: `
311<name> is a name in the namespace.
312`,
313 Long: `
314Get retrieves the permissions on the usage of a name.
315
316The output is a JSON-encoded Permissions object (defined in
317v.io/v23/security/access/types.vdl).
318`,
319}
320
321func runPermissionsGet(cmd *cmdline.Command, args []string) error {
322 if expected, got := 1, len(args); expected != got {
323 return cmd.UsageErrorf("get: incorrect number of arguments, expected %d, got %d", expected, got)
324 }
325 name := args[0]
326 ctx, cancel := context.WithTimeout(gctx, time.Minute)
327 defer cancel()
328
329 perms, _, err := v23.GetNamespace(ctx).GetPermissions(ctx, name)
330 if err != nil {
331 return err
332 }
333 return json.NewEncoder(cmd.Stdout()).Encode(perms)
334}
335
Nicolas Lacasse0dc334e2015-04-10 10:19:41 -0700336var cmdDelete = &cmdline.Command{
337 Run: runDelete,
338 Name: "delete",
339 Short: "Deletes a name from the namespace",
340 ArgsName: "<name>",
341 ArgsLong: "<name> is a name to delete.",
342 Long: "Deletes a name from the namespace.",
343}
344
345func runDelete(cmd *cmdline.Command, args []string) error {
346 if expected, got := 1, len(args); expected != got {
347 return cmd.UsageErrorf("delete: incorrect number of arguments, expected %d, got %d", expected, got)
348 }
349 name := args[0]
350 ctx, cancel := context.WithTimeout(gctx, time.Minute)
351 defer cancel()
352
353 return v23.GetNamespace(ctx).Delete(ctx, name, flagDeleteSubtree)
354}
355
Robin Thellend18205cf2014-10-21 13:53:59 -0700356func root() *cmdline.Command {
Robin Thellendc300a952015-04-08 15:14:43 -0700357 cmdGlob.Flags.BoolVar(&flagLongGlob, "l", false, "Long listing format.")
Asim Shankarb2cc1292015-02-23 15:22:45 -0800358 cmdResolve.Flags.BoolVar(&flagInsecureResolve, "insecure", false, "Insecure mode: May return results from untrusted servers and invoke Resolve on untrusted mounttables")
359 cmdResolveToMT.Flags.BoolVar(&flagInsecureResolveToMT, "insecure", false, "Insecure mode: May return results from untrusted servers and invoke Resolve on untrusted mounttables")
Nicolas Lacasse0dc334e2015-04-10 10:19:41 -0700360 cmdDelete.Flags.BoolVar(&flagDeleteSubtree, "r", false, "Delete all children of the name in addition to the name itself.")
Robin Thellend4f5f5052014-07-01 15:43:10 -0700361 return &cmdline.Command{
362 Name: "namespace",
Todd Wang6ed3b6c2015-04-08 14:37:04 -0700363 Short: "resolves and manages names in the Vanadium namespace",
Robin Thellend4f5f5052014-07-01 15:43:10 -0700364 Long: `
Todd Wang6ed3b6c2015-04-08 14:37:04 -0700365Command namespace resolves and manages names in the Vanadium namespace.
Robin Thellend4f5f5052014-07-01 15:43:10 -0700366
Asim Shankarf32d24d2015-04-01 16:34:26 -0700367The namespace roots are set from the command line via --v23.namespace.root
368command line option or from environment variables that have a name starting
369with V23_NAMESPACE, e.g. V23_NAMESPACE, V23_NAMESPACE_2, V23_NAMESPACE_GOOGLE,
370etc. The command line options override the environment.
Robin Thellend4f5f5052014-07-01 15:43:10 -0700371`,
Nicolas Lacasse0dc334e2015-04-10 10:19:41 -0700372 Children: []*cmdline.Command{cmdGlob, cmdMount, cmdUnmount, cmdResolve, cmdResolveToMT, cmdPermissions, cmdDelete},
Robin Thellend4f5f5052014-07-01 15:43:10 -0700373 }
374}