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 | |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 5 | // The following enables go generate to generate the doc.go file. |
Nicolas Lacasse | 1b1b938 | 2015-09-24 10:00:35 -0700 | [diff] [blame] | 6 | //go:generate go run $JIRI_ROOT/release/go/src/v.io/x/lib/cmdline/testdata/gendoc.go . |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 7 | |
Robin Thellend | 18205cf | 2014-10-21 13:53:59 -0700 | [diff] [blame] | 8 | package main |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 9 | |
| 10 | import ( |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 11 | "errors" |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 12 | "fmt" |
Todd Wang | 1624bf9 | 2015-04-22 16:53:57 -0700 | [diff] [blame] | 13 | "regexp" |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 14 | "time" |
| 15 | |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame] | 16 | "v.io/x/lib/cmdline" |
| 17 | |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 18 | "v.io/v23" |
| 19 | "v.io/v23/context" |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 20 | "v.io/v23/naming" |
| 21 | "v.io/v23/options" |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 22 | "v.io/v23/rpc" |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 23 | "v.io/v23/security" |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame] | 24 | |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 25 | "v.io/x/ref/lib/v23cmd" |
Suharsh Sivakumar | dcc11d7 | 2015-05-11 12:19:20 -0700 | [diff] [blame] | 26 | _ "v.io/x/ref/runtime/factories/generic" |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 27 | ) |
| 28 | |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 29 | func main() { |
Todd Wang | 9560b9c | 2015-05-11 13:27:58 -0700 | [diff] [blame] | 30 | cmdline.HideGlobalFlagsExcept(regexp.MustCompile(`^v23\.namespace\.root$`)) |
| 31 | cmdline.Main(cmdRoot) |
Todd Wang | 1624bf9 | 2015-04-22 16:53:57 -0700 | [diff] [blame] | 32 | } |
| 33 | |
Todd Wang | 9560b9c | 2015-05-11 13:27:58 -0700 | [diff] [blame] | 34 | var cmdGlob = &cmdline.Command{ |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 35 | Runner: v23cmd.RunnerFunc(runGlob), |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 36 | Name: "glob", |
| 37 | Short: "returns all matching entries in the mount table", |
| 38 | Long: "returns all matching entries in the mount table", |
Bogdan Caprita | decd105 | 2014-11-08 16:15:54 -0800 | [diff] [blame] | 39 | ArgsName: "[<mount name>] <pattern>", |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 40 | ArgsLong: ` |
Bogdan Caprita | decd105 | 2014-11-08 16:15:54 -0800 | [diff] [blame] | 41 | <mount name> is a mount name on a mount table. Defaults to namespace root. |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 42 | <pattern> is a glob pattern that is matched against all the entries below the |
| 43 | specified mount name. |
| 44 | `, |
| 45 | } |
| 46 | |
Todd Wang | 9560b9c | 2015-05-11 13:27:58 -0700 | [diff] [blame] | 47 | func runGlob(ctx *context.T, env *cmdline.Env, args []string) error { |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 48 | ctx, cancel := context.WithTimeout(ctx, time.Minute) |
Matt Rosencrantz | d599e38 | 2015-01-12 11:13:32 -0800 | [diff] [blame] | 49 | defer cancel() |
| 50 | |
Bogdan Caprita | decd105 | 2014-11-08 16:15:54 -0800 | [diff] [blame] | 51 | if len(args) == 1 { |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 52 | roots := v23.GetNamespace(ctx).Roots() |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 53 | if len(roots) == 0 { |
| 54 | return errors.New("no namespace root") |
| 55 | } |
| 56 | args = append([]string{roots[0]}, args...) |
Bogdan Caprita | decd105 | 2014-11-08 16:15:54 -0800 | [diff] [blame] | 57 | } |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 58 | if expected, got := 2, len(args); expected != got { |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 59 | return env.UsageErrorf("glob: incorrect number of arguments, expected %d, got %d", expected, got) |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 60 | } |
Matt Rosencrantz | d599e38 | 2015-01-12 11:13:32 -0800 | [diff] [blame] | 61 | |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 62 | name, pattern := args[0], args[1] |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 63 | client := v23.GetClient(ctx) |
David Why Use Two When One Will Do Presotto | c279841 | 2015-09-08 12:53:34 -0700 | [diff] [blame] | 64 | call, err := client.StartCall(ctx, name, rpc.GlobMethod, []interface{}{pattern}, options.Preresolved{}) |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 65 | if err != nil { |
| 66 | return err |
| 67 | } |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 68 | for { |
Todd Wang | 2331dd0 | 2015-03-17 15:38:39 -0700 | [diff] [blame] | 69 | var gr naming.GlobReply |
David Why Use Two When One Will Do Presotto | e5e62d0 | 2015-02-19 14:35:20 -0800 | [diff] [blame] | 70 | if err := call.Recv(&gr); err != nil { |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 71 | break |
| 72 | } |
David Why Use Two When One Will Do Presotto | e5e62d0 | 2015-02-19 14:35:20 -0800 | [diff] [blame] | 73 | switch v := gr.(type) { |
Todd Wang | 2331dd0 | 2015-03-17 15:38:39 -0700 | [diff] [blame] | 74 | case naming.GlobReplyEntry: |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 75 | fmt.Fprint(env.Stdout, v.Value.Name) |
David Why Use Two When One Will Do Presotto | e5e62d0 | 2015-02-19 14:35:20 -0800 | [diff] [blame] | 76 | for _, s := range v.Value.Servers { |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 77 | fmt.Fprintf(env.Stdout, " %s (Deadline %s)", s.Server, s.Deadline.Time) |
David Why Use Two When One Will Do Presotto | e5e62d0 | 2015-02-19 14:35:20 -0800 | [diff] [blame] | 78 | } |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 79 | fmt.Fprintln(env.Stdout) |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 80 | } |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 81 | } |
Todd Wang | e77f995 | 2015-02-18 13:20:50 -0800 | [diff] [blame] | 82 | if err := call.Finish(); err != nil { |
| 83 | return err |
Shyam Jayaraman | c4aed6e | 2014-07-22 14:25:06 -0700 | [diff] [blame] | 84 | } |
Todd Wang | e77f995 | 2015-02-18 13:20:50 -0800 | [diff] [blame] | 85 | return nil |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 86 | } |
| 87 | |
Todd Wang | 9560b9c | 2015-05-11 13:27:58 -0700 | [diff] [blame] | 88 | var cmdMount = &cmdline.Command{ |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 89 | Runner: v23cmd.RunnerFunc(runMount), |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 90 | Name: "mount", |
| 91 | Short: "Mounts a server <name> onto a mount table", |
| 92 | Long: "Mounts a server <name> onto a mount table", |
Robin Thellend | 5820666 | 2015-02-17 17:36:08 -0800 | [diff] [blame] | 93 | ArgsName: "<mount name> <name> <ttl> [M|R]", |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 94 | ArgsLong: ` |
| 95 | <mount name> is a mount name on a mount table. |
Robin Thellend | 5820666 | 2015-02-17 17:36:08 -0800 | [diff] [blame] | 96 | |
Bogdan Caprita | d9281a3 | 2014-07-02 14:40:39 -0700 | [diff] [blame] | 97 | <name> is the rooted object name of the server. |
Robin Thellend | 5820666 | 2015-02-17 17:36:08 -0800 | [diff] [blame] | 98 | |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 99 | <ttl> is the TTL of the new entry. It is a decimal number followed by a unit |
| 100 | suffix (s, m, h). A value of 0s represents an infinite duration. |
Robin Thellend | 5820666 | 2015-02-17 17:36:08 -0800 | [diff] [blame] | 101 | |
| 102 | [M|R] are mount options. M indicates that <name> is a mounttable. R indicates |
| 103 | that existing entries should be removed. |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 104 | `, |
| 105 | } |
| 106 | |
Todd Wang | 9560b9c | 2015-05-11 13:27:58 -0700 | [diff] [blame] | 107 | func runMount(ctx *context.T, env *cmdline.Env, args []string) error { |
David Why Use Two When One Will Do Presotto | 59a254c | 2014-10-30 13:09:29 -0700 | [diff] [blame] | 108 | got := len(args) |
| 109 | if got < 2 || got > 4 { |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 110 | return env.UsageErrorf("mount: incorrect number of arguments, expected 2, 3, or 4, got %d", got) |
David Why Use Two When One Will Do Presotto | 59a254c | 2014-10-30 13:09:29 -0700 | [diff] [blame] | 111 | } |
Asim Shankar | b2cc129 | 2015-02-23 15:22:45 -0800 | [diff] [blame] | 112 | name := args[0] |
| 113 | server := args[1] |
Cosmos Nicolaou | 036c30c | 2015-03-24 10:05:20 -0700 | [diff] [blame] | 114 | |
Todd Wang | 1aa5769 | 2014-11-11 13:53:29 -0800 | [diff] [blame] | 115 | var flags naming.MountFlag |
David Why Use Two When One Will Do Presotto | 59a254c | 2014-10-30 13:09:29 -0700 | [diff] [blame] | 116 | var seconds uint32 |
| 117 | if got >= 3 { |
| 118 | ttl, err := time.ParseDuration(args[2]) |
| 119 | if err != nil { |
| 120 | return fmt.Errorf("TTL parse error: %v", err) |
| 121 | } |
| 122 | seconds = uint32(ttl.Seconds()) |
| 123 | } |
| 124 | if got >= 4 { |
| 125 | for _, c := range args[3] { |
| 126 | switch c { |
| 127 | case 'M': |
Todd Wang | 1aa5769 | 2014-11-11 13:53:29 -0800 | [diff] [blame] | 128 | flags |= naming.MountFlag(naming.MT) |
David Why Use Two When One Will Do Presotto | 59a254c | 2014-10-30 13:09:29 -0700 | [diff] [blame] | 129 | case 'R': |
Todd Wang | 1aa5769 | 2014-11-11 13:53:29 -0800 | [diff] [blame] | 130 | flags |= naming.MountFlag(naming.Replace) |
David Why Use Two When One Will Do Presotto | 59a254c | 2014-10-30 13:09:29 -0700 | [diff] [blame] | 131 | } |
| 132 | } |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 133 | } |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 134 | ctx, cancel := context.WithTimeout(ctx, time.Minute) |
Matt Rosencrantz | 137b8d2 | 2014-08-18 09:56:15 -0700 | [diff] [blame] | 135 | defer cancel() |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 136 | client := v23.GetClient(ctx) |
David Why Use Two When One Will Do Presotto | c279841 | 2015-09-08 12:53:34 -0700 | [diff] [blame] | 137 | if err := client.Call(ctx, name, "Mount", []interface{}{server, seconds, flags}, nil, options.Preresolved{}); err != nil { |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 138 | return err |
David Why Use Two When One Will Do Presotto | 59a254c | 2014-10-30 13:09:29 -0700 | [diff] [blame] | 139 | } |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 140 | fmt.Fprintln(env.Stdout, "Name mounted successfully.") |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 141 | return nil |
| 142 | } |
| 143 | |
Todd Wang | 9560b9c | 2015-05-11 13:27:58 -0700 | [diff] [blame] | 144 | var cmdUnmount = &cmdline.Command{ |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 145 | Runner: v23cmd.RunnerFunc(runUnmount), |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 146 | Name: "unmount", |
| 147 | Short: "removes server <name> from the mount table", |
| 148 | Long: "removes server <name> from the mount table", |
| 149 | ArgsName: "<mount name> <name>", |
| 150 | ArgsLong: ` |
| 151 | <mount name> is a mount name on a mount table. |
Bogdan Caprita | d9281a3 | 2014-07-02 14:40:39 -0700 | [diff] [blame] | 152 | <name> is the rooted object name of the server. |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 153 | `, |
| 154 | } |
| 155 | |
Todd Wang | 9560b9c | 2015-05-11 13:27:58 -0700 | [diff] [blame] | 156 | func runUnmount(ctx *context.T, env *cmdline.Env, args []string) error { |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 157 | if expected, got := 2, len(args); expected != got { |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 158 | return env.UsageErrorf("unmount: incorrect number of arguments, expected %d, got %d", expected, got) |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 159 | } |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 160 | ctx, cancel := context.WithTimeout(ctx, time.Minute) |
Matt Rosencrantz | 137b8d2 | 2014-08-18 09:56:15 -0700 | [diff] [blame] | 161 | defer cancel() |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 162 | client := v23.GetClient(ctx) |
David Why Use Two When One Will Do Presotto | c279841 | 2015-09-08 12:53:34 -0700 | [diff] [blame] | 163 | if err := client.Call(ctx, args[0], "Unmount", []interface{}{args[1]}, nil, options.Preresolved{}); err != nil { |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 164 | return err |
David Why Use Two When One Will Do Presotto | 59a254c | 2014-10-30 13:09:29 -0700 | [diff] [blame] | 165 | } |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 166 | fmt.Fprintln(env.Stdout, "Unmount successful or name not mounted.") |
Todd Wang | e77f995 | 2015-02-18 13:20:50 -0800 | [diff] [blame] | 167 | return nil |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 168 | } |
| 169 | |
Todd Wang | 9560b9c | 2015-05-11 13:27:58 -0700 | [diff] [blame] | 170 | var cmdResolveStep = &cmdline.Command{ |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 171 | Runner: v23cmd.RunnerFunc(runResolveStep), |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 172 | Name: "resolvestep", |
| 173 | Short: "takes the next step in resolving a name.", |
| 174 | Long: "takes the next step in resolving a name.", |
| 175 | ArgsName: "<mount name>", |
| 176 | ArgsLong: ` |
| 177 | <mount name> is a mount name on a mount table. |
| 178 | `, |
| 179 | } |
| 180 | |
Todd Wang | 9560b9c | 2015-05-11 13:27:58 -0700 | [diff] [blame] | 181 | func runResolveStep(ctx *context.T, env *cmdline.Env, args []string) error { |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 182 | if expected, got := 1, len(args); expected != got { |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 183 | return env.UsageErrorf("mount: incorrect number of arguments, expected %d, got %d", expected, got) |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 184 | } |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 185 | ctx, cancel := context.WithTimeout(ctx, time.Minute) |
Matt Rosencrantz | 137b8d2 | 2014-08-18 09:56:15 -0700 | [diff] [blame] | 186 | defer cancel() |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 187 | client := v23.GetClient(ctx) |
Todd Wang | 2331dd0 | 2015-03-17 15:38:39 -0700 | [diff] [blame] | 188 | var entry naming.MountEntry |
David Why Use Two When One Will Do Presotto | c279841 | 2015-09-08 12:53:34 -0700 | [diff] [blame] | 189 | if err := client.Call(ctx, args[0], "ResolveStep", nil, []interface{}{&entry}, options.Preresolved{}); err != nil { |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 190 | return err |
| 191 | } |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 192 | fmt.Fprintf(env.Stdout, "Servers: %v Suffix: %q MT: %v\n", entry.Servers, entry.Name, entry.ServesMountTable) |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 193 | return nil |
| 194 | } |
| 195 | |
Todd Wang | 9560b9c | 2015-05-11 13:27:58 -0700 | [diff] [blame] | 196 | var cmdRoot = &cmdline.Command{ |
Todd Wang | 338f90c | 2015-05-07 19:42:46 -0700 | [diff] [blame] | 197 | Name: "mounttable", |
| 198 | Short: "sends commands to Vanadium mounttable services", |
| 199 | Long: ` |
Todd Wang | 6ed3b6c | 2015-04-08 14:37:04 -0700 | [diff] [blame] | 200 | Command mounttable sends commands to Vanadium mounttable services. |
Todd Wang | fcb72a5 | 2014-10-01 09:53:56 -0700 | [diff] [blame] | 201 | `, |
Todd Wang | 9560b9c | 2015-05-11 13:27:58 -0700 | [diff] [blame] | 202 | Children: []*cmdline.Command{cmdGlob, cmdMount, cmdUnmount, cmdResolveStep}, |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 203 | } |
Asim Shankar | b2cc129 | 2015-02-23 15:22:45 -0800 | [diff] [blame] | 204 | |
| 205 | func blessingPatternsFromServer(ctx *context.T, server string) ([]security.BlessingPattern, error) { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame] | 206 | ctx.Infof("Contacting %q to determine the blessings presented by it", server) |
Asim Shankar | b2cc129 | 2015-02-23 15:22:45 -0800 | [diff] [blame] | 207 | ctx, cancel := context.WithTimeout(ctx, time.Minute) |
| 208 | defer cancel() |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 209 | call, err := v23.GetClient(ctx).StartCall(ctx, server, rpc.ReservedSignature, nil) |
Asim Shankar | b2cc129 | 2015-02-23 15:22:45 -0800 | [diff] [blame] | 210 | if err != nil { |
| 211 | return nil, fmt.Errorf("Unable to extract blessings presented by %q: %v", server, err) |
| 212 | } |
| 213 | blessings, _ := call.RemoteBlessings() |
| 214 | if len(blessings) == 0 { |
| 215 | return nil, fmt.Errorf("No recognizable blessings presented by %q, it cannot be securely mounted", server) |
| 216 | } |
| 217 | // This translation between BlessingPattern and string is silly! |
| 218 | // Kill the BlessingPatterns type and make methods on that type |
| 219 | // functions instead! |
| 220 | patterns := make([]security.BlessingPattern, len(blessings)) |
| 221 | for i := range blessings { |
| 222 | patterns[i] = security.BlessingPattern(blessings[i]) |
| 223 | } |
| 224 | return patterns, nil |
| 225 | } |