@bifos/nhncloud-cli 0.10.1 → 0.11.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,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/index.ts
27
- var import_commander48 = require("commander");
27
+ var import_commander53 = require("commander");
28
28
  var import_chalk18 = __toESM(require("chalk"));
29
29
 
30
30
  // src/utils/spinner.ts
@@ -6794,6 +6794,102 @@ var import_chalk16 = __toESM(require("chalk"));
6794
6794
  // src/commands/ncs/helpers.ts
6795
6795
  var import_node_fs7 = require("fs");
6796
6796
  var MAX_JSON_PAYLOAD_BYTES = 1e6;
6797
+ var NCS_RFC3339_PATTERN = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?(Z|([+-])(\d{2}):(\d{2}))$/;
6798
+ var NCS_RELATIVE_TIME_PATTERN = /^(\d+)(m|h|d)$/;
6799
+ var NCS_TIME_EXAMPLES = "\uC2DC\uAC04\uB300 \uD3EC\uD568 RFC3339(\uC608: 2026-05-01T00:00:00+09:00) \uB610\uB294 \uC0C1\uB300\uC2DC\uAC04(\uC608: 30m, 1h, 2d, now)";
6800
+ function ncsTimeError(option, value, detail) {
6801
+ const suffix = detail ? ` ${detail}` : "";
6802
+ return new NhnCloudCliError(
6803
+ `${option} \uC2DC\uAC04 \uD615\uC2DD \uC624\uB958: ${JSON.stringify(value)}. ${NCS_TIME_EXAMPLES}\uC744 \uC0AC\uC6A9\uD558\uC138\uC694.${suffix}`,
6804
+ EXIT_PARAM_ERROR
6805
+ );
6806
+ }
6807
+ function isLeapYear(year) {
6808
+ return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
6809
+ }
6810
+ function daysInMonth(year, month) {
6811
+ if (month === 2) return isLeapYear(year) ? 29 : 28;
6812
+ return [4, 6, 9, 11].includes(month) ? 30 : 31;
6813
+ }
6814
+ function formatNcsUtcTime(timestamp, option, input) {
6815
+ const date = new Date(timestamp);
6816
+ if (!Number.isFinite(timestamp) || Number.isNaN(date.getTime())) {
6817
+ throw ncsTimeError(option, input, "\uC720\uD6A8\uD55C Date \uBC94\uC704\uB97C \uBC97\uC5B4\uB0AC\uC2B5\uB2C8\uB2E4.");
6818
+ }
6819
+ const iso = date.toISOString();
6820
+ const secondPrecision = iso.replace(/\.\d{3}Z$/, "Z");
6821
+ if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/.test(secondPrecision)) {
6822
+ throw ncsTimeError(option, input, "UTC \uC5F0\uB3C4\uAC00 \uC9C0\uC6D0 \uBC94\uC704\uB97C \uBC97\uC5B4\uB0AC\uC2B5\uB2C8\uB2E4.");
6823
+ }
6824
+ return secondPrecision;
6825
+ }
6826
+ function parseNcsAbsoluteTime(input, option) {
6827
+ const match = NCS_RFC3339_PATTERN.exec(input);
6828
+ if (!match) throw ncsTimeError(option, input);
6829
+ const year = Number(match[1]);
6830
+ const month = Number(match[2]);
6831
+ const day = Number(match[3]);
6832
+ const hour = Number(match[4]);
6833
+ const minute = Number(match[5]);
6834
+ const second = Number(match[6]);
6835
+ const offsetHour = match[10] === void 0 ? 0 : Number(match[10]);
6836
+ const offsetMinute = match[11] === void 0 ? 0 : Number(match[11]);
6837
+ if (month < 1 || month > 12 || day < 1 || day > daysInMonth(year, month) || hour > 23 || minute > 59 || second > 59 || offsetHour > 23 || offsetMinute > 59) {
6838
+ throw ncsTimeError(option, input, "\uB0A0\uC9DC\xB7\uC2DC\uAC01\xB7\uC2DC\uAC04\uB300 \uC624\uD504\uC14B\uC744 \uD655\uC778\uD558\uC138\uC694.");
6839
+ }
6840
+ const parsedTimestamp = Date.parse(input);
6841
+ const timestamp = Math.floor(parsedTimestamp / 1e3) * 1e3;
6842
+ return {
6843
+ value: formatNcsUtcTime(timestamp, option, input),
6844
+ timestamp
6845
+ };
6846
+ }
6847
+ function parseNcsTime(input, option, baseTimestamp) {
6848
+ const trimmed = input.trim();
6849
+ if (trimmed === "now") {
6850
+ return {
6851
+ value: formatNcsUtcTime(baseTimestamp, option, input),
6852
+ timestamp: Math.floor(baseTimestamp / 1e3) * 1e3
6853
+ };
6854
+ }
6855
+ const relativeMatch = NCS_RELATIVE_TIME_PATTERN.exec(trimmed);
6856
+ if (relativeMatch) {
6857
+ const amount = Number(relativeMatch[1]);
6858
+ const unitMs = relativeMatch[2] === "m" ? 6e4 : relativeMatch[2] === "h" ? 36e5 : 864e5;
6859
+ const deltaMs = amount * unitMs;
6860
+ if (!Number.isSafeInteger(amount) || !Number.isSafeInteger(deltaMs)) {
6861
+ throw ncsTimeError(option, input, "\uC0C1\uB300\uC2DC\uAC04\uC774 \uC548\uC804\uD55C \uC815\uC218 \uBC94\uC704\uB97C \uBC97\uC5B4\uB0AC\uC2B5\uB2C8\uB2E4.");
6862
+ }
6863
+ const timestamp = baseTimestamp - deltaMs;
6864
+ return {
6865
+ value: formatNcsUtcTime(timestamp, option, input),
6866
+ timestamp: Math.floor(timestamp / 1e3) * 1e3
6867
+ };
6868
+ }
6869
+ return parseNcsAbsoluteTime(trimmed, option);
6870
+ }
6871
+ function normalizeNcsTimeRange(from, to, now) {
6872
+ if (from === void 0 && to === void 0) return {};
6873
+ const baseTimestamp = (now ?? /* @__PURE__ */ new Date()).getTime();
6874
+ if (!Number.isFinite(baseTimestamp)) {
6875
+ throw new NhnCloudCliError(
6876
+ `NCS \uC2DC\uAC04 \uC815\uADDC\uD654 \uAE30\uC900 \uC2DC\uAC01\uC774 \uC720\uD6A8\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. ${NCS_TIME_EXAMPLES}\uC744 \uC0AC\uC6A9\uD558\uC138\uC694.`,
6877
+ EXIT_PARAM_ERROR
6878
+ );
6879
+ }
6880
+ const normalizedFrom = from === void 0 ? void 0 : parseNcsTime(from, "--from", baseTimestamp);
6881
+ const normalizedTo = to === void 0 ? void 0 : parseNcsTime(to, "--to", baseTimestamp);
6882
+ if (normalizedFrom !== void 0 && normalizedTo !== void 0 && normalizedFrom.timestamp > normalizedTo.timestamp) {
6883
+ throw new NhnCloudCliError(
6884
+ `--from \uC2DC\uAC04\uC774 --to \uC2DC\uAC04\uBCF4\uB2E4 \uB2A6\uC2B5\uB2C8\uB2E4. ${NCS_TIME_EXAMPLES}\uC744 \uC0AC\uC6A9\uD558\uC138\uC694.`,
6885
+ EXIT_PARAM_ERROR
6886
+ );
6887
+ }
6888
+ return {
6889
+ ...normalizedFrom === void 0 ? {} : { from: normalizedFrom.value },
6890
+ ...normalizedTo === void 0 ? {} : { to: normalizedTo.value }
6891
+ };
6892
+ }
6797
6893
  async function resolveNcsAppKey(profileName, appKeyOpt) {
6798
6894
  if (appKeyOpt) return appKeyOpt;
6799
6895
  let cred;
@@ -7162,7 +7258,13 @@ var getCommand7 = new import_commander46.Command("get").description("NCS workloa
7162
7258
  ids: [workload.id]
7163
7259
  });
7164
7260
  });
7165
- var logsCommand = new import_commander46.Command("logs").description("NCS workload task \uC758 \uCEE8\uD14C\uC774\uB108 \uB85C\uADF8\uB97C \uC870\uD68C\uD55C\uB2E4").argument("<id>", "workload ID").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").option("--task <taskId>", "task ID (\uD544\uC218)").option("--container <name>", "\uCEE8\uD14C\uC774\uB108 \uC774\uB984 (\uD544\uC218)").option("--from <time>", "\uB85C\uADF8 \uC2DC\uC791 \uC2DC\uAC04 (\uAE30\uBCF8: \uD604\uC7AC\uB85C\uBD80\uD130 5\uBD84 \uC804)").option("--to <time>", "\uB85C\uADF8 \uC885\uB8CC \uC2DC\uAC04 (\uAE30\uBCF8: \uD604\uC7AC \uC2DC\uAC04)").option("--page <page>", "\uC870\uD68C\uD560 page \uBC88\uD638").option("--size <size>", "page \uB2F9 \uD56D\uBAA9 \uC218 (\uAE30\uBCF8: API \uAE30\uBCF8\uAC12 100)").action(async (id, _opts, cmd) => {
7261
+ var logsCommand = new import_commander46.Command("logs").description("NCS workload task \uC758 \uCEE8\uD14C\uC774\uB108 \uB85C\uADF8\uB97C \uC870\uD68C\uD55C\uB2E4").argument("<id>", "workload ID").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").option("--task <taskId>", "task ID (\uD544\uC218)").option("--container <name>", "\uCEE8\uD14C\uC774\uB108 \uC774\uB984 (\uD544\uC218)").option(
7262
+ "--from <time>",
7263
+ "\uB85C\uADF8 \uC2DC\uC791: \uC2DC\uAC04\uB300 \uD3EC\uD568 RFC3339, now \uB610\uB294 0 \uC774\uC0C1\uC758 \uC815\uC218\uC640 m/h/d \uB2E8\uC704 (\uC608: 30m, 1h, 2d). UTC Z\uB85C \uC815\uADDC\uD654\uD558\uBA70 \uC0DD\uB7B5 \uC2DC API \uAE30\uBCF8 \uBC94\uC704"
7264
+ ).option(
7265
+ "--to <time>",
7266
+ "\uB85C\uADF8 \uC885\uB8CC: \uC2DC\uAC04\uB300 \uD3EC\uD568 RFC3339, now \uB610\uB294 0 \uC774\uC0C1\uC758 \uC815\uC218\uC640 m/h/d \uB2E8\uC704 (\uC608: 30m, 1h, 2d). UTC Z\uB85C \uC815\uADDC\uD654\uD558\uBA70 \uC0DD\uB7B5 \uC2DC API \uAE30\uBCF8 \uBC94\uC704"
7267
+ ).option("--page <page>", "\uC870\uD68C\uD560 page \uBC88\uD638").option("--size <size>", "page \uB2F9 \uD56D\uBAA9 \uC218 (\uAE30\uBCF8: API \uAE30\uBCF8\uAC12 100)").action(async (id, _opts, cmd) => {
7166
7268
  const opts = cmd.optsWithGlobals();
7167
7269
  requireNonEmpty(id, "id");
7168
7270
  if (!opts.task || !opts.task.trim()) {
@@ -7177,14 +7279,14 @@ var logsCommand = new import_commander46.Command("logs").description("NCS worklo
7177
7279
  EXIT_PARAM_ERROR
7178
7280
  );
7179
7281
  }
7282
+ const timeRange = normalizeNcsTimeRange(opts.from, opts.to);
7180
7283
  const { client } = await resolveNcsClient(opts);
7181
7284
  startSpinner(`NCS workload "${id}" task "${opts.task}" \uB85C\uADF8 \uC870\uD68C \uC911...`);
7182
7285
  let logs;
7183
7286
  try {
7184
7287
  const result = await client.getWorkloadLogs(id, opts.task, {
7185
7288
  container: opts.container,
7186
- from: opts.from,
7187
- to: opts.to,
7289
+ ...timeRange,
7188
7290
  page: parsePositiveIntegerOption(opts.page, "--page"),
7189
7291
  size: parsePositiveIntegerOption(opts.size, "--size")
7190
7292
  });
@@ -7201,7 +7303,13 @@ var logsCommand = new import_commander46.Command("logs").description("NCS worklo
7201
7303
  ids: []
7202
7304
  });
7203
7305
  });
7204
- var eventsCommand2 = new import_commander46.Command("events").description("NCS workload task \uC758 \uC774\uBCA4\uD2B8\uB97C \uC870\uD68C\uD55C\uB2E4").argument("<id>", "workload ID").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").option("--task <taskId>", "task ID (\uD544\uC218)").option("--type <type>", "\uC774\uBCA4\uD2B8 \uD0C0\uC785 (Normal | Warning)").option("--q <query>", "\uC774\uBCA4\uD2B8 \uB0B4\uC6A9 \uD544\uD130\uB9C1").option("--from <time>", "\uC774\uBCA4\uD2B8 \uB9C8\uC9C0\uB9C9 \uBC1C\uC0DD \uC2DC\uC791 \uC2DC\uAC04 (\uAE30\uBCF8: \uD604\uC7AC\uB85C\uBD80\uD130 1\uC2DC\uAC04 \uC804)").option("--to <time>", "\uC774\uBCA4\uD2B8 \uB9C8\uC9C0\uB9C9 \uBC1C\uC0DD \uC885\uB8CC \uC2DC\uAC04 (\uAE30\uBCF8: \uD604\uC7AC \uC2DC\uAC04)").option("--page <page>", "\uC870\uD68C\uD560 page \uBC88\uD638").option("--size <size>", "page \uB2F9 \uD56D\uBAA9 \uC218 (\uAE30\uBCF8: API \uAE30\uBCF8\uAC12 10)").action(async (id, _opts, cmd) => {
7306
+ var eventsCommand2 = new import_commander46.Command("events").description("NCS workload task \uC758 \uC774\uBCA4\uD2B8\uB97C \uC870\uD68C\uD55C\uB2E4").argument("<id>", "workload ID").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").option("--task <taskId>", "task ID (\uD544\uC218)").option("--type <type>", "\uC774\uBCA4\uD2B8 \uD0C0\uC785 (Normal | Warning)").option("--q <query>", "\uC774\uBCA4\uD2B8 \uB0B4\uC6A9 \uD544\uD130\uB9C1").option(
7307
+ "--from <time>",
7308
+ "\uC774\uBCA4\uD2B8 \uC2DC\uC791: \uC2DC\uAC04\uB300 \uD3EC\uD568 RFC3339, now \uB610\uB294 0 \uC774\uC0C1\uC758 \uC815\uC218\uC640 m/h/d \uB2E8\uC704 (\uC608: 30m, 1h, 2d). UTC Z\uB85C \uC815\uADDC\uD654\uD558\uBA70 \uC0DD\uB7B5 \uC2DC API \uAE30\uBCF8 \uBC94\uC704"
7309
+ ).option(
7310
+ "--to <time>",
7311
+ "\uC774\uBCA4\uD2B8 \uC885\uB8CC: \uC2DC\uAC04\uB300 \uD3EC\uD568 RFC3339, now \uB610\uB294 0 \uC774\uC0C1\uC758 \uC815\uC218\uC640 m/h/d \uB2E8\uC704 (\uC608: 30m, 1h, 2d). UTC Z\uB85C \uC815\uADDC\uD654\uD558\uBA70 \uC0DD\uB7B5 \uC2DC API \uAE30\uBCF8 \uBC94\uC704"
7312
+ ).option("--page <page>", "\uC870\uD68C\uD560 page \uBC88\uD638").option("--size <size>", "page \uB2F9 \uD56D\uBAA9 \uC218 (\uAE30\uBCF8: API \uAE30\uBCF8\uAC12 10)").action(async (id, _opts, cmd) => {
7205
7313
  const opts = cmd.optsWithGlobals();
7206
7314
  requireNonEmpty(id, "id");
7207
7315
  if (!opts.task || !opts.task.trim()) {
@@ -7210,6 +7318,7 @@ var eventsCommand2 = new import_commander46.Command("events").description("NCS w
7210
7318
  EXIT_PARAM_ERROR
7211
7319
  );
7212
7320
  }
7321
+ const timeRange = normalizeNcsTimeRange(opts.from, opts.to);
7213
7322
  const { client } = await resolveNcsClient(opts);
7214
7323
  startSpinner(`NCS workload "${id}" task "${opts.task}" \uC774\uBCA4\uD2B8 \uC870\uD68C \uC911...`);
7215
7324
  let totalCount;
@@ -7218,8 +7327,7 @@ var eventsCommand2 = new import_commander46.Command("events").description("NCS w
7218
7327
  const result = await client.getWorkloadEvents(id, opts.task, {
7219
7328
  type: opts.type,
7220
7329
  q: opts.q,
7221
- from: opts.from,
7222
- to: opts.to,
7330
+ ...timeRange,
7223
7331
  page: parsePositiveIntegerOption(opts.page, "--page"),
7224
7332
  size: parsePositiveIntegerOption(opts.size, "--size")
7225
7333
  });
@@ -7551,6 +7659,920 @@ var resultCommand = new import_commander47.Command("result").description("NCS wo
7551
7659
  });
7552
7660
  var malwareCommand = new import_commander47.Command("malware").description("NCS \uC545\uC131\uCF54\uB4DC \uAC80\uC0AC \uAD00\uB9AC").addCommand(configCommand).addCommand(resultCommand);
7553
7661
 
7662
+ // src/commands/loadbalancer/list.ts
7663
+ var import_commander48 = require("commander");
7664
+
7665
+ // src/commands/loadbalancer/helpers.ts
7666
+ var import_node_net = require("net");
7667
+
7668
+ // src/services/loadbalancer/client.ts
7669
+ var import_ky13 = __toESM(require("ky"));
7670
+
7671
+ // src/services/loadbalancer/types.ts
7672
+ function isRecord(value) {
7673
+ return typeof value === "object" && value !== null;
7674
+ }
7675
+ function isNonEmptyString(value) {
7676
+ return typeof value === "string" && value.length > 0;
7677
+ }
7678
+ function isIpAclAction(value) {
7679
+ return value === "ALLOW" || value === "DENY";
7680
+ }
7681
+ function isLoadBalancerIpAclGroup(value) {
7682
+ return isRecord(value) && isNonEmptyString(value["ipacl_group_id"]);
7683
+ }
7684
+ function isIpAclGroupLoadBalancer(value) {
7685
+ return isRecord(value) && isNonEmptyString(value["loadbalancer_id"]);
7686
+ }
7687
+ function isLoadBalancer(value) {
7688
+ if (!isRecord(value)) return false;
7689
+ return isNonEmptyString(value["id"]) && typeof value["name"] === "string" && typeof value["vip_address"] === "string" && typeof value["provisioning_status"] === "string" && typeof value["operating_status"] === "string" && (value["ipacl_group_action"] === null || isIpAclAction(value["ipacl_group_action"])) && Array.isArray(value["ipacl_groups"]) && value["ipacl_groups"].every(isLoadBalancerIpAclGroup);
7690
+ }
7691
+ function isIpAclGroup(value) {
7692
+ if (!isRecord(value)) return false;
7693
+ return isNonEmptyString(value["id"]) && typeof value["name"] === "string" && isIpAclAction(value["action"]) && typeof value["ipacl_target_count"] === "string" && Array.isArray(value["loadbalancers"]) && value["loadbalancers"].every(isIpAclGroupLoadBalancer);
7694
+ }
7695
+ function isIpAclTarget(value) {
7696
+ if (!isRecord(value)) return false;
7697
+ return isNonEmptyString(value["id"]) && typeof value["cidr_address"] === "string" && typeof value["description"] === "string" && isNonEmptyString(value["ipacl_group_id"]);
7698
+ }
7699
+ function isIpAclBinding(value) {
7700
+ return isRecord(value) && isNonEmptyString(value["loadbalancer_id"]) && isNonEmptyString(value["ipacl_group_id"]);
7701
+ }
7702
+
7703
+ // src/services/loadbalancer/client.ts
7704
+ var DEFAULT_TIMEOUT_MS9 = 3e4;
7705
+ function isRecord2(value) {
7706
+ return typeof value === "object" && value !== null;
7707
+ }
7708
+ function requireNonEmptyId(id, label) {
7709
+ const normalized = id.trim();
7710
+ if (!normalized) {
7711
+ throw new NhnCloudCliError(`${label}\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.`, EXIT_PARAM_ERROR);
7712
+ }
7713
+ return normalized;
7714
+ }
7715
+ function readArrayField(response, key, itemGuard, missingKeyMessage, invalidItemMessage) {
7716
+ if (!isRecord2(response) || !Array.isArray(response[key])) {
7717
+ throw new NhnCloudCliError(missingKeyMessage, EXIT_API_ERROR);
7718
+ }
7719
+ const items = response[key];
7720
+ if (!items.every(itemGuard)) {
7721
+ throw new NhnCloudCliError(invalidItemMessage, EXIT_API_ERROR);
7722
+ }
7723
+ return items;
7724
+ }
7725
+ function readObjectField(response, key, itemGuard, missingKeyMessage, invalidItemMessage) {
7726
+ if (!isRecord2(response) || !(key in response)) {
7727
+ throw new NhnCloudCliError(missingKeyMessage, EXIT_API_ERROR);
7728
+ }
7729
+ const item = response[key];
7730
+ if (!itemGuard(item)) {
7731
+ throw new NhnCloudCliError(invalidItemMessage, EXIT_API_ERROR);
7732
+ }
7733
+ return item;
7734
+ }
7735
+ var LoadBalancerClient = class {
7736
+ tokenId;
7737
+ endpoint;
7738
+ constructor(tokenId, networkEndpoint) {
7739
+ this.tokenId = tokenId;
7740
+ this.endpoint = `${networkEndpoint}/lbaas`;
7741
+ }
7742
+ authHeaders() {
7743
+ return { "X-Auth-Token": this.tokenId };
7744
+ }
7745
+ async listLoadBalancers(query) {
7746
+ const raw = await this.getJson("/loadbalancers", query);
7747
+ return readArrayField(
7748
+ raw,
7749
+ "loadbalancers",
7750
+ isLoadBalancer,
7751
+ "loadbalancer list \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 loadbalancers \uBC30\uC5F4\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
7752
+ "loadbalancer list \uC751\uB2F5\uC758 Load Balancer \uD56D\uBAA9 \uD615\uC2DD\uC774 \uC608\uC0C1\uACFC \uB2E4\uB985\uB2C8\uB2E4 \u2014 API \uC751\uB2F5 \uD544\uB4DC\uB97C \uD655\uC778\uD558\uC138\uC694."
7753
+ );
7754
+ }
7755
+ async getLoadBalancer(id) {
7756
+ const raw = await this.getJson(`/loadbalancers/${encodeURIComponent(id)}`);
7757
+ return readObjectField(
7758
+ raw,
7759
+ "loadbalancer",
7760
+ isLoadBalancer,
7761
+ "loadbalancer get \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 loadbalancer \uAC1D\uCCB4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
7762
+ "loadbalancer get \uC751\uB2F5\uC758 Load Balancer \uD56D\uBAA9 \uD615\uC2DD\uC774 \uC608\uC0C1\uACFC \uB2E4\uB985\uB2C8\uB2E4 \u2014 API \uC751\uB2F5 \uD544\uB4DC\uB97C \uD655\uC778\uD558\uC138\uC694."
7763
+ );
7764
+ }
7765
+ async listIpAclGroups(query) {
7766
+ const raw = await this.getJson("/ipacl-groups", query);
7767
+ return readArrayField(
7768
+ raw,
7769
+ "ipacl_groups",
7770
+ isIpAclGroup,
7771
+ "loadbalancer ipacl list \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 ipacl_groups \uBC30\uC5F4\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
7772
+ "loadbalancer ipacl list \uC751\uB2F5\uC758 IP ACL \uADF8\uB8F9 \uD56D\uBAA9 \uD615\uC2DD\uC774 \uC608\uC0C1\uACFC \uB2E4\uB985\uB2C8\uB2E4 \u2014 API \uC751\uB2F5 \uD544\uB4DC\uB97C \uD655\uC778\uD558\uC138\uC694."
7773
+ );
7774
+ }
7775
+ async getIpAclGroup(id) {
7776
+ const raw = await this.getJson(`/ipacl-groups/${encodeURIComponent(id)}`);
7777
+ return readObjectField(
7778
+ raw,
7779
+ "ipacl_group",
7780
+ isIpAclGroup,
7781
+ "loadbalancer ipacl get \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 ipacl_group \uAC1D\uCCB4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
7782
+ "loadbalancer ipacl get \uC751\uB2F5\uC758 IP ACL \uADF8\uB8F9 \uD56D\uBAA9 \uD615\uC2DD\uC774 \uC608\uC0C1\uACFC \uB2E4\uB985\uB2C8\uB2E4 \u2014 API \uC751\uB2F5 \uD544\uB4DC\uB97C \uD655\uC778\uD558\uC138\uC694."
7783
+ );
7784
+ }
7785
+ async listIpAclTargets(query) {
7786
+ const raw = await this.getJson("/ipacl-targets", query);
7787
+ return readArrayField(
7788
+ raw,
7789
+ "ipacl_targets",
7790
+ isIpAclTarget,
7791
+ "loadbalancer ipacl target list \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 ipacl_targets \uBC30\uC5F4\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
7792
+ "loadbalancer ipacl target list \uC751\uB2F5\uC758 IP ACL \uB300\uC0C1 \uD56D\uBAA9 \uD615\uC2DD\uC774 \uC608\uC0C1\uACFC \uB2E4\uB985\uB2C8\uB2E4 \u2014 API \uC751\uB2F5 \uD544\uB4DC\uB97C \uD655\uC778\uD558\uC138\uC694."
7793
+ );
7794
+ }
7795
+ async createIpAclGroup(input) {
7796
+ const request = { ipacl_group: input };
7797
+ const raw = await this.postJson("/ipacl-groups", request);
7798
+ return readObjectField(
7799
+ raw,
7800
+ "ipacl_group",
7801
+ isIpAclGroup,
7802
+ "loadbalancer ipacl create \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 ipacl_group \uAC1D\uCCB4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
7803
+ "loadbalancer ipacl create \uC751\uB2F5\uC758 IP ACL \uADF8\uB8F9 \uD56D\uBAA9 \uD615\uC2DD\uC774 \uC608\uC0C1\uACFC \uB2E4\uB985\uB2C8\uB2E4 \u2014 API \uC751\uB2F5 \uD544\uB4DC\uB97C \uD655\uC778\uD558\uC138\uC694."
7804
+ );
7805
+ }
7806
+ async deleteIpAclGroup(id) {
7807
+ const normalizedId = requireNonEmptyId(id, "IP ACL \uADF8\uB8F9 ID");
7808
+ await this.deleteNoContent(`/ipacl-groups/${encodeURIComponent(normalizedId)}`);
7809
+ }
7810
+ async getIpAclTarget(id) {
7811
+ const normalizedId = requireNonEmptyId(id, "IP ACL \uB300\uC0C1 ID");
7812
+ const raw = await this.getJson(`/ipacl-targets/${encodeURIComponent(normalizedId)}`);
7813
+ return readObjectField(
7814
+ raw,
7815
+ "ipacl_target",
7816
+ isIpAclTarget,
7817
+ "loadbalancer ipacl target get \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 ipacl_target \uAC1D\uCCB4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
7818
+ "loadbalancer ipacl target get \uC751\uB2F5\uC758 IP ACL \uB300\uC0C1 \uD56D\uBAA9 \uD615\uC2DD\uC774 \uC608\uC0C1\uACFC \uB2E4\uB985\uB2C8\uB2E4 \u2014 API \uC751\uB2F5 \uD544\uB4DC\uB97C \uD655\uC778\uD558\uC138\uC694."
7819
+ );
7820
+ }
7821
+ async createIpAclTarget(input) {
7822
+ const request = { ipacl_target: input };
7823
+ const raw = await this.postJson("/ipacl-targets", request);
7824
+ return readObjectField(
7825
+ raw,
7826
+ "ipacl_target",
7827
+ isIpAclTarget,
7828
+ "loadbalancer ipacl target add \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 ipacl_target \uAC1D\uCCB4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
7829
+ "loadbalancer ipacl target add \uC751\uB2F5\uC758 IP ACL \uB300\uC0C1 \uD56D\uBAA9 \uD615\uC2DD\uC774 \uC608\uC0C1\uACFC \uB2E4\uB985\uB2C8\uB2E4 \u2014 API \uC751\uB2F5 \uD544\uB4DC\uB97C \uD655\uC778\uD558\uC138\uC694."
7830
+ );
7831
+ }
7832
+ async deleteIpAclTarget(id) {
7833
+ const normalizedId = requireNonEmptyId(id, "IP ACL \uB300\uC0C1 ID");
7834
+ await this.deleteNoContent(`/ipacl-targets/${encodeURIComponent(normalizedId)}`);
7835
+ }
7836
+ async bindIpAclGroups(loadBalancerId, ipAclGroupIds) {
7837
+ const normalizedLoadBalancerId = requireNonEmptyId(
7838
+ loadBalancerId,
7839
+ "Load Balancer ID"
7840
+ );
7841
+ const request = {
7842
+ ipacl_groups_binding: ipAclGroupIds.map((id) => ({
7843
+ ipacl_group_id: requireNonEmptyId(id, "IP ACL \uADF8\uB8F9 ID")
7844
+ }))
7845
+ };
7846
+ const raw = await this.putJson(
7847
+ `/loadbalancers/${encodeURIComponent(normalizedLoadBalancerId)}/bind_ipacl_groups`,
7848
+ request
7849
+ );
7850
+ if (!Array.isArray(raw)) {
7851
+ throw new NhnCloudCliError(
7852
+ "loadbalancer set-ipacl \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 binding \uBC30\uC5F4\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
7853
+ EXIT_API_ERROR
7854
+ );
7855
+ }
7856
+ if (!raw.every(isIpAclBinding)) {
7857
+ throw new NhnCloudCliError(
7858
+ "loadbalancer set-ipacl \uC751\uB2F5\uC758 binding \uD56D\uBAA9 \uD615\uC2DD\uC774 \uC608\uC0C1\uACFC \uB2E4\uB985\uB2C8\uB2E4 \u2014 API \uC751\uB2F5 \uD544\uB4DC\uB97C \uD655\uC778\uD558\uC138\uC694.",
7859
+ EXIT_API_ERROR
7860
+ );
7861
+ }
7862
+ return raw;
7863
+ }
7864
+ async getJson(path3, searchParams) {
7865
+ const url = `${this.endpoint}${path3}`;
7866
+ try {
7867
+ return await import_ky13.default.get(url, {
7868
+ headers: this.authHeaders(),
7869
+ searchParams,
7870
+ retry: 0,
7871
+ timeout: DEFAULT_TIMEOUT_MS9
7872
+ }).json();
7873
+ } catch (error) {
7874
+ throw toNhnCloudCliError(error);
7875
+ }
7876
+ }
7877
+ async postJson(path3, json) {
7878
+ const url = `${this.endpoint}${path3}`;
7879
+ try {
7880
+ return await import_ky13.default.post(url, {
7881
+ headers: this.authHeaders(),
7882
+ json,
7883
+ retry: 0,
7884
+ timeout: DEFAULT_TIMEOUT_MS9
7885
+ }).json();
7886
+ } catch (error) {
7887
+ throw toNhnCloudCliError(error);
7888
+ }
7889
+ }
7890
+ async putJson(path3, json) {
7891
+ const url = `${this.endpoint}${path3}`;
7892
+ try {
7893
+ return await import_ky13.default.put(url, {
7894
+ headers: this.authHeaders(),
7895
+ json,
7896
+ retry: 0,
7897
+ timeout: DEFAULT_TIMEOUT_MS9
7898
+ }).json();
7899
+ } catch (error) {
7900
+ throw toNhnCloudCliError(error);
7901
+ }
7902
+ }
7903
+ async deleteNoContent(path3) {
7904
+ const url = `${this.endpoint}${path3}`;
7905
+ try {
7906
+ await import_ky13.default.delete(url, {
7907
+ headers: this.authHeaders(),
7908
+ retry: 0,
7909
+ timeout: DEFAULT_TIMEOUT_MS9
7910
+ });
7911
+ } catch (error) {
7912
+ throw toNhnCloudCliError(error);
7913
+ }
7914
+ }
7915
+ };
7916
+
7917
+ // src/commands/loadbalancer/helpers.ts
7918
+ function requireResourceInput(value, label) {
7919
+ const normalized = value.trim();
7920
+ if (!normalized) {
7921
+ throw new NhnCloudCliError(`${label} \uC774\uB984 \uB610\uB294 UUID\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.`, EXIT_PARAM_ERROR);
7922
+ }
7923
+ return normalized;
7924
+ }
7925
+ function optionalTrimmed(value) {
7926
+ if (value === void 0) return void 0;
7927
+ return value.trim();
7928
+ }
7929
+ function requireYes(yes, operation) {
7930
+ if (!yes) {
7931
+ throw new NhnCloudCliError(
7932
+ `${operation}\uC5D0\uB294 --yes \uD50C\uB798\uADF8\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.`,
7933
+ EXIT_PARAM_ERROR
7934
+ );
7935
+ }
7936
+ return true;
7937
+ }
7938
+ function parseIpAclAction(value) {
7939
+ if (value !== "ALLOW" && value !== "DENY") {
7940
+ throw new NhnCloudCliError(
7941
+ `--action\uC740 ALLOW \uB610\uB294 DENY\uC5EC\uC57C \uD569\uB2C8\uB2E4: ${JSON.stringify(value)}`,
7942
+ EXIT_PARAM_ERROR
7943
+ );
7944
+ }
7945
+ return value;
7946
+ }
7947
+ function collectOption(value, previous = []) {
7948
+ return [...previous, value];
7949
+ }
7950
+ function requireResourceInputs(values, label) {
7951
+ if (values.length === 0) {
7952
+ throw new NhnCloudCliError(`${label}\uC744(\uB97C) \uD55C \uAC1C \uC774\uC0C1 \uC9C0\uC815\uD574\uC57C \uD569\uB2C8\uB2E4.`, EXIT_PARAM_ERROR);
7953
+ }
7954
+ return values.map((value) => requireResourceInput(value, label));
7955
+ }
7956
+ function parseIpOrCidr(value) {
7957
+ const normalized = value.trim();
7958
+ const parts = normalized.split("/");
7959
+ const address = parts[0] ?? "";
7960
+ const version = (0, import_node_net.isIP)(address);
7961
+ if (version === 0 || parts.length > 2) {
7962
+ throw new NhnCloudCliError(
7963
+ `--cidr\uC740 IP \uC8FC\uC18C \uB610\uB294 CIDR\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4: ${JSON.stringify(value)}`,
7964
+ EXIT_PARAM_ERROR
7965
+ );
7966
+ }
7967
+ if (parts.length === 2) {
7968
+ const prefix = parts[1] ?? "";
7969
+ const maxPrefix = version === 4 ? 32 : 128;
7970
+ if (!/^\d+$/.test(prefix) || Number(prefix) > maxPrefix) {
7971
+ throw new NhnCloudCliError(
7972
+ `--cidr prefix\uAC00 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: ${JSON.stringify(value)}`,
7973
+ EXIT_PARAM_ERROR
7974
+ );
7975
+ }
7976
+ }
7977
+ return normalized;
7978
+ }
7979
+ function resolvedId(resource, label) {
7980
+ const id = resource.id.trim();
7981
+ if (!id) {
7982
+ throw new NhnCloudCliError(`${label} \uC870\uD68C \uACB0\uACFC\uC758 UUID\uAC00 \uBE44\uC5B4 \uC788\uC2B5\uB2C8\uB2E4.`, EXIT_PARAM_ERROR);
7983
+ }
7984
+ return id;
7985
+ }
7986
+ function resolveFromList(resources, input, label) {
7987
+ const exactId = resources.find((resource) => resource.id === input);
7988
+ if (exactId) return resolvedId(exactId, label);
7989
+ const nameMatches = resources.filter((resource) => resource.name === input);
7990
+ if (nameMatches.length === 1) return resolvedId(nameMatches[0], label);
7991
+ if (nameMatches.length === 0) {
7992
+ throw new NhnCloudCliError(
7993
+ `${label}\uC744(\uB97C) \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${JSON.stringify(input)}`,
7994
+ EXIT_PARAM_ERROR
7995
+ );
7996
+ }
7997
+ const candidateIds = nameMatches.map((resource) => resolvedId(resource, label)).sort();
7998
+ throw new NhnCloudCliError(
7999
+ `${label} \uC774\uB984\uC774 \uC911\uBCF5\uB429\uB2C8\uB2E4: ${JSON.stringify(input)} (\uD6C4\uBCF4 UUID: ${candidateIds.join(", ")})`,
8000
+ EXIT_PARAM_ERROR
8001
+ );
8002
+ }
8003
+ async function resolveLoadBalancerId(client, value) {
8004
+ const input = requireResourceInput(value, "Load Balancer");
8005
+ const resources = await client.listLoadBalancers();
8006
+ return resolveFromList(resources, input, "Load Balancer");
8007
+ }
8008
+ async function resolveIpAclGroupId(client, value) {
8009
+ const input = requireResourceInput(value, "IP ACL \uADF8\uB8F9");
8010
+ const resources = await client.listIpAclGroups();
8011
+ return resolveFromList(resources, input, "IP ACL \uADF8\uB8F9");
8012
+ }
8013
+ async function resolveIpAclGroups(client, values) {
8014
+ const inputs = requireResourceInputs(values, "IP ACL \uADF8\uB8F9");
8015
+ const resources = await client.listIpAclGroups();
8016
+ return inputs.map((input) => {
8017
+ const id = resolveFromList(resources, input, "IP ACL \uADF8\uB8F9");
8018
+ const group = resources.find((resource) => resource.id === id);
8019
+ if (!group) {
8020
+ throw new NhnCloudCliError(
8021
+ `IP ACL \uADF8\uB8F9 \uC870\uD68C \uACB0\uACFC\uC5D0\uC11C UUID\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${JSON.stringify(id)}`,
8022
+ EXIT_PARAM_ERROR
8023
+ );
8024
+ }
8025
+ return group;
8026
+ });
8027
+ }
8028
+ async function resolveLoadBalancerClient(opts) {
8029
+ const { profileName, tokenId, networkEndpoint } = await resolveIaasTokenContext(opts);
8030
+ return {
8031
+ client: new LoadBalancerClient(tokenId, networkEndpoint),
8032
+ profileName
8033
+ };
8034
+ }
8035
+
8036
+ // src/commands/loadbalancer/list.ts
8037
+ var listCommand10 = new import_commander48.Command("list").description("Load Balancer \uBAA9\uB85D\uC744 \uC870\uD68C\uD55C\uB2E4 (\uC804\uCCB4 \uD544\uB4DC\uB294 --json)").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) => {
8038
+ const opts = cmd.optsWithGlobals();
8039
+ const { client } = await resolveLoadBalancerClient(opts);
8040
+ startSpinner("Load Balancer \uBAA9\uB85D \uC870\uD68C \uC911...");
8041
+ let loadBalancers;
8042
+ let success = false;
8043
+ try {
8044
+ loadBalancers = await client.listLoadBalancers();
8045
+ success = true;
8046
+ } catch (error) {
8047
+ stopSpinner(false);
8048
+ throw error;
8049
+ } finally {
8050
+ if (success) stopSpinner(true);
8051
+ }
8052
+ output(opts, {
8053
+ headers: [
8054
+ "id",
8055
+ "name",
8056
+ "vip_address",
8057
+ "provisioning_status",
8058
+ "operating_status",
8059
+ "ipacl_group_action"
8060
+ ],
8061
+ rows: loadBalancers.map((loadBalancer) => [
8062
+ loadBalancer.id,
8063
+ loadBalancer.name,
8064
+ loadBalancer.vip_address,
8065
+ loadBalancer.provisioning_status,
8066
+ loadBalancer.operating_status,
8067
+ loadBalancer.ipacl_group_action ?? ""
8068
+ ]),
8069
+ raw: loadBalancers,
8070
+ ids: loadBalancers.map((loadBalancer) => loadBalancer.id)
8071
+ });
8072
+ });
8073
+
8074
+ // src/commands/loadbalancer/get.ts
8075
+ var import_commander49 = require("commander");
8076
+ var getCommand8 = new import_commander49.Command("get").description("Load Balancer\uB97C \uC774\uB984 \uB610\uB294 UUID\uB85C \uC870\uD68C\uD55C\uB2E4").argument("<loadbalancer>", "Load Balancer \uC774\uB984 \uB610\uB294 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 (loadBalancerInput, _opts, cmd) => {
8077
+ const opts = cmd.optsWithGlobals();
8078
+ const input = requireResourceInput(loadBalancerInput, "Load Balancer");
8079
+ const { client } = await resolveLoadBalancerClient(opts);
8080
+ startSpinner("Load Balancer \uC870\uD68C \uC911...");
8081
+ let loadBalancer;
8082
+ let success = false;
8083
+ try {
8084
+ const id = await resolveLoadBalancerId(client, input);
8085
+ loadBalancer = await client.getLoadBalancer(id);
8086
+ success = true;
8087
+ } catch (error) {
8088
+ stopSpinner(false);
8089
+ throw error;
8090
+ } finally {
8091
+ if (success) stopSpinner(true);
8092
+ }
8093
+ output(opts, {
8094
+ headers: ["field", "value"],
8095
+ rows: [
8096
+ ["id", loadBalancer.id],
8097
+ ["name", loadBalancer.name],
8098
+ ["vip_address", loadBalancer.vip_address],
8099
+ ["provisioning_status", loadBalancer.provisioning_status],
8100
+ ["operating_status", loadBalancer.operating_status],
8101
+ ["ipacl_group_action", loadBalancer.ipacl_group_action ?? ""],
8102
+ [
8103
+ "ipacl_group_ids",
8104
+ loadBalancer.ipacl_groups.map((group) => group.ipacl_group_id).join(", ")
8105
+ ]
8106
+ ],
8107
+ raw: loadBalancer,
8108
+ ids: [loadBalancer.id]
8109
+ });
8110
+ });
8111
+
8112
+ // src/commands/loadbalancer/ipacl.ts
8113
+ var import_commander51 = require("commander");
8114
+
8115
+ // src/commands/loadbalancer/target.ts
8116
+ var import_commander50 = require("commander");
8117
+
8118
+ // src/commands/loadbalancer/rebind.ts
8119
+ function sanitizeForTerminal(value) {
8120
+ return value.replace(/[\x00-\x1F\x7F]/g, "?");
8121
+ }
8122
+ function shellQuote(value) {
8123
+ return `'${value.replace(/'/g, `'"'"'`)}'`;
8124
+ }
8125
+ function contextArgv(context) {
8126
+ return [
8127
+ ...context.profile === void 0 ? [] : ["--profile", context.profile],
8128
+ ...context.region === void 0 ? [] : ["--region", context.region]
8129
+ ];
8130
+ }
8131
+ function retryArgv(snapshot, context = {}) {
8132
+ if (snapshot.ipacl_group_ids.length === 0) {
8133
+ return [
8134
+ "nhncloud",
8135
+ "loadbalancer",
8136
+ "clear-ipacl",
8137
+ snapshot.loadbalancer_id,
8138
+ ...contextArgv(context),
8139
+ "--yes",
8140
+ "--json"
8141
+ ];
8142
+ }
8143
+ return [
8144
+ "nhncloud",
8145
+ "loadbalancer",
8146
+ "set-ipacl",
8147
+ snapshot.loadbalancer_id,
8148
+ ...snapshot.ipacl_group_ids.flatMap((id) => ["--group", id]),
8149
+ ...contextArgv(context),
8150
+ "--yes",
8151
+ "--json"
8152
+ ];
8153
+ }
8154
+ function retryCommand(argv) {
8155
+ return argv.map(shellQuote).join(" ");
8156
+ }
8157
+ async function snapshotIpAclBindings(client, loadBalancerIds) {
8158
+ const uniqueIds = [...new Set(loadBalancerIds)].sort();
8159
+ const snapshots = [];
8160
+ for (const loadBalancerId of uniqueIds) {
8161
+ const loadBalancer = await client.getLoadBalancer(loadBalancerId);
8162
+ snapshots.push({
8163
+ loadbalancer_id: loadBalancer.id,
8164
+ ipacl_group_ids: loadBalancer.ipacl_groups.map((group) => group.ipacl_group_id)
8165
+ });
8166
+ }
8167
+ return snapshots;
8168
+ }
8169
+ async function rebindIpAclSnapshots(client, snapshots, retryContext = {}) {
8170
+ const succeeded = [];
8171
+ const failed = [];
8172
+ for (const snapshot of snapshots) {
8173
+ try {
8174
+ await client.bindIpAclGroups(
8175
+ snapshot.loadbalancer_id,
8176
+ snapshot.ipacl_group_ids
8177
+ );
8178
+ succeeded.push(snapshot);
8179
+ } catch (error) {
8180
+ const argv = retryArgv(snapshot, retryContext);
8181
+ failed.push({
8182
+ ...snapshot,
8183
+ error: error instanceof Error ? error.message : String(error),
8184
+ retry_argv: argv,
8185
+ retry_command: retryCommand(argv)
8186
+ });
8187
+ }
8188
+ }
8189
+ return { skipped: false, succeeded, failed };
8190
+ }
8191
+ function skippedRebindResult() {
8192
+ return { skipped: true, succeeded: [], failed: [] };
8193
+ }
8194
+
8195
+ // src/commands/loadbalancer/target.ts
8196
+ function outputTargetWriteResult(opts, result) {
8197
+ output(opts, {
8198
+ headers: ["field", "value"],
8199
+ rows: [
8200
+ ["operation", result.operation],
8201
+ ["status", result.status],
8202
+ ["target_id", result.target.id],
8203
+ ["ipacl_group_id", result.target.ipacl_group_id],
8204
+ ["rebind_skipped", String(result.rebind.skipped)],
8205
+ ["rebind_succeeded", String(result.rebind.succeeded.length)],
8206
+ ["rebind_failed", String(result.rebind.failed.length)]
8207
+ ],
8208
+ raw: result,
8209
+ ids: [result.target.id]
8210
+ });
8211
+ }
8212
+ function writeTargetWarnings(group, result) {
8213
+ if (result.rebind.skipped) {
8214
+ process.stderr.write(
8215
+ "\uACBD\uACE0: --no-rebind\uB85C \uC7AC\uBC14\uC778\uB529\uC744 \uC0DD\uB7B5\uD588\uC2B5\uB2C8\uB2E4. \uB370\uC774\uD130 \uC601\uC5ED\uC5D0 \uADDC\uCE59\uC774 \uC989\uC2DC \uBC18\uC601\uB418\uC9C0 \uC54A\uC744 \uC218 \uC788\uC2B5\uB2C8\uB2E4.\n"
8216
+ );
8217
+ }
8218
+ process.stderr.write(
8219
+ "\uC548\uB0B4: IP ACL \uB300\uC0C1 \uBCC0\uACBD\uC774 \uB370\uC774\uD130 \uC601\uC5ED\uC5D0 \uBC18\uC601\uB418\uAE30\uAE4C\uC9C0 \uC57D 10~20\uCD08\uAC00 \uAC78\uB9B4 \uC218 \uC788\uC2B5\uB2C8\uB2E4.\n"
8220
+ );
8221
+ if (group.action === "ALLOW") {
8222
+ process.stderr.write(
8223
+ "\uACBD\uACE0: ALLOW \uADF8\uB8F9 \uB300\uC0C1\uC5D0\uB294 Load Balancer\uAC00 \uC18D\uD55C VPC\uC758 private CIDR\uC744 \uC0AC\uC6A9\uD574\uC57C \uD569\uB2C8\uB2E4.\n"
8224
+ );
8225
+ }
8226
+ if (result.rebind.failed.length > 0) {
8227
+ process.stderr.write(
8228
+ `\uACBD\uACE0: ${result.rebind.failed.length}\uAC1C Load Balancer \uC7AC\uBC14\uC778\uB529\uC774 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. \uC544\uB798 \uBA85\uB839\uC73C\uB85C \uBCF5\uAD6C\uD558\uC138\uC694.
8229
+ `
8230
+ );
8231
+ for (const failure of result.rebind.failed) {
8232
+ process.stderr.write(`${sanitizeForTerminal(failure.retry_command)}
8233
+ `);
8234
+ process.stderr.write(` \uC624\uB958: ${sanitizeForTerminal(failure.error)}
8235
+ `);
8236
+ }
8237
+ }
8238
+ }
8239
+ function targetWriteResult(operation, target, rebind) {
8240
+ return {
8241
+ operation,
8242
+ status: rebind.failed.length === 0 ? "succeeded" : "partial",
8243
+ target: {
8244
+ id: target.id,
8245
+ ipacl_group_id: target.ipacl_group_id
8246
+ },
8247
+ rebind
8248
+ };
8249
+ }
8250
+ var listCommand11 = new import_commander50.Command("list").description("IP ACL \uB300\uC0C1 \uBAA9\uB85D\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<group>", "IP ACL \uADF8\uB8F9 \uC774\uB984 \uB610\uB294 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 (groupInput, _opts, cmd) => {
8251
+ const opts = cmd.optsWithGlobals();
8252
+ const input = requireResourceInput(groupInput, "IP ACL \uADF8\uB8F9");
8253
+ const { client } = await resolveLoadBalancerClient(opts);
8254
+ startSpinner("IP ACL \uB300\uC0C1 \uBAA9\uB85D \uC870\uD68C \uC911...");
8255
+ let targets;
8256
+ let success = false;
8257
+ try {
8258
+ const groupId = await resolveIpAclGroupId(client, input);
8259
+ targets = await client.listIpAclTargets({ ipacl_group_id: groupId });
8260
+ success = true;
8261
+ } catch (error) {
8262
+ stopSpinner(false);
8263
+ throw error;
8264
+ } finally {
8265
+ if (success) stopSpinner(true);
8266
+ }
8267
+ output(opts, {
8268
+ headers: ["id", "cidr_address", "description", "ipacl_group_id"],
8269
+ rows: targets.map((target) => [
8270
+ target.id,
8271
+ target.cidr_address,
8272
+ target.description,
8273
+ target.ipacl_group_id
8274
+ ]),
8275
+ raw: targets,
8276
+ ids: targets.map((target) => target.id)
8277
+ });
8278
+ });
8279
+ var addCommand = new import_commander50.Command("add").description("IP ACL \uB300\uC0C1\uC744 \uCD94\uAC00\uD558\uACE0 \uC5F0\uACB0\uB41C Load Balancer\uB97C \uC7AC\uBC14\uC778\uB529\uD55C\uB2E4").argument("<group>", "IP ACL \uADF8\uB8F9 \uC774\uB984 \uB610\uB294 UUID").requiredOption("--cidr <ip-or-cidr>", "\uCD94\uAC00\uD560 IP \uC8FC\uC18C \uB610\uB294 CIDR").option("--description <text>", "IP ACL \uB300\uC0C1 \uC124\uBA85").option("--no-rebind", "\uB300\uC0C1 \uCD94\uAC00 \uD6C4 Load Balancer \uC7AC\uBC14\uC778\uB529 \uC0DD\uB7B5").option("--yes", "\uB300\uC0C1 \uCD94\uAC00 \uD655\uC778").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 (groupInput, _opts, cmd) => {
8280
+ const opts = cmd.optsWithGlobals();
8281
+ requireYes(opts.yes, "IP ACL \uB300\uC0C1 \uCD94\uAC00");
8282
+ const parsedGroup = requireResourceInput(groupInput, "IP ACL \uADF8\uB8F9");
8283
+ const parsedCidr = parseIpOrCidr(opts.cidr ?? "");
8284
+ const parsedDescription = optionalTrimmed(opts.description);
8285
+ const { client } = await resolveLoadBalancerClient(opts);
8286
+ startSpinner("IP ACL \uB300\uC0C1 \uCD94\uAC00\uC640 Load Balancer \uC7AC\uBC14\uC778\uB529 \uC911...");
8287
+ let group;
8288
+ let target;
8289
+ let rebind;
8290
+ try {
8291
+ const groupId = await resolveIpAclGroupId(client, parsedGroup);
8292
+ group = await client.getIpAclGroup(groupId);
8293
+ const snapshots = opts.rebind === false ? [] : await snapshotIpAclBindings(
8294
+ client,
8295
+ group.loadbalancers.map((item) => item.loadbalancer_id)
8296
+ );
8297
+ target = await client.createIpAclTarget({
8298
+ ipacl_group_id: group.id,
8299
+ cidr_address: parsedCidr,
8300
+ ...parsedDescription === void 0 ? {} : { description: parsedDescription }
8301
+ });
8302
+ rebind = opts.rebind === false ? skippedRebindResult() : await rebindIpAclSnapshots(client, snapshots, {
8303
+ profile: opts.profile,
8304
+ region: opts.region
8305
+ });
8306
+ } catch (error) {
8307
+ stopSpinner(false);
8308
+ throw error;
8309
+ }
8310
+ stopSpinner(true);
8311
+ const result = targetWriteResult("ipacl-target-add", target, rebind);
8312
+ outputTargetWriteResult(opts, result);
8313
+ writeTargetWarnings(group, result);
8314
+ if (result.status === "partial") process.exitCode = EXIT_API_ERROR;
8315
+ });
8316
+ var removeCommand = new import_commander50.Command("remove").description("IP ACL \uB300\uC0C1\uC744 \uC0AD\uC81C\uD558\uACE0 \uC5F0\uACB0\uB41C Load Balancer\uB97C \uC7AC\uBC14\uC778\uB529\uD55C\uB2E4").argument("<target-id>", "\uC0AD\uC81C\uD560 IP ACL \uB300\uC0C1 UUID").option("--no-rebind", "\uB300\uC0C1 \uC0AD\uC81C \uD6C4 Load Balancer \uC7AC\uBC14\uC778\uB529 \uC0DD\uB7B5").option("--yes", "\uB300\uC0C1 \uC0AD\uC81C \uD655\uC778").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 (targetInput, _opts, cmd) => {
8317
+ const opts = cmd.optsWithGlobals();
8318
+ requireYes(opts.yes, "IP ACL \uB300\uC0C1 \uC0AD\uC81C");
8319
+ const parsedTargetId = requireResourceInput(targetInput, "IP ACL \uB300\uC0C1");
8320
+ const { client } = await resolveLoadBalancerClient(opts);
8321
+ startSpinner("IP ACL \uB300\uC0C1 \uC0AD\uC81C\uC640 Load Balancer \uC7AC\uBC14\uC778\uB529 \uC911...");
8322
+ let group;
8323
+ let target;
8324
+ let rebind;
8325
+ try {
8326
+ target = await client.getIpAclTarget(parsedTargetId);
8327
+ group = await client.getIpAclGroup(target.ipacl_group_id);
8328
+ const snapshots = opts.rebind === false ? [] : await snapshotIpAclBindings(
8329
+ client,
8330
+ group.loadbalancers.map((item) => item.loadbalancer_id)
8331
+ );
8332
+ await client.deleteIpAclTarget(target.id);
8333
+ rebind = opts.rebind === false ? skippedRebindResult() : await rebindIpAclSnapshots(client, snapshots, {
8334
+ profile: opts.profile,
8335
+ region: opts.region
8336
+ });
8337
+ } catch (error) {
8338
+ stopSpinner(false);
8339
+ throw error;
8340
+ }
8341
+ stopSpinner(true);
8342
+ const result = targetWriteResult("ipacl-target-remove", target, rebind);
8343
+ outputTargetWriteResult(opts, result);
8344
+ writeTargetWarnings(group, result);
8345
+ if (result.status === "partial") process.exitCode = EXIT_API_ERROR;
8346
+ });
8347
+ var targetCommand = new import_commander50.Command("target").description("IP ACL \uB300\uC0C1 \uC870\uD68C\xB7\uAD00\uB9AC");
8348
+ targetCommand.addCommand(listCommand11);
8349
+ targetCommand.addCommand(addCommand);
8350
+ targetCommand.addCommand(removeCommand);
8351
+
8352
+ // src/commands/loadbalancer/ipacl.ts
8353
+ var listCommand12 = new import_commander51.Command("list").description("IP ACL \uADF8\uB8F9 \uBAA9\uB85D\uC744 \uC870\uD68C\uD55C\uB2E4 (\uC804\uCCB4 \uD544\uB4DC\uB294 --json)").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) => {
8354
+ const opts = cmd.optsWithGlobals();
8355
+ const { client } = await resolveLoadBalancerClient(opts);
8356
+ startSpinner("IP ACL \uADF8\uB8F9 \uBAA9\uB85D \uC870\uD68C \uC911...");
8357
+ let groups;
8358
+ let success = false;
8359
+ try {
8360
+ groups = await client.listIpAclGroups();
8361
+ success = true;
8362
+ } catch (error) {
8363
+ stopSpinner(false);
8364
+ throw error;
8365
+ } finally {
8366
+ if (success) stopSpinner(true);
8367
+ }
8368
+ output(opts, {
8369
+ headers: ["id", "name", "action", "ipacl_target_count", "loadbalancer_count"],
8370
+ rows: groups.map((group) => [
8371
+ group.id,
8372
+ group.name,
8373
+ group.action,
8374
+ group.ipacl_target_count,
8375
+ String(group.loadbalancers.length)
8376
+ ]),
8377
+ raw: groups,
8378
+ ids: groups.map((group) => group.id)
8379
+ });
8380
+ });
8381
+ var getCommand9 = new import_commander51.Command("get").description("IP ACL \uADF8\uB8F9\uC744 \uC774\uB984 \uB610\uB294 UUID\uB85C \uC870\uD68C\uD55C\uB2E4").argument("<group>", "IP ACL \uADF8\uB8F9 \uC774\uB984 \uB610\uB294 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 (groupInput, _opts, cmd) => {
8382
+ const opts = cmd.optsWithGlobals();
8383
+ const input = requireResourceInput(groupInput, "IP ACL \uADF8\uB8F9");
8384
+ const { client } = await resolveLoadBalancerClient(opts);
8385
+ startSpinner("IP ACL \uADF8\uB8F9 \uC870\uD68C \uC911...");
8386
+ let group;
8387
+ let success = false;
8388
+ try {
8389
+ const id = await resolveIpAclGroupId(client, input);
8390
+ group = await client.getIpAclGroup(id);
8391
+ success = true;
8392
+ } catch (error) {
8393
+ stopSpinner(false);
8394
+ throw error;
8395
+ } finally {
8396
+ if (success) stopSpinner(true);
8397
+ }
8398
+ output(opts, {
8399
+ headers: ["field", "value"],
8400
+ rows: [
8401
+ ["id", group.id],
8402
+ ["name", group.name],
8403
+ ["action", group.action],
8404
+ ["ipacl_target_count", group.ipacl_target_count],
8405
+ [
8406
+ "loadbalancer_ids",
8407
+ group.loadbalancers.map((loadBalancer) => loadBalancer.loadbalancer_id).join(", ")
8408
+ ]
8409
+ ],
8410
+ raw: group,
8411
+ ids: [group.id]
8412
+ });
8413
+ });
8414
+ var createCommand8 = new import_commander51.Command("create").description("IP ACL \uADF8\uB8F9\uC744 \uC0DD\uC131\uD55C\uB2E4").requiredOption("--name <name>", "IP ACL \uADF8\uB8F9 \uC774\uB984").requiredOption("--action <ALLOW|DENY>", "IP \uC811\uADFC \uC81C\uC5B4 \uB3D9\uC791").option("--description <text>", "IP ACL \uADF8\uB8F9 \uC124\uBA85").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) => {
8415
+ const opts = cmd.optsWithGlobals();
8416
+ const parsedName = requireResourceInput(opts.name ?? "", "IP ACL \uADF8\uB8F9");
8417
+ const parsedAction = parseIpAclAction(opts.action ?? "");
8418
+ const parsedDescription = optionalTrimmed(opts.description);
8419
+ const { client } = await resolveLoadBalancerClient(opts);
8420
+ startSpinner("IP ACL \uADF8\uB8F9 \uC0DD\uC131 \uC911...");
8421
+ let group;
8422
+ try {
8423
+ group = await client.createIpAclGroup({
8424
+ name: parsedName,
8425
+ action: parsedAction,
8426
+ ...parsedDescription === void 0 ? {} : { description: parsedDescription }
8427
+ });
8428
+ } catch (error) {
8429
+ stopSpinner(false);
8430
+ throw error;
8431
+ }
8432
+ stopSpinner(true);
8433
+ const result = {
8434
+ operation: "ipacl-group-create",
8435
+ status: "succeeded",
8436
+ ipacl_group_id: group.id
8437
+ };
8438
+ output(opts, {
8439
+ headers: ["field", "value"],
8440
+ rows: Object.entries(result).map(([key, value]) => [key, value]),
8441
+ raw: result,
8442
+ ids: [group.id]
8443
+ });
8444
+ });
8445
+ var deleteCommand7 = new import_commander51.Command("delete").description("IP ACL \uADF8\uB8F9\uACFC \uD558\uC704 \uB300\uC0C1\uC744 \uC0AD\uC81C\uD55C\uB2E4").argument("<group>", "IP ACL \uADF8\uB8F9 \uC774\uB984 \uB610\uB294 UUID").option("--yes", "\uC0AD\uC81C\uC640 \uC5F0\uACB0 \uADDC\uCE59 \uC81C\uAC70 \uD655\uC778").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 (groupInput, _opts, cmd) => {
8446
+ const opts = cmd.optsWithGlobals();
8447
+ const confirmedYes = requireYes(opts.yes, "IP ACL \uADF8\uB8F9 \uC0AD\uC81C");
8448
+ const parsedGroup = requireResourceInput(groupInput, "IP ACL \uADF8\uB8F9");
8449
+ if (confirmedYes) {
8450
+ process.stderr.write(
8451
+ "\uACBD\uACE0: \uADF8\uB8F9\uC758 \uBAA8\uB4E0 \uB300\uC0C1\uACFC Load Balancer \uC5F0\uACB0 \uADDC\uCE59\uC774 \uD568\uAED8 \uC81C\uAC70\uB429\uB2C8\uB2E4.\n"
8452
+ );
8453
+ }
8454
+ const { client } = await resolveLoadBalancerClient(opts);
8455
+ startSpinner("IP ACL \uADF8\uB8F9 \uC0AD\uC81C \uC911...");
8456
+ let groupId;
8457
+ try {
8458
+ groupId = await resolveIpAclGroupId(client, parsedGroup);
8459
+ await client.deleteIpAclGroup(groupId);
8460
+ } catch (error) {
8461
+ stopSpinner(false);
8462
+ throw error;
8463
+ }
8464
+ stopSpinner(true);
8465
+ const result = {
8466
+ operation: "ipacl-group-delete",
8467
+ status: "succeeded",
8468
+ ipacl_group_id: groupId
8469
+ };
8470
+ output(opts, {
8471
+ headers: ["field", "value"],
8472
+ rows: Object.entries(result).map(([key, value]) => [key, value]),
8473
+ raw: result,
8474
+ ids: [groupId]
8475
+ });
8476
+ });
8477
+ var ipaclCommand = new import_commander51.Command("ipacl").description("IP ACL \uADF8\uB8F9\xB7\uB300\uC0C1 \uC870\uD68C");
8478
+ ipaclCommand.addCommand(listCommand12);
8479
+ ipaclCommand.addCommand(getCommand9);
8480
+ ipaclCommand.addCommand(createCommand8);
8481
+ ipaclCommand.addCommand(deleteCommand7);
8482
+ ipaclCommand.addCommand(targetCommand);
8483
+
8484
+ // src/commands/loadbalancer/help.ts
8485
+ function configureLoadBalancerHelp(command) {
8486
+ command.configureHelp({ showGlobalOptions: true });
8487
+ for (const child of command.commands) {
8488
+ configureLoadBalancerHelp(child);
8489
+ }
8490
+ }
8491
+
8492
+ // src/commands/loadbalancer/binding.ts
8493
+ var import_commander52 = require("commander");
8494
+ function bindingResult(operation, loadBalancerId, groupIds) {
8495
+ return {
8496
+ operation,
8497
+ status: "succeeded",
8498
+ loadbalancer_id: loadBalancerId,
8499
+ ipacl_group_ids: groupIds
8500
+ };
8501
+ }
8502
+ function outputBindingResult(opts, result) {
8503
+ output(opts, {
8504
+ headers: ["field", "value"],
8505
+ rows: [
8506
+ ["operation", result.operation],
8507
+ ["status", result.status],
8508
+ ["loadbalancer_id", result.loadbalancer_id],
8509
+ ["ipacl_group_ids", result.ipacl_group_ids.join(", ")]
8510
+ ],
8511
+ raw: result,
8512
+ ids: [result.loadbalancer_id]
8513
+ });
8514
+ }
8515
+ var setIpAclCommand2 = new import_commander52.Command("set-ipacl").description("Load Balancer\uC758 IP ACL \uADF8\uB8F9 \uC5F0\uACB0\uC744 \uC804\uCCB4 \uAD50\uCCB4\uD55C\uB2E4").argument("<loadbalancer>", "Load Balancer \uC774\uB984 \uB610\uB294 UUID").requiredOption(
8516
+ "--group <group>",
8517
+ "\uC801\uC6A9\uD560 IP ACL \uADF8\uB8F9 \uC774\uB984 \uB610\uB294 UUID (\uBC18\uBCF5 \uAC00\uB2A5)",
8518
+ collectOption
8519
+ ).option("--yes", "\uAE30\uC874 \uC5F0\uACB0 \uC804\uCCB4 \uAD50\uCCB4 \uD655\uC778").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 (loadBalancerInput, _opts, cmd) => {
8520
+ const opts = cmd.optsWithGlobals();
8521
+ const confirmedYes = requireYes(opts.yes, "Load Balancer IP ACL \uC5F0\uACB0 \uAD50\uCCB4");
8522
+ const parsedLoadBalancer = requireResourceInput(loadBalancerInput, "Load Balancer");
8523
+ const parsedGroups = requireResourceInputs(opts.group ?? [], "IP ACL \uADF8\uB8F9");
8524
+ const { client } = await resolveLoadBalancerClient(opts);
8525
+ startSpinner("Load Balancer IP ACL \uC5F0\uACB0 \uAD50\uCCB4 \uC911...");
8526
+ let loadBalancerId;
8527
+ let groupIds;
8528
+ try {
8529
+ loadBalancerId = await resolveLoadBalancerId(client, parsedLoadBalancer);
8530
+ const groups = await resolveIpAclGroups(client, parsedGroups);
8531
+ groupIds = groups.map((group) => group.id);
8532
+ if (new Set(groupIds).size !== groupIds.length) {
8533
+ throw new NhnCloudCliError(
8534
+ "\uAC19\uC740 IP ACL \uADF8\uB8F9\uC744 \uC911\uBCF5 \uC9C0\uC815\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
8535
+ EXIT_PARAM_ERROR
8536
+ );
8537
+ }
8538
+ if (new Set(groups.map((group) => group.action)).size > 1) {
8539
+ throw new NhnCloudCliError(
8540
+ "\uD568\uAED8 \uC801\uC6A9\uD560 IP ACL \uADF8\uB8F9\uC758 action\uC740 \uBAA8\uB450 \uAC19\uC544\uC57C \uD569\uB2C8\uB2E4.",
8541
+ EXIT_PARAM_ERROR
8542
+ );
8543
+ }
8544
+ if (confirmedYes) await client.bindIpAclGroups(loadBalancerId, groupIds);
8545
+ } catch (error) {
8546
+ stopSpinner(false);
8547
+ throw error;
8548
+ }
8549
+ stopSpinner(true);
8550
+ outputBindingResult(
8551
+ opts,
8552
+ bindingResult("loadbalancer-set-ipacl", loadBalancerId, groupIds)
8553
+ );
8554
+ });
8555
+ var clearIpAclCommand = new import_commander52.Command("clear-ipacl").description("Load Balancer\uC758 \uBAA8\uB4E0 IP ACL \uADF8\uB8F9 \uC5F0\uACB0\uC744 \uD574\uC81C\uD55C\uB2E4").argument("<loadbalancer>", "Load Balancer \uC774\uB984 \uB610\uB294 UUID").option("--yes", "\uBAA8\uB4E0 IP ACL \uC5F0\uACB0 \uD574\uC81C \uD655\uC778").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 (loadBalancerInput, _opts, cmd) => {
8556
+ const opts = cmd.optsWithGlobals();
8557
+ const confirmedYes = requireYes(opts.yes, "Load Balancer IP ACL \uC5F0\uACB0 \uD574\uC81C");
8558
+ const parsedLoadBalancer = requireResourceInput(loadBalancerInput, "Load Balancer");
8559
+ const { client } = await resolveLoadBalancerClient(opts);
8560
+ startSpinner("Load Balancer IP ACL \uC5F0\uACB0 \uD574\uC81C \uC911...");
8561
+ let loadBalancerId;
8562
+ try {
8563
+ loadBalancerId = await resolveLoadBalancerId(client, parsedLoadBalancer);
8564
+ if (confirmedYes) await client.bindIpAclGroups(loadBalancerId, []);
8565
+ } catch (error) {
8566
+ stopSpinner(false);
8567
+ throw error;
8568
+ }
8569
+ stopSpinner(true);
8570
+ outputBindingResult(
8571
+ opts,
8572
+ bindingResult("loadbalancer-clear-ipacl", loadBalancerId, [])
8573
+ );
8574
+ });
8575
+
7554
8576
  // src/index.ts
7555
8577
  var rootAgentHints = `
7556
8578
  Agent hints:
@@ -7592,6 +8614,14 @@ Agent workflow:
7592
8614
  1. nhncloud floatingip list --json
7593
8615
  2. nhncloud floatingip create --json
7594
8616
  `;
8617
+ var loadbalancerAgentWorkflow = `
8618
+ Agent workflow:
8619
+ 1. nhncloud loadbalancer list --json
8620
+ 2. nhncloud loadbalancer ipacl list --json
8621
+ 3. nhncloud loadbalancer ipacl target list <group> --json
8622
+ 4. \uC4F0\uAE30 \uC804\uC5D0\uB294 --profile, --region, --yes, --json\uC744 \uBA85\uC2DC\uD55C\uB2E4.
8623
+ 5. \uB300\uC0C1 \uBCC0\uACBD\uC740 \uAE30\uBCF8\uC73C\uB85C \uC7AC\uBC14\uC778\uB529\uD55C\uB2E4. exit code 1\uC774\uBA74 rebind.failed[].retry_argv\uB97C \uC77D\uB294\uB2E4.
8624
+ `;
7595
8625
  var ncrAgentWorkflow = `
7596
8626
  Agent workflow:
7597
8627
  1. nhncloud ncr list --json
@@ -7610,8 +8640,8 @@ Agent workflow:
7610
8640
  2. nhncloud ncs workload list --json
7611
8641
  3. nhncloud ncs workload get <id> --json
7612
8642
  `;
7613
- var program = new import_commander48.Command();
7614
- program.name("nhncloud").description("NHN Cloud CLI \u2014 AI agent & terminal friendly").version("0.10.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").addHelpText("after", rootAgentHints);
8643
+ var program = new import_commander53.Command();
8644
+ program.name("nhncloud").description("NHN Cloud CLI \u2014 AI agent & terminal friendly").version("0.11.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);
7615
8645
  program.hook("preAction", () => {
7616
8646
  const opts = program.opts();
7617
8647
  if (!opts.color || process.env["NO_COLOR"]) {
@@ -7622,12 +8652,12 @@ program.hook("preAction", () => {
7622
8652
  }
7623
8653
  });
7624
8654
  program.addCommand(configureCommand);
7625
- var logncrashCommand = new import_commander48.Command("logncrash").description("Log & Crash \uAD00\uB828 \uBA85\uB839").addHelpText("after", logncrashAgentWorkflow);
8655
+ var logncrashCommand = new import_commander53.Command("logncrash").description("Log & Crash \uAD00\uB828 \uBA85\uB839").addHelpText("after", logncrashAgentWorkflow);
7626
8656
  logncrashCommand.addCommand(searchCommand);
7627
8657
  logncrashCommand.addCommand(sendCommand);
7628
8658
  logncrashCommand.addCommand(exportCommand);
7629
8659
  program.addCommand(logncrashCommand);
7630
- var deployCommand = new import_commander48.Command("deploy").description("NHN Cloud Deploy \uAD00\uB828 \uBA85\uB839").addHelpText("after", deployAgentWorkflow);
8660
+ var deployCommand = new import_commander53.Command("deploy").description("NHN Cloud Deploy \uAD00\uB828 \uBA85\uB839").addHelpText("after", deployAgentWorkflow);
7631
8661
  deployCommand.addCommand(runCommand);
7632
8662
  deployCommand.addCommand(artifactsCommand);
7633
8663
  deployCommand.addCommand(serverGroupsCommand);
@@ -7637,7 +8667,7 @@ deployCommand.addCommand(binariesCommand);
7637
8667
  deployCommand.addCommand(uploadCommand);
7638
8668
  deployCommand.addCommand(downloadCommand);
7639
8669
  program.addCommand(deployCommand);
7640
- var instanceCommand = new import_commander48.Command("instance").description("Compute \uC778\uC2A4\uD134\uC2A4 \uAD00\uB828 \uBA85\uB839").addHelpText("after", instanceAgentWorkflow);
8670
+ var instanceCommand = new import_commander53.Command("instance").description("Compute \uC778\uC2A4\uD134\uC2A4 \uAD00\uB828 \uBA85\uB839").addHelpText("after", instanceAgentWorkflow);
7641
8671
  instanceCommand.addCommand(listCommand);
7642
8672
  instanceCommand.addCommand(flavorsCommand);
7643
8673
  instanceCommand.addCommand(availabilityZonesCommand);
@@ -7656,36 +8686,44 @@ instanceCommand.addCommand(keypairCommand);
7656
8686
  instanceCommand.addCommand(volumeCommand);
7657
8687
  instanceCommand.addCommand(volumesCommand);
7658
8688
  program.addCommand(instanceCommand);
7659
- var networkCommand = new import_commander48.Command("network").description("VPC\xB7\uC11C\uBE0C\uB137 \uC870\uD68C").addHelpText("after", networkAgentWorkflow);
8689
+ var networkCommand = new import_commander53.Command("network").description("VPC\xB7\uC11C\uBE0C\uB137 \uC870\uD68C").addHelpText("after", networkAgentWorkflow);
7660
8690
  networkCommand.addCommand(listCommand3);
7661
8691
  networkCommand.addCommand(subnetCommand);
7662
8692
  program.addCommand(networkCommand);
7663
- var volumeCommand2 = new import_commander48.Command("volume").description("Block Storage \uBCFC\uB968 \uAD00\uB828 \uBA85\uB839").addHelpText("after", volumeAgentWorkflow);
8693
+ var volumeCommand2 = new import_commander53.Command("volume").description("Block Storage \uBCFC\uB968 \uAD00\uB828 \uBA85\uB839").addHelpText("after", volumeAgentWorkflow);
7664
8694
  volumeCommand2.addCommand(listCommand2);
7665
8695
  volumeCommand2.addCommand(getCommand);
7666
8696
  volumeCommand2.addCommand(createCommand);
7667
8697
  program.addCommand(volumeCommand2);
7668
- var floatingipCommand = new import_commander48.Command("floatingip").description(
8698
+ var floatingipCommand = new import_commander53.Command("floatingip").description(
7669
8699
  "Floating IP(\uC778\uC2A4\uD134\uC2A4 \uACF5\uC778 IP) \uAD00\uB9AC"
7670
8700
  ).addHelpText("after", floatingIpAgentWorkflow);
7671
8701
  floatingipCommand.addCommand(listCommand4);
7672
8702
  floatingipCommand.addCommand(createCommand2);
7673
8703
  floatingipCommand.addCommand(deleteCommand);
7674
8704
  program.addCommand(floatingipCommand);
7675
- var ncrCommand = new import_commander48.Command("ncr").description("NHN Container Registry \uAD00\uB828 \uBA85\uB839").addHelpText("after", ncrAgentWorkflow);
8705
+ var loadbalancerCommand = new import_commander53.Command("loadbalancer").description("Load Balancer\xB7IP ACL \uC870\uD68C\xB7\uAD00\uB9AC").addHelpText("after", loadbalancerAgentWorkflow);
8706
+ loadbalancerCommand.addCommand(listCommand10);
8707
+ loadbalancerCommand.addCommand(getCommand8);
8708
+ loadbalancerCommand.addCommand(ipaclCommand);
8709
+ loadbalancerCommand.addCommand(setIpAclCommand2);
8710
+ loadbalancerCommand.addCommand(clearIpAclCommand);
8711
+ configureLoadBalancerHelp(loadbalancerCommand);
8712
+ program.addCommand(loadbalancerCommand);
8713
+ var ncrCommand = new import_commander53.Command("ncr").description("NHN Container Registry \uAD00\uB828 \uBA85\uB839").addHelpText("after", ncrAgentWorkflow);
7676
8714
  ncrCommand.addCommand(listCommand5);
7677
8715
  ncrCommand.addCommand(getCommand3);
7678
8716
  ncrCommand.addCommand(imagesCommand2);
7679
8717
  ncrCommand.addCommand(tagsCommand);
7680
8718
  program.addCommand(ncrCommand);
7681
- var nksCommand = new import_commander48.Command("nks").description("NHN Kubernetes Service \uAD00\uB828 \uBA85\uB839").addHelpText("after", nksAgentWorkflow);
8719
+ var nksCommand = new import_commander53.Command("nks").description("NHN Kubernetes Service \uAD00\uB828 \uBA85\uB839").addHelpText("after", nksAgentWorkflow);
7682
8720
  nksCommand.addCommand(supportsCommand);
7683
8721
  nksCommand.addCommand(clusterCommand);
7684
8722
  nksCommand.addCommand(nodegroupCommand);
7685
8723
  nksCommand.addCommand(addonTypeCommand);
7686
8724
  nksCommand.addCommand(addonCommand);
7687
8725
  program.addCommand(nksCommand);
7688
- var ncsCommand = new import_commander48.Command("ncs").description("NHN Container Service \uAD00\uB828 \uBA85\uB839").addHelpText("after", ncsAgentWorkflow);
8726
+ var ncsCommand = new import_commander53.Command("ncs").description("NHN Container Service \uAD00\uB828 \uBA85\uB839").addHelpText("after", ncsAgentWorkflow);
7689
8727
  ncsCommand.addCommand(templateCommand);
7690
8728
  ncsCommand.addCommand(workloadCommand);
7691
8729
  ncsCommand.addCommand(malwareCommand);