Commit 6412234c authored by Josianne Hyson's avatar Josianne Hyson

Update GitLab Import to log to all exceptions

We want to ensure that all exceptions go through the same exception
handler so that we have consistent error handling.

Update manual logging instances to use the shared handler so that we can
take advantage of the exception handling introduced in
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17819

Ensure that all raised errors are logged to this shared handler before
continuing to raise.

Addresses https://gitlab.com/gitlab-org/gitlab/issues/38101
parent 91d59c17
...@@ -11,11 +11,7 @@ module Groups ...@@ -11,11 +11,7 @@ module Groups
end end
def execute def execute
unless @current_user.can?(:admin_group, @group) validate_user_permissions
raise ::Gitlab::ImportExport::Error.new(
"User with ID: %s does not have permission to Group %s with ID: %s." %
[@current_user.id, @group.name, @group.id])
end
save! save!
ensure ensure
...@@ -26,6 +22,19 @@ module Groups ...@@ -26,6 +22,19 @@ module Groups
attr_accessor :shared attr_accessor :shared
def validate_user_permissions
unless @current_user.can?(:admin_group, @group)
@shared.error(
::Gitlab::ImportExport::Error.new(
"User with ID: %s does not have permission to Group %s with ID: %s." %
[@current_user.id, @group.name, @group.id]
)
)
notify_error!
end
end
def save! def save!
if savers.all?(&:save) if savers.all?(&:save)
notify_success notify_success
......
...@@ -12,15 +12,14 @@ module Groups ...@@ -12,15 +12,14 @@ module Groups
end end
def execute def execute
validate_user_permissions if valid_user_permissions? && import_file && restorer.restore
notify_success
if import_file && restorer.restore
@group @group
else else
raise StandardError.new(@shared.errors.to_sentence) notify_error!
end end
rescue => e
raise StandardError.new(e.message)
ensure ensure
remove_import_file remove_import_file
end end
...@@ -49,13 +48,42 @@ module Groups ...@@ -49,13 +48,42 @@ module Groups
upload.save! upload.save!
end end
def validate_user_permissions def valid_user_permissions?
unless current_user.can?(:admin_group, group) if current_user.can?(:admin_group, group)
raise ::Gitlab::ImportExport::Error.new( true
"User with ID: %s does not have permission to Group %s with ID: %s." % else
[current_user.id, group.name, group.id]) @shared.error(
Gitlab::ImportExport::Error.new(
"User with ID: %s does not have permission to Group %s with ID: %s." %
[current_user.id, group.name, group.id]
)
)
false
end end
end end
def notify_success
@shared.logger.info(
group_id: @group.id,
group_name: @group.name,
message: 'Group Import/Export: Import succeeded'
)
end
def notify_error
@shared.logger.error(
group_id: @group.id,
group_name: @group.name,
message: "Group Import/Export: Errors occurred, see '#{Gitlab::ErrorTracking::Logger.file_name}' for details"
)
end
def notify_error!
notify_error
raise Gitlab::ImportExport::Error.new(@shared.errors.to_sentence)
end
end end
end end
end end
---
title: Ensure all errors are logged in Group Import
merge_request: 25619
author:
type: changed
...@@ -49,11 +49,7 @@ module Gitlab ...@@ -49,11 +49,7 @@ module Gitlab
json = IO.read(@path) json = IO.read(@path)
ActiveSupport::JSON.decode(json) ActiveSupport::JSON.decode(json)
rescue => e rescue => e
@shared.logger.error( @shared.error(e)
group_id: @group.id,
group_name: @group.name,
message: "Import/Export error: #{e.message}"
)
raise Gitlab::ImportExport::Error.new('Incorrect JSON format') raise Gitlab::ImportExport::Error.new('Incorrect JSON format')
end end
......
...@@ -94,14 +94,6 @@ module Gitlab ...@@ -94,14 +94,6 @@ module Gitlab
end end
end end
def log_error(details)
@logger.error(log_base_data.merge(details))
end
def log_debug(details)
@logger.debug(log_base_data.merge(details))
end
def log_base_data def log_base_data
log = { log = {
importer: 'Import/Export', importer: 'Import/Export',
......
...@@ -38,12 +38,31 @@ describe Groups::ImportExport::ExportService do ...@@ -38,12 +38,31 @@ describe Groups::ImportExport::ExportService do
let!(:another_user) { create(:user) } let!(:another_user) { create(:user) }
let(:service) { described_class.new(group: group, user: another_user, params: { shared: shared }) } let(:service) { described_class.new(group: group, user: another_user, params: { shared: shared }) }
let(:expected_message) do
"User with ID: %s does not have permission to Group %s with ID: %s." %
[another_user.id, group.name, group.id]
end
it 'fails' do it 'fails' do
expected_message =
"User with ID: %s does not have permission to Group %s with ID: %s." %
[another_user.id, group.name, group.id]
expect { service.execute }.to raise_error(Gitlab::ImportExport::Error).with_message(expected_message) expect { service.execute }.to raise_error(Gitlab::ImportExport::Error).with_message(expected_message)
end end
it 'logs the error' do
expect(shared.logger).to receive(:error).with(
group_id: group.id,
group_name: group.name,
error: expected_message,
message: 'Group Import/Export: Export failed'
)
expect { service.execute }.to raise_error(Gitlab::ImportExport::Error)
end
it 'tracks the error' do
expect(shared).to receive(:error) { |param| expect(param.message).to eq expected_message }
expect { service.execute }.to raise_error(Gitlab::ImportExport::Error)
end
end end
context 'when export fails' do context 'when export fails' do
......
...@@ -9,6 +9,8 @@ describe Groups::ImportExport::ImportService do ...@@ -9,6 +9,8 @@ describe Groups::ImportExport::ImportService do
let(:service) { described_class.new(group: group, user: user) } let(:service) { described_class.new(group: group, user: user) }
let(:import_file) { fixture_file_upload('spec/fixtures/group_export.tar.gz') } let(:import_file) { fixture_file_upload('spec/fixtures/group_export.tar.gz') }
let(:import_logger) { instance_double(Gitlab::Import::Logger) }
subject { service.execute } subject { service.execute }
before do before do
...@@ -25,13 +27,82 @@ describe Groups::ImportExport::ImportService do ...@@ -25,13 +27,82 @@ describe Groups::ImportExport::ImportService do
expect(group.import_export_upload.import_file.file).to be_nil expect(group.import_export_upload.import_file.file).to be_nil
end end
it 'logs the import success' do
allow(Gitlab::Import::Logger).to receive(:build).and_return(import_logger)
expect(import_logger).to receive(:info).with(
group_id: group.id,
group_name: group.name,
message: 'Group Import/Export: Import succeeded'
)
subject
end
end end
context 'when user does not have correct permissions' do context 'when user does not have correct permissions' do
let(:user) { create(:user) } let(:user) { create(:user) }
it 'raises exception' do it 'logs the error and raises an exception' do
expect { subject }.to raise_error(StandardError) allow(Gitlab::Import::Logger).to receive(:build).and_return(import_logger)
expect(import_logger).to receive(:error).with(
group_id: group.id,
group_name: group.name,
message: a_string_including('Errors occurred')
)
expect { subject }.to raise_error(Gitlab::ImportExport::Error)
end
it 'tracks the error' do
shared = Gitlab::ImportExport::Shared.new(group)
allow(Gitlab::ImportExport::Shared).to receive(:new).and_return(shared)
expect(shared).to receive(:error) do |param|
expect(param.message).to include 'does not have permission to'
end
expect { subject }.to raise_error(Gitlab::ImportExport::Error)
end
end
context 'when there are errors with the import file' do
let(:import_file) { fixture_file_upload('spec/fixtures/symlink_export.tar.gz') }
before do
allow(Gitlab::Import::Logger).to receive(:build).and_return(import_logger)
end
it 'logs the error and raises an exception' do
expect(import_logger).to receive(:error).with(
group_id: group.id,
group_name: group.name,
message: a_string_including('Errors occurred')
)
expect { subject }.to raise_error(Gitlab::ImportExport::Error)
end
end
context 'when there are errors with the sub-relations' do
let(:import_file) { fixture_file_upload('spec/fixtures/group_export_invalid_subrelations.tar.gz') }
it 'successfully imports the group' do
expect(subject).to be_truthy
end
it 'logs the import success' do
allow(Gitlab::Import::Logger).to receive(:build).and_return(import_logger)
expect(import_logger).to receive(:info).with(
group_id: group.id,
group_name: group.name,
message: 'Group Import/Export: Import succeeded'
)
subject
end end
end end
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