This commit is contained in:
Leland Batey 2016-10-31 15:20:29 -07:00
Родитель 6f8479741e
Коммит 4bb0e7f9f4
14 изменённых файлов: 72 добавлений и 173 удалений

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

@ -22,6 +22,24 @@ import (
"strconv"
)
type optionParseErr struct {
err error
}
func (o optionParseErr) Optional() bool {
return true
}
func (o optionParseErr) Error() string {
return o.err.Error()
}
func optionalParseErr(expected string, line int, val string) error {
return optionParseErr{
err: fmt.Errorf("parser expected %v in line '%v', instead found '%v'", expected, line, val),
}
}
func parseErr(expected string, line int, val string) error {
err := fmt.Errorf("parser expected %v in line '%v', instead found '%v'", expected, line, val)
return err
@ -302,7 +320,9 @@ func ParseHttpBindings(lex *SvcLexer) ([]*HTTPBinding, error) {
return append(rv, new_opt), nil
}
return nil, parseErr("'option' or 'additional_bindings' while parsing options", lex.GetLineNumber(), val)
opt := optionalParseErr("'option' or 'additional_bindings' while parsing options", lex.GetLineNumber(), val)
return nil, opt
}
func ParseBindingFields(lex *SvcLexer) ([]*Field, error) {

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

@ -54,13 +54,6 @@ type ClientArg struct {
// from FlagArg or the invocation of a json unmarshal function.
GoConvertInvoc string
// ProtobufType contains the raw value of the type of the original protobuf
// field corresponding to this arg, as provided by the protocol buffer
// compiler. For a list of these basic types and their corresponding Go
// types, see the ProtoToGoTypeMap map in this file.
// Deprecated by Svcdef.
ProtbufType string
// IsBaseType is true if this arg corresponds to a protobuf field which is
// any of the basic types, or a basic type but repeated. If this the field
// was a nested message or a map, IsBaseType is false.

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

@ -62,7 +62,6 @@ func TestNewClientServiceArgs(t *testing.T) {
GoArg: "ASum",
GoType: "[]int64",
GoConvertInvoc: "\nvar ASum []int64\nif flagASum != nil && len(*flagASum) > 0 {\n\terr = json.Unmarshal([]byte(*flagASum), &ASum)\n\tif err != nil {\n\t\tpanic(errors.Wrapf(err, \"unmarshalling ASum from %v:\", flagASum))\n\t}\n}\n",
ProtbufType: "",
IsBaseType: true,
Repeated: true,
},
@ -76,7 +75,6 @@ func TestNewClientServiceArgs(t *testing.T) {
GoArg: "BSum",
GoType: "int64",
GoConvertInvoc: "BSum := *flagBSum",
ProtbufType: "",
IsBaseType: true,
Repeated: false,
},

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

@ -20,7 +20,6 @@ import (
"github.com/TuneLab/go-truss/gengokit/httptransport"
templateFileAssets "github.com/TuneLab/go-truss/gengokit/template"
"github.com/TuneLab/go-truss/deftree"
"github.com/TuneLab/go-truss/svcdef"
"github.com/TuneLab/go-truss/truss/truss"
)
@ -43,7 +42,6 @@ type templateExecutor struct {
// PackageName is the name of the package containing the service definition
PackageName string
// GRPC/Protobuff service, with all parameters and return values accessible
//Service *deftree.ProtoService
Service *svcdef.Service
ClientArgs *clientarggen.ClientServiceArgs
// A helper struct for generating http transport functionality.
@ -51,11 +49,7 @@ type templateExecutor struct {
funcMap template.FuncMap
}
func newTemplateExecutor(dt deftree.Deftree, sd *svcdef.Svcdef, conf config.Config) (*templateExecutor, error) {
//service, err := getProtoService(dt)
//if err != nil {
//return nil, errors.Wrap(err, "no service found; aborting generating gokit service")
//}
func newTemplateExecutor(sd *svcdef.Svcdef, conf config.Config) (*templateExecutor, error) {
funcMap := template.FuncMap{
"ToLower": strings.ToLower,
@ -74,12 +68,11 @@ func newTemplateExecutor(dt deftree.Deftree, sd *svcdef.Svcdef, conf config.Conf
}, nil
}
// GenerateGokit returns a gokit service generated from a service definition (deftree),
// GenerateGokit returns a gokit service generated from a service definition (svcdef),
// the package to the root of the generated service goPackage, the package
// to the .pb.go service struct files (goPBPackage) and any prevously generated files.
func GenerateGokit(dt deftree.Deftree, sd *svcdef.Svcdef, conf config.Config) ([]truss.NamedReadWriter, error) {
//te, err := newTemplateExecutor(dt, goPackage, goPBPackage)
te, err := newTemplateExecutor(dt, sd, conf)
func GenerateGokit(sd *svcdef.Svcdef, conf config.Config) ([]truss.NamedReadWriter, error) {
te, err := newTemplateExecutor(sd, conf)
if err != nil {
return nil, errors.Wrap(err, "could not create template executor")
}
@ -106,24 +99,6 @@ func GenerateGokit(dt deftree.Deftree, sd *svcdef.Svcdef, conf config.Config) ([
return codeGenFiles, nil
}
// getProtoService finds returns the service within a deftree.Deftree
func getProtoService(dt deftree.Deftree) (*deftree.ProtoService, error) {
md := dt.(*deftree.MicroserviceDefinition)
files := md.Files
var service *deftree.ProtoService
for _, file := range files {
if len(file.Services) > 0 {
service = file.Services[0]
}
}
if service == nil {
return nil, errors.New("no service found")
}
return service, nil
}
// generateResponseFile contains logic to choose how to render a template file
// based on path and if that file was generated previously. It accepts a
// template path to render, a templateExecutor to apply to the template, and a
@ -278,7 +253,6 @@ func updateClientMethods(clientHandler io.Reader, te *templateExecutor) (outCode
// serviceFunctionNames returns a slice of function names which are in the
// definition files plus the function "NewService". Used for inserting and
// removing functions from previously generated handler files
//func serviceFunctionsNames(methods []*deftree.ServiceMethod) []string {
func serviceFunctionsNames(methods []*svcdef.ServiceMethod) []string {
var svcFuncs []string
for _, m := range methods {
@ -292,7 +266,6 @@ func serviceFunctionsNames(methods []*svcdef.ServiceMethod) []string {
// trimServiceFuncs removes functions in funcsInFile from the
// templateExecutor and returns a pointer to a new templateExecutor
func (te templateExecutor) trimServiceFuncs(funcsInFile map[string]bool) *templateExecutor {
//var methodsToTemplate []*deftree.ServiceMethod
var methodsToTemplate []*svcdef.ServiceMethod
for _, m := range te.Service.Methods {

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

@ -8,7 +8,6 @@ import (
"path/filepath"
"testing"
"github.com/TuneLab/go-truss/deftree"
"github.com/TuneLab/go-truss/svcdef"
"github.com/TuneLab/go-truss/gengokit/config"
@ -70,75 +69,22 @@ func TestNewTemplateExecutor(t *testing.T) {
if err != nil {
t.Fatal(err)
}
dt, err := deftree.NewFromString(def)
if err != nil {
t.Fatal(err)
}
conf := config.Config{
GoPackage: "github.com/TuneLab/go-truss/gengokit/general-service",
PBPackage: "github.com/TuneLab/go-truss/gengokit/general-service",
}
te, err := newTemplateExecutor(dt, sd, conf)
te, err := newTemplateExecutor(sd, conf)
if err != nil {
t.Fatal(err)
}
if got, want := te.PackageName, dt.GetName(); got != want {
if got, want := te.PackageName, sd.PkgName; got != want {
t.Fatalf("\n`%v` was PackageName\n`%v` was wanted", got, want)
}
}
func TestGetProtoService(t *testing.T) {
const def = `
syntax = "proto3";
// General package
package general;
import "google/api/annotations.proto";
// RequestMessage is so foo
message RequestMessage {
string input = 1;
}
// ResponseMessage is so bar
message ResponseMessage {
string output = 1;
}
// ProtoService is a service
service ProtoService {
// ProtoMethod is simple. Like a gopher.
rpc ProtoMethod (RequestMessage) returns (ResponseMessage) {
// No {} in path and no body, everything is in the query
option (google.api.http) = {
get: "/route"
};
}
}
`
dt, err := deftree.NewFromString(def)
if err != nil {
t.Fatal(err)
}
svc, err := getProtoService(dt)
if err != nil {
t.Fatal(err)
}
if got, want := svc.Name, "ProtoService"; got != want {
t.Fatalf("\n`%v` was service name\n`%v` was wanted", got, want)
}
if got, want := svc.Methods[0].Name, "ProtoMethod"; got != want {
t.Fatalf("\n`%v` was rpc in service\n`%v` was wanted", got, want)
}
}
func TestApplyTemplateFromPath(t *testing.T) {
const def = `
syntax = "proto3";
@ -173,17 +119,13 @@ func TestApplyTemplateFromPath(t *testing.T) {
if err != nil {
t.Fatal(err)
}
dt, err := deftree.NewFromString(def)
if err != nil {
t.Fatal(err)
}
conf := config.Config{
GoPackage: "github.com/TuneLab/go-truss",
PBPackage: "github.com/TuneLab/go-truss/gengokit/general-service",
}
te, err := newTemplateExecutor(dt, sd, conf)
te, err := newTemplateExecutor(sd, conf)
if err != nil {
t.Fatal(err)
}
@ -303,10 +245,6 @@ func svcMethodsNames(methods []*svcdef.ServiceMethod) []string {
}
func stringToTemplateExector(def, importPath string) (*templateExecutor, error) {
dt, err := deftree.NewFromString(def)
if err != nil {
return nil, err
}
sd, err := svcdef.NewFromString(def)
if err != nil {
return nil, err
@ -317,7 +255,7 @@ func stringToTemplateExector(def, importPath string) (*templateExecutor, error)
PBPackage: importPath,
}
te, err := newTemplateExecutor(dt, sd, conf)
te, err := newTemplateExecutor(sd, conf)
if err != nil {
return nil, err
}
@ -361,17 +299,13 @@ func TestUpdateServerMethods(t *testing.T) {
if err != nil {
t.Fatal(err)
}
dt, err := deftree.NewFromString(def)
if err != nil {
t.Fatal(err)
}
conf := config.Config{
GoPackage: "github.com/TuneLab/go-truss/gengokit",
PBPackage: "github.com/TuneLab/go-truss/gengokit/general-service",
}
te, err := newTemplateExecutor(dt, sd, conf)
te, err := newTemplateExecutor(sd, conf)
if err != nil {
t.Fatal(err)
}
@ -494,31 +428,23 @@ func TestAllTemplates(t *testing.T) {
if err != nil {
t.Fatal(err)
}
dt, err := deftree.NewFromString(def)
if err != nil {
t.Fatal(err)
}
conf := config.Config{
GoPackage: "github.com/TuneLab/go-truss/gengokit",
PBPackage: "github.com/TuneLab/go-truss/gengokit/general-service",
}
te, err := newTemplateExecutor(dt, sd, conf)
te, err := newTemplateExecutor(sd, conf)
if err != nil {
t.Fatal(err)
}
dt2, err := deftree.NewFromString(def2)
if err != nil {
t.Fatal(err)
}
sd2, err := svcdef.NewFromString(def)
if err != nil {
t.Fatal(err)
}
te2, err := newTemplateExecutor(dt2, sd2, conf)
te2, err := newTemplateExecutor(sd2, conf)
if err != nil {
t.Fatal(err)
}

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

@ -1,5 +1,5 @@
// Package httptransport provides functions and template helpers for templating
// the http-transport of a go-kit based microservice.
// the http-transport of a go-kit based service.
package httptransport
import (
@ -19,7 +19,7 @@ import (
// Helper is the base struct for the data structure containing all the
// information necessary to correctly template the HTTP transport functionality
// of a microservice. Helper must be built from a Svcdef.
// of a service. Helper must be built from a Svcdef.
type Helper struct {
Methods []*Method
PathParamsBuilder string

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

@ -56,9 +56,7 @@ func TestNewMethod(t *testing.T) {
LowCamelName: "a",
LocalName: "ASum",
Location: "path",
ProtobufType: "",
GoType: "int64",
ProtobufLabel: "",
ConvertFunc: "ASum, err := strconv.ParseInt(ASumStr, 10, 64)",
TypeConversion: "ASum",
IsBaseType: true,
@ -69,9 +67,7 @@ func TestNewMethod(t *testing.T) {
LowCamelName: "b",
LocalName: "BSum",
Location: "query",
ProtobufType: "",
GoType: "int64",
ProtobufLabel: "",
ConvertFunc: "BSum, err := strconv.ParseInt(BSumStr, 10, 64)",
TypeConversion: "BSum",
IsBaseType: true,

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

@ -185,7 +185,7 @@ func QueryParams(vals url.Values) (map[string]string, error) {
// HTTPAssistFuncs is a source code literal of all the helper functions used
// for encoding and decoding http request to and from generated protobuf
// structs, and is used within the generated code of each microservice.
// structs, and is used within the generated code of each service.
var HTTPAssistFuncs = PathParamsTemplate + BuildParamMapTemplate + RemoveBracesTemplate + QueryParamsTemplate
var serverTemplate = `

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

@ -15,28 +15,24 @@ func TestGenClientEncode(t *testing.T) {
Verb: "get",
Fields: []*Field{
&Field{
Name: "a",
CamelName: "A",
LowCamelName: "a",
LocalName: "ASum",
Location: "path",
ProtobufType: "TYPE_INT64",
GoType: "int64",
ProtobufLabel: "LABEL_OPTIONAL",
ConvertFunc: "ASum, err := strconv.ParseInt(ASumStr, 10, 64)",
IsBaseType: true,
Name: "a",
CamelName: "A",
LowCamelName: "a",
LocalName: "ASum",
Location: "path",
GoType: "int64",
ConvertFunc: "ASum, err := strconv.ParseInt(ASumStr, 10, 64)",
IsBaseType: true,
},
&Field{
Name: "b",
CamelName: "B",
LowCamelName: "b",
LocalName: "BSum",
Location: "query",
ProtobufType: "TYPE_INT64",
GoType: "int64",
ProtobufLabel: "LABEL_OPTIONAL",
ConvertFunc: "BSum, err := strconv.ParseInt(BSumStr, 10, 64)",
IsBaseType: true,
Name: "b",
CamelName: "B",
LowCamelName: "b",
LocalName: "BSum",
Location: "query",
GoType: "int64",
ConvertFunc: "BSum, err := strconv.ParseInt(BSumStr, 10, 64)",
IsBaseType: true,
},
},
}
@ -117,9 +113,7 @@ func TestGenServerDecode(t *testing.T) {
LowCamelName: "a",
LocalName: "ASum",
Location: "path",
ProtobufType: "TYPE_INT64",
GoType: "int64",
ProtobufLabel: "LABEL_OPTIONAL",
ConvertFunc: "ASum, err := strconv.ParseInt(ASumStr, 10, 64)",
TypeConversion: "ASum",
IsBaseType: true,
@ -130,9 +124,7 @@ func TestGenServerDecode(t *testing.T) {
LowCamelName: "b",
LocalName: "BSum",
Location: "query",
ProtobufType: "TYPE_INT64",
GoType: "int64",
ProtobufLabel: "LABEL_OPTIONAL",
ConvertFunc: "BSum, err := strconv.ParseInt(BSumStr, 10, 64)",
TypeConversion: "BSum",
IsBaseType: true,

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

@ -49,16 +49,9 @@ type Field struct {
LocalName string
// The location within the the http request that this field is to be found.
Location string
// The protobuf type that this field is of.
// Deprecated by Svcdef.
ProtobufType string
// The type within the Go language that's used to represent the original
// field that this field refers to.
GoType string
// The protobuf label for the original field that this field refers to. Is
// probably "OPTIONAL", though may be "REPEATED".
// Deprecated by Svcdef.
ProtobufLabel string
// The string form of the function to be used to convert the incoming
// string msg from a string into it's intended type.
ConvertFunc string

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

@ -94,7 +94,7 @@ func nameServiceNameClientClient_mainGotemplate() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "NAME-service/NAME-client/client_main.gotemplate", size: 2809, mode: os.FileMode(436), modTime: time.Unix(1477950095, 0)}
info := bindataFileInfo{name: "NAME-service/NAME-client/client_main.gotemplate", size: 2809, mode: os.FileMode(436), modTime: time.Unix(1477958362, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@ -114,7 +114,7 @@ func nameServiceNameServerServer_mainGotemplate() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "NAME-service/NAME-server/server_main.gotemplate", size: 2868, mode: os.FileMode(436), modTime: time.Unix(1477950095, 0)}
info := bindataFileInfo{name: "NAME-service/NAME-server/server_main.gotemplate", size: 2868, mode: os.FileMode(436), modTime: time.Unix(1477958362, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@ -134,7 +134,7 @@ func nameServiceGeneratedClientGrpcClientGotemplate() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "NAME-service/generated/client/grpc/client.gotemplate", size: 2229, mode: os.FileMode(436), modTime: time.Unix(1477951177, 0)}
info := bindataFileInfo{name: "NAME-service/generated/client/grpc/client.gotemplate", size: 2229, mode: os.FileMode(436), modTime: time.Unix(1477958362, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@ -174,7 +174,7 @@ func nameServiceGeneratedEndpointsGotemplate() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "NAME-service/generated/endpoints.gotemplate", size: 2100, mode: os.FileMode(436), modTime: time.Unix(1477950095, 0)}
info := bindataFileInfo{name: "NAME-service/generated/endpoints.gotemplate", size: 2100, mode: os.FileMode(436), modTime: time.Unix(1477958362, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@ -194,7 +194,7 @@ func nameServiceGeneratedTransport_grpcGotemplate() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "NAME-service/generated/transport_grpc.gotemplate", size: 3655, mode: os.FileMode(436), modTime: time.Unix(1477950095, 0)}
info := bindataFileInfo{name: "NAME-service/generated/transport_grpc.gotemplate", size: 3655, mode: os.FileMode(436), modTime: time.Unix(1477958362, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@ -234,7 +234,7 @@ func nameServiceHandlersClientClient_handlerGotemplate() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "NAME-service/handlers/client/client_handler.gotemplate", size: 1050, mode: os.FileMode(436), modTime: time.Unix(1477950095, 0)}
info := bindataFileInfo{name: "NAME-service/handlers/client/client_handler.gotemplate", size: 1050, mode: os.FileMode(436), modTime: time.Unix(1477958362, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@ -254,7 +254,7 @@ func nameServiceHandlersServerServer_handlerGotemplate() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "NAME-service/handlers/server/server_handler.gotemplate", size: 1174, mode: os.FileMode(436), modTime: time.Unix(1477950696, 0)}
info := bindataFileInfo{name: "NAME-service/handlers/server/server_handler.gotemplate", size: 1174, mode: os.FileMode(436), modTime: time.Unix(1477958362, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@ -274,7 +274,7 @@ func nameServicePartial_templateClient_handlerMethods() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "NAME-service/partial_template/client_handler.methods", size: 846, mode: os.FileMode(436), modTime: time.Unix(1477950095, 0)}
info := bindataFileInfo{name: "NAME-service/partial_template/client_handler.methods", size: 846, mode: os.FileMode(436), modTime: time.Unix(1477958362, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@ -294,7 +294,7 @@ func nameServicePartial_templateServiceInterface() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "NAME-service/partial_template/service.interface", size: 188, mode: os.FileMode(436), modTime: time.Unix(1477950095, 0)}
info := bindataFileInfo{name: "NAME-service/partial_template/service.interface", size: 188, mode: os.FileMode(436), modTime: time.Unix(1477958362, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@ -314,7 +314,7 @@ func nameServicePartial_templateServiceMethods() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "NAME-service/partial_template/service.methods", size: 521, mode: os.FileMode(436), modTime: time.Unix(1477950095, 0)}
info := bindataFileInfo{name: "NAME-service/partial_template/service.methods", size: 521, mode: os.FileMode(436), modTime: time.Unix(1477958362, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}

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

@ -14,6 +14,15 @@ import (
"github.com/TuneLab/go-truss/deftree/svcparse"
)
type optional interface {
Optional() bool
}
func isOptionalError(err error) bool {
opt, ok := errors.Cause(err).(optional)
return ok && opt.Optional()
}
// consolidateHTTP accepts a SvcDef and the io.Readers for the proto files
// comprising the definition. It modifies the SvcDef so that HTTPBindings and
// their associated HTTPParamters are added to each ServiceMethod. After this,
@ -25,7 +34,7 @@ func consolidateHTTP(sd *Svcdef, protoFiles []io.Reader) error {
lex := svcparse.NewSvcLexer(pfile)
protosvc, err := svcparse.ParseService(lex)
if err != nil {
if strings.Contains(err.Error(), "'option' or 'additional_bindings'") {
if isOptionalError(err) {
log.Warnf("Parser found rpc method which lacks HTTP " +
"annotations; this is allowed, but will result in HTTP " +
"transport not being generated.")

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

@ -387,7 +387,6 @@ func NewField(f *ast.Field) (*Field, error) {
// isExported returns true if the provided name of a declaration begins with a
// capital letter.
func isExported(name string) bool {
// Abuse DecodeRuneInString to get the first rune in the string
r, _ := utf8.DecodeRuneInString(name)
if unicode.IsUpper(r) {
return true

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

@ -197,7 +197,7 @@ func generateCode(cfg *truss.Config, dt deftree.Deftree, sd *svcdef.Svcdef) ([]t
PreviousFiles: cfg.PrevGen,
}
genGokitFiles, err := gengokit.GenerateGokit(dt, sd, conf)
genGokitFiles, err := gengokit.GenerateGokit(sd, conf)
if err != nil {
return nil, errors.Wrap(err, "cannot generate gokit service")
}