Commit 58a8d4f8 authored by Harsh Chouraria's avatar Harsh Chouraria Committed by Michael Kozono

Add Backup and Restore tasks for Terraform States

Reuses standard file upload storage to cover Terraform
states backup

Adds a seed for generating terraform state files
under each project

Manual testing (in local GDK env):

- Verfied seed addition via `bin/rake db:seed_fu FILTER=terraform`
- Verified seed addition is repeatable, with no-ops if versions
  pre-exist
- Created backup: `bin/rake gitlab:backup:create`
- Verified output shows up:

```
2021-06-05 23:48:54 +0530 -- Dumping terraform states ...
2021-06-05 23:48:54 +0530 -- done
```

- Verified tar contains terraform_state.tar.gz
- Verified terraform_state.tar.gz carries content
- Destroyed all records: `Terraform::State.destroy_all`
- Deleted all files: `rm -rf shared/terraform_state/*`
- Performed restore: `bin/rake gitlab:backup:restore`
- Verified `Terraform::State.all` shows back older records
- Verified association of builds to some of these records
- Verified `shared/terraform_state/` is repopulated
- Verified `Terraform::StateVersion.each do |sv| pp sv.file.read end`
  works and shows the seed-added data
- Verified skipping of `terraform_state` keyword works:

```
2021-06-06 00:11:33 +0530 -- Dumping terraform states ...
2021-06-06 00:11:33 +0530 -- [SKIPPED]
```

Verified with same workflow as above (backup, destroy, delete,
then restore) that skipped backup variant does not contain
`terraform_state.tar.gz` and does not show up those files after
restore

Miscellany:

- Adds a missing test for LFS backups
- Adds File operation fixes to neighboring tests
  so when they fail RSpec is able to show diffs
- Modified test validates unknown SKIP values not
  breaking backups
  - This is useful to catch any regressions during
    upgrades where pre-installs scripts may refer
    to a new SKIP value that isn't recognized by
    the old version

Changelog: added
parent 92bcf428
...@@ -463,7 +463,7 @@ db:backup_and_restore: ...@@ -463,7 +463,7 @@ db:backup_and_restore:
script: script:
- . scripts/prepare_build.sh - . scripts/prepare_build.sh
- bundle exec rake db:drop db:create db:structure:load db:seed_fu - bundle exec rake db:drop db:create db:structure:load db:seed_fu
- mkdir -p tmp/tests/public/uploads tmp/tests/{artifacts,pages,lfs-objects,registry} - mkdir -p tmp/tests/public/uploads tmp/tests/{artifacts,pages,lfs-objects,terraform_state,registry}
- bundle exec rake gitlab:backup:create - bundle exec rake gitlab:backup:create
- date - date
- bundle exec rake gitlab:backup:restore - bundle exec rake gitlab:backup:restore
......
# frozen_string_literal: true
TERRAFORM_FILE_VERSION = 1
# Create sample terraform states in existing projects
Gitlab::Seeder.quiet do
tfdata = {terraform_version: '0.14.1'}.to_json
Project.not_mass_generated.find_each do |project|
# Create as the project's creator
user = project.creator
# Set a build job source, if one exists for the project
build = project.builds.last
remote_state_handler = ::Terraform::RemoteStateHandler.new(project, user, name: project.path, lock_id: nil)
remote_state_handler.handle_with_lock do |state|
# Upload a file if a version does not already exist
state.update_file!(CarrierWaveStringFile.new(tfdata), version: TERRAFORM_FILE_VERSION, build: build) if state.latest_version.nil?
end
# rubocop:disable Rails/Output
print '.'
# rubocop:enable Rails/Output
end
end
...@@ -58,6 +58,7 @@ including: ...@@ -58,6 +58,7 @@ including:
- CI/CD job output logs - CI/CD job output logs
- CI/CD job artifacts - CI/CD job artifacts
- LFS objects - LFS objects
- Terraform states
- Container Registry images - Container Registry images
- GitLab Pages content - GitLab Pages content
- Snippets - Snippets
...@@ -65,7 +66,6 @@ including: ...@@ -65,7 +66,6 @@ including:
Backups do not include: Backups do not include:
- [Terraform state files](../administration/terraform_state.md)
- [Package registry files](../administration/packages/index.md) - [Package registry files](../administration/packages/index.md)
- [Mattermost data](https://docs.mattermost.com/administration/config-settings.html#file-storage) - [Mattermost data](https://docs.mattermost.com/administration/config-settings.html#file-storage)
...@@ -276,6 +276,7 @@ You can exclude specific directories from the backup by adding the environment v ...@@ -276,6 +276,7 @@ You can exclude specific directories from the backup by adding the environment v
- `builds` (CI job output logs) - `builds` (CI job output logs)
- `artifacts` (CI job artifacts) - `artifacts` (CI job artifacts)
- `lfs` (LFS objects) - `lfs` (LFS objects)
- `terraform_state` (Terraform states)
- `registry` (Container Registry images) - `registry` (Container Registry images)
- `pages` (Pages content) - `pages` (Pages content)
- `repositories` (Git repositories data) - `repositories` (Git repositories data)
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
module Backup module Backup
class Manager class Manager
ARCHIVES_TO_BACKUP = %w[uploads builds artifacts pages lfs registry].freeze ARCHIVES_TO_BACKUP = %w[uploads builds artifacts pages lfs terraform_state registry].freeze
FOLDERS_TO_BACKUP = %w[repositories db].freeze FOLDERS_TO_BACKUP = %w[repositories db].freeze
FILE_NAME_SUFFIX = '_gitlab_backup.tar' FILE_NAME_SUFFIX = '_gitlab_backup.tar'
......
# frozen_string_literal: true
module Backup
class TerraformState < Backup::Files
attr_reader :progress
def initialize(progress)
@progress = progress
super('terraform_state', Settings.terraform_state.storage_path, excludes: ['tmp'])
end
end
end
...@@ -16,6 +16,7 @@ namespace :gitlab do ...@@ -16,6 +16,7 @@ namespace :gitlab do
Rake::Task['gitlab:backup:artifacts:create'].invoke Rake::Task['gitlab:backup:artifacts:create'].invoke
Rake::Task['gitlab:backup:pages:create'].invoke Rake::Task['gitlab:backup:pages:create'].invoke
Rake::Task['gitlab:backup:lfs:create'].invoke Rake::Task['gitlab:backup:lfs:create'].invoke
Rake::Task['gitlab:backup:terraform_state:create'].invoke
Rake::Task['gitlab:backup:registry:create'].invoke Rake::Task['gitlab:backup:registry:create'].invoke
backup = Backup::Manager.new(progress) backup = Backup::Manager.new(progress)
...@@ -83,6 +84,7 @@ namespace :gitlab do ...@@ -83,6 +84,7 @@ namespace :gitlab do
Rake::Task['gitlab:backup:artifacts:restore'].invoke unless backup.skipped?('artifacts') Rake::Task['gitlab:backup:artifacts:restore'].invoke unless backup.skipped?('artifacts')
Rake::Task['gitlab:backup:pages:restore'].invoke unless backup.skipped?('pages') Rake::Task['gitlab:backup:pages:restore'].invoke unless backup.skipped?('pages')
Rake::Task['gitlab:backup:lfs:restore'].invoke unless backup.skipped?('lfs') Rake::Task['gitlab:backup:lfs:restore'].invoke unless backup.skipped?('lfs')
Rake::Task['gitlab:backup:terraform_state:restore'].invoke unless backup.skipped?('terraform_state')
Rake::Task['gitlab:backup:registry:restore'].invoke unless backup.skipped?('registry') Rake::Task['gitlab:backup:registry:restore'].invoke unless backup.skipped?('registry')
Rake::Task['gitlab:shell:setup'].invoke Rake::Task['gitlab:shell:setup'].invoke
Rake::Task['cache:clear'].invoke Rake::Task['cache:clear'].invoke
...@@ -254,6 +256,25 @@ namespace :gitlab do ...@@ -254,6 +256,25 @@ namespace :gitlab do
end end
end end
namespace :terraform_state do
task create: :gitlab_environment do
puts_time "Dumping terraform states ... ".color(:blue)
if ENV["SKIP"] && ENV["SKIP"].include?("terraform_state")
puts_time "[SKIPPED]".color(:cyan)
else
Backup::TerraformState.new(progress).dump
puts_time "done".color(:green)
end
end
task restore: :gitlab_environment do
puts_time "Restoring terraform states ... ".color(:blue)
Backup::TerraformState.new(progress).restore
puts_time "done".color(:green)
end
end
namespace :registry do namespace :registry do
task create: :gitlab_environment do task create: :gitlab_environment do
puts_time "Dumping container registry images ... ".color(:blue) puts_time "Dumping container registry images ... ".color(:blue)
......
...@@ -12,7 +12,7 @@ RSpec.describe Backup::Artifacts do ...@@ -12,7 +12,7 @@ RSpec.describe Backup::Artifacts do
Dir.mktmpdir do |tmpdir| Dir.mktmpdir do |tmpdir|
allow(JobArtifactUploader).to receive(:root) { "#{tmpdir}" } allow(JobArtifactUploader).to receive(:root) { "#{tmpdir}" }
expect(backup.app_files_dir).to eq("#{tmpdir}") expect(backup.app_files_dir).to eq("#{File.realpath(tmpdir)}")
end end
end end
end end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Backup::Lfs do
let(:progress) { StringIO.new }
subject(:backup) { described_class.new(progress) }
describe '#dump' do
before do
allow(File).to receive(:realpath).and_call_original
allow(File).to receive(:realpath).with('/var/lfs-objects').and_return('/var/lfs-objects')
allow(File).to receive(:realpath).with('/var/lfs-objects/..').and_return('/var')
allow(Settings.lfs).to receive(:storage_path).and_return('/var/lfs-objects')
end
it 'uses the correct lfs dir in tar command', :aggregate_failures do
expect(backup.app_files_dir).to eq('/var/lfs-objects')
expect(backup).to receive(:tar).and_return('blabla-tar')
expect(backup).to receive(:run_pipeline!).with([%w(blabla-tar --exclude=lost+found -C /var/lfs-objects -cf - .), 'gzip -c -1'], any_args).and_return([[true, true], ''])
expect(backup).to receive(:pipeline_succeeded?).and_return(true)
backup.dump
end
end
end
...@@ -15,7 +15,7 @@ RSpec.describe Backup::Manager do ...@@ -15,7 +15,7 @@ RSpec.describe Backup::Manager do
end end
describe '#pack' do describe '#pack' do
let(:expected_backup_contents) { %w(repositories db uploads.tar.gz builds.tar.gz artifacts.tar.gz pages.tar.gz lfs.tar.gz backup_information.yml) } let(:expected_backup_contents) { %w(repositories db uploads.tar.gz builds.tar.gz artifacts.tar.gz pages.tar.gz lfs.tar.gz terraform_state.tar.gz backup_information.yml) }
let(:tar_file) { '1546300800_2019_01_01_12.3_gitlab_backup.tar' } let(:tar_file) { '1546300800_2019_01_01_12.3_gitlab_backup.tar' }
let(:tar_system_options) { { out: [tar_file, 'w', Gitlab.config.backup.archive_permissions] } } let(:tar_system_options) { { out: [tar_file, 'w', Gitlab.config.backup.archive_permissions] } }
let(:tar_cmdline) { ['tar', '-cf', '-', *expected_backup_contents, tar_system_options] } let(:tar_cmdline) { ['tar', '-cf', '-', *expected_backup_contents, tar_system_options] }
...@@ -57,7 +57,7 @@ RSpec.describe Backup::Manager do ...@@ -57,7 +57,7 @@ RSpec.describe Backup::Manager do
end end
context 'when skipped is set in backup_information.yml' do context 'when skipped is set in backup_information.yml' do
let(:expected_backup_contents) { %w{db uploads.tar.gz builds.tar.gz artifacts.tar.gz pages.tar.gz lfs.tar.gz backup_information.yml} } let(:expected_backup_contents) { %w{db uploads.tar.gz builds.tar.gz artifacts.tar.gz pages.tar.gz lfs.tar.gz terraform_state.tar.gz backup_information.yml} }
let(:backup_information) do let(:backup_information) do
{ {
backup_created_at: Time.zone.parse('2019-01-01'), backup_created_at: Time.zone.parse('2019-01-01'),
...@@ -74,7 +74,7 @@ RSpec.describe Backup::Manager do ...@@ -74,7 +74,7 @@ RSpec.describe Backup::Manager do
end end
context 'when a directory does not exist' do context 'when a directory does not exist' do
let(:expected_backup_contents) { %w{db uploads.tar.gz builds.tar.gz artifacts.tar.gz pages.tar.gz lfs.tar.gz backup_information.yml} } let(:expected_backup_contents) { %w{db uploads.tar.gz builds.tar.gz artifacts.tar.gz pages.tar.gz lfs.tar.gz terraform_state.tar.gz backup_information.yml} }
before do before do
expect(Dir).to receive(:exist?).with(File.join(Gitlab.config.backup.path, 'repositories')).and_return(false) expect(Dir).to receive(:exist?).with(File.join(Gitlab.config.backup.path, 'repositories')).and_return(false)
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Backup::TerraformState do
let(:progress) { StringIO.new }
subject(:backup) { described_class.new(progress) }
describe '#dump' do
before do
allow(File).to receive(:realpath).and_call_original
allow(File).to receive(:realpath).with('/var/terraform_state').and_return('/var/terraform_state')
allow(File).to receive(:realpath).with('/var/terraform_state/..').and_return('/var')
allow(Settings.terraform_state).to receive(:storage_path).and_return('/var/terraform_state')
end
it 'uses the correct storage dir in tar command and excludes tmp', :aggregate_failures do
expect(backup.app_files_dir).to eq('/var/terraform_state')
expect(backup).to receive(:tar).and_return('blabla-tar')
expect(backup).to receive(:run_pipeline!).with([%w(blabla-tar --exclude=lost+found --exclude=./tmp -C /var/terraform_state -cf - .), 'gzip -c -1'], any_args).and_return([[true, true], ''])
expect(backup).to receive(:pipeline_succeeded?).and_return(true)
backup.dump
end
end
end
...@@ -14,13 +14,14 @@ RSpec.describe Backup::Uploads do ...@@ -14,13 +14,14 @@ RSpec.describe Backup::Uploads do
allow(Gitlab.config.uploads).to receive(:storage_path) { tmpdir } allow(Gitlab.config.uploads).to receive(:storage_path) { tmpdir }
expect(backup.app_files_dir).to eq("#{tmpdir}/uploads") expect(backup.app_files_dir).to eq("#{File.realpath(tmpdir)}/uploads")
end end
end end
end end
describe '#dump' do describe '#dump' do
before do before do
allow(File).to receive(:realpath).and_call_original
allow(File).to receive(:realpath).with('/var/uploads').and_return('/var/uploads') allow(File).to receive(:realpath).with('/var/uploads').and_return('/var/uploads')
allow(File).to receive(:realpath).with('/var/uploads/..').and_return('/var') allow(File).to receive(:realpath).with('/var/uploads/..').and_return('/var')
allow(Gitlab.config.uploads).to receive(:storage_path) { '/var' } allow(Gitlab.config.uploads).to receive(:storage_path) { '/var' }
......
...@@ -148,6 +148,8 @@ module TestEnv ...@@ -148,6 +148,8 @@ module TestEnv
FileUtils.mkdir_p(backup_path) FileUtils.mkdir_p(backup_path)
FileUtils.mkdir_p(pages_path) FileUtils.mkdir_p(pages_path)
FileUtils.mkdir_p(artifacts_path) FileUtils.mkdir_p(artifacts_path)
FileUtils.mkdir_p(lfs_path)
FileUtils.mkdir_p(terraform_state_path)
end end
def setup_gitlab_shell def setup_gitlab_shell
...@@ -414,6 +416,14 @@ module TestEnv ...@@ -414,6 +416,14 @@ module TestEnv
Gitlab.config.artifacts.storage_path Gitlab.config.artifacts.storage_path
end end
def lfs_path
Gitlab.config.lfs.storage_path
end
def terraform_state_path
Gitlab.config.terraform_state.storage_path
end
# When no cached assets exist, manually hit the root path to create them # When no cached assets exist, manually hit the root path to create them
# #
# Otherwise they'd be created by the first test, often timing out and # Otherwise they'd be created by the first test, often timing out and
......
...@@ -4,6 +4,7 @@ require 'rake_helper' ...@@ -4,6 +4,7 @@ require 'rake_helper'
RSpec.describe 'gitlab:app namespace rake task', :delete do RSpec.describe 'gitlab:app namespace rake task', :delete do
let(:enable_registry) { true } let(:enable_registry) { true }
let(:backup_types) { %w{db repo uploads builds artifacts pages lfs terraform_state registry} }
def tars_glob def tars_glob
Dir.glob(File.join(Gitlab.config.backup.path, '*_gitlab_backup.tar')) Dir.glob(File.join(Gitlab.config.backup.path, '*_gitlab_backup.tar'))
...@@ -14,7 +15,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -14,7 +15,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end end
def backup_files def backup_files
%w(backup_information.yml artifacts.tar.gz builds.tar.gz lfs.tar.gz pages.tar.gz) %w(backup_information.yml artifacts.tar.gz builds.tar.gz lfs.tar.gz terraform_state.tar.gz pages.tar.gz)
end end
def backup_directories def backup_directories
...@@ -47,7 +48,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -47,7 +48,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end end
def reenable_backup_sub_tasks def reenable_backup_sub_tasks
%w{db repo uploads builds artifacts pages lfs registry}.each do |subtask| backup_types.each do |subtask|
Rake::Task["gitlab:backup:#{subtask}:create"].reenable Rake::Task["gitlab:backup:#{subtask}:create"].reenable
end end
end end
...@@ -71,14 +72,9 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -71,14 +72,9 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
allow(YAML).to receive(:load_file) allow(YAML).to receive(:load_file)
.and_return({ gitlab_version: gitlab_version }) .and_return({ gitlab_version: gitlab_version })
expect(Rake::Task['gitlab:db:drop_tables']).to receive(:invoke) expect(Rake::Task['gitlab:db:drop_tables']).to receive(:invoke)
expect(Rake::Task['gitlab:backup:db:restore']).to receive(:invoke) backup_types.each do |subtask|
expect(Rake::Task['gitlab:backup:repo:restore']).to receive(:invoke) expect(Rake::Task["gitlab:backup:#{subtask}:restore"]).to receive(:invoke)
expect(Rake::Task['gitlab:backup:builds:restore']).to receive(:invoke) end
expect(Rake::Task['gitlab:backup:uploads:restore']).to receive(:invoke)
expect(Rake::Task['gitlab:backup:artifacts:restore']).to receive(:invoke)
expect(Rake::Task['gitlab:backup:pages:restore']).to receive(:invoke)
expect(Rake::Task['gitlab:backup:lfs:restore']).to receive(:invoke)
expect(Rake::Task['gitlab:backup:registry:restore']).to receive(:invoke)
expect(Rake::Task['gitlab:shell:setup']).to receive(:invoke) expect(Rake::Task['gitlab:shell:setup']).to receive(:invoke)
end end
...@@ -95,7 +91,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -95,7 +91,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
context 'when the restore directory is not empty' do context 'when the restore directory is not empty' do
before do before do
# We only need a backup of the repositories for this test # We only need a backup of the repositories for this test
stub_env('SKIP', 'db,uploads,builds,artifacts,lfs,registry') stub_env('SKIP', 'db,uploads,builds,artifacts,lfs,terraform_state,registry')
create(:project, :repository) create(:project, :repository)
end end
...@@ -139,11 +135,9 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -139,11 +135,9 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect(Rake::Task['gitlab:backup:artifacts:restore']).to receive(:invoke) expect(Rake::Task['gitlab:backup:artifacts:restore']).to receive(:invoke)
expect(Rake::Task['gitlab:backup:pages:restore']).to receive(:invoke) expect(Rake::Task['gitlab:backup:pages:restore']).to receive(:invoke)
expect(Rake::Task['gitlab:backup:lfs:restore']).to receive(:invoke) expect(Rake::Task['gitlab:backup:lfs:restore']).to receive(:invoke)
expect(Rake::Task['gitlab:backup:terraform_state:restore']).to receive(:invoke)
expect(Rake::Task['gitlab:backup:registry:restore']).to receive(:invoke) expect(Rake::Task['gitlab:backup:registry:restore']).to receive(:invoke)
expect(Rake::Task['gitlab:shell:setup']).to receive(:invoke) expect(Rake::Task['gitlab:shell:setup']).to receive(:invoke)
# We only need a backup of the repositories for this test
stub_env('SKIP', 'db,uploads,builds,artifacts,lfs,registry')
end end
it 'restores the data' do it 'restores the data' do
...@@ -202,10 +196,8 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -202,10 +196,8 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end end
context 'specific backup tasks' do context 'specific backup tasks' do
let(:task_list) { %w(db repo uploads builds artifacts pages lfs registry) }
it 'prints a progress message to stdout' do it 'prints a progress message to stdout' do
task_list.each do |task| backup_types.each do |task|
expect { run_rake_task("gitlab:backup:#{task}:create") }.to output(/Dumping /).to_stdout_from_any_process expect { run_rake_task("gitlab:backup:#{task}:create") }.to output(/Dumping /).to_stdout_from_any_process
end end
end end
...@@ -219,10 +211,11 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -219,10 +211,11 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping artifacts ... ") expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping artifacts ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping pages ... ") expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping pages ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping lfs objects ... ") expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping lfs objects ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping terraform states ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping container registry images ... ") expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping container registry images ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "done").exactly(7).times expect(Gitlab::BackupLogger).to receive(:info).with(message: "done").exactly(8).times
task_list.each do |task| backup_types.each do |task|
run_rake_task("gitlab:backup:#{task}:create") run_rake_task("gitlab:backup:#{task}:create")
end end
end end
...@@ -255,7 +248,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -255,7 +248,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
tar_contents, exit_status = Gitlab::Popen.popen( tar_contents, exit_status = Gitlab::Popen.popen(
%W{tar -tvf #{backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz pages.tar.gz lfs.tar.gz registry.tar.gz} %W{tar -tvf #{backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz pages.tar.gz lfs.tar.gz terraform_state.tar.gz registry.tar.gz}
) )
expect(exit_status).to eq(0) expect(exit_status).to eq(0)
...@@ -266,6 +259,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -266,6 +259,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect(tar_contents).to match('artifacts.tar.gz') expect(tar_contents).to match('artifacts.tar.gz')
expect(tar_contents).to match('pages.tar.gz') expect(tar_contents).to match('pages.tar.gz')
expect(tar_contents).to match('lfs.tar.gz') expect(tar_contents).to match('lfs.tar.gz')
expect(tar_contents).to match('terraform_state.tar.gz')
expect(tar_contents).to match('registry.tar.gz') expect(tar_contents).to match('registry.tar.gz')
expect(tar_contents).not_to match(%r{^.{4,9}[rwx].* (database.sql.gz|uploads.tar.gz|repositories|builds.tar.gz|pages.tar.gz|artifacts.tar.gz|registry.tar.gz)/$}) expect(tar_contents).not_to match(%r{^.{4,9}[rwx].* (database.sql.gz|uploads.tar.gz|repositories|builds.tar.gz|pages.tar.gz|artifacts.tar.gz|registry.tar.gz)/$})
end end
...@@ -274,7 +268,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -274,7 +268,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
temp_dirs = Dir.glob( temp_dirs = Dir.glob(
File.join(Gitlab.config.backup.path, '{db,repositories,uploads,builds,artifacts,pages,lfs,registry}') File.join(Gitlab.config.backup.path, '{db,repositories,uploads,builds,artifacts,pages,lfs,terraform_state,registry}')
) )
expect(temp_dirs).to be_empty expect(temp_dirs).to be_empty
...@@ -304,7 +298,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -304,7 +298,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
before do before do
# We only need a backup of the repositories for this test # We only need a backup of the repositories for this test
stub_env('SKIP', 'db,uploads,builds,artifacts,lfs,registry') stub_env('SKIP', 'db,uploads,builds,artifacts,lfs,terraform_state,registry')
stub_storage_settings( second_storage_name => { stub_storage_settings( second_storage_name => {
'gitaly_address' => Gitlab.config.repositories.storages.default.gitaly_address, 'gitaly_address' => Gitlab.config.repositories.storages.default.gitaly_address,
'path' => TestEnv::SECOND_STORAGE_PATH 'path' => TestEnv::SECOND_STORAGE_PATH
...@@ -378,7 +372,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -378,7 +372,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
context 'concurrency settings' do context 'concurrency settings' do
before do before do
# We only need a backup of the repositories for this test # We only need a backup of the repositories for this test
stub_env('SKIP', 'db,uploads,builds,artifacts,lfs,registry') stub_env('SKIP', 'db,uploads,builds,artifacts,lfs,terraform_state,registry')
create(:project, :repository) create(:project, :repository)
end end
...@@ -425,31 +419,33 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -425,31 +419,33 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end end
# backup_create task # backup_create task
describe "Skipping items" do describe "Skipping items in a backup" do
before do before do
stub_env('SKIP', 'repositories,uploads') stub_env('SKIP', 'an-unknown-type,repositories,uploads,anotherunknowntype')
create(:project, :repository) create(:project, :repository)
end end
it "does not contain skipped item" do it "does not contain repositories and uploads" do
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
tar_contents, _exit_status = Gitlab::Popen.popen( tar_contents, _exit_status = Gitlab::Popen.popen(
%W{tar -tvf #{backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz pages.tar.gz lfs.tar.gz registry.tar.gz} %W{tar -tvf #{backup_tar} db uploads.tar.gz repositories builds.tar.gz artifacts.tar.gz pages.tar.gz lfs.tar.gz terraform_state.tar.gz registry.tar.gz}
) )
expect(tar_contents).to match('db/') expect(tar_contents).to match('db/')
expect(tar_contents).to match('uploads.tar.gz') expect(tar_contents).to match('uploads.tar.gz: Not found in archive')
expect(tar_contents).to match('builds.tar.gz') expect(tar_contents).to match('builds.tar.gz')
expect(tar_contents).to match('artifacts.tar.gz') expect(tar_contents).to match('artifacts.tar.gz')
expect(tar_contents).to match('lfs.tar.gz') expect(tar_contents).to match('lfs.tar.gz')
expect(tar_contents).to match('terraform_state.tar.gz')
expect(tar_contents).to match('pages.tar.gz') expect(tar_contents).to match('pages.tar.gz')
expect(tar_contents).to match('registry.tar.gz') expect(tar_contents).to match('registry.tar.gz')
expect(tar_contents).not_to match('repositories/') expect(tar_contents).not_to match('repositories/')
expect(tar_contents).to match('repositories: Not found in archive')
end end
it 'does not invoke repositories restore' do it 'does not invoke restore of repositories and uploads' do
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
allow(Rake::Task['gitlab:shell:setup']) allow(Rake::Task['gitlab:shell:setup'])
...@@ -463,6 +459,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -463,6 +459,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect(Rake::Task['gitlab:backup:artifacts:restore']).to receive :invoke expect(Rake::Task['gitlab:backup:artifacts:restore']).to receive :invoke
expect(Rake::Task['gitlab:backup:pages:restore']).to receive :invoke expect(Rake::Task['gitlab:backup:pages:restore']).to receive :invoke
expect(Rake::Task['gitlab:backup:lfs:restore']).to receive :invoke expect(Rake::Task['gitlab:backup:lfs:restore']).to receive :invoke
expect(Rake::Task['gitlab:backup:terraform_state:restore']).to receive :invoke
expect(Rake::Task['gitlab:backup:registry:restore']).to receive :invoke expect(Rake::Task['gitlab:backup:registry:restore']).to receive :invoke
expect(Rake::Task['gitlab:shell:setup']).to receive :invoke expect(Rake::Task['gitlab:shell:setup']).to receive :invoke
expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout_from_any_process expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout_from_any_process
...@@ -488,6 +485,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -488,6 +485,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
'builds.tar.gz', 'builds.tar.gz',
'artifacts.tar.gz', 'artifacts.tar.gz',
'lfs.tar.gz', 'lfs.tar.gz',
'terraform_state.tar.gz',
'pages.tar.gz', 'pages.tar.gz',
'registry.tar.gz', 'registry.tar.gz',
'repositories' 'repositories'
...@@ -501,14 +499,9 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do ...@@ -501,14 +499,9 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
.to receive(:invoke).and_return(true) .to receive(:invoke).and_return(true)
expect(Rake::Task['gitlab:db:drop_tables']).to receive :invoke expect(Rake::Task['gitlab:db:drop_tables']).to receive :invoke
expect(Rake::Task['gitlab:backup:db:restore']).to receive :invoke backup_types.each do |subtask|
expect(Rake::Task['gitlab:backup:repo:restore']).to receive :invoke expect(Rake::Task["gitlab:backup:#{subtask}:restore"]).to receive :invoke
expect(Rake::Task['gitlab:backup:uploads:restore']).to receive :invoke end
expect(Rake::Task['gitlab:backup:builds:restore']).to receive :invoke
expect(Rake::Task['gitlab:backup:artifacts:restore']).to receive :invoke
expect(Rake::Task['gitlab:backup:pages:restore']).to receive :invoke
expect(Rake::Task['gitlab:backup:lfs:restore']).to receive :invoke
expect(Rake::Task['gitlab:backup:registry:restore']).to receive :invoke
expect(Rake::Task['gitlab:shell:setup']).to receive :invoke expect(Rake::Task['gitlab:shell:setup']).to receive :invoke
expect { run_rake_task("gitlab:backup:restore") }.to output.to_stdout_from_any_process expect { run_rake_task("gitlab:backup:restore") }.to output.to_stdout_from_any_process
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