Add parsesvcname package for getting service name
This commit is contained in:
Родитель
56ab033558
Коммит
43e814950b
|
@ -0,0 +1,86 @@
|
|||
package parsesvcname
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/TuneLab/go-truss/svcdef"
|
||||
"github.com/TuneLab/go-truss/truss/execprotoc"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// FromPaths accepts the paths of protobuf definition files and returns the
|
||||
// name of the service in that protobuf definition file.
|
||||
func FromPaths(gopath string, protoDefPaths []string) (string, error) {
|
||||
td, err := ioutil.TempDir("", "parsesvcname")
|
||||
defer os.RemoveAll(td)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to create temporary directory for .pb.go files")
|
||||
}
|
||||
err = execprotoc.GeneratePBDotGo(protoDefPaths, []string{gopath}, td)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to generate .pb.go files from protobuf definition files")
|
||||
}
|
||||
|
||||
// Get path names of .pb.go files
|
||||
pbgoPaths := []string{}
|
||||
for _, p := range protoDefPaths {
|
||||
base := filepath.Base(p)
|
||||
barename := strings.TrimSuffix(base, filepath.Ext(p))
|
||||
pbgp := filepath.Join(td, barename+".pb.go")
|
||||
pbgoPaths = append(pbgoPaths, pbgp)
|
||||
}
|
||||
|
||||
// Open all .pb.go files and store in map to be passed to svcdef.New()
|
||||
openFiles := func(paths []string) (map[string]io.Reader, error) {
|
||||
rv := map[string]io.Reader{}
|
||||
for _, p := range paths {
|
||||
reader, err := os.Open(p)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "cannot open file %q", p)
|
||||
}
|
||||
rv[p] = reader
|
||||
}
|
||||
return rv, nil
|
||||
}
|
||||
pbgoFiles, err := openFiles(pbgoPaths)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "cannot open all .pb.go files")
|
||||
}
|
||||
pbFiles, err := openFiles(protoDefPaths)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "cannot open all .proto files")
|
||||
}
|
||||
|
||||
sd, err := svcdef.New(pbgoFiles, pbFiles)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to create service definition; did you pass ALL the protobuf files to truss?")
|
||||
}
|
||||
|
||||
return sd.Service.Name, nil
|
||||
}
|
||||
|
||||
func FromReaders(gopath string, protoDefReaders []io.Reader) (string, error) {
|
||||
protoDir, err := ioutil.TempDir("", "parsesvcname-fromreaders")
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to create temporary directory for protobuf files")
|
||||
}
|
||||
// Ensures all the temporary files are removed
|
||||
defer os.RemoveAll(protoDir)
|
||||
|
||||
protoDefPaths := []string{}
|
||||
for _, rdr := range protoDefReaders {
|
||||
f, err := ioutil.TempFile(protoDir, "parsesvcname-fromreader")
|
||||
_, err = io.Copy(f, rdr)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "couldn't copy contents of our proto file into the os.File: ")
|
||||
}
|
||||
path := f.Name()
|
||||
f.Close()
|
||||
protoDefPaths = append(protoDefPaths, path)
|
||||
}
|
||||
return FromPaths(gopath, protoDefPaths)
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package parsesvcname
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Provide a basic proto file to test that FromPaths returns the name of the
|
||||
// service in the file at the provided path.
|
||||
func TestFromPaths(t *testing.T) {
|
||||
protoStr := `
|
||||
syntax = "proto3";
|
||||
package echo;
|
||||
|
||||
import "github.com/TuneLab/go-genproto/googleapis/api/serviceconfig/annotations.proto";
|
||||
|
||||
service BounceEcho {
|
||||
rpc Echo (EchoRequest) returns (EchoResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/echo"
|
||||
};
|
||||
}
|
||||
}
|
||||
message EchoRequest {
|
||||
string In = 1;
|
||||
}
|
||||
message EchoResponse {
|
||||
string Out = 1;
|
||||
}
|
||||
`
|
||||
protoDir, err := ioutil.TempDir("", "parsesvcname-test")
|
||||
if err != nil {
|
||||
t.Fatal("cannot create temp directory to store proto definition: ", err)
|
||||
}
|
||||
defer os.RemoveAll(protoDir)
|
||||
f, err := ioutil.TempFile(protoDir, "trusstest")
|
||||
_, err = io.Copy(f, strings.NewReader(protoStr))
|
||||
if err != nil {
|
||||
t.Fatal("couldn't copy contents of our proto file into the os.File: ", err)
|
||||
}
|
||||
path := f.Name()
|
||||
f.Close()
|
||||
|
||||
svcname, err := FromPaths(os.Getenv("GOPATH"), []string{path})
|
||||
if err != nil {
|
||||
t.Fatal("failed to get service name from path: ", err)
|
||||
}
|
||||
|
||||
if got, want := svcname, "BounceEcho"; got != want {
|
||||
t.Fatalf("got != want; got = %q, want = %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// Provide a basic protobuf file to FromReader to ensure it returns the service
|
||||
// name we expect.
|
||||
func TestFromReader(t *testing.T) {
|
||||
protoStr := `
|
||||
syntax = "proto3";
|
||||
package echo;
|
||||
|
||||
import "github.com/TuneLab/go-genproto/googleapis/api/serviceconfig/annotations.proto";
|
||||
|
||||
service BounceEcho {
|
||||
rpc Echo (EchoRequest) returns (EchoResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/echo"
|
||||
};
|
||||
}
|
||||
}
|
||||
message EchoRequest {
|
||||
string In = 1;
|
||||
}
|
||||
message EchoResponse {
|
||||
string Out = 1;
|
||||
}
|
||||
`
|
||||
svcname, err := FromReaders(os.Getenv("GOPATH"), []io.Reader{strings.NewReader(protoStr)})
|
||||
if err != nil {
|
||||
t.Fatal("failed to get service name from path: ", err)
|
||||
}
|
||||
|
||||
if got, want := svcname, "BounceEcho"; got != want {
|
||||
t.Fatalf("got != want; got = %q, want = %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that passing a protobuf file that's not importing google annotations will function properly.
|
||||
func TestNoAnnotations(t *testing.T) {
|
||||
protoStr := `
|
||||
syntax = "proto3";
|
||||
package echo;
|
||||
|
||||
service BounceEcho {
|
||||
rpc Echo (EchoRequest) returns (EchoResponse) {}
|
||||
}
|
||||
message EchoRequest {
|
||||
string In = 1;
|
||||
}
|
||||
message EchoResponse {
|
||||
string Out = 1;
|
||||
}
|
||||
`
|
||||
svcname, err := FromReaders(os.Getenv("GOPATH"), []io.Reader{strings.NewReader(protoStr)})
|
||||
if err != nil {
|
||||
t.Fatal("failed to get service name from path: ", err)
|
||||
}
|
||||
|
||||
if got, want := svcname, "BounceEcho"; got != want {
|
||||
t.Fatalf("got != want; got = %q, want = %q", got, want)
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче