1package mode
2
3import (
4	"fmt"
5	"strings"
6
7	"github.com/ktr0731/evans/config"
8	"github.com/ktr0731/evans/grpc"
9	"github.com/ktr0731/evans/grpc/grpcreflection"
10	"github.com/ktr0731/evans/idl"
11	"github.com/ktr0731/evans/idl/proto"
12	"github.com/ktr0731/evans/usecase"
13	"github.com/pkg/errors"
14)
15
16func newSpec(cfg *config.Config, grpcClient grpcreflection.Client) (spec idl.Spec, err error) {
17	if cfg.Server.Reflection {
18		spec, err = proto.LoadByReflection(grpcClient)
19	} else {
20		spec, err = proto.LoadFiles(cfg.Default.ProtoPath, cfg.Default.ProtoFile)
21	}
22	if errors.Is(err, grpcreflection.ErrTLSHandshakeFailed) {
23		return nil, errors.New("TLS handshake failed. check whether client or server is misconfigured")
24	} else if err != nil {
25		return nil, errors.Wrap(err, "failed to instantiate the spec")
26	}
27	return spec, nil
28}
29
30func newGRPCClient(cfg *config.Config) (grpc.Client, error) {
31	addr := fmt.Sprintf("%s:%s", cfg.Server.Host, cfg.Server.Port)
32	if cfg.Request.Web {
33		//TODO: remove second arg
34		return grpc.NewWebClient(addr, cfg.Server.Reflection, false, "", "", ""), nil
35	}
36	client, err := grpc.NewClient(
37		addr,
38		cfg.Server.Name,
39		cfg.Server.Reflection,
40		cfg.Server.TLS,
41		cfg.Request.CACertFile,
42		cfg.Request.CertFile,
43		cfg.Request.CertKeyFile)
44	if err != nil {
45		return nil, errors.Wrap(err, "failed to instantiate a gRPC client")
46	}
47	return client, nil
48}
49
50func gRPCReflectionPackageFilteredPackages(pkgNames []string) []string {
51	pkgs := make([]string, len(pkgNames))
52	copy(pkgs, pkgNames)
53
54	n := grpcreflection.ServiceName[:strings.LastIndex(grpcreflection.ServiceName, ".")]
55	for i := range pkgs {
56		if n == pkgs[i] {
57			return append(pkgs[:i], pkgs[i+1:]...)
58		}
59	}
60	return pkgs
61}
62
63func setDefault(cfg *config.Config) error {
64	// If the spec has only one package, mark it as the default package.
65	if cfg.Default.Package == "" {
66		pkgs := gRPCReflectionPackageFilteredPackages(usecase.ListPackages())
67		if len(pkgs) == 1 {
68			cfg.Default.Package = pkgs[0]
69		} else {
70			hasEmptyPackage := func() bool {
71				for _, pkg := range pkgs {
72					if pkg == "" {
73						return true
74					}
75				}
76				return false
77			}()
78			if !hasEmptyPackage {
79				return nil
80			}
81		}
82	}
83
84	if err := usecase.UsePackage(cfg.Default.Package); err != nil {
85		return errors.Wrapf(err, "failed to set '%s' as the default package", cfg.Default.Package)
86	}
87
88	// If the spec has only one service, mark it as the default service.
89	if cfg.Default.Service == "" {
90		svcNames := usecase.ListServicesOld()
91		if len(svcNames) != 1 {
92			return nil
93		}
94
95		cfg.Default.Service = svcNames[0]
96		i := strings.LastIndex(cfg.Default.Service, ".")
97		if i != -1 {
98			cfg.Default.Service = cfg.Default.Service[i+1:]
99		}
100	}
101	if err := usecase.UseService(cfg.Default.Service); err != nil {
102		return errors.Wrapf(err, "failed to set '%s' as the default service", cfg.Default.Service)
103	}
104	return nil
105}
106