docs: add Pulp integration guide; stop tracking MANUAL.md

- PULP_INTEGRATION.md: 실제 Pulp 연동 절차(서버 준비·Remote/Repo/Distribution·환경변수)
  + 실서버 첫 연동 시 필드 매핑 보정 체크리스트 + 트러블슈팅
- MANUAL.md(Coder 워크스페이스 안내, 이 레포 산출물 아님) 추적 해제 + .gitignore
  (로컬 파일은 유지)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-17 17:05:53 +09:00
parent bfd84fe94a
commit 87db12117e
3 changed files with 141 additions and 486 deletions

139
PULP_INTEGRATION.md Normal file
View File

@@ -0,0 +1,139 @@
# 실제 Pulp 연동 가이드
이 콘솔은 **BFF**로서 실제 **Pulp 3** 서버의 REST API(`/pulp/api/v3/`)에 붙어 동작한다.
지금까지 본 화면은 `PULP_DEMO=true`(가짜 인메모리 데이터)였고, **실연동하려면 Pulp 서버 +
환경변수**가 필요하다. 이 문서는 그 절차와, 실서버에서 흔히 보정이 필요한 지점을 정리한다.
---
## 0. 준비물
- **Pulp 3 서버** (RPM 플러그인 `pulp_rpm` 설치; DEB면 `pulp_deb`)
- Pulp **admin 계정**(또는 API 권한 계정) — 사용자/비밀번호
- 콘솔이 Pulp 주소에 **네트워크 도달 가능**할 것
- (선택) **Postgres** — 배포 감사 로그(`deploy_audit`) 저장용 `DATABASE_URL`
- 사내 HTTPS Pulp면 **사내 CA(.pem)** 또는 검증 끄기 옵션
---
## 1. (테스트용) Pulp 서버 빠르게 띄우기
실서버가 없으면 컨테이너로 올인원 Pulp를 띄워 테스트할 수 있다(podman/docker 동일).
```bash
mkdir -p ~/pulp/{settings,pgsql,storage}
podman run -d --name pulp -p 8080:80 \
-v ~/pulp/settings:/etc/pulp \
-v ~/pulp/pgsql:/var/lib/pgsql \
-v ~/pulp/storage:/var/lib/pulp \
docker.io/pulp/pulp
# 기동까지 1~2분. admin 비밀번호 설정:
podman exec -it pulp pulpcore-manager reset-admin-password
```
- API 주소: `http://localhost:8080/pulp/api/v3/`
- 상태 확인: `curl -u admin:<pw> http://localhost:8080/pulp/api/v3/status/`
> 폐쇄망 운영 Pulp는 인프라팀이 구축한 주소/계정을 그대로 쓰면 된다(위 컨테이너는 개발 검증용).
---
## 2. 화면에 보일 콘텐츠 만들기 (Remote → Repository → Distribution)
대시보드에 저장소가 보이려면 Pulp에 **Repository**가 있어야 하고, 동기화하려면 **Remote**가,
배포하려면 **Distribution**이 있어야 한다. `pulp` CLI(`pip install pulp-cli`)로 RPM 예시:
```bash
# pulp CLI 설정 (한 번)
pulp config create --base-url http://localhost:8080 --username admin --password <pw>
# 1) Remote (외부 미러 소스 정의) — 검증을 켜려면 gpgkey/tls_validation 설정
pulp rpm remote create --name rocky9-baseos \
--url https://dl.rockylinux.org/pub/rocky/9/BaseOS/x86_64/os/
# 2) Repository (그릇) + remote 연결
pulp rpm repository create --name rocky9-baseos --remote rocky9-baseos \
--autopublish # 동기화 후 자동 publication (배포 단계 단순화에 도움)
# 3) (콘솔에서 동기화해도 되고) CLI 동기화로 첫 스냅샷 생성
pulp rpm repository sync --name rocky9-baseos
# 4) Distribution (운영이 보는 공개 URL) — 배포 확정이 PATCH 할 대상
pulp rpm distribution create --name rocky9-baseos \
--base-path rocky9-baseos --repository rocky9-baseos
```
- 이렇게 하면 콘솔 대시보드에 `rocky9-baseos`가 뜨고, **동기화/버전 목록/배포 확정**을 UI에서 시험할 수 있다.
- **배포 확정**은 Distribution을 특정 publication으로 교체하므로, distribution이 미리 있어야 한다.
`--autopublish` + distribution을 repository에 연결해두면 우리 콘솔의 역추적(publication→version)이 잘 맞는다.
---
## 3. 콘솔 환경변수 설정
`.env`(루트, git 미추적) 또는 실행 환경에 설정. **`PULP_DEMO`는 빼거나 false.**
```bash
PULP_BASE_URL=http://localhost:8080 # 실제 Pulp 주소
PULP_USERNAME=admin
PULP_PASSWORD=******** # 비밀번호 (커밋 금지)
PULP_VERIFY_TLS=true # 사내 HTTPS+CA면 PULP_CA_FILE 사용
PULP_CA_FILE=/path/boknet-ca.pem # 사내 self-signed CA 경로(있을 때만)
DATABASE_URL=postgresql://... # 배포 감사 로그용(없으면 배포는 되나 기록 실패 경고)
# PULP_DEMO 미설정
```
> 비밀번호/`DATABASE_URL`은 코드/깃에 두지 않는다. Coolify 배포 시엔 Environment Variables에 넣는다.
---
## 4. 실행 & 확인
```bash
.venv/Scripts/python.exe -m uvicorn app.main:app --reload # Windows
```
| 확인 | 기대 |
|---|---|
| `GET /healthz` | `{"ok": true}` (앱 생존, Pulp와 무관) |
| `GET /pulp-status` | 🟢 "Pulp 연결됨" (실패 시 사유 표시) |
| 대시보드 `/` | 실제 저장소 목록·검증 배지·패키지 수 |
| 동기화 버튼 | sync task 시작 → 진행률 폴링 → 새 버전 |
| 버전 페이지 | 스냅샷 목록 + 현재 배포 버전 배지 |
| 배포 확정 | publication 생성 → distribution 교체 → 감사 로그 |
---
## 5. 실서버 첫 연동 시 보정 체크리스트
스펙/일반적 Pulp 구조 기준으로 구현했으므로, 실제 응답 형태에 따라 아래가 안 맞을 수 있다.
각 항목이 이상하면 해당 코드를 실제 JSON에 맞춰 조정한다.
| 증상 | 확인할 Pulp 필드 | 고칠 곳 |
|---|---|---|
| 검증 배지가 항상 ⚪/⚠️ | `repository.repo_config``gpgcheck` / `repo-gpgcheck` 키 형태 | `app/views.py` `gpg_status()` |
| 패키지 수·증감이 0 | `version.content_summary.present/added/removed` 구조 | `app/views.py` `_content_count()` |
| "현재 배포 버전" 배지가 안 뜸 | `distribution.publication` 유무 / `publication.repository_version` 경로, 또는 distribution이 `repository` 직접 배포(최신 추종) | `app/routes/versions.py` `_deployed_version_number()`, `app/routes/deploy.py` `_distribution_for_repo()` |
| 동기화 진행률/완료 안 잡힘 | task의 `progress_reports[]`, `created_resources[]`, `state` | `app/views.py` `task_progress()` |
| 배포가 distribution을 못 찾음 | repo↔distribution 매핑 규칙 | `app/routes/deploy.py` `_distribution_for_repo()` |
> 실서버 응답을 한 번 떠보면 빠르다: `curl -u admin:<pw> http://<pulp>/pulp/api/v3/repositories/rpm/rpm/ | jq`.
---
## 6. 트러블슈팅
- **`/pulp-status` 연결 실패** → 주소/포트/방화벽, HTTPS면 CA(`PULP_CA_FILE`) 또는 임시로 `PULP_VERIFY_TLS=false`.
- **401 Unauthorized** → `PULP_USERNAME`/`PULP_PASSWORD` 확인.
- **대시보드가 비어 있음** → Pulp에 Repository가 없거나 RPM 플러그인 미설치. §2로 콘텐츠 생성.
- **배포 버튼 비활성** → 해당 저장소가 검증(pass) 상태가 아님(= remote에 gpgkey/tls_validation 미설정 → `repo_config`에 gpgcheck 없음). 의도된 안전장치.
- **"감사 로그 기록 실패"** → `DATABASE_URL` 미설정/접속 불가. 배포 자체는 성공.
---
## 7. DEB(Ubuntu/Debian) 저장소
현재 라우트는 RPM(`/repositories/rpm/rpm/` 등) 경로에 맞춰져 있다. DEB는 `rpm/rpm` 자리를
`deb/apt`로 바꾸면 된다 — `app/pulp_client.py`의 경로를 콘텐츠 타입으로 파라미터화하면 양쪽을
지원할 수 있다(1차 MVP는 RPM 집중).