Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-12-22 03:15:20 +00:00
parent 4314202d9d
commit dc93436903
31 changed files with 325 additions and 105 deletions

View file

@ -463,7 +463,7 @@ db:backup_and_restore:
script:
- . scripts/prepare_build.sh
- 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
- date
- bundle exec rake gitlab:backup:restore

View file

@ -44,6 +44,11 @@ module Types
null: true,
description: 'Name given to the token.'
field :status,
GraphQL::Types::String,
null: true,
description: 'Current status of the token.'
def cluster_agent
Gitlab::Graphql::Loaders::BatchModelLoader.new(::Clusters::Agent, object.agent_id).find
end

View file

@ -36,8 +36,8 @@ module Clusters
requested_project == project
end
def active?
agent_tokens.where("last_used_at > ?", INACTIVE_AFTER.ago).exists?
def connected?
agent_tokens.active.where("last_used_at > ?", INACTIVE_AFTER.ago).exists?
end
end
end

View file

@ -23,13 +23,18 @@ module Clusters
scope :order_last_used_at_desc, -> { order(::Gitlab::Database.nulls_last_order('last_used_at', 'DESC')) }
enum status: {
active: 0,
revoked: 1
}
def track_usage
track_values = { last_used_at: Time.current.utc }
cache_attributes(track_values)
if can_update_track_values?
log_activity_event!(track_values[:last_used_at]) unless agent.active?
log_activity_event!(track_values[:last_used_at]) unless agent.connected?
# Use update_column so updated_at is skipped
update_columns(track_values)

View file

@ -0,0 +1,26 @@
# 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

View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddStatusToClusterAgentTokens < Gitlab::Database::Migration[1.0]
def change
add_column :cluster_agent_tokens, :status, :smallint, null: false, default: 0
end
end

View file

@ -0,0 +1,26 @@
# frozen_string_literal: true
class CleanupAfterDropInvalidSecurityFindings < Gitlab::Database::Migration[1.0]
MIGRATION = "DropInvalidSecurityFindings"
INDEX_NAME = "tmp_index_uuid_is_null"
disable_ddl_transaction!
def up
# Make sure all jobs scheduled by
# db/post_migrate/20211110151350_schedule_drop_invalid_security_findings.rb
# are finished
finalize_background_migration(MIGRATION)
# Created by db/post_migrate/20211110151320_add_temporary_index_on_security_findings_uuid.rb
remove_concurrent_index_by_name :security_findings, INDEX_NAME
end
def down
add_concurrent_index(
:security_findings,
:id,
where: "uuid IS NULL",
name: INDEX_NAME
)
end
end

View file

@ -0,0 +1 @@
46767d804bde08ad4a076f20436652f980eb935a79b2ad30b4735b956be69a7a

View file

@ -0,0 +1 @@
907fafc18fa515fff8f716f6464263ccc8a9b6e5ead36f30b05089100fd71b6b

View file

@ -12384,6 +12384,7 @@ CREATE TABLE cluster_agent_tokens (
description text,
name text,
last_used_at timestamp with time zone,
status smallint DEFAULT 0 NOT NULL,
CONSTRAINT check_0fb634d04d CHECK ((name IS NOT NULL)),
CONSTRAINT check_2b79dbb315 CHECK ((char_length(name) <= 255)),
CONSTRAINT check_4e4ec5070a CHECK ((char_length(description) <= 1024)),
@ -27982,8 +27983,6 @@ CREATE UNIQUE INDEX tmp_index_on_tmp_project_id_on_namespaces ON namespaces USIN
CREATE INDEX tmp_index_on_vulnerabilities_non_dismissed ON vulnerabilities USING btree (id) WHERE (state <> 2);
CREATE INDEX tmp_index_uuid_is_null ON security_findings USING btree (id) WHERE (uuid IS NULL);
CREATE UNIQUE INDEX uniq_pkgs_deb_grp_architectures_on_distribution_id_and_name ON packages_debian_group_architectures USING btree (distribution_id, name);
CREATE UNIQUE INDEX uniq_pkgs_deb_grp_components_on_distribution_id_and_name ON packages_debian_group_components USING btree (distribution_id, name);

View file

@ -8960,6 +8960,7 @@ GitLab CI/CD configuration template.
| <a id="clusteragenttokenid"></a>`id` | [`ClustersAgentTokenID!`](#clustersagenttokenid) | Global ID of the token. |
| <a id="clusteragenttokenlastusedat"></a>`lastUsedAt` | [`Time`](#time) | Timestamp the token was last used. |
| <a id="clusteragenttokenname"></a>`name` | [`String`](#string) | Name given to the token. |
| <a id="clusteragenttokenstatus"></a>`status` | [`String`](#string) | Current status of the token. |
### `CodeCoverageActivity`

View file

@ -58,6 +58,7 @@ including:
- CI/CD job output logs
- CI/CD job artifacts
- LFS objects
- Terraform states
- Container Registry images
- GitLab Pages content
- Snippets
@ -65,7 +66,6 @@ including:
Backups do not include:
- [Terraform state files](../administration/terraform_state.md)
- [Package registry files](../administration/packages/index.md)
- [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
- `builds` (CI job output logs)
- `artifacts` (CI job artifacts)
- `lfs` (LFS objects)
- `terraform_state` (Terraform states)
- `registry` (Container Registry images)
- `pages` (Pages content)
- `repositories` (Git repositories data)

View file

@ -2,7 +2,7 @@
module Backup
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
FILE_NAME_SUFFIX = '_gitlab_backup.tar'

View file

@ -0,0 +1,13 @@
# 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

View file

@ -165,7 +165,7 @@ module Gitlab
authorization_token, _options = token_and_options(current_request)
::Clusters::AgentToken.find_by_token(authorization_token)
::Clusters::AgentToken.active.find_by_token(authorization_token)
end
def find_runner_from_token

View file

@ -76,20 +76,7 @@ module Gitlab
def self.cleanup_leftovers!
PostgresIndex.reindexing_leftovers.each do |index|
Gitlab::AppLogger.info("Removing index #{index.identifier} which is a leftover, temporary index from previous reindexing activity")
retries = Gitlab::Database::WithLockRetriesOutsideTransaction.new(
connection: index.connection,
timing_configuration: REMOVE_INDEX_RETRY_CONFIG,
klass: self.class,
logger: Gitlab::AppLogger
)
retries.run(raise_on_exhaustion: false) do
index.connection.tap do |conn|
conn.execute("DROP INDEX CONCURRENTLY IF EXISTS #{conn.quote_table_name(index.schema)}.#{conn.quote_table_name(index.name)}")
end
end
Coordinator.new(index).drop
end
end
end

View file

@ -31,6 +31,25 @@ module Gitlab
end
end
def drop
try_obtain_lease do
Gitlab::AppLogger.info("Removing index #{index.identifier} which is a leftover, temporary index from previous reindexing activity")
retries = Gitlab::Database::WithLockRetriesOutsideTransaction.new(
connection: index.connection,
timing_configuration: REMOVE_INDEX_RETRY_CONFIG,
klass: self.class,
logger: Gitlab::AppLogger
)
retries.run(raise_on_exhaustion: false) do
index.connection.tap do |conn|
conn.execute("DROP INDEX CONCURRENTLY IF EXISTS #{conn.quote_table_name(index.schema)}.#{conn.quote_table_name(index.name)}")
end
end
end
end
private
def with_notifications(action)

View file

@ -16,6 +16,7 @@ namespace :gitlab do
Rake::Task['gitlab:backup:artifacts:create'].invoke
Rake::Task['gitlab:backup:pages:create'].invoke
Rake::Task['gitlab:backup:lfs:create'].invoke
Rake::Task['gitlab:backup:terraform_state:create'].invoke
Rake::Task['gitlab:backup:registry:create'].invoke
backup = Backup::Manager.new(progress)
@ -83,6 +84,7 @@ namespace :gitlab do
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: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:shell:setup'].invoke
Rake::Task['cache:clear'].invoke
@ -254,6 +256,25 @@ namespace :gitlab do
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
task create: :gitlab_environment do
puts_time "Dumping container registry images ... ".color(:blue)

View file

View file

@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe GitlabSchema.types['ClusterAgentToken'] do
let(:fields) { %i[cluster_agent created_at created_by_user description id last_used_at name] }
let(:fields) { %i[cluster_agent created_at created_by_user description id last_used_at name status] }
it { expect(described_class.graphql_name).to eq('ClusterAgentToken') }

View file

@ -12,7 +12,7 @@ RSpec.describe Backup::Artifacts do
Dir.mktmpdir do |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

View file

@ -0,0 +1,27 @@
# 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

View file

@ -15,7 +15,7 @@ RSpec.describe Backup::Manager do
end
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_system_options) { { out: [tar_file, 'w', Gitlab.config.backup.archive_permissions] } }
let(:tar_cmdline) { ['tar', '-cf', '-', *expected_backup_contents, tar_system_options] }
@ -57,7 +57,7 @@ RSpec.describe Backup::Manager do
end
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
{
backup_created_at: Time.zone.parse('2019-01-01'),
@ -74,7 +74,7 @@ RSpec.describe Backup::Manager do
end
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
expect(Dir).to receive(:exist?).with(File.join(Gitlab.config.backup.path, 'repositories')).and_return(false)

View file

@ -0,0 +1,27 @@
# 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

View file

@ -14,13 +14,14 @@ RSpec.describe Backup::Uploads do
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
describe '#dump' 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')
allow(Gitlab.config.uploads).to receive(:storage_path) { '/var' }

View file

@ -939,21 +939,19 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
describe '#cluster_agent_token_from_authorization_token' do
let_it_be(:agent_token, freeze: true) { create(:cluster_agent_token) }
let_it_be(:agent_token) { create(:cluster_agent_token) }
subject { cluster_agent_token_from_authorization_token }
context 'when route_setting is empty' do
it 'returns nil' do
expect(cluster_agent_token_from_authorization_token).to be_nil
end
it { is_expected.to be_nil }
end
context 'when route_setting allows cluster agent token' do
let(:route_authentication_setting) { { cluster_agent_token_allowed: true } }
context 'Authorization header is empty' do
it 'returns nil' do
expect(cluster_agent_token_from_authorization_token).to be_nil
end
it { is_expected.to be_nil }
end
context 'Authorization header is incorrect' do
@ -961,9 +959,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
request.headers['Authorization'] = 'Bearer ABCD'
end
it 'returns nil' do
expect(cluster_agent_token_from_authorization_token).to be_nil
end
it { is_expected.to be_nil }
end
context 'Authorization header is malformed' do
@ -971,9 +967,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
request.headers['Authorization'] = 'Bearer'
end
it 'returns nil' do
expect(cluster_agent_token_from_authorization_token).to be_nil
end
it { is_expected.to be_nil }
end
context 'Authorization header matches agent token' do
@ -981,8 +975,14 @@ RSpec.describe Gitlab::Auth::AuthFinders do
request.headers['Authorization'] = "Bearer #{agent_token.token}"
end
it 'returns the agent token' do
expect(cluster_agent_token_from_authorization_token).to eq(agent_token)
it { is_expected.to eq(agent_token) }
context 'agent token has been revoked' do
before do
agent_token.revoked!
end
it { is_expected.to be_nil }
end
end
end

View file

@ -6,30 +6,34 @@ RSpec.describe Gitlab::Database::Reindexing::Coordinator do
include Database::DatabaseHelpers
include ExclusiveLeaseHelpers
describe '.perform' do
let(:notifier) { instance_double(Gitlab::Database::Reindexing::GrafanaNotifier, notify_start: nil, notify_end: nil) }
let(:index) { create(:postgres_index) }
let(:connection) { index.connection }
let!(:lease) { stub_exclusive_lease(lease_key, uuid, timeout: lease_timeout) }
let(:lease_key) { "gitlab/database/reindexing/coordinator/#{Gitlab::Database::PRIMARY_DATABASE_NAME}" }
let(:lease_timeout) { 1.day }
let(:uuid) { 'uuid' }
around do |example|
model = Gitlab::Database.database_base_models[Gitlab::Database::PRIMARY_DATABASE_NAME]
Gitlab::Database::SharedModel.using_connection(model.connection) do
example.run
end
end
before do
swapout_view_for_table(:postgres_indexes)
end
describe '#perform' do
subject { described_class.new(index, notifier).perform }
let(:index) { create(:postgres_index) }
let(:notifier) { instance_double(Gitlab::Database::Reindexing::GrafanaNotifier, notify_start: nil, notify_end: nil) }
let(:reindexer) { instance_double(Gitlab::Database::Reindexing::ReindexConcurrently, perform: nil) }
let(:action) { create(:reindex_action, index: index) }
let!(:lease) { stub_exclusive_lease(lease_key, uuid, timeout: lease_timeout) }
let(:lease_key) { "gitlab/database/reindexing/coordinator/#{Gitlab::Database::PRIMARY_DATABASE_NAME}" }
let(:lease_timeout) { 1.day }
let(:uuid) { 'uuid' }
around do |example|
model = Gitlab::Database.database_base_models[Gitlab::Database::PRIMARY_DATABASE_NAME]
Gitlab::Database::SharedModel.using_connection(model.connection) do
example.run
end
end
before do
swapout_view_for_table(:postgres_indexes)
allow(Gitlab::Database::Reindexing::ReindexConcurrently).to receive(:new).with(index).and_return(reindexer)
allow(Gitlab::Database::Reindexing::ReindexAction).to receive(:create_for).with(index).and_return(action)
end
@ -87,4 +91,40 @@ RSpec.describe Gitlab::Database::Reindexing::Coordinator do
end
end
end
describe '#drop' do
let(:connection) { index.connection }
subject(:drop) { described_class.new(index, notifier).drop }
context 'when exclusive lease is granted' do
it 'drops the index with lock retries' do
expect(lease).to receive(:try_obtain).ordered.and_return(uuid)
expect_query("SET lock_timeout TO '60000ms'")
expect_query("DROP INDEX CONCURRENTLY IF EXISTS \"public\".\"#{index.name}\"")
expect_query("RESET idle_in_transaction_session_timeout; RESET lock_timeout")
expect(Gitlab::ExclusiveLease).to receive(:cancel).ordered.with(lease_key, uuid)
drop
end
def expect_query(sql)
expect(connection).to receive(:execute).ordered.with(sql).and_wrap_original do |method, sql|
method.call(sql.sub(/CONCURRENTLY/, ''))
end
end
end
context 'when exclusive lease is not granted' do
it 'does not drop the index' do
expect(lease).to receive(:try_obtain).ordered.and_return(false)
expect(Gitlab::Database::WithLockRetriesOutsideTransaction).not_to receive(:new)
expect(connection).not_to receive(:execute)
drop
end
end
end
end

View file

@ -76,12 +76,12 @@ RSpec.describe Clusters::Agent do
end
end
describe '#active?' do
describe '#connected?' do
let_it_be(:agent) { create(:cluster_agent) }
let!(:token) { create(:cluster_agent_token, agent: agent, last_used_at: last_used_at) }
subject { agent.active? }
subject { agent.connected? }
context 'agent has never connected' do
let(:last_used_at) { nil }
@ -99,6 +99,14 @@ RSpec.describe Clusters::Agent do
let(:last_used_at) { 2.minutes.ago }
it { is_expected.to be_truthy }
context 'agent token has been revoked' do
before do
token.revoked!
end
it { is_expected.to be_falsey }
end
end
context 'agent has multiple tokens' do

View file

@ -9,6 +9,8 @@ RSpec.describe Clusters::AgentToken do
it { is_expected.to validate_length_of(:name).is_at_most(255) }
it { is_expected.to validate_presence_of(:name) }
it_behaves_like 'having unique enum values'
describe 'scopes' do
describe '.order_last_used_at_desc' do
let_it_be(:token_1) { create(:cluster_agent_token, last_used_at: 7.days.ago) }
@ -76,9 +78,9 @@ RSpec.describe Clusters::AgentToken do
end
end
context 'agent is inactive' do
context 'agent is not connected' do
before do
allow(agent).to receive(:active?).and_return(false)
allow(agent).to receive(:connected?).and_return(false)
end
it 'creates an activity event' do
@ -94,9 +96,9 @@ RSpec.describe Clusters::AgentToken do
end
end
context 'agent is active' do
context 'agent is connected' do
before do
allow(agent).to receive(:active?).and_return(true)
allow(agent).to receive(:connected?).and_return(true)
end
it 'does not create an activity event' do

View file

@ -148,6 +148,8 @@ module TestEnv
FileUtils.mkdir_p(backup_path)
FileUtils.mkdir_p(pages_path)
FileUtils.mkdir_p(artifacts_path)
FileUtils.mkdir_p(lfs_path)
FileUtils.mkdir_p(terraform_state_path)
end
def setup_gitlab_shell
@ -414,6 +416,14 @@ module TestEnv
Gitlab.config.artifacts.storage_path
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
#
# Otherwise they'd be created by the first test, often timing out and

View file

@ -4,6 +4,7 @@ require 'rake_helper'
RSpec.describe 'gitlab:app namespace rake task', :delete do
let(:enable_registry) { true }
let(:backup_types) { %w{db repo uploads builds artifacts pages lfs terraform_state registry} }
def tars_glob
Dir.glob(File.join(Gitlab.config.backup.path, '*_gitlab_backup.tar'))
@ -14,7 +15,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
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
def backup_directories
@ -47,7 +48,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
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
end
end
@ -71,14 +72,9 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
allow(YAML).to receive(:load_file)
.and_return({ gitlab_version: gitlab_version })
expect(Rake::Task['gitlab:db:drop_tables']).to receive(:invoke)
expect(Rake::Task['gitlab:backup:db:restore']).to receive(:invoke)
expect(Rake::Task['gitlab:backup:repo:restore']).to receive(:invoke)
expect(Rake::Task['gitlab:backup:builds:restore']).to receive(:invoke)
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)
backup_types.each do |subtask|
expect(Rake::Task["gitlab:backup:#{subtask}:restore"]).to receive(:invoke)
end
expect(Rake::Task['gitlab:shell:setup']).to receive(:invoke)
end
@ -95,7 +91,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
context 'when the restore directory is not empty' do
before do
# 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)
end
@ -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:pages: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: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
it 'restores the data' do
@ -202,10 +196,8 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
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
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
end
end
@ -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 pages ... ")
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: "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")
end
end
@ -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
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)
@ -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('pages.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).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
@ -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
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
@ -304,7 +298,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
before do
# 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 => {
'gitaly_address' => Gitlab.config.repositories.storages.default.gitaly_address,
'path' => TestEnv::SECOND_STORAGE_PATH
@ -378,7 +372,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
context 'concurrency settings' do
before do
# 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)
end
@ -425,31 +419,33 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
# backup_create task
describe "Skipping items" do
describe "Skipping items in a backup" do
before do
stub_env('SKIP', 'repositories,uploads')
stub_env('SKIP', 'an-unknown-type,repositories,uploads,anotherunknowntype')
create(:project, :repository)
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
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('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('artifacts.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('registry.tar.gz')
expect(tar_contents).not_to match('repositories/')
expect(tar_contents).to match('repositories: Not found in archive')
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
allow(Rake::Task['gitlab:shell:setup'])
@ -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:pages: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:shell:setup']).to receive :invoke
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
'builds.tar.gz',
'artifacts.tar.gz',
'lfs.tar.gz',
'terraform_state.tar.gz',
'pages.tar.gz',
'registry.tar.gz',
'repositories'
@ -501,14 +499,9 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
.to receive(:invoke).and_return(true)
expect(Rake::Task['gitlab:db:drop_tables']).to receive :invoke
expect(Rake::Task['gitlab:backup:db:restore']).to receive :invoke
expect(Rake::Task['gitlab:backup:repo:restore']).to receive :invoke
expect(Rake::Task['gitlab:backup:uploads:restore']).to receive :invoke
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
backup_types.each do |subtask|
expect(Rake::Task["gitlab:backup:#{subtask}:restore"]).to receive :invoke
end
expect(Rake::Task['gitlab:shell:setup']).to receive :invoke
expect { run_rake_task("gitlab:backup:restore") }.to output.to_stdout_from_any_process
end