@bifos/nhncloud-cli 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,919 +5,249 @@
5
5
  [![CI](https://github.com/jon890/nhncloud-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/jon890/nhncloud-cli/actions/workflows/ci.yml)
6
6
  [![license](https://img.shields.io/npm/l/@bifos/nhncloud-cli.svg)](https://github.com/jon890/nhncloud-cli/blob/main/LICENSE)
7
7
 
8
- NHN Cloud 서비스를 AWS CLI 방식으로 호출하는 통합 CLI.
9
- 현재 147개 command catalog 항목을 지원한다.
10
- `configure`, `commands`, `logncrash search/send/export`, `deploy`, `instance`, `network`, `volume`, `floatingip` 명령을 지원한다.
11
- `loadbalancer`, `ncr`, `nks`, `ncs` 명령으로 NHN Cloud 서비스를 조회·운영할 수 있다.
12
- `skills`/`doctor` 로 Claude Code 스킬 설치와 상태 진단을 지원한다.
8
+ [NHN Cloud](https://www.nhncloud.com) 를 AI 에이전트가 다룰 수 있게 만든 CLI 다.
13
9
 
14
- ## 설치
10
+ Compute·Network·Block Storage·Load Balancer·Container Registry·Kubernetes·Container Service·Log & Crash·Deploy 를 명령 한 줄로 다루고, 결과를 `--json` 으로 내보낸다.
11
+ Claude Code 같은 에이전트에 스킬로 설치하면 "인스턴스 목록 보여줘" 같은 자연어 지시를 그대로 처리한다.
15
12
 
16
13
  ```bash
17
14
  npm install -g @bifos/nhncloud-cli
15
+ nhncloud configure
16
+ nhncloud skills install
18
17
  ```
19
18
 
20
- ## 초기 설정
19
+ ## 설치와 설정
21
20
 
22
- `nhncloud configure` 를 실행하면 대화형 마법사가 자격증명을 안내한다.
21
+ Node.js 20 이상이 필요하다.
23
22
 
24
23
  ```bash
25
- nhncloud configure
24
+ npm install -g @bifos/nhncloud-cli
26
25
  ```
27
26
 
28
- - profile → 공통 UAK(id/secret) → logncrash appkey → iaas 자격증명 → ncr appkey → ncs appkey 순으로 입력한다.
29
- - profile 은 프로젝트 단위다 — 여러 NHN Cloud 프로젝트를 쓰면 profile 을 분리하되, 같은 UAK 를 쓴다면
30
- 대화형 마법사가 기존 profile 의 UAK 재사용 여부를 먼저 물어 재입력을 줄여준다.
31
- - 저장 전 연결 테스트를 자동으로 수행한다 (`--no-verify` 로 생략 가능).
32
- - CI/자동화는 flag 로 비대화형 설정이 가능하다.
27
+ `nhncloud configure` 가 profile 과 서비스별 자격증명을 대화형으로 받는다.
28
+ 공통 UAK, Log & Crash appkey, iaas 자격증명, NCR appkey, NCS appkey 순으로 입력한다.
29
+ 저장 전 연결 테스트를 자동으로 수행한다 (`--no-verify` 로 생략).
33
30
 
34
31
  ```bash
35
- # 공통 UAK + logncrash + ncs 비대화형 설정
36
- nhncloud configure \
37
- --uak-id <uak-id> --uak-secret <uak-secret> \
38
- --logncrash-appkey <appkey> \
39
- [--ncs-appkey <appkey>] \
40
- --no-verify
41
-
42
- # iaas (Compute) 비대화형 설정 — API 비밀번호는 env 권장
43
- NHNCLOUD_IAAS_PASSWORD=<api-password> nhncloud configure \
44
- --iaas-tenant-id <tenant-id> \
45
- --iaas-username <iam-username> \
46
- --iaas-region kr1 \
47
- --no-verify
32
+ nhncloud configure
33
+ nhncloud doctor # 설정이 제대로 됐는지 확인
48
34
  ```
49
35
 
50
- > **iaas password 안내**: `--iaas-password` 에 입력하는 값은 NHN Cloud 콘솔 IAM 의 **API 비밀번호**입니다.
51
- > 로그인 비밀번호와 다릅니다.
52
- > IAM 사용자 상세 페이지 → "API 비밀번호 설정"에서 별도로 발급하세요.
53
- >
54
- > **iaas username 안내**: `--iaas-username` 은 NHN Cloud 계정 이메일 또는 IAM 계정 ID(사번)입니다.
55
- > tenantId 와 비슷한 "API 사용자 ID"(UUID)가 아닙니다.
56
-
57
- 저장 경로: `~/.nhncloud/credentials.json` (mode 0600), `~/.nhncloud/config.json`.
58
-
59
- profile 해석 우선순위: `--profile` 옵션 > `NHNCLOUD_PROFILE` 환경변수 > `config.defaultProfile` > `"default"`.
36
+ 자격증명은 `~/.nhncloud/credentials.json`(mode 0600), 설정은 `~/.nhncloud/config.json` 에 저장한다.
37
+ profile 우선순위는 `--profile` > `NHNCLOUD_PROFILE` > `config.defaultProfile` > `default` 다.
60
38
 
61
- ### Claude Code 스킬 설치 (선택)
39
+ > **iaas 자격증명의 함정 두 가지**
40
+ >
41
+ > `--iaas-password` 는 NHN Cloud 콘솔 IAM 의 **API 비밀번호**다. 로그인 비밀번호와 다르다.
42
+ > IAM 사용자 상세 페이지의 "API 비밀번호 설정"에서 따로 발급한다.
43
+ >
44
+ > `--iaas-username` 은 계정 이메일 또는 **IAM 계정 ID(사번)** 다.
45
+ > tenantId 와 비슷하게 생긴 "API 사용자 ID"(UUID) 가 아니다.
62
46
 
63
- Claude Code 에서 이 CLI 를 AI 에이전트 스킬로 쓰려면 스킬을 `~/.claude/skills` 에 설치한다.
47
+ CI·자동화는 flag 로 비대화형 설정한다. 비밀번호는 환경변수를 권장한다.
64
48
 
65
49
  ```bash
66
- # 심볼릭 링크로 설치 (전역 설치 전제 — npx 환경은 불가)
67
- nhncloud skills install
68
-
69
- # 설치 상태 확인
70
- nhncloud skills
71
-
72
- # 제거
73
- nhncloud skills uninstall
50
+ NHNCLOUD_IAAS_PASSWORD=<api-password> nhncloud configure \
51
+ --uak-id <uak-id> --uak-secret <uak-secret> \
52
+ --logncrash-appkey <appkey> \
53
+ --iaas-tenant-id <tenant-id> --iaas-username <iam-username> --iaas-region kr1 \
54
+ --no-verify
74
55
  ```
75
56
 
76
- ### 상태 진단
57
+ 에이전트에서 쓰려면 스킬을 설치한다. Claude Code 가 이 CLI 의 사용법을 알게 된다.
77
58
 
78
59
  ```bash
79
- # 자격증명·스킬 설치 상태를 오프라인으로 진단
80
- nhncloud doctor
81
- ```
82
-
83
- ## 사용 예
84
-
85
- ### 배포 (Deploy)
86
-
87
- `nhncloud configure --uak-id <id> --uak-secret <secret>` 으로 UAK 를 설정한 뒤,
88
- `~/.nhncloud/config.json` 에 deploy target (배포 좌표)을 추가한다.
89
-
90
- ```json
91
- {
92
- "version": 1,
93
- "deploy": {
94
- "targets": {
95
- "my-service": {
96
- "appKey": "<appKey>",
97
- "artifactId": "<artifactId>",
98
- "serverGroupId": "<serverGroupId>",
99
- "scenarioIds": "<id1,id2>"
100
- }
101
- }
102
- }
103
- }
60
+ nhncloud skills install
61
+ nhncloud skills status
104
62
  ```
105
63
 
106
- ```bash
107
- # 배포 실행 (동기 완료 대기)
108
- nhncloud deploy run my-service
109
-
110
- # 즉시 반환 (비동기)
111
- nhncloud deploy run my-service --async
64
+ 전역 설치 없이 `npx --yes @bifos/nhncloud-cli@latest skills install` 로도 설치된다 — 관리 저장소에 복사되므로 임시 패키지 경로가 사라져도 남는다.
65
+ CLI 를 새 버전으로 올린 뒤에는 `nhncloud skills update` 를 실행해야 스킬도 갱신된다.
112
66
 
113
- # 특정 호스트만 배포
114
- nhncloud deploy run my-service --target-hosts host1,host2
67
+ 상태는 `current`, `missing`, `outdated`, `broken`, `unmanaged`, `modified`, `corrupt` 중 하나이고, 출력에 딸린 복구 명령을 따르면 된다.
68
+ 사용자 항목이나 수정·손상된 저장소는 자동으로 덮어쓰지 않는다.
115
69
 
116
- # 아티팩트 목록 조회
117
- nhncloud deploy artifacts my-service
70
+ ## 사용법
118
71
 
119
- # 서버그룹 목록 조회
120
- nhncloud deploy server-groups my-service
72
+ 설정을 마치면 에이전트에게 한국어로 시키면 된다.
121
73
 
122
- # 배포 이력 조회
123
- nhncloud deploy histories my-service
124
-
125
- # 바이너리 그룹 목록 — 그룹 key 확인
126
- nhncloud deploy binary-groups my-service
127
-
128
- # 위에서 확인한 key 로 바이너리 목록 조회
129
- nhncloud deploy binaries my-service --binary-group <key>
130
-
131
- # 업로드 최신순 정렬 + 전체 필드는 --json
132
- nhncloud deploy binaries my-service --binary-group <key> --sort-key UPLOAD_DATE --sort-direction DESC --json
133
-
134
- # 바이너리 업로드 — binary-groups 로 확인한 그룹 key 에 파일 올리기
135
- nhncloud deploy upload <target> --file ./build/app.jar --binary-group <key> --description "release build"
74
+ ```
75
+ "인스턴스 목록 보여줘"
76
+ "kr1 리전에 인스턴스 만들고 ACTIVE 될 때까지 기다려줘"
77
+ "최근 1시간 에러 로그 찾아줘"
78
+ "배포 실행하고 완료되면 알려줘"
79
+ "이 로드밸런서에 IP ACL 그룹 붙여줘"
80
+ "클러스터 kubeconfig 받아줘"
81
+ "레지스트리 이미지 태그 목록 보여줘"
82
+ ```
136
83
 
137
- # 업로드 응답의 binaryKey 만 필요하면 --quiet
138
- nhncloud deploy upload <target> --file ./build/app.jar --binary-group <key> --quiet
84
+ 에이전트가 알맞은 `nhncloud` 명령으로 옮기고, 필요하면 인스턴스 id 나 VPC id 를 먼저 조회한다.
139
85
 
140
- # 바이너리 다운로드 — 파일로 저장 (기본 덮어쓰기 거부, --force 로 강제)
141
- nhncloud deploy download <target> --binary-group <key> --binary-key <binary-key> -o ./app.jar
142
- ```
86
+ 에이전트가 쓰는 명령 카탈로그와 판단 기준은 [스킬 문서](skills/nhncloud-cli/SKILL.md)에 있다.
87
+ 서비스별 상세는 [references/](skills/nhncloud-cli/references/) 아래 파일로 나뉘어 있다.
143
88
 
144
- ### 로그 검색
89
+ ## 에이전트 없이 직접 쓰기
145
90
 
146
- Log & Crash Search v3는 profile의 logncrash appkey와 공통 UAK를 사용한다.
147
- CLI가 UAK를 OAuth 토큰으로 교환해 `X-NHN-Authorization: Bearer <token>`으로 인증한다.
148
- 기존 logncrash secret은 검색에 사용하거나 새 설정에 저장하지 않는다.
149
- 전환 호환 옵션 `nhncloud configure --logncrash-secret`은 경고 후 무시한다.
91
+ 터미널에서 바로 쓸 수도 있다.
150
92
 
151
93
  ```bash
152
- # 최근 1시간 NORMAL 로그
153
- nhncloud logncrash search \
154
- --query 'logType:"NORMAL"' \
155
- --from 1h \
156
- --to now
157
-
158
- # body 필드 키워드 검색
159
- nhncloud logncrash search \
160
- --query 'body:request_received' \
161
- --from 1h \
162
- --to now
163
-
164
- # body 부분 문자열 검색
165
- nhncloud logncrash search \
166
- --query 'body:*request_received*' \
167
- --from 1h \
168
- --to now
169
-
170
- # 다음 페이지 조회: 직전 JSON의 nextCursor를 그대로 전달
171
- next_cursor="$(nhncloud logncrash search \
172
- --query '*' --from 1h --to now --json | jq -r '.nextCursor // empty')"
173
- if [ -n "$next_cursor" ]; then
174
- nhncloud logncrash search \
175
- --query '*' --from 1h --to now \
176
- --cursor "$next_cursor" --json
177
- fi
94
+ nhncloud instance list # 인스턴스 목록
95
+ nhncloud instance get <instance-id> # 인스턴스 상세
96
+ nhncloud network list # VPC 목록
97
+ nhncloud volume list # 블록 스토리지 볼륨
98
+ nhncloud floatingip list # Floating IP
99
+ nhncloud loadbalancer list # 로드밸런서
100
+ nhncloud ncr list # 컨테이너 레지스트리
101
+ nhncloud nks cluster list # Kubernetes 클러스터
102
+ nhncloud deploy artifacts # 배포 아티팩트
103
+ nhncloud logncrash search --query '*' --from 1h --to now # 최근 1시간 로그
104
+ nhncloud apigateway service list # API Gateway 서비스
178
105
  ```
179
106
 
180
- `--query` 는 콘솔의 간편 검색어가 아니라 Log & Crash Search API 의 Lucene 쿼리다.
181
- body 검색 의도가 명확하면 `body:<keyword>` 또는 `body:*<keyword>*` 처럼 필드를 지정한다.
182
-
183
- 시간은 상대시간 (`1h` / `30m` / `2d` / `now`) 또는 ISO8601 (`2026-05-01T00:00:00+09:00`) 로 입력한다.
184
- API 제약상 검색 시작은 최근 90일 이내, 검색 범위는 31일 이하여야 한다 (초과 시 입력 오류로 거절).
185
- 전송 직후에는 인덱싱 지연으로 잠시 0건이 나올 수 있다.
186
- 반복 검색이나 넓은 wildcard 검색은 API rate limit 에 걸릴 수 있으므로 시간 범위를 좁혀 확인한다.
187
- 검색 결과는 `logTime DESC`로 고정 정렬한다.
188
- `--page`는 전환 호환을 위해 남아 있지만 `0`만 허용한다.
189
- 다음 페이지는 JSON 응답에 `nextCursor`가 있을 때 그 값을 `--cursor`로 변형 없이 전달한다.
190
-
191
- ### 로그 대량 추출 (export)
107
+ 전체 명령과 옵션은 `--help` 로 본다. 현재 164개다.
192
108
 
193
109
  ```bash
194
- # 검색 결과 전체를 파일로 추출 (JSON Lines, scroll 순회)
195
- nhncloud logncrash export \
196
- --query 'logType:"ERROR"' \
197
- --from 1h --to now \
198
- --output errors.jsonl
199
-
200
- # JSON 배열 형식으로 추출
201
- nhncloud logncrash export --query 'logType:"ERROR"' --from 1h --to now \
202
- --output errors.json --format json
110
+ nhncloud --help
111
+ nhncloud instance --help
112
+ nhncloud instance create --help
203
113
  ```
204
114
 
205
- 단발 검색(`search`)과 달리 scroll API 로 전체 결과(최대 10만 건)를 순회해 파일로 저장한다.
206
- 진행 상황은 stderr, 데이터는 파일에만 기록된다(stdout 비움).
207
- 중간 요청이 실패하면 원본 오류를 확인하고 검색 시간 범위를 좁혀 다시 실행한다.
208
- 기존 `--size`는 전환 호환 옵션이다.
209
- 명시하면 10~100 범위를 검증하고 폐기 예정 경고를 출력하지만 Search v3 요청에는 전달하지 않는다.
210
- 시간 범위 제한은 search 와 동일(90일 이내·31일 이하).
211
-
212
- #### export 옵션
213
-
214
- | 옵션 | 필수 | 설명 |
215
- |------|:---:|------|
216
- | `--query <lucene>` | 예 | Lucene 질의 문자열 |
217
- | `--from <time>` | 예 | 검색 시작 (ISO8601 또는 상대시간 `1h`/`30m`/`2d`/`now`) |
218
- | `--to <time>` | 예 | 검색 끝 |
219
- | `--output <file>` | 예 | 출력 파일 경로 |
220
- | `--format <fmt>` | 아니오 | `jsonl`(기본, 한 줄당 한 로그) 또는 `json`(배열) |
221
- | `--size <n>` | 아니오 | 폐기 예정 호환 옵션. 10~100 검증 후 경고하고 v3 요청에서는 무시 |
222
- | `--force` | 아니오 | 출력 파일이 있으면 덮어쓴다 (기본 거부) |
223
- | `--profile <name>` | 아니오 | 사용할 profile 이름 |
224
-
225
- ### 로그 전송
115
+ 기계가 읽을 카탈로그가 필요하면 `commands` 를 쓴다. 외부 API 를 호출하지 않고 Commander 트리 메타데이터만 출력한다.
226
116
 
227
117
  ```bash
228
- # 로그 한 건 전송 — 본문 직접
229
- nhncloud logncrash send --body "결제 완료" --level INFO
230
-
231
- # 파일에서 본문 읽어 전송
232
- nhncloud logncrash send --file ./error.log --level ERROR
233
-
234
- # 파이프(stdin)로 전송
235
- echo "배치 작업 종료" | nhncloud logncrash send --level INFO
236
-
237
- # 프로젝트 버전·소스 지정
238
- nhncloud logncrash send --body "deploy 시작" --app-version 2.3.0 --source batch
118
+ nhncloud commands --json | jq '.commands[] | select(.path=="nks cluster list")'
239
119
  ```
240
120
 
241
- > `logncrash send`는 Search v3 전환의 영향을 받지 않는다.
242
- > 검색과 다른 collector로 전송하며 appkey만 사용한다.
243
- > 단일 로그 본문은 8MB까지 허용한다.
244
-
245
- ### 출력 모드
246
-
247
- | 모드 | 옵션 | 용도 |
248
- |------|------|------|
249
- | 테이블 | (기본) | 사람이 읽는 고정 컬럼 출력 |
250
- | JSON | `--json` | 자동화·AI 에이전트용 raw 데이터 + 페이지 메타 |
251
- | quiet | `--quiet` | 행별 최소 출력 |
121
+ 출력은 세 가지 모드다.
252
122
 
253
- `--json`은 CLI가 가공한 출력 계약이다.
254
- NHN Cloud 또는 OpenStack 원본 응답의 최상위 래퍼를 그대로 보존하지 않을 수 있다.
123
+ | 플래그 | 출력 | 쓰는 곳 |
124
+ | --- | --- | --- |
125
+ | (없음) | 사람이 읽는 표 | 터미널 |
126
+ | `--json` | JSON | 파싱, 명령 연결 |
127
+ | `--quiet` | 식별자만 | 스크립트 |
255
128
 
256
- ### 자동화와 AI 에이전트
129
+ 전역 옵션이라 모든 명령에 붙일 수 있다. `--no-color` 와 `--request-timeout <sec>` 도 같은 자리에서 쓴다.
130
+ 요청 타임아웃은 초 단위이며 기본값은 30초, 허용 범위는 1~3600초다.
131
+ `NHNCLOUD_REQUEST_TIMEOUT` 환경변수로도 지정할 수 있으며 명령줄 옵션이 환경변수보다 우선한다.
257
132
 
258
- 명령 경로, 인수, 옵션은 `nhncloud commands --json`으로 확인한다.
259
- 이 명령은 외부 API를 호출하지 않고 Commander tree metadata만 stdout에 출력한다.
133
+ `--json` 은 CLI 가 가공한 출력 계약이라 원본 응답의 최상위 래퍼를 그대로 보존하지 않는다.
134
+ 예를 들어 `instance get --json` 은 `.server.status` 가 아니라 `.status` 를 읽는다.
135
+ 명령별 shape 는 [common.md 의 JSON shape 요약](skills/nhncloud-cli/references/common.md)에 있다.
260
136
 
261
137
  ```bash
262
- nhncloud commands --json | jq '.commands[] | select(.path=="nks cluster list")'
263
- ```
264
-
265
- root와 주요 service group의 `--help`에는 짧은 agent hint가 포함된다.
266
- 긴 사용법은 README와 공개 skill reference를 기준으로 확인한다.
267
-
268
- | 명령 | `--json` 출력 shape |
269
- |------|---------------------|
270
- | `commands` | `{ commands: [{ path, description, arguments, options, subcommands }] }` |
271
- | `logncrash search` | `{ totalItems, pageNumber, pageSize, data, nextCursor? }` 객체 |
272
- | `logncrash export` | 파일 출력 전용. stdout JSON 없음 |
273
- | `deploy artifacts` | Deploy API `body` 객체 |
274
- | `deploy server-groups` | Deploy API `body` 객체 |
275
- | `deploy histories` | Deploy API `body` 객체 |
276
- | `deploy binary-groups` | `binaryGroups` 래퍼를 언랩한 배열 |
277
- | `deploy binaries` | `{ totalCount, binaries }` 객체 |
278
- | `deploy upload` | `{ downloadUrl, binaryKey }` 객체 |
279
- | `instance list` | `servers` 래퍼를 언랩한 server 배열 |
280
- | `instance get` | `server` 래퍼를 언랩한 단일 server 객체 |
281
- | `instance create --wait` | `server` 래퍼를 언랩한 단일 server 객체 |
282
- | `instance flavors` | `flavors` 래퍼를 언랩한 flavor 배열 |
283
- | `instance images` | `images` 래퍼를 언랩한 image 배열 |
284
- | `instance availability-zones` | `availabilityZoneInfo` 래퍼를 언랩한 배열 |
285
- | `instance keypairs` | `keypairs[].keypair`를 flatten한 keypair 배열 |
286
- | `instance volumes` | `volumeAttachments` 래퍼를 언랩한 attachment 배열 |
287
- | `network list` | VPC 배열 |
288
- | `network subnet list` | subnet 배열 |
289
- | `volume list` | volume 배열 |
290
- | `volume get` | 단일 volume 객체 |
291
- | `volume create` | 단일 volume 객체 |
292
- | `floatingip list` | floating IP 배열 |
293
- | `floatingip create` | 단일 floating IP 객체 |
294
- | `loadbalancer list` | Load Balancer 배열 |
295
- | `loadbalancer get` | 단일 Load Balancer 객체 |
296
- | `loadbalancer ipacl list` | IP ACL 그룹 배열 |
297
- | `loadbalancer ipacl get` | 단일 IP ACL 그룹 객체 |
298
- | `loadbalancer ipacl target list` | IP ACL 대상 배열 |
299
- | `loadbalancer ipacl create/delete` | 작업 상태와 IP ACL 그룹 UUID 객체 |
300
- | `loadbalancer ipacl target add/remove` | 대상 UUID와 재바인딩 결과 객체 |
301
- | `loadbalancer set-ipacl/clear-ipacl` | 작업 상태와 Load Balancer UUID·그룹 UUID 객체 |
302
- | `ncr list` | `registries` 래퍼를 언랩한 registry 배열 |
303
- | `ncr get` | `registry` 래퍼를 언랩한 단일 registry 객체 |
304
- | `ncr images` | repository 배열 |
305
- | `ncr tags` | tag 배열 |
306
- | `nks supports` | 지원 Kubernetes version / event type 객체 |
307
- | `nks cluster list` | cluster 배열 |
308
- | `nks cluster events` | event 배열 |
309
- | `nks nodegroup list` | nodegroup 배열 |
310
- | `nks addon-type list` | addon type 배열 |
311
- | `nks addon list` | addon 배열 |
312
- | `nks cluster addon list` | cluster addon 배열 |
313
-
314
- NKS의 단건 조회는 API 객체를 그대로 반환한다.
315
- 예를 들어 `nks cluster get`, `nks cluster event`, `nks nodegroup get`, `nks addon-type get`, `nks addon get`, `nks cluster addon get`, `nks cluster ipacl`, `nks nodegroup autoscale` 은 table 출력용 최소 컬럼을 만들고 `--json` 에서는 raw 객체를 보존한다.
316
- NKS 쓰기 명령 중 생성·resize·설정 변경·노드 action·애드온 변경은 `{ uuid }` 응답을 반환한다.
317
- 삭제 명령은 성공 메시지만 stderr에 쓰고 stdout은 비운다.
318
- `nks cluster kubeconfig` 는 kubeconfig 문자열을 stdout 또는 파일로 저장한다.
319
-
320
- 예를 들어 `instance get --json`은 `.server.status`가 아니라 `.status`를 읽는다.
321
-
322
- ### 체이닝 예시
323
-
324
- ```bash
325
- # 인스턴스 상태 확인
326
138
  nhncloud instance get <instance-id> --json | jq -r '.status'
327
-
328
- # 검색 결과에서 logBody 만 추출
329
139
  nhncloud logncrash search --query '*' --from 1h --to now --json | jq -r '.data[].logBody'
330
-
331
- # 전체 건수 확인
332
- nhncloud logncrash search --query '*' --from 1d --to now --json | jq '.totalItems'
333
140
  ```
334
141
 
335
- ## 옵션
336
-
337
- | 옵션 | 필수 | 설명 |
338
- |------|:---:|------|
339
- | `--query <lucene>` | 예 | Lucene 질의 문자열 |
340
- | `--from <time>` | 예 | 검색 시작 (ISO8601 또는 상대시간) |
341
- | `--to <time>` | 예 | 검색 끝 |
342
- | `--page <n>` | 아니오 | 전환 호환용 pageNumber. 기본 0이며 0만 허용 |
343
- | `--size <n>` | 아니오 | pageSize (기본 10, 범위 1~100) |
344
- | `--cursor <value>` | 아니오 | 직전 JSON 응답의 불투명한 `nextCursor` |
345
- | `--profile <name>` | 아니오 | 사용할 profile |
346
-
347
- 전역 옵션: `--json` / `--quiet` / `--no-color`.
348
-
349
- ## 종료 코드
142
+ ### 종료 코드
350
143
 
351
144
  | 코드 | 의미 |
352
- |:---:|------|
145
+ | :---: | --- |
353
146
  | 0 | 성공 |
354
147
  | 1 | API 오류 |
355
148
  | 2 | 인증 실패 (401/403) |
356
149
  | 3 | 입력 오류 (파라미터·시간 범위) |
357
150
  | 4 | 설정 오류 (자격증명 누락) |
358
151
 
359
- ### 인스턴스 (Instance)
360
-
361
- `~/.nhncloud/credentials.json` 에 `iaas` 블록을 추가하거나 `nhncloud configure` 로 설정한다.
362
-
363
- ```json
364
- {
365
- "version": 1,
366
- "profiles": {
367
- "default": {
368
- "iaas": {
369
- "tenantId": "<tenant-id>",
370
- "username": "<iam-username>",
371
- "password": "<api-password>",
372
- "region": "kr1"
373
- }
374
- }
375
- }
376
- }
377
- ```
378
-
379
- ```bash
380
- # 인스턴스 목록 조회
381
- nhncloud instance list
382
-
383
- # 이미지 목록 (create --image <id> 에 넣을 image id 확인)
384
- nhncloud instance images
385
-
386
- # public 이미지만, 전체 필드 JSON
387
- nhncloud instance images --visibility public --json
388
-
389
- # 페이지네이션 — 다음 페이지
390
- nhncloud instance images --limit 20 --marker <last-image-id>
391
-
392
- # 인스턴스 타입(flavor) 목록 — id·name 만
393
- nhncloud instance flavors
394
-
395
- # 타입 상세 — vcpus·ram·disk 포함 (테이블은 핵심 5컬럼)
396
- nhncloud instance flavors --detail
152
+ ### 되돌리기 어려운 명령의 확인
397
153
 
398
- # 전체 필드(is_public·extra_specs 등)는 --json 으로
399
- nhncloud instance flavors --detail --json
154
+ 삭제·전체 교체처럼 되돌리기 어려운 명령은 실행 전 확인을 요구한다.
155
+ 자동화·파이프 등 비대화형 실행에서는 `--yes` 를 명시해야 한다.
156
+ 플래그가 없으면 API 를 호출하기 전에 종료 코드 3 으로 끝난다.
400
157
 
401
- # RAM 8GB 이상 타입만 필터
402
- nhncloud instance flavors --detail --min-ram 8192
158
+ `--region` 은 IaaS 와 NKS 계열에서 결과를 가르므로, 기본값에 기대지 말고 명시하는 편이 안전하다.
403
159
 
404
- # 가용성 영역(availability zone) 목록 (영역명·가용 여부)
405
- nhncloud instance availability-zones
160
+ ## 프로젝트 구조
406
161
 
407
- # 전체 응답(zoneState 등)은 --json 으로
408
- nhncloud instance availability-zones --json
409
-
410
- # 단일 인스턴스 상태 조회
411
- nhncloud instance get <instance-id>
412
-
413
- # 인스턴스 생성 (즉시 반환, BUILD 상태)
414
- nhncloud instance create \
415
- --name my-server \
416
- --flavor <flavor-id> \
417
- --image <image-id> \
418
- --network <network-uuid>
419
-
420
- # 인스턴스 생성 + ACTIVE 대기 (IP 할당까지 폴링)
421
- nhncloud instance create \
422
- --name my-server \
423
- --flavor <flavor-id> \
424
- --image <image-id> \
425
- --network <network-uuid> \
426
- --wait
427
-
428
- # GPU(g2) 등 boot-from-volume 필수 flavor — --boot-volume-size 지정
429
- nhncloud instance create \
430
- --name gpu-server \
431
- --flavor <gpu-flavor-id> \
432
- --image <image-id> \
433
- --network <network-uuid> \
434
- --boot-volume-size 30 \
435
- --wait
436
-
437
- # cloud-init user-data 주입 (부팅 시 자동 셋업 — NVIDIA 드라이버·docker 등)
438
- nhncloud instance create \
439
- --name gpu-runner \
440
- --flavor <gpu-flavor-id> \
441
- --image <image-id> \
442
- --network <network-uuid> \
443
- --boot-volume-size 30 \
444
- --user-data ./cloud-init.yaml \
445
- --wait
446
-
447
- # --quiet --wait: 첫 IP 한 줄만 stdout (CI 파이프용)
448
- IP=$(nhncloud instance create --name ci-runner \
449
- --flavor <flavor-id> --image <image-id> --network <network-uuid> \
450
- --wait --quiet)
451
-
452
- # 인스턴스 삭제 (confirm 생략)
453
- nhncloud instance delete <instance-id> --yes
454
-
455
- # 인스턴스 타입(flavor) 변경 — 후보 id 는 instance flavors 로 조회
456
- nhncloud instance flavors --detail
457
- nhncloud instance resize <instance-id> --flavor <flavor-id>
458
-
459
- # resize 후 VERIFY_RESIZE 상태 — 확정 또는 롤백
460
- nhncloud instance resize-confirm <instance-id>
461
- nhncloud instance resize-revert <instance-id>
462
-
463
- # 인스턴스 정지 / 시작
464
- nhncloud instance stop <instance-id>
465
- nhncloud instance start <instance-id>
466
-
467
- # 재부팅 (기본 SOFT)
468
- nhncloud instance reboot <instance-id>
469
-
470
- # HARD 재부팅 (강제 전원 cycle)
471
- nhncloud instance reboot <instance-id> --hard
472
-
473
- # 키페어 목록 (name·fingerprint)
474
- nhncloud instance keypairs
475
-
476
- # 단일 키페어 조회
477
- nhncloud instance keypair get <keypair-name>
478
-
479
- # 키페어 생성 — NHN 이 키쌍 생성, private_key 를 0600 파일로 저장 (한 번만 받을 수 있음)
480
- nhncloud instance keypair create <keypair-name> -o ./my-key.pem
481
-
482
- # 기존 공개키 등록 (private_key 미반환)
483
- nhncloud instance keypair create <keypair-name> --public-key ~/.ssh/id_rsa.pub
484
-
485
- # 키페어 삭제
486
- nhncloud instance keypair delete <keypair-name>
487
162
  ```
488
-
489
- > **private_key 안내**: 키페어 생성 시 NHN 이 만든 private_key 는 생성 응답 **한 번만** 반환됩니다.
490
- > `-o <keyfile>` 로 저장하거나 stdout 을 안전한 곳에 보관하세요. 분실 시 복구할 수 없습니다.
491
-
492
- 지원 region: `kr1` / `kr2` / `kr3` / `jp1` (`--region` 으로 override 가능).
493
-
494
- ### 네트워크 (Network)
495
-
496
- `instance create --network <uuid>` 에 넣을 VPC id 를 확인하거나 서브넷 구성을 조회한다.
497
- `network` 명령군은 `instance` 와 같은 `iaas` 자격증명·Keystone 토큰을 공유한다 — 별도 설정이 필요 없다.
498
-
499
- ```bash
500
- # VPC 목록 (instance create --network <uuid> 에 넣을 VPC id 확인)
501
- nhncloud network list
502
-
503
- # 전체 필드 JSON
504
- nhncloud network list --json
505
-
506
- # 서브넷 목록 (소속 VPC·CIDR·가용 IP 확인)
507
- nhncloud network subnet list
508
-
509
- # 다른 region
510
- nhncloud network list --region kr2
511
-
512
- # create 흐름 — 확인한 VPC id 를 --network 에 사용 (--network 가 받는 uuid = VPC id, 실측 확정)
513
- nhncloud instance create \
514
- --name web \
515
- --flavor <flavor-id> \
516
- --image <image-id> \
517
- --network <network-uuid>
518
- ```
519
-
520
- > **`--network` 가 받는 id**: `network list` 의 VPC id 를 그대로 `--network` 에 사용한다.
521
- > subnet id 가 아니다 — `instance list --json` 의 addresses 키와 VPC name 이 1:1 대응함을 실측으로 확인.
522
-
523
- ### Block Storage (Volume)
524
-
525
- 독립 블록 스토리지 볼륨을 관리한다.
526
- `volume` 명령군은 `instance`·`network` 와 같은 `iaas` 자격증명·Keystone 토큰을 공유한다 — 별도 설정이 필요 없다.
527
-
528
- **볼륨 생성(`volume create`)·인스턴스 연결(`instance volume attach`)·연결 해제(`instance volume detach`)는 쓰기 작업이므로 실행 전 환경을 확인한다(수동 QA 필수).**
529
-
530
- ```bash
531
- # 볼륨 목록 조회
532
- nhncloud volume list
533
-
534
- # 정렬·페이지네이션
535
- nhncloud volume list --sort created_at:desc --limit 20
536
-
537
- # 단일 볼륨 조회
538
- nhncloud volume get <volume-id>
539
-
540
- # 전체 필드 JSON
541
- nhncloud volume get <volume-id> --json
542
-
543
- # 볼륨 생성 — ⚠️ 쓰기 작업, 실행 전 환경 확인 필수
544
- nhncloud volume create --size 10
545
-
546
- # 이름·타입 지정
547
- nhncloud volume create --size 50 --name my-volume --volume-type "General SSD"
548
-
549
- # 인스턴스와 같은 가용성 영역에 생성
550
- nhncloud volume create --size 50 --volume-type "General SSD" --availability-zone kr-pub-a
551
-
552
- # 인스턴스에 연결된 볼륨 목록 조회
553
- nhncloud instance volumes <instance-id>
554
-
555
- # 볼륨 연결 — ⚠️ 쓰기 작업 (--volume 플래그로 볼륨 ID 지정)
556
- nhncloud instance volume attach <instance-id> --volume <volume-id>
557
-
558
- # 볼륨 연결 해제 — ⚠️ 쓰기 작업 (인스턴스 ID + 볼륨 ID 위치 인수)
559
- nhncloud instance volume detach <instance-id> <volume-id>
560
- ```
561
-
562
- > **UX 비대칭**: `attach` 는 `--volume <id>` 플래그로 볼륨을 지정하고,
563
- > `detach` 는 `<instanceId> <volumeId>` 위치 인수 두 개로 지정한다.
564
-
565
- 지원 region: `kr1` / `kr2` / `kr3` / `jp1` (`--region` 으로 override 가능).
566
-
567
- ### 공인 IP (Floating IP)
568
-
569
- Floating IP 를 발급해 인스턴스에 부여하는 공인 IP 를 관리한다.
570
- `floatingip` 명령군은 `network` 와 같은 `iaas` 자격증명·Keystone 토큰을 공유한다.
571
-
572
- ```bash
573
- # Floating IP 목록
574
- nhncloud floatingip list
575
-
576
- # Floating IP 발급 (--network 미지정 시 외부 VPC 자동 조회)
577
- nhncloud floatingip create
578
- nhncloud floatingip create --network <network-uuid>
579
-
580
- # 삭제
581
- nhncloud floatingip delete <floatingip-id> --yes
582
- ```
583
-
584
- > **associate**: `floatingip associate <floatingip-id> <instance-id>` 는 instance→port_id 매핑 경로 미확정으로 보류 중.
585
- > 실측으로 경로가 확정되면 후속 task 에서 추가한다.
586
-
587
- ### Load Balancer와 IP ACL
588
-
589
- Load Balancer와 IP ACL 그룹·대상을 조회하고 관리한다.
590
- `loadbalancer` 명령군은 `network`와 같은 `iaas` 자격증명·Keystone 토큰·network endpoint를 공유한다.
591
-
592
- 자동화에서는 profile과 region을 명시하고 `--json`으로 조회한다.
593
-
594
- ```bash
595
- # Load Balancer 목록과 단건 조회
596
- nhncloud loadbalancer list --profile <profile> --region <region> --json
597
- nhncloud loadbalancer get <loadbalancer> --profile <profile> --region <region> --json
598
-
599
- # IP ACL 그룹 목록과 단건 조회
600
- nhncloud loadbalancer ipacl list --profile <profile> --region <region> --json
601
- nhncloud loadbalancer ipacl get <group> --profile <profile> --region <region> --json
602
-
603
- # 그룹에 속한 IP ACL 대상 조회
604
- nhncloud loadbalancer ipacl target list <group> \
605
- --profile <profile> \
606
- --region <region> \
607
- --json
608
-
609
- # IP ACL 그룹 생성과 삭제
610
- nhncloud loadbalancer ipacl create \
611
- --name <group-name> \
612
- --action ALLOW \
613
- --description <description> \
614
- --profile <profile> \
615
- --region <region> \
616
- --json
617
- nhncloud loadbalancer ipacl delete <group> \
618
- --profile <profile> \
619
- --region <region> \
620
- --yes \
621
- --json
622
-
623
- # Load Balancer의 IP ACL 그룹 전체 교체와 전체 해제
624
- nhncloud loadbalancer set-ipacl <loadbalancer> \
625
- --group <group> \
626
- --group <other-group> \
627
- --profile <profile> \
628
- --region <region> \
629
- --yes \
630
- --json
631
- nhncloud loadbalancer clear-ipacl <loadbalancer> \
632
- --profile <profile> \
633
- --region <region> \
634
- --yes \
635
- --json
636
-
637
- # IP ACL 대상 추가와 삭제
638
- nhncloud loadbalancer ipacl target add <group> \
639
- --cidr <ip-or-cidr> \
640
- --profile <profile> \
641
- --region <region> \
642
- --yes \
643
- --json
644
- nhncloud loadbalancer ipacl target remove <target-id> \
645
- --profile <profile> \
646
- --region <region> \
647
- --yes \
648
- --json
649
- ```
650
-
651
- `<loadbalancer>`와 `<group>`에는 이름 또는 UUID를 넣는다.
652
- UUID가 정확히 일치하면 바로 선택하고, 이름은 정확히 하나만 일치해야 한다.
653
- 같은 이름이 여러 개면 오류에 표시되는 후보 UUID를 사용한다.
654
-
655
- 기본 테이블의 Load Balancer 목록 컬럼은 `id`, `name`, `vip_address`, `provisioning_status`, `operating_status`, `ipacl_group_action`이다.
656
- IP ACL 그룹 목록 컬럼은 `id`, `name`, `action`, `ipacl_target_count`, `loadbalancer_count`다.
657
- IP ACL 대상 목록 컬럼은 `id`, `cidr_address`, `description`, `ipacl_group_id`다.
658
- `--json`은 응답 래퍼를 제거한 객체 또는 배열을 stdout에 출력하고, `--quiet`는 리소스 UUID만 한 줄에 하나씩 stdout에 출력한다.
659
- 진행 상황, 운영 경고, 오류는 stderr로 분리된다.
660
-
661
- 쓰기 명령은 대화형 확인을 열지 않는다.
662
- 삭제, 연결 교체, 대상 변경에는 `--yes`가 필수다.
663
- `set-ipacl`은 지정한 그룹 목록으로 기존 연결을 전체 교체하고, `clear-ipacl`은 모든 연결을 해제한다.
664
-
665
- 대상 추가·삭제는 변경 전에 연결 상태를 수집한 뒤 관련 Load Balancer를 순차 재바인딩한다.
666
- `--no-rebind`를 쓰면 재바인딩을 생략하지만 데이터 영역에 규칙이 즉시 반영되지 않을 수 있다.
667
- 대상 변경은 반영까지 약 10–20초가 걸릴 수 있다.
668
- `ALLOW` 그룹에는 Load Balancer가 속한 VPC의 private CIDR을 사용한다.
669
-
670
- 재바인딩이 일부 실패하면 대상 변경은 되돌리지 않는다.
671
- 명령은 `status: "partial"`과 `rebind.failed[].retry_argv`를 stdout JSON에 먼저 출력한 뒤 종료 코드 1을 반환한다.
672
- AI 에이전트는 문자열인 `retry_command`보다 배열인 `retry_argv`를 우선 사용한다.
673
- 사용자가 명시한 `--profile`과 `--region`도 복구 배열에 보존된다.
674
-
675
- ```bash
676
- result_file="$(mktemp)"
677
- if ! nhncloud loadbalancer ipacl target add <group> \
678
- --cidr <ip-or-cidr> \
679
- --profile <profile> \
680
- --region <region> \
681
- --yes \
682
- --json >"$result_file"; then
683
- jq '.rebind.failed[] | {error, retry_argv}' "$result_file"
684
- fi
163
+ src/
164
+ index.ts CLI 진입점
165
+ api/ 공통 endpoint, 응답 봉투, HTTP 오류 처리 (ky)
166
+ services/ 서비스별 API 클라이언트와 타입 가드
167
+ commands/ Commander.js 명령 정의
168
+ config/ ~/.nhncloud/ 자격증명·설정 스키마와 profile 해석
169
+ cache/ ~/.nhncloud/cache/ 토큰 캐시
170
+ formatters/ 표·JSON·quiet 출력
171
+ skill/ Claude Code 스킬 설치·갱신
172
+ utils/ 에러, 스피너, 종료 코드
685
173
  ```
686
174
 
687
- ### NHN Container Registry (NCR)
688
-
689
- NCR Management API 로 레지스트리를 조회한다.
690
- 인증은 공통 UAK(`X-TC-AUTHENTICATION-ID/SECRET` 정적 헤더)를 재사용하며 OAuth 토큰 교환이 없다.
691
- appKey 는 NHN Cloud 콘솔 → Container Registry 서비스에서 확인한다.
692
-
693
- ```bash
694
- # ncr appkey 설정 (비대화형)
695
- nhncloud configure --ncr-appkey <appkey>
696
-
697
- # 레지스트리 목록 조회
698
- nhncloud ncr list --app-key <appkey>
699
-
700
- # region 지정 (기본: kr1)
701
- nhncloud ncr list --region kr2 --app-key <appkey>
702
-
703
- # JSON 출력
704
- nhncloud ncr list --app-key <appkey> --json
705
-
706
- # 단일 레지스트리 조회 (이름 또는 ID)
707
- nhncloud ncr get <registry-name> --app-key <appkey>
708
- ```
709
-
710
- appKey 를 `nhncloud configure --ncr-appkey <appkey>` 로 저장해 두면 `--app-key` 없이도 호출할 수 있다.
711
-
712
- ```bash
713
- # configure 로 저장 후 --app-key 생략
714
- nhncloud configure --ncr-appkey <appkey>
715
- nhncloud ncr list
716
- nhncloud ncr get <registry-name>
717
- ```
718
-
719
- 이미지(repository)·태그는 레지스트리 데이터플레인 Harbor REST API 를 직접 호출한다.
720
- UAK 를 Basic Auth 로 사용하며 추가 설정은 없다.
721
-
722
- ```bash
723
- # 이미지(repository) 목록 조회
724
- nhncloud ncr images <registry>
725
-
726
- # region 지정
727
- nhncloud ncr images <registry> --region kr2
728
-
729
- # JSON 출력
730
- nhncloud ncr images <registry> --json
175
+ 의존 방향은 `commands/` → `services/` → `api/` 이고, `utils/` 와 `formatters/` 는 그 아래에서 공유한다.
176
+ `services/` 가 `commands/` 를 import 하지 않는다 — 역류는 금지다.
731
177
 
732
- # 특정 이미지의 태그 목록 조회
733
- nhncloud ncr tags <registry> <repository>
178
+ | 문서 | 담는 것 |
179
+ | --- | --- |
180
+ | [docs/prd.md](docs/prd.md) | 제품 목적과 범위 |
181
+ | [docs/flow.md](docs/flow.md) | 사용자 흐름 |
182
+ | [docs/code-architecture.md](docs/code-architecture.md) | 디렉터리 트리, 레이어, 경계 |
183
+ | [docs/data-schema.md](docs/data-schema.md) | 자격증명과 캐시 스키마 |
184
+ | [docs/adr/INDEX.md](docs/adr/INDEX.md) | 기술 의사결정 기록 (27건) |
185
+ | [docs/pitfalls/INDEX.md](docs/pitfalls/INDEX.md) | 반복해서 발견된 회피 패턴 (104건) |
734
186
 
735
- # JSON 출력 (태그·push_time·size)
736
- nhncloud ncr tags <registry> <repository> --json
737
- ```
187
+ ## 기여하기
738
188
 
739
- ### NHN Kubernetes Service (NKS)
189
+ 이슈와 PR 모두 환영한다.
740
190
 
741
- NKS는 `iaas` 자격증명으로 Keystone 토큰을 발급하고 `container-infra` API를 호출한다.
742
- 지원 region은 `kr1`, `kr2`, `kr3` 이다.
191
+ ### 개발 환경
743
192
 
744
193
  ```bash
745
- # 지원 Kubernetes version / event type 조회
746
- nhncloud nks supports
747
-
748
- # 클러스터와 노드 그룹 조회
749
- nhncloud nks cluster list
750
- nhncloud nks cluster get <cluster>
751
- nhncloud nks cluster events <cluster>
752
- nhncloud nks cluster event <cluster> <event>
753
- nhncloud nks cluster ipacl <cluster>
754
- nhncloud nks nodegroup list <cluster>
755
- nhncloud nks nodegroup get <cluster> <nodegroup>
756
- nhncloud nks nodegroup autoscale <cluster> <nodegroup>
757
-
758
- # kubeconfig stdout 출력 또는 mode 0600 파일 저장
759
- nhncloud nks cluster kubeconfig <cluster>
760
- nhncloud nks cluster kubeconfig <cluster> --output ./kubeconfig
761
- nhncloud nks cluster kubeconfig <cluster> --output ./kubeconfig --force
762
-
763
- # 애드온 조회
764
- nhncloud nks addon-type list
765
- nhncloud nks addon-type get <addon-type>
766
- nhncloud nks addon list --k8s-version v1.30.1
767
- nhncloud nks addon get <addon>
768
- nhncloud nks cluster addon list <cluster>
769
- nhncloud nks cluster addon get <cluster> <addon>
770
- ```
194
+ git clone https://github.com/jon890/nhncloud-cli.git
195
+ cd nhncloud-cli
196
+ pnpm install
771
197
 
772
- 복잡한 쓰기 작업은 공식 API payload를 JSON 파일로 전달한다.
773
- 삭제·제거 명령은 비대화형 환경에서 `--yes` 가 필요하다.
198
+ pnpm run build # tsup 으로 dist/index.js 단일 번들 생성
199
+ pnpm test # vitest
200
+ pnpm tsc --noEmit # 타입 검사 (빌드는 타입을 검사하지 않는다)
774
201
 
775
- ```bash
776
- # 클러스터 / 노드 그룹 생성
777
- nhncloud nks cluster create --file ./cluster-create.json
778
- nhncloud nks nodegroup create <cluster> --file ./nodegroup-create.json
779
-
780
- # resize / upgrade
781
- nhncloud nks cluster resize <cluster> --nodegroup worker --node-count 3
782
- nhncloud nks nodegroup upgrade <cluster> worker --version v1.30.1
783
-
784
- # 삭제 / 노드 action
785
- nhncloud nks cluster delete <cluster> --yes
786
- nhncloud nks nodegroup delete <cluster> worker --yes
787
- nhncloud nks nodegroup stop-node <cluster> worker --nodes node-1,node-2
788
- nhncloud nks nodegroup start-node <cluster> worker --nodes node-1,node-2
789
-
790
- # 애드온 설치 / 업데이트 / 제거
791
- nhncloud nks cluster addon install <cluster> \
792
- --name coredns \
793
- --version 1.0.0 \
794
- --resolve-conflicts overwrite
795
-
796
- nhncloud nks cluster addon update <cluster> coredns \
797
- --version 1.0.1 \
798
- --resolve-conflicts preserve
799
-
800
- nhncloud nks cluster addon remove <cluster> coredns --yes
801
-
802
- # payload 파일 기반 변경
803
- nhncloud nks cluster set-ipacl <cluster> --file ./ipacl.json
804
- nhncloud nks cluster renew-certificate <cluster> --term-of-validity 3
805
- nhncloud nks cluster update-sgw <cluster> --ncr-sgw <uuid> --obs-sgw <uuid>
806
- nhncloud nks cluster set-control-plane-log <cluster> --file ./control-plane-log.json
807
- nhncloud nks nodegroup set-autoscale <cluster> worker --file ./autoscale.json
808
- nhncloud nks nodegroup set-metric-autoscale <cluster> worker --file ./metric-autoscale.json
809
- nhncloud nks nodegroup set-userscript <cluster> worker --file ./userscript.sh
810
- nhncloud nks nodegroup update-flavor <cluster> worker --flavor <flavor-uuid>
811
- nhncloud nks nodegroup set-fip-auto-bind <cluster> worker --file ./fip-auto-bind.json
812
- nhncloud nks nodegroup set-labels <cluster> worker --file ./labels.json
202
+ node dist/index.js --help # 빌드 결과 직접 실행
203
+ node dist/index.js commands --json
813
204
  ```
814
205
 
815
- ### NHN Container Service (NCS)
206
+ `pnpm` 을 쓴다. 빌드는 `tsup`(esbuild) 이 담당하고 `tsc` 는 타입 검사 전용이므로,
207
+ 타입 오류를 잡으려면 `pnpm tsc --noEmit` 를 따로 돌려야 한다.
816
208
 
817
- NCS는 template(설계도)과 workload(런타임 실행)를 조회한다.
818
- 인증은 Deploy와 같은 UAK OAuth Bearer 토큰을 재사용하며(profile 토큰 캐시 공유), appkey는 경로에 포함한다.
819
- 지원 region은 `kr1`(판교), `kr3`(광주)만이다.
820
- appkey는 `nhncloud configure` (대화형 또는 `--ncs-appkey`) 로 설정하거나 `--app-key` 옵션으로 직접 넘긴다.
209
+ ### 새 명령을 추가할 때
821
210
 
822
- template(설계도)의 생성·삭제, workload(런타임 실행)의 생성·변경·실행제어(일시정지/재개/재시작/삭제), 악성코드 검사(malware) 설정·결과 조회를 지원한다.
211
+ 1. [공식 API 문서](https://docs.nhncloud.com)로 엔드포인트와 요청·응답 구조를 먼저 확인한다. 확정할 수 없으면 추측해 구현하지 않는다
212
+ 2. `src/services/<service>/` 에 API 클라이언트와 타입 가드를 둔다. 공식 예제 JSON 과 필드 타입을 맞춘다
213
+ 3. `src/commands/<service>/` 에 명령을 정의한다. 인접한 명령의 구조를 따르는 것이 가장 빠르다
214
+ 4. 출력은 `src/formatters/` 에서 표·JSON·quiet 세 모드를 모두 지원한다
215
+ 5. `src/**/*.test.ts` 에 테스트를 추가한다
216
+ 6. 명령이나 옵션이 바뀌면 이 README 와 `skills/nhncloud-cli/references/` 를 함께 갱신한다
823
217
 
824
- ```bash
825
- # template(설계도) 목록/단건/버전 조회
826
- nhncloud ncs template list --app-key <appkey>
827
- nhncloud ncs template get <template-id> --app-key <appkey>
828
- nhncloud ncs template version list <template-id> --app-key <appkey>
829
- nhncloud ncs template version get <template-id> <version> --app-key <appkey>
830
-
831
- # workload(런타임 실행) 목록/단건 조회
832
- nhncloud ncs workload list --app-key <appkey>
833
- nhncloud ncs workload get <workload-id> --app-key <appkey>
834
-
835
- # task 컨테이너 로그/이벤트 조회 (--task는 workload get 응답의 tasks[].id)
836
- nhncloud ncs workload logs <workload-id> \
837
- --task <task-id> \
838
- --container <name> \
839
- --from 1h \
840
- --to now \
841
- --profile <profile> \
842
- --json
843
- nhncloud ncs workload events <workload-id> \
844
- --task <task-id> \
845
- --from 1h \
846
- --to now \
847
- --profile <profile> \
848
- --json
849
-
850
- # 실행 히스토리 / 예약 실행 히스토리 조회
851
- nhncloud ncs workload history <workload-id> --app-key <appkey>
852
- nhncloud ncs workload history get <workload-id> <history-id> --app-key <appkey>
853
- nhncloud ncs workload schedule-history <workload-id> --app-key <appkey>
854
- ```
218
+ HTTP 호출은 `ky` 만 쓰고, 사용자 오류는 `NhnCloudCliError` 와 `src/utils/exit-codes.ts` 의 종료 코드를 쓴다.
219
+ 데이터는 stdout, 진행 상황·경고·오류는 stderr 로 분리한다.
855
220
 
856
- `workload logs`와 `workload events`의 `--from`·`--to`는 다음 입력을 받는다.
221
+ NHN Cloud API 가 문서와 다르거나 직관에 반하면 [docs/adr/](docs/adr/) 에 기록한다.
222
+ 엔드포인트 버전 이중 prefix 나 200 응답 속 `isSuccessful: false` 처럼, 모르고 접근하면 다시 막히는 것들이 이미 27건 쌓여 있다.
857
223
 
858
- - 시간대와 초를 포함한 RFC3339 절대시간
859
- - `now`
860
- - 0 이상의 정수 뒤에 `m`, `h`, `d` 중 하나를 붙인 상대시간
224
+ ### PR 을 낼 때
861
225
 
862
- 상대시간 예시는 `30m`, `1h`, `2d`다.
226
+ - 커밋과 PR 제목은 `type(scope): 설명` 형식을 쓴다
227
+ - 커밋 메시지와 PR 본문은 한국어로 쓴다
228
+ - PR 을 열면 CI 가 타입 검사·테스트·빌드를 돌리고, Claude 가 코드 리뷰를 남긴다
229
+ - 리뷰의 🔴 항목은 머지 전에 반영한다
863
230
 
864
- 입력은 API 호출 전에 UTC 초 단위 `Z` 문자열로 정규화된다.
865
- 두 옵션을 모두 생략하면 API 기본 범위를 사용하고, 한쪽만 지정할 수도 있다.
866
- 잘못된 날짜, 시간대 없는 절대시간, 역전된 범위는 자격증명과 API에 접근하기 전에 종료 코드 3으로 거부한다.
867
- 조회 데이터는 stdout, 진행 상황과 오류는 stderr에 출력한다.
231
+ 이 저장소와 npm 패키지는 공개된다.
232
+ 문서·코드·테스트 fixture·이슈 본문에 실제 자격증명이나 사용자 리소스 ID 를 남기지 않고 `<instance-id>` 같은 placeholder 로 바꾼다.
868
233
 
869
- template 생성·버전 생성처럼 복잡한 입력은 공식 API payload를 JSON 파일로 전달한다.
870
- 삭제 명령은 비대화형 환경에서 `--yes`가 필요하다.
234
+ ### 버그와 제안
871
235
 
872
- ```bash
873
- # template(설계도) 생성 / 삭제
874
- nhncloud ncs template create --file ./template-create.json --app-key <appkey>
875
- nhncloud ncs template delete <template-id> --yes --app-key <appkey>
876
-
877
- # template 버전 생성 / 삭제 (--file 의 sourceVersion 필드가 필수)
878
- nhncloud ncs template version create <template-id> --file ./version-create.json --app-key <appkey>
879
- nhncloud ncs template version delete <template-id> <version> --yes --app-key <appkey>
880
-
881
- # workload 실행제어 — 일시정지 / 재개 / task 재시작 / 삭제
882
- nhncloud ncs workload pause <workload-id> --app-key <appkey>
883
- nhncloud ncs workload resume <workload-id> --app-key <appkey>
884
- nhncloud ncs workload restart <workload-id> --task <task-id> --app-key <appkey>
885
- nhncloud ncs workload delete <workload-id> --yes --app-key <appkey>
886
- ```
236
+ [GitHub Issues](https://github.com/jon890/nhncloud-cli/issues) 에 올린다.
237
+ 설정 문제라면 `nhncloud doctor` 출력을 함께 붙이면 진단이 빠르다 (비밀값은 가려서 붙인다).
887
238
 
888
- workload 생성은 비동기다.
889
- `--wait`를 주면 `Running` 상태가 될 때까지 폴링하고, `--timeout`(초, 기본 300)으로 대기 시간을 조절한다.
890
- 변경은 `update`(PUT, 전체 교체)와 `patch`(PATCH, JSON Patch 배열로 부분 변경) 두 가지다.
239
+ ## 기술 스택
891
240
 
892
- ```bash
893
- # workload 생성 (--wait로 Running 대기)
894
- nhncloud ncs workload create --file ./workload-create.json --wait --app-key <appkey>
241
+ | 분류 | 사용 |
242
+ | --- | --- |
243
+ | 언어·런타임 | TypeScript, Node.js 20+ |
244
+ | CLI 프레임워크 | Commander.js |
245
+ | HTTP | ky |
246
+ | 출력 | chalk, cli-table3, ora |
247
+ | 대화형 입력 | @inquirer/prompts |
248
+ | 빌드 | tsup (CJS 단일 번들) |
249
+ | 테스트 | vitest |
895
250
 
896
- # workload 전체 교체 / 부분 변경(JSON Patch 배열)
897
- nhncloud ncs workload update <workload-id> --file ./workload-update.json --app-key <appkey>
898
- nhncloud ncs workload patch <workload-id> --file ./workload-patch.json --app-key <appkey>
899
- ```
251
+ ## 라이선스
900
252
 
901
- 악성코드 검사(malware) 설정은 appkey 단위이고, 검사 결과는 workload 실행 히스토리 단위로 조회한다.
902
-
903
- ```bash
904
- # 악성코드 검사 설정 조회 / 변경
905
- nhncloud ncs malware config get --app-key <appkey>
906
- nhncloud ncs malware config set --enabled true --app-key <appkey>
907
-
908
- # 악성코드 검사 결과 조회 (workload history get 응답의 id를 historyId로 사용)
909
- nhncloud ncs malware result <workload-id> <history-id> --app-key <appkey>
910
- ```
911
-
912
- ## 개발
913
-
914
- ```bash
915
- pnpm install
916
- pnpm run build # tsup 단일 번들 (dist/index.js)
917
- pnpm tsc --noEmit # 타입 체크
918
- node dist/index.js instance --help
919
- node dist/index.js logncrash search --help
920
- node dist/index.js ncr --help
921
- node dist/index.js nks --help
922
- node dist/index.js commands --json
923
- ```
253
+ MIT