@bifos/nhncloud-cli 0.5.1 → 0.7.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/dist/index.js CHANGED
@@ -24,8 +24,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/index.ts
27
- var import_commander38 = require("commander");
28
- var import_chalk12 = __toESM(require("chalk"));
27
+ var import_commander43 = require("commander");
28
+ var import_chalk14 = __toESM(require("chalk"));
29
29
 
30
30
  // src/utils/spinner.ts
31
31
  var import_ora = __toESM(require("ora"));
@@ -317,7 +317,7 @@ function iaasCachePath(profile, region) {
317
317
  function isIaasTokenCache(val) {
318
318
  if (typeof val !== "object" || val === null) return false;
319
319
  const obj = val;
320
- return typeof obj["tokenId"] === "string" && typeof obj["expiresAt"] === "string" && typeof obj["computeEndpoint"] === "string" && typeof obj["imageEndpoint"] === "string" && typeof obj["networkEndpoint"] === "string" && typeof obj["blockStorageEndpoint"] === "string";
320
+ return typeof obj["tokenId"] === "string" && typeof obj["expiresAt"] === "string" && typeof obj["computeEndpoint"] === "string" && typeof obj["imageEndpoint"] === "string" && typeof obj["networkEndpoint"] === "string" && typeof obj["blockStorageEndpoint"] === "string" && typeof obj["nksEndpoint"] === "string";
321
321
  }
322
322
  async function readIaasToken(profile, region) {
323
323
  const filePath = iaasCachePath(profile, region);
@@ -334,7 +334,8 @@ async function readIaasToken(profile, region) {
334
334
  computeEndpoint: parsed.computeEndpoint,
335
335
  imageEndpoint: parsed.imageEndpoint,
336
336
  networkEndpoint: parsed.networkEndpoint,
337
- blockStorageEndpoint: parsed.blockStorageEndpoint
337
+ blockStorageEndpoint: parsed.blockStorageEndpoint,
338
+ nksEndpoint: parsed.nksEndpoint
338
339
  };
339
340
  } catch {
340
341
  return null;
@@ -349,7 +350,8 @@ async function writeIaasToken(profile, region, data) {
349
350
  computeEndpoint: data.computeEndpoint,
350
351
  imageEndpoint: data.imageEndpoint,
351
352
  networkEndpoint: data.networkEndpoint,
352
- blockStorageEndpoint: data.blockStorageEndpoint
353
+ blockStorageEndpoint: data.blockStorageEndpoint,
354
+ nksEndpoint: data.nksEndpoint
353
355
  };
354
356
  const tmp = filePath + "." + (0, import_node_crypto.randomBytes)(4).toString("hex") + ".tmp";
355
357
  await (0, import_promises2.writeFile)(tmp, JSON.stringify(cache, null, 2), { encoding: "utf-8", mode: 384 });
@@ -495,6 +497,11 @@ var BLOCKSTORAGE_HOST = {
495
497
  jp1: "jp1-api-block-storage-infrastructure.nhncloudservice.com"
496
498
  };
497
499
  var IAAS_REGIONS = Object.keys(INSTANCE_HOST).join(", ");
500
+ var NKS_HOST = {
501
+ kr1: "kr1-api-kubernetes-infrastructure.nhncloudservice.com",
502
+ kr2: "kr2-api-kubernetes-infrastructure.nhncloudservice.com",
503
+ kr3: "kr3-api-kubernetes-infrastructure.nhncloudservice.com"
504
+ };
498
505
  var NCR_HOST = {
499
506
  kr1: "kr1-ncr.api.nhncloudservice.com",
500
507
  kr2: "kr2-ncr.api.nhncloudservice.com",
@@ -550,6 +557,16 @@ function blockStorageHost(region) {
550
557
  }
551
558
  return host;
552
559
  }
560
+ function nksHost(region) {
561
+ const host = NKS_HOST[region];
562
+ if (!host) {
563
+ throw new NhnCloudCliError(
564
+ `\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 NKS region \uC785\uB2C8\uB2E4: "${region}". \uC0AC\uC6A9 \uAC00\uB2A5\uD55C region: ${Object.keys(NKS_HOST).join(", ")}`,
565
+ EXIT_PARAM_ERROR
566
+ );
567
+ }
568
+ return host;
569
+ }
553
570
 
554
571
  // src/api/keystone.ts
555
572
  function isKeystoneTokenResponse(val) {
@@ -570,7 +587,8 @@ async function getIaasToken(profile, iaas, forceRefresh = false) {
570
587
  computeEndpoint: cached.computeEndpoint,
571
588
  imageEndpoint: cached.imageEndpoint,
572
589
  networkEndpoint: cached.networkEndpoint,
573
- blockStorageEndpoint: cached.blockStorageEndpoint
590
+ blockStorageEndpoint: cached.blockStorageEndpoint,
591
+ nksEndpoint: cached.nksEndpoint
574
592
  };
575
593
  }
576
594
  }
@@ -579,6 +597,7 @@ async function getIaasToken(profile, iaas, forceRefresh = false) {
579
597
  const imageEndpoint = `https://${imageHost(iaas.region)}/v2`;
580
598
  const networkEndpoint = `https://${networkHost(iaas.region)}/v2.0`;
581
599
  const blockStorageEndpoint = `https://${blockStorageHost(iaas.region)}/v2/${encodeURIComponent(iaas.tenantId)}`;
600
+ const nksEndpoint = `https://${nksHost(iaas.region)}/v1`;
582
601
  let raw;
583
602
  try {
584
603
  raw = await import_ky3.default.post(keystoneIdentityUrl(), {
@@ -605,9 +624,9 @@ async function getIaasToken(profile, iaas, forceRefresh = false) {
605
624
  const tokenId = raw.access.token.id;
606
625
  const expiresAt = raw.access.token.expires;
607
626
  if (!forceRefresh) {
608
- await writeIaasToken(profile, iaas.region, { tokenId, expiresAt, computeEndpoint, imageEndpoint, networkEndpoint, blockStorageEndpoint });
627
+ await writeIaasToken(profile, iaas.region, { tokenId, expiresAt, computeEndpoint, imageEndpoint, networkEndpoint, blockStorageEndpoint, nksEndpoint });
609
628
  }
610
- return { tokenId, computeEndpoint, imageEndpoint, networkEndpoint, blockStorageEndpoint };
629
+ return { tokenId, computeEndpoint, imageEndpoint, networkEndpoint, blockStorageEndpoint, nksEndpoint };
611
630
  }
612
631
 
613
632
  // src/services/logncrash/client.ts
@@ -1219,6 +1238,40 @@ function output(opts, data) {
1219
1238
  }
1220
1239
  }
1221
1240
 
1241
+ // src/commands/parse-options.ts
1242
+ var POSITIVE_INTEGER_PATTERN = /^[1-9]\d*$/;
1243
+ var NON_NEGATIVE_INTEGER_PATTERN = /^(0|[1-9]\d*)$/;
1244
+ function describeRange({ min, max }) {
1245
+ if (min !== void 0 && max !== void 0) return `${min} \uC774\uC0C1 ${max} \uC774\uD558\uC758 \uC815\uC218`;
1246
+ if (min !== void 0) return `${min} \uC774\uC0C1\uC758 \uC815\uC218`;
1247
+ if (max !== void 0) return `${max} \uC774\uD558\uC758 \uC815\uC218`;
1248
+ return "0 \uC774\uC0C1\uC758 \uC815\uC218";
1249
+ }
1250
+ function throwIntegerOptionError(value, flag, range) {
1251
+ throw new NhnCloudCliError(
1252
+ `${flag} \uB294 ${describeRange(range)}\uC5EC\uC57C \uD569\uB2C8\uB2E4 (\uC785\uB825: ${JSON.stringify(value)}).`,
1253
+ EXIT_PARAM_ERROR
1254
+ );
1255
+ }
1256
+ function parseIntegerOption(value, flag, range) {
1257
+ if (value === void 0) return void 0;
1258
+ const pattern = range.min !== void 0 && range.min > 0 ? POSITIVE_INTEGER_PATTERN : NON_NEGATIVE_INTEGER_PATTERN;
1259
+ if (!pattern.test(value)) {
1260
+ throwIntegerOptionError(value, flag, range);
1261
+ }
1262
+ const parsed = Number(value);
1263
+ if (!Number.isInteger(parsed) || range.min !== void 0 && parsed < range.min || range.max !== void 0 && parsed > range.max) {
1264
+ throwIntegerOptionError(value, flag, range);
1265
+ }
1266
+ return parsed;
1267
+ }
1268
+ function parsePositiveIntegerOption(value, flag) {
1269
+ return parseIntegerOption(value, flag, { min: 1 });
1270
+ }
1271
+ function parseNonNegativeIntegerOption(value, flag) {
1272
+ return parseIntegerOption(value, flag, { min: 0 });
1273
+ }
1274
+
1222
1275
  // src/commands/logncrash/search.ts
1223
1276
  function getString(value) {
1224
1277
  return typeof value === "string" ? value : String(value ?? "");
@@ -1240,17 +1293,8 @@ var searchCommand = new import_commander2.Command("search").description("Log & C
1240
1293
  if (!opts.to) {
1241
1294
  throw new NhnCloudCliError("--to \uC635\uC158\uC740 \uD544\uC218\uC785\uB2C8\uB2E4. \uC608: --to now", EXIT_PARAM_ERROR);
1242
1295
  }
1243
- const page = parseInt(opts.page ?? "0", 10);
1244
- const size = parseInt(opts.size ?? "10", 10);
1245
- if (isNaN(page) || page < 0) {
1246
- throw new NhnCloudCliError("--page \uB294 0 \uC774\uC0C1\uC758 \uC815\uC218\uC5EC\uC57C \uD569\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
1247
- }
1248
- if (isNaN(size) || size < 1) {
1249
- throw new NhnCloudCliError("--size \uB294 1 \uC774\uC0C1\uC758 \uC815\uC218\uC5EC\uC57C \uD569\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
1250
- }
1251
- if (size > 100) {
1252
- throw new NhnCloudCliError("--size \uB294 \uCD5C\uB300 100 \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
1253
- }
1296
+ const page = parseNonNegativeIntegerOption(opts.page ?? "0", "--page");
1297
+ const size = parseIntegerOption(opts.size ?? "10", "--size", { min: 1, max: 100 });
1254
1298
  const fromIso = resolveTime(opts.from);
1255
1299
  const toIso = resolveTime(opts.to);
1256
1300
  assertSearchRange(fromIso, toIso);
@@ -1778,6 +1822,7 @@ async function createDeployClient(profileOpt) {
1778
1822
  // src/commands/deploy/run.ts
1779
1823
  var runCommand = new import_commander5.Command("run").description("\uBC30\uD3EC\uB97C \uC2E4\uD589\uD55C\uB2E4").argument("<target>", "config.json \uC5D0 \uC815\uC758\uB41C deploy target \uC774\uB984").option("--app-key <k>", "target \uC758 appKey override").option("--artifact-id <id>", "target \uC758 artifactId override").option("--server-group-id <id>", "target \uC758 serverGroupId override").option("--scenario-ids <csv>", "target \uC758 scenarioIds override").option("--target-hosts <csv>", "\uB300\uC0C1 \uD638\uC2A4\uD2B8 (\uC0DD\uB7B5 \uC2DC \uC11C\uBC84\uADF8\uB8F9 \uC804\uCCB4)").option("--concurrent <n>", "\uBCD1\uB82C \uBC30\uD3EC \uC218 (\uAE30\uBCF8 1)", "1").option("--next-when-fail", "\uC2DC\uB098\uB9AC\uC624 \uC2E4\uD328 \uC2DC\uC5D0\uB3C4 \uC9C4\uD589").option("--note <s>", "\uBC30\uD3EC \uBA54\uBAA8").option("--async", "\uC989\uC2DC \uBC18\uD658 (\uAE30\uBCF8\uC740 \uC644\uB8CC \uB300\uAE30)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (targetName, _opts, cmd) => {
1780
1824
  const opts = cmd.optsWithGlobals();
1825
+ const concurrentNum = parsePositiveIntegerOption(opts.concurrent ?? "1", "--concurrent");
1781
1826
  const target = await getDeployTarget(targetName);
1782
1827
  const appKey = opts.appKey ?? target.appKey;
1783
1828
  const artifactId = opts.artifactId ?? target.artifactId;
@@ -1793,7 +1838,7 @@ var runCommand = new import_commander5.Command("run").description("\uBC30\uD3EC\
1793
1838
  serverGroupId,
1794
1839
  scenarioIds,
1795
1840
  targetHosts: opts.targetHosts,
1796
- concurrentNum: parseInt(opts.concurrent ?? "1", 10),
1841
+ concurrentNum,
1797
1842
  nextWhenFail: opts.nextWhenFail ?? false,
1798
1843
  deployNote: opts.note,
1799
1844
  async: opts.async ?? false
@@ -2129,6 +2174,15 @@ var downloadCommand = new import_commander12.Command("download").description("\u
2129
2174
  // src/commands/instance/list.ts
2130
2175
  var import_commander13 = require("commander");
2131
2176
 
2177
+ // src/commands/iaas.ts
2178
+ async function resolveIaasTokenContext(opts) {
2179
+ const profileName = await resolveProfileName(opts.profile);
2180
+ const iaas = await getIaasCredential(profileName);
2181
+ const effectiveIaas = opts.region ? { ...iaas, region: opts.region } : iaas;
2182
+ const tokenContext = await getIaasToken(profileName, effectiveIaas);
2183
+ return { profileName, ...tokenContext };
2184
+ }
2185
+
2132
2186
  // src/services/instance/client.ts
2133
2187
  var import_ky7 = __toESM(require("ky"));
2134
2188
  var DEFAULT_TIMEOUT_MS3 = 3e4;
@@ -2676,10 +2730,7 @@ var InstanceClient = class {
2676
2730
 
2677
2731
  // src/commands/instance/helpers.ts
2678
2732
  async function resolveInstanceClient(opts) {
2679
- const profileName = await resolveProfileName(opts.profile);
2680
- const iaas = await getIaasCredential(profileName);
2681
- const effectiveIaas = opts.region ? { ...iaas, region: opts.region } : iaas;
2682
- const { tokenId, computeEndpoint, imageEndpoint } = await getIaasToken(profileName, effectiveIaas);
2733
+ const { profileName, tokenId, computeEndpoint, imageEndpoint } = await resolveIaasTokenContext(opts);
2683
2734
  return { client: new InstanceClient(tokenId, computeEndpoint, imageEndpoint), profileName };
2684
2735
  }
2685
2736
 
@@ -2717,7 +2768,7 @@ function isVolume(val) {
2717
2768
  if (typeof val !== "object" || val === null) return false;
2718
2769
  const obj = val;
2719
2770
  return typeof obj["id"] === "string" && // Cinder 는 --name 미지정 시 null — null 인 볼륨 하나가 list 전체를 거부하지 않게 허용 (isImage 선례).
2720
- (typeof obj["name"] === "string" || obj["name"] === null) && typeof obj["size"] === "number" && typeof obj["status"] === "string" && Array.isArray(obj["attachments"]);
2771
+ (typeof obj["name"] === "string" || obj["name"] === null) && typeof obj["size"] === "number" && typeof obj["status"] === "string" && (obj["availability_zone"] === void 0 || typeof obj["availability_zone"] === "string") && Array.isArray(obj["attachments"]);
2721
2772
  }
2722
2773
  function isVolumesResponse(val) {
2723
2774
  if (typeof val !== "object" || val === null) return false;
@@ -2781,6 +2832,7 @@ var BlockStorageClient = class {
2781
2832
  if (params.name !== void 0) volumeBody["name"] = params.name;
2782
2833
  if (params.description !== void 0) volumeBody["description"] = params.description;
2783
2834
  if (params.volume_type !== void 0) volumeBody["volume_type"] = params.volume_type;
2835
+ if (params.availability_zone !== void 0) volumeBody["availability_zone"] = params.availability_zone;
2784
2836
  if (params.snapshot_id !== void 0) volumeBody["snapshot_id"] = params.snapshot_id;
2785
2837
  try {
2786
2838
  const raw = await import_ky8.default.post(url, {
@@ -2804,10 +2856,7 @@ var BlockStorageClient = class {
2804
2856
 
2805
2857
  // src/commands/volume/helpers.ts
2806
2858
  async function resolveVolumeClient(opts) {
2807
- const profileName = await resolveProfileName(opts.profile);
2808
- const iaas = await getIaasCredential(profileName);
2809
- const effectiveIaas = opts.region ? { ...iaas, region: opts.region } : iaas;
2810
- const { tokenId, blockStorageEndpoint } = await getIaasToken(profileName, effectiveIaas);
2859
+ const { profileName, tokenId, blockStorageEndpoint } = await resolveIaasTokenContext(opts);
2811
2860
  return { client: new BlockStorageClient(tokenId, blockStorageEndpoint), profileName };
2812
2861
  }
2813
2862
 
@@ -2889,7 +2938,7 @@ var getCommand = new import_commander15.Command("get").description("\uB2E8\uC77C
2889
2938
  // src/commands/volume/create.ts
2890
2939
  var import_commander16 = require("commander");
2891
2940
  var import_chalk3 = __toESM(require("chalk"));
2892
- var createCommand = new import_commander16.Command("create").description("\uBCFC\uB968\uC744 \uBC1C\uAE09\uD55C\uB2E4").requiredOption("--size <gb>", "\uBCFC\uB968 \uD06C\uAE30(GB) \u2014 \uD544\uC218").option("--name <name>", "\uBCFC\uB968 \uC774\uB984").option("--description <text>", "\uBCFC\uB968 \uC124\uBA85").option("--volume-type <type>", "\uBCFC\uB968 \uD0C0\uC785").option("--snapshot-id <id>", "\uC2A4\uB0C5\uC0F7 ID (\uC2A4\uB0C5\uC0F7\uC5D0\uC11C \uBCFC\uB968 \uC0DD\uC131)").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (_opts, cmd) => {
2941
+ var createCommand = new import_commander16.Command("create").description("\uBCFC\uB968\uC744 \uBC1C\uAE09\uD55C\uB2E4").requiredOption("--size <gb>", "\uBCFC\uB968 \uD06C\uAE30(GB) \u2014 \uD544\uC218").option("--name <name>", "\uBCFC\uB968 \uC774\uB984").option("--description <text>", "\uBCFC\uB968 \uC124\uBA85").option("--volume-type <type>", "\uBCFC\uB968 \uD0C0\uC785").option("--availability-zone <az>", "\uAC00\uC6A9\uC131 \uC601\uC5ED(AZ). instance availability-zones \uB85C \uC870\uD68C\uD55C zoneName \uC9C0\uC815").option("--snapshot-id <id>", "\uC2A4\uB0C5\uC0F7 ID (\uC2A4\uB0C5\uC0F7\uC5D0\uC11C \uBCFC\uB968 \uC0DD\uC131)").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (_opts, cmd) => {
2893
2942
  const opts = cmd.optsWithGlobals();
2894
2943
  if (!/^[1-9]\d*$/.test(opts.size)) {
2895
2944
  throw new NhnCloudCliError(
@@ -2898,6 +2947,13 @@ var createCommand = new import_commander16.Command("create").description("\uBCFC
2898
2947
  );
2899
2948
  }
2900
2949
  const sizeNum = Number(opts.size);
2950
+ const availabilityZone = opts.availabilityZone?.trim();
2951
+ if (opts.availabilityZone !== void 0 && availabilityZone === "") {
2952
+ throw new NhnCloudCliError(
2953
+ `--availability-zone \uC740 \uACF5\uBC31\uC774 \uC544\uB2CC \uBB38\uC790\uC5F4\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4: ${JSON.stringify(opts.availabilityZone)}`,
2954
+ EXIT_PARAM_ERROR
2955
+ );
2956
+ }
2901
2957
  const { client } = await resolveVolumeClient(opts);
2902
2958
  startSpinner("\uBCFC\uB968 \uBC1C\uAE09 \uC911...");
2903
2959
  let volume;
@@ -2907,6 +2963,7 @@ var createCommand = new import_commander16.Command("create").description("\uBCFC
2907
2963
  name: opts.name,
2908
2964
  description: opts.description,
2909
2965
  volume_type: opts.volumeType,
2966
+ availability_zone: availabilityZone,
2910
2967
  snapshot_id: opts.snapshotId
2911
2968
  });
2912
2969
  } catch (err) {
@@ -2922,6 +2979,7 @@ var createCommand = new import_commander16.Command("create").description("\uBCFC
2922
2979
  ["size", String(volume.size)],
2923
2980
  ["status", volume.status],
2924
2981
  ["volume_type", volume.volume_type ?? ""],
2982
+ ["availability_zone", volume.availability_zone ?? ""],
2925
2983
  ["created_at", volume.created_at]
2926
2984
  ];
2927
2985
  output(opts, {
@@ -3108,10 +3166,7 @@ var NetworkClient = class {
3108
3166
 
3109
3167
  // src/commands/network/helpers.ts
3110
3168
  async function resolveNetworkClient(opts) {
3111
- const profileName = await resolveProfileName(opts.profile);
3112
- const iaas = await getIaasCredential(profileName);
3113
- const effectiveIaas = opts.region ? { ...iaas, region: opts.region } : iaas;
3114
- const { tokenId, networkEndpoint } = await getIaasToken(profileName, effectiveIaas);
3169
+ const { profileName, tokenId, networkEndpoint } = await resolveIaasTokenContext(opts);
3115
3170
  return { client: new NetworkClient(tokenId, networkEndpoint), profileName };
3116
3171
  }
3117
3172
 
@@ -3276,18 +3331,10 @@ var deleteCommand = new import_commander21.Command("delete").description("Floati
3276
3331
 
3277
3332
  // src/commands/instance/flavors.ts
3278
3333
  var import_commander22 = require("commander");
3279
- function parseNonNegInt(value, flag) {
3280
- if (value === void 0) return void 0;
3281
- const n = Number(value);
3282
- if (!Number.isInteger(n) || n < 0) {
3283
- throw new NhnCloudCliError(`${flag} \uB294 0 \uC774\uC0C1\uC758 \uC815\uC218\uC5EC\uC57C \uD569\uB2C8\uB2E4 (\uC785\uB825: ${value}).`, EXIT_PARAM_ERROR);
3284
- }
3285
- return n;
3286
- }
3287
3334
  var flavorsCommand = new import_commander22.Command("flavors").description("\uC778\uC2A4\uD134\uC2A4 \uD0C0\uC785(flavor)\uC744 \uC870\uD68C\uD55C\uB2E4 (\uAE30\uBCF8 id\xB7name, --detail \uB85C \uC2A4\uD399, \uC804\uCCB4 \uD544\uB4DC\uB294 --json)").option("--detail", "vcpus\xB7ram\xB7disk \uB4F1 \uC2A4\uD399 \uD3EC\uD568 (GET /flavors/detail)").option("--min-disk <gb>", "\uCD5C\uC18C \uBE14\uB85D \uC2A4\uD1A0\uB9AC\uC9C0 \uD06C\uAE30(GB) \uC774\uC0C1\uB9CC \uD544\uD130").option("--min-ram <mb>", "\uCD5C\uC18C RAM \uD06C\uAE30(MB) \uC774\uC0C1\uB9CC \uD544\uD130").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (_opts, cmd) => {
3288
3335
  const opts = cmd.optsWithGlobals();
3289
- const minDisk = parseNonNegInt(opts.minDisk, "--min-disk");
3290
- const minRam = parseNonNegInt(opts.minRam, "--min-ram");
3336
+ const minDisk = parseNonNegativeIntegerOption(opts.minDisk, "--min-disk");
3337
+ const minRam = parseNonNegativeIntegerOption(opts.minRam, "--min-ram");
3291
3338
  const { client } = await resolveInstanceClient(opts);
3292
3339
  startSpinner("\uC778\uC2A4\uD134\uC2A4 \uD0C0\uC785 \uC870\uD68C \uC911...");
3293
3340
  try {
@@ -3444,7 +3491,9 @@ var createCommand3 = new import_commander25.Command("create").description("\uC77
3444
3491
  );
3445
3492
  }
3446
3493
  }
3447
- const timeoutMs = parseInt(opts.timeout ?? "300", 10) * 1e3;
3494
+ const timeoutMs = parsePositiveIntegerOption(opts.timeout ?? "300", "--timeout") * 1e3;
3495
+ const bootVolumeSize = parsePositiveIntegerOption(opts.bootVolumeSize, "--boot-volume-size");
3496
+ const ephemeralDiskSize = parsePositiveIntegerOption(opts.ephemeralDiskSize, "--ephemeral-disk-size");
3448
3497
  const { client } = await resolveInstanceClient(opts);
3449
3498
  startSpinner("\uC778\uC2A4\uD134\uC2A4 \uC0DD\uC131 \uC911...");
3450
3499
  let server;
@@ -3454,10 +3503,10 @@ var createCommand3 = new import_commander25.Command("create").description("\uC77
3454
3503
  flavorRef: opts.flavor,
3455
3504
  imageRef: opts.image,
3456
3505
  networks,
3457
- bootVolumeSize: opts.bootVolumeSize !== void 0 ? parseInt(opts.bootVolumeSize, 10) : void 0,
3506
+ bootVolumeSize,
3458
3507
  keyName: opts.keyName,
3459
3508
  securityGroups: opts.securityGroup && opts.securityGroup.length > 0 ? opts.securityGroup : void 0,
3460
- ephemeralDiskSize: opts.ephemeralDiskSize !== void 0 ? parseInt(opts.ephemeralDiskSize, 10) : void 0,
3509
+ ephemeralDiskSize,
3461
3510
  protect: opts.protect,
3462
3511
  userDataBase64
3463
3512
  });
@@ -3639,17 +3688,9 @@ var resizeRevertCommand = new import_commander28.Command("resize-revert").descri
3639
3688
  // src/commands/instance/images.ts
3640
3689
  var import_commander29 = require("commander");
3641
3690
  var VISIBILITY_VALUES = ["public", "private", "shared"];
3642
- function parsePositiveInt5(value, flag) {
3643
- if (value === void 0) return void 0;
3644
- const n = Number(value);
3645
- if (!Number.isInteger(n) || n < 1) {
3646
- throw new NhnCloudCliError(`${flag} \uB294 1 \uC774\uC0C1\uC758 \uC815\uC218\uC5EC\uC57C \uD569\uB2C8\uB2E4 (\uC785\uB825: ${value}).`, EXIT_PARAM_ERROR);
3647
- }
3648
- return n;
3649
- }
3650
3691
  var imagesCommand = new import_commander29.Command("images").description("\uC774\uBBF8\uC9C0 \uBAA9\uB85D\uC744 \uC870\uD68C\uD55C\uB2E4 (create --image <id> \uC18C\uC2A4, \uC804\uCCB4 \uD544\uB4DC\uB294 --json)").option("--limit <n>", "\uD55C \uD398\uC774\uC9C0 \uCD5C\uB300 \uAC1C\uC218 (\uAE30\uBCF8: \uC11C\uBC84 \uAE30\uBCF8\uAC12 25)").option("--marker <id>", "\uC774 image id \uB2E4\uC74C\uBD80\uD130 \uC870\uD68C (\uD398\uC774\uC9C0\uB124\uC774\uC158)").option("--name <name>", "\uC774\uB984\uC73C\uB85C \uD544\uD130").option("--visibility <v>", `\uB178\uCD9C \uBC94\uC704 \uD544\uD130 (${VISIBILITY_VALUES.join("|")})`).option("--owner <id>", "\uC18C\uC720\uC790(\uD504\uB85C\uC81D\uD2B8 id)\uB85C \uD544\uD130").option("--status <status>", "\uC0C1\uD0DC\uB85C \uD544\uD130 (\uC608: active)").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (_opts, cmd) => {
3651
3692
  const opts = cmd.optsWithGlobals();
3652
- const limit = parsePositiveInt5(opts.limit, "--limit");
3693
+ const limit = parsePositiveIntegerOption(opts.limit, "--limit");
3653
3694
  if (opts.visibility !== void 0 && !VISIBILITY_VALUES.includes(opts.visibility)) {
3654
3695
  throw new NhnCloudCliError(
3655
3696
  `--visibility \uB294 ${VISIBILITY_VALUES.join(" | ")} \uC911 \uD558\uB098\uC5EC\uC57C \uD569\uB2C8\uB2E4 (\uC785\uB825: ${opts.visibility}).`,
@@ -4206,78 +4247,1536 @@ var tagsCommand = new import_commander37.Command("tags").description("\uD2B9\uC8
4206
4247
  });
4207
4248
  });
4208
4249
 
4209
- // src/index.ts
4210
- var program = new import_commander38.Command();
4211
- program.name("nhncloud").description("NHN Cloud CLI \u2014 AI agent & terminal friendly").version("0.5.1").option("--json", "JSON \uD615\uC2DD\uC73C\uB85C \uCD9C\uB825").option("--quiet", "\uCD5C\uC18C \uCD9C\uB825 (\uC790\uB3D9\uD654\uC6A9)").option("--no-color", "\uC0C9\uC0C1 \uBE44\uD65C\uC131\uD654");
4212
- program.hook("preAction", () => {
4213
- const opts = program.opts();
4214
- if (!opts.color || process.env["NO_COLOR"]) {
4215
- import_chalk12.default.level = 0;
4250
+ // src/commands/commands.ts
4251
+ var import_commander38 = require("commander");
4252
+ function commandPath(command) {
4253
+ const names = [];
4254
+ let current2 = command;
4255
+ while (current2?.parent) {
4256
+ names.unshift(current2.name());
4257
+ current2 = current2.parent;
4258
+ }
4259
+ return names.join(" ");
4260
+ }
4261
+ function collectCommand(command) {
4262
+ const path = commandPath(command);
4263
+ if (!path || path === "help") return null;
4264
+ return {
4265
+ path,
4266
+ description: command.description() || command.summary() || "",
4267
+ arguments: command.registeredArguments.map((arg) => arg.name()),
4268
+ options: command.options.filter((option) => !option.hidden).map((option) => option.flags),
4269
+ subcommands: command.commands.map((subcommand) => subcommand.name()).filter((name) => name !== "help"),
4270
+ ...path === "commands" ? { metadata: true } : {}
4271
+ };
4272
+ }
4273
+ function collectCommandCatalog(program2) {
4274
+ const commands = [];
4275
+ function visit(command) {
4276
+ const entry = collectCommand(command);
4277
+ if (entry) commands.push(entry);
4278
+ for (const subcommand of command.commands) {
4279
+ visit(subcommand);
4280
+ }
4216
4281
  }
4217
- if (opts.json || opts.quiet) {
4218
- setQuiet(true);
4282
+ for (const command of program2.commands) {
4283
+ visit(command);
4219
4284
  }
4220
- });
4221
- program.addCommand(configureCommand);
4222
- var logncrashCommand = new import_commander38.Command("logncrash").description("Log & Crash \uAD00\uB828 \uBA85\uB839");
4223
- logncrashCommand.addCommand(searchCommand);
4224
- logncrashCommand.addCommand(sendCommand);
4225
- logncrashCommand.addCommand(exportCommand);
4226
- program.addCommand(logncrashCommand);
4227
- var deployCommand = new import_commander38.Command("deploy").description("NHN Cloud Deploy \uAD00\uB828 \uBA85\uB839");
4228
- deployCommand.addCommand(runCommand);
4229
- deployCommand.addCommand(artifactsCommand);
4230
- deployCommand.addCommand(serverGroupsCommand);
4231
- deployCommand.addCommand(historiesCommand);
4232
- deployCommand.addCommand(binaryGroupsCommand);
4233
- deployCommand.addCommand(binariesCommand);
4234
- deployCommand.addCommand(uploadCommand);
4235
- deployCommand.addCommand(downloadCommand);
4236
- program.addCommand(deployCommand);
4237
- var instanceCommand = new import_commander38.Command("instance").description("Compute \uC778\uC2A4\uD134\uC2A4 \uAD00\uB828 \uBA85\uB839");
4238
- instanceCommand.addCommand(listCommand);
4239
- instanceCommand.addCommand(flavorsCommand);
4240
- instanceCommand.addCommand(availabilityZonesCommand);
4241
- instanceCommand.addCommand(getCommand2);
4242
- instanceCommand.addCommand(createCommand3);
4243
- instanceCommand.addCommand(deleteCommand2);
4244
- instanceCommand.addCommand(startCommand);
4245
- instanceCommand.addCommand(stopCommand);
4246
- instanceCommand.addCommand(rebootCommand);
4247
- instanceCommand.addCommand(resizeCommand);
4248
- instanceCommand.addCommand(resizeConfirmCommand);
4249
- instanceCommand.addCommand(resizeRevertCommand);
4250
- instanceCommand.addCommand(imagesCommand);
4251
- instanceCommand.addCommand(keypairsCommand);
4252
- instanceCommand.addCommand(keypairCommand);
4253
- instanceCommand.addCommand(volumeCommand);
4254
- instanceCommand.addCommand(volumesCommand);
4255
- program.addCommand(instanceCommand);
4256
- var networkCommand = new import_commander38.Command("network").description("VPC\xB7\uC11C\uBE0C\uB137 \uC870\uD68C");
4257
- networkCommand.addCommand(listCommand3);
4258
- networkCommand.addCommand(subnetCommand);
4259
- program.addCommand(networkCommand);
4260
- var volumeCommand2 = new import_commander38.Command("volume").description("Block Storage \uBCFC\uB968 \uAD00\uB828 \uBA85\uB839");
4261
- volumeCommand2.addCommand(listCommand2);
4262
- volumeCommand2.addCommand(getCommand);
4263
- volumeCommand2.addCommand(createCommand);
4264
- program.addCommand(volumeCommand2);
4265
- var floatingipCommand = new import_commander38.Command("floatingip").description(
4266
- "Floating IP(\uC778\uC2A4\uD134\uC2A4 \uACF5\uC778 IP) \uAD00\uB9AC"
4267
- );
4285
+ commands.sort((a, b) => a.path.localeCompare(b.path));
4286
+ return { commands };
4287
+ }
4288
+ function createCommandsCommand(program2) {
4289
+ return new import_commander38.Command("commands").description("\uBA85\uB839 \uACBD\uB85C\uC640 \uC635\uC158 catalog\uB97C \uCD9C\uB825\uD55C\uB2E4").action((_opts, cmd) => {
4290
+ const opts = cmd.optsWithGlobals();
4291
+ const catalog = collectCommandCatalog(program2);
4292
+ output(opts, {
4293
+ headers: ["path", "description", "options"],
4294
+ rows: catalog.commands.map((entry) => [
4295
+ entry.path,
4296
+ entry.description,
4297
+ entry.options.join(", ")
4298
+ ]),
4299
+ raw: catalog,
4300
+ ids: catalog.commands.map((entry) => entry.path)
4301
+ });
4302
+ });
4303
+ }
4304
+
4305
+ // src/commands/nks/supports.ts
4306
+ var import_commander39 = require("commander");
4307
+
4308
+ // src/commands/nks/helpers.ts
4309
+ var import_promises4 = require("fs/promises");
4310
+
4311
+ // src/services/nks/client.ts
4312
+ var import_ky11 = __toESM(require("ky"));
4313
+
4314
+ // src/services/nks/types.ts
4315
+ function isNksClusterSummary(val) {
4316
+ if (typeof val !== "object" || val === null) return false;
4317
+ const obj = val;
4318
+ return typeof obj["uuid"] === "string" && typeof obj["name"] === "string" && typeof obj["status"] === "string" && typeof obj["health_status"] === "string" && (typeof obj["node_count"] === "number" || typeof obj["node_count"] === "string") && typeof obj["kube_tag"] === "string";
4319
+ }
4320
+ function isNksSupports(val) {
4321
+ if (typeof val !== "object" || val === null) return false;
4322
+ const obj = val;
4323
+ return isPlainObject(obj["supported_k8s"]) && isPlainObject(obj["supported_event_type"]);
4324
+ }
4325
+ function isPlainObject(val) {
4326
+ return typeof val === "object" && val !== null && !Array.isArray(val);
4327
+ }
4328
+ function isNksNamedResource(val) {
4329
+ if (!isPlainObject(val)) return false;
4330
+ if ("header" in val || "body" in val) return false;
4331
+ const uuid = val["uuid"];
4332
+ const id = val["id"];
4333
+ const name = val["name"];
4334
+ const status = val["status"];
4335
+ const hasKnownResourceField = typeof uuid === "string" || typeof id === "string" || typeof name === "string" || typeof status === "string";
4336
+ return hasKnownResourceField && (uuid === void 0 || typeof uuid === "string") && (id === void 0 || typeof id === "string") && (name === void 0 || typeof name === "string") && (status === void 0 || typeof status === "string");
4337
+ }
4338
+ function isNksNodeGroupSummary(val) {
4339
+ if (!isPlainObject(val)) return false;
4340
+ return typeof val["uuid"] === "string" && typeof val["name"] === "string" && typeof val["status"] === "string";
4341
+ }
4342
+ function isNksAddonType(val) {
4343
+ return isPlainObject(val) && typeof val["name"] === "string";
4344
+ }
4345
+ function isNksAddon(val) {
4346
+ return isPlainObject(val) && typeof val["name"] === "string";
4347
+ }
4348
+ function isNksClusterIpAcl(val) {
4349
+ if (!isPlainObject(val) || "header" in val || "body" in val) return false;
4350
+ if (typeof val["cluster_uuid"] !== "string" || !isBooleanLike(val["enable"])) return false;
4351
+ const isEnabled = val["enable"] === true || val["enable"] === "true";
4352
+ if (!isEnabled) return true;
4353
+ return typeof val["action"] === "string" && Array.isArray(val["ipacl_targets"]);
4354
+ }
4355
+ function isNksNodeGroupAutoscale(val) {
4356
+ return isPlainObject(val) && !("header" in val) && !("body" in val) && isBooleanLike(val["ca_enable"]) && typeof val["clusterautoscale"] === "string";
4357
+ }
4358
+ function isBooleanLike(val) {
4359
+ return typeof val === "boolean" || val === "true" || val === "false";
4360
+ }
4361
+ function isNksUuidResponse(val) {
4362
+ return isPlainObject(val) && typeof val["uuid"] === "string";
4363
+ }
4364
+
4365
+ // src/services/nks/client.ts
4366
+ var DEFAULT_TIMEOUT_MS7 = 3e4;
4367
+ function isArrayFieldResponse(key, val, itemGuard) {
4368
+ if (typeof val !== "object" || val === null) return false;
4369
+ const field = val[key];
4370
+ return Array.isArray(field) && field.every(itemGuard);
4371
+ }
4372
+ function isClustersResponse(val) {
4373
+ return isArrayFieldResponse("clusters", val, isNksClusterSummary);
4374
+ }
4375
+ function isNamedResourceArrayResponse(key, val) {
4376
+ return isArrayFieldResponse(key, val, isNksNamedResource);
4377
+ }
4378
+ function isConfigResponse(val) {
4379
+ if (typeof val !== "object" || val === null) return false;
4380
+ const obj = val;
4381
+ return typeof obj["config"] === "string";
4382
+ }
4383
+ function isNodeGroupsResponse(val) {
4384
+ return isArrayFieldResponse("nodegroups", val, isNksNodeGroupSummary);
4385
+ }
4386
+ function isAddonTypesResponse(val) {
4387
+ return isArrayFieldResponse("addon_types", val, isNksAddonType);
4388
+ }
4389
+ function isAddonsResponse(val) {
4390
+ return isArrayFieldResponse("addons", val, isNksAddon);
4391
+ }
4392
+ var NksClient = class {
4393
+ tokenId;
4394
+ nksEndpoint;
4395
+ constructor(tokenId, nksEndpoint) {
4396
+ this.tokenId = tokenId;
4397
+ this.nksEndpoint = nksEndpoint;
4398
+ }
4399
+ authHeaders() {
4400
+ return {
4401
+ "X-Auth-Token": this.tokenId,
4402
+ "OpenStack-API-Version": "container-infra latest"
4403
+ };
4404
+ }
4405
+ /** NKS 지원 Kubernetes 버전과 event type 을 조회한다 (GET /supports). */
4406
+ async supports() {
4407
+ const url = `${this.nksEndpoint}/supports`;
4408
+ try {
4409
+ const raw = await import_ky11.default.get(url, {
4410
+ headers: this.authHeaders(),
4411
+ retry: 0,
4412
+ timeout: DEFAULT_TIMEOUT_MS7
4413
+ }).json();
4414
+ if (!isNksSupports(raw)) {
4415
+ throw new NhnCloudCliError(
4416
+ "nks supports \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 supported_k8s / supported_event_type \uAC1D\uCCB4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
4417
+ EXIT_API_ERROR
4418
+ );
4419
+ }
4420
+ return raw;
4421
+ } catch (err) {
4422
+ throw toNhnCloudCliError(err);
4423
+ }
4424
+ }
4425
+ /** NKS 클러스터 목록을 조회한다 (GET /clusters). */
4426
+ async listClusters() {
4427
+ const url = `${this.nksEndpoint}/clusters`;
4428
+ try {
4429
+ const raw = await import_ky11.default.get(url, {
4430
+ headers: this.authHeaders(),
4431
+ retry: 0,
4432
+ timeout: DEFAULT_TIMEOUT_MS7
4433
+ }).json();
4434
+ if (!isClustersResponse(raw)) {
4435
+ throw new NhnCloudCliError(
4436
+ "nks cluster list \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 clusters \uBC30\uC5F4\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
4437
+ EXIT_API_ERROR
4438
+ );
4439
+ }
4440
+ return raw.clusters;
4441
+ } catch (err) {
4442
+ throw toNhnCloudCliError(err);
4443
+ }
4444
+ }
4445
+ async getCluster(cluster) {
4446
+ return this.getFlatNamedResource(
4447
+ `/clusters/${encodeURIComponent(cluster)}`,
4448
+ "nks cluster get \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 cluster \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4."
4449
+ );
4450
+ }
4451
+ async createCluster(payload) {
4452
+ return this.requestUuid("post", "/clusters", payload, "nks cluster create \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 uuid \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.");
4453
+ }
4454
+ async deleteCluster(cluster) {
4455
+ await this.requestNoBody("delete", `/clusters/${encodeURIComponent(cluster)}`);
4456
+ }
4457
+ async resizeCluster(params) {
4458
+ const payload = {
4459
+ nodegroup: params.nodegroup,
4460
+ node_count: params.nodeCount
4461
+ };
4462
+ if (params.nodesToRemove && params.nodesToRemove.length > 0) {
4463
+ payload["nodes_to_remove"] = params.nodesToRemove;
4464
+ }
4465
+ return this.requestUuid(
4466
+ "post",
4467
+ `/clusters/${encodeURIComponent(params.cluster)}/actions/resize`,
4468
+ payload,
4469
+ "nks cluster resize \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 uuid \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
4470
+ );
4471
+ }
4472
+ async setClusterIpAcl(cluster, payload) {
4473
+ return this.requestUuid(
4474
+ "post",
4475
+ `/clusters/${encodeURIComponent(cluster)}/api_ep_ipacl`,
4476
+ payload,
4477
+ "nks cluster set-ipacl \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 uuid \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
4478
+ );
4479
+ }
4480
+ async renewClusterCertificate(cluster, termOfValidity) {
4481
+ return this.requestUuid(
4482
+ "patch",
4483
+ `/certificates/${encodeURIComponent(cluster)}`,
4484
+ { term_of_validity: termOfValidity },
4485
+ "nks cluster renew-certificate \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 uuid \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
4486
+ );
4487
+ }
4488
+ async updateClusterServiceGateway(cluster, ncrSgw, obsSgw) {
4489
+ return this.requestUuid(
4490
+ "post",
4491
+ `/clusters/${encodeURIComponent(cluster)}/actions/update_sgw`,
4492
+ { ncr_sgw: ncrSgw, obs_sgw: obsSgw },
4493
+ "nks cluster update-sgw \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 uuid \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
4494
+ );
4495
+ }
4496
+ async setControlPlaneLog(cluster, controlPlaneLog) {
4497
+ return this.requestUuid(
4498
+ "patch",
4499
+ `/clusters/${encodeURIComponent(cluster)}`,
4500
+ { type: "control_plane_log", control_plane_log: controlPlaneLog },
4501
+ "nks cluster set-control-plane-log \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 uuid \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
4502
+ );
4503
+ }
4504
+ async listClusterEvents(cluster) {
4505
+ return this.getNamedResourceArray(
4506
+ "events",
4507
+ `/clusters/${encodeURIComponent(cluster)}/events`,
4508
+ "nks cluster events \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 events \uBC30\uC5F4\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."
4509
+ );
4510
+ }
4511
+ async getClusterEvent(cluster, event) {
4512
+ return this.getFlatNamedResource(
4513
+ `/clusters/${encodeURIComponent(cluster)}/events/${encodeURIComponent(event)}`,
4514
+ "nks cluster event \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 event \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4."
4515
+ );
4516
+ }
4517
+ async getClusterKubeconfig(cluster) {
4518
+ const raw = await this.getJson(`/clusters/${encodeURIComponent(cluster)}/config`);
4519
+ if (!isConfigResponse(raw)) {
4520
+ throw new NhnCloudCliError(
4521
+ "nks cluster kubeconfig \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 config \uBB38\uC790\uC5F4\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
4522
+ EXIT_API_ERROR
4523
+ );
4524
+ }
4525
+ return raw.config;
4526
+ }
4527
+ async getClusterIpAcl(cluster) {
4528
+ const raw = await this.getJson(`/clusters/${encodeURIComponent(cluster)}/api_ep_ipacl`);
4529
+ if (!isNksClusterIpAcl(raw)) {
4530
+ throw new NhnCloudCliError(
4531
+ "nks cluster ipacl \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 cluster_uuid, enable, action, ipacl_targets \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
4532
+ EXIT_API_ERROR
4533
+ );
4534
+ }
4535
+ return raw;
4536
+ }
4537
+ async listNodeGroups(cluster) {
4538
+ const raw = await this.getJson(`/clusters/${encodeURIComponent(cluster)}/nodegroups`);
4539
+ if (!isNodeGroupsResponse(raw)) {
4540
+ throw new NhnCloudCliError(
4541
+ "nks nodegroup list \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 nodegroups \uBC30\uC5F4\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
4542
+ EXIT_API_ERROR
4543
+ );
4544
+ }
4545
+ return raw.nodegroups;
4546
+ }
4547
+ async getNodeGroup(cluster, nodegroup) {
4548
+ const raw = await this.getJson(`/clusters/${encodeURIComponent(cluster)}/nodegroups/${encodeURIComponent(nodegroup)}`);
4549
+ if (!isNksNodeGroupSummary(raw)) {
4550
+ throw new NhnCloudCliError(
4551
+ "nks nodegroup get \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 nodegroup \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4.",
4552
+ EXIT_API_ERROR
4553
+ );
4554
+ }
4555
+ return raw;
4556
+ }
4557
+ async getNodeGroupAutoscale(cluster, nodegroup) {
4558
+ const raw = await this.getJson(`/clusters/${encodeURIComponent(cluster)}/nodegroups/${encodeURIComponent(nodegroup)}/autoscale`);
4559
+ if (!isNksNodeGroupAutoscale(raw)) {
4560
+ throw new NhnCloudCliError(
4561
+ "nks nodegroup autoscale \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 ca_enable, clusterautoscale \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
4562
+ EXIT_API_ERROR
4563
+ );
4564
+ }
4565
+ return raw;
4566
+ }
4567
+ async createNodeGroup(cluster, payload) {
4568
+ return this.requestUuid(
4569
+ "post",
4570
+ `/clusters/${encodeURIComponent(cluster)}/nodegroups`,
4571
+ payload,
4572
+ "nks nodegroup create \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 uuid \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
4573
+ );
4574
+ }
4575
+ async deleteNodeGroup(cluster, nodegroup) {
4576
+ await this.requestNoBody("delete", `/clusters/${encodeURIComponent(cluster)}/nodegroups/${encodeURIComponent(nodegroup)}`);
4577
+ }
4578
+ async stopNodeGroupNodes(cluster, nodegroup, nodes) {
4579
+ return this.requestUuid(
4580
+ "post",
4581
+ `/clusters/${encodeURIComponent(cluster)}/nodegroups/${encodeURIComponent(nodegroup)}/stop_node`,
4582
+ { node_list: nodes.join(":") },
4583
+ "nks nodegroup stop-node \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 uuid \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
4584
+ );
4585
+ }
4586
+ async startNodeGroupNodes(cluster, nodegroup, nodes) {
4587
+ return this.requestUuid(
4588
+ "post",
4589
+ `/clusters/${encodeURIComponent(cluster)}/nodegroups/${encodeURIComponent(nodegroup)}/start_node`,
4590
+ { node_list: nodes.join(":") },
4591
+ "nks nodegroup start-node \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 uuid \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
4592
+ );
4593
+ }
4594
+ async setNodeGroupAutoscale(cluster, nodegroup, payload) {
4595
+ return this.requestUuid(
4596
+ "post",
4597
+ `/clusters/${encodeURIComponent(cluster)}/nodegroups/${encodeURIComponent(nodegroup)}/autoscale`,
4598
+ payload,
4599
+ "nks nodegroup set-autoscale \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 uuid \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
4600
+ );
4601
+ }
4602
+ async setNodeGroupMetricAutoscale(cluster, nodegroup, payload) {
4603
+ return this.patchNodeGroup(cluster, nodegroup, "metric_base_autoscale", payload);
4604
+ }
4605
+ async upgradeNodeGroup(cluster, nodegroup, params) {
4606
+ const payload = { version: params.version };
4607
+ if (params.numBufferNodes !== void 0) payload["num_buffer_nodes"] = params.numBufferNodes;
4608
+ if (params.numMaxUnavailableNodes !== void 0) payload["num_max_unavailable_nodes"] = params.numMaxUnavailableNodes;
4609
+ return this.requestUuid(
4610
+ "post",
4611
+ `/clusters/${encodeURIComponent(cluster)}/nodegroups/${encodeURIComponent(nodegroup)}/upgrade`,
4612
+ payload,
4613
+ "nks nodegroup upgrade \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 uuid \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
4614
+ );
4615
+ }
4616
+ async setNodeGroupUserscript(cluster, nodegroup, contents) {
4617
+ return this.requestUuid(
4618
+ "post",
4619
+ `/clusters/${encodeURIComponent(cluster)}/nodegroups/${encodeURIComponent(nodegroup)}/userscript`,
4620
+ { contents },
4621
+ "nks nodegroup set-userscript \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 uuid \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
4622
+ );
4623
+ }
4624
+ async updateNodeGroupFlavor(cluster, nodegroup, params) {
4625
+ const payload = { flavor_id: params.flavorId };
4626
+ if (params.numBufferNodes !== void 0) payload["num_buffer_nodes"] = params.numBufferNodes;
4627
+ if (params.numMaxUnavailableNodes !== void 0) payload["num_max_unavailable_nodes"] = params.numMaxUnavailableNodes;
4628
+ return this.patchNodeGroup(cluster, nodegroup, "flavor_id", payload);
4629
+ }
4630
+ async setNodeGroupFipAutoBind(cluster, nodegroup, payload) {
4631
+ return this.patchNodeGroup(cluster, nodegroup, "fip_auto_bind", payload);
4632
+ }
4633
+ async setNodeGroupLabels(cluster, nodegroup, payload) {
4634
+ return this.patchNodeGroup(cluster, nodegroup, "k8s_node_labels", payload);
4635
+ }
4636
+ async listAddonTypes() {
4637
+ const raw = await this.getJson("/addon_types");
4638
+ if (!isAddonTypesResponse(raw)) {
4639
+ throw new NhnCloudCliError(
4640
+ "nks addon-type list \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 addon_types \uBC30\uC5F4\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
4641
+ EXIT_API_ERROR
4642
+ );
4643
+ }
4644
+ return raw.addon_types;
4645
+ }
4646
+ async getAddonType(addonType) {
4647
+ const raw = await this.getJson(`/addon_types/${encodeURIComponent(addonType)}`);
4648
+ if (!isNksAddonType(raw)) {
4649
+ throw new NhnCloudCliError(
4650
+ "nks addon-type get \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 addon_type \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4.",
4651
+ EXIT_API_ERROR
4652
+ );
4653
+ }
4654
+ return raw;
4655
+ }
4656
+ async listAddons(filters) {
4657
+ const searchParams = {};
4658
+ if (filters.k8sVersion) searchParams["k8s_version"] = filters.k8sVersion;
4659
+ if (filters.image) searchParams["image"] = filters.image;
4660
+ if (filters.platformVersion) searchParams["platform_version"] = filters.platformVersion;
4661
+ const raw = await this.getJson("/addons", searchParams);
4662
+ if (!isAddonsResponse(raw)) {
4663
+ throw new NhnCloudCliError(
4664
+ "nks addon list \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 addons \uBC30\uC5F4\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
4665
+ EXIT_API_ERROR
4666
+ );
4667
+ }
4668
+ return raw.addons;
4669
+ }
4670
+ async getAddon(addon) {
4671
+ const raw = await this.getJson(`/addons/${encodeURIComponent(addon)}`);
4672
+ if (!isNksAddon(raw)) {
4673
+ throw new NhnCloudCliError(
4674
+ "nks addon get \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 addon \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4.",
4675
+ EXIT_API_ERROR
4676
+ );
4677
+ }
4678
+ return raw;
4679
+ }
4680
+ async listClusterAddons(cluster) {
4681
+ const raw = await this.getJson(`/clusters/${encodeURIComponent(cluster)}/addons`);
4682
+ if (!isAddonsResponse(raw)) {
4683
+ throw new NhnCloudCliError(
4684
+ "nks cluster addon list \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 addons \uBC30\uC5F4\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
4685
+ EXIT_API_ERROR
4686
+ );
4687
+ }
4688
+ return raw.addons;
4689
+ }
4690
+ async getClusterAddon(cluster, addon) {
4691
+ const raw = await this.getJson(`/clusters/${encodeURIComponent(cluster)}/addons/${encodeURIComponent(addon)}`);
4692
+ if (!isNksAddon(raw)) {
4693
+ throw new NhnCloudCliError(
4694
+ "nks cluster addon get \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 addon \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4.",
4695
+ EXIT_API_ERROR
4696
+ );
4697
+ }
4698
+ return raw;
4699
+ }
4700
+ async installClusterAddon(cluster, params) {
4701
+ return this.requestUuid(
4702
+ "post",
4703
+ `/clusters/${encodeURIComponent(cluster)}/addons/`,
4704
+ {
4705
+ name: params.name,
4706
+ version: params.version,
4707
+ resolve_conflicts: params.resolveConflicts
4708
+ },
4709
+ "nks cluster addon install \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 uuid \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
4710
+ );
4711
+ }
4712
+ async updateClusterAddon(cluster, addon, params) {
4713
+ return this.requestUuid(
4714
+ "patch",
4715
+ `/clusters/${encodeURIComponent(cluster)}/addons/${encodeURIComponent(addon)}`,
4716
+ {
4717
+ version: params.version,
4718
+ resolve_conflicts: params.resolveConflicts
4719
+ },
4720
+ "nks cluster addon update \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 uuid \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
4721
+ );
4722
+ }
4723
+ async removeClusterAddon(cluster, addon) {
4724
+ const url = `${this.nksEndpoint}/clusters/${encodeURIComponent(cluster)}/addons/${encodeURIComponent(addon)}`;
4725
+ try {
4726
+ const raw = await import_ky11.default.delete(url, { headers: this.authHeaders(), retry: 0, timeout: DEFAULT_TIMEOUT_MS7 }).json();
4727
+ if (!isNksUuidResponse(raw)) {
4728
+ throw new NhnCloudCliError(
4729
+ "nks cluster addon remove \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 uuid \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
4730
+ EXIT_API_ERROR
4731
+ );
4732
+ }
4733
+ return raw;
4734
+ } catch (err) {
4735
+ throw toNhnCloudCliError(err);
4736
+ }
4737
+ }
4738
+ async getNamedResourceArray(key, path, errorMessage) {
4739
+ const raw = await this.getJson(path);
4740
+ if (!isNamedResourceArrayResponse(key, raw)) {
4741
+ throw new NhnCloudCliError(errorMessage, EXIT_API_ERROR);
4742
+ }
4743
+ return raw[key];
4744
+ }
4745
+ async getFlatNamedResource(path, errorMessage) {
4746
+ const raw = await this.getJson(path);
4747
+ if (!isNksNamedResource(raw)) {
4748
+ throw new NhnCloudCliError(errorMessage, EXIT_API_ERROR);
4749
+ }
4750
+ return raw;
4751
+ }
4752
+ async getJson(path, searchParams) {
4753
+ const url = `${this.nksEndpoint}${path}`;
4754
+ try {
4755
+ return await import_ky11.default.get(url, {
4756
+ headers: this.authHeaders(),
4757
+ searchParams,
4758
+ retry: 0,
4759
+ timeout: DEFAULT_TIMEOUT_MS7
4760
+ }).json();
4761
+ } catch (err) {
4762
+ throw toNhnCloudCliError(err);
4763
+ }
4764
+ }
4765
+ async requestUuid(method, path, payload, errorMessage) {
4766
+ const raw = await this.requestJson(method, path, payload);
4767
+ if (!isNksUuidResponse(raw)) {
4768
+ throw new NhnCloudCliError(errorMessage, EXIT_API_ERROR);
4769
+ }
4770
+ return raw;
4771
+ }
4772
+ async requestNoBody(method, path, payload) {
4773
+ const url = `${this.nksEndpoint}${path}`;
4774
+ try {
4775
+ if (method === "delete") {
4776
+ await import_ky11.default.delete(url, { headers: this.authHeaders(), retry: 0, timeout: DEFAULT_TIMEOUT_MS7 });
4777
+ return;
4778
+ }
4779
+ await import_ky11.default.post(url, { headers: this.authHeaders(), json: payload, retry: 0, timeout: DEFAULT_TIMEOUT_MS7 });
4780
+ } catch (err) {
4781
+ throw toNhnCloudCliError(err);
4782
+ }
4783
+ }
4784
+ async requestJson(method, path, payload) {
4785
+ const url = `${this.nksEndpoint}${path}`;
4786
+ try {
4787
+ const options = { headers: this.authHeaders(), json: payload, retry: 0, timeout: DEFAULT_TIMEOUT_MS7 };
4788
+ return method === "post" ? await import_ky11.default.post(url, options).json() : await import_ky11.default.patch(url, options).json();
4789
+ } catch (err) {
4790
+ throw toNhnCloudCliError(err);
4791
+ }
4792
+ }
4793
+ async patchNodeGroup(cluster, nodegroup, type, payload) {
4794
+ return this.requestUuid(
4795
+ "patch",
4796
+ `/clusters/${encodeURIComponent(cluster)}/nodegroups/${encodeURIComponent(nodegroup)}`,
4797
+ { ...payload, type },
4798
+ "nks nodegroup patch \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 uuid \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
4799
+ );
4800
+ }
4801
+ };
4802
+
4803
+ // src/commands/nks/helpers.ts
4804
+ async function resolveNksClient(opts) {
4805
+ const { profileName, tokenId, nksEndpoint } = await resolveIaasTokenContext(opts);
4806
+ return { client: new NksClient(tokenId, nksEndpoint), profileName };
4807
+ }
4808
+ async function readJsonFile(path) {
4809
+ let raw;
4810
+ try {
4811
+ raw = await (0, import_promises4.readFile)(path, "utf-8");
4812
+ } catch (err) {
4813
+ const message = err instanceof Error ? err.message : String(err);
4814
+ throw new NhnCloudCliError(`JSON \uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${path} (${message})`, EXIT_PARAM_ERROR);
4815
+ }
4816
+ try {
4817
+ const parsed = JSON.parse(raw);
4818
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
4819
+ throw new Error("top-level JSON object required");
4820
+ }
4821
+ return parsed;
4822
+ } catch (err) {
4823
+ const message = err instanceof Error ? err.message : String(err);
4824
+ throw new NhnCloudCliError(`JSON \uD30C\uC77C \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: ${path} (${message})`, EXIT_PARAM_ERROR);
4825
+ }
4826
+ }
4827
+ async function readTextFile(path) {
4828
+ try {
4829
+ return await (0, import_promises4.readFile)(path, "utf-8");
4830
+ } catch (err) {
4831
+ const message = err instanceof Error ? err.message : String(err);
4832
+ throw new NhnCloudCliError(`\uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${path} (${message})`, EXIT_PARAM_ERROR);
4833
+ }
4834
+ }
4835
+ function parsePositiveInteger(value, optionName) {
4836
+ if (!/^[1-9]\d*$/.test(value)) {
4837
+ throw new NhnCloudCliError(`${optionName} \uB294 \uC591\uC758 \uC815\uC218\uC5EC\uC57C \uD569\uB2C8\uB2E4: ${JSON.stringify(value)}`, EXIT_PARAM_ERROR);
4838
+ }
4839
+ return Number(value);
4840
+ }
4841
+ function parseNonNegativeInteger(value, optionName) {
4842
+ if (!/^\d+$/.test(value)) {
4843
+ throw new NhnCloudCliError(`${optionName} \uB294 0 \uC774\uC0C1\uC758 \uC815\uC218\uC5EC\uC57C \uD569\uB2C8\uB2E4: ${JSON.stringify(value)}`, EXIT_PARAM_ERROR);
4844
+ }
4845
+ return Number(value);
4846
+ }
4847
+
4848
+ // src/commands/nks/supports.ts
4849
+ var supportsCommand = new import_commander39.Command("supports").description("NKS \uC9C0\uC6D0 Kubernetes \uBC84\uC804\uACFC event type \uC744 \uC870\uD68C\uD55C\uB2E4").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (_opts, cmd) => {
4850
+ const opts = cmd.optsWithGlobals();
4851
+ const { client } = await resolveNksClient(opts);
4852
+ startSpinner("NKS \uC9C0\uC6D0 \uC815\uBCF4 \uC870\uD68C \uC911...");
4853
+ let supports;
4854
+ try {
4855
+ supports = await client.supports();
4856
+ } catch (err) {
4857
+ stopSpinner(false);
4858
+ throw err;
4859
+ }
4860
+ stopSpinner(true);
4861
+ output(opts, {
4862
+ headers: ["kubernetes_version", "supported"],
4863
+ rows: Object.entries(supports.supported_k8s).map(([version, supported]) => [
4864
+ version,
4865
+ String(supported)
4866
+ ]),
4867
+ raw: supports,
4868
+ ids: Object.keys(supports.supported_k8s)
4869
+ });
4870
+ });
4871
+
4872
+ // src/commands/nks/cluster.ts
4873
+ var import_promises5 = require("fs/promises");
4874
+ var import_commander40 = require("commander");
4875
+ var import_chalk12 = __toESM(require("chalk"));
4876
+ var listCommand6 = new import_commander40.Command("list").description("NKS \uD074\uB7EC\uC2A4\uD130 \uBAA9\uB85D\uC744 \uC870\uD68C\uD55C\uB2E4").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (_opts, cmd) => {
4877
+ const opts = cmd.optsWithGlobals();
4878
+ const { client } = await resolveNksClient(opts);
4879
+ startSpinner("NKS \uD074\uB7EC\uC2A4\uD130 \uBAA9\uB85D \uC870\uD68C \uC911...");
4880
+ let clusters;
4881
+ try {
4882
+ clusters = await client.listClusters();
4883
+ } catch (err) {
4884
+ stopSpinner(false);
4885
+ throw err;
4886
+ }
4887
+ stopSpinner(true);
4888
+ output(opts, {
4889
+ headers: ["uuid", "name", "status", "health_status", "node_count", "kube_tag"],
4890
+ rows: clusters.map((cluster) => [
4891
+ cluster.uuid,
4892
+ cluster.name,
4893
+ cluster.status,
4894
+ cluster.health_status,
4895
+ String(cluster.node_count),
4896
+ cluster.kube_tag
4897
+ ]),
4898
+ raw: clusters,
4899
+ ids: clusters.map((cluster) => cluster.uuid)
4900
+ });
4901
+ });
4902
+ function resourceId(resource) {
4903
+ return resource.uuid ?? resource.id ?? resource.name ?? "";
4904
+ }
4905
+ function resourceRow(resource) {
4906
+ return [
4907
+ resourceId(resource),
4908
+ resource.name ?? "",
4909
+ resource.status ?? ""
4910
+ ];
4911
+ }
4912
+ function addonRow(addon) {
4913
+ return [
4914
+ addon.uuid ?? addon.id ?? addon.name,
4915
+ addon.name,
4916
+ addon.version ?? "",
4917
+ addon.status ?? ""
4918
+ ];
4919
+ }
4920
+ function clusterIpAclRow(ipAcl) {
4921
+ return [
4922
+ ipAcl.cluster_uuid,
4923
+ String(ipAcl.enable),
4924
+ ipAcl.action ?? "",
4925
+ String(ipAcl.ipacl_targets?.length ?? 0)
4926
+ ];
4927
+ }
4928
+ function uuidOutput(opts, result, label) {
4929
+ process.stderr.write(import_chalk12.default.green(`\u2713 ${label} \uC694\uCCAD \uC644\uB8CC (uuid: ${result.uuid})
4930
+ `));
4931
+ output(opts, {
4932
+ headers: ["field", "value"],
4933
+ rows: [["uuid", result.uuid]],
4934
+ raw: result,
4935
+ ids: [result.uuid]
4936
+ });
4937
+ }
4938
+ async function confirmDangerousAction(message, yes) {
4939
+ const isTTY = process.stdin.isTTY;
4940
+ if (!isTTY && !yes) {
4941
+ throw new NhnCloudCliError(
4942
+ "\uBE44\uB300\uD654\uD615 \uD658\uACBD\uC5D0\uC11C \uC704\uD5D8 \uC791\uC5C5\uC740 --yes \uD50C\uB798\uADF8\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
4943
+ EXIT_PARAM_ERROR
4944
+ );
4945
+ }
4946
+ if (!isTTY || yes) return true;
4947
+ const { confirm } = await import("@inquirer/prompts");
4948
+ const ok = await confirm({ message, default: false });
4949
+ if (!ok) {
4950
+ process.stderr.write(import_chalk12.default.yellow("\uC791\uC5C5\uC774 \uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\n"));
4951
+ }
4952
+ return ok;
4953
+ }
4954
+ async function writeKubeconfigFile(path, contents, force) {
4955
+ try {
4956
+ await (0, import_promises5.writeFile)(path, contents, {
4957
+ encoding: "utf-8",
4958
+ mode: 384,
4959
+ flag: force ? "w" : "wx"
4960
+ });
4961
+ await (0, import_promises5.chmod)(path, 384);
4962
+ } catch (err) {
4963
+ if (err instanceof Error && "code" in err && err.code === "EEXIST") {
4964
+ throw new NhnCloudCliError(
4965
+ `\uD30C\uC77C\uC774 \uC774\uBBF8 \uC874\uC7AC\uD569\uB2C8\uB2E4: ${path}. \uB36E\uC5B4\uC4F0\uB824\uBA74 --force \uB97C \uC9C0\uC815\uD558\uC138\uC694.`,
4966
+ EXIT_PARAM_ERROR
4967
+ );
4968
+ }
4969
+ throw err;
4970
+ }
4971
+ }
4972
+ var createCommand4 = new import_commander40.Command("create").description("NKS \uD074\uB7EC\uC2A4\uD130\uB97C \uC0DD\uC131\uD55C\uB2E4").requiredOption("--file <json>", "\uACF5\uC2DD API payload JSON \uD30C\uC77C").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (_opts, cmd) => {
4973
+ const opts = cmd.optsWithGlobals();
4974
+ const payload = await readJsonFile(opts.file);
4975
+ const { client } = await resolveNksClient(opts);
4976
+ startSpinner("NKS \uD074\uB7EC\uC2A4\uD130 \uC0DD\uC131 \uC694\uCCAD \uC911...");
4977
+ let result;
4978
+ try {
4979
+ result = await client.createCluster(payload);
4980
+ } catch (err) {
4981
+ stopSpinner(false);
4982
+ throw err;
4983
+ }
4984
+ stopSpinner(true);
4985
+ uuidOutput(opts, result, "\uD074\uB7EC\uC2A4\uD130 \uC0DD\uC131");
4986
+ });
4987
+ var deleteCommand3 = new import_commander40.Command("delete").description("NKS \uD074\uB7EC\uC2A4\uD130\uB97C \uC0AD\uC81C\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").option("--yes", "\uD655\uC778 \uD504\uB86C\uD504\uD2B8 \uC0DD\uB7B5 (CI/\uBE44\uB300\uD654\uD615 \uD544\uC218)").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, _opts, cmd) => {
4988
+ const opts = cmd.optsWithGlobals();
4989
+ const ok = await confirmDangerousAction(`NKS \uD074\uB7EC\uC2A4\uD130 "${cluster}" \uB97C \uC0AD\uC81C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?`, opts.yes);
4990
+ if (!ok) return;
4991
+ const { client } = await resolveNksClient(opts);
4992
+ startSpinner("NKS \uD074\uB7EC\uC2A4\uD130 \uC0AD\uC81C \uC694\uCCAD \uC911...");
4993
+ try {
4994
+ await client.deleteCluster(cluster);
4995
+ } catch (err) {
4996
+ stopSpinner(false);
4997
+ throw err;
4998
+ }
4999
+ stopSpinner(true);
5000
+ process.stderr.write(import_chalk12.default.green(`\u2713 NKS \uD074\uB7EC\uC2A4\uD130 "${cluster}" \uC0AD\uC81C \uC694\uCCAD \uC644\uB8CC
5001
+ `));
5002
+ });
5003
+ var resizeCommand2 = new import_commander40.Command("resize").description("NKS \uD074\uB7EC\uC2A4\uD130 \uB178\uB4DC \uADF8\uB8F9 \uD06C\uAE30\uB97C \uBCC0\uACBD\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").requiredOption("--nodegroup <name-or-uuid>", "\uB178\uB4DC \uADF8\uB8F9 UUID \uB610\uB294 \uC774\uB984").requiredOption("--node-count <n>", "\uBCC0\uACBD\uD560 \uB178\uB4DC \uC218").option("--nodes-to-remove <csv>", "\uC0AD\uC81C\uD560 \uB178\uB4DC \uC774\uB984/ID CSV").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, _opts, cmd) => {
5004
+ const opts = cmd.optsWithGlobals();
5005
+ const nodeCount = parsePositiveInteger(opts.nodeCount, "--node-count");
5006
+ const nodesToRemove = opts.nodesToRemove?.split(",").map((node) => node.trim()).filter(Boolean);
5007
+ if (!nodesToRemove || nodesToRemove.length === 0) {
5008
+ process.stderr.write(import_chalk12.default.yellow("\uC8FC\uC758: --nodes-to-remove \uAC00 \uC5C6\uC73C\uBA74 \uAC10\uCD95 \uC2DC API\uAC00 \uC0AD\uC81C \uB178\uB4DC\uB97C \uC120\uD0DD\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.\n"));
5009
+ }
5010
+ const { client } = await resolveNksClient(opts);
5011
+ startSpinner("NKS \uD074\uB7EC\uC2A4\uD130 resize \uC694\uCCAD \uC911...");
5012
+ let result;
5013
+ try {
5014
+ result = await client.resizeCluster({
5015
+ cluster,
5016
+ nodegroup: opts.nodegroup,
5017
+ nodeCount,
5018
+ nodesToRemove
5019
+ });
5020
+ } catch (err) {
5021
+ stopSpinner(false);
5022
+ throw err;
5023
+ }
5024
+ stopSpinner(true);
5025
+ uuidOutput(opts, result, "\uD074\uB7EC\uC2A4\uD130 resize");
5026
+ });
5027
+ var setIpAclCommand = new import_commander40.Command("set-ipacl").description("NKS \uD074\uB7EC\uC2A4\uD130 API endpoint IP ACL \uC744 \uC124\uC815\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").requiredOption("--file <json>", "\uACF5\uC2DD API payload JSON \uD30C\uC77C").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, _opts, cmd) => {
5028
+ const opts = cmd.optsWithGlobals();
5029
+ const payload = await readJsonFile(opts.file);
5030
+ const { client } = await resolveNksClient(opts);
5031
+ startSpinner("NKS IP ACL \uC124\uC815 \uC694\uCCAD \uC911...");
5032
+ let result;
5033
+ try {
5034
+ result = await client.setClusterIpAcl(cluster, payload);
5035
+ } catch (err) {
5036
+ stopSpinner(false);
5037
+ throw err;
5038
+ }
5039
+ stopSpinner(true);
5040
+ uuidOutput(opts, result, "IP ACL \uC124\uC815");
5041
+ });
5042
+ var renewCertificateCommand = new import_commander40.Command("renew-certificate").description("NKS \uD074\uB7EC\uC2A4\uD130 \uC778\uC99D\uC11C\uB97C \uAC31\uC2E0\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").requiredOption("--term-of-validity <1-5>", "\uC778\uC99D\uC11C \uC720\uD6A8 \uAE30\uAC04(\uB144)").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, _opts, cmd) => {
5043
+ const opts = cmd.optsWithGlobals();
5044
+ const term = parsePositiveInteger(opts.termOfValidity, "--term-of-validity");
5045
+ if (term < 1 || term > 5) {
5046
+ throw new NhnCloudCliError("--term-of-validity \uB294 1~5 \uC0AC\uC774\uC5EC\uC57C \uD569\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
5047
+ }
5048
+ const { client } = await resolveNksClient(opts);
5049
+ startSpinner("NKS \uC778\uC99D\uC11C \uAC31\uC2E0 \uC694\uCCAD \uC911...");
5050
+ let result;
5051
+ try {
5052
+ result = await client.renewClusterCertificate(cluster, term);
5053
+ } catch (err) {
5054
+ stopSpinner(false);
5055
+ throw err;
5056
+ }
5057
+ stopSpinner(true);
5058
+ uuidOutput(opts, result, "\uC778\uC99D\uC11C \uAC31\uC2E0");
5059
+ });
5060
+ var updateSgwCommand = new import_commander40.Command("update-sgw").description("NKS \uD074\uB7EC\uC2A4\uD130 \uC11C\uBE44\uC2A4 \uAC8C\uC774\uD2B8\uC6E8\uC774\uB97C \uBCC0\uACBD\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").requiredOption("--ncr-sgw <uuid>", "NCR service gateway UUID").requiredOption("--obs-sgw <uuid>", "Object Storage service gateway UUID").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, _opts, cmd) => {
5061
+ const opts = cmd.optsWithGlobals();
5062
+ const { client } = await resolveNksClient(opts);
5063
+ startSpinner("NKS \uC11C\uBE44\uC2A4 \uAC8C\uC774\uD2B8\uC6E8\uC774 \uBCC0\uACBD \uC694\uCCAD \uC911...");
5064
+ let result;
5065
+ try {
5066
+ result = await client.updateClusterServiceGateway(cluster, opts.ncrSgw, opts.obsSgw);
5067
+ } catch (err) {
5068
+ stopSpinner(false);
5069
+ throw err;
5070
+ }
5071
+ stopSpinner(true);
5072
+ uuidOutput(opts, result, "\uC11C\uBE44\uC2A4 \uAC8C\uC774\uD2B8\uC6E8\uC774 \uBCC0\uACBD");
5073
+ });
5074
+ var setControlPlaneLogCommand = new import_commander40.Command("set-control-plane-log").description("NKS \uD074\uB7EC\uC2A4\uD130 control plane log \uC124\uC815\uC744 \uBCC0\uACBD\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").requiredOption("--file <json>", "control_plane_log \uAC1D\uCCB4 JSON \uD30C\uC77C").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, _opts, cmd) => {
5075
+ const opts = cmd.optsWithGlobals();
5076
+ const controlPlaneLog = await readJsonFile(opts.file);
5077
+ const { client } = await resolveNksClient(opts);
5078
+ startSpinner("NKS control plane log \uC124\uC815 \uC694\uCCAD \uC911...");
5079
+ let result;
5080
+ try {
5081
+ result = await client.setControlPlaneLog(cluster, controlPlaneLog);
5082
+ } catch (err) {
5083
+ stopSpinner(false);
5084
+ throw err;
5085
+ }
5086
+ stopSpinner(true);
5087
+ uuidOutput(opts, result, "control plane log \uC124\uC815");
5088
+ });
5089
+ var getCommand4 = new import_commander40.Command("get").description("NKS \uD074\uB7EC\uC2A4\uD130\uB97C \uC870\uD68C\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, _opts, cmd) => {
5090
+ const opts = cmd.optsWithGlobals();
5091
+ const { client } = await resolveNksClient(opts);
5092
+ startSpinner("NKS \uD074\uB7EC\uC2A4\uD130 \uC870\uD68C \uC911...");
5093
+ let result;
5094
+ try {
5095
+ result = await client.getCluster(cluster);
5096
+ } catch (err) {
5097
+ stopSpinner(false);
5098
+ throw err;
5099
+ }
5100
+ stopSpinner(true);
5101
+ output(opts, {
5102
+ headers: ["id", "name", "status"],
5103
+ rows: [resourceRow(result)],
5104
+ raw: result,
5105
+ ids: [resourceId(result)]
5106
+ });
5107
+ });
5108
+ var eventsCommand = new import_commander40.Command("events").description("NKS \uD074\uB7EC\uC2A4\uD130 \uC791\uC5C5 \uC774\uB825\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, _opts, cmd) => {
5109
+ const opts = cmd.optsWithGlobals();
5110
+ const { client } = await resolveNksClient(opts);
5111
+ startSpinner("NKS \uD074\uB7EC\uC2A4\uD130 \uC791\uC5C5 \uC774\uB825 \uC870\uD68C \uC911...");
5112
+ let events;
5113
+ try {
5114
+ events = await client.listClusterEvents(cluster);
5115
+ } catch (err) {
5116
+ stopSpinner(false);
5117
+ throw err;
5118
+ }
5119
+ stopSpinner(true);
5120
+ output(opts, {
5121
+ headers: ["id", "name", "status"],
5122
+ rows: events.map(resourceRow),
5123
+ raw: events,
5124
+ ids: events.map(resourceId)
5125
+ });
5126
+ });
5127
+ var eventCommand = new import_commander40.Command("event").description("NKS \uD074\uB7EC\uC2A4\uD130 \uC791\uC5C5 \uC774\uB825 \uB2E8\uAC74\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").argument("<event>", "\uC791\uC5C5 \uC774\uB825 UUID \uB610\uB294 ID").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, event, _opts, cmd) => {
5128
+ const opts = cmd.optsWithGlobals();
5129
+ const { client } = await resolveNksClient(opts);
5130
+ startSpinner("NKS \uD074\uB7EC\uC2A4\uD130 \uC791\uC5C5 \uC774\uB825 \uC870\uD68C \uC911...");
5131
+ let result;
5132
+ try {
5133
+ result = await client.getClusterEvent(cluster, event);
5134
+ } catch (err) {
5135
+ stopSpinner(false);
5136
+ throw err;
5137
+ }
5138
+ stopSpinner(true);
5139
+ output(opts, {
5140
+ headers: ["id", "name", "status"],
5141
+ rows: [resourceRow(result)],
5142
+ raw: result,
5143
+ ids: [resourceId(result)]
5144
+ });
5145
+ });
5146
+ var kubeconfigCommand = new import_commander40.Command("kubeconfig").description("NKS \uD074\uB7EC\uC2A4\uD130 kubeconfig \uB97C \uCD9C\uB825\uD558\uAC70\uB098 \uC800\uC7A5\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").option("--output <file>", "kubeconfig \uC800\uC7A5 \uACBD\uB85C").option("--force", "\uAE30\uC874 \uD30C\uC77C \uB36E\uC5B4\uC4F0\uAE30").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, _opts, cmd) => {
5147
+ const opts = cmd.optsWithGlobals();
5148
+ const { client } = await resolveNksClient(opts);
5149
+ startSpinner("NKS kubeconfig \uC870\uD68C \uC911...");
5150
+ let kubeconfig;
5151
+ try {
5152
+ kubeconfig = await client.getClusterKubeconfig(cluster);
5153
+ } catch (err) {
5154
+ stopSpinner(false);
5155
+ throw err;
5156
+ }
5157
+ stopSpinner(true);
5158
+ if (opts.output) {
5159
+ await writeKubeconfigFile(opts.output, kubeconfig, opts.force);
5160
+ process.stderr.write(import_chalk12.default.green(`\u2713 kubeconfig \uB97C \uC800\uC7A5\uD588\uC2B5\uB2C8\uB2E4: ${opts.output}
5161
+ `));
5162
+ return;
5163
+ }
5164
+ process.stdout.write(kubeconfig.endsWith("\n") ? kubeconfig : kubeconfig + "\n");
5165
+ });
5166
+ var ipAclCommand = new import_commander40.Command("ipacl").description("NKS \uD074\uB7EC\uC2A4\uD130 API endpoint IP ACL \uC744 \uC870\uD68C\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, _opts, cmd) => {
5167
+ const opts = cmd.optsWithGlobals();
5168
+ const { client } = await resolveNksClient(opts);
5169
+ startSpinner("NKS IP ACL \uC870\uD68C \uC911...");
5170
+ let result;
5171
+ try {
5172
+ result = await client.getClusterIpAcl(cluster);
5173
+ } catch (err) {
5174
+ stopSpinner(false);
5175
+ throw err;
5176
+ }
5177
+ stopSpinner(true);
5178
+ output(opts, {
5179
+ headers: ["cluster_uuid", "enable", "action", "target_count"],
5180
+ rows: [clusterIpAclRow(result)],
5181
+ raw: result,
5182
+ ids: [result.cluster_uuid]
5183
+ });
5184
+ });
5185
+ var clusterAddonListCommand = new import_commander40.Command("list").description("NKS \uD074\uB7EC\uC2A4\uD130\uC5D0 \uC124\uCE58\uB41C \uC560\uB4DC\uC628 \uBAA9\uB85D\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, _opts, cmd) => {
5186
+ const opts = cmd.optsWithGlobals();
5187
+ const { client } = await resolveNksClient(opts);
5188
+ startSpinner("NKS \uD074\uB7EC\uC2A4\uD130 \uC560\uB4DC\uC628 \uBAA9\uB85D \uC870\uD68C \uC911...");
5189
+ let addons;
5190
+ try {
5191
+ addons = await client.listClusterAddons(cluster);
5192
+ } catch (err) {
5193
+ stopSpinner(false);
5194
+ throw err;
5195
+ }
5196
+ stopSpinner(true);
5197
+ output(opts, {
5198
+ headers: ["id", "name", "version", "status"],
5199
+ rows: addons.map(addonRow),
5200
+ raw: addons,
5201
+ ids: addons.map((addon) => addon.uuid ?? addon.id ?? addon.name)
5202
+ });
5203
+ });
5204
+ var clusterAddonGetCommand = new import_commander40.Command("get").description("NKS \uD074\uB7EC\uC2A4\uD130\uC5D0 \uC124\uCE58\uB41C \uC560\uB4DC\uC628\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").argument("<addon>", "\uC560\uB4DC\uC628 UUID \uB610\uB294 \uC774\uB984").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, addon, _opts, cmd) => {
5205
+ const opts = cmd.optsWithGlobals();
5206
+ const { client } = await resolveNksClient(opts);
5207
+ startSpinner("NKS \uD074\uB7EC\uC2A4\uD130 \uC560\uB4DC\uC628 \uC870\uD68C \uC911...");
5208
+ let result;
5209
+ try {
5210
+ result = await client.getClusterAddon(cluster, addon);
5211
+ } catch (err) {
5212
+ stopSpinner(false);
5213
+ throw err;
5214
+ }
5215
+ stopSpinner(true);
5216
+ output(opts, {
5217
+ headers: ["id", "name", "version", "status"],
5218
+ rows: [addonRow(result)],
5219
+ raw: result,
5220
+ ids: [result.uuid ?? result.id ?? result.name]
5221
+ });
5222
+ });
5223
+ function parseResolveConflicts(value) {
5224
+ if (value === "none" || value === "overwrite" || value === "preserve") {
5225
+ return value;
5226
+ }
5227
+ throw new NhnCloudCliError(
5228
+ `--resolve-conflicts \uB294 none, overwrite, preserve \uC911 \uD558\uB098\uC5EC\uC57C \uD569\uB2C8\uB2E4: ${JSON.stringify(value)}`,
5229
+ EXIT_PARAM_ERROR
5230
+ );
5231
+ }
5232
+ var clusterAddonInstallCommand = new import_commander40.Command("install").description("NKS \uD074\uB7EC\uC2A4\uD130 \uC560\uB4DC\uC628\uC744 \uC124\uCE58\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").requiredOption("--name <name>", "\uC560\uB4DC\uC628 \uC774\uB984").requiredOption("--version <version>", "\uC560\uB4DC\uC628 \uBC84\uC804").requiredOption("--resolve-conflicts <none|overwrite|preserve>", "\uCDA9\uB3CC \uD574\uACB0 \uC815\uCC45").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, _opts, cmd) => {
5233
+ const opts = cmd.optsWithGlobals();
5234
+ const resolveConflicts = parseResolveConflicts(opts.resolveConflicts);
5235
+ const { client } = await resolveNksClient(opts);
5236
+ startSpinner("NKS \uD074\uB7EC\uC2A4\uD130 \uC560\uB4DC\uC628 \uC124\uCE58 \uC694\uCCAD \uC911...");
5237
+ let result;
5238
+ try {
5239
+ result = await client.installClusterAddon(cluster, {
5240
+ name: opts.name,
5241
+ version: opts.version,
5242
+ resolveConflicts
5243
+ });
5244
+ } catch (err) {
5245
+ stopSpinner(false);
5246
+ throw err;
5247
+ }
5248
+ stopSpinner(true);
5249
+ uuidOutput(opts, result, "\uD074\uB7EC\uC2A4\uD130 \uC560\uB4DC\uC628 \uC124\uCE58");
5250
+ });
5251
+ var clusterAddonUpdateCommand = new import_commander40.Command("update").description("NKS \uD074\uB7EC\uC2A4\uD130 \uC560\uB4DC\uC628\uC744 \uC5C5\uB370\uC774\uD2B8\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").argument("<addon>", "\uC560\uB4DC\uC628 UUID \uB610\uB294 \uC774\uB984").requiredOption("--version <version>", "\uC560\uB4DC\uC628 \uBC84\uC804").requiredOption("--resolve-conflicts <none|overwrite|preserve>", "\uCDA9\uB3CC \uD574\uACB0 \uC815\uCC45").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, addon, _opts, cmd) => {
5252
+ const opts = cmd.optsWithGlobals();
5253
+ const resolveConflicts = parseResolveConflicts(opts.resolveConflicts);
5254
+ const { client } = await resolveNksClient(opts);
5255
+ startSpinner("NKS \uD074\uB7EC\uC2A4\uD130 \uC560\uB4DC\uC628 \uC5C5\uB370\uC774\uD2B8 \uC694\uCCAD \uC911...");
5256
+ let result;
5257
+ try {
5258
+ result = await client.updateClusterAddon(cluster, addon, {
5259
+ version: opts.version,
5260
+ resolveConflicts
5261
+ });
5262
+ } catch (err) {
5263
+ stopSpinner(false);
5264
+ throw err;
5265
+ }
5266
+ stopSpinner(true);
5267
+ uuidOutput(opts, result, "\uD074\uB7EC\uC2A4\uD130 \uC560\uB4DC\uC628 \uC5C5\uB370\uC774\uD2B8");
5268
+ });
5269
+ var clusterAddonRemoveCommand = new import_commander40.Command("remove").description("NKS \uD074\uB7EC\uC2A4\uD130 \uC560\uB4DC\uC628\uC744 \uC81C\uAC70\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").argument("<addon>", "\uC560\uB4DC\uC628 UUID \uB610\uB294 \uC774\uB984").option("--yes", "\uD655\uC778 \uD504\uB86C\uD504\uD2B8 \uC0DD\uB7B5 (CI/\uBE44\uB300\uD654\uD615 \uD544\uC218)").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, addon, _opts, cmd) => {
5270
+ const opts = cmd.optsWithGlobals();
5271
+ const ok = await confirmDangerousAction(`NKS \uD074\uB7EC\uC2A4\uD130 \uC560\uB4DC\uC628 "${addon}" \uC744 \uC81C\uAC70\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?`, opts.yes);
5272
+ if (!ok) return;
5273
+ const { client } = await resolveNksClient(opts);
5274
+ startSpinner("NKS \uD074\uB7EC\uC2A4\uD130 \uC560\uB4DC\uC628 \uC81C\uAC70 \uC694\uCCAD \uC911...");
5275
+ let result;
5276
+ try {
5277
+ result = await client.removeClusterAddon(cluster, addon);
5278
+ } catch (err) {
5279
+ stopSpinner(false);
5280
+ throw err;
5281
+ }
5282
+ stopSpinner(true);
5283
+ uuidOutput(opts, result, "\uD074\uB7EC\uC2A4\uD130 \uC560\uB4DC\uC628 \uC81C\uAC70");
5284
+ });
5285
+ var clusterAddonCommand = new import_commander40.Command("addon").description("NKS \uD074\uB7EC\uC2A4\uD130 \uC560\uB4DC\uC628 \uAD00\uB828 \uBA85\uB839").addCommand(clusterAddonListCommand).addCommand(clusterAddonGetCommand).addCommand(clusterAddonInstallCommand).addCommand(clusterAddonUpdateCommand).addCommand(clusterAddonRemoveCommand);
5286
+ var clusterCommand = new import_commander40.Command("cluster").description("NKS \uD074\uB7EC\uC2A4\uD130 \uAD00\uB828 \uBA85\uB839").addCommand(listCommand6).addCommand(getCommand4).addCommand(createCommand4).addCommand(deleteCommand3).addCommand(resizeCommand2).addCommand(eventsCommand).addCommand(eventCommand).addCommand(kubeconfigCommand).addCommand(ipAclCommand).addCommand(setIpAclCommand).addCommand(renewCertificateCommand).addCommand(updateSgwCommand).addCommand(setControlPlaneLogCommand).addCommand(clusterAddonCommand);
5287
+
5288
+ // src/commands/nks/nodegroup.ts
5289
+ var import_commander41 = require("commander");
5290
+ var import_chalk13 = __toESM(require("chalk"));
5291
+ function nodeGroupRow(nodegroup) {
5292
+ return [
5293
+ nodegroup.uuid,
5294
+ nodegroup.name,
5295
+ nodegroup.status,
5296
+ String(nodegroup["node_count"] ?? ""),
5297
+ String(nodegroup["flavor_id"] ?? "")
5298
+ ];
5299
+ }
5300
+ function rawObjectRows(resource) {
5301
+ return Object.entries(resource).map(([key, value]) => [
5302
+ key,
5303
+ typeof value === "object" && value !== null ? JSON.stringify(value) : String(value)
5304
+ ]);
5305
+ }
5306
+ function uuidOutput2(opts, result, label) {
5307
+ process.stderr.write(import_chalk13.default.green(`\u2713 ${label} \uC694\uCCAD \uC644\uB8CC (uuid: ${result.uuid})
5308
+ `));
5309
+ output(opts, {
5310
+ headers: ["field", "value"],
5311
+ rows: [["uuid", result.uuid]],
5312
+ raw: result,
5313
+ ids: [result.uuid]
5314
+ });
5315
+ }
5316
+ function parseCsv(value, optionName) {
5317
+ const values = value.split(",").map((item) => item.trim()).filter(Boolean);
5318
+ if (values.length === 0) {
5319
+ throw new NhnCloudCliError(`${optionName} \uB294 \uBE44\uC5B4 \uC788\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`, EXIT_PARAM_ERROR);
5320
+ }
5321
+ return values;
5322
+ }
5323
+ function optionalPositiveInteger(value, optionName) {
5324
+ return value === void 0 ? void 0 : parsePositiveInteger(value, optionName);
5325
+ }
5326
+ function optionalNonNegativeInteger(value, optionName) {
5327
+ return value === void 0 ? void 0 : parseNonNegativeInteger(value, optionName);
5328
+ }
5329
+ async function confirmDangerousAction2(message, yes) {
5330
+ const isTTY = process.stdin.isTTY;
5331
+ if (!isTTY && !yes) {
5332
+ throw new NhnCloudCliError(
5333
+ "\uBE44\uB300\uD654\uD615 \uD658\uACBD\uC5D0\uC11C \uC704\uD5D8 \uC791\uC5C5\uC740 --yes \uD50C\uB798\uADF8\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
5334
+ EXIT_PARAM_ERROR
5335
+ );
5336
+ }
5337
+ if (!isTTY || yes) return true;
5338
+ const { confirm } = await import("@inquirer/prompts");
5339
+ const ok = await confirm({ message, default: false });
5340
+ if (!ok) process.stderr.write(import_chalk13.default.yellow("\uC791\uC5C5\uC774 \uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\n"));
5341
+ return ok;
5342
+ }
5343
+ var listCommand7 = new import_commander41.Command("list").description("NKS \uB178\uB4DC \uADF8\uB8F9 \uBAA9\uB85D\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, _opts, cmd) => {
5344
+ const opts = cmd.optsWithGlobals();
5345
+ const { client } = await resolveNksClient(opts);
5346
+ startSpinner("NKS \uB178\uB4DC \uADF8\uB8F9 \uBAA9\uB85D \uC870\uD68C \uC911...");
5347
+ let nodegroups;
5348
+ try {
5349
+ nodegroups = await client.listNodeGroups(cluster);
5350
+ } catch (err) {
5351
+ stopSpinner(false);
5352
+ throw err;
5353
+ }
5354
+ stopSpinner(true);
5355
+ output(opts, {
5356
+ headers: ["uuid", "name", "status", "node_count", "flavor_id"],
5357
+ rows: nodegroups.map(nodeGroupRow),
5358
+ raw: nodegroups,
5359
+ ids: nodegroups.map((nodegroup) => nodegroup.uuid)
5360
+ });
5361
+ });
5362
+ var getCommand5 = new import_commander41.Command("get").description("NKS \uB178\uB4DC \uADF8\uB8F9\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").argument("<nodegroup>", "\uB178\uB4DC \uADF8\uB8F9 UUID \uB610\uB294 \uC774\uB984").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, nodegroup, _opts, cmd) => {
5363
+ const opts = cmd.optsWithGlobals();
5364
+ const { client } = await resolveNksClient(opts);
5365
+ startSpinner("NKS \uB178\uB4DC \uADF8\uB8F9 \uC870\uD68C \uC911...");
5366
+ let result;
5367
+ try {
5368
+ result = await client.getNodeGroup(cluster, nodegroup);
5369
+ } catch (err) {
5370
+ stopSpinner(false);
5371
+ throw err;
5372
+ }
5373
+ stopSpinner(true);
5374
+ output(opts, {
5375
+ headers: ["uuid", "name", "status", "node_count", "flavor_id"],
5376
+ rows: [nodeGroupRow(result)],
5377
+ raw: result,
5378
+ ids: [result.uuid]
5379
+ });
5380
+ });
5381
+ var createCommand5 = new import_commander41.Command("create").description("NKS \uB178\uB4DC \uADF8\uB8F9\uC744 \uC0DD\uC131\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").requiredOption("--file <json>", "\uACF5\uC2DD API payload JSON \uD30C\uC77C").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, _opts, cmd) => {
5382
+ const opts = cmd.optsWithGlobals();
5383
+ const payload = await readJsonFile(opts.file);
5384
+ const { client } = await resolveNksClient(opts);
5385
+ startSpinner("NKS \uB178\uB4DC \uADF8\uB8F9 \uC0DD\uC131 \uC694\uCCAD \uC911...");
5386
+ let result;
5387
+ try {
5388
+ result = await client.createNodeGroup(cluster, payload);
5389
+ } catch (err) {
5390
+ stopSpinner(false);
5391
+ throw err;
5392
+ }
5393
+ stopSpinner(true);
5394
+ uuidOutput2(opts, result, "\uB178\uB4DC \uADF8\uB8F9 \uC0DD\uC131");
5395
+ });
5396
+ var deleteCommand4 = new import_commander41.Command("delete").description("NKS \uB178\uB4DC \uADF8\uB8F9\uC744 \uC0AD\uC81C\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").argument("<nodegroup>", "\uB178\uB4DC \uADF8\uB8F9 UUID \uB610\uB294 \uC774\uB984").option("--yes", "\uD655\uC778 \uD504\uB86C\uD504\uD2B8 \uC0DD\uB7B5 (CI/\uBE44\uB300\uD654\uD615 \uD544\uC218)").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, nodegroup, _opts, cmd) => {
5397
+ const opts = cmd.optsWithGlobals();
5398
+ const ok = await confirmDangerousAction2(`NKS \uB178\uB4DC \uADF8\uB8F9 "${nodegroup}" \uB97C \uC0AD\uC81C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?`, opts.yes);
5399
+ if (!ok) return;
5400
+ const { client } = await resolveNksClient(opts);
5401
+ startSpinner("NKS \uB178\uB4DC \uADF8\uB8F9 \uC0AD\uC81C \uC694\uCCAD \uC911...");
5402
+ try {
5403
+ await client.deleteNodeGroup(cluster, nodegroup);
5404
+ } catch (err) {
5405
+ stopSpinner(false);
5406
+ throw err;
5407
+ }
5408
+ stopSpinner(true);
5409
+ process.stderr.write(import_chalk13.default.green(`\u2713 NKS \uB178\uB4DC \uADF8\uB8F9 "${nodegroup}" \uC0AD\uC81C \uC694\uCCAD \uC644\uB8CC
5410
+ `));
5411
+ });
5412
+ function nodeActionCommand(name) {
5413
+ return new import_commander41.Command(name).description(`NKS \uB178\uB4DC \uADF8\uB8F9 \uB178\uB4DC\uB97C ${name === "stop-node" ? "\uC911\uC9C0" : "\uC2DC\uC791"}\uD55C\uB2E4`).argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").argument("<nodegroup>", "\uB178\uB4DC \uADF8\uB8F9 UUID \uB610\uB294 \uC774\uB984").requiredOption("--nodes <csv>", "\uB300\uC0C1 \uB178\uB4DC CSV").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, nodegroup, _opts, cmd) => {
5414
+ const opts = cmd.optsWithGlobals();
5415
+ const nodes = parseCsv(opts.nodes, "--nodes");
5416
+ const { client } = await resolveNksClient(opts);
5417
+ startSpinner(`NKS \uB178\uB4DC ${name === "stop-node" ? "\uC911\uC9C0" : "\uC2DC\uC791"} \uC694\uCCAD \uC911...`);
5418
+ let result;
5419
+ try {
5420
+ result = name === "stop-node" ? await client.stopNodeGroupNodes(cluster, nodegroup, nodes) : await client.startNodeGroupNodes(cluster, nodegroup, nodes);
5421
+ } catch (err) {
5422
+ stopSpinner(false);
5423
+ throw err;
5424
+ }
5425
+ stopSpinner(true);
5426
+ uuidOutput2(opts, result, `\uB178\uB4DC ${name === "stop-node" ? "\uC911\uC9C0" : "\uC2DC\uC791"}`);
5427
+ });
5428
+ }
5429
+ var autoscaleCommand = new import_commander41.Command("autoscale").description("NKS \uB178\uB4DC \uADF8\uB8F9 autoscale \uC124\uC815\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").argument("<nodegroup>", "\uB178\uB4DC \uADF8\uB8F9 UUID \uB610\uB294 \uC774\uB984").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, nodegroup, _opts, cmd) => {
5430
+ const opts = cmd.optsWithGlobals();
5431
+ const { client } = await resolveNksClient(opts);
5432
+ startSpinner("NKS \uB178\uB4DC \uADF8\uB8F9 autoscale \uC870\uD68C \uC911...");
5433
+ let result;
5434
+ try {
5435
+ result = await client.getNodeGroupAutoscale(cluster, nodegroup);
5436
+ } catch (err) {
5437
+ stopSpinner(false);
5438
+ throw err;
5439
+ }
5440
+ stopSpinner(true);
5441
+ output(opts, {
5442
+ headers: ["field", "value"],
5443
+ rows: rawObjectRows(result),
5444
+ raw: result,
5445
+ ids: []
5446
+ });
5447
+ });
5448
+ var setAutoscaleCommand = new import_commander41.Command("set-autoscale").description("NKS \uB178\uB4DC \uADF8\uB8F9 autoscale \uC124\uC815\uC744 \uBCC0\uACBD\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").argument("<nodegroup>", "\uB178\uB4DC \uADF8\uB8F9 UUID \uB610\uB294 \uC774\uB984").requiredOption("--file <json>", "\uACF5\uC2DD API payload JSON \uD30C\uC77C").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, nodegroup, _opts, cmd) => {
5449
+ const opts = cmd.optsWithGlobals();
5450
+ const payload = await readJsonFile(opts.file);
5451
+ const { client } = await resolveNksClient(opts);
5452
+ startSpinner("NKS \uB178\uB4DC \uADF8\uB8F9 autoscale \uBCC0\uACBD \uC694\uCCAD \uC911...");
5453
+ let result;
5454
+ try {
5455
+ result = await client.setNodeGroupAutoscale(cluster, nodegroup, payload);
5456
+ } catch (err) {
5457
+ stopSpinner(false);
5458
+ throw err;
5459
+ }
5460
+ stopSpinner(true);
5461
+ uuidOutput2(opts, result, "autoscale \uBCC0\uACBD");
5462
+ });
5463
+ var setMetricAutoscaleCommand = new import_commander41.Command("set-metric-autoscale").description("NKS \uB178\uB4DC \uADF8\uB8F9 metric autoscale \uC124\uC815\uC744 \uBCC0\uACBD\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").argument("<nodegroup>", "\uB178\uB4DC \uADF8\uB8F9 UUID \uB610\uB294 \uC774\uB984").requiredOption("--file <json>", "\uACF5\uC2DD API payload JSON \uD30C\uC77C").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, nodegroup, _opts, cmd) => {
5464
+ const opts = cmd.optsWithGlobals();
5465
+ const payload = await readJsonFile(opts.file);
5466
+ const { client } = await resolveNksClient(opts);
5467
+ startSpinner("NKS metric autoscale \uBCC0\uACBD \uC694\uCCAD \uC911...");
5468
+ let result;
5469
+ try {
5470
+ result = await client.setNodeGroupMetricAutoscale(cluster, nodegroup, payload);
5471
+ } catch (err) {
5472
+ stopSpinner(false);
5473
+ throw err;
5474
+ }
5475
+ stopSpinner(true);
5476
+ uuidOutput2(opts, result, "metric autoscale \uBCC0\uACBD");
5477
+ });
5478
+ var upgradeCommand = new import_commander41.Command("upgrade").description("NKS \uB178\uB4DC \uADF8\uB8F9 Kubernetes version \uC744 \uC5C5\uADF8\uB808\uC774\uB4DC\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").argument("<nodegroup>", "\uB178\uB4DC \uADF8\uB8F9 UUID \uB610\uB294 \uC774\uB984").requiredOption("--version <v>", "\uB300\uC0C1 Kubernetes version").option("--num-buffer-nodes <n>", "buffer node \uC218").option("--num-max-unavailable-nodes <n>", "\uCD5C\uB300 unavailable node \uC218").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, nodegroup, _opts, cmd) => {
5479
+ const opts = cmd.optsWithGlobals();
5480
+ const { client } = await resolveNksClient(opts);
5481
+ startSpinner("NKS \uB178\uB4DC \uADF8\uB8F9 upgrade \uC694\uCCAD \uC911...");
5482
+ let result;
5483
+ try {
5484
+ result = await client.upgradeNodeGroup(cluster, nodegroup, {
5485
+ version: opts.version,
5486
+ numBufferNodes: optionalNonNegativeInteger(opts.numBufferNodes, "--num-buffer-nodes"),
5487
+ numMaxUnavailableNodes: optionalPositiveInteger(opts.numMaxUnavailableNodes, "--num-max-unavailable-nodes")
5488
+ });
5489
+ } catch (err) {
5490
+ stopSpinner(false);
5491
+ throw err;
5492
+ }
5493
+ stopSpinner(true);
5494
+ uuidOutput2(opts, result, "\uB178\uB4DC \uADF8\uB8F9 upgrade");
5495
+ });
5496
+ var setUserscriptCommand = new import_commander41.Command("set-userscript").description("NKS \uB178\uB4DC \uADF8\uB8F9 user script \uB97C \uBCC0\uACBD\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").argument("<nodegroup>", "\uB178\uB4DC \uADF8\uB8F9 UUID \uB610\uB294 \uC774\uB984").requiredOption("--file <script>", "script \uD30C\uC77C").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, nodegroup, _opts, cmd) => {
5497
+ const opts = cmd.optsWithGlobals();
5498
+ const contents = await readTextFile(opts.file);
5499
+ const { client } = await resolveNksClient(opts);
5500
+ startSpinner("NKS node user script \uBCC0\uACBD \uC694\uCCAD \uC911...");
5501
+ let result;
5502
+ try {
5503
+ result = await client.setNodeGroupUserscript(cluster, nodegroup, contents);
5504
+ } catch (err) {
5505
+ stopSpinner(false);
5506
+ throw err;
5507
+ }
5508
+ stopSpinner(true);
5509
+ uuidOutput2(opts, result, "user script \uBCC0\uACBD");
5510
+ });
5511
+ var updateFlavorCommand = new import_commander41.Command("update-flavor").description("NKS \uB178\uB4DC \uADF8\uB8F9 flavor \uB97C \uBCC0\uACBD\uD55C\uB2E4").argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").argument("<nodegroup>", "\uB178\uB4DC \uADF8\uB8F9 UUID \uB610\uB294 \uC774\uB984").requiredOption("--flavor <uuid>", "\uBCC0\uACBD\uD560 flavor UUID").option("--num-buffer-nodes <n>", "buffer node \uC218").option("--num-max-unavailable-nodes <n>", "\uCD5C\uB300 unavailable node \uC218").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, nodegroup, _opts, cmd) => {
5512
+ const opts = cmd.optsWithGlobals();
5513
+ const { client } = await resolveNksClient(opts);
5514
+ startSpinner("NKS \uB178\uB4DC \uADF8\uB8F9 flavor \uBCC0\uACBD \uC694\uCCAD \uC911...");
5515
+ let result;
5516
+ try {
5517
+ result = await client.updateNodeGroupFlavor(cluster, nodegroup, {
5518
+ flavorId: opts.flavor,
5519
+ numBufferNodes: optionalNonNegativeInteger(opts.numBufferNodes, "--num-buffer-nodes"),
5520
+ numMaxUnavailableNodes: optionalPositiveInteger(opts.numMaxUnavailableNodes, "--num-max-unavailable-nodes")
5521
+ });
5522
+ } catch (err) {
5523
+ stopSpinner(false);
5524
+ throw err;
5525
+ }
5526
+ stopSpinner(true);
5527
+ uuidOutput2(opts, result, "flavor \uBCC0\uACBD");
5528
+ });
5529
+ function patchPayloadCommand(name) {
5530
+ return new import_commander41.Command(name).description(`NKS \uB178\uB4DC \uADF8\uB8F9 ${name === "set-fip-auto-bind" ? "Floating IP \uC790\uB3D9 \uC5F0\uACB0" : "Kubernetes labels"} \uC124\uC815\uC744 \uBCC0\uACBD\uD55C\uB2E4`).argument("<cluster>", "\uD074\uB7EC\uC2A4\uD130 UUID \uB610\uB294 \uC774\uB984").argument("<nodegroup>", "\uB178\uB4DC \uADF8\uB8F9 UUID \uB610\uB294 \uC774\uB984").requiredOption("--file <json>", "\uACF5\uC2DD API payload JSON \uD30C\uC77C").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (cluster, nodegroup, _opts, cmd) => {
5531
+ const opts = cmd.optsWithGlobals();
5532
+ const payload = await readJsonFile(opts.file);
5533
+ const { client } = await resolveNksClient(opts);
5534
+ startSpinner(`NKS \uB178\uB4DC \uADF8\uB8F9 ${name} \uC694\uCCAD \uC911...`);
5535
+ let result;
5536
+ try {
5537
+ result = name === "set-fip-auto-bind" ? await client.setNodeGroupFipAutoBind(cluster, nodegroup, payload) : await client.setNodeGroupLabels(cluster, nodegroup, payload);
5538
+ } catch (err) {
5539
+ stopSpinner(false);
5540
+ throw err;
5541
+ }
5542
+ stopSpinner(true);
5543
+ uuidOutput2(opts, result, name);
5544
+ });
5545
+ }
5546
+ var nodegroupCommand = new import_commander41.Command("nodegroup").description("NKS \uB178\uB4DC \uADF8\uB8F9 \uAD00\uB828 \uBA85\uB839").addCommand(listCommand7).addCommand(getCommand5).addCommand(createCommand5).addCommand(deleteCommand4).addCommand(nodeActionCommand("stop-node")).addCommand(nodeActionCommand("start-node")).addCommand(autoscaleCommand).addCommand(setAutoscaleCommand).addCommand(setMetricAutoscaleCommand).addCommand(upgradeCommand).addCommand(setUserscriptCommand).addCommand(updateFlavorCommand).addCommand(patchPayloadCommand("set-fip-auto-bind")).addCommand(patchPayloadCommand("set-labels"));
5547
+
5548
+ // src/commands/nks/addon.ts
5549
+ var import_commander42 = require("commander");
5550
+ function addonTypeRow(addonType) {
5551
+ return [
5552
+ addonType.uuid ?? addonType.id ?? addonType.name,
5553
+ addonType.name,
5554
+ String(addonType["version"] ?? "")
5555
+ ];
5556
+ }
5557
+ function addonRow2(addon) {
5558
+ return [
5559
+ addon.uuid ?? addon.id ?? addon.name,
5560
+ addon.name,
5561
+ addon.version ?? "",
5562
+ addon.status ?? ""
5563
+ ];
5564
+ }
5565
+ var addonTypeListCommand = new import_commander42.Command("list").description("NKS \uC560\uB4DC\uC628 \uD0C0\uC785 \uBAA9\uB85D\uC744 \uC870\uD68C\uD55C\uB2E4").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (_opts, cmd) => {
5566
+ const opts = cmd.optsWithGlobals();
5567
+ const { client } = await resolveNksClient(opts);
5568
+ startSpinner("NKS \uC560\uB4DC\uC628 \uD0C0\uC785 \uBAA9\uB85D \uC870\uD68C \uC911...");
5569
+ let addonTypes;
5570
+ try {
5571
+ addonTypes = await client.listAddonTypes();
5572
+ } catch (err) {
5573
+ stopSpinner(false);
5574
+ throw err;
5575
+ }
5576
+ stopSpinner(true);
5577
+ output(opts, {
5578
+ headers: ["id", "name", "version"],
5579
+ rows: addonTypes.map(addonTypeRow),
5580
+ raw: addonTypes,
5581
+ ids: addonTypes.map((addonType) => addonType.uuid ?? addonType.id ?? addonType.name)
5582
+ });
5583
+ });
5584
+ var addonTypeGetCommand = new import_commander42.Command("get").description("NKS \uC560\uB4DC\uC628 \uD0C0\uC785\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<addon-type>", "\uC560\uB4DC\uC628 \uD0C0\uC785 UUID \uB610\uB294 \uC774\uB984").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (addonType, _opts, cmd) => {
5585
+ const opts = cmd.optsWithGlobals();
5586
+ const { client } = await resolveNksClient(opts);
5587
+ startSpinner("NKS \uC560\uB4DC\uC628 \uD0C0\uC785 \uC870\uD68C \uC911...");
5588
+ let result;
5589
+ try {
5590
+ result = await client.getAddonType(addonType);
5591
+ } catch (err) {
5592
+ stopSpinner(false);
5593
+ throw err;
5594
+ }
5595
+ stopSpinner(true);
5596
+ output(opts, {
5597
+ headers: ["id", "name", "version"],
5598
+ rows: [addonTypeRow(result)],
5599
+ raw: result,
5600
+ ids: [result.uuid ?? result.id ?? result.name]
5601
+ });
5602
+ });
5603
+ var addonTypeCommand = new import_commander42.Command("addon-type").description("NKS \uC560\uB4DC\uC628 \uD0C0\uC785 \uAD00\uB828 \uBA85\uB839").addCommand(addonTypeListCommand).addCommand(addonTypeGetCommand);
5604
+ var addonListCommand = new import_commander42.Command("list").description("NKS \uC560\uB4DC\uC628 \uBAA9\uB85D\uC744 \uC870\uD68C\uD55C\uB2E4").option("--k8s-version <version>", "Kubernetes version filter").option("--image <image>", "image filter").option("--platform-version <version>", "platform version filter").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (_opts, cmd) => {
5605
+ const opts = cmd.optsWithGlobals();
5606
+ const { client } = await resolveNksClient(opts);
5607
+ startSpinner("NKS \uC560\uB4DC\uC628 \uBAA9\uB85D \uC870\uD68C \uC911...");
5608
+ let addons;
5609
+ try {
5610
+ addons = await client.listAddons({
5611
+ k8sVersion: opts.k8sVersion,
5612
+ image: opts.image,
5613
+ platformVersion: opts.platformVersion
5614
+ });
5615
+ } catch (err) {
5616
+ stopSpinner(false);
5617
+ throw err;
5618
+ }
5619
+ stopSpinner(true);
5620
+ output(opts, {
5621
+ headers: ["id", "name", "version", "status"],
5622
+ rows: addons.map(addonRow2),
5623
+ raw: addons,
5624
+ ids: addons.map((addon) => addon.uuid ?? addon.id ?? addon.name)
5625
+ });
5626
+ });
5627
+ var addonGetCommand = new import_commander42.Command("get").description("NKS \uC560\uB4DC\uC628\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<addon>", "\uC560\uB4DC\uC628 UUID \uB610\uB294 \uC774\uB984").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (addon, _opts, cmd) => {
5628
+ const opts = cmd.optsWithGlobals();
5629
+ const { client } = await resolveNksClient(opts);
5630
+ startSpinner("NKS \uC560\uB4DC\uC628 \uC870\uD68C \uC911...");
5631
+ let result;
5632
+ try {
5633
+ result = await client.getAddon(addon);
5634
+ } catch (err) {
5635
+ stopSpinner(false);
5636
+ throw err;
5637
+ }
5638
+ stopSpinner(true);
5639
+ output(opts, {
5640
+ headers: ["id", "name", "version", "status"],
5641
+ rows: [addonRow2(result)],
5642
+ raw: result,
5643
+ ids: [result.uuid ?? result.id ?? result.name]
5644
+ });
5645
+ });
5646
+ var addonCommand = new import_commander42.Command("addon").description("NKS \uC560\uB4DC\uC628 \uAD00\uB828 \uBA85\uB839").addCommand(addonListCommand).addCommand(addonGetCommand);
5647
+
5648
+ // src/index.ts
5649
+ var rootAgentHints = `
5650
+ Agent hints:
5651
+ - Prefer --json for structured output.
5652
+ - Use --quiet only when the command documents an identifier output.
5653
+ - Use --profile <name> to avoid relying on default profile.
5654
+ - For IaaS/NKS commands, use --region <region> when region matters.
5655
+ - Run "nhncloud commands --json" to inspect command paths and options.
5656
+ `;
5657
+ var logncrashAgentWorkflow = `
5658
+ Agent workflow:
5659
+ 1. nhncloud logncrash search --query '*' --from 1h --to now --json
5660
+ 2. nhncloud logncrash export --query '<lucene>' --from 1h --to now --output logs.jsonl
5661
+ `;
5662
+ var deployAgentWorkflow = `
5663
+ Agent workflow:
5664
+ 1. nhncloud deploy artifacts <target> --json
5665
+ 2. nhncloud deploy server-groups <target> --json
5666
+ 3. nhncloud deploy run <target>
5667
+ `;
5668
+ var instanceAgentWorkflow = `
5669
+ Agent workflow:
5670
+ 1. nhncloud instance images --json
5671
+ 2. nhncloud instance flavors --detail --json
5672
+ 3. nhncloud instance list --json
5673
+ `;
5674
+ var networkAgentWorkflow = `
5675
+ Agent workflow:
5676
+ 1. nhncloud network list --json
5677
+ 2. nhncloud network subnet list --json
5678
+ `;
5679
+ var volumeAgentWorkflow = `
5680
+ Agent workflow:
5681
+ 1. nhncloud volume list --json
5682
+ 2. nhncloud volume get <volume-id> --json
5683
+ `;
5684
+ var floatingIpAgentWorkflow = `
5685
+ Agent workflow:
5686
+ 1. nhncloud floatingip list --json
5687
+ 2. nhncloud floatingip create --json
5688
+ `;
5689
+ var ncrAgentWorkflow = `
5690
+ Agent workflow:
5691
+ 1. nhncloud ncr list --json
5692
+ 2. nhncloud ncr images <registry> --json
5693
+ 3. nhncloud ncr tags <registry> <repository> --json
5694
+ `;
5695
+ var nksAgentWorkflow = `
5696
+ Agent workflow:
5697
+ 1. nhncloud nks supports --json
5698
+ 2. nhncloud nks cluster list --json
5699
+ 3. nhncloud nks cluster get <cluster> --json
5700
+ `;
5701
+ var program = new import_commander43.Command();
5702
+ program.name("nhncloud").description("NHN Cloud CLI \u2014 AI agent & terminal friendly").version("0.7.0").option("--json", "JSON \uD615\uC2DD\uC73C\uB85C \uCD9C\uB825").option("--quiet", "\uCD5C\uC18C \uCD9C\uB825 (\uC790\uB3D9\uD654\uC6A9)").option("--no-color", "\uC0C9\uC0C1 \uBE44\uD65C\uC131\uD654").addHelpText("after", rootAgentHints);
5703
+ program.hook("preAction", () => {
5704
+ const opts = program.opts();
5705
+ if (!opts.color || process.env["NO_COLOR"]) {
5706
+ import_chalk14.default.level = 0;
5707
+ }
5708
+ if (opts.json || opts.quiet) {
5709
+ setQuiet(true);
5710
+ }
5711
+ });
5712
+ program.addCommand(configureCommand);
5713
+ var logncrashCommand = new import_commander43.Command("logncrash").description("Log & Crash \uAD00\uB828 \uBA85\uB839").addHelpText("after", logncrashAgentWorkflow);
5714
+ logncrashCommand.addCommand(searchCommand);
5715
+ logncrashCommand.addCommand(sendCommand);
5716
+ logncrashCommand.addCommand(exportCommand);
5717
+ program.addCommand(logncrashCommand);
5718
+ var deployCommand = new import_commander43.Command("deploy").description("NHN Cloud Deploy \uAD00\uB828 \uBA85\uB839").addHelpText("after", deployAgentWorkflow);
5719
+ deployCommand.addCommand(runCommand);
5720
+ deployCommand.addCommand(artifactsCommand);
5721
+ deployCommand.addCommand(serverGroupsCommand);
5722
+ deployCommand.addCommand(historiesCommand);
5723
+ deployCommand.addCommand(binaryGroupsCommand);
5724
+ deployCommand.addCommand(binariesCommand);
5725
+ deployCommand.addCommand(uploadCommand);
5726
+ deployCommand.addCommand(downloadCommand);
5727
+ program.addCommand(deployCommand);
5728
+ var instanceCommand = new import_commander43.Command("instance").description("Compute \uC778\uC2A4\uD134\uC2A4 \uAD00\uB828 \uBA85\uB839").addHelpText("after", instanceAgentWorkflow);
5729
+ instanceCommand.addCommand(listCommand);
5730
+ instanceCommand.addCommand(flavorsCommand);
5731
+ instanceCommand.addCommand(availabilityZonesCommand);
5732
+ instanceCommand.addCommand(getCommand2);
5733
+ instanceCommand.addCommand(createCommand3);
5734
+ instanceCommand.addCommand(deleteCommand2);
5735
+ instanceCommand.addCommand(startCommand);
5736
+ instanceCommand.addCommand(stopCommand);
5737
+ instanceCommand.addCommand(rebootCommand);
5738
+ instanceCommand.addCommand(resizeCommand);
5739
+ instanceCommand.addCommand(resizeConfirmCommand);
5740
+ instanceCommand.addCommand(resizeRevertCommand);
5741
+ instanceCommand.addCommand(imagesCommand);
5742
+ instanceCommand.addCommand(keypairsCommand);
5743
+ instanceCommand.addCommand(keypairCommand);
5744
+ instanceCommand.addCommand(volumeCommand);
5745
+ instanceCommand.addCommand(volumesCommand);
5746
+ program.addCommand(instanceCommand);
5747
+ var networkCommand = new import_commander43.Command("network").description("VPC\xB7\uC11C\uBE0C\uB137 \uC870\uD68C").addHelpText("after", networkAgentWorkflow);
5748
+ networkCommand.addCommand(listCommand3);
5749
+ networkCommand.addCommand(subnetCommand);
5750
+ program.addCommand(networkCommand);
5751
+ var volumeCommand2 = new import_commander43.Command("volume").description("Block Storage \uBCFC\uB968 \uAD00\uB828 \uBA85\uB839").addHelpText("after", volumeAgentWorkflow);
5752
+ volumeCommand2.addCommand(listCommand2);
5753
+ volumeCommand2.addCommand(getCommand);
5754
+ volumeCommand2.addCommand(createCommand);
5755
+ program.addCommand(volumeCommand2);
5756
+ var floatingipCommand = new import_commander43.Command("floatingip").description(
5757
+ "Floating IP(\uC778\uC2A4\uD134\uC2A4 \uACF5\uC778 IP) \uAD00\uB9AC"
5758
+ ).addHelpText("after", floatingIpAgentWorkflow);
4268
5759
  floatingipCommand.addCommand(listCommand4);
4269
5760
  floatingipCommand.addCommand(createCommand2);
4270
5761
  floatingipCommand.addCommand(deleteCommand);
4271
5762
  program.addCommand(floatingipCommand);
4272
- var ncrCommand = new import_commander38.Command("ncr").description("NHN Container Registry \uAD00\uB828 \uBA85\uB839");
5763
+ var ncrCommand = new import_commander43.Command("ncr").description("NHN Container Registry \uAD00\uB828 \uBA85\uB839").addHelpText("after", ncrAgentWorkflow);
4273
5764
  ncrCommand.addCommand(listCommand5);
4274
5765
  ncrCommand.addCommand(getCommand3);
4275
5766
  ncrCommand.addCommand(imagesCommand2);
4276
5767
  ncrCommand.addCommand(tagsCommand);
4277
5768
  program.addCommand(ncrCommand);
5769
+ var nksCommand = new import_commander43.Command("nks").description("NHN Kubernetes Service \uAD00\uB828 \uBA85\uB839").addHelpText("after", nksAgentWorkflow);
5770
+ nksCommand.addCommand(supportsCommand);
5771
+ nksCommand.addCommand(clusterCommand);
5772
+ nksCommand.addCommand(nodegroupCommand);
5773
+ nksCommand.addCommand(addonTypeCommand);
5774
+ nksCommand.addCommand(addonCommand);
5775
+ program.addCommand(nksCommand);
5776
+ program.addCommand(createCommandsCommand(program));
4278
5777
  program.parseAsync().catch((err) => {
4279
5778
  const message = err instanceof Error ? err.message : String(err);
4280
5779
  const exitCode = err instanceof NhnCloudCliError ? err.exitCode : 1;
4281
- process.stderr.write(import_chalk12.default.red(`\uC624\uB958: ${message}`) + "\n");
5780
+ process.stderr.write(import_chalk14.default.red(`\uC624\uB958: ${message}`) + "\n");
4282
5781
  process.exit(exitCode);
4283
5782
  });