feat(cli): clusterName 환경별 소스명 매핑 + 운영 소스 3-모드 결정 조회(datasource options/ls) + 검증·문서 · v0.32.0

This commit is contained in:
2026-09-06 03:41:17 +09:00
parent 789aaee5b4
commit 075d7bc3d7
9 changed files with 356 additions and 62 deletions

View File

@ -45,13 +45,28 @@ CLI 가 스스로 전제조건을 검사하고 오류를 안내하므로, 실패
- **배포/승격** — `yakcloud project deploy` (v* 태그 push → CI → 개발 클러스터) · `--local`(러너 없이 로컬
build+push+리컨실) · `yakcloud project promote [vX.Y.Z] --to val|prod` (같은 이미지, 재빌드 없이 승격).
- **앱 설정** — `domain <fqdn> [wl]` · `scale <wl> <n>` · `set <wl> --image/--port/--health/--cpu/--mem/--path/--rewrite`
· `env <wl> KEY=VAL [--secret K] [--unset K]` · `datasource ls` · `source add <name> <type> [plan] [--shared]` · `bind|unbind <wl> <source> <alias>`.
· `env <wl> KEY=VAL [--secret K] [--unset K]` · `datasource ls [--env prod|val] [--cluster <id>] [--json]` · `datasource options <type> [--env prod|val] [--cluster <id>] [--json]`
· `source add <name> <type> [plan] [--shared]` · `bind|unbind <wl> <source> <alias>`.
### 운영 소스 모드 결정 (에이전트 흐름 — 사람은 거의 안 씀)
로컬(dev)은 도커로 논리 이름 그대로 뜨므로 결정 불필요. **운영(prod/val)은 소스마다 모드를 골라야** 한다:
1. **정보 조회**: `yakcloud datasource options <type> --env prod --json`
`{ modes:[…], sharedAvailable:bool, existing:[…], existingError? }``modes`=이 타입이 지원하는 모드, `sharedAvailable`=공유 서버가 이 배포에 있는지, `existing`=기존 소스, `existingError`=조회 실패 사유(있으면 빈 `existing` 이 '없음'이 아니라 '조회 실패'임).
2. **결정 → 매니페스트**:
- **공유 가능**(`sharedAvailable:true`)하고 원하면 → `requires``{ mode: shared }` (백엔드가 격리 DB 민팅).
- **기존 외부 소스에 붙임** → `datasource ls --env prod` 로 이름 확인 후 `environments.prod.requires``{ name:<논리>, clusterName:<그 이름> }`.
- **외부 새로 등록**(remote) → 접속정보는 **매니페스트/git 금지**(자격 격리) → 콘솔/API로 등록 후 이름 참조.
- **그 외** → `{ mode: local, plan: small }`(인클러스터 전용 생성).
- **타입 제약**: `oracle`=remote 전용, `redis`·`minio`=shared 없음, 나머지 6종(postgresql·mysql·mariadb·mongodb·rabbitmq·solr)=local/remote/shared 3모드. `datasource options``modes` 가 그 타입에 실제 가능한 모드를 알려준다.
## 매니페스트 (`yakcloud.yaml`)
- `project` — 이름(이미지 경로).
- `environments.{dev,val,prod}.cluster` — 대상 클러스터 이름/id (val 선택, +`prod.domains`). 로컬 dev 는 `yakcloud dev`.
- `requires[]``{ name, type, plan | mode: shared }`. type ∈ postgresql·mysql·mariadb·mongodb·redis·minio·rabbitmq·solr·oracle.
이름이 클러스터의 READY 소스와 일치하면 스킵, 없으면 프로비저닝(shared=공유 외부, 백엔드가 격리 DB 민팅).
- **환경 오버레이 병합** — 최상위 `requires`/`workloads`=base(공유 정체), `environments.<env>` 는 그 환경의 '차이만'. `requires` 는 논리 `name` 매칭 병합(같은 name=덮어쓰기, 새 name=추가). 오버레이는 **base 하고만** 병합되고 dev↔val↔prod 끼리 상속 안 함. `type` 은 base 또는 그 환경에 반드시 있어야 하며, 없으면 배포 전 검증 오류로 막는다.
- `requires[]``{ name, type, plan | mode: shared, clusterName? }`. type ∈ postgresql·mysql·mariadb·mongodb·redis·minio·rabbitmq·solr·oracle.
이름이 클러스터의 READY 소스와 일치하면 스킵, 없으면 프로비저닝(shared=공유 외부, 백엔드가 격리 DB 민팅; 원격 기본은 인클러스터 아님).
`clusterName` = 논리 `name` 과 다른 '실제 클러스터 소스 이름'(기본=name) — 주로 `environments.<env>` 오버레이에서
로컬↔운영 소스명이 다를 때 매핑. binds 는 항상 논리 `name` 참조(불변).
- `workloads[]``build`(도커 컨텍스트)·`image`(`gitea.yakenator.io/<GITEA_USER>/<project>-<name>:${TAG}``port`·
`health`·`replicas`(≥2 무중단)·`resources{cpu,mem}`·`expose{path,rewrite,host|hosts}`·`binds[]{alias,source}`.