직접 전송 가져오기 도구에 새로운 관계 추가하기
높은 수준에서, 직접 전송 가져오기 도구에 새로운 관계를 추가하려면 다음을 수행해야 합니다:
- 내보낼 데이터 목록에 새로운 관계를 추가합니다.
- 가져오기 측에 데이터 처리 지침이 있는 새 ETL(추출/변환/로드) 파이프라인을 추가합니다.
- 새로 생성된 파이프라인을 가져오기 단계 목록에 추가합니다.
- 충분한 테스트 범위를 보장합니다.
소스에서 내보내기
내보내는 관계의 유형은 몇 가지가 있습니다:
- ActiveRecord 연관.
import_export.yml
파일에서 읽어 JSON으로 직렬화하여 NDJSON 파일에 기록합니다. 각 관계는.gz
파일에 내보내지거나, 컬렉션의 경우.tar.gz
파일로 내보내지며, 업로드되고 GitLab의 목적지 인스턴스의 REST API를 사용하여 다운로드 및 가져오기됩니다. - 이진 파일. 예를 들어, 업로드 또는 LFS 객체.
- 수동으로 내보내지지 않고 가져오는 동안 GraphQL API에서 직접 읽는 몇 가지 관계.
ActiveRecord 연관의 경우 성능상의 이유로 NDJSON을 GraphQL API보다 사용해야 합니다. 심하게 중첩된 연관은 많은 네트워크 요청을 생성할 수 있으며 전체 마이그레이션 속도를 느리게 할 수 있습니다.
ActiveRecord 관계 내보내기
직접 전송 가져오기 도구의 기본 동작은 파일 기반 가져오기 도구에 크게 의존하며, 내보내기에 포함될 Project
연관 목록을 설명하는 import_export.yml
파일을 사용합니다. Group
에 대해 비슷한 import_export.yml
도 사용할 수 있습니다.
예를 들어, 새로운 Project
연관인 documents
가 있다고 가정해 보겠습니다. 이 새로운 연관을 가져오기 지원을 추가하려면 다음을 수행해야 합니다:
-
import_export.yml
파일에 추가합니다. - 새 관계에 대한 테스트 범위를 추가합니다.
- 추가된 관계가 예상대로 내보내지고 있는지 확인합니다.
import_export.yml
파일에 추가하기
참고: 이 파일에 나열된 연관은 위에서 아래로 가져옵니다. 순서에 의존하는 연관이 있는 경우, 해당 연관을 요구하는 연관 앞에 의존성을 배치해야 합니다. 예를 들어, 문서는 병합 요청보다 먼저 가져와야 하며, 그렇지 않으면 유효하지 않습니다.
-
import_export.yml
안의tree.project
에 연관을 추가합니다.diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml index 43d66e0e67b7..0880a27dfce2 100644 --- a/lib/gitlab/import_export/project/import_export.yml +++ b/lib/gitlab/import_export/project/import_export.yml @@ -122,6 +122,7 @@ tree: - label: - :priorities - :service_desk_setting + - :documents group_members: - :user
참고: 귀하의 연관이 엔터프라이즈 에디션 전용 기능과 관련이 있는 경우, 파일 끝에
ee.tree.project
트리에 추가하여 엔터프라이즈 에디션 인스턴스의 GitLab에서만 내보내고 가져올 수 있도록 해야 합니다.귀하의 연관에 하위 관계를 포함할 필요가 없다면, 이것으로 충분합니다. 하지만 더 많은 하위 관계를 포함해야 하는 경우(예: 노트), 그것들을 나열해야 합니다. 문서에는 노트(노트에 상금 아이콘이 있는)와 상금 아이콘(문서에 있는)을 포함할 수 있다고 가정해 보겠습니다. 이 경우 우리의 관계는 다음과 같이 됩니다:
diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml index 43d66e0e67b7..0880a27dfce2 100644 --- a/lib/gitlab/import_export/project/import_export.yml +++ b/lib/gitlab/import_export/project/import_export.yml @@ -122,6 +122,7 @@ tree: - label: - :priorities - :service_desk_setting + - documents: - :award_emoji - notes: - :award_emoji group_members: - :user
-
관계의
included_attributes
를 추가합니다. 기본적으로 YAML 파일의included_attributes
에 나열되지 않은 모든 관계 속성은 내보내기 및 가져오기에서 필터링됩니다. 필요한 속성을 포함하려면included_attributes
목록에 추가해야 합니다:diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml index 43d66e0e67b7..dbf0e1275ecf 100644 --- a/lib/gitlab/import_export/project/import_export.yml +++ b/lib/gitlab/import_export/project/import_export.yml @@ -142,6 +142,9 @@ import_only_tree: # 지정된 모델에 대해 다음 속성만 포함합니다. included_attributes: + documents: + - :title + - :description user: - :id - :public_email
-
관계의
excluded_attributes
를 추가합니다. 파일에 존재하는excluded_attributes
목록도 있습니다.Project
의 경우 제외된 속성을 추가할 필요는 없지만Group
의 경우에는 여전히 필요합니다. 이 목록은 내보내기에 포함되지 않아야 하며 가져올 때 무시해야 하는 속성을 나타냅니다. 이러한 속성은 일반적으로 다음을 포함합니다:-
_id
또는_ids
로 끝나는 모든 것 -
attributes
(사용자 정의 속성 제외)를 포함하는 모든 것 -
_html
로 끝나는 모든 것 - 민감한 모든 것(예: 토큰, 암호화된 데이터)
금지된 참조의 전체 목록은 여기에서 확인할 수 있습니다.
-
-
관계의
methods
를 추가합니다. 연관에 내보내야 하는 메서드(예:document.signature
)가 있는 경우methods
섹션에 추가할 수 있습니다. 내보낸 값은 내보내고 가져올 때 사용할 수 있습니다. 예를 들어, 내보낸 값으로 필드를 할당할 수 있습니다.
예를 들어, note_diff_file.diff_export
메서드의 반환 값을 내보내고 가져올 때 이 메서드의 내보낸 값을 설정할 수 있습니다.
새로운 관계에 대한 테스트 커버리지 추가
직접 전송이 저수준의 파일 기반 가져오기(importer)를 사용하므로, 파일 기반 가져오기(importer)의 범위 내에서 새로운 관계에 대한 테스트 커버리지를 추가해야 하며, 여기에는 직접 전송 가져오기(importer)의 내보내기 측면도 포함됩니다. 다음에 테스트를 추가하세요:
-
spec/lib/gitlab/import_export/project/tree_saver_spec.rb
.Group
에 대한 유사한 파일이 있습니다. -
ee/spec/lib/ee/gitlab/import_export/project/tree_saver_spec.rb
는 EE 전용 관계에 해당합니다.
다른 관계의 예를 따라 새로운 테스트를 추가하세요.
추가된 관계가 예상대로 내보내지고 있는지 확인
import_export.yml
에 지정된 새로 추가된 관계는 디스크에 작성된 내보내기 파일에 자동으로 추가되므로, 추가적인 작업은 필요 없습니다.
관계를 추가하고 테스트를 추가한 후에는 수동으로 관계가 내보내지는지 확인할 수 있습니다. 다음 두 곳에 자동으로 포함되어야 합니다:
-
파일 기반 가져오기 및 내보내기. 프로젝트 내보내기 기능을 사용하여 내보내고, 다운로드하고, 내보낸 데이터를 검사하세요.
-
직접 전송 내보내기.
export_relations
API를 사용하여 내보내고, 다운로드하고, 내보낸 관계를 검사하세요
(일괄로 내보낼 수 있습니다).
이진 관계 내보내기
이진 관계에 대한 지원을 추가하는 경우:
-
디스크에서 내보내기를 수행하는 새로운 내보내기 서비스를 생성합니다. 예제는
BulkImports::LfsObjectsExportService
를 참조하세요. -
관계를
file_relations
목록에 추가하세요. -
관계를
BulkImports::FileExportService
에 추가하세요.
목적지에서 가져오기
위에서 언급한 바와 같이, 직접 전송 가져오기에는 세 가지 종류의 관계가 있습니다:
-
export_relations
API에서 다운로드된 NDJSON 내보내기 관계. 예:documents.ndjson.gz
. -
GraphQL API 관계. 예:
members
정보는 GraphQL을 사용하여 그룹 및 프로젝트 사용자 회원 정보를 가져옵니다. -
export_relations
API에서 다운로드된 이진 관계. 예:lfs_objects.tar.gz
.
직접 전송 가져오기(importer)는 추출/변환/적재 데이터 처리 기술을 기반으로 하기 때문에, 관계를 가져오려면 다음을 정의해야 합니다:
-
새로운 관계 가져오기 파이프라인. 예:
DocumentsPipeline
. -
파이프라인이 데이터를 어디서 어떻게 추출할지를 아는 데이터 추출기. 예:
NdjsonPipeline
. -
데이터를 필요한 형식으로 변환하는 클래스 집합인 변환기 목록.
-
데이터를 영구적으로 저장하는 로더. 예: 데이터베이스에 행을 저장하거나 새로운 LFS 객체를 생성합니다.
가져오는 관계의 유형에 관계없이, 파이프라인 클래스 구조는 동일합니다:
module BulkImports
module Common
module Pipelines
class DocumentsPipeline
include Pipeline
def extract(context)
BulkImports::Pipeline::ExtractedData.new(data: file_paths)
end
def transform(context, object)
...
end
def load(context, object)
document.save!
end
end
end
end
end
NDJSON에서 관계 가져오기
파이프라인 정의하기
이전 예에서, 우리의 documents
관계는 NDJSON 파일로 내보내집니다. 이 경우 다음 두 가지를 사용할 수 있습니다:
-
NdjsonPipeline
, JSON을 ActiveRecord 객체로 자동으로 변환하는 데이터 변환을 포함하고 있으며(내부적으로 파일 기반 가져오기 사용). -
NdjsonExtractor
,/export_relations/download
REST API 엔드포인트를 사용하여 소스 인스턴스에서.ndjson.gz
파일을 다운로드합니다.
ETL 파이프라인의 각 단계는 메서드 또는 클래스 형태로 정의할 수 있습니다.
class DocumentsPipeline
include NdjsonPipeline
relation_name 'documents'
extractor ::BulkImports::Common::Extractors::NdjsonExtractor, relation: relation
end
이 새로운 파이프라인은 이제:
- 소스 인스턴스에서
documents.ndjson.gz
파일을 다운로드합니다. - NDJSON 파일의 내용을 읽고 JSON을 역직렬화하여 ActiveRecord 객체로 변환합니다.
- 데이터베이스에 프로젝트 범위 내에서 저장합니다.
파이프라인은 다음 중 하나에 배치될 수 있습니다:
-
BulkImports::Common::Pipelines
네임스페이스에, 그룹 및 프로젝트 마이그레이션에서 공유되고 사용될 경우. 예를 들어,LabelsPipeline
은 공통 파이프라인이며 그룹과 프로젝트 단계 목록 모두에서 참조됩니다. - 프로젝트 마이그레이션에 속하는 경우
BulkImports::Projects::Pipelines
네임스페이스에. - 그룹 마이그레이션에 속하는 경우
BulkImports::Groups::Pipelines
네임스페이스에.
단계에 새로운 파이프라인 추가하기
직접 전송 가져오기 도구는 단계별로 그룹과 프로젝트의 마이그레이션을 수행합니다. 단계 목록은 다음에 정의되어 있습니다:
-
Project
:lib/bulk_imports/projects/stage.rb
. -
Group
:lib/bulk_imports/groups/stage.rb
.
각 단계는:
- 병렬로 실행되는 여러 파이프라인을 가질 수 있습니다.
- 다음 단계로 이동하기 전에 완전히 완료되어야 합니다.
우리의 파이프라인을 Project
단계에 추가해 봅시다:
module BulkImports
module Projects
class Stage < ::BulkImports::Stage
private
def config
{
project: {
pipeline: BulkImports::Projects::Pipelines::ProjectPipeline,
stage: 0
},
repository: {
pipeline: BulkImports::Projects::Pipelines::RepositoryPipeline,
maximum_source_version: '15.0.0',
stage: 1
},
documents: {
pipeline: BulkImports::Projects::Pipelines::DocumentsPipeline,
minimum_source_version: '16.11.0',
stage: 2
}
end
end
end
end
우리는 다음과 같이 지정했습니다:
-
stage: 2
, 따라서 프로젝트와 리포지토리 단계가 먼저 완료되어야 우리 파이프라인이 단계 2에서 실행됩니다. -
minimum_source_version: '16.11.0'
. 이 이정표에서 내보내기를 위한documents
관계를 도입했기 때문에 이전 GitLab 버전에서는 사용할 수 없습니다. 따라서 이 파이프라인은 소스 버전이 16.11 이상인 경우에만 실행됩니다.
maximum_source_version
속성을 지정할 수 있습니다.테스트로 파이프라인 커버하기
우리는 이미 내보내기 측을 테스트하여 커버했기 때문에, 가져오기 측도 동일하게 해야 합니다. 직접 전송 가져오기 도구의 경우 각 파이프라인은 이 예제와 유사한 별도의 사양 파일을 가집니다.
GraphQL API에서 관계 가져오기
관계가 GraphQL API를 통해 사용 가능한 경우, GraphQlExtractor
를 사용하여 파이프라인 클래스 내에서 변환 및 로딩을 수행할 수 있습니다.
MembersPipeline
예제:
module BulkImports
module Common
module Pipelines
class MembersPipeline
include Pipeline
transformer Common::Transformers::ProhibitedAttributesTransformer
transformer Common::Transformers::MemberAttributesTransformer
def extract(context)
graphql_extractor.extract(context)
end
def load(_context, data)
...
member.save!
end
private
def graphql_extractor
@graphql_extractor ||= BulkImports::Common::Extractors::GraphqlExtractor
.new(query: BulkImports::Common::Graphql::GetMembersQuery)
end
end
end
end
end
나머지 단계는 위의 단계와 동일합니다.
이진 관계 가져오기
이진 관계 파이프라인은 다른 파이프라인과 동일한 구조를 가지고 있으며, extract/transform/load 단계에서 발생하는 일을 정의하기만 하면 됩니다.
LfsObjectsPipeline
예제:
module BulkImports
module Common
module Pipelines
class LfsObjectsPipeline
include Pipeline
file_extraction_pipeline!
def extract(_context)
download_service.execute
decompression_service.execute
extraction_service.execute
...
end
def load(_context, file_path)
...
lfs_object.save!
end
end
end
end
end
데이터 다운로드를 돕기 위한 여러 헬퍼 서비스 클래스가 있습니다:
-
BulkImports::FileDownloadService
: 주어진 위치에서 파일을 다운로드합니다. -
BulkImports::FileDecompressionService
: 필요한 검증을 포함한 Gzip 압축 해제 서비스입니다. -
BulkImports::ArchiveExtractionService
: Tar 압축 해제 서비스입니다.