Commit 8f71ff07 authored by Ash McKenzie's avatar Ash McKenzie

Geo: Redirect secondary HTTP git push to primary

parent 6a083e88
......@@ -3,6 +3,7 @@
class Projects::GitHttpClientController < Projects::ApplicationController
include ActionController::HttpAuthentication::Basic
include KerberosSpnegoHelper
prepend ::EE::Projects::GitHttpClientController
attr_reader :authentication_result, :redirected_path
......
module EE
module Projects
module GitHttpClientController
extend ActiveSupport::Concern
prepended do
before_action :redirect_push_to_primary, only: [:info_refs]
end
private
def redirect_push_to_primary
redirect_to(primary_full_url) if redirect_push_to_primary?
end
def primary_full_url
File.join(::Gitlab::Geo.primary_node.url, request_fullpath_for_primary)
end
def request_fullpath_for_primary
relative_url_root = ::Gitlab.config.gitlab.relative_url_root.chomp('/')
request.fullpath.sub(relative_url_root, '')
end
def redirect_push_to_primary?
git_push_request? && ::Gitlab::Geo.secondary_with_primary?
end
def git_push_request?
git_command == 'git-receive-pack'
end
end
end
end
---
title: 'Geo: HTTP git push to secondary now redirects to the primary'
merge_request: 5785
author:
type: added
......@@ -13,6 +13,8 @@ describe "Git HTTP requests (Geo)" do
# Ensure the token always comes from the real time of the request
let!(:auth_token) { Gitlab::Geo::BaseRequest.new.authorization }
let(:env) { valid_geo_env }
before do
stub_licensed_features(geo: true)
stub_current_geo_node(secondary)
......@@ -21,30 +23,14 @@ describe "Git HTTP requests (Geo)" do
shared_examples_for 'Geo sync request' do
subject do
make_request
response
end
context 'valid Geo JWT token' do
let(:env) { valid_geo_env }
it 'returns an OK response' do
is_expected.to have_gitlab_http_status(:ok)
expect(response.content_type).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
expect(json_response).to include('ShowAllRefs' => true)
end
end
context 'post-dated Geo JWT token' do
let(:env) { valid_geo_env }
it { travel_to(11.minutes.ago) { is_expected.to have_gitlab_http_status(:unauthorized) } }
end
context 'expired Geo JWT token' do
let(:env) { valid_geo_env }
it { travel_to(Time.now + 11.minutes) { is_expected.to have_gitlab_http_status(:unauthorized) } }
end
......@@ -54,14 +40,21 @@ describe "Git HTTP requests (Geo)" do
it { is_expected.to have_gitlab_http_status(:unauthorized) }
end
context 'valid Geo JWT token' do
it 'returns an OK response' do
is_expected.to have_gitlab_http_status(:ok)
expect(response.content_type).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
expect(json_response).to include('ShowAllRefs' => true)
end
end
context 'no Geo JWT token' do
let(:env) { workhorse_internal_api_request_header }
it { is_expected.to have_gitlab_http_status(:unauthorized) }
end
context 'Geo is unlicensed' do
let(:env) { valid_geo_env }
before do
stub_licensed_features(geo: false)
end
......@@ -71,6 +64,7 @@ describe "Git HTTP requests (Geo)" do
end
describe 'GET info_refs' do
context 'git pull' do
def make_request
get "/#{project.full_path}.git/info/refs", { service: 'git-upload-pack' }, env
end
......@@ -86,6 +80,26 @@ describe "Git HTTP requests (Geo)" do
end
end
context 'git push' do
def make_request
get url, { service: 'git-receive-pack' }, env
end
let(:url) { "/#{project.full_path}.git/info/refs" }
subject do
make_request
response
end
it 'redirects to the primary' do
is_expected.to have_gitlab_http_status(:redirect)
redirect_location = "#{primary.url.chomp('/')}#{url}?service=git-receive-pack"
expect(subject.header['Location']).to eq(redirect_location)
end
end
end
describe 'POST upload_pack' do
def make_request
post "/#{project.full_path}.git/git-upload-pack", {}, env
......@@ -107,9 +121,8 @@ describe "Git HTTP requests (Geo)" do
end
def geo_env(authorization)
env = workhorse_internal_api_request_header
workhorse_internal_api_request_header.tap do |env|
env['HTTP_AUTHORIZATION'] = authorization
env
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment