github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/client/cli/run/util.go (about) 1 package runtime 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "os" 8 "os/exec" 9 "path/filepath" 10 11 pb "github.com/tickoalcantara12/micro/v3/proto/runtime" 12 "github.com/tickoalcantara12/micro/v3/service/build/util/tar" 13 "github.com/tickoalcantara12/micro/v3/service/client" 14 "github.com/tickoalcantara12/micro/v3/service/context" 15 "github.com/tickoalcantara12/micro/v3/service/runtime" 16 "github.com/tickoalcantara12/micro/v3/service/runtime/source/git" 17 "github.com/urfave/cli/v2" 18 ) 19 20 const bufferSize = 1024 21 22 // upload source to the server. will return the source id, e.g. source://foo-bar and an error if 23 // one occurred. The ID returned can be used as a source in runtime.Create. 24 func upload(ctx *cli.Context, srv *runtime.Service, source *git.Source) (string, error) { 25 // if the source exists within a local git repository, archive the whole repository, otherwise 26 // just archive the folder 27 var data io.Reader 28 var err error 29 if len(source.LocalRepoRoot) > 0 { 30 data, err = tar.Archive(source.LocalRepoRoot) 31 } else { 32 data, err = tar.Archive(source.FullPath) 33 } 34 if err != nil { 35 return "", err 36 } 37 38 // create an upload stream 39 cli := pb.NewSourceService("runtime", client.DefaultClient) 40 stream, err := cli.Upload(context.DefaultContext, client.WithAuthToken()) 41 if err != nil { 42 return "", err 43 } 44 45 // read bytes from the tar and stream it to the server 46 buffer := make([]byte, bufferSize) 47 var sentService bool 48 for { 49 num, err := data.Read(buffer) 50 if err == io.EOF { 51 break 52 } else if err != nil { 53 return "", err 54 } 55 56 req := &pb.UploadRequest{Data: buffer[:num]} 57 58 // construct the service object, we'll send this on the first message only to reduce the amount of 59 // data needed to be streamed 60 if !sentService { 61 req.Service = &pb.Service{Name: srv.Name, Version: srv.Version} 62 sentService = true 63 } 64 65 if err := stream.Send(req); err != nil { 66 return "", err 67 } 68 } 69 70 // wait for the server to process the source 71 rsp, err := stream.CloseAndRecv() 72 if err != nil { 73 return "", err 74 } 75 return rsp.Id, nil 76 } 77 78 // vendorDependencies will use `go mod vendor` to generate a vendor directory containing all of a 79 // services deps. This is then uploaded to the server along with the source code to be built into 80 // a binary. 81 func vendorDependencies(dir string) error { 82 // find the go command 83 gopath, err := locateGo() 84 if err != nil { 85 return err 86 } 87 88 // construct the command 89 cmd := exec.Command(gopath, "mod", "vendor") 90 cmd.Env = append(os.Environ(), "GO111MODULE=auto") 91 cmd.Dir = dir 92 93 // execute the command and get the error output 94 outp := bytes.NewBuffer(nil) 95 cmd.Stderr = outp 96 if err := cmd.Run(); err != nil { 97 return fmt.Errorf("%v: %v", err, outp.String()) 98 } 99 100 return nil 101 } 102 103 // locateGo locates the go command 104 func locateGo() (string, error) { 105 if gr := os.Getenv("GOROOT"); len(gr) > 0 { 106 return filepath.Join(gr, "bin", "go"), nil 107 } 108 109 // check path 110 for _, p := range filepath.SplitList(os.Getenv("PATH")) { 111 bin := filepath.Join(p, "go") 112 if _, err := os.Stat(bin); err == nil { 113 return bin, nil 114 } 115 } 116 117 return exec.LookPath("go") 118 }