diff --git a/workhorse/internal/upstream/routes.go b/workhorse/internal/upstream/routes.go index 8c85c5144e586167c9f257ad28099285b1b1bbea..07bbd57421eae3969edfa87b27a5af6c7c55eaca 100644 --- a/workhorse/internal/upstream/routes.go +++ b/workhorse/internal/upstream/routes.go @@ -56,6 +56,7 @@ const ( apiPattern = `^/api/` ciAPIPattern = `^/ci/api/` gitProjectPattern = `^/.+\.git/` + geoGitProjectPattern = `^/[^-].+\.git/` // Prevent matching routes like /-/push_from_secondary projectPattern = `^/([^/]+/){1,}[^/]+/` apiProjectPattern = apiPattern + `v4/projects/[^/]+/` // API: Projects can be encoded via group%2Fsubgroup%2Fproject snippetUploadPattern = `^/uploads/personal_snippet` @@ -348,10 +349,9 @@ func configureRoutes(u *upstream) { // pulls are performed against a different source of truth. Ideally, we'd // proxy/redirect pulls as well, when the secondary is not up-to-date. // - u.route("GET", gitProjectPattern+`info/refs\z`, git.GetInfoRefsHandler(api)), - u.route("POST", gitProjectPattern+`git-upload-pack\z`, contentEncodingHandler(git.UploadPack(api)), withMatcher(isContentType("application/x-git-upload-pack-request"))), - u.route("POST", gitProjectPattern+`git-receive-pack\z`, contentEncodingHandler(git.ReceivePack(api)), withMatcher(isContentType("application/x-git-receive-pack-request"))), - u.route("PUT", gitProjectPattern+`gitlab-lfs/objects/([0-9a-f]{64})/([0-9]+)\z`, lfs.PutStore(api, signingProxy, preparers.lfs), withMatcher(isContentType("application/octet-stream"))), + u.route("GET", geoGitProjectPattern+`info/refs\z`, git.GetInfoRefsHandler(api)), + u.route("POST", geoGitProjectPattern+`git-upload-pack\z`, contentEncodingHandler(git.UploadPack(api)), withMatcher(isContentType("application/x-git-upload-pack-request"))), + u.route("GET", geoGitProjectPattern+`gitlab-lfs/objects/([0-9a-f]{64})\z`, defaultUpstream), // Serve health checks from this Geo secondary u.route("", "^/-/(readiness|liveness)$", static.DeployPage(probeUpstream)), diff --git a/workhorse/internal/upstream/upstream_test.go b/workhorse/internal/upstream/upstream_test.go index efc85dd6c2e0ed63bad39a3aa6763f7a6aadec93..3c9427673840bca37d8915750e196c6c797317bf 100644 --- a/workhorse/internal/upstream/upstream_test.go +++ b/workhorse/internal/upstream/upstream_test.go @@ -99,6 +99,8 @@ func TestGeoProxyFeatureEnabledOnGeoSecondarySite(t *testing.T) { defer wsDeferredClose() testCases := []testCase{ + {"push from secondary is forwarded", "/-/push_from_secondary/foo/bar.git/info/refs", "Geo primary received request to path /-/push_from_secondary/foo/bar.git/info/refs"}, + {"LFS files are served locally", "/group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6", "Local Rails server received request to path /group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6"}, {"jobs request is forwarded", "/api/v4/jobs/request", "Geo primary received request to path /api/v4/jobs/request"}, {"health check is served locally", "/-/health", "Local Rails server received request to path /-/health"}, {"unknown route is forwarded", "/anything", "Geo primary received request to path /anything"}, @@ -117,6 +119,7 @@ func TestGeoProxyFeatureDisabledOnNonGeoSecondarySite(t *testing.T) { defer wsDeferredClose() testCases := []testCase{ + {"LFS files are served locally", "/group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6", "Local Rails server received request to path /group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6"}, {"jobs request is served locally", "/api/v4/jobs/request", "Local Rails server received request to path /api/v4/jobs/request"}, {"health check is served locally", "/-/health", "Local Rails server received request to path /-/health"}, {"unknown route is served locally", "/anything", "Local Rails server received request to path /anything"}, @@ -134,6 +137,7 @@ func TestGeoProxyFeatureEnabledOnNonGeoSecondarySite(t *testing.T) { defer wsDeferredClose() testCases := []testCase{ + {"LFS files are served locally", "/group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6", "Local Rails server received request to path /group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6"}, {"jobs request is served locally", "/api/v4/jobs/request", "Local Rails server received request to path /api/v4/jobs/request"}, {"health check is served locally", "/-/health", "Local Rails server received request to path /-/health"}, {"unknown route is served locally", "/anything", "Local Rails server received request to path /anything"}, @@ -151,6 +155,7 @@ func TestGeoProxyFeatureEnabledButWithAPIError(t *testing.T) { defer wsDeferredClose() testCases := []testCase{ + {"LFS files are served locally", "/group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6", "Local Rails server received request to path /group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6"}, {"jobs request is served locally", "/api/v4/jobs/request", "Local Rails server received request to path /api/v4/jobs/request"}, {"health check is served locally", "/-/health", "Local Rails server received request to path /-/health"}, {"unknown route is served locally", "/anything", "Local Rails server received request to path /anything"}, @@ -174,12 +179,15 @@ func TestGeoProxyFeatureEnablingAndDisabling(t *testing.T) { defer wsDeferredClose() testCasesLocal := []testCase{ + {"LFS files are served locally", "/group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6", "Local Rails server received request to path /group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6"}, {"jobs request is served locally", "/api/v4/jobs/request", "Local Rails server received request to path /api/v4/jobs/request"}, {"health check is served locally", "/-/health", "Local Rails server received request to path /-/health"}, {"unknown route is served locally", "/anything", "Local Rails server received request to path /anything"}, } testCasesProxied := []testCase{ + {"push from secondary is forwarded", "/-/push_from_secondary/foo/bar.git/info/refs", "Geo primary received request to path /-/push_from_secondary/foo/bar.git/info/refs"}, + {"LFS files are served locally", "/group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6", "Local Rails server received request to path /group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6"}, {"jobs request is forwarded", "/api/v4/jobs/request", "Geo primary received request to path /api/v4/jobs/request"}, {"health check is served locally", "/-/health", "Local Rails server received request to path /-/health"}, {"unknown route is forwarded", "/anything", "Geo primary received request to path /anything"},