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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'workhorse')
-rw-r--r--workhorse/gitaly_integration_test.go447
-rw-r--r--workhorse/gitaly_test.go2
-rw-r--r--workhorse/go.mod4
-rw-r--r--workhorse/go.sum10
-rw-r--r--workhorse/internal/gitaly/gitaly.go10
5 files changed, 269 insertions, 204 deletions
diff --git a/workhorse/gitaly_integration_test.go b/workhorse/gitaly_integration_test.go
index ed44aaddbc3..a21c31aea49 100644
--- a/workhorse/gitaly_integration_test.go
+++ b/workhorse/gitaly_integration_test.go
@@ -8,6 +8,7 @@ import (
"bytes"
"context"
"fmt"
+ "net/url"
"os"
"os/exec"
"path"
@@ -26,32 +27,52 @@ import (
)
var (
- gitalyAddress string
- jsonGitalyServer string
+ gitalyAddresses []string
)
+// Convert from tcp://127.0.0.1:8075 to dns scheme variants:
+// * dns:127.0.0.1:8075
+// * dns:///127.0.0.1:8075
+func convertToDNSSchemes(address string) []string {
+ uri, err := url.Parse(address)
+ if err != nil {
+ panic(fmt.Sprintf("invalid GITALY_ADDRESS url %s: %s", address, err))
+ }
+ return []string{
+ fmt.Sprintf("dns:///%s", uri.Host),
+ fmt.Sprintf("dns:%s", uri.Host),
+ }
+}
+
+func jsonGitalyServer(address string) string {
+ return fmt.Sprintf(`"GitalyServer":{"Address":"%s", "Token": ""}`, address)
+}
+
func init() {
- gitalyAddress = os.Getenv("GITALY_ADDRESS")
- jsonGitalyServer = fmt.Sprintf(`"GitalyServer":{"Address":"%s", "Token": ""}`, gitalyAddress)
+ rawAddress := os.Getenv("GITALY_ADDRESS")
+ if rawAddress != "" {
+ gitalyAddresses = append(gitalyAddresses, rawAddress)
+ gitalyAddresses = append(gitalyAddresses, convertToDNSSchemes(rawAddress)...)
+ }
}
func skipUnlessRealGitaly(t *testing.T) {
- t.Log(gitalyAddress)
- if gitalyAddress != "" {
+ t.Log(gitalyAddresses)
+ if len(gitalyAddresses) != 0 {
return
}
t.Skip(`Please set GITALY_ADDRESS="..." to run Gitaly integration tests`)
}
-func realGitalyAuthResponse(apiResponse *api.Response) *api.Response {
+func realGitalyAuthResponse(gitalyAddress string, apiResponse *api.Response) *api.Response {
apiResponse.GitalyServer.Address = gitalyAddress
return apiResponse
}
-func realGitalyOkBody(t *testing.T) *api.Response {
- return realGitalyAuthResponse(gitOkBody(t))
+func realGitalyOkBody(t *testing.T, gitalyAddress string) *api.Response {
+ return realGitalyAuthResponse(gitalyAddress, gitOkBody(t))
}
func ensureGitalyRepository(t *testing.T, apiResponse *api.Response) error {
@@ -105,241 +126,273 @@ func ensureGitalyRepository(t *testing.T, apiResponse *api.Response) error {
func TestAllowedClone(t *testing.T) {
skipUnlessRealGitaly(t)
- // Create the repository in the Gitaly server
- apiResponse := realGitalyOkBody(t)
- require.NoError(t, ensureGitalyRepository(t, apiResponse))
-
- // Prepare test server and backend
- ts := testAuthServer(t, nil, nil, 200, apiResponse)
- defer ts.Close()
- ws := startWorkhorseServer(ts.URL)
- defer ws.Close()
-
- // Do the git clone
- require.NoError(t, os.RemoveAll(scratchDir))
- cloneCmd := exec.Command("git", "clone", fmt.Sprintf("%s/%s", ws.URL, testRepo), checkoutDir)
- runOrFail(t, cloneCmd)
-
- // We may have cloned an 'empty' repository, 'git log' will fail in it
- logCmd := exec.Command("git", "log", "-1", "--oneline")
- logCmd.Dir = checkoutDir
- runOrFail(t, logCmd)
+ for _, gitalyAddress := range gitalyAddresses {
+ t.Run(gitalyAddress, func(t *testing.T) {
+ // Create the repository in the Gitaly server
+ apiResponse := realGitalyOkBody(t, gitalyAddress)
+ require.NoError(t, ensureGitalyRepository(t, apiResponse))
+
+ // Prepare test server and backend
+ ts := testAuthServer(t, nil, nil, 200, apiResponse)
+ defer ts.Close()
+ ws := startWorkhorseServer(ts.URL)
+ defer ws.Close()
+
+ // Do the git clone
+ require.NoError(t, os.RemoveAll(scratchDir))
+ cloneCmd := exec.Command("git", "clone", fmt.Sprintf("%s/%s", ws.URL, testRepo), checkoutDir)
+ runOrFail(t, cloneCmd)
+
+ // We may have cloned an 'empty' repository, 'git log' will fail in it
+ logCmd := exec.Command("git", "log", "-1", "--oneline")
+ logCmd.Dir = checkoutDir
+ runOrFail(t, logCmd)
+ })
+ }
}
func TestAllowedShallowClone(t *testing.T) {
skipUnlessRealGitaly(t)
- // Create the repository in the Gitaly server
- apiResponse := realGitalyOkBody(t)
- require.NoError(t, ensureGitalyRepository(t, apiResponse))
-
- // Prepare test server and backend
- ts := testAuthServer(t, nil, nil, 200, apiResponse)
- defer ts.Close()
- ws := startWorkhorseServer(ts.URL)
- defer ws.Close()
-
- // Shallow git clone (depth 1)
- require.NoError(t, os.RemoveAll(scratchDir))
- cloneCmd := exec.Command("git", "clone", "--depth", "1", fmt.Sprintf("%s/%s", ws.URL, testRepo), checkoutDir)
- runOrFail(t, cloneCmd)
-
- // We may have cloned an 'empty' repository, 'git log' will fail in it
- logCmd := exec.Command("git", "log", "-1", "--oneline")
- logCmd.Dir = checkoutDir
- runOrFail(t, logCmd)
+ for _, gitalyAddress := range gitalyAddresses {
+ t.Run(gitalyAddress, func(t *testing.T) {
+ // Create the repository in the Gitaly server
+ apiResponse := realGitalyOkBody(t, gitalyAddress)
+ require.NoError(t, ensureGitalyRepository(t, apiResponse))
+
+ // Prepare test server and backend
+ ts := testAuthServer(t, nil, nil, 200, apiResponse)
+ defer ts.Close()
+ ws := startWorkhorseServer(ts.URL)
+ defer ws.Close()
+
+ // Shallow git clone (depth 1)
+ require.NoError(t, os.RemoveAll(scratchDir))
+ cloneCmd := exec.Command("git", "clone", "--depth", "1", fmt.Sprintf("%s/%s", ws.URL, testRepo), checkoutDir)
+ runOrFail(t, cloneCmd)
+
+ // We may have cloned an 'empty' repository, 'git log' will fail in it
+ logCmd := exec.Command("git", "log", "-1", "--oneline")
+ logCmd.Dir = checkoutDir
+ runOrFail(t, logCmd)
+ })
+ }
}
func TestAllowedPush(t *testing.T) {
skipUnlessRealGitaly(t)
- // Create the repository in the Gitaly server
- apiResponse := realGitalyOkBody(t)
- require.NoError(t, ensureGitalyRepository(t, apiResponse))
-
- // Prepare the test server and backend
- ts := testAuthServer(t, nil, nil, 200, apiResponse)
- defer ts.Close()
- ws := startWorkhorseServer(ts.URL)
- defer ws.Close()
-
- // Perform the git push
- pushCmd := exec.Command("git", "push", fmt.Sprintf("%s/%s", ws.URL, testRepo), fmt.Sprintf("master:%s", newBranch()))
- pushCmd.Dir = checkoutDir
- runOrFail(t, pushCmd)
+ for _, gitalyAddress := range gitalyAddresses {
+ t.Run(gitalyAddress, func(t *testing.T) {
+ // Create the repository in the Gitaly server
+ apiResponse := realGitalyOkBody(t, gitalyAddress)
+ require.NoError(t, ensureGitalyRepository(t, apiResponse))
+
+ // Prepare the test server and backend
+ ts := testAuthServer(t, nil, nil, 200, apiResponse)
+ defer ts.Close()
+ ws := startWorkhorseServer(ts.URL)
+ defer ws.Close()
+
+ // Perform the git push
+ pushCmd := exec.Command("git", "push", fmt.Sprintf("%s/%s", ws.URL, testRepo), fmt.Sprintf("master:%s", newBranch()))
+ pushCmd.Dir = checkoutDir
+ runOrFail(t, pushCmd)
+ })
+ }
}
func TestAllowedGetGitBlob(t *testing.T) {
skipUnlessRealGitaly(t)
- // Create the repository in the Gitaly server
- apiResponse := realGitalyOkBody(t)
- require.NoError(t, ensureGitalyRepository(t, apiResponse))
-
- // the LICENSE file in the test repository
- oid := "50b27c6518be44c42c4d87966ae2481ce895624c"
- expectedBody := "The MIT License (MIT)"
- bodyLen := 1075
-
- jsonParams := fmt.Sprintf(
- `{
- %s,
- "GetBlobRequest":{
- "repository":{"storage_name":"%s", "relative_path":"%s"},
- "oid":"%s",
- "limit":-1
- }
- }`,
- jsonGitalyServer, apiResponse.Repository.StorageName, apiResponse.Repository.RelativePath, oid,
- )
-
- resp, body, err := doSendDataRequest("/something", "git-blob", jsonParams)
- require.NoError(t, err)
- shortBody := string(body[:len(expectedBody)])
-
- require.Equal(t, 200, resp.StatusCode, "GET %q: status code", resp.Request.URL)
- require.Equal(t, expectedBody, shortBody, "GET %q: response body", resp.Request.URL)
- testhelper.RequireResponseHeader(t, resp, "Content-Length", strconv.Itoa(bodyLen))
- requireNginxResponseBuffering(t, "no", resp, "GET %q: nginx response buffering", resp.Request.URL)
+ for _, gitalyAddress := range gitalyAddresses {
+ t.Run(gitalyAddress, func(t *testing.T) {
+ // Create the repository in the Gitaly server
+ apiResponse := realGitalyOkBody(t, gitalyAddress)
+ require.NoError(t, ensureGitalyRepository(t, apiResponse))
+
+ // the LICENSE file in the test repository
+ oid := "50b27c6518be44c42c4d87966ae2481ce895624c"
+ expectedBody := "The MIT License (MIT)"
+ bodyLen := 1075
+
+ jsonParams := fmt.Sprintf(
+ `{
+ %s,
+ "GetBlobRequest":{
+ "repository":{"storage_name":"%s", "relative_path":"%s"},
+ "oid":"%s",
+ "limit":-1
+ }
+ }`,
+ jsonGitalyServer(gitalyAddress), apiResponse.Repository.StorageName, apiResponse.Repository.RelativePath, oid,
+ )
+
+ resp, body, err := doSendDataRequest("/something", "git-blob", jsonParams)
+ require.NoError(t, err)
+ shortBody := string(body[:len(expectedBody)])
+
+ require.Equal(t, 200, resp.StatusCode, "GET %q: status code", resp.Request.URL)
+ require.Equal(t, expectedBody, shortBody, "GET %q: response body", resp.Request.URL)
+ testhelper.RequireResponseHeader(t, resp, "Content-Length", strconv.Itoa(bodyLen))
+ requireNginxResponseBuffering(t, "no", resp, "GET %q: nginx response buffering", resp.Request.URL)
+ })
+ }
}
func TestAllowedGetGitArchive(t *testing.T) {
skipUnlessRealGitaly(t)
- // Create the repository in the Gitaly server
- apiResponse := realGitalyOkBody(t)
- require.NoError(t, ensureGitalyRepository(t, apiResponse))
-
- archivePath := path.Join(scratchDir, "my/path")
- archivePrefix := "repo-1"
-
- msg := serializedProtoMessage("GetArchiveRequest", &gitalypb.GetArchiveRequest{
- Repository: &apiResponse.Repository,
- CommitId: "HEAD",
- Prefix: archivePrefix,
- Format: gitalypb.GetArchiveRequest_TAR,
- Path: []byte("files"),
- })
- jsonParams := buildGitalyRPCParams(gitalyAddress, rpcArg{"ArchivePath", archivePath}, msg)
-
- resp, body, err := doSendDataRequest("/archive.tar", "git-archive", jsonParams)
- require.NoError(t, err)
- require.Equal(t, 200, resp.StatusCode, "GET %q: status code", resp.Request.URL)
- requireNginxResponseBuffering(t, "no", resp, "GET %q: nginx response buffering", resp.Request.URL)
-
- // Ensure the tar file is readable
- foundEntry := false
- tr := tar.NewReader(bytes.NewReader(body))
- for {
- hdr, err := tr.Next()
- if err != nil {
- break
- }
+ for _, gitalyAddress := range gitalyAddresses {
+ t.Run(gitalyAddress, func(t *testing.T) {
+ // Create the repository in the Gitaly server
+ apiResponse := realGitalyOkBody(t, gitalyAddress)
+ require.NoError(t, ensureGitalyRepository(t, apiResponse))
+
+ archivePath := path.Join(scratchDir, "my/path")
+ archivePrefix := "repo-1"
+
+ msg := serializedProtoMessage("GetArchiveRequest", &gitalypb.GetArchiveRequest{
+ Repository: &apiResponse.Repository,
+ CommitId: "HEAD",
+ Prefix: archivePrefix,
+ Format: gitalypb.GetArchiveRequest_TAR,
+ Path: []byte("files"),
+ })
+ jsonParams := buildGitalyRPCParams(gitalyAddress, rpcArg{"ArchivePath", archivePath}, msg)
+
+ resp, body, err := doSendDataRequest("/archive.tar", "git-archive", jsonParams)
+ require.NoError(t, err)
+ require.Equal(t, 200, resp.StatusCode, "GET %q: status code", resp.Request.URL)
+ requireNginxResponseBuffering(t, "no", resp, "GET %q: nginx response buffering", resp.Request.URL)
+
+ // Ensure the tar file is readable
+ foundEntry := false
+ tr := tar.NewReader(bytes.NewReader(body))
+ for {
+ hdr, err := tr.Next()
+ if err != nil {
+ break
+ }
+
+ if hdr.Name == archivePrefix+"/" {
+ foundEntry = true
+ break
+ }
+ }
- if hdr.Name == archivePrefix+"/" {
- foundEntry = true
- break
- }
+ require.True(t, foundEntry, "Couldn't find %v directory entry", archivePrefix)
+ })
}
-
- require.True(t, foundEntry, "Couldn't find %v directory entry", archivePrefix)
}
func TestAllowedGetGitArchiveOldPayload(t *testing.T) {
skipUnlessRealGitaly(t)
- // Create the repository in the Gitaly server
- apiResponse := realGitalyOkBody(t)
- repo := &apiResponse.Repository
- require.NoError(t, ensureGitalyRepository(t, apiResponse))
+ for _, gitalyAddress := range gitalyAddresses {
+ t.Run(gitalyAddress, func(t *testing.T) {
+ // Create the repository in the Gitaly server
+ apiResponse := realGitalyOkBody(t, gitalyAddress)
+ repo := &apiResponse.Repository
+ require.NoError(t, ensureGitalyRepository(t, apiResponse))
- archivePath := path.Join(scratchDir, "my/path")
- archivePrefix := "repo-1"
+ archivePath := path.Join(scratchDir, "my/path")
+ archivePrefix := "repo-1"
- jsonParams := fmt.Sprintf(
- `{
+ jsonParams := fmt.Sprintf(
+ `{
%s,
"GitalyRepository":{"storage_name":"%s","relative_path":"%s"},
"ArchivePath":"%s",
"ArchivePrefix":"%s",
"CommitId":"%s"
}`,
- jsonGitalyServer, repo.StorageName, repo.RelativePath, archivePath, archivePrefix, "HEAD",
- )
-
- resp, body, err := doSendDataRequest("/archive.tar", "git-archive", jsonParams)
- require.NoError(t, err)
- require.Equal(t, 200, resp.StatusCode, "GET %q: status code", resp.Request.URL)
- requireNginxResponseBuffering(t, "no", resp, "GET %q: nginx response buffering", resp.Request.URL)
-
- // Ensure the tar file is readable
- foundEntry := false
- tr := tar.NewReader(bytes.NewReader(body))
- for {
- hdr, err := tr.Next()
- if err != nil {
- break
- }
+ jsonGitalyServer(gitalyAddress), repo.StorageName, repo.RelativePath, archivePath, archivePrefix, "HEAD",
+ )
+
+ resp, body, err := doSendDataRequest("/archive.tar", "git-archive", jsonParams)
+ require.NoError(t, err)
+ require.Equal(t, 200, resp.StatusCode, "GET %q: status code", resp.Request.URL)
+ requireNginxResponseBuffering(t, "no", resp, "GET %q: nginx response buffering", resp.Request.URL)
+
+ // Ensure the tar file is readable
+ foundEntry := false
+ tr := tar.NewReader(bytes.NewReader(body))
+ for {
+ hdr, err := tr.Next()
+ if err != nil {
+ break
+ }
+
+ if hdr.Name == archivePrefix+"/" {
+ foundEntry = true
+ break
+ }
+ }
- if hdr.Name == archivePrefix+"/" {
- foundEntry = true
- break
- }
+ require.True(t, foundEntry, "Couldn't find %v directory entry", archivePrefix)
+ })
}
-
- require.True(t, foundEntry, "Couldn't find %v directory entry", archivePrefix)
}
func TestAllowedGetGitDiff(t *testing.T) {
skipUnlessRealGitaly(t)
- // Create the repository in the Gitaly server
- apiResponse := realGitalyOkBody(t)
- require.NoError(t, ensureGitalyRepository(t, apiResponse))
-
- msg := serializedMessage("RawDiffRequest", &gitalypb.RawDiffRequest{
- Repository: &apiResponse.Repository,
- LeftCommitId: "b0e52af38d7ea43cf41d8a6f2471351ac036d6c9",
- RightCommitId: "732401c65e924df81435deb12891ef570167d2e2",
- })
- jsonParams := buildGitalyRPCParams(gitalyAddress, msg)
-
- resp, body, err := doSendDataRequest("/something", "git-diff", jsonParams)
- require.NoError(t, err)
-
- require.Equal(t, 200, resp.StatusCode, "GET %q: status code", resp.Request.URL)
- requireNginxResponseBuffering(t, "no", resp, "GET %q: nginx response buffering", resp.Request.URL)
-
- expectedBody := "diff --git a/LICENSE b/LICENSE\n"
- require.Equal(t, expectedBody, string(body[:len(expectedBody)]),
- "GET %q: response body", resp.Request.URL)
+ for _, gitalyAddress := range gitalyAddresses {
+ t.Run(gitalyAddress, func(t *testing.T) {
+ // Create the repository in the Gitaly server
+ apiResponse := realGitalyOkBody(t, gitalyAddress)
+ require.NoError(t, ensureGitalyRepository(t, apiResponse))
+
+ msg := serializedMessage("RawDiffRequest", &gitalypb.RawDiffRequest{
+ Repository: &apiResponse.Repository,
+ LeftCommitId: "b0e52af38d7ea43cf41d8a6f2471351ac036d6c9",
+ RightCommitId: "732401c65e924df81435deb12891ef570167d2e2",
+ })
+ jsonParams := buildGitalyRPCParams(gitalyAddress, msg)
+
+ resp, body, err := doSendDataRequest("/something", "git-diff", jsonParams)
+ require.NoError(t, err)
+
+ require.Equal(t, 200, resp.StatusCode, "GET %q: status code", resp.Request.URL)
+ requireNginxResponseBuffering(t, "no", resp, "GET %q: nginx response buffering", resp.Request.URL)
+
+ expectedBody := "diff --git a/LICENSE b/LICENSE\n"
+ require.Equal(t, expectedBody, string(body[:len(expectedBody)]),
+ "GET %q: response body", resp.Request.URL)
+ })
+ }
}
func TestAllowedGetGitFormatPatch(t *testing.T) {
skipUnlessRealGitaly(t)
- // Create the repository in the Gitaly server
- apiResponse := realGitalyOkBody(t)
- require.NoError(t, ensureGitalyRepository(t, apiResponse))
-
- msg := serializedMessage("RawPatchRequest", &gitalypb.RawPatchRequest{
- Repository: &apiResponse.Repository,
- LeftCommitId: "b0e52af38d7ea43cf41d8a6f2471351ac036d6c9",
- RightCommitId: "0e1b353b348f8477bdbec1ef47087171c5032cd9",
- })
- jsonParams := buildGitalyRPCParams(gitalyAddress, msg)
-
- resp, body, err := doSendDataRequest("/something", "git-format-patch", jsonParams)
- require.NoError(t, err)
-
- require.Equal(t, 200, resp.StatusCode, "GET %q: status code", resp.Request.URL)
- requireNginxResponseBuffering(t, "no", resp, "GET %q: nginx response buffering", resp.Request.URL)
-
- requirePatchSeries(t, body,
- "732401c65e924df81435deb12891ef570167d2e2",
- "33bcff41c232a11727ac6d660bd4b0c2ba86d63d",
- "0e1b353b348f8477bdbec1ef47087171c5032cd9",
- )
+ for _, gitalyAddress := range gitalyAddresses {
+ t.Run(gitalyAddress, func(t *testing.T) {
+ // Create the repository in the Gitaly server
+ apiResponse := realGitalyOkBody(t, gitalyAddress)
+ require.NoError(t, ensureGitalyRepository(t, apiResponse))
+
+ msg := serializedMessage("RawPatchRequest", &gitalypb.RawPatchRequest{
+ Repository: &apiResponse.Repository,
+ LeftCommitId: "b0e52af38d7ea43cf41d8a6f2471351ac036d6c9",
+ RightCommitId: "0e1b353b348f8477bdbec1ef47087171c5032cd9",
+ })
+ jsonParams := buildGitalyRPCParams(gitalyAddress, msg)
+
+ resp, body, err := doSendDataRequest("/something", "git-format-patch", jsonParams)
+ require.NoError(t, err)
+
+ require.Equal(t, 200, resp.StatusCode, "GET %q: status code", resp.Request.URL)
+ requireNginxResponseBuffering(t, "no", resp, "GET %q: nginx response buffering", resp.Request.URL)
+
+ requirePatchSeries(t, body,
+ "732401c65e924df81435deb12891ef570167d2e2",
+ "33bcff41c232a11727ac6d660bd4b0c2ba86d63d",
+ "0e1b353b348f8477bdbec1ef47087171c5032cd9",
+ )
+ })
+ }
}
var extractPatchSeriesMatcher = regexp.MustCompile(`^From (\w+)`)
diff --git a/workhorse/gitaly_test.go b/workhorse/gitaly_test.go
index 2d7f727003f..de896475a99 100644
--- a/workhorse/gitaly_test.go
+++ b/workhorse/gitaly_test.go
@@ -439,7 +439,7 @@ func TestPostUploadPackProxiedToGitalySuccessfully(t *testing.T) {
bodySplit := strings.SplitN(body, "\000", 2)
require.Len(t, bodySplit, 2)
- gitalyRequest := &gitalypb.PostUploadPackRequest{}
+ gitalyRequest := &gitalypb.PostUploadPackWithSidechannelRequest{}
require.NoError(t, jsonpb.UnmarshalString(bodySplit[0], gitalyRequest))
require.Equal(t, apiResponse.Repository.StorageName, gitalyRequest.Repository.StorageName)
diff --git a/workhorse/go.mod b/workhorse/go.mod
index 6e397a75019..76374a28f5c 100644
--- a/workhorse/go.mod
+++ b/workhorse/go.mod
@@ -26,7 +26,7 @@ require (
github.com/sirupsen/logrus v1.9.0
github.com/smartystreets/goconvey v1.7.2
github.com/stretchr/testify v1.8.1
- gitlab.com/gitlab-org/gitaly/v15 v15.8.1
+ gitlab.com/gitlab-org/gitaly/v15 v15.9.0-rc4
gitlab.com/gitlab-org/golang-archive-zip v0.1.1
gitlab.com/gitlab-org/labkit v1.17.0
gocloud.dev v0.28.0
@@ -111,7 +111,7 @@ require (
golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e // indirect
golang.org/x/mod v0.6.0 // indirect
golang.org/x/sync v0.1.0 // indirect
- golang.org/x/sys v0.4.0 // indirect
+ golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.6.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
diff --git a/workhorse/go.sum b/workhorse/go.sum
index 5e1d22d2fa1..64749d157d3 100644
--- a/workhorse/go.sum
+++ b/workhorse/go.sum
@@ -1435,6 +1435,7 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
github.com/miekg/dns v1.1.48/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
+github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
@@ -1845,8 +1846,8 @@ github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
-gitlab.com/gitlab-org/gitaly/v15 v15.8.1 h1:i/38/jLhvXwiztdrUCh9YxCrYufWS0K6pKQnbF3vy8U=
-gitlab.com/gitlab-org/gitaly/v15 v15.8.1/go.mod h1:typ7BQ9JuglkeTvW3Vn1SwFcZ1FMn8P3GrWcPuZQ0EU=
+gitlab.com/gitlab-org/gitaly/v15 v15.9.0-rc4 h1:n6VW2djSoiGaajMUkVy+crRnyiUePcW1v1T3wPd2hhI=
+gitlab.com/gitlab-org/gitaly/v15 v15.9.0-rc4/go.mod h1:y0OCqEn0WWmyycVpde494A5qhCszhlx2b+od6vSzsOU=
gitlab.com/gitlab-org/golang-archive-zip v0.1.1 h1:35k9giivbxwF03+8A05Cm8YoxoakU8FBCj5gysjCTCE=
gitlab.com/gitlab-org/golang-archive-zip v0.1.1/go.mod h1:ZDtqpWPGPB9qBuZnZDrKQjIdJtkN7ZAoVwhT6H2o2kE=
gitlab.com/gitlab-org/labkit v1.17.0 h1:mEkoLzXorLNdt8NkfgYS5xMDhdqCsIJaeEVtSf7d8cU=
@@ -2003,6 +2004,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/exp v0.0.0-20221031165847-c99f073a8326 h1:QfTh0HpN6hlw6D3vu8DAwC8pBIwikq0AI1evdm+FksE=
golang.org/x/exp v0.0.0-20221031165847-c99f073a8326/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e h1:qyrTQ++p1afMkO4DPEeLGq/3oTsdlvdH4vqZUBWzUKM=
golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
@@ -2328,8 +2330,8 @@ golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
-golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
diff --git a/workhorse/internal/gitaly/gitaly.go b/workhorse/internal/gitaly/gitaly.go
index af7425be1cf..eace87dda36 100644
--- a/workhorse/internal/gitaly/gitaly.go
+++ b/workhorse/internal/gitaly/gitaly.go
@@ -192,6 +192,16 @@ func newConnection(server api.GitalyServer) (*grpc.ClientConn, error) {
),
),
),
+
+ // In https://gitlab.com/groups/gitlab-org/-/epics/8971, we added DNS discovery support to Praefect. This was
+ // done by making two changes:
+ // - Configure client-side round-robin load-balancing in client dial options. We added that as a default option
+ // inside gitaly client in gitaly client since v15.9.0
+ // - Configure DNS resolving. Due to some technical limitations, we don't use gRPC's built-in DNS resolver.
+ // Instead, we implement our own DNS resolver. This resolver is exposed via the following configuration.
+ // Afterward, workhorse can detect and handle DNS discovery automatically. The user needs to setup and set
+ // Gitaly address to something like "dns:gitaly.service.dc1.consul"
+ gitalyclient.WithGitalyDNSResolver(gitalyclient.DefaultDNSResolverBuilderConfig()),
)
conn, connErr := gitalyclient.DialSidechannel(context.Background(), server.Address, sidechannelRegistry, connOpts) // lint:allow context.Background