Refactor gitlab:app:checks to use SystemCheck

This commit is contained in:
Gabriel Mazetto 2017-05-25 16:16:25 +02:00
parent 45378bdd3a
commit 13e88c9395
22 changed files with 777 additions and 503 deletions

View File

@ -0,0 +1,31 @@
module SystemCheck
module App
class DatabaseConfigExistsCheck < SystemCheck::BaseCheck
set_name 'Database config exists?'
def check?
database_config_file = Rails.root.join('config', 'database.yml')
File.exist?(database_config_file)
end
def show_error
try_fixing_it(
'Copy config/database.yml.<your db> to config/database.yml',
'Check that the information in config/database.yml is correct'
)
for_more_information(
see_database_guide,
'http://guides.rubyonrails.org/getting_started.html#configuring-a-database'
)
fix_and_rerun
end
private
def see_database_guide
'doc/install/databases.md'
end
end
end
end

View File

@ -0,0 +1,50 @@
module SystemCheck
module App
class GitConfigCheck < SystemCheck::BaseCheck
OPTIONS = {
'core.autocrlf' => 'input'
}.freeze
set_name 'Git configured with autocrlf=input?'
def check?
correct_options = OPTIONS.map do |name, value|
run_command(%W(#{Gitlab.config.git.bin_path} config --global --get #{name})).try(:squish) == value
end
correct_options.all?
end
def repair!
auto_fix_git_config(OPTIONS)
end
def show_error
try_fixing_it(
sudo_gitlab("\"#{Gitlab.config.git.bin_path}\" config --global core.autocrlf \"#{OPTIONS['core.autocrlf']}\"")
)
for_more_information(
see_installation_guide_section 'GitLab'
)
end
private
# Tries to configure git itself
#
# Returns true if all subcommands were successfull (according to their exit code)
# Returns false if any or all subcommands failed.
def auto_fix_git_config(options)
if !@warned_user_not_gitlab
command_success = options.map do |name, value|
system(*%W(#{Gitlab.config.git.bin_path} config --global #{name} #{value}))
end
command_success.all?
else
false
end
end
end
end
end

View File

@ -0,0 +1,29 @@
module SystemCheck
module App
class GitVersionCheck < SystemCheck::BaseCheck
set_name -> { "Git version >= #{self.required_version} ?" }
set_check_pass -> { "yes (#{self.current_version})" }
def self.required_version
@required_version ||= Gitlab::VersionInfo.new(2, 7, 3)
end
def self.current_version
@current_version ||= Gitlab::VersionInfo.parse(run_command(%W(#{Gitlab.config.git.bin_path} --version)))
end
def check?
self.class.current_version.valid? && self.class.required_version <= self.class.current_version
end
def show_error
puts "Your git bin path is \"#{Gitlab.config.git.bin_path}\""
try_fixing_it(
"Update your git to a version >= #{self.class.required_version} from #{self.class.current_version}"
)
fix_and_rerun
end
end
end
end

View File

@ -0,0 +1,24 @@
module SystemCheck
module App
class GitlabConfigExistsCheck < SystemCheck::BaseCheck
set_name 'GitLab config exists?'
def check?
gitlab_config_file = Rails.root.join('config', 'gitlab.yml')
File.exist?(gitlab_config_file)
end
def show_error
try_fixing_it(
'Copy config/gitlab.yml.example to config/gitlab.yml',
'Update config/gitlab.yml to match your setup'
)
for_more_information(
see_installation_guide_section 'GitLab'
)
fix_and_rerun
end
end
end
end

View File

@ -0,0 +1,32 @@
module SystemCheck
module App
class GitlabConfigNotOutdatedCheck < SystemCheck::BaseCheck
set_name 'GitLab config outdated?'
set_check_pass 'no'
set_check_fail 'yes'
set_skip_reason "can't check because of previous errors"
def skip?
gitlab_config_file = Rails.root.join('config', 'gitlab.yml')
!File.exist?(gitlab_config_file)
end
def check?
# omniauth or ldap could have been deleted from the file
!Gitlab.config['git_host']
end
def show_error
try_fixing_it(
'Backup your config/gitlab.yml',
'Copy config/gitlab.yml.example to config/gitlab.yml',
'Update config/gitlab.yml to match your setup'
)
for_more_information(
see_installation_guide_section 'GitLab'
)
fix_and_rerun
end
end
end
end

View File

@ -0,0 +1,27 @@
module SystemCheck
module App
class InitScriptExistsCheck < SystemCheck::BaseCheck
set_name 'Init script exists?'
set_skip_reason 'skipped (omnibus-gitlab has no init script)'
def skip?
omnibus_gitlab?
end
def check?
script_path = '/etc/init.d/gitlab'
File.exist?(script_path)
end
def show_error
try_fixing_it(
'Install the init script'
)
for_more_information(
see_installation_guide_section 'Install Init Script'
)
fix_and_rerun
end
end
end
end

View File

@ -0,0 +1,44 @@
module SystemCheck
module App
class InitScriptUpToDateCheck < SystemCheck::BaseCheck
SCRIPT_PATH = '/etc/init.d/gitlab'.freeze
set_name 'Init script up-to-date?'
set_skip_reason 'skipped (omnibus-gitlab has no init script)'
def skip?
omnibus_gitlab?
end
def multi_check
recipe_path = Rails.root.join('lib/support/init.d/', 'gitlab')
unless File.exist?(SCRIPT_PATH)
puts "can't check because of previous errors".color(:magenta)
return
end
recipe_content = File.read(recipe_path)
script_content = File.read(SCRIPT_PATH)
if recipe_content == script_content
puts 'yes'.color(:green)
else
puts 'no'.color(:red)
show_error
end
end
def show_error
try_fixing_it(
'Re-download the init script'
)
for_more_information(
see_installation_guide_section 'Install Init Script'
)
fix_and_rerun
end
end
end
end

View File

@ -0,0 +1,28 @@
module SystemCheck
module App
class LogWritableCheck < SystemCheck::BaseCheck
set_name 'Log directory writable?'
def check?
File.writable?(log_path)
end
def show_error
try_fixing_it(
"sudo chown -R gitlab #{log_path}",
"sudo chmod -R u+rwX #{log_path}"
)
for_more_information(
see_installation_guide_section 'GitLab'
)
fix_and_rerun
end
private
def log_path
Rails.root.join('log')
end
end
end
end

View File

@ -0,0 +1,20 @@
module SystemCheck
module App
class MigrationsAreUpCheck < SystemCheck::BaseCheck
set_name 'All migrations up?'
def check?
migration_status, _ = Gitlab::Popen.popen(%w(bundle exec rake db:migrate:status))
migration_status !~ /down\s+\d{14}/
end
def show_error
try_fixing_it(
sudo_gitlab('bundle exec rake db:migrate RAILS_ENV=production')
)
fix_and_rerun
end
end
end
end

View File

@ -0,0 +1,20 @@
module SystemCheck
module App
class OrphanedGroupMembersCheck < SystemCheck::BaseCheck
set_name 'Database contains orphaned GroupMembers?'
set_check_pass 'no'
set_check_fail 'yes'
def check?
!GroupMember.where('user_id not in (select id from users)').exists?
end
def show_error
try_fixing_it(
'You can delete the orphaned records using something along the lines of:',
sudo_gitlab("bundle exec rails runner -e production 'GroupMember.where(\"user_id NOT IN (SELECT id FROM users)\").delete_all'")
)
end
end
end
end

View File

@ -0,0 +1,37 @@
module SystemCheck
module App
class ProjectsHaveNamespaceCheck < SystemCheck::BaseCheck
set_name 'projects have namespace: '
set_skip_reason "can't check, you have no projects"
def skip?
!Project.exists?
end
def multi_check
puts ''
Project.find_each(batch_size: 100) do |project|
print sanitized_message(project)
if project.namespace
puts 'yes'.color(:green)
else
puts 'no'.color(:red)
show_error
end
end
end
def show_error
try_fixing_it(
"Migrate global projects"
)
for_more_information(
"doc/update/5.4-to-6.0.md in section \"#global-projects\""
)
fix_and_rerun
end
end
end
end

View File

@ -0,0 +1,25 @@
module SystemCheck
module App
class RedisVersionCheck < SystemCheck::BaseCheck
MIN_REDIS_VERSION = '2.8.0'.freeze
set_name "Redis version >= #{MIN_REDIS_VERSION}?"
def check?
redis_version = run_command(%w(redis-cli --version))
redis_version = redis_version.try(:match, /redis-cli (\d+\.\d+\.\d+)/)
redis_version && (Gem::Version.new(redis_version[1]) > Gem::Version.new(MIN_REDIS_VERSION))
end
def show_error
try_fixing_it(
"Update your redis server to a version >= #{MIN_REDIS_VERSION}"
)
for_more_information(
'gitlab-public-wiki/wiki/Trouble-Shooting-Guide in section sidekiq'
)
fix_and_rerun
end
end
end
end

View File

@ -0,0 +1,27 @@
module SystemCheck
module App
class RubyVersionCheck < SystemCheck::BaseCheck
set_name -> { "Ruby version >= #{self.required_version} ?" }
set_check_pass -> { "yes (#{self.current_version})" }
def self.required_version
@required_version ||= Gitlab::VersionInfo.new(2, 1, 0)
end
def self.current_version
@current_version ||= Gitlab::VersionInfo.parse(run_command(%w(ruby --version)))
end
def check?
self.class.current_version.valid? && self.class.required_version <= self.class.current_version
end
def show_error
try_fixing_it(
"Update your ruby to a version >= #{self.class.required_version} from #{self.class.current_version}"
)
fix_and_rerun
end
end
end
end

View File

@ -0,0 +1,28 @@
module SystemCheck
module App
class TmpWritableCheck < SystemCheck::BaseCheck
set_name 'Tmp directory writable?'
def check?
File.writable?(tmp_path)
end
def show_error
try_fixing_it(
"sudo chown -R gitlab #{tmp_path}",
"sudo chmod -R u+rwX #{tmp_path}"
)
for_more_information(
see_installation_guide_section 'GitLab'
)
fix_and_rerun
end
private
def tmp_path
Rails.root.join('tmp')
end
end
end
end

View File

@ -0,0 +1,21 @@
module SystemCheck
module App
class UploadsDirectoryExistsCheck < SystemCheck::BaseCheck
set_name 'Uploads directory exists?'
def check?
File.directory?(Rails.root.join('public/uploads'))
end
def show_error
try_fixing_it(
"sudo -u #{gitlab_user} mkdir #{Rails.root}/public/uploads"
)
for_more_information(
see_installation_guide_section 'GitLab'
)
fix_and_rerun
end
end
end
end

View File

@ -0,0 +1,36 @@
module SystemCheck
module App
class UploadsPathPermissionCheck < SystemCheck::BaseCheck
set_name 'Uploads directory has correct permissions?'
set_skip_reason 'skipped (no uploads folder found)'
def skip?
!File.directory?(rails_uploads_path)
end
def check?
File.stat(uploads_fullpath).mode == 040700
end
def show_error
try_fixing_it(
"sudo chmod 700 #{uploads_fullpath}"
)
for_more_information(
see_installation_guide_section 'GitLab'
)
fix_and_rerun
end
private
def rails_uploads_path
Rails.root.join('public/uploads')
end
def uploads_fullpath
File.realpath(rails_uploads_path)
end
end
end
end

View File

@ -0,0 +1,40 @@
module SystemCheck
module App
class UploadsPathTmpPermissionCheck < SystemCheck::BaseCheck
set_name 'Uploads directory tmp has correct permissions?'
set_skip_reason 'skipped (no tmp uploads folder yet)'
def skip?
!File.directory?(uploads_fullpath) || !Dir.exist?(upload_path_tmp)
end
def check?
# If tmp upload dir has incorrect permissions, assume others do as well
# Verify drwx------ permissions
File.stat(upload_path_tmp).mode == 040700 && File.owned?(upload_path_tmp)
end
def show_error
try_fixing_it(
"sudo chown -R #{gitlab_user} #{uploads_fullpath}",
"sudo find #{uploads_fullpath} -type f -exec chmod 0644 {} \\;",
"sudo find #{uploads_fullpath} -type d -not -path #{uploads_fullpath} -exec chmod 0700 {} \\;"
)
for_more_information(
see_installation_guide_section 'GitLab'
)
fix_and_rerun
end
private
def upload_path_tmp
File.join(uploads_fullpath, 'tmp')
end
def uploads_fullpath
File.realpath(Rails.root.join('public/uploads'))
end
end
end
end

View File

@ -2,16 +2,103 @@ module SystemCheck
# Base class for Checks. You must inherit from here
# and implement the methods below when necessary
class BaseCheck
include ::Gitlab::TaskHelpers
include Helpers
# Define a custom term for when check passed
#
# @param [String] term used when check passed (default: 'yes')
def self.set_check_pass(term)
@check_pass = term
end
# Define a custom term for when check failed
#
# @param [String] term used when check failed (default: 'no')
def self.set_check_fail(term)
@check_fail = term
end
# Define the name of the SystemCheck that will be displayed during execution
#
# @param [String] name of the check
def self.set_name(name)
@name = name
end
# Define the reason why we skipped the SystemCheck
#
# This is only used if subclass implements `#skip?`
#
# @param [String] reason to be displayed
def self.set_skip_reason(reason)
@skip_reason = reason
end
# Term to be displayed when check passed
#
# @return [String] term when check passed ('yes' if not re-defined in a subclass)
def self.check_pass
call_or_return(@check_pass) || 'yes'
end
## Term to be displayed when check failed
#
# @return [String] term when check failed ('no' if not re-defined in a subclass)
def self.check_fail
call_or_return(@check_fail) || 'no'
end
# Name of the SystemCheck defined by the subclass
#
# @return [String] the name
def self.display_name
call_or_return(@name) || self.name
end
# Skip reason defined by the subclass
#
# @return [String] the reason
def self.skip_reason
call_or_return(@skip_reason) || 'skipped'
end
# Does the check support automatically repair routine?
#
# @return [Boolean] whether check implemented `#repair!` method or not
def can_repair?
self.class.instance_methods(false).include?(:repair!)
end
def can_skip?
self.class.instance_methods(false).include?(:skip?)
end
def is_multi_check?
self.class.instance_methods(false).include?(:multi_check)
end
# Execute the check routine
#
# This is where you should implement the main logic that will return
# a boolean at the end
#
# You should not print any output to STDOUT here, use the specific methods instead
#
# @return [Boolean] whether the check passed or not
# @return [Boolean] whether check passed or failed
def check?
raise NotImplementedError
end
# Execute a custom check that cover multiple unities
#
# When using multi_check you have to provide the output yourself
def multi_check
raise NotImplementedError
end
# Prints troubleshooting instructions
#
# This is where you should print detailed information for any error found during #check?
#
# You may use helper methods to help format the output:
@ -23,50 +110,21 @@ module SystemCheck
raise NotImplementedError
end
# If skip returns true, than no other method on this check will be executed
# When implemented by a subclass, will attempt to fix the issue automatically
def repair!
raise NotImplementedError
end
# When implemented by a subclass, will evaluate whether check should be skipped or not
#
# @return [Boolean] whether or not this check should be skipped
def skip?
false
raise NotImplementedError
end
# If you enabled #skip? here is where you define a custom message explaining why
#
# Do not print anything to STDOUT, return a string.
#
# @return [String] message why this check was skipped
def skip_message
end
protected
# Display a formatted list of instructions on how to fix the issue identified by the #check?
#
# @param [Array<String>] steps one or short sentences with help how to fix the issue
def try_fixing_it(*steps)
steps = steps.shift if steps.first.is_a?(Array)
$stdout.puts ' Try fixing it:'.color(:blue)
steps.each do |step|
$stdout.puts " #{step}"
end
end
# Display a message telling to fix and rerun the checks
def fix_and_rerun
$stdout.puts ' Please fix the error above and rerun the checks.'.color(:red)
end
# Display a formatted list of references (documentation or links) where to find more information
#
# @param [Array<String>] sources one or more references (documentation or links)
def for_more_information(*sources)
sources = sources.shift if sources.first.is_a?(Array)
$stdout.puts ' For more information see:'.color(:blue)
sources.each do |source|
$stdout.puts ' #{source}'
end
def self.call_or_return(input)
input.respond_to?(:call) ? input.call : input
end
private_class_method :call_or_return
end
end

View File

@ -0,0 +1,80 @@
module SystemCheck
module Helpers
# Display a message telling to fix and rerun the checks
def fix_and_rerun
$stdout.puts ' Please fix the error above and rerun the checks.'.color(:red)
end
# Display a formatted list of references (documentation or links) where to find more information
#
# @param [Array<String>] sources one or more references (documentation or links)
def for_more_information(*sources)
sources = sources.shift if sources.first.is_a?(Array)
$stdout.puts ' For more information see:'.color(:blue)
sources.each do |source|
$stdout.puts " #{source}"
end
end
def see_installation_guide_section(section)
"doc/install/installation.md in section \"#{section}\""
end
# @deprecated This will no longer be used when all checks were executed using SystemCheck
def finished_checking(component)
$stdout.puts ''
$stdout.puts "Checking #{component.color(:yellow)} ... #{'Finished'.color(:green)}"
$stdout.puts ''
end
# @deprecated This will no longer be used when all checks were executed using SystemCheck
def start_checking(component)
$stdout.puts "Checking #{component.color(:yellow)} ..."
$stdout.puts ''
end
# Display a formatted list of instructions on how to fix the issue identified by the #check?
#
# @param [Array<String>] steps one or short sentences with help how to fix the issue
def try_fixing_it(*steps)
steps = steps.shift if steps.first.is_a?(Array)
$stdout.puts ' Try fixing it:'.color(:blue)
steps.each do |step|
$stdout.puts " #{step}"
end
end
def sanitized_message(project)
if should_sanitize?
"#{project.namespace_id.to_s.color(:yellow)}/#{project.id.to_s.color(:yellow)} ... "
else
"#{project.name_with_namespace.color(:yellow)} ... "
end
end
def should_sanitize?
if ENV['SANITIZE'] == 'true'
true
else
false
end
end
def omnibus_gitlab?
Dir.pwd == '/opt/gitlab/embedded/service/gitlab-rails'
end
def gitlab_user
Gitlab.config.gitlab.user
end
def sudo_gitlab(command)
"sudo -u #{gitlab_user} -H #{command}"
end
end
end

View File

@ -10,20 +10,51 @@ module SystemCheck
start_checking(component)
@checks.each do |check|
$stdout.print "#{check.name}"
if check.skip?
$stdout.puts "skipped #{'(' + skip_message + ')' if skip_message}".color(:magenta)
elsif check.check?
$stdout.puts 'yes'.color(:green)
else
$stdout.puts 'no'.color(:red)
check.show_error
end
run_check(check)
end
finished_checking(component)
end
# Executes a single check
#
# @param [SystemCheck::BaseCheck] check
def run_check(check)
$stdout.print "#{check.display_name} ... "
c = check.new
# When implements a multi check, we don't control the output
if c.is_multi_check?
c.multi_check
return
end
# When implements skip method, we run it first, and if true, skip the check
if c.can_skip? && c.skip?
$stdout.puts check.skip_reason.color(:magenta)
return
end
if c.check?
$stdout.puts check.check_pass.color(:green)
else
$stdout.puts check.check_fail.color(:red)
if c.can_repair?
$stdout.print 'Trying to fix error automatically. ...'
if c.repair!
$stdout.puts 'Success'.color(:green)
return
else
$stdout.puts 'Failed'.color(:red)
end
end
c.show_error
end
end
private
# Prints header content for the series of checks to be executed for this component

View File

@ -1,5 +1,9 @@
# Temporary hack, until we migrate all checks to SystemCheck format
require 'system_check'
require 'system_check/helpers'
namespace :gitlab do
desc "GitLab | Check the configuration of GitLab and its environment"
desc 'GitLab | Check the configuration of GitLab and its environment'
task check: %w{gitlab:gitlab_shell:check
gitlab:sidekiq:check
gitlab:incoming_email:check
@ -7,331 +11,38 @@ namespace :gitlab do
gitlab:app:check}
namespace :app do
desc "GitLab | Check the configuration of the GitLab Rails app"
desc 'GitLab | Check the configuration of the GitLab Rails app'
task check: :environment do
warn_user_is_not_gitlab
start_checking "GitLab"
check_git_config
check_database_config_exists
check_migrations_are_up
check_orphaned_group_members
check_gitlab_config_exists
check_gitlab_config_not_outdated
check_log_writable
check_tmp_writable
check_uploads
check_init_script_exists
check_init_script_up_to_date
check_projects_have_namespace
check_redis_version
check_ruby_version
check_git_version
checks = [
SystemCheck::App::GitConfigCheck,
SystemCheck::App::DatabaseConfigExistsCheck,
SystemCheck::App::MigrationsAreUpCheck,
SystemCheck::App::OrphanedGroupMembersCheck,
SystemCheck::App::GitlabConfigExistsCheck,
SystemCheck::App::GitlabConfigNotOutdatedCheck,
SystemCheck::App::LogWritableCheck,
SystemCheck::App::TmpWritableCheck,
SystemCheck::App::UploadsDirectoryExistsCheck,
SystemCheck::App::UploadsPathPermissionCheck,
SystemCheck::App::UploadsPathTmpPermissionCheck,
SystemCheck::App::InitScriptExistsCheck,
SystemCheck::App::InitScriptUpToDateCheck,
SystemCheck::App::ProjectsHaveNamespaceCheck,
SystemCheck::App::RedisVersionCheck,
SystemCheck::App::RubyVersionCheck,
SystemCheck::App::GitVersionCheck
]
SystemCheck.run('GitLab', checks)
check_active_users
finished_checking "GitLab"
end
# Checks
########################
def check_git_config
print "Git configured with autocrlf=input? ... "
options = {
"core.autocrlf" => "input"
}
correct_options = options.map do |name, value|
run_command(%W(#{Gitlab.config.git.bin_path} config --global --get #{name})).try(:squish) == value
end
if correct_options.all?
puts "yes".color(:green)
else
print "Trying to fix Git error automatically. ..."
if auto_fix_git_config(options)
puts "Success".color(:green)
else
puts "Failed".color(:red)
try_fixing_it(
sudo_gitlab("\"#{Gitlab.config.git.bin_path}\" config --global core.autocrlf \"#{options["core.autocrlf"]}\"")
)
for_more_information(
see_installation_guide_section "GitLab"
)
end
end
end
def check_database_config_exists
print "Database config exists? ... "
database_config_file = Rails.root.join("config", "database.yml")
if File.exist?(database_config_file)
puts "yes".color(:green)
else
puts "no".color(:red)
try_fixing_it(
"Copy config/database.yml.<your db> to config/database.yml",
"Check that the information in config/database.yml is correct"
)
for_more_information(
see_database_guide,
"http://guides.rubyonrails.org/getting_started.html#configuring-a-database"
)
fix_and_rerun
end
end
def check_gitlab_config_exists
print "GitLab config exists? ... "
gitlab_config_file = Rails.root.join("config", "gitlab.yml")
if File.exist?(gitlab_config_file)
puts "yes".color(:green)
else
puts "no".color(:red)
try_fixing_it(
"Copy config/gitlab.yml.example to config/gitlab.yml",
"Update config/gitlab.yml to match your setup"
)
for_more_information(
see_installation_guide_section "GitLab"
)
fix_and_rerun
end
end
def check_gitlab_config_not_outdated
print "GitLab config outdated? ... "
gitlab_config_file = Rails.root.join("config", "gitlab.yml")
unless File.exist?(gitlab_config_file)
puts "can't check because of previous errors".color(:magenta)
end
# omniauth or ldap could have been deleted from the file
unless Gitlab.config['git_host']
puts "no".color(:green)
else
puts "yes".color(:red)
try_fixing_it(
"Backup your config/gitlab.yml",
"Copy config/gitlab.yml.example to config/gitlab.yml",
"Update config/gitlab.yml to match your setup"
)
for_more_information(
see_installation_guide_section "GitLab"
)
fix_and_rerun
end
end
def check_init_script_exists
print "Init script exists? ... "
if omnibus_gitlab?
puts 'skipped (omnibus-gitlab has no init script)'.color(:magenta)
return
end
script_path = "/etc/init.d/gitlab"
if File.exist?(script_path)
puts "yes".color(:green)
else
puts "no".color(:red)
try_fixing_it(
"Install the init script"
)
for_more_information(
see_installation_guide_section "Install Init Script"
)
fix_and_rerun
end
end
def check_init_script_up_to_date
print "Init script up-to-date? ... "
if omnibus_gitlab?
puts 'skipped (omnibus-gitlab has no init script)'.color(:magenta)
return
end
recipe_path = Rails.root.join("lib/support/init.d/", "gitlab")
script_path = "/etc/init.d/gitlab"
unless File.exist?(script_path)
puts "can't check because of previous errors".color(:magenta)
return
end
recipe_content = File.read(recipe_path)
script_content = File.read(script_path)
if recipe_content == script_content
puts "yes".color(:green)
else
puts "no".color(:red)
try_fixing_it(
"Redownload the init script"
)
for_more_information(
see_installation_guide_section "Install Init Script"
)
fix_and_rerun
end
end
def check_migrations_are_up
print "All migrations up? ... "
migration_status, _ = Gitlab::Popen.popen(%w(bundle exec rake db:migrate:status))
unless migration_status =~ /down\s+\d{14}/
puts "yes".color(:green)
else
puts "no".color(:red)
try_fixing_it(
sudo_gitlab("bundle exec rake db:migrate RAILS_ENV=production")
)
fix_and_rerun
end
end
def check_orphaned_group_members
print "Database contains orphaned GroupMembers? ... "
if GroupMember.where("user_id not in (select id from users)").count > 0
puts "yes".color(:red)
try_fixing_it(
"You can delete the orphaned records using something along the lines of:",
sudo_gitlab("bundle exec rails runner -e production 'GroupMember.where(\"user_id NOT IN (SELECT id FROM users)\").delete_all'")
)
else
puts "no".color(:green)
end
end
def check_log_writable
print "Log directory writable? ... "
log_path = Rails.root.join("log")
if File.writable?(log_path)
puts "yes".color(:green)
else
puts "no".color(:red)
try_fixing_it(
"sudo chown -R gitlab #{log_path}",
"sudo chmod -R u+rwX #{log_path}"
)
for_more_information(
see_installation_guide_section "GitLab"
)
fix_and_rerun
end
end
def check_tmp_writable
print "Tmp directory writable? ... "
tmp_path = Rails.root.join("tmp")
if File.writable?(tmp_path)
puts "yes".color(:green)
else
puts "no".color(:red)
try_fixing_it(
"sudo chown -R gitlab #{tmp_path}",
"sudo chmod -R u+rwX #{tmp_path}"
)
for_more_information(
see_installation_guide_section "GitLab"
)
fix_and_rerun
end
end
def check_uploads
print "Uploads directory setup correctly? ... "
unless File.directory?(Rails.root.join('public/uploads'))
puts "no".color(:red)
try_fixing_it(
"sudo -u #{gitlab_user} mkdir #{Rails.root}/public/uploads"
)
for_more_information(
see_installation_guide_section "GitLab"
)
fix_and_rerun
return
end
upload_path = File.realpath(Rails.root.join('public/uploads'))
upload_path_tmp = File.join(upload_path, 'tmp')
if File.stat(upload_path).mode == 040700
unless Dir.exist?(upload_path_tmp)
puts 'skipped (no tmp uploads folder yet)'.color(:magenta)
return
end
# If tmp upload dir has incorrect permissions, assume others do as well
# Verify drwx------ permissions
if File.stat(upload_path_tmp).mode == 040700 && File.owned?(upload_path_tmp)
puts "yes".color(:green)
else
puts "no".color(:red)
try_fixing_it(
"sudo chown -R #{gitlab_user} #{upload_path}",
"sudo find #{upload_path} -type f -exec chmod 0644 {} \\;",
"sudo find #{upload_path} -type d -not -path #{upload_path} -exec chmod 0700 {} \\;"
)
for_more_information(
see_installation_guide_section "GitLab"
)
fix_and_rerun
end
else
puts "no".color(:red)
try_fixing_it(
"sudo chmod 700 #{upload_path}"
)
for_more_information(
see_installation_guide_section "GitLab"
)
fix_and_rerun
end
end
def check_redis_version
min_redis_version = "2.8.0"
print "Redis version >= #{min_redis_version}? ... "
redis_version = run_command(%w(redis-cli --version))
redis_version = redis_version.try(:match, /redis-cli (\d+\.\d+\.\d+)/)
if redis_version &&
(Gem::Version.new(redis_version[1]) > Gem::Version.new(min_redis_version))
puts "yes".color(:green)
else
puts "no".color(:red)
try_fixing_it(
"Update your redis server to a version >= #{min_redis_version}"
)
for_more_information(
"gitlab-public-wiki/wiki/Trouble-Shooting-Guide in section sidekiq"
)
fix_and_rerun
end
end
end
namespace :gitlab_shell do
include SystemCheck::Helpers
desc "GitLab | Check the configuration of GitLab Shell"
task check: :environment do
warn_user_is_not_gitlab
@ -513,33 +224,6 @@ namespace :gitlab do
end
end
def check_projects_have_namespace
print "projects have namespace: ... "
unless Project.count > 0
puts "can't check, you have no projects".color(:magenta)
return
end
puts ""
Project.find_each(batch_size: 100) do |project|
print sanitized_message(project)
if project.namespace
puts "yes".color(:green)
else
puts "no".color(:red)
try_fixing_it(
"Migrate global projects"
)
for_more_information(
"doc/update/5.4-to-6.0.md in section \"#global-projects\""
)
fix_and_rerun
end
end
end
# Helper methods
########################
@ -565,6 +249,8 @@ namespace :gitlab do
end
namespace :sidekiq do
include SystemCheck::Helpers
desc "GitLab | Check the configuration of Sidekiq"
task check: :environment do
warn_user_is_not_gitlab
@ -623,6 +309,8 @@ namespace :gitlab do
end
namespace :incoming_email do
include SystemCheck::Helpers
desc "GitLab | Check the configuration of Reply by email"
task check: :environment do
warn_user_is_not_gitlab
@ -757,6 +445,8 @@ namespace :gitlab do
end
namespace :ldap do
include SystemCheck::Helpers
task :check, [:limit] => :environment do |_, args|
# Only show up to 100 results because LDAP directories can be very big.
# This setting only affects the `rake gitlab:check` script.
@ -812,6 +502,8 @@ namespace :gitlab do
end
namespace :repo do
include SystemCheck::Helpers
desc "GitLab | Check the integrity of the repositories managed by GitLab"
task check: :environment do
Gitlab.config.repositories.storages.each do |name, repository_storage|
@ -826,6 +518,8 @@ namespace :gitlab do
end
namespace :user do
include SystemCheck::Helpers
desc "GitLab | Check the integrity of a specific user's repositories"
task :check_repos, [:username] => :environment do |t, args|
username = args[:username] || prompt("Check repository integrity for fsername? ".color(:blue))
@ -848,60 +542,6 @@ namespace :gitlab do
# Helper methods
##########################
# @deprecated Please use SystemChecks
def fix_and_rerun
puts " Please fix the error above and rerun the checks.".color(:red)
end
# @deprecated Please use SystemChecks
def for_more_information(*sources)
sources = sources.shift if sources.first.is_a?(Array)
puts " For more information see:".color(:blue)
sources.each do |source|
puts " #{source}"
end
end
# @deprecated Please use SystemChecks
def finished_checking(component)
puts ""
puts "Checking #{component.color(:yellow)} ... #{"Finished".color(:green)}"
puts ""
end
def see_database_guide
"doc/install/databases.md"
end
def see_installation_guide_section(section)
"doc/install/installation.md in section \"#{section}\""
end
def sudo_gitlab(command)
"sudo -u #{gitlab_user} -H #{command}"
end
def gitlab_user
Gitlab.config.gitlab.user
end
# @deprecated Please use SystemChecks
def start_checking(component)
puts "Checking #{component.color(:yellow)} ..."
puts ""
end
# @deprecated Please use SystemChecks
def try_fixing_it(*steps)
steps = steps.shift if steps.first.is_a?(Array)
puts " Try fixing it:".color(:blue)
steps.each do |step|
puts " #{step}"
end
end
def check_gitlab_shell
required_version = Gitlab::VersionInfo.new(gitlab_shell_major_version, gitlab_shell_minor_version, gitlab_shell_patch_version)
current_version = Gitlab::VersionInfo.parse(gitlab_shell_version)
@ -914,65 +554,10 @@ namespace :gitlab do
end
end
def check_ruby_version
required_version = Gitlab::VersionInfo.new(2, 1, 0)
current_version = Gitlab::VersionInfo.parse(run_command(%w(ruby --version)))
print "Ruby version >= #{required_version} ? ... "
if current_version.valid? && required_version <= current_version
puts "yes (#{current_version})".color(:green)
else
puts "no".color(:red)
try_fixing_it(
"Update your ruby to a version >= #{required_version} from #{current_version}"
)
fix_and_rerun
end
end
def check_git_version
required_version = Gitlab::VersionInfo.new(2, 7, 3)
current_version = Gitlab::VersionInfo.parse(run_command(%W(#{Gitlab.config.git.bin_path} --version)))
puts "Your git bin path is \"#{Gitlab.config.git.bin_path}\""
print "Git version >= #{required_version} ? ... "
if current_version.valid? && required_version <= current_version
puts "yes (#{current_version})".color(:green)
else
puts "no".color(:red)
try_fixing_it(
"Update your git to a version >= #{required_version} from #{current_version}"
)
fix_and_rerun
end
end
def check_active_users
puts "Active users: #{User.active.count}"
end
def omnibus_gitlab?
Dir.pwd == '/opt/gitlab/embedded/service/gitlab-rails'
end
def sanitized_message(project)
if should_sanitize?
"#{project.namespace_id.to_s.color(:yellow)}/#{project.id.to_s.color(:yellow)} ... "
else
"#{project.name_with_namespace.color(:yellow)} ... "
end
end
def should_sanitize?
if ENV['SANITIZE'] == "true"
true
else
false
end
end
def check_repo_integrity(repo_dir)
puts "\nChecking repo at #{repo_dir.color(:yellow)}"

View File

@ -113,6 +113,7 @@ module Gitlab
end
end
# TODO: MIGRATED
# Tries to configure git itself
#
# Returns true if all subcommands were successfull (according to their exit code)