Commit 78b3d73f authored by Toon Claes's avatar Toon Claes

test: Move most of the Gitaly setup to GitalySetup

To make it easier to maintain the code that sets up Gitaly, move all the
code together in GitalySetup.
parent 12667bfa
......@@ -14,6 +14,8 @@ require 'bundler'
module GitalySetup
extend self
REPOS_STORAGE = 'default'
LOGGER = begin
default_name = ENV['CI'] ? 'DEBUG' : 'WARN'
level_name = ENV['GITLAB_TESTING_LOG_LEVEL']&.upcase
......@@ -93,6 +95,10 @@ module GitalySetup
end
end
def repos_path(storage = REPOS_STORAGE)
Gitlab.config.repositories.storages[REPOS_STORAGE].legacy_disk_path
end
def service_binary(service)
case service
when :gitaly, :gitaly2
......@@ -210,4 +216,133 @@ module GitalySetup
raise "could not connect to #{socket}"
end
def gitaly_socket_path
Gitlab::GitalyClient.address(REPOS_STORAGE).delete_prefix('unix:')
end
def gitaly_dir
socket_path = gitaly_socket_path
socket_path = File.expand_path(gitaly_socket_path) if expand_path_for_socket?
File.dirname(socket_path)
end
# Linux fails with "bind: invalid argument" if a UNIX socket path exceeds 108 characters:
# https://github.com/golang/go/issues/6895. We use absolute paths in CI to ensure
# that changes in the current working directory don't affect GRPC reconnections.
def expand_path_for_socket?
!!ENV['CI']
end
def setup_gitaly
unless ENV['CI']
# In CI Gitaly is built in the setup-test-env job and saved in the
# artifacts. So when tests are started, there's no need to build Gitaly.
build_gitaly
end
Gitlab::SetupHelper::Gitaly.create_configuration(
gitaly_dir,
{ 'default' => repos_path },
force: true,
options: {
prometheus_listen_addr: 'localhost:9236'
}
)
Gitlab::SetupHelper::Gitaly.create_configuration(
gitaly_dir,
{ 'default' => repos_path },
force: true,
options: {
internal_socket_dir: File.join(gitaly_dir, "internal_gitaly2"),
gitaly_socket: "gitaly2.socket",
config_filename: "gitaly2.config.toml"
}
)
Gitlab::SetupHelper::Praefect.create_configuration(gitaly_dir, { 'praefect' => repos_path }, force: true)
end
def socket_path(service)
File.join(tmp_tests_gitaly_dir, "#{service}.socket")
end
def praefect_socket_path
"unix:" + socket_path(:praefect)
end
def wait(service)
sleep_time = 10
sleep_interval = 0.1
socket = socket_path(service)
Integer(sleep_time / sleep_interval).times do
Socket.unix(socket)
return
rescue StandardError
sleep sleep_interval
end
raise "could not connect to #{service} at #{socket.inspect} after #{sleep_time} seconds"
end
def stop(pid)
Process.kill('KILL', pid)
rescue Errno::ESRCH
# The process can already be gone if the test run was INTerrupted.
end
def spawn_gitaly
spawn_script = Rails.root.join('scripts/gitaly-test-spawn').to_s
Bundler.with_original_env do
unless system(spawn_script)
raise gitaly_failure_message
end
end
gitaly_pid = Integer(File.read(TMP_TEST_PATH.join('gitaly.pid')))
gitaly2_pid = Integer(File.read(TMP_TEST_PATH.join('gitaly2.pid')))
praefect_pid = Integer(File.read(TMP_TEST_PATH.join('praefect.pid')))
Kernel.at_exit do
pids = [gitaly_pid, gitaly2_pid, praefect_pid]
pids.each { |pid| stop(pid) }
end
wait('gitaly')
wait('praefect')
end
def gitaly_failure_message
message = "gitaly spawn failed\n\n"
message += "- The `gitaly` binary does not exist: #{gitaly_binary}\n" unless File.exist?(gitaly_binary)
message += "- The `praefect` binary does not exist: #{praefect_binary}\n" unless File.exist?(praefect_binary)
message += "- The `git` binary does not exist: #{git_binary}\n" unless File.exist?(git_binary)
message += "\nCheck log/gitaly-test.log for errors.\n"
unless ci?
message += "\nIf binaries are missing, try running `make -C tmp/tests/gitaly build git.`\n"
message += "\nOtherwise, try running `rm -rf #{gitaly_dir}`."
end
message
end
def git_binary
File.join(gitaly_dir, "_build", "deps", "git", "install", "bin", "git")
end
def gitaly_binary
File.join(gitaly_dir, "_build", "bin", "gitaly")
end
def praefect_binary
File.join(gitaly_dir, "_build", "bin", "praefect")
end
def git_binary_exists?
File.exist?(git_binary)
end
end
# frozen_string_literal: true
require 'parallel'
require_relative 'gitaly_setup'
module TestEnv
extend self
......@@ -93,7 +94,6 @@ module TestEnv
}.freeze
TMP_TEST_PATH = Rails.root.join('tmp', 'tests').freeze
REPOS_STORAGE = 'default'
SECOND_STORAGE_PATH = Rails.root.join('tmp', 'tests', 'second_storage')
SETUP_METHODS = %i[setup_gitaly setup_gitlab_shell setup_workhorse setup_factory_repo setup_forked_repo].freeze
......@@ -128,7 +128,7 @@ module TestEnv
# Can be overriden
def post_init
start_gitaly(gitaly_dir)
start_gitaly
end
# Clean /tmp/tests
......@@ -142,7 +142,7 @@ module TestEnv
end
FileUtils.mkdir_p(
Gitlab::GitalyClient::StorageSettings.allow_disk_access { TestEnv.repos_path }
Gitlab::GitalyClient::StorageSettings.allow_disk_access { GitalySetup.repos_path }
)
FileUtils.mkdir_p(SECOND_STORAGE_PATH)
FileUtils.mkdir_p(backup_path)
......@@ -159,114 +159,28 @@ module TestEnv
def setup_gitaly
component_timed_setup('Gitaly',
install_dir: gitaly_dir,
install_dir: GitalySetup.gitaly_dir,
version: Gitlab::GitalyClient.expected_server_version,
task: "gitlab:gitaly:clone",
fresh_install: ENV.key?('FORCE_GITALY_INSTALL'),
task_args: [gitaly_dir, repos_path, gitaly_url].compact) do
unless ci? # In CI we run scripts/gitaly-test-build
GitalySetup.build_gitaly
end
Gitlab::SetupHelper::Gitaly.create_configuration(
gitaly_dir,
{ 'default' => repos_path },
force: true,
options: {
prometheus_listen_addr: 'localhost:9236'
}
)
Gitlab::SetupHelper::Gitaly.create_configuration(
gitaly_dir,
{ 'default' => repos_path },
force: true,
options: {
internal_socket_dir: File.join(gitaly_dir, "internal_gitaly2"),
gitaly_socket: "gitaly2.socket",
config_filename: "gitaly2.config.toml"
}
)
Gitlab::SetupHelper::Praefect.create_configuration(gitaly_dir, { 'praefect' => repos_path }, force: true)
end
end
def gitaly_socket_path
Gitlab::GitalyClient.address('default').sub(/\Aunix:/, '')
end
def gitaly_dir
socket_path = gitaly_socket_path
socket_path = File.expand_path(gitaly_socket_path) if expand_path?
File.dirname(socket_path)
end
# Linux fails with "bind: invalid argument" if a UNIX socket path exceeds 108 characters:
# https://github.com/golang/go/issues/6895. We use absolute paths in CI to ensure
# that changes in the current working directory don't affect GRPC reconnections.
def expand_path?
!!ENV['CI']
task_args: [GitalySetup.gitaly_dir, GitalySetup.repos_path, gitaly_url].compact) do
GitalySetup.setup_gitaly
end
end
def start_gitaly(gitaly_dir)
def start_gitaly
if ci?
# Gitaly has been spawned outside this process already
return
end
spawn_script = Rails.root.join('scripts/gitaly-test-spawn').to_s
Bundler.with_original_env do
unless system(spawn_script)
raise gitaly_failure_message
end
end
gitaly_pid = Integer(File.read(TMP_TEST_PATH.join('gitaly.pid')))
gitaly2_pid = Integer(File.read(TMP_TEST_PATH.join('gitaly2.pid')))
praefect_pid = Integer(File.read(TMP_TEST_PATH.join('praefect.pid')))
Kernel.at_exit do
pids = [gitaly_pid, gitaly2_pid, praefect_pid]
pids.each { |pid| stop(pid) }
end
wait('gitaly')
wait('praefect')
end
def stop(pid)
Process.kill('KILL', pid)
rescue Errno::ESRCH
# The process can already be gone if the test run was INTerrupted.
GitalySetup.spawn_gitaly
end
def gitaly_url
ENV.fetch('GITALY_REPO_URL', nil)
end
def socket_path(service)
TMP_TEST_PATH.join('gitaly', "#{service}.socket").to_s
end
def praefect_socket_path
"unix:" + socket_path(:praefect)
end
def wait(service)
sleep_time = 10
sleep_interval = 0.1
socket = socket_path(service)
Integer(sleep_time / sleep_interval).times do
Socket.unix(socket)
return
rescue StandardError
sleep sleep_interval
end
raise "could not connect to #{service} at #{socket.inspect} after #{sleep_time} seconds"
end
# Feature specs are run through Workhorse
def setup_workhorse
# Always rebuild the config file
......@@ -382,8 +296,7 @@ module TestEnv
def rm_storage_dir(storage, dir)
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
repos_path = Gitlab.config.repositories.storages[storage].legacy_disk_path
target_repo_refs_path = File.join(repos_path, dir)
target_repo_refs_path = File.join(GitalySetup.repos_path(storage), dir)
FileUtils.remove_dir(target_repo_refs_path)
end
rescue Errno::ENOENT
......@@ -391,8 +304,7 @@ module TestEnv
def storage_dir_exists?(storage, dir)
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
repos_path = Gitlab.config.repositories.storages[storage].legacy_disk_path
File.exist?(File.join(repos_path, dir))
File.exist?(File.join(GitalySetup.repos_path(storage), dir))
end
end
......@@ -405,7 +317,7 @@ module TestEnv
end
def repos_path
@repos_path ||= Gitlab.config.repositories.storages[REPOS_STORAGE].legacy_disk_path
@repos_path ||= GitalySetup.repos_path
end
def backup_path
......@@ -619,39 +531,6 @@ module TestEnv
expected_version == sha.chomp
end
def gitaly_failure_message
message = "gitaly spawn failed\n\n"
message += "- The `gitaly` binary does not exist: #{gitaly_binary}\n" unless File.exist?(gitaly_binary)
message += "- The `praefect` binary does not exist: #{praefect_binary}\n" unless File.exist?(praefect_binary)
message += "- The `git` binary does not exist: #{git_binary}\n" unless File.exist?(git_binary)
message += "\nCheck log/gitaly-test.log for errors.\n"
unless ci?
message += "\nIf binaries are missing, try running `make -C tmp/tests/gitaly build git.`\n"
message += "\nOtherwise, try running `rm -rf #{gitaly_dir}`."
end
message
end
def git_binary
File.join(gitaly_dir, "_build", "deps", "git", "install", "bin", "git")
end
def gitaly_binary
File.join(gitaly_dir, "_build", "bin", "gitaly")
end
def praefect_binary
File.join(gitaly_dir, "_build", "bin", "praefect")
end
def git_binary_exists?
File.exist?(git_binary)
end
end
require_relative('../../../ee/spec/support/helpers/ee/test_env') if Gitlab.ee?
......
# frozen_string_literal: true
require_relative 'helpers/test_env'
require_relative 'helpers/gitaly_setup'
RSpec.configure do |config|
config.before(:each, :praefect) do
allow(Gitlab.config.repositories.storages['default']).to receive(:[]).and_call_original
allow(Gitlab.config.repositories.storages['default']).to receive(:[]).with('gitaly_address')
.and_return(TestEnv.praefect_socket_path)
.and_return(GitalySetup.praefect_socket_path)
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