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:
authorKim "BKC" Carlbäcker <kim.carlbacker@gmail.com>2017-09-22 11:25:50 +0300
committerKim "BKC" Carlbäcker <kim.carlbacker@gmail.com>2017-09-29 23:35:04 +0300
commitb3bcd7810a75dda671c26b2162bd13e8f0b4b090 (patch)
tree2423e1361b489c0dc165520b8e5a089abdeaaba4
parent3cec5a47fdb56ccd83bc6829b36d8123b72ab797 (diff)
Implement cmd/gitaly-ssh command
-rw-r--r--.gitignore2
-rw-r--r--CHANGELOG.md2
-rw-r--r--cmd/gitaly-ssh/main.go57
-rw-r--r--cmd/gitaly-ssh/receive_pack.go33
-rw-r--r--cmd/gitaly-ssh/upload_pack.go33
-rw-r--r--internal/service/ssh/cmd/gitaly-receive-pack/main.go49
-rw-r--r--internal/service/ssh/cmd/gitaly-upload-pack/main.go56
-rw-r--r--internal/service/ssh/receive_pack_test.go22
-rw-r--r--internal/service/ssh/testhelper_test.go16
-rw-r--r--internal/service/ssh/upload_pack_test.go59
10 files changed, 185 insertions, 144 deletions
diff --git a/.gitignore b/.gitignore
index ca6bf2d4c..5975a83ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,7 +6,7 @@
/internal/service/smarthttp/testdata
/internal/testhelper/testdata
/config.toml
-/internal/service/ssh/gitaly-*-pack
+/internal/service/ssh/gitaly-ssh
/.ruby-bundle
/ruby/vendor/bundle
/ruby/.bundle
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3eb65f4d8..bcc5e33d8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,8 @@ UNRELEASED
https://gitlab.com/gitlab-org/gitaly/merge_requests/379
- Implement RepositoryService.GetArchive RPC
https://gitlab.com/gitlab-org/gitaly/merge_requests/370
+- Add `gitaly-ssh` command
+ https://gitlab.com/gitlab-org/gitaly/merge_requests/368
v0.42.0
diff --git a/cmd/gitaly-ssh/main.go b/cmd/gitaly-ssh/main.go
new file mode 100644
index 000000000..195d6370f
--- /dev/null
+++ b/cmd/gitaly-ssh/main.go
@@ -0,0 +1,57 @@
+package main
+
+import (
+ "log"
+ "os"
+
+ "gitlab.com/gitlab-org/gitaly/auth"
+ "gitlab.com/gitlab-org/gitaly/client"
+ "google.golang.org/grpc"
+)
+
+type packFn func(_, _ string) (int32, error)
+
+// GITALY_ADDRESS="tcp://1.2.3.4:9999" or "unix:/var/run/gitaly.sock"
+// GITALY_TOKEN="foobar1234"
+// GITALY_PAYLOAD="{repo...}"
+// GITALY_WD="/path/to/working-directory"
+// gitaly-ssh upload-pack <git-garbage-x2>
+func main() {
+ // < 4 since git throws on 2x garbage here
+ if n := len(os.Args); n < 4 {
+ // TODO: Errors needs to be sent back some other way... pipes?
+ log.Fatalf("invalid number of arguments, expected at least 1, got %d", n-1)
+ }
+
+ var packer packFn
+ switch os.Args[1] {
+ case "upload-pack":
+ packer = uploadPack
+ case "receive-pack":
+ packer = receivePack
+ default:
+ log.Fatalf("invalid pack command: %q", os.Args[1])
+ }
+
+ if wd := os.Getenv("GITALY_WD"); wd != "" {
+ if err := os.Chdir(wd); err != nil {
+ log.Fatalf("change to : %v", err)
+ }
+ }
+
+ code, err := packer(os.Getenv("GITALY_ADDRESS"), os.Getenv("GITALY_PAYLOAD"))
+ if err != nil {
+ log.Fatalf("%s: %v", os.Args[1], err)
+ }
+
+ os.Exit(int(code))
+}
+
+func dialOpts() []grpc.DialOption {
+ connOpts := client.DefaultDialOpts
+ if token := os.Getenv("GITALY_TOKEN"); token != "" {
+ connOpts = append(connOpts, grpc.WithPerRPCCredentials(gitalyauth.RPCCredentials(token)))
+ }
+
+ return connOpts
+}
diff --git a/cmd/gitaly-ssh/receive_pack.go b/cmd/gitaly-ssh/receive_pack.go
new file mode 100644
index 000000000..5b6489d67
--- /dev/null
+++ b/cmd/gitaly-ssh/receive_pack.go
@@ -0,0 +1,33 @@
+package main
+
+import (
+ "context"
+ "fmt"
+ "os"
+
+ "github.com/golang/protobuf/jsonpb"
+
+ pb "gitlab.com/gitlab-org/gitaly-proto/go"
+ "gitlab.com/gitlab-org/gitaly/client"
+)
+
+func receivePack(url, req string) (int32, error) {
+ var request pb.SSHReceivePackRequest
+ if err := jsonpb.UnmarshalString(req, &request); err != nil {
+ return 0, fmt.Errorf("json unmarshal: %v", err)
+ }
+
+ if url == "" {
+ return 0, fmt.Errorf("gitaly address can not be empty")
+ }
+ conn, err := client.Dial(url, dialOpts())
+ if err != nil {
+ return 0, fmt.Errorf("dial %q: %v", url, err)
+ }
+ defer conn.Close()
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ return client.ReceivePack(ctx, conn, os.Stdin, os.Stdout, os.Stderr, &request)
+}
diff --git a/cmd/gitaly-ssh/upload_pack.go b/cmd/gitaly-ssh/upload_pack.go
new file mode 100644
index 000000000..9526ea295
--- /dev/null
+++ b/cmd/gitaly-ssh/upload_pack.go
@@ -0,0 +1,33 @@
+package main
+
+import (
+ "context"
+ "fmt"
+ "os"
+
+ "github.com/golang/protobuf/jsonpb"
+
+ pb "gitlab.com/gitlab-org/gitaly-proto/go"
+ "gitlab.com/gitlab-org/gitaly/client"
+)
+
+func uploadPack(url, req string) (int32, error) {
+ var request pb.SSHUploadPackRequest
+ if err := jsonpb.UnmarshalString(req, &request); err != nil {
+ return 0, fmt.Errorf("json unmarshal: %v", err)
+ }
+
+ if url == "" {
+ return 0, fmt.Errorf("gitaly address can not be empty")
+ }
+ conn, err := client.Dial(url, dialOpts())
+ if err != nil {
+ return 0, fmt.Errorf("dial %q: %v", url, err)
+ }
+ defer conn.Close()
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ return client.UploadPack(ctx, conn, os.Stdin, os.Stdout, os.Stderr, &request)
+}
diff --git a/internal/service/ssh/cmd/gitaly-receive-pack/main.go b/internal/service/ssh/cmd/gitaly-receive-pack/main.go
deleted file mode 100644
index 90114b5d5..000000000
--- a/internal/service/ssh/cmd/gitaly-receive-pack/main.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package main
-
-import (
- "log"
- "os"
- "strings"
- "time"
-
- "golang.org/x/net/context"
-
- pb "gitlab.com/gitlab-org/gitaly-proto/go"
- "gitlab.com/gitlab-org/gitaly/client"
-)
-
-func main() {
- if !(len(os.Args) >= 3 && strings.HasPrefix(os.Args[2], "git-receive-pack")) {
- log.Fatalf("Not a valid command")
- }
-
- addr := os.Getenv("GITALY_SOCKET")
- if len(addr) == 0 {
- log.Fatalf("GITALY_SOCKET not set")
- }
-
- conn, err := client.Dial(addr, client.DefaultDialOpts)
- if err != nil {
- log.Fatalf("Error: %v", err)
- }
- defer conn.Close()
-
- req := &pb.SSHReceivePackRequest{
- Repository: &pb.Repository{
- RelativePath: os.Getenv("GL_RELATIVEPATH"),
- StorageName: os.Getenv("GL_STORAGENAME"),
- },
- GlRepository: os.Getenv("GL_REPOSITORY"),
- GlId: os.Getenv("GL_ID"),
- GlUsername: os.Getenv("GL_USERNAME"),
- }
-
- ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
- defer cancel()
- code, err := client.ReceivePack(ctx, conn, os.Stdin, os.Stdout, os.Stderr, req)
- if err != nil {
- log.Fatalf("Error: %v", err)
- }
-
- os.Exit(int(code))
-}
diff --git a/internal/service/ssh/cmd/gitaly-upload-pack/main.go b/internal/service/ssh/cmd/gitaly-upload-pack/main.go
deleted file mode 100644
index 8df5dfe56..000000000
--- a/internal/service/ssh/cmd/gitaly-upload-pack/main.go
+++ /dev/null
@@ -1,56 +0,0 @@
-package main
-
-import (
- "log"
- "os"
- "strings"
- "time"
-
- "golang.org/x/net/context"
-
- pb "gitlab.com/gitlab-org/gitaly-proto/go"
- "gitlab.com/gitlab-org/gitaly/client"
-)
-
-func main() {
- if !(len(os.Args) >= 3 && strings.HasPrefix(os.Args[2], "git-upload-pack")) {
- log.Fatalf("Not a valid command")
- }
-
- addr := os.Getenv("GITALY_SOCKET")
- if len(addr) == 0 {
- log.Fatalf("GITALY_SOCKET not set")
- }
-
- conn, err := client.Dial(addr, client.DefaultDialOpts)
- if err != nil {
- log.Fatalf("Error: %v", err)
- }
- defer conn.Close()
-
- req := &pb.SSHUploadPackRequest{
- Repository: &pb.Repository{
- RelativePath: os.Getenv("GL_RELATIVEPATH"),
- StorageName: os.Getenv("GL_STORAGENAME"),
- },
- }
-
- // Use GL_CONFIG_OPTIONS instead of GIT_CONFIG_PARAMETERS because the latter
- // would be swallowed by the client git process
- gitConfig := os.Getenv("GL_CONFIG_OPTIONS")
-
- if len(gitConfig) > 0 {
- configs := strings.Split(gitConfig, " ")
-
- req.GitConfigOptions = append(req.GitConfigOptions, configs...)
- }
-
- ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
- defer cancel()
- code, err := client.UploadPack(ctx, conn, os.Stdin, os.Stdout, os.Stderr, req)
- if err != nil {
- log.Fatalf("Error: %v", err)
- }
-
- os.Exit(int(code))
-}
diff --git a/internal/service/ssh/receive_pack_test.go b/internal/service/ssh/receive_pack_test.go
index 5cbaad0dc..f10948f39 100644
--- a/internal/service/ssh/receive_pack_test.go
+++ b/internal/service/ssh/receive_pack_test.go
@@ -10,6 +10,9 @@ import (
"testing"
"time"
+ "github.com/golang/protobuf/jsonpb"
+ "github.com/stretchr/testify/require"
+
"gitlab.com/gitlab-org/gitaly/internal/testhelper"
pb "gitlab.com/gitlab-org/gitaly-proto/go"
@@ -121,16 +124,21 @@ func testCloneAndPush(t *testing.T, storageName, glID string) (string, string, e
makeCommit(t, localRepoPath)
+ pbTempRepo := &pb.Repository{StorageName: storageName, RelativePath: tempRepo}
+ pbMarshaler := &jsonpb.Marshaler{}
+ payload, err := pbMarshaler.MarshalToString(&pb.SSHReceivePackRequest{
+ Repository: pbTempRepo,
+ GlRepository: pbTempRepo.GetRelativePath(),
+ GlId: glID,
+ })
+ require.NoError(t, err)
+
cmd := exec.Command("git", "-C", localRepoPath, "push", "-v", "git@localhost:test/test.git", "master")
cmd.Env = []string{
- fmt.Sprintf("GITALY_SOCKET=unix://%s", serverSocketPath),
- fmt.Sprintf("GL_STORAGENAME=%s", storageName),
- fmt.Sprintf("GL_RELATIVEPATH=%s", tempRepo),
- fmt.Sprintf("GL_REPOSITORY=%s", testRepo.GetRelativePath()),
- fmt.Sprintf("GOPATH=%s", os.Getenv("GOPATH")),
+ fmt.Sprintf("GITALY_PAYLOAD=%s", payload),
+ fmt.Sprintf("GITALY_ADDRESS=unix:%s", serverSocketPath),
fmt.Sprintf("PATH=%s", ".:"+os.Getenv("PATH")),
- fmt.Sprintf("GIT_SSH_COMMAND=%s", receivePackPath),
- fmt.Sprintf("GL_ID=%s", glID),
+ fmt.Sprintf(`GIT_SSH_COMMAND=%s receive-pack`, gitalySSHPath),
}
out, err := cmd.CombinedOutput()
if err != nil {
diff --git a/internal/service/ssh/testhelper_test.go b/internal/service/ssh/testhelper_test.go
index 285c70382..87fbcf6b1 100644
--- a/internal/service/ssh/testhelper_test.go
+++ b/internal/service/ssh/testhelper_test.go
@@ -25,8 +25,7 @@ var (
serverSocketPath = testhelper.GetTemporaryGitalySocketFileName()
testRepo *pb.Repository
- uploadPackPath string
- receivePackPath string
+ gitalySSHPath string
cwd string
)
@@ -48,15 +47,10 @@ func testMain(m *testing.M) int {
testRepo = testhelper.TestRepository()
// Build the test-binary that we need
- os.Remove("gitaly-upload-pack")
- testhelper.MustRunCommand(nil, nil, "go", "build", "gitlab.com/gitlab-org/gitaly/internal/service/ssh/cmd/gitaly-upload-pack")
- defer os.Remove("gitaly-upload-pack")
- uploadPackPath = path.Join(cwd, "gitaly-upload-pack")
-
- os.Remove("gitaly-receive-pack")
- testhelper.MustRunCommand(nil, nil, "go", "build", "gitlab.com/gitlab-org/gitaly/internal/service/ssh/cmd/gitaly-receive-pack")
- defer os.Remove("gitaly-receive-pack")
- receivePackPath = path.Join(cwd, "gitaly-receive-pack")
+ os.Remove("gitaly-ssh")
+ testhelper.MustRunCommand(nil, nil, "go", "build", "gitlab.com/gitlab-org/gitaly/cmd/gitaly-ssh")
+ defer os.Remove("gitaly-ssh")
+ gitalySSHPath = path.Join(cwd, "gitaly-ssh")
return m.Run()
}
diff --git a/internal/service/ssh/upload_pack_test.go b/internal/service/ssh/upload_pack_test.go
index 8530c14d4..7f1ef2db0 100644
--- a/internal/service/ssh/upload_pack_test.go
+++ b/internal/service/ssh/upload_pack_test.go
@@ -9,6 +9,9 @@ import (
"strings"
"testing"
+ "github.com/golang/protobuf/jsonpb"
+ "github.com/stretchr/testify/require"
+
"gitlab.com/gitlab-org/gitaly/internal/testhelper"
pb "gitlab.com/gitlab-org/gitaly-proto/go"
@@ -72,19 +75,26 @@ func TestUploadPackCloneSuccess(t *testing.T) {
localRepoPath := path.Join(testRepoRoot, "gitlab-test-upload-pack-local")
- tests := []*exec.Cmd{
- exec.Command("git", "clone", "--depth", "1", "git@localhost:test/test.git", localRepoPath),
- exec.Command("git", "clone", "git@localhost:test/test.git", localRepoPath),
+ tests := []struct {
+ cmd *exec.Cmd
+ desc string
+ }{
+ {
+ cmd: exec.Command("git", "clone", "git@localhost:test/test.git", localRepoPath),
+ desc: "full clone",
+ },
+ {
+ cmd: exec.Command("git", "clone", "--depth", "1", "git@localhost:test/test.git", localRepoPath),
+ desc: "shallow clone",
+ },
}
- for _, cmd := range tests {
- lHead, rHead, _, _, err := testClone(t, testRepo.GetStorageName(), testRepo.GetRelativePath(), localRepoPath, "", cmd)
- if err != nil {
- t.Fatalf("clone failed: %v", err)
- }
- if strings.Compare(lHead, rHead) != 0 {
- t.Fatalf("local and remote head not equal. clone failed: %q != %q", lHead, rHead)
- }
+ for _, tc := range tests {
+ t.Run(tc.desc, func(t *testing.T) {
+ lHead, rHead, _, _, err := testClone(t, testRepo.GetStorageName(), testRepo.GetRelativePath(), localRepoPath, "", tc.cmd)
+ require.NoError(t, err, "clone failed")
+ require.Equal(t, lHead, rHead, "local and remote head not equal")
+ })
}
}
@@ -92,7 +102,7 @@ func TestUploadPackCloneHideTags(t *testing.T) {
server := runSSHServer(t)
defer server.Stop()
- localRepoPath := path.Join(testRepoRoot, "gitlab-test-upload-pack-local")
+ localRepoPath := path.Join(testRepoRoot, "gitlab-test-upload-pack-local-hide-tags")
cmd := exec.Command("git", "clone", "--mirror", "git@localhost:test/test.git", localRepoPath)
@@ -113,7 +123,7 @@ func TestUploadPackCloneFailure(t *testing.T) {
server := runSSHServer(t)
defer server.Stop()
- localRepoPath := path.Join(testRepoRoot, "gitlab-test-upload-pack-local")
+ localRepoPath := path.Join(testRepoRoot, "gitlab-test-upload-pack-local-failure")
cmd := exec.Command("git", "clone", "git@localhost:test/test.git", localRepoPath)
@@ -125,15 +135,24 @@ func TestUploadPackCloneFailure(t *testing.T) {
func testClone(t *testing.T, storageName, relativePath, localRepoPath string, gitConfig string, cmd *exec.Cmd) (string, string, string, string, error) {
defer os.RemoveAll(localRepoPath)
+
+ pbTempRepo := &pb.Repository{StorageName: storageName, RelativePath: relativePath}
+ req := &pb.SSHUploadPackRequest{
+ Repository: pbTempRepo,
+ }
+ if gitConfig != "" {
+ req.GitConfigOptions = strings.Split(gitConfig, " ")
+ }
+ pbMarshaler := &jsonpb.Marshaler{}
+ payload, err := pbMarshaler.MarshalToString(req)
+
+ require.NoError(t, err)
+
cmd.Env = []string{
- fmt.Sprintf("GITALY_SOCKET=unix://%s", serverSocketPath),
- fmt.Sprintf("GL_STORAGENAME=%s", storageName),
- fmt.Sprintf("GL_RELATIVEPATH=%s", relativePath),
- fmt.Sprintf("GL_REPOSITORY=%s", testRepo.GetRelativePath()),
- fmt.Sprintf("GOPATH=%s", os.Getenv("GOPATH")),
+ fmt.Sprintf("GITALY_ADDRESS=unix:%s", serverSocketPath),
+ fmt.Sprintf("GITALY_PAYLOAD=%s", payload),
fmt.Sprintf("PATH=%s", ".:"+os.Getenv("PATH")),
- fmt.Sprintf("GL_CONFIG_OPTIONS=%s", gitConfig),
- "GIT_SSH_COMMAND=gitaly-upload-pack",
+ fmt.Sprintf(`GIT_SSH_COMMAND=%s upload-pack`, gitalySSHPath),
}
out, err := cmd.CombinedOutput()