Merge pull request #8 from TuneLab/truss-integration-test-refactor

Refactor truss and integration_tests
This commit is contained in:
hasLeland 2016-08-02 14:19:09 -07:00 коммит произвёл GitHub
Родитель 85636cbc38 b30bbb71b1
Коммит 9245d19ab2
5 изменённых файлов: 456 добавлений и 519 удалений

Просмотреть файл

@ -17,7 +17,9 @@ clean:
# Run truss on all proto files in all dirs in ./tests/
test:
go test -tags=integration
go test -tags=integration -v ./integration_tests
testclean:
go test -tags=integration ./integration_tests -clean

Просмотреть файл

@ -0,0 +1,186 @@
package generator
import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
log "github.com/Sirupsen/logrus"
templates "github.com/TuneLab/gob/truss/template"
)
func init() {
log.SetLevel(log.DebugLevel)
log.SetFormatter(&log.TextFormatter{
ForceColors: true,
})
}
// GenerateMicroservice takes a golang importPath, a path to .proto definition files workingDirectory, and a slice of
// definition files DefinitionFiles and outputs a ./service direcotry in workingDirectory with a generated and built golang microservice
func GenerateMicroservice(importPath string, workingDirectory string, definitionFiles []string) {
done := make(chan bool)
// Stage 1
buildDirectories(workingDirectory)
outputGoogleImport(workingDirectory)
// Stage 2, 3, 4
generatePbGoCmd := "--go_out=Mgoogle/api/annotations.proto=" + importPath + "/service/DONOTEDIT/third_party/googleapis/google/api,plugins=grpc:./service/DONOTEDIT/pb"
const generateDocsCmd = "--truss-doc_out=."
const generateGoKitCmd = "--truss-gokit_out=."
go protoc(workingDirectory, definitionFiles, generatePbGoCmd, done)
go protoc(workingDirectory, definitionFiles, generateDocsCmd, done)
go protoc(workingDirectory, definitionFiles, generateGoKitCmd, done)
<-done
<-done
<-done
// Stage 5
go goBuild("server", importPath+"/service/DONOTEDIT/cmd/svc/...", done)
go goBuild("cliclient", importPath+"/service/DONOTEDIT/cmd/cliclient/...", done)
<-done
<-done
}
// buildDirectories puts the following directories in place
// .
// └── service
// ├── bin
// └── DONOTEDIT
// ├── pb
// └── third_party
// └── googleapis
// └── google
// └── api
func buildDirectories(workingDirectory string) {
// third_party created by going through assets in template
// and creating directoires that are not there
for _, filePath := range templates.AssetNames() {
fullPath := workingDirectory + "/" + filePath
dirPath := filepath.Dir(fullPath)
err := os.MkdirAll(dirPath, 0777)
if err != nil {
log.WithField("DirPath", dirPath).WithError(err).Fatal("Cannot create directories")
}
}
// Create the directory where protoc will store the compiled .pb.go files
err := os.MkdirAll(workingDirectory+"/service/DONOTEDIT/pb", 0777)
if err != nil {
log.WithField("DirPath", "service/DONOTEDIT/pb").WithError(err).Fatal("Cannot create directories")
}
// Create the directory where go build will put the compiled binaries
err = os.MkdirAll(workingDirectory+"/service/bin", 0777)
if err != nil {
log.WithField("DirPath", "service/bin").WithError(err).Fatal("Cannot create directories")
}
}
// outputGoogleImport places imported and required google.api.http protobuf option files
// into their required directories as part of stage one generation
func outputGoogleImport(workingDirectory string) {
// Output files that are stored in template package
for _, filePath := range templates.AssetNames() {
fileBytes, _ := templates.Asset(filePath)
fullPath := workingDirectory + "/" + filePath
err := ioutil.WriteFile(fullPath, fileBytes, 0666)
if err != nil {
log.WithField("FilePath", fullPath).WithError(err).Fatal("Cannot create ")
}
}
}
// goBuild calls the `$ go get ` to install dependenices
// and then calls `$ go build service/bin/$name $path`
// to put the iterating binaries in the correct place
func goBuild(name string, path string, done chan bool) {
// $ go get
goGetExec := exec.Command(
"go",
"get",
"-d",
"-v",
path,
)
goGetExec.Stderr = os.Stderr
log.WithField("cmd", strings.Join(goGetExec.Args, " ")).Info("go get")
val, err := goGetExec.Output()
if err != nil {
log.WithFields(log.Fields{
"output": string(val),
"input": goGetExec.Args,
}).WithError(err).Warn("go get failed")
}
// $ go build
goBuildExec := exec.Command(
"go",
"build",
"-o",
"service/bin/"+name,
path,
)
goBuildExec.Stderr = os.Stderr
log.WithField("cmd", strings.Join(goBuildExec.Args, " ")).Info("go build")
val, err = goBuildExec.Output()
if err != nil {
log.WithFields(log.Fields{
"output": string(val),
"input": goBuildExec.Args,
}).WithError(err).Fatal("go build failed")
}
done <- true
}
func protoc(workingDirectory string, definitionPaths []string, command string, done chan bool) {
const googleApiHttpImportPath = "/service/DONOTEDIT/third_party/googleapis"
cmdArgs := []string{
"-I.",
"-I" + workingDirectory + googleApiHttpImportPath,
command,
}
// Append each definition file path to the end of that command args
cmdArgs = append(cmdArgs, definitionPaths...)
protocExec := exec.Command(
"protoc",
cmdArgs...,
)
protocExec.Stderr = os.Stderr
log.WithField("cmd", strings.Join(protocExec.Args, " ")).Info("protoc")
val, err := protocExec.Output()
if err != nil {
log.WithFields(log.Fields{
"output": string(val),
"input": protocExec.Args,
}).WithError(err).Fatal("Protoc call failed")
}
done <- true
}

Просмотреть файл

@ -1,312 +1,2 @@
// This file is here so that go's tooling does not complain there are no builable gofiles in this directory
package integration
import (
"bytes"
"io/ioutil"
"net"
"path/filepath"
"strings"
"time"
"os"
"os/exec"
"strconv"
log "github.com/Sirupsen/logrus"
)
// From within a folder with a truss `service`
// These are the paths to the compiled binaries
const RELATIVESERVERPATH = "/service/bin/server"
const RELATIVECLIENTPATH = "/service/bin/cliclient"
// runReference stores data about a client-server interaction
// This data is then used to display output
type runReference struct {
path string
clientErr bool
serverErr bool
clientOutput string
serverOutput string
}
func init() {
log.SetLevel(log.InfoLevel)
log.SetFormatter(&log.TextFormatter{
ForceColors: true,
})
}
func runIntegrationTests() bool {
allPassed := true
workingDirectory, err := os.Getwd()
if err != nil {
log.WithError(err).Fatal("Cannot get working directory")
}
workingDirectory = workingDirectory + "/test_service_definitions"
// runRefs will be passed to all gorutines running communication tests
// and will be read to display output
runRefs := make(chan runReference)
// tasksCount is increased for every server/client call
// and decreased every time one is display, for exiting
tasksCount := 0
// Loop through all directories in the running path
dirs, err := ioutil.ReadDir(workingDirectory)
for _, d := range dirs {
// If this item is not a directory skip it
if !d.IsDir() {
continue
}
// Clean up the service directories in each test
if fileExists(workingDirectory + "/" + d.Name() + "/service") {
os.RemoveAll(workingDirectory + "/" + d.Name() + "/service")
}
// tests will be run on the fullpath to directory
testDir := workingDirectory + "/" + d.Name()
// On port relative to 8082, increasing by tasksCount
port := 8082 + tasksCount
log.WithField("Service", d.Name()).Info("Starting integration test")
// Running the integration tests one at a time because truss running on all files at once
// seems to slow the system more than distribute the work
communicationTestRan := runTest(testDir, port, runRefs)
// If communication test ran, increase the running tasksCount
if communicationTestRan {
tasksCount = tasksCount + 1
} else {
allPassed = false
}
}
// range through the runRefs channel, display info if pass
// display warn with debug info if fail
for i := 0; i < tasksCount; i++ {
ref := <-runRefs
if ref.clientErr || ref.serverErr {
log.WithField("Service", filepath.Base(ref.path)).Warn("Communication test FAILED")
log.Warnf("Client Output\n%v", ref.clientOutput)
log.Warnf("Server Output\n%v", ref.serverOutput)
allPassed = false
} else {
log.WithField("Service", filepath.Base(ref.path)).Info("Communication test passed")
}
}
if allPassed {
// Clean up the service directories in each test
dirs, err = ioutil.ReadDir(workingDirectory)
for _, d := range dirs {
// If this item is not a directory skip it
if !d.IsDir() {
continue
}
if fileExists(workingDirectory + "/" + d.Name() + "/service") {
os.RemoveAll(workingDirectory + "/" + d.Name() + "/service")
}
}
}
return allPassed
}
// runTest generates, builds, and runs truss services
// testPath is the full path to the definition files
// portRef is a reference port to launch services on
// runRefs is a channel where references to client/server communication will be passed back
// runTest returns a bool representing whether or not the client/server communication was tested
func runTest(testPath string, portRef int, runRefs chan runReference) (communicationTestRan bool) {
// Build the full path to this directory and the path to the client and server
// binaries within it
log.WithField("Test path", testPath).Debug()
// Generate and build service
truss(testPath)
serverPath := testPath + RELATIVESERVERPATH
clientPath := testPath + RELATIVECLIENTPATH
// If the server and client binary exist then run them against each other
if fileExists(serverPath) && fileExists(clientPath) {
port := portRef
debugPort := portRef + 1000
checkPort(port)
log.WithFields(log.Fields{
"testPath": testPath,
"port": port,
"debugPort": debugPort,
}).
Debug("LAUNCH")
go runServerAndClient(testPath, port, debugPort, runRefs)
return true
}
return false
}
// truss calls truss on *.proto in path
// Truss logs to Stdout when generation passes or fails
func truss(path string) {
var protofiles []string
files, err := ioutil.ReadDir(path)
for _, f := range files {
if f.IsDir() {
continue
}
if strings.HasSuffix(f.Name(), ".proto") {
protofiles = append(protofiles, f.Name())
}
}
trussExec := exec.Command(
"truss",
protofiles...,
)
trussExec.Dir = path
log.WithField("Path", path).Debug("Exec Truss")
val, err := trussExec.CombinedOutput()
if err != nil {
log.Warn(err)
log.Warn(trussExec.Args)
log.Warn(path)
log.WithField("Service", filepath.Base(path)).Warn("Truss generation FAILED")
log.Warnf("Truss Output:\n%v", string(val))
} else {
log.WithField("Service", filepath.Base(path)).Info("Truss generation passed")
}
}
// checkPort checks if port is being used
// TODO: Make work
func checkPort(port int) {
log.Debug("Checking Port")
ips, _ := net.LookupIP("localhost")
listener, err := net.ListenTCP("tcp",
&net.TCPAddr{
IP: ips[0],
Port: port,
})
_ = listener
log.Debug("Checking Error")
if err != nil {
log.WithField("port", port).Warn("PORT MAY BE TAKEN")
}
listener.Close()
//net.Dial("tcp", "localhost:"+strconv.Itoa(port))
}
func runServerAndClient(path string, port int, debugPort int, refChan chan runReference) {
// Output buffer for the server Stdout and Stderr
serverOut := bytes.NewBuffer(nil)
// Get the server command ready with the port
server := exec.Command(
path+RELATIVESERVERPATH,
"-grpc.addr",
":"+strconv.Itoa(port),
"-debug.addr",
":"+strconv.Itoa(debugPort),
)
// Put serverOut to be the writer of data from Stdout and Stderr
server.Stdout = serverOut
server.Stderr = serverOut
log.Debug("Starting the server!")
// Start the server
serverErrChan := make(chan error)
go func() {
err := server.Run()
serverErrChan <- err
defer server.Process.Kill()
}()
// We may need to wait a few miliseconds for the server to startup
retryTime := time.Millisecond * 100
t := time.NewTimer(retryTime)
for server.Process == nil {
<-t.C
t.Reset(retryTime)
log.WithField("path", path).Debug("Timer Reset")
}
<-t.C
log.WithField("path", path).Debug("Timer Reset last")
cOut, cErr := runClient(path, port)
log.WithField("Client Output", string(cOut)).Debug("Client returned")
var sErr bool
// If the server ever stopped then it errored
// If it did not stop, kill it and see if that errors
select {
case <-serverErrChan:
sErr = true
default:
if server.Process == nil {
// This likely means the server never started
sErr = true
} else {
// If the Process is not nil, kill it, clean up our mess
err := server.Process.Kill()
if err != nil {
sErr = true
} else {
sErr = false
}
}
}
// Construct a reference to what happened here
ref := runReference{
path: path,
clientErr: cErr,
serverErr: sErr,
clientOutput: string(cOut),
serverOutput: serverOut.String(),
}
refChan <- ref
}
func runClient(path string, port int) ([]byte, bool) {
client := exec.Command(
path+RELATIVECLIENTPATH,
"-grpc.addr",
":"+strconv.Itoa(port),
)
log.Debug("Starting the client!")
cOut, err := client.CombinedOutput()
var cErr bool
if err != nil {
log.WithError(err).Warn()
cErr = true
} else {
cErr = false
}
return cOut, cErr
}
// fileExists checks if a file at the given path exists. Returns true if the
// file exists, and false if the file does not exist.
func fileExists(path string) bool {
if _, err := os.Stat(path); err == nil {
return true
}
return false
}

Просмотреть файл

@ -3,12 +3,234 @@
package integration
import (
"bytes"
"flag"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"time"
"testing"
)
func TestTruss(t *testing.T) {
allPassed := runIntegrationTests()
if !allPassed {
t.Fail()
func init() {
clean := flag.Bool("clean", false, "Remove all generated test files and do nothing else")
flag.Parse()
if *clean {
wd, _ := os.Getwd()
servicesDir := wd + "/test_service_definitions"
cleanTests(servicesDir)
os.Exit(0)
}
}
// runReference stores data about a client-server interaction
// This data is then used to display output
type runReference struct {
name string
clientErr bool
serverErr bool
clientOutput string
serverOutput string
}
func TestTruss(t *testing.T) {
wd, _ := os.Getwd()
servicesDir := wd + "/test_service_definitions"
runRefs := make(chan runReference)
runCount := 0
dirs, _ := ioutil.ReadDir(servicesDir)
for i, d := range dirs {
// If this item is not a directory skip it
if !d.IsDir() {
continue
}
// tests will be run on the fullpath to service directoru
sDir := servicesDir + "/" + d.Name()
// Clean up the service directories in each test
if fileExists(sDir + "/service") {
os.RemoveAll(sDir + "/service")
}
// On port relative to 8082
port := 8082 + i
// Running the integration tests one at a time because truss running on all files at once
// seems to slow the system more than distribute the work
t.Logf("Running integration test for %v...", d.Name())
out, err := truss(sDir)
// If truss fails, test error and skip communication
if err != nil {
t.Errorf("Truss generation FAILED - %v\nTruss Output:\n%v", d.Name(), out)
continue
}
go runServerAndClient(sDir, port, port+1000, runRefs)
runCount++
}
for i := 0; i < runCount; i++ {
ref := <-runRefs
if ref.clientErr || ref.serverErr {
t.Errorf("Communication test FAILED - %v", ref.name)
t.Logf("Client Output\n%v", ref.clientOutput)
t.Logf("Server Output\n%v", ref.serverOutput)
}
}
// If nothing failed, delete the generated files
if !t.Failed() {
cleanTests(servicesDir)
}
}
// truss calls truss on *.proto in path
// Truss logs to Stdout when generation passes or fails
func truss(path string) (string, error) {
var protofiles []string
files, err := ioutil.ReadDir(path)
for _, f := range files {
if f.IsDir() {
continue
}
if strings.HasSuffix(f.Name(), ".proto") {
protofiles = append(protofiles, f.Name())
}
}
trussExec := exec.Command(
"truss",
protofiles...,
)
trussExec.Dir = path
out, err := trussExec.CombinedOutput()
return string(out), err
}
func runServerAndClient(path string, port int, debugPort int, runRefs chan runReference) {
// From within a folder with a truss `service`
// These are the paths to the compiled binaries
const relativeServerPath = "/service/bin/server"
// Output buffer for the server Stdout and Stderr
serverOut := bytes.NewBuffer(nil)
// Get the server command ready with the port
server := exec.Command(
path+relativeServerPath,
"-grpc.addr",
":"+strconv.Itoa(port),
"-debug.addr",
":"+strconv.Itoa(debugPort),
)
// Put serverOut to be the writer of data from Stdout and Stderr
server.Stdout = serverOut
server.Stderr = serverOut
// Start the server
serverErrChan := make(chan error)
go func() {
err := server.Run()
serverErrChan <- err
defer server.Process.Kill()
}()
// We may need to wait a few miliseconds for the server to startup
retryTime := time.Millisecond * 100
t := time.NewTimer(retryTime)
for server.Process == nil {
<-t.C
t.Reset(retryTime)
}
<-t.C
cOut, cErr := runClient(path, port)
var sErr bool
// If the server ever stopped then it errored
// If it did not stop, kill it and see if that errors
select {
case <-serverErrChan:
sErr = true
default:
if server.Process == nil {
// This likely means the server never started
sErr = true
} else {
// If the Process is not nil, kill it, clean up our mess
err := server.Process.Kill()
if err != nil {
sErr = true
} else {
sErr = false
}
}
}
// Construct a reference to what happened here
ref := runReference{
name: filepath.Base(path),
clientErr: cErr,
serverErr: sErr,
clientOutput: string(cOut),
serverOutput: serverOut.String(),
}
runRefs <- ref
}
func runClient(path string, port int) ([]byte, bool) {
const relativeClientPath = "/service/bin/cliclient"
client := exec.Command(
path+relativeClientPath,
"-grpc.addr",
":"+strconv.Itoa(port),
)
cOut, err := client.CombinedOutput()
var cErr bool
if err != nil {
cErr = true
} else {
cErr = false
}
return cOut, cErr
}
// fileExists checks if a file at the given path exists. Returns true if the
// file exists, and false if the file does not exist.
func fileExists(path string) bool {
if _, err := os.Stat(path); err == nil {
return true
}
return false
}
func cleanTests(servicesDir string) {
// Clean up the service directories in each test
dirs, _ := ioutil.ReadDir(servicesDir)
for _, d := range dirs {
// If this item is not a directory skip it
if !d.IsDir() {
continue
}
if fileExists(servicesDir + "/" + d.Name() + "/service") {
os.RemoveAll(servicesDir + "/" + d.Name() + "/service")
}
}
}

Просмотреть файл

@ -2,61 +2,21 @@ package main
import (
"flag"
"fmt"
"io/ioutil"
//"fmt"
"os"
"os/exec"
"path/filepath"
"path"
"strings"
log "github.com/Sirupsen/logrus"
"github.com/TuneLab/gob/truss/generator"
templates "github.com/TuneLab/gob/truss/template"
log "github.com/Sirupsen/logrus"
)
const GENERATED_PATH = "service"
const GOOGLE_API_HTTP_IMPORT_PATH = "/service/DONOTEDIT/third_party/googleapis"
type globalStruct struct {
workingDirectory string
genImportPath string
GOPATH string
generatePbGoCmd string
generateDocsCmd string
generateGoKitCmd string
}
var global globalStruct
// We build up environment knowledge here
// 1. Get working directory
// 2. Get $GOPATH
// 3. Use 1,2 to build path for golang imports for this package
// 4. Build 3 proto commands to invoke
func init() {
log.SetLevel(log.DebugLevel)
log.SetFormatter(&log.TextFormatter{
ForceColors: true,
})
var err error
global.workingDirectory, err = os.Getwd()
if err != nil {
log.WithError(err).Fatal("Cannot get working directory")
}
global.GOPATH = os.Getenv("GOPATH")
// From `$GOPATH/src/org/user/thing` get `org/user/thing` from importing in golang
global.genImportPath = strings.TrimPrefix(global.workingDirectory, global.GOPATH+"/src/")
// Generate grpc golang code
global.generatePbGoCmd = "--go_out=Mgoogle/api/annotations.proto=" + global.genImportPath + GOOGLE_API_HTTP_IMPORT_PATH + "/google/api,plugins=grpc:./service/DONOTEDIT/pb"
// Generate documentation
global.generateDocsCmd = "--truss-doc_out=."
// Generate gokit-base service
global.generateGoKitCmd = "--truss-gokit_out=."
}
// Stages are documented in README.md
@ -64,175 +24,52 @@ func main() {
flag.Parse()
if len(flag.Args()) == 0 {
fmt.Fprintf(os.Stderr, "usage: truss microservice.proto\n")
log.Fatal("No proto files passed")
os.Exit(1)
}
definitionPaths := flag.Args()
rawDefinitionPaths := flag.Args()
Stage1()
execWd, err := os.Getwd()
if err != nil {
log.WithError(err).Fatal("Cannot get working directory")
}
// Stage 2, 3, 4
Stage234(definitionPaths)
var workingDirectory string
var definitionFiles []string
// Stage 5
Stage5()
// Parsed passed file paths
for _, def := range rawDefinitionPaths {
// If the definition file path is not absolute, then make it absolute using trusses working directory
if !path.IsAbs(def) {
def = path.Clean(def)
def = path.Join(execWd, def)
}
}
// The working direcotry for this definition file
wd := path.Dir(def)
// Add the base name of definition file to the slice
definitionFiles = append(definitionFiles, path.Base(def))
func Stage1() {
// Stage 1
global.buildDirectories()
global.outputGoogleImport()
}
func Stage234(definitionPaths []string) {
genPbGoDone := make(chan bool)
genDocsDone := make(chan bool)
genGoKitDone := make(chan bool)
go global.protoc(definitionPaths, global.generatePbGoCmd, genPbGoDone)
go global.protoc(definitionPaths, global.generateDocsCmd, genDocsDone)
go global.protoc(definitionPaths, global.generateGoKitCmd, genGoKitDone)
<-genPbGoDone
<-genDocsDone
<-genGoKitDone
}
func Stage5() {
serverDone := make(chan bool)
clientDone := make(chan bool)
go goBuild("server", "./service/DONOTEDIT/cmd/svc/...", serverDone)
go goBuild("cliclient", "./service/DONOTEDIT/cmd/cliclient/...", clientDone)
<-serverDone
<-clientDone
}
// buildDirectories puts the following directories in place
// .
// └── service
// ├── bin
// └── DONOTEDIT
// ├── pb
// └── third_party
// └── googleapis
// └── google
// └── api
func (g globalStruct) buildDirectories() {
// third_party created by going through assets in template
// and creating directoires that are not there
for _, filePath := range templates.AssetNames() {
fullPath := g.workingDirectory + "/" + filePath
dirPath := filepath.Dir(fullPath)
err := os.MkdirAll(dirPath, 0777)
if err != nil {
log.WithField("DirPath", dirPath).WithError(err).Fatal("Cannot create directories")
// If the working directory has not beenset before set it
if workingDirectory == "" {
workingDirectory = wd
} else {
// If the working directory for this definition file is different than the previous
if wd != workingDirectory {
log.Fatal("Passed protofiles reside in different directories")
}
}
}
// Create the directory where protoc will store the compiled .pb.go files
err := os.MkdirAll("service/DONOTEDIT/pb", 0777)
if err != nil {
log.WithField("DirPath", "service/DONOTEDIT/pb").WithError(err).Fatal("Cannot create directories")
goPath := os.Getenv("GOPATH")
if !strings.HasPrefix(workingDirectory, goPath) {
log.Fatal("truss envoked from outside of $GOPATH")
}
// Create the directory where go build will put the compiled binaries
err = os.MkdirAll("service/bin", 0777)
if err != nil {
log.WithField("DirPath", "service/bin").WithError(err).Fatal("Cannot create directories")
}
}
// outputGoogleImport places imported and required google.api.http protobuf option files
// into their required directories as part of stage one generation
func (g globalStruct) outputGoogleImport() {
// Output files that are stored in template package
for _, filePath := range templates.AssetNames() {
fileBytes, _ := templates.Asset(filePath)
fullPath := g.workingDirectory + "/" + filePath
err := ioutil.WriteFile(fullPath, fileBytes, 0666)
if err != nil {
log.WithField("FilePath", fullPath).WithError(err).Fatal("Cannot create ")
}
}
}
// goBuild calls the `$ go get ` to install dependenices
// and then calls `$ go build service/bin/$name $path`
// to put the iterating binaries in the correct place
func goBuild(name string, path string, done chan bool) {
goGetExec := exec.Command(
"go",
"get",
"-d",
"-v",
path,
)
goGetExec.Stderr = os.Stderr
log.WithField("cmd", strings.Join(goGetExec.Args, " ")).Info("go get")
val, err := goGetExec.Output()
if err != nil {
log.WithFields(log.Fields{
"output": string(val),
"input": goGetExec.Args,
}).WithError(err).Warn("go get failed")
}
goBuildExec := exec.Command(
"go",
"build",
"-o",
"service/bin/"+name,
path,
)
//env := os.Environ()
//env = append(env, "CGO_ENABLED=0")
//goBuildExec.Env = env
goBuildExec.Stderr = os.Stderr
log.WithField("cmd", strings.Join(goBuildExec.Args, " ")).Info("go build")
val, err = goBuildExec.Output()
if err != nil {
log.WithFields(log.Fields{
"output": string(val),
"input": goBuildExec.Args,
}).WithError(err).Fatal("go build failed")
}
done <- true
}
func (g globalStruct) protoc(definitionPaths []string, command string, done chan bool) {
cmdArgs := []string{
"-I.",
"-I" + g.workingDirectory + GOOGLE_API_HTTP_IMPORT_PATH,
command,
}
// Append each definition file path to the end of that command args
cmdArgs = append(cmdArgs, definitionPaths...)
protocExec := exec.Command(
"protoc",
cmdArgs...,
)
protocExec.Stderr = os.Stderr
log.WithField("cmd", strings.Join(protocExec.Args, " ")).Info("protoc")
val, err := protocExec.Output()
if err != nil {
log.WithFields(log.Fields{
"output": string(val),
"input": protocExec.Args,
}).WithError(err).Fatal("Protoc call failed")
}
done <- true
// From `$GOPATH/src/org/user/thing` get `org/user/thing` for importing in golang
genImportPath := strings.TrimPrefix(workingDirectory, goPath+"/src/")
generator.GenerateMicroservice(genImportPath, workingDirectory, definitionFiles)
}