├── .gitignore ├── template └── {{ProjectName}} │ ├── scripts │ ├── version.sh │ ├── test.sh │ ├── integration.sh │ ├── installprotoc.sh │ ├── docker.sh │ ├── awx.sh │ ├── build.sh │ └── genproto.sh │ ├── .gitignore │ ├── version.go │ ├── pkg │ ├── version.go │ ├── utils.go │ ├── pubsub │ │ ├── pubsub.go │ │ └── kafka.go │ ├── signal.go │ ├── prometheus.go │ ├── metrics │ │ ├── measure.go │ │ └── metrics.go │ ├── db │ │ ├── posgres.go │ │ └── cassandra.go │ └── log.go │ ├── internal │ ├── entity │ │ └── example.go │ ├── repositories │ │ ├── errors.go │ │ └── example_repo.go │ ├── service │ │ └── service_impl.go │ └── config.go │ ├── main.go │ ├── test │ ├── example_test.go │ ├── config.yaml │ ├── grpc_test.go │ ├── main_test.go │ └── http_test.go │ ├── api │ ├── http │ │ ├── routes.go │ │ ├── stub.go │ │ └── handler.go │ ├── proto │ │ ├── rpc.proto │ │ └── src │ │ │ └── rpc.pb.go │ └── grpc │ │ ├── handler.go │ │ ├── errors.go │ │ ├── util.go │ │ └── stub.go │ ├── assets │ └── cassandra │ │ └── history_messages.cql │ ├── testkit │ ├── config.go │ └── grpc.go │ ├── README.md │ ├── go.mod │ ├── .gitlab-ci.yml │ ├── cmd │ └── server.go │ ├── Makefile │ └── go.sum ├── README.md └── project.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* -------------------------------------------------------------------------------- /template/{{ProjectName}}/scripts/version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo 0.0-1 -------------------------------------------------------------------------------- /template/{{ProjectName}}/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | vendor 3 | build/release 4 | build/debug 5 | build/_proto -------------------------------------------------------------------------------- /template/{{ProjectName}}/version.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | var ( 4 | BuildVersion = "" 5 | BuildTime = "" 6 | ) -------------------------------------------------------------------------------- /template/{{ProjectName}}/pkg/version.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | var ( 4 | BuildVersion = "" 5 | BuildTime = "" 6 | ) 7 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/internal/entity/example.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | type Example struct { 4 | Title string 5 | Body string 6 | } -------------------------------------------------------------------------------- /template/{{ProjectName}}/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "{{ProjectName}}/cmd" 5 | ) 6 | 7 | func main() { 8 | cmd.Main() 9 | } 10 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/internal/repositories/errors.go: -------------------------------------------------------------------------------- 1 | package repositories 2 | 3 | import "github.com/pkg/errors" 4 | 5 | var ( 6 | ErrUserNotFound = errors.New("UserNotFound") 7 | ) 8 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ "$1" == "" ]]; then 4 | go test -count=1 ./test/ 5 | 6 | else 7 | go test -count=1 -v -run $1 ./test/ 8 | fi 9 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/scripts/integration.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ "$1" == "" ]]; then 4 | go test -count=1 -v ./test/ 5 | 6 | else 7 | go test -count=1 -v -run $1 ./test/ 8 | fi 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## GoTemp 2 | Template for go projects 3 | 4 | 5 | `boilr init` 6 | 7 | `boilr template download balemessenger/gotemp example-tag` 8 | 9 | `boilr template use example-tag ./target/path` 10 | 11 | -------------------------------------------------------------------------------- /project.json: -------------------------------------------------------------------------------- 1 | { 2 | "ProjectName": "", 3 | "Description": "", 4 | "Cassandra": true, 5 | "Postgres" : true, 6 | "Cassandra" : true, 7 | "Kafka" : true, 8 | "Grpc" : true, 9 | "Http" : true 10 | } -------------------------------------------------------------------------------- /template/{{ProjectName}}/test/example_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestExample(t *testing.T) { 10 | assert.Equal(t, 1, 1) 11 | } 12 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/api/http/routes.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | func (s *Server) setupRouter() { 4 | s.engine.GET("/health", s.handler.HealthCheck) 5 | s.engine.POST("/example", s.handler.Example) 6 | s.authorized.POST("/example", s.handler.AdminExample) 7 | } 8 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/pkg/utils.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | import ( 4 | "encoding/hex" 5 | "regexp" 6 | ) 7 | 8 | func ConvertToHex(token []byte) string { 9 | str := hex.EncodeToString(token) 10 | var re = regexp.MustCompile("[^a-fA-F0-9]") 11 | return re.ReplaceAllString(str, "") 12 | } 13 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/assets/cassandra/history_messages.cql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS example ( 2 | user_id int, 3 | sequence_nr int, 4 | timebucket int, 5 | is_deleted boolean, 6 | PRIMARY KEY ((user_id, partition_nr), sequence_nr, timebucket) 7 | ) WITH CLUSTERING ORDER BY (sequence_nr DESC, timebucket DESC); -------------------------------------------------------------------------------- /template/{{ProjectName}}/scripts/installprotoc.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PROTOC_ZIP=protoc-3.7.1-linux-x86_64.zip 4 | curl -OL https://github.com/google/protobuf/releases/download/v3.7.1/$PROTOC_ZIP 5 | sudo unzip -o $PROTOC_ZIP -d /usr/local bin/protoc 6 | sudo unzip -o $PROTOC_ZIP -d /usr/local include/* 7 | rm -f $PROTOC_ZIP -------------------------------------------------------------------------------- /template/{{ProjectName}}/scripts/docker.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | VERSION=`${PWD}/scripts/version.sh` 4 | TIME=$(date) 5 | 6 | echo "version: ${VERSION}" 7 | docker build --build-arg docker_version=$VERSION -t docker.bale.ai/molana/{{ProjectName}}:$VERSION -f deploy/Dockerfile . 8 | docker push docker.bale.ai/molana/{{ProjectName}}:$VERSION -------------------------------------------------------------------------------- /template/{{ProjectName}}/pkg/pubsub/pubsub.go: -------------------------------------------------------------------------------- 1 | package pubsub 2 | 3 | import "time" 4 | 5 | type PubSubMessage struct { 6 | Value []byte 7 | Timestamp time.Time 8 | } 9 | 10 | type PubSub interface { 11 | Subscribe(topics []string) error 12 | ReadMessage() (*PubSubMessage, error) 13 | Ack() error 14 | Close() error 15 | } 16 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/api/proto/rpc.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package ai.bale.{{ProjectName}}; 4 | 5 | service Example { 6 | rpc RpcExample (ExampleRequest) returns (ResponseVoid) { 7 | } 8 | } 9 | 10 | message ExampleRequest { 11 | int64 auth_id = 1; 12 | int64 user_id = 2; 13 | } 14 | 15 | message ResponseVoid { 16 | } 17 | 18 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/testkit/config.go: -------------------------------------------------------------------------------- 1 | package testkit 2 | 3 | import ( 4 | "fmt" 5 | "{{ProjectName}}/internal" 6 | "os" 7 | ) 8 | 9 | func InitTestConfig(relativePath string) *internal.Config{ 10 | configPath := fmt.Sprintf("%s/%s", os.Getenv("PWD"), relativePath) 11 | fmt.Println("Config path: ", configPath) 12 | return internal.NewConfig(configPath) 13 | } 14 | 15 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/README.md: -------------------------------------------------------------------------------- 1 | ##{{ProjectName}} 2 | 3 | 4 | **Run** 5 | 6 | `make run` 7 | 8 | **Run test** 9 | 10 | Run all tests: 11 | `make test` 12 | 13 | Run specific test: 14 | `make test method=TestExampleRoute` 15 | 16 | **Proto** 17 | `make proto arg=build` 18 | 19 | 20 | **Release** 21 | 22 | `make release` 23 | 24 | **Deploy** 25 | 26 | - Increase version number in version.sh file 27 | 28 | - `make deploy` -------------------------------------------------------------------------------- /template/{{ProjectName}}/internal/repositories/example_repo.go: -------------------------------------------------------------------------------- 1 | package repositories 2 | 3 | import ( 4 | "{{ProjectName}}/pkg/db" 5 | ) 6 | 7 | type ExampleRepo interface { 8 | GetAllExampleIds() []int32 9 | } 10 | 11 | type ExampleRepoImpl struct { 12 | db *db.PostgresDb 13 | } 14 | 15 | func NewExampleRepo(db *db.PostgresDb) *ExampleRepoImpl { 16 | return &ExampleRepoImpl{db: db} 17 | } 18 | 19 | func (p *ExampleRepoImpl) GetAllExampleIds() []int32 { 20 | return nil 21 | } 22 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/pkg/signal.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/signal" 7 | "syscall" 8 | ) 9 | 10 | type SignalDef struct { 11 | } 12 | 13 | var Signal = SignalDef{} 14 | 15 | func (SignalDef) Wait() { 16 | signals := make(chan os.Signal, 1) 17 | done := make(chan bool, 1) 18 | signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) 19 | go func() { 20 | sig := <-signals 21 | fmt.Println("Signal received: ", sig) 22 | done <- true 23 | }() 24 | <-done 25 | } 26 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/api/grpc/handler.go: -------------------------------------------------------------------------------- 1 | package grpc 2 | 3 | import ( 4 | "context" 5 | api "{{ProjectName}}/api/proto/src" 6 | "{{ProjectName}}/internal/service" 7 | ) 8 | 9 | type Handler struct { 10 | service *service.ExampleServiceImpl 11 | } 12 | 13 | func NewHandler(service *service.ExampleServiceImpl) *Handler { 14 | return &Handler{service: service} 15 | } 16 | 17 | func (h *Handler) RpcExample(ctx context.Context, req *api.ExampleRequest) (*api.ResponseVoid, error) { 18 | return h.service.RpcExample(ctx, req) 19 | } 20 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/pkg/prometheus.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | import ( 4 | "fmt" 5 | "github.com/prometheus/client_golang/prometheus/promhttp" 6 | "net/http" 7 | ) 8 | 9 | type Prometheus struct{} 10 | 11 | func NewPrometheus(port int) *Prometheus { 12 | go runPrometheusHttpServer(port) 13 | return &Prometheus{} 14 | } 15 | 16 | func runPrometheusHttpServer(port int) { 17 | http.Handle("/metrics", promhttp.Handler()) 18 | err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil) 19 | if err != nil { 20 | Logger.Error("Failed to listen prometheus server: ", err) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/go.mod: -------------------------------------------------------------------------------- 1 | module {{ProjectName}} 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/confluentinc/confluent-kafka-go v1.0.0 7 | github.com/gin-gonic/gin v1.4.0 8 | github.com/gocql/gocql v0.0.0-20190810123941-df4b9cc33030 9 | github.com/gogo/protobuf v1.2.1 10 | github.com/jackc/pgx v3.5.0+incompatible 11 | github.com/patrickmn/go-cache v2.1.0+incompatible 12 | github.com/prometheus/client_golang v1.0.0 13 | github.com/sirupsen/logrus v1.4.2 14 | github.com/spf13/viper v1.4.0 15 | github.com/stretchr/testify v1.3.0 16 | golang.org/x/net v0.0.0-20190522155817-f3200d17e092 17 | google.golang.org/grpc v1.21.0 18 | ) 19 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/scripts/awx.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | VERSION=`${PWD}/scripts/version.sh` 4 | 5 | curl -X POST \ 6 | https://1001.bale.ai/api/v2/job_templates/00/launch/ \ 7 | -H 'Authorization: Basic amVua2luczpqc0BscyZzcyMx' \ 8 | -H 'Content-Type: application/json' \ 9 | -H 'Postman-Token: 6d5c2995-d8c2-4c9e-886b-f8a11487aaa2' \ 10 | -H 'cache-control: no-cache' \ 11 | -d '{ 12 | "extra_vars":{ 13 | "_config_repo_url": "ssh://git@prd-gitlab.c002.obale.ir:2222/bale/prd/{{ProjectName}}.git", 14 | "_service": "{{ProjectName}}", 15 | "_hosts": "nav1152", 16 | "_version": "docker.bale.ai/molana/{{ProjectName}}:'$VERSION'" 17 | } 18 | }' -------------------------------------------------------------------------------- /template/{{ProjectName}}/test/config.yaml: -------------------------------------------------------------------------------- 1 | core: 2 | mode: "release" # release, debug, test 3 | {{ if Postgres }} 4 | postgres: 5 | host: "192.168.32.110" 6 | port: 5432 7 | db: "nasim" 8 | user: "nasim" 9 | pass: "nasim" 10 | batch_count: 5 11 | {{ end }} 12 | {{ if Kafka }} 13 | kafka: 14 | bootstrap_servers: "192.168.32.110" 15 | group_id: "random" 16 | auto_offset_reset: "latest" 17 | topic: "{{ProjectName}}" 18 | {{ end }} 19 | prometheus: 20 | port: 8080 21 | log: 22 | level: debug 23 | endpoints: 24 | {{ if Grpc }} 25 | grpc: 26 | address: "127.0.0.1:5050" 27 | {{ end }} 28 | http: 29 | address: ":4040" 30 | user: "test" 31 | pass: "test" -------------------------------------------------------------------------------- /template/{{ProjectName}}/internal/service/service_impl.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "context" 5 | api "{{ProjectName}}/api/proto/src" 6 | "{{ProjectName}}/internal/repositories" 7 | ) 8 | 9 | type ExampleServiceImpl struct { 10 | // Inject dependencies 11 | option Option 12 | } 13 | 14 | type Option struct { 15 | } 16 | 17 | func NewExampleService() *ExampleServiceImpl { 18 | return &ExampleServiceImpl{ 19 | option: Option{}, 20 | } 21 | } 22 | 23 | func (h *ExampleServiceImpl) RpcExample(ctx context.Context, request *api.ExampleRequest) (*api.ResponseVoid, error) { 24 | if request.UserId == 10 { 25 | return nil, repositories.ErrUserNotFound 26 | } else { 27 | return &api.ResponseVoid{}, nil 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | VERSION=`${PWD}/scripts/version.sh` 4 | TIME=$(date) 5 | 6 | if [ -d build/release ]; then 7 | mkdir -p build/release 8 | mkdir -p build/debug 9 | fi 10 | 11 | if [ "$1" == "release" ]; then 12 | echo "Building in release mode" 13 | go build -o build/release/{{ProjectName}}_$VERSION -a -installsuffix cgo -ldflags="-X '{{ProjectName}}/version.BuildTime=$TIME' -X '{{ProjectName}}/version.BuildVersion=$VERSION' -s" main.go 14 | else 15 | echo "Building in debug mode" 16 | go build -o build/debug/{{ProjectName}}_$VERSION -a -v -installsuffix cgo -ldflags="-X '{{ProjectName}}/version.BuildTime=$TIME' -X '{{ProjectName}}/version.BuildVersion=$VERSION' -s" main.go 17 | fi -------------------------------------------------------------------------------- /template/{{ProjectName}}/pkg/metrics/measure.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import ( 4 | "github.com/patrickmn/go-cache" 5 | "time" 6 | ) 7 | 8 | type Measure struct { 9 | gc *cache.Cache 10 | } 11 | 12 | func NewMeasure() *Measure { 13 | return &Measure{cache.New(5*time.Minute, 10*time.Minute)} 14 | } 15 | 16 | func (m *Measure) StartRecord(key string, startTime *time.Time) { 17 | 18 | if startTime != nil { 19 | m.gc.Set(key, *startTime, cache.DefaultExpiration) 20 | } else { 21 | m.gc.Set(key, time.Now(), cache.DefaultExpiration) 22 | } 23 | } 24 | 25 | func (m *Measure) CommitRecord(key string) *time.Duration { 26 | value, found := m.gc.Get(key) 27 | if found { 28 | elapsed := time.Since(value.(time.Time)) 29 | return &elapsed 30 | } else { 31 | return nil 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/api/grpc/errors.go: -------------------------------------------------------------------------------- 1 | package grpc 2 | 3 | import ( 4 | "google.golang.org/grpc/codes" 5 | "google.golang.org/grpc/status" 6 | ) 7 | 8 | var ( 9 | ErrGRPCWrongToken = status.New(codes.Internal, "WrongToken").Err() 10 | ErrGRPCInvalidArgument = status.New(codes.InvalidArgument, "InvalidArgument").Err() 11 | ErrGRPCNotImplemented = status.New(codes.Unimplemented, "NotImplemented").Err() 12 | ErrGRPCInternal = status.New(codes.Internal, "Internal").Err() 13 | ErrGRPCUnAuthorized = status.New(codes.Unauthenticated, "UnAuthorized").Err() 14 | ErrGRPCResourcePermissionDenied = status.New(codes.PermissionDenied, "Permission denied").Err() 15 | ErrGRPCUserNotFound = status.New(codes.NotFound, "UserNotFound").Err() 16 | 17 | ) 18 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/pkg/db/posgres.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "fmt" 5 | "github.com/jinzhu/gorm" 6 | _ "github.com/jinzhu/gorm/dialects/postgres" 7 | "{{ProjectName}}/pkg" 8 | ) 9 | 10 | type PostgresDb struct { 11 | db *gorm.DB 12 | } 13 | 14 | type PostgresConfig struct { 15 | Host string 16 | Port int 17 | User string 18 | Pass string 19 | Db string 20 | } 21 | 22 | func NewPostgres(PosgresConfig PostgresConfig) *PostgresDb { 23 | url := fmt.Sprintf("host=%v port=%v user=%v dbname=%v password=%v sslmode=disable", PosgresConfig.Host, PosgresConfig.Port, PosgresConfig.User, PosgresConfig.Db, PosgresConfig.Pass) 24 | db, err := gorm.Open("postgres", url) 25 | if err != nil { 26 | pkg.Logger.Fatal("failed to connect database", err) 27 | } 28 | db.LogMode(true) 29 | 30 | return &PostgresDb{ 31 | db: db, 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/testkit/grpc.go: -------------------------------------------------------------------------------- 1 | package testkit 2 | 3 | import ( 4 | "google.golang.org/grpc" 5 | api "{{ProjectName}}/api/proto/src" 6 | "log" 7 | "sync" 8 | ) 9 | 10 | var ( 11 | grpcOnce sync.Once 12 | grpcClient *GrpcClient 13 | ) 14 | 15 | type GrpcClient struct { 16 | api.ExampleClient 17 | } 18 | 19 | func NewGrpcClient() *GrpcClient { 20 | 21 | return &GrpcClient{} 22 | } 23 | 24 | func GetGrpcClient() *GrpcClient{ 25 | grpcOnce.Do(func() { 26 | grpcClient = NewGrpcClient() 27 | }) 28 | return grpcClient 29 | } 30 | 31 | func (c *GrpcClient) Initialize(address string){ 32 | // Set up a connection to the server. 33 | conn, err := grpc.Dial(address, grpc.WithInsecure()) 34 | if err != nil { 35 | log.Fatal("did not connect: %v", err) 36 | } 37 | client := api.NewExampleClient(conn) 38 | c.ExampleClient = client 39 | } 40 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/api/http/stub.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "{{ProjectName}}/pkg" 6 | ) 7 | 8 | type Server struct { 9 | engine *gin.Engine 10 | authorized *gin.RouterGroup 11 | handler *Handler 12 | } 13 | 14 | type Option struct { 15 | Address string 16 | User string 17 | Pass string 18 | } 19 | 20 | func NewHttpServer(option Option) *Server { 21 | engine := gin.Default() 22 | auth := engine.Group("/admin", gin.BasicAuth(gin.Accounts{ 23 | option.User: option.Pass, 24 | })) 25 | s := Server{ 26 | engine: engine, 27 | authorized: auth, 28 | handler: NewHttpHandler(), 29 | } 30 | s.setupRouter() 31 | 32 | go func(address string) { 33 | err := s.engine.Run(address) 34 | if err != nil { 35 | pkg.Logger.Fatal(err) 36 | } 37 | }(option.Address) 38 | 39 | return &s 40 | } 41 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/test/grpc_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "context" 5 | "github.com/stretchr/testify/assert" 6 | "{{ProjectName}}/api/grpc" 7 | api "{{ProjectName}}/api/proto/src" 8 | "{{ProjectName}}/testkit" 9 | "testing" 10 | "time" 11 | ) 12 | 13 | func TestExampleGrpc(t *testing.T) { 14 | 15 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 16 | defer cancel() 17 | rsp, err := testkit.GetGrpcClient().RpcExample(ctx, &api.ExampleRequest{AuthId: int64(10), UserId: int64(10)}) 18 | assert.NotNil(t, err) 19 | assert.Nil(t, rsp) 20 | assert.Equal(t, err, grpc.ErrGRPCUserNotFound) 21 | 22 | rsp, err = testkit.GetGrpcClient().RpcExample(ctx, &api.ExampleRequest{AuthId: int64(20), UserId: int64(20)}) 23 | assert.NotNil(t, rsp) 24 | assert.Nil(t, err) 25 | 26 | assert.IsType(t, rsp, &api.ResponseVoid{}) 27 | 28 | } 29 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/api/http/handler.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "net/http" 6 | "{{ProjectName}}/internal/entity" 7 | ) 8 | 9 | type Handler struct { 10 | } 11 | 12 | func NewHttpHandler() *Handler { 13 | return &Handler{} 14 | } 15 | 16 | func (h *Handler) HealthCheck(c *gin.Context) { 17 | c.JSON(http.StatusOK, gin.H{"status": 1}) 18 | return 19 | } 20 | 21 | func (h *Handler) AdminExample(c *gin.Context) { 22 | c.JSON(http.StatusOK, gin.H{"message": "Hello Admin"}) 23 | return 24 | } 25 | 26 | func (h *Handler) Example(c *gin.Context) { 27 | var example entity.Example 28 | err := c.ShouldBindJSON(&example) 29 | 30 | if err != nil { 31 | c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) 32 | return 33 | } 34 | 35 | c.JSON(http.StatusOK, gin.H{"title": example.Title, "body": example.Body}) 36 | return 37 | } -------------------------------------------------------------------------------- /template/{{ProjectName}}/.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: docker.bale.ai/opr/gobase:1.26 2 | 3 | before_script: 4 | - mkdir -p .cache 5 | - export GOPATH="$CI_PROJECT_DIR/.cache" 6 | 7 | stages: 8 | - test 9 | - build 10 | - deploy 11 | 12 | cache: 13 | key: golang-{{ProjectName}} 14 | paths: 15 | - .cache 16 | 17 | test: 18 | stage: test 19 | script: 20 | - make test 21 | tags: [docker] 22 | 23 | build: 24 | only: 25 | - master 26 | stage: build 27 | script: 28 | - mkdir -p .cache 29 | - export GOPATH="$CI_PROJECT_DIR/.cache" 30 | - make build BUILD_NUMBER=$CI_PIPELINE_ID 31 | artifacts: 32 | paths: 33 | - build/release/{{ProjectName}}_`scripts/version.sh`-$CI_PIPELINE_ID 34 | expire_in: 1 day 35 | tags: [docker] 36 | 37 | 38 | deploy: 39 | only: 40 | - master 41 | stage: deploy 42 | script: 43 | - git tag `scripts/version.sh`-$CI_PIPELINE_ID 44 | - git push "https://${GITLAB_CICD_USERNAME}:${GITLAB_CICD_TOKEN}@anbar.bale.ai/${CI_PROJECT_PATH}.git" --tags 45 | - make docker BUILD_NUMBER=$CI_PIPELINE_ID 46 | tags: [shell] -------------------------------------------------------------------------------- /template/{{ProjectName}}/test/main_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | grpc2 "{{ProjectName}}/api/grpc" 5 | "{{ProjectName}}/internal" 6 | 7 | "{{ProjectName}}/api/http" 8 | "{{ProjectName}}/internal/service" 9 | "{{ProjectName}}/pkg" 10 | "{{ProjectName}}/testkit" 11 | "math/rand" 12 | "os" 13 | "testing" 14 | "time" 15 | ) 16 | 17 | var Conf *internal.Config 18 | 19 | func setup() { 20 | rand.Seed(time.Now().Unix()) 21 | Conf = testkit.InitTestConfig("config.yaml") 22 | pkg.Logger.SetLevel(Conf.Log.Level) 23 | 24 | srv := service.NewExampleService() // Inject dependencies here 25 | grpc2.NewGrpcServer(srv, grpc2.Option{ 26 | Address: Conf.Endpoints.Grpc.Address, 27 | }) 28 | 29 | testkit.GetGrpcClient().Initialize(Conf.Endpoints.Grpc.Address) 30 | 31 | http.NewHttpServer( 32 | http.Option{ 33 | Address: Conf.Endpoints.Http.Address, 34 | User: Conf.Endpoints.Http.User, 35 | Pass: Conf.Endpoints.Http.Pass, 36 | }) 37 | 38 | time.Sleep(4000 * time.Millisecond) 39 | } 40 | 41 | func teardown() { 42 | 43 | } 44 | 45 | func TestMain(m *testing.M) { 46 | setup() 47 | r := m.Run() 48 | teardown() 49 | os.Exit(r) 50 | } 51 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/pkg/log.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | import ( 4 | "errors" 5 | "github.com/sirupsen/logrus" 6 | "io" 7 | "log" 8 | "os" 9 | ) 10 | 11 | var Logger = defaultLogger() 12 | 13 | type Log struct { 14 | *logrus.Logger 15 | } 16 | 17 | func NewLog(level string) *Log { 18 | l, err := stdoutInit(level) 19 | if err != nil { 20 | log.Panic(err) 21 | } 22 | return &Log{l} 23 | } 24 | 25 | func (l *Log) SetLevel(lvl string) error { 26 | level, err := logrus.ParseLevel(lvl) 27 | if err != nil { 28 | err = errors.New("failed to parse level") 29 | return err 30 | } 31 | l.Logger.Level = level 32 | return nil 33 | } 34 | 35 | func defaultLogger() *Log { 36 | return NewLog("DEBUG") 37 | } 38 | 39 | func stdoutInit(lvl string) (*logrus.Logger, error) { 40 | var err error 41 | logger := logrus.New() 42 | logger.SetFormatter(&logrus.TextFormatter{ 43 | DisableColors: false, 44 | FullTimestamp: true, 45 | }) 46 | level, err := logrus.ParseLevel(lvl) 47 | if err != nil { 48 | err = errors.New("failed to parse level") 49 | return nil, err 50 | } 51 | logger.Level = level 52 | var logWriter io.Writer = os.Stdout 53 | logger.SetOutput(logWriter) 54 | 55 | return logger, err 56 | } 57 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/api/grpc/util.go: -------------------------------------------------------------------------------- 1 | package grpc 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/pkg/errors" 7 | _ "github.com/pkg/errors" 8 | "google.golang.org/grpc/codes" 9 | "google.golang.org/grpc/status" 10 | "{{ProjectName}}/internal/repositories" 11 | "{{ProjectName}}/pkg" 12 | ) 13 | 14 | type stackTracer interface { 15 | StackTrace() errors.StackTrace 16 | } 17 | 18 | var toGRPCErrorMap = map[error]error{ 19 | repositories.ErrUserNotFound: ErrGRPCUserNotFound, 20 | } 21 | 22 | func getStackTrace(err error) string { 23 | if err, ok := err.(stackTracer); ok { 24 | return fmt.Sprintf("%+v", err.StackTrace()) 25 | } 26 | return "" 27 | } 28 | 29 | func togRPCErrorM(err error) error { 30 | // let gRPC server convert to codes.Canceled, codes.DeadlineExceeded 31 | if err == context.Canceled || err == context.DeadlineExceeded { 32 | return err 33 | } 34 | grpcErr, ok := toGRPCErrorMap[err] 35 | if !ok { 36 | pkg.Logger.WithField("stacktrace", getStackTrace(err)).Error(err) 37 | return status.Error(codes.Unknown, err.Error()) 38 | } 39 | return grpcErr 40 | } 41 | 42 | func togRPCError(err error) error { 43 | switch err := err.(type) { 44 | case nil: 45 | return nil 46 | //case cassandra.ErrMessageNotFound: 47 | // return ErrGRPCMessageNotFound 48 | 49 | default: 50 | return togRPCErrorM(err) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/pkg/pubsub/kafka.go: -------------------------------------------------------------------------------- 1 | package pubsub 2 | 3 | import ( 4 | "fmt" 5 | "github.com/confluentinc/confluent-kafka-go/kafka" 6 | "math/rand" 7 | "time" 8 | "{{ProjectName}}/pkg" 9 | ) 10 | 11 | type KafkaPubSub struct { 12 | consumer *kafka.Consumer 13 | } 14 | 15 | type KafkaOption struct { 16 | Servers string 17 | GroupId string 18 | OffsetReset string 19 | } 20 | 21 | func NewKafka(option KafkaOption) *KafkaPubSub { 22 | rand.Seed(time.Now().Unix()) 23 | var gId = fmt.Sprintf("groupid_%d", rand.Int31()) 24 | if option.GroupId != "random" { 25 | gId = option.GroupId 26 | } 27 | consumer, err := kafka.NewConsumer(&kafka.ConfigMap{ 28 | "bootstrap.servers": option.Servers, 29 | "group.id": gId, 30 | "auto.offset.reset": option.OffsetReset, 31 | }) 32 | 33 | if err != nil { 34 | pkg.Logger.Fatal(err) 35 | } 36 | return &KafkaPubSub{ 37 | consumer: consumer, 38 | } 39 | } 40 | 41 | func (pb *KafkaPubSub) Subscribe(topics []string) error { 42 | pkg.Logger.Debug("Subscribe to kafka topic:", topics) 43 | return pb.consumer.SubscribeTopics(topics, nil) 44 | } 45 | 46 | func (pb *KafkaPubSub) ReadMessage() (*PubSubMessage, error) { 47 | message, err := pb.consumer.ReadMessage(-1) 48 | if err != nil { 49 | return nil, err 50 | } 51 | 52 | return &PubSubMessage{Value: message.Value, Timestamp: message.Timestamp}, nil 53 | } 54 | 55 | func (pb *KafkaPubSub) Ack() error { 56 | panic("implement me") 57 | } 58 | 59 | func (pb *KafkaPubSub) Close() error { 60 | panic("implement me") 61 | } 62 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/test/http_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "log" 7 | "{{ProjectName}}/internal/entity" 8 | "fmt" 9 | "github.com/stretchr/testify/assert" 10 | "io/ioutil" 11 | "net/http" 12 | "testing" 13 | "{{ProjectName}}/internal/entity" 14 | ) 15 | 16 | func TestHealthRoute(t *testing.T) { 17 | url := fmt.Sprint("http://127.0.0.1:4040/health") 18 | rsp, err := http.Get(url) 19 | if err != nil { 20 | log.Fatal(err) 21 | } 22 | 23 | assert.Equal(t, http.StatusOK, rsp.StatusCode) 24 | body, err := ioutil.ReadAll(rsp.Body) 25 | if err != nil { 26 | log.Fatal(err) 27 | } 28 | assert.Equal(t, string(body), "{\"status\":1}") 29 | } 30 | 31 | func TestExampleRoute(t *testing.T) { 32 | 33 | url := fmt.Sprint("http://127.0.0.1:4040/example") 34 | b, err := json.Marshal(entity.Example{Title: "helloTitle", Body: "helloBody"}) 35 | 36 | rsp, err := http.Post(url, "application/json", bytes.NewBuffer(b)) 37 | if err != nil { 38 | log.Fatal(err) 39 | } 40 | 41 | assert.Equal(t, http.StatusOK, rsp.StatusCode) 42 | body, err := ioutil.ReadAll(rsp.Body) 43 | if err != nil { 44 | log.Fatal(err) 45 | } 46 | assert.Contains(t, string(body), "helloTitle") 47 | 48 | } 49 | 50 | func TestAdminExampleRoute(t *testing.T) { 51 | user := Conf.Endpoints.Http.User 52 | pass := Conf.Endpoints.Http.Pass 53 | url := fmt.Sprintf("http://%s:%s@127.0.0.1:4040/admin/example", user, pass) 54 | 55 | rsp, err := http.Post(url, "application/json", bytes.NewBuffer([]byte{})) 56 | if err != nil { 57 | log.Fatal(err) 58 | } 59 | assert.Equal(t, http.StatusOK, rsp.StatusCode) 60 | 61 | } 62 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/pkg/metrics/metrics.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import ( 4 | "sync" 5 | "github.com/prometheus/client_golang/prometheus" 6 | "github.com/prometheus/client_golang/prometheus/promauto" 7 | ) 8 | 9 | const ServiceNamespace = "{{ProjectName}}" 10 | 11 | var ( 12 | metricsOnce sync.Once 13 | metrics *Metrics 14 | ) 15 | 16 | type Metrics struct { 17 | *Measure 18 | MethodDurations *prometheus.SummaryVec 19 | MethodCount *prometheus.CounterVec 20 | MethodSuccessCount *prometheus.CounterVec 21 | MethodErrorCount *prometheus.CounterVec 22 | } 23 | 24 | func GetMetrics() *Metrics { 25 | metricsOnce.Do(func() { 26 | metrics = NewMetrics() 27 | metrics.Initialize() 28 | }) 29 | return metrics 30 | } 31 | 32 | func NewMetrics() *Metrics { 33 | methodLabels := []string{"service_name", "method"} 34 | return &Metrics{ 35 | Measure: NewMeasure(), 36 | MethodDurations: prometheus.NewSummaryVec( 37 | prometheus.SummaryOpts{ 38 | Name: "method_durations_nanoseconds", 39 | Help: "Total Rpc latency.", 40 | Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, 41 | }, methodLabels), 42 | MethodCount: promauto.NewCounterVec(prometheus.CounterOpts{ 43 | Name: "method_total", 44 | Help: "The total number of rpc error", 45 | }, methodLabels), 46 | MethodSuccessCount: promauto.NewCounterVec(prometheus.CounterOpts{ 47 | Name: "method_success_total", 48 | Help: "The total number of rpc error", 49 | }, methodLabels), 50 | MethodErrorCount: promauto.NewCounterVec(prometheus.CounterOpts{ 51 | Name: "method_error_total", 52 | Help: "The total number of rpc error", 53 | }, methodLabels), 54 | } 55 | } 56 | 57 | func (metrics *Metrics) Initialize() { 58 | prometheus.MustRegister(metrics.MethodDurations) 59 | } -------------------------------------------------------------------------------- /template/{{ProjectName}}/cmd/server.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | "{{ProjectName}}/api/grpc" 7 | "{{ProjectName}}/api/http" 8 | "{{ProjectName}}/internal" 9 | "{{ProjectName}}/internal/service" 10 | "{{ProjectName}}/pkg" 11 | "{{ProjectName}}/pkg/db" 12 | {{ if Kafka }} 13 | "{{ProjectName}}/pkg/pubsub" 14 | {{ end }} 15 | ) 16 | 17 | type Server struct { 18 | isReady chan bool 19 | } 20 | 21 | func NewServer() *Server { 22 | fmt.Println("{{ProjectName}} build version:", pkg.BuildVersion) 23 | fmt.Println("{{ProjectName}} build time:", pkg.BuildTime) 24 | conf := internal.NewConfig("") 25 | pkg.Logger.SetLevel(conf.Log.Level) 26 | 27 | {{ if Postgres }} 28 | _ = db.NewPostgres(db.PostgresConfig{ 29 | Host: conf.Postgres.Host, 30 | Port: conf.Postgres.Port, 31 | User: conf.Postgres.User, 32 | Pass: conf.Postgres.Pass, 33 | Db: conf.Postgres.DB, 34 | }) 35 | {{ end }} 36 | {{ if Cassandra }} 37 | _ = db.NewCassandra(db.CassConfig{ 38 | Hosts: conf.Cassandra.Hosts, 39 | Port: conf.Cassandra.Port, 40 | Password: conf.Cassandra.Password, 41 | Username: conf.Cassandra.Username, 42 | KeySpace: conf.Cassandra.KeySpace, 43 | Consistency: conf.Cassandra.Consistency, 44 | PageSize: conf.Cassandra.PageSize, 45 | Timeout: time.Duration(conf.Cassandra.Timeout) * time.Millisecond, 46 | DataCenter: conf.Cassandra.DataCenter, 47 | PartitionSize: conf.Cassandra.PartitionSize, 48 | }) 49 | {{ end }} 50 | {{ if Kafka }} 51 | _ = pubsub.NewKafka( 52 | pubsub.KafkaOption{ 53 | Servers: conf.Kafka.BootstrapServers, 54 | GroupId: conf.Kafka.GroupId, 55 | OffsetReset: conf.Kafka.AutoOffsetReset, 56 | }) 57 | {{ end }} 58 | // TODO: Init repositories here 59 | srv := service.NewExampleService() // Inject dependencies here 60 | {{ if Grpc }} 61 | grpc.NewGrpcServer(srv, grpc.Option{ 62 | Address: conf.Endpoints.Grpc.Address, 63 | }) 64 | {{ end }} 65 | 66 | http.NewHttpServer( 67 | http.Option{ 68 | Address: conf.Endpoints.Http.Address, 69 | User: conf.Endpoints.Http.User, 70 | Pass: conf.Endpoints.Http.Pass, 71 | }) 72 | 73 | pkg.NewPrometheus(conf.Prometheus.Port) 74 | 75 | return &Server{ 76 | isReady: make(chan bool), 77 | } 78 | } 79 | 80 | func (s *Server) Run() bool { 81 | go s.start() 82 | return <-s.isReady 83 | } 84 | 85 | func (s *Server) start() { 86 | // Write your entry point 87 | s.isReady <- true 88 | } 89 | 90 | func Main() { 91 | server := NewServer() 92 | pkg.Logger.Info("Hello {{ProjectName}}") 93 | server.Run() 94 | pkg.Signal.Wait() 95 | } 96 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/pkg/db/cassandra.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "fmt" 5 | "github.com/scylladb/gocqlx/qb" 6 | "{{ProjectName}}/pkg" 7 | "strings" 8 | "time" 9 | "io/ioutil" 10 | "github.com/gocql/gocql" 11 | ) 12 | 13 | type CassandraDB struct { 14 | session *gocql.Session 15 | } 16 | 17 | type CassConfig struct { 18 | Hosts []string 19 | Port int 20 | Username string 21 | Password string 22 | KeySpace string 23 | Consistency string 24 | PageSize int 25 | Timeout time.Duration 26 | DataCenter string 27 | PartitionSize int32 28 | } 29 | 30 | func NewCassandra(option CassConfig) *CassandraDB { 31 | db := CassandraDB{} 32 | var err error 33 | consistency := gocql.LocalOne 34 | err = consistency.UnmarshalText([]byte(option.Consistency)) 35 | if err != nil { 36 | pkg.Logger.Errorf("Error in unmarshaling consistency level. Set default consistency LocalOne. Error: %s", err.Error()) 37 | } else { 38 | pkg.Logger.Infof("Consistency level set to %s", consistency) 39 | } 40 | 41 | pkg.Logger.Debug("Cassandra configs : ", option) 42 | 43 | cluster := gocql.NewCluster(option.Hosts...) 44 | cluster.Keyspace = option.KeySpace 45 | cluster.Authenticator = gocql.PasswordAuthenticator{ 46 | Username: option.Username, 47 | Password: option.Password} 48 | cluster.PageSize = option.PageSize 49 | cluster.Port = option.Port 50 | cluster.Consistency = consistency 51 | cluster.Timeout = option.Timeout 52 | if option.DataCenter != "" { 53 | pkg.Logger.Infof("Set datacenter to %s", option.DataCenter) 54 | cluster.PoolConfig.HostSelectionPolicy = gocql.DCAwareRoundRobinPolicy(option.DataCenter) 55 | cluster.HostFilter = gocql.DataCentreHostFilter(option.DataCenter) 56 | } 57 | 58 | db.session, err = cluster.CreateSession() 59 | 60 | if err != nil { 61 | pkg.Logger.Panic(err) 62 | } 63 | return &db 64 | } 65 | 66 | func (c *CassandraDB) PrintQuery(stmt string, mp qb.M) { 67 | var result = stmt 68 | 69 | for key, value := range mp { 70 | t1 := key + "=?" 71 | t2 := key + "<=?" 72 | t3 := key + ">=?" 73 | v := fmt.Sprintf("%v", value) 74 | result = strings.Replace(result, t1, key+"="+v, 1) 75 | result = strings.Replace(result, t2, key+"<="+v, 1) 76 | result = strings.Replace(result, t3, key+">="+v, 1) 77 | } 78 | pkg.Logger.Debug(result) 79 | } 80 | 81 | //CreateTables(os.Getenv("PWD") + "/../assets/cassandra/example.cql") 82 | func (c *CassandraDB) CreateTables(paths []string) { 83 | for _, path := range paths { 84 | result, err := ioutil.ReadFile(path) 85 | if err != nil { 86 | pkg.Logger.Error(err) 87 | } 88 | query := string(result) 89 | 90 | err = c.session.Query(query).Exec() 91 | 92 | if err != nil { 93 | pkg.Logger.Error(err) 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/scripts/genproto.sh: -------------------------------------------------------------------------------- 1 | 2 | #!/usr/bin/env bash 3 | # 4 | # Generate all etcd protobuf bindings. 5 | # Run from repository root. 6 | # 7 | set -e 8 | 9 | if ! [[ "$0" =~ scripts/genproto.sh ]]; then 10 | echo "must be run from repository root" 11 | exit 255 12 | fi 13 | 14 | if [[ $(protoc --version | cut -f2 -d' ') != "3.7.1" ]]; then 15 | echo "could not find protoc 3.7.1, is it installed + in PATH?" 16 | exit 255 17 | fi 18 | 19 | 20 | # directories containing protos to be built 21 | DIRS="./api/proto" 22 | 23 | # disable go mod 24 | export GO111MODULE=off 25 | 26 | # exact version of packages to build 27 | GOGO_PROTO_SHA="1adfc126b41513cc696b209667c8656ea7aac67c" 28 | GRPC_GATEWAY_SHA="92583770e3f01b09a0d3e9bdf64321d8bebd48f2" 29 | SCHWAG_SHA="b7d0fc9aadaaae3d61aaadfc12e4a2f945514912" 30 | 31 | # set up self-contained GOPATH for building 32 | mkdir -p ${PWD}/build/_proto 33 | export GOPATH=${PWD}/build/_proto/gopath.proto 34 | export GOBIN=${PWD}/build/_proto/bin 35 | export PATH="${GOBIN}:${PATH}" 36 | 37 | GOGOPROTO_ROOT="${GOPATH}/src/github.com/gogo/protobuf" 38 | GOGOPROTO_PATH="${GOGOPROTO_ROOT}:${GOGOPROTO_ROOT}/protobuf" 39 | GRPC_GATEWAY_ROOT="${GOPATH}/src/github.com/grpc-ecosystem/grpc-gateway" 40 | 41 | 42 | if [[ "$1" == "build" ]]; then 43 | # Ensure we have the right version of protoc-gen-gogo by building it every time. 44 | # TODO(jonboulle): vendor this instead of `go get`ting it. 45 | echo "Building protoc-gen-gogo ..." 46 | go get -u github.com/gogo/protobuf/{proto,protoc-gen-gogo,gogoproto} 47 | go get -u golang.org/x/tools/cmd/goimports 48 | pushd "${GOGOPROTO_ROOT}" 49 | git reset --hard "${GOGO_PROTO_SHA}" 50 | make install 51 | popd 52 | 53 | # generate gateway code 54 | echo "Building gateway code ..." 55 | go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway 56 | go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger 57 | pushd "${GRPC_GATEWAY_ROOT}" 58 | git reset --hard "${GRPC_GATEWAY_SHA}" 59 | go install ./protoc-gen-grpc-gateway 60 | popd 61 | fi 62 | 63 | 64 | echo "Generating protos ..." 65 | for dir in ${DIRS}; do 66 | pushd "${dir}" 67 | 68 | protoc -I=".:${GRPC_GATEWAY_ROOT}/third_party/googleapis" --gogofast_out=plugins=grpc,\ 69 | Mgoogle/protobuf/any.proto=github.com/gogo/protobuf/types,\ 70 | Mgoogle/protobuf/duration.proto=github.com/gogo/protobuf/types,\ 71 | Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types,\ 72 | Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,\ 73 | Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types:./src \ 74 | ./*.proto 75 | 76 | # protoc --gofast_out=plugins=grpc:./src -I=".:${GRPC_GATEWAY_ROOT}/third_party/googleapis" ./*.proto 77 | # shellcheck disable=SC1117 78 | # protoc --go_out=plugins=grpc:./src ./*.proto 79 | goimports -w ./src/*.pb.go 80 | popd 81 | done -------------------------------------------------------------------------------- /template/{{ProjectName}}/api/grpc/stub.go: -------------------------------------------------------------------------------- 1 | package grpc 2 | 3 | import ( 4 | "google.golang.org/grpc" 5 | api "{{ProjectName}}/api/proto/src" 6 | "{{ProjectName}}/internal/service" 7 | "{{ProjectName}}/pkg" 8 | "net" 9 | "google.golang.org/grpc/metadata" 10 | "context" 11 | "strconv" 12 | "time" 13 | "{{ProjectName}}/pkg/metrics" 14 | "strings" 15 | grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" 16 | "github.com/grpc-ecosystem/go-grpc-middleware" 17 | ) 18 | 19 | type Server struct{} 20 | 21 | type Option struct { 22 | Address string 23 | } 24 | 25 | func NewGrpcServer(service *service.ExampleServiceImpl, option Option) *Server { 26 | go listenGrpc(service, option.Address) 27 | return &Server{} 28 | } 29 | 30 | func listenGrpc(service *service.ExampleServiceImpl, address string) { 31 | lis, err := net.Listen("tcp", address) 32 | if err != nil { 33 | pkg.Logger.Fatalf("failed to listen: %v", err) 34 | } 35 | pkg.Logger.Info("Start listening on address: ", address) 36 | s := grpc.NewServer(grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer( 37 | rpcInterceptor(), 38 | ))) 39 | grpc_prometheus.Register(s) 40 | api.RegisterExampleServer(s, NewHandler(service)) 41 | if err := s.Serve(lis); err != nil { 42 | pkg.Logger.Fatalf("failed to serve: %v", err) 43 | } 44 | } 45 | 46 | func GetAuthClientId(ctx context.Context) (int32, error) { 47 | headers, ok := metadata.FromIncomingContext(ctx) 48 | if ok { 49 | userIdHeader := headers["user_id"] 50 | if len(userIdHeader) == 0 { 51 | return -1, ErrGRPCUnAuthorized 52 | } 53 | userID := userIdHeader[0] 54 | i2, _ := strconv.ParseInt(userID, 10, 64) 55 | return int32(i2), nil 56 | } 57 | return -1, ErrGRPCUnAuthorized 58 | } 59 | func authInterceptor() grpc.UnaryServerInterceptor { 60 | return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { 61 | id, err := GetAuthClientId(ctx) 62 | if err != nil { 63 | return nil, err 64 | } 65 | ctx = context.WithValue(ctx, "user_id", id) 66 | return handler(ctx, req) 67 | } 68 | } 69 | 70 | func rpcInterceptor() grpc.UnaryServerInterceptor { 71 | return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { 72 | start := time.Now() 73 | m, err := handler(ctx, req) 74 | rpcName := extractRpcName(info) 75 | if err != nil { 76 | metrics.GetMetrics().MethodErrorCount.WithLabelValues(metrics.ServiceNamespace, rpcName).Add(1) 77 | } else { 78 | metrics.GetMetrics().MethodSuccessCount.WithLabelValues(metrics.ServiceNamespace, rpcName).Add(1) 79 | } 80 | metrics.GetMetrics().MethodCount.WithLabelValues(metrics.ServiceNamespace, rpcName).Add(1) 81 | metrics.GetMetrics().MethodDurations.WithLabelValues(metrics.ServiceNamespace, rpcName). 82 | Observe(float64(time.Since(start).Nanoseconds())) 83 | return m, togRPCError(err) 84 | } 85 | } 86 | 87 | func extractRpcName(info *grpc.UnaryServerInfo) string { 88 | return "Request" + strings.Split(info.FullMethod, "/")[2] 89 | } -------------------------------------------------------------------------------- /template/{{ProjectName}}/Makefile: -------------------------------------------------------------------------------- 1 | PWD := $(shell pwd) 2 | GOPATH := $(shell go env GOPATH) 3 | 4 | GOOS := $(shell go env GOOS) 5 | GOOSALT ?= 'linux' 6 | ifeq ($(GOOS),'darwin') 7 | GOOSALT = 'mac' 8 | endif 9 | 10 | PKG := {{ProjectName}} 11 | PKG_LIST := $(shell go list ${PKG}/... | grep -v /vendor/) 12 | GO_FILES := $(shell find . -name '*.go' | grep -v /vendor/) 13 | 14 | all: build 15 | 16 | checks: 17 | @echo "Checking dependencies" 18 | @(env bash $(PWD)/buildscripts/checkdeps.sh) 19 | 20 | getdeps: 21 | @echo "Running $@" 22 | @(env bash $(PWD)/scripts/installprotoc.sh $(arg)) 23 | # @mkdir -p ${GOPATH}/bin 24 | # @which golint 1>/dev/null || (echo "Installing golint" && go get -u golang.org/x/lint/golint) 25 | # @which staticcheck 1>/dev/null || (echo "Installing staticcheck" && wget --quiet -O ${GOPATH}/bin/staticcheck https://github.com/dominikh/go-tools/releases/download/2019.1/staticcheck_${GOOS}_amd64 && chmod +x ${GOPATH}/bin/staticcheck) 26 | # @which misspell 1>/dev/null || (echo "Installing misspell" && wget --quiet https://github.com/client9/misspell/releases/download/v0.3.4/misspell_0.3.4_${GOOSALT}_64bit.tar.gz && tar xf misspell_0.3.4_${GOOSALT}_64bit.tar.gz && mv misspell ${GOPATH}/bin/misspell && chmod +x ${GOPATH}/bin/misspell && rm -f misspell_0.3.4_${GOOSALT}_64bit.tar.gz) 27 | 28 | verifiers: getdeps vet fmt lint staticcheck spelling 29 | 30 | vet: 31 | @echo "Running $@" 32 | @GO111MODULE=on go vet ./... 33 | 34 | fmt: 35 | @echo "Running $@" 36 | @GO111MODULE=on gofmt -w -d api/ 37 | @GO111MODULE=on gofmt -w -d cmd/ 38 | @GO111MODULE=on gofmt -w -d internal/ 39 | @GO111MODULE=on gofmt -w -d pkg/ 40 | @GO111MODULE=on gofmt -w -d test/ 41 | 42 | lint: 43 | @echo "Running $@" 44 | @GO111MODULE=on ${GOPATH}/bin/golint -set_exit_status cmd/... 45 | @GO111MODULE=on ${GOPATH}/bin/golint -set_exit_status internal/... 46 | @GO111MODULE=on ${GOPATH}/bin/golint -set_exit_status pkg/... 47 | @GO111MODULE=on ${GOPATH}/bin/golint -set_exit_status test/... 48 | 49 | staticcheck: 50 | @echo "Running $@" 51 | @GO111MODULE=on ${GOPATH}/bin/staticcheck api/... 52 | @GO111MODULE=on ${GOPATH}/bin/staticcheck cmd/... 53 | @GO111MODULE=on ${GOPATH}/bin/staticcheck internal/... 54 | @GO111MODULE=on ${GOPATH}/bin/staticcheck pkg/... 55 | @GO111MODULE=on ${GOPATH}/bin/staticcheck test/... 56 | 57 | spelling: 58 | @GO111MODULE=on ${GOPATH}/bin/misspell -locale US -error `find cmd/` 59 | @GO111MODULE=on ${GOPATH}/bin/misspell -locale US -error `find internal/` 60 | @GO111MODULE=on ${GOPATH}/bin/misspell -locale US -error `find pkg/` 61 | @GO111MODULE=on ${GOPATH}/bin/misspell -locale US -error `find test/` 62 | @GO111MODULE=on ${GOPATH}/bin/misspell -locale US -error `find docs/` 63 | 64 | init: 65 | @echo "Running $@" 66 | @GO111MODULE=on go mod init 67 | 68 | vendor: 69 | @echo "Running $@" 70 | @GO111MODULE=on go mod vendor 71 | 72 | build: 73 | @echo "Running $@" 74 | @GO111MODULE=on ${PWD}/scripts/build.sh release 75 | 76 | test: fmt 77 | @echo "Running unit tests $(method)" 78 | @GO111MODULE=on ${PWD}/scripts/test.sh $(method) 79 | 80 | coverage: build 81 | @echo "Running all coverage" 82 | @GO111MODULE=on CGO_ENABLED=0 go test -v -coverprofile=coverage.txt -covermode=atomic ./... 83 | 84 | run: fmt 85 | @echo "Running $@" 86 | @GO111MODULE=on go run main.go 87 | 88 | docker: 89 | @echo "Running $@" 90 | @(env bash $(PWD)/scripts/docker.sh) 91 | 92 | deploy: docker 93 | @echo "Running $@" 94 | @(env bash $(PWD)/scripts/awx.sh) 95 | 96 | proto: 97 | @echo "Running $@" 98 | @(env bash $(PWD)/scripts/genproto.sh $(arg)) 99 | 100 | clean: 101 | @echo "Cleaning up all the generated files" 102 | @find . -name '*.pb.go' | xargs rm -fv 103 | @rm -rvf build/debug 104 | @rm -rvf build/release 105 | 106 | .PHONY: all test clean vendor build -------------------------------------------------------------------------------- /template/{{ProjectName}}/internal/config.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | log "github.com/sirupsen/logrus" 7 | "github.com/spf13/viper" 8 | "io/ioutil" 9 | "strings" 10 | ) 11 | 12 | type Config struct { 13 | ConfYaml 14 | } 15 | 16 | func NewConfig(path string) *Config { 17 | conf, err := loadConf(path) 18 | if err != nil { 19 | log.Fatalf("Load yaml config file error: '%v'", err) 20 | return nil 21 | } 22 | return &Config{ 23 | ConfYaml: conf, 24 | } 25 | } 26 | 27 | var defaultConf = []byte(` 28 | core: 29 | mode: "release" # release, debug, test 30 | work_pool_size: 1000 31 | {{ if Cassandra }} 32 | cassandra: 33 | hosts: ["127.0.0.1"] 34 | port: 9042 35 | user: "" 36 | password: "" 37 | keyspace: "test" 38 | consistency: "LOCAL_ONE" 39 | pagesize: 5000 40 | timeout: 16000 41 | datacenter: "" 42 | partition_size: 10 43 | {{ end }} 44 | {{ if Postgres }} 45 | postgres: 46 | host: "" 47 | port: 5432 48 | db: "" 49 | user: "" 50 | pass: "" 51 | batch_count: 5 52 | {{ end }} 53 | {{ if Kafka }} 54 | kafka: 55 | bootstrap_servers: "" 56 | group_id: "random" 57 | auto_offset_reset: "earliest" 58 | topic: "{{ProjectName}}" 59 | {{ end }} 60 | prometheus: 61 | port: 8080 62 | log: 63 | level: debug 64 | endpoints: 65 | {{ if Grpc }} 66 | grpc: 67 | address: "127.0.0.1:5050" 68 | {{ end }} 69 | http: 70 | address: ":4040" 71 | user: "test" 72 | pass: "test" 73 | `) 74 | 75 | type ConfYaml struct { 76 | Core SectionCore `yaml:"core"` 77 | {{ if Cassandra }} 78 | Cassandra SectionCassandra `yaml:cassandra` 79 | {{ end }} 80 | {{ if Postgres }} 81 | Postgres SectionPostgres `yaml:"postgres"` 82 | {{ end }} 83 | {{ if Kafka }} 84 | Kafka SectionKafka `yaml:"kafka"` 85 | {{ end }} 86 | Prometheus SectionPrometheus `yaml:"prometheus"` 87 | Log SectionLog `yaml:"log"` 88 | Endpoints SectionEndpoints `yaml:"endpoints"` 89 | } 90 | 91 | // SectionCore is sub section of config. 92 | type SectionCore struct { 93 | Mode string `yaml:"mode"` 94 | WorkPoolSize int `yaml:"work_pool_size"` 95 | } 96 | 97 | {{ if Cassandra }} 98 | type SectionCassandra struct { 99 | Hosts []string `yaml:"hosts"` 100 | Port int `yaml:"port"` 101 | Username string `yaml:"user"` 102 | Password string `yaml:"password"` 103 | KeySpace string `yaml:"keyspace"` 104 | Consistency string `yaml:"consistency"` 105 | PageSize int `yaml:"pagesize"` 106 | Timeout int64 `yaml:"timeout"` 107 | DataCenter string `yaml:"datacenter"` 108 | PartitionSize int32 `yaml:"partition_size"` 109 | } 110 | {{ end }} 111 | {{ if Postgres }} 112 | // SectionPostgres is sub section of config. 113 | type SectionPostgres struct { 114 | Host string `yaml:"host"` 115 | Port int `yaml:"port"` 116 | DB string `yaml:"db"` 117 | User string `yaml:"user"` 118 | Pass string `yaml:"pass"` 119 | BatchCount int `yaml:"batch_count"` 120 | } 121 | {{ end }} 122 | 123 | {{ if Kafka }} 124 | // SectionKafka is sub section of config. 125 | type SectionKafka struct { 126 | BootstrapServers string `yaml:"bootstrap_servers"` 127 | GroupId string `yaml:"group_id"` 128 | AutoOffsetReset string `yaml:"auto_offset_reset"` 129 | Topic string `yaml:"topic"` 130 | } 131 | {{ end }} 132 | 133 | type SectionPrometheus struct { 134 | Port int `yaml:"port"` 135 | } 136 | 137 | type SectionLog struct { 138 | Level string `yaml:"level"` 139 | } 140 | 141 | type SectionEndpoints struct { 142 | {{ if Grpc }} 143 | Grpc SectionGrpc `yaml:"grpc"` 144 | {{ end }} 145 | Http SectionHttp `yaml:"http"` 146 | } 147 | 148 | {{ if Grpc }} 149 | type SectionGrpc struct { 150 | Address string `yaml:"address"` 151 | } 152 | {{ end }} 153 | 154 | type SectionHttp struct { 155 | Address string `yaml:"address"` 156 | User string `yaml:"user"` 157 | Pass string `yaml:"pass"` 158 | } 159 | 160 | // LoadConf load config from file and read in environment variables that match 161 | func loadConf(confPath string) (ConfYaml, error) { 162 | var conf ConfYaml 163 | 164 | viper.SetConfigType("yaml") 165 | viper.AutomaticEnv() // read in environment variables that match 166 | viper.SetEnvPrefix("{{ProjectName}}") // will be uppercased automatically 167 | viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) 168 | 169 | if confPath != "" { 170 | content, err := ioutil.ReadFile(confPath) 171 | 172 | if err != nil { 173 | log.Errorf("File does not exist : %s", confPath) 174 | return conf, err 175 | } 176 | 177 | if err := viper.ReadConfig(bytes.NewBuffer(content)); err != nil { 178 | return conf, err 179 | } 180 | } else { 181 | // Search config in home directory with name ".pkg" (without extension). 182 | viper.AddConfigPath(".") 183 | viper.AddConfigPath("$HOME/.{{ProjectName}}") 184 | viper.AddConfigPath("/etc/{{ProjectName}}/") 185 | viper.SetConfigName("config") 186 | 187 | // If a config file is found, read it in. 188 | if err := viper.ReadInConfig(); err == nil { 189 | fmt.Println("Using config file:", viper.ConfigFileUsed()) 190 | } else { 191 | // load default config 192 | if err := viper.ReadConfig(bytes.NewBuffer(defaultConf)); err != nil { 193 | return conf, err 194 | } 195 | } 196 | } 197 | 198 | // Core 199 | conf.Core.Mode = viper.GetString("core.mode") 200 | conf.Core.WorkPoolSize = viper.GetInt("core.work_pool_size") 201 | 202 | {{ if Cassandra }} 203 | // Cassandra 204 | conf.Cassandra.Hosts = viper.GetStringSlice("cassandra.hosts") 205 | conf.Cassandra.Port = viper.GetInt("cassandra.port") 206 | conf.Cassandra.Username = viper.GetString("cassandra.user") 207 | conf.Cassandra.Password = viper.GetString("cassandra.password") 208 | conf.Cassandra.KeySpace = viper.GetString("cassandra.keyspace") 209 | conf.Cassandra.Consistency = viper.GetString("cassandra.consistency") 210 | conf.Cassandra.PageSize = viper.GetInt("cassandra.pagesize") 211 | conf.Cassandra.Timeout = viper.GetInt64("cassandra.timeout") 212 | conf.Cassandra.DataCenter = viper.GetString("cassandra.datacenter") 213 | conf.Cassandra.PartitionSize = viper.GetInt32("cassandra.partition_size") 214 | {{ end }} 215 | {{ if Postgres }} 216 | // Postgres 217 | conf.Postgres.Host = viper.GetString("postgres.host") 218 | conf.Postgres.Port = viper.GetInt("postgres.port") 219 | conf.Postgres.DB = viper.GetString("postgres.db") 220 | conf.Postgres.User = viper.GetString("postgres.user") 221 | conf.Postgres.Pass = viper.GetString("postgres.pass") 222 | conf.Postgres.BatchCount = viper.GetInt("postgres.batch_count") 223 | {{ end }} 224 | 225 | 226 | {{ if Kafka }} 227 | // Kafka 228 | conf.Kafka.BootstrapServers = viper.GetString("kafka.bootstrap_servers") 229 | conf.Kafka.GroupId = viper.GetString("kafka.group_id") 230 | conf.Kafka.AutoOffsetReset = viper.GetString("kafka.auto_offset_reset") 231 | conf.Kafka.Topic = viper.GetString("kafka.topic") 232 | {{ end }} 233 | 234 | // Prometheus 235 | conf.Prometheus.Port = viper.GetInt("prometheus.port") 236 | 237 | //Log 238 | conf.Log.Level = viper.GetString("log.level") 239 | 240 | //Endpoints 241 | {{ if Grpc }} 242 | conf.Endpoints.Grpc.Address = viper.GetString("endpoints.grpc.address") 243 | {{ end }} 244 | conf.Endpoints.Http.Address = viper.GetString("endpoints.http.address") 245 | conf.Endpoints.Http.User = viper.GetString("endpoints.http.user") 246 | conf.Endpoints.Http.Pass = viper.GetString("endpoints.http.pass") 247 | 248 | return conf, nil 249 | } 250 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/api/proto/src/rpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-gogo. DO NOT EDIT. 2 | // source: rpc.proto 3 | 4 | /* 5 | Package ai_bale_a is a generated protocol buffer package. 6 | 7 | It is generated from these files: 8 | rpc.proto 9 | 10 | It has these top-level messages: 11 | ExampleRequest 12 | ResponseVoid 13 | */ 14 | package ai_bale_a 15 | 16 | import proto "github.com/gogo/protobuf/proto" 17 | import fmt "fmt" 18 | import math "math" 19 | 20 | import context "golang.org/x/net/context" 21 | import grpc "google.golang.org/grpc" 22 | 23 | import io "io" 24 | 25 | // Reference imports to suppress errors if they are not otherwise used. 26 | var _ = proto.Marshal 27 | var _ = fmt.Errorf 28 | var _ = math.Inf 29 | 30 | // This is a compile-time assertion to ensure that this generated file 31 | // is compatible with the proto package it is being compiled against. 32 | // A compilation error at this line likely means your copy of the 33 | // proto package needs to be updated. 34 | const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package 35 | 36 | type ExampleRequest struct { 37 | AuthId int64 `protobuf:"varint,1,opt,name=auth_id,json=authId,proto3" json:"auth_id,omitempty"` 38 | UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` 39 | } 40 | 41 | func (m *ExampleRequest) Reset() { *m = ExampleRequest{} } 42 | func (m *ExampleRequest) String() string { return proto.CompactTextString(m) } 43 | func (*ExampleRequest) ProtoMessage() {} 44 | func (*ExampleRequest) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{0} } 45 | 46 | func (m *ExampleRequest) GetAuthId() int64 { 47 | if m != nil { 48 | return m.AuthId 49 | } 50 | return 0 51 | } 52 | 53 | func (m *ExampleRequest) GetUserId() int64 { 54 | if m != nil { 55 | return m.UserId 56 | } 57 | return 0 58 | } 59 | 60 | type ResponseVoid struct { 61 | } 62 | 63 | func (m *ResponseVoid) Reset() { *m = ResponseVoid{} } 64 | func (m *ResponseVoid) String() string { return proto.CompactTextString(m) } 65 | func (*ResponseVoid) ProtoMessage() {} 66 | func (*ResponseVoid) Descriptor() ([]byte, []int) { return fileDescriptorRpc, []int{1} } 67 | 68 | func init() { 69 | proto.RegisterType((*ExampleRequest)(nil), "ai.bale.a.ExampleRequest") 70 | proto.RegisterType((*ResponseVoid)(nil), "ai.bale.a.ResponseVoid") 71 | } 72 | 73 | // Reference imports to suppress errors if they are not otherwise used. 74 | var _ context.Context 75 | var _ grpc.ClientConn 76 | 77 | // This is a compile-time assertion to ensure that this generated file 78 | // is compatible with the grpc package it is being compiled against. 79 | const _ = grpc.SupportPackageIsVersion4 80 | 81 | // Client API for Example service 82 | 83 | type ExampleClient interface { 84 | RpcExample(ctx context.Context, in *ExampleRequest, opts ...grpc.CallOption) (*ResponseVoid, error) 85 | } 86 | 87 | type exampleClient struct { 88 | cc *grpc.ClientConn 89 | } 90 | 91 | func NewExampleClient(cc *grpc.ClientConn) ExampleClient { 92 | return &exampleClient{cc} 93 | } 94 | 95 | func (c *exampleClient) RpcExample(ctx context.Context, in *ExampleRequest, opts ...grpc.CallOption) (*ResponseVoid, error) { 96 | out := new(ResponseVoid) 97 | err := grpc.Invoke(ctx, "/ai.bale.a.Example/RpcExample", in, out, c.cc, opts...) 98 | if err != nil { 99 | return nil, err 100 | } 101 | return out, nil 102 | } 103 | 104 | // Server API for Example service 105 | 106 | type ExampleServer interface { 107 | RpcExample(context.Context, *ExampleRequest) (*ResponseVoid, error) 108 | } 109 | 110 | func RegisterExampleServer(s *grpc.Server, srv ExampleServer) { 111 | s.RegisterService(&_Example_serviceDesc, srv) 112 | } 113 | 114 | func _Example_RpcExample_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 115 | in := new(ExampleRequest) 116 | if err := dec(in); err != nil { 117 | return nil, err 118 | } 119 | if interceptor == nil { 120 | return srv.(ExampleServer).RpcExample(ctx, in) 121 | } 122 | info := &grpc.UnaryServerInfo{ 123 | Server: srv, 124 | FullMethod: "/ai.bale.a.Example/RpcExample", 125 | } 126 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 127 | return srv.(ExampleServer).RpcExample(ctx, req.(*ExampleRequest)) 128 | } 129 | return interceptor(ctx, in, info, handler) 130 | } 131 | 132 | var _Example_serviceDesc = grpc.ServiceDesc{ 133 | ServiceName: "ai.bale.a.Example", 134 | HandlerType: (*ExampleServer)(nil), 135 | Methods: []grpc.MethodDesc{ 136 | { 137 | MethodName: "RpcExample", 138 | Handler: _Example_RpcExample_Handler, 139 | }, 140 | }, 141 | Streams: []grpc.StreamDesc{}, 142 | Metadata: "rpc.proto", 143 | } 144 | 145 | func (m *ExampleRequest) Marshal() (dAtA []byte, err error) { 146 | size := m.Size() 147 | dAtA = make([]byte, size) 148 | n, err := m.MarshalTo(dAtA) 149 | if err != nil { 150 | return nil, err 151 | } 152 | return dAtA[:n], nil 153 | } 154 | 155 | func (m *ExampleRequest) MarshalTo(dAtA []byte) (int, error) { 156 | var i int 157 | _ = i 158 | var l int 159 | _ = l 160 | if m.AuthId != 0 { 161 | dAtA[i] = 0x8 162 | i++ 163 | i = encodeVarintRpc(dAtA, i, uint64(m.AuthId)) 164 | } 165 | if m.UserId != 0 { 166 | dAtA[i] = 0x10 167 | i++ 168 | i = encodeVarintRpc(dAtA, i, uint64(m.UserId)) 169 | } 170 | return i, nil 171 | } 172 | 173 | func (m *ResponseVoid) Marshal() (dAtA []byte, err error) { 174 | size := m.Size() 175 | dAtA = make([]byte, size) 176 | n, err := m.MarshalTo(dAtA) 177 | if err != nil { 178 | return nil, err 179 | } 180 | return dAtA[:n], nil 181 | } 182 | 183 | func (m *ResponseVoid) MarshalTo(dAtA []byte) (int, error) { 184 | var i int 185 | _ = i 186 | var l int 187 | _ = l 188 | return i, nil 189 | } 190 | 191 | func encodeVarintRpc(dAtA []byte, offset int, v uint64) int { 192 | for v >= 1<<7 { 193 | dAtA[offset] = uint8(v&0x7f | 0x80) 194 | v >>= 7 195 | offset++ 196 | } 197 | dAtA[offset] = uint8(v) 198 | return offset + 1 199 | } 200 | func (m *ExampleRequest) Size() (n int) { 201 | var l int 202 | _ = l 203 | if m.AuthId != 0 { 204 | n += 1 + sovRpc(uint64(m.AuthId)) 205 | } 206 | if m.UserId != 0 { 207 | n += 1 + sovRpc(uint64(m.UserId)) 208 | } 209 | return n 210 | } 211 | 212 | func (m *ResponseVoid) Size() (n int) { 213 | var l int 214 | _ = l 215 | return n 216 | } 217 | 218 | func sovRpc(x uint64) (n int) { 219 | for { 220 | n++ 221 | x >>= 7 222 | if x == 0 { 223 | break 224 | } 225 | } 226 | return n 227 | } 228 | func sozRpc(x uint64) (n int) { 229 | return sovRpc(uint64((x << 1) ^ uint64((int64(x) >> 63)))) 230 | } 231 | func (m *ExampleRequest) Unmarshal(dAtA []byte) error { 232 | l := len(dAtA) 233 | iNdEx := 0 234 | for iNdEx < l { 235 | preIndex := iNdEx 236 | var wire uint64 237 | for shift := uint(0); ; shift += 7 { 238 | if shift >= 64 { 239 | return ErrIntOverflowRpc 240 | } 241 | if iNdEx >= l { 242 | return io.ErrUnexpectedEOF 243 | } 244 | b := dAtA[iNdEx] 245 | iNdEx++ 246 | wire |= (uint64(b) & 0x7F) << shift 247 | if b < 0x80 { 248 | break 249 | } 250 | } 251 | fieldNum := int32(wire >> 3) 252 | wireType := int(wire & 0x7) 253 | if wireType == 4 { 254 | return fmt.Errorf("proto: ExampleRequest: wiretype end group for non-group") 255 | } 256 | if fieldNum <= 0 { 257 | return fmt.Errorf("proto: ExampleRequest: illegal tag %d (wire type %d)", fieldNum, wire) 258 | } 259 | switch fieldNum { 260 | case 1: 261 | if wireType != 0 { 262 | return fmt.Errorf("proto: wrong wireType = %d for field AuthId", wireType) 263 | } 264 | m.AuthId = 0 265 | for shift := uint(0); ; shift += 7 { 266 | if shift >= 64 { 267 | return ErrIntOverflowRpc 268 | } 269 | if iNdEx >= l { 270 | return io.ErrUnexpectedEOF 271 | } 272 | b := dAtA[iNdEx] 273 | iNdEx++ 274 | m.AuthId |= (int64(b) & 0x7F) << shift 275 | if b < 0x80 { 276 | break 277 | } 278 | } 279 | case 2: 280 | if wireType != 0 { 281 | return fmt.Errorf("proto: wrong wireType = %d for field UserId", wireType) 282 | } 283 | m.UserId = 0 284 | for shift := uint(0); ; shift += 7 { 285 | if shift >= 64 { 286 | return ErrIntOverflowRpc 287 | } 288 | if iNdEx >= l { 289 | return io.ErrUnexpectedEOF 290 | } 291 | b := dAtA[iNdEx] 292 | iNdEx++ 293 | m.UserId |= (int64(b) & 0x7F) << shift 294 | if b < 0x80 { 295 | break 296 | } 297 | } 298 | default: 299 | iNdEx = preIndex 300 | skippy, err := skipRpc(dAtA[iNdEx:]) 301 | if err != nil { 302 | return err 303 | } 304 | if skippy < 0 { 305 | return ErrInvalidLengthRpc 306 | } 307 | if (iNdEx + skippy) > l { 308 | return io.ErrUnexpectedEOF 309 | } 310 | iNdEx += skippy 311 | } 312 | } 313 | 314 | if iNdEx > l { 315 | return io.ErrUnexpectedEOF 316 | } 317 | return nil 318 | } 319 | func (m *ResponseVoid) Unmarshal(dAtA []byte) error { 320 | l := len(dAtA) 321 | iNdEx := 0 322 | for iNdEx < l { 323 | preIndex := iNdEx 324 | var wire uint64 325 | for shift := uint(0); ; shift += 7 { 326 | if shift >= 64 { 327 | return ErrIntOverflowRpc 328 | } 329 | if iNdEx >= l { 330 | return io.ErrUnexpectedEOF 331 | } 332 | b := dAtA[iNdEx] 333 | iNdEx++ 334 | wire |= (uint64(b) & 0x7F) << shift 335 | if b < 0x80 { 336 | break 337 | } 338 | } 339 | fieldNum := int32(wire >> 3) 340 | wireType := int(wire & 0x7) 341 | if wireType == 4 { 342 | return fmt.Errorf("proto: ResponseVoid: wiretype end group for non-group") 343 | } 344 | if fieldNum <= 0 { 345 | return fmt.Errorf("proto: ResponseVoid: illegal tag %d (wire type %d)", fieldNum, wire) 346 | } 347 | switch fieldNum { 348 | default: 349 | iNdEx = preIndex 350 | skippy, err := skipRpc(dAtA[iNdEx:]) 351 | if err != nil { 352 | return err 353 | } 354 | if skippy < 0 { 355 | return ErrInvalidLengthRpc 356 | } 357 | if (iNdEx + skippy) > l { 358 | return io.ErrUnexpectedEOF 359 | } 360 | iNdEx += skippy 361 | } 362 | } 363 | 364 | if iNdEx > l { 365 | return io.ErrUnexpectedEOF 366 | } 367 | return nil 368 | } 369 | func skipRpc(dAtA []byte) (n int, err error) { 370 | l := len(dAtA) 371 | iNdEx := 0 372 | for iNdEx < l { 373 | var wire uint64 374 | for shift := uint(0); ; shift += 7 { 375 | if shift >= 64 { 376 | return 0, ErrIntOverflowRpc 377 | } 378 | if iNdEx >= l { 379 | return 0, io.ErrUnexpectedEOF 380 | } 381 | b := dAtA[iNdEx] 382 | iNdEx++ 383 | wire |= (uint64(b) & 0x7F) << shift 384 | if b < 0x80 { 385 | break 386 | } 387 | } 388 | wireType := int(wire & 0x7) 389 | switch wireType { 390 | case 0: 391 | for shift := uint(0); ; shift += 7 { 392 | if shift >= 64 { 393 | return 0, ErrIntOverflowRpc 394 | } 395 | if iNdEx >= l { 396 | return 0, io.ErrUnexpectedEOF 397 | } 398 | iNdEx++ 399 | if dAtA[iNdEx-1] < 0x80 { 400 | break 401 | } 402 | } 403 | return iNdEx, nil 404 | case 1: 405 | iNdEx += 8 406 | return iNdEx, nil 407 | case 2: 408 | var length int 409 | for shift := uint(0); ; shift += 7 { 410 | if shift >= 64 { 411 | return 0, ErrIntOverflowRpc 412 | } 413 | if iNdEx >= l { 414 | return 0, io.ErrUnexpectedEOF 415 | } 416 | b := dAtA[iNdEx] 417 | iNdEx++ 418 | length |= (int(b) & 0x7F) << shift 419 | if b < 0x80 { 420 | break 421 | } 422 | } 423 | iNdEx += length 424 | if length < 0 { 425 | return 0, ErrInvalidLengthRpc 426 | } 427 | return iNdEx, nil 428 | case 3: 429 | for { 430 | var innerWire uint64 431 | var start int = iNdEx 432 | for shift := uint(0); ; shift += 7 { 433 | if shift >= 64 { 434 | return 0, ErrIntOverflowRpc 435 | } 436 | if iNdEx >= l { 437 | return 0, io.ErrUnexpectedEOF 438 | } 439 | b := dAtA[iNdEx] 440 | iNdEx++ 441 | innerWire |= (uint64(b) & 0x7F) << shift 442 | if b < 0x80 { 443 | break 444 | } 445 | } 446 | innerWireType := int(innerWire & 0x7) 447 | if innerWireType == 4 { 448 | break 449 | } 450 | next, err := skipRpc(dAtA[start:]) 451 | if err != nil { 452 | return 0, err 453 | } 454 | iNdEx = start + next 455 | } 456 | return iNdEx, nil 457 | case 4: 458 | return iNdEx, nil 459 | case 5: 460 | iNdEx += 4 461 | return iNdEx, nil 462 | default: 463 | return 0, fmt.Errorf("proto: illegal wireType %d", wireType) 464 | } 465 | } 466 | panic("unreachable") 467 | } 468 | 469 | var ( 470 | ErrInvalidLengthRpc = fmt.Errorf("proto: negative length found during unmarshaling") 471 | ErrIntOverflowRpc = fmt.Errorf("proto: integer overflow") 472 | ) 473 | 474 | func init() { proto.RegisterFile("rpc.proto", fileDescriptorRpc) } 475 | 476 | var fileDescriptorRpc = []byte{ 477 | // 168 bytes of a gzipped FileDescriptorProto 478 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2c, 0x2a, 0x48, 0xd6, 479 | 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4c, 0xcc, 0xd4, 0x4b, 0x4a, 0xcc, 0x49, 0xd5, 0x4b, 480 | 0x54, 0x72, 0xe2, 0xe2, 0x73, 0xad, 0x48, 0xcc, 0x2d, 0xc8, 0x49, 0x0d, 0x4a, 0x2d, 0x2c, 0x4d, 481 | 0x2d, 0x2e, 0x11, 0x12, 0xe7, 0x62, 0x4f, 0x2c, 0x2d, 0xc9, 0x88, 0xcf, 0x4c, 0x91, 0x60, 0x54, 482 | 0x60, 0xd4, 0x60, 0x0e, 0x62, 0x03, 0x71, 0x3d, 0x53, 0x40, 0x12, 0xa5, 0xc5, 0xa9, 0x45, 0x20, 483 | 0x09, 0x26, 0x88, 0x04, 0x88, 0xeb, 0x99, 0xa2, 0xc4, 0xc7, 0xc5, 0x13, 0x94, 0x5a, 0x5c, 0x90, 484 | 0x9f, 0x57, 0x9c, 0x1a, 0x96, 0x9f, 0x99, 0x62, 0xe4, 0xcb, 0xc5, 0x0e, 0x35, 0x53, 0xc8, 0x89, 485 | 0x8b, 0x2b, 0xa8, 0x20, 0x19, 0xc6, 0x93, 0xd4, 0x83, 0x5b, 0xac, 0x87, 0x6a, 0xab, 0x94, 0x38, 486 | 0x92, 0x14, 0xb2, 0x61, 0x4a, 0x0c, 0x4e, 0x3c, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 487 | 0xf8, 0xe0, 0x91, 0x1c, 0x63, 0x12, 0x1b, 0xd8, 0x0b, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 488 | 0x7a, 0x99, 0xae, 0x04, 0xcf, 0x00, 0x00, 0x00, 489 | } 490 | -------------------------------------------------------------------------------- /template/{{ProjectName}}/go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 3 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 4 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 5 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 6 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 7 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 8 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 9 | github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= 10 | github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= 11 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 12 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 13 | github.com/confluentinc/confluent-kafka-go v1.0.0/go.mod h1:u2zNLny2xq+5rWeTQjFHbDzzNuba4P1vo31r9r4uAdg= 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-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 17 | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 18 | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 19 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 20 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 21 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 22 | github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= 23 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 24 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 25 | github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= 26 | github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= 27 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 28 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 29 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 30 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 31 | github.com/gocql/gocql v0.0.0-20190810123941-df4b9cc33030/go.mod h1:Q7Sru5153KG8D9zwueuQJB3ccJf9/bIwF/x8b3oKgT8= 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/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 35 | github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 36 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 37 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 38 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 39 | github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 40 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 41 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 42 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 43 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 44 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 45 | github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= 46 | github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= 47 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 48 | github.com/jackc/pgx v3.5.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= 49 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 50 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 51 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 52 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 53 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 54 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 55 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 56 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 57 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 58 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 59 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 60 | github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 61 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 62 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 63 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 64 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 65 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 66 | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= 67 | github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= 68 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 69 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 70 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 71 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 72 | github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= 73 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 74 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 75 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 76 | github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 77 | github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 78 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 79 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 80 | github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 81 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 82 | github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= 83 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 84 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 85 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 86 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= 87 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 88 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 89 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 90 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 91 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 92 | github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= 93 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 94 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 95 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 96 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 97 | github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 98 | github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= 99 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 100 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 101 | go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 102 | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 103 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 104 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 105 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 106 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 107 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 108 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 109 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 110 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 111 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 112 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 113 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 114 | golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 115 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 116 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 117 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 118 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 119 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 120 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 121 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 122 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 123 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 124 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 125 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 126 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 127 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 128 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 129 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 130 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 131 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 132 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 133 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 134 | google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 135 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 136 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 137 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 138 | gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= 139 | gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= 140 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 141 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 142 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 143 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 144 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 145 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 146 | --------------------------------------------------------------------------------