Import/Export 개발 문서
Import/Export 기능에 대한 일반적인 개발지침과 팁.
본 문서는 YouTube에서 제공되는 Import/Export 201 프레젠테이션을 기반으로 합니다.
더 많은 문맥을 원하신다면 YouTube의 Import/Export 개발 심층 분석을 시청하실 수 있습니다.
보안
Import/Export 기능은 지속적으로 업데이트됩니다(내보낼 새로운 요소를 추가함). 그러나 코드는 오랜 기간 동안 리팩토링되지 않았습니다. 우리는 동적인 성격이 보안 문제의 수를 증가시키지 않도록 코드 감사를 수행해야 합니다. GitLab 팀 멤버들은 이 비밀 이슈에서 더 많은 정보를 확인할 수 있습니다: https://gitlab.com/gitlab-org/gitlab/-/issues/20720
.
코드 내 보안
일부 클래스는 Import/Export에 대한 보안 계층을 제공합니다.
AttributeCleaner
는 모든 금지된 키를 제거합니다.
# AttributeCleaner
# 모든 `_ids` 및 다른 금지된 키를 제거합니다
class AttributeCleaner
ALLOWED_REFERENCES = RelationFactory::PROJECT_REFERENCES + RelationFactory::USER_REFERENCES + ['group_id']
def clean
@relation_hash.reject do |key, _value|
prohibited_key?(key) || !@relation_class.attribute_method?(key) || excluded_key?(key)
end.except('id')
end
...
AttributeConfigurationSpec
은 새 열의 추가를 확인하고 승인합니다.
# AttributeConfigurationSpec
<<-MSG
프로젝트 Import/Export를 사용하여 내보내어진 #{relation_class}에 새로운 속성이 있는 것 같습니다:
SAFE_MODEL_ATTRIBUTES 내에 그 속성(들)을 추가하십시오. 그것(들)이 내보낼 수 있는 경우.
해당 모델을 IMPORT_EXPORT_CONFIG에서 +excluded_attributes+ 섹션에 추가하여 그 속성(들)을 디렉터리에서 제외하십시오.
SAFE_MODEL_ATTRIBUTES: #{File.expand_path(safe_attributes_file)}
IMPORT_EXPORT_CONFIG: #{Gitlab::ImportExport.config_file}
MSG
ModelConfigurationSpec
은 새 모델의 추가를 확인하고 승인합니다.
# ModelConfigurationSpec
<<-MSG
#{parent_model_name}과 관련된 새로운 모델들 <#{new_models.join(',')}>이 Import/Export 기능으로 내보내집니다.
만약 이 모델이 내보내어져야 한다고 생각한다면, `#{Gitlab::ImportExport.config_file}`에 추가하세요.
반드시 `#{File.expand_path(ce_models_yml)}`에 추가하십시오.
이 오류를 처리했음을 신호로 보여주고 향후에 이 오류가 표시되는 것을 방지하기 위해
MSG
ExportFileSpec
은 암호화되거나 민감한 열을 감지합니다.
# ExportFileSpec
<<-MSG
해시 #{parent.inspect}의 일부인 새로운 민감한 단어 <#{key_found}>를 발견했습니다.
만약 이 정보가 내보내어지지 않아야 한다고 생각한다면, IMPORT_EXPORT_CONFIG에서 모델 또는 속성을 제외하십시오.
그렇지 않으면, +safe_list+에 예외를 추가하여 현재 SPEC에서 #{sensitive_word}를 키로 사용하고, 해당 해시 또는 모델을 값으로 사용하십시오.
또한, 해당 속성이 생성된 고유한 토큰이라면, RelationFactory::TOKEN_RESET_MODELS에 추가하여 같은 인스턴스로 가져올 때
중복 열 문제를 방지하기 위해 재설정해야 한다면 추가하세요.
IMPORT_EXPORT_CONFIG: #{Gitlab::ImportExport.config_file}
CURRENT_SPEC: #{__FILE__}
MSG
버전 관리
Import/Export는 단일 GitLab 릴리스 중에 빈번한 상수 변경으로 엄격한 SemVer를 사용하지 않습니다. 중대한 변경이 있을 때 업데이트가 필요합니다.
# ImportExport
module Gitlab
module ImportExport
extend self
# 모든 버전 업데이트마다 import_export.md의 히스토리를 최신 상태로 유지해야 합니다.
VERSION = '0.2.4'
호환성
프로젝트 가져오기 및 내보내기 시 호환성을 확인하세요.
버전을 업그레이드해야 하는 경우
모델/열을 이름을 변경하거나 형식을 변경하는 경우, JSON 구조 또는 아카이브 파일의 파일 구조를 수정해야 합니다.
다음의 경우에는 버전을 업그레이드할 필요가 없습니다:
- 새로운 열 또는 모델 추가
- 열 또는 모델 제거 (DB 제약조건이 없는 경우)
- 새로운 것을(예: 새로운 유형의 업로드) 내보냅니다.
버전을 업그레이드할 때마다 통합 사양이 실패하고 다음 명령으로 수정할 수 있습니다:
bundle exec rake gitlab:import_export:bump_version
코드 빠르게 살펴보기
Import/Export 구성 (import_export.yml
)
주요 구성인 import_export.yml
은 내보내거나 가져올 수 있는 모델을 정의합니다.
프로젝트 내보내기/가져오기에 포함할 모델 관계:
project_tree:
- labels:
- :priorities
- milestones:
- events:
- :push_event_payload
- issues:
- events:
# ...
지정된 모델에 대해 포함할 속성만 포함:
포함된 속성:
사용자:
- :id
- :public_email
# ...
지정된 모델에 대해 제외할 속성을 포함하지 않습니다:
제외된 속성:
프로젝트:
- :name
- :path
- ...
내보내기에 의해 호출될 추가적인 메소드:
# Methods
methods:
labels:
- :type
label:
- :type
모델 관계의 사용자 정의 내보낼 순서:
# 특정 관계에 대한 사용자 정의 내보내기 재정렬 지정
# 예를 들어 problems를 해결하기 위해 issues의 상대적인 위치에 대한 사용자 정의 내보내기 재정렬을 사용하여, 상대적인 위치 값은 재설정할 수 있지만, 여전히 내부로 사용되는 문제가 처리되도록 issues 순서를 내보낸 프로젝트에 있던 순서대로 유지합니다.
# 기본적으로 관계의 정렬은 PK로 수행됩니다.
# column - 재정렬할 열을 지정합니다. 기본적으로 관계의 PK입니다.
# direction - 정렬 방향을 지정합니다 :asc 또는 :desc, 기본값은 :asc입니다
# nulls_position - null 값이 어디에 위치하는지를 지정합니다. 사용자 정의 정렬 열에는 null이 포함될 수 있기 때문에 이번에도 nulls가 위치할 장소를 지정해야 합니다
# :nulls_last 또는 :nulls_first가 될 수 있으며, 기본값은 :nulls_last입니다
내보내기 재정렬:
프로젝트:
이슈:
열: :relative_position
방향: :asc
nulls_position: :nulls_last
조건부 익스포트
프로젝트와 그룹을 익스포트하는 사용자가 외부 리소스에 연결되어 있는 경우, 프로젝트 또는 그룹을 익스포트할 수 있는 사용자인지 확인해야 할 수 있습니다. include_if_exportable
은 리소스에 대한 연결의 배열을 수락합니다. 익스포트 중에 리소스의 exportable_association?
메서드가 연결의 이름과 사용자를 사용하여 연결된 리소스를 익스포트할 수 있는지 유효성을 검사합니다.
예를 들어:
include_if_exportable:
project:
issues:
- epic_issue
이 정의는 다음을 수행합니다.
- 이슈의
exportable_association?(:epic_issue, current_user: current_user)
메서드를 호출합니다. - 메서드가 true를 반환하면 이슈의
epic_issue
연결을 이슈에 포함시킵니다.
가져오기
가져오기 작업 상태는 none
에서 finished
또는 failed
로 다른 상태로 이동합니다:
import_status: none -> scheduled -> started -> finished/failed
상태가 started
인 동안 Importer
코드는 가져오기에 필요한 각 단계를 처리합니다.
# ImportExport::Importer
module Gitlab
module ImportExport
class Importer
def execute
if import_file && check_version! && restorers.all?(&:restore) && overwrite_project
project
else
raise Projects::ImportService::Error.new(@shared.errors.join(', '))
end
rescue => e
raise Projects::ImportService::Error.new(e.message)
ensure
remove_import_file
end
def restorers
[repo_restorer, wiki_restorer, project_tree, avatar_restorer,
uploads_restorer, lfs_restorer, statistics_restorer]
end
익스포트 서비스는 Importer
와 유사하며, 데이터를 저장하는 대신 데이터를 복원합니다.
익스포트
# ImportExport::ExportService
module Projects
module ImportExport
class ExportService < BaseService
def save_all!
if save_services
Gitlab::ImportExport::Saver.save(project: project, shared: @shared)
notify_success
else
cleanup_and_notify_error!
end
end
def save_services
[version_saver, avatar_saver, project_tree_saver, uploads_saver, repo_saver,
wiki_repo_saver, lfs_saver].all?(&:save)
end
테스트 픽스처
Import/Export 스펙에 사용되는 픽스처는 spec/fixtures/lib/gitlab/import_export
에 있습니다. 프로젝트와 그룹 픽스처가 모두 있습니다.
이러한 픽스처의 각 버전에는 두 가지 버전이 있습니다.
- 모든 객체가 포함된 사람이 읽을 수 있는 단일 JSON 파일,
project.json
또는group.json
로 호출되는 파일이 있습니다. -
ndjson
형식의 파일 트리를 포함하는tree
라는 폴더가 있습니다. 이 폴더의 파일을 꼭 필요한 경우를 제외하고는 매뉴얼으로 편집하지 마십시오.
인간이 읽을 수 있는 JSON 파일에서 NDJSON 트리를 생성하는 도구는 gitlab-org/memory-team/team-tools
프로젝트에 있습니다.
프로젝트
legacy-project-json-to-ndjson.sh
를 사용하여 NDJSON 트리를 생성합니다.
NDJSON 트리는 다음과 같은 모습입니다:
tree
├── project
│ ├── auto_devops.ndjson
│ ├── boards.ndjson
│ ├── ci_cd_settings.ndjson
│ ├── ci_pipelines.ndjson
│ ├── container_expiration_policy.ndjson
│ ├── custom_attributes.ndjson
│ ├── error_tracking_setting.ndjson
│ ├── external_pull_requests.ndjson
│ ├── issues.ndjson
│ ├── labels.ndjson
│ ├── merge_requests.ndjson
│ ├── milestones.ndjson
│ ├── pipeline_schedules.ndjson
│ ├── project_badges.ndjson
│ ├── project_feature.ndjson
│ ├── project_members.ndjson
│ ├── protected_branches.ndjson
│ ├── protected_tags.ndjson
│ ├── releases.ndjson
│ ├── services.ndjson
│ ├── snippets.ndjson
│ └── triggers.ndjson
└── project.json
그룹
legacy-group-json-to-ndjson.rb
를 사용하여 NDJSON 트리를 생성합니다.
NDJSON 트리는 다음과 같은 모습입니다:
tree
└── groups
├── 4351
│ ├── badges.ndjson
│ ├── boards.ndjson
│ ├── epics.ndjson
│ ├── labels.ndjson
│ ├── members.ndjson
│ └── milestones.ndjson
├── 4352
│ ├── badges.ndjson
│ ├── boards.ndjson
│ ├── epics.ndjson
│ ├── labels.ndjson
│ ├── members.ndjson
│ └── milestones.ndjson
├── _all.ndjson
├── 4351.json
└── 4352.json
json
파일과 tree
폴더 모두 업데이트하는지 확인하십시오.