Commit e3acc982 authored by Bob Van Landuyt's avatar Bob Van Landuyt

Override values from JSON with import data

This overrides values defined in the project JSON with the values
provided in project.import_data.data['override_params'].

These could be passed from the API.
parent e40c0085
---
title: Allow overriding params on project import through API
merge_request: 18086
author:
type: added
...@@ -111,6 +111,9 @@ POST /projects/import ...@@ -111,6 +111,9 @@ POST /projects/import
| `namespace` | integer/string | no | The ID or path of the namespace that the project will be imported to. Defaults to the current user's namespace | | `namespace` | integer/string | no | The ID or path of the namespace that the project will be imported to. Defaults to the current user's namespace |
| `file` | string | yes | The file to be uploaded | | `file` | string | yes | The file to be uploaded |
| `path` | string | yes | Name and path for new project | | `path` | string | yes | Name and path for new project |
| `override_params` | Hash | no | Supports all fields defined in the [Project API](projects.md)] |
The override params passed will take precendence over all values defined inside the export file.
To upload a file from your filesystem, use the `--form` argument. This causes To upload a file from your filesystem, use the `--form` argument. This causes
cURL to post data using the header `Content-Type: multipart/form-data`. cURL to post data using the header `Content-Type: multipart/form-data`.
......
...@@ -77,13 +77,13 @@ module Gitlab ...@@ -77,13 +77,13 @@ module Gitlab
end end
def default_relation_list def default_relation_list
Gitlab::ImportExport::Reader.new(shared: @shared).tree.reject do |model| reader.tree.reject do |model|
model.is_a?(Hash) && model[:project_members] model.is_a?(Hash) && model[:project_members]
end end
end end
def restore_project def restore_project
params = project_params params = project_params.symbolize_keys
if params[:description].present? if params[:description].present?
params[:description_html] = nil params[:description_html] = nil
...@@ -94,7 +94,20 @@ module Gitlab ...@@ -94,7 +94,20 @@ module Gitlab
end end
def project_params def project_params
@tree_hash.reject do |key, value| @project_params ||= json_params.merge(override_params)
end
def override_params
return {} unless params = @project.import_data&.data&.fetch('override_params')
@override_params ||= params.select do |key, _value|
Project.column_names.include?(key.to_s) &&
!reader.project_tree[:except].include?(key.to_sym)
end
end
def json_params
@json_params ||= @tree_hash.reject do |key, value|
# return params that are not 1 to many or 1 to 1 relations # return params that are not 1 to many or 1 to 1 relations
value.respond_to?(:each) && !Project.column_names.include?(key) value.respond_to?(:each) && !Project.column_names.include?(key)
end end
...@@ -181,6 +194,10 @@ module Gitlab ...@@ -181,6 +194,10 @@ module Gitlab
relation_hash.merge(params) relation_hash.merge(params)
end end
def reader
@reader ||= Gitlab::ImportExport::Reader.new(shared: @shared)
end
end end
end end
end end
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
"description": "Nisi et repellendus ut enim quo accusamus vel magnam.", "description": "Nisi et repellendus ut enim quo accusamus vel magnam.",
"visibility_level": 10, "visibility_level": 10,
"archived": false, "archived": false,
"description_html": "description", "description_html": "<p dir=\"auto\">Nisi et repellendus ut enim quo accusamus vel magnam.</p>",
"labels": [ "labels": [
{ {
"id": 2, "id": 2,
......
...@@ -47,7 +47,8 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do ...@@ -47,7 +47,8 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
end end
it 'has the project html description' do it 'has the project html description' do
expect(Project.find_by_path('project').description_html).to eq('description') expected_description_html = "<p dir=\"auto\">Nisi et repellendus ut enim quo accusamus vel magnam.</p>"
expect(Project.find_by_path('project').description_html).to eq(expected_description_html)
end end
it 'has the same label associated to two issues' do it 'has the same label associated to two issues' do
...@@ -317,6 +318,24 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do ...@@ -317,6 +318,24 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
end end
end end
context 'when the project has overriden params in import data' do
it 'overwrites the params stored in the JSON' do
project.create_import_data(data: { override_params: { description: "Overridden" } })
restored_project_json
expect(project.description).to eq("Overridden")
end
it 'does not allow setting params that are excluded from import_export settings' do
project.create_import_data(data: { override_params: { lfs_enabled: true } })
restored_project_json
expect(project.lfs_enabled).to be_nil
end
end
context 'with a project that has a group' do context 'with a project that has a group' do
let!(:project) do let!(:project) do
create(:project, create(:project,
......
...@@ -71,7 +71,7 @@ describe API::ProjectImport do ...@@ -71,7 +71,7 @@ describe API::ProjectImport do
expect(json_response['error']).to eq('file is invalid') expect(json_response['error']).to eq('file is invalid')
end end
it 'allows overriding project params' do it 'stores params that can be overridden' do
stub_import(namespace) stub_import(namespace)
override_params = { 'description' => 'Hello world' } override_params = { 'description' => 'Hello world' }
...@@ -85,7 +85,7 @@ describe API::ProjectImport do ...@@ -85,7 +85,7 @@ describe API::ProjectImport do
expect(import_project.import_data.data['override_params']).to eq(override_params) expect(import_project.import_data.data['override_params']).to eq(override_params)
end end
it 'does store params that are not allowed' do it 'does not store params that are not allowed' do
stub_import(namespace) stub_import(namespace)
override_params = { 'not_allowed' => 'Hello world' } override_params = { 'not_allowed' => 'Hello world' }
...@@ -99,6 +99,21 @@ describe API::ProjectImport do ...@@ -99,6 +99,21 @@ describe API::ProjectImport do
expect(import_project.import_data.data['override_params']).to be_empty expect(import_project.import_data.data['override_params']).to be_empty
end end
it 'correctly overrides params during the import' do
override_params = { 'description' => 'Hello world' }
Sidekiq::Testing.inline! do
post api('/projects/import', user),
path: 'test-import',
file: fixture_file_upload(file),
namespace: namespace.id,
override_params: override_params
end
import_project = Project.find(json_response['id'])
expect(import_project.description).to eq('Hello world')
end
def stub_import(namespace) def stub_import(namespace)
expect_any_instance_of(Project).to receive(:import_schedule) expect_any_instance_of(Project).to receive(:import_schedule)
expect(::Projects::CreateService).to receive(:new).with(user, hash_including(namespace_id: namespace.id)).and_call_original expect(::Projects::CreateService).to receive(:new).with(user, hash_including(namespace_id: namespace.id)).and_call_original
......
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