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  }