@bifos/nhncloud-cli 0.10.0 → 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/README.md +142 -4
- package/dist/index.js +1094 -37
- package/package.json +1 -1
- package/skills/nhncloud-cli/SKILL.md +21 -5
- package/skills/nhncloud-cli/references/loadbalancer.md +237 -0
- package/skills/nhncloud-cli/references/ncs.md +43 -1
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
|
|
27
|
+
var import_commander53 = require("commander");
|
|
28
28
|
var import_chalk18 = __toESM(require("chalk"));
|
|
29
29
|
|
|
30
30
|
// src/utils/spinner.ts
|
|
@@ -315,15 +315,18 @@ var import_node_path2 = require("path");
|
|
|
315
315
|
var import_node_os2 = require("os");
|
|
316
316
|
var import_node_crypto = require("crypto");
|
|
317
317
|
var CACHE_DIR = (0, import_node_path2.join)((0, import_node_os2.homedir)(), ".nhncloud", "cache");
|
|
318
|
+
function credentialFingerprint(material) {
|
|
319
|
+
return (0, import_node_crypto.createHash)("sha256").update(material).digest("hex");
|
|
320
|
+
}
|
|
318
321
|
function iaasCachePath(profile, region) {
|
|
319
322
|
return (0, import_node_path2.join)(CACHE_DIR, `iaas-token-${profile}-${region}.json`);
|
|
320
323
|
}
|
|
321
324
|
function isIaasTokenCache(val) {
|
|
322
325
|
if (typeof val !== "object" || val === null) return false;
|
|
323
326
|
const obj = val;
|
|
324
|
-
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";
|
|
327
|
+
return typeof obj["tokenId"] === "string" && typeof obj["expiresAt"] === "string" && typeof obj["credentialHash"] === "string" && typeof obj["computeEndpoint"] === "string" && typeof obj["imageEndpoint"] === "string" && typeof obj["networkEndpoint"] === "string" && typeof obj["blockStorageEndpoint"] === "string" && typeof obj["nksEndpoint"] === "string";
|
|
325
328
|
}
|
|
326
|
-
async function readIaasToken(profile, region) {
|
|
329
|
+
async function readIaasToken(profile, region, credentialHash) {
|
|
327
330
|
const filePath = iaasCachePath(profile, region);
|
|
328
331
|
try {
|
|
329
332
|
const raw = await (0, import_promises2.readFile)(filePath, "utf-8");
|
|
@@ -332,6 +335,7 @@ async function readIaasToken(profile, region) {
|
|
|
332
335
|
const expiresAt = new Date(parsed.expiresAt).getTime();
|
|
333
336
|
const BUFFER_MS = 6e4;
|
|
334
337
|
if (expiresAt - Date.now() < BUFFER_MS) return null;
|
|
338
|
+
if (parsed.credentialHash !== credentialHash) return null;
|
|
335
339
|
return {
|
|
336
340
|
tokenId: parsed.tokenId,
|
|
337
341
|
expiresAt: parsed.expiresAt,
|
|
@@ -351,6 +355,7 @@ async function writeIaasToken(profile, region, data) {
|
|
|
351
355
|
const cache = {
|
|
352
356
|
tokenId: data.tokenId,
|
|
353
357
|
expiresAt: data.expiresAt,
|
|
358
|
+
credentialHash: data.credentialHash,
|
|
354
359
|
computeEndpoint: data.computeEndpoint,
|
|
355
360
|
imageEndpoint: data.imageEndpoint,
|
|
356
361
|
networkEndpoint: data.networkEndpoint,
|
|
@@ -362,14 +367,14 @@ async function writeIaasToken(profile, region, data) {
|
|
|
362
367
|
await (0, import_promises2.rename)(tmp, filePath);
|
|
363
368
|
}
|
|
364
369
|
function tokenCachePath(profile) {
|
|
365
|
-
return (0, import_node_path2.join)(CACHE_DIR, `
|
|
370
|
+
return (0, import_node_path2.join)(CACHE_DIR, `user-access-token-${profile}.json`);
|
|
366
371
|
}
|
|
367
372
|
function isTokenCache(val) {
|
|
368
373
|
if (typeof val !== "object" || val === null) return false;
|
|
369
374
|
const obj = val;
|
|
370
|
-
return typeof obj["accessToken"] === "string" && typeof obj["expiresAt"] === "string";
|
|
375
|
+
return typeof obj["accessToken"] === "string" && typeof obj["expiresAt"] === "string" && typeof obj["credentialHash"] === "string";
|
|
371
376
|
}
|
|
372
|
-
async function readToken(profile) {
|
|
377
|
+
async function readToken(profile, credentialHash) {
|
|
373
378
|
const filePath = tokenCachePath(profile);
|
|
374
379
|
try {
|
|
375
380
|
const raw = await (0, import_promises2.readFile)(filePath, "utf-8");
|
|
@@ -379,17 +384,19 @@ async function readToken(profile) {
|
|
|
379
384
|
const now = Date.now();
|
|
380
385
|
const BUFFER_MS = 6e4;
|
|
381
386
|
if (expiresAt - now < BUFFER_MS) return null;
|
|
387
|
+
if (parsed.credentialHash !== credentialHash) return null;
|
|
382
388
|
return { accessToken: parsed.accessToken, expiresAt: parsed.expiresAt };
|
|
383
389
|
} catch {
|
|
384
390
|
return null;
|
|
385
391
|
}
|
|
386
392
|
}
|
|
387
|
-
async function writeToken(profile, accessToken, expiresAt) {
|
|
393
|
+
async function writeToken(profile, accessToken, expiresAt, credentialHash) {
|
|
388
394
|
const filePath = tokenCachePath(profile);
|
|
389
395
|
await (0, import_promises2.mkdir)((0, import_node_path2.dirname)(filePath), { recursive: true });
|
|
390
396
|
const data = {
|
|
391
397
|
accessToken,
|
|
392
|
-
expiresAt: expiresAt.toISOString()
|
|
398
|
+
expiresAt: expiresAt.toISOString(),
|
|
399
|
+
credentialHash
|
|
393
400
|
};
|
|
394
401
|
const tmp = filePath + "." + (0, import_node_crypto.randomBytes)(4).toString("hex") + ".tmp";
|
|
395
402
|
await (0, import_promises2.writeFile)(tmp, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
|
|
@@ -424,8 +431,9 @@ function isTokenResponse(val) {
|
|
|
424
431
|
return typeof obj["access_token"] === "string" && typeof obj["expires_in"] === "number";
|
|
425
432
|
}
|
|
426
433
|
async function getAccessToken(profile, uakId, uakSecret, forceRefresh = false) {
|
|
434
|
+
const credentialHash = credentialFingerprint(JSON.stringify([uakId, uakSecret]));
|
|
427
435
|
if (!forceRefresh) {
|
|
428
|
-
const cached = await readToken(profile);
|
|
436
|
+
const cached = await readToken(profile, credentialHash);
|
|
429
437
|
if (cached !== null) {
|
|
430
438
|
return cached.accessToken;
|
|
431
439
|
}
|
|
@@ -449,7 +457,7 @@ async function getAccessToken(profile, uakId, uakSecret, forceRefresh = false) {
|
|
|
449
457
|
}
|
|
450
458
|
if (!forceRefresh) {
|
|
451
459
|
const expiresAt = new Date(Date.now() + raw.expires_in * 1e3);
|
|
452
|
-
await writeToken(profile, raw.access_token, expiresAt);
|
|
460
|
+
await writeToken(profile, raw.access_token, expiresAt, credentialHash);
|
|
453
461
|
}
|
|
454
462
|
return raw.access_token;
|
|
455
463
|
}
|
|
@@ -597,8 +605,11 @@ function isKeystoneTokenResponse(val) {
|
|
|
597
605
|
return typeof token["id"] === "string" && typeof token["expires"] === "string";
|
|
598
606
|
}
|
|
599
607
|
async function getIaasToken(profile, iaas, forceRefresh = false) {
|
|
608
|
+
const credentialHash = credentialFingerprint(
|
|
609
|
+
JSON.stringify([iaas.tenantId, iaas.username, iaas.password])
|
|
610
|
+
);
|
|
600
611
|
if (!forceRefresh) {
|
|
601
|
-
const cached = await readIaasToken(profile, iaas.region);
|
|
612
|
+
const cached = await readIaasToken(profile, iaas.region, credentialHash);
|
|
602
613
|
if (cached !== null) {
|
|
603
614
|
return {
|
|
604
615
|
tokenId: cached.tokenId,
|
|
@@ -642,7 +653,7 @@ async function getIaasToken(profile, iaas, forceRefresh = false) {
|
|
|
642
653
|
const tokenId = raw.access.token.id;
|
|
643
654
|
const expiresAt = raw.access.token.expires;
|
|
644
655
|
if (!forceRefresh) {
|
|
645
|
-
await writeIaasToken(profile, iaas.region, { tokenId, expiresAt, computeEndpoint, imageEndpoint, networkEndpoint, blockStorageEndpoint, nksEndpoint });
|
|
656
|
+
await writeIaasToken(profile, iaas.region, { tokenId, expiresAt, credentialHash, computeEndpoint, imageEndpoint, networkEndpoint, blockStorageEndpoint, nksEndpoint });
|
|
646
657
|
}
|
|
647
658
|
return { tokenId, computeEndpoint, imageEndpoint, networkEndpoint, blockStorageEndpoint, nksEndpoint };
|
|
648
659
|
}
|
|
@@ -3887,11 +3898,6 @@ function isVolume(val) {
|
|
|
3887
3898
|
return typeof obj["id"] === "string" && // Cinder 는 --name 미지정 시 null — null 인 볼륨 하나가 list 전체를 거부하지 않게 허용 (isImage 선례).
|
|
3888
3899
|
(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"]);
|
|
3889
3900
|
}
|
|
3890
|
-
function isVolumesResponse(val) {
|
|
3891
|
-
if (typeof val !== "object" || val === null) return false;
|
|
3892
|
-
const obj = val;
|
|
3893
|
-
return Array.isArray(obj["volumes"]) && obj["volumes"].every(isVolume);
|
|
3894
|
-
}
|
|
3895
3901
|
function isVolumeResponse(val) {
|
|
3896
3902
|
if (typeof val !== "object" || val === null) return false;
|
|
3897
3903
|
const obj = val;
|
|
@@ -3909,7 +3915,7 @@ var BlockStorageClient = class {
|
|
|
3909
3915
|
return { "X-Auth-Token": this.tokenId };
|
|
3910
3916
|
}
|
|
3911
3917
|
async list(params) {
|
|
3912
|
-
const url = `${this.endpoint}/volumes`;
|
|
3918
|
+
const url = `${this.endpoint}/volumes/detail`;
|
|
3913
3919
|
const searchParams = {};
|
|
3914
3920
|
if (params?.sort !== void 0) searchParams["sort"] = params.sort;
|
|
3915
3921
|
if (params?.limit !== void 0) searchParams["limit"] = params.limit;
|
|
@@ -3917,13 +3923,26 @@ var BlockStorageClient = class {
|
|
|
3917
3923
|
if (params?.marker !== void 0) searchParams["marker"] = params.marker;
|
|
3918
3924
|
try {
|
|
3919
3925
|
const raw = await import_ky9.default.get(url, { headers: this.authHeaders(), searchParams, retry: 0, timeout: DEFAULT_TIMEOUT_MS5 }).json();
|
|
3920
|
-
if (
|
|
3926
|
+
if (typeof raw !== "object" || raw === null) {
|
|
3927
|
+
throw new NhnCloudCliError(
|
|
3928
|
+
"volume list \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 volumes \uBC30\uC5F4\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
3929
|
+
EXIT_API_ERROR
|
|
3930
|
+
);
|
|
3931
|
+
}
|
|
3932
|
+
const obj = raw;
|
|
3933
|
+
if (!Array.isArray(obj["volumes"])) {
|
|
3921
3934
|
throw new NhnCloudCliError(
|
|
3922
3935
|
"volume list \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 volumes \uBC30\uC5F4\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
3923
3936
|
EXIT_API_ERROR
|
|
3924
3937
|
);
|
|
3925
3938
|
}
|
|
3926
|
-
|
|
3939
|
+
if (!obj["volumes"].every(isVolume)) {
|
|
3940
|
+
throw new NhnCloudCliError(
|
|
3941
|
+
"volume list \uC751\uB2F5\uC758 \uBCFC\uB968 \uD56D\uBAA9 \uD615\uC2DD\uC774 \uC608\uC0C1\uACFC \uB2E4\uB985\uB2C8\uB2E4 \u2014 API \uC751\uB2F5 \uD544\uB4DC\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
3942
|
+
EXIT_API_ERROR
|
|
3943
|
+
);
|
|
3944
|
+
}
|
|
3945
|
+
return obj["volumes"];
|
|
3927
3946
|
} catch (err) {
|
|
3928
3947
|
throw toNhnCloudCliError(err);
|
|
3929
3948
|
}
|
|
@@ -6775,6 +6794,102 @@ var import_chalk16 = __toESM(require("chalk"));
|
|
|
6775
6794
|
// src/commands/ncs/helpers.ts
|
|
6776
6795
|
var import_node_fs7 = require("fs");
|
|
6777
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
|
+
}
|
|
6778
6893
|
async function resolveNcsAppKey(profileName, appKeyOpt) {
|
|
6779
6894
|
if (appKeyOpt) return appKeyOpt;
|
|
6780
6895
|
let cred;
|
|
@@ -7143,7 +7258,13 @@ var getCommand7 = new import_commander46.Command("get").description("NCS workloa
|
|
|
7143
7258
|
ids: [workload.id]
|
|
7144
7259
|
});
|
|
7145
7260
|
});
|
|
7146
|
-
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(
|
|
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) => {
|
|
7147
7268
|
const opts = cmd.optsWithGlobals();
|
|
7148
7269
|
requireNonEmpty(id, "id");
|
|
7149
7270
|
if (!opts.task || !opts.task.trim()) {
|
|
@@ -7158,14 +7279,14 @@ var logsCommand = new import_commander46.Command("logs").description("NCS worklo
|
|
|
7158
7279
|
EXIT_PARAM_ERROR
|
|
7159
7280
|
);
|
|
7160
7281
|
}
|
|
7282
|
+
const timeRange = normalizeNcsTimeRange(opts.from, opts.to);
|
|
7161
7283
|
const { client } = await resolveNcsClient(opts);
|
|
7162
7284
|
startSpinner(`NCS workload "${id}" task "${opts.task}" \uB85C\uADF8 \uC870\uD68C \uC911...`);
|
|
7163
7285
|
let logs;
|
|
7164
7286
|
try {
|
|
7165
7287
|
const result = await client.getWorkloadLogs(id, opts.task, {
|
|
7166
7288
|
container: opts.container,
|
|
7167
|
-
|
|
7168
|
-
to: opts.to,
|
|
7289
|
+
...timeRange,
|
|
7169
7290
|
page: parsePositiveIntegerOption(opts.page, "--page"),
|
|
7170
7291
|
size: parsePositiveIntegerOption(opts.size, "--size")
|
|
7171
7292
|
});
|
|
@@ -7182,7 +7303,13 @@ var logsCommand = new import_commander46.Command("logs").description("NCS worklo
|
|
|
7182
7303
|
ids: []
|
|
7183
7304
|
});
|
|
7184
7305
|
});
|
|
7185
|
-
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(
|
|
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) => {
|
|
7186
7313
|
const opts = cmd.optsWithGlobals();
|
|
7187
7314
|
requireNonEmpty(id, "id");
|
|
7188
7315
|
if (!opts.task || !opts.task.trim()) {
|
|
@@ -7191,6 +7318,7 @@ var eventsCommand2 = new import_commander46.Command("events").description("NCS w
|
|
|
7191
7318
|
EXIT_PARAM_ERROR
|
|
7192
7319
|
);
|
|
7193
7320
|
}
|
|
7321
|
+
const timeRange = normalizeNcsTimeRange(opts.from, opts.to);
|
|
7194
7322
|
const { client } = await resolveNcsClient(opts);
|
|
7195
7323
|
startSpinner(`NCS workload "${id}" task "${opts.task}" \uC774\uBCA4\uD2B8 \uC870\uD68C \uC911...`);
|
|
7196
7324
|
let totalCount;
|
|
@@ -7199,8 +7327,7 @@ var eventsCommand2 = new import_commander46.Command("events").description("NCS w
|
|
|
7199
7327
|
const result = await client.getWorkloadEvents(id, opts.task, {
|
|
7200
7328
|
type: opts.type,
|
|
7201
7329
|
q: opts.q,
|
|
7202
|
-
|
|
7203
|
-
to: opts.to,
|
|
7330
|
+
...timeRange,
|
|
7204
7331
|
page: parsePositiveIntegerOption(opts.page, "--page"),
|
|
7205
7332
|
size: parsePositiveIntegerOption(opts.size, "--size")
|
|
7206
7333
|
});
|
|
@@ -7532,6 +7659,920 @@ var resultCommand = new import_commander47.Command("result").description("NCS wo
|
|
|
7532
7659
|
});
|
|
7533
7660
|
var malwareCommand = new import_commander47.Command("malware").description("NCS \uC545\uC131\uCF54\uB4DC \uAC80\uC0AC \uAD00\uB9AC").addCommand(configCommand).addCommand(resultCommand);
|
|
7534
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
|
+
|
|
7535
8576
|
// src/index.ts
|
|
7536
8577
|
var rootAgentHints = `
|
|
7537
8578
|
Agent hints:
|
|
@@ -7573,6 +8614,14 @@ Agent workflow:
|
|
|
7573
8614
|
1. nhncloud floatingip list --json
|
|
7574
8615
|
2. nhncloud floatingip create --json
|
|
7575
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
|
+
`;
|
|
7576
8625
|
var ncrAgentWorkflow = `
|
|
7577
8626
|
Agent workflow:
|
|
7578
8627
|
1. nhncloud ncr list --json
|
|
@@ -7591,8 +8640,8 @@ Agent workflow:
|
|
|
7591
8640
|
2. nhncloud ncs workload list --json
|
|
7592
8641
|
3. nhncloud ncs workload get <id> --json
|
|
7593
8642
|
`;
|
|
7594
|
-
var program = new
|
|
7595
|
-
program.name("nhncloud").description("NHN Cloud CLI \u2014 AI agent & terminal friendly").version("0.
|
|
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);
|
|
7596
8645
|
program.hook("preAction", () => {
|
|
7597
8646
|
const opts = program.opts();
|
|
7598
8647
|
if (!opts.color || process.env["NO_COLOR"]) {
|
|
@@ -7603,12 +8652,12 @@ program.hook("preAction", () => {
|
|
|
7603
8652
|
}
|
|
7604
8653
|
});
|
|
7605
8654
|
program.addCommand(configureCommand);
|
|
7606
|
-
var logncrashCommand = new
|
|
8655
|
+
var logncrashCommand = new import_commander53.Command("logncrash").description("Log & Crash \uAD00\uB828 \uBA85\uB839").addHelpText("after", logncrashAgentWorkflow);
|
|
7607
8656
|
logncrashCommand.addCommand(searchCommand);
|
|
7608
8657
|
logncrashCommand.addCommand(sendCommand);
|
|
7609
8658
|
logncrashCommand.addCommand(exportCommand);
|
|
7610
8659
|
program.addCommand(logncrashCommand);
|
|
7611
|
-
var deployCommand = new
|
|
8660
|
+
var deployCommand = new import_commander53.Command("deploy").description("NHN Cloud Deploy \uAD00\uB828 \uBA85\uB839").addHelpText("after", deployAgentWorkflow);
|
|
7612
8661
|
deployCommand.addCommand(runCommand);
|
|
7613
8662
|
deployCommand.addCommand(artifactsCommand);
|
|
7614
8663
|
deployCommand.addCommand(serverGroupsCommand);
|
|
@@ -7618,7 +8667,7 @@ deployCommand.addCommand(binariesCommand);
|
|
|
7618
8667
|
deployCommand.addCommand(uploadCommand);
|
|
7619
8668
|
deployCommand.addCommand(downloadCommand);
|
|
7620
8669
|
program.addCommand(deployCommand);
|
|
7621
|
-
var instanceCommand = new
|
|
8670
|
+
var instanceCommand = new import_commander53.Command("instance").description("Compute \uC778\uC2A4\uD134\uC2A4 \uAD00\uB828 \uBA85\uB839").addHelpText("after", instanceAgentWorkflow);
|
|
7622
8671
|
instanceCommand.addCommand(listCommand);
|
|
7623
8672
|
instanceCommand.addCommand(flavorsCommand);
|
|
7624
8673
|
instanceCommand.addCommand(availabilityZonesCommand);
|
|
@@ -7637,36 +8686,44 @@ instanceCommand.addCommand(keypairCommand);
|
|
|
7637
8686
|
instanceCommand.addCommand(volumeCommand);
|
|
7638
8687
|
instanceCommand.addCommand(volumesCommand);
|
|
7639
8688
|
program.addCommand(instanceCommand);
|
|
7640
|
-
var networkCommand = new
|
|
8689
|
+
var networkCommand = new import_commander53.Command("network").description("VPC\xB7\uC11C\uBE0C\uB137 \uC870\uD68C").addHelpText("after", networkAgentWorkflow);
|
|
7641
8690
|
networkCommand.addCommand(listCommand3);
|
|
7642
8691
|
networkCommand.addCommand(subnetCommand);
|
|
7643
8692
|
program.addCommand(networkCommand);
|
|
7644
|
-
var volumeCommand2 = new
|
|
8693
|
+
var volumeCommand2 = new import_commander53.Command("volume").description("Block Storage \uBCFC\uB968 \uAD00\uB828 \uBA85\uB839").addHelpText("after", volumeAgentWorkflow);
|
|
7645
8694
|
volumeCommand2.addCommand(listCommand2);
|
|
7646
8695
|
volumeCommand2.addCommand(getCommand);
|
|
7647
8696
|
volumeCommand2.addCommand(createCommand);
|
|
7648
8697
|
program.addCommand(volumeCommand2);
|
|
7649
|
-
var floatingipCommand = new
|
|
8698
|
+
var floatingipCommand = new import_commander53.Command("floatingip").description(
|
|
7650
8699
|
"Floating IP(\uC778\uC2A4\uD134\uC2A4 \uACF5\uC778 IP) \uAD00\uB9AC"
|
|
7651
8700
|
).addHelpText("after", floatingIpAgentWorkflow);
|
|
7652
8701
|
floatingipCommand.addCommand(listCommand4);
|
|
7653
8702
|
floatingipCommand.addCommand(createCommand2);
|
|
7654
8703
|
floatingipCommand.addCommand(deleteCommand);
|
|
7655
8704
|
program.addCommand(floatingipCommand);
|
|
7656
|
-
var
|
|
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);
|
|
7657
8714
|
ncrCommand.addCommand(listCommand5);
|
|
7658
8715
|
ncrCommand.addCommand(getCommand3);
|
|
7659
8716
|
ncrCommand.addCommand(imagesCommand2);
|
|
7660
8717
|
ncrCommand.addCommand(tagsCommand);
|
|
7661
8718
|
program.addCommand(ncrCommand);
|
|
7662
|
-
var nksCommand = new
|
|
8719
|
+
var nksCommand = new import_commander53.Command("nks").description("NHN Kubernetes Service \uAD00\uB828 \uBA85\uB839").addHelpText("after", nksAgentWorkflow);
|
|
7663
8720
|
nksCommand.addCommand(supportsCommand);
|
|
7664
8721
|
nksCommand.addCommand(clusterCommand);
|
|
7665
8722
|
nksCommand.addCommand(nodegroupCommand);
|
|
7666
8723
|
nksCommand.addCommand(addonTypeCommand);
|
|
7667
8724
|
nksCommand.addCommand(addonCommand);
|
|
7668
8725
|
program.addCommand(nksCommand);
|
|
7669
|
-
var ncsCommand = new
|
|
8726
|
+
var ncsCommand = new import_commander53.Command("ncs").description("NHN Container Service \uAD00\uB828 \uBA85\uB839").addHelpText("after", ncsAgentWorkflow);
|
|
7670
8727
|
ncsCommand.addCommand(templateCommand);
|
|
7671
8728
|
ncsCommand.addCommand(workloadCommand);
|
|
7672
8729
|
ncsCommand.addCommand(malwareCommand);
|