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

@ -23,22 +23,23 @@ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, AskUserQuestion
- **`dev up|deploy|status|clean|down`** → **로컬 kind 개발 클러스터**. `dev up`(최초 1회, kind+인그레스) → `dev deploy`(소스+워크로드를 로컬에서 관리형과 동일한 바인딩 env로; 콘솔/CI 불필요). `$ARGUMENTS` 실행 후 출력 그대로 + 접속 URL(`http://<project>.dev.localhost/`) 안내. `dev down`(kind 삭제)은 실행 전 한 줄 알리고 진행.
- **`project promote [vX.Y.Z] [--to val|prod]`** → 그 이미지를 **재빌드 없이 상위 환경으로** 승격(개발→검증→운영, 기본 --to prod).
파괴적/외부노출이므로 실행 전 무엇을(어느 태그를 어느 환경 클러스터로) 하는지 한 줄 알리고 진행.
- **그 외 전부**(`project deploy|info|check|update`, `datasource ls`, `domain`, `scale`, `set`, `env`,
- **그 외 전부**(`project deploy|info|check|update`, `datasource ls|options`, `domain`, `scale`, `set`, `env`,
`source`, `bind`, `unbind`, `config`, `upgrade`) → `yakcloud $ARGUMENTS` 를 실행하고 **출력을 그대로** 보여준 뒤,
필요할 때만 한 줄로 해석. 배포/승격/삭제성(`deploy`·`promote`·`source rm`·`unbind`·`domain`)은 실행 전 무엇을 하는지 한 줄 알리고 진행.
- **로컬 개발 = `yakcloud dev`(로컬 kind)**, 검증·운영 = 관리형 yakcloud 클러스터. 같은 매니페스트·같은 바인딩 계약으로 직선. 매니페스트 `environments.{dev,val,prod}`(val=검증계, 선택).
- **로컬 개발 = `yakcloud dev`(로컬 kind)**, 검증·운영 = 관리형 yakcloud 클러스터. 같은 매니페스트·같은 바인딩 계약으로 직선. 매니페스트 = base(공유 정체) + `environments.{dev,val,prod}`(차이만; val=검증계, 선택). requires 는 논리 `name` 매칭으로 병합되고, 오버레이는 base 하고만 병합된다(dev↔val↔prod 끼리 상속 없음). 잘못 짜면 배포 전 친절한 검증 오류가 뜬다.
## 2) `project init` — 마법사 대체 (핵심)
터미널 마법사는 TTY가 없으면 안 뜬다. 네가 대신한다:
1. `yakcloud project init <name> -y`**비대화형 스캐폴딩**(기본 매니페스트 생성; `bin/`·`install.sh` 잔재 없음).
2. `$ARGUMENTS`/대화 맥락에 이미 있는 값은 **재질문 금지**. 부족한 핵심값만 `AskUserQuestion` 으로 모은다:
**개발 클러스터, (검증 클러스터·선택), 운영 클러스터**(같으면 하나로), 앱 포트, 노출 경로(기본 `/`), CPU/메모리, 필요한 데이터소스(있으면), 운영 도메인(있으면).
→ 매니페스트 `environments.dev.cluster` / (`environments.val.cluster`) / `environments.prod.cluster` / `environments.prod.domains` 에 반영.
→ 매니페스트 `environments.dev.cluster` / (`environments.val.cluster`) / `environments.prod.cluster` / `environments.prod.domains` 에 반영. 참고: `requires[].name` 은 binds·오버레이 매칭용 논리 이름(불변)이고, 실제 클러스터 소스 이름은 `clusterName`(기본=name) — 로컬↔운영 소스명이 다를 때 `environments.<env>` 오버레이에서 `clusterName` 만 바꿔 매핑한다(binds 는 항상 논리 name 참조).
3. 모은 값을 CLI로 반영:
- `yakcloud set <wl> --port … --cpu … --mem … --path …`
- 소스: 인클러스터(local)=`yakcloud source add <name> <type> [plan]`, 공유 외부(shared)=`yakcloud source add <name> mongodb --shared`(백엔드가 클러스터별 격리 DB 민팅; 콘솔/API 등록도 가능) + `yakcloud bind <wl> <name> <alias>`.
- 소스(운영은 3-모드 중 결정): **local**(인클러스터 신규)=`yakcloud source add <name> <type> [plan]`, **shared**(공유·`datasource options` 로 sharedAvailable 확인 후 백엔드가 클러스터별 격리 DB 민팅)=`yakcloud source add <name> <type> --shared`, **remote**(기존 외부·접속정보는 매니페스트/git 에 넣지 말고 콘솔/API 등록) + `yakcloud bind <wl> <name> <alias>`. 타입 제약: oracle=remote 전용, redis·minio=shared 없음, 나머지 6종=3모드 전부. 로컬 dev 는 도커로 논리 이름 그대로 떠서 결정 불필요(이 조회/결정은 운영·검증용).
- 도메인: `yakcloud domain <fqdn> <wl>`
- 이용 가능한 클러스터 소스를 먼저 보고 싶으면 `yakcloud datasource ls`.
- 이용 가능한 클러스터 소스를 먼저 보고 싶으면 `yakcloud datasource ls [--env prod|val] [--cluster <id>] [--json]` — 대상 환경/클러스터의 기존 소스 목록(에이전트용 `--json`).
- 운영/검증에서 소스 모드를 정하기 전엔 `yakcloud datasource options <type> [--env prod|val] [--cluster <id>] [--json]` — 타입별 지원모드(local/remote/shared) + 이 배포의 공유 가용성(sharedAvailable) + 기존 소스(existing) + 조회실패 구분(existingError)을 확인.
4. 자격 미설정이면(`yakcloud config` 로 확인) 터미널 `yakcloud login` 안내.
5. 다음 단계(개발 → `yakcloud project deploy`) 를 요약.

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}`.