drone/gitrpc/server/server.go

143 lines
4.2 KiB
Go

// Copyright 2023 Harness, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package server
import (
"errors"
"fmt"
"net"
"os"
"path/filepath"
"github.com/harness/gitness/gitrpc/internal/middleware"
"github.com/harness/gitness/gitrpc/internal/service"
"github.com/harness/gitness/gitrpc/internal/storage"
"github.com/harness/gitness/gitrpc/rpc"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
"google.golang.org/grpc"
"google.golang.org/grpc/keepalive"
)
const (
repoSubdirName = "repos"
ReposGraveyardSubdirName = "cleanup"
)
type GRPCServer struct {
*grpc.Server
Port int
}
func NewServer(config Config, adapter service.GitAdapter) (*GRPCServer, error) {
if err := config.Validate(); err != nil {
return nil, fmt.Errorf("configuration is invalid: %w", err)
}
// Create repos folder
reposRoot := filepath.Join(config.GitRoot, repoSubdirName)
if _, err := os.Stat(reposRoot); errors.Is(err, os.ErrNotExist) {
if err = os.MkdirAll(reposRoot, 0o700); err != nil {
return nil, err
}
}
// interceptors
errIntc := middleware.NewErrInterceptor()
logIntc := middleware.NewLogInterceptor()
s := grpc.NewServer(
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
grpc_recovery.UnaryServerInterceptor(),
logIntc.UnaryInterceptor(),
errIntc.UnaryInterceptor(),
)),
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
grpc_recovery.StreamServerInterceptor(),
logIntc.StreamInterceptor(),
errIntc.StreamInterceptor(),
)),
grpc.KeepaliveParams(keepalive.ServerParameters{
MaxConnectionAge: config.MaxConnAge,
MaxConnectionAgeGrace: config.MaxConnAgeGrace,
}),
)
store := storage.NewLocalStore()
// create a temp dir for deleted repositories
// this dir should get cleaned up peridocally if it's not empty
reposGraveyard := filepath.Join(config.GitRoot, ReposGraveyardSubdirName)
if _, errdir := os.Stat(reposGraveyard); os.IsNotExist(errdir) {
if errdir = os.MkdirAll(reposGraveyard, 0o700); errdir != nil {
return nil, errdir
}
}
// initialize services
repoService, err := service.NewRepositoryService(adapter, store, reposRoot, config.TmpDir,
config.GitHookPath, reposGraveyard)
if err != nil {
return nil, err
}
refService, err := service.NewReferenceService(adapter, reposRoot, config.TmpDir)
if err != nil {
return nil, err
}
httpService, err := service.NewHTTPService(adapter, reposRoot)
if err != nil {
return nil, err
}
commitFilesService, err := service.NewCommitFilesService(adapter, reposRoot, config.TmpDir)
if err != nil {
return nil, err
}
diffService, err := service.NewDiffService(adapter, reposRoot, config.TmpDir)
if err != nil {
return nil, err
}
mergeService, err := service.NewMergeService(adapter, reposRoot, config.TmpDir)
if err != nil {
return nil, err
}
blameService := service.NewBlameService(adapter, reposRoot)
pushService := service.NewPushService(adapter, reposRoot)
// register services
rpc.RegisterRepositoryServiceServer(s, repoService)
rpc.RegisterReferenceServiceServer(s, refService)
rpc.RegisterSmartHTTPServiceServer(s, httpService)
rpc.RegisterCommitFilesServiceServer(s, commitFilesService)
rpc.RegisterDiffServiceServer(s, diffService)
rpc.RegisterMergeServiceServer(s, mergeService)
rpc.RegisterBlameServiceServer(s, blameService)
rpc.RegisterPushServiceServer(s, pushService)
return &GRPCServer{
Server: s,
Port: config.Port,
}, nil
}
func (s *GRPCServer) Start() error {
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", s.Port))
if err != nil {
return err
}
return s.Server.Serve(lis)
}
func (s *GRPCServer) Stop() error {
s.Server.GracefulStop()
return nil
}