summaryrefslogtreecommitdiff
path: root/internal/handler/exec.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/handler/exec.go')
-rw-r--r--internal/handler/exec.go114
1 files changed, 34 insertions, 80 deletions
diff --git a/internal/handler/exec.go b/internal/handler/exec.go
index 9bd8018..44b02a7 100644
--- a/internal/handler/exec.go
+++ b/internal/handler/exec.go
@@ -6,56 +6,57 @@ import (
"strconv"
"strings"
- grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
- grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
"google.golang.org/grpc"
grpccodes "google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
grpcstatus "google.golang.org/grpc/status"
"gitlab.com/gitlab-org/gitlab-shell/internal/config"
+ "gitlab.com/gitlab-org/gitlab-shell/internal/gitaly"
"gitlab.com/gitlab-org/gitlab-shell/internal/gitlabnet/accessverifier"
"gitlab.com/gitlab-org/gitlab-shell/internal/sshenv"
- gitalyauth "gitlab.com/gitlab-org/gitaly/v14/auth"
- "gitlab.com/gitlab-org/gitaly/v14/client"
pb "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
- "gitlab.com/gitlab-org/labkit/correlation"
- grpccorrelation "gitlab.com/gitlab-org/labkit/correlation/grpc"
"gitlab.com/gitlab-org/labkit/log"
- grpctracing "gitlab.com/gitlab-org/labkit/tracing/grpc"
)
// GitalyHandlerFunc implementations are responsible for making
// an appropriate Gitaly call using the provided client and context
// and returning an error from the Gitaly call.
-type GitalyHandlerFunc func(ctx context.Context, client *grpc.ClientConn, registry *client.SidechannelRegistry) (int32, error)
+type GitalyHandlerFunc func(ctx context.Context, client *grpc.ClientConn) (int32, error)
type GitalyCommand struct {
- Config *config.Config
- ServiceName string
- Address string
- Token string
- Features map[string]string
- DialSidechannel bool
+ Config *config.Config
+ Response *accessverifier.Response
+ Command gitaly.Command
+}
+
+func NewGitalyCommand(cfg *config.Config, serviceName string, response *accessverifier.Response) *GitalyCommand {
+ gc := gitaly.Command{
+ ServiceName: serviceName,
+ Address: response.Gitaly.Address,
+ Token: response.Gitaly.Token,
+ DialSidechannel: response.Gitaly.UseSidechannel,
+ }
+
+ return &GitalyCommand{Config: cfg, Response: response, Command: gc}
}
// RunGitalyCommand provides a bootstrap for Gitaly commands executed
// through GitLab-Shell. It ensures that logging, tracing and other
// common concerns are configured before executing the `handler`.
func (gc *GitalyCommand) RunGitalyCommand(ctx context.Context, handler GitalyHandlerFunc) error {
- registry := client.NewSidechannelRegistry(log.ContextLogger(ctx))
- conn, err := getConn(ctx, gc, registry)
+ // We leave the connection open for future reuse
+ conn, err := gc.getConn(ctx)
if err != nil {
log.ContextLogger(ctx).WithError(fmt.Errorf("RunGitalyCommand: %v", err)).Error("Failed to get connection to execute Git command")
return err
}
- defer conn.Close()
- childCtx := withOutgoingMetadata(ctx, gc.Features)
+ childCtx := withOutgoingMetadata(ctx, gc.Response.Gitaly.Features)
ctxlog := log.ContextLogger(childCtx)
- exitStatus, err := handler(childCtx, conn, registry)
+ exitStatus, err := handler(childCtx, conn)
if err != nil {
if grpcstatus.Convert(err).Code() == grpccodes.Unavailable {
@@ -72,35 +73,35 @@ func (gc *GitalyCommand) RunGitalyCommand(ctx context.Context, handler GitalyHan
// PrepareContext wraps a given context with a correlation ID and logs the command to
// be run.
-func (gc *GitalyCommand) PrepareContext(ctx context.Context, repository *pb.Repository, response *accessverifier.Response, env sshenv.Env) (context.Context, context.CancelFunc) {
+func (gc *GitalyCommand) PrepareContext(ctx context.Context, repository *pb.Repository, env sshenv.Env) (context.Context, context.CancelFunc) {
ctx, cancel := context.WithCancel(ctx)
- gc.LogExecution(ctx, repository, response, env)
+ gc.LogExecution(ctx, repository, env)
md, ok := metadata.FromOutgoingContext(ctx)
if !ok {
md = metadata.New(nil)
}
- md.Append("key_id", strconv.Itoa(response.KeyId))
- md.Append("key_type", response.KeyType)
- md.Append("user_id", response.UserId)
- md.Append("username", response.Username)
+ md.Append("key_id", strconv.Itoa(gc.Response.KeyId))
+ md.Append("key_type", gc.Response.KeyType)
+ md.Append("user_id", gc.Response.UserId)
+ md.Append("username", gc.Response.Username)
md.Append("remote_ip", env.RemoteAddr)
ctx = metadata.NewOutgoingContext(ctx, md)
return ctx, cancel
}
-func (gc *GitalyCommand) LogExecution(ctx context.Context, repository *pb.Repository, response *accessverifier.Response, env sshenv.Env) {
+func (gc *GitalyCommand) LogExecution(ctx context.Context, repository *pb.Repository, env sshenv.Env) {
fields := log.Fields{
- "command": gc.ServiceName,
+ "command": gc.Command.ServiceName,
"gl_project_path": repository.GlProjectPath,
"gl_repository": repository.GlRepository,
- "user_id": response.UserId,
- "username": response.Username,
+ "user_id": gc.Response.UserId,
+ "username": gc.Response.Username,
"git_protocol": env.GitProtocolVersion,
"remote_ip": env.RemoteAddr,
- "gl_key_type": response.KeyType,
- "gl_key_id": response.KeyId,
+ "gl_key_type": gc.Response.KeyType,
+ "gl_key_id": gc.Response.KeyId,
}
log.WithContextFields(ctx, fields).Info("executing git command")
@@ -118,53 +119,6 @@ func withOutgoingMetadata(ctx context.Context, features map[string]string) conte
return metadata.NewOutgoingContext(ctx, md)
}
-func getConn(ctx context.Context, gc *GitalyCommand, registry *client.SidechannelRegistry) (*grpc.ClientConn, error) {
- if gc.Address == "" {
- return nil, fmt.Errorf("no gitaly_address given")
- }
-
- serviceName := correlation.ExtractClientNameFromContext(ctx)
- if serviceName == "" {
- serviceName = "gitlab-shell-unknown"
-
- log.WithContextFields(ctx, log.Fields{"service_name": serviceName}).Warn("No gRPC service name specified, defaulting to gitlab-shell-unknown")
- }
-
- serviceName = fmt.Sprintf("%s-%s", serviceName, gc.ServiceName)
-
- connOpts := client.DefaultDialOpts
- connOpts = append(
- connOpts,
- grpc.WithStreamInterceptor(
- grpc_middleware.ChainStreamClient(
- grpctracing.StreamClientTracingInterceptor(),
- grpc_prometheus.StreamClientInterceptor,
- grpccorrelation.StreamClientCorrelationInterceptor(
- grpccorrelation.WithClientName(serviceName),
- ),
- ),
- ),
-
- grpc.WithUnaryInterceptor(
- grpc_middleware.ChainUnaryClient(
- grpctracing.UnaryClientTracingInterceptor(),
- grpc_prometheus.UnaryClientInterceptor,
- grpccorrelation.UnaryClientCorrelationInterceptor(
- grpccorrelation.WithClientName(serviceName),
- ),
- ),
- ),
- )
-
- if gc.Token != "" {
- connOpts = append(connOpts,
- grpc.WithPerRPCCredentials(gitalyauth.RPCCredentialsV2(gc.Token)),
- )
- }
-
- if gc.DialSidechannel {
- return client.DialSidechannel(ctx, gc.Address, registry, connOpts)
- }
-
- return client.DialContext(ctx, gc.Address, connOpts)
+func (gc *GitalyCommand) getConn(ctx context.Context) (*grpc.ClientConn, error) {
+ return gc.Config.GitalyClient.GetConnection(ctx, gc.Command)
}