feat: port reduction (#323)

* move mgmt pkg

* begin package restructure

* rename auth package to authz

* begin start api

* move auth

* move admin

* fix merge

* configs and interceptors

* interceptor

* revert generate-grpc.sh

* some cleanups

* console

* move console

* fix tests and merging

* js linting

* merge

* merging and configs

* change k8s base to current ports

* fixes

* cleanup

* regenerate proto

* remove unnecessary whitespace

* missing param

* go mod tidy

* fix merging

* move login pkg

* cleanup

* move api pkgs again

* fix pkg naming

* fix generate-static.sh for login

* update workflow

* fixes

* logging

* remove duplicate

* comment for optional gateway interfaces

* regenerate protos

* fix proto imports for grpc web

* protos

* grpc web generate

* grpc web generate

* fix changes

* add translation interceptor

* fix merging

* regenerate mgmt proto
This commit is contained in:
Livio Amstutz
2020-07-08 13:56:37 +02:00
committed by GitHub
parent 708652a655
commit 3549a8b64e
330 changed files with 30495 additions and 30809 deletions

View File

@@ -3,12 +3,14 @@ package server
import (
"context"
"net/http"
"strings"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"google.golang.org/grpc"
"github.com/caos/logging"
grpc_util "github.com/caos/zitadel/internal/api/grpc"
client_middleware "github.com/caos/zitadel/internal/api/grpc/client/middleware"
http_util "github.com/caos/zitadel/internal/api/http"
http_mw "github.com/caos/zitadel/internal/api/http/middleware"
@@ -22,26 +24,41 @@ const (
var (
DefaultJSONMarshaler = &runtime.JSONPb{OrigName: false, EmitDefaults: false}
DefaultServeMuxOptions = []runtime.ServeMuxOption{
runtime.WithMarshalerOption(DefaultJSONMarshaler.ContentType(), DefaultJSONMarshaler),
runtime.WithMarshalerOption(mimeWildcard, DefaultJSONMarshaler),
runtime.WithMarshalerOption(runtime.MIMEWildcard, DefaultJSONMarshaler),
runtime.WithIncomingHeaderMatcher(runtime.DefaultHeaderMatcher),
runtime.WithOutgoingHeaderMatcher(runtime.DefaultHeaderMatcher),
DefaultServeMuxOptions = func(customHeaders ...string) []runtime.ServeMuxOption {
return []runtime.ServeMuxOption{
runtime.WithMarshalerOption(DefaultJSONMarshaler.ContentType(), DefaultJSONMarshaler),
runtime.WithMarshalerOption(mimeWildcard, DefaultJSONMarshaler),
runtime.WithMarshalerOption(runtime.MIMEWildcard, DefaultJSONMarshaler),
runtime.WithIncomingHeaderMatcher(DefaultHeaderMatcher(customHeaders...)),
runtime.WithOutgoingHeaderMatcher(runtime.DefaultHeaderMatcher),
}
}
DefaultHeaderMatcher = func(customHeaders ...string) runtime.HeaderMatcherFunc {
return func(header string) (string, bool) {
for _, customHeader := range customHeaders {
if strings.HasPrefix(strings.ToLower(header), customHeader) {
return header, true
}
}
return runtime.DefaultHeaderMatcher(header)
}
}
)
type Gateway interface {
GRPCEndpoint() string
GatewayPort() string
Gateway() GatewayFunc
RegisterGateway() GatewayFunc
GatewayPathPrefix() string
}
type GatewayFunc func(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) error
//optional extending interfaces of Gateway below
type gatewayCustomServeMuxOptions interface {
GatewayServeMuxOptions() []runtime.ServeMuxOption
}
type grpcGatewayCustomInterceptor interface {
GatewayHTTPInterceptor(http.Handler) http.Handler
}
@@ -50,28 +67,62 @@ type gatewayCustomCallOptions interface {
GatewayCallOptions() []grpc.DialOption
}
func StartGateway(ctx context.Context, g Gateway) {
mux := createMux(ctx, g)
serveGateway(ctx, mux, gatewayPort(g.GatewayPort()), g)
type GatewayHandler struct {
mux *http.ServeMux
serverPort string
gatewayPort string
customHeaders []string
}
func createMux(ctx context.Context, g Gateway) *runtime.ServeMux {
muxOptions := DefaultServeMuxOptions
func CreateGatewayHandler(config grpc_util.Config) *GatewayHandler {
return &GatewayHandler{
mux: http.NewServeMux(),
serverPort: config.ServerPort,
gatewayPort: config.GatewayPort,
customHeaders: config.CustomHeaders,
}
}
//RegisterGateway registers a handler (Gateway interface) on defined port
//Gateway interface may be extended with optional implementation of interfaces (gatewayCustomServeMuxOptions, ...)
func (g *GatewayHandler) RegisterGateway(ctx context.Context, gateway Gateway) {
handler := createGateway(ctx, gateway, g.serverPort, g.customHeaders...)
prefix := gateway.GatewayPathPrefix()
g.RegisterHandler(prefix, handler)
}
func (g *GatewayHandler) RegisterHandler(prefix string, handler http.Handler) {
http_util.RegisterHandler(g.mux, prefix, handler)
}
func (g *GatewayHandler) Serve(ctx context.Context) {
http_util.Serve(ctx, g.mux, g.gatewayPort, "api")
}
func createGateway(ctx context.Context, g Gateway, port string, customHeaders ...string) http.Handler {
mux := createMux(g, customHeaders...)
opts := createDialOptions(g)
err := g.RegisterGateway()(ctx, mux, http_util.Endpoint(port), opts)
logging.Log("SERVE-7B7G0E").OnError(err).Panic("failed to register grpc gateway")
return addInterceptors(mux, g)
}
func createMux(g Gateway, customHeaders ...string) *runtime.ServeMux {
muxOptions := DefaultServeMuxOptions(customHeaders...)
if customOpts, ok := g.(gatewayCustomServeMuxOptions); ok {
muxOptions = customOpts.GatewayServeMuxOptions()
}
mux := runtime.NewServeMux(muxOptions...)
return runtime.NewServeMux(muxOptions...)
}
func createDialOptions(g Gateway) []grpc.DialOption {
opts := []grpc.DialOption{grpc.WithInsecure()}
opts = append(opts, client_middleware.DefaultTracingStatsClient())
if customOpts, ok := g.(gatewayCustomCallOptions); ok {
opts = append(opts, customOpts.GatewayCallOptions()...)
}
err := g.Gateway()(ctx, mux, g.GRPCEndpoint(), opts)
logging.Log("SERVE-7B7G0E").OnError(err).Panic("failed to create mux for grpc gateway")
return mux
return opts
}
func addInterceptors(handler http.Handler, g Gateway) http.Handler {
@@ -83,26 +134,6 @@ func addInterceptors(handler http.Handler, g Gateway) http.Handler {
return http_mw.CORSInterceptorOpts(http_mw.DefaultCORSOptions, handler)
}
func serveGateway(ctx context.Context, handler http.Handler, port string, g Gateway) {
server := &http.Server{
Handler: addInterceptors(handler, g),
}
listener := http_util.CreateListener(port)
go func() {
<-ctx.Done()
err := server.Shutdown(ctx)
logging.Log("SERVE-m7kBlq").OnError(err).Warn("error during graceful shutdown of grpc gateway")
}()
go func() {
err := server.Serve(listener)
logging.Log("SERVE-tBHR60").OnError(err).Panic("grpc gateway serve failed")
}()
logging.LogWithFields("SERVE-KHh0Cb", "port", port).Info("grpc gateway is listening")
}
func gatewayPort(port string) string {
if port == "" {
return defaultGatewayPort

View File

@@ -2,37 +2,39 @@ package middleware
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/caos/zitadel/internal/api"
"github.com/caos/zitadel/internal/api/auth"
"github.com/caos/zitadel/internal/api/authz"
grpc_util "github.com/caos/zitadel/internal/api/grpc"
"github.com/caos/zitadel/internal/api/http"
)
func AuthorizationInterceptor(verifier auth.TokenVerifier, authConfig *auth.Config, authMethods auth.MethodMapping) func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
func AuthorizationInterceptor(verifier *authz.TokenVerifier, authConfig authz.Config) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
authOpt, needsToken := authMethods[info.FullMethod]
if !needsToken {
return handler(ctx, req)
}
authToken := ""
//TODO: Remove check internal as soon as authentification is implemented
if !auth.CheckInternal(ctx) {
authToken = grpc_util.GetAuthorizationHeader(ctx)
if authToken == "" {
return nil, status.Error(codes.Unauthenticated, "auth header missing")
}
}
orgID := grpc_util.GetHeader(ctx, api.ZitadelOrgID)
ctx, err := auth.CheckUserAuthorization(ctx, req, authToken, orgID, verifier, authConfig, authOpt)
if err != nil {
return nil, err
}
return handler(ctx, req)
return authorize(ctx, req, info, handler, verifier, authConfig)
}
}
func authorize(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler, verifier *authz.TokenVerifier, authConfig authz.Config) (interface{}, error) {
authOpt, needsToken := verifier.CheckAuthMethod(info.FullMethod)
if !needsToken {
return handler(ctx, req)
}
authToken := grpc_util.GetAuthorizationHeader(ctx)
if authToken == "" {
return nil, status.Error(codes.Unauthenticated, "auth header missing")
}
orgID := grpc_util.GetHeader(ctx, http.ZitadelOrgID)
ctx, err := authz.CheckUserAuthorization(ctx, req, authToken, orgID, verifier, authConfig, authOpt, info.FullMethod)
if err != nil {
return nil, err
}
return handler(ctx, req)
}

View File

@@ -0,0 +1,148 @@
package middleware
import (
"context"
"reflect"
"testing"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"github.com/caos/zitadel/internal/api/authz"
)
var (
mockMethods = authz.MethodMapping{
"need.authentication": authz.Option{
Permission: "authenticated",
},
}
)
type verifierMock struct{}
func (v *verifierMock) VerifyAccessToken(ctx context.Context, token, clientID string) (string, string, error) {
return "", "", nil
}
func (v *verifierMock) ResolveGrants(ctx context.Context) (*authz.Grant, error) {
return nil, nil
}
func (v *verifierMock) ProjectIDByClientID(ctx context.Context, clientID string) (string, error) {
return "", nil
}
func (v *verifierMock) VerifierClientID(ctx context.Context, appName string) (string, error) {
return "", nil
}
func Test_authorize(t *testing.T) {
type args struct {
ctx context.Context
req interface{}
info *grpc.UnaryServerInfo
handler grpc.UnaryHandler
verifier *authz.TokenVerifier
authConfig authz.Config
authMethods authz.MethodMapping
}
type res struct {
want interface{}
wantErr bool
}
tests := []struct {
name string
args args
res res
}{
{
"no token needed ok",
args{
ctx: context.Background(),
req: &mockReq{},
info: mockInfo("/no/token/needed"),
handler: emptyMockHandler,
verifier: func() *authz.TokenVerifier {
verifier := authz.Start(&verifierMock{})
verifier.RegisterServer("need", "need", authz.MethodMapping{})
return verifier
}(),
authMethods: mockMethods,
},
res{
&mockReq{},
false,
},
},
{
"auth header missing error",
args{
ctx: context.Background(),
req: &mockReq{},
info: mockInfo("/need/authentication"),
handler: emptyMockHandler,
verifier: func() *authz.TokenVerifier {
verifier := authz.Start(&verifierMock{})
verifier.RegisterServer("need", "need", authz.MethodMapping{"/need/authentication": authz.Option{Permission: "authenticated"}})
return verifier
}(),
authConfig: authz.Config{},
authMethods: mockMethods,
},
res{
nil,
true,
},
},
{
"unauthorized error",
args{
ctx: metadata.NewIncomingContext(context.Background(), metadata.Pairs("authorization", "wrong")),
req: &mockReq{},
info: mockInfo("/need/authentication"),
handler: emptyMockHandler,
verifier: func() *authz.TokenVerifier {
verifier := authz.Start(&verifierMock{})
verifier.RegisterServer("need", "need", authz.MethodMapping{"/need/authentication": authz.Option{Permission: "authenticated"}})
return verifier
}(),
authConfig: authz.Config{},
authMethods: mockMethods,
},
res{
nil,
true,
},
},
{
"authorized ok",
args{
ctx: metadata.NewIncomingContext(context.Background(), metadata.Pairs("authorization", "Bearer token")),
req: &mockReq{},
info: mockInfo("/need/authentication"),
handler: emptyMockHandler,
verifier: func() *authz.TokenVerifier {
verifier := authz.Start(&verifierMock{})
verifier.RegisterServer("need", "need", authz.MethodMapping{"/need/authentication": authz.Option{Permission: "authenticated"}})
return verifier
}(),
authConfig: authz.Config{},
authMethods: mockMethods,
},
res{
&mockReq{},
false,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := authorize(tt.args.ctx, tt.args.req, tt.args.info, tt.args.handler, tt.args.verifier, tt.args.authConfig)
if (err != nil) != tt.res.wantErr {
t.Errorf("authorize() error = %v, wantErr %v", err, tt.res.wantErr)
return
}
if !reflect.DeepEqual(got, tt.res.want) {
t.Errorf("authorize() got = %v, want %v", got, tt.res.want)
}
})
}
}

View File

@@ -4,18 +4,22 @@ import (
"context"
"golang.org/x/text/language"
"google.golang.org/grpc"
grpc_util "github.com/caos/zitadel/internal/api/grpc"
"github.com/caos/zitadel/internal/i18n"
_ "github.com/caos/zitadel/internal/statik"
)
func ErrorHandler(defaultLanguage language.Tag) func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
func ErrorHandler(defaultLanguage language.Tag) grpc.UnaryServerInterceptor {
translator := newZitadelTranslator(defaultLanguage)
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
resp, err := handler(ctx, req)
return resp, grpc_util.CaosToGRPCError(err, ctx, translator)
return toGRPCError(ctx, req, handler, translator)
}
}
func toGRPCError(ctx context.Context, req interface{}, handler grpc.UnaryHandler, translator *i18n.Translator) (interface{}, error) {
resp, err := handler(ctx, req)
return resp, grpc_util.CaosToGRPCError(ctx, err, translator)
}

View File

@@ -0,0 +1,63 @@
package middleware
import (
"context"
"reflect"
"testing"
"google.golang.org/grpc"
)
func Test_toGRPCError(t *testing.T) {
type args struct {
ctx context.Context
req interface{}
handler grpc.UnaryHandler
}
type res struct {
want interface{}
wantErr bool
}
tests := []struct {
name string
args args
res res
}{
{
"no error",
args{
ctx: context.Background(),
req: &mockReq{},
handler: emptyMockHandler,
},
res{
&mockReq{},
false,
},
},
{
"error",
args{
ctx: context.Background(),
req: &mockReq{},
handler: errorMockHandler,
},
res{
nil,
true,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := toGRPCError(tt.args.ctx, tt.args.req, tt.args.handler, nil)
if (err != nil) != tt.res.wantErr {
t.Errorf("toGRPCError() error = %v, wantErr %v", err, tt.res.wantErr)
return
}
if !reflect.DeepEqual(got, tt.res.want) {
t.Errorf("toGRPCError() got = %v, want %v", got, tt.res.want)
}
})
}
}

View File

@@ -0,0 +1,26 @@
package middleware
import (
"context"
"google.golang.org/grpc"
"github.com/caos/zitadel/internal/errors"
)
func emptyMockHandler(_ context.Context, req interface{}) (interface{}, error) {
return req, nil
}
func errorMockHandler(_ context.Context, req interface{}) (interface{}, error) {
return nil, errors.ThrowInternal(nil, "test", "error")
}
type mockReq struct{}
func mockInfo(path string) *grpc.UnaryServerInfo {
return &grpc.UnaryServerInfo{
Server: nil,
FullMethod: path,
}
}

View File

@@ -9,13 +9,28 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/stats"
"github.com/caos/zitadel/internal/api/http"
"github.com/caos/zitadel/internal/tracing"
)
type GRPCMethod string
func TracingStatsServer(ignoredMethods ...GRPCMethod) grpc.ServerOption {
return grpc.StatsHandler(&tracingServerHandler{ignoredMethods, ocgrpc.ServerHandler{StartOptions: trace.StartOptions{Sampler: tracing.Sampler(), SpanKind: trace.SpanKindServer}}})
return grpc.StatsHandler(
&tracingServerHandler{
ignoredMethods,
ocgrpc.ServerHandler{
StartOptions: trace.StartOptions{
Sampler: tracing.Sampler(),
SpanKind: trace.SpanKindServer,
},
},
},
)
}
func DefaultTracingStatsServer() grpc.ServerOption {
return TracingStatsServer(http.Healthz, http.Readiness, http.Validation)
}
type tracingServerHandler struct {

View File

@@ -0,0 +1,71 @@
package middleware
import (
"context"
"testing"
"go.opencensus.io/plugin/ocgrpc"
"go.opencensus.io/trace"
"google.golang.org/grpc/stats"
)
func Test_tracingServerHandler_TagRPC(t *testing.T) {
type fields struct {
IgnoredMethods []GRPCMethod
ServerHandler ocgrpc.ServerHandler
}
type args struct {
ctx context.Context
tagInfo *stats.RPCTagInfo
}
type res struct {
wantSpan bool
}
tests := []struct {
name string
fields fields
args args
res res
}{
{
"ignored method",
fields{
IgnoredMethods: []GRPCMethod{"ignore"},
ServerHandler: ocgrpc.ServerHandler{},
},
args{
ctx: context.Background(),
tagInfo: &stats.RPCTagInfo{
FullMethodName: "ignore",
},
},
res{false},
},
{
"tag",
fields{
IgnoredMethods: []GRPCMethod{"ignore"},
ServerHandler: ocgrpc.ServerHandler{},
},
args{
ctx: context.Background(),
tagInfo: &stats.RPCTagInfo{
FullMethodName: "tag",
},
},
res{true},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &tracingServerHandler{
IgnoredMethods: tt.fields.IgnoredMethods,
ServerHandler: tt.fields.ServerHandler,
}
got := s.TagRPC(tt.args.ctx, tt.args.tagInfo)
if (trace.FromContext(got) != nil) != tt.res.wantSpan {
t.Errorf("TagRPC() = %v, want %v", got, tt.res.wantSpan)
}
})
}
}

View File

@@ -26,7 +26,10 @@ func (v *Validator) Healthz(_ context.Context, e *empty.Empty) (*empty.Empty, er
}
func (v *Validator) Ready(ctx context.Context, e *empty.Empty) (*empty.Empty, error) {
return e, ready(ctx, v.validations)
if len(validate(ctx, v.validations)) == 0 {
return e, nil
}
return nil, errors.ThrowInternal(nil, "API-2jD9a", "not ready")
}
func (v *Validator) Validate(ctx context.Context, _ *empty.Empty) (*structpb.Struct, error) {
@@ -34,13 +37,6 @@ func (v *Validator) Validate(ctx context.Context, _ *empty.Empty) (*structpb.Str
return proto.ToPBStruct(validations)
}
func ready(ctx context.Context, validations map[string]ValidationFunction) error {
if len(validate(ctx, validations)) == 0 {
return nil
}
return errors.ThrowInternal(nil, "API-2jD9a", "not ready")
}
func validate(ctx context.Context, validations map[string]ValidationFunction) map[string]error {
errors := make(map[string]error)
for id, validation := range validations {

View File

@@ -0,0 +1,158 @@
package server
import (
"context"
"reflect"
"testing"
"github.com/golang/protobuf/ptypes/empty"
"github.com/caos/zitadel/internal/errors"
)
func TestValidator_Healthz(t *testing.T) {
type fields struct {
validations map[string]ValidationFunction
}
type res struct {
want *empty.Empty
hasErr bool
}
tests := []struct {
name string
fields fields
res res
}{
{
"ok",
fields{},
res{
&empty.Empty{},
false,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
v := &Validator{
validations: tt.fields.validations,
}
got, err := v.Healthz(nil, &empty.Empty{})
if (err != nil) != tt.res.hasErr {
t.Errorf("Healthz() error = %v, wantErr %v", err, tt.res.hasErr)
return
}
if !reflect.DeepEqual(got, tt.res.want) {
t.Errorf("Healthz() got = %v, want %v", got, tt.res.want)
}
})
}
}
func TestValidator_Ready(t *testing.T) {
type fields struct {
validations map[string]ValidationFunction
}
type res struct {
want *empty.Empty
hasErr bool
}
tests := []struct {
name string
fields fields
res res
}{
{
"unready error",
fields{validations: map[string]ValidationFunction{
"error": func(_ context.Context) error {
return errors.ThrowInternal(nil, "id", "message")
},
}},
res{
nil,
true,
},
},
{
"ready ok",
fields{validations: map[string]ValidationFunction{
"ok": func(_ context.Context) error {
return nil
},
}},
res{
&empty.Empty{},
false,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
v := &Validator{
validations: tt.fields.validations,
}
got, err := v.Ready(context.Background(), &empty.Empty{})
if (err != nil) != tt.res.hasErr {
t.Errorf("Ready() error = %v, wantErr %v", err, tt.res.hasErr)
return
}
if !reflect.DeepEqual(got, tt.res.want) {
t.Errorf("Ready() got = %v, want %v", got, tt.res.want)
}
})
}
}
func Test_validate(t *testing.T) {
type args struct {
validations map[string]ValidationFunction
}
type res struct {
want map[string]error
}
tests := []struct {
name string
args args
res res
}{
{
"no error empty",
args{
validations: map[string]ValidationFunction{
"ok": func(_ context.Context) error {
return nil
},
},
},
res{
map[string]error{},
},
},
{
"error in list",
args{
validations: map[string]ValidationFunction{
"ok": func(_ context.Context) error {
return nil
},
"error": func(_ context.Context) error {
return errors.ThrowInternal(nil, "id", "message")
},
},
},
res{
map[string]error{
"error": errors.ThrowInternal(nil, "id", "message"),
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := validate(context.Background(), tt.args.validations); !reflect.DeepEqual(got, tt.res.want) {
t.Errorf("validate() = %v, want %v", got, tt.res.want)
}
})
}
}

View File

@@ -2,12 +2,14 @@ package server
import (
"context"
"github.com/caos/zitadel/internal/config/systemdefaults"
"net"
"github.com/caos/logging"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
"golang.org/x/text/language"
"google.golang.org/grpc"
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/api/grpc/server/middleware"
"github.com/caos/zitadel/internal/api/http"
)
@@ -16,30 +18,36 @@ const (
)
type Server interface {
GRPCPort() string
GRPCServer(defaults systemdefaults.SystemDefaults) (*grpc.Server, error)
Gateway
RegisterServer(*grpc.Server)
AppName() string
MethodPrefix() string
AuthMethods() authz.MethodMapping
}
func StartServer(ctx context.Context, s Server, defaults systemdefaults.SystemDefaults) {
port := grpcPort(s.GRPCPort())
listener := http.CreateListener(port)
server := createGrpcServer(s, defaults)
serveServer(ctx, server, listener, port)
func CreateServer(verifier *authz.TokenVerifier, authConfig authz.Config, lang language.Tag) *grpc.Server {
return grpc.NewServer(
middleware.TracingStatsServer(http.Healthz, http.Readiness, http.Validation),
grpc.UnaryInterceptor(
grpc_middleware.ChainUnaryServer(
middleware.ErrorHandler(lang),
middleware.TranslationHandler(lang),
grpc_middleware.ChainUnaryServer(
middleware.AuthorizationInterceptor(verifier, authConfig),
),
),
),
)
}
func createGrpcServer(s Server, defaults systemdefaults.SystemDefaults) *grpc.Server {
grpcServer, err := s.GRPCServer(defaults)
logging.Log("SERVE-k280HZ").OnError(err).Panic("failed to create grpc server")
return grpcServer
}
func serveServer(ctx context.Context, server *grpc.Server, listener net.Listener, port string) {
func Serve(ctx context.Context, server *grpc.Server, port string) {
go func() {
<-ctx.Done()
server.GracefulStop()
}()
go func() {
listener := http.CreateListener(port)
err := server.Serve(listener)
logging.Log("SERVE-Ga3e94").OnError(err).Panic("grpc server serve failed")
}()