Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/doctor/reset_tokens_spec.rb')
-rw-r--r--spec/lib/gitlab/doctor/reset_tokens_spec.rb133
1 files changed, 133 insertions, 0 deletions
diff --git a/spec/lib/gitlab/doctor/reset_tokens_spec.rb b/spec/lib/gitlab/doctor/reset_tokens_spec.rb
new file mode 100644
index 00000000000..0cc947efdb4
--- /dev/null
+++ b/spec/lib/gitlab/doctor/reset_tokens_spec.rb
@@ -0,0 +1,133 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Doctor::ResetTokens, feature_category: :runner_fleet do
+ let(:logger) { instance_double('Logger') }
+ let(:model_names) { %w[Project Group] }
+ let(:token_names) { %w[runners_token] }
+ let(:dry_run) { false }
+ let(:doctor) { described_class.new(logger, model_names: model_names, token_names: token_names, dry_run: dry_run) }
+
+ let_it_be(:functional_project) { create(:project).tap(&:runners_token) }
+ let_it_be(:functional_group) { create(:group).tap(&:runners_token) }
+
+ let(:broken_project) { create(:project).tap { |project| project.update_columns(runners_token_encrypted: 'aaa') } }
+ let(:project_with_cipher_error) do
+ create(:project).tap do |project|
+ project.update_columns(
+ runners_token_encrypted: '|rXs75DSHXPE9MGAIgyxcut8pZc72gaa/2ojU0GS1+R+cXNqkbUB13Vb5BaMwf47d98980fc1')
+ end
+ end
+
+ let(:broken_group) { create(:group, runners_token_encrypted: 'aaa') }
+
+ subject(:run!) do
+ expect(logger).to receive(:info).with(
+ "Resetting #{token_names.join(', ')} on #{model_names.join(', ')} if they can not be read"
+ )
+ expect(logger).to receive(:info).with('Done!')
+ doctor.run!
+ end
+
+ before do
+ allow(logger).to receive(:info).with(%r{Checked \d/\d Projects})
+ allow(logger).to receive(:info).with(%r{Checked \d Projects})
+ allow(logger).to receive(:info).with(%r{Checked \d/\d Groups})
+ allow(logger).to receive(:info).with(%r{Checked \d Groups})
+ end
+
+ it 'fixes broken project and not the functional project' do
+ expect(logger).to receive(:debug).with("> Fix Project[#{broken_project.id}].runners_token")
+
+ expect { run! }.to change { broken_project.reload.runners_token_encrypted }.from('aaa')
+ .and not_change { functional_project.reload.runners_token_encrypted }
+ expect { broken_project.runners_token }.not_to raise_error
+ end
+
+ it 'fixes project with cipher error' do
+ expect { project_with_cipher_error.runners_token }.to raise_error(OpenSSL::Cipher::CipherError)
+ expect(logger).to receive(:debug).with("> Fix Project[#{project_with_cipher_error.id}].runners_token")
+
+ expect { run! }.to change { project_with_cipher_error.reload.runners_token_encrypted }
+ expect { project_with_cipher_error.runners_token }.not_to raise_error
+ end
+
+ it 'fixes broken group and not the functional group' do
+ expect(logger).to receive(:debug).with("> Fix Group[#{broken_group.id}].runners_token")
+
+ expect { run! }.to change { broken_group.reload.runners_token_encrypted }.from('aaa')
+ .and not_change { functional_group.reload.runners_token_encrypted }
+
+ expect { broken_group.runners_token }.not_to raise_error
+ end
+
+ context 'when one model specified' do
+ let(:model_names) { %w[Project] }
+
+ it 'fixes broken project' do
+ expect(logger).to receive(:debug).with("> Fix Project[#{broken_project.id}].runners_token")
+
+ expect { run! }.to change { broken_project.reload.runners_token_encrypted }.from('aaa')
+ expect { broken_project.runners_token }.not_to raise_error
+ end
+
+ it 'does not fix other models' do
+ expect { run! }.not_to change { broken_group.reload.runners_token_encrypted }.from('aaa')
+ end
+ end
+
+ context 'when non-existing token field is given' do
+ let(:token_names) { %w[nonexisting_token] }
+
+ it 'does not fix anything' do
+ expect { run! }.not_to change { broken_project.reload.runners_token_encrypted }.from('aaa')
+ end
+ end
+
+ context 'when executing in a dry-run mode' do
+ let(:dry_run) { true }
+
+ it 'prints info about fixed project, but does not actually do anything' do
+ expect(logger).to receive(:info).with('Executing in DRY RUN mode, no records will actually be updated')
+ expect(logger).to receive(:debug).with("> Fix Project[#{broken_project.id}].runners_token")
+
+ expect { run! }.not_to change { broken_project.reload.runners_token_encrypted }.from('aaa')
+ expect { broken_project.runners_token }.to raise_error(TypeError)
+ end
+ end
+
+ it 'prints progress along the way' do
+ stub_const('Gitlab::Doctor::ResetTokens::PRINT_PROGRESS_EVERY', 1)
+
+ broken_project
+ project_with_cipher_error
+
+ expect(logger).to receive(:info).with(
+ "Resetting #{token_names.join(', ')} on #{model_names.join(', ')} if they can not be read"
+ )
+ expect(logger).to receive(:info).with('Checked 1/3 Projects')
+ expect(logger).to receive(:debug).with("> Fix Project[#{broken_project.id}].runners_token")
+ expect(logger).to receive(:info).with('Checked 2/3 Projects')
+ expect(logger).to receive(:debug).with("> Fix Project[#{project_with_cipher_error.id}].runners_token")
+ expect(logger).to receive(:info).with('Checked 3/3 Projects')
+ expect(logger).to receive(:info).with('Done!')
+
+ doctor.run!
+ end
+
+ it "prints 'Something went wrong' error when encounters unexpected exception, but continues" do
+ broken_project
+ project_with_cipher_error
+
+ expect(logger).to receive(:debug).with(
+ "> Something went wrong for Project[#{broken_project.id}].runners_token: Error message")
+ expect(logger).to receive(:debug).with("> Fix Project[#{project_with_cipher_error.id}].runners_token")
+
+ expect(broken_project).to receive(:runners_token).and_raise("Error message")
+ expect(Project).to receive(:find_each).and_return([broken_project, project_with_cipher_error].each)
+
+ expect { run! }.to not_change { broken_project.reload.runners_token_encrypted }.from('aaa')
+ .and change { project_with_cipher_error.reload.runners_token_encrypted }
+ end
+end