diff options
Diffstat (limited to 'spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb')
-rw-r--r-- | spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb | 168 |
1 files changed, 159 insertions, 9 deletions
diff --git a/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb b/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb index 451fd6c6f46..42cf9c54798 100644 --- a/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb +++ b/spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb @@ -9,12 +9,21 @@ RSpec.describe Gitlab::ImportExport::AfterExportStrategies::WebUploadStrategy do allow_next_instance_of(ProjectExportWorker) do |job| allow(job).to receive(:jid).and_return(SecureRandom.hex(8)) end + + stub_feature_flags(import_export_web_upload_stream: false) + stub_uploads_object_storage(FileUploader, enabled: false) end let(:example_url) { 'http://www.example.com' } let(:strategy) { subject.new(url: example_url, http_method: 'post') } - let!(:project) { create(:project, :with_export) } - let!(:user) { build(:user) } + let(:user) { build(:user) } + let(:project) { import_export_upload.project } + let(:import_export_upload) do + create( + :import_export_upload, + export_file: fixture_file_upload('spec/fixtures/gitlab/import_export/lightweight_project_export.tar.gz') + ) + end subject { described_class } @@ -36,20 +45,42 @@ RSpec.describe Gitlab::ImportExport::AfterExportStrategies::WebUploadStrategy do describe '#execute' do context 'when upload succeeds' do before do - allow(strategy).to receive(:send_file) - allow(strategy).to receive(:handle_response_error) + stub_full_request(example_url, method: :post).to_return(status: 200) end - it 'does not remove the exported project file after the upload' do + it 'does not remove the exported project file after the upload', :aggregate_failures do expect(project).not_to receive(:remove_exports) - strategy.execute(user, project) + expect { strategy.execute(user, project) }.not_to change(project, :export_status) + + expect(project.export_status).to eq(:finished) end - it 'has finished export status' do - strategy.execute(user, project) + it 'logs when upload starts and finishes' do + export_size = import_export_upload.export_file.size + + expect_next_instance_of(Gitlab::Export::Logger) do |logger| + expect(logger).to receive(:info).ordered.with( + { + message: "Started uploading project", + project_id: project.id, + project_name: project.name, + export_size: export_size + } + ) + + expect(logger).to receive(:info).ordered.with( + { + message: "Finished uploading project", + project_id: project.id, + project_name: project.name, + export_size: export_size, + upload_duration: anything + } + ) + end - expect(project.export_status).to eq(:finished) + strategy.execute(user, project) end end @@ -64,5 +95,124 @@ RSpec.describe Gitlab::ImportExport::AfterExportStrategies::WebUploadStrategy do expect(errors.first).to eq "Error uploading the project. Code 404: Page not found" end end + + context 'when object store is disabled' do + it 'reads file from disk and uploads to external url' do + stub_request(:post, example_url).to_return(status: 200) + expect(Gitlab::ImportExport::RemoteStreamUpload).not_to receive(:new) + expect(Gitlab::HttpIO).not_to receive(:new) + + strategy.execute(user, project) + + expect(a_request(:post, example_url)).to have_been_made + end + end + + context 'when object store is enabled' do + before do + object_store_url = 'http://object-storage/project.tar.gz' + stub_uploads_object_storage(FileUploader) + stub_request(:get, object_store_url) + stub_request(:post, example_url) + allow(import_export_upload.export_file).to receive(:url).and_return(object_store_url) + allow(import_export_upload.export_file).to receive(:file_storage?).and_return(false) + end + + it 'reads file using Gitlab::HttpIO and uploads to external url' do + expect_next_instance_of(Gitlab::HttpIO) do |http_io| + expect(http_io).to receive(:read).and_call_original + end + expect(Gitlab::ImportExport::RemoteStreamUpload).not_to receive(:new) + + strategy.execute(user, project) + + expect(a_request(:post, example_url)).to have_been_made + end + end + + context 'when `import_export_web_upload_stream` feature is enabled' do + before do + stub_feature_flags(import_export_web_upload_stream: true) + end + + context 'when remote object store is disabled' do + it 'reads file from disk and uploads to external url' do + stub_request(:post, example_url).to_return(status: 200) + expect(Gitlab::ImportExport::RemoteStreamUpload).not_to receive(:new) + expect(Gitlab::HttpIO).not_to receive(:new) + + strategy.execute(user, project) + + expect(a_request(:post, example_url)).to have_been_made + end + end + + context 'when object store is enabled' do + let(:object_store_url) { 'http://object-storage/project.tar.gz' } + + before do + stub_uploads_object_storage(FileUploader) + + allow(import_export_upload.export_file).to receive(:url).and_return(object_store_url) + allow(import_export_upload.export_file).to receive(:file_storage?).and_return(false) + end + + it 'uploads file as a remote stream' do + arguments = { + download_url: object_store_url, + upload_url: example_url, + options: { + upload_method: :post, + upload_content_type: 'application/gzip' + } + } + + expect_next_instance_of(Gitlab::ImportExport::RemoteStreamUpload, arguments) do |remote_stream_upload| + expect(remote_stream_upload).to receive(:execute) + end + expect(Gitlab::HttpIO).not_to receive(:new) + + strategy.execute(user, project) + end + + context 'when upload as remote stream raises an exception' do + before do + allow_next_instance_of(Gitlab::ImportExport::RemoteStreamUpload) do |remote_stream_upload| + allow(remote_stream_upload).to receive(:execute).and_raise( + Gitlab::ImportExport::RemoteStreamUpload::StreamError.new('Exception error message', 'Response body') + ) + end + end + + it 'logs the exception and stores the error message' do + expect_next_instance_of(Gitlab::Export::Logger) do |logger| + expect(logger).to receive(:error).ordered.with( + { + project_id: project.id, + project_name: project.name, + message: 'Exception error message', + response_body: 'Response body' + } + ) + + expect(logger).to receive(:error).ordered.with( + { + project_id: project.id, + project_name: project.name, + message: 'After export strategy failed', + 'exception.class' => 'Gitlab::ImportExport::RemoteStreamUpload::StreamError', + 'exception.message' => 'Exception error message', + 'exception.backtrace' => anything + } + ) + end + + strategy.execute(user, project) + + expect(project.import_export_shared.errors.first).to eq('Exception error message') + end + end + end + end end end |