Commit 06dfc9ab authored by Ash McKenzie's avatar Ash McKenzie

Prefix classes/modules & methods with Geo or geo_

Also included is a small refactor aimed at
improving performance and readability.
parent 419a758b
......@@ -5,22 +5,33 @@ module EE
module GitHttpClientController
extend ActiveSupport::Concern
# This module is responsible for determining if an incoming secondary bound
# HTTP request should be redirected to the primary.
# This module is responsible for determining if an incoming Geo secondary
# bound HTTP request should be redirected to the Primary.
#
# Why? A secondary is not allowed to perform any write actions, so any
# request of this type need to be sent through to the primary. By
# request of this type needs to be sent through to the Primary. By
# redirecting within code, we allow clients to git pull/push using their
# secondary git remote without needing an additional primary remote.
#
# The method for redirection *must* happen as early as possible in the
# request. For example, putting the redirection logic in #access_check
# will not work because the git client will not accept a 302 in response
# to verifying credentials.
#
# Current secondary HTTP requests to redirect: -
#
# * git pull (repository is not replicated)
# * GET /namespace/repo.git/info/refs?service=git-upload-pack
#
# * git lfs pull (repository is not replicated)
# * GET /namespace/repo.git/gitlab-lfs/objects/<oid>
#
# * git push
# * GET /repo.git/info/refs?service=git-receive-pack
# * POST /repo.git/git-receive-pack
# * GET /namespace/repo.git/info/refs?service=git-receive-pack
# * POST /namespace/repo.git/git-receive-pack
#
# * git lfs push (usually happens automatically as part of a `git push`)
# * POST /repo.git/info/lfs/objects/batch (and we examine
# * POST /namespace/repo.git/info/lfs/objects/batch (and we examine
# params[:operation] to ensure we're dealing with an upload request)
#
# For more detail, see the following links:
......@@ -30,13 +41,13 @@ module EE
#
prepended do
prepend_before_action do
redirect_to(primary_full_url) if redirect?
redirect_to(geo_primary_full_url) if geo_redirect?
end
end
private
class RouteHelper
class GeoRouteHelper
attr_reader :controller_name, :action_name
CONTROLLER_AND_ACTIONS_TO_REDIRECT = {
......@@ -92,11 +103,11 @@ module EE
end
end
class GitLFSHelper
class GeoGitLFSHelper
MINIMUM_GIT_LFS_VERSION = '2.4.2'.freeze
def initialize(route_helper, operation, current_version)
@route_helper = route_helper
def initialize(geo_route_helper, operation, current_version)
@geo_route_helper = geo_route_helper
@operation = operation
@current_version = current_version
end
......@@ -110,8 +121,7 @@ module EE
end
def redirect?
return false unless route_helper.match?('lfs_api', 'batch')
return true if upload?
return true if batch_upload?
false
end
......@@ -124,15 +134,19 @@ module EE
private
attr_reader :route_helper, :operation, :current_version
attr_reader :geo_route_helper, :operation, :current_version
def incorrect_version_message
translation = _("You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com")
translation % { min_git_lfs_version: MINIMUM_GIT_LFS_VERSION }
end
def upload?
operation == 'upload'
def batch_request?
geo_route_helper.match?('lfs_api', 'batch')
end
def batch_upload?
batch_request? && operation == 'upload'
end
def wanted_version
......@@ -140,52 +154,45 @@ module EE
end
end
def route_helper
@route_helper ||= RouteHelper.new(controller_name, action_name, params[:service])
def geo_route_helper
@geo_route_helper ||= GeoRouteHelper.new(controller_name, action_name, params[:service])
end
def git_lfs_helper
def geo_git_lfs_helper
# params[:operation] explained: https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md#requests
@git_lfs_helper ||= GitLFSHelper.new(route_helper, params[:operation], request.headers['User-Agent'])
@geo_git_lfs_helper ||= GeoGitLFSHelper.new(geo_route_helper, params[:operation], request.headers['User-Agent'])
end
def request_fullpath_for_primary
def geo_request_fullpath_for_primary
relative_url_root = ::Gitlab.config.gitlab.relative_url_root.chomp('/')
request.fullpath.sub(relative_url_root, '')
end
def primary_full_url
path = File.join(secondary_referrer_path_prefix, request_fullpath_for_primary)
def geo_primary_full_url
path = File.join(geo_secondary_referrer_path_prefix, geo_request_fullpath_for_primary)
::Gitlab::Utils.append_path(::Gitlab::Geo.primary_node.internal_url, path)
end
def secondary_referrer_path_prefix
def geo_secondary_referrer_path_prefix
File.join(::Gitlab::Geo::GitPushHttp::PATH_PREFIX, ::Gitlab::Geo.current_node.id.to_s)
end
def redirect?
# Don't redirect if we're not a secondary with a primary
def geo_redirect?
return false unless ::Gitlab::Geo.secondary_with_primary?
return true if geo_route_helper.redirect?
# Redirect as the request matches RouteHelper::CONTROLLER_AND_ACTIONS_TO_REDIRECT
return true if route_helper.redirect?
# Look to redirect, as we're an LFS batch upload request
if git_lfs_helper.redirect?
# Redirect as git-lfs version is at least 2.4.2
return true if git_lfs_helper.version_ok?
if geo_git_lfs_helper.redirect?
return true if geo_git_lfs_helper.version_ok?
# git-lfs 2.4.2 is really only required for requests that involve
# redirection, so we only render if it's an LFS upload operation
#
render(git_lfs_helper.incorrect_version_response)
render(geo_git_lfs_helper.incorrect_version_response)
# Don't redirect
return false
end
# Don't redirect
false
end
end
......
......@@ -8,6 +8,7 @@ module EE
prepended do
helpers do
include ::Gitlab::Utils::StrongMemoize
extend ::Gitlab::Utils::Override
override :lfs_authentication_url
......@@ -17,22 +18,27 @@ module EE
override :ee_post_receive_response_hook
def ee_post_receive_response_hook(response)
response.add_basic_message(geo_secondary_lag_message) if ::Gitlab::Geo.primary?
response.add_basic_message(geo_secondary_lag_message) if geo_display_secondary_lag_message?
end
def geo_secondary_lag_message
lag = current_replication_lag
return if lag.to_i <= 0
def geo_display_secondary_lag_message?
::Gitlab::Geo.primary? && geo_current_replication_lag.to_i > 0
end
"Current replication lag: #{lag} seconds"
def geo_secondary_lag_message
"Current replication lag: #{geo_current_replication_lag} seconds"
end
def current_replication_lag
fetch_geo_node_referrer&.status&.db_replication_lag_seconds
def geo_current_replication_lag
strong_memoize(:geo_current_replication_lag) do
geo_referred_node&.status&.db_replication_lag_seconds
end
end
def fetch_geo_node_referrer
::Gitlab::Geo::GitPushHttp.new(params[:identifier], params[:gl_repository]).fetch_referrer_node
def geo_referred_node
strong_memoize(:geo_referred_node) do
::Gitlab::Geo::GitPushHttp.new(params[:identifier], params[:gl_repository]).fetch_referrer_node
end
end
override :check_allowed
......
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