Skip to content

Commit

Permalink
add proto client/server (#719)
Browse files Browse the repository at this point in the history
* add proto client/server
  • Loading branch information
tonybase authored Feb 24, 2021
1 parent 5b0b39e commit 7cbb057
Show file tree
Hide file tree
Showing 15 changed files with 238 additions and 88 deletions.
21 changes: 10 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,16 @@ kratos new helloworld
cd helloworld
# 生成proto模板
kratos proto add api/helloworld/helloworld.proto
# 生成service模板
kratos proto service api/helloworld/helloworld.proto -t internal/service
# 安装生成工具
make init
# 生成api下所有proto文件
make proto
# 编译cmd下所有main文件
make build
# 进行单元测试
make test
# 生成proto源码
kratos proto client api/helloworld/helloworld.proto
# 生成server模板
kratos proto server api/helloworld/helloworld.proto -t internal/service
# 编译成可执行文件
cd /cmd/helloworld
go build
# 运行程序
./helloword
```

### Kratos Boot
Expand Down
19 changes: 19 additions & 0 deletions cmd/kratos/internal/base/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package base

import (
"os"
"os/exec"
)

// GoGet go get path.
func GoGet(path ...string) error {
for _, p := range path {
cmd := exec.Command("go", "get", "-u", p)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return err
}
}
return nil
}
40 changes: 40 additions & 0 deletions cmd/kratos/internal/base/mod.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package base

import (
"bufio"
"bytes"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"

"golang.org/x/mod/modfile"
)
Expand All @@ -14,3 +20,37 @@ func ModulePath(filename string) (string, error) {
}
return modfile.ModulePath(modBytes), nil
}

// ModuleVersion returns module version.
func ModuleVersion(path string) (string, error) {
stdout := &bytes.Buffer{}
fd := exec.Command("go", "mod", "graph")
fd.Stdout = stdout
fd.Stderr = stdout
if err := fd.Run(); err != nil {
return "", err
}
rd := bufio.NewReader(stdout)
for {
line, _, err := rd.ReadLine()
if err != nil {
return "", err
}
str := string(line)
i := strings.Index(str, "@")
if strings.Contains(str, path+"@") && i != -1 {
return path + str[i:], nil
}
}
}

// KratosMod returns kratos mod.
func KratosMod() string {
gopath := os.Getenv("GOPATH")
if path, err := ModuleVersion("github.com/go-kratos/kratos/v2"); err == nil {
// $GOPATH/pkg/mod/github.com/go-kratos/kratos@v2
return filepath.Join(gopath, "pkg", "mod", path)
}
// $GOPATH/src/github.com/go-kratos/kratos
return filepath.Join(gopath, "src", "github.com", "go-kratos", "kratos")
}
11 changes: 11 additions & 0 deletions cmd/kratos/internal/base/mod_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package base

import "testing"

func TestModuleVersion(t *testing.T) {
v, err := ModuleVersion("golang.org/x/mod")
if err != nil {
t.Fatal(err)
}
t.Log(v)
}
4 changes: 2 additions & 2 deletions cmd/kratos/internal/base/repo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import (
)

func TestRepo(t *testing.T) {
r := NewRepo(RepoURL("https://github.com/go-kratos/service-layout.git"))
r := NewRepo("https://github.com/go-kratos/service-layout.git")
if err := r.Clone(context.Background()); err != nil {
t.Fatal(err)
}
if err := r.CopyTo(context.Background(), "/tmp/test_repo"); err != nil {
if err := r.CopyTo(context.Background(), "/tmp/test_repo", "github.com/go-kratos/kratos-layout", nil); err != nil {
t.Fatal(err)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package new
package project

import (
"context"
Expand All @@ -18,8 +18,8 @@ type Project struct {
Name string
}

// Generate generate template project.
func (p *Project) Generate(ctx context.Context, dir string) error {
// New new a project from remote repo.
func (p *Project) New(ctx context.Context, dir string) error {
to := path.Join(dir, p.Name)
if _, err := os.Stat(to); !os.IsNotExist(err) {
return fmt.Errorf("%s already exists", p.Name)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package new
package project

import (
"context"
Expand Down Expand Up @@ -29,7 +29,7 @@ func run(cmd *cobra.Command, args []string) {
return
}
p := &Project{Name: args[0]}
if err := p.Generate(ctx, wd); err != nil {
if err := p.New(ctx, wd); err != nil {
fmt.Fprintf(os.Stderr, "\033[31mERROR: %s\033[m\n", err)
return
}
Expand Down
83 changes: 83 additions & 0 deletions cmd/kratos/internal/proto/client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package client

import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"

"github.com/go-kratos/kratos/cmd/kratos/v2/internal/base"
"github.com/spf13/cobra"
)

var (
// CmdClient represents the source command.
CmdClient = &cobra.Command{
Use: "client",
Short: "Generate the proto client code",
Long: "Generate the proto client code. Example: kratos proto client helloworld.proto",
Run: run,
}
)

func run(cmd *cobra.Command, args []string) {
if len(args) == 0 {
fmt.Println("Please enter the proto file or directory")
return
}
var (
err error
proto = strings.TrimSpace(args[0])
)
if _, err = exec.LookPath("protoc-gen-go-http"); err != nil {
// update the kratos plugins
if err := exec.Command("kratos", "upgrade").Run(); err != nil {
fmt.Println(err)
}
}
if strings.HasSuffix(proto, ".proto") {
err = generate(proto)
} else {
err = walk(proto)
}
if err != nil {
fmt.Println(err)
}
}

func walk(dir string) error {
if dir == "" {
dir = "."
}
return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if ext := filepath.Ext(path); ext != ".proto" {
return nil
}
return generate(path)
})
}

// generate is used to execute the generate command for the specified proto file
func generate(proto string) error {
path, name := filepath.Split(proto)
fd := exec.Command("protoc", []string{
"--proto_path=.",
"--proto_path=" + filepath.Join(base.KratosMod(), "api"),
"--proto_path=" + filepath.Join(base.KratosMod(), "third_party"),
"--proto_path=" + filepath.Join(os.Getenv("GOPATH"), "src"),
"--go_out=paths=source_relative:.",
"--go-grpc_out=paths=source_relative:.",
"--go-http_out=paths=source_relative:.",
"--go-errors_out=paths=source_relative:.",
name,
}...)
fd.Stdout = os.Stdout
fd.Stderr = os.Stderr
fd.Dir = path
if err := fd.Run(); err != nil {
return err
}
fmt.Printf("proto: %s\n", proto)
return nil
}
8 changes: 4 additions & 4 deletions cmd/kratos/internal/proto/proto.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package proto

import (
"github.com/go-kratos/kratos/cmd/kratos/v2/internal/proto/add"
"github.com/go-kratos/kratos/cmd/kratos/v2/internal/proto/service"
"github.com/go-kratos/kratos/cmd/kratos/v2/internal/proto/source"
"github.com/go-kratos/kratos/cmd/kratos/v2/internal/proto/client"
"github.com/go-kratos/kratos/cmd/kratos/v2/internal/proto/server"

"github.com/spf13/cobra"
)
Expand All @@ -18,8 +18,8 @@ var CmdProto = &cobra.Command{

func init() {
CmdProto.AddCommand(add.CmdAdd)
CmdProto.AddCommand(source.CmdSource)
CmdProto.AddCommand(service.CmdService)
CmdProto.AddCommand(client.CmdClient)
CmdProto.AddCommand(server.CmdServer)
}

func run(cmd *cobra.Command, args []string) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package service
package server

import (
"fmt"
Expand All @@ -12,22 +12,22 @@ import (
"github.com/spf13/cobra"
)

// CmdService represents the service command.
var CmdService = &cobra.Command{
Use: "service",
Short: "Generate the proto Service implementations",
Long: "Generate the proto Service implementations. Example: kratos proto service api/xxx.proto -target-dir=internal/service",
// CmdServer the service command.
var CmdServer = &cobra.Command{
Use: "server",
Short: "Generate the proto Server implementations",
Long: "Generate the proto Server implementations. Example: kratos proto server api/xxx.proto -target-dir=internal/service",
Run: run,
}
var targetDir string

func init() {
CmdService.Flags().StringVarP(&targetDir, "-target-dir", "t", "internal/service", "generate target directory")
CmdServer.Flags().StringVarP(&targetDir, "-target-dir", "t", "internal/service", "generate target directory")
}

func run(cmd *cobra.Command, args []string) {
if len(args) == 0 {
fmt.Fprintln(os.Stderr, "Please specify the proto file. Example: kratos proto service api/xxx.proto")
fmt.Fprintln(os.Stderr, "Please specify the proto file. Example: kratos proto server api/xxx.proto")
return
}
reader, err := os.Open(args[0])
Expand Down Expand Up @@ -66,21 +66,23 @@ func run(cmd *cobra.Command, args []string) {
res = append(res, cs)
}),
)
if _, err := os.Stat(targetDir); os.IsNotExist(err) {
fmt.Printf("Target directory: %s does not exsits\n", targetDir)
return
}
for _, s := range res {
to := path.Join(targetDir, strings.ToLower(s.Service)+".go")
_, err := os.Stat(to)
if !os.IsNotExist(err) {
fmt.Fprintf(os.Stderr, "%s already exists\n", s.Service)
continue
}
if err = os.MkdirAll(targetDir, os.ModeDir); err != nil {
fmt.Fprintf(os.Stderr, "Failed to create file directory: %s\n", targetDir)
if _, err := os.Stat(to); !os.IsNotExist(err) {
fmt.Fprintf(os.Stderr, "%s already exists: %s\n", s.Service, to)
continue
}
b, err := s.execute()
if err != nil {
log.Fatal(err)
}
ioutil.WriteFile(to, b, 0644)
if err := ioutil.WriteFile(to, b, 0644); err != nil {
log.Fatal(err)
}
fmt.Println(to)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package service
package server

import (
"bytes"
Expand Down
28 changes: 0 additions & 28 deletions cmd/kratos/internal/proto/source/source.go

This file was deleted.

30 changes: 30 additions & 0 deletions cmd/kratos/internal/upgrade/upgrade.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package upgrade

import (
"fmt"

"github.com/go-kratos/kratos/cmd/kratos/v2/internal/base"
"github.com/spf13/cobra"
)

// CmdUpgrade represents the upgrade command.
var CmdUpgrade = &cobra.Command{
Use: "upgrade",
Short: "Upgrade the kratos tools",
Long: "Upgrade the kratos tools. Example: kratos upgrade",
Run: Run,
}

// Run upgrade the kratos tools.
func Run(cmd *cobra.Command, args []string) {
err := base.GoGet(
"github.com/go-kratos/kratos/cmd/kratos/v2",
"github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2",
"github.com/go-kratos/kratos/cmd/protoc-gen-go-errors/v2",
"google.golang.org/protobuf/cmd/protoc-gen-go",
"google.golang.org/grpc/cmd/protoc-gen-go-grpc",
)
if err != nil {
fmt.Println(err)
}
}
Loading

0 comments on commit 7cbb057

Please sign in to comment.