@bifos/nhncloud-cli 0.10.1 → 0.12.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 +169 -14
- package/dist/index.js +1198 -138
- package/package.json +1 -1
- package/skills/nhncloud-cli/SKILL.md +31 -59
- package/skills/nhncloud-cli/references/common.md +24 -3
- package/skills/nhncloud-cli/references/loadbalancer.md +237 -0
- package/skills/nhncloud-cli/references/logncrash.md +32 -10
- package/skills/nhncloud-cli/references/ncs.md +43 -1
- package/skills/nhncloud-cli/references/troubleshooting.md +12 -3
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
|
|
@@ -114,7 +114,7 @@ nhncloud configure \uB97C \uC2E4\uD589\uD574 \uC790\uACA9\uC99D\uBA85\uC744 \uC1
|
|
|
114
114
|
profiles: {
|
|
115
115
|
default: {
|
|
116
116
|
userAccessKey: { id: "<uak-id>", secret: "<uak-secret>" },
|
|
117
|
-
logncrash: { appkey: "<appkey>"
|
|
117
|
+
logncrash: { appkey: "<appkey>" }
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
},
|
|
@@ -215,7 +215,7 @@ ${CREDENTIALS_PATH} \uC5D0\uC11C profiles.${profileName} \uBE14\uB85D\uC744 \uCD
|
|
|
215
215
|
throw new NhnCloudCliError(
|
|
216
216
|
`profile "${profileName}" \uC5D0 "${service}" \uC790\uACA9\uC99D\uBA85\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.
|
|
217
217
|
${CREDENTIALS_PATH} \uC5D0\uC11C profiles.${profileName}.${service} \uBE14\uB85D\uC744 \uCD94\uAC00\uD558\uC138\uC694.
|
|
218
|
-
\uC608\uC2DC: { "appkey": "<appkey>"
|
|
218
|
+
\uC608\uC2DC: { "appkey": "<appkey>" }`,
|
|
219
219
|
EXIT_CONFIG_ERROR
|
|
220
220
|
);
|
|
221
221
|
}
|
|
@@ -681,33 +681,26 @@ function unwrap(res) {
|
|
|
681
681
|
// src/services/logncrash/client.ts
|
|
682
682
|
var LogncrashClient = class {
|
|
683
683
|
appkey;
|
|
684
|
-
/**
|
|
685
|
-
|
|
686
|
-
constructor(appkey,
|
|
684
|
+
/** Search v3 읽기 요청에만 필요하다. collector send 는 인증 헤더를 쓰지 않는다(ADR-014). */
|
|
685
|
+
accessToken;
|
|
686
|
+
constructor(appkey, accessToken) {
|
|
687
687
|
this.appkey = appkey;
|
|
688
|
-
this.
|
|
688
|
+
this.accessToken = accessToken;
|
|
689
689
|
}
|
|
690
|
-
async
|
|
691
|
-
|
|
692
|
-
throw new NhnCloudCliError(
|
|
693
|
-
"logncrash search \uC5D0\uB294 secret \uC774 \uD544\uC694\uD569\uB2C8\uB2E4. configure \uB85C logncrash secret \uC744 \uC124\uC815\uD558\uC138\uC694.",
|
|
694
|
-
EXIT_CONFIG_ERROR
|
|
695
|
-
);
|
|
696
|
-
}
|
|
690
|
+
async cursorSearch(params) {
|
|
691
|
+
const headers = this.readHeaders();
|
|
697
692
|
const endpoint = endpointFor("logncrash");
|
|
698
|
-
const url = `${endpoint}/
|
|
693
|
+
const url = `${endpoint}/v3/${encodeURIComponent(this.appkey)}/logs/cursor`;
|
|
699
694
|
try {
|
|
700
695
|
const res = await import_ky4.default.post(url, {
|
|
701
|
-
headers
|
|
702
|
-
"X-LNCS-SECRET": this.secret,
|
|
703
|
-
"Content-Type": "application/json"
|
|
704
|
-
},
|
|
696
|
+
headers,
|
|
705
697
|
json: {
|
|
706
698
|
query: params.query,
|
|
707
699
|
from: params.from,
|
|
708
700
|
to: params.to,
|
|
709
|
-
|
|
710
|
-
pageSize: params.pageSize
|
|
701
|
+
sort: { logTime: "DESC" },
|
|
702
|
+
...params.pageSize !== void 0 ? { pageSize: params.pageSize } : {},
|
|
703
|
+
...params.cursor !== void 0 ? { cursor: params.cursor } : {}
|
|
711
704
|
}
|
|
712
705
|
}).json();
|
|
713
706
|
return unwrap(res);
|
|
@@ -716,29 +709,19 @@ var LogncrashClient = class {
|
|
|
716
709
|
}
|
|
717
710
|
}
|
|
718
711
|
/**
|
|
719
|
-
* scroll 검색을 시작한다.
|
|
720
|
-
* body 는 search 와 동일(query/from/to/pageSize). 응답 scrollKey 로 scrollNext 를 이어 호출한다.
|
|
712
|
+
* v3 scroll 검색을 시작한다. 응답 scrollKey 로 scrollNext 를 이어 호출한다.
|
|
721
713
|
*/
|
|
722
714
|
async scrollStart(params) {
|
|
723
|
-
|
|
724
|
-
throw new NhnCloudCliError(
|
|
725
|
-
"logncrash scroll \uC5D0\uB294 secret \uC774 \uD544\uC694\uD569\uB2C8\uB2E4. configure \uB85C logncrash secret \uC744 \uC124\uC815\uD558\uC138\uC694.",
|
|
726
|
-
EXIT_CONFIG_ERROR
|
|
727
|
-
);
|
|
728
|
-
}
|
|
715
|
+
const headers = this.readHeaders();
|
|
729
716
|
const endpoint = endpointFor("logncrash");
|
|
730
|
-
const url = `${endpoint}/
|
|
717
|
+
const url = `${endpoint}/v3/${encodeURIComponent(this.appkey)}/logs/scroll`;
|
|
731
718
|
try {
|
|
732
719
|
const res = await import_ky4.default.post(url, {
|
|
733
|
-
headers
|
|
734
|
-
"X-LNCS-SECRET": this.secret,
|
|
735
|
-
"Content-Type": "application/json"
|
|
736
|
-
},
|
|
720
|
+
headers,
|
|
737
721
|
json: {
|
|
738
722
|
query: params.query,
|
|
739
723
|
from: params.from,
|
|
740
|
-
to: params.to
|
|
741
|
-
pageSize: params.pageSize ?? 100
|
|
724
|
+
to: params.to
|
|
742
725
|
}
|
|
743
726
|
}).json();
|
|
744
727
|
return unwrap(res);
|
|
@@ -747,31 +730,30 @@ var LogncrashClient = class {
|
|
|
747
730
|
}
|
|
748
731
|
}
|
|
749
732
|
/**
|
|
750
|
-
* scroll 다음 페이지를 가져온다.
|
|
751
|
-
* body 는 보내지 않는다(scrollKey 가 좌표). scrollKey 만료 시 API 가 실패 봉투를 주며,
|
|
752
|
-
* unwrap 이 EXIT_API_ERROR 로 변환한다 — 호출부에서 만료 안내 메시지로 감싼다.
|
|
733
|
+
* v3 scroll 다음 페이지를 가져온다. body 없이 scrollKey 경로만 사용한다.
|
|
753
734
|
*/
|
|
754
735
|
async scrollNext(scrollKey) {
|
|
755
|
-
|
|
756
|
-
throw new NhnCloudCliError(
|
|
757
|
-
"logncrash scroll \uC5D0\uB294 secret \uC774 \uD544\uC694\uD569\uB2C8\uB2E4. configure \uB85C logncrash secret \uC744 \uC124\uC815\uD558\uC138\uC694.",
|
|
758
|
-
EXIT_CONFIG_ERROR
|
|
759
|
-
);
|
|
760
|
-
}
|
|
736
|
+
const headers = this.readHeaders();
|
|
761
737
|
const endpoint = endpointFor("logncrash");
|
|
762
|
-
const url = `${endpoint}/
|
|
738
|
+
const url = `${endpoint}/v3/${encodeURIComponent(this.appkey)}/logs/scroll/${encodeURIComponent(scrollKey)}`;
|
|
763
739
|
try {
|
|
764
740
|
const res = await import_ky4.default.post(url, {
|
|
765
|
-
headers
|
|
766
|
-
"X-LNCS-SECRET": this.secret,
|
|
767
|
-
"Content-Type": "application/json"
|
|
768
|
-
}
|
|
741
|
+
headers
|
|
769
742
|
}).json();
|
|
770
743
|
return unwrap(res);
|
|
771
744
|
} catch (err) {
|
|
772
745
|
throw toNhnCloudCliError(err);
|
|
773
746
|
}
|
|
774
747
|
}
|
|
748
|
+
readHeaders() {
|
|
749
|
+
if (!this.accessToken) {
|
|
750
|
+
throw new NhnCloudCliError(
|
|
751
|
+
"Log & Crash Search v3 \uD638\uCD9C\uC5D0\uB294 \uACF5\uD1B5 UAK\uB85C \uBC1C\uAE09\uD55C access token\uC774 \uD544\uC694\uD569\uB2C8\uB2E4. nhncloud configure\uB85C UAK\uB97C \uC124\uC815\uD558\uC138\uC694.",
|
|
752
|
+
EXIT_CONFIG_ERROR
|
|
753
|
+
);
|
|
754
|
+
}
|
|
755
|
+
return { "X-NHN-Authorization": `Bearer ${this.accessToken}` };
|
|
756
|
+
}
|
|
775
757
|
/**
|
|
776
758
|
* 로그 한 건을 Log & Crash collector 로 전송한다 (ADR-014).
|
|
777
759
|
* - host: api-logncrash (검색의 api-lncs-search 와 별도)
|
|
@@ -1766,17 +1748,17 @@ async function verifyNcs(uak, appkey) {
|
|
|
1766
1748
|
throw err;
|
|
1767
1749
|
}
|
|
1768
1750
|
}
|
|
1769
|
-
async function verifyLogncrash(
|
|
1770
|
-
if (!
|
|
1771
|
-
const client = new LogncrashClient(cred.appkey, cred.secret);
|
|
1751
|
+
async function verifyLogncrash(uak, appkey) {
|
|
1752
|
+
if (!appkey) return false;
|
|
1772
1753
|
const now = /* @__PURE__ */ new Date();
|
|
1773
1754
|
const oneMinuteAgo = new Date(now.getTime() - 6e4);
|
|
1774
1755
|
try {
|
|
1775
|
-
await
|
|
1756
|
+
const token = await getAccessToken("__verify__", uak.id, uak.secret, true);
|
|
1757
|
+
const client = new LogncrashClient(appkey, token);
|
|
1758
|
+
await client.cursorSearch({
|
|
1776
1759
|
query: "*",
|
|
1777
1760
|
from: oneMinuteAgo.toISOString(),
|
|
1778
1761
|
to: now.toISOString(),
|
|
1779
|
-
pageNumber: 0,
|
|
1780
1762
|
pageSize: 1
|
|
1781
1763
|
});
|
|
1782
1764
|
return true;
|
|
@@ -1789,7 +1771,7 @@ async function verifyLogncrash(cred) {
|
|
|
1789
1771
|
}
|
|
1790
1772
|
|
|
1791
1773
|
// src/commands/configure.ts
|
|
1792
|
-
async function saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, doVerify) {
|
|
1774
|
+
async function saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, doVerify, logncrashUak = uak) {
|
|
1793
1775
|
if (doVerify) {
|
|
1794
1776
|
if (uak) {
|
|
1795
1777
|
const ok = await verifyUserAccessKey(uak);
|
|
@@ -1803,12 +1785,18 @@ async function saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, doVeri
|
|
|
1803
1785
|
}
|
|
1804
1786
|
}
|
|
1805
1787
|
if (logncrash) {
|
|
1806
|
-
|
|
1788
|
+
if (!logncrashUak) {
|
|
1789
|
+
throw new NhnCloudCliError(
|
|
1790
|
+
"logncrash Search v3 \uAC80\uC99D\uC5D0\uB294 \uACF5\uD1B5 UAK\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. --uak-id\uC640 UAK secret\uC744 \uD568\uAED8 \uC124\uC815\uD558\uAC70\uB098 \uAE30\uC874 profile\uC5D0 UAK\uB97C \uC124\uC815\uD558\uC138\uC694.",
|
|
1791
|
+
EXIT_CONFIG_ERROR
|
|
1792
|
+
);
|
|
1793
|
+
}
|
|
1794
|
+
const ok = await verifyLogncrash(logncrashUak, logncrash.appkey ?? "");
|
|
1807
1795
|
if (ok) {
|
|
1808
1796
|
process.stderr.write(import_chalk.default.green(" \u2713 logncrash \uC5F0\uACB0 \uC131\uACF5\n"));
|
|
1809
1797
|
} else {
|
|
1810
1798
|
throw new NhnCloudCliError(
|
|
1811
|
-
"logncrash \uC778\uC99D \uC2E4\uD328 \u2014 appkey
|
|
1799
|
+
"logncrash \uC778\uC99D \uC2E4\uD328 \u2014 appkey \uB610\uB294 UAK\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
1812
1800
|
EXIT_AUTH_ERROR
|
|
1813
1801
|
);
|
|
1814
1802
|
}
|
|
@@ -1932,8 +1920,7 @@ async function runInteractive(opts) {
|
|
|
1932
1920
|
message: "logncrash appkey",
|
|
1933
1921
|
validate: (v) => v.trim().length > 0 || "logncrash appkey \uB97C \uC785\uB825\uD558\uC138\uC694"
|
|
1934
1922
|
});
|
|
1935
|
-
|
|
1936
|
-
logncrash = { appkey, secret };
|
|
1923
|
+
logncrash = { appkey: appkey.trim() };
|
|
1937
1924
|
}
|
|
1938
1925
|
let iaas;
|
|
1939
1926
|
const setupIaas = await confirm({
|
|
@@ -1994,7 +1981,7 @@ async function runInteractive(opts) {
|
|
|
1994
1981
|
}
|
|
1995
1982
|
if (opts.verify) {
|
|
1996
1983
|
try {
|
|
1997
|
-
await saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, true);
|
|
1984
|
+
await saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, true, uak);
|
|
1998
1985
|
} catch (err) {
|
|
1999
1986
|
if (err instanceof NhnCloudCliError && err.exitCode === EXIT_AUTH_ERROR) {
|
|
2000
1987
|
process.stderr.write(import_chalk.default.red(` \u2717 ${err.message}
|
|
@@ -2007,22 +1994,43 @@ async function runInteractive(opts) {
|
|
|
2007
1994
|
process.stderr.write(import_chalk.default.yellow("\uC800\uC7A5\uC774 \uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\n"));
|
|
2008
1995
|
return;
|
|
2009
1996
|
}
|
|
2010
|
-
await saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, false);
|
|
1997
|
+
await saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, false, uak);
|
|
2011
1998
|
} else {
|
|
2012
1999
|
throw err;
|
|
2013
2000
|
}
|
|
2014
2001
|
}
|
|
2015
2002
|
} else {
|
|
2016
|
-
await saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, false);
|
|
2003
|
+
await saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, false, uak);
|
|
2017
2004
|
}
|
|
2018
2005
|
}
|
|
2019
2006
|
async function runNonInteractive(opts) {
|
|
2020
|
-
const profileName = await resolveProfileName(opts.profile);
|
|
2021
2007
|
const uakSecret = opts.uakSecret ?? process.env["NHNCLOUD_UAK_SECRET"];
|
|
2022
|
-
const logncrashSecret = opts.logncrashSecret ?? process.env["NHNCLOUD_LOGNCRASH_SECRET"];
|
|
2023
2008
|
const iaasPassword = opts.iaasPassword ?? process.env["NHNCLOUD_IAAS_PASSWORD"];
|
|
2024
|
-
|
|
2025
|
-
|
|
2009
|
+
if (opts.uakId !== void 0 && opts.uakId.trim().length === 0) {
|
|
2010
|
+
throw new NhnCloudCliError("--uak-id \uAC12\uC740 \uBE44\uC5B4 \uC788\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
2011
|
+
}
|
|
2012
|
+
if (uakSecret !== void 0 && uakSecret.length === 0) {
|
|
2013
|
+
throw new NhnCloudCliError("UAK secret \uAC12\uC740 \uBE44\uC5B4 \uC788\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
2014
|
+
}
|
|
2015
|
+
if (opts.uakId !== void 0 !== (uakSecret !== void 0)) {
|
|
2016
|
+
throw new NhnCloudCliError(
|
|
2017
|
+
"\uBE44\uB300\uD654\uD615 \uBAA8\uB4DC\uC5D0\uC11C --uak-id\uC640 UAK secret\uC740 \uD568\uAED8 \uC9C0\uC815\uD574\uC57C \uD569\uB2C8\uB2E4.",
|
|
2018
|
+
EXIT_PARAM_ERROR
|
|
2019
|
+
);
|
|
2020
|
+
}
|
|
2021
|
+
if (opts.logncrashAppkey !== void 0 && opts.logncrashAppkey.trim().length === 0) {
|
|
2022
|
+
throw new NhnCloudCliError("--logncrash-appkey \uAC12\uC740 \uBE44\uC5B4 \uC788\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
2023
|
+
}
|
|
2024
|
+
if (opts.logncrashSecret !== void 0) {
|
|
2025
|
+
process.stderr.write(
|
|
2026
|
+
import_chalk.default.yellow(
|
|
2027
|
+
"\uACBD\uACE0: --logncrash-secret\uC740 \uD3D0\uAE30 \uC608\uC815\uC774\uBA70 Search v3 \uC778\uC99D\uC5D0 \uC0AC\uC6A9\uD558\uAC70\uB098 \uC800\uC7A5\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.\n"
|
|
2028
|
+
)
|
|
2029
|
+
);
|
|
2030
|
+
}
|
|
2031
|
+
const profileName = await resolveProfileName(opts.profile);
|
|
2032
|
+
const uak = opts.uakId !== void 0 && uakSecret !== void 0 ? { id: opts.uakId.trim(), secret: uakSecret } : void 0;
|
|
2033
|
+
const logncrash = opts.logncrashAppkey?.trim() ? { appkey: opts.logncrashAppkey.trim() } : void 0;
|
|
2026
2034
|
const iaas = opts.iaasTenantId && opts.iaasUsername && iaasPassword ? {
|
|
2027
2035
|
tenantId: opts.iaasTenantId,
|
|
2028
2036
|
username: opts.iaasUsername,
|
|
@@ -2033,20 +2041,33 @@ async function runNonInteractive(opts) {
|
|
|
2033
2041
|
const ncs = opts.ncsAppkey?.trim() ? { appkey: opts.ncsAppkey.trim() } : void 0;
|
|
2034
2042
|
if (!uak && !logncrash && !iaas && !ncr && !ncs) {
|
|
2035
2043
|
throw new NhnCloudCliError(
|
|
2036
|
-
"\uBE44\uB300\uD654\uD615 \uBAA8\uB4DC: --uak-id + UAK secret, --logncrash-appkey
|
|
2044
|
+
"\uBE44\uB300\uD654\uD615 \uBAA8\uB4DC: --uak-id + UAK secret, --logncrash-appkey,\n--iaas-tenant-id + --iaas-username + iaas password,\n--ncr-appkey, \uB610\uB294 --ncs-appkey \uC911 \uD558\uB098\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.\nsecret/password \uB294 \uB178\uCD9C \uBC29\uC9C0\uB97C \uC704\uD574 \uD658\uACBD\uBCC0\uC218 \uAD8C\uC7A5:\nNHNCLOUD_UAK_SECRET / NHNCLOUD_IAAS_PASSWORD.",
|
|
2037
2045
|
EXIT_PARAM_ERROR
|
|
2038
2046
|
);
|
|
2039
2047
|
}
|
|
2048
|
+
let logncrashUak = uak;
|
|
2049
|
+
if (opts.verify && logncrash && !logncrashUak) {
|
|
2050
|
+
logncrashUak = await getUserAccessKey(profileName);
|
|
2051
|
+
}
|
|
2040
2052
|
if (opts.verify) {
|
|
2041
2053
|
process.stderr.write(import_chalk.default.gray("\uC5F0\uACB0 \uD14C\uC2A4\uD2B8 \uC911\u2026\n"));
|
|
2042
2054
|
}
|
|
2043
|
-
await saveAndVerify(
|
|
2055
|
+
await saveAndVerify(
|
|
2056
|
+
profileName,
|
|
2057
|
+
uak,
|
|
2058
|
+
logncrash,
|
|
2059
|
+
iaas,
|
|
2060
|
+
ncr,
|
|
2061
|
+
ncs,
|
|
2062
|
+
opts.verify,
|
|
2063
|
+
logncrashUak
|
|
2064
|
+
);
|
|
2044
2065
|
}
|
|
2045
|
-
var configureCommand = new import_commander.Command("configure").description("\uC790\uACA9\uC99D\uBA85 \uC124\uC815 \uB9C8\uBC95\uC0AC (\uB300\uD654\uD615 + flag)").option("--profile <name>", "\uB300\uC0C1 profile \uC774\uB984 (\uAE30\uBCF8: default)").option("--uak-id <id>", "\uAC1C\uC778 UAK ID (\uBE44\uB300\uD654\uD615)").option("--uak-secret <secret>", "\uAC1C\uC778 UAK Secret (\uBE44\uB300\uD654\uD615, \uB178\uCD9C \uBC29\uC9C0\uB85C env NHNCLOUD_UAK_SECRET \uAD8C\uC7A5)").option("--logncrash-appkey <key>", "logncrash appkey (\uBE44\uB300\uD654\uD615)").option("--logncrash-secret <secret>", "
|
|
2066
|
+
var configureCommand = new import_commander.Command("configure").description("\uC790\uACA9\uC99D\uBA85 \uC124\uC815 \uB9C8\uBC95\uC0AC (\uB300\uD654\uD615 + flag)").option("--profile <name>", "\uB300\uC0C1 profile \uC774\uB984 (\uAE30\uBCF8: default)").option("--uak-id <id>", "\uAC1C\uC778 UAK ID (\uBE44\uB300\uD654\uD615)").option("--uak-secret <secret>", "\uAC1C\uC778 UAK Secret (\uBE44\uB300\uD654\uD615, \uB178\uCD9C \uBC29\uC9C0\uB85C env NHNCLOUD_UAK_SECRET \uAD8C\uC7A5)").option("--logncrash-appkey <key>", "logncrash appkey (\uBE44\uB300\uD654\uD615)").option("--logncrash-secret <secret>", "\uD3D0\uAE30 \uC608\uC815: Search v3\uC5D0\uC11C\uB294 \uC0AC\uC6A9\xB7\uC800\uC7A5\uD558\uC9C0 \uC54A\uC74C").option("--iaas-tenant-id <id>", "iaas tenantId / \uD504\uB85C\uC81D\uD2B8 ID (\uBE44\uB300\uD654\uD615)").option("--iaas-username <user>", "iaas IAM username (\uBE44\uB300\uD654\uD615)").option(
|
|
2046
2067
|
"--iaas-password <pass>",
|
|
2047
2068
|
"iaas API \uBE44\uBC00\uBC88\uD638 (\uBE44\uB300\uD654\uD615, \uB178\uCD9C \uBC29\uC9C0\uB85C env NHNCLOUD_IAAS_PASSWORD \uAD8C\uC7A5)"
|
|
2048
2069
|
).option("--iaas-region <region>", "iaas region (\uAE30\uBCF8: kr1)", "kr1").option("--ncr-appkey <key>", "ncr appkey (\uBE44\uB300\uD654\uD615)").option("--ncs-appkey <key>", "ncs appkey (\uBE44\uB300\uD654\uD615)").option("--no-verify", "\uC5F0\uACB0 \uD14C\uC2A4\uD2B8 \uC0DD\uB7B5").action(async (opts) => {
|
|
2049
|
-
const hasFlag = opts.uakId || opts.uakSecret || opts.logncrashAppkey || opts.logncrashSecret || opts.iaasTenantId || opts.iaasUsername || opts.iaasPassword || opts.ncrAppkey || opts.ncsAppkey;
|
|
2070
|
+
const hasFlag = opts.uakId !== void 0 || opts.uakSecret !== void 0 || opts.logncrashAppkey !== void 0 || opts.logncrashSecret !== void 0 || opts.iaasTenantId !== void 0 || opts.iaasUsername !== void 0 || opts.iaasPassword !== void 0 || opts.ncrAppkey !== void 0 || opts.ncsAppkey !== void 0;
|
|
2050
2071
|
try {
|
|
2051
2072
|
if (hasFlag) {
|
|
2052
2073
|
await runNonInteractive(opts);
|
|
@@ -2400,6 +2421,21 @@ function parseNonNegativeIntegerOption(value, flag) {
|
|
|
2400
2421
|
return parseIntegerOption(value, flag, { min: 0 });
|
|
2401
2422
|
}
|
|
2402
2423
|
|
|
2424
|
+
// src/commands/logncrash/helpers.ts
|
|
2425
|
+
async function resolveLogncrashClient(profile) {
|
|
2426
|
+
const profileName = await resolveProfileName(profile);
|
|
2427
|
+
const credential = await getServiceCredential("logncrash", profileName);
|
|
2428
|
+
if (typeof credential.appkey !== "string" || credential.appkey.length === 0) {
|
|
2429
|
+
throw new NhnCloudCliError(
|
|
2430
|
+
`profile "${profileName}"\uC758 logncrash \uC790\uACA9\uC99D\uBA85\uC5D0 appkey\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. nhncloud configure\uB85C appkey\uB97C \uC124\uC815\uD558\uC138\uC694.`,
|
|
2431
|
+
EXIT_CONFIG_ERROR
|
|
2432
|
+
);
|
|
2433
|
+
}
|
|
2434
|
+
const uak = await getUserAccessKey(profileName);
|
|
2435
|
+
const accessToken = await getAccessToken(profileName, uak.id, uak.secret);
|
|
2436
|
+
return new LogncrashClient(credential.appkey, accessToken);
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2403
2439
|
// src/commands/logncrash/search.ts
|
|
2404
2440
|
function getString(value) {
|
|
2405
2441
|
return typeof value === "string" ? value : String(value ?? "");
|
|
@@ -2410,7 +2446,7 @@ function formatLogRow(log) {
|
|
|
2410
2446
|
const body = truncate(getString(log["logBody"] ?? log["body"] ?? log["message"] ?? ""), 60);
|
|
2411
2447
|
return [logTime, logType, body];
|
|
2412
2448
|
}
|
|
2413
|
-
var searchCommand = new import_commander4.Command("search").description("Log & Crash \uB85C\uADF8 \uAC80\uC0C9").option("--query <lucene>", "Lucene \uC9C8\uC758 \uBB38\uC790\uC5F4 (\uD544\uC218)").option("--from <time>", "\uAC80\uC0C9 \uC2DC\uC791: ISO8601 \uB610\uB294 \uC0C1\uB300\uC2DC\uAC04 (1h/30m/2d/now) (\uD544\uC218)").option("--to <time>", "\uAC80\uC0C9 \uB05D: ISO8601 \uB610\uB294 \uC0C1\uB300\uC2DC\uAC04 (\uD544\uC218)").option("--page <n>", "pageNumber (\uAE30\uBCF8 0)", "0").option("--size <n>", "pageSize (\uAE30\uBCF8 10, \uCD5C\uB300 100)", "10").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (_opts, cmd) => {
|
|
2449
|
+
var searchCommand = new import_commander4.Command("search").description("Log & Crash \uB85C\uADF8 \uAC80\uC0C9").option("--query <lucene>", "Lucene \uC9C8\uC758 \uBB38\uC790\uC5F4 (\uD544\uC218)").option("--from <time>", "\uAC80\uC0C9 \uC2DC\uC791: ISO8601 \uB610\uB294 \uC0C1\uB300\uC2DC\uAC04 (1h/30m/2d/now) (\uD544\uC218)").option("--to <time>", "\uAC80\uC0C9 \uB05D: ISO8601 \uB610\uB294 \uC0C1\uB300\uC2DC\uAC04 (\uD544\uC218)").option("--page <n>", "pageNumber (\uAE30\uBCF8 0)", "0").option("--size <n>", "pageSize (\uAE30\uBCF8 10, \uCD5C\uB300 100)", "10").option("--cursor <value>", "\uB2E4\uC74C \uD398\uC774\uC9C0 \uC870\uD68C\uC6A9 opaque cursor").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (_opts, cmd) => {
|
|
2414
2450
|
const opts = cmd.optsWithGlobals();
|
|
2415
2451
|
if (!opts.query) {
|
|
2416
2452
|
throw new NhnCloudCliError(`--query \uC635\uC158\uC740 \uD544\uC218\uC785\uB2C8\uB2E4. \uC608: --query 'logType:"NORMAL"'`, EXIT_PARAM_ERROR);
|
|
@@ -2423,35 +2459,28 @@ var searchCommand = new import_commander4.Command("search").description("Log & C
|
|
|
2423
2459
|
}
|
|
2424
2460
|
const page = parseNonNegativeIntegerOption(opts.page ?? "0", "--page");
|
|
2425
2461
|
const size = parseIntegerOption(opts.size ?? "10", "--size", { min: 1, max: 100 });
|
|
2426
|
-
|
|
2427
|
-
const toIso = resolveTime(opts.to);
|
|
2428
|
-
assertSearchRange(fromIso, toIso);
|
|
2429
|
-
const profileName = await resolveProfileName(opts.profile);
|
|
2430
|
-
const cred = await getServiceCredential("logncrash", profileName);
|
|
2431
|
-
if (!cred.appkey) {
|
|
2462
|
+
if (page !== 0) {
|
|
2432
2463
|
throw new NhnCloudCliError(
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
EXIT_CONFIG_ERROR
|
|
2464
|
+
"Search v3\uC5D0\uC11C\uB294 --page 0\uB9CC \uC9C0\uC6D0\uD569\uB2C8\uB2E4. \uB2E4\uC74C \uD398\uC774\uC9C0\uB294 --cursor <nextCursor>\uB97C \uC0AC\uC6A9\uD558\uC138\uC694.",
|
|
2465
|
+
EXIT_PARAM_ERROR
|
|
2436
2466
|
);
|
|
2437
2467
|
}
|
|
2438
|
-
if (
|
|
2439
|
-
throw new NhnCloudCliError(
|
|
2440
|
-
`profile "${profileName}" \uC758 logncrash \uC790\uACA9\uC99D\uBA85\uC5D0 secret \uC774 \uC5C6\uC2B5\uB2C8\uB2E4.
|
|
2441
|
-
credentials.json \uC5D0 "secret": "<secretkey>" \uB97C \uCD94\uAC00\uD558\uC138\uC694.`,
|
|
2442
|
-
EXIT_CONFIG_ERROR
|
|
2443
|
-
);
|
|
2468
|
+
if (opts.cursor !== void 0 && opts.cursor.trim().length === 0) {
|
|
2469
|
+
throw new NhnCloudCliError("--cursor \uAC12\uC740 \uBE44\uC5B4 \uC788\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
2444
2470
|
}
|
|
2445
|
-
const
|
|
2471
|
+
const fromIso = resolveTime(opts.from);
|
|
2472
|
+
const toIso = resolveTime(opts.to);
|
|
2473
|
+
assertSearchRange(fromIso, toIso);
|
|
2474
|
+
const client = await resolveLogncrashClient(opts.profile);
|
|
2446
2475
|
startSpinner("\uB85C\uADF8 \uAC80\uC0C9 \uC911...");
|
|
2447
2476
|
let result;
|
|
2448
2477
|
try {
|
|
2449
|
-
result = await client.
|
|
2478
|
+
result = await client.cursorSearch({
|
|
2450
2479
|
query: opts.query,
|
|
2451
2480
|
from: fromIso,
|
|
2452
2481
|
to: toIso,
|
|
2453
|
-
|
|
2454
|
-
|
|
2482
|
+
pageSize: size,
|
|
2483
|
+
...opts.cursor !== void 0 ? { cursor: opts.cursor } : {}
|
|
2455
2484
|
});
|
|
2456
2485
|
} catch (err) {
|
|
2457
2486
|
stopSpinner(false);
|
|
@@ -2467,7 +2496,8 @@ credentials.json \uC5D0 "secret": "<secretkey>" \uB97C \uCD94\uAC00\uD558\uC138\
|
|
|
2467
2496
|
totalItems: result.totalItems,
|
|
2468
2497
|
pageNumber: result.pageNumber,
|
|
2469
2498
|
pageSize: result.pageSize,
|
|
2470
|
-
data: result.data
|
|
2499
|
+
data: result.data,
|
|
2500
|
+
...result.nextCursor !== void 0 ? { nextCursor: result.nextCursor } : {}
|
|
2471
2501
|
},
|
|
2472
2502
|
ids
|
|
2473
2503
|
});
|
|
@@ -2581,7 +2611,7 @@ function assertWritable(path3, force) {
|
|
|
2581
2611
|
EXIT_PARAM_ERROR
|
|
2582
2612
|
);
|
|
2583
2613
|
}
|
|
2584
|
-
var exportCommand = new import_commander6.Command("export").description("Log & Crash \uB85C\uADF8\uB97C scroll \uB85C \uC804\uCCB4 \uCD94\uCD9C\uD574 \uD30C\uC77C\uB85C \uC800\uC7A5 (\uB300\uB7C9 \uCD94\uCD9C)").option("--query <lucene>", "Lucene \uC9C8\uC758 \uBB38\uC790\uC5F4 (\uD544\uC218)").option("--from <time>", "\uAC80\uC0C9 \uC2DC\uC791: ISO8601 \uB610\uB294 \uC0C1\uB300\uC2DC\uAC04 (1h/30m/2d/now) (\uD544\uC218)").option("--to <time>", "\uAC80\uC0C9 \uB05D: ISO8601 \uB610\uB294 \uC0C1\uB300\uC2DC\uAC04 (\uD544\uC218)").option("--output <file>", "\uCD9C\uB825 \uD30C\uC77C \uACBD\uB85C (\uD544\uC218)").option("--format <fmt>", "\uCD9C\uB825 \uD615\uC2DD: jsonl(\uAE30\uBCF8, \uD55C \uC904\uB2F9 \uD55C \uB85C\uADF8) \uB610\uB294 json(\uBC30\uC5F4)", "jsonl").option("--size <n>", "
|
|
2614
|
+
var exportCommand = new import_commander6.Command("export").description("Log & Crash \uB85C\uADF8\uB97C scroll \uB85C \uC804\uCCB4 \uCD94\uCD9C\uD574 \uD30C\uC77C\uB85C \uC800\uC7A5 (\uB300\uB7C9 \uCD94\uCD9C)").option("--query <lucene>", "Lucene \uC9C8\uC758 \uBB38\uC790\uC5F4 (\uD544\uC218)").option("--from <time>", "\uAC80\uC0C9 \uC2DC\uC791: ISO8601 \uB610\uB294 \uC0C1\uB300\uC2DC\uAC04 (1h/30m/2d/now) (\uD544\uC218)").option("--to <time>", "\uAC80\uC0C9 \uB05D: ISO8601 \uB610\uB294 \uC0C1\uB300\uC2DC\uAC04 (\uD544\uC218)").option("--output <file>", "\uCD9C\uB825 \uD30C\uC77C \uACBD\uB85C (\uD544\uC218)").option("--format <fmt>", "\uCD9C\uB825 \uD615\uC2DD: jsonl(\uAE30\uBCF8, \uD55C \uC904\uB2F9 \uD55C \uB85C\uADF8) \uB610\uB294 json(\uBC30\uC5F4)", "jsonl").option("--size <n>", "\uD3D0\uAE30 \uC608\uC815: Search v3\uC5D0\uC11C\uB294 \uBB34\uC2DC\uB428 (\uD638\uD658 \uAC80\uC99D \uBC94\uC704 10~100)").option("--force", "\uCD9C\uB825 \uD30C\uC77C\uC774 \uC788\uC73C\uBA74 \uB36E\uC5B4\uC4F4\uB2E4").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (_opts, cmd) => {
|
|
2585
2615
|
const opts = cmd.optsWithGlobals();
|
|
2586
2616
|
if (!opts.query) {
|
|
2587
2617
|
throw new NhnCloudCliError(`--query \uC635\uC158\uC740 \uD544\uC218\uC785\uB2C8\uB2E4. \uC608: --query 'logType:"NORMAL"'`, EXIT_PARAM_ERROR);
|
|
@@ -2599,35 +2629,23 @@ var exportCommand = new import_commander6.Command("export").description("Log & C
|
|
|
2599
2629
|
if (format !== "jsonl" && format !== "json") {
|
|
2600
2630
|
throw new NhnCloudCliError("--format \uC740 jsonl \uB610\uB294 json \uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
2601
2631
|
}
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2632
|
+
if (opts.size !== void 0) {
|
|
2633
|
+
if (!/^[1-9]\d*$/.test(opts.size)) {
|
|
2634
|
+
throw new NhnCloudCliError("--size \uB294 \uC591\uC758 \uC815\uC218\uC5EC\uC57C \uD569\uB2C8\uB2E4 (\uD638\uD658 \uBC94\uC704 10~100).", EXIT_PARAM_ERROR);
|
|
2635
|
+
}
|
|
2636
|
+
const size = parseInt(opts.size, 10);
|
|
2637
|
+
if (size < 10 || size > 100) {
|
|
2638
|
+
throw new NhnCloudCliError("--size \uB294 10~100 \uC0AC\uC774\uC5EC\uC57C \uD569\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
2639
|
+
}
|
|
2640
|
+
process.stderr.write(
|
|
2641
|
+
"\uACBD\uACE0: logncrash export --size\uB294 \uD3D0\uAE30 \uC608\uC815\uC774\uBA70 Search v3 \uC694\uCCAD\uC5D0\uC11C\uB294 \uBB34\uC2DC\uB429\uB2C8\uB2E4.\n"
|
|
2642
|
+
);
|
|
2609
2643
|
}
|
|
2610
2644
|
const fromIso = resolveTime(opts.from);
|
|
2611
2645
|
const toIso = resolveTime(opts.to);
|
|
2612
2646
|
assertSearchRange(fromIso, toIso);
|
|
2613
2647
|
assertWritable(opts.output, opts.force ?? false);
|
|
2614
|
-
const
|
|
2615
|
-
const cred = await getServiceCredential("logncrash", profileName);
|
|
2616
|
-
if (!cred.appkey) {
|
|
2617
|
-
throw new NhnCloudCliError(
|
|
2618
|
-
`profile "${profileName}" \uC758 logncrash \uC790\uACA9\uC99D\uBA85\uC5D0 appkey \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.
|
|
2619
|
-
credentials.json \uC5D0 "appkey": "<appkey>" \uB97C \uCD94\uAC00\uD558\uC138\uC694.`,
|
|
2620
|
-
EXIT_CONFIG_ERROR
|
|
2621
|
-
);
|
|
2622
|
-
}
|
|
2623
|
-
if (!cred.secret) {
|
|
2624
|
-
throw new NhnCloudCliError(
|
|
2625
|
-
`profile "${profileName}" \uC758 logncrash \uC790\uACA9\uC99D\uBA85\uC5D0 secret \uC774 \uC5C6\uC2B5\uB2C8\uB2E4.
|
|
2626
|
-
credentials.json \uC5D0 "secret": "<secret>" \uB97C \uCD94\uAC00\uD558\uC138\uC694.`,
|
|
2627
|
-
EXIT_CONFIG_ERROR
|
|
2628
|
-
);
|
|
2629
|
-
}
|
|
2630
|
-
const client = new LogncrashClient(cred.appkey, cred.secret);
|
|
2648
|
+
const client = await resolveLogncrashClient(opts.profile);
|
|
2631
2649
|
const tmp = opts.output + "." + (0, import_node_crypto2.randomBytes)(4).toString("hex") + ".tmp";
|
|
2632
2650
|
const stream = (0, import_node_fs2.createWriteStream)(tmp, { encoding: "utf-8" });
|
|
2633
2651
|
const spinner = startSpinner("\uB85C\uADF8 \uCD94\uCD9C \uC911...");
|
|
@@ -2645,12 +2663,16 @@ credentials.json \uC5D0 "secret": "<secret>" \uB97C \uCD94\uAC00\uD558\uC138\uC6
|
|
|
2645
2663
|
};
|
|
2646
2664
|
try {
|
|
2647
2665
|
if (format === "json") stream.write("[");
|
|
2648
|
-
let res = await client.scrollStart({
|
|
2666
|
+
let res = await client.scrollStart({
|
|
2667
|
+
query: opts.query,
|
|
2668
|
+
from: fromIso,
|
|
2669
|
+
to: toIso
|
|
2670
|
+
});
|
|
2649
2671
|
total = res.totalItems;
|
|
2650
2672
|
writePage(res.data);
|
|
2651
2673
|
spinner.text = `\uB85C\uADF8 \uCD94\uCD9C \uC911... ${count}/${total}`;
|
|
2652
2674
|
while (res.data.length > 0 && res.scrollKey && count < Math.min(total, MAX_TOTAL)) {
|
|
2653
|
-
res = await
|
|
2675
|
+
res = await scrollNextWithHint(client, res.scrollKey);
|
|
2654
2676
|
writePage(res.data);
|
|
2655
2677
|
spinner.text = `\uB85C\uADF8 \uCD94\uCD9C \uC911... ${count}/${total}`;
|
|
2656
2678
|
}
|
|
@@ -2684,13 +2706,13 @@ credentials.json \uC5D0 "secret": "<secret>" \uB97C \uCD94\uAC00\uD558\uC138\uC6
|
|
|
2684
2706
|
process.stderr.write(`${opts.output} \uC5D0 ${count}\uAC74 \uC800\uC7A5
|
|
2685
2707
|
`);
|
|
2686
2708
|
});
|
|
2687
|
-
async function
|
|
2709
|
+
async function scrollNextWithHint(client, scrollKey) {
|
|
2688
2710
|
try {
|
|
2689
2711
|
return await client.scrollNext(scrollKey);
|
|
2690
2712
|
} catch (err) {
|
|
2691
2713
|
if (err instanceof NhnCloudCliError && err.exitCode === EXIT_API_ERROR) {
|
|
2692
2714
|
throw new NhnCloudCliError(
|
|
2693
|
-
`scroll \uB2E4\uC74C \uD398\uC774\uC9C0 \uC694\uCCAD\uC774 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4 (\uC6D0\uC778: ${err.message}).
|
|
2715
|
+
`scroll \uB2E4\uC74C \uD398\uC774\uC9C0 \uC694\uCCAD\uC774 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4 (\uC6D0\uC778: ${err.message}). \uAC80\uC0C9 \uBC94\uC704\uB97C \uC881\uD600 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.`,
|
|
2694
2716
|
EXIT_API_ERROR
|
|
2695
2717
|
);
|
|
2696
2718
|
}
|
|
@@ -6794,6 +6816,102 @@ var import_chalk16 = __toESM(require("chalk"));
|
|
|
6794
6816
|
// src/commands/ncs/helpers.ts
|
|
6795
6817
|
var import_node_fs7 = require("fs");
|
|
6796
6818
|
var MAX_JSON_PAYLOAD_BYTES = 1e6;
|
|
6819
|
+
var NCS_RFC3339_PATTERN = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?(Z|([+-])(\d{2}):(\d{2}))$/;
|
|
6820
|
+
var NCS_RELATIVE_TIME_PATTERN = /^(\d+)(m|h|d)$/;
|
|
6821
|
+
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)";
|
|
6822
|
+
function ncsTimeError(option, value, detail) {
|
|
6823
|
+
const suffix = detail ? ` ${detail}` : "";
|
|
6824
|
+
return new NhnCloudCliError(
|
|
6825
|
+
`${option} \uC2DC\uAC04 \uD615\uC2DD \uC624\uB958: ${JSON.stringify(value)}. ${NCS_TIME_EXAMPLES}\uC744 \uC0AC\uC6A9\uD558\uC138\uC694.${suffix}`,
|
|
6826
|
+
EXIT_PARAM_ERROR
|
|
6827
|
+
);
|
|
6828
|
+
}
|
|
6829
|
+
function isLeapYear(year) {
|
|
6830
|
+
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
6831
|
+
}
|
|
6832
|
+
function daysInMonth(year, month) {
|
|
6833
|
+
if (month === 2) return isLeapYear(year) ? 29 : 28;
|
|
6834
|
+
return [4, 6, 9, 11].includes(month) ? 30 : 31;
|
|
6835
|
+
}
|
|
6836
|
+
function formatNcsUtcTime(timestamp, option, input) {
|
|
6837
|
+
const date = new Date(timestamp);
|
|
6838
|
+
if (!Number.isFinite(timestamp) || Number.isNaN(date.getTime())) {
|
|
6839
|
+
throw ncsTimeError(option, input, "\uC720\uD6A8\uD55C Date \uBC94\uC704\uB97C \uBC97\uC5B4\uB0AC\uC2B5\uB2C8\uB2E4.");
|
|
6840
|
+
}
|
|
6841
|
+
const iso = date.toISOString();
|
|
6842
|
+
const secondPrecision = iso.replace(/\.\d{3}Z$/, "Z");
|
|
6843
|
+
if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/.test(secondPrecision)) {
|
|
6844
|
+
throw ncsTimeError(option, input, "UTC \uC5F0\uB3C4\uAC00 \uC9C0\uC6D0 \uBC94\uC704\uB97C \uBC97\uC5B4\uB0AC\uC2B5\uB2C8\uB2E4.");
|
|
6845
|
+
}
|
|
6846
|
+
return secondPrecision;
|
|
6847
|
+
}
|
|
6848
|
+
function parseNcsAbsoluteTime(input, option) {
|
|
6849
|
+
const match = NCS_RFC3339_PATTERN.exec(input);
|
|
6850
|
+
if (!match) throw ncsTimeError(option, input);
|
|
6851
|
+
const year = Number(match[1]);
|
|
6852
|
+
const month = Number(match[2]);
|
|
6853
|
+
const day = Number(match[3]);
|
|
6854
|
+
const hour = Number(match[4]);
|
|
6855
|
+
const minute = Number(match[5]);
|
|
6856
|
+
const second = Number(match[6]);
|
|
6857
|
+
const offsetHour = match[10] === void 0 ? 0 : Number(match[10]);
|
|
6858
|
+
const offsetMinute = match[11] === void 0 ? 0 : Number(match[11]);
|
|
6859
|
+
if (month < 1 || month > 12 || day < 1 || day > daysInMonth(year, month) || hour > 23 || minute > 59 || second > 59 || offsetHour > 23 || offsetMinute > 59) {
|
|
6860
|
+
throw ncsTimeError(option, input, "\uB0A0\uC9DC\xB7\uC2DC\uAC01\xB7\uC2DC\uAC04\uB300 \uC624\uD504\uC14B\uC744 \uD655\uC778\uD558\uC138\uC694.");
|
|
6861
|
+
}
|
|
6862
|
+
const parsedTimestamp = Date.parse(input);
|
|
6863
|
+
const timestamp = Math.floor(parsedTimestamp / 1e3) * 1e3;
|
|
6864
|
+
return {
|
|
6865
|
+
value: formatNcsUtcTime(timestamp, option, input),
|
|
6866
|
+
timestamp
|
|
6867
|
+
};
|
|
6868
|
+
}
|
|
6869
|
+
function parseNcsTime(input, option, baseTimestamp) {
|
|
6870
|
+
const trimmed = input.trim();
|
|
6871
|
+
if (trimmed === "now") {
|
|
6872
|
+
return {
|
|
6873
|
+
value: formatNcsUtcTime(baseTimestamp, option, input),
|
|
6874
|
+
timestamp: Math.floor(baseTimestamp / 1e3) * 1e3
|
|
6875
|
+
};
|
|
6876
|
+
}
|
|
6877
|
+
const relativeMatch = NCS_RELATIVE_TIME_PATTERN.exec(trimmed);
|
|
6878
|
+
if (relativeMatch) {
|
|
6879
|
+
const amount = Number(relativeMatch[1]);
|
|
6880
|
+
const unitMs = relativeMatch[2] === "m" ? 6e4 : relativeMatch[2] === "h" ? 36e5 : 864e5;
|
|
6881
|
+
const deltaMs = amount * unitMs;
|
|
6882
|
+
if (!Number.isSafeInteger(amount) || !Number.isSafeInteger(deltaMs)) {
|
|
6883
|
+
throw ncsTimeError(option, input, "\uC0C1\uB300\uC2DC\uAC04\uC774 \uC548\uC804\uD55C \uC815\uC218 \uBC94\uC704\uB97C \uBC97\uC5B4\uB0AC\uC2B5\uB2C8\uB2E4.");
|
|
6884
|
+
}
|
|
6885
|
+
const timestamp = baseTimestamp - deltaMs;
|
|
6886
|
+
return {
|
|
6887
|
+
value: formatNcsUtcTime(timestamp, option, input),
|
|
6888
|
+
timestamp: Math.floor(timestamp / 1e3) * 1e3
|
|
6889
|
+
};
|
|
6890
|
+
}
|
|
6891
|
+
return parseNcsAbsoluteTime(trimmed, option);
|
|
6892
|
+
}
|
|
6893
|
+
function normalizeNcsTimeRange(from, to, now) {
|
|
6894
|
+
if (from === void 0 && to === void 0) return {};
|
|
6895
|
+
const baseTimestamp = (now ?? /* @__PURE__ */ new Date()).getTime();
|
|
6896
|
+
if (!Number.isFinite(baseTimestamp)) {
|
|
6897
|
+
throw new NhnCloudCliError(
|
|
6898
|
+
`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.`,
|
|
6899
|
+
EXIT_PARAM_ERROR
|
|
6900
|
+
);
|
|
6901
|
+
}
|
|
6902
|
+
const normalizedFrom = from === void 0 ? void 0 : parseNcsTime(from, "--from", baseTimestamp);
|
|
6903
|
+
const normalizedTo = to === void 0 ? void 0 : parseNcsTime(to, "--to", baseTimestamp);
|
|
6904
|
+
if (normalizedFrom !== void 0 && normalizedTo !== void 0 && normalizedFrom.timestamp > normalizedTo.timestamp) {
|
|
6905
|
+
throw new NhnCloudCliError(
|
|
6906
|
+
`--from \uC2DC\uAC04\uC774 --to \uC2DC\uAC04\uBCF4\uB2E4 \uB2A6\uC2B5\uB2C8\uB2E4. ${NCS_TIME_EXAMPLES}\uC744 \uC0AC\uC6A9\uD558\uC138\uC694.`,
|
|
6907
|
+
EXIT_PARAM_ERROR
|
|
6908
|
+
);
|
|
6909
|
+
}
|
|
6910
|
+
return {
|
|
6911
|
+
...normalizedFrom === void 0 ? {} : { from: normalizedFrom.value },
|
|
6912
|
+
...normalizedTo === void 0 ? {} : { to: normalizedTo.value }
|
|
6913
|
+
};
|
|
6914
|
+
}
|
|
6797
6915
|
async function resolveNcsAppKey(profileName, appKeyOpt) {
|
|
6798
6916
|
if (appKeyOpt) return appKeyOpt;
|
|
6799
6917
|
let cred;
|
|
@@ -7162,7 +7280,13 @@ var getCommand7 = new import_commander46.Command("get").description("NCS workloa
|
|
|
7162
7280
|
ids: [workload.id]
|
|
7163
7281
|
});
|
|
7164
7282
|
});
|
|
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(
|
|
7283
|
+
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(
|
|
7284
|
+
"--from <time>",
|
|
7285
|
+
"\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"
|
|
7286
|
+
).option(
|
|
7287
|
+
"--to <time>",
|
|
7288
|
+
"\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"
|
|
7289
|
+
).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
7290
|
const opts = cmd.optsWithGlobals();
|
|
7167
7291
|
requireNonEmpty(id, "id");
|
|
7168
7292
|
if (!opts.task || !opts.task.trim()) {
|
|
@@ -7177,14 +7301,14 @@ var logsCommand = new import_commander46.Command("logs").description("NCS worklo
|
|
|
7177
7301
|
EXIT_PARAM_ERROR
|
|
7178
7302
|
);
|
|
7179
7303
|
}
|
|
7304
|
+
const timeRange = normalizeNcsTimeRange(opts.from, opts.to);
|
|
7180
7305
|
const { client } = await resolveNcsClient(opts);
|
|
7181
7306
|
startSpinner(`NCS workload "${id}" task "${opts.task}" \uB85C\uADF8 \uC870\uD68C \uC911...`);
|
|
7182
7307
|
let logs;
|
|
7183
7308
|
try {
|
|
7184
7309
|
const result = await client.getWorkloadLogs(id, opts.task, {
|
|
7185
7310
|
container: opts.container,
|
|
7186
|
-
|
|
7187
|
-
to: opts.to,
|
|
7311
|
+
...timeRange,
|
|
7188
7312
|
page: parsePositiveIntegerOption(opts.page, "--page"),
|
|
7189
7313
|
size: parsePositiveIntegerOption(opts.size, "--size")
|
|
7190
7314
|
});
|
|
@@ -7201,7 +7325,13 @@ var logsCommand = new import_commander46.Command("logs").description("NCS worklo
|
|
|
7201
7325
|
ids: []
|
|
7202
7326
|
});
|
|
7203
7327
|
});
|
|
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(
|
|
7328
|
+
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(
|
|
7329
|
+
"--from <time>",
|
|
7330
|
+
"\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"
|
|
7331
|
+
).option(
|
|
7332
|
+
"--to <time>",
|
|
7333
|
+
"\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"
|
|
7334
|
+
).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
7335
|
const opts = cmd.optsWithGlobals();
|
|
7206
7336
|
requireNonEmpty(id, "id");
|
|
7207
7337
|
if (!opts.task || !opts.task.trim()) {
|
|
@@ -7210,6 +7340,7 @@ var eventsCommand2 = new import_commander46.Command("events").description("NCS w
|
|
|
7210
7340
|
EXIT_PARAM_ERROR
|
|
7211
7341
|
);
|
|
7212
7342
|
}
|
|
7343
|
+
const timeRange = normalizeNcsTimeRange(opts.from, opts.to);
|
|
7213
7344
|
const { client } = await resolveNcsClient(opts);
|
|
7214
7345
|
startSpinner(`NCS workload "${id}" task "${opts.task}" \uC774\uBCA4\uD2B8 \uC870\uD68C \uC911...`);
|
|
7215
7346
|
let totalCount;
|
|
@@ -7218,8 +7349,7 @@ var eventsCommand2 = new import_commander46.Command("events").description("NCS w
|
|
|
7218
7349
|
const result = await client.getWorkloadEvents(id, opts.task, {
|
|
7219
7350
|
type: opts.type,
|
|
7220
7351
|
q: opts.q,
|
|
7221
|
-
|
|
7222
|
-
to: opts.to,
|
|
7352
|
+
...timeRange,
|
|
7223
7353
|
page: parsePositiveIntegerOption(opts.page, "--page"),
|
|
7224
7354
|
size: parsePositiveIntegerOption(opts.size, "--size")
|
|
7225
7355
|
});
|
|
@@ -7551,6 +7681,920 @@ var resultCommand = new import_commander47.Command("result").description("NCS wo
|
|
|
7551
7681
|
});
|
|
7552
7682
|
var malwareCommand = new import_commander47.Command("malware").description("NCS \uC545\uC131\uCF54\uB4DC \uAC80\uC0AC \uAD00\uB9AC").addCommand(configCommand).addCommand(resultCommand);
|
|
7553
7683
|
|
|
7684
|
+
// src/commands/loadbalancer/list.ts
|
|
7685
|
+
var import_commander48 = require("commander");
|
|
7686
|
+
|
|
7687
|
+
// src/commands/loadbalancer/helpers.ts
|
|
7688
|
+
var import_node_net = require("net");
|
|
7689
|
+
|
|
7690
|
+
// src/services/loadbalancer/client.ts
|
|
7691
|
+
var import_ky13 = __toESM(require("ky"));
|
|
7692
|
+
|
|
7693
|
+
// src/services/loadbalancer/types.ts
|
|
7694
|
+
function isRecord(value) {
|
|
7695
|
+
return typeof value === "object" && value !== null;
|
|
7696
|
+
}
|
|
7697
|
+
function isNonEmptyString(value) {
|
|
7698
|
+
return typeof value === "string" && value.length > 0;
|
|
7699
|
+
}
|
|
7700
|
+
function isIpAclAction(value) {
|
|
7701
|
+
return value === "ALLOW" || value === "DENY";
|
|
7702
|
+
}
|
|
7703
|
+
function isLoadBalancerIpAclGroup(value) {
|
|
7704
|
+
return isRecord(value) && isNonEmptyString(value["ipacl_group_id"]);
|
|
7705
|
+
}
|
|
7706
|
+
function isIpAclGroupLoadBalancer(value) {
|
|
7707
|
+
return isRecord(value) && isNonEmptyString(value["loadbalancer_id"]);
|
|
7708
|
+
}
|
|
7709
|
+
function isLoadBalancer(value) {
|
|
7710
|
+
if (!isRecord(value)) return false;
|
|
7711
|
+
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);
|
|
7712
|
+
}
|
|
7713
|
+
function isIpAclGroup(value) {
|
|
7714
|
+
if (!isRecord(value)) return false;
|
|
7715
|
+
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);
|
|
7716
|
+
}
|
|
7717
|
+
function isIpAclTarget(value) {
|
|
7718
|
+
if (!isRecord(value)) return false;
|
|
7719
|
+
return isNonEmptyString(value["id"]) && typeof value["cidr_address"] === "string" && typeof value["description"] === "string" && isNonEmptyString(value["ipacl_group_id"]);
|
|
7720
|
+
}
|
|
7721
|
+
function isIpAclBinding(value) {
|
|
7722
|
+
return isRecord(value) && isNonEmptyString(value["loadbalancer_id"]) && isNonEmptyString(value["ipacl_group_id"]);
|
|
7723
|
+
}
|
|
7724
|
+
|
|
7725
|
+
// src/services/loadbalancer/client.ts
|
|
7726
|
+
var DEFAULT_TIMEOUT_MS9 = 3e4;
|
|
7727
|
+
function isRecord2(value) {
|
|
7728
|
+
return typeof value === "object" && value !== null;
|
|
7729
|
+
}
|
|
7730
|
+
function requireNonEmptyId(id, label) {
|
|
7731
|
+
const normalized = id.trim();
|
|
7732
|
+
if (!normalized) {
|
|
7733
|
+
throw new NhnCloudCliError(`${label}\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.`, EXIT_PARAM_ERROR);
|
|
7734
|
+
}
|
|
7735
|
+
return normalized;
|
|
7736
|
+
}
|
|
7737
|
+
function readArrayField(response, key, itemGuard, missingKeyMessage, invalidItemMessage) {
|
|
7738
|
+
if (!isRecord2(response) || !Array.isArray(response[key])) {
|
|
7739
|
+
throw new NhnCloudCliError(missingKeyMessage, EXIT_API_ERROR);
|
|
7740
|
+
}
|
|
7741
|
+
const items = response[key];
|
|
7742
|
+
if (!items.every(itemGuard)) {
|
|
7743
|
+
throw new NhnCloudCliError(invalidItemMessage, EXIT_API_ERROR);
|
|
7744
|
+
}
|
|
7745
|
+
return items;
|
|
7746
|
+
}
|
|
7747
|
+
function readObjectField(response, key, itemGuard, missingKeyMessage, invalidItemMessage) {
|
|
7748
|
+
if (!isRecord2(response) || !(key in response)) {
|
|
7749
|
+
throw new NhnCloudCliError(missingKeyMessage, EXIT_API_ERROR);
|
|
7750
|
+
}
|
|
7751
|
+
const item = response[key];
|
|
7752
|
+
if (!itemGuard(item)) {
|
|
7753
|
+
throw new NhnCloudCliError(invalidItemMessage, EXIT_API_ERROR);
|
|
7754
|
+
}
|
|
7755
|
+
return item;
|
|
7756
|
+
}
|
|
7757
|
+
var LoadBalancerClient = class {
|
|
7758
|
+
tokenId;
|
|
7759
|
+
endpoint;
|
|
7760
|
+
constructor(tokenId, networkEndpoint) {
|
|
7761
|
+
this.tokenId = tokenId;
|
|
7762
|
+
this.endpoint = `${networkEndpoint}/lbaas`;
|
|
7763
|
+
}
|
|
7764
|
+
authHeaders() {
|
|
7765
|
+
return { "X-Auth-Token": this.tokenId };
|
|
7766
|
+
}
|
|
7767
|
+
async listLoadBalancers(query) {
|
|
7768
|
+
const raw = await this.getJson("/loadbalancers", query);
|
|
7769
|
+
return readArrayField(
|
|
7770
|
+
raw,
|
|
7771
|
+
"loadbalancers",
|
|
7772
|
+
isLoadBalancer,
|
|
7773
|
+
"loadbalancer list \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 loadbalancers \uBC30\uC5F4\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
7774
|
+
"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."
|
|
7775
|
+
);
|
|
7776
|
+
}
|
|
7777
|
+
async getLoadBalancer(id) {
|
|
7778
|
+
const raw = await this.getJson(`/loadbalancers/${encodeURIComponent(id)}`);
|
|
7779
|
+
return readObjectField(
|
|
7780
|
+
raw,
|
|
7781
|
+
"loadbalancer",
|
|
7782
|
+
isLoadBalancer,
|
|
7783
|
+
"loadbalancer get \uC751\uB2F5 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 loadbalancer \uAC1D\uCCB4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
7784
|
+
"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."
|
|
7785
|
+
);
|
|
7786
|
+
}
|
|
7787
|
+
async listIpAclGroups(query) {
|
|
7788
|
+
const raw = await this.getJson("/ipacl-groups", query);
|
|
7789
|
+
return readArrayField(
|
|
7790
|
+
raw,
|
|
7791
|
+
"ipacl_groups",
|
|
7792
|
+
isIpAclGroup,
|
|
7793
|
+
"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.",
|
|
7794
|
+
"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."
|
|
7795
|
+
);
|
|
7796
|
+
}
|
|
7797
|
+
async getIpAclGroup(id) {
|
|
7798
|
+
const raw = await this.getJson(`/ipacl-groups/${encodeURIComponent(id)}`);
|
|
7799
|
+
return readObjectField(
|
|
7800
|
+
raw,
|
|
7801
|
+
"ipacl_group",
|
|
7802
|
+
isIpAclGroup,
|
|
7803
|
+
"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.",
|
|
7804
|
+
"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."
|
|
7805
|
+
);
|
|
7806
|
+
}
|
|
7807
|
+
async listIpAclTargets(query) {
|
|
7808
|
+
const raw = await this.getJson("/ipacl-targets", query);
|
|
7809
|
+
return readArrayField(
|
|
7810
|
+
raw,
|
|
7811
|
+
"ipacl_targets",
|
|
7812
|
+
isIpAclTarget,
|
|
7813
|
+
"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.",
|
|
7814
|
+
"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."
|
|
7815
|
+
);
|
|
7816
|
+
}
|
|
7817
|
+
async createIpAclGroup(input) {
|
|
7818
|
+
const request = { ipacl_group: input };
|
|
7819
|
+
const raw = await this.postJson("/ipacl-groups", request);
|
|
7820
|
+
return readObjectField(
|
|
7821
|
+
raw,
|
|
7822
|
+
"ipacl_group",
|
|
7823
|
+
isIpAclGroup,
|
|
7824
|
+
"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.",
|
|
7825
|
+
"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."
|
|
7826
|
+
);
|
|
7827
|
+
}
|
|
7828
|
+
async deleteIpAclGroup(id) {
|
|
7829
|
+
const normalizedId = requireNonEmptyId(id, "IP ACL \uADF8\uB8F9 ID");
|
|
7830
|
+
await this.deleteNoContent(`/ipacl-groups/${encodeURIComponent(normalizedId)}`);
|
|
7831
|
+
}
|
|
7832
|
+
async getIpAclTarget(id) {
|
|
7833
|
+
const normalizedId = requireNonEmptyId(id, "IP ACL \uB300\uC0C1 ID");
|
|
7834
|
+
const raw = await this.getJson(`/ipacl-targets/${encodeURIComponent(normalizedId)}`);
|
|
7835
|
+
return readObjectField(
|
|
7836
|
+
raw,
|
|
7837
|
+
"ipacl_target",
|
|
7838
|
+
isIpAclTarget,
|
|
7839
|
+
"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.",
|
|
7840
|
+
"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."
|
|
7841
|
+
);
|
|
7842
|
+
}
|
|
7843
|
+
async createIpAclTarget(input) {
|
|
7844
|
+
const request = { ipacl_target: input };
|
|
7845
|
+
const raw = await this.postJson("/ipacl-targets", request);
|
|
7846
|
+
return readObjectField(
|
|
7847
|
+
raw,
|
|
7848
|
+
"ipacl_target",
|
|
7849
|
+
isIpAclTarget,
|
|
7850
|
+
"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.",
|
|
7851
|
+
"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."
|
|
7852
|
+
);
|
|
7853
|
+
}
|
|
7854
|
+
async deleteIpAclTarget(id) {
|
|
7855
|
+
const normalizedId = requireNonEmptyId(id, "IP ACL \uB300\uC0C1 ID");
|
|
7856
|
+
await this.deleteNoContent(`/ipacl-targets/${encodeURIComponent(normalizedId)}`);
|
|
7857
|
+
}
|
|
7858
|
+
async bindIpAclGroups(loadBalancerId, ipAclGroupIds) {
|
|
7859
|
+
const normalizedLoadBalancerId = requireNonEmptyId(
|
|
7860
|
+
loadBalancerId,
|
|
7861
|
+
"Load Balancer ID"
|
|
7862
|
+
);
|
|
7863
|
+
const request = {
|
|
7864
|
+
ipacl_groups_binding: ipAclGroupIds.map((id) => ({
|
|
7865
|
+
ipacl_group_id: requireNonEmptyId(id, "IP ACL \uADF8\uB8F9 ID")
|
|
7866
|
+
}))
|
|
7867
|
+
};
|
|
7868
|
+
const raw = await this.putJson(
|
|
7869
|
+
`/loadbalancers/${encodeURIComponent(normalizedLoadBalancerId)}/bind_ipacl_groups`,
|
|
7870
|
+
request
|
|
7871
|
+
);
|
|
7872
|
+
if (!Array.isArray(raw)) {
|
|
7873
|
+
throw new NhnCloudCliError(
|
|
7874
|
+
"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.",
|
|
7875
|
+
EXIT_API_ERROR
|
|
7876
|
+
);
|
|
7877
|
+
}
|
|
7878
|
+
if (!raw.every(isIpAclBinding)) {
|
|
7879
|
+
throw new NhnCloudCliError(
|
|
7880
|
+
"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.",
|
|
7881
|
+
EXIT_API_ERROR
|
|
7882
|
+
);
|
|
7883
|
+
}
|
|
7884
|
+
return raw;
|
|
7885
|
+
}
|
|
7886
|
+
async getJson(path3, searchParams) {
|
|
7887
|
+
const url = `${this.endpoint}${path3}`;
|
|
7888
|
+
try {
|
|
7889
|
+
return await import_ky13.default.get(url, {
|
|
7890
|
+
headers: this.authHeaders(),
|
|
7891
|
+
searchParams,
|
|
7892
|
+
retry: 0,
|
|
7893
|
+
timeout: DEFAULT_TIMEOUT_MS9
|
|
7894
|
+
}).json();
|
|
7895
|
+
} catch (error) {
|
|
7896
|
+
throw toNhnCloudCliError(error);
|
|
7897
|
+
}
|
|
7898
|
+
}
|
|
7899
|
+
async postJson(path3, json) {
|
|
7900
|
+
const url = `${this.endpoint}${path3}`;
|
|
7901
|
+
try {
|
|
7902
|
+
return await import_ky13.default.post(url, {
|
|
7903
|
+
headers: this.authHeaders(),
|
|
7904
|
+
json,
|
|
7905
|
+
retry: 0,
|
|
7906
|
+
timeout: DEFAULT_TIMEOUT_MS9
|
|
7907
|
+
}).json();
|
|
7908
|
+
} catch (error) {
|
|
7909
|
+
throw toNhnCloudCliError(error);
|
|
7910
|
+
}
|
|
7911
|
+
}
|
|
7912
|
+
async putJson(path3, json) {
|
|
7913
|
+
const url = `${this.endpoint}${path3}`;
|
|
7914
|
+
try {
|
|
7915
|
+
return await import_ky13.default.put(url, {
|
|
7916
|
+
headers: this.authHeaders(),
|
|
7917
|
+
json,
|
|
7918
|
+
retry: 0,
|
|
7919
|
+
timeout: DEFAULT_TIMEOUT_MS9
|
|
7920
|
+
}).json();
|
|
7921
|
+
} catch (error) {
|
|
7922
|
+
throw toNhnCloudCliError(error);
|
|
7923
|
+
}
|
|
7924
|
+
}
|
|
7925
|
+
async deleteNoContent(path3) {
|
|
7926
|
+
const url = `${this.endpoint}${path3}`;
|
|
7927
|
+
try {
|
|
7928
|
+
await import_ky13.default.delete(url, {
|
|
7929
|
+
headers: this.authHeaders(),
|
|
7930
|
+
retry: 0,
|
|
7931
|
+
timeout: DEFAULT_TIMEOUT_MS9
|
|
7932
|
+
});
|
|
7933
|
+
} catch (error) {
|
|
7934
|
+
throw toNhnCloudCliError(error);
|
|
7935
|
+
}
|
|
7936
|
+
}
|
|
7937
|
+
};
|
|
7938
|
+
|
|
7939
|
+
// src/commands/loadbalancer/helpers.ts
|
|
7940
|
+
function requireResourceInput(value, label) {
|
|
7941
|
+
const normalized = value.trim();
|
|
7942
|
+
if (!normalized) {
|
|
7943
|
+
throw new NhnCloudCliError(`${label} \uC774\uB984 \uB610\uB294 UUID\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.`, EXIT_PARAM_ERROR);
|
|
7944
|
+
}
|
|
7945
|
+
return normalized;
|
|
7946
|
+
}
|
|
7947
|
+
function optionalTrimmed(value) {
|
|
7948
|
+
if (value === void 0) return void 0;
|
|
7949
|
+
return value.trim();
|
|
7950
|
+
}
|
|
7951
|
+
function requireYes(yes, operation) {
|
|
7952
|
+
if (!yes) {
|
|
7953
|
+
throw new NhnCloudCliError(
|
|
7954
|
+
`${operation}\uC5D0\uB294 --yes \uD50C\uB798\uADF8\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.`,
|
|
7955
|
+
EXIT_PARAM_ERROR
|
|
7956
|
+
);
|
|
7957
|
+
}
|
|
7958
|
+
return true;
|
|
7959
|
+
}
|
|
7960
|
+
function parseIpAclAction(value) {
|
|
7961
|
+
if (value !== "ALLOW" && value !== "DENY") {
|
|
7962
|
+
throw new NhnCloudCliError(
|
|
7963
|
+
`--action\uC740 ALLOW \uB610\uB294 DENY\uC5EC\uC57C \uD569\uB2C8\uB2E4: ${JSON.stringify(value)}`,
|
|
7964
|
+
EXIT_PARAM_ERROR
|
|
7965
|
+
);
|
|
7966
|
+
}
|
|
7967
|
+
return value;
|
|
7968
|
+
}
|
|
7969
|
+
function collectOption(value, previous = []) {
|
|
7970
|
+
return [...previous, value];
|
|
7971
|
+
}
|
|
7972
|
+
function requireResourceInputs(values, label) {
|
|
7973
|
+
if (values.length === 0) {
|
|
7974
|
+
throw new NhnCloudCliError(`${label}\uC744(\uB97C) \uD55C \uAC1C \uC774\uC0C1 \uC9C0\uC815\uD574\uC57C \uD569\uB2C8\uB2E4.`, EXIT_PARAM_ERROR);
|
|
7975
|
+
}
|
|
7976
|
+
return values.map((value) => requireResourceInput(value, label));
|
|
7977
|
+
}
|
|
7978
|
+
function parseIpOrCidr(value) {
|
|
7979
|
+
const normalized = value.trim();
|
|
7980
|
+
const parts = normalized.split("/");
|
|
7981
|
+
const address = parts[0] ?? "";
|
|
7982
|
+
const version = (0, import_node_net.isIP)(address);
|
|
7983
|
+
if (version === 0 || parts.length > 2) {
|
|
7984
|
+
throw new NhnCloudCliError(
|
|
7985
|
+
`--cidr\uC740 IP \uC8FC\uC18C \uB610\uB294 CIDR\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4: ${JSON.stringify(value)}`,
|
|
7986
|
+
EXIT_PARAM_ERROR
|
|
7987
|
+
);
|
|
7988
|
+
}
|
|
7989
|
+
if (parts.length === 2) {
|
|
7990
|
+
const prefix = parts[1] ?? "";
|
|
7991
|
+
const maxPrefix = version === 4 ? 32 : 128;
|
|
7992
|
+
if (!/^\d+$/.test(prefix) || Number(prefix) > maxPrefix) {
|
|
7993
|
+
throw new NhnCloudCliError(
|
|
7994
|
+
`--cidr prefix\uAC00 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: ${JSON.stringify(value)}`,
|
|
7995
|
+
EXIT_PARAM_ERROR
|
|
7996
|
+
);
|
|
7997
|
+
}
|
|
7998
|
+
}
|
|
7999
|
+
return normalized;
|
|
8000
|
+
}
|
|
8001
|
+
function resolvedId(resource, label) {
|
|
8002
|
+
const id = resource.id.trim();
|
|
8003
|
+
if (!id) {
|
|
8004
|
+
throw new NhnCloudCliError(`${label} \uC870\uD68C \uACB0\uACFC\uC758 UUID\uAC00 \uBE44\uC5B4 \uC788\uC2B5\uB2C8\uB2E4.`, EXIT_PARAM_ERROR);
|
|
8005
|
+
}
|
|
8006
|
+
return id;
|
|
8007
|
+
}
|
|
8008
|
+
function resolveFromList(resources, input, label) {
|
|
8009
|
+
const exactId = resources.find((resource) => resource.id === input);
|
|
8010
|
+
if (exactId) return resolvedId(exactId, label);
|
|
8011
|
+
const nameMatches = resources.filter((resource) => resource.name === input);
|
|
8012
|
+
if (nameMatches.length === 1) return resolvedId(nameMatches[0], label);
|
|
8013
|
+
if (nameMatches.length === 0) {
|
|
8014
|
+
throw new NhnCloudCliError(
|
|
8015
|
+
`${label}\uC744(\uB97C) \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${JSON.stringify(input)}`,
|
|
8016
|
+
EXIT_PARAM_ERROR
|
|
8017
|
+
);
|
|
8018
|
+
}
|
|
8019
|
+
const candidateIds = nameMatches.map((resource) => resolvedId(resource, label)).sort();
|
|
8020
|
+
throw new NhnCloudCliError(
|
|
8021
|
+
`${label} \uC774\uB984\uC774 \uC911\uBCF5\uB429\uB2C8\uB2E4: ${JSON.stringify(input)} (\uD6C4\uBCF4 UUID: ${candidateIds.join(", ")})`,
|
|
8022
|
+
EXIT_PARAM_ERROR
|
|
8023
|
+
);
|
|
8024
|
+
}
|
|
8025
|
+
async function resolveLoadBalancerId(client, value) {
|
|
8026
|
+
const input = requireResourceInput(value, "Load Balancer");
|
|
8027
|
+
const resources = await client.listLoadBalancers();
|
|
8028
|
+
return resolveFromList(resources, input, "Load Balancer");
|
|
8029
|
+
}
|
|
8030
|
+
async function resolveIpAclGroupId(client, value) {
|
|
8031
|
+
const input = requireResourceInput(value, "IP ACL \uADF8\uB8F9");
|
|
8032
|
+
const resources = await client.listIpAclGroups();
|
|
8033
|
+
return resolveFromList(resources, input, "IP ACL \uADF8\uB8F9");
|
|
8034
|
+
}
|
|
8035
|
+
async function resolveIpAclGroups(client, values) {
|
|
8036
|
+
const inputs = requireResourceInputs(values, "IP ACL \uADF8\uB8F9");
|
|
8037
|
+
const resources = await client.listIpAclGroups();
|
|
8038
|
+
return inputs.map((input) => {
|
|
8039
|
+
const id = resolveFromList(resources, input, "IP ACL \uADF8\uB8F9");
|
|
8040
|
+
const group = resources.find((resource) => resource.id === id);
|
|
8041
|
+
if (!group) {
|
|
8042
|
+
throw new NhnCloudCliError(
|
|
8043
|
+
`IP ACL \uADF8\uB8F9 \uC870\uD68C \uACB0\uACFC\uC5D0\uC11C UUID\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${JSON.stringify(id)}`,
|
|
8044
|
+
EXIT_PARAM_ERROR
|
|
8045
|
+
);
|
|
8046
|
+
}
|
|
8047
|
+
return group;
|
|
8048
|
+
});
|
|
8049
|
+
}
|
|
8050
|
+
async function resolveLoadBalancerClient(opts) {
|
|
8051
|
+
const { profileName, tokenId, networkEndpoint } = await resolveIaasTokenContext(opts);
|
|
8052
|
+
return {
|
|
8053
|
+
client: new LoadBalancerClient(tokenId, networkEndpoint),
|
|
8054
|
+
profileName
|
|
8055
|
+
};
|
|
8056
|
+
}
|
|
8057
|
+
|
|
8058
|
+
// src/commands/loadbalancer/list.ts
|
|
8059
|
+
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) => {
|
|
8060
|
+
const opts = cmd.optsWithGlobals();
|
|
8061
|
+
const { client } = await resolveLoadBalancerClient(opts);
|
|
8062
|
+
startSpinner("Load Balancer \uBAA9\uB85D \uC870\uD68C \uC911...");
|
|
8063
|
+
let loadBalancers;
|
|
8064
|
+
let success = false;
|
|
8065
|
+
try {
|
|
8066
|
+
loadBalancers = await client.listLoadBalancers();
|
|
8067
|
+
success = true;
|
|
8068
|
+
} catch (error) {
|
|
8069
|
+
stopSpinner(false);
|
|
8070
|
+
throw error;
|
|
8071
|
+
} finally {
|
|
8072
|
+
if (success) stopSpinner(true);
|
|
8073
|
+
}
|
|
8074
|
+
output(opts, {
|
|
8075
|
+
headers: [
|
|
8076
|
+
"id",
|
|
8077
|
+
"name",
|
|
8078
|
+
"vip_address",
|
|
8079
|
+
"provisioning_status",
|
|
8080
|
+
"operating_status",
|
|
8081
|
+
"ipacl_group_action"
|
|
8082
|
+
],
|
|
8083
|
+
rows: loadBalancers.map((loadBalancer) => [
|
|
8084
|
+
loadBalancer.id,
|
|
8085
|
+
loadBalancer.name,
|
|
8086
|
+
loadBalancer.vip_address,
|
|
8087
|
+
loadBalancer.provisioning_status,
|
|
8088
|
+
loadBalancer.operating_status,
|
|
8089
|
+
loadBalancer.ipacl_group_action ?? ""
|
|
8090
|
+
]),
|
|
8091
|
+
raw: loadBalancers,
|
|
8092
|
+
ids: loadBalancers.map((loadBalancer) => loadBalancer.id)
|
|
8093
|
+
});
|
|
8094
|
+
});
|
|
8095
|
+
|
|
8096
|
+
// src/commands/loadbalancer/get.ts
|
|
8097
|
+
var import_commander49 = require("commander");
|
|
8098
|
+
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) => {
|
|
8099
|
+
const opts = cmd.optsWithGlobals();
|
|
8100
|
+
const input = requireResourceInput(loadBalancerInput, "Load Balancer");
|
|
8101
|
+
const { client } = await resolveLoadBalancerClient(opts);
|
|
8102
|
+
startSpinner("Load Balancer \uC870\uD68C \uC911...");
|
|
8103
|
+
let loadBalancer;
|
|
8104
|
+
let success = false;
|
|
8105
|
+
try {
|
|
8106
|
+
const id = await resolveLoadBalancerId(client, input);
|
|
8107
|
+
loadBalancer = await client.getLoadBalancer(id);
|
|
8108
|
+
success = true;
|
|
8109
|
+
} catch (error) {
|
|
8110
|
+
stopSpinner(false);
|
|
8111
|
+
throw error;
|
|
8112
|
+
} finally {
|
|
8113
|
+
if (success) stopSpinner(true);
|
|
8114
|
+
}
|
|
8115
|
+
output(opts, {
|
|
8116
|
+
headers: ["field", "value"],
|
|
8117
|
+
rows: [
|
|
8118
|
+
["id", loadBalancer.id],
|
|
8119
|
+
["name", loadBalancer.name],
|
|
8120
|
+
["vip_address", loadBalancer.vip_address],
|
|
8121
|
+
["provisioning_status", loadBalancer.provisioning_status],
|
|
8122
|
+
["operating_status", loadBalancer.operating_status],
|
|
8123
|
+
["ipacl_group_action", loadBalancer.ipacl_group_action ?? ""],
|
|
8124
|
+
[
|
|
8125
|
+
"ipacl_group_ids",
|
|
8126
|
+
loadBalancer.ipacl_groups.map((group) => group.ipacl_group_id).join(", ")
|
|
8127
|
+
]
|
|
8128
|
+
],
|
|
8129
|
+
raw: loadBalancer,
|
|
8130
|
+
ids: [loadBalancer.id]
|
|
8131
|
+
});
|
|
8132
|
+
});
|
|
8133
|
+
|
|
8134
|
+
// src/commands/loadbalancer/ipacl.ts
|
|
8135
|
+
var import_commander51 = require("commander");
|
|
8136
|
+
|
|
8137
|
+
// src/commands/loadbalancer/target.ts
|
|
8138
|
+
var import_commander50 = require("commander");
|
|
8139
|
+
|
|
8140
|
+
// src/commands/loadbalancer/rebind.ts
|
|
8141
|
+
function sanitizeForTerminal(value) {
|
|
8142
|
+
return value.replace(/[\x00-\x1F\x7F]/g, "?");
|
|
8143
|
+
}
|
|
8144
|
+
function shellQuote(value) {
|
|
8145
|
+
return `'${value.replace(/'/g, `'"'"'`)}'`;
|
|
8146
|
+
}
|
|
8147
|
+
function contextArgv(context) {
|
|
8148
|
+
return [
|
|
8149
|
+
...context.profile === void 0 ? [] : ["--profile", context.profile],
|
|
8150
|
+
...context.region === void 0 ? [] : ["--region", context.region]
|
|
8151
|
+
];
|
|
8152
|
+
}
|
|
8153
|
+
function retryArgv(snapshot, context = {}) {
|
|
8154
|
+
if (snapshot.ipacl_group_ids.length === 0) {
|
|
8155
|
+
return [
|
|
8156
|
+
"nhncloud",
|
|
8157
|
+
"loadbalancer",
|
|
8158
|
+
"clear-ipacl",
|
|
8159
|
+
snapshot.loadbalancer_id,
|
|
8160
|
+
...contextArgv(context),
|
|
8161
|
+
"--yes",
|
|
8162
|
+
"--json"
|
|
8163
|
+
];
|
|
8164
|
+
}
|
|
8165
|
+
return [
|
|
8166
|
+
"nhncloud",
|
|
8167
|
+
"loadbalancer",
|
|
8168
|
+
"set-ipacl",
|
|
8169
|
+
snapshot.loadbalancer_id,
|
|
8170
|
+
...snapshot.ipacl_group_ids.flatMap((id) => ["--group", id]),
|
|
8171
|
+
...contextArgv(context),
|
|
8172
|
+
"--yes",
|
|
8173
|
+
"--json"
|
|
8174
|
+
];
|
|
8175
|
+
}
|
|
8176
|
+
function retryCommand(argv) {
|
|
8177
|
+
return argv.map(shellQuote).join(" ");
|
|
8178
|
+
}
|
|
8179
|
+
async function snapshotIpAclBindings(client, loadBalancerIds) {
|
|
8180
|
+
const uniqueIds = [...new Set(loadBalancerIds)].sort();
|
|
8181
|
+
const snapshots = [];
|
|
8182
|
+
for (const loadBalancerId of uniqueIds) {
|
|
8183
|
+
const loadBalancer = await client.getLoadBalancer(loadBalancerId);
|
|
8184
|
+
snapshots.push({
|
|
8185
|
+
loadbalancer_id: loadBalancer.id,
|
|
8186
|
+
ipacl_group_ids: loadBalancer.ipacl_groups.map((group) => group.ipacl_group_id)
|
|
8187
|
+
});
|
|
8188
|
+
}
|
|
8189
|
+
return snapshots;
|
|
8190
|
+
}
|
|
8191
|
+
async function rebindIpAclSnapshots(client, snapshots, retryContext = {}) {
|
|
8192
|
+
const succeeded = [];
|
|
8193
|
+
const failed = [];
|
|
8194
|
+
for (const snapshot of snapshots) {
|
|
8195
|
+
try {
|
|
8196
|
+
await client.bindIpAclGroups(
|
|
8197
|
+
snapshot.loadbalancer_id,
|
|
8198
|
+
snapshot.ipacl_group_ids
|
|
8199
|
+
);
|
|
8200
|
+
succeeded.push(snapshot);
|
|
8201
|
+
} catch (error) {
|
|
8202
|
+
const argv = retryArgv(snapshot, retryContext);
|
|
8203
|
+
failed.push({
|
|
8204
|
+
...snapshot,
|
|
8205
|
+
error: error instanceof Error ? error.message : String(error),
|
|
8206
|
+
retry_argv: argv,
|
|
8207
|
+
retry_command: retryCommand(argv)
|
|
8208
|
+
});
|
|
8209
|
+
}
|
|
8210
|
+
}
|
|
8211
|
+
return { skipped: false, succeeded, failed };
|
|
8212
|
+
}
|
|
8213
|
+
function skippedRebindResult() {
|
|
8214
|
+
return { skipped: true, succeeded: [], failed: [] };
|
|
8215
|
+
}
|
|
8216
|
+
|
|
8217
|
+
// src/commands/loadbalancer/target.ts
|
|
8218
|
+
function outputTargetWriteResult(opts, result) {
|
|
8219
|
+
output(opts, {
|
|
8220
|
+
headers: ["field", "value"],
|
|
8221
|
+
rows: [
|
|
8222
|
+
["operation", result.operation],
|
|
8223
|
+
["status", result.status],
|
|
8224
|
+
["target_id", result.target.id],
|
|
8225
|
+
["ipacl_group_id", result.target.ipacl_group_id],
|
|
8226
|
+
["rebind_skipped", String(result.rebind.skipped)],
|
|
8227
|
+
["rebind_succeeded", String(result.rebind.succeeded.length)],
|
|
8228
|
+
["rebind_failed", String(result.rebind.failed.length)]
|
|
8229
|
+
],
|
|
8230
|
+
raw: result,
|
|
8231
|
+
ids: [result.target.id]
|
|
8232
|
+
});
|
|
8233
|
+
}
|
|
8234
|
+
function writeTargetWarnings(group, result) {
|
|
8235
|
+
if (result.rebind.skipped) {
|
|
8236
|
+
process.stderr.write(
|
|
8237
|
+
"\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"
|
|
8238
|
+
);
|
|
8239
|
+
}
|
|
8240
|
+
process.stderr.write(
|
|
8241
|
+
"\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"
|
|
8242
|
+
);
|
|
8243
|
+
if (group.action === "ALLOW") {
|
|
8244
|
+
process.stderr.write(
|
|
8245
|
+
"\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"
|
|
8246
|
+
);
|
|
8247
|
+
}
|
|
8248
|
+
if (result.rebind.failed.length > 0) {
|
|
8249
|
+
process.stderr.write(
|
|
8250
|
+
`\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.
|
|
8251
|
+
`
|
|
8252
|
+
);
|
|
8253
|
+
for (const failure of result.rebind.failed) {
|
|
8254
|
+
process.stderr.write(`${sanitizeForTerminal(failure.retry_command)}
|
|
8255
|
+
`);
|
|
8256
|
+
process.stderr.write(` \uC624\uB958: ${sanitizeForTerminal(failure.error)}
|
|
8257
|
+
`);
|
|
8258
|
+
}
|
|
8259
|
+
}
|
|
8260
|
+
}
|
|
8261
|
+
function targetWriteResult(operation, target, rebind) {
|
|
8262
|
+
return {
|
|
8263
|
+
operation,
|
|
8264
|
+
status: rebind.failed.length === 0 ? "succeeded" : "partial",
|
|
8265
|
+
target: {
|
|
8266
|
+
id: target.id,
|
|
8267
|
+
ipacl_group_id: target.ipacl_group_id
|
|
8268
|
+
},
|
|
8269
|
+
rebind
|
|
8270
|
+
};
|
|
8271
|
+
}
|
|
8272
|
+
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) => {
|
|
8273
|
+
const opts = cmd.optsWithGlobals();
|
|
8274
|
+
const input = requireResourceInput(groupInput, "IP ACL \uADF8\uB8F9");
|
|
8275
|
+
const { client } = await resolveLoadBalancerClient(opts);
|
|
8276
|
+
startSpinner("IP ACL \uB300\uC0C1 \uBAA9\uB85D \uC870\uD68C \uC911...");
|
|
8277
|
+
let targets;
|
|
8278
|
+
let success = false;
|
|
8279
|
+
try {
|
|
8280
|
+
const groupId = await resolveIpAclGroupId(client, input);
|
|
8281
|
+
targets = await client.listIpAclTargets({ ipacl_group_id: groupId });
|
|
8282
|
+
success = true;
|
|
8283
|
+
} catch (error) {
|
|
8284
|
+
stopSpinner(false);
|
|
8285
|
+
throw error;
|
|
8286
|
+
} finally {
|
|
8287
|
+
if (success) stopSpinner(true);
|
|
8288
|
+
}
|
|
8289
|
+
output(opts, {
|
|
8290
|
+
headers: ["id", "cidr_address", "description", "ipacl_group_id"],
|
|
8291
|
+
rows: targets.map((target) => [
|
|
8292
|
+
target.id,
|
|
8293
|
+
target.cidr_address,
|
|
8294
|
+
target.description,
|
|
8295
|
+
target.ipacl_group_id
|
|
8296
|
+
]),
|
|
8297
|
+
raw: targets,
|
|
8298
|
+
ids: targets.map((target) => target.id)
|
|
8299
|
+
});
|
|
8300
|
+
});
|
|
8301
|
+
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) => {
|
|
8302
|
+
const opts = cmd.optsWithGlobals();
|
|
8303
|
+
requireYes(opts.yes, "IP ACL \uB300\uC0C1 \uCD94\uAC00");
|
|
8304
|
+
const parsedGroup = requireResourceInput(groupInput, "IP ACL \uADF8\uB8F9");
|
|
8305
|
+
const parsedCidr = parseIpOrCidr(opts.cidr ?? "");
|
|
8306
|
+
const parsedDescription = optionalTrimmed(opts.description);
|
|
8307
|
+
const { client } = await resolveLoadBalancerClient(opts);
|
|
8308
|
+
startSpinner("IP ACL \uB300\uC0C1 \uCD94\uAC00\uC640 Load Balancer \uC7AC\uBC14\uC778\uB529 \uC911...");
|
|
8309
|
+
let group;
|
|
8310
|
+
let target;
|
|
8311
|
+
let rebind;
|
|
8312
|
+
try {
|
|
8313
|
+
const groupId = await resolveIpAclGroupId(client, parsedGroup);
|
|
8314
|
+
group = await client.getIpAclGroup(groupId);
|
|
8315
|
+
const snapshots = opts.rebind === false ? [] : await snapshotIpAclBindings(
|
|
8316
|
+
client,
|
|
8317
|
+
group.loadbalancers.map((item) => item.loadbalancer_id)
|
|
8318
|
+
);
|
|
8319
|
+
target = await client.createIpAclTarget({
|
|
8320
|
+
ipacl_group_id: group.id,
|
|
8321
|
+
cidr_address: parsedCidr,
|
|
8322
|
+
...parsedDescription === void 0 ? {} : { description: parsedDescription }
|
|
8323
|
+
});
|
|
8324
|
+
rebind = opts.rebind === false ? skippedRebindResult() : await rebindIpAclSnapshots(client, snapshots, {
|
|
8325
|
+
profile: opts.profile,
|
|
8326
|
+
region: opts.region
|
|
8327
|
+
});
|
|
8328
|
+
} catch (error) {
|
|
8329
|
+
stopSpinner(false);
|
|
8330
|
+
throw error;
|
|
8331
|
+
}
|
|
8332
|
+
stopSpinner(true);
|
|
8333
|
+
const result = targetWriteResult("ipacl-target-add", target, rebind);
|
|
8334
|
+
outputTargetWriteResult(opts, result);
|
|
8335
|
+
writeTargetWarnings(group, result);
|
|
8336
|
+
if (result.status === "partial") process.exitCode = EXIT_API_ERROR;
|
|
8337
|
+
});
|
|
8338
|
+
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) => {
|
|
8339
|
+
const opts = cmd.optsWithGlobals();
|
|
8340
|
+
requireYes(opts.yes, "IP ACL \uB300\uC0C1 \uC0AD\uC81C");
|
|
8341
|
+
const parsedTargetId = requireResourceInput(targetInput, "IP ACL \uB300\uC0C1");
|
|
8342
|
+
const { client } = await resolveLoadBalancerClient(opts);
|
|
8343
|
+
startSpinner("IP ACL \uB300\uC0C1 \uC0AD\uC81C\uC640 Load Balancer \uC7AC\uBC14\uC778\uB529 \uC911...");
|
|
8344
|
+
let group;
|
|
8345
|
+
let target;
|
|
8346
|
+
let rebind;
|
|
8347
|
+
try {
|
|
8348
|
+
target = await client.getIpAclTarget(parsedTargetId);
|
|
8349
|
+
group = await client.getIpAclGroup(target.ipacl_group_id);
|
|
8350
|
+
const snapshots = opts.rebind === false ? [] : await snapshotIpAclBindings(
|
|
8351
|
+
client,
|
|
8352
|
+
group.loadbalancers.map((item) => item.loadbalancer_id)
|
|
8353
|
+
);
|
|
8354
|
+
await client.deleteIpAclTarget(target.id);
|
|
8355
|
+
rebind = opts.rebind === false ? skippedRebindResult() : await rebindIpAclSnapshots(client, snapshots, {
|
|
8356
|
+
profile: opts.profile,
|
|
8357
|
+
region: opts.region
|
|
8358
|
+
});
|
|
8359
|
+
} catch (error) {
|
|
8360
|
+
stopSpinner(false);
|
|
8361
|
+
throw error;
|
|
8362
|
+
}
|
|
8363
|
+
stopSpinner(true);
|
|
8364
|
+
const result = targetWriteResult("ipacl-target-remove", target, rebind);
|
|
8365
|
+
outputTargetWriteResult(opts, result);
|
|
8366
|
+
writeTargetWarnings(group, result);
|
|
8367
|
+
if (result.status === "partial") process.exitCode = EXIT_API_ERROR;
|
|
8368
|
+
});
|
|
8369
|
+
var targetCommand = new import_commander50.Command("target").description("IP ACL \uB300\uC0C1 \uC870\uD68C\xB7\uAD00\uB9AC");
|
|
8370
|
+
targetCommand.addCommand(listCommand11);
|
|
8371
|
+
targetCommand.addCommand(addCommand);
|
|
8372
|
+
targetCommand.addCommand(removeCommand);
|
|
8373
|
+
|
|
8374
|
+
// src/commands/loadbalancer/ipacl.ts
|
|
8375
|
+
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) => {
|
|
8376
|
+
const opts = cmd.optsWithGlobals();
|
|
8377
|
+
const { client } = await resolveLoadBalancerClient(opts);
|
|
8378
|
+
startSpinner("IP ACL \uADF8\uB8F9 \uBAA9\uB85D \uC870\uD68C \uC911...");
|
|
8379
|
+
let groups;
|
|
8380
|
+
let success = false;
|
|
8381
|
+
try {
|
|
8382
|
+
groups = await client.listIpAclGroups();
|
|
8383
|
+
success = true;
|
|
8384
|
+
} catch (error) {
|
|
8385
|
+
stopSpinner(false);
|
|
8386
|
+
throw error;
|
|
8387
|
+
} finally {
|
|
8388
|
+
if (success) stopSpinner(true);
|
|
8389
|
+
}
|
|
8390
|
+
output(opts, {
|
|
8391
|
+
headers: ["id", "name", "action", "ipacl_target_count", "loadbalancer_count"],
|
|
8392
|
+
rows: groups.map((group) => [
|
|
8393
|
+
group.id,
|
|
8394
|
+
group.name,
|
|
8395
|
+
group.action,
|
|
8396
|
+
group.ipacl_target_count,
|
|
8397
|
+
String(group.loadbalancers.length)
|
|
8398
|
+
]),
|
|
8399
|
+
raw: groups,
|
|
8400
|
+
ids: groups.map((group) => group.id)
|
|
8401
|
+
});
|
|
8402
|
+
});
|
|
8403
|
+
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) => {
|
|
8404
|
+
const opts = cmd.optsWithGlobals();
|
|
8405
|
+
const input = requireResourceInput(groupInput, "IP ACL \uADF8\uB8F9");
|
|
8406
|
+
const { client } = await resolveLoadBalancerClient(opts);
|
|
8407
|
+
startSpinner("IP ACL \uADF8\uB8F9 \uC870\uD68C \uC911...");
|
|
8408
|
+
let group;
|
|
8409
|
+
let success = false;
|
|
8410
|
+
try {
|
|
8411
|
+
const id = await resolveIpAclGroupId(client, input);
|
|
8412
|
+
group = await client.getIpAclGroup(id);
|
|
8413
|
+
success = true;
|
|
8414
|
+
} catch (error) {
|
|
8415
|
+
stopSpinner(false);
|
|
8416
|
+
throw error;
|
|
8417
|
+
} finally {
|
|
8418
|
+
if (success) stopSpinner(true);
|
|
8419
|
+
}
|
|
8420
|
+
output(opts, {
|
|
8421
|
+
headers: ["field", "value"],
|
|
8422
|
+
rows: [
|
|
8423
|
+
["id", group.id],
|
|
8424
|
+
["name", group.name],
|
|
8425
|
+
["action", group.action],
|
|
8426
|
+
["ipacl_target_count", group.ipacl_target_count],
|
|
8427
|
+
[
|
|
8428
|
+
"loadbalancer_ids",
|
|
8429
|
+
group.loadbalancers.map((loadBalancer) => loadBalancer.loadbalancer_id).join(", ")
|
|
8430
|
+
]
|
|
8431
|
+
],
|
|
8432
|
+
raw: group,
|
|
8433
|
+
ids: [group.id]
|
|
8434
|
+
});
|
|
8435
|
+
});
|
|
8436
|
+
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) => {
|
|
8437
|
+
const opts = cmd.optsWithGlobals();
|
|
8438
|
+
const parsedName = requireResourceInput(opts.name ?? "", "IP ACL \uADF8\uB8F9");
|
|
8439
|
+
const parsedAction = parseIpAclAction(opts.action ?? "");
|
|
8440
|
+
const parsedDescription = optionalTrimmed(opts.description);
|
|
8441
|
+
const { client } = await resolveLoadBalancerClient(opts);
|
|
8442
|
+
startSpinner("IP ACL \uADF8\uB8F9 \uC0DD\uC131 \uC911...");
|
|
8443
|
+
let group;
|
|
8444
|
+
try {
|
|
8445
|
+
group = await client.createIpAclGroup({
|
|
8446
|
+
name: parsedName,
|
|
8447
|
+
action: parsedAction,
|
|
8448
|
+
...parsedDescription === void 0 ? {} : { description: parsedDescription }
|
|
8449
|
+
});
|
|
8450
|
+
} catch (error) {
|
|
8451
|
+
stopSpinner(false);
|
|
8452
|
+
throw error;
|
|
8453
|
+
}
|
|
8454
|
+
stopSpinner(true);
|
|
8455
|
+
const result = {
|
|
8456
|
+
operation: "ipacl-group-create",
|
|
8457
|
+
status: "succeeded",
|
|
8458
|
+
ipacl_group_id: group.id
|
|
8459
|
+
};
|
|
8460
|
+
output(opts, {
|
|
8461
|
+
headers: ["field", "value"],
|
|
8462
|
+
rows: Object.entries(result).map(([key, value]) => [key, value]),
|
|
8463
|
+
raw: result,
|
|
8464
|
+
ids: [group.id]
|
|
8465
|
+
});
|
|
8466
|
+
});
|
|
8467
|
+
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) => {
|
|
8468
|
+
const opts = cmd.optsWithGlobals();
|
|
8469
|
+
const confirmedYes = requireYes(opts.yes, "IP ACL \uADF8\uB8F9 \uC0AD\uC81C");
|
|
8470
|
+
const parsedGroup = requireResourceInput(groupInput, "IP ACL \uADF8\uB8F9");
|
|
8471
|
+
if (confirmedYes) {
|
|
8472
|
+
process.stderr.write(
|
|
8473
|
+
"\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"
|
|
8474
|
+
);
|
|
8475
|
+
}
|
|
8476
|
+
const { client } = await resolveLoadBalancerClient(opts);
|
|
8477
|
+
startSpinner("IP ACL \uADF8\uB8F9 \uC0AD\uC81C \uC911...");
|
|
8478
|
+
let groupId;
|
|
8479
|
+
try {
|
|
8480
|
+
groupId = await resolveIpAclGroupId(client, parsedGroup);
|
|
8481
|
+
await client.deleteIpAclGroup(groupId);
|
|
8482
|
+
} catch (error) {
|
|
8483
|
+
stopSpinner(false);
|
|
8484
|
+
throw error;
|
|
8485
|
+
}
|
|
8486
|
+
stopSpinner(true);
|
|
8487
|
+
const result = {
|
|
8488
|
+
operation: "ipacl-group-delete",
|
|
8489
|
+
status: "succeeded",
|
|
8490
|
+
ipacl_group_id: groupId
|
|
8491
|
+
};
|
|
8492
|
+
output(opts, {
|
|
8493
|
+
headers: ["field", "value"],
|
|
8494
|
+
rows: Object.entries(result).map(([key, value]) => [key, value]),
|
|
8495
|
+
raw: result,
|
|
8496
|
+
ids: [groupId]
|
|
8497
|
+
});
|
|
8498
|
+
});
|
|
8499
|
+
var ipaclCommand = new import_commander51.Command("ipacl").description("IP ACL \uADF8\uB8F9\xB7\uB300\uC0C1 \uC870\uD68C");
|
|
8500
|
+
ipaclCommand.addCommand(listCommand12);
|
|
8501
|
+
ipaclCommand.addCommand(getCommand9);
|
|
8502
|
+
ipaclCommand.addCommand(createCommand8);
|
|
8503
|
+
ipaclCommand.addCommand(deleteCommand7);
|
|
8504
|
+
ipaclCommand.addCommand(targetCommand);
|
|
8505
|
+
|
|
8506
|
+
// src/commands/loadbalancer/help.ts
|
|
8507
|
+
function configureLoadBalancerHelp(command) {
|
|
8508
|
+
command.configureHelp({ showGlobalOptions: true });
|
|
8509
|
+
for (const child of command.commands) {
|
|
8510
|
+
configureLoadBalancerHelp(child);
|
|
8511
|
+
}
|
|
8512
|
+
}
|
|
8513
|
+
|
|
8514
|
+
// src/commands/loadbalancer/binding.ts
|
|
8515
|
+
var import_commander52 = require("commander");
|
|
8516
|
+
function bindingResult(operation, loadBalancerId, groupIds) {
|
|
8517
|
+
return {
|
|
8518
|
+
operation,
|
|
8519
|
+
status: "succeeded",
|
|
8520
|
+
loadbalancer_id: loadBalancerId,
|
|
8521
|
+
ipacl_group_ids: groupIds
|
|
8522
|
+
};
|
|
8523
|
+
}
|
|
8524
|
+
function outputBindingResult(opts, result) {
|
|
8525
|
+
output(opts, {
|
|
8526
|
+
headers: ["field", "value"],
|
|
8527
|
+
rows: [
|
|
8528
|
+
["operation", result.operation],
|
|
8529
|
+
["status", result.status],
|
|
8530
|
+
["loadbalancer_id", result.loadbalancer_id],
|
|
8531
|
+
["ipacl_group_ids", result.ipacl_group_ids.join(", ")]
|
|
8532
|
+
],
|
|
8533
|
+
raw: result,
|
|
8534
|
+
ids: [result.loadbalancer_id]
|
|
8535
|
+
});
|
|
8536
|
+
}
|
|
8537
|
+
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(
|
|
8538
|
+
"--group <group>",
|
|
8539
|
+
"\uC801\uC6A9\uD560 IP ACL \uADF8\uB8F9 \uC774\uB984 \uB610\uB294 UUID (\uBC18\uBCF5 \uAC00\uB2A5)",
|
|
8540
|
+
collectOption
|
|
8541
|
+
).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) => {
|
|
8542
|
+
const opts = cmd.optsWithGlobals();
|
|
8543
|
+
const confirmedYes = requireYes(opts.yes, "Load Balancer IP ACL \uC5F0\uACB0 \uAD50\uCCB4");
|
|
8544
|
+
const parsedLoadBalancer = requireResourceInput(loadBalancerInput, "Load Balancer");
|
|
8545
|
+
const parsedGroups = requireResourceInputs(opts.group ?? [], "IP ACL \uADF8\uB8F9");
|
|
8546
|
+
const { client } = await resolveLoadBalancerClient(opts);
|
|
8547
|
+
startSpinner("Load Balancer IP ACL \uC5F0\uACB0 \uAD50\uCCB4 \uC911...");
|
|
8548
|
+
let loadBalancerId;
|
|
8549
|
+
let groupIds;
|
|
8550
|
+
try {
|
|
8551
|
+
loadBalancerId = await resolveLoadBalancerId(client, parsedLoadBalancer);
|
|
8552
|
+
const groups = await resolveIpAclGroups(client, parsedGroups);
|
|
8553
|
+
groupIds = groups.map((group) => group.id);
|
|
8554
|
+
if (new Set(groupIds).size !== groupIds.length) {
|
|
8555
|
+
throw new NhnCloudCliError(
|
|
8556
|
+
"\uAC19\uC740 IP ACL \uADF8\uB8F9\uC744 \uC911\uBCF5 \uC9C0\uC815\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
8557
|
+
EXIT_PARAM_ERROR
|
|
8558
|
+
);
|
|
8559
|
+
}
|
|
8560
|
+
if (new Set(groups.map((group) => group.action)).size > 1) {
|
|
8561
|
+
throw new NhnCloudCliError(
|
|
8562
|
+
"\uD568\uAED8 \uC801\uC6A9\uD560 IP ACL \uADF8\uB8F9\uC758 action\uC740 \uBAA8\uB450 \uAC19\uC544\uC57C \uD569\uB2C8\uB2E4.",
|
|
8563
|
+
EXIT_PARAM_ERROR
|
|
8564
|
+
);
|
|
8565
|
+
}
|
|
8566
|
+
if (confirmedYes) await client.bindIpAclGroups(loadBalancerId, groupIds);
|
|
8567
|
+
} catch (error) {
|
|
8568
|
+
stopSpinner(false);
|
|
8569
|
+
throw error;
|
|
8570
|
+
}
|
|
8571
|
+
stopSpinner(true);
|
|
8572
|
+
outputBindingResult(
|
|
8573
|
+
opts,
|
|
8574
|
+
bindingResult("loadbalancer-set-ipacl", loadBalancerId, groupIds)
|
|
8575
|
+
);
|
|
8576
|
+
});
|
|
8577
|
+
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) => {
|
|
8578
|
+
const opts = cmd.optsWithGlobals();
|
|
8579
|
+
const confirmedYes = requireYes(opts.yes, "Load Balancer IP ACL \uC5F0\uACB0 \uD574\uC81C");
|
|
8580
|
+
const parsedLoadBalancer = requireResourceInput(loadBalancerInput, "Load Balancer");
|
|
8581
|
+
const { client } = await resolveLoadBalancerClient(opts);
|
|
8582
|
+
startSpinner("Load Balancer IP ACL \uC5F0\uACB0 \uD574\uC81C \uC911...");
|
|
8583
|
+
let loadBalancerId;
|
|
8584
|
+
try {
|
|
8585
|
+
loadBalancerId = await resolveLoadBalancerId(client, parsedLoadBalancer);
|
|
8586
|
+
if (confirmedYes) await client.bindIpAclGroups(loadBalancerId, []);
|
|
8587
|
+
} catch (error) {
|
|
8588
|
+
stopSpinner(false);
|
|
8589
|
+
throw error;
|
|
8590
|
+
}
|
|
8591
|
+
stopSpinner(true);
|
|
8592
|
+
outputBindingResult(
|
|
8593
|
+
opts,
|
|
8594
|
+
bindingResult("loadbalancer-clear-ipacl", loadBalancerId, [])
|
|
8595
|
+
);
|
|
8596
|
+
});
|
|
8597
|
+
|
|
7554
8598
|
// src/index.ts
|
|
7555
8599
|
var rootAgentHints = `
|
|
7556
8600
|
Agent hints:
|
|
@@ -7592,6 +8636,14 @@ Agent workflow:
|
|
|
7592
8636
|
1. nhncloud floatingip list --json
|
|
7593
8637
|
2. nhncloud floatingip create --json
|
|
7594
8638
|
`;
|
|
8639
|
+
var loadbalancerAgentWorkflow = `
|
|
8640
|
+
Agent workflow:
|
|
8641
|
+
1. nhncloud loadbalancer list --json
|
|
8642
|
+
2. nhncloud loadbalancer ipacl list --json
|
|
8643
|
+
3. nhncloud loadbalancer ipacl target list <group> --json
|
|
8644
|
+
4. \uC4F0\uAE30 \uC804\uC5D0\uB294 --profile, --region, --yes, --json\uC744 \uBA85\uC2DC\uD55C\uB2E4.
|
|
8645
|
+
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.
|
|
8646
|
+
`;
|
|
7595
8647
|
var ncrAgentWorkflow = `
|
|
7596
8648
|
Agent workflow:
|
|
7597
8649
|
1. nhncloud ncr list --json
|
|
@@ -7610,8 +8662,8 @@ Agent workflow:
|
|
|
7610
8662
|
2. nhncloud ncs workload list --json
|
|
7611
8663
|
3. nhncloud ncs workload get <id> --json
|
|
7612
8664
|
`;
|
|
7613
|
-
var program = new
|
|
7614
|
-
program.name("nhncloud").description("NHN Cloud CLI \u2014 AI agent & terminal friendly").version("0.
|
|
8665
|
+
var program = new import_commander53.Command();
|
|
8666
|
+
program.name("nhncloud").description("NHN Cloud CLI \u2014 AI agent & terminal friendly").version("0.12.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
8667
|
program.hook("preAction", () => {
|
|
7616
8668
|
const opts = program.opts();
|
|
7617
8669
|
if (!opts.color || process.env["NO_COLOR"]) {
|
|
@@ -7622,12 +8674,12 @@ program.hook("preAction", () => {
|
|
|
7622
8674
|
}
|
|
7623
8675
|
});
|
|
7624
8676
|
program.addCommand(configureCommand);
|
|
7625
|
-
var logncrashCommand = new
|
|
8677
|
+
var logncrashCommand = new import_commander53.Command("logncrash").description("Log & Crash \uAD00\uB828 \uBA85\uB839").addHelpText("after", logncrashAgentWorkflow);
|
|
7626
8678
|
logncrashCommand.addCommand(searchCommand);
|
|
7627
8679
|
logncrashCommand.addCommand(sendCommand);
|
|
7628
8680
|
logncrashCommand.addCommand(exportCommand);
|
|
7629
8681
|
program.addCommand(logncrashCommand);
|
|
7630
|
-
var deployCommand = new
|
|
8682
|
+
var deployCommand = new import_commander53.Command("deploy").description("NHN Cloud Deploy \uAD00\uB828 \uBA85\uB839").addHelpText("after", deployAgentWorkflow);
|
|
7631
8683
|
deployCommand.addCommand(runCommand);
|
|
7632
8684
|
deployCommand.addCommand(artifactsCommand);
|
|
7633
8685
|
deployCommand.addCommand(serverGroupsCommand);
|
|
@@ -7637,7 +8689,7 @@ deployCommand.addCommand(binariesCommand);
|
|
|
7637
8689
|
deployCommand.addCommand(uploadCommand);
|
|
7638
8690
|
deployCommand.addCommand(downloadCommand);
|
|
7639
8691
|
program.addCommand(deployCommand);
|
|
7640
|
-
var instanceCommand = new
|
|
8692
|
+
var instanceCommand = new import_commander53.Command("instance").description("Compute \uC778\uC2A4\uD134\uC2A4 \uAD00\uB828 \uBA85\uB839").addHelpText("after", instanceAgentWorkflow);
|
|
7641
8693
|
instanceCommand.addCommand(listCommand);
|
|
7642
8694
|
instanceCommand.addCommand(flavorsCommand);
|
|
7643
8695
|
instanceCommand.addCommand(availabilityZonesCommand);
|
|
@@ -7656,36 +8708,44 @@ instanceCommand.addCommand(keypairCommand);
|
|
|
7656
8708
|
instanceCommand.addCommand(volumeCommand);
|
|
7657
8709
|
instanceCommand.addCommand(volumesCommand);
|
|
7658
8710
|
program.addCommand(instanceCommand);
|
|
7659
|
-
var networkCommand = new
|
|
8711
|
+
var networkCommand = new import_commander53.Command("network").description("VPC\xB7\uC11C\uBE0C\uB137 \uC870\uD68C").addHelpText("after", networkAgentWorkflow);
|
|
7660
8712
|
networkCommand.addCommand(listCommand3);
|
|
7661
8713
|
networkCommand.addCommand(subnetCommand);
|
|
7662
8714
|
program.addCommand(networkCommand);
|
|
7663
|
-
var volumeCommand2 = new
|
|
8715
|
+
var volumeCommand2 = new import_commander53.Command("volume").description("Block Storage \uBCFC\uB968 \uAD00\uB828 \uBA85\uB839").addHelpText("after", volumeAgentWorkflow);
|
|
7664
8716
|
volumeCommand2.addCommand(listCommand2);
|
|
7665
8717
|
volumeCommand2.addCommand(getCommand);
|
|
7666
8718
|
volumeCommand2.addCommand(createCommand);
|
|
7667
8719
|
program.addCommand(volumeCommand2);
|
|
7668
|
-
var floatingipCommand = new
|
|
8720
|
+
var floatingipCommand = new import_commander53.Command("floatingip").description(
|
|
7669
8721
|
"Floating IP(\uC778\uC2A4\uD134\uC2A4 \uACF5\uC778 IP) \uAD00\uB9AC"
|
|
7670
8722
|
).addHelpText("after", floatingIpAgentWorkflow);
|
|
7671
8723
|
floatingipCommand.addCommand(listCommand4);
|
|
7672
8724
|
floatingipCommand.addCommand(createCommand2);
|
|
7673
8725
|
floatingipCommand.addCommand(deleteCommand);
|
|
7674
8726
|
program.addCommand(floatingipCommand);
|
|
7675
|
-
var
|
|
8727
|
+
var loadbalancerCommand = new import_commander53.Command("loadbalancer").description("Load Balancer\xB7IP ACL \uC870\uD68C\xB7\uAD00\uB9AC").addHelpText("after", loadbalancerAgentWorkflow);
|
|
8728
|
+
loadbalancerCommand.addCommand(listCommand10);
|
|
8729
|
+
loadbalancerCommand.addCommand(getCommand8);
|
|
8730
|
+
loadbalancerCommand.addCommand(ipaclCommand);
|
|
8731
|
+
loadbalancerCommand.addCommand(setIpAclCommand2);
|
|
8732
|
+
loadbalancerCommand.addCommand(clearIpAclCommand);
|
|
8733
|
+
configureLoadBalancerHelp(loadbalancerCommand);
|
|
8734
|
+
program.addCommand(loadbalancerCommand);
|
|
8735
|
+
var ncrCommand = new import_commander53.Command("ncr").description("NHN Container Registry \uAD00\uB828 \uBA85\uB839").addHelpText("after", ncrAgentWorkflow);
|
|
7676
8736
|
ncrCommand.addCommand(listCommand5);
|
|
7677
8737
|
ncrCommand.addCommand(getCommand3);
|
|
7678
8738
|
ncrCommand.addCommand(imagesCommand2);
|
|
7679
8739
|
ncrCommand.addCommand(tagsCommand);
|
|
7680
8740
|
program.addCommand(ncrCommand);
|
|
7681
|
-
var nksCommand = new
|
|
8741
|
+
var nksCommand = new import_commander53.Command("nks").description("NHN Kubernetes Service \uAD00\uB828 \uBA85\uB839").addHelpText("after", nksAgentWorkflow);
|
|
7682
8742
|
nksCommand.addCommand(supportsCommand);
|
|
7683
8743
|
nksCommand.addCommand(clusterCommand);
|
|
7684
8744
|
nksCommand.addCommand(nodegroupCommand);
|
|
7685
8745
|
nksCommand.addCommand(addonTypeCommand);
|
|
7686
8746
|
nksCommand.addCommand(addonCommand);
|
|
7687
8747
|
program.addCommand(nksCommand);
|
|
7688
|
-
var ncsCommand = new
|
|
8748
|
+
var ncsCommand = new import_commander53.Command("ncs").description("NHN Container Service \uAD00\uB828 \uBA85\uB839").addHelpText("after", ncsAgentWorkflow);
|
|
7689
8749
|
ncsCommand.addCommand(templateCommand);
|
|
7690
8750
|
ncsCommand.addCommand(workloadCommand);
|
|
7691
8751
|
ncsCommand.addCommand(malwareCommand);
|