func callService(srv *registry.Service, namespace string, ctx *cli.Context) error {
	args, flags, err := splitCmdArgs(ctx.Args().Slice())
	if err != nil {
		return err
	}
	endpoint, err := constructEndpoint(args)
	if err != nil {
		return err
	}
	var ep *registry.Endpoint
	for _, e := range srv.Endpoints {
		if e.Name == endpoint {
			ep = e
			break
		}
	}
	if ep == nil {
		return fmt.Errorf("Endpoint %v not found for service %v", endpoint, srv.Name)
	}
	body, err := flagsToRequest(flags, ep.Request)
	if err != nil {
		return err
	}
	callCtx := ctx.Context
	if util.IsBuiltInService(srv.Name) {
		callCtx = context.DefaultContext
	} else if len(namespace) > 0 {
		callCtx = context.SetNamespace(callCtx, namespace)
	}
	req := client.DefaultClient.NewRequest(srv.Name, endpoint, body, client.WithContentType("application/json"))
	var rsp json.RawMessage
	if err := client.DefaultClient.Call(callCtx, req, &rsp, client.WithAuthToken()); err != nil {
		return err
	}
	var out bytes.Buffer
	defer out.Reset()
	if err := json.Indent(&out, rsp, "", "\t"); err != nil {
		return err
	}
	out.Write([]byte("\n"))
	out.WriteTo(os.Stdout)
	return nil
}
callService will call a service using the arguments and flags provided
in the context. It will print the result or error to stdout. If there
was an error performing the call, it will be returned.
package cmd
import (
	"bytes"
	"encoding/json"
	"fmt"
	"os"
	"sort"
	"strconv"
	"strings"
	"unicode"
	"github.com/micro/micro/v3/cmd/cli/namespace"
	"github.com/micro/micro/v3/cmd/cli/util"
	"github.com/micro/micro/v3/service/client"
	"github.com/micro/micro/v3/service/context"
	"github.com/micro/micro/v3/service/registry"
	"github.com/stretchr/objx"
	"github.com/urfave/cli/v2"
)
func lookupService(ctx *cli.Context) (*registry.Service, string, error) {
	name := ctx.Args().First()
	if util.IsBuiltInService(name) {
		srv, err := serviceWithName(name, registry.DefaultDomain)
		return srv, registry.DefaultDomain, err
	}
	env, err := util.GetEnv(ctx)
	if err != nil {
		return nil, "", err
	}
	domain, err := namespace.Get(env.Name)
	if err != nil {
		return nil, "", err
	}
	if srv, err := serviceWithName(name, domain); err != nil {
		return nil, "", err
	} else if srv != nil {
		return srv, domain, nil
	}
	if domain == registry.DefaultDomain {
		return nil, "", nil
	}
	srv, err := serviceWithName(name, registry.DefaultDomain)
	return srv, registry.DefaultDomain, err
}
func formatServiceUsage(srv *registry.Service, c *cli.Context) string {
	alias := c.Args().First()
	subcommand := c.Args().Get(1)
	commands := make([]string, len(srv.Endpoints))
	endpoints := make([]*registry.Endpoint, len(srv.Endpoints))
	for i, e := range srv.Endpoints {
		parts := strings.Split(e.Name, ".")
		for i, part := range parts {
			parts[i] = lowcaseInitial(part)
		}
		name := strings.Join(parts, ".")
		name = strings.TrimPrefix(name, alias+".")
		commands[i] = strings.Replace(name, ".", " ", 1)
		endpoints[i] = e
	}
	result := ""
	if len(subcommand) > 0 && subcommand != "--help" {
		result += fmt.Sprintf("NAME:\n\tmicro %v %v\n\n", alias, subcommand)
		result += fmt.Sprintf("USAGE:\n\tmicro %v %v [flags]\n\n", alias, subcommand)
		result += fmt.Sprintf("FLAGS:\n")
		for i, command := range commands {
			if command == subcommand {
				result += renderFlags(endpoints[i])
			}
		}
	} else {
		sort.Strings(commands)
		result += fmt.Sprintf("NAME:\n\tmicro %v\n\n", alias)
		result += fmt.Sprintf("VERSION:\n\t%v\n\n", srv.Version)
		result += fmt.Sprintf("USAGE:\n\tmicro %v [command]\n\n", alias)
		result += fmt.Sprintf("COMMANDS:\n\t%v\n", strings.Join(commands, "\n\t"))
	}
	return result
}
func lowcaseInitial(str string) string {
	for i, v := range str {
		return string(unicode.ToLower(v)) + str[i+1:]
	}
	return ""
}
func renderFlags(endpoint *registry.Endpoint) string {
	ret := ""
	for _, value := range endpoint.Request.Values {
		ret += renderValue([]string{}, value) + "\n"
	}
	return ret
}
func renderValue(path []string, value *registry.Value) string {
	if len(value.Values) > 0 {
		renders := []string{}
		for _, v := range value.Values {
			renders = append(renders, renderValue(append(path, value.Name), v))
		}
		return strings.Join(renders, "\n")
	}
	return fmt.Sprintf("\t--%v %v", strings.Join(append(path, value.Name), "_"), value.Type)
}