go-micro.dev/v5@v5.12.0/cmd/micro/cli/util/util.go (about) 1 // Package cliutil contains methods used across all cli commands 2 // @todo: get rid of os.Exits and use errors instread 3 package util 4 5 import ( 6 "fmt" 7 "regexp" 8 "strings" 9 10 "github.com/urfave/cli/v2" 11 merrors "go-micro.dev/v5/errors" 12 ) 13 14 type Exec func(*cli.Context, []string) ([]byte, error) 15 16 func Print(e Exec) func(*cli.Context) error { 17 return func(c *cli.Context) error { 18 rsp, err := e(c, c.Args().Slice()) 19 if err != nil { 20 return CliError(err) 21 } 22 if len(rsp) > 0 { 23 fmt.Printf("%s\n", string(rsp)) 24 } 25 return nil 26 } 27 } 28 29 // CliError returns a user friendly message from error. If we can't determine a good one returns an error with code 128 30 func CliError(err error) cli.ExitCoder { 31 if err == nil { 32 return nil 33 } 34 // if it's already a cli.ExitCoder we use this 35 cerr, ok := err.(cli.ExitCoder) 36 if ok { 37 return cerr 38 } 39 40 // grpc errors 41 if mname := regexp.MustCompile(`malformed method name: \\?"(\w+)\\?"`).FindStringSubmatch(err.Error()); len(mname) > 0 { 42 return cli.Exit(fmt.Sprintf(`Method name "%s" invalid format. Expecting service.endpoint`, mname[1]), 3) 43 } 44 if service := regexp.MustCompile(`service ([\w\.]+): route not found`).FindStringSubmatch(err.Error()); len(service) > 0 { 45 return cli.Exit(fmt.Sprintf(`Service "%s" not found`, service[1]), 4) 46 } 47 if service := regexp.MustCompile(`unknown service ([\w\.]+)`).FindStringSubmatch(err.Error()); len(service) > 0 { 48 if strings.Contains(service[0], ".") { 49 return cli.Exit(fmt.Sprintf(`Service method "%s" not found`, service[1]), 5) 50 } 51 return cli.Exit(fmt.Sprintf(`Service "%s" not found`, service[1]), 5) 52 } 53 if address := regexp.MustCompile(`Error while dialing dial tcp.*?([\w]+\.[\w:\.]+): `).FindStringSubmatch(err.Error()); len(address) > 0 { 54 return cli.Exit(fmt.Sprintf(`Failed to connect to micro server at %s`, address[1]), 4) 55 } 56 57 merr, ok := err.(*merrors.Error) 58 if !ok { 59 return cli.Exit(err, 128) 60 } 61 62 switch merr.Code { 63 case 408: 64 return cli.Exit("Request timed out", 1) 65 case 401: 66 // TODO check if not signed in, prompt to sign in 67 return cli.Exit("Not authorized to perform this request", 2) 68 } 69 70 // fallback to using the detail from the merr 71 return cli.Exit(merr.Detail, 127) 72 }