Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Chandler <wchandler@gitlab.com>2021-12-03 19:41:28 +0300
committerWill Chandler <wchandler@gitlab.com>2021-12-13 20:03:09 +0300
commit9deaf47f1ecb00f0f36d18ee4a0fb1576f5a0efe (patch)
tree1f6662333aaf19e98845fbb5609ee191c990a16a
parent6ae82339b1bc5b81ffd974434002faf2d376b8bf (diff)
ssh: Log error on git command failure
If the `git upload-pack` process forked by `SSHUploadPack` or `git upload-archive` from `SSHUploadArchive` exits with a non-zero return code, the result of executing `stream.Send` to respond to the client will be returned, causing the request to be seen as successful by Gitaly. Clients will correctly receive the non-zero return code, but a status of `OK` will be logged and the `grpc_server_handled_total` metric will increment for `grpc_code=OK`. This commit corrects `SSHUploadPack` and `SSHArchivePack` to return an error when git fails. Changelog: fixed
-rw-r--r--internal/git/localrepo/remote_extra_test.go2
-rw-r--r--internal/gitaly/service/ssh/upload_archive.go7
-rw-r--r--internal/gitaly/service/ssh/upload_pack.go7
-rw-r--r--internal/gitaly/service/ssh/upload_pack_test.go38
4 files changed, 47 insertions, 7 deletions
diff --git a/internal/git/localrepo/remote_extra_test.go b/internal/git/localrepo/remote_extra_test.go
index 2cfa720a0..acb91442d 100644
--- a/internal/git/localrepo/remote_extra_test.go
+++ b/internal/git/localrepo/remote_extra_test.go
@@ -132,7 +132,7 @@ func TestRepo_FetchInternal(t *testing.T) {
)
require.EqualError(t, err, "exit status 128")
require.IsType(t, err, localrepo.ErrFetchFailed{})
- require.Equal(t, "fatal: couldn't find remote ref refs/does/not/exist\nfatal: the remote end hung up unexpectedly\n", stderr.String())
+ require.Contains(t, stderr.String(), "fatal: couldn't find remote ref refs/does/not/exist\nfatal: the remote end hung up unexpectedly\n")
})
t.Run("with env", func(t *testing.T) {
diff --git a/internal/gitaly/service/ssh/upload_archive.go b/internal/gitaly/service/ssh/upload_archive.go
index ea5de6984..9ca40558d 100644
--- a/internal/gitaly/service/ssh/upload_archive.go
+++ b/internal/gitaly/service/ssh/upload_archive.go
@@ -68,9 +68,12 @@ func (s *server) sshUploadArchive(stream gitalypb.SSHService_SSHUploadArchiveSer
if err := cmd.Wait(); err != nil {
if status, ok := command.ExitStatus(err); ok {
- return stream.Send(&gitalypb.SSHUploadArchiveResponse{
+ if sendErr := stream.Send(&gitalypb.SSHUploadArchiveResponse{
ExitStatus: &gitalypb.ExitStatus{Value: int32(status)},
- })
+ }); sendErr != nil {
+ return sendErr
+ }
+ return fmt.Errorf("SSHUploadPack: %v", err)
}
return fmt.Errorf("wait cmd: %v", err)
}
diff --git a/internal/gitaly/service/ssh/upload_pack.go b/internal/gitaly/service/ssh/upload_pack.go
index d2ac79a7a..656346d9f 100644
--- a/internal/gitaly/service/ssh/upload_pack.go
+++ b/internal/gitaly/service/ssh/upload_pack.go
@@ -125,9 +125,12 @@ func (s *server) sshUploadPack(stream gitalypb.SSHService_SSHUploadPackServer, r
wg.Wait()
if status, ok := command.ExitStatus(err); ok {
- return stream.Send(&gitalypb.SSHUploadPackResponse{
+ if sendErr := stream.Send(&gitalypb.SSHUploadPackResponse{
ExitStatus: &gitalypb.ExitStatus{Value: int32(status)},
- })
+ }); sendErr != nil {
+ return sendErr
+ }
+ return fmt.Errorf("SSHUploadPack: %v", err)
}
return fmt.Errorf("cmd wait: %v", err)
}
diff --git a/internal/gitaly/service/ssh/upload_pack_test.go b/internal/gitaly/service/ssh/upload_pack_test.go
index caa7bee00..599f85c13 100644
--- a/internal/gitaly/service/ssh/upload_pack_test.go
+++ b/internal/gitaly/service/ssh/upload_pack_test.go
@@ -3,7 +3,6 @@ package ssh
import (
"bytes"
"fmt"
- "io"
"os"
"os/exec"
"path/filepath"
@@ -153,7 +152,7 @@ func requireFailedSSHStream(t *testing.T, recv func() (int32, error)) {
select {
case <-done:
- require.Equal(t, io.EOF, err)
+ testhelper.RequireGrpcCode(t, err, codes.Internal)
require.NotEqual(t, 0, code, "exit status")
case <-time.After(10 * time.Second):
t.Fatal("timeout waiting for SSH stream")
@@ -545,6 +544,41 @@ func TestUploadPackCloneFailure(t *testing.T) {
require.Error(t, err, "clone didn't fail")
}
+func TestUploadPackCloneGitFailure(t *testing.T) {
+ cfg, repo, _ := testcfg.BuildWithRepo(t)
+
+ serverSocketPath := runSSHServer(t, cfg)
+
+ client, conn := newSSHClient(t, serverSocketPath)
+ defer conn.Close()
+
+ configPath := filepath.Join(cfg.Storages[0].Path, repo.RelativePath, "config")
+ gitconfig, err := os.Create(configPath)
+ require.NoError(t, err)
+
+ // Writing an invalid config will allow repo to pass the `IsGitDirectory` check but still
+ // trigger an error when git tries to access the repo.
+ _, err = gitconfig.WriteString("Not a valid git config")
+ require.NoError(t, err)
+
+ require.NoError(t, gitconfig.Close())
+
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+ stream, err := client.SSHUploadPack(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err = stream.Send(&gitalypb.SSHUploadPackRequest{Repository: repo}); err != nil {
+ t.Fatal(err)
+ }
+ require.NoError(t, stream.CloseSend())
+
+ err = testPostUploadPackFailedResponse(t, stream)
+ testhelper.RequireGrpcCode(t, err, codes.Internal)
+}
+
func testPostUploadPackFailedResponse(t *testing.T, stream gitalypb.SSHService_SSHUploadPackClient) error {
var err error
var res *gitalypb.SSHUploadPackResponse