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
Unverified Commit 3bc0463c authored by Igor Drozdov's avatar Igor Drozdov
Browse files

Acceptance test for Geo push

It imitates a push to the secondary and verifies that the push
is redirected to the primary
parent da4a4d77
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -24,8 +24,12 @@ import (
"github.com/stretchr/testify/require"
gitalyClient "gitlab.com/gitlab-org/gitaly/v15/client"
pb "gitlab.com/gitlab-org/gitaly/v15/proto/go/gitalypb"
"gitlab.com/gitlab-org/gitlab-shell/v14/internal/testhelper"
"gitlab.com/gitlab-org/gitaly/v15/streamio"
"golang.org/x/crypto/ssh"
"google.golang.org/grpc"
"gitlab.com/gitlab-org/gitlab-shell/v14/client/testserver"
"gitlab.com/gitlab-org/gitlab-shell/v14/internal/testhelper"
)
var (
Loading
Loading
@@ -67,7 +71,7 @@ func rootDir() string {
return filepath.Join(filepath.Dir(currentFile), "..", "..")
}
func ensureGitalyRepository(t *testing.T) {
func ensureGitalyRepository(t *testing.T) (*grpc.ClientConn, *pb.Repository) {
if os.Getenv("GITALY_CONNECTION_INFO") == "" {
t.Skip("GITALY_CONNECTION_INFO is not set")
}
Loading
Loading
@@ -83,23 +87,99 @@ func ensureGitalyRepository(t *testing.T) {
_, err = namespace.RemoveNamespace(context.Background(), rmNsReq)
require.NoError(t, err)
gl_repository := &pb.Repository{StorageName: gitalyConnInfo.Storage, RelativePath: testRepo}
createReq := &pb.CreateRepositoryFromURLRequest{Repository: gl_repository, Url: testRepoImportUrl}
glRepository := &pb.Repository{StorageName: gitalyConnInfo.Storage, RelativePath: testRepo}
createReq := &pb.CreateRepositoryFromURLRequest{Repository: glRepository, Url: testRepoImportUrl}
_, err = repository.CreateRepositoryFromURL(context.Background(), createReq)
require.NoError(t, err)
return conn, glRepository
}
func successAPI(t *testing.T) http.Handler {
func startGitOverHTTPServer(t *testing.T) string {
ctx := context.Background()
conn, glRepository := ensureGitalyRepository(t)
client := pb.NewSmartHTTPServiceClient(conn)
requests := []testserver.TestRequestHandler{
{
Path: "/info/refs",
Handler: func(w http.ResponseWriter, r *http.Request) {
rpcRequest := &pb.InfoRefsRequest{
Repository: glRepository,
}
var reader io.Reader
switch r.URL.Query().Get("service") {
case "git-receive-pack":
stream, err := client.InfoRefsReceivePack(ctx, rpcRequest)
require.NoError(t, err)
reader = streamio.NewReader(func() ([]byte, error) {
resp, err := stream.Recv()
return resp.GetData(), err
})
default:
t.FailNow()
}
_, err := io.Copy(w, reader)
require.NoError(t, err)
},
},
{
Path: "/git-receive-pack",
Handler: func(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body)
require.NoError(t, err)
defer r.Body.Close()
require.Equal(t, string(body), "0000")
},
},
}
return testserver.StartHttpServer(t, requests)
}
func buildAllowedResponse(t *testing.T, filename string) string {
testhelper.PrepareTestRootDir(t)
body, err := os.ReadFile(filepath.Join(testhelper.TestRoot, filename))
require.NoError(t, err)
response := strings.Replace(string(body), "GITALY_REPOSITORY", testRepo, 1)
if gitalyConnInfo != nil {
response = strings.Replace(response, "GITALY_ADDRESS", gitalyConnInfo.Address, 1)
response = strings.Replace(response, "GITALY_STORAGE", gitalyConnInfo.Storage, 1)
}
return response
}
type customHandler struct {
url string
caller http.HandlerFunc
}
func successAPI(t *testing.T, handlers ...customHandler) http.Handler {
t.Helper()
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
testhelper.PrepareTestRootDir(t)
t.Logf("gitlab-api-mock: received request: %s %s", r.Method, r.RequestURI)
w.Header().Set("Content-Type", "application/json")
switch r.URL.EscapedPath() {
url := r.URL.EscapedPath()
for _, handler := range handlers {
if url == handler.url {
handler.caller(w, r)
return
}
}
switch url {
case "/api/v4/internal/authorized_keys":
fmt.Fprintf(w, `{"id":1, "key":"%s"}`, r.FormValue("key"))
case "/api/v4/internal/discover":
Loading
Loading
@@ -111,17 +191,9 @@ func successAPI(t *testing.T) http.Handler {
case "/api/v4/internal/two_factor_otp_check":
fmt.Fprint(w, `{"success": true}`)
case "/api/v4/internal/allowed":
body, err := os.ReadFile(filepath.Join(testhelper.TestRoot, "responses/allowed_without_console_messages.json"))
require.NoError(t, err)
response := strings.Replace(string(body), "GITALY_REPOSITORY", testRepo, 1)
if gitalyConnInfo != nil {
response = strings.Replace(response, "GITALY_ADDRESS", gitalyConnInfo.Address, 1)
response = strings.Replace(response, "GITALY_STORAGE", gitalyConnInfo.Storage, 1)
}
response := buildAllowedResponse(t, "responses/allowed_without_console_messages.json")
fmt.Fprint(w, response)
_, err := fmt.Fprint(w, response)
require.NoError(t, err)
case "/api/v4/internal/lfs_authenticate":
fmt.Fprint(w, `{"username": "test-user", "lfs_token": "testlfstoken", "repo_path": "foo", "expires_in": 7200}`)
Loading
Loading
@@ -418,6 +490,51 @@ func TestGitReceivePackSuccess(t *testing.T) {
require.Equal(t, "0000", outputLines[len(outputLines)-1])
}
func TestGeoGitReceivePackSuccess(t *testing.T) {
url := startGitOverHTTPServer(t)
handler := customHandler{
url: "/api/v4/internal/allowed",
caller: func(w http.ResponseWriter, _ *http.Request) {
response := buildAllowedResponse(t, "responses/allowed_with_geo_push_payload.json")
response = strings.Replace(response, "PRIMARY_REPO", url, 1)
w.WriteHeader(300)
_, err := fmt.Fprint(w, response)
require.NoError(t, err)
},
}
client := runSSHD(t, successAPI(t, handler))
session, err := client.NewSession()
require.NoError(t, err)
defer session.Close()
stdin, err := session.StdinPipe()
require.NoError(t, err)
stdout, err := session.StdoutPipe()
require.NoError(t, err)
err = session.Start(fmt.Sprintf("git-receive-pack %s", testRepo))
require.NoError(t, err)
// Gracefully close connection
_, err = fmt.Fprintln(stdin, "0000")
require.NoError(t, err)
stdin.Close()
output, err := io.ReadAll(stdout)
require.NoError(t, err)
outputLines := strings.Split(string(output), "\n")
for i := 0; i < (len(outputLines) - 1); i++ {
require.Regexp(t, "^[0-9a-f]{44} refs/(heads|tags)/[^ ]+", outputLines[i])
}
require.Equal(t, "0000", outputLines[len(outputLines)-1])
}
func TestGitUploadPackSuccess(t *testing.T) {
ensureGitalyRepository(t)
Loading
Loading
{
"status": true,
"gl_repository": "project-26",
"gl_project_path": "group/private",
"gl_id": "user-1",
"gl_username": "root",
"git_config_options": [],
"gitaly": {
"repository": {
"storage_name": "default",
"relative_path": "GITALY_REPOSITORY",
"git_object_directory": "objects/",
"git_alternate_object_directories": ["objects/"],
"gl_repository": "project-26",
"gl_project_path": "group/private"
},
"address": "GITALY_ADDRESS",
"token": "token"
},
"payload" : {
"data": {
"geo_proxy_direct_to_primary": true,
"request_headers": { "Authorization": "Bearer token" },
"primary_repo": "PRIMARY_REPO"
}
},
"git_protocol": "protocol",
"gl_console_messages": ["console", "message"]
}
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