Commit eb2b186f authored by Nick Thomas's avatar Nick Thomas

Merge branch 'id-git-upload-archive' into 'master'

Go implementation for git-upload-archive

Closes #162

See merge request gitlab-org/gitlab-shell!307
parents f61185b8 60e258e3
......@@ -7,6 +7,7 @@ import (
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/readwriter"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/receivepack"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/twofactorrecover"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/uploadarchive"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/uploadpack"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/config"
)
......@@ -41,6 +42,8 @@ func buildCommand(args *commandargs.CommandArgs, config *config.Config, readWrit
return &receivepack.Command{Config: config, Args: args, ReadWriter: readWriter}
case commandargs.UploadPack:
return &uploadpack.Command{Config: config, Args: args, ReadWriter: readWriter}
case commandargs.UploadArchive:
return &uploadarchive.Command{Config: config, Args: args, ReadWriter: readWriter}
}
return nil
......
......@@ -9,6 +9,7 @@ import (
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/fallback"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/receivepack"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/twofactorrecover"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/uploadarchive"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/uploadpack"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/config"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/testhelper"
......@@ -81,6 +82,18 @@ func TestNew(t *testing.T) {
},
expectedType: &uploadpack.Command{},
},
{
desc: "it returns a UploadArchive command if the feature is enabled",
config: &config.Config{
GitlabUrl: "http+unix://gitlab.socket",
Migration: config.MigrationConfig{Enabled: true, Features: []string{"git-upload-archive"}},
},
environment: map[string]string{
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": "git-upload-archive",
},
expectedType: &uploadarchive.Command{},
},
{
desc: "it returns a Fallback command if the feature is unimplemented",
config: &config.Config{
......
......@@ -15,6 +15,7 @@ const (
TwoFactorRecover CommandType = "2fa_recovery_codes"
ReceivePack CommandType = "git-receive-pack"
UploadPack CommandType = "git-upload-pack"
UploadArchive CommandType = "git-upload-archive"
)
var (
......
......@@ -83,6 +83,13 @@ func TestParseSuccess(t *testing.T) {
"SSH_ORIGINAL_COMMAND": `git upload-pack "group/repo"`,
},
expectedArgs: &CommandArgs{SshArgs: []string{"git-upload-pack", "group/repo"}, CommandType: UploadPack},
}, {
desc: "It parses git-upload-archive command",
environment: map[string]string{
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": "git-upload-archive 'group/repo'",
},
expectedArgs: &CommandArgs{SshArgs: []string{"git-upload-archive", "group/repo"}, CommandType: UploadArchive},
},
}
......
package uploadarchive
import (
"context"
"google.golang.org/grpc"
pb "gitlab.com/gitlab-org/gitaly-proto/go/gitalypb"
"gitlab.com/gitlab-org/gitaly/client"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/commandargs"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/gitlabnet/accessverifier"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/handler"
)
func (c *Command) performGitalyCall(response *accessverifier.Response) error {
gc := &handler.GitalyCommand{
Config: c.Config,
ServiceName: string(commandargs.UploadArchive),
Address: response.Gitaly.Address,
Token: response.Gitaly.Token,
}
request := &pb.SSHUploadArchiveRequest{Repository: &response.Gitaly.Repo}
return gc.RunGitalyCommand(func(ctx context.Context, conn *grpc.ClientConn) (int32, error) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
rw := c.ReadWriter
return client.UploadArchive(ctx, conn, rw.In, rw.Out, rw.ErrOut, request)
})
}
package uploadarchive
import (
"bytes"
"testing"
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/commandargs"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/readwriter"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/config"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/gitlabnet/testserver"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/testhelper/requesthandlers"
)
func TestUploadPack(t *testing.T) {
gitalyAddress, cleanup := testserver.StartGitalyServer(t)
defer cleanup()
requests := requesthandlers.BuildAllowedWithGitalyHandlers(t, gitalyAddress)
url, cleanup := testserver.StartHttpServer(t, requests)
defer cleanup()
output := &bytes.Buffer{}
input := &bytes.Buffer{}
userId := "1"
repo := "group/repo"
cmd := &Command{
Config: &config.Config{GitlabUrl: url},
Args: &commandargs.CommandArgs{GitlabKeyId: userId, CommandType: commandargs.UploadArchive, SshArgs: []string{"git-upload-archive", repo}},
ReadWriter: &readwriter.ReadWriter{ErrOut: output, Out: output, In: input},
}
err := cmd.Execute()
require.NoError(t, err)
require.Equal(t, "UploadArchive: "+repo, output.String())
}
package uploadarchive
import (
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/commandargs"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/readwriter"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/shared/accessverifier"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/shared/disallowedcommand"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/config"
)
type Command struct {
Config *config.Config
Args *commandargs.CommandArgs
ReadWriter *readwriter.ReadWriter
}
func (c *Command) Execute() error {
args := c.Args.SshArgs
if len(args) != 2 {
return disallowedcommand.Error
}
repo := args[1]
response, err := c.verifyAccess(repo)
if err != nil {
return err
}
return c.performGitalyCall(response)
}
func (c *Command) verifyAccess(repo string) (*accessverifier.Response, error) {
cmd := accessverifier.Command{c.Config, c.Args, c.ReadWriter}
return cmd.Verify(c.Args.CommandType, repo)
}
package uploadarchive
import (
"bytes"
"testing"
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/commandargs"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/readwriter"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/config"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/gitlabnet/testserver"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/testhelper/requesthandlers"
)
func TestForbiddenAccess(t *testing.T) {
requests := requesthandlers.BuildDisallowedByApiHandlers(t)
url, cleanup := testserver.StartHttpServer(t, requests)
defer cleanup()
output := &bytes.Buffer{}
cmd := &Command{
Config: &config.Config{GitlabUrl: url},
Args: &commandargs.CommandArgs{GitlabKeyId: "disallowed", SshArgs: []string{"git-upload-archive", "group/repo"}},
ReadWriter: &readwriter.ReadWriter{ErrOut: output, Out: output},
}
err := cmd.Execute()
require.Equal(t, "Disallowed by API call", err.Error())
}
......@@ -41,6 +41,14 @@ func (s *testGitalyServer) SSHUploadPack(stream pb.SSHService_SSHUploadPackServe
}
func (s *testGitalyServer) SSHUploadArchive(stream pb.SSHService_SSHUploadArchiveServer) error {
req, err := stream.Recv()
if err != nil {
return err
}
response := []byte("UploadArchive: " + req.Repository.GlRepository)
stream.Send(&pb.SSHUploadArchiveResponse{Stdout: response})
return nil
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment