plugin.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. package plugin
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "io/ioutil"
  9. "net/http"
  10. "os"
  11. "os/exec"
  12. "path/filepath"
  13. "strings"
  14. "github.com/tal-tech/go-zero/tools/goctl/api/parser"
  15. "github.com/tal-tech/go-zero/tools/goctl/api/spec"
  16. "github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
  17. "github.com/tal-tech/go-zero/tools/goctl/util"
  18. "github.com/urfave/cli"
  19. )
  20. const (
  21. pluginArg = "_plugin"
  22. )
  23. type Plugin struct {
  24. Api *spec.ApiSpec
  25. Style string
  26. Dir string
  27. }
  28. func PluginCommand(c *cli.Context) error {
  29. ex, err := os.Executable()
  30. if err != nil {
  31. panic(err)
  32. }
  33. var plugin = c.String("plugin")
  34. if len(plugin) == 0 {
  35. return errors.New("missing plugin")
  36. }
  37. transferData, err := prepareArgs(c)
  38. if err != nil {
  39. return err
  40. }
  41. bin, download, err := getCommand(plugin)
  42. if err != nil {
  43. return err
  44. }
  45. if download {
  46. defer func() {
  47. _ = os.Remove(bin)
  48. }()
  49. }
  50. content, err := execx.Run(bin, filepath.Dir(ex), bytes.NewBuffer(transferData))
  51. if err != nil {
  52. return err
  53. }
  54. fmt.Println(content)
  55. return nil
  56. }
  57. func prepareArgs(c *cli.Context) ([]byte, error) {
  58. apiPath := c.String("api")
  59. var transferData Plugin
  60. if len(apiPath) > 0 && util.FileExists(apiPath) {
  61. p, err := parser.NewParser(apiPath)
  62. if err != nil {
  63. return nil, err
  64. }
  65. api, err := p.Parse()
  66. if err != nil {
  67. return nil, err
  68. }
  69. transferData.Api = api
  70. }
  71. dirAbs, err := filepath.Abs(c.String("dir"))
  72. if err != nil {
  73. return nil, err
  74. }
  75. transferData.Dir = dirAbs
  76. transferData.Style = c.String("style")
  77. data, err := json.Marshal(transferData)
  78. if err != nil {
  79. return nil, err
  80. }
  81. return data, nil
  82. }
  83. func getCommand(arg string) (string, bool, error) {
  84. p, err := exec.LookPath(arg)
  85. if err == nil {
  86. abs, err := filepath.Abs(p)
  87. if err != nil {
  88. return "", false, err
  89. }
  90. return abs, false, nil
  91. }
  92. var defaultErr = errors.New("invalid plugin value " + arg)
  93. if strings.HasPrefix(arg, "http") {
  94. items := strings.Split(arg, "/")
  95. if len(items) == 0 {
  96. return "", false, defaultErr
  97. }
  98. filename, err := filepath.Abs(pluginArg + items[len(items)-1])
  99. if err != nil {
  100. return "", false, err
  101. }
  102. err = downloadFile(filename, arg)
  103. if err != nil {
  104. return "", false, err
  105. }
  106. os.Chmod(filename, os.ModePerm)
  107. return filename, true, nil
  108. }
  109. return arg, false, nil
  110. }
  111. func downloadFile(filepath string, url string) error {
  112. resp, err := http.Get(url)
  113. if err != nil {
  114. return err
  115. }
  116. defer func() {
  117. _ = resp.Body.Close()
  118. }()
  119. out, err := os.Create(filepath)
  120. if err != nil {
  121. return err
  122. }
  123. defer func() {
  124. _ = out.Close()
  125. }()
  126. _, err = io.Copy(out, resp.Body)
  127. return err
  128. }
  129. func NewPlugin() (*Plugin, error) {
  130. var plugin Plugin
  131. content, err := ioutil.ReadAll(os.Stdin)
  132. if err != nil {
  133. return nil, err
  134. }
  135. err = json.Unmarshal(content, &plugin)
  136. if err != nil {
  137. return nil, err
  138. }
  139. return &plugin, nil
  140. }