project_import_spec.rb 5.97 KB
Newer Older
James Lopez's avatar
James Lopez committed
1 2 3 4 5
require 'spec_helper'

describe API::ProjectImport do
  let(:export_path) { "#{Dir.tmpdir}/project_export_spec" }
  let(:user) { create(:user) }
6
  let(:file) { File.join('spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') }
James Lopez's avatar
James Lopez committed
7
  let(:namespace) { create(:group) }
James Lopez's avatar
James Lopez committed
8 9
  before do
    allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
10 11
    stub_feature_flags(import_export_object_storage: true)
    stub_uploads_object_storage(FileUploader)
James Lopez's avatar
James Lopez committed
12

James Lopez's avatar
James Lopez committed
13
    namespace.add_owner(user)
James Lopez's avatar
James Lopez committed
14 15 16 17 18 19
  end

  after do
    FileUtils.rm_rf(export_path, secure: true)
  end

James Lopez's avatar
James Lopez committed
20
  describe 'POST /projects/import' do
James Lopez's avatar
James Lopez committed
21
    it 'schedules an import using a namespace' do
22
      stub_import(namespace)
James Lopez's avatar
James Lopez committed
23

James Lopez's avatar
James Lopez committed
24 25 26 27 28 29
      post api('/projects/import', user), path: 'test-import', file: fixture_file_upload(file), namespace: namespace.id

      expect(response).to have_gitlab_http_status(201)
    end

    it 'schedules an import using the namespace path' do
30
      stub_import(namespace)
James Lopez's avatar
James Lopez committed
31

James Lopez's avatar
James Lopez committed
32
      post api('/projects/import', user), path: 'test-import', file: fixture_file_upload(file), namespace: namespace.full_path
James Lopez's avatar
James Lopez committed
33

James Lopez's avatar
James Lopez committed
34
      expect(response).to have_gitlab_http_status(201)
James Lopez's avatar
James Lopez committed
35
    end
James Lopez's avatar
James Lopez committed
36 37

    it 'schedules an import at the user namespace level' do
38
      stub_import(user.namespace)
James Lopez's avatar
James Lopez committed
39 40 41 42 43 44

      post api('/projects/import', user), path: 'test-import2', file: fixture_file_upload(file)

      expect(response).to have_gitlab_http_status(201)
    end

45
    it 'does not schedule an import for a namespace that does not exist' do
46
      expect_any_instance_of(Project).not_to receive(:import_schedule)
47
      expect(::Projects::CreateService).not_to receive(:new)
48 49 50 51 52 53 54

      post api('/projects/import', user), namespace: 'nonexistent', path: 'test-import2', file: fixture_file_upload(file)

      expect(response).to have_gitlab_http_status(404)
      expect(json_response['message']).to eq('404 Namespace Not Found')
    end

James Lopez's avatar
James Lopez committed
55 56 57 58 59 60 61 62
    it 'does not schedule an import if the user has no permission to the namespace' do
      expect_any_instance_of(Project).not_to receive(:import_schedule)

      post(api('/projects/import', create(:user)),
           path: 'test-import3',
           file: fixture_file_upload(file),
           namespace: namespace.full_path)

63 64
      expect(response).to have_gitlab_http_status(404)
      expect(json_response['message']).to eq('404 Namespace Not Found')
James Lopez's avatar
James Lopez committed
65 66 67 68 69 70 71 72 73 74
    end

    it 'does not schedule an import if the user uploads no valid file' do
      expect_any_instance_of(Project).not_to receive(:import_schedule)

      post api('/projects/import', user), path: 'test-import3', file: './random/test'

      expect(response).to have_gitlab_http_status(400)
      expect(json_response['error']).to eq('file is invalid')
    end
75

76
    it 'stores params that can be overridden' do
77 78 79 80 81 82 83 84 85 86 87 88 89
      stub_import(namespace)
      override_params = { 'description' => 'Hello world' }

      post api('/projects/import', user),
           path: 'test-import',
           file: fixture_file_upload(file),
           namespace: namespace.id,
           override_params: override_params
      import_project = Project.find(json_response['id'])

      expect(import_project.import_data.data['override_params']).to eq(override_params)
    end

90
    it 'does not store params that are not allowed' do
91 92 93 94 95 96 97 98 99 100 101 102 103
      stub_import(namespace)
      override_params = { 'not_allowed' => 'Hello world' }

      post api('/projects/import', user),
           path: 'test-import',
           file: fixture_file_upload(file),
           namespace: namespace.id,
           override_params: override_params
      import_project = Project.find(json_response['id'])

      expect(import_project.import_data.data['override_params']).to be_empty
    end

104 105 106
    it 'correctly overrides params during the import' do
      override_params = { 'description' => 'Hello world' }

107
      perform_enqueued_jobs do
108 109 110 111 112 113 114 115 116 117 118
        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

119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
    context 'when target path already exists in namespace' do
      let(:existing_project) { create(:project, namespace: user.namespace) }

      it 'does not schedule an import' do
        expect_any_instance_of(Project).not_to receive(:import_schedule)

        post api('/projects/import', user), path: existing_project.path, file: fixture_file_upload(file)

        expect(response).to have_gitlab_http_status(400)
        expect(json_response['message']).to eq('Name has already been taken')
      end

      context 'when param overwrite is true' do
        it 'schedules an import' do
          stub_import(user.namespace)

          post api('/projects/import', user), path: existing_project.path, file: fixture_file_upload(file), overwrite: true

          expect(response).to have_gitlab_http_status(201)
        end
      end
    end

142 143
    def stub_import(namespace)
      expect_any_instance_of(Project).to receive(:import_schedule)
144
      expect(::Projects::CreateService).to receive(:new).with(user, hash_including(namespace_id: namespace.id)).and_call_original
145
    end
James Lopez's avatar
James Lopez committed
146 147 148 149
  end

  describe 'GET /projects/:id/import' do
    it 'returns the import status' do
150
      project = create(:project, :import_started)
151
      project.add_maintainer(user)
James Lopez's avatar
James Lopez committed
152 153 154 155

      get api("/projects/#{project.id}/import", user)

      expect(response).to have_gitlab_http_status(200)
James Lopez's avatar
James Lopez committed
156
      expect(json_response).to include('import_status' => 'started')
James Lopez's avatar
James Lopez committed
157 158 159
    end

    it 'returns the import status and the error if failed' do
160
      project = create(:project, :import_failed)
161
      project.add_maintainer(user)
Lin Jen-Shin's avatar
Lin Jen-Shin committed
162
      project.import_state.update(last_error: 'error')
James Lopez's avatar
James Lopez committed
163 164 165 166

      get api("/projects/#{project.id}/import", user)

      expect(response).to have_gitlab_http_status(200)
James Lopez's avatar
James Lopez committed
167
      expect(json_response).to include('import_status' => 'failed',
James Lopez's avatar
James Lopez committed
168
                                       'import_error' => 'error')
James Lopez's avatar
James Lopez committed
169
    end
James Lopez's avatar
James Lopez committed
170 171
  end
end