Commit 0db58ea8 authored by Nick Thomas's avatar Nick Thomas

Merge branch '37256-bump-wh-version' into 'master'

Enable workhorse upload acceleration for Project Import uploads via API

See merge request gitlab-org/gitlab!26914
parents 26e13666 1a1c954a
---
title: Enable Workhorse upload acceleration for Project Import uploads via API
merge_request: 26914
author:
type: performance
...@@ -4,42 +4,41 @@ require 'spec_helper' ...@@ -4,42 +4,41 @@ require 'spec_helper'
describe API::ProjectImport do describe API::ProjectImport do
include ExternalAuthorizationServiceHelpers include ExternalAuthorizationServiceHelpers
include WorkhorseHelpers
let(:export_path) { "#{Dir.tmpdir}/project_export_spec" }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:file) { File.join('spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') }
let(:namespace) { create(:group) } let(:namespace) { create(:group) }
before do let(:file) { File.join('spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') }
allow_next_instance_of(Gitlab::ImportExport) do |instance| let(:file_name) { 'project_export.tar.gz' }
allow(instance).to receive(:storage_path).and_return(export_path)
end
namespace.add_owner(user)
end
after do let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
FileUtils.rm_rf(export_path, secure: true) let(:workhorse_headers) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
end
describe 'POST /projects/import' do let(:file_upload) { fixture_file_upload(file) }
let(:override_params) { { 'external_authorization_classification_label' => 'Hello world' } }
before do before do
enable_external_authorization_service_check enable_external_authorization_service_check
stub_licensed_features(external_authorization_service_api_management: true) stub_licensed_features(external_authorization_service_api_management: true)
namespace.add_owner(user)
end end
subject do describe 'POST /projects/import' do
Sidekiq::Testing.inline! do let(:params) do
post api('/projects/import', user), {
params: {
path: 'test-import', path: 'test-import',
file: fixture_file_upload(file),
namespace: namespace.id, namespace: namespace.id,
override_params: override_params override_params: override_params
} }
end end
let(:override_params) { { 'external_authorization_classification_label' => 'Hello world' } }
subject do
Sidekiq::Testing.inline! do
upload_archive(file_upload, workhorse_headers, params)
end
end end
it 'overrides the classification label' do it 'overrides the classification label' do
...@@ -62,4 +61,15 @@ describe API::ProjectImport do ...@@ -62,4 +61,15 @@ describe API::ProjectImport do
end end
end end
end end
def upload_archive(file, headers = {}, params = {})
workhorse_finalize(
api("/projects/import", user),
method: :post,
file_key: :file,
params: params.merge(file: file_upload),
headers: headers,
send_rewritten_field: true
)
end
end end
...@@ -4,11 +4,12 @@ module API ...@@ -4,11 +4,12 @@ module API
module Helpers module Helpers
module FileUploadHelpers module FileUploadHelpers
def file_is_valid? def file_is_valid?
params[:file] && params[:file]['tempfile'].respond_to?(:read) filename = params[:file]&.original_filename
filename && ImportExportUploader::EXTENSION_WHITELIST.include?(File.extname(filename).delete('.'))
end end
def validate_file! def validate_file!
render_api_error!('Uploaded file is invalid', 400) unless file_is_valid? render_api_error!({ error: _('You need to upload a GitLab project export archive (ending in .gz).') }, 422) unless file_is_valid?
end end
end end
end end
......
...@@ -21,10 +21,6 @@ module API ...@@ -21,10 +21,6 @@ module API
def rate_limiter def rate_limiter
::Gitlab::ApplicationRateLimiter ::Gitlab::ApplicationRateLimiter
end end
def with_workhorse_upload_acceleration?
request.headers[Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER].present?
end
end end
before do before do
...@@ -46,11 +42,7 @@ module API ...@@ -46,11 +42,7 @@ module API
params do params do
requires :path, type: String, desc: 'The new project path and name' requires :path, type: String, desc: 'The new project path and name'
# TODO: remove rubocop disable - https://gitlab.com/gitlab-org/gitlab/issues/14960 requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The project export file to be imported'
# and mark WH fields as required (instead of optional) after the WH version including
# https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/459
# is deployed and GITLAB_WORKHORSE_VERSION is updated accordingly.
requires :file, types: [::API::Validations::Types::WorkhorseFile, File], desc: 'The project export file to be imported' # rubocop:disable Scalability/FileUploads
optional :name, type: String, desc: 'The name of the project to be imported. Defaults to the path of the project if not provided.' optional :name, type: String, desc: 'The name of the project to be imported. Defaults to the path of the project if not provided.'
optional :namespace, type: String, desc: "The ID or name of the namespace that the project will be imported into. Defaults to the current user's namespace." optional :namespace, type: String, desc: "The ID or name of the namespace that the project will be imported into. Defaults to the current user's namespace."
optional :overwrite, type: Boolean, default: false, desc: 'If there is a project in the same namespace and with the same name overwrite it' optional :overwrite, type: Boolean, default: false, desc: 'If there is a project in the same namespace and with the same name overwrite it'
...@@ -75,7 +67,7 @@ module API ...@@ -75,7 +67,7 @@ module API
success Entities::ProjectImportStatus success Entities::ProjectImportStatus
end end
post 'import' do post 'import' do
require_gitlab_workhorse! if with_workhorse_upload_acceleration? require_gitlab_workhorse!
key = "project_import".to_sym key = "project_import".to_sym
...@@ -87,27 +79,19 @@ module API ...@@ -87,27 +79,19 @@ module API
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42437') Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42437')
validate_file!
namespace = if import_params[:namespace] namespace = if import_params[:namespace]
find_namespace!(import_params[:namespace]) find_namespace!(import_params[:namespace])
else else
current_user.namespace current_user.namespace
end end
# TODO: remove the condition after the WH version including
# https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/459
# is deployed and GITLAB_WORKHORSE_VERSION is updated accordingly.
file = if with_workhorse_upload_acceleration?
import_params[:file] || bad_request!('Unable to process project import file')
else
validate_file!
import_params[:file]['tempfile']
end
project_params = { project_params = {
path: import_params[:path], path: import_params[:path],
namespace_id: namespace.id, namespace_id: namespace.id,
name: import_params[:name], name: import_params[:name],
file: file, file: import_params[:file],
overwrite: import_params[:overwrite] overwrite: import_params[:overwrite]
} }
......
This diff is collapsed.
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