As we reevaluate how to best support and maintain Staging Ref in the future, we encourage development teams using this environment to highlight their use cases in the following issue: https://gitlab.com/gitlab-com/gl-infra/software-delivery/framework/software-delivery-framework-issue-tracker/-/issues/36.

Skip to content
Snippets Groups Projects
Commit a02fb7a8 authored by Vasilii Iakliushin's avatar Vasilii Iakliushin
Browse files

Geo: Replace Git over HTTP calls with Workhorse HTTP endpoint for SSH

Contributes to https://gitlab.com/gitlab-org/gitlab-shell/-/issues/762

**Problem**

There is a new endpoint for SSH Pull implemented in Workhorse. We
want to use it for Geo Git Pull calls.

**Solution**

* Define a boolean parameter `GeoProxyFetchSSHDirectToPrimary` hidden
behind the feature flag.
* Make a call to `ssh-upload-pack` endpoint for git pull commands.

Changelog: added
parent 1e98ed2a
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -37,6 +37,11 @@ func (c *PullCommand) Execute(ctx context.Context) error {
data := c.Response.Payload.Data
client := &git.Client{URL: data.PrimaryRepo, Headers: data.RequestHeaders}
// For Git over SSH routing
if data.GeoProxyFetchSSHDirectToPrimary {
return c.requestSSHUploadPack(ctx, client)
}
if err := c.requestInfoRefs(ctx, client); err != nil {
return err
}
Loading
Loading
@@ -64,6 +69,18 @@ func (c *PullCommand) requestInfoRefs(ctx context.Context, client *git.Client) e
return err
}
func (c *PullCommand) requestSSHUploadPack(ctx context.Context, client *git.Client) error {
response, err := client.SSHUploadPack(ctx, io.NopCloser(c.ReadWriter.In))
if err != nil {
return err
}
defer response.Body.Close()
_, err = io.Copy(c.ReadWriter.Out, response.Body)
return err
}
func (c *PullCommand) requestUploadPack(ctx context.Context, client *git.Client, geoProxyFetchDirectToPrimaryWithOptions bool) error {
pipeReader, pipeWriter := io.Pipe()
go c.readFromStdin(pipeWriter, geoProxyFetchDirectToPrimaryWithOptions)
Loading
Loading
Loading
Loading
@@ -58,6 +58,27 @@ func TestPullExecuteWithDepth(t *testing.T) {
require.Equal(t, infoRefsWithoutPrefix, output.String())
}
func TestPullExecuteWithSSHUploadPack(t *testing.T) {
url := setupSSHPull(t, http.StatusOK)
output := &bytes.Buffer{}
input := strings.NewReader(cloneResponse + "0009done\n")
cmd := &PullCommand{
Config: &config.Config{GitlabUrl: url},
ReadWriter: &readwriter.ReadWriter{Out: output, In: input},
Response: &accessverifier.Response{
Payload: accessverifier.CustomPayload{
Data: accessverifier.CustomPayloadData{
PrimaryRepo: url, GeoProxyFetchDirectToPrimaryWithOptions: true, GeoProxyFetchSSHDirectToPrimary: true,
},
},
},
}
require.NoError(t, cmd.Execute(context.Background()))
require.Equal(t, "upload-pack-response", output.String())
}
func TestPullExecuteWithFailedInfoRefs(t *testing.T) {
testCases := []struct {
desc string
Loading
Loading
@@ -157,3 +178,23 @@ func setupPull(t *testing.T, uploadPackStatusCode int) string {
return testserver.StartHttpServer(t, requests)
}
func setupSSHPull(t *testing.T, uploadPackStatusCode int) string {
requests := []testserver.TestRequestHandler{
{
Path: "/ssh-upload-pack",
Handler: func(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body)
require.NoError(t, err)
defer r.Body.Close()
require.True(t, strings.HasSuffix(string(body), "0009done\n"))
w.Write([]byte("upload-pack-response"))
w.WriteHeader(uploadPackStatusCode)
},
},
}
return testserver.StartHttpServer(t, requests)
}
Loading
Loading
@@ -56,6 +56,7 @@ type CustomPayloadData struct {
GeoProxyDirectToPrimary bool `json:"geo_proxy_direct_to_primary"`
GeoProxyFetchDirectToPrimary bool `json:"geo_proxy_fetch_direct_to_primary"`
GeoProxyFetchDirectToPrimaryWithOptions bool `json:"geo_proxy_fetch_direct_to_primary_with_options"`
GeoProxyFetchSSHDirectToPrimary bool `json:"geo_proxy_fetch_ssh_direct_to_primary"`
}
// CustomPayload represents a custom payload
Loading
Loading
Loading
Loading
@@ -56,6 +56,16 @@ func (c *Client) UploadPack(ctx context.Context, body io.Reader) (*http.Response
return c.do(request)
}
// SSHUploadPack sends a SSH Git fetch request to the server.
func (c *Client) SSHUploadPack(ctx context.Context, body io.Reader) (*http.Response, error) {
request, err := http.NewRequestWithContext(ctx, http.MethodPost, c.URL+"/ssh-upload-pack", body)
if err != nil {
return nil, err
}
return c.do(request)
}
func (c *Client) do(request *http.Request) (*http.Response, error) {
for k, v := range c.Headers {
request.Header.Add(k, v)
Loading
Loading
Loading
Loading
@@ -64,6 +64,20 @@ func TestUploadPack(t *testing.T) {
require.Equal(t, "git-upload-pack: content", string(body))
}
func TestSSHUploadPack(t *testing.T) {
client := setup(t)
refsBody := "0032want 0a53e9ddeaddad63ad106860237bbf53411d11a7\n"
response, err := client.SSHUploadPack(context.Background(), bytes.NewReader([]byte(refsBody)))
require.NoError(t, err)
defer response.Body.Close()
body, err := io.ReadAll(response.Body)
require.NoError(t, err)
require.Equal(t, "ssh-upload-pack: content", string(body))
}
func TestFailedHTTPRequest(t *testing.T) {
requests := []testserver.TestRequestHandler{
{
Loading
Loading
@@ -166,6 +180,19 @@ func setup(t *testing.T) *Client {
w.Write([]byte("git-upload-pack: content"))
},
},
{
Path: "/ssh-upload-pack",
Handler: func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, customHeaders["Authorization"], r.Header.Get("Authorization"))
require.Equal(t, customHeaders["Header-One"], r.Header.Get("Header-One"))
_, err := io.ReadAll(r.Body)
require.NoError(t, err)
defer r.Body.Close()
w.Write([]byte("ssh-upload-pack: content"))
},
},
}
client := &Client{
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment