├── .gitignore ├── iocodec ├── doc.go ├── decoder.go └── encoder.go ├── testdata ├── nosvc │ ├── nosvc.proto │ └── nosvc.cobra.pb.go └── pb │ ├── bank.proto │ └── bank.cobra.pb.go ├── ci └── install-protoc.sh ├── example ├── pb │ ├── timer.proto │ ├── bank.proto │ ├── maplist.proto │ ├── crud.proto │ ├── cache.proto │ ├── Makefile │ ├── nested.proto │ ├── maplist.cobra.pb.go │ ├── timer.cobra.pb.go │ ├── bank.cobra.pb.go │ ├── nested.cobra.pb.go │ ├── crud.cobra.pb.go │ ├── cache.cobra.pb.go │ ├── timer.pb.go │ ├── bank.pb.go │ └── maplist.pb.go ├── README.md ├── server │ ├── nestedmessage.go │ ├── main.go │ ├── timer.go │ ├── bank.go │ ├── crud.go │ └── cache.go ├── main.go └── cmd │ └── root.go ├── link_client.go ├── go.mod ├── .circleci └── config.yml ├── doc.go ├── LICENSE ├── main.go ├── golden_test.go ├── README.md ├── client ├── args.go └── client.go └── go.sum /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | vendor 3 | protoc-gen-cobra 4 | -------------------------------------------------------------------------------- /iocodec/doc.go: -------------------------------------------------------------------------------- 1 | // Package iocodec provides multiple input decoders and output encoders. 2 | package iocodec 3 | -------------------------------------------------------------------------------- /testdata/nosvc/nosvc.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package nosvc; 4 | 5 | message No { string no = 1; } 6 | 7 | message Svc { string svc = 1; } 8 | -------------------------------------------------------------------------------- /ci/install-protoc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | curl -sSL "https://github.com/protocolbuffers/protobuf/releases/download/v3.10.0/protoc-3.10.0-linux-x86_64.zip" -o /tmp/protoc.zip 6 | unzip /tmp/protoc.zip -d /tmp/protoc 7 | sudo mv /tmp/protoc/bin/protoc /usr/local/bin/protoc 8 | -------------------------------------------------------------------------------- /example/pb/timer.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb; 4 | 5 | service Timer { 6 | rpc Tick(TickRequest) returns (stream TickResponse); 7 | } 8 | 9 | message TickRequest { 10 | int32 interval = 1; 11 | } 12 | 13 | message TickResponse { 14 | string time = 1; 15 | } 16 | -------------------------------------------------------------------------------- /link_client.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The protoc-gen-cobra authors. All rights reserved. 2 | // 3 | // Based on protoc-gen-go from https://github.com/golang/protobuf. 4 | // Copyright 2015 The Go Authors. All rights reserved. 5 | 6 | package main 7 | 8 | import _ "github.com/tetratelabs/protoc-gen-cobra/client" 9 | -------------------------------------------------------------------------------- /example/pb/bank.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb; 4 | 5 | service Bank { 6 | rpc Deposit(DepositRequest) returns (DepositReply); 7 | } 8 | 9 | message DepositRequest { 10 | string account = 1; 11 | double amount = 2; 12 | } 13 | 14 | message DepositReply { 15 | string account = 1; 16 | double balance = 2; 17 | } 18 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # Example 2 | 3 | This directory contains an example application. 4 | 5 | Files: 6 | 7 | * `cmd/` dir and `main.go`: generated by "cobra init" and left untouched 8 | * `pb/*.proto`: example protobuf descriptor 9 | * `pb/Makefile`: generates grpc client and server, and cobra client code 10 | * `link.go`: links generated pb client commands to cmd 11 | -------------------------------------------------------------------------------- /example/pb/maplist.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb; 4 | 5 | service MapList { 6 | rpc Method(MapListRequest) returns (MapListResponse); 7 | } 8 | 9 | message MapListRequest{ 10 | map map_field = 1; 11 | repeated string list_field = 2; 12 | } 13 | 14 | message MapListResponse { 15 | map map_field = 1; 16 | repeated string list_field = 2; 17 | } 18 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tetratelabs/protoc-gen-cobra 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/golang/protobuf v1.3.2 7 | github.com/spf13/cobra v0.0.5 8 | github.com/spf13/pflag v1.0.5 9 | github.com/spf13/viper v1.4.0 10 | golang.org/x/net v0.0.0-20191009170851-d66e71096ffb 11 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 12 | google.golang.org/grpc v1.24.0 13 | gopkg.in/yaml.v2 v2.2.4 14 | ) 15 | -------------------------------------------------------------------------------- /example/pb/crud.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb; 4 | 5 | service CRUD { 6 | rpc Create(CreateCRUD) returns (CRUDObject); 7 | rpc Get(GetCRUD) returns (CRUDObject); 8 | rpc Update(CRUDObject) returns (CRUDObject); 9 | rpc Delete(CRUDObject) returns (Empty); 10 | } 11 | 12 | message CRUDObject { 13 | string name = 1; 14 | string value = 2; 15 | } 16 | 17 | message CreateCRUD { 18 | string name = 1; 19 | string value = 2; 20 | } 21 | 22 | message GetCRUD { 23 | string name = 1; 24 | } 25 | 26 | message Empty {} 27 | -------------------------------------------------------------------------------- /example/pb/cache.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb; 4 | 5 | service Cache { 6 | rpc Set(SetRequest) returns (SetResponse); 7 | rpc Get(GetRequest) returns (GetResponse); 8 | 9 | rpc MultiSet(stream SetRequest) returns (SetResponse); 10 | rpc MultiGet(stream GetRequest) returns (stream GetResponse); 11 | } 12 | 13 | message SetRequest { 14 | string key = 1; 15 | string value = 2; 16 | } 17 | 18 | message SetResponse { 19 | } 20 | 21 | message GetRequest { 22 | string key = 1; 23 | } 24 | 25 | message GetResponse { 26 | string value = 1; 27 | } 28 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | workflows: 4 | version: 2 5 | build: 6 | jobs: 7 | - build: 8 | filters: 9 | tags: 10 | only: /.*/ 11 | executors: 12 | build: 13 | docker: 14 | - image: circleci/golang:1.13.1 15 | working_directory: ~/src 16 | 17 | jobs: 18 | build: 19 | executor: build 20 | steps: 21 | - checkout 22 | - run: ./ci/install-protoc.sh 23 | - run: GOPROXY=https://proxy.golang.org go mod download 24 | - run: go build -o protoc-gen-cobra main.go 25 | - run: go test -v 26 | -------------------------------------------------------------------------------- /example/pb/Makefile: -------------------------------------------------------------------------------- 1 | PROTO_SOURCES = $(wildcard *.proto) 2 | GO_SOURCES = $(patsubst %.proto,%.pb.go,$(PROTO_SOURCES)) 3 | COBRA_SOURCES = $(patsubst %.proto,%.cobra.pb.go,$(PROTO_SOURCES)) 4 | 5 | all: $(GO_SOURCES) $(COBRA_SOURCES) 6 | 7 | $(GO_SOURCES) $(COBRA_SOURCES): 8 | protoc \ 9 | -I. \ 10 | --gofast_out=plugins=grpc:. \ 11 | --cobra_out=plugins=client:. \ 12 | $(PROTO_SOURCES) 13 | goimports -w $(COBRA_SOURCES) 14 | 15 | clean: 16 | rm -f $(GO_SOURCES) $(COBRA_SOURCES) 17 | 18 | deps: 19 | go get github.com/gogo/protobuf/protoc-gen-gofast 20 | go get github.com/tetratelabs/protoc-gen-cobra 21 | -------------------------------------------------------------------------------- /example/server/nestedmessage.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "golang.org/x/net/context" 5 | 6 | "github.com/tetratelabs/protoc-gen-cobra/example/pb" 7 | ) 8 | 9 | type NestedMessage struct{} 10 | 11 | var _ pb.NestedMessagesServer = NestedMessage{} 12 | 13 | func (NestedMessage) Get(_ context.Context, req *pb.NestedRequest) (*pb.NestedResponse, error) { 14 | return &pb.NestedResponse{ 15 | Return: req.Inner.Value + req.TopLevel.Value, 16 | }, nil 17 | } 18 | 19 | func (NestedMessage) GetDeeplyNested(_ context.Context, req *pb.DeeplyNested) (*pb.NestedResponse, error) { 20 | return &pb.NestedResponse{ 21 | Return: req.L0.L1.L2.L3, 22 | }, nil 23 | } 24 | -------------------------------------------------------------------------------- /example/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net" 6 | 7 | "google.golang.org/grpc" 8 | 9 | "github.com/tetratelabs/protoc-gen-cobra/example/pb" 10 | ) 11 | 12 | func main() { 13 | ln, err := net.Listen("tcp", ":8080") 14 | if err != nil { 15 | log.Fatal(err) 16 | } 17 | opts := []grpc.ServerOption{} 18 | srv := grpc.NewServer(opts...) 19 | pb.RegisterBankServer(srv, NewBank()) 20 | pb.RegisterCacheServer(srv, NewCache()) 21 | pb.RegisterTimerServer(srv, NewTimer()) 22 | pb.RegisterCRUDServer(srv, NewCRUD()) 23 | pb.RegisterNestedMessagesServer(srv, NestedMessage{}) 24 | err = srv.Serve(ln) 25 | if err != nil { 26 | log.Fatal(err) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /testdata/nosvc/nosvc.cobra.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by tetratelabs/protoc-gen-cobra. 2 | // source: nosvc/nosvc.proto 3 | // DO NOT EDIT! 4 | 5 | /* 6 | Package nosvc is a generated protocol buffer package. 7 | 8 | It is generated from these files: 9 | nosvc/nosvc.proto 10 | 11 | It has these top-level commands: 12 | */ 13 | 14 | package nosvc 15 | 16 | import ( 17 | proto "github.com/golang/protobuf/proto" 18 | ) 19 | 20 | // This is a compile-time assertion to ensure that this generated file 21 | // is compatible with the proto package it is being compiled against. 22 | // A compilation error at this line likely means your copy of the 23 | // proto package needs to be updated. 24 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package 25 | -------------------------------------------------------------------------------- /example/server/timer.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "time" 5 | 6 | "google.golang.org/grpc" 7 | "google.golang.org/grpc/codes" 8 | 9 | "github.com/tetratelabs/protoc-gen-cobra/example/pb" 10 | ) 11 | 12 | type Timer struct{} 13 | 14 | func NewTimer() *Timer { return &Timer{} } 15 | 16 | func (t *Timer) Tick(in *pb.TickRequest, stream pb.Timer_TickServer) error { 17 | if in.Interval < 1 { 18 | return grpc.Errorf(codes.InvalidArgument, "interval param must be greater than 0") 19 | } 20 | now := time.Now() 21 | interval := time.Duration(in.Interval) * time.Second 22 | tick := time.NewTicker(interval) 23 | defer tick.Stop() 24 | for range tick.C { 25 | now = now.Add(interval) 26 | err := stream.Send(&pb.TickResponse{ 27 | Time: now.String(), 28 | }) 29 | if err != nil { 30 | return err 31 | } 32 | } 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /example/server/bank.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "sync" 5 | 6 | "golang.org/x/net/context" 7 | "google.golang.org/grpc" 8 | "google.golang.org/grpc/codes" 9 | 10 | "github.com/tetratelabs/protoc-gen-cobra/example/pb" 11 | ) 12 | 13 | type Bank struct { 14 | mu sync.Mutex 15 | accountBalance map[string]float64 16 | } 17 | 18 | func NewBank() *Bank { 19 | return &Bank{ 20 | accountBalance: make(map[string]float64), 21 | } 22 | } 23 | 24 | func (b *Bank) Deposit(ctx context.Context, in *pb.DepositRequest) (*pb.DepositReply, error) { 25 | if in.Account == "" { 26 | return nil, grpc.Errorf(codes.InvalidArgument, "missing account name") 27 | } 28 | b.mu.Lock() 29 | v := b.accountBalance[in.Account] + in.Amount 30 | b.accountBalance[in.Account] = v 31 | b.mu.Unlock() 32 | reply := &pb.DepositReply{ 33 | Account: in.Account, 34 | Balance: v, 35 | } 36 | return reply, nil 37 | } 38 | -------------------------------------------------------------------------------- /example/pb/nested.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb; 4 | 5 | service NestedMessages { 6 | rpc Get(NestedRequest) returns (NestedResponse); 7 | rpc GetDeeplyNested(DeeplyNested) returns (NestedResponse); 8 | } 9 | 10 | message TopLevelNestedType { 11 | string value = 1; 12 | } 13 | 14 | message NestedRequest { 15 | message InnerNestedType { 16 | string value = 1; 17 | } 18 | InnerNestedType inner = 1; 19 | TopLevelNestedType top_level = 2; 20 | } 21 | 22 | message NestedResponse { 23 | string return = 1; 24 | } 25 | 26 | message DeeplyNested { 27 | message DeeplyNestedOuter { 28 | message DeeplyNestedInner { 29 | message DeeplyNestedInnermost { 30 | string l3 = 1; 31 | } 32 | DeeplyNestedInnermost l2 = 1; 33 | } 34 | DeeplyNestedInner l1 = 1; 35 | } 36 | DeeplyNestedOuter l0 = 1; 37 | } 38 | -------------------------------------------------------------------------------- /testdata/pb/bank.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb; 4 | 5 | service Bank { rpc Deposit(DepositRequest) returns (DepositReply); } 6 | 7 | message DepositRequest { 8 | string parent = 1; 9 | string tenant = 2; 10 | string environment = 3; 11 | 12 | repeated ClusterWithNamespaces clusters = 4; 13 | ClusterWithNamespaces cluster_with_namespaces = 5; 14 | 15 | message ClusterWithNamespaces { 16 | Cluster cluster = 1; 17 | repeated NamespaceWithDeployments namespaces = 2; 18 | }; 19 | 20 | message NamespaceWithDeployments { 21 | Namespace namespace = 1; 22 | repeated DeploymentWithEndpoints deployments = 2; 23 | }; 24 | 25 | message DeploymentWithEndpoints { 26 | Deployment deployment = 1; 27 | repeated Endpoint endpoints = 2; 28 | }; 29 | } 30 | 31 | message Deployment {} 32 | message Endpoint {} 33 | message Namespace {} 34 | message Cluster {} 35 | 36 | message DepositReply { string id = 1; } 37 | -------------------------------------------------------------------------------- /example/main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 NAME HERE 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package main 16 | 17 | import ( 18 | "github.com/tetratelabs/protoc-gen-cobra/example/cmd" 19 | "github.com/tetratelabs/protoc-gen-cobra/example/pb" 20 | ) 21 | 22 | func init() { 23 | // Add client generated commands to cobra's root cmd. 24 | cmd.RootCmd.AddCommand(pb.BankClientCommand()) 25 | cmd.RootCmd.AddCommand(pb.CacheClientCommand()) 26 | cmd.RootCmd.AddCommand(pb.TimerClientCommand()) 27 | cmd.RootCmd.AddCommand(pb.NestedMessagesClientCommand()) 28 | cmd.RootCmd.AddCommand(pb.CRUDClientCommand()) 29 | } 30 | 31 | func main() { 32 | cmd.Execute() 33 | } 34 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The protoc-gen-cobra authors. All rights reserved. 2 | // 3 | // Based on protoc-gen-go from https://github.com/golang/protobuf. 4 | // Copyright 2015 The Go Authors. All rights reserved. 5 | 6 | /* 7 | protoc-gen-cobra is a plugin for the Google protocol buffer compiler to 8 | generate Go code to be used for building command line clients using cobra. 9 | Run it by building this program and putting it in your path with the name 10 | protoc-gen-cobra 11 | That word 'cobra' at the end becomes part of the option string set for the 12 | protocol compiler, so once the protocol compiler (protoc) is installed 13 | you can run 14 | protoc --cobra_out=output_directory input_directory/file.proto 15 | to generate Go bindings for the protocol defined by file.proto. 16 | With that input, the output will be written to 17 | output_directory/file.cobra.pb.go 18 | Use it combined with the grpc output 19 | protoc --go_out=plugins=grpc:. --cobra_out=plugins=client:. *.proto 20 | 21 | The generated code is documented in the package comment for 22 | the library. 23 | 24 | See the README and documentation for protocol buffers to learn more: 25 | https://developers.google.com/protocol-buffers/ 26 | 27 | */ 28 | package documentation 29 | -------------------------------------------------------------------------------- /example/server/crud.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "sync" 5 | 6 | "google.golang.org/grpc/status" 7 | 8 | "golang.org/x/net/context" 9 | "google.golang.org/grpc/codes" 10 | 11 | "github.com/tetratelabs/protoc-gen-cobra/example/pb" 12 | ) 13 | 14 | type CRUD struct { 15 | kv sync.Map 16 | } 17 | 18 | func NewCRUD() *CRUD { 19 | return &CRUD{sync.Map{}} 20 | } 21 | func (c *CRUD) Create(_ context.Context, req *pb.CreateCRUD) (*pb.CRUDObject, error) { 22 | c.kv.Store(req.Name, req.Value) 23 | return &pb.CRUDObject{ 24 | Name: req.Name, 25 | Value: req.Value, 26 | }, nil 27 | } 28 | 29 | func (c *CRUD) Get(_ context.Context, req *pb.GetCRUD) (*pb.CRUDObject, error) { 30 | val, found := c.kv.Load(req.Name) 31 | if !found { 32 | return nil, status.Error(codes.NotFound, "could not find key "+req.Name) 33 | } 34 | return &pb.CRUDObject{ 35 | Name: req.Name, 36 | Value: val.(string), 37 | }, nil 38 | } 39 | 40 | func (c *CRUD) Update(ctx context.Context, req *pb.CRUDObject) (*pb.CRUDObject, error) { 41 | return c.Create(ctx, &pb.CreateCRUD{Name: req.Name, Value: req.Value}) 42 | } 43 | 44 | func (c *CRUD) Delete(_ context.Context, req *pb.CRUDObject) (*pb.Empty, error) { 45 | c.kv.Delete(req.Name) 46 | return &pb.Empty{}, nil 47 | } 48 | -------------------------------------------------------------------------------- /example/server/cache.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io" 5 | "sync" 6 | 7 | "golang.org/x/net/context" 8 | 9 | "github.com/tetratelabs/protoc-gen-cobra/example/pb" 10 | ) 11 | 12 | type Cache struct { 13 | mu sync.Mutex 14 | kv map[string]string 15 | } 16 | 17 | func NewCache() *Cache { 18 | return &Cache{ 19 | kv: make(map[string]string), 20 | } 21 | } 22 | 23 | func (c *Cache) Set(ctx context.Context, in *pb.SetRequest) (*pb.SetResponse, error) { 24 | c.mu.Lock() 25 | c.kv[in.Key] = in.Value 26 | c.mu.Unlock() 27 | return &pb.SetResponse{}, nil 28 | } 29 | 30 | func (c *Cache) Get(ctx context.Context, in *pb.GetRequest) (*pb.GetResponse, error) { 31 | c.mu.Lock() 32 | defer c.mu.Unlock() 33 | return &pb.GetResponse{ 34 | Value: c.kv[in.Key], 35 | }, nil 36 | } 37 | 38 | func (c *Cache) MultiSet(stream pb.Cache_MultiSetServer) error { 39 | for { 40 | req, err := stream.Recv() 41 | if err == io.EOF { 42 | break 43 | } 44 | if err != nil { 45 | return err 46 | } 47 | c.mu.Lock() 48 | c.kv[req.Key] = req.Value 49 | c.mu.Unlock() 50 | } 51 | return stream.SendAndClose(&pb.SetResponse{}) 52 | } 53 | 54 | func (c *Cache) MultiGet(stream pb.Cache_MultiGetServer) error { 55 | for { 56 | req, err := stream.Recv() 57 | if err == io.EOF { 58 | return nil 59 | } 60 | if err != nil { 61 | return err 62 | } 63 | c.mu.Lock() 64 | v := c.kv[req.Key] 65 | c.mu.Unlock() 66 | stream.Send(&pb.GetResponse{ 67 | Value: v, 68 | }) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /iocodec/decoder.go: -------------------------------------------------------------------------------- 1 | package iocodec 2 | 3 | import ( 4 | "encoding/json" 5 | "encoding/xml" 6 | "io" 7 | "io/ioutil" 8 | 9 | "gopkg.in/yaml.v2" 10 | ) 11 | 12 | // DefaultDecoders contains the default list of decoders per MIME type. 13 | var DefaultDecoders = DecoderGroup{ 14 | "xml": DecoderMakerFunc(func(r io.Reader) Decoder { return xml.NewDecoder(r) }), 15 | "json": DecoderMakerFunc(func(r io.Reader) Decoder { return json.NewDecoder(r) }), 16 | "yaml": DecoderMakerFunc(func(r io.Reader) Decoder { return &yamlDecoder{r} }), 17 | "noop": DecoderMakerFunc(func(r io.Reader) Decoder { return noop{} }), 18 | } 19 | 20 | type ( 21 | // A Decoder decodes data into v. 22 | Decoder interface { 23 | Decode(v interface{}) error 24 | } 25 | 26 | // A DecoderGroup maps MIME types to DecoderMakers. 27 | DecoderGroup map[string]DecoderMaker 28 | 29 | // A DecoderMaker creates and returns a new Decoder. 30 | DecoderMaker interface { 31 | NewDecoder(r io.Reader) Decoder 32 | } 33 | 34 | // DecoderMakerFunc is an adapter for creating DecoderMakers 35 | // from functions. 36 | DecoderMakerFunc func(r io.Reader) Decoder 37 | 38 | noop struct{} 39 | ) 40 | 41 | // NewDecoder implements the DecoderMaker interface. 42 | func (f DecoderMakerFunc) NewDecoder(r io.Reader) Decoder { 43 | return f(r) 44 | } 45 | 46 | type yamlDecoder struct { 47 | r io.Reader 48 | } 49 | 50 | func (yd *yamlDecoder) Decode(v interface{}) error { 51 | b, err := ioutil.ReadAll(yd.r) 52 | if err != nil { 53 | return err 54 | } 55 | return yaml.Unmarshal(b, v) 56 | } 57 | 58 | func (noop) Decode(v interface{}) error { 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Cobra command line generator for Go Protocol Buffers + gRPC 2 | Copyright 2016 The protoc-gen-cobra authors. All rights reserved. 3 | 4 | Based on protoc-gen-go from https://github.com/golang/protobuf 5 | 6 | Go support for Protocol Buffers - Google's data interchange format 7 | 8 | Copyright 2010 The Go Authors. All rights reserved. 9 | https://github.com/golang/protobuf 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are 13 | met: 14 | 15 | * Redistributions of source code must retain the above copyright 16 | notice, this list of conditions and the following disclaimer. 17 | * Redistributions in binary form must reproduce the above 18 | copyright notice, this list of conditions and the following disclaimer 19 | in the documentation and/or other materials provided with the 20 | distribution. 21 | * Neither the name of Google Inc. nor the names of its 22 | contributors may be used to endorse or promote products derived from 23 | this software without specific prior written permission. 24 | 25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | 37 | -------------------------------------------------------------------------------- /iocodec/encoder.go: -------------------------------------------------------------------------------- 1 | package iocodec 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "encoding/xml" 7 | "io" 8 | 9 | "gopkg.in/yaml.v2" 10 | ) 11 | 12 | // DefaultEncoders contains the default list of encoders per MIME type. 13 | var DefaultEncoders = EncoderGroup{ 14 | "xml": EncoderMakerFunc(func(w io.Writer) Encoder { return &xmlEncoder{w} }), 15 | "json": EncoderMakerFunc(func(w io.Writer) Encoder { return &jsonEncoder{w, false} }), 16 | "prettyjson": EncoderMakerFunc(func(w io.Writer) Encoder { return &jsonEncoder{w, true} }), 17 | "yaml": EncoderMakerFunc(func(w io.Writer) Encoder { return &yamlEncoder{w} }), 18 | } 19 | 20 | type ( 21 | // An Encoder encodes data from v. 22 | Encoder interface { 23 | Encode(v interface{}) error 24 | } 25 | 26 | // An EncoderGroup maps MIME types to EncoderMakers. 27 | EncoderGroup map[string]EncoderMaker 28 | 29 | // An EncoderMaker creates and returns a new Encoder. 30 | EncoderMaker interface { 31 | NewEncoder(w io.Writer) Encoder 32 | } 33 | 34 | // EncoderMakerFunc is an adapter for creating EncoderMakers 35 | // from functions. 36 | EncoderMakerFunc func(w io.Writer) Encoder 37 | ) 38 | 39 | // NewEncoder implements the EncoderMaker interface. 40 | func (f EncoderMakerFunc) NewEncoder(w io.Writer) Encoder { 41 | return f(w) 42 | } 43 | 44 | type xmlEncoder struct { 45 | w io.Writer 46 | } 47 | 48 | func (xe *xmlEncoder) Encode(v interface{}) error { 49 | xe.w.Write([]byte(xml.Header)) 50 | defer xe.w.Write([]byte("\n")) 51 | e := xml.NewEncoder(xe.w) 52 | e.Indent("", "\t") 53 | return e.Encode(v) 54 | } 55 | 56 | type jsonEncoder struct { 57 | w io.Writer 58 | pretty bool 59 | } 60 | 61 | func (je *jsonEncoder) Encode(v interface{}) error { 62 | if je.pretty { 63 | b, err := json.Marshal(v) 64 | if err != nil { 65 | return err 66 | } 67 | var out bytes.Buffer 68 | err = json.Indent(&out, b, "", "\t") 69 | if err != nil { 70 | return err 71 | } 72 | _, err = io.Copy(je.w, &out) 73 | if err != nil { 74 | return err 75 | } 76 | _, err = je.w.Write([]byte("\n")) 77 | return err 78 | } 79 | return json.NewEncoder(je.w).Encode(v) 80 | } 81 | 82 | type yamlEncoder struct { 83 | w io.Writer 84 | } 85 | 86 | func (ye *yamlEncoder) Encode(v interface{}) error { 87 | b, err := yaml.Marshal(v) 88 | if err != nil { 89 | return err 90 | } 91 | _, err = ye.w.Write(b) 92 | return err 93 | } 94 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The protoc-gen-cobra authors. All rights reserved. 2 | // 3 | // Based on protoc-gen-go from https://github.com/golang/protobuf. 4 | // Copyright 2010 The Go Authors. All rights reserved. 5 | 6 | // protoc-gen-cobra is a plugin for the Google protocol buffer compiler to 7 | // generate Go code to be used for building command line tools using cobra. 8 | // Run it by building this program and putting it in your path with 9 | // the name 10 | // protoc-gen-cobra 11 | // That word 'cobra' at the end becomes part of the option string set for the 12 | // protocol compiler, so once the protocol compiler (protoc) is installed 13 | // you can run 14 | // protoc --cobra_out=output_directory input_directory/file.proto 15 | // to generate Go bindings for the protocol defined by file.proto. 16 | // With that input, the output will be written to 17 | // output_directory/file.pb.go 18 | // Use it combined with the grpc output 19 | // protoc --go_out=plugins=grpc:. --cobra_out=plugins=client:. *.proto 20 | // 21 | // The generated code is documented in the package comment for 22 | // the library. 23 | // 24 | // See the README and documentation for protocol buffers to learn more: 25 | // https://developers.google.com/protocol-buffers/ 26 | package main 27 | 28 | import ( 29 | "io/ioutil" 30 | "os" 31 | 32 | "github.com/golang/protobuf/proto" 33 | 34 | "github.com/tetratelabs/protoc-gen-cobra/generator" 35 | ) 36 | 37 | func main() { 38 | // Begin by allocating a generator. The request and response structures are stored there 39 | // so we can do error handling easily - the response structure contains the field to 40 | // report failure. 41 | g := generator.New() 42 | 43 | data, err := ioutil.ReadAll(os.Stdin) 44 | if err != nil { 45 | g.Error(err, "reading input") 46 | } 47 | 48 | if err := proto.Unmarshal(data, g.Request); err != nil { 49 | g.Error(err, "parsing input proto") 50 | } 51 | 52 | if len(g.Request.FileToGenerate) == 0 { 53 | g.Fail("no files to generate") 54 | } 55 | 56 | g.CommandLineParameters(g.Request.GetParameter()) 57 | 58 | // Create a wrapped version of the Descriptors and EnumDescriptors that 59 | // point to the file that defines them. 60 | g.WrapTypes() 61 | 62 | g.SetPackageNames() 63 | 64 | g.GenerateAllFiles() 65 | 66 | // Send back the results. 67 | data, err = proto.Marshal(g.Response) 68 | if err != nil { 69 | g.Error(err, "failed to marshal output proto") 70 | } 71 | _, err = os.Stdout.Write(data) 72 | if err != nil { 73 | g.Error(err, "failed to write output proto") 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /example/cmd/root.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2016 NAME HERE 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package cmd 16 | 17 | import ( 18 | "fmt" 19 | "os" 20 | 21 | "github.com/spf13/cobra" 22 | "github.com/spf13/viper" 23 | ) 24 | 25 | var cfgFile string 26 | 27 | // This represents the base command when called without any subcommands 28 | var RootCmd = &cobra.Command{ 29 | Use: "example", 30 | Short: "A brief description of your application", 31 | Long: `A longer description that spans multiple lines and likely contains 32 | examples and usage of using your application. For example: 33 | 34 | Cobra is a CLI library for Go that empowers applications. 35 | This application is a tool to generate the needed files 36 | to quickly create a Cobra application.`, 37 | // Uncomment the following line if your bare application 38 | // has an action associated with it: 39 | // Run: func(cmd *cobra.Command, args []string) { }, 40 | } 41 | 42 | // Execute adds all child commands to the root command sets flags appropriately. 43 | // This is called by main.main(). It only needs to happen once to the rootCmd. 44 | func Execute() { 45 | if err := RootCmd.Execute(); err != nil { 46 | fmt.Println(err) 47 | os.Exit(-1) 48 | } 49 | } 50 | 51 | func init() { 52 | cobra.OnInitialize(initConfig) 53 | 54 | // Here you will define your flags and configuration settings. 55 | // Cobra supports Persistent Flags, which, if defined here, 56 | // will be global for your application. 57 | 58 | RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.example.yaml)") 59 | // Cobra also supports local flags, which will only run 60 | // when this action is called directly. 61 | RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 62 | } 63 | 64 | // initConfig reads in config file and ENV variables if set. 65 | func initConfig() { 66 | if cfgFile != "" { // enable ability to specify config file via flag 67 | viper.SetConfigFile(cfgFile) 68 | } 69 | 70 | viper.SetConfigName(".example") // name of config file (without extension) 71 | viper.AddConfigPath("$HOME") // adding home directory as first search path 72 | viper.AutomaticEnv() // read in environment variables that match 73 | 74 | // If a config file is found, read it in. 75 | if err := viper.ReadInConfig(); err == nil { 76 | fmt.Println("Using config file:", viper.ConfigFileUsed()) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /golden_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "flag" 6 | "io/ioutil" 7 | "os" 8 | "os/exec" 9 | "path/filepath" 10 | "regexp" 11 | "strings" 12 | "testing" 13 | ) 14 | 15 | var regenerate = flag.Bool("regenerate", false, "regenerate golden files") 16 | 17 | // When the environment variable RUN_AS_PROTOC_GEN_COBRA is set, we skip running tests and instead 18 | // act as protoc-gen-cobra. This allows the test binary to pass itself to protoc. 19 | func init() { 20 | if os.Getenv("RUN_AS_PROTOC_GEN_COBRA") != "" { 21 | main() 22 | os.Exit(0) 23 | } 24 | } 25 | 26 | func TestGolden(t *testing.T) { 27 | workdir, err := ioutil.TempDir("", "proto-test") 28 | if err != nil { 29 | t.Fatal(err) 30 | } 31 | defer os.RemoveAll(workdir) 32 | 33 | packages := map[string][]string{} 34 | err = filepath.Walk("testdata", func(path string, info os.FileInfo, err error) error { 35 | if !strings.HasSuffix(path, ".proto") { 36 | return nil 37 | } 38 | dir := filepath.Dir(path) 39 | packages[dir] = append(packages[dir], path) 40 | return nil 41 | }) 42 | if err != nil { 43 | t.Fatal(err) 44 | } 45 | 46 | // Compile each package, using this binary as protoc-gen-cobra. 47 | for _, sources := range packages { 48 | args := []string{"-Itestdata", "--cobra_out=plugins=client,paths=source_relative:" + workdir} 49 | args = append(args, sources...) 50 | t.Log(args) 51 | protoc(t, args) 52 | } 53 | 54 | filepath.Walk(workdir, func(genPath string, info os.FileInfo, _ error) error { 55 | if info.IsDir() { 56 | return nil 57 | } 58 | 59 | relPath, err := filepath.Rel(workdir, genPath) 60 | if err != nil { 61 | t.Errorf("filepath.Rel(%q, %q): %v", workdir, genPath, err) 62 | return nil 63 | } 64 | if filepath.SplitList(relPath)[0] == ".." { 65 | t.Errorf("generated file %q is not relative to %q", genPath, workdir) 66 | } 67 | 68 | goldenPath := filepath.Join("testdata", relPath) 69 | 70 | got, err := ioutil.ReadFile(genPath) 71 | if err != nil { 72 | t.Error(err) 73 | return nil 74 | } 75 | if *regenerate { 76 | // If --regenerate set, just rewrite the golden files. 77 | err := ioutil.WriteFile(goldenPath, got, 0666) 78 | if err != nil { 79 | t.Error(err) 80 | } 81 | return nil 82 | } 83 | 84 | want, err := ioutil.ReadFile(goldenPath) 85 | if err != nil { 86 | t.Error(err) 87 | return nil 88 | } 89 | 90 | want = fdescRE.ReplaceAll(want, nil) 91 | got = fdescRE.ReplaceAll(got, nil) 92 | if bytes.Equal(got, want) { 93 | return nil 94 | } 95 | 96 | cmd := exec.Command("diff", "-u", goldenPath, genPath) 97 | out, _ := cmd.CombinedOutput() 98 | t.Errorf("golden file differs: %v\n%v", relPath, string(out)) 99 | return nil 100 | }) 101 | } 102 | 103 | var fdescRE = regexp.MustCompile(`(?ms)^var fileDescriptor.*}`) 104 | 105 | func protoc(t *testing.T, args []string) { 106 | cmd := exec.Command("protoc", "--plugin=protoc-gen-cobra="+os.Args[0]) 107 | cmd.Args = append(cmd.Args, args...) 108 | // We set the RUN_AS_PROTOC_GEN_COBRA environment variable to indicate that the subprocess 109 | // should act as a proto compiler rather than a test. 110 | cmd.Env = append(os.Environ(), "RUN_AS_PROTOC_GEN_COBRA=1") 111 | out, err := cmd.CombinedOutput() 112 | if len(out) > 0 || err != nil { 113 | t.Log("RUNNING: ", strings.Join(cmd.Args, " ")) 114 | } 115 | if len(out) > 0 { 116 | t.Log(string(out)) 117 | } 118 | if err != nil { 119 | t.Fatalf("protoc: %v", err) 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # protoc-gen-cobra 2 | 3 | Cobra command line tool generator for Go gRPC. 4 | 5 | [![GoDoc](https://godoc.org/github.com/fiorix/protoc-gen-cobra?status.svg)](https://godoc.org/github.com/fiorix/protoc-gen-cobra) 6 | 7 | ### What's this? 8 | 9 | A plugin for the [protobuf](https://github.com/google/protobuf) compiler protoc, that generates Go code using [cobra](https://github.com/spf13/cobra). It is capable of generating client code for command line tools consistent with your protobuf description. 10 | 11 | This: 12 | 13 | ``` 14 | service Bank { 15 | rpc Deposit(DepositRequest) returns (DepositReply) 16 | } 17 | 18 | message DepositRequest { 19 | string account = 1; 20 | double amount = 2; 21 | } 22 | 23 | message DepositReply { 24 | string account = 1; 25 | double balance = 2; 26 | } 27 | ``` 28 | 29 | produces a client that can do: 30 | 31 | ``` 32 | echo '{"account":"foobar","amount":10}' | command bank deposit 33 | ``` 34 | 35 | It generates one [cobra.Command](https://godoc.org/github.com/spf13/cobra#Command) per gRPC service (e.g. bank). The service's rpc methods are sub-commands, and share the same command line semantics. They take a request file for input, or stdin, and prints the response to the terminal, in the specified format. The client currently supports basic connectivity settings such as tls on/off, tls client authentication and so on. 36 | 37 | ``` 38 | $ ./example bank deposit -h 39 | Deposit client 40 | 41 | You can use environment variables with the same name of the command flags. 42 | All caps and s/-/_, e.g. SERVER_ADDR. 43 | 44 | Usage: 45 | example bank deposit [flags] 46 | 47 | Examples: 48 | 49 | Save a sample request to a file (or refer to your protobuf descriptor to create one): 50 | deposit -p > req.json 51 | 52 | Submit request using file: 53 | deposit -f req.json 54 | 55 | Authenticate using the Authorization header (requires transport security): 56 | export AUTH_TOKEN=your_access_token 57 | export SERVER_ADDR=api.example.com:443 58 | echo '{json}' | deposit --tls 59 | 60 | Flags: 61 | --auth-token string authorization token 62 | --auth-token-type string authorization token type (default "Bearer") 63 | --jwt-key string jwt key 64 | --jwt-key-file string jwt key file 65 | -p, --print-sample-request print sample request file and exit 66 | -f, --request-file string client request file (must be json, yaml, or xml); use "-" for stdin + json 67 | -o, --response-format string response format (json, prettyjson, yaml, or xml) (default "json") 68 | -s, --server-addr string server address in form of host:port (default "localhost:8080") 69 | --timeout duration client connection timeout (default 10s) 70 | --tls enable tls 71 | --tls-ca-cert-file string ca certificate file 72 | --tls-cert-file string client certificate file 73 | --tls-insecure-skip-verify INSECURE: skip tls checks 74 | --tls-key-file string client key file 75 | --tls-server-name string tls server name override 76 | ``` 77 | 78 | This is an experiment. Was bored of writing the same boilerplate code to interact with gRPC servers, wanted something like [kubectl](http://kubernetes.io/docs/user-guide/kubectl-overview/). At some point I might want to generate server code too, similar to what go-swagger does. Perhaps look at using go-openapi too. Tests are lacking. 79 | 80 | ### Streams 81 | 82 | gRPC client and server streams are supported, you can do pipes from the command line. On server streams, each response is printed out using the specified response format. Client streams input must be formatted as json, one document per line, from a file or stdin. 83 | 84 | Example client stream: 85 | 86 | ``` 87 | $ cat req.json 88 | {"key":"hello","value":"world"} 89 | {"key":"foo","value":"bar"} 90 | 91 | $ ./example cache multiset -f req.json 92 | ``` 93 | 94 | Example client and server streams: 95 | 96 | ``` 97 | $ echo -ne '{"key":"hello"}\n{"key":"foo"}\n' | ./example cache multiget 98 | {"value":"world"} 99 | {"value":"bar"} 100 | ``` 101 | 102 | Idle server streams hang until the server closes the stream, or a timeout occurs. 103 | -------------------------------------------------------------------------------- /example/pb/maplist.cobra.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by tetratelabs/protoc-gen-cobra. 2 | // source: maplist.proto 3 | // DO NOT EDIT! 4 | 5 | package pb 6 | 7 | import ( 8 | tls "crypto/tls" 9 | x509 "crypto/x509" 10 | fmt "fmt" 11 | ioutil "io/ioutil" 12 | log "log" 13 | net "net" 14 | os "os" 15 | filepath "path/filepath" 16 | time "time" 17 | 18 | proto "github.com/golang/protobuf/proto" 19 | cobra "github.com/spf13/cobra" 20 | pflag "github.com/spf13/pflag" 21 | iocodec "github.com/tetratelabs/protoc-gen-cobra/iocodec" 22 | context "golang.org/x/net/context" 23 | oauth2 "golang.org/x/oauth2" 24 | grpc "google.golang.org/grpc" 25 | credentials "google.golang.org/grpc/credentials" 26 | oauth "google.golang.org/grpc/credentials/oauth" 27 | ) 28 | 29 | // This is a compile-time assertion to ensure that this generated file 30 | // is compatible with the grpc package it is being compiled against. 31 | const _ = grpc.SupportPackageIsVersion4 32 | 33 | var _DefaultMapListClientCommandConfig = _NewMapListClientCommandConfig() 34 | 35 | type _MapListClientCommandConfig struct { 36 | ServerAddr string 37 | RequestFile string 38 | Stdin bool 39 | PrintSampleRequest bool 40 | ResponseFormat string 41 | Timeout time.Duration 42 | TLS bool 43 | ServerName string 44 | InsecureSkipVerify bool 45 | CACertFile string 46 | CertFile string 47 | KeyFile string 48 | AuthToken string 49 | AuthTokenType string 50 | JWTKey string 51 | JWTKeyFile string 52 | } 53 | 54 | func _NewMapListClientCommandConfig() *_MapListClientCommandConfig { 55 | c := &_MapListClientCommandConfig{ 56 | ServerAddr: "localhost:8080", 57 | ResponseFormat: "json", 58 | Timeout: 10 * time.Second, 59 | AuthTokenType: "Bearer", 60 | } 61 | return c 62 | } 63 | 64 | func (o *_MapListClientCommandConfig) AddFlags(fs *pflag.FlagSet) { 65 | fs.StringVarP(&o.ServerAddr, "server-addr", "s", o.ServerAddr, "server address in form of host:port") 66 | fs.StringVarP(&o.RequestFile, "request-file", "f", o.RequestFile, "client request file (must be json, yaml, or xml); use \"-\" for stdin + json") 67 | fs.BoolVar(&o.Stdin, "stdin", o.Stdin, "read client request from STDIN; alternative for '-f -'") 68 | fs.BoolVarP(&o.PrintSampleRequest, "print-sample-request", "p", o.PrintSampleRequest, "print sample request file and exit") 69 | fs.StringVarP(&o.ResponseFormat, "response-format", "o", o.ResponseFormat, "response format (json, prettyjson, yaml, or xml)") 70 | fs.DurationVar(&o.Timeout, "timeout", o.Timeout, "client connection timeout") 71 | fs.BoolVar(&o.TLS, "tls", o.TLS, "enable tls") 72 | fs.StringVar(&o.ServerName, "tls-server-name", o.ServerName, "tls server name override") 73 | fs.BoolVar(&o.InsecureSkipVerify, "tls-insecure-skip-verify", o.InsecureSkipVerify, "INSECURE: skip tls checks") 74 | fs.StringVar(&o.CACertFile, "tls-ca-cert-file", o.CACertFile, "ca certificate file") 75 | fs.StringVar(&o.CertFile, "tls-cert-file", o.CertFile, "client certificate file") 76 | fs.StringVar(&o.KeyFile, "tls-key-file", o.KeyFile, "client key file") 77 | fs.StringVar(&o.AuthToken, "auth-token", o.AuthToken, "authorization token") 78 | fs.StringVar(&o.AuthTokenType, "auth-token-type", o.AuthTokenType, "authorization token type") 79 | fs.StringVar(&o.JWTKey, "jwt-key", o.JWTKey, "jwt key") 80 | fs.StringVar(&o.JWTKeyFile, "jwt-key-file", o.JWTKeyFile, "jwt key file") 81 | } 82 | 83 | func MapListClientCommand() *cobra.Command { 84 | cmd := &cobra.Command{ 85 | Use: "maplist", 86 | } 87 | _DefaultMapListClientCommandConfig.AddFlags(cmd.PersistentFlags()) 88 | 89 | for _, s := range _MapListClientSubCommands { 90 | cmd.AddCommand(s()) 91 | } 92 | return cmd 93 | } 94 | 95 | func _DialMapList() (*grpc.ClientConn, MapListClient, error) { 96 | cfg := _DefaultMapListClientCommandConfig 97 | opts := []grpc.DialOption{ 98 | grpc.WithBlock(), 99 | grpc.WithTimeout(cfg.Timeout), 100 | } 101 | if cfg.TLS { 102 | tlsConfig := &tls.Config{} 103 | if cfg.InsecureSkipVerify { 104 | tlsConfig.InsecureSkipVerify = true 105 | } 106 | if cfg.CACertFile != "" { 107 | cacert, err := ioutil.ReadFile(cfg.CACertFile) 108 | if err != nil { 109 | return nil, nil, fmt.Errorf("ca cert: %v", err) 110 | } 111 | certpool := x509.NewCertPool() 112 | certpool.AppendCertsFromPEM(cacert) 113 | tlsConfig.RootCAs = certpool 114 | } 115 | if cfg.CertFile != "" { 116 | if cfg.KeyFile == "" { 117 | return nil, nil, fmt.Errorf("missing key file") 118 | } 119 | pair, err := tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile) 120 | if err != nil { 121 | return nil, nil, fmt.Errorf("cert/key: %v", err) 122 | } 123 | tlsConfig.Certificates = []tls.Certificate{pair} 124 | } 125 | if cfg.ServerName != "" { 126 | tlsConfig.ServerName = cfg.ServerName 127 | } else { 128 | addr, _, _ := net.SplitHostPort(cfg.ServerAddr) 129 | tlsConfig.ServerName = addr 130 | } 131 | //tlsConfig.BuildNameToCertificate() 132 | cred := credentials.NewTLS(tlsConfig) 133 | opts = append(opts, grpc.WithTransportCredentials(cred)) 134 | } else { 135 | opts = append(opts, grpc.WithInsecure()) 136 | } 137 | if cfg.AuthToken != "" { 138 | cred := oauth.NewOauthAccess(&oauth2.Token{ 139 | AccessToken: cfg.AuthToken, 140 | TokenType: cfg.AuthTokenType, 141 | }) 142 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 143 | } 144 | if cfg.JWTKey != "" { 145 | cred, err := oauth.NewJWTAccessFromKey([]byte(cfg.JWTKey)) 146 | if err != nil { 147 | return nil, nil, fmt.Errorf("jwt key: %v", err) 148 | } 149 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 150 | } 151 | if cfg.JWTKeyFile != "" { 152 | cred, err := oauth.NewJWTAccessFromFile(cfg.JWTKeyFile) 153 | if err != nil { 154 | return nil, nil, fmt.Errorf("jwt key file: %v", err) 155 | } 156 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 157 | } 158 | conn, err := grpc.Dial(cfg.ServerAddr, opts...) 159 | if err != nil { 160 | return nil, nil, err 161 | } 162 | return conn, NewMapListClient(conn), nil 163 | } 164 | 165 | type _MapListRoundTripFunc func(cli MapListClient, in iocodec.Decoder, out iocodec.Encoder) error 166 | 167 | func _MapListRoundTrip(sample interface{}, fn _MapListRoundTripFunc) error { 168 | cfg := _DefaultMapListClientCommandConfig 169 | var em iocodec.EncoderMaker 170 | var ok bool 171 | if cfg.ResponseFormat == "" { 172 | em = iocodec.DefaultEncoders["json"] 173 | } else { 174 | em, ok = iocodec.DefaultEncoders[cfg.ResponseFormat] 175 | if !ok { 176 | return fmt.Errorf("invalid response format: %q", cfg.ResponseFormat) 177 | } 178 | } 179 | if cfg.PrintSampleRequest { 180 | return em.NewEncoder(os.Stdout).Encode(sample) 181 | } 182 | // read the input request, first from stdin, then from a file, otherwise from args only 183 | var d iocodec.Decoder 184 | if cfg.Stdin || cfg.RequestFile == "-" { 185 | d = iocodec.DefaultDecoders["json"].NewDecoder(os.Stdin) 186 | } else if cfg.RequestFile != "" { 187 | f, err := os.Open(cfg.RequestFile) 188 | if err != nil { 189 | return fmt.Errorf("request file: %v", err) 190 | } 191 | defer f.Close() 192 | ext := filepath.Ext(cfg.RequestFile) 193 | if len(ext) > 0 && ext[0] == '.' { 194 | ext = ext[1:] 195 | } 196 | dm, ok := iocodec.DefaultDecoders[ext] 197 | if !ok { 198 | return fmt.Errorf("invalid request file format: %q", ext) 199 | } 200 | d = dm.NewDecoder(f) 201 | } else { 202 | d = iocodec.DefaultDecoders["noop"].NewDecoder(os.Stdin) 203 | } 204 | conn, client, err := _DialMapList() 205 | if err != nil { 206 | return err 207 | } 208 | defer conn.Close() 209 | return fn(client, d, em.NewEncoder(os.Stdout)) 210 | } 211 | 212 | func _MapListMethodClientCommand() *cobra.Command { 213 | reqArgs := &MapListRequest{} 214 | 215 | cmd := &cobra.Command{ 216 | Use: "method", 217 | Long: "Method client; call by piping a request in to stdin (--stdin), reading a file (--file), or via flags per field", 218 | Example: "TODO: print protobuf method comments here", 219 | Run: func(cmd *cobra.Command, args []string) { 220 | var v MapListRequest 221 | err := _MapListRoundTrip(v, func(cli MapListClient, in iocodec.Decoder, out iocodec.Encoder) error { 222 | 223 | err := in.Decode(&v) 224 | if err != nil { 225 | return err 226 | } 227 | 228 | proto.Merge(&v, reqArgs) 229 | resp, err := cli.Method(context.Background(), &v) 230 | 231 | if err != nil { 232 | return err 233 | } 234 | 235 | return out.Encode(resp) 236 | 237 | }) 238 | if err != nil { 239 | log.Fatal(err) 240 | } 241 | }, 242 | } 243 | 244 | cmd.PersistentFlags() // Warning: list flags are not yet supported (field "MapField") 245 | cmd.PersistentFlags() // Warning: list flags are not yet supported (field "ListField") 246 | 247 | return cmd 248 | } 249 | 250 | var _MapListClientSubCommands = []func() *cobra.Command{ 251 | _MapListMethodClientCommand, 252 | } 253 | -------------------------------------------------------------------------------- /example/pb/timer.cobra.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by tetratelabs/protoc-gen-cobra. 2 | // source: timer.proto 3 | // DO NOT EDIT! 4 | 5 | package pb 6 | 7 | import ( 8 | tls "crypto/tls" 9 | x509 "crypto/x509" 10 | fmt "fmt" 11 | io "io" 12 | ioutil "io/ioutil" 13 | log "log" 14 | net "net" 15 | os "os" 16 | filepath "path/filepath" 17 | time "time" 18 | 19 | cobra "github.com/spf13/cobra" 20 | pflag "github.com/spf13/pflag" 21 | iocodec "github.com/tetratelabs/protoc-gen-cobra/iocodec" 22 | context "golang.org/x/net/context" 23 | oauth2 "golang.org/x/oauth2" 24 | grpc "google.golang.org/grpc" 25 | credentials "google.golang.org/grpc/credentials" 26 | oauth "google.golang.org/grpc/credentials/oauth" 27 | ) 28 | 29 | // This is a compile-time assertion to ensure that this generated file 30 | // is compatible with the grpc package it is being compiled against. 31 | const _ = grpc.SupportPackageIsVersion4 32 | 33 | var _DefaultTimerClientCommandConfig = _NewTimerClientCommandConfig() 34 | 35 | type _TimerClientCommandConfig struct { 36 | ServerAddr string 37 | RequestFile string 38 | Stdin bool 39 | PrintSampleRequest bool 40 | ResponseFormat string 41 | Timeout time.Duration 42 | TLS bool 43 | ServerName string 44 | InsecureSkipVerify bool 45 | CACertFile string 46 | CertFile string 47 | KeyFile string 48 | AuthToken string 49 | AuthTokenType string 50 | JWTKey string 51 | JWTKeyFile string 52 | } 53 | 54 | func _NewTimerClientCommandConfig() *_TimerClientCommandConfig { 55 | c := &_TimerClientCommandConfig{ 56 | ServerAddr: "localhost:8080", 57 | ResponseFormat: "json", 58 | Timeout: 10 * time.Second, 59 | AuthTokenType: "Bearer", 60 | } 61 | return c 62 | } 63 | 64 | func (o *_TimerClientCommandConfig) AddFlags(fs *pflag.FlagSet) { 65 | fs.StringVarP(&o.ServerAddr, "server-addr", "s", o.ServerAddr, "server address in form of host:port") 66 | fs.StringVarP(&o.RequestFile, "request-file", "f", o.RequestFile, "client request file (must be json, yaml, or xml); use \"-\" for stdin + json") 67 | fs.BoolVar(&o.Stdin, "stdin", o.Stdin, "read client request from STDIN; alternative for '-f -'") 68 | fs.BoolVarP(&o.PrintSampleRequest, "print-sample-request", "p", o.PrintSampleRequest, "print sample request file and exit") 69 | fs.StringVarP(&o.ResponseFormat, "response-format", "o", o.ResponseFormat, "response format (json, prettyjson, yaml, or xml)") 70 | fs.DurationVar(&o.Timeout, "timeout", o.Timeout, "client connection timeout") 71 | fs.BoolVar(&o.TLS, "tls", o.TLS, "enable tls") 72 | fs.StringVar(&o.ServerName, "tls-server-name", o.ServerName, "tls server name override") 73 | fs.BoolVar(&o.InsecureSkipVerify, "tls-insecure-skip-verify", o.InsecureSkipVerify, "INSECURE: skip tls checks") 74 | fs.StringVar(&o.CACertFile, "tls-ca-cert-file", o.CACertFile, "ca certificate file") 75 | fs.StringVar(&o.CertFile, "tls-cert-file", o.CertFile, "client certificate file") 76 | fs.StringVar(&o.KeyFile, "tls-key-file", o.KeyFile, "client key file") 77 | fs.StringVar(&o.AuthToken, "auth-token", o.AuthToken, "authorization token") 78 | fs.StringVar(&o.AuthTokenType, "auth-token-type", o.AuthTokenType, "authorization token type") 79 | fs.StringVar(&o.JWTKey, "jwt-key", o.JWTKey, "jwt key") 80 | fs.StringVar(&o.JWTKeyFile, "jwt-key-file", o.JWTKeyFile, "jwt key file") 81 | } 82 | 83 | func TimerClientCommand() *cobra.Command { 84 | cmd := &cobra.Command{ 85 | Use: "timer", 86 | } 87 | _DefaultTimerClientCommandConfig.AddFlags(cmd.PersistentFlags()) 88 | 89 | for _, s := range _TimerClientSubCommands { 90 | cmd.AddCommand(s()) 91 | } 92 | return cmd 93 | } 94 | 95 | func _DialTimer() (*grpc.ClientConn, TimerClient, error) { 96 | cfg := _DefaultTimerClientCommandConfig 97 | opts := []grpc.DialOption{ 98 | grpc.WithBlock(), 99 | grpc.WithTimeout(cfg.Timeout), 100 | } 101 | if cfg.TLS { 102 | tlsConfig := &tls.Config{} 103 | if cfg.InsecureSkipVerify { 104 | tlsConfig.InsecureSkipVerify = true 105 | } 106 | if cfg.CACertFile != "" { 107 | cacert, err := ioutil.ReadFile(cfg.CACertFile) 108 | if err != nil { 109 | return nil, nil, fmt.Errorf("ca cert: %v", err) 110 | } 111 | certpool := x509.NewCertPool() 112 | certpool.AppendCertsFromPEM(cacert) 113 | tlsConfig.RootCAs = certpool 114 | } 115 | if cfg.CertFile != "" { 116 | if cfg.KeyFile == "" { 117 | return nil, nil, fmt.Errorf("missing key file") 118 | } 119 | pair, err := tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile) 120 | if err != nil { 121 | return nil, nil, fmt.Errorf("cert/key: %v", err) 122 | } 123 | tlsConfig.Certificates = []tls.Certificate{pair} 124 | } 125 | if cfg.ServerName != "" { 126 | tlsConfig.ServerName = cfg.ServerName 127 | } else { 128 | addr, _, _ := net.SplitHostPort(cfg.ServerAddr) 129 | tlsConfig.ServerName = addr 130 | } 131 | //tlsConfig.BuildNameToCertificate() 132 | cred := credentials.NewTLS(tlsConfig) 133 | opts = append(opts, grpc.WithTransportCredentials(cred)) 134 | } else { 135 | opts = append(opts, grpc.WithInsecure()) 136 | } 137 | if cfg.AuthToken != "" { 138 | cred := oauth.NewOauthAccess(&oauth2.Token{ 139 | AccessToken: cfg.AuthToken, 140 | TokenType: cfg.AuthTokenType, 141 | }) 142 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 143 | } 144 | if cfg.JWTKey != "" { 145 | cred, err := oauth.NewJWTAccessFromKey([]byte(cfg.JWTKey)) 146 | if err != nil { 147 | return nil, nil, fmt.Errorf("jwt key: %v", err) 148 | } 149 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 150 | } 151 | if cfg.JWTKeyFile != "" { 152 | cred, err := oauth.NewJWTAccessFromFile(cfg.JWTKeyFile) 153 | if err != nil { 154 | return nil, nil, fmt.Errorf("jwt key file: %v", err) 155 | } 156 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 157 | } 158 | conn, err := grpc.Dial(cfg.ServerAddr, opts...) 159 | if err != nil { 160 | return nil, nil, err 161 | } 162 | return conn, NewTimerClient(conn), nil 163 | } 164 | 165 | type _TimerRoundTripFunc func(cli TimerClient, in iocodec.Decoder, out iocodec.Encoder) error 166 | 167 | func _TimerRoundTrip(sample interface{}, fn _TimerRoundTripFunc) error { 168 | cfg := _DefaultTimerClientCommandConfig 169 | var em iocodec.EncoderMaker 170 | var ok bool 171 | if cfg.ResponseFormat == "" { 172 | em = iocodec.DefaultEncoders["json"] 173 | } else { 174 | em, ok = iocodec.DefaultEncoders[cfg.ResponseFormat] 175 | if !ok { 176 | return fmt.Errorf("invalid response format: %q", cfg.ResponseFormat) 177 | } 178 | } 179 | if cfg.PrintSampleRequest { 180 | return em.NewEncoder(os.Stdout).Encode(sample) 181 | } 182 | // read the input request, first from stdin, then from a file, otherwise from args only 183 | var d iocodec.Decoder 184 | if cfg.Stdin || cfg.RequestFile == "-" { 185 | d = iocodec.DefaultDecoders["json"].NewDecoder(os.Stdin) 186 | } else if cfg.RequestFile != "" { 187 | f, err := os.Open(cfg.RequestFile) 188 | if err != nil { 189 | return fmt.Errorf("request file: %v", err) 190 | } 191 | defer f.Close() 192 | ext := filepath.Ext(cfg.RequestFile) 193 | if len(ext) > 0 && ext[0] == '.' { 194 | ext = ext[1:] 195 | } 196 | dm, ok := iocodec.DefaultDecoders[ext] 197 | if !ok { 198 | return fmt.Errorf("invalid request file format: %q", ext) 199 | } 200 | d = dm.NewDecoder(f) 201 | } else { 202 | d = iocodec.DefaultDecoders["noop"].NewDecoder(os.Stdin) 203 | } 204 | conn, client, err := _DialTimer() 205 | if err != nil { 206 | return err 207 | } 208 | defer conn.Close() 209 | return fn(client, d, em.NewEncoder(os.Stdout)) 210 | } 211 | 212 | func _TimerTickClientCommand() *cobra.Command { 213 | reqArgs := &TickRequest{} 214 | 215 | cmd := &cobra.Command{ 216 | Use: "tick", 217 | Long: "Tick client; call by piping a request in to stdin (--stdin), reading a file (--file), or via flags per field", 218 | Example: "TODO: print protobuf method comments here", 219 | Run: func(cmd *cobra.Command, args []string) { 220 | var v TickRequest 221 | err := _TimerRoundTrip(v, func(cli TimerClient, in iocodec.Decoder, out iocodec.Encoder) error { 222 | 223 | err := in.Decode(&v) 224 | if err != nil { 225 | return err 226 | } 227 | 228 | stream, err := cli.Tick(context.Background(), &v) 229 | 230 | if err != nil { 231 | return err 232 | } 233 | 234 | for { 235 | v, err := stream.Recv() 236 | if err == io.EOF { 237 | break 238 | } 239 | if err != nil { 240 | return err 241 | } 242 | err = out.Encode(v) 243 | if err != nil { 244 | return err 245 | } 246 | } 247 | return nil 248 | 249 | }) 250 | if err != nil { 251 | log.Fatal(err) 252 | } 253 | }, 254 | } 255 | 256 | cmd.PersistentFlags().Int32Var(&reqArgs.Interval, "interval", 0, "get-comment-from-proto") 257 | 258 | return cmd 259 | } 260 | 261 | var _TimerClientSubCommands = []func() *cobra.Command{ 262 | _TimerTickClientCommand, 263 | } 264 | -------------------------------------------------------------------------------- /example/pb/bank.cobra.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by tetratelabs/protoc-gen-cobra. 2 | // source: bank.proto 3 | // DO NOT EDIT! 4 | 5 | /* 6 | Package pb is a generated protocol buffer package. 7 | 8 | It is generated from these files: 9 | bank.proto 10 | cache.proto 11 | crud.proto 12 | maplist.proto 13 | nested.proto 14 | timer.proto 15 | 16 | It has these top-level commands: 17 | BankClientCommand 18 | CacheClientCommand 19 | CRUDClientCommand 20 | MapListClientCommand 21 | NestedMessagesClientCommand 22 | TimerClientCommand 23 | */ 24 | 25 | package pb 26 | 27 | import ( 28 | tls "crypto/tls" 29 | x509 "crypto/x509" 30 | fmt "fmt" 31 | ioutil "io/ioutil" 32 | log "log" 33 | net "net" 34 | os "os" 35 | filepath "path/filepath" 36 | time "time" 37 | 38 | proto "github.com/golang/protobuf/proto" 39 | cobra "github.com/spf13/cobra" 40 | pflag "github.com/spf13/pflag" 41 | iocodec "github.com/tetratelabs/protoc-gen-cobra/iocodec" 42 | context "golang.org/x/net/context" 43 | oauth2 "golang.org/x/oauth2" 44 | grpc "google.golang.org/grpc" 45 | credentials "google.golang.org/grpc/credentials" 46 | oauth "google.golang.org/grpc/credentials/oauth" 47 | ) 48 | 49 | // This is a compile-time assertion to ensure that this generated file 50 | // is compatible with the proto package it is being compiled against. 51 | // A compilation error at this line likely means your copy of the 52 | // proto package needs to be updated. 53 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package 54 | 55 | // This is a compile-time assertion to ensure that this generated file 56 | // is compatible with the grpc package it is being compiled against. 57 | const _ = grpc.SupportPackageIsVersion4 58 | 59 | var _DefaultBankClientCommandConfig = _NewBankClientCommandConfig() 60 | 61 | type _BankClientCommandConfig struct { 62 | ServerAddr string 63 | RequestFile string 64 | Stdin bool 65 | PrintSampleRequest bool 66 | ResponseFormat string 67 | Timeout time.Duration 68 | TLS bool 69 | ServerName string 70 | InsecureSkipVerify bool 71 | CACertFile string 72 | CertFile string 73 | KeyFile string 74 | AuthToken string 75 | AuthTokenType string 76 | JWTKey string 77 | JWTKeyFile string 78 | } 79 | 80 | func _NewBankClientCommandConfig() *_BankClientCommandConfig { 81 | c := &_BankClientCommandConfig{ 82 | ServerAddr: "localhost:8080", 83 | ResponseFormat: "json", 84 | Timeout: 10 * time.Second, 85 | AuthTokenType: "Bearer", 86 | } 87 | return c 88 | } 89 | 90 | func (o *_BankClientCommandConfig) AddFlags(fs *pflag.FlagSet) { 91 | fs.StringVarP(&o.ServerAddr, "server-addr", "s", o.ServerAddr, "server address in form of host:port") 92 | fs.StringVarP(&o.RequestFile, "request-file", "f", o.RequestFile, "client request file (must be json, yaml, or xml); use \"-\" for stdin + json") 93 | fs.BoolVar(&o.Stdin, "stdin", o.Stdin, "read client request from STDIN; alternative for '-f -'") 94 | fs.BoolVarP(&o.PrintSampleRequest, "print-sample-request", "p", o.PrintSampleRequest, "print sample request file and exit") 95 | fs.StringVarP(&o.ResponseFormat, "response-format", "o", o.ResponseFormat, "response format (json, prettyjson, yaml, or xml)") 96 | fs.DurationVar(&o.Timeout, "timeout", o.Timeout, "client connection timeout") 97 | fs.BoolVar(&o.TLS, "tls", o.TLS, "enable tls") 98 | fs.StringVar(&o.ServerName, "tls-server-name", o.ServerName, "tls server name override") 99 | fs.BoolVar(&o.InsecureSkipVerify, "tls-insecure-skip-verify", o.InsecureSkipVerify, "INSECURE: skip tls checks") 100 | fs.StringVar(&o.CACertFile, "tls-ca-cert-file", o.CACertFile, "ca certificate file") 101 | fs.StringVar(&o.CertFile, "tls-cert-file", o.CertFile, "client certificate file") 102 | fs.StringVar(&o.KeyFile, "tls-key-file", o.KeyFile, "client key file") 103 | fs.StringVar(&o.AuthToken, "auth-token", o.AuthToken, "authorization token") 104 | fs.StringVar(&o.AuthTokenType, "auth-token-type", o.AuthTokenType, "authorization token type") 105 | fs.StringVar(&o.JWTKey, "jwt-key", o.JWTKey, "jwt key") 106 | fs.StringVar(&o.JWTKeyFile, "jwt-key-file", o.JWTKeyFile, "jwt key file") 107 | } 108 | 109 | func BankClientCommand() *cobra.Command { 110 | cmd := &cobra.Command{ 111 | Use: "bank", 112 | } 113 | _DefaultBankClientCommandConfig.AddFlags(cmd.PersistentFlags()) 114 | 115 | for _, s := range _BankClientSubCommands { 116 | cmd.AddCommand(s()) 117 | } 118 | return cmd 119 | } 120 | 121 | func _DialBank() (*grpc.ClientConn, BankClient, error) { 122 | cfg := _DefaultBankClientCommandConfig 123 | opts := []grpc.DialOption{ 124 | grpc.WithBlock(), 125 | grpc.WithTimeout(cfg.Timeout), 126 | } 127 | if cfg.TLS { 128 | tlsConfig := &tls.Config{} 129 | if cfg.InsecureSkipVerify { 130 | tlsConfig.InsecureSkipVerify = true 131 | } 132 | if cfg.CACertFile != "" { 133 | cacert, err := ioutil.ReadFile(cfg.CACertFile) 134 | if err != nil { 135 | return nil, nil, fmt.Errorf("ca cert: %v", err) 136 | } 137 | certpool := x509.NewCertPool() 138 | certpool.AppendCertsFromPEM(cacert) 139 | tlsConfig.RootCAs = certpool 140 | } 141 | if cfg.CertFile != "" { 142 | if cfg.KeyFile == "" { 143 | return nil, nil, fmt.Errorf("missing key file") 144 | } 145 | pair, err := tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile) 146 | if err != nil { 147 | return nil, nil, fmt.Errorf("cert/key: %v", err) 148 | } 149 | tlsConfig.Certificates = []tls.Certificate{pair} 150 | } 151 | if cfg.ServerName != "" { 152 | tlsConfig.ServerName = cfg.ServerName 153 | } else { 154 | addr, _, _ := net.SplitHostPort(cfg.ServerAddr) 155 | tlsConfig.ServerName = addr 156 | } 157 | //tlsConfig.BuildNameToCertificate() 158 | cred := credentials.NewTLS(tlsConfig) 159 | opts = append(opts, grpc.WithTransportCredentials(cred)) 160 | } else { 161 | opts = append(opts, grpc.WithInsecure()) 162 | } 163 | if cfg.AuthToken != "" { 164 | cred := oauth.NewOauthAccess(&oauth2.Token{ 165 | AccessToken: cfg.AuthToken, 166 | TokenType: cfg.AuthTokenType, 167 | }) 168 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 169 | } 170 | if cfg.JWTKey != "" { 171 | cred, err := oauth.NewJWTAccessFromKey([]byte(cfg.JWTKey)) 172 | if err != nil { 173 | return nil, nil, fmt.Errorf("jwt key: %v", err) 174 | } 175 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 176 | } 177 | if cfg.JWTKeyFile != "" { 178 | cred, err := oauth.NewJWTAccessFromFile(cfg.JWTKeyFile) 179 | if err != nil { 180 | return nil, nil, fmt.Errorf("jwt key file: %v", err) 181 | } 182 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 183 | } 184 | conn, err := grpc.Dial(cfg.ServerAddr, opts...) 185 | if err != nil { 186 | return nil, nil, err 187 | } 188 | return conn, NewBankClient(conn), nil 189 | } 190 | 191 | type _BankRoundTripFunc func(cli BankClient, in iocodec.Decoder, out iocodec.Encoder) error 192 | 193 | func _BankRoundTrip(sample interface{}, fn _BankRoundTripFunc) error { 194 | cfg := _DefaultBankClientCommandConfig 195 | var em iocodec.EncoderMaker 196 | var ok bool 197 | if cfg.ResponseFormat == "" { 198 | em = iocodec.DefaultEncoders["json"] 199 | } else { 200 | em, ok = iocodec.DefaultEncoders[cfg.ResponseFormat] 201 | if !ok { 202 | return fmt.Errorf("invalid response format: %q", cfg.ResponseFormat) 203 | } 204 | } 205 | if cfg.PrintSampleRequest { 206 | return em.NewEncoder(os.Stdout).Encode(sample) 207 | } 208 | // read the input request, first from stdin, then from a file, otherwise from args only 209 | var d iocodec.Decoder 210 | if cfg.Stdin || cfg.RequestFile == "-" { 211 | d = iocodec.DefaultDecoders["json"].NewDecoder(os.Stdin) 212 | } else if cfg.RequestFile != "" { 213 | f, err := os.Open(cfg.RequestFile) 214 | if err != nil { 215 | return fmt.Errorf("request file: %v", err) 216 | } 217 | defer f.Close() 218 | ext := filepath.Ext(cfg.RequestFile) 219 | if len(ext) > 0 && ext[0] == '.' { 220 | ext = ext[1:] 221 | } 222 | dm, ok := iocodec.DefaultDecoders[ext] 223 | if !ok { 224 | return fmt.Errorf("invalid request file format: %q", ext) 225 | } 226 | d = dm.NewDecoder(f) 227 | } else { 228 | d = iocodec.DefaultDecoders["noop"].NewDecoder(os.Stdin) 229 | } 230 | conn, client, err := _DialBank() 231 | if err != nil { 232 | return err 233 | } 234 | defer conn.Close() 235 | return fn(client, d, em.NewEncoder(os.Stdout)) 236 | } 237 | 238 | func _BankDepositClientCommand() *cobra.Command { 239 | reqArgs := &DepositRequest{} 240 | 241 | cmd := &cobra.Command{ 242 | Use: "deposit", 243 | Long: "Deposit client; call by piping a request in to stdin (--stdin), reading a file (--file), or via flags per field", 244 | Example: "TODO: print protobuf method comments here", 245 | Run: func(cmd *cobra.Command, args []string) { 246 | var v DepositRequest 247 | err := _BankRoundTrip(v, func(cli BankClient, in iocodec.Decoder, out iocodec.Encoder) error { 248 | 249 | err := in.Decode(&v) 250 | if err != nil { 251 | return err 252 | } 253 | 254 | proto.Merge(&v, reqArgs) 255 | resp, err := cli.Deposit(context.Background(), &v) 256 | 257 | if err != nil { 258 | return err 259 | } 260 | 261 | return out.Encode(resp) 262 | 263 | }) 264 | if err != nil { 265 | log.Fatal(err) 266 | } 267 | }, 268 | } 269 | 270 | cmd.PersistentFlags().StringVar(&reqArgs.Account, "account", "", "get-comment-from-proto") 271 | cmd.PersistentFlags().Float64Var(&reqArgs.Amount, "amount", 0, "get-comment-from-proto") 272 | 273 | return cmd 274 | } 275 | 276 | var _BankClientSubCommands = []func() *cobra.Command{ 277 | _BankDepositClientCommand, 278 | } 279 | -------------------------------------------------------------------------------- /testdata/pb/bank.cobra.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by tetratelabs/protoc-gen-cobra. 2 | // source: pb/bank.proto 3 | // DO NOT EDIT! 4 | 5 | /* 6 | Package pb is a generated protocol buffer package. 7 | 8 | It is generated from these files: 9 | pb/bank.proto 10 | 11 | It has these top-level commands: 12 | BankClientCommand 13 | */ 14 | 15 | package pb 16 | 17 | import ( 18 | proto "github.com/golang/protobuf/proto" 19 | cobra "github.com/spf13/cobra" 20 | context "golang.org/x/net/context" 21 | credentials "google.golang.org/grpc/credentials" 22 | filepath "path/filepath" 23 | fmt1 "fmt" 24 | grpc "google.golang.org/grpc" 25 | io "io" 26 | iocodec "github.com/tetratelabs/protoc-gen-cobra/iocodec" 27 | ioutil "io/ioutil" 28 | json "encoding/json" 29 | log "log" 30 | net "net" 31 | oauth "google.golang.org/grpc/credentials/oauth" 32 | oauth2 "golang.org/x/oauth2" 33 | os "os" 34 | pflag "github.com/spf13/pflag" 35 | template "text/template" 36 | time "time" 37 | tls "crypto/tls" 38 | x509 "crypto/x509" 39 | ) 40 | 41 | // This is a compile-time assertion to ensure that this generated file 42 | // is compatible with the proto package it is being compiled against. 43 | // A compilation error at this line likely means your copy of the 44 | // proto package needs to be updated. 45 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package 46 | 47 | // This is a compile-time assertion to ensure that this generated file 48 | // is compatible with the grpc package it is being compiled against. 49 | const _ = grpc.SupportPackageIsVersion4 50 | 51 | var _DefaultBankClientCommandConfig = _NewBankClientCommandConfig() 52 | 53 | type _BankClientCommandConfig struct { 54 | ServerAddr string 55 | RequestFile string 56 | Stdin bool 57 | PrintSampleRequest bool 58 | ResponseFormat string 59 | Timeout time.Duration 60 | TLS bool 61 | ServerName string 62 | InsecureSkipVerify bool 63 | CACertFile string 64 | CertFile string 65 | KeyFile string 66 | AuthToken string 67 | AuthTokenType string 68 | JWTKey string 69 | JWTKeyFile string 70 | } 71 | 72 | func _NewBankClientCommandConfig() *_BankClientCommandConfig { 73 | c := &_BankClientCommandConfig{ 74 | ServerAddr: "localhost:8080", 75 | ResponseFormat: "json", 76 | Timeout: 10 * time.Second, 77 | AuthTokenType: "Bearer", 78 | } 79 | return c 80 | } 81 | 82 | func (o *_BankClientCommandConfig) AddFlags(fs *pflag.FlagSet) { 83 | fs.StringVarP(&o.ServerAddr, "server-addr", "s", o.ServerAddr, "server address in form of host:port") 84 | fs.StringVarP(&o.RequestFile, "request-file", "f", o.RequestFile, "client request file (must be json, yaml, or xml); use \"-\" for stdin + json") 85 | fs.BoolVar(&o.Stdin, "stdin", o.Stdin, "read client request from STDIN; alternative for '-f -'") 86 | fs.BoolVarP(&o.PrintSampleRequest, "print-sample-request", "p", o.PrintSampleRequest, "print sample request file and exit") 87 | fs.StringVarP(&o.ResponseFormat, "response-format", "o", o.ResponseFormat, "response format (json, prettyjson, yaml, or xml)") 88 | fs.DurationVar(&o.Timeout, "timeout", o.Timeout, "client connection timeout") 89 | fs.BoolVar(&o.TLS, "tls", o.TLS, "enable tls") 90 | fs.StringVar(&o.ServerName, "tls-server-name", o.ServerName, "tls server name override") 91 | fs.BoolVar(&o.InsecureSkipVerify, "tls-insecure-skip-verify", o.InsecureSkipVerify, "INSECURE: skip tls checks") 92 | fs.StringVar(&o.CACertFile, "tls-ca-cert-file", o.CACertFile, "ca certificate file") 93 | fs.StringVar(&o.CertFile, "tls-cert-file", o.CertFile, "client certificate file") 94 | fs.StringVar(&o.KeyFile, "tls-key-file", o.KeyFile, "client key file") 95 | fs.StringVar(&o.AuthToken, "auth-token", o.AuthToken, "authorization token") 96 | fs.StringVar(&o.AuthTokenType, "auth-token-type", o.AuthTokenType, "authorization token type") 97 | fs.StringVar(&o.JWTKey, "jwt-key", o.JWTKey, "jwt key") 98 | fs.StringVar(&o.JWTKeyFile, "jwt-key-file", o.JWTKeyFile, "jwt key file") 99 | } 100 | 101 | func BankClientCommand() *cobra.Command { 102 | cmd := &cobra.Command{ 103 | Use: "bank", 104 | } 105 | _DefaultBankClientCommandConfig.AddFlags(cmd.PersistentFlags()) 106 | 107 | for _, s := range _BankClientSubCommands { 108 | cmd.AddCommand(s()) 109 | } 110 | return cmd 111 | } 112 | 113 | func _DialBank() (*grpc.ClientConn, BankClient, error) { 114 | cfg := _DefaultBankClientCommandConfig 115 | opts := []grpc.DialOption{ 116 | grpc.WithBlock(), 117 | grpc.WithTimeout(cfg.Timeout), 118 | } 119 | if cfg.TLS { 120 | tlsConfig := &tls.Config{} 121 | if cfg.InsecureSkipVerify { 122 | tlsConfig.InsecureSkipVerify = true 123 | } 124 | if cfg.CACertFile != "" { 125 | cacert, err := ioutil.ReadFile(cfg.CACertFile) 126 | if err != nil { 127 | return nil, nil, fmt.Errorf("ca cert: %v", err) 128 | } 129 | certpool := x509.NewCertPool() 130 | certpool.AppendCertsFromPEM(cacert) 131 | tlsConfig.RootCAs = certpool 132 | } 133 | if cfg.CertFile != "" { 134 | if cfg.KeyFile == "" { 135 | return nil, nil, fmt.Errorf("missing key file") 136 | } 137 | pair, err := tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile) 138 | if err != nil { 139 | return nil, nil, fmt.Errorf("cert/key: %v", err) 140 | } 141 | tlsConfig.Certificates = []tls.Certificate{pair} 142 | } 143 | if cfg.ServerName != "" { 144 | tlsConfig.ServerName = cfg.ServerName 145 | } else { 146 | addr, _, _ := net.SplitHostPort(cfg.ServerAddr) 147 | tlsConfig.ServerName = addr 148 | } 149 | //tlsConfig.BuildNameToCertificate() 150 | cred := credentials.NewTLS(tlsConfig) 151 | opts = append(opts, grpc.WithTransportCredentials(cred)) 152 | } else { 153 | opts = append(opts, grpc.WithInsecure()) 154 | } 155 | if cfg.AuthToken != "" { 156 | cred := oauth.NewOauthAccess(&oauth2.Token{ 157 | AccessToken: cfg.AuthToken, 158 | TokenType: cfg.AuthTokenType, 159 | }) 160 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 161 | } 162 | if cfg.JWTKey != "" { 163 | cred, err := oauth.NewJWTAccessFromKey([]byte(cfg.JWTKey)) 164 | if err != nil { 165 | return nil, nil, fmt.Errorf("jwt key: %v", err) 166 | } 167 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 168 | } 169 | if cfg.JWTKeyFile != "" { 170 | cred, err := oauth.NewJWTAccessFromFile(cfg.JWTKeyFile) 171 | if err != nil { 172 | return nil, nil, fmt.Errorf("jwt key file: %v", err) 173 | } 174 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 175 | } 176 | conn, err := grpc.Dial(cfg.ServerAddr, opts...) 177 | if err != nil { 178 | return nil, nil, err 179 | } 180 | return conn, NewBankClient(conn), nil 181 | } 182 | 183 | type _BankRoundTripFunc func(cli BankClient, in iocodec.Decoder, out iocodec.Encoder) error 184 | 185 | func _BankRoundTrip(sample interface{}, fn _BankRoundTripFunc) error { 186 | cfg := _DefaultBankClientCommandConfig 187 | var em iocodec.EncoderMaker 188 | var ok bool 189 | if cfg.ResponseFormat == "" { 190 | em = iocodec.DefaultEncoders["json"] 191 | } else { 192 | em, ok = iocodec.DefaultEncoders[cfg.ResponseFormat] 193 | if !ok { 194 | return fmt.Errorf("invalid response format: %q", cfg.ResponseFormat) 195 | } 196 | } 197 | if cfg.PrintSampleRequest { 198 | return em.NewEncoder(os.Stdout).Encode(sample) 199 | } 200 | // read the input request, first from stdin, then from a file, otherwise from args only 201 | var d iocodec.Decoder 202 | if cfg.Stdin || cfg.RequestFile == "-" { 203 | d = iocodec.DefaultDecoders["json"].NewDecoder(os.Stdin) 204 | } else if cfg.RequestFile != "" { 205 | f, err := os.Open(cfg.RequestFile) 206 | if err != nil { 207 | return fmt.Errorf("request file: %v", err) 208 | } 209 | defer f.Close() 210 | ext := filepath.Ext(cfg.RequestFile) 211 | if len(ext) > 0 && ext[0] == '.' { 212 | ext = ext[1:] 213 | } 214 | dm, ok := iocodec.DefaultDecoders[ext] 215 | if !ok { 216 | return fmt.Errorf("invalid request file format: %q", ext) 217 | } 218 | d = dm.NewDecoder(f) 219 | } else { 220 | d = iocodec.DefaultDecoders["noop"].NewDecoder(os.Stdin) 221 | } 222 | conn, client, err := _DialBank() 223 | if err != nil { 224 | return err 225 | } 226 | defer conn.Close() 227 | return fn(client, d, em.NewEncoder(os.Stdout)) 228 | } 229 | 230 | func _BankDepositClientCommand() *cobra.Command { 231 | reqArgs := &DepositRequest{ 232 | ClusterWithNamespaces: &DepositRequest_ClusterWithNamespaces{ 233 | Cluster: &Cluster{}, 234 | Namespaces: []*DepositRequest_NamespaceWithDeployments{}, 235 | }, 236 | Clusters: []*DepositRequest_ClusterWithNamespaces{}, 237 | } 238 | 239 | cmd := &cobra.Command{ 240 | Use: "deposit", 241 | Long: "Deposit client; call by piping a request in to stdin (--stdin), reading a file (--file), or via flags per field", 242 | Example: "TODO: print protobuf method comments here", 243 | Run: func(cmd *cobra.Command, args []string) { 244 | var v DepositRequest 245 | err := _BankRoundTrip(v, func(cli BankClient, in iocodec.Decoder, out iocodec.Encoder) error { 246 | 247 | err := in.Decode(&v) 248 | if err != nil { 249 | return err 250 | } 251 | 252 | proto.Merge(&v, reqArgs) 253 | resp, err := cli.Deposit(context.Background(), &v) 254 | 255 | if err != nil { 256 | return err 257 | } 258 | 259 | return out.Encode(resp) 260 | 261 | }) 262 | if err != nil { 263 | log.Fatal(err) 264 | } 265 | }, 266 | } 267 | 268 | cmd.PersistentFlags().StringVar(&reqArgs.Parent, "parent", "", "get-comment-from-proto") 269 | cmd.PersistentFlags().StringVar(&reqArgs.Tenant, "tenant", "", "get-comment-from-proto") 270 | cmd.PersistentFlags().StringVar(&reqArgs.Environment, "environment", "", "get-comment-from-proto") 271 | cmd.PersistentFlags() // Warning: list flags are not yet supported (field "Clusters") 272 | cmd.PersistentFlags() // Warning: list flags are not yet supported (field "Namespaces") 273 | 274 | return cmd 275 | } 276 | 277 | var _BankClientSubCommands = []func() *cobra.Command{ 278 | _BankDepositClientCommand, 279 | } 280 | -------------------------------------------------------------------------------- /client/args.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "sort" 8 | "strings" 9 | 10 | pb "github.com/golang/protobuf/protoc-gen-go/descriptor" 11 | 12 | "github.com/tetratelabs/protoc-gen-cobra/generator" 13 | ) 14 | 15 | type protoTypeCache map[string]entry 16 | type entry struct { 17 | d *pb.DescriptorProto 18 | f, n bool 19 | } 20 | 21 | func (p protoTypeCache) byName(desc []*pb.DescriptorProto, name string, log func(...interface{})) (*pb.DescriptorProto, bool, bool) { 22 | return byName(p, desc, name, false, log) 23 | } 24 | 25 | func byName(p protoTypeCache, desc []*pb.DescriptorProto, name string, nested bool, log func(...interface{})) (*pb.DescriptorProto, bool, bool) { 26 | log("searching for ", name) 27 | if entry, found := p[name]; found { 28 | log("* found ", entry.d.GetName(), "in cache ", fmt.Sprintf("%v", p)) 29 | return entry.d, entry.f, entry.n 30 | } 31 | 32 | for _, d := range desc { 33 | if d.GetName() == name { 34 | p[name] = entry{d, true, nested} 35 | log("* comparing against ", d.GetName(), " inserting into cache: \n// ", fmt.Sprintf("%v", p)) 36 | return d, true, nested 37 | } else { 38 | log(" comparing against ", d.GetName()) 39 | } 40 | if desc, found, _ := byName(p, d.NestedType, name, true, prefix(" ", log)); found { 41 | return desc, found, true 42 | } 43 | } 44 | return nil, false, false 45 | } 46 | 47 | func prefix(pre string, l func(...interface{})) func(...interface{}) { 48 | return func(i ...interface{}) { l(append([]interface{}{pre}, i...)...) } 49 | } 50 | 51 | func noop(...interface{}) {} 52 | 53 | // first return is the instantiation of the struct and fields that are messages; second is the set of 54 | // flag declarations using the fields of the struct to receive values 55 | func (c *client) generateRequestFlags(file *generator.FileDescriptor, d *pb.DescriptorProto, types protoTypeCache) (string, []string) { 56 | if d == nil { 57 | return "", []string{} 58 | } 59 | flags := c.generateSubMessageRequestFlags("reqArgs", "", d, file, types) 60 | initialize := c.generateRequestInitialization(d, file, types) 61 | return initialize, flags 62 | } 63 | 64 | func (c *client) generateSubMessageRequestFlags(objectName, flagPrefix string, d *pb.DescriptorProto, file *generator.FileDescriptor, types protoTypeCache) []string { 65 | out := make([]string, 0, len(d.Field)) 66 | 67 | for _, f := range d.Field { 68 | fieldName := goFieldName(f) 69 | fieldFlagName := strings.ToLower(fieldName) 70 | if f.GetLabel() == pb.FieldDescriptorProto_LABEL_REPEATED { 71 | // TODO 72 | out = append(out, fmt.Sprintf(`.PersistentFlags() // Warning: list flags are not yet supported (field %q)`, fieldName)) 73 | continue 74 | } 75 | 76 | switch f.GetType() { 77 | // Field is a complex type (another message, or an enum) 78 | case pb.FieldDescriptorProto_TYPE_MESSAGE: 79 | // if both type and name are set, descriptor must be either a message or enum 80 | _, _, ttype := inputNames(f.GetTypeName()) 81 | if fdesc, found, _ := types.byName(file.MessageType, ttype, noop /*prefix("// ", c.P)*/); found { 82 | if fdesc.GetOptions().GetMapEntry() { 83 | // TODO 84 | return []string{fmt.Sprintf(`.PersistentFlags() // Warning: map flags are not yet supported (message %q)`, d.GetName())} 85 | } 86 | 87 | flags := c.generateSubMessageRequestFlags(objectName+"."+fieldName, flagPrefix+fieldFlagName+"-", fdesc, file, types) 88 | out = append(out, flags...) 89 | } 90 | case pb.FieldDescriptorProto_TYPE_ENUM: 91 | // TODO 92 | case pb.FieldDescriptorProto_TYPE_STRING: 93 | out = append(out, fmt.Sprintf(`.PersistentFlags().StringVar(&%s.%s, "%s%s", "", "%s")`, 94 | objectName, fieldName, flagPrefix, fieldFlagName, "get-comment-from-proto")) 95 | case pb.FieldDescriptorProto_TYPE_BYTES: 96 | out = append(out, fmt.Sprintf(`.PersistentFlags().BytesBase64Var(&%s.%s, "%s%s", []byte{}, "%s")`, 97 | objectName, fieldName, flagPrefix, fieldFlagName, "get-comment-from-proto")) 98 | case pb.FieldDescriptorProto_TYPE_BOOL: 99 | out = append(out, fmt.Sprintf(`.PersistentFlags().BoolVar(&%s.%s, "%s%s", false, "%s")`, 100 | objectName, fieldName, flagPrefix, fieldFlagName, "get-comment-from-proto")) 101 | case pb.FieldDescriptorProto_TYPE_FLOAT: 102 | out = append(out, fmt.Sprintf(`.PersistentFlags().Float32Var(&%s.%s, "%s%s", 0, "%s")`, 103 | objectName, fieldName, flagPrefix, fieldFlagName, "get-comment-from-proto")) 104 | case pb.FieldDescriptorProto_TYPE_DOUBLE: 105 | out = append(out, fmt.Sprintf(`.PersistentFlags().Float64Var(&%s.%s, "%s%s", 0, "%s")`, 106 | objectName, fieldName, flagPrefix, fieldFlagName, "get-comment-from-proto")) 107 | case pb.FieldDescriptorProto_TYPE_INT32: 108 | out = append(out, fmt.Sprintf(`.PersistentFlags().Int32Var(&%s.%s, "%s%s", 0, "%s")`, 109 | objectName, fieldName, flagPrefix, fieldFlagName, "get-comment-from-proto")) 110 | case pb.FieldDescriptorProto_TYPE_FIXED32: 111 | out = append(out, fmt.Sprintf(`.PersistentFlags().Int32Var(&%s.%s, "%s%s", 0, "%s")`, 112 | objectName, fieldName, flagPrefix, fieldFlagName, "get-comment-from-proto")) 113 | case pb.FieldDescriptorProto_TYPE_SFIXED32: 114 | out = append(out, fmt.Sprintf(`.PersistentFlags().Int32Var(&%s.%s, "%s%s", 0, "%s")`, 115 | objectName, fieldName, flagPrefix, fieldFlagName, "get-comment-from-proto")) 116 | case pb.FieldDescriptorProto_TYPE_SINT32: 117 | out = append(out, fmt.Sprintf(`.PersistentFlags().Int32Var(&%s.%s, "%s%s", 0, "%s")`, 118 | objectName, fieldName, flagPrefix, fieldFlagName, "get-comment-from-proto")) 119 | case pb.FieldDescriptorProto_TYPE_UINT32: 120 | out = append(out, fmt.Sprintf(`.PersistentFlags().Uint32Var(&%s.%s, "%s%s", 0, "%s")`, 121 | objectName, fieldName, flagPrefix, fieldFlagName, "get-comment-from-proto")) 122 | case pb.FieldDescriptorProto_TYPE_INT64: 123 | out = append(out, fmt.Sprintf(`.PersistentFlags().Int64Var(&%s.%s, "%s%s", 0, "%s")`, 124 | objectName, fieldName, flagPrefix, fieldFlagName, "get-comment-from-proto")) 125 | case pb.FieldDescriptorProto_TYPE_FIXED64: 126 | out = append(out, fmt.Sprintf(`.PersistentFlags().Int64Var(&%s.%s, "%s%s", 0, "%s")`, 127 | objectName, fieldName, flagPrefix, fieldFlagName, "get-comment-from-proto")) 128 | case pb.FieldDescriptorProto_TYPE_SFIXED64: 129 | out = append(out, fmt.Sprintf(`.PersistentFlags().Int64Var(&%s.%s, "%s%s", 0, "%s")`, 130 | objectName, fieldName, flagPrefix, fieldFlagName, "get-comment-from-proto")) 131 | case pb.FieldDescriptorProto_TYPE_SINT64: 132 | out = append(out, fmt.Sprintf(`.PersistentFlags().Int64Var(&%s.%s, "%s%s", 0, "%s")`, 133 | objectName, fieldName, flagPrefix, fieldFlagName, "get-comment-from-proto")) 134 | case pb.FieldDescriptorProto_TYPE_UINT64: 135 | out = append(out, fmt.Sprintf(`.PersistentFlags().Uint64Var(&%s.%s, "%s%s", 0, "%s")`, 136 | objectName, fieldName, flagPrefix, fieldFlagName, "get-comment-from-proto")) 137 | 138 | case pb.FieldDescriptorProto_TYPE_GROUP: 139 | default: 140 | } 141 | } 142 | return out 143 | } 144 | 145 | func goFieldName(f *pb.FieldDescriptorProto) string { 146 | fieldName := f.GetJsonName() 147 | if fieldName != "" { 148 | fieldName = strings.ToUpper(string(fieldName[0])) + fieldName[1:] 149 | } 150 | return fieldName 151 | } 152 | 153 | func (c *client) generateRequestInitialization(d *pb.DescriptorProto, file *generator.FileDescriptor, types protoTypeCache) string { 154 | debug := &bytes.Buffer{} 155 | initialize := genReqInit(d, file, types, "", false, debug, noop /*prefix("// ", c.P)*/) 156 | // c.P(debug.String()) 157 | return initialize 158 | } 159 | 160 | func genReqInit(d *pb.DescriptorProto, file *generator.FileDescriptor, types protoTypeCache, typePrefix string, repeated bool, w io.Writer, log func(...interface{})) string { 161 | if repeated { 162 | // if we're repeated, we only want to compute the type then bail, we won't figure out if we're trying to create an instance 163 | out := fmt.Sprintf("[]*%s%s{}", typePrefix, d.GetName()) 164 | fmt.Fprintf(w, "// computed %q\n", out) 165 | return out 166 | } 167 | 168 | fields := make(map[string]string) 169 | fmt.Fprintf(w, "// generating initialization for %s with prefix %q which has %d fields\n", d.GetName(), typePrefix, len(d.Field)) 170 | for _, f := range d.Field { 171 | switch f.GetType() { 172 | case pb.FieldDescriptorProto_TYPE_MESSAGE: 173 | _, _, ttype := inputNames(f.GetTypeName()) 174 | desc, found, nested := types.byName(file.MessageType, ttype, log) 175 | fmt.Fprintf(w, "// searching for type %q with ttype %q for field %q\n", f.GetTypeName(), ttype, f.GetName()) 176 | if !found { 177 | fmt.Fprint(w, "// not found, skipping\n") 178 | continue 179 | } 180 | 181 | if desc.GetOptions().GetMapEntry() { 182 | fmt.Fprintf(w, "// skipping map fields, which do not need to be initialized") 183 | continue 184 | } 185 | 186 | prefix := typePrefix 187 | if nested { 188 | for _, df := range d.Field { 189 | if strings.Contains(fmt.Sprintf(".%s.", df.GetTypeName()), d.GetName()) { 190 | prefix += d.GetName() + "_" 191 | break 192 | } 193 | } 194 | } else { 195 | prefix = "" 196 | } 197 | 198 | fmt.Fprintf(w, "// found, recursing with %q\n", desc.GetName()) 199 | m := genReqInit(desc, file, types, prefix, listField(f), w, log) 200 | fmt.Fprintf(w, "// found field %q which we'll initialize with %q\n", goFieldName(f), m) 201 | fields[goFieldName(f)] = m 202 | default: 203 | fmt.Fprintf(w, "// found non-message field %q\n", f.GetName()) 204 | } 205 | } 206 | 207 | // This needs to be consistent. 208 | keys := make([]string, 0, len(fields)) 209 | for k := range fields { 210 | keys = append(keys, k) 211 | } 212 | sort.Strings(keys) 213 | 214 | vals := make([]string, 0, len(keys)) 215 | for _, k := range keys { 216 | vals = append(vals, k+": "+fields[k]) 217 | } 218 | values := "{}" 219 | if len(vals) > 0 { 220 | values = fmt.Sprintf("{\n%s,\n}", strings.Join(vals, ",\n")) 221 | } 222 | 223 | prefix := fmt.Sprintf("&%s%s", typePrefix, d.GetName()) 224 | 225 | out := prefix + values 226 | fmt.Fprintf(w, "// computed %q\n", out) 227 | return out 228 | } 229 | 230 | func listField(d *pb.FieldDescriptorProto) bool { 231 | return d.GetLabel() == pb.FieldDescriptorProto_LABEL_REPEATED 232 | } 233 | -------------------------------------------------------------------------------- /example/pb/nested.cobra.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by tetratelabs/protoc-gen-cobra. 2 | // source: nested.proto 3 | // DO NOT EDIT! 4 | 5 | package pb 6 | 7 | import ( 8 | tls "crypto/tls" 9 | x509 "crypto/x509" 10 | fmt "fmt" 11 | ioutil "io/ioutil" 12 | log "log" 13 | net "net" 14 | os "os" 15 | filepath "path/filepath" 16 | time "time" 17 | 18 | proto "github.com/golang/protobuf/proto" 19 | cobra "github.com/spf13/cobra" 20 | pflag "github.com/spf13/pflag" 21 | iocodec "github.com/tetratelabs/protoc-gen-cobra/iocodec" 22 | context "golang.org/x/net/context" 23 | oauth2 "golang.org/x/oauth2" 24 | grpc "google.golang.org/grpc" 25 | credentials "google.golang.org/grpc/credentials" 26 | oauth "google.golang.org/grpc/credentials/oauth" 27 | ) 28 | 29 | // This is a compile-time assertion to ensure that this generated file 30 | // is compatible with the grpc package it is being compiled against. 31 | const _ = grpc.SupportPackageIsVersion4 32 | 33 | var _DefaultNestedMessagesClientCommandConfig = _NewNestedMessagesClientCommandConfig() 34 | 35 | type _NestedMessagesClientCommandConfig struct { 36 | ServerAddr string 37 | RequestFile string 38 | Stdin bool 39 | PrintSampleRequest bool 40 | ResponseFormat string 41 | Timeout time.Duration 42 | TLS bool 43 | ServerName string 44 | InsecureSkipVerify bool 45 | CACertFile string 46 | CertFile string 47 | KeyFile string 48 | AuthToken string 49 | AuthTokenType string 50 | JWTKey string 51 | JWTKeyFile string 52 | } 53 | 54 | func _NewNestedMessagesClientCommandConfig() *_NestedMessagesClientCommandConfig { 55 | c := &_NestedMessagesClientCommandConfig{ 56 | ServerAddr: "localhost:8080", 57 | ResponseFormat: "json", 58 | Timeout: 10 * time.Second, 59 | AuthTokenType: "Bearer", 60 | } 61 | return c 62 | } 63 | 64 | func (o *_NestedMessagesClientCommandConfig) AddFlags(fs *pflag.FlagSet) { 65 | fs.StringVarP(&o.ServerAddr, "server-addr", "s", o.ServerAddr, "server address in form of host:port") 66 | fs.StringVarP(&o.RequestFile, "request-file", "f", o.RequestFile, "client request file (must be json, yaml, or xml); use \"-\" for stdin + json") 67 | fs.BoolVar(&o.Stdin, "stdin", o.Stdin, "read client request from STDIN; alternative for '-f -'") 68 | fs.BoolVarP(&o.PrintSampleRequest, "print-sample-request", "p", o.PrintSampleRequest, "print sample request file and exit") 69 | fs.StringVarP(&o.ResponseFormat, "response-format", "o", o.ResponseFormat, "response format (json, prettyjson, yaml, or xml)") 70 | fs.DurationVar(&o.Timeout, "timeout", o.Timeout, "client connection timeout") 71 | fs.BoolVar(&o.TLS, "tls", o.TLS, "enable tls") 72 | fs.StringVar(&o.ServerName, "tls-server-name", o.ServerName, "tls server name override") 73 | fs.BoolVar(&o.InsecureSkipVerify, "tls-insecure-skip-verify", o.InsecureSkipVerify, "INSECURE: skip tls checks") 74 | fs.StringVar(&o.CACertFile, "tls-ca-cert-file", o.CACertFile, "ca certificate file") 75 | fs.StringVar(&o.CertFile, "tls-cert-file", o.CertFile, "client certificate file") 76 | fs.StringVar(&o.KeyFile, "tls-key-file", o.KeyFile, "client key file") 77 | fs.StringVar(&o.AuthToken, "auth-token", o.AuthToken, "authorization token") 78 | fs.StringVar(&o.AuthTokenType, "auth-token-type", o.AuthTokenType, "authorization token type") 79 | fs.StringVar(&o.JWTKey, "jwt-key", o.JWTKey, "jwt key") 80 | fs.StringVar(&o.JWTKeyFile, "jwt-key-file", o.JWTKeyFile, "jwt key file") 81 | } 82 | 83 | func NestedMessagesClientCommand() *cobra.Command { 84 | cmd := &cobra.Command{ 85 | Use: "nestedmessages", 86 | } 87 | _DefaultNestedMessagesClientCommandConfig.AddFlags(cmd.PersistentFlags()) 88 | 89 | for _, s := range _NestedMessagesClientSubCommands { 90 | cmd.AddCommand(s()) 91 | } 92 | return cmd 93 | } 94 | 95 | func _DialNestedMessages() (*grpc.ClientConn, NestedMessagesClient, error) { 96 | cfg := _DefaultNestedMessagesClientCommandConfig 97 | opts := []grpc.DialOption{ 98 | grpc.WithBlock(), 99 | grpc.WithTimeout(cfg.Timeout), 100 | } 101 | if cfg.TLS { 102 | tlsConfig := &tls.Config{} 103 | if cfg.InsecureSkipVerify { 104 | tlsConfig.InsecureSkipVerify = true 105 | } 106 | if cfg.CACertFile != "" { 107 | cacert, err := ioutil.ReadFile(cfg.CACertFile) 108 | if err != nil { 109 | return nil, nil, fmt.Errorf("ca cert: %v", err) 110 | } 111 | certpool := x509.NewCertPool() 112 | certpool.AppendCertsFromPEM(cacert) 113 | tlsConfig.RootCAs = certpool 114 | } 115 | if cfg.CertFile != "" { 116 | if cfg.KeyFile == "" { 117 | return nil, nil, fmt.Errorf("missing key file") 118 | } 119 | pair, err := tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile) 120 | if err != nil { 121 | return nil, nil, fmt.Errorf("cert/key: %v", err) 122 | } 123 | tlsConfig.Certificates = []tls.Certificate{pair} 124 | } 125 | if cfg.ServerName != "" { 126 | tlsConfig.ServerName = cfg.ServerName 127 | } else { 128 | addr, _, _ := net.SplitHostPort(cfg.ServerAddr) 129 | tlsConfig.ServerName = addr 130 | } 131 | //tlsConfig.BuildNameToCertificate() 132 | cred := credentials.NewTLS(tlsConfig) 133 | opts = append(opts, grpc.WithTransportCredentials(cred)) 134 | } else { 135 | opts = append(opts, grpc.WithInsecure()) 136 | } 137 | if cfg.AuthToken != "" { 138 | cred := oauth.NewOauthAccess(&oauth2.Token{ 139 | AccessToken: cfg.AuthToken, 140 | TokenType: cfg.AuthTokenType, 141 | }) 142 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 143 | } 144 | if cfg.JWTKey != "" { 145 | cred, err := oauth.NewJWTAccessFromKey([]byte(cfg.JWTKey)) 146 | if err != nil { 147 | return nil, nil, fmt.Errorf("jwt key: %v", err) 148 | } 149 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 150 | } 151 | if cfg.JWTKeyFile != "" { 152 | cred, err := oauth.NewJWTAccessFromFile(cfg.JWTKeyFile) 153 | if err != nil { 154 | return nil, nil, fmt.Errorf("jwt key file: %v", err) 155 | } 156 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 157 | } 158 | conn, err := grpc.Dial(cfg.ServerAddr, opts...) 159 | if err != nil { 160 | return nil, nil, err 161 | } 162 | return conn, NewNestedMessagesClient(conn), nil 163 | } 164 | 165 | type _NestedMessagesRoundTripFunc func(cli NestedMessagesClient, in iocodec.Decoder, out iocodec.Encoder) error 166 | 167 | func _NestedMessagesRoundTrip(sample interface{}, fn _NestedMessagesRoundTripFunc) error { 168 | cfg := _DefaultNestedMessagesClientCommandConfig 169 | var em iocodec.EncoderMaker 170 | var ok bool 171 | if cfg.ResponseFormat == "" { 172 | em = iocodec.DefaultEncoders["json"] 173 | } else { 174 | em, ok = iocodec.DefaultEncoders[cfg.ResponseFormat] 175 | if !ok { 176 | return fmt.Errorf("invalid response format: %q", cfg.ResponseFormat) 177 | } 178 | } 179 | if cfg.PrintSampleRequest { 180 | return em.NewEncoder(os.Stdout).Encode(sample) 181 | } 182 | // read the input request, first from stdin, then from a file, otherwise from args only 183 | var d iocodec.Decoder 184 | if cfg.Stdin || cfg.RequestFile == "-" { 185 | d = iocodec.DefaultDecoders["json"].NewDecoder(os.Stdin) 186 | } else if cfg.RequestFile != "" { 187 | f, err := os.Open(cfg.RequestFile) 188 | if err != nil { 189 | return fmt.Errorf("request file: %v", err) 190 | } 191 | defer f.Close() 192 | ext := filepath.Ext(cfg.RequestFile) 193 | if len(ext) > 0 && ext[0] == '.' { 194 | ext = ext[1:] 195 | } 196 | dm, ok := iocodec.DefaultDecoders[ext] 197 | if !ok { 198 | return fmt.Errorf("invalid request file format: %q", ext) 199 | } 200 | d = dm.NewDecoder(f) 201 | } else { 202 | d = iocodec.DefaultDecoders["noop"].NewDecoder(os.Stdin) 203 | } 204 | conn, client, err := _DialNestedMessages() 205 | if err != nil { 206 | return err 207 | } 208 | defer conn.Close() 209 | return fn(client, d, em.NewEncoder(os.Stdout)) 210 | } 211 | 212 | func _NestedMessagesGetClientCommand() *cobra.Command { 213 | reqArgs := &NestedRequest{ 214 | Inner: &NestedRequest_InnerNestedType{}, 215 | TopLevel: &TopLevelNestedType{}, 216 | } 217 | 218 | cmd := &cobra.Command{ 219 | Use: "get", 220 | Long: "Get client; call by piping a request in to stdin (--stdin), reading a file (--file), or via flags per field", 221 | Example: "TODO: print protobuf method comments here", 222 | Run: func(cmd *cobra.Command, args []string) { 223 | var v NestedRequest 224 | err := _NestedMessagesRoundTrip(v, func(cli NestedMessagesClient, in iocodec.Decoder, out iocodec.Encoder) error { 225 | 226 | err := in.Decode(&v) 227 | if err != nil { 228 | return err 229 | } 230 | 231 | proto.Merge(&v, reqArgs) 232 | resp, err := cli.Get(context.Background(), &v) 233 | 234 | if err != nil { 235 | return err 236 | } 237 | 238 | return out.Encode(resp) 239 | 240 | }) 241 | if err != nil { 242 | log.Fatal(err) 243 | } 244 | }, 245 | } 246 | 247 | cmd.PersistentFlags().StringVar(&reqArgs.Inner.Value, "inner-value", "", "get-comment-from-proto") 248 | cmd.PersistentFlags().StringVar(&reqArgs.TopLevel.Value, "toplevel-value", "", "get-comment-from-proto") 249 | 250 | return cmd 251 | } 252 | 253 | func _NestedMessagesGetDeeplyNestedClientCommand() *cobra.Command { 254 | reqArgs := &DeeplyNested{ 255 | L0: &DeeplyNested_DeeplyNestedOuter{ 256 | L1: &DeeplyNested_DeeplyNestedOuter_DeeplyNestedInner{ 257 | L2: &DeeplyNested_DeeplyNestedOuter_DeeplyNestedInner_DeeplyNestedInnermost{}, 258 | }, 259 | }, 260 | } 261 | 262 | cmd := &cobra.Command{ 263 | Use: "getdeeplynested", 264 | Long: "GetDeeplyNested client; call by piping a request in to stdin (--stdin), reading a file (--file), or via flags per field", 265 | Example: "TODO: print protobuf method comments here", 266 | Run: func(cmd *cobra.Command, args []string) { 267 | var v DeeplyNested 268 | err := _NestedMessagesRoundTrip(v, func(cli NestedMessagesClient, in iocodec.Decoder, out iocodec.Encoder) error { 269 | 270 | err := in.Decode(&v) 271 | if err != nil { 272 | return err 273 | } 274 | 275 | proto.Merge(&v, reqArgs) 276 | resp, err := cli.GetDeeplyNested(context.Background(), &v) 277 | 278 | if err != nil { 279 | return err 280 | } 281 | 282 | return out.Encode(resp) 283 | 284 | }) 285 | if err != nil { 286 | log.Fatal(err) 287 | } 288 | }, 289 | } 290 | 291 | cmd.PersistentFlags().StringVar(&reqArgs.L0.L1.L2.L3, "l0-l1-l2-l3", "", "get-comment-from-proto") 292 | 293 | return cmd 294 | } 295 | 296 | var _NestedMessagesClientSubCommands = []func() *cobra.Command{ 297 | _NestedMessagesGetClientCommand, 298 | _NestedMessagesGetDeeplyNestedClientCommand, 299 | } 300 | -------------------------------------------------------------------------------- /example/pb/crud.cobra.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by tetratelabs/protoc-gen-cobra. 2 | // source: crud.proto 3 | // DO NOT EDIT! 4 | 5 | package pb 6 | 7 | import ( 8 | tls "crypto/tls" 9 | x509 "crypto/x509" 10 | fmt "fmt" 11 | ioutil "io/ioutil" 12 | log "log" 13 | net "net" 14 | os "os" 15 | filepath "path/filepath" 16 | time "time" 17 | 18 | proto "github.com/golang/protobuf/proto" 19 | cobra "github.com/spf13/cobra" 20 | pflag "github.com/spf13/pflag" 21 | iocodec "github.com/tetratelabs/protoc-gen-cobra/iocodec" 22 | context "golang.org/x/net/context" 23 | oauth2 "golang.org/x/oauth2" 24 | grpc "google.golang.org/grpc" 25 | credentials "google.golang.org/grpc/credentials" 26 | oauth "google.golang.org/grpc/credentials/oauth" 27 | ) 28 | 29 | // This is a compile-time assertion to ensure that this generated file 30 | // is compatible with the grpc package it is being compiled against. 31 | const _ = grpc.SupportPackageIsVersion4 32 | 33 | var _DefaultCRUDClientCommandConfig = _NewCRUDClientCommandConfig() 34 | 35 | type _CRUDClientCommandConfig struct { 36 | ServerAddr string 37 | RequestFile string 38 | Stdin bool 39 | PrintSampleRequest bool 40 | ResponseFormat string 41 | Timeout time.Duration 42 | TLS bool 43 | ServerName string 44 | InsecureSkipVerify bool 45 | CACertFile string 46 | CertFile string 47 | KeyFile string 48 | AuthToken string 49 | AuthTokenType string 50 | JWTKey string 51 | JWTKeyFile string 52 | } 53 | 54 | func _NewCRUDClientCommandConfig() *_CRUDClientCommandConfig { 55 | c := &_CRUDClientCommandConfig{ 56 | ServerAddr: "localhost:8080", 57 | ResponseFormat: "json", 58 | Timeout: 10 * time.Second, 59 | AuthTokenType: "Bearer", 60 | } 61 | return c 62 | } 63 | 64 | func (o *_CRUDClientCommandConfig) AddFlags(fs *pflag.FlagSet) { 65 | fs.StringVarP(&o.ServerAddr, "server-addr", "s", o.ServerAddr, "server address in form of host:port") 66 | fs.StringVarP(&o.RequestFile, "request-file", "f", o.RequestFile, "client request file (must be json, yaml, or xml); use \"-\" for stdin + json") 67 | fs.BoolVar(&o.Stdin, "stdin", o.Stdin, "read client request from STDIN; alternative for '-f -'") 68 | fs.BoolVarP(&o.PrintSampleRequest, "print-sample-request", "p", o.PrintSampleRequest, "print sample request file and exit") 69 | fs.StringVarP(&o.ResponseFormat, "response-format", "o", o.ResponseFormat, "response format (json, prettyjson, yaml, or xml)") 70 | fs.DurationVar(&o.Timeout, "timeout", o.Timeout, "client connection timeout") 71 | fs.BoolVar(&o.TLS, "tls", o.TLS, "enable tls") 72 | fs.StringVar(&o.ServerName, "tls-server-name", o.ServerName, "tls server name override") 73 | fs.BoolVar(&o.InsecureSkipVerify, "tls-insecure-skip-verify", o.InsecureSkipVerify, "INSECURE: skip tls checks") 74 | fs.StringVar(&o.CACertFile, "tls-ca-cert-file", o.CACertFile, "ca certificate file") 75 | fs.StringVar(&o.CertFile, "tls-cert-file", o.CertFile, "client certificate file") 76 | fs.StringVar(&o.KeyFile, "tls-key-file", o.KeyFile, "client key file") 77 | fs.StringVar(&o.AuthToken, "auth-token", o.AuthToken, "authorization token") 78 | fs.StringVar(&o.AuthTokenType, "auth-token-type", o.AuthTokenType, "authorization token type") 79 | fs.StringVar(&o.JWTKey, "jwt-key", o.JWTKey, "jwt key") 80 | fs.StringVar(&o.JWTKeyFile, "jwt-key-file", o.JWTKeyFile, "jwt key file") 81 | } 82 | 83 | func CRUDClientCommand() *cobra.Command { 84 | cmd := &cobra.Command{ 85 | Use: "crud", 86 | } 87 | _DefaultCRUDClientCommandConfig.AddFlags(cmd.PersistentFlags()) 88 | 89 | for _, s := range _CRUDClientSubCommands { 90 | cmd.AddCommand(s()) 91 | } 92 | return cmd 93 | } 94 | 95 | func _DialCRUD() (*grpc.ClientConn, CRUDClient, error) { 96 | cfg := _DefaultCRUDClientCommandConfig 97 | opts := []grpc.DialOption{ 98 | grpc.WithBlock(), 99 | grpc.WithTimeout(cfg.Timeout), 100 | } 101 | if cfg.TLS { 102 | tlsConfig := &tls.Config{} 103 | if cfg.InsecureSkipVerify { 104 | tlsConfig.InsecureSkipVerify = true 105 | } 106 | if cfg.CACertFile != "" { 107 | cacert, err := ioutil.ReadFile(cfg.CACertFile) 108 | if err != nil { 109 | return nil, nil, fmt.Errorf("ca cert: %v", err) 110 | } 111 | certpool := x509.NewCertPool() 112 | certpool.AppendCertsFromPEM(cacert) 113 | tlsConfig.RootCAs = certpool 114 | } 115 | if cfg.CertFile != "" { 116 | if cfg.KeyFile == "" { 117 | return nil, nil, fmt.Errorf("missing key file") 118 | } 119 | pair, err := tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile) 120 | if err != nil { 121 | return nil, nil, fmt.Errorf("cert/key: %v", err) 122 | } 123 | tlsConfig.Certificates = []tls.Certificate{pair} 124 | } 125 | if cfg.ServerName != "" { 126 | tlsConfig.ServerName = cfg.ServerName 127 | } else { 128 | addr, _, _ := net.SplitHostPort(cfg.ServerAddr) 129 | tlsConfig.ServerName = addr 130 | } 131 | //tlsConfig.BuildNameToCertificate() 132 | cred := credentials.NewTLS(tlsConfig) 133 | opts = append(opts, grpc.WithTransportCredentials(cred)) 134 | } else { 135 | opts = append(opts, grpc.WithInsecure()) 136 | } 137 | if cfg.AuthToken != "" { 138 | cred := oauth.NewOauthAccess(&oauth2.Token{ 139 | AccessToken: cfg.AuthToken, 140 | TokenType: cfg.AuthTokenType, 141 | }) 142 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 143 | } 144 | if cfg.JWTKey != "" { 145 | cred, err := oauth.NewJWTAccessFromKey([]byte(cfg.JWTKey)) 146 | if err != nil { 147 | return nil, nil, fmt.Errorf("jwt key: %v", err) 148 | } 149 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 150 | } 151 | if cfg.JWTKeyFile != "" { 152 | cred, err := oauth.NewJWTAccessFromFile(cfg.JWTKeyFile) 153 | if err != nil { 154 | return nil, nil, fmt.Errorf("jwt key file: %v", err) 155 | } 156 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 157 | } 158 | conn, err := grpc.Dial(cfg.ServerAddr, opts...) 159 | if err != nil { 160 | return nil, nil, err 161 | } 162 | return conn, NewCRUDClient(conn), nil 163 | } 164 | 165 | type _CRUDRoundTripFunc func(cli CRUDClient, in iocodec.Decoder, out iocodec.Encoder) error 166 | 167 | func _CRUDRoundTrip(sample interface{}, fn _CRUDRoundTripFunc) error { 168 | cfg := _DefaultCRUDClientCommandConfig 169 | var em iocodec.EncoderMaker 170 | var ok bool 171 | if cfg.ResponseFormat == "" { 172 | em = iocodec.DefaultEncoders["json"] 173 | } else { 174 | em, ok = iocodec.DefaultEncoders[cfg.ResponseFormat] 175 | if !ok { 176 | return fmt.Errorf("invalid response format: %q", cfg.ResponseFormat) 177 | } 178 | } 179 | if cfg.PrintSampleRequest { 180 | return em.NewEncoder(os.Stdout).Encode(sample) 181 | } 182 | // read the input request, first from stdin, then from a file, otherwise from args only 183 | var d iocodec.Decoder 184 | if cfg.Stdin || cfg.RequestFile == "-" { 185 | d = iocodec.DefaultDecoders["json"].NewDecoder(os.Stdin) 186 | } else if cfg.RequestFile != "" { 187 | f, err := os.Open(cfg.RequestFile) 188 | if err != nil { 189 | return fmt.Errorf("request file: %v", err) 190 | } 191 | defer f.Close() 192 | ext := filepath.Ext(cfg.RequestFile) 193 | if len(ext) > 0 && ext[0] == '.' { 194 | ext = ext[1:] 195 | } 196 | dm, ok := iocodec.DefaultDecoders[ext] 197 | if !ok { 198 | return fmt.Errorf("invalid request file format: %q", ext) 199 | } 200 | d = dm.NewDecoder(f) 201 | } else { 202 | d = iocodec.DefaultDecoders["noop"].NewDecoder(os.Stdin) 203 | } 204 | conn, client, err := _DialCRUD() 205 | if err != nil { 206 | return err 207 | } 208 | defer conn.Close() 209 | return fn(client, d, em.NewEncoder(os.Stdout)) 210 | } 211 | 212 | func _CRUDCreateClientCommand() *cobra.Command { 213 | reqArgs := &CreateCRUD{} 214 | 215 | cmd := &cobra.Command{ 216 | Use: "create", 217 | Long: "Create client; call by piping a request in to stdin (--stdin), reading a file (--file), or via flags per field", 218 | Example: "TODO: print protobuf method comments here", 219 | Run: func(cmd *cobra.Command, args []string) { 220 | var v CreateCRUD 221 | err := _CRUDRoundTrip(v, func(cli CRUDClient, in iocodec.Decoder, out iocodec.Encoder) error { 222 | 223 | err := in.Decode(&v) 224 | if err != nil { 225 | return err 226 | } 227 | 228 | proto.Merge(&v, reqArgs) 229 | resp, err := cli.Create(context.Background(), &v) 230 | 231 | if err != nil { 232 | return err 233 | } 234 | 235 | return out.Encode(resp) 236 | 237 | }) 238 | if err != nil { 239 | log.Fatal(err) 240 | } 241 | }, 242 | } 243 | 244 | cmd.PersistentFlags().StringVar(&reqArgs.Name, "name", "", "get-comment-from-proto") 245 | cmd.PersistentFlags().StringVar(&reqArgs.Value, "value", "", "get-comment-from-proto") 246 | 247 | return cmd 248 | } 249 | 250 | func _CRUDGetClientCommand() *cobra.Command { 251 | reqArgs := &GetCRUD{} 252 | 253 | cmd := &cobra.Command{ 254 | Use: "get", 255 | Long: "Get client; call by piping a request in to stdin (--stdin), reading a file (--file), or via flags per field", 256 | Example: "TODO: print protobuf method comments here", 257 | Run: func(cmd *cobra.Command, args []string) { 258 | var v GetCRUD 259 | err := _CRUDRoundTrip(v, func(cli CRUDClient, in iocodec.Decoder, out iocodec.Encoder) error { 260 | 261 | err := in.Decode(&v) 262 | if err != nil { 263 | return err 264 | } 265 | 266 | proto.Merge(&v, reqArgs) 267 | resp, err := cli.Get(context.Background(), &v) 268 | 269 | if err != nil { 270 | return err 271 | } 272 | 273 | return out.Encode(resp) 274 | 275 | }) 276 | if err != nil { 277 | log.Fatal(err) 278 | } 279 | }, 280 | } 281 | 282 | cmd.PersistentFlags().StringVar(&reqArgs.Name, "name", "", "get-comment-from-proto") 283 | 284 | return cmd 285 | } 286 | 287 | func _CRUDUpdateClientCommand() *cobra.Command { 288 | reqArgs := &CRUDObject{} 289 | 290 | cmd := &cobra.Command{ 291 | Use: "update", 292 | Long: "Update client; call by piping a request in to stdin (--stdin), reading a file (--file), or via flags per field", 293 | Example: "TODO: print protobuf method comments here", 294 | Run: func(cmd *cobra.Command, args []string) { 295 | var v CRUDObject 296 | err := _CRUDRoundTrip(v, func(cli CRUDClient, in iocodec.Decoder, out iocodec.Encoder) error { 297 | 298 | err := in.Decode(&v) 299 | if err != nil { 300 | return err 301 | } 302 | 303 | proto.Merge(&v, reqArgs) 304 | resp, err := cli.Update(context.Background(), &v) 305 | 306 | if err != nil { 307 | return err 308 | } 309 | 310 | return out.Encode(resp) 311 | 312 | }) 313 | if err != nil { 314 | log.Fatal(err) 315 | } 316 | }, 317 | } 318 | 319 | cmd.PersistentFlags().StringVar(&reqArgs.Name, "name", "", "get-comment-from-proto") 320 | cmd.PersistentFlags().StringVar(&reqArgs.Value, "value", "", "get-comment-from-proto") 321 | 322 | return cmd 323 | } 324 | 325 | func _CRUDDeleteClientCommand() *cobra.Command { 326 | reqArgs := &CRUDObject{} 327 | 328 | cmd := &cobra.Command{ 329 | Use: "delete", 330 | Long: "Delete client; call by piping a request in to stdin (--stdin), reading a file (--file), or via flags per field", 331 | Example: "TODO: print protobuf method comments here", 332 | Run: func(cmd *cobra.Command, args []string) { 333 | var v CRUDObject 334 | err := _CRUDRoundTrip(v, func(cli CRUDClient, in iocodec.Decoder, out iocodec.Encoder) error { 335 | 336 | err := in.Decode(&v) 337 | if err != nil { 338 | return err 339 | } 340 | 341 | proto.Merge(&v, reqArgs) 342 | resp, err := cli.Delete(context.Background(), &v) 343 | 344 | if err != nil { 345 | return err 346 | } 347 | 348 | return out.Encode(resp) 349 | 350 | }) 351 | if err != nil { 352 | log.Fatal(err) 353 | } 354 | }, 355 | } 356 | 357 | cmd.PersistentFlags().StringVar(&reqArgs.Name, "name", "", "get-comment-from-proto") 358 | cmd.PersistentFlags().StringVar(&reqArgs.Value, "value", "", "get-comment-from-proto") 359 | 360 | return cmd 361 | } 362 | 363 | var _CRUDClientSubCommands = []func() *cobra.Command{ 364 | _CRUDCreateClientCommand, 365 | _CRUDGetClientCommand, 366 | _CRUDUpdateClientCommand, 367 | _CRUDDeleteClientCommand, 368 | } 369 | -------------------------------------------------------------------------------- /example/pb/cache.cobra.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by tetratelabs/protoc-gen-cobra. 2 | // source: cache.proto 3 | // DO NOT EDIT! 4 | 5 | package pb 6 | 7 | import ( 8 | tls "crypto/tls" 9 | x509 "crypto/x509" 10 | fmt "fmt" 11 | io "io" 12 | ioutil "io/ioutil" 13 | log "log" 14 | net "net" 15 | os "os" 16 | filepath "path/filepath" 17 | time "time" 18 | 19 | proto "github.com/golang/protobuf/proto" 20 | cobra "github.com/spf13/cobra" 21 | pflag "github.com/spf13/pflag" 22 | iocodec "github.com/tetratelabs/protoc-gen-cobra/iocodec" 23 | context "golang.org/x/net/context" 24 | oauth2 "golang.org/x/oauth2" 25 | grpc "google.golang.org/grpc" 26 | credentials "google.golang.org/grpc/credentials" 27 | oauth "google.golang.org/grpc/credentials/oauth" 28 | ) 29 | 30 | // This is a compile-time assertion to ensure that this generated file 31 | // is compatible with the grpc package it is being compiled against. 32 | const _ = grpc.SupportPackageIsVersion4 33 | 34 | var _DefaultCacheClientCommandConfig = _NewCacheClientCommandConfig() 35 | 36 | type _CacheClientCommandConfig struct { 37 | ServerAddr string 38 | RequestFile string 39 | Stdin bool 40 | PrintSampleRequest bool 41 | ResponseFormat string 42 | Timeout time.Duration 43 | TLS bool 44 | ServerName string 45 | InsecureSkipVerify bool 46 | CACertFile string 47 | CertFile string 48 | KeyFile string 49 | AuthToken string 50 | AuthTokenType string 51 | JWTKey string 52 | JWTKeyFile string 53 | } 54 | 55 | func _NewCacheClientCommandConfig() *_CacheClientCommandConfig { 56 | c := &_CacheClientCommandConfig{ 57 | ServerAddr: "localhost:8080", 58 | ResponseFormat: "json", 59 | Timeout: 10 * time.Second, 60 | AuthTokenType: "Bearer", 61 | } 62 | return c 63 | } 64 | 65 | func (o *_CacheClientCommandConfig) AddFlags(fs *pflag.FlagSet) { 66 | fs.StringVarP(&o.ServerAddr, "server-addr", "s", o.ServerAddr, "server address in form of host:port") 67 | fs.StringVarP(&o.RequestFile, "request-file", "f", o.RequestFile, "client request file (must be json, yaml, or xml); use \"-\" for stdin + json") 68 | fs.BoolVar(&o.Stdin, "stdin", o.Stdin, "read client request from STDIN; alternative for '-f -'") 69 | fs.BoolVarP(&o.PrintSampleRequest, "print-sample-request", "p", o.PrintSampleRequest, "print sample request file and exit") 70 | fs.StringVarP(&o.ResponseFormat, "response-format", "o", o.ResponseFormat, "response format (json, prettyjson, yaml, or xml)") 71 | fs.DurationVar(&o.Timeout, "timeout", o.Timeout, "client connection timeout") 72 | fs.BoolVar(&o.TLS, "tls", o.TLS, "enable tls") 73 | fs.StringVar(&o.ServerName, "tls-server-name", o.ServerName, "tls server name override") 74 | fs.BoolVar(&o.InsecureSkipVerify, "tls-insecure-skip-verify", o.InsecureSkipVerify, "INSECURE: skip tls checks") 75 | fs.StringVar(&o.CACertFile, "tls-ca-cert-file", o.CACertFile, "ca certificate file") 76 | fs.StringVar(&o.CertFile, "tls-cert-file", o.CertFile, "client certificate file") 77 | fs.StringVar(&o.KeyFile, "tls-key-file", o.KeyFile, "client key file") 78 | fs.StringVar(&o.AuthToken, "auth-token", o.AuthToken, "authorization token") 79 | fs.StringVar(&o.AuthTokenType, "auth-token-type", o.AuthTokenType, "authorization token type") 80 | fs.StringVar(&o.JWTKey, "jwt-key", o.JWTKey, "jwt key") 81 | fs.StringVar(&o.JWTKeyFile, "jwt-key-file", o.JWTKeyFile, "jwt key file") 82 | } 83 | 84 | func CacheClientCommand() *cobra.Command { 85 | cmd := &cobra.Command{ 86 | Use: "cache", 87 | } 88 | _DefaultCacheClientCommandConfig.AddFlags(cmd.PersistentFlags()) 89 | 90 | for _, s := range _CacheClientSubCommands { 91 | cmd.AddCommand(s()) 92 | } 93 | return cmd 94 | } 95 | 96 | func _DialCache() (*grpc.ClientConn, CacheClient, error) { 97 | cfg := _DefaultCacheClientCommandConfig 98 | opts := []grpc.DialOption{ 99 | grpc.WithBlock(), 100 | grpc.WithTimeout(cfg.Timeout), 101 | } 102 | if cfg.TLS { 103 | tlsConfig := &tls.Config{} 104 | if cfg.InsecureSkipVerify { 105 | tlsConfig.InsecureSkipVerify = true 106 | } 107 | if cfg.CACertFile != "" { 108 | cacert, err := ioutil.ReadFile(cfg.CACertFile) 109 | if err != nil { 110 | return nil, nil, fmt.Errorf("ca cert: %v", err) 111 | } 112 | certpool := x509.NewCertPool() 113 | certpool.AppendCertsFromPEM(cacert) 114 | tlsConfig.RootCAs = certpool 115 | } 116 | if cfg.CertFile != "" { 117 | if cfg.KeyFile == "" { 118 | return nil, nil, fmt.Errorf("missing key file") 119 | } 120 | pair, err := tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile) 121 | if err != nil { 122 | return nil, nil, fmt.Errorf("cert/key: %v", err) 123 | } 124 | tlsConfig.Certificates = []tls.Certificate{pair} 125 | } 126 | if cfg.ServerName != "" { 127 | tlsConfig.ServerName = cfg.ServerName 128 | } else { 129 | addr, _, _ := net.SplitHostPort(cfg.ServerAddr) 130 | tlsConfig.ServerName = addr 131 | } 132 | //tlsConfig.BuildNameToCertificate() 133 | cred := credentials.NewTLS(tlsConfig) 134 | opts = append(opts, grpc.WithTransportCredentials(cred)) 135 | } else { 136 | opts = append(opts, grpc.WithInsecure()) 137 | } 138 | if cfg.AuthToken != "" { 139 | cred := oauth.NewOauthAccess(&oauth2.Token{ 140 | AccessToken: cfg.AuthToken, 141 | TokenType: cfg.AuthTokenType, 142 | }) 143 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 144 | } 145 | if cfg.JWTKey != "" { 146 | cred, err := oauth.NewJWTAccessFromKey([]byte(cfg.JWTKey)) 147 | if err != nil { 148 | return nil, nil, fmt.Errorf("jwt key: %v", err) 149 | } 150 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 151 | } 152 | if cfg.JWTKeyFile != "" { 153 | cred, err := oauth.NewJWTAccessFromFile(cfg.JWTKeyFile) 154 | if err != nil { 155 | return nil, nil, fmt.Errorf("jwt key file: %v", err) 156 | } 157 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 158 | } 159 | conn, err := grpc.Dial(cfg.ServerAddr, opts...) 160 | if err != nil { 161 | return nil, nil, err 162 | } 163 | return conn, NewCacheClient(conn), nil 164 | } 165 | 166 | type _CacheRoundTripFunc func(cli CacheClient, in iocodec.Decoder, out iocodec.Encoder) error 167 | 168 | func _CacheRoundTrip(sample interface{}, fn _CacheRoundTripFunc) error { 169 | cfg := _DefaultCacheClientCommandConfig 170 | var em iocodec.EncoderMaker 171 | var ok bool 172 | if cfg.ResponseFormat == "" { 173 | em = iocodec.DefaultEncoders["json"] 174 | } else { 175 | em, ok = iocodec.DefaultEncoders[cfg.ResponseFormat] 176 | if !ok { 177 | return fmt.Errorf("invalid response format: %q", cfg.ResponseFormat) 178 | } 179 | } 180 | if cfg.PrintSampleRequest { 181 | return em.NewEncoder(os.Stdout).Encode(sample) 182 | } 183 | // read the input request, first from stdin, then from a file, otherwise from args only 184 | var d iocodec.Decoder 185 | if cfg.Stdin || cfg.RequestFile == "-" { 186 | d = iocodec.DefaultDecoders["json"].NewDecoder(os.Stdin) 187 | } else if cfg.RequestFile != "" { 188 | f, err := os.Open(cfg.RequestFile) 189 | if err != nil { 190 | return fmt.Errorf("request file: %v", err) 191 | } 192 | defer f.Close() 193 | ext := filepath.Ext(cfg.RequestFile) 194 | if len(ext) > 0 && ext[0] == '.' { 195 | ext = ext[1:] 196 | } 197 | dm, ok := iocodec.DefaultDecoders[ext] 198 | if !ok { 199 | return fmt.Errorf("invalid request file format: %q", ext) 200 | } 201 | d = dm.NewDecoder(f) 202 | } else { 203 | d = iocodec.DefaultDecoders["noop"].NewDecoder(os.Stdin) 204 | } 205 | conn, client, err := _DialCache() 206 | if err != nil { 207 | return err 208 | } 209 | defer conn.Close() 210 | return fn(client, d, em.NewEncoder(os.Stdout)) 211 | } 212 | 213 | func _CacheSetClientCommand() *cobra.Command { 214 | reqArgs := &SetRequest{} 215 | 216 | cmd := &cobra.Command{ 217 | Use: "set", 218 | Long: "Set client; call by piping a request in to stdin (--stdin), reading a file (--file), or via flags per field", 219 | Example: "TODO: print protobuf method comments here", 220 | Run: func(cmd *cobra.Command, args []string) { 221 | var v SetRequest 222 | err := _CacheRoundTrip(v, func(cli CacheClient, in iocodec.Decoder, out iocodec.Encoder) error { 223 | 224 | err := in.Decode(&v) 225 | if err != nil { 226 | return err 227 | } 228 | 229 | proto.Merge(&v, reqArgs) 230 | resp, err := cli.Set(context.Background(), &v) 231 | 232 | if err != nil { 233 | return err 234 | } 235 | 236 | return out.Encode(resp) 237 | 238 | }) 239 | if err != nil { 240 | log.Fatal(err) 241 | } 242 | }, 243 | } 244 | 245 | cmd.PersistentFlags().StringVar(&reqArgs.Key, "key", "", "get-comment-from-proto") 246 | cmd.PersistentFlags().StringVar(&reqArgs.Value, "value", "", "get-comment-from-proto") 247 | 248 | return cmd 249 | } 250 | 251 | func _CacheGetClientCommand() *cobra.Command { 252 | reqArgs := &GetRequest{} 253 | 254 | cmd := &cobra.Command{ 255 | Use: "get", 256 | Long: "Get client; call by piping a request in to stdin (--stdin), reading a file (--file), or via flags per field", 257 | Example: "TODO: print protobuf method comments here", 258 | Run: func(cmd *cobra.Command, args []string) { 259 | var v GetRequest 260 | err := _CacheRoundTrip(v, func(cli CacheClient, in iocodec.Decoder, out iocodec.Encoder) error { 261 | 262 | err := in.Decode(&v) 263 | if err != nil { 264 | return err 265 | } 266 | 267 | proto.Merge(&v, reqArgs) 268 | resp, err := cli.Get(context.Background(), &v) 269 | 270 | if err != nil { 271 | return err 272 | } 273 | 274 | return out.Encode(resp) 275 | 276 | }) 277 | if err != nil { 278 | log.Fatal(err) 279 | } 280 | }, 281 | } 282 | 283 | cmd.PersistentFlags().StringVar(&reqArgs.Key, "key", "", "get-comment-from-proto") 284 | 285 | return cmd 286 | } 287 | 288 | func _CacheMultiSetClientCommand() *cobra.Command { 289 | reqArgs := &SetRequest{} 290 | 291 | cmd := &cobra.Command{ 292 | Use: "multiset", 293 | Long: "MultiSet client; call by piping a request in to stdin (--stdin), reading a file (--file), or via flags per field", 294 | Example: "TODO: print protobuf method comments here", 295 | Run: func(cmd *cobra.Command, args []string) { 296 | var v SetRequest 297 | err := _CacheRoundTrip(v, func(cli CacheClient, in iocodec.Decoder, out iocodec.Encoder) error { 298 | 299 | stream, err := cli.MultiSet(context.Background()) 300 | if err != nil { 301 | return err 302 | } 303 | for { 304 | err = in.Decode(&v) 305 | if err == io.EOF { 306 | stream.CloseSend() 307 | break 308 | } 309 | if err != nil { 310 | return err 311 | } 312 | err = stream.Send(&v) 313 | if err != nil { 314 | return err 315 | } 316 | } 317 | 318 | resp, err := stream.CloseAndRecv() 319 | if err != nil { 320 | return err 321 | } 322 | 323 | return out.Encode(resp) 324 | 325 | }) 326 | if err != nil { 327 | log.Fatal(err) 328 | } 329 | }, 330 | } 331 | 332 | cmd.PersistentFlags().StringVar(&reqArgs.Key, "key", "", "get-comment-from-proto") 333 | cmd.PersistentFlags().StringVar(&reqArgs.Value, "value", "", "get-comment-from-proto") 334 | 335 | return cmd 336 | } 337 | 338 | func _CacheMultiGetClientCommand() *cobra.Command { 339 | reqArgs := &GetRequest{} 340 | 341 | cmd := &cobra.Command{ 342 | Use: "multiget", 343 | Long: "MultiGet client; call by piping a request in to stdin (--stdin), reading a file (--file), or via flags per field", 344 | Example: "TODO: print protobuf method comments here", 345 | Run: func(cmd *cobra.Command, args []string) { 346 | var v GetRequest 347 | err := _CacheRoundTrip(v, func(cli CacheClient, in iocodec.Decoder, out iocodec.Encoder) error { 348 | 349 | stream, err := cli.MultiGet(context.Background()) 350 | if err != nil { 351 | return err 352 | } 353 | for { 354 | err = in.Decode(&v) 355 | if err == io.EOF { 356 | stream.CloseSend() 357 | break 358 | } 359 | if err != nil { 360 | return err 361 | } 362 | err = stream.Send(&v) 363 | if err != nil { 364 | return err 365 | } 366 | } 367 | 368 | for { 369 | v, err := stream.Recv() 370 | if err == io.EOF { 371 | break 372 | } 373 | if err != nil { 374 | return err 375 | } 376 | err = out.Encode(v) 377 | if err != nil { 378 | return err 379 | } 380 | } 381 | return nil 382 | 383 | }) 384 | if err != nil { 385 | log.Fatal(err) 386 | } 387 | }, 388 | } 389 | 390 | cmd.PersistentFlags().StringVar(&reqArgs.Key, "key", "", "get-comment-from-proto") 391 | 392 | return cmd 393 | } 394 | 395 | var _CacheClientSubCommands = []func() *cobra.Command{ 396 | _CacheSetClientCommand, 397 | _CacheGetClientCommand, 398 | _CacheMultiSetClientCommand, 399 | _CacheMultiGetClientCommand, 400 | } 401 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= 3 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 4 | github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= 5 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 6 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 7 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 8 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 9 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 10 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 11 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 12 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 13 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 14 | github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= 15 | github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 16 | github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= 17 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 18 | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 19 | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 20 | github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= 21 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 22 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 23 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 24 | github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= 25 | github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= 26 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 27 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 28 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 29 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 30 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 31 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 32 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 33 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 34 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= 35 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 36 | github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 37 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 38 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 39 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 40 | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 41 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 42 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 43 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 44 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 45 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 46 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 47 | github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= 48 | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= 49 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 50 | github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= 51 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 52 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 53 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 54 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 55 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 56 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 57 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 58 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 59 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 60 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 61 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 62 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 63 | github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= 64 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 65 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 66 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 67 | github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= 68 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 69 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 70 | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= 71 | github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= 72 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 73 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 74 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 75 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 76 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 77 | github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= 78 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 79 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 80 | github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 81 | github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 82 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 83 | github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 84 | github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= 85 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 86 | github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 87 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 88 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= 89 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 90 | github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= 91 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 92 | github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= 93 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 94 | github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= 95 | github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= 96 | github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= 97 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 98 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 99 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 100 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 101 | github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= 102 | github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= 103 | github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= 104 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 105 | github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= 106 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 107 | github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 108 | github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= 109 | github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= 110 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 111 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 112 | go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 113 | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 114 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 115 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 116 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 117 | golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 118 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 119 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 120 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 121 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 122 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 123 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 124 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 125 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 126 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 127 | golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 128 | golang.org/x/net v0.0.0-20191009170851-d66e71096ffb h1:TR699M2v0qoKTOHxeLgp6zPqaQNs74f01a/ob9W0qko= 129 | golang.org/x/net v0.0.0-20191009170851-d66e71096ffb/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 130 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 131 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= 132 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 133 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 134 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 135 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 136 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 137 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 138 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 139 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 140 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 141 | golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 142 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= 143 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 144 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 145 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 146 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 147 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 148 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 149 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 150 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 151 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 152 | google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= 153 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 154 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= 155 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 156 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 157 | google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 158 | google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= 159 | google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= 160 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 161 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 162 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 163 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 164 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 165 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 166 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 167 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 168 | gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= 169 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 170 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 171 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 172 | -------------------------------------------------------------------------------- /example/pb/timer.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-gogo. DO NOT EDIT. 2 | // source: timer.proto 3 | 4 | package pb 5 | 6 | import proto "github.com/golang/protobuf/proto" 7 | import fmt "fmt" 8 | import math "math" 9 | 10 | import ( 11 | context "golang.org/x/net/context" 12 | grpc "google.golang.org/grpc" 13 | ) 14 | 15 | import io "io" 16 | 17 | // Reference imports to suppress errors if they are not otherwise used. 18 | var _ = proto.Marshal 19 | var _ = fmt.Errorf 20 | var _ = math.Inf 21 | 22 | // This is a compile-time assertion to ensure that this generated file 23 | // is compatible with the proto package it is being compiled against. 24 | // A compilation error at this line likely means your copy of the 25 | // proto package needs to be updated. 26 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package 27 | 28 | type TickRequest struct { 29 | Interval int32 `protobuf:"varint,1,opt,name=interval,proto3" json:"interval,omitempty"` 30 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 31 | XXX_unrecognized []byte `json:"-"` 32 | XXX_sizecache int32 `json:"-"` 33 | } 34 | 35 | func (m *TickRequest) Reset() { *m = TickRequest{} } 36 | func (m *TickRequest) String() string { return proto.CompactTextString(m) } 37 | func (*TickRequest) ProtoMessage() {} 38 | func (*TickRequest) Descriptor() ([]byte, []int) { 39 | return fileDescriptor_timer_468c66ad9c568581, []int{0} 40 | } 41 | func (m *TickRequest) XXX_Unmarshal(b []byte) error { 42 | return m.Unmarshal(b) 43 | } 44 | func (m *TickRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 45 | if deterministic { 46 | return xxx_messageInfo_TickRequest.Marshal(b, m, deterministic) 47 | } else { 48 | b = b[:cap(b)] 49 | n, err := m.MarshalTo(b) 50 | if err != nil { 51 | return nil, err 52 | } 53 | return b[:n], nil 54 | } 55 | } 56 | func (dst *TickRequest) XXX_Merge(src proto.Message) { 57 | xxx_messageInfo_TickRequest.Merge(dst, src) 58 | } 59 | func (m *TickRequest) XXX_Size() int { 60 | return m.Size() 61 | } 62 | func (m *TickRequest) XXX_DiscardUnknown() { 63 | xxx_messageInfo_TickRequest.DiscardUnknown(m) 64 | } 65 | 66 | var xxx_messageInfo_TickRequest proto.InternalMessageInfo 67 | 68 | func (m *TickRequest) GetInterval() int32 { 69 | if m != nil { 70 | return m.Interval 71 | } 72 | return 0 73 | } 74 | 75 | type TickResponse struct { 76 | Time string `protobuf:"bytes,1,opt,name=time,proto3" json:"time,omitempty"` 77 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 78 | XXX_unrecognized []byte `json:"-"` 79 | XXX_sizecache int32 `json:"-"` 80 | } 81 | 82 | func (m *TickResponse) Reset() { *m = TickResponse{} } 83 | func (m *TickResponse) String() string { return proto.CompactTextString(m) } 84 | func (*TickResponse) ProtoMessage() {} 85 | func (*TickResponse) Descriptor() ([]byte, []int) { 86 | return fileDescriptor_timer_468c66ad9c568581, []int{1} 87 | } 88 | func (m *TickResponse) XXX_Unmarshal(b []byte) error { 89 | return m.Unmarshal(b) 90 | } 91 | func (m *TickResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 92 | if deterministic { 93 | return xxx_messageInfo_TickResponse.Marshal(b, m, deterministic) 94 | } else { 95 | b = b[:cap(b)] 96 | n, err := m.MarshalTo(b) 97 | if err != nil { 98 | return nil, err 99 | } 100 | return b[:n], nil 101 | } 102 | } 103 | func (dst *TickResponse) XXX_Merge(src proto.Message) { 104 | xxx_messageInfo_TickResponse.Merge(dst, src) 105 | } 106 | func (m *TickResponse) XXX_Size() int { 107 | return m.Size() 108 | } 109 | func (m *TickResponse) XXX_DiscardUnknown() { 110 | xxx_messageInfo_TickResponse.DiscardUnknown(m) 111 | } 112 | 113 | var xxx_messageInfo_TickResponse proto.InternalMessageInfo 114 | 115 | func (m *TickResponse) GetTime() string { 116 | if m != nil { 117 | return m.Time 118 | } 119 | return "" 120 | } 121 | 122 | func init() { 123 | proto.RegisterType((*TickRequest)(nil), "pb.TickRequest") 124 | proto.RegisterType((*TickResponse)(nil), "pb.TickResponse") 125 | } 126 | 127 | // Reference imports to suppress errors if they are not otherwise used. 128 | var _ context.Context 129 | var _ grpc.ClientConn 130 | 131 | // This is a compile-time assertion to ensure that this generated file 132 | // is compatible with the grpc package it is being compiled against. 133 | const _ = grpc.SupportPackageIsVersion4 134 | 135 | // TimerClient is the client API for Timer service. 136 | // 137 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 138 | type TimerClient interface { 139 | Tick(ctx context.Context, in *TickRequest, opts ...grpc.CallOption) (Timer_TickClient, error) 140 | } 141 | 142 | type timerClient struct { 143 | cc *grpc.ClientConn 144 | } 145 | 146 | func NewTimerClient(cc *grpc.ClientConn) TimerClient { 147 | return &timerClient{cc} 148 | } 149 | 150 | func (c *timerClient) Tick(ctx context.Context, in *TickRequest, opts ...grpc.CallOption) (Timer_TickClient, error) { 151 | stream, err := c.cc.NewStream(ctx, &_Timer_serviceDesc.Streams[0], "/pb.Timer/Tick", opts...) 152 | if err != nil { 153 | return nil, err 154 | } 155 | x := &timerTickClient{stream} 156 | if err := x.ClientStream.SendMsg(in); err != nil { 157 | return nil, err 158 | } 159 | if err := x.ClientStream.CloseSend(); err != nil { 160 | return nil, err 161 | } 162 | return x, nil 163 | } 164 | 165 | type Timer_TickClient interface { 166 | Recv() (*TickResponse, error) 167 | grpc.ClientStream 168 | } 169 | 170 | type timerTickClient struct { 171 | grpc.ClientStream 172 | } 173 | 174 | func (x *timerTickClient) Recv() (*TickResponse, error) { 175 | m := new(TickResponse) 176 | if err := x.ClientStream.RecvMsg(m); err != nil { 177 | return nil, err 178 | } 179 | return m, nil 180 | } 181 | 182 | // TimerServer is the server API for Timer service. 183 | type TimerServer interface { 184 | Tick(*TickRequest, Timer_TickServer) error 185 | } 186 | 187 | func RegisterTimerServer(s *grpc.Server, srv TimerServer) { 188 | s.RegisterService(&_Timer_serviceDesc, srv) 189 | } 190 | 191 | func _Timer_Tick_Handler(srv interface{}, stream grpc.ServerStream) error { 192 | m := new(TickRequest) 193 | if err := stream.RecvMsg(m); err != nil { 194 | return err 195 | } 196 | return srv.(TimerServer).Tick(m, &timerTickServer{stream}) 197 | } 198 | 199 | type Timer_TickServer interface { 200 | Send(*TickResponse) error 201 | grpc.ServerStream 202 | } 203 | 204 | type timerTickServer struct { 205 | grpc.ServerStream 206 | } 207 | 208 | func (x *timerTickServer) Send(m *TickResponse) error { 209 | return x.ServerStream.SendMsg(m) 210 | } 211 | 212 | var _Timer_serviceDesc = grpc.ServiceDesc{ 213 | ServiceName: "pb.Timer", 214 | HandlerType: (*TimerServer)(nil), 215 | Methods: []grpc.MethodDesc{}, 216 | Streams: []grpc.StreamDesc{ 217 | { 218 | StreamName: "Tick", 219 | Handler: _Timer_Tick_Handler, 220 | ServerStreams: true, 221 | }, 222 | }, 223 | Metadata: "timer.proto", 224 | } 225 | 226 | func (m *TickRequest) Marshal() (dAtA []byte, err error) { 227 | size := m.Size() 228 | dAtA = make([]byte, size) 229 | n, err := m.MarshalTo(dAtA) 230 | if err != nil { 231 | return nil, err 232 | } 233 | return dAtA[:n], nil 234 | } 235 | 236 | func (m *TickRequest) MarshalTo(dAtA []byte) (int, error) { 237 | var i int 238 | _ = i 239 | var l int 240 | _ = l 241 | if m.Interval != 0 { 242 | dAtA[i] = 0x8 243 | i++ 244 | i = encodeVarintTimer(dAtA, i, uint64(m.Interval)) 245 | } 246 | if m.XXX_unrecognized != nil { 247 | i += copy(dAtA[i:], m.XXX_unrecognized) 248 | } 249 | return i, nil 250 | } 251 | 252 | func (m *TickResponse) Marshal() (dAtA []byte, err error) { 253 | size := m.Size() 254 | dAtA = make([]byte, size) 255 | n, err := m.MarshalTo(dAtA) 256 | if err != nil { 257 | return nil, err 258 | } 259 | return dAtA[:n], nil 260 | } 261 | 262 | func (m *TickResponse) MarshalTo(dAtA []byte) (int, error) { 263 | var i int 264 | _ = i 265 | var l int 266 | _ = l 267 | if len(m.Time) > 0 { 268 | dAtA[i] = 0xa 269 | i++ 270 | i = encodeVarintTimer(dAtA, i, uint64(len(m.Time))) 271 | i += copy(dAtA[i:], m.Time) 272 | } 273 | if m.XXX_unrecognized != nil { 274 | i += copy(dAtA[i:], m.XXX_unrecognized) 275 | } 276 | return i, nil 277 | } 278 | 279 | func encodeVarintTimer(dAtA []byte, offset int, v uint64) int { 280 | for v >= 1<<7 { 281 | dAtA[offset] = uint8(v&0x7f | 0x80) 282 | v >>= 7 283 | offset++ 284 | } 285 | dAtA[offset] = uint8(v) 286 | return offset + 1 287 | } 288 | func (m *TickRequest) Size() (n int) { 289 | if m == nil { 290 | return 0 291 | } 292 | var l int 293 | _ = l 294 | if m.Interval != 0 { 295 | n += 1 + sovTimer(uint64(m.Interval)) 296 | } 297 | if m.XXX_unrecognized != nil { 298 | n += len(m.XXX_unrecognized) 299 | } 300 | return n 301 | } 302 | 303 | func (m *TickResponse) Size() (n int) { 304 | if m == nil { 305 | return 0 306 | } 307 | var l int 308 | _ = l 309 | l = len(m.Time) 310 | if l > 0 { 311 | n += 1 + l + sovTimer(uint64(l)) 312 | } 313 | if m.XXX_unrecognized != nil { 314 | n += len(m.XXX_unrecognized) 315 | } 316 | return n 317 | } 318 | 319 | func sovTimer(x uint64) (n int) { 320 | for { 321 | n++ 322 | x >>= 7 323 | if x == 0 { 324 | break 325 | } 326 | } 327 | return n 328 | } 329 | func sozTimer(x uint64) (n int) { 330 | return sovTimer(uint64((x << 1) ^ uint64((int64(x) >> 63)))) 331 | } 332 | func (m *TickRequest) Unmarshal(dAtA []byte) error { 333 | l := len(dAtA) 334 | iNdEx := 0 335 | for iNdEx < l { 336 | preIndex := iNdEx 337 | var wire uint64 338 | for shift := uint(0); ; shift += 7 { 339 | if shift >= 64 { 340 | return ErrIntOverflowTimer 341 | } 342 | if iNdEx >= l { 343 | return io.ErrUnexpectedEOF 344 | } 345 | b := dAtA[iNdEx] 346 | iNdEx++ 347 | wire |= (uint64(b) & 0x7F) << shift 348 | if b < 0x80 { 349 | break 350 | } 351 | } 352 | fieldNum := int32(wire >> 3) 353 | wireType := int(wire & 0x7) 354 | if wireType == 4 { 355 | return fmt.Errorf("proto: TickRequest: wiretype end group for non-group") 356 | } 357 | if fieldNum <= 0 { 358 | return fmt.Errorf("proto: TickRequest: illegal tag %d (wire type %d)", fieldNum, wire) 359 | } 360 | switch fieldNum { 361 | case 1: 362 | if wireType != 0 { 363 | return fmt.Errorf("proto: wrong wireType = %d for field Interval", wireType) 364 | } 365 | m.Interval = 0 366 | for shift := uint(0); ; shift += 7 { 367 | if shift >= 64 { 368 | return ErrIntOverflowTimer 369 | } 370 | if iNdEx >= l { 371 | return io.ErrUnexpectedEOF 372 | } 373 | b := dAtA[iNdEx] 374 | iNdEx++ 375 | m.Interval |= (int32(b) & 0x7F) << shift 376 | if b < 0x80 { 377 | break 378 | } 379 | } 380 | default: 381 | iNdEx = preIndex 382 | skippy, err := skipTimer(dAtA[iNdEx:]) 383 | if err != nil { 384 | return err 385 | } 386 | if skippy < 0 { 387 | return ErrInvalidLengthTimer 388 | } 389 | if (iNdEx + skippy) > l { 390 | return io.ErrUnexpectedEOF 391 | } 392 | m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) 393 | iNdEx += skippy 394 | } 395 | } 396 | 397 | if iNdEx > l { 398 | return io.ErrUnexpectedEOF 399 | } 400 | return nil 401 | } 402 | func (m *TickResponse) Unmarshal(dAtA []byte) error { 403 | l := len(dAtA) 404 | iNdEx := 0 405 | for iNdEx < l { 406 | preIndex := iNdEx 407 | var wire uint64 408 | for shift := uint(0); ; shift += 7 { 409 | if shift >= 64 { 410 | return ErrIntOverflowTimer 411 | } 412 | if iNdEx >= l { 413 | return io.ErrUnexpectedEOF 414 | } 415 | b := dAtA[iNdEx] 416 | iNdEx++ 417 | wire |= (uint64(b) & 0x7F) << shift 418 | if b < 0x80 { 419 | break 420 | } 421 | } 422 | fieldNum := int32(wire >> 3) 423 | wireType := int(wire & 0x7) 424 | if wireType == 4 { 425 | return fmt.Errorf("proto: TickResponse: wiretype end group for non-group") 426 | } 427 | if fieldNum <= 0 { 428 | return fmt.Errorf("proto: TickResponse: illegal tag %d (wire type %d)", fieldNum, wire) 429 | } 430 | switch fieldNum { 431 | case 1: 432 | if wireType != 2 { 433 | return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) 434 | } 435 | var stringLen uint64 436 | for shift := uint(0); ; shift += 7 { 437 | if shift >= 64 { 438 | return ErrIntOverflowTimer 439 | } 440 | if iNdEx >= l { 441 | return io.ErrUnexpectedEOF 442 | } 443 | b := dAtA[iNdEx] 444 | iNdEx++ 445 | stringLen |= (uint64(b) & 0x7F) << shift 446 | if b < 0x80 { 447 | break 448 | } 449 | } 450 | intStringLen := int(stringLen) 451 | if intStringLen < 0 { 452 | return ErrInvalidLengthTimer 453 | } 454 | postIndex := iNdEx + intStringLen 455 | if postIndex > l { 456 | return io.ErrUnexpectedEOF 457 | } 458 | m.Time = string(dAtA[iNdEx:postIndex]) 459 | iNdEx = postIndex 460 | default: 461 | iNdEx = preIndex 462 | skippy, err := skipTimer(dAtA[iNdEx:]) 463 | if err != nil { 464 | return err 465 | } 466 | if skippy < 0 { 467 | return ErrInvalidLengthTimer 468 | } 469 | if (iNdEx + skippy) > l { 470 | return io.ErrUnexpectedEOF 471 | } 472 | m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) 473 | iNdEx += skippy 474 | } 475 | } 476 | 477 | if iNdEx > l { 478 | return io.ErrUnexpectedEOF 479 | } 480 | return nil 481 | } 482 | func skipTimer(dAtA []byte) (n int, err error) { 483 | l := len(dAtA) 484 | iNdEx := 0 485 | for iNdEx < l { 486 | var wire uint64 487 | for shift := uint(0); ; shift += 7 { 488 | if shift >= 64 { 489 | return 0, ErrIntOverflowTimer 490 | } 491 | if iNdEx >= l { 492 | return 0, io.ErrUnexpectedEOF 493 | } 494 | b := dAtA[iNdEx] 495 | iNdEx++ 496 | wire |= (uint64(b) & 0x7F) << shift 497 | if b < 0x80 { 498 | break 499 | } 500 | } 501 | wireType := int(wire & 0x7) 502 | switch wireType { 503 | case 0: 504 | for shift := uint(0); ; shift += 7 { 505 | if shift >= 64 { 506 | return 0, ErrIntOverflowTimer 507 | } 508 | if iNdEx >= l { 509 | return 0, io.ErrUnexpectedEOF 510 | } 511 | iNdEx++ 512 | if dAtA[iNdEx-1] < 0x80 { 513 | break 514 | } 515 | } 516 | return iNdEx, nil 517 | case 1: 518 | iNdEx += 8 519 | return iNdEx, nil 520 | case 2: 521 | var length int 522 | for shift := uint(0); ; shift += 7 { 523 | if shift >= 64 { 524 | return 0, ErrIntOverflowTimer 525 | } 526 | if iNdEx >= l { 527 | return 0, io.ErrUnexpectedEOF 528 | } 529 | b := dAtA[iNdEx] 530 | iNdEx++ 531 | length |= (int(b) & 0x7F) << shift 532 | if b < 0x80 { 533 | break 534 | } 535 | } 536 | iNdEx += length 537 | if length < 0 { 538 | return 0, ErrInvalidLengthTimer 539 | } 540 | return iNdEx, nil 541 | case 3: 542 | for { 543 | var innerWire uint64 544 | var start int = iNdEx 545 | for shift := uint(0); ; shift += 7 { 546 | if shift >= 64 { 547 | return 0, ErrIntOverflowTimer 548 | } 549 | if iNdEx >= l { 550 | return 0, io.ErrUnexpectedEOF 551 | } 552 | b := dAtA[iNdEx] 553 | iNdEx++ 554 | innerWire |= (uint64(b) & 0x7F) << shift 555 | if b < 0x80 { 556 | break 557 | } 558 | } 559 | innerWireType := int(innerWire & 0x7) 560 | if innerWireType == 4 { 561 | break 562 | } 563 | next, err := skipTimer(dAtA[start:]) 564 | if err != nil { 565 | return 0, err 566 | } 567 | iNdEx = start + next 568 | } 569 | return iNdEx, nil 570 | case 4: 571 | return iNdEx, nil 572 | case 5: 573 | iNdEx += 4 574 | return iNdEx, nil 575 | default: 576 | return 0, fmt.Errorf("proto: illegal wireType %d", wireType) 577 | } 578 | } 579 | panic("unreachable") 580 | } 581 | 582 | var ( 583 | ErrInvalidLengthTimer = fmt.Errorf("proto: negative length found during unmarshaling") 584 | ErrIntOverflowTimer = fmt.Errorf("proto: integer overflow") 585 | ) 586 | 587 | func init() { proto.RegisterFile("timer.proto", fileDescriptor_timer_468c66ad9c568581) } 588 | 589 | var fileDescriptor_timer_468c66ad9c568581 = []byte{ 590 | // 154 bytes of a gzipped FileDescriptorProto 591 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2e, 0xc9, 0xcc, 0x4d, 592 | 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2a, 0x48, 0x52, 0xd2, 0xe4, 0xe2, 0x0e, 593 | 0xc9, 0x4c, 0xce, 0x0e, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0x92, 0xe2, 0xe2, 0xc8, 0xcc, 594 | 0x2b, 0x49, 0x2d, 0x2a, 0x4b, 0xcc, 0x91, 0x60, 0x54, 0x60, 0xd4, 0x60, 0x0d, 0x82, 0xf3, 0x95, 595 | 0x94, 0xb8, 0x78, 0x20, 0x4a, 0x8b, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x85, 0x84, 0xb8, 0x58, 0x40, 596 | 0xa6, 0x81, 0xd5, 0x71, 0x06, 0x81, 0xd9, 0x46, 0x26, 0x5c, 0xac, 0x21, 0x20, 0x1b, 0x84, 0xb4, 597 | 0xb9, 0x58, 0x40, 0x8a, 0x85, 0xf8, 0xf5, 0x0a, 0x92, 0xf4, 0x90, 0x6c, 0x90, 0x12, 0x40, 0x08, 598 | 0x40, 0xcc, 0x31, 0x60, 0x74, 0x12, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 599 | 0x8f, 0xe4, 0x18, 0x67, 0x3c, 0x96, 0x63, 0x48, 0x62, 0x03, 0xbb, 0xd0, 0x18, 0x10, 0x00, 0x00, 600 | 0xff, 0xff, 0xa0, 0xa1, 0x58, 0x36, 0xb0, 0x00, 0x00, 0x00, 601 | } 602 | -------------------------------------------------------------------------------- /example/pb/bank.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-gogo. DO NOT EDIT. 2 | // source: bank.proto 3 | 4 | package pb 5 | 6 | import proto "github.com/golang/protobuf/proto" 7 | import fmt "fmt" 8 | import math "math" 9 | 10 | import ( 11 | context "golang.org/x/net/context" 12 | grpc "google.golang.org/grpc" 13 | ) 14 | 15 | import encoding_binary "encoding/binary" 16 | 17 | import io "io" 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package 29 | 30 | type DepositRequest struct { 31 | Account string `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"` 32 | Amount float64 `protobuf:"fixed64,2,opt,name=amount,proto3" json:"amount,omitempty"` 33 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 34 | XXX_unrecognized []byte `json:"-"` 35 | XXX_sizecache int32 `json:"-"` 36 | } 37 | 38 | func (m *DepositRequest) Reset() { *m = DepositRequest{} } 39 | func (m *DepositRequest) String() string { return proto.CompactTextString(m) } 40 | func (*DepositRequest) ProtoMessage() {} 41 | func (*DepositRequest) Descriptor() ([]byte, []int) { 42 | return fileDescriptor_bank_24a687593763ef7d, []int{0} 43 | } 44 | func (m *DepositRequest) XXX_Unmarshal(b []byte) error { 45 | return m.Unmarshal(b) 46 | } 47 | func (m *DepositRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 48 | if deterministic { 49 | return xxx_messageInfo_DepositRequest.Marshal(b, m, deterministic) 50 | } else { 51 | b = b[:cap(b)] 52 | n, err := m.MarshalTo(b) 53 | if err != nil { 54 | return nil, err 55 | } 56 | return b[:n], nil 57 | } 58 | } 59 | func (dst *DepositRequest) XXX_Merge(src proto.Message) { 60 | xxx_messageInfo_DepositRequest.Merge(dst, src) 61 | } 62 | func (m *DepositRequest) XXX_Size() int { 63 | return m.Size() 64 | } 65 | func (m *DepositRequest) XXX_DiscardUnknown() { 66 | xxx_messageInfo_DepositRequest.DiscardUnknown(m) 67 | } 68 | 69 | var xxx_messageInfo_DepositRequest proto.InternalMessageInfo 70 | 71 | func (m *DepositRequest) GetAccount() string { 72 | if m != nil { 73 | return m.Account 74 | } 75 | return "" 76 | } 77 | 78 | func (m *DepositRequest) GetAmount() float64 { 79 | if m != nil { 80 | return m.Amount 81 | } 82 | return 0 83 | } 84 | 85 | type DepositReply struct { 86 | Account string `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"` 87 | Balance float64 `protobuf:"fixed64,2,opt,name=balance,proto3" json:"balance,omitempty"` 88 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 89 | XXX_unrecognized []byte `json:"-"` 90 | XXX_sizecache int32 `json:"-"` 91 | } 92 | 93 | func (m *DepositReply) Reset() { *m = DepositReply{} } 94 | func (m *DepositReply) String() string { return proto.CompactTextString(m) } 95 | func (*DepositReply) ProtoMessage() {} 96 | func (*DepositReply) Descriptor() ([]byte, []int) { 97 | return fileDescriptor_bank_24a687593763ef7d, []int{1} 98 | } 99 | func (m *DepositReply) XXX_Unmarshal(b []byte) error { 100 | return m.Unmarshal(b) 101 | } 102 | func (m *DepositReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 103 | if deterministic { 104 | return xxx_messageInfo_DepositReply.Marshal(b, m, deterministic) 105 | } else { 106 | b = b[:cap(b)] 107 | n, err := m.MarshalTo(b) 108 | if err != nil { 109 | return nil, err 110 | } 111 | return b[:n], nil 112 | } 113 | } 114 | func (dst *DepositReply) XXX_Merge(src proto.Message) { 115 | xxx_messageInfo_DepositReply.Merge(dst, src) 116 | } 117 | func (m *DepositReply) XXX_Size() int { 118 | return m.Size() 119 | } 120 | func (m *DepositReply) XXX_DiscardUnknown() { 121 | xxx_messageInfo_DepositReply.DiscardUnknown(m) 122 | } 123 | 124 | var xxx_messageInfo_DepositReply proto.InternalMessageInfo 125 | 126 | func (m *DepositReply) GetAccount() string { 127 | if m != nil { 128 | return m.Account 129 | } 130 | return "" 131 | } 132 | 133 | func (m *DepositReply) GetBalance() float64 { 134 | if m != nil { 135 | return m.Balance 136 | } 137 | return 0 138 | } 139 | 140 | func init() { 141 | proto.RegisterType((*DepositRequest)(nil), "pb.DepositRequest") 142 | proto.RegisterType((*DepositReply)(nil), "pb.DepositReply") 143 | } 144 | 145 | // Reference imports to suppress errors if they are not otherwise used. 146 | var _ context.Context 147 | var _ grpc.ClientConn 148 | 149 | // This is a compile-time assertion to ensure that this generated file 150 | // is compatible with the grpc package it is being compiled against. 151 | const _ = grpc.SupportPackageIsVersion4 152 | 153 | // BankClient is the client API for Bank service. 154 | // 155 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 156 | type BankClient interface { 157 | Deposit(ctx context.Context, in *DepositRequest, opts ...grpc.CallOption) (*DepositReply, error) 158 | } 159 | 160 | type bankClient struct { 161 | cc *grpc.ClientConn 162 | } 163 | 164 | func NewBankClient(cc *grpc.ClientConn) BankClient { 165 | return &bankClient{cc} 166 | } 167 | 168 | func (c *bankClient) Deposit(ctx context.Context, in *DepositRequest, opts ...grpc.CallOption) (*DepositReply, error) { 169 | out := new(DepositReply) 170 | err := c.cc.Invoke(ctx, "/pb.Bank/Deposit", in, out, opts...) 171 | if err != nil { 172 | return nil, err 173 | } 174 | return out, nil 175 | } 176 | 177 | // BankServer is the server API for Bank service. 178 | type BankServer interface { 179 | Deposit(context.Context, *DepositRequest) (*DepositReply, error) 180 | } 181 | 182 | func RegisterBankServer(s *grpc.Server, srv BankServer) { 183 | s.RegisterService(&_Bank_serviceDesc, srv) 184 | } 185 | 186 | func _Bank_Deposit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 187 | in := new(DepositRequest) 188 | if err := dec(in); err != nil { 189 | return nil, err 190 | } 191 | if interceptor == nil { 192 | return srv.(BankServer).Deposit(ctx, in) 193 | } 194 | info := &grpc.UnaryServerInfo{ 195 | Server: srv, 196 | FullMethod: "/pb.Bank/Deposit", 197 | } 198 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 199 | return srv.(BankServer).Deposit(ctx, req.(*DepositRequest)) 200 | } 201 | return interceptor(ctx, in, info, handler) 202 | } 203 | 204 | var _Bank_serviceDesc = grpc.ServiceDesc{ 205 | ServiceName: "pb.Bank", 206 | HandlerType: (*BankServer)(nil), 207 | Methods: []grpc.MethodDesc{ 208 | { 209 | MethodName: "Deposit", 210 | Handler: _Bank_Deposit_Handler, 211 | }, 212 | }, 213 | Streams: []grpc.StreamDesc{}, 214 | Metadata: "bank.proto", 215 | } 216 | 217 | func (m *DepositRequest) Marshal() (dAtA []byte, err error) { 218 | size := m.Size() 219 | dAtA = make([]byte, size) 220 | n, err := m.MarshalTo(dAtA) 221 | if err != nil { 222 | return nil, err 223 | } 224 | return dAtA[:n], nil 225 | } 226 | 227 | func (m *DepositRequest) MarshalTo(dAtA []byte) (int, error) { 228 | var i int 229 | _ = i 230 | var l int 231 | _ = l 232 | if len(m.Account) > 0 { 233 | dAtA[i] = 0xa 234 | i++ 235 | i = encodeVarintBank(dAtA, i, uint64(len(m.Account))) 236 | i += copy(dAtA[i:], m.Account) 237 | } 238 | if m.Amount != 0 { 239 | dAtA[i] = 0x11 240 | i++ 241 | encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Amount)))) 242 | i += 8 243 | } 244 | if m.XXX_unrecognized != nil { 245 | i += copy(dAtA[i:], m.XXX_unrecognized) 246 | } 247 | return i, nil 248 | } 249 | 250 | func (m *DepositReply) Marshal() (dAtA []byte, err error) { 251 | size := m.Size() 252 | dAtA = make([]byte, size) 253 | n, err := m.MarshalTo(dAtA) 254 | if err != nil { 255 | return nil, err 256 | } 257 | return dAtA[:n], nil 258 | } 259 | 260 | func (m *DepositReply) MarshalTo(dAtA []byte) (int, error) { 261 | var i int 262 | _ = i 263 | var l int 264 | _ = l 265 | if len(m.Account) > 0 { 266 | dAtA[i] = 0xa 267 | i++ 268 | i = encodeVarintBank(dAtA, i, uint64(len(m.Account))) 269 | i += copy(dAtA[i:], m.Account) 270 | } 271 | if m.Balance != 0 { 272 | dAtA[i] = 0x11 273 | i++ 274 | encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Balance)))) 275 | i += 8 276 | } 277 | if m.XXX_unrecognized != nil { 278 | i += copy(dAtA[i:], m.XXX_unrecognized) 279 | } 280 | return i, nil 281 | } 282 | 283 | func encodeVarintBank(dAtA []byte, offset int, v uint64) int { 284 | for v >= 1<<7 { 285 | dAtA[offset] = uint8(v&0x7f | 0x80) 286 | v >>= 7 287 | offset++ 288 | } 289 | dAtA[offset] = uint8(v) 290 | return offset + 1 291 | } 292 | func (m *DepositRequest) Size() (n int) { 293 | if m == nil { 294 | return 0 295 | } 296 | var l int 297 | _ = l 298 | l = len(m.Account) 299 | if l > 0 { 300 | n += 1 + l + sovBank(uint64(l)) 301 | } 302 | if m.Amount != 0 { 303 | n += 9 304 | } 305 | if m.XXX_unrecognized != nil { 306 | n += len(m.XXX_unrecognized) 307 | } 308 | return n 309 | } 310 | 311 | func (m *DepositReply) Size() (n int) { 312 | if m == nil { 313 | return 0 314 | } 315 | var l int 316 | _ = l 317 | l = len(m.Account) 318 | if l > 0 { 319 | n += 1 + l + sovBank(uint64(l)) 320 | } 321 | if m.Balance != 0 { 322 | n += 9 323 | } 324 | if m.XXX_unrecognized != nil { 325 | n += len(m.XXX_unrecognized) 326 | } 327 | return n 328 | } 329 | 330 | func sovBank(x uint64) (n int) { 331 | for { 332 | n++ 333 | x >>= 7 334 | if x == 0 { 335 | break 336 | } 337 | } 338 | return n 339 | } 340 | func sozBank(x uint64) (n int) { 341 | return sovBank(uint64((x << 1) ^ uint64((int64(x) >> 63)))) 342 | } 343 | func (m *DepositRequest) Unmarshal(dAtA []byte) error { 344 | l := len(dAtA) 345 | iNdEx := 0 346 | for iNdEx < l { 347 | preIndex := iNdEx 348 | var wire uint64 349 | for shift := uint(0); ; shift += 7 { 350 | if shift >= 64 { 351 | return ErrIntOverflowBank 352 | } 353 | if iNdEx >= l { 354 | return io.ErrUnexpectedEOF 355 | } 356 | b := dAtA[iNdEx] 357 | iNdEx++ 358 | wire |= (uint64(b) & 0x7F) << shift 359 | if b < 0x80 { 360 | break 361 | } 362 | } 363 | fieldNum := int32(wire >> 3) 364 | wireType := int(wire & 0x7) 365 | if wireType == 4 { 366 | return fmt.Errorf("proto: DepositRequest: wiretype end group for non-group") 367 | } 368 | if fieldNum <= 0 { 369 | return fmt.Errorf("proto: DepositRequest: illegal tag %d (wire type %d)", fieldNum, wire) 370 | } 371 | switch fieldNum { 372 | case 1: 373 | if wireType != 2 { 374 | return fmt.Errorf("proto: wrong wireType = %d for field Account", wireType) 375 | } 376 | var stringLen uint64 377 | for shift := uint(0); ; shift += 7 { 378 | if shift >= 64 { 379 | return ErrIntOverflowBank 380 | } 381 | if iNdEx >= l { 382 | return io.ErrUnexpectedEOF 383 | } 384 | b := dAtA[iNdEx] 385 | iNdEx++ 386 | stringLen |= (uint64(b) & 0x7F) << shift 387 | if b < 0x80 { 388 | break 389 | } 390 | } 391 | intStringLen := int(stringLen) 392 | if intStringLen < 0 { 393 | return ErrInvalidLengthBank 394 | } 395 | postIndex := iNdEx + intStringLen 396 | if postIndex > l { 397 | return io.ErrUnexpectedEOF 398 | } 399 | m.Account = string(dAtA[iNdEx:postIndex]) 400 | iNdEx = postIndex 401 | case 2: 402 | if wireType != 1 { 403 | return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) 404 | } 405 | var v uint64 406 | if (iNdEx + 8) > l { 407 | return io.ErrUnexpectedEOF 408 | } 409 | v = uint64(encoding_binary.LittleEndian.Uint64(dAtA[iNdEx:])) 410 | iNdEx += 8 411 | m.Amount = float64(math.Float64frombits(v)) 412 | default: 413 | iNdEx = preIndex 414 | skippy, err := skipBank(dAtA[iNdEx:]) 415 | if err != nil { 416 | return err 417 | } 418 | if skippy < 0 { 419 | return ErrInvalidLengthBank 420 | } 421 | if (iNdEx + skippy) > l { 422 | return io.ErrUnexpectedEOF 423 | } 424 | m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) 425 | iNdEx += skippy 426 | } 427 | } 428 | 429 | if iNdEx > l { 430 | return io.ErrUnexpectedEOF 431 | } 432 | return nil 433 | } 434 | func (m *DepositReply) Unmarshal(dAtA []byte) error { 435 | l := len(dAtA) 436 | iNdEx := 0 437 | for iNdEx < l { 438 | preIndex := iNdEx 439 | var wire uint64 440 | for shift := uint(0); ; shift += 7 { 441 | if shift >= 64 { 442 | return ErrIntOverflowBank 443 | } 444 | if iNdEx >= l { 445 | return io.ErrUnexpectedEOF 446 | } 447 | b := dAtA[iNdEx] 448 | iNdEx++ 449 | wire |= (uint64(b) & 0x7F) << shift 450 | if b < 0x80 { 451 | break 452 | } 453 | } 454 | fieldNum := int32(wire >> 3) 455 | wireType := int(wire & 0x7) 456 | if wireType == 4 { 457 | return fmt.Errorf("proto: DepositReply: wiretype end group for non-group") 458 | } 459 | if fieldNum <= 0 { 460 | return fmt.Errorf("proto: DepositReply: illegal tag %d (wire type %d)", fieldNum, wire) 461 | } 462 | switch fieldNum { 463 | case 1: 464 | if wireType != 2 { 465 | return fmt.Errorf("proto: wrong wireType = %d for field Account", wireType) 466 | } 467 | var stringLen uint64 468 | for shift := uint(0); ; shift += 7 { 469 | if shift >= 64 { 470 | return ErrIntOverflowBank 471 | } 472 | if iNdEx >= l { 473 | return io.ErrUnexpectedEOF 474 | } 475 | b := dAtA[iNdEx] 476 | iNdEx++ 477 | stringLen |= (uint64(b) & 0x7F) << shift 478 | if b < 0x80 { 479 | break 480 | } 481 | } 482 | intStringLen := int(stringLen) 483 | if intStringLen < 0 { 484 | return ErrInvalidLengthBank 485 | } 486 | postIndex := iNdEx + intStringLen 487 | if postIndex > l { 488 | return io.ErrUnexpectedEOF 489 | } 490 | m.Account = string(dAtA[iNdEx:postIndex]) 491 | iNdEx = postIndex 492 | case 2: 493 | if wireType != 1 { 494 | return fmt.Errorf("proto: wrong wireType = %d for field Balance", wireType) 495 | } 496 | var v uint64 497 | if (iNdEx + 8) > l { 498 | return io.ErrUnexpectedEOF 499 | } 500 | v = uint64(encoding_binary.LittleEndian.Uint64(dAtA[iNdEx:])) 501 | iNdEx += 8 502 | m.Balance = float64(math.Float64frombits(v)) 503 | default: 504 | iNdEx = preIndex 505 | skippy, err := skipBank(dAtA[iNdEx:]) 506 | if err != nil { 507 | return err 508 | } 509 | if skippy < 0 { 510 | return ErrInvalidLengthBank 511 | } 512 | if (iNdEx + skippy) > l { 513 | return io.ErrUnexpectedEOF 514 | } 515 | m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) 516 | iNdEx += skippy 517 | } 518 | } 519 | 520 | if iNdEx > l { 521 | return io.ErrUnexpectedEOF 522 | } 523 | return nil 524 | } 525 | func skipBank(dAtA []byte) (n int, err error) { 526 | l := len(dAtA) 527 | iNdEx := 0 528 | for iNdEx < l { 529 | var wire uint64 530 | for shift := uint(0); ; shift += 7 { 531 | if shift >= 64 { 532 | return 0, ErrIntOverflowBank 533 | } 534 | if iNdEx >= l { 535 | return 0, io.ErrUnexpectedEOF 536 | } 537 | b := dAtA[iNdEx] 538 | iNdEx++ 539 | wire |= (uint64(b) & 0x7F) << shift 540 | if b < 0x80 { 541 | break 542 | } 543 | } 544 | wireType := int(wire & 0x7) 545 | switch wireType { 546 | case 0: 547 | for shift := uint(0); ; shift += 7 { 548 | if shift >= 64 { 549 | return 0, ErrIntOverflowBank 550 | } 551 | if iNdEx >= l { 552 | return 0, io.ErrUnexpectedEOF 553 | } 554 | iNdEx++ 555 | if dAtA[iNdEx-1] < 0x80 { 556 | break 557 | } 558 | } 559 | return iNdEx, nil 560 | case 1: 561 | iNdEx += 8 562 | return iNdEx, nil 563 | case 2: 564 | var length int 565 | for shift := uint(0); ; shift += 7 { 566 | if shift >= 64 { 567 | return 0, ErrIntOverflowBank 568 | } 569 | if iNdEx >= l { 570 | return 0, io.ErrUnexpectedEOF 571 | } 572 | b := dAtA[iNdEx] 573 | iNdEx++ 574 | length |= (int(b) & 0x7F) << shift 575 | if b < 0x80 { 576 | break 577 | } 578 | } 579 | iNdEx += length 580 | if length < 0 { 581 | return 0, ErrInvalidLengthBank 582 | } 583 | return iNdEx, nil 584 | case 3: 585 | for { 586 | var innerWire uint64 587 | var start int = iNdEx 588 | for shift := uint(0); ; shift += 7 { 589 | if shift >= 64 { 590 | return 0, ErrIntOverflowBank 591 | } 592 | if iNdEx >= l { 593 | return 0, io.ErrUnexpectedEOF 594 | } 595 | b := dAtA[iNdEx] 596 | iNdEx++ 597 | innerWire |= (uint64(b) & 0x7F) << shift 598 | if b < 0x80 { 599 | break 600 | } 601 | } 602 | innerWireType := int(innerWire & 0x7) 603 | if innerWireType == 4 { 604 | break 605 | } 606 | next, err := skipBank(dAtA[start:]) 607 | if err != nil { 608 | return 0, err 609 | } 610 | iNdEx = start + next 611 | } 612 | return iNdEx, nil 613 | case 4: 614 | return iNdEx, nil 615 | case 5: 616 | iNdEx += 4 617 | return iNdEx, nil 618 | default: 619 | return 0, fmt.Errorf("proto: illegal wireType %d", wireType) 620 | } 621 | } 622 | panic("unreachable") 623 | } 624 | 625 | var ( 626 | ErrInvalidLengthBank = fmt.Errorf("proto: negative length found during unmarshaling") 627 | ErrIntOverflowBank = fmt.Errorf("proto: integer overflow") 628 | ) 629 | 630 | func init() { proto.RegisterFile("bank.proto", fileDescriptor_bank_24a687593763ef7d) } 631 | 632 | var fileDescriptor_bank_24a687593763ef7d = []byte{ 633 | // 173 bytes of a gzipped FileDescriptorProto 634 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4a, 0x4a, 0xcc, 0xcb, 635 | 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2a, 0x48, 0x52, 0x72, 0xe2, 0xe2, 0x73, 0x49, 636 | 0x2d, 0xc8, 0x2f, 0xce, 0x2c, 0x09, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0x92, 0xe0, 0x62, 637 | 0x4f, 0x4c, 0x4e, 0xce, 0x2f, 0xcd, 0x2b, 0x91, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x82, 0x71, 638 | 0x85, 0xc4, 0xb8, 0xd8, 0x12, 0x73, 0xc1, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0x8c, 0x41, 0x50, 0x9e, 639 | 0x92, 0x13, 0x17, 0x0f, 0xdc, 0x8c, 0x82, 0x9c, 0x4a, 0x3c, 0x26, 0x48, 0x70, 0xb1, 0x27, 0x25, 640 | 0xe6, 0x24, 0xe6, 0x25, 0xa7, 0x42, 0x8d, 0x80, 0x71, 0x8d, 0xcc, 0xb9, 0x58, 0x9c, 0x12, 0xf3, 641 | 0xb2, 0x85, 0xf4, 0xb9, 0xd8, 0xa1, 0x66, 0x09, 0x09, 0xe9, 0x15, 0x24, 0xe9, 0xa1, 0x3a, 0x4e, 642 | 0x4a, 0x00, 0x45, 0xac, 0x20, 0xa7, 0xd2, 0x49, 0xe0, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 643 | 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf1, 0x58, 0x8e, 0x21, 0x89, 0x0d, 0xec, 0x3b, 0x63, 0x40, 644 | 0x00, 0x00, 0x00, 0xff, 0xff, 0xa5, 0x6a, 0x33, 0xe8, 0xeb, 0x00, 0x00, 0x00, 645 | } 646 | -------------------------------------------------------------------------------- /client/client.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The protoc-gen-cobra authors. All rights reserved. 2 | // 3 | // Based on protoc-gen-go from https://github.com/golang/protobuf. 4 | // Copyright 2015 The Go Authors. All rights reserved. 5 | 6 | // Package client outputs a gRPC service client in Go code, using cobra. 7 | // It runs as a plugin for the Go protocol buffer compiler plugin. 8 | // It is linked in to protoc-gen-cobra. 9 | package client 10 | 11 | import ( 12 | "bytes" 13 | "fmt" 14 | "path" 15 | "sort" 16 | "strconv" 17 | "strings" 18 | "text/template" 19 | 20 | pb "github.com/golang/protobuf/protoc-gen-go/descriptor" 21 | 22 | "github.com/tetratelabs/protoc-gen-cobra/generator" 23 | ) 24 | 25 | // generatedCodeVersion indicates a version of the generated code. 26 | // It is incremented whenever an incompatibility between the generated code and 27 | // the grpc package is introduced; the generated code references 28 | // a constant, grpc.SupportPackageIsVersionN (where N is generatedCodeVersion). 29 | const generatedCodeVersion = 4 30 | 31 | func init() { 32 | generator.RegisterPlugin(new(client)) 33 | } 34 | 35 | // client is an implementation of the Go protocol buffer compiler's 36 | // plugin architecture. It generates bindings for gRPC support. 37 | type client struct { 38 | gen *generator.Generator 39 | } 40 | 41 | // Name returns the name of this plugin, "client". 42 | func (c *client) Name() string { 43 | return "client" 44 | } 45 | 46 | // map of import pkg name to unique name 47 | type importPkg map[string]*pkgInfo 48 | 49 | type pkgInfo struct { 50 | ImportPath string 51 | KnownType string 52 | UniqueName string 53 | } 54 | 55 | var importPkgsByName = importPkg{ 56 | "cobra": {ImportPath: "github.com/spf13/cobra", KnownType: "Command"}, 57 | "context": {ImportPath: "golang.org/x/net/context", KnownType: "Context"}, 58 | "credentials": {ImportPath: "google.golang.org/grpc/credentials", KnownType: "AuthInfo"}, 59 | "filepath": {ImportPath: "path/filepath", KnownType: "WalkFunc"}, 60 | "grpc": {ImportPath: "google.golang.org/grpc", KnownType: "ClientConn"}, 61 | "io": {ImportPath: "io", KnownType: "Reader"}, 62 | "iocodec": {ImportPath: "github.com/tetratelabs/protoc-gen-cobra/iocodec", KnownType: "Encoder"}, 63 | "ioutil": {ImportPath: "io/ioutil", KnownType: "=Discard"}, 64 | "json": {ImportPath: "encoding/json", KnownType: "Encoder"}, 65 | "log": {ImportPath: "log", KnownType: "Logger"}, 66 | "net": {ImportPath: "net", KnownType: "IP"}, 67 | "oauth": {ImportPath: "google.golang.org/grpc/credentials/oauth", KnownType: "TokenSource"}, 68 | "oauth2": {ImportPath: "golang.org/x/oauth2", KnownType: "Token"}, 69 | "os": {ImportPath: "os", KnownType: "File"}, 70 | "pflag": {ImportPath: "github.com/spf13/pflag", KnownType: "FlagSet"}, 71 | "template": {ImportPath: "text/template", KnownType: "Template"}, 72 | "time": {ImportPath: "time", KnownType: "Time"}, 73 | "tls": {ImportPath: "crypto/tls", KnownType: "Config"}, 74 | "x509": {ImportPath: "crypto/x509", KnownType: "Certificate"}, 75 | "fmt": {ImportPath: "fmt", KnownType: "Writer"}, 76 | } 77 | var sortedImportPkgNames = make([]string, 0, len(importPkgsByName)) 78 | 79 | // Init initializes the plugin. 80 | func (c *client) Init(gen *generator.Generator) { 81 | c.gen = gen 82 | for k := range importPkgsByName { 83 | importPkgsByName[k].UniqueName = generator.RegisterUniquePackageName(k, nil) 84 | sortedImportPkgNames = append(sortedImportPkgNames, k) 85 | } 86 | sort.Strings(sortedImportPkgNames) 87 | } 88 | 89 | // P forwards to c.gen.P. 90 | func (c *client) P(args ...interface{}) { c.gen.P(args...) } 91 | 92 | // Generate generates code for the services in the given file. 93 | func (c *client) Generate(file *generator.FileDescriptor) { 94 | if len(file.FileDescriptorProto.Service) == 0 { 95 | return 96 | } 97 | 98 | // Assert version compatibility. 99 | c.P("// This is a compile-time assertion to ensure that this generated file") 100 | c.P("// is compatible with the grpc package it is being compiled against.") 101 | c.P("const _ = ", importPkgsByName["grpc"].UniqueName, ".SupportPackageIsVersion", generatedCodeVersion) 102 | c.P() 103 | 104 | for i, service := range file.FileDescriptorProto.Service { 105 | c.generateService(file, service, i) 106 | } 107 | } 108 | 109 | // GenerateImports generates the import declaration for this file. 110 | func (c *client) GenerateImports(file *generator.FileDescriptor, imports []*generator.FileDescriptor) { 111 | c.P("import (") 112 | 113 | // proto import is hard coded 114 | c.P("proto ", strconv.Quote(c.gen.ImportPrefix+"github.com/golang/protobuf/proto")) 115 | 116 | if len(file.FileDescriptorProto.Service) == 0 { 117 | c.P(")") 118 | return 119 | } 120 | 121 | for _, n := range sortedImportPkgNames { 122 | v := importPkgsByName[n] 123 | c.P(v.UniqueName, " ", strconv.Quote(path.Join(c.gen.ImportPrefix, v.ImportPath))) 124 | } 125 | 126 | importPathByPackage := map[string]string{} 127 | for _, imp := range imports { 128 | if *file.Package == *imp.Package { 129 | continue 130 | } 131 | if imp.FileDescriptorProto.GetOptions().GetGoPackage() != "" { 132 | importPathByPackage[*imp.FileDescriptorProto.Package] = strconv.Quote(*imp.FileDescriptorProto.Options.GoPackage) 133 | } else { 134 | importPathByPackage[*imp.FileDescriptorProto.Package] = strconv.Quote(path.Join(c.gen.ImportPrefix, *imp.FileDescriptorProto.Package)) 135 | } 136 | } 137 | 138 | importedPackagesByName := map[string]string{} 139 | for _, service := range file.FileDescriptorProto.Service { 140 | for _, method := range service.Method { 141 | importName, pkg, _ := inputNames(method.GetInputType()) 142 | 143 | if importPath, found := importPathByPackage[pkg]; found { 144 | importedPackagesByName[importName] = importPath 145 | } 146 | } 147 | } 148 | importedPackageNames := make([]string, 0, len(importedPackagesByName)) 149 | for n := range importedPackagesByName { 150 | importedPackageNames = append(importedPackageNames, n) 151 | } 152 | sort.Strings(importedPackageNames) 153 | for _, n := range importedPackageNames { 154 | c.P(n, " ", importedPackagesByName[n]) 155 | } 156 | c.P(")") 157 | c.P() 158 | } 159 | 160 | // reservedClientName records whether a client name is reserved on the client side. 161 | var reservedClientName = map[string]bool{ 162 | // TODO: do we need any in gRPC? 163 | } 164 | 165 | // generateService generates all the code for the named service. 166 | func (c *client) generateService(file *generator.FileDescriptor, service *pb.ServiceDescriptorProto, index int) { 167 | origServName := service.GetName() 168 | fullServName := origServName 169 | if pkg := file.GetPackage(); pkg != "" { 170 | fullServName = pkg + "." + fullServName 171 | } 172 | servName := generator.CamelCase(origServName) 173 | 174 | c.P() 175 | c.generateCommand(servName) 176 | c.P() 177 | 178 | subCommands := make([]string, len(service.Method)) 179 | for i, method := range service.Method { 180 | subCommands[i] = c.generateSubcommand(servName, file, method) 181 | } 182 | c.P() 183 | 184 | c.generateCommandsList(servName, subCommands) 185 | } 186 | 187 | var generateCommandListTemplate = template.Must(template.New("command list").Parse(` 188 | var _{{.Name}}ClientSubCommands = []func() *cobra.Command{ {{ range .SubCommands }} 189 | {{ . }},{{end}} 190 | } 191 | `)) 192 | 193 | func (c *client) generateCommandsList(name string, subCommands []string) { 194 | var b bytes.Buffer 195 | err := generateCommandListTemplate.Execute(&b, struct { 196 | Name string 197 | SubCommands []string 198 | }{ 199 | Name: name, 200 | SubCommands: subCommands, 201 | }) 202 | if err != nil { 203 | c.gen.Error(err, "exec cmd list template") 204 | } 205 | c.P(b.String()) 206 | c.P() 207 | } 208 | 209 | var generateCommandTemplateCode = ` 210 | var _Default{{.Name}}ClientCommandConfig = _New{{.Name}}ClientCommandConfig() 211 | 212 | type _{{.Name}}ClientCommandConfig struct { 213 | ServerAddr string 214 | RequestFile string 215 | Stdin bool 216 | PrintSampleRequest bool 217 | ResponseFormat string 218 | Timeout time.Duration 219 | TLS bool 220 | ServerName string 221 | InsecureSkipVerify bool 222 | CACertFile string 223 | CertFile string 224 | KeyFile string 225 | AuthToken string 226 | AuthTokenType string 227 | JWTKey string 228 | JWTKeyFile string 229 | } 230 | 231 | func _New{{.Name}}ClientCommandConfig() *_{{.Name}}ClientCommandConfig { 232 | c := &_{{.Name}}ClientCommandConfig{ 233 | ServerAddr: "localhost:8080", 234 | ResponseFormat: "json", 235 | Timeout: 10 * time.Second, 236 | AuthTokenType: "Bearer", 237 | } 238 | return c 239 | } 240 | 241 | func (o *_{{.Name}}ClientCommandConfig) AddFlags(fs *pflag.FlagSet) { 242 | fs.StringVarP(&o.ServerAddr, "server-addr", "s", o.ServerAddr, "server address in form of host:port") 243 | fs.StringVarP(&o.RequestFile, "request-file", "f", o.RequestFile, "client request file (must be json, yaml, or xml); use \"-\" for stdin + json") 244 | fs.BoolVar(&o.Stdin, "stdin", o.Stdin, "read client request from STDIN; alternative for '-f -'") 245 | fs.BoolVarP(&o.PrintSampleRequest, "print-sample-request", "p", o.PrintSampleRequest, "print sample request file and exit") 246 | fs.StringVarP(&o.ResponseFormat, "response-format", "o", o.ResponseFormat, "response format (json, prettyjson, yaml, or xml)") 247 | fs.DurationVar(&o.Timeout, "timeout", o.Timeout, "client connection timeout") 248 | fs.BoolVar(&o.TLS, "tls", o.TLS, "enable tls") 249 | fs.StringVar(&o.ServerName, "tls-server-name", o.ServerName, "tls server name override") 250 | fs.BoolVar(&o.InsecureSkipVerify, "tls-insecure-skip-verify", o.InsecureSkipVerify, "INSECURE: skip tls checks") 251 | fs.StringVar(&o.CACertFile, "tls-ca-cert-file", o.CACertFile, "ca certificate file") 252 | fs.StringVar(&o.CertFile, "tls-cert-file", o.CertFile, "client certificate file") 253 | fs.StringVar(&o.KeyFile, "tls-key-file", o.KeyFile, "client key file") 254 | fs.StringVar(&o.AuthToken, "auth-token", o.AuthToken, "authorization token") 255 | fs.StringVar(&o.AuthTokenType, "auth-token-type", o.AuthTokenType, "authorization token type") 256 | fs.StringVar(&o.JWTKey, "jwt-key", o.JWTKey, "jwt key") 257 | fs.StringVar(&o.JWTKeyFile, "jwt-key-file", o.JWTKeyFile, "jwt key file") 258 | } 259 | 260 | func {{.Name}}ClientCommand() *cobra.Command { 261 | cmd := &cobra.Command { 262 | Use: "{{.UseName}}", 263 | } 264 | _Default{{.Name}}ClientCommandConfig.AddFlags(cmd.PersistentFlags()) 265 | 266 | for _, s := range _{{.Name}}ClientSubCommands { 267 | cmd.AddCommand(s()) 268 | } 269 | return cmd 270 | } 271 | 272 | func _Dial{{.Name}}() (*grpc.ClientConn, {{.Name}}Client, error) { 273 | cfg := _Default{{.Name}}ClientCommandConfig 274 | opts := []grpc.DialOption{ 275 | grpc.WithBlock(), 276 | grpc.WithTimeout(cfg.Timeout), 277 | } 278 | if cfg.TLS { 279 | tlsConfig := &tls.Config{} 280 | if cfg.InsecureSkipVerify { 281 | tlsConfig.InsecureSkipVerify = true 282 | } 283 | if cfg.CACertFile != "" { 284 | cacert, err := ioutil.ReadFile(cfg.CACertFile) 285 | if err != nil { 286 | return nil, nil, fmt.Errorf("ca cert: %v", err) 287 | } 288 | certpool := x509.NewCertPool() 289 | certpool.AppendCertsFromPEM(cacert) 290 | tlsConfig.RootCAs = certpool 291 | } 292 | if cfg.CertFile != "" { 293 | if cfg.KeyFile == "" { 294 | return nil, nil, fmt.Errorf("missing key file") 295 | } 296 | pair, err := tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile) 297 | if err != nil { 298 | return nil, nil, fmt.Errorf("cert/key: %v", err) 299 | } 300 | tlsConfig.Certificates = []tls.Certificate{pair} 301 | } 302 | if cfg.ServerName != "" { 303 | tlsConfig.ServerName = cfg.ServerName 304 | } else { 305 | addr, _, _ := net.SplitHostPort(cfg.ServerAddr) 306 | tlsConfig.ServerName = addr 307 | } 308 | //tlsConfig.BuildNameToCertificate() 309 | cred := credentials.NewTLS(tlsConfig) 310 | opts = append(opts, grpc.WithTransportCredentials(cred)) 311 | } else { 312 | opts = append(opts, grpc.WithInsecure()) 313 | } 314 | if cfg.AuthToken != "" { 315 | cred := oauth.NewOauthAccess(&oauth2.Token{ 316 | AccessToken: cfg.AuthToken, 317 | TokenType: cfg.AuthTokenType, 318 | }) 319 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 320 | } 321 | if cfg.JWTKey != "" { 322 | cred, err := oauth.NewJWTAccessFromKey([]byte(cfg.JWTKey)) 323 | if err != nil { 324 | return nil, nil, fmt.Errorf("jwt key: %v", err) 325 | } 326 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 327 | } 328 | if cfg.JWTKeyFile != "" { 329 | cred, err := oauth.NewJWTAccessFromFile(cfg.JWTKeyFile) 330 | if err != nil { 331 | return nil, nil, fmt.Errorf("jwt key file: %v", err) 332 | } 333 | opts = append(opts, grpc.WithPerRPCCredentials(cred)) 334 | } 335 | conn, err := grpc.Dial(cfg.ServerAddr, opts...) 336 | if err != nil { 337 | return nil, nil, err 338 | } 339 | return conn, New{{.Name}}Client(conn), nil 340 | } 341 | 342 | type _{{.Name}}RoundTripFunc func(cli {{.Name}}Client, in iocodec.Decoder, out iocodec.Encoder) error 343 | 344 | func _{{.Name}}RoundTrip(sample interface{}, fn _{{.Name}}RoundTripFunc) error { 345 | cfg := _Default{{.Name}}ClientCommandConfig 346 | var em iocodec.EncoderMaker 347 | var ok bool 348 | if cfg.ResponseFormat == "" { 349 | em = iocodec.DefaultEncoders["json"] 350 | } else { 351 | em, ok = iocodec.DefaultEncoders[cfg.ResponseFormat] 352 | if !ok { 353 | return fmt.Errorf("invalid response format: %q", cfg.ResponseFormat) 354 | } 355 | } 356 | if cfg.PrintSampleRequest { 357 | return em.NewEncoder(os.Stdout).Encode(sample) 358 | } 359 | // read the input request, first from stdin, then from a file, otherwise from args only 360 | var d iocodec.Decoder 361 | if cfg.Stdin || cfg.RequestFile == "-" { 362 | d = iocodec.DefaultDecoders["json"].NewDecoder(os.Stdin) 363 | } else if cfg.RequestFile != "" { 364 | f, err := os.Open(cfg.RequestFile) 365 | if err != nil { 366 | return fmt.Errorf("request file: %v", err) 367 | } 368 | defer f.Close() 369 | ext := filepath.Ext(cfg.RequestFile) 370 | if len(ext) > 0 && ext[0] == '.' { 371 | ext = ext[1:] 372 | } 373 | dm, ok := iocodec.DefaultDecoders[ext] 374 | if !ok { 375 | return fmt.Errorf("invalid request file format: %q", ext) 376 | } 377 | d = dm.NewDecoder(f) 378 | } else { 379 | d = iocodec.DefaultDecoders["noop"].NewDecoder(os.Stdin) 380 | } 381 | conn, client, err := _Dial{{.Name}}() 382 | if err != nil { 383 | return err 384 | } 385 | defer conn.Close() 386 | return fn(client, d, em.NewEncoder(os.Stdout)) 387 | } 388 | ` 389 | 390 | var generateCommandTemplate = template.Must(template.New("cmd").Parse(generateCommandTemplateCode)) 391 | 392 | func (c *client) generateCommand(servName string) { 393 | var b bytes.Buffer 394 | err := generateCommandTemplate.Execute(&b, struct { 395 | Name string 396 | UseName string 397 | }{ 398 | Name: servName, 399 | UseName: strings.ToLower(servName), 400 | }) 401 | if err != nil { 402 | c.gen.Error(err, "exec cmd template") 403 | } 404 | c.P(b.String()) 405 | c.P() 406 | } 407 | 408 | var generateSubcommandTemplateCode = ` 409 | func _{{.FullName}}ClientCommand() *cobra.Command { 410 | reqArgs := {{ .InitializeRequestFlagsObj }} 411 | 412 | cmd := &cobra.Command{ 413 | Use: "{{.UseName}}", 414 | Long: "{{ .Name }} client; call by piping a request in to stdin (--stdin), reading a file (--file), or via flags per field", 415 | Example: "TODO: print protobuf method comments here", 416 | Run: func(cmd *cobra.Command, args []string) { 417 | var v {{ with .InputPackage }}{{ . }}.{{ end }}{{.InputType}} 418 | err := _{{.ServiceName}}RoundTrip(v, func(cli {{.ServiceName}}Client, in iocodec.Decoder, out iocodec.Encoder) error { 419 | {{if .ClientStream}} 420 | stream, err := cli.{{.Name}}(context.Background()) 421 | if err != nil { 422 | return err 423 | } 424 | for { 425 | err = in.Decode(&v) 426 | if err == io.EOF { 427 | stream.CloseSend() 428 | break 429 | } 430 | if err != nil { 431 | return err 432 | } 433 | err = stream.Send(&v) 434 | if err != nil { 435 | return err 436 | } 437 | } 438 | {{else}} 439 | err := in.Decode(&v) 440 | if err != nil { 441 | return err 442 | } 443 | {{if .ServerStream}} 444 | stream, err := cli.{{.Name}}(context.Background(), &v) 445 | {{else}} 446 | proto.Merge(&v, reqArgs) 447 | resp, err := cli.{{.Name}}(context.Background(), &v) 448 | {{end}} 449 | if err != nil { 450 | return err 451 | } 452 | {{end}} 453 | {{if .ServerStream}} 454 | for { 455 | v, err := stream.Recv() 456 | if err == io.EOF { 457 | break 458 | } 459 | if err != nil { 460 | return err 461 | } 462 | err = out.Encode(v) 463 | if err != nil { 464 | return err 465 | } 466 | } 467 | return nil 468 | {{else}} 469 | {{if .ClientStream}} 470 | resp, err := stream.CloseAndRecv() 471 | if err != nil { 472 | return err 473 | } 474 | {{end}} 475 | return out.Encode(resp) 476 | {{end}} 477 | }) 478 | if err != nil { 479 | log.Fatal(err) 480 | } 481 | }, 482 | } 483 | 484 | {{ range .RequestFlags }} 485 | cmd{{ . }}{{ end }} 486 | 487 | return cmd 488 | } 489 | ` 490 | 491 | var generateSubcommandTemplate = template.Must(template.New("subcmd").Parse(generateSubcommandTemplateCode)) 492 | 493 | // writes the subcommand to c.P and returns a golang fragment which is a reference to the constructor for this method 494 | func (c *client) generateSubcommand(servName string, file *generator.FileDescriptor, method *pb.MethodDescriptorProto) string { 495 | /* 496 | if method.GetClientStreaming() || method.GetServerStreaming() { 497 | return // TODO: handle streams correctly 498 | } 499 | */ 500 | origMethName := method.GetName() 501 | methName := generator.CamelCase(origMethName) 502 | if reservedClientName[methName] { 503 | methName += "_" 504 | } 505 | 506 | importName, inputPackage, inputType := inputNames(method.GetInputType()) 507 | if inputPackage == file.PackageName() { 508 | importName = "" 509 | } 510 | 511 | // TODO: fix below 512 | _ = importName 513 | 514 | types := make(protoTypeCache) 515 | inputDesc, _, _ := types.byName(file.MessageType, inputType, noop /*prefix("// ", c.P)*/) 516 | obj, reqArgFlags := c.generateRequestFlags(file, inputDesc, types) 517 | 518 | var b bytes.Buffer 519 | err := generateSubcommandTemplate.Execute(&b, struct { 520 | Name string 521 | UseName string 522 | ServiceName string 523 | FullName string 524 | InputPackage string 525 | InputType string 526 | InitializeRequestFlagsObj string 527 | RequestFlags []string 528 | ClientStream bool 529 | ServerStream bool 530 | }{ 531 | Name: methName, 532 | UseName: strings.ToLower(methName), 533 | ServiceName: servName, 534 | FullName: servName + methName, 535 | InputPackage: "", /*importName TODO: fix - not needed for Tetrate's protos today*/ 536 | InputType: inputType, 537 | InitializeRequestFlagsObj: obj, 538 | RequestFlags: reqArgFlags, 539 | ClientStream: method.GetClientStreaming(), 540 | ServerStream: method.GetServerStreaming(), 541 | }) 542 | if err != nil { 543 | c.gen.Error(err, "exec subcmd template") 544 | } 545 | c.P(b.String()) 546 | c.P() 547 | return "_" + servName + methName + "ClientCommand" 548 | } 549 | 550 | func inputNames(s string) (importName, inputPackage, inputType string) { 551 | _, typ := path.Split(s) // e.g. `.pkg.Type` 552 | typz := strings.Split(strings.Trim(typ, `.`), ".") 553 | if len(typz) < 2 { 554 | return 555 | } 556 | typeIdx := len(typz) - 1 557 | 558 | // .pkg.subpkg.Type -> pkg_subpkg_pb 559 | importName = fmt.Sprintf("%s_pb", strings.Join(typz[:typeIdx], `_`)) 560 | 561 | // .pkg.subpkg.Type -> pkg.subpkg 562 | inputPackage = strings.Join(typz[:typeIdx], `.`) 563 | 564 | // .pkg.subpkg.Type -> Type 565 | inputType = typz[typeIdx] 566 | 567 | return 568 | } 569 | -------------------------------------------------------------------------------- /example/pb/maplist.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-gogo. DO NOT EDIT. 2 | // source: maplist.proto 3 | 4 | package pb 5 | 6 | import proto "github.com/golang/protobuf/proto" 7 | import fmt "fmt" 8 | import math "math" 9 | 10 | import ( 11 | context "golang.org/x/net/context" 12 | grpc "google.golang.org/grpc" 13 | ) 14 | 15 | import io "io" 16 | 17 | // Reference imports to suppress errors if they are not otherwise used. 18 | var _ = proto.Marshal 19 | var _ = fmt.Errorf 20 | var _ = math.Inf 21 | 22 | // This is a compile-time assertion to ensure that this generated file 23 | // is compatible with the proto package it is being compiled against. 24 | // A compilation error at this line likely means your copy of the 25 | // proto package needs to be updated. 26 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package 27 | 28 | type MapListRequest struct { 29 | MapField map[string]string `protobuf:"bytes,1,rep,name=map_field,json=mapField" json:"map_field,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` 30 | ListField []string `protobuf:"bytes,2,rep,name=list_field,json=listField" json:"list_field,omitempty"` 31 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 32 | XXX_unrecognized []byte `json:"-"` 33 | XXX_sizecache int32 `json:"-"` 34 | } 35 | 36 | func (m *MapListRequest) Reset() { *m = MapListRequest{} } 37 | func (m *MapListRequest) String() string { return proto.CompactTextString(m) } 38 | func (*MapListRequest) ProtoMessage() {} 39 | func (*MapListRequest) Descriptor() ([]byte, []int) { 40 | return fileDescriptor_maplist_c72b2737842081a8, []int{0} 41 | } 42 | func (m *MapListRequest) XXX_Unmarshal(b []byte) error { 43 | return m.Unmarshal(b) 44 | } 45 | func (m *MapListRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 46 | if deterministic { 47 | return xxx_messageInfo_MapListRequest.Marshal(b, m, deterministic) 48 | } else { 49 | b = b[:cap(b)] 50 | n, err := m.MarshalTo(b) 51 | if err != nil { 52 | return nil, err 53 | } 54 | return b[:n], nil 55 | } 56 | } 57 | func (dst *MapListRequest) XXX_Merge(src proto.Message) { 58 | xxx_messageInfo_MapListRequest.Merge(dst, src) 59 | } 60 | func (m *MapListRequest) XXX_Size() int { 61 | return m.Size() 62 | } 63 | func (m *MapListRequest) XXX_DiscardUnknown() { 64 | xxx_messageInfo_MapListRequest.DiscardUnknown(m) 65 | } 66 | 67 | var xxx_messageInfo_MapListRequest proto.InternalMessageInfo 68 | 69 | func (m *MapListRequest) GetMapField() map[string]string { 70 | if m != nil { 71 | return m.MapField 72 | } 73 | return nil 74 | } 75 | 76 | func (m *MapListRequest) GetListField() []string { 77 | if m != nil { 78 | return m.ListField 79 | } 80 | return nil 81 | } 82 | 83 | type MapListResponse struct { 84 | MapField map[string]string `protobuf:"bytes,1,rep,name=map_field,json=mapField" json:"map_field,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` 85 | ListField []string `protobuf:"bytes,2,rep,name=list_field,json=listField" json:"list_field,omitempty"` 86 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 87 | XXX_unrecognized []byte `json:"-"` 88 | XXX_sizecache int32 `json:"-"` 89 | } 90 | 91 | func (m *MapListResponse) Reset() { *m = MapListResponse{} } 92 | func (m *MapListResponse) String() string { return proto.CompactTextString(m) } 93 | func (*MapListResponse) ProtoMessage() {} 94 | func (*MapListResponse) Descriptor() ([]byte, []int) { 95 | return fileDescriptor_maplist_c72b2737842081a8, []int{1} 96 | } 97 | func (m *MapListResponse) XXX_Unmarshal(b []byte) error { 98 | return m.Unmarshal(b) 99 | } 100 | func (m *MapListResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 101 | if deterministic { 102 | return xxx_messageInfo_MapListResponse.Marshal(b, m, deterministic) 103 | } else { 104 | b = b[:cap(b)] 105 | n, err := m.MarshalTo(b) 106 | if err != nil { 107 | return nil, err 108 | } 109 | return b[:n], nil 110 | } 111 | } 112 | func (dst *MapListResponse) XXX_Merge(src proto.Message) { 113 | xxx_messageInfo_MapListResponse.Merge(dst, src) 114 | } 115 | func (m *MapListResponse) XXX_Size() int { 116 | return m.Size() 117 | } 118 | func (m *MapListResponse) XXX_DiscardUnknown() { 119 | xxx_messageInfo_MapListResponse.DiscardUnknown(m) 120 | } 121 | 122 | var xxx_messageInfo_MapListResponse proto.InternalMessageInfo 123 | 124 | func (m *MapListResponse) GetMapField() map[string]string { 125 | if m != nil { 126 | return m.MapField 127 | } 128 | return nil 129 | } 130 | 131 | func (m *MapListResponse) GetListField() []string { 132 | if m != nil { 133 | return m.ListField 134 | } 135 | return nil 136 | } 137 | 138 | func init() { 139 | proto.RegisterType((*MapListRequest)(nil), "pb.MapListRequest") 140 | proto.RegisterMapType((map[string]string)(nil), "pb.MapListRequest.MapFieldEntry") 141 | proto.RegisterType((*MapListResponse)(nil), "pb.MapListResponse") 142 | proto.RegisterMapType((map[string]string)(nil), "pb.MapListResponse.MapFieldEntry") 143 | } 144 | 145 | // Reference imports to suppress errors if they are not otherwise used. 146 | var _ context.Context 147 | var _ grpc.ClientConn 148 | 149 | // This is a compile-time assertion to ensure that this generated file 150 | // is compatible with the grpc package it is being compiled against. 151 | const _ = grpc.SupportPackageIsVersion4 152 | 153 | // MapListClient is the client API for MapList service. 154 | // 155 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 156 | type MapListClient interface { 157 | Method(ctx context.Context, in *MapListRequest, opts ...grpc.CallOption) (*MapListResponse, error) 158 | } 159 | 160 | type mapListClient struct { 161 | cc *grpc.ClientConn 162 | } 163 | 164 | func NewMapListClient(cc *grpc.ClientConn) MapListClient { 165 | return &mapListClient{cc} 166 | } 167 | 168 | func (c *mapListClient) Method(ctx context.Context, in *MapListRequest, opts ...grpc.CallOption) (*MapListResponse, error) { 169 | out := new(MapListResponse) 170 | err := c.cc.Invoke(ctx, "/pb.MapList/Method", in, out, opts...) 171 | if err != nil { 172 | return nil, err 173 | } 174 | return out, nil 175 | } 176 | 177 | // MapListServer is the server API for MapList service. 178 | type MapListServer interface { 179 | Method(context.Context, *MapListRequest) (*MapListResponse, error) 180 | } 181 | 182 | func RegisterMapListServer(s *grpc.Server, srv MapListServer) { 183 | s.RegisterService(&_MapList_serviceDesc, srv) 184 | } 185 | 186 | func _MapList_Method_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 187 | in := new(MapListRequest) 188 | if err := dec(in); err != nil { 189 | return nil, err 190 | } 191 | if interceptor == nil { 192 | return srv.(MapListServer).Method(ctx, in) 193 | } 194 | info := &grpc.UnaryServerInfo{ 195 | Server: srv, 196 | FullMethod: "/pb.MapList/Method", 197 | } 198 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 199 | return srv.(MapListServer).Method(ctx, req.(*MapListRequest)) 200 | } 201 | return interceptor(ctx, in, info, handler) 202 | } 203 | 204 | var _MapList_serviceDesc = grpc.ServiceDesc{ 205 | ServiceName: "pb.MapList", 206 | HandlerType: (*MapListServer)(nil), 207 | Methods: []grpc.MethodDesc{ 208 | { 209 | MethodName: "Method", 210 | Handler: _MapList_Method_Handler, 211 | }, 212 | }, 213 | Streams: []grpc.StreamDesc{}, 214 | Metadata: "maplist.proto", 215 | } 216 | 217 | func (m *MapListRequest) Marshal() (dAtA []byte, err error) { 218 | size := m.Size() 219 | dAtA = make([]byte, size) 220 | n, err := m.MarshalTo(dAtA) 221 | if err != nil { 222 | return nil, err 223 | } 224 | return dAtA[:n], nil 225 | } 226 | 227 | func (m *MapListRequest) MarshalTo(dAtA []byte) (int, error) { 228 | var i int 229 | _ = i 230 | var l int 231 | _ = l 232 | if len(m.MapField) > 0 { 233 | for k, _ := range m.MapField { 234 | dAtA[i] = 0xa 235 | i++ 236 | v := m.MapField[k] 237 | mapSize := 1 + len(k) + sovMaplist(uint64(len(k))) + 1 + len(v) + sovMaplist(uint64(len(v))) 238 | i = encodeVarintMaplist(dAtA, i, uint64(mapSize)) 239 | dAtA[i] = 0xa 240 | i++ 241 | i = encodeVarintMaplist(dAtA, i, uint64(len(k))) 242 | i += copy(dAtA[i:], k) 243 | dAtA[i] = 0x12 244 | i++ 245 | i = encodeVarintMaplist(dAtA, i, uint64(len(v))) 246 | i += copy(dAtA[i:], v) 247 | } 248 | } 249 | if len(m.ListField) > 0 { 250 | for _, s := range m.ListField { 251 | dAtA[i] = 0x12 252 | i++ 253 | l = len(s) 254 | for l >= 1<<7 { 255 | dAtA[i] = uint8(uint64(l)&0x7f | 0x80) 256 | l >>= 7 257 | i++ 258 | } 259 | dAtA[i] = uint8(l) 260 | i++ 261 | i += copy(dAtA[i:], s) 262 | } 263 | } 264 | if m.XXX_unrecognized != nil { 265 | i += copy(dAtA[i:], m.XXX_unrecognized) 266 | } 267 | return i, nil 268 | } 269 | 270 | func (m *MapListResponse) Marshal() (dAtA []byte, err error) { 271 | size := m.Size() 272 | dAtA = make([]byte, size) 273 | n, err := m.MarshalTo(dAtA) 274 | if err != nil { 275 | return nil, err 276 | } 277 | return dAtA[:n], nil 278 | } 279 | 280 | func (m *MapListResponse) MarshalTo(dAtA []byte) (int, error) { 281 | var i int 282 | _ = i 283 | var l int 284 | _ = l 285 | if len(m.MapField) > 0 { 286 | for k, _ := range m.MapField { 287 | dAtA[i] = 0xa 288 | i++ 289 | v := m.MapField[k] 290 | mapSize := 1 + len(k) + sovMaplist(uint64(len(k))) + 1 + len(v) + sovMaplist(uint64(len(v))) 291 | i = encodeVarintMaplist(dAtA, i, uint64(mapSize)) 292 | dAtA[i] = 0xa 293 | i++ 294 | i = encodeVarintMaplist(dAtA, i, uint64(len(k))) 295 | i += copy(dAtA[i:], k) 296 | dAtA[i] = 0x12 297 | i++ 298 | i = encodeVarintMaplist(dAtA, i, uint64(len(v))) 299 | i += copy(dAtA[i:], v) 300 | } 301 | } 302 | if len(m.ListField) > 0 { 303 | for _, s := range m.ListField { 304 | dAtA[i] = 0x12 305 | i++ 306 | l = len(s) 307 | for l >= 1<<7 { 308 | dAtA[i] = uint8(uint64(l)&0x7f | 0x80) 309 | l >>= 7 310 | i++ 311 | } 312 | dAtA[i] = uint8(l) 313 | i++ 314 | i += copy(dAtA[i:], s) 315 | } 316 | } 317 | if m.XXX_unrecognized != nil { 318 | i += copy(dAtA[i:], m.XXX_unrecognized) 319 | } 320 | return i, nil 321 | } 322 | 323 | func encodeVarintMaplist(dAtA []byte, offset int, v uint64) int { 324 | for v >= 1<<7 { 325 | dAtA[offset] = uint8(v&0x7f | 0x80) 326 | v >>= 7 327 | offset++ 328 | } 329 | dAtA[offset] = uint8(v) 330 | return offset + 1 331 | } 332 | func (m *MapListRequest) Size() (n int) { 333 | if m == nil { 334 | return 0 335 | } 336 | var l int 337 | _ = l 338 | if len(m.MapField) > 0 { 339 | for k, v := range m.MapField { 340 | _ = k 341 | _ = v 342 | mapEntrySize := 1 + len(k) + sovMaplist(uint64(len(k))) + 1 + len(v) + sovMaplist(uint64(len(v))) 343 | n += mapEntrySize + 1 + sovMaplist(uint64(mapEntrySize)) 344 | } 345 | } 346 | if len(m.ListField) > 0 { 347 | for _, s := range m.ListField { 348 | l = len(s) 349 | n += 1 + l + sovMaplist(uint64(l)) 350 | } 351 | } 352 | if m.XXX_unrecognized != nil { 353 | n += len(m.XXX_unrecognized) 354 | } 355 | return n 356 | } 357 | 358 | func (m *MapListResponse) Size() (n int) { 359 | if m == nil { 360 | return 0 361 | } 362 | var l int 363 | _ = l 364 | if len(m.MapField) > 0 { 365 | for k, v := range m.MapField { 366 | _ = k 367 | _ = v 368 | mapEntrySize := 1 + len(k) + sovMaplist(uint64(len(k))) + 1 + len(v) + sovMaplist(uint64(len(v))) 369 | n += mapEntrySize + 1 + sovMaplist(uint64(mapEntrySize)) 370 | } 371 | } 372 | if len(m.ListField) > 0 { 373 | for _, s := range m.ListField { 374 | l = len(s) 375 | n += 1 + l + sovMaplist(uint64(l)) 376 | } 377 | } 378 | if m.XXX_unrecognized != nil { 379 | n += len(m.XXX_unrecognized) 380 | } 381 | return n 382 | } 383 | 384 | func sovMaplist(x uint64) (n int) { 385 | for { 386 | n++ 387 | x >>= 7 388 | if x == 0 { 389 | break 390 | } 391 | } 392 | return n 393 | } 394 | func sozMaplist(x uint64) (n int) { 395 | return sovMaplist(uint64((x << 1) ^ uint64((int64(x) >> 63)))) 396 | } 397 | func (m *MapListRequest) Unmarshal(dAtA []byte) error { 398 | l := len(dAtA) 399 | iNdEx := 0 400 | for iNdEx < l { 401 | preIndex := iNdEx 402 | var wire uint64 403 | for shift := uint(0); ; shift += 7 { 404 | if shift >= 64 { 405 | return ErrIntOverflowMaplist 406 | } 407 | if iNdEx >= l { 408 | return io.ErrUnexpectedEOF 409 | } 410 | b := dAtA[iNdEx] 411 | iNdEx++ 412 | wire |= (uint64(b) & 0x7F) << shift 413 | if b < 0x80 { 414 | break 415 | } 416 | } 417 | fieldNum := int32(wire >> 3) 418 | wireType := int(wire & 0x7) 419 | if wireType == 4 { 420 | return fmt.Errorf("proto: MapListRequest: wiretype end group for non-group") 421 | } 422 | if fieldNum <= 0 { 423 | return fmt.Errorf("proto: MapListRequest: illegal tag %d (wire type %d)", fieldNum, wire) 424 | } 425 | switch fieldNum { 426 | case 1: 427 | if wireType != 2 { 428 | return fmt.Errorf("proto: wrong wireType = %d for field MapField", wireType) 429 | } 430 | var msglen int 431 | for shift := uint(0); ; shift += 7 { 432 | if shift >= 64 { 433 | return ErrIntOverflowMaplist 434 | } 435 | if iNdEx >= l { 436 | return io.ErrUnexpectedEOF 437 | } 438 | b := dAtA[iNdEx] 439 | iNdEx++ 440 | msglen |= (int(b) & 0x7F) << shift 441 | if b < 0x80 { 442 | break 443 | } 444 | } 445 | if msglen < 0 { 446 | return ErrInvalidLengthMaplist 447 | } 448 | postIndex := iNdEx + msglen 449 | if postIndex > l { 450 | return io.ErrUnexpectedEOF 451 | } 452 | if m.MapField == nil { 453 | m.MapField = make(map[string]string) 454 | } 455 | var mapkey string 456 | var mapvalue string 457 | for iNdEx < postIndex { 458 | entryPreIndex := iNdEx 459 | var wire uint64 460 | for shift := uint(0); ; shift += 7 { 461 | if shift >= 64 { 462 | return ErrIntOverflowMaplist 463 | } 464 | if iNdEx >= l { 465 | return io.ErrUnexpectedEOF 466 | } 467 | b := dAtA[iNdEx] 468 | iNdEx++ 469 | wire |= (uint64(b) & 0x7F) << shift 470 | if b < 0x80 { 471 | break 472 | } 473 | } 474 | fieldNum := int32(wire >> 3) 475 | if fieldNum == 1 { 476 | var stringLenmapkey uint64 477 | for shift := uint(0); ; shift += 7 { 478 | if shift >= 64 { 479 | return ErrIntOverflowMaplist 480 | } 481 | if iNdEx >= l { 482 | return io.ErrUnexpectedEOF 483 | } 484 | b := dAtA[iNdEx] 485 | iNdEx++ 486 | stringLenmapkey |= (uint64(b) & 0x7F) << shift 487 | if b < 0x80 { 488 | break 489 | } 490 | } 491 | intStringLenmapkey := int(stringLenmapkey) 492 | if intStringLenmapkey < 0 { 493 | return ErrInvalidLengthMaplist 494 | } 495 | postStringIndexmapkey := iNdEx + intStringLenmapkey 496 | if postStringIndexmapkey > l { 497 | return io.ErrUnexpectedEOF 498 | } 499 | mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) 500 | iNdEx = postStringIndexmapkey 501 | } else if fieldNum == 2 { 502 | var stringLenmapvalue uint64 503 | for shift := uint(0); ; shift += 7 { 504 | if shift >= 64 { 505 | return ErrIntOverflowMaplist 506 | } 507 | if iNdEx >= l { 508 | return io.ErrUnexpectedEOF 509 | } 510 | b := dAtA[iNdEx] 511 | iNdEx++ 512 | stringLenmapvalue |= (uint64(b) & 0x7F) << shift 513 | if b < 0x80 { 514 | break 515 | } 516 | } 517 | intStringLenmapvalue := int(stringLenmapvalue) 518 | if intStringLenmapvalue < 0 { 519 | return ErrInvalidLengthMaplist 520 | } 521 | postStringIndexmapvalue := iNdEx + intStringLenmapvalue 522 | if postStringIndexmapvalue > l { 523 | return io.ErrUnexpectedEOF 524 | } 525 | mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) 526 | iNdEx = postStringIndexmapvalue 527 | } else { 528 | iNdEx = entryPreIndex 529 | skippy, err := skipMaplist(dAtA[iNdEx:]) 530 | if err != nil { 531 | return err 532 | } 533 | if skippy < 0 { 534 | return ErrInvalidLengthMaplist 535 | } 536 | if (iNdEx + skippy) > postIndex { 537 | return io.ErrUnexpectedEOF 538 | } 539 | iNdEx += skippy 540 | } 541 | } 542 | m.MapField[mapkey] = mapvalue 543 | iNdEx = postIndex 544 | case 2: 545 | if wireType != 2 { 546 | return fmt.Errorf("proto: wrong wireType = %d for field ListField", wireType) 547 | } 548 | var stringLen uint64 549 | for shift := uint(0); ; shift += 7 { 550 | if shift >= 64 { 551 | return ErrIntOverflowMaplist 552 | } 553 | if iNdEx >= l { 554 | return io.ErrUnexpectedEOF 555 | } 556 | b := dAtA[iNdEx] 557 | iNdEx++ 558 | stringLen |= (uint64(b) & 0x7F) << shift 559 | if b < 0x80 { 560 | break 561 | } 562 | } 563 | intStringLen := int(stringLen) 564 | if intStringLen < 0 { 565 | return ErrInvalidLengthMaplist 566 | } 567 | postIndex := iNdEx + intStringLen 568 | if postIndex > l { 569 | return io.ErrUnexpectedEOF 570 | } 571 | m.ListField = append(m.ListField, string(dAtA[iNdEx:postIndex])) 572 | iNdEx = postIndex 573 | default: 574 | iNdEx = preIndex 575 | skippy, err := skipMaplist(dAtA[iNdEx:]) 576 | if err != nil { 577 | return err 578 | } 579 | if skippy < 0 { 580 | return ErrInvalidLengthMaplist 581 | } 582 | if (iNdEx + skippy) > l { 583 | return io.ErrUnexpectedEOF 584 | } 585 | m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) 586 | iNdEx += skippy 587 | } 588 | } 589 | 590 | if iNdEx > l { 591 | return io.ErrUnexpectedEOF 592 | } 593 | return nil 594 | } 595 | func (m *MapListResponse) Unmarshal(dAtA []byte) error { 596 | l := len(dAtA) 597 | iNdEx := 0 598 | for iNdEx < l { 599 | preIndex := iNdEx 600 | var wire uint64 601 | for shift := uint(0); ; shift += 7 { 602 | if shift >= 64 { 603 | return ErrIntOverflowMaplist 604 | } 605 | if iNdEx >= l { 606 | return io.ErrUnexpectedEOF 607 | } 608 | b := dAtA[iNdEx] 609 | iNdEx++ 610 | wire |= (uint64(b) & 0x7F) << shift 611 | if b < 0x80 { 612 | break 613 | } 614 | } 615 | fieldNum := int32(wire >> 3) 616 | wireType := int(wire & 0x7) 617 | if wireType == 4 { 618 | return fmt.Errorf("proto: MapListResponse: wiretype end group for non-group") 619 | } 620 | if fieldNum <= 0 { 621 | return fmt.Errorf("proto: MapListResponse: illegal tag %d (wire type %d)", fieldNum, wire) 622 | } 623 | switch fieldNum { 624 | case 1: 625 | if wireType != 2 { 626 | return fmt.Errorf("proto: wrong wireType = %d for field MapField", wireType) 627 | } 628 | var msglen int 629 | for shift := uint(0); ; shift += 7 { 630 | if shift >= 64 { 631 | return ErrIntOverflowMaplist 632 | } 633 | if iNdEx >= l { 634 | return io.ErrUnexpectedEOF 635 | } 636 | b := dAtA[iNdEx] 637 | iNdEx++ 638 | msglen |= (int(b) & 0x7F) << shift 639 | if b < 0x80 { 640 | break 641 | } 642 | } 643 | if msglen < 0 { 644 | return ErrInvalidLengthMaplist 645 | } 646 | postIndex := iNdEx + msglen 647 | if postIndex > l { 648 | return io.ErrUnexpectedEOF 649 | } 650 | if m.MapField == nil { 651 | m.MapField = make(map[string]string) 652 | } 653 | var mapkey string 654 | var mapvalue string 655 | for iNdEx < postIndex { 656 | entryPreIndex := iNdEx 657 | var wire uint64 658 | for shift := uint(0); ; shift += 7 { 659 | if shift >= 64 { 660 | return ErrIntOverflowMaplist 661 | } 662 | if iNdEx >= l { 663 | return io.ErrUnexpectedEOF 664 | } 665 | b := dAtA[iNdEx] 666 | iNdEx++ 667 | wire |= (uint64(b) & 0x7F) << shift 668 | if b < 0x80 { 669 | break 670 | } 671 | } 672 | fieldNum := int32(wire >> 3) 673 | if fieldNum == 1 { 674 | var stringLenmapkey uint64 675 | for shift := uint(0); ; shift += 7 { 676 | if shift >= 64 { 677 | return ErrIntOverflowMaplist 678 | } 679 | if iNdEx >= l { 680 | return io.ErrUnexpectedEOF 681 | } 682 | b := dAtA[iNdEx] 683 | iNdEx++ 684 | stringLenmapkey |= (uint64(b) & 0x7F) << shift 685 | if b < 0x80 { 686 | break 687 | } 688 | } 689 | intStringLenmapkey := int(stringLenmapkey) 690 | if intStringLenmapkey < 0 { 691 | return ErrInvalidLengthMaplist 692 | } 693 | postStringIndexmapkey := iNdEx + intStringLenmapkey 694 | if postStringIndexmapkey > l { 695 | return io.ErrUnexpectedEOF 696 | } 697 | mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) 698 | iNdEx = postStringIndexmapkey 699 | } else if fieldNum == 2 { 700 | var stringLenmapvalue uint64 701 | for shift := uint(0); ; shift += 7 { 702 | if shift >= 64 { 703 | return ErrIntOverflowMaplist 704 | } 705 | if iNdEx >= l { 706 | return io.ErrUnexpectedEOF 707 | } 708 | b := dAtA[iNdEx] 709 | iNdEx++ 710 | stringLenmapvalue |= (uint64(b) & 0x7F) << shift 711 | if b < 0x80 { 712 | break 713 | } 714 | } 715 | intStringLenmapvalue := int(stringLenmapvalue) 716 | if intStringLenmapvalue < 0 { 717 | return ErrInvalidLengthMaplist 718 | } 719 | postStringIndexmapvalue := iNdEx + intStringLenmapvalue 720 | if postStringIndexmapvalue > l { 721 | return io.ErrUnexpectedEOF 722 | } 723 | mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) 724 | iNdEx = postStringIndexmapvalue 725 | } else { 726 | iNdEx = entryPreIndex 727 | skippy, err := skipMaplist(dAtA[iNdEx:]) 728 | if err != nil { 729 | return err 730 | } 731 | if skippy < 0 { 732 | return ErrInvalidLengthMaplist 733 | } 734 | if (iNdEx + skippy) > postIndex { 735 | return io.ErrUnexpectedEOF 736 | } 737 | iNdEx += skippy 738 | } 739 | } 740 | m.MapField[mapkey] = mapvalue 741 | iNdEx = postIndex 742 | case 2: 743 | if wireType != 2 { 744 | return fmt.Errorf("proto: wrong wireType = %d for field ListField", wireType) 745 | } 746 | var stringLen uint64 747 | for shift := uint(0); ; shift += 7 { 748 | if shift >= 64 { 749 | return ErrIntOverflowMaplist 750 | } 751 | if iNdEx >= l { 752 | return io.ErrUnexpectedEOF 753 | } 754 | b := dAtA[iNdEx] 755 | iNdEx++ 756 | stringLen |= (uint64(b) & 0x7F) << shift 757 | if b < 0x80 { 758 | break 759 | } 760 | } 761 | intStringLen := int(stringLen) 762 | if intStringLen < 0 { 763 | return ErrInvalidLengthMaplist 764 | } 765 | postIndex := iNdEx + intStringLen 766 | if postIndex > l { 767 | return io.ErrUnexpectedEOF 768 | } 769 | m.ListField = append(m.ListField, string(dAtA[iNdEx:postIndex])) 770 | iNdEx = postIndex 771 | default: 772 | iNdEx = preIndex 773 | skippy, err := skipMaplist(dAtA[iNdEx:]) 774 | if err != nil { 775 | return err 776 | } 777 | if skippy < 0 { 778 | return ErrInvalidLengthMaplist 779 | } 780 | if (iNdEx + skippy) > l { 781 | return io.ErrUnexpectedEOF 782 | } 783 | m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) 784 | iNdEx += skippy 785 | } 786 | } 787 | 788 | if iNdEx > l { 789 | return io.ErrUnexpectedEOF 790 | } 791 | return nil 792 | } 793 | func skipMaplist(dAtA []byte) (n int, err error) { 794 | l := len(dAtA) 795 | iNdEx := 0 796 | for iNdEx < l { 797 | var wire uint64 798 | for shift := uint(0); ; shift += 7 { 799 | if shift >= 64 { 800 | return 0, ErrIntOverflowMaplist 801 | } 802 | if iNdEx >= l { 803 | return 0, io.ErrUnexpectedEOF 804 | } 805 | b := dAtA[iNdEx] 806 | iNdEx++ 807 | wire |= (uint64(b) & 0x7F) << shift 808 | if b < 0x80 { 809 | break 810 | } 811 | } 812 | wireType := int(wire & 0x7) 813 | switch wireType { 814 | case 0: 815 | for shift := uint(0); ; shift += 7 { 816 | if shift >= 64 { 817 | return 0, ErrIntOverflowMaplist 818 | } 819 | if iNdEx >= l { 820 | return 0, io.ErrUnexpectedEOF 821 | } 822 | iNdEx++ 823 | if dAtA[iNdEx-1] < 0x80 { 824 | break 825 | } 826 | } 827 | return iNdEx, nil 828 | case 1: 829 | iNdEx += 8 830 | return iNdEx, nil 831 | case 2: 832 | var length int 833 | for shift := uint(0); ; shift += 7 { 834 | if shift >= 64 { 835 | return 0, ErrIntOverflowMaplist 836 | } 837 | if iNdEx >= l { 838 | return 0, io.ErrUnexpectedEOF 839 | } 840 | b := dAtA[iNdEx] 841 | iNdEx++ 842 | length |= (int(b) & 0x7F) << shift 843 | if b < 0x80 { 844 | break 845 | } 846 | } 847 | iNdEx += length 848 | if length < 0 { 849 | return 0, ErrInvalidLengthMaplist 850 | } 851 | return iNdEx, nil 852 | case 3: 853 | for { 854 | var innerWire uint64 855 | var start int = iNdEx 856 | for shift := uint(0); ; shift += 7 { 857 | if shift >= 64 { 858 | return 0, ErrIntOverflowMaplist 859 | } 860 | if iNdEx >= l { 861 | return 0, io.ErrUnexpectedEOF 862 | } 863 | b := dAtA[iNdEx] 864 | iNdEx++ 865 | innerWire |= (uint64(b) & 0x7F) << shift 866 | if b < 0x80 { 867 | break 868 | } 869 | } 870 | innerWireType := int(innerWire & 0x7) 871 | if innerWireType == 4 { 872 | break 873 | } 874 | next, err := skipMaplist(dAtA[start:]) 875 | if err != nil { 876 | return 0, err 877 | } 878 | iNdEx = start + next 879 | } 880 | return iNdEx, nil 881 | case 4: 882 | return iNdEx, nil 883 | case 5: 884 | iNdEx += 4 885 | return iNdEx, nil 886 | default: 887 | return 0, fmt.Errorf("proto: illegal wireType %d", wireType) 888 | } 889 | } 890 | panic("unreachable") 891 | } 892 | 893 | var ( 894 | ErrInvalidLengthMaplist = fmt.Errorf("proto: negative length found during unmarshaling") 895 | ErrIntOverflowMaplist = fmt.Errorf("proto: integer overflow") 896 | ) 897 | 898 | func init() { proto.RegisterFile("maplist.proto", fileDescriptor_maplist_c72b2737842081a8) } 899 | 900 | var fileDescriptor_maplist_c72b2737842081a8 = []byte{ 901 | // 239 bytes of a gzipped FileDescriptorProto 902 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcd, 0x4d, 0x2c, 0xc8, 903 | 0xc9, 0x2c, 0x2e, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2a, 0x48, 0x52, 0x5a, 0xcd, 904 | 0xc8, 0xc5, 0xe7, 0x9b, 0x58, 0xe0, 0x93, 0x59, 0x5c, 0x12, 0x94, 0x5a, 0x58, 0x9a, 0x5a, 0x5c, 905 | 0x22, 0x64, 0xcb, 0xc5, 0x99, 0x9b, 0x58, 0x10, 0x9f, 0x96, 0x99, 0x9a, 0x93, 0x22, 0xc1, 0xa8, 906 | 0xc0, 0xac, 0xc1, 0x6d, 0xa4, 0xa0, 0x57, 0x90, 0xa4, 0x87, 0xaa, 0x0c, 0xc4, 0x75, 0x03, 0x29, 907 | 0x71, 0xcd, 0x2b, 0x29, 0xaa, 0x0c, 0xe2, 0xc8, 0x85, 0x72, 0x85, 0x64, 0xb9, 0xb8, 0x40, 0x76, 908 | 0x40, 0xf5, 0x33, 0x29, 0x30, 0x6b, 0x70, 0x06, 0x71, 0x82, 0x44, 0xc0, 0xd2, 0x52, 0xd6, 0x5c, 909 | 0xbc, 0x28, 0x3a, 0x85, 0x04, 0xb8, 0x98, 0xb3, 0x53, 0x2b, 0x25, 0x18, 0x15, 0x18, 0x35, 0x38, 910 | 0x83, 0x40, 0x4c, 0x21, 0x11, 0x2e, 0xd6, 0xb2, 0xc4, 0x9c, 0xd2, 0x54, 0x09, 0x26, 0xb0, 0x18, 911 | 0x84, 0x63, 0xc5, 0x64, 0xc1, 0xa8, 0xb4, 0x96, 0x91, 0x8b, 0x1f, 0xee, 0x8c, 0xe2, 0x82, 0xfc, 912 | 0xbc, 0xe2, 0x54, 0x21, 0x3b, 0x4c, 0xe7, 0x2a, 0xa2, 0x38, 0x17, 0xa2, 0x6e, 0x20, 0xdc, 0x6b, 913 | 0x64, 0xc3, 0xc5, 0x0e, 0x75, 0x86, 0x90, 0x21, 0x17, 0x9b, 0x6f, 0x6a, 0x49, 0x46, 0x7e, 0x8a, 914 | 0x90, 0x10, 0x66, 0x60, 0x4a, 0x09, 0x63, 0x71, 0xb1, 0x93, 0xc0, 0x89, 0x47, 0x72, 0x8c, 0x17, 915 | 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe3, 0xb1, 0x1c, 0x43, 0x12, 0x1b, 0x38, 0xe2, 916 | 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xd1, 0x8c, 0xaf, 0xc9, 0x01, 0x00, 0x00, 917 | } 918 | --------------------------------------------------------------------------------