summaryrefslogtreecommitdiff
path: root/lib/backup
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-03-18 20:02:30 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-03-18 20:02:30 +0000
commit41fe97390ceddf945f3d967b8fdb3de4c66b7dea (patch)
tree9c8d89a8624828992f06d892cd2f43818ff5dcc8 /lib/backup
parent0804d2dc31052fb45a1efecedc8e06ce9bc32862 (diff)
downloadgitlab-ce-41fe97390ceddf945f3d967b8fdb3de4c66b7dea.tar.gz
Add latest changes from gitlab-org/gitlab@14-9-stable-eev14.9.0-rc42
Diffstat (limited to 'lib/backup')
-rw-r--r--lib/backup/artifacts.rb7
-rw-r--r--lib/backup/builds.rb7
-rw-r--r--lib/backup/database.rb77
-rw-r--r--lib/backup/files.rb27
-rw-r--r--lib/backup/gitaly_backup.rb18
-rw-r--r--lib/backup/gitaly_rpc_backup.rb9
-rw-r--r--lib/backup/lfs.rb7
-rw-r--r--lib/backup/manager.rb257
-rw-r--r--lib/backup/packages.rb7
-rw-r--r--lib/backup/pages.rb7
-rw-r--r--lib/backup/registry.rb8
-rw-r--r--lib/backup/repositories.rb24
-rw-r--r--lib/backup/task.rb46
-rw-r--r--lib/backup/terraform_state.rb7
-rw-r--r--lib/backup/uploads.rb7
15 files changed, 302 insertions, 213 deletions
diff --git a/lib/backup/artifacts.rb b/lib/backup/artifacts.rb
index 163446998e9..4ef76b0aaf3 100644
--- a/lib/backup/artifacts.rb
+++ b/lib/backup/artifacts.rb
@@ -2,14 +2,11 @@
module Backup
class Artifacts < Backup::Files
- attr_reader :progress
-
def initialize(progress)
- @progress = progress
-
- super('artifacts', JobArtifactUploader.root, excludes: ['tmp'])
+ super(progress, 'artifacts', JobArtifactUploader.root, excludes: ['tmp'])
end
+ override :human_name
def human_name
_('artifacts')
end
diff --git a/lib/backup/builds.rb b/lib/backup/builds.rb
index 51a68ca933d..fbf932e3f6b 100644
--- a/lib/backup/builds.rb
+++ b/lib/backup/builds.rb
@@ -2,14 +2,11 @@
module Backup
class Builds < Backup::Files
- attr_reader :progress
-
def initialize(progress)
- @progress = progress
-
- super('builds', Settings.gitlab_ci.builds_path)
+ super(progress, 'builds', Settings.gitlab_ci.builds_path)
end
+ override :human_name
def human_name
_('builds')
end
diff --git a/lib/backup/database.rb b/lib/backup/database.rb
index de26dbab038..afc84a4b913 100644
--- a/lib/backup/database.rb
+++ b/lib/backup/database.rb
@@ -3,10 +3,10 @@
require 'yaml'
module Backup
- class Database
+ class Database < Task
+ extend ::Gitlab::Utils::Override
include Backup::Helper
- attr_reader :progress
- attr_reader :config, :db_file_name
+ attr_reader :force, :config
IGNORED_ERRORS = [
# Ignore warnings
@@ -18,13 +18,14 @@ module Backup
].freeze
IGNORED_ERRORS_REGEXP = Regexp.union(IGNORED_ERRORS).freeze
- def initialize(progress, filename: nil)
- @progress = progress
+ def initialize(progress, force:)
+ super(progress)
@config = ActiveRecord::Base.configurations.find_db_config(Rails.env).configuration_hash
- @db_file_name = filename || File.join(Gitlab.config.backup.path, 'db', 'database.sql.gz')
+ @force = force
end
- def dump
+ override :dump
+ def dump(db_file_name)
FileUtils.mkdir_p(File.dirname(db_file_name))
FileUtils.rm_f(db_file_name)
compress_rd, compress_wr = IO.pipe
@@ -64,12 +65,24 @@ module Backup
raise DatabaseBackupError.new(config, db_file_name) unless success
end
- def restore
+ override :restore
+ def restore(db_file_name)
+ unless force
+ progress.puts 'Removing all tables. Press `Ctrl-C` within 5 seconds to abort'.color(:yellow)
+ sleep(5)
+ end
+
+ # Drop all tables Load the schema to ensure we don't have any newer tables
+ # hanging out from a failed upgrade
+ puts_time 'Cleaning the database ... '.color(:blue)
+ Rake::Task['gitlab:db:drop_tables'].invoke
+ puts_time 'done'.color(:green)
+
decompress_rd, decompress_wr = IO.pipe
decompress_pid = spawn(*%w(gzip -cd), out: decompress_wr, in: db_file_name)
decompress_wr.close
- status, errors =
+ status, @errors =
case config[:adapter]
when "postgresql" then
progress.print "Restoring PostgreSQL database #{database} ... "
@@ -81,33 +94,47 @@ module Backup
Process.waitpid(decompress_pid)
success = $?.success? && status.success?
- if errors.present?
+ if @errors.present?
progress.print "------ BEGIN ERRORS -----\n".color(:yellow)
- progress.print errors.join.color(:yellow)
+ progress.print @errors.join.color(:yellow)
progress.print "------ END ERRORS -------\n".color(:yellow)
end
report_success(success)
raise Backup::Error, 'Restore failed' unless success
+ end
- if errors.present?
- warning = <<~MSG
- There were errors in restoring the schema. This may cause
- issues if this results in missing indexes, constraints, or
- columns. Please record the errors above and contact GitLab
- Support if you have questions:
- https://about.gitlab.com/support/
- MSG
-
- warn warning.color(:red)
- Gitlab::TaskHelpers.ask_to_continue
- end
+ override :pre_restore_warning
+ def pre_restore_warning
+ return if force
+
+ <<-MSG.strip_heredoc
+ Be sure to stop Puma, Sidekiq, and any other process that
+ connects to the database before proceeding. For Omnibus
+ installs, see the following link for more information:
+ https://docs.gitlab.com/ee/raketasks/backup_restore.html#restore-for-omnibus-gitlab-installations
+
+ Before restoring the database, we will remove all existing
+ tables to avoid future upgrade problems. Be aware that if you have
+ custom tables in the GitLab database these tables and all data will be
+ removed.
+ MSG
end
- def enabled
- true
+ override :post_restore_warning
+ def post_restore_warning
+ return unless @errors.present?
+
+ <<-MSG.strip_heredoc
+ There were errors in restoring the schema. This may cause
+ issues if this results in missing indexes, constraints, or
+ columns. Please record the errors above and contact GitLab
+ Support if you have questions:
+ https://about.gitlab.com/support/
+ MSG
end
+ override :human_name
def human_name
_('database')
end
diff --git a/lib/backup/files.rb b/lib/backup/files.rb
index db6278360a3..7fa07e40cee 100644
--- a/lib/backup/files.rb
+++ b/lib/backup/files.rb
@@ -1,25 +1,27 @@
# frozen_string_literal: true
require 'open3'
-require_relative 'helper'
module Backup
- class Files
+ class Files < Task
+ extend ::Gitlab::Utils::Override
include Backup::Helper
DEFAULT_EXCLUDE = 'lost+found'
- attr_reader :name, :backup_tarball, :excludes
+ attr_reader :name, :excludes
+
+ def initialize(progress, name, app_files_dir, excludes: [])
+ super(progress)
- def initialize(name, app_files_dir, excludes: [])
@name = name
@app_files_dir = app_files_dir
- @backup_tarball = File.join(Gitlab.config.backup.path, name + '.tar.gz')
@excludes = [DEFAULT_EXCLUDE].concat(excludes)
end
# Copy files from public/files to backup/files
- def dump
+ override :dump
+ def dump(backup_tarball)
FileUtils.mkdir_p(Gitlab.config.backup.path)
FileUtils.rm_f(backup_tarball)
@@ -35,7 +37,7 @@ module Backup
unless status == 0
puts output
- raise_custom_error
+ raise_custom_error(backup_tarball)
end
tar_cmd = [tar, exclude_dirs(:tar), %W[-C #{backup_files_realpath} -cf - .]].flatten
@@ -47,11 +49,12 @@ module Backup
end
unless pipeline_succeeded?(tar_status: status_list[0], gzip_status: status_list[1], output: output)
- raise_custom_error
+ raise_custom_error(backup_tarball)
end
end
- def restore
+ override :restore
+ def restore(backup_tarball)
backup_existing_files_dir
cmd_list = [%w[gzip -cd], %W[#{tar} --unlink-first --recursive-unlink -C #{app_files_realpath} -xf -]]
@@ -61,10 +64,6 @@ module Backup
end
end
- def enabled
- true
- end
-
def tar
if system(*%w[gtar --version], out: '/dev/null')
# It looks like we can get GNU tar by running 'gtar'
@@ -146,7 +145,7 @@ module Backup
end
end
- def raise_custom_error
+ def raise_custom_error(backup_tarball)
raise FileBackupError.new(app_files_realpath, backup_tarball)
end
diff --git a/lib/backup/gitaly_backup.rb b/lib/backup/gitaly_backup.rb
index 8ac09e94004..b688ff7f13b 100644
--- a/lib/backup/gitaly_backup.rb
+++ b/lib/backup/gitaly_backup.rb
@@ -9,13 +9,16 @@ module Backup
# @param [StringIO] progress IO interface to output progress
# @param [Integer] max_parallelism max parallelism when running backups
# @param [Integer] storage_parallelism max parallelism per storage (is affected by max_parallelism)
- def initialize(progress, max_parallelism: nil, storage_parallelism: nil)
+ # @param [String] backup_id unique identifier for the backup
+ def initialize(progress, max_parallelism: nil, storage_parallelism: nil, incremental: false, backup_id: nil)
@progress = progress
@max_parallelism = max_parallelism
@storage_parallelism = storage_parallelism
+ @incremental = incremental
+ @backup_id = backup_id
end
- def start(type)
+ def start(type, backup_repos_path)
raise Error, 'already started' if started?
command = case type
@@ -30,6 +33,13 @@ module Backup
args = []
args += ['-parallel', @max_parallelism.to_s] if @max_parallelism
args += ['-parallel-storage', @storage_parallelism.to_s] if @storage_parallelism
+ if Feature.enabled?(:incremental_repository_backup, default_enabled: :yaml)
+ args += ['-layout', 'pointer']
+ if type == :create
+ args += ['-incremental'] if @incremental
+ args += ['-id', @backup_id] if @backup_id
+ end
+ end
@input_stream, stdout, @thread = Open3.popen2(build_env, bin_path, command, '-path', backup_repos_path, *args)
@@ -93,10 +103,6 @@ module Backup
@thread.present?
end
- def backup_repos_path
- File.absolute_path(File.join(Gitlab.config.backup.path, 'repositories'))
- end
-
def bin_path
File.absolute_path(Gitlab.config.backup.gitaly_backup_path)
end
diff --git a/lib/backup/gitaly_rpc_backup.rb b/lib/backup/gitaly_rpc_backup.rb
index bbd83cd2157..89ed27cfa13 100644
--- a/lib/backup/gitaly_rpc_backup.rb
+++ b/lib/backup/gitaly_rpc_backup.rb
@@ -7,10 +7,11 @@ module Backup
@progress = progress
end
- def start(type)
+ def start(type, backup_repos_path)
raise Error, 'already started' if @type
@type = type
+ @backup_repos_path = backup_repos_path
case type
when :create
FileUtils.rm_rf(backup_repos_path)
@@ -31,7 +32,7 @@ module Backup
backup_restore = BackupRestore.new(
progress,
repository_type.repository_for(container),
- backup_repos_path
+ @backup_repos_path
)
case @type
@@ -52,10 +53,6 @@ module Backup
attr_reader :progress
- def backup_repos_path
- @backup_repos_path ||= File.join(Gitlab.config.backup.path, 'repositories')
- end
-
class BackupRestore
attr_accessor :progress, :repository, :backup_repos_path
diff --git a/lib/backup/lfs.rb b/lib/backup/lfs.rb
index 17f7b8bf8b0..e92f235a2d7 100644
--- a/lib/backup/lfs.rb
+++ b/lib/backup/lfs.rb
@@ -2,14 +2,11 @@
module Backup
class Lfs < Backup::Files
- attr_reader :progress
-
def initialize(progress)
- @progress = progress
-
- super('lfs', Settings.lfs.storage_path)
+ super(progress, 'lfs', Settings.lfs.storage_path)
end
+ override :human_name
def human_name
_('lfs objects')
end
diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb
index 5b393cf9477..6e90824fce2 100644
--- a/lib/backup/manager.rb
+++ b/lib/backup/manager.rb
@@ -2,43 +2,84 @@
module Backup
class Manager
- ARCHIVES_TO_BACKUP = %w[uploads builds artifacts pages lfs terraform_state registry packages].freeze
- FOLDERS_TO_BACKUP = %w[repositories db].freeze
FILE_NAME_SUFFIX = '_gitlab_backup.tar'
+ MANIFEST_NAME = 'backup_information.yml'
+
+ TaskDefinition = Struct.new(
+ :destination_path, # Where the task should put its backup file/dir.
+ :destination_optional, # `true` if the destination might not exist on a successful backup.
+ :cleanup_path, # Path to remove after a successful backup. Uses `destination_path` when not specified.
+ :task,
+ keyword_init: true
+ )
attr_reader :progress
- def initialize(progress)
+ def initialize(progress, definitions: nil)
@progress = progress
max_concurrency = ENV.fetch('GITLAB_BACKUP_MAX_CONCURRENCY', 1).to_i
max_storage_concurrency = ENV.fetch('GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY', 1).to_i
-
- @tasks = {
- 'db' => Database.new(progress),
- 'repositories' => Repositories.new(progress,
- strategy: repository_backup_strategy,
- max_concurrency: max_concurrency,
- max_storage_concurrency: max_storage_concurrency),
- 'uploads' => Uploads.new(progress),
- 'builds' => Builds.new(progress),
- 'artifacts' => Artifacts.new(progress),
- 'pages' => Pages.new(progress),
- 'lfs' => Lfs.new(progress),
- 'terraform_state' => TerraformState.new(progress),
- 'registry' => Registry.new(progress),
- 'packages' => Packages.new(progress)
+ force = ENV['force'] == 'yes'
+ incremental = Gitlab::Utils.to_boolean(ENV['INCREMENTAL'], default: false)
+
+ @definitions = definitions || {
+ 'db' => TaskDefinition.new(
+ destination_path: 'db/database.sql.gz',
+ cleanup_path: 'db',
+ task: Database.new(progress, force: force)
+ ),
+ 'repositories' => TaskDefinition.new(
+ destination_path: 'repositories',
+ destination_optional: true,
+ task: Repositories.new(progress,
+ strategy: repository_backup_strategy(incremental),
+ max_concurrency: max_concurrency,
+ max_storage_concurrency: max_storage_concurrency)
+ ),
+ 'uploads' => TaskDefinition.new(
+ destination_path: 'uploads.tar.gz',
+ task: Uploads.new(progress)
+ ),
+ 'builds' => TaskDefinition.new(
+ destination_path: 'builds.tar.gz',
+ task: Builds.new(progress)
+ ),
+ 'artifacts' => TaskDefinition.new(
+ destination_path: 'artifacts.tar.gz',
+ task: Artifacts.new(progress)
+ ),
+ 'pages' => TaskDefinition.new(
+ destination_path: 'pages.tar.gz',
+ task: Pages.new(progress)
+ ),
+ 'lfs' => TaskDefinition.new(
+ destination_path: 'lfs.tar.gz',
+ task: Lfs.new(progress)
+ ),
+ 'terraform_state' => TaskDefinition.new(
+ destination_path: 'terraform_state.tar.gz',
+ task: TerraformState.new(progress)
+ ),
+ 'registry' => TaskDefinition.new(
+ destination_path: 'registry.tar.gz',
+ task: Registry.new(progress)
+ ),
+ 'packages' => TaskDefinition.new(
+ destination_path: 'packages.tar.gz',
+ task: Packages.new(progress)
+ )
}.freeze
end
def create
- @tasks.keys.each do |task_name|
+ @definitions.keys.each do |task_name|
run_create_task(task_name)
end
- write_info
+ write_backup_information
- if ENV['SKIP'] && ENV['SKIP'].include?('tar')
+ if skipped?('tar')
upload
else
pack
@@ -54,21 +95,23 @@ module Backup
end
def run_create_task(task_name)
- task = @tasks[task_name]
+ definition = @definitions[task_name]
- puts_time "Dumping #{task.human_name} ... ".color(:blue)
+ build_backup_information
+ puts_time "Dumping #{definition.task.human_name} ... ".color(:blue)
- unless task.enabled
+ unless definition.task.enabled
puts_time "[DISABLED]".color(:cyan)
return
end
- if ENV["SKIP"] && ENV["SKIP"].include?(task_name)
+ if skipped?(task_name)
puts_time "[SKIPPED]".color(:cyan)
return
end
- task.dump
+ definition.task.dump(File.join(Gitlab.config.backup.path, definition.destination_path))
+
puts_time "done".color(:green)
rescue Backup::DatabaseBackupError, Backup::FileBackupError => e
@@ -77,42 +120,11 @@ module Backup
def restore
cleanup_required = unpack
+ read_backup_information
verify_backup_version
- unless skipped?('db')
- begin
- unless ENV['force'] == 'yes'
- warning = <<-MSG.strip_heredoc
- Be sure to stop Puma, Sidekiq, and any other process that
- connects to the database before proceeding. For Omnibus
- installs, see the following link for more information:
- https://docs.gitlab.com/ee/raketasks/backup_restore.html#restore-for-omnibus-gitlab-installations
-
- Before restoring the database, we will remove all existing
- tables to avoid future upgrade problems. Be aware that if you have
- custom tables in the GitLab database these tables and all data will be
- removed.
- MSG
- puts warning.color(:red)
- Gitlab::TaskHelpers.ask_to_continue
- puts 'Removing all tables. Press `Ctrl-C` within 5 seconds to abort'.color(:yellow)
- sleep(5)
- end
-
- # Drop all tables Load the schema to ensure we don't have any newer tables
- # hanging out from a failed upgrade
- puts_time 'Cleaning the database ... '.color(:blue)
- Rake::Task['gitlab:db:drop_tables'].invoke
- puts_time 'done'.color(:green)
- run_restore_task('db')
- rescue Gitlab::TaskAbortedByUserError
- puts "Quitting...".color(:red)
- exit 1
- end
- end
-
- @tasks.except('db').keys.each do |task_name|
- run_restore_task(task_name) unless skipped?(task_name)
+ @definitions.keys.each do |task_name|
+ run_restore_task(task_name) if !skipped?(task_name) && enabled_task?(task_name)
end
Rake::Task['gitlab:shell:setup'].invoke
@@ -130,30 +142,71 @@ module Backup
end
def run_restore_task(task_name)
- task = @tasks[task_name]
+ definition = @definitions[task_name]
- puts_time "Restoring #{task.human_name} ... ".color(:blue)
+ read_backup_information
+ puts_time "Restoring #{definition.task.human_name} ... ".color(:blue)
- unless task.enabled
+ unless definition.task.enabled
puts_time "[DISABLED]".color(:cyan)
return
end
- task.restore
+ warning = definition.task.pre_restore_warning
+ if warning.present?
+ puts_time warning.color(:red)
+ Gitlab::TaskHelpers.ask_to_continue
+ end
+
+ definition.task.restore(File.join(Gitlab.config.backup.path, definition.destination_path))
+
puts_time "done".color(:green)
+
+ warning = definition.task.post_restore_warning
+ if warning.present?
+ puts_time warning.color(:red)
+ Gitlab::TaskHelpers.ask_to_continue
+ end
+
+ rescue Gitlab::TaskAbortedByUserError
+ puts_time "Quitting...".color(:red)
+ exit 1
end
- def write_info
+ private
+
+ def read_backup_information
+ @backup_information ||= YAML.load_file(File.join(backup_path, MANIFEST_NAME))
+ end
+
+ def write_backup_information
# Make sure there is a connection
ActiveRecord::Base.connection.reconnect!
Dir.chdir(backup_path) do
- File.open("#{backup_path}/backup_information.yml", "w+") do |file|
+ File.open("#{backup_path}/#{MANIFEST_NAME}", "w+") do |file|
file << backup_information.to_yaml.gsub(/^---\n/, '')
end
end
end
+ def build_backup_information
+ @backup_information ||= {
+ db_version: ActiveRecord::Migrator.current_version.to_s,
+ backup_created_at: Time.now,
+ gitlab_version: Gitlab::VERSION,
+ tar_version: tar_version,
+ installation_type: Gitlab::INSTALLATION_TYPE,
+ skipped: ENV["SKIP"]
+ }
+ end
+
+ def backup_information
+ raise Backup::Error, "#{MANIFEST_NAME} not yet loaded" unless @backup_information
+
+ @backup_information
+ end
+
def pack
Dir.chdir(backup_path) do
# create archive
@@ -182,8 +235,11 @@ module Backup
upload = directory.files.create(create_attributes)
if upload
- progress.puts "done".color(:green)
- upload
+ if upload.respond_to?(:encryption) && upload.encryption
+ progress.puts "done (encrypted with #{upload.encryption})".color(:green)
+ else
+ progress.puts "done".color(:green)
+ end
else
puts "uploading backup to #{remote_directory} failed".color(:red)
raise Backup::Error, 'Backup failed'
@@ -193,18 +249,19 @@ module Backup
def cleanup
progress.print "Deleting tmp directories ... "
- backup_contents.each do |dir|
- next unless File.exist?(File.join(backup_path, dir))
-
- if FileUtils.rm_rf(File.join(backup_path, dir))
- progress.puts "done".color(:green)
- else
- puts "deleting tmp directory '#{dir}' failed".color(:red)
- raise Backup::Error, 'Backup failed'
- end
+ remove_backup_path(MANIFEST_NAME)
+ @definitions.each do |_, definition|
+ remove_backup_path(definition.cleanup_path || definition.destination_path)
end
end
+ def remove_backup_path(path)
+ return unless File.exist?(File.join(backup_path, path))
+
+ FileUtils.rm_rf(File.join(backup_path, path))
+ progress.puts "done".color(:green)
+ end
+
def remove_tmp
# delete tmp inside backups
progress.print "Deleting backups/tmp ... "
@@ -255,15 +312,15 @@ module Backup
def verify_backup_version
Dir.chdir(backup_path) do
# restoring mismatching backups can lead to unexpected problems
- if settings[:gitlab_version] != Gitlab::VERSION
+ if backup_information[:gitlab_version] != Gitlab::VERSION
progress.puts(<<~HEREDOC.color(:red))
GitLab version mismatch:
Your current GitLab version (#{Gitlab::VERSION}) differs from the GitLab version in the backup!
Please switch to the following version and try again:
- version: #{settings[:gitlab_version]}
+ version: #{backup_information[:gitlab_version]}
HEREDOC
progress.puts
- progress.puts "Hint: git checkout v#{settings[:gitlab_version]}"
+ progress.puts "Hint: git checkout v#{backup_information[:gitlab_version]}"
exit 1
end
end
@@ -319,13 +376,11 @@ module Backup
end
def skipped?(item)
- settings[:skipped] && settings[:skipped].include?(item) || !enabled_task?(item)
+ backup_information[:skipped] && backup_information[:skipped].include?(item)
end
- private
-
def enabled_task?(task_name)
- @tasks[task_name].enabled
+ @definitions[task_name].task.enabled
end
def backup_file?(file)
@@ -333,7 +388,7 @@ module Backup
end
def non_tarred_backup?
- File.exist?(File.join(backup_path, 'backup_information.yml'))
+ File.exist?(File.join(backup_path, MANIFEST_NAME))
end
def backup_path
@@ -380,19 +435,10 @@ module Backup
end
def backup_contents
- folders_to_backup + archives_to_backup + ["backup_information.yml"]
- end
-
- def archives_to_backup
- ARCHIVES_TO_BACKUP.map { |name| (name + ".tar.gz") unless skipped?(name) }.compact
- end
-
- def folders_to_backup
- FOLDERS_TO_BACKUP.select { |name| !skipped?(name) && Dir.exist?(File.join(backup_path, name)) }
- end
-
- def settings
- @settings ||= YAML.load_file("backup_information.yml")
+ [MANIFEST_NAME] + @definitions.reject do |name, definition|
+ skipped?(name) || !enabled_task?(name) ||
+ (definition.destination_optional && !File.exist?(File.join(backup_path, definition.destination_path)))
+ end.values.map(&:destination_path)
end
def tar_file
@@ -403,17 +449,6 @@ module Backup
end
end
- def backup_information
- @backup_information ||= {
- db_version: ActiveRecord::Migrator.current_version.to_s,
- backup_created_at: Time.now,
- gitlab_version: Gitlab::VERSION,
- tar_version: tar_version,
- installation_type: Gitlab::INSTALLATION_TYPE,
- skipped: ENV["SKIP"]
- }
- end
-
def create_attributes
attrs = {
key: remote_target,
@@ -447,11 +482,11 @@ module Backup
Gitlab.config.backup.upload.connection&.provider&.downcase == 'google'
end
- def repository_backup_strategy
+ def repository_backup_strategy(incremental)
if Feature.enabled?(:gitaly_backup, default_enabled: :yaml)
max_concurrency = ENV['GITLAB_BACKUP_MAX_CONCURRENCY'].presence
max_storage_concurrency = ENV['GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY'].presence
- Backup::GitalyBackup.new(progress, max_parallelism: max_concurrency, storage_parallelism: max_storage_concurrency)
+ Backup::GitalyBackup.new(progress, incremental: incremental, max_parallelism: max_concurrency, storage_parallelism: max_storage_concurrency)
else
Backup::GitalyRpcBackup.new(progress)
end
diff --git a/lib/backup/packages.rb b/lib/backup/packages.rb
index 037ff31fd9b..9384e007162 100644
--- a/lib/backup/packages.rb
+++ b/lib/backup/packages.rb
@@ -2,14 +2,11 @@
module Backup
class Packages < Backup::Files
- attr_reader :progress
-
def initialize(progress)
- @progress = progress
-
- super('packages', Settings.packages.storage_path, excludes: ['tmp'])
+ super(progress, 'packages', Settings.packages.storage_path, excludes: ['tmp'])
end
+ override :human_name
def human_name
_('packages')
end
diff --git a/lib/backup/pages.rb b/lib/backup/pages.rb
index 724972d212d..ebed6820724 100644
--- a/lib/backup/pages.rb
+++ b/lib/backup/pages.rb
@@ -6,14 +6,11 @@ module Backup
# if some of these files are still there, we don't need them in the backup
LEGACY_PAGES_TMP_PATH = '@pages.tmp'
- attr_reader :progress
-
def initialize(progress)
- @progress = progress
-
- super('pages', Gitlab.config.pages.path, excludes: [LEGACY_PAGES_TMP_PATH])
+ super(progress, 'pages', Gitlab.config.pages.path, excludes: [LEGACY_PAGES_TMP_PATH])
end
+ override :human_name
def human_name
_('pages')
end
diff --git a/lib/backup/registry.rb b/lib/backup/registry.rb
index 7ba3a9e9c60..68ea635034d 100644
--- a/lib/backup/registry.rb
+++ b/lib/backup/registry.rb
@@ -2,18 +2,16 @@
module Backup
class Registry < Backup::Files
- attr_reader :progress
-
def initialize(progress)
- @progress = progress
-
- super('registry', Settings.registry.path)
+ super(progress, 'registry', Settings.registry.path)
end
+ override :human_name
def human_name
_('container registry images')
end
+ override :enabled
def enabled
Gitlab.config.registry.enabled
end
diff --git a/lib/backup/repositories.rb b/lib/backup/repositories.rb
index e7c3e869928..3633ebd661e 100644
--- a/lib/backup/repositories.rb
+++ b/lib/backup/repositories.rb
@@ -3,16 +3,20 @@
require 'yaml'
module Backup
- class Repositories
+ class Repositories < Task
+ extend ::Gitlab::Utils::Override
+
def initialize(progress, strategy:, max_concurrency: 1, max_storage_concurrency: 1)
- @progress = progress
+ super(progress)
+
@strategy = strategy
@max_concurrency = max_concurrency
@max_storage_concurrency = max_storage_concurrency
end
- def dump
- strategy.start(:create)
+ override :dump
+ def dump(path)
+ strategy.start(:create, path)
# gitaly-backup is designed to handle concurrency on its own. So we want
# to avoid entering the buggy concurrency code here when gitaly-backup
@@ -50,8 +54,9 @@ module Backup
strategy.finish!
end
- def restore
- strategy.start(:restore)
+ override :restore
+ def restore(path)
+ strategy.start(:restore, path)
enqueue_consecutive
ensure
@@ -61,17 +66,14 @@ module Backup
restore_object_pools
end
- def enabled
- true
- end
-
+ override :human_name
def human_name
_('repositories')
end
private
- attr_reader :progress, :strategy, :max_concurrency, :max_storage_concurrency
+ attr_reader :strategy, :max_concurrency, :max_storage_concurrency
def check_valid_storages!
repository_storage_klasses.each do |klass|
diff --git a/lib/backup/task.rb b/lib/backup/task.rb
new file mode 100644
index 00000000000..15cd2aa64d3
--- /dev/null
+++ b/lib/backup/task.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Backup
+ class Task
+ def initialize(progress)
+ @progress = progress
+ end
+
+ # human readable task name used for logging
+ def human_name
+ raise NotImplementedError
+ end
+
+ # dump task backup to `path`
+ def dump(path)
+ raise NotImplementedError
+ end
+
+ # restore task backup from `path`
+ def restore(path)
+ raise NotImplementedError
+ end
+
+ # a string returned here will be displayed to the user before calling #restore
+ def pre_restore_warning
+ end
+
+ # a string returned here will be displayed to the user after calling #restore
+ def post_restore_warning
+ end
+
+ # returns `true` when the task should be used
+ def enabled
+ true
+ end
+
+ private
+
+ attr_reader :progress
+
+ def puts_time(msg)
+ progress.puts "#{Time.zone.now} -- #{msg}"
+ Gitlab::BackupLogger.info(message: "#{Rainbow.uncolor(msg)}")
+ end
+ end
+end
diff --git a/lib/backup/terraform_state.rb b/lib/backup/terraform_state.rb
index be82793fe03..05f61d248be 100644
--- a/lib/backup/terraform_state.rb
+++ b/lib/backup/terraform_state.rb
@@ -2,14 +2,11 @@
module Backup
class TerraformState < Backup::Files
- attr_reader :progress
-
def initialize(progress)
- @progress = progress
-
- super('terraform_state', Settings.terraform_state.storage_path, excludes: ['tmp'])
+ super(progress, 'terraform_state', Settings.terraform_state.storage_path, excludes: ['tmp'])
end
+ override :human_name
def human_name
_('terraform states')
end
diff --git a/lib/backup/uploads.rb b/lib/backup/uploads.rb
index 7048a9a8ff5..700f2af4415 100644
--- a/lib/backup/uploads.rb
+++ b/lib/backup/uploads.rb
@@ -2,14 +2,11 @@
module Backup
class Uploads < Backup::Files
- attr_reader :progress
-
def initialize(progress)
- @progress = progress
-
- super('uploads', File.join(Gitlab.config.uploads.storage_path, "uploads"), excludes: ['tmp'])
+ super(progress, 'uploads', File.join(Gitlab.config.uploads.storage_path, "uploads"), excludes: ['tmp'])
end
+ override :human_name
def human_name
_('uploads')
end