@bifos/nhncloud-cli 0.18.0 → 0.20.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 +115 -190
- package/dist/index.js +2321 -368
- package/package.json +25 -4
- package/skills/nhncloud-cli/SKILL.md +4 -3
- package/skills/nhncloud-cli/references/apigateway.md +2 -6
- package/skills/nhncloud-cli/references/common.md +107 -26
- package/skills/nhncloud-cli/references/deploy.md +0 -1
- package/skills/nhncloud-cli/references/loadbalancer.md +2 -3
- package/skills/nhncloud-cli/references/logncrash.md +6 -9
- package/skills/nhncloud-cli/references/ncs.md +3 -3
- package/skills/nhncloud-cli/references/nks.md +1 -1
- package/skills/nhncloud-cli/references/skm.md +118 -0
- package/skills/nhncloud-cli/references/troubleshooting.md +17 -31
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_commander72 = require("commander");
|
|
28
28
|
var import_chalk18 = __toESM(require("chalk"));
|
|
29
29
|
|
|
30
30
|
// src/utils/spinner.ts
|
|
@@ -333,6 +333,69 @@ async function warnLegacyDeployTargets() {
|
|
|
333
333
|
)
|
|
334
334
|
);
|
|
335
335
|
}
|
|
336
|
+
async function readJsonState(filePath) {
|
|
337
|
+
let raw;
|
|
338
|
+
try {
|
|
339
|
+
raw = await (0, import_promises.readFile)(filePath, "utf-8");
|
|
340
|
+
} catch (err) {
|
|
341
|
+
const code = err.code;
|
|
342
|
+
if (code === "ENOENT") return { state: "missing" };
|
|
343
|
+
return { state: "unreadable", reason: `\uD30C\uC77C\uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4 (${code ?? "UNKNOWN"})` };
|
|
344
|
+
}
|
|
345
|
+
try {
|
|
346
|
+
return { state: "ok", parsed: JSON.parse(raw) };
|
|
347
|
+
} catch {
|
|
348
|
+
return { state: "invalid", reason: "JSON \uD615\uC2DD\uC774 \uC544\uB2D9\uB2C8\uB2E4" };
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
async function inspectPermissions(filePath) {
|
|
352
|
+
try {
|
|
353
|
+
const { mode } = await (0, import_promises.stat)(filePath);
|
|
354
|
+
if (process.platform === "win32") return "unknown";
|
|
355
|
+
return (mode & 63) === 0 ? "ok" : "too-open";
|
|
356
|
+
} catch {
|
|
357
|
+
return void 0;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
function summarizeProfile(name, value) {
|
|
361
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
362
|
+
return { name, environment: "invalid", blocks: [] };
|
|
363
|
+
}
|
|
364
|
+
const profile = value;
|
|
365
|
+
const env = profile["environment"];
|
|
366
|
+
const environment = env === void 0 ? "real" : env === "gov" ? "gov" : "invalid";
|
|
367
|
+
const blocks = Object.keys(profile).filter((key) => key !== "environment").sort();
|
|
368
|
+
return { name, environment, blocks };
|
|
369
|
+
}
|
|
370
|
+
async function inspectCredentialsFile() {
|
|
371
|
+
const result = await readJsonState(CREDENTIALS_PATH);
|
|
372
|
+
const permissions = result.state === "missing" ? void 0 : await inspectPermissions(CREDENTIALS_PATH);
|
|
373
|
+
const base = { path: CREDENTIALS_PATH, ...permissions ? { permissions } : {}, profiles: [] };
|
|
374
|
+
if (result.state !== "ok") {
|
|
375
|
+
return { ...base, state: result.state, ...result.reason ? { reason: result.reason } : {} };
|
|
376
|
+
}
|
|
377
|
+
if (!isCredentials(result.parsed)) {
|
|
378
|
+
return { ...base, state: "invalid", reason: "version: 1 \uACFC profiles \uD544\uB4DC\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4" };
|
|
379
|
+
}
|
|
380
|
+
const profiles = Object.entries(result.parsed.profiles).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([name, value]) => summarizeProfile(name, value));
|
|
381
|
+
return { ...base, state: "ok", profiles };
|
|
382
|
+
}
|
|
383
|
+
async function inspectConfigFile() {
|
|
384
|
+
const result = await readJsonState(CONFIG_PATH);
|
|
385
|
+
const base = { path: CONFIG_PATH, defaultProfile: null };
|
|
386
|
+
if (result.state !== "ok") {
|
|
387
|
+
return { ...base, state: result.state, ...result.reason ? { reason: result.reason } : {} };
|
|
388
|
+
}
|
|
389
|
+
if (!isConfig(result.parsed)) {
|
|
390
|
+
return { ...base, state: "invalid", reason: "version: 1 \uC774 \uD544\uC694\uD569\uB2C8\uB2E4" };
|
|
391
|
+
}
|
|
392
|
+
const defaultProfile = result.parsed.defaultProfile;
|
|
393
|
+
return {
|
|
394
|
+
...base,
|
|
395
|
+
state: "ok",
|
|
396
|
+
defaultProfile: typeof defaultProfile === "string" && defaultProfile !== "" ? defaultProfile : null
|
|
397
|
+
};
|
|
398
|
+
}
|
|
336
399
|
|
|
337
400
|
// src/utils/terminal.ts
|
|
338
401
|
function sanitizeForTerminal(value) {
|
|
@@ -400,19 +463,113 @@ function parseNonNegativeIntegerOption(value, flag) {
|
|
|
400
463
|
|
|
401
464
|
// src/commands/commander-errors.ts
|
|
402
465
|
var import_commander = require("commander");
|
|
403
|
-
|
|
466
|
+
|
|
467
|
+
// src/commands/unknown-option-hint.ts
|
|
468
|
+
function normalizeName(name) {
|
|
469
|
+
return name.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
470
|
+
}
|
|
471
|
+
function parseUnknownOptionName(message) {
|
|
472
|
+
return /unknown option '--([^'=]+)/.exec(message)?.[1];
|
|
473
|
+
}
|
|
474
|
+
function findReferencedArgument(optionName, commandPath2, argumentNames) {
|
|
475
|
+
const option = normalizeName(optionName);
|
|
476
|
+
const normalized = argumentNames.map(normalizeName);
|
|
477
|
+
const exact = normalized.indexOf(option);
|
|
478
|
+
if (exact !== -1) {
|
|
479
|
+
return argumentNames[exact];
|
|
480
|
+
}
|
|
481
|
+
const prefixed = argumentNames.filter((_, i) => normalized[i].startsWith(`${option}-`));
|
|
482
|
+
const candidates = new Set(prefixed.length === 1 ? prefixed : []);
|
|
483
|
+
const segments = commandPath2.slice(1).map(normalizeName);
|
|
484
|
+
argumentNames.forEach((name, i) => {
|
|
485
|
+
const otherArguments = normalized.filter((_, j) => j !== i);
|
|
486
|
+
const matched = segments.some(
|
|
487
|
+
(segment) => !otherArguments.includes(segment) && option === `${segment}-${normalized[i]}`
|
|
488
|
+
);
|
|
489
|
+
if (matched) {
|
|
490
|
+
candidates.add(name);
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
return candidates.size === 1 ? [...candidates][0] : void 0;
|
|
494
|
+
}
|
|
495
|
+
function formatArgument(argument) {
|
|
496
|
+
const name = argument.variadic ? `${argument.name}...` : argument.name;
|
|
497
|
+
return argument.required ? `<${name}>` : `[${name}]`;
|
|
498
|
+
}
|
|
499
|
+
function buildUnknownOptionHint(input) {
|
|
500
|
+
if (input.message.includes("(Did you mean")) {
|
|
501
|
+
return "";
|
|
502
|
+
}
|
|
503
|
+
const optionName = parseUnknownOptionName(input.message);
|
|
504
|
+
if (optionName === void 0) {
|
|
505
|
+
return "";
|
|
506
|
+
}
|
|
507
|
+
const referenced = findReferencedArgument(
|
|
508
|
+
optionName,
|
|
509
|
+
input.commandPath,
|
|
510
|
+
input.arguments.map((argument2) => argument2.name)
|
|
511
|
+
);
|
|
512
|
+
const argument = input.arguments.find((candidate) => candidate.name === referenced);
|
|
513
|
+
if (argument === void 0) {
|
|
514
|
+
return "";
|
|
515
|
+
}
|
|
516
|
+
return `\uC548\uB0B4: --${optionName} \uB294 \uC635\uC158\uC774 \uC544\uB2D9\uB2C8\uB2E4. \uC704\uCE58 \uC778\uC218 ${formatArgument(argument)} \uB85C \uC804\uB2EC\uD558\uC138\uC694.
|
|
517
|
+
\uC0AC\uC6A9\uBC95: ${input.commandPath.join(" ")} ${input.usage}
|
|
518
|
+
`;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// src/commands/commander-errors.ts
|
|
522
|
+
function writeUnknownOptionHint(command, error) {
|
|
523
|
+
const commandPath2 = [];
|
|
524
|
+
for (let current2 = command; current2 !== null; current2 = current2.parent) {
|
|
525
|
+
commandPath2.unshift(current2.name());
|
|
526
|
+
}
|
|
527
|
+
const hint = buildUnknownOptionHint({
|
|
528
|
+
message: error.message,
|
|
529
|
+
commandPath: commandPath2,
|
|
530
|
+
usage: command.usage(),
|
|
531
|
+
arguments: command.registeredArguments.map((argument) => ({
|
|
532
|
+
name: argument.name(),
|
|
533
|
+
required: argument.required,
|
|
534
|
+
variadic: argument.variadic
|
|
535
|
+
}))
|
|
536
|
+
});
|
|
537
|
+
if (hint === "") {
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
const writeErr = command.configureOutput().writeErr;
|
|
541
|
+
if (writeErr) {
|
|
542
|
+
writeErr(hint);
|
|
543
|
+
} else {
|
|
544
|
+
process.stderr.write(hint);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
function handleCommanderError(command, error) {
|
|
404
548
|
if (error.code === "commander.missingMandatoryOptionValue") {
|
|
405
549
|
error.exitCode = EXIT_PARAM_ERROR;
|
|
550
|
+
} else if (error.code === "commander.unknownOption") {
|
|
551
|
+
writeUnknownOptionHint(command, error);
|
|
406
552
|
}
|
|
407
553
|
throw error;
|
|
408
554
|
}
|
|
409
555
|
function configureCommanderExitCodes(root) {
|
|
410
|
-
root.exitOverride(
|
|
556
|
+
root.exitOverride((error) => handleCommanderError(root, error));
|
|
411
557
|
for (const command of root.commands) {
|
|
412
558
|
configureCommanderExitCodes(command);
|
|
413
559
|
}
|
|
414
560
|
}
|
|
415
561
|
|
|
562
|
+
// src/commands/help.ts
|
|
563
|
+
function configureGlobalOptionsHelp(root) {
|
|
564
|
+
root.configureHelp({ showGlobalOptions: true });
|
|
565
|
+
for (const child of root.commands) {
|
|
566
|
+
configureGlobalOptionsHelp(child);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// src/version.ts
|
|
571
|
+
var CLI_VERSION = true ? "0.20.0" : "0.0.0-dev";
|
|
572
|
+
|
|
416
573
|
// src/commands/configure.ts
|
|
417
574
|
var import_commander2 = require("commander");
|
|
418
575
|
var import_chalk2 = __toESM(require("chalk"));
|
|
@@ -517,6 +674,13 @@ async function writeToken(profile, accessToken, expiresAt, credentialHash) {
|
|
|
517
674
|
|
|
518
675
|
// src/api/httpError.ts
|
|
519
676
|
var import_ky = require("ky");
|
|
677
|
+
async function readHttpErrorBody(err) {
|
|
678
|
+
try {
|
|
679
|
+
return await err.response.clone().json();
|
|
680
|
+
} catch {
|
|
681
|
+
return void 0;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
520
684
|
function toNhnCloudCliError(err) {
|
|
521
685
|
if (err instanceof NhnCloudCliError) {
|
|
522
686
|
return err;
|
|
@@ -592,10 +756,12 @@ var import_ky3 = __toESM(require("ky"));
|
|
|
592
756
|
var ENDPOINTS = {
|
|
593
757
|
logncrash: "https://api-lncs-search.nhncloudservice.com",
|
|
594
758
|
"logncrash-collector": "https://api-logncrash.nhncloudservice.com",
|
|
595
|
-
deploy: "https://api-deploy.nhncloudservice.com"
|
|
759
|
+
deploy: "https://api-deploy.nhncloudservice.com",
|
|
760
|
+
skm: "https://api-keymanager.nhncloudservice.com"
|
|
596
761
|
};
|
|
597
762
|
var GOV_ENDPOINTS = {
|
|
598
|
-
deploy: "https://api-tcd.gov-nhncloudservice.com"
|
|
763
|
+
deploy: "https://api-tcd.gov-nhncloudservice.com",
|
|
764
|
+
skm: "https://api-keymanager.gov-nhncloudservice.com"
|
|
599
765
|
};
|
|
600
766
|
function endpointFor(service, environment = "real") {
|
|
601
767
|
const endpoints = environment === "gov" ? GOV_ENDPOINTS : ENDPOINTS;
|
|
@@ -875,12 +1041,9 @@ async function toLogncrashError(err) {
|
|
|
875
1041
|
return toNhnCloudCliError(err);
|
|
876
1042
|
}
|
|
877
1043
|
let requestId = null;
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
requestId = body.requestId;
|
|
882
|
-
}
|
|
883
|
-
} catch {
|
|
1044
|
+
const body = await readHttpErrorBody(err);
|
|
1045
|
+
if (typeof body === "object" && body !== null && "requestId" in body && typeof body.requestId === "string") {
|
|
1046
|
+
requestId = body.requestId;
|
|
884
1047
|
}
|
|
885
1048
|
return new LogncrashServerError(
|
|
886
1049
|
`API \uD638\uCD9C \uC2E4\uD328 (500): ${err.message}`,
|
|
@@ -2009,7 +2172,7 @@ async function verifyLogncrash(uak, appkey) {
|
|
|
2009
2172
|
}
|
|
2010
2173
|
|
|
2011
2174
|
// src/commands/configure.ts
|
|
2012
|
-
async function saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, apigateway, deploy, doVerify, logncrashUak = uak) {
|
|
2175
|
+
async function saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, apigateway, skm, deploy, doVerify, logncrashUak = uak) {
|
|
2013
2176
|
if (doVerify) {
|
|
2014
2177
|
if (await getProfileEnvironment(profileName, true) === "gov") {
|
|
2015
2178
|
throw new NhnCloudCliError(
|
|
@@ -2115,6 +2278,9 @@ async function saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, apigat
|
|
|
2115
2278
|
if (apigateway) {
|
|
2116
2279
|
await setServiceCredential(profileName, "apigateway", apigateway);
|
|
2117
2280
|
}
|
|
2281
|
+
if (skm) {
|
|
2282
|
+
await setServiceCredential(profileName, "skm", skm);
|
|
2283
|
+
}
|
|
2118
2284
|
if (deploy) {
|
|
2119
2285
|
await setServiceCredential(profileName, "deploy", deploy);
|
|
2120
2286
|
}
|
|
@@ -2244,7 +2410,7 @@ async function runInteractive(opts) {
|
|
|
2244
2410
|
}
|
|
2245
2411
|
if (opts.verify) {
|
|
2246
2412
|
try {
|
|
2247
|
-
await saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, void 0, deploy, true, uak);
|
|
2413
|
+
await saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, void 0, void 0, deploy, true, uak);
|
|
2248
2414
|
} catch (err) {
|
|
2249
2415
|
if (err instanceof NhnCloudCliError && err.exitCode === EXIT_AUTH_ERROR) {
|
|
2250
2416
|
process.stderr.write(import_chalk2.default.red(` \u2717 ${sanitizeMultilineForTerminal(err.message)}
|
|
@@ -2257,13 +2423,13 @@ async function runInteractive(opts) {
|
|
|
2257
2423
|
process.stderr.write(import_chalk2.default.yellow("\uC800\uC7A5\uC774 \uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\n"));
|
|
2258
2424
|
return;
|
|
2259
2425
|
}
|
|
2260
|
-
await saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, void 0, deploy, false, uak);
|
|
2426
|
+
await saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, void 0, void 0, deploy, false, uak);
|
|
2261
2427
|
} else {
|
|
2262
2428
|
throw err;
|
|
2263
2429
|
}
|
|
2264
2430
|
}
|
|
2265
2431
|
} else {
|
|
2266
|
-
await saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, void 0, deploy, false, uak);
|
|
2432
|
+
await saveAndVerify(profileName, uak, logncrash, iaas, ncr, ncs, void 0, void 0, deploy, false, uak);
|
|
2267
2433
|
}
|
|
2268
2434
|
}
|
|
2269
2435
|
async function runNonInteractive(opts) {
|
|
@@ -2287,6 +2453,9 @@ async function runNonInteractive(opts) {
|
|
|
2287
2453
|
if (opts.apigatewayAppkey !== void 0 && opts.apigatewayAppkey.trim().length === 0) {
|
|
2288
2454
|
throw new NhnCloudCliError("--apigateway-appkey \uAC12\uC740 \uBE44\uC5B4 \uC788\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
2289
2455
|
}
|
|
2456
|
+
if (opts.skmAppkey !== void 0 && opts.skmAppkey.trim().length === 0) {
|
|
2457
|
+
throw new NhnCloudCliError("--skm-appkey \uAC12\uC740 \uBE44\uC5B4 \uC788\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
2458
|
+
}
|
|
2290
2459
|
if (opts.deployAppkey !== void 0 && opts.deployAppkey.trim().length === 0) {
|
|
2291
2460
|
throw new NhnCloudCliError("--deploy-appkey \uAC12\uC740 \uBE44\uC5B4 \uC788\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
2292
2461
|
}
|
|
@@ -2309,10 +2478,11 @@ async function runNonInteractive(opts) {
|
|
|
2309
2478
|
const ncr = opts.ncrAppkey?.trim() ? { appkey: opts.ncrAppkey.trim() } : void 0;
|
|
2310
2479
|
const ncs = opts.ncsAppkey?.trim() ? { appkey: opts.ncsAppkey.trim() } : void 0;
|
|
2311
2480
|
const apigateway = opts.apigatewayAppkey?.trim() ? { appkey: opts.apigatewayAppkey.trim() } : void 0;
|
|
2481
|
+
const skm = opts.skmAppkey?.trim() ? { appkey: opts.skmAppkey.trim() } : void 0;
|
|
2312
2482
|
const deploy = opts.deployAppkey?.trim() ? { appkey: opts.deployAppkey.trim() } : void 0;
|
|
2313
|
-
if (!uak && !logncrash && !iaas && !ncr && !ncs && !apigateway && !deploy) {
|
|
2483
|
+
if (!uak && !logncrash && !iaas && !ncr && !ncs && !apigateway && !skm && !deploy) {
|
|
2314
2484
|
throw new NhnCloudCliError(
|
|
2315
|
-
"\uBE44\uB300\uD654\uD615 \uBAA8\uB4DC: --uak-id + UAK secret, --logncrash-appkey,\n--iaas-tenant-id + --iaas-username + iaas password,\n--ncr-appkey, --ncs-appkey, --apigateway-appkey, \uB610\uB294 --deploy-appkey\n\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.",
|
|
2485
|
+
"\uBE44\uB300\uD654\uD615 \uBAA8\uB4DC: --uak-id + UAK secret, --logncrash-appkey,\n--iaas-tenant-id + --iaas-username + iaas password,\n--ncr-appkey, --ncs-appkey, --apigateway-appkey, --skm-appkey, \uB610\uB294 --deploy-appkey\n\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.",
|
|
2316
2486
|
EXIT_PARAM_ERROR
|
|
2317
2487
|
);
|
|
2318
2488
|
}
|
|
@@ -2331,6 +2501,7 @@ async function runNonInteractive(opts) {
|
|
|
2331
2501
|
ncr,
|
|
2332
2502
|
ncs,
|
|
2333
2503
|
apigateway,
|
|
2504
|
+
skm,
|
|
2334
2505
|
deploy,
|
|
2335
2506
|
opts.verify,
|
|
2336
2507
|
logncrashUak
|
|
@@ -2339,8 +2510,8 @@ async function runNonInteractive(opts) {
|
|
|
2339
2510
|
var configureCommand = new import_commander2.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(
|
|
2340
2511
|
"--iaas-password <pass>",
|
|
2341
2512
|
"iaas API \uBE44\uBC00\uBC88\uD638 (\uBE44\uB300\uD654\uD615, \uB178\uCD9C \uBC29\uC9C0\uB85C env NHNCLOUD_IAAS_PASSWORD \uAD8C\uC7A5)"
|
|
2342
|
-
).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("--apigateway-appkey <key>", "API Gateway appkey (\uBE44\uB300\uD654\uD615)").option("--deploy-appkey <key>", "deploy appkey (\uBE44\uB300\uD654\uD615)").option("--no-verify", "\uC5F0\uACB0 \uD14C\uC2A4\uD2B8 \uC0DD\uB7B5").action(async (opts) => {
|
|
2343
|
-
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 || opts.apigatewayAppkey !== void 0 || opts.deployAppkey !== void 0;
|
|
2513
|
+
).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("--apigateway-appkey <key>", "API Gateway appkey (\uBE44\uB300\uD654\uD615)").option("--skm-appkey <key>", "Secure Key Manager appkey (\uBE44\uB300\uD654\uD615)").option("--deploy-appkey <key>", "deploy appkey (\uBE44\uB300\uD654\uD615)").option("--no-verify", "\uC5F0\uACB0 \uD14C\uC2A4\uD2B8 \uC0DD\uB7B5").action(async (opts) => {
|
|
2514
|
+
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 || opts.apigatewayAppkey !== void 0 || opts.skmAppkey !== void 0 || opts.deployAppkey !== void 0;
|
|
2344
2515
|
try {
|
|
2345
2516
|
if (hasFlag) {
|
|
2346
2517
|
await runNonInteractive(opts);
|
|
@@ -2498,14 +2669,14 @@ function compareByCodePoint(left, right) {
|
|
|
2498
2669
|
return leftPoints.length - rightPoints.length;
|
|
2499
2670
|
}
|
|
2500
2671
|
function ensureRegularFile(filePath) {
|
|
2501
|
-
let
|
|
2672
|
+
let stat4;
|
|
2502
2673
|
try {
|
|
2503
|
-
|
|
2674
|
+
stat4 = (0, import_node_fs2.lstatSync)(filePath);
|
|
2504
2675
|
} catch (error) {
|
|
2505
2676
|
const reason = error instanceof Error ? error.message : String(error);
|
|
2506
2677
|
throw new NhnCloudCliError(`\uC2A4\uD0AC \uD30C\uC77C\uC744 \uD655\uC778\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${filePath} (${reason})`, EXIT_PARAM_ERROR);
|
|
2507
2678
|
}
|
|
2508
|
-
if (
|
|
2679
|
+
if (stat4.isSymbolicLink() || !stat4.isFile()) {
|
|
2509
2680
|
throw new NhnCloudCliError(`\uC2A4\uD0AC \uCF58\uD150\uCE20\uB294 \uC815\uADDC \uD30C\uC77C\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4: ${filePath}`, EXIT_PARAM_ERROR);
|
|
2510
2681
|
}
|
|
2511
2682
|
}
|
|
@@ -2522,21 +2693,21 @@ function collectReferenceFiles(referencesRoot, currentDir, files) {
|
|
|
2522
2693
|
}
|
|
2523
2694
|
for (const entry of entries) {
|
|
2524
2695
|
const entryPath = import_node_path4.default.join(currentDir, entry.name);
|
|
2525
|
-
let
|
|
2696
|
+
let stat4;
|
|
2526
2697
|
try {
|
|
2527
|
-
|
|
2698
|
+
stat4 = (0, import_node_fs2.lstatSync)(entryPath);
|
|
2528
2699
|
} catch (error) {
|
|
2529
2700
|
const reason = error instanceof Error ? error.message : String(error);
|
|
2530
2701
|
throw new NhnCloudCliError(`\uC2A4\uD0AC \uCF58\uD150\uCE20\uB97C \uD655\uC778\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${entryPath} (${reason})`, EXIT_PARAM_ERROR);
|
|
2531
2702
|
}
|
|
2532
|
-
if (
|
|
2703
|
+
if (stat4.isSymbolicLink()) {
|
|
2533
2704
|
throw new NhnCloudCliError(`\uC2A4\uD0AC \uCF58\uD150\uCE20\uC5D0 \uC2EC\uBCFC\uB9AD \uB9C1\uD06C\uB97C \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${entryPath}`, EXIT_PARAM_ERROR);
|
|
2534
2705
|
}
|
|
2535
|
-
if (
|
|
2706
|
+
if (stat4.isDirectory()) {
|
|
2536
2707
|
collectReferenceFiles(referencesRoot, entryPath, files);
|
|
2537
2708
|
continue;
|
|
2538
2709
|
}
|
|
2539
|
-
if (!
|
|
2710
|
+
if (!stat4.isFile()) {
|
|
2540
2711
|
throw new NhnCloudCliError(`\uC2A4\uD0AC \uCF58\uD150\uCE20\uB294 \uC815\uADDC \uD30C\uC77C \uB610\uB294 \uB514\uB809\uD130\uB9AC\uC5EC\uC57C \uD569\uB2C8\uB2E4: ${entryPath}`, EXIT_PARAM_ERROR);
|
|
2541
2712
|
}
|
|
2542
2713
|
files.push(`references/${import_node_path4.default.relative(referencesRoot, entryPath).split(import_node_path4.default.sep).join("/")}`);
|
|
@@ -2584,12 +2755,24 @@ function calculateSkillContentDigest(skillRoot) {
|
|
|
2584
2755
|
var PACKAGE_NAME3 = "@bifos/nhncloud-cli";
|
|
2585
2756
|
var SKILL_NAME2 = "nhncloud-cli";
|
|
2586
2757
|
var DIGEST_HEX_PATTERN = /^[0-9a-f]{64}$/;
|
|
2587
|
-
var
|
|
2758
|
+
var SKILL_AGENTS = ["claude", "codex"];
|
|
2759
|
+
var SKILL_AGENT_NAMES = { claude: "Claude Code", codex: "Codex" };
|
|
2760
|
+
var STATUS_PRIORITY = [
|
|
2761
|
+
"corrupt",
|
|
2762
|
+
"modified",
|
|
2763
|
+
"unmanaged",
|
|
2764
|
+
"broken",
|
|
2765
|
+
"outdated",
|
|
2766
|
+
"missing",
|
|
2767
|
+
"current"
|
|
2768
|
+
];
|
|
2769
|
+
var PROTECTED_STATUSES = ["unmanaged", "modified", "corrupt"];
|
|
2770
|
+
var defaultOperations = { rename: import_promises3.rename, rm: import_promises3.rm };
|
|
2588
2771
|
function sourcePath(context) {
|
|
2589
2772
|
return import_node_path5.default.join(context.packageRoot, "skills", SKILL_NAME2);
|
|
2590
2773
|
}
|
|
2591
|
-
function destinationPath(context) {
|
|
2592
|
-
return import_node_path5.default.join(context.homeDir, ".claude", "skills", SKILL_NAME2);
|
|
2774
|
+
function destinationPath(context, agent) {
|
|
2775
|
+
return agent === "claude" ? import_node_path5.default.join(context.homeDir, ".claude", "skills", SKILL_NAME2) : import_node_path5.default.join(context.homeDir, ".agents", "skills", SKILL_NAME2);
|
|
2593
2776
|
}
|
|
2594
2777
|
function resolveLinkTarget(linkPath, rawTarget) {
|
|
2595
2778
|
return import_node_path5.default.isAbsolute(rawTarget) ? import_node_path5.default.normalize(rawTarget) : import_node_path5.default.resolve(import_node_path5.default.dirname(linkPath), rawTarget);
|
|
@@ -2700,16 +2883,74 @@ async function inspectRepository(targetPath, expected) {
|
|
|
2700
2883
|
}
|
|
2701
2884
|
return { status: "valid", installedVersion: manifest.packageVersion };
|
|
2702
2885
|
}
|
|
2703
|
-
function statusBase(context) {
|
|
2886
|
+
function statusBase(context, agent) {
|
|
2704
2887
|
return {
|
|
2705
2888
|
schemaVersion: 1,
|
|
2706
|
-
destination: destinationPath(context),
|
|
2889
|
+
destination: destinationPath(context, agent),
|
|
2707
2890
|
source: sourcePath(context),
|
|
2708
2891
|
currentVersion: context.currentVersion
|
|
2709
2892
|
};
|
|
2710
2893
|
}
|
|
2711
|
-
async function
|
|
2712
|
-
const
|
|
2894
|
+
async function managedRepositoryStatus(context, base, linkTarget, repositoryLocation, isExpectedPath) {
|
|
2895
|
+
const repositoryName = parseRepositoryName(repositoryLocation);
|
|
2896
|
+
if (!repositoryName) {
|
|
2897
|
+
return { ...base, status: "corrupt", linkTarget, managed: true };
|
|
2898
|
+
}
|
|
2899
|
+
const repository = await inspectRepository(repositoryLocation, repositoryName);
|
|
2900
|
+
if (repository.status === "modified" || repository.status === "corrupt") {
|
|
2901
|
+
return {
|
|
2902
|
+
...base,
|
|
2903
|
+
status: repository.status,
|
|
2904
|
+
installedVersion: repository.installedVersion ?? repositoryName.version,
|
|
2905
|
+
linkTarget,
|
|
2906
|
+
managed: true
|
|
2907
|
+
};
|
|
2908
|
+
}
|
|
2909
|
+
if (repository.status === "missing") {
|
|
2910
|
+
return {
|
|
2911
|
+
...base,
|
|
2912
|
+
status: "broken",
|
|
2913
|
+
installedVersion: repositoryName.version,
|
|
2914
|
+
linkTarget,
|
|
2915
|
+
managed: true
|
|
2916
|
+
};
|
|
2917
|
+
}
|
|
2918
|
+
const currentDigest = calculateSkillContentDigest(base.source);
|
|
2919
|
+
const isCurrent = repositoryName.version === context.currentVersion && repositoryName.digest === currentDigest && await isExpectedPath(repositoryPath(context, currentDigest));
|
|
2920
|
+
return {
|
|
2921
|
+
...base,
|
|
2922
|
+
status: isCurrent ? "current" : "outdated",
|
|
2923
|
+
installedVersion: repository.installedVersion,
|
|
2924
|
+
linkTarget,
|
|
2925
|
+
managed: true
|
|
2926
|
+
};
|
|
2927
|
+
}
|
|
2928
|
+
async function optionalRealpath(targetPath) {
|
|
2929
|
+
try {
|
|
2930
|
+
return await (0, import_promises3.realpath)(targetPath);
|
|
2931
|
+
} catch (error) {
|
|
2932
|
+
if (isNodeError(error, "ENOENT")) {
|
|
2933
|
+
return void 0;
|
|
2934
|
+
}
|
|
2935
|
+
throw managerError(`\uC2A4\uD0AC \uACBD\uB85C\uB97C \uD655\uC778\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${targetPath}`, error);
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
async function inspectIndirectManagedLink(context, base, linkTarget) {
|
|
2939
|
+
const realRoot = await optionalRealpath(repositoryRoot(context));
|
|
2940
|
+
if (!realRoot) {
|
|
2941
|
+
return void 0;
|
|
2942
|
+
}
|
|
2943
|
+
const realTarget = await optionalRealpath(linkTarget);
|
|
2944
|
+
if (!realTarget || import_node_path5.default.dirname(realTarget) !== realRoot) {
|
|
2945
|
+
return void 0;
|
|
2946
|
+
}
|
|
2947
|
+
return managedRepositoryStatus(context, base, linkTarget, realTarget, async (expectedPath) => {
|
|
2948
|
+
const realExpected = await optionalRealpath(expectedPath);
|
|
2949
|
+
return realExpected !== void 0 && realExpected === realTarget;
|
|
2950
|
+
});
|
|
2951
|
+
}
|
|
2952
|
+
async function inspectAgentSkill(context, agent) {
|
|
2953
|
+
const base = statusBase(context, agent);
|
|
2713
2954
|
const destinationStat = await optionalLstat(base.destination);
|
|
2714
2955
|
if (!destinationStat) {
|
|
2715
2956
|
return { ...base, status: "missing", managed: false };
|
|
@@ -2742,38 +2983,17 @@ async function inspectSkill(context) {
|
|
|
2742
2983
|
};
|
|
2743
2984
|
}
|
|
2744
2985
|
if (isManagedRepositoryLocation(context, linkTarget)) {
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
const repository = await inspectRepository(linkTarget, repositoryName);
|
|
2749
|
-
if (repository.status === "modified" || repository.status === "corrupt") {
|
|
2750
|
-
return {
|
|
2751
|
-
...base,
|
|
2752
|
-
status: repository.status,
|
|
2753
|
-
installedVersion: repository.installedVersion ?? repositoryName.version,
|
|
2754
|
-
linkTarget,
|
|
2755
|
-
managed: true
|
|
2756
|
-
};
|
|
2757
|
-
}
|
|
2758
|
-
if (repository.status === "missing") {
|
|
2759
|
-
return {
|
|
2760
|
-
...base,
|
|
2761
|
-
status: "broken",
|
|
2762
|
-
installedVersion: repositoryName.version,
|
|
2763
|
-
linkTarget,
|
|
2764
|
-
managed: true
|
|
2765
|
-
};
|
|
2766
|
-
}
|
|
2767
|
-
const currentDigest = calculateSkillContentDigest(base.source);
|
|
2768
|
-
const expectedPath = repositoryPath(context, currentDigest);
|
|
2769
|
-
const isCurrent = repositoryName.version === context.currentVersion && repositoryName.digest === currentDigest && import_node_path5.default.resolve(linkTarget) === import_node_path5.default.resolve(expectedPath);
|
|
2770
|
-
return {
|
|
2771
|
-
...base,
|
|
2772
|
-
status: isCurrent ? "current" : "outdated",
|
|
2773
|
-
installedVersion: repository.installedVersion,
|
|
2986
|
+
return managedRepositoryStatus(
|
|
2987
|
+
context,
|
|
2988
|
+
base,
|
|
2774
2989
|
linkTarget,
|
|
2775
|
-
|
|
2776
|
-
|
|
2990
|
+
linkTarget,
|
|
2991
|
+
async (expectedPath) => import_node_path5.default.resolve(linkTarget) === import_node_path5.default.resolve(expectedPath)
|
|
2992
|
+
);
|
|
2993
|
+
}
|
|
2994
|
+
const indirect = await inspectIndirectManagedLink(context, base, linkTarget);
|
|
2995
|
+
if (indirect) {
|
|
2996
|
+
return indirect;
|
|
2777
2997
|
}
|
|
2778
2998
|
const legacyPackage = targetStat.isDirectory() ? await readLegacyPackageMetadata(linkTarget) : void 0;
|
|
2779
2999
|
if (legacyPackage) {
|
|
@@ -2787,6 +3007,14 @@ async function inspectSkill(context) {
|
|
|
2787
3007
|
}
|
|
2788
3008
|
return { ...base, status: "unmanaged", linkTarget, managed: false };
|
|
2789
3009
|
}
|
|
3010
|
+
function aggregateStatus(statuses) {
|
|
3011
|
+
return STATUS_PRIORITY.find((token) => statuses.some((status) => status.status === token)) ?? "current";
|
|
3012
|
+
}
|
|
3013
|
+
async function inspectSkill(context) {
|
|
3014
|
+
const claude = await inspectAgentSkill(context, "claude");
|
|
3015
|
+
const codex = await inspectAgentSkill(context, "codex");
|
|
3016
|
+
return { ...claude, status: aggregateStatus([claude, codex]), agents: { claude, codex } };
|
|
3017
|
+
}
|
|
2790
3018
|
function utcBackupSuffix() {
|
|
2791
3019
|
return `${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}-${(0, import_node_crypto3.randomUUID)()}`;
|
|
2792
3020
|
}
|
|
@@ -2883,35 +3111,123 @@ async function prepareRepository(context, force, operations) {
|
|
|
2883
3111
|
await (0, import_promises3.rm)(staging, { recursive: true, force: true });
|
|
2884
3112
|
}
|
|
2885
3113
|
}
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
const
|
|
2891
|
-
const
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
3114
|
+
function temporaryLinkPath(destination) {
|
|
3115
|
+
return import_node_path5.default.join(import_node_path5.default.dirname(destination), `.${SKILL_NAME2}.link-${(0, import_node_crypto3.randomUUID)()}`);
|
|
3116
|
+
}
|
|
3117
|
+
async function planLinkSwitches(context, previous) {
|
|
3118
|
+
const switches = [];
|
|
3119
|
+
for (const agent of SKILL_AGENTS) {
|
|
3120
|
+
const agentStatus = previous.agents[agent];
|
|
3121
|
+
if (agentStatus.status === "current") {
|
|
3122
|
+
continue;
|
|
3123
|
+
}
|
|
3124
|
+
const destination = destinationPath(context, agent);
|
|
3125
|
+
const parent = import_node_path5.default.dirname(destination);
|
|
3126
|
+
await (0, import_promises3.mkdir)(parent, { recursive: true });
|
|
3127
|
+
const resolvedDestination = import_node_path5.default.join(await (0, import_promises3.realpath)(parent), import_node_path5.default.basename(destination));
|
|
3128
|
+
const sameTarget = switches.find((entry) => entry.resolvedDestination === resolvedDestination);
|
|
3129
|
+
if (sameTarget) {
|
|
3130
|
+
sameTarget.agents.push(agent);
|
|
3131
|
+
continue;
|
|
3132
|
+
}
|
|
3133
|
+
let previousRawTarget;
|
|
3134
|
+
if (agentStatus.status !== "missing" && agentStatus.status !== "unmanaged") {
|
|
2900
3135
|
try {
|
|
2901
|
-
await
|
|
3136
|
+
previousRawTarget = await (0, import_promises3.readlink)(destination);
|
|
2902
3137
|
} catch (error) {
|
|
2903
|
-
|
|
3138
|
+
throw managerError(`\uC2A4\uD0AC \uB9C1\uD06C\uB97C \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${destination}`, error);
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3141
|
+
switches.push({
|
|
3142
|
+
agents: [agent],
|
|
3143
|
+
destination,
|
|
3144
|
+
resolvedDestination,
|
|
3145
|
+
previous: agentStatus,
|
|
3146
|
+
previousRawTarget,
|
|
3147
|
+
temporaryLink: temporaryLinkPath(destination),
|
|
3148
|
+
activated: false
|
|
3149
|
+
});
|
|
3150
|
+
}
|
|
3151
|
+
return switches;
|
|
3152
|
+
}
|
|
3153
|
+
async function rollbackLinkSwitches(switches, operations, temporaryLinks) {
|
|
3154
|
+
const failed = [];
|
|
3155
|
+
const preservedBackups = [];
|
|
3156
|
+
const removeEntry = operations.rm ?? defaultOperations.rm;
|
|
3157
|
+
let firstError;
|
|
3158
|
+
for (const entry of [...switches].reverse()) {
|
|
3159
|
+
try {
|
|
3160
|
+
if (entry.activated && entry.backup) {
|
|
3161
|
+
await removeEntry(entry.destination, { force: true });
|
|
3162
|
+
await operations.rename(entry.backup, entry.destination);
|
|
3163
|
+
} else if (entry.activated && entry.previousRawTarget !== void 0) {
|
|
3164
|
+
const restoreLink = temporaryLinkPath(entry.destination);
|
|
3165
|
+
temporaryLinks.push(restoreLink);
|
|
3166
|
+
await (0, import_promises3.symlink)(entry.previousRawTarget, restoreLink);
|
|
3167
|
+
await operations.rename(restoreLink, entry.destination);
|
|
3168
|
+
} else if (entry.activated && entry.previous.status === "missing") {
|
|
3169
|
+
await removeEntry(entry.destination, { force: true });
|
|
3170
|
+
} else if (!entry.activated && entry.backup) {
|
|
3171
|
+
await operations.rename(entry.backup, entry.destination);
|
|
3172
|
+
}
|
|
3173
|
+
} catch (error) {
|
|
3174
|
+
failed.push(entry.destination);
|
|
3175
|
+
if (entry.backup) {
|
|
3176
|
+
preservedBackups.push(entry.backup);
|
|
2904
3177
|
}
|
|
2905
|
-
|
|
3178
|
+
firstError ??= error;
|
|
2906
3179
|
}
|
|
3180
|
+
}
|
|
3181
|
+
return { failed, preservedBackups, firstError };
|
|
3182
|
+
}
|
|
3183
|
+
async function switchActiveLinks(context, repository, previous, operations) {
|
|
3184
|
+
const switches = await planLinkSwitches(context, previous);
|
|
3185
|
+
const temporaryLinks = switches.map((entry) => entry.temporaryLink);
|
|
3186
|
+
const backupPaths = [];
|
|
3187
|
+
try {
|
|
3188
|
+
let failure;
|
|
3189
|
+
let failedAfterVerification = false;
|
|
2907
3190
|
try {
|
|
2908
|
-
|
|
3191
|
+
for (const entry of switches) {
|
|
3192
|
+
await (0, import_promises3.symlink)(repository, entry.temporaryLink);
|
|
3193
|
+
}
|
|
3194
|
+
for (const entry of switches) {
|
|
3195
|
+
if (entry.previous.status === "unmanaged") {
|
|
3196
|
+
entry.backup = await backupPath(entry.destination, operations);
|
|
3197
|
+
backupPaths.push(entry.backup);
|
|
3198
|
+
}
|
|
3199
|
+
await operations.rename(entry.temporaryLink, entry.destination);
|
|
3200
|
+
entry.activated = true;
|
|
3201
|
+
}
|
|
3202
|
+
const status = await inspectSkill(context);
|
|
3203
|
+
if (status.status === "current") {
|
|
3204
|
+
return { backupPaths, status };
|
|
3205
|
+
}
|
|
3206
|
+
failure = managerError(`\uC2A4\uD0AC \uC124\uCE58 \uD6C4 \uC0C1\uD0DC\uAC00 current\uAC00 \uC544\uB2D9\uB2C8\uB2E4: ${status.status}`);
|
|
3207
|
+
failedAfterVerification = true;
|
|
2909
3208
|
} catch (error) {
|
|
2910
|
-
|
|
3209
|
+
failure = error;
|
|
2911
3210
|
}
|
|
2912
|
-
|
|
3211
|
+
const rollback = await rollbackLinkSwitches(switches, operations, temporaryLinks);
|
|
3212
|
+
if (rollback.failed.length > 0) {
|
|
3213
|
+
throw managerError(
|
|
3214
|
+
`\uC2A4\uD0AC \uC804\uD658\uC5D0 \uC2E4\uD328\uD588\uACE0 \uC77C\uBD80 \uACBD\uB85C\uB97C \uB418\uB3CC\uB9AC\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${rollback.failed.join(", ")}; \uBCF4\uC874\uD55C \uBC31\uC5C5: ${rollback.preservedBackups.join(", ") || "\uC5C6\uC74C"}; \uC804\uD658 \uC624\uB958: ${toReason(failure)}`,
|
|
3215
|
+
rollback.firstError
|
|
3216
|
+
);
|
|
3217
|
+
}
|
|
3218
|
+
if (failedAfterVerification) {
|
|
3219
|
+
throw failure;
|
|
3220
|
+
}
|
|
3221
|
+
const changed = switches.filter((entry) => entry.activated || entry.backup !== void 0);
|
|
3222
|
+
if (changed.length === 0) {
|
|
3223
|
+
throw managerError("\uC2A4\uD0AC \uC804\uD658\uC744 \uC2DC\uC791\uD558\uC9C0 \uBABB\uD574 \uC5B4\uB5A4 \uACBD\uB85C\uB3C4 \uBC14\uAFB8\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4", failure);
|
|
3224
|
+
}
|
|
3225
|
+
throw managerError(
|
|
3226
|
+
`\uC2A4\uD0AC \uC804\uD658\uC5D0 \uC2E4\uD328\uD574 \uBC14\uAFBC \uACBD\uB85C\uB97C \uC774\uC804 \uC0C1\uD0DC\uB85C \uB418\uB3CC\uB838\uC2B5\uB2C8\uB2E4: ${changed.map((entry) => entry.destination).join(", ")}`,
|
|
3227
|
+
failure
|
|
3228
|
+
);
|
|
2913
3229
|
} finally {
|
|
2914
|
-
await (0, import_promises3.rm)(
|
|
3230
|
+
await Promise.all(temporaryLinks.map((link) => (0, import_promises3.rm)(link, { force: true })));
|
|
2915
3231
|
}
|
|
2916
3232
|
}
|
|
2917
3233
|
function installAction(status) {
|
|
@@ -2946,23 +3262,26 @@ async function installSkillInternal(context, options = {}, operations = defaultO
|
|
|
2946
3262
|
backupPaths: []
|
|
2947
3263
|
};
|
|
2948
3264
|
}
|
|
2949
|
-
if (
|
|
2950
|
-
|
|
3265
|
+
if (!force) {
|
|
3266
|
+
for (const agent of SKILL_AGENTS) {
|
|
3267
|
+
const agentStatus = previousStatus.agents[agent];
|
|
3268
|
+
if (PROTECTED_STATUSES.includes(agentStatus.status)) {
|
|
3269
|
+
throw managerError(
|
|
3270
|
+
`${SKILL_AGENT_NAMES[agent]} \uC2A4\uD0AC \uC0C1\uD0DC\uAC00 ${agentStatus.status}\uC785\uB2C8\uB2E4. --force\uB85C \uBC31\uC5C5 \uD6C4 \uAD50\uCCB4\uD558\uC138\uC694: ${agentStatus.destination}`
|
|
3271
|
+
);
|
|
3272
|
+
}
|
|
3273
|
+
}
|
|
2951
3274
|
}
|
|
2952
3275
|
const prepared = await prepareRepository(context, force, operations);
|
|
2953
|
-
const
|
|
2954
|
-
const status = await inspectSkill(context);
|
|
2955
|
-
if (status.status !== "current") {
|
|
2956
|
-
throw managerError(`\uC2A4\uD0AC \uC124\uCE58 \uD6C4 \uC0C1\uD0DC\uAC00 current\uAC00 \uC544\uB2D9\uB2C8\uB2E4: ${status.status}`);
|
|
2957
|
-
}
|
|
3276
|
+
const switched = await switchActiveLinks(context, prepared.repository, previousStatus, operations);
|
|
2958
3277
|
return {
|
|
2959
3278
|
schemaVersion: 1,
|
|
2960
3279
|
action: installAction(previousStatus.status),
|
|
2961
3280
|
changed: true,
|
|
2962
3281
|
previousStatus,
|
|
2963
|
-
status,
|
|
3282
|
+
status: switched.status,
|
|
2964
3283
|
repositoryPath: prepared.repository,
|
|
2965
|
-
backupPaths: [...prepared.backupPaths, ...
|
|
3284
|
+
backupPaths: [...prepared.backupPaths, ...switched.backupPaths]
|
|
2966
3285
|
};
|
|
2967
3286
|
}
|
|
2968
3287
|
async function installSkill(context, options = {}, operations = defaultOperations) {
|
|
@@ -2975,73 +3294,185 @@ async function installSkill(context, options = {}, operations = defaultOperation
|
|
|
2975
3294
|
throw managerError("\uC2A4\uD0AC\uC744 \uC124\uCE58\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.", error);
|
|
2976
3295
|
}
|
|
2977
3296
|
}
|
|
3297
|
+
async function tryRestoreCandidate(candidate, destination, operations) {
|
|
3298
|
+
try {
|
|
3299
|
+
if (await optionalLstat(destination)) {
|
|
3300
|
+
return { restored: false, preserved: candidate };
|
|
3301
|
+
}
|
|
3302
|
+
await operations.rename(candidate, destination);
|
|
3303
|
+
return { restored: true };
|
|
3304
|
+
} catch (error) {
|
|
3305
|
+
return { restored: false, error, preserved: candidate };
|
|
3306
|
+
}
|
|
3307
|
+
}
|
|
2978
3308
|
async function restoreUninstallCandidate(candidate, destination, operations, originalError) {
|
|
2979
|
-
|
|
3309
|
+
const result = await tryRestoreCandidate(candidate, destination, operations);
|
|
3310
|
+
if (result.restored) {
|
|
3311
|
+
throw managerError(`\uD65C\uC131 \uC2A4\uD0AC \uB9C1\uD06C\uB97C \uC81C\uAC70\uD558\uC9C0 \uC54A\uACE0 \uC6D0\uB798 \uC704\uCE58\uB85C \uBCF5\uC6D0\uD588\uC2B5\uB2C8\uB2E4: ${destination}`, originalError);
|
|
3312
|
+
}
|
|
3313
|
+
if (result.error === void 0) {
|
|
2980
3314
|
throw managerError(
|
|
2981
3315
|
`\uD65C\uC131 \uC2A4\uD0AC \uACBD\uB85C\uAC00 \uB3D9\uC2DC\uC5D0 \uBCC0\uACBD\uB418\uC5B4 \uC81C\uAC70\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uC774\uB3D9\uB41C \uD56D\uBAA9\uC744 \uBCF4\uC874\uD588\uC2B5\uB2C8\uB2E4: ${candidate}`,
|
|
2982
3316
|
originalError
|
|
2983
3317
|
);
|
|
2984
3318
|
}
|
|
3319
|
+
throw managerError(
|
|
3320
|
+
`\uD65C\uC131 \uC2A4\uD0AC \uB9C1\uD06C\uB97C \uC81C\uAC70\uD558\uC9C0 \uBABB\uD588\uACE0 \uC6D0\uB798 \uC704\uCE58\uB85C \uBCF5\uC6D0\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uC774\uB3D9\uB41C \uD56D\uBAA9: ${candidate}; \uC81C\uAC70 \uC624\uB958: ${toReason(originalError)}`,
|
|
3321
|
+
result.error
|
|
3322
|
+
);
|
|
3323
|
+
}
|
|
3324
|
+
async function tryRestoreRemovedLink(destination, rawTarget, operations) {
|
|
3325
|
+
const restoreLink = temporaryLinkPath(destination);
|
|
2985
3326
|
try {
|
|
2986
|
-
await
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
3327
|
+
if (await optionalLstat(destination)) {
|
|
3328
|
+
return { restored: false };
|
|
3329
|
+
}
|
|
3330
|
+
await (0, import_promises3.symlink)(rawTarget, restoreLink);
|
|
3331
|
+
await operations.rename(restoreLink, destination);
|
|
3332
|
+
return { restored: true };
|
|
3333
|
+
} catch (error) {
|
|
3334
|
+
return { restored: false, error };
|
|
3335
|
+
} finally {
|
|
3336
|
+
await (0, import_promises3.rm)(restoreLink, { force: true });
|
|
2992
3337
|
}
|
|
2993
|
-
throw managerError(`\uD65C\uC131 \uC2A4\uD0AC \uB9C1\uD06C\uB97C \uC81C\uAC70\uD558\uC9C0 \uC54A\uACE0 \uC6D0\uB798 \uC704\uCE58\uB85C \uBCF5\uC6D0\uD588\uC2B5\uB2C8\uB2E4: ${destination}`, originalError);
|
|
2994
3338
|
}
|
|
2995
|
-
async function
|
|
2996
|
-
const
|
|
2997
|
-
const
|
|
2998
|
-
|
|
2999
|
-
|
|
3339
|
+
async function planUninstallTargets(context) {
|
|
3340
|
+
const statuses = [];
|
|
3341
|
+
for (const agent of SKILL_AGENTS) {
|
|
3342
|
+
const status = await inspectAgentSkill(context, agent);
|
|
3343
|
+
if (status.status !== "missing" && (!status.managed || !status.linkTarget)) {
|
|
3344
|
+
throw managerError(`\uAD00\uB9AC\uB418\uC9C0 \uC54A\uC740 \uC2A4\uD0AC \uD56D\uBAA9\uC774\uBBC0\uB85C \uC5B4\uB290 \uACBD\uB85C\uB3C4 \uC81C\uAC70\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4: ${status.destination}`);
|
|
3345
|
+
}
|
|
3346
|
+
statuses.push({ agent, status });
|
|
3347
|
+
}
|
|
3348
|
+
const targets = [];
|
|
3349
|
+
for (const { agent, status } of statuses) {
|
|
3350
|
+
if (status.status === "missing" || !status.linkTarget) {
|
|
3351
|
+
continue;
|
|
3352
|
+
}
|
|
3353
|
+
const realParent = await optionalRealpath(import_node_path5.default.dirname(status.destination));
|
|
3354
|
+
if (!realParent) {
|
|
3355
|
+
continue;
|
|
3356
|
+
}
|
|
3357
|
+
const resolvedDestination = import_node_path5.default.join(realParent, import_node_path5.default.basename(status.destination));
|
|
3358
|
+
const sameTarget = targets.find((entry) => entry.resolvedDestination === resolvedDestination);
|
|
3359
|
+
if (sameTarget) {
|
|
3360
|
+
sameTarget.agents.push(agent);
|
|
3361
|
+
continue;
|
|
3362
|
+
}
|
|
3363
|
+
targets.push({
|
|
3364
|
+
agents: [agent],
|
|
3365
|
+
destination: status.destination,
|
|
3366
|
+
resolvedDestination,
|
|
3367
|
+
linkTarget: status.linkTarget
|
|
3368
|
+
});
|
|
3369
|
+
}
|
|
3370
|
+
return targets;
|
|
3371
|
+
}
|
|
3372
|
+
function uninstallRollbackError(results, originalError, handledLabel) {
|
|
3373
|
+
const failed = results.filter(({ result }) => !result.restored);
|
|
3374
|
+
if (failed.length === 0) {
|
|
3375
|
+
return managerError(
|
|
3376
|
+
`\uC2A4\uD0AC \uC81C\uAC70\uC5D0 \uC2E4\uD328\uD574 ${handledLabel}\uB97C \uC774\uC804 \uC0C1\uD0DC\uB85C \uB418\uB3CC\uB838\uC2B5\uB2C8\uB2E4: ${results.map(({ destination }) => destination).join(", ")}`,
|
|
3377
|
+
originalError
|
|
3378
|
+
);
|
|
3000
3379
|
}
|
|
3001
|
-
|
|
3002
|
-
|
|
3380
|
+
const failedText = failed.map(
|
|
3381
|
+
({ destination, result }) => result.preserved ? `${destination} (\uC774\uB3D9\uB41C \uD56D\uBAA9: ${result.preserved})` : destination
|
|
3382
|
+
).join(", ");
|
|
3383
|
+
return managerError(
|
|
3384
|
+
`\uC2A4\uD0AC \uC81C\uAC70\uC5D0 \uC2E4\uD328\uD588\uACE0 \uC77C\uBD80 \uACBD\uB85C\uB97C \uB418\uB3CC\uB9AC\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${failedText}; \uC81C\uAC70 \uC624\uB958: ${toReason(originalError)}`,
|
|
3385
|
+
failed.find(({ result }) => result.error !== void 0)?.result.error
|
|
3386
|
+
);
|
|
3387
|
+
}
|
|
3388
|
+
async function rollbackMovedCandidates(moved, operations, originalError) {
|
|
3389
|
+
const results = [];
|
|
3390
|
+
for (const target of [...moved].reverse()) {
|
|
3391
|
+
results.push({
|
|
3392
|
+
destination: target.destination,
|
|
3393
|
+
result: await tryRestoreCandidate(target.candidate, target.destination, operations)
|
|
3394
|
+
});
|
|
3003
3395
|
}
|
|
3396
|
+
throw uninstallRollbackError(results, originalError, "\uC62E\uAE34 \uACBD\uB85C");
|
|
3397
|
+
}
|
|
3398
|
+
async function moveUninstallCandidate(target, moved, operations) {
|
|
3399
|
+
const { destination } = target;
|
|
3004
3400
|
const candidate = import_node_path5.default.join(import_node_path5.default.dirname(destination), `.${SKILL_NAME2}.uninstall-${(0, import_node_crypto3.randomUUID)()}`);
|
|
3005
3401
|
try {
|
|
3006
3402
|
await operations.rename(destination, candidate);
|
|
3007
3403
|
} catch (error) {
|
|
3008
3404
|
if (isNodeError(error, "ENOENT")) {
|
|
3009
|
-
return
|
|
3405
|
+
return void 0;
|
|
3406
|
+
}
|
|
3407
|
+
const moveError = managerError(`\uD65C\uC131 \uC2A4\uD0AC \uB9C1\uD06C\uB97C \uC81C\uAC70\uC6A9 \uC784\uC2DC \uACBD\uB85C\uB85C \uC774\uB3D9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${destination}`, error);
|
|
3408
|
+
if (moved.length === 0) {
|
|
3409
|
+
throw moveError;
|
|
3010
3410
|
}
|
|
3011
|
-
|
|
3411
|
+
return await rollbackMovedCandidates(moved, operations, moveError);
|
|
3012
3412
|
}
|
|
3013
|
-
let
|
|
3413
|
+
let rawTarget;
|
|
3414
|
+
let verificationError;
|
|
3014
3415
|
try {
|
|
3015
3416
|
const candidateStat = await (0, import_promises3.lstat)(candidate);
|
|
3016
3417
|
if (!candidateStat.isSymbolicLink()) {
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
new Error("\uAC80\uC0AC \uD6C4 \uD65C\uC131 \
|
|
3022
|
-
|
|
3418
|
+
verificationError = new Error("\uAC80\uC0AC \uD6C4 \uD65C\uC131 \uACBD\uB85C\uAC00 \uC2EC\uBCFC\uB9AD \uB9C1\uD06C\uAC00 \uC544\uB2CC \uD56D\uBAA9\uC73C\uB85C \uBCC0\uACBD\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
|
|
3419
|
+
} else {
|
|
3420
|
+
rawTarget = await (0, import_promises3.readlink)(candidate);
|
|
3421
|
+
if (resolveLinkTarget(destination, rawTarget) !== target.linkTarget) {
|
|
3422
|
+
verificationError = new Error("\uAC80\uC0AC \uD6C4 \uD65C\uC131 \uC2A4\uD0AC \uB9C1\uD06C \uB300\uC0C1\uC774 \uBCC0\uACBD\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
|
|
3423
|
+
}
|
|
3023
3424
|
}
|
|
3024
|
-
candidateTarget = resolveLinkTarget(destination, await (0, import_promises3.readlink)(candidate));
|
|
3025
3425
|
} catch (error) {
|
|
3026
|
-
|
|
3027
|
-
throw error;
|
|
3028
|
-
}
|
|
3029
|
-
return await restoreUninstallCandidate(candidate, destination, operations, error);
|
|
3426
|
+
verificationError = error;
|
|
3030
3427
|
}
|
|
3031
|
-
if (
|
|
3032
|
-
|
|
3033
|
-
candidate,
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
new Error("\uAC80\uC0AC \uD6C4 \uD65C\uC131 \uC2A4\uD0AC \uB9C1\uD06C \uB300\uC0C1\uC774 \uBCC0\uACBD\uB418\uC5C8\uC2B5\uB2C8\uB2E4.")
|
|
3037
|
-
);
|
|
3428
|
+
if (verificationError !== void 0 || rawTarget === void 0) {
|
|
3429
|
+
if (moved.length === 0) {
|
|
3430
|
+
return await restoreUninstallCandidate(candidate, destination, operations, verificationError);
|
|
3431
|
+
}
|
|
3432
|
+
return await rollbackMovedCandidates([...moved, { destination, candidate }], operations, verificationError);
|
|
3038
3433
|
}
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3434
|
+
return { ...target, candidate, rawTarget };
|
|
3435
|
+
}
|
|
3436
|
+
async function removeUninstallCandidates(moved, operations) {
|
|
3437
|
+
const removeEntry = operations.rm ?? defaultOperations.rm;
|
|
3438
|
+
for (const [index, target] of moved.entries()) {
|
|
3439
|
+
try {
|
|
3440
|
+
await removeEntry(target.candidate, { force: true });
|
|
3441
|
+
} catch (originalError) {
|
|
3442
|
+
if (index === 0) {
|
|
3443
|
+
if (moved.length === 1) {
|
|
3444
|
+
return await restoreUninstallCandidate(target.candidate, target.destination, operations, originalError);
|
|
3445
|
+
}
|
|
3446
|
+
return await rollbackMovedCandidates(moved, operations, originalError);
|
|
3447
|
+
}
|
|
3448
|
+
const results = [];
|
|
3449
|
+
for (const [restoreIndex, entry] of moved.entries()) {
|
|
3450
|
+
const result = restoreIndex < index ? await tryRestoreRemovedLink(entry.destination, entry.rawTarget, operations) : await tryRestoreCandidate(entry.candidate, entry.destination, operations);
|
|
3451
|
+
results.push({ destination: entry.destination, result });
|
|
3452
|
+
}
|
|
3453
|
+
throw uninstallRollbackError(results, originalError, "\uC9C0\uC6B4 \uACBD\uB85C");
|
|
3454
|
+
}
|
|
3043
3455
|
}
|
|
3044
|
-
|
|
3456
|
+
}
|
|
3457
|
+
async function uninstallSkill(context, operations = defaultOperations) {
|
|
3458
|
+
const targets = await planUninstallTargets(context);
|
|
3459
|
+
const moved = [];
|
|
3460
|
+
for (const target of targets) {
|
|
3461
|
+
const movedTarget = await moveUninstallCandidate(target, moved, operations);
|
|
3462
|
+
if (movedTarget) {
|
|
3463
|
+
moved.push(movedTarget);
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
await removeUninstallCandidates(moved, operations);
|
|
3467
|
+
const agentResult = (agent) => ({
|
|
3468
|
+
action: moved.some((target) => target.agents.includes(agent)) ? "removed" : "absent",
|
|
3469
|
+
destination: destinationPath(context, agent)
|
|
3470
|
+
});
|
|
3471
|
+
const agents = { claude: agentResult("claude"), codex: agentResult("codex") };
|
|
3472
|
+
return {
|
|
3473
|
+
action: SKILL_AGENTS.some((agent) => agents[agent].action === "removed") ? "removed" : "absent",
|
|
3474
|
+
agents
|
|
3475
|
+
};
|
|
3045
3476
|
}
|
|
3046
3477
|
|
|
3047
3478
|
// src/formatters/table.ts
|
|
@@ -3117,9 +3548,16 @@ function outputSkillStatus(opts, status) {
|
|
|
3117
3548
|
rows: [
|
|
3118
3549
|
["\uC0C1\uD0DC", status.status],
|
|
3119
3550
|
["\uD604\uC7AC \uBC84\uC804", status.currentVersion],
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3551
|
+
...SKILL_AGENTS.flatMap((agent) => {
|
|
3552
|
+
const name = SKILL_AGENT_NAMES[agent];
|
|
3553
|
+
const agentStatus = status.agents[agent];
|
|
3554
|
+
return [
|
|
3555
|
+
[`${name} \uC0C1\uD0DC`, agentStatus.status],
|
|
3556
|
+
[`${name} \uC124\uCE58 \uBC84\uC804`, terminalText(agentStatus.installedVersion)],
|
|
3557
|
+
[`${name} \uC124\uCE58 \uACBD\uB85C`, terminalText(agentStatus.destination)],
|
|
3558
|
+
[`${name} \uB9C1\uD06C \uB300\uC0C1`, terminalText(agentStatus.linkTarget)]
|
|
3559
|
+
];
|
|
3560
|
+
}),
|
|
3123
3561
|
["\uBCF5\uAD6C \uBA85\uB839", skillRecoveryCommand(status.status) ?? "\uC870\uCE58 \uC5C6\uC74C"]
|
|
3124
3562
|
],
|
|
3125
3563
|
raw: status,
|
|
@@ -3134,7 +3572,10 @@ function outputSkillInstallResult(opts, result) {
|
|
|
3134
3572
|
["\uBCC0\uACBD \uC5EC\uBD80", result.changed ? "\uBCC0\uACBD\uB428" : "\uBCC0\uACBD \uC5C6\uC74C"],
|
|
3135
3573
|
["\uC774\uC804 \uC0C1\uD0DC", result.previousStatus.status],
|
|
3136
3574
|
["\uD604\uC7AC \uC0C1\uD0DC", result.status.status],
|
|
3137
|
-
|
|
3575
|
+
...SKILL_AGENTS.map((agent) => [
|
|
3576
|
+
`${SKILL_AGENT_NAMES[agent]} \uC124\uCE58 \uACBD\uB85C`,
|
|
3577
|
+
terminalText(result.status.agents[agent].destination)
|
|
3578
|
+
]),
|
|
3138
3579
|
["\uAD00\uB9AC \uC800\uC7A5\uC18C", terminalText(result.repositoryPath)],
|
|
3139
3580
|
[
|
|
3140
3581
|
"\uBC31\uC5C5 \uACBD\uB85C",
|
|
@@ -3150,7 +3591,14 @@ function outputSkillUninstallResult(opts, result) {
|
|
|
3150
3591
|
headers: ["\uD56D\uBAA9", "\uAC12"],
|
|
3151
3592
|
rows: [
|
|
3152
3593
|
["\uC791\uC5C5", result.action === "removed" ? "\uD65C\uC131 \uB9C1\uD06C \uC81C\uAC70 \uC644\uB8CC" : "\uD65C\uC131 \uB9C1\uD06C \uC5C6\uC74C"],
|
|
3153
|
-
|
|
3594
|
+
...SKILL_AGENTS.flatMap((agent) => {
|
|
3595
|
+
const name = SKILL_AGENT_NAMES[agent];
|
|
3596
|
+
const agentResult = result.agents[agent];
|
|
3597
|
+
return [
|
|
3598
|
+
[`${name} \uC124\uCE58 \uACBD\uB85C`, terminalText(agentResult.destination)],
|
|
3599
|
+
[`${name} \uACB0\uACFC`, agentResult.action === "removed" ? "\uD65C\uC131 \uB9C1\uD06C \uC81C\uAC70" : "\uD65C\uC131 \uB9C1\uD06C \uC5C6\uC74C"]
|
|
3600
|
+
];
|
|
3601
|
+
}),
|
|
3154
3602
|
["\uAD00\uB9AC \uC800\uC7A5\uC18C", "\uBCF4\uC874\uB428"]
|
|
3155
3603
|
],
|
|
3156
3604
|
raw: result,
|
|
@@ -3173,7 +3621,7 @@ async function showStatus(cmd, dependencies) {
|
|
|
3173
3621
|
}
|
|
3174
3622
|
function createInstallCommand(name, dependencies) {
|
|
3175
3623
|
return new import_commander3.Command(name).description(
|
|
3176
|
-
name === "install" ? "Claude Code \uC2A4\uD0AC\uC744 \uAD00\uB9AC \uC800\uC7A5\uC18C\uC5D0 \uC124\uCE58\uD55C\uB2E4" : "Claude Code \uC2A4\uD0AC\uC744 \uD604\uC7AC CLI \uBC84\uC804\uC73C\uB85C \uAC31\uC2E0\uD55C\uB2E4"
|
|
3624
|
+
name === "install" ? "Claude Code\xB7Codex \uC2A4\uD0AC\uC744 \uAD00\uB9AC \uC800\uC7A5\uC18C\uC5D0 \uC124\uCE58\uD55C\uB2E4" : "Claude Code\xB7Codex \uC2A4\uD0AC\uC744 \uD604\uC7AC CLI \uBC84\uC804\uC73C\uB85C \uAC31\uC2E0\uD55C\uB2E4"
|
|
3177
3625
|
).option("--force", "\uC0AC\uC6A9\uC790 \uD56D\uBAA9\uC774\uB098 \uC218\uC815\xB7\uC190\uC0C1\uB41C \uAD00\uB9AC \uC800\uC7A5\uC18C\uB97C \uBC31\uC5C5 \uD6C4 \uAD50\uCCB4\uD55C\uB2E4").action(async (_localOpts, cmd) => {
|
|
3178
3626
|
const opts = cmd.optsWithGlobals();
|
|
3179
3627
|
const context = dependencies.createContext();
|
|
@@ -3182,98 +3630,282 @@ function createInstallCommand(name, dependencies) {
|
|
|
3182
3630
|
});
|
|
3183
3631
|
}
|
|
3184
3632
|
function createSkillsCommand(dependencies = defaultDependencies) {
|
|
3185
|
-
const statusCommand = new import_commander3.Command("status").description("Claude Code \uC2A4\uD0AC\uC758 \uAD00\uB9AC \uC0C1\uD0DC\uB97C \uC870\uD68C\uD55C\uB2E4").action(async (_opts, cmd) => showStatus(cmd, dependencies));
|
|
3186
|
-
const uninstallCommand = new import_commander3.Command("uninstall").description("\uD65C\uC131 Claude Code \uC2A4\uD0AC \uB9C1\uD06C\uB97C \uC81C\uAC70\uD55C\uB2E4").action(async (_opts, cmd) => {
|
|
3633
|
+
const statusCommand = new import_commander3.Command("status").description("Claude Code\xB7Codex \uC2A4\uD0AC\uC758 \uAD00\uB9AC \uC0C1\uD0DC\uB97C \uC870\uD68C\uD55C\uB2E4").action(async (_opts, cmd) => showStatus(cmd, dependencies));
|
|
3634
|
+
const uninstallCommand = new import_commander3.Command("uninstall").description("\uD65C\uC131 Claude Code\xB7Codex \uC2A4\uD0AC \uB9C1\uD06C\uB97C \uC81C\uAC70\uD55C\uB2E4").action(async (_opts, cmd) => {
|
|
3187
3635
|
const opts = cmd.optsWithGlobals();
|
|
3188
3636
|
const context = dependencies.createContext();
|
|
3189
|
-
const
|
|
3190
|
-
const action = await dependencies.uninstall(context);
|
|
3637
|
+
const uninstalled = await dependencies.uninstall(context);
|
|
3191
3638
|
const result = {
|
|
3192
3639
|
schemaVersion: 1,
|
|
3193
|
-
action,
|
|
3194
|
-
changed: action === "removed",
|
|
3640
|
+
action: uninstalled.action,
|
|
3641
|
+
changed: uninstalled.action === "removed",
|
|
3195
3642
|
status: "missing",
|
|
3196
|
-
destination:
|
|
3197
|
-
repositoryPreserved: true
|
|
3643
|
+
destination: uninstalled.agents.claude.destination,
|
|
3644
|
+
repositoryPreserved: true,
|
|
3645
|
+
agents: uninstalled.agents
|
|
3198
3646
|
};
|
|
3199
3647
|
outputSkillUninstallResult(opts, result);
|
|
3200
3648
|
});
|
|
3201
|
-
return new import_commander3.Command("skills").description(`Claude Code \uC2A4\uD0AC(${SKILL_NAME3}) \uC124\uCE58 \uAD00\uB9AC`).addCommand(statusCommand).addCommand(createInstallCommand("install", dependencies)).addCommand(createInstallCommand("update", dependencies)).addCommand(uninstallCommand).action(async (_opts, cmd) => showStatus(cmd, dependencies));
|
|
3649
|
+
return new import_commander3.Command("skills").description(`Claude Code\xB7Codex \uC2A4\uD0AC(${SKILL_NAME3}) \uC124\uCE58 \uAD00\uB9AC`).addCommand(statusCommand).addCommand(createInstallCommand("install", dependencies)).addCommand(createInstallCommand("update", dependencies)).addCommand(uninstallCommand).action(async (_opts, cmd) => showStatus(cmd, dependencies));
|
|
3202
3650
|
}
|
|
3203
3651
|
var skillsCommand = createSkillsCommand();
|
|
3204
3652
|
|
|
3205
3653
|
// src/commands/doctor.ts
|
|
3206
3654
|
var import_commander4 = require("commander");
|
|
3207
3655
|
var import_chalk3 = __toESM(require("chalk"));
|
|
3208
|
-
var
|
|
3209
|
-
var
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3656
|
+
var SKILL_ERROR_REASON = "\uACF5\uAC1C \uC2A4\uD0AC \uC0C1\uD0DC\uB97C \uD310\uC815\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4";
|
|
3657
|
+
var defaultDependencies2 = {
|
|
3658
|
+
inspectCredentials: inspectCredentialsFile,
|
|
3659
|
+
inspectConfig: inspectConfigFile,
|
|
3660
|
+
resolveProfile: resolveProfileName,
|
|
3661
|
+
createSkillContext: createSkillManagerContext,
|
|
3662
|
+
inspectSkill: inspectAgentSkill,
|
|
3663
|
+
connection: {
|
|
3664
|
+
getUserAccessKey,
|
|
3665
|
+
getIaasCredential,
|
|
3666
|
+
getOptionalServiceCredential,
|
|
3667
|
+
verifyUserAccessKey,
|
|
3668
|
+
verifyIaas,
|
|
3669
|
+
verifyLogncrash,
|
|
3670
|
+
verifyNcr,
|
|
3671
|
+
verifyNcs
|
|
3672
|
+
}
|
|
3673
|
+
};
|
|
3674
|
+
async function resolveTargetProfile(cliProfile, dependencies) {
|
|
3216
3675
|
try {
|
|
3217
|
-
|
|
3218
|
-
} catch {
|
|
3219
|
-
|
|
3676
|
+
return await dependencies.resolveProfile(cliProfile);
|
|
3677
|
+
} catch (err) {
|
|
3678
|
+
if (err instanceof NhnCloudCliError) return null;
|
|
3679
|
+
throw err;
|
|
3220
3680
|
}
|
|
3681
|
+
}
|
|
3682
|
+
async function inspectAgentSkillForDoctor(dependencies, agent) {
|
|
3221
3683
|
try {
|
|
3222
|
-
const
|
|
3223
|
-
return {
|
|
3224
|
-
} catch {
|
|
3225
|
-
|
|
3684
|
+
const status = await dependencies.inspectSkill(dependencies.createSkillContext(), agent);
|
|
3685
|
+
return { ...status, recoveryCommand: skillRecoveryCommand(status.status) ?? null };
|
|
3686
|
+
} catch (err) {
|
|
3687
|
+
const code = typeof err === "object" && err !== null && "code" in err && typeof err.code === "string" ? err.code : void 0;
|
|
3688
|
+
return { status: "error", reason: code ? `${SKILL_ERROR_REASON}: ${code}` : SKILL_ERROR_REASON };
|
|
3226
3689
|
}
|
|
3227
3690
|
}
|
|
3228
|
-
|
|
3691
|
+
function connectionHasFailure(connection) {
|
|
3692
|
+
return connection.checked && Object.values(connection.targets).some((target) => target.status === "failed");
|
|
3693
|
+
}
|
|
3694
|
+
var CONNECTION_TARGETS = ["userAccessKey", "iaas", "logncrash", "ncr", "ncs"];
|
|
3695
|
+
function skipAll(reason) {
|
|
3696
|
+
return Object.fromEntries(
|
|
3697
|
+
CONNECTION_TARGETS.map((target) => [target, { status: "skipped", reason }])
|
|
3698
|
+
);
|
|
3699
|
+
}
|
|
3700
|
+
async function runVerify(verify) {
|
|
3229
3701
|
try {
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
return null;
|
|
3702
|
+
return await verify() ? { status: "ok" } : { status: "failed", reason: "auth" };
|
|
3703
|
+
} catch (err) {
|
|
3704
|
+
const exitCode = err instanceof NhnCloudCliError ? err.exitCode : EXIT_API_ERROR;
|
|
3705
|
+
return { status: "failed", reason: "error", exitCode };
|
|
3235
3706
|
}
|
|
3236
3707
|
}
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
console.log(` ${import_chalk3.default.red("\u274C \uBBF8\uC124\uC815")} \u2014 ${CREDENTIALS_PATH2} \uC5C6\uC74C. nhncloud configure \uB85C \uC124\uC815\uD558\uC138\uC694.`);
|
|
3244
|
-
} else if (creds.parseError) {
|
|
3245
|
-
console.log(` ${import_chalk3.default.red("\u274C \uD30C\uC2F1 \uC624\uB958")} \u2014 ${CREDENTIALS_PATH2} \uAC00 \uC62C\uBC14\uB978 JSON \uC778\uC9C0 \uD655\uC778\uD558\uC138\uC694.`);
|
|
3246
|
-
} else if (creds.profiles.length === 0) {
|
|
3247
|
-
console.log(` ${import_chalk3.default.yellow("\u26A0 profile \uC5C6\uC74C")} \u2014 nhncloud configure \uB85C \uC124\uC815\uD558\uC138\uC694.`);
|
|
3248
|
-
} else {
|
|
3249
|
-
console.log(` ${import_chalk3.default.green("\u2713 \uC124\uC815\uB428")} \u2014 profile: ${creds.profiles.join(", ")}`);
|
|
3250
|
-
console.log(` \uAE30\uBCF8 profile: ${defaultProfile ? import_chalk3.default.green(defaultProfile) : import_chalk3.default.gray("\uBBF8\uC9C0\uC815 (default \uC0AC\uC6A9)")}`);
|
|
3708
|
+
async function readRequired(read) {
|
|
3709
|
+
try {
|
|
3710
|
+
return { value: await read() };
|
|
3711
|
+
} catch (err) {
|
|
3712
|
+
const reason = err instanceof NhnCloudCliError ? "not-configured" : "profile-unavailable";
|
|
3713
|
+
return { skipped: { status: "skipped", reason } };
|
|
3251
3714
|
}
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
}
|
|
3259
|
-
|
|
3260
|
-
|
|
3715
|
+
}
|
|
3716
|
+
async function readAppkey(service, profileName, deps) {
|
|
3717
|
+
try {
|
|
3718
|
+
const credential = await deps.getOptionalServiceCredential(service, profileName);
|
|
3719
|
+
if (!credential?.appkey) return { skipped: { status: "skipped", reason: "not-configured" } };
|
|
3720
|
+
return { appkey: credential.appkey };
|
|
3721
|
+
} catch {
|
|
3722
|
+
return { skipped: { status: "skipped", reason: "profile-unavailable" } };
|
|
3723
|
+
}
|
|
3724
|
+
}
|
|
3725
|
+
async function checkConnection(profileName, credentials, profileSummary, deps) {
|
|
3726
|
+
if (credentials.state !== "ok" || profileName === null || profileSummary === void 0 || profileSummary.environment === "invalid") {
|
|
3727
|
+
return skipAll("profile-unavailable");
|
|
3728
|
+
}
|
|
3729
|
+
if (profileSummary.environment === "gov") return skipAll("gov-unsupported");
|
|
3730
|
+
const uakRead = await readRequired(() => deps.getUserAccessKey(profileName));
|
|
3731
|
+
const uak = "value" in uakRead ? uakRead.value : void 0;
|
|
3732
|
+
const userAccessKey = "value" in uakRead ? await runVerify(() => deps.verifyUserAccessKey(uakRead.value)) : uakRead.skipped;
|
|
3733
|
+
const iaasRead = await readRequired(() => deps.getIaasCredential(profileName));
|
|
3734
|
+
const iaasResult = "value" in iaasRead ? await runVerify(() => deps.verifyIaas(iaasRead.value)) : iaasRead.skipped;
|
|
3735
|
+
const checkAppkeyService = async (service, verify, usesOAuth) => {
|
|
3736
|
+
const read = await readAppkey(service, profileName, deps);
|
|
3737
|
+
if ("skipped" in read) return read.skipped;
|
|
3738
|
+
if (uak === void 0) return { status: "skipped", reason: "uak-missing" };
|
|
3739
|
+
if (usesOAuth && userAccessKey.status !== "ok") return { status: "skipped", reason: "uak-failed" };
|
|
3740
|
+
return runVerify(() => verify(uak, read.appkey));
|
|
3741
|
+
};
|
|
3742
|
+
const logncrash = await checkAppkeyService("logncrash", deps.verifyLogncrash, true);
|
|
3743
|
+
const ncr = await checkAppkeyService("ncr", deps.verifyNcr, false);
|
|
3744
|
+
const ncs = await checkAppkeyService("ncs", deps.verifyNcs, true);
|
|
3745
|
+
return { userAccessKey, iaas: iaasResult, logncrash, ncr, ncs };
|
|
3746
|
+
}
|
|
3747
|
+
async function buildDoctorReport(options, dependencies) {
|
|
3748
|
+
const credentials = await dependencies.inspectCredentials();
|
|
3749
|
+
const config = await dependencies.inspectConfig();
|
|
3750
|
+
const profileName = await resolveTargetProfile(options.profile, dependencies);
|
|
3751
|
+
const profileSummary = credentials.state === "ok" && profileName !== null ? credentials.profiles.find((summary) => summary.name === profileName) : void 0;
|
|
3752
|
+
const connection = options.checkConnection ? {
|
|
3753
|
+
checked: true,
|
|
3754
|
+
profile: profileName,
|
|
3755
|
+
targets: await checkConnection(profileName, credentials, profileSummary, dependencies.connection)
|
|
3756
|
+
} : { checked: false };
|
|
3757
|
+
const claude = await inspectAgentSkillForDoctor(dependencies, "claude");
|
|
3758
|
+
const codex = await inspectAgentSkillForDoctor(dependencies, "codex");
|
|
3759
|
+
const ready = profileSummary !== void 0 && profileSummary.environment !== "invalid" && profileSummary.blocks.length > 0 && !connectionHasFailure(connection);
|
|
3760
|
+
return {
|
|
3761
|
+
schemaVersion: 1,
|
|
3762
|
+
ready,
|
|
3763
|
+
credentials,
|
|
3764
|
+
config,
|
|
3765
|
+
profile: { name: profileName, exists: profileSummary !== void 0 },
|
|
3766
|
+
connection,
|
|
3767
|
+
skills: { agents: { claude, codex } }
|
|
3768
|
+
};
|
|
3769
|
+
}
|
|
3770
|
+
function line(text = "") {
|
|
3771
|
+
process.stdout.write(`${text}
|
|
3772
|
+
`);
|
|
3773
|
+
}
|
|
3774
|
+
function printCredentialsSection(credentials) {
|
|
3775
|
+
const filePath = sanitizeForTerminal(credentials.path);
|
|
3776
|
+
const reason = sanitizeForTerminal(credentials.reason ?? "");
|
|
3777
|
+
line(import_chalk3.default.bold("\uC790\uACA9\uC99D\uBA85"));
|
|
3778
|
+
switch (credentials.state) {
|
|
3779
|
+
case "missing":
|
|
3780
|
+
line(` ${import_chalk3.default.red("\u274C \uBBF8\uC124\uC815")} \u2014 ${filePath} \uC5C6\uC74C. nhncloud configure \uB85C \uC124\uC815\uD558\uC138\uC694.`);
|
|
3781
|
+
break;
|
|
3782
|
+
case "invalid":
|
|
3783
|
+
line(` ${import_chalk3.default.red("\u274C \uD615\uC2DD \uC624\uB958")} \u2014 ${filePath}: ${reason}`);
|
|
3784
|
+
break;
|
|
3785
|
+
case "unreadable":
|
|
3786
|
+
line(` ${import_chalk3.default.red("\u274C \uC77D\uAE30 \uC2E4\uD328")} \u2014 ${filePath}: ${reason}`);
|
|
3787
|
+
break;
|
|
3788
|
+
case "ok":
|
|
3789
|
+
if (credentials.profiles.length === 0) {
|
|
3790
|
+
line(` ${import_chalk3.default.yellow("\u26A0 profile \uC5C6\uC74C")} \u2014 nhncloud configure \uB85C \uC124\uC815\uD558\uC138\uC694.`);
|
|
3791
|
+
break;
|
|
3792
|
+
}
|
|
3793
|
+
line(` ${import_chalk3.default.green("\u2713 \uC124\uC815\uB428")} \u2014 profile:`);
|
|
3794
|
+
for (const summary of credentials.profiles) {
|
|
3795
|
+
const name = sanitizeForTerminal(summary.name);
|
|
3796
|
+
const blocks = summary.blocks.map(sanitizeForTerminal).join(", ") || "-";
|
|
3797
|
+
if (summary.environment === "invalid") {
|
|
3798
|
+
line(` ${name} ${import_chalk3.default.yellow("\u26A0 environment \uAC12\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4")} [${blocks}]`);
|
|
3799
|
+
} else {
|
|
3800
|
+
line(` ${name}${summary.environment === "gov" ? " (gov)" : ""} [${blocks}]`);
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3803
|
+
break;
|
|
3804
|
+
}
|
|
3805
|
+
if (credentials.permissions === "too-open") {
|
|
3806
|
+
line(` ${import_chalk3.default.yellow("\u26A0 \uD30C\uC77C \uAD8C\uD55C\uC774 \uB113\uC2B5\uB2C8\uB2E4")} \u2014 chmod 600 ${filePath}`);
|
|
3807
|
+
}
|
|
3808
|
+
}
|
|
3809
|
+
function printConfigSection(config) {
|
|
3810
|
+
line(import_chalk3.default.bold("\n\uC124\uC815 \uD30C\uC77C"));
|
|
3811
|
+
if (config.state === "invalid" || config.state === "unreadable") {
|
|
3812
|
+
line(
|
|
3813
|
+
` ${import_chalk3.default.red(config.state === "invalid" ? "\u274C \uD615\uC2DD \uC624\uB958" : "\u274C \uC77D\uAE30 \uC2E4\uD328")} \u2014 ${sanitizeForTerminal(config.path)}: ${sanitizeForTerminal(config.reason ?? "")}`
|
|
3261
3814
|
);
|
|
3815
|
+
}
|
|
3816
|
+
line(
|
|
3817
|
+
` \uAE30\uBCF8 profile: ${config.defaultProfile ? import_chalk3.default.green(sanitizeForTerminal(config.defaultProfile)) : import_chalk3.default.gray("\uBBF8\uC9C0\uC815 (default \uC0AC\uC6A9)")}`
|
|
3818
|
+
);
|
|
3819
|
+
}
|
|
3820
|
+
function printProfileSection(profile) {
|
|
3821
|
+
line(import_chalk3.default.bold("\n\uB300\uC0C1 profile"));
|
|
3822
|
+
if (profile.name === null) {
|
|
3823
|
+
line(` ${import_chalk3.default.red("\u274C \uD574\uC11D \uC2E4\uD328")} \u2014 config.json \uC744 \uBA3C\uC800 \uACE0\uCE58\uC138\uC694.`);
|
|
3824
|
+
} else if (profile.exists) {
|
|
3825
|
+
line(` ${import_chalk3.default.green(`\u2713 ${sanitizeForTerminal(profile.name)}`)}`);
|
|
3262
3826
|
} else {
|
|
3263
|
-
|
|
3264
|
-
` ${
|
|
3827
|
+
line(
|
|
3828
|
+
` ${import_chalk3.default.yellow(`\u26A0 ${sanitizeForTerminal(profile.name)} \uC5C6\uC74C`)} \u2014 nhncloud configure \uB85C \uC124\uC815\uD558\uC138\uC694.`
|
|
3265
3829
|
);
|
|
3266
3830
|
}
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3831
|
+
}
|
|
3832
|
+
function printSkillLine(agent, skill) {
|
|
3833
|
+
const name = SKILL_AGENT_NAMES[agent];
|
|
3834
|
+
if (skill.status === "error") {
|
|
3835
|
+
line(` ${name}: ${import_chalk3.default.yellow("\u26A0 error")} \u2014 ${sanitizeForTerminal(skill.reason)}`);
|
|
3836
|
+
} else if (skill.status === "current") {
|
|
3837
|
+
const version = sanitizeForTerminal(skill.installedVersion ?? skill.currentVersion);
|
|
3838
|
+
line(` ${name}: ${import_chalk3.default.green(`\u2713 current (${version})`)}`);
|
|
3839
|
+
} else if (skill.status === "missing") {
|
|
3840
|
+
line(` ${name}: ${import_chalk3.default.gray(`\uBBF8\uC124\uCE58 \u2014 ${skill.recoveryCommand}`)}`);
|
|
3270
3841
|
} else {
|
|
3271
|
-
|
|
3842
|
+
line(` ${name}: ${import_chalk3.default.yellow(`\u26A0 ${skill.status}`)} \u2014 ${skill.recoveryCommand}`);
|
|
3272
3843
|
}
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3844
|
+
}
|
|
3845
|
+
function printSkillSection(agents) {
|
|
3846
|
+
line(import_chalk3.default.bold("\n\uACF5\uAC1C \uC2A4\uD0AC"));
|
|
3847
|
+
for (const agent of SKILL_AGENTS) printSkillLine(agent, agents[agent]);
|
|
3848
|
+
}
|
|
3849
|
+
var SKIP_REASONS = {
|
|
3850
|
+
"not-configured": "\uC124\uC815 \uC5C6\uC74C",
|
|
3851
|
+
"uak-missing": "\uACF5\uD1B5 userAccessKey \uC5C6\uC74C",
|
|
3852
|
+
"uak-failed": "userAccessKey \uD655\uC778\uC774 \uC131\uACF5\uD558\uC9C0 \uC54A\uC544 \uAC74\uB108\uB700",
|
|
3853
|
+
"gov-unsupported": "\uACF5\uACF5\uB9DD profile \uC740 \uC5F0\uACB0 \uD655\uC778\uC744 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC74C",
|
|
3854
|
+
"profile-unavailable": "\uB300\uC0C1 profile \uC744 \uC77D\uC744 \uC218 \uC5C6\uC74C"
|
|
3855
|
+
};
|
|
3856
|
+
function printConnectionSection(connection) {
|
|
3857
|
+
if (!connection.checked) return;
|
|
3858
|
+
line(import_chalk3.default.bold("\n\uC5F0\uACB0 \uD655\uC778"));
|
|
3859
|
+
for (const target of CONNECTION_TARGETS) {
|
|
3860
|
+
const result = connection.targets[target];
|
|
3861
|
+
const label = ` ${target}:`;
|
|
3862
|
+
if (result.status === "ok") {
|
|
3863
|
+
const region = target === "ncr" || target === "ncs" ? " (kr1)" : "";
|
|
3864
|
+
line(`${label} ${import_chalk3.default.green(`\u2713 \uC131\uACF5${region}`)}`);
|
|
3865
|
+
} else if (result.status === "failed" && result.reason === "auth") {
|
|
3866
|
+
line(`${label} ${import_chalk3.default.red("\u274C \uC778\uC99D \uC2E4\uD328")} \u2014 \uD0A4\uB098 appkey \uB97C \uD655\uC778\uD558\uC138\uC694.`);
|
|
3867
|
+
} else if (result.status === "failed") {
|
|
3868
|
+
line(`${label} ${import_chalk3.default.red(`\u274C \uC624\uB958 (\uC885\uB8CC \uCF54\uB4DC ${result.exitCode ?? EXIT_API_ERROR})`)}`);
|
|
3869
|
+
} else {
|
|
3870
|
+
const reason = result.reason ? SKIP_REASONS[result.reason] ?? result.reason : "";
|
|
3871
|
+
line(`${label} ${import_chalk3.default.gray(`\uAC74\uB108\uB700 \u2014 ${reason}`)}`);
|
|
3872
|
+
}
|
|
3873
|
+
}
|
|
3874
|
+
}
|
|
3875
|
+
function printText(report) {
|
|
3876
|
+
line(import_chalk3.default.bold("\n\u{1F50D} nhncloud-cli \uC9C4\uB2E8\n"));
|
|
3877
|
+
printCredentialsSection(report.credentials);
|
|
3878
|
+
printConfigSection(report.config);
|
|
3879
|
+
printProfileSection(report.profile);
|
|
3880
|
+
printConnectionSection(report.connection);
|
|
3881
|
+
printSkillSection(report.skills.agents);
|
|
3882
|
+
line();
|
|
3883
|
+
if (report.ready) {
|
|
3884
|
+
line(import_chalk3.default.green("\u2713 \uAE30\uBCF8 \uC124\uC815\uC774 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4."));
|
|
3885
|
+
} else {
|
|
3886
|
+
line(import_chalk3.default.yellow("\u26A0 \uC124\uC815\uC774 \uD544\uC694\uD569\uB2C8\uB2E4: nhncloud configure"));
|
|
3887
|
+
}
|
|
3888
|
+
line();
|
|
3889
|
+
}
|
|
3890
|
+
function createDoctorCommand(dependencies = defaultDependencies2) {
|
|
3891
|
+
return new import_commander4.Command("doctor").description("\uC790\uACA9\uC99D\uBA85\xB7\uC124\uC815\xB7\uC2A4\uD0AC \uC0C1\uD0DC\uB97C \uC9C4\uB2E8\uD55C\uB2E4(\uAE30\uBCF8 \uC624\uD504\uB77C\uC778, --check-connection \uC73C\uB85C \uC5F0\uACB0 \uD655\uC778)").option("--profile <name>", "\uC9C4\uB2E8\uD560 profile \uC774\uB984").option("--check-connection", "\uB300\uC0C1 profile \uC758 \uC790\uACA9\uC99D\uBA85\uC73C\uB85C \uC2E4\uC81C \uC5F0\uACB0\uC744 \uD655\uC778\uD55C\uB2E4 (\uC678\uBD80 API \uD638\uCD9C)").action(async (_opts, cmd) => {
|
|
3892
|
+
const opts = cmd.optsWithGlobals();
|
|
3893
|
+
const report = await buildDoctorReport(
|
|
3894
|
+
{ profile: opts.profile, checkConnection: opts.checkConnection },
|
|
3895
|
+
dependencies
|
|
3896
|
+
);
|
|
3897
|
+
if (opts.json) {
|
|
3898
|
+
printJson(report);
|
|
3899
|
+
} else if (opts.quiet) {
|
|
3900
|
+
process.stdout.write(report.ready ? "ready\n" : "not-ready\n");
|
|
3901
|
+
} else {
|
|
3902
|
+
printText(report);
|
|
3903
|
+
}
|
|
3904
|
+
});
|
|
3905
|
+
}
|
|
3906
|
+
var doctorCommand = createDoctorCommand();
|
|
3907
|
+
|
|
3908
|
+
// src/commands/logncrash/search.ts
|
|
3277
3909
|
var import_commander5 = require("commander");
|
|
3278
3910
|
|
|
3279
3911
|
// src/utils/time.ts
|
|
@@ -3520,19 +4152,19 @@ var VALID_LEVELS = ["DEBUG", "INFO", "WARN", "ERROR", "FATAL"];
|
|
|
3520
4152
|
function resolveBody(opts) {
|
|
3521
4153
|
if (opts.body !== void 0) return opts.body;
|
|
3522
4154
|
if (opts.file !== void 0) {
|
|
3523
|
-
let
|
|
4155
|
+
let stat4;
|
|
3524
4156
|
try {
|
|
3525
|
-
|
|
4157
|
+
stat4 = (0, import_node_fs3.statSync)(opts.file);
|
|
3526
4158
|
} catch (e) {
|
|
3527
4159
|
const reason = e.code ?? (e instanceof Error ? e.message : String(e));
|
|
3528
4160
|
throw new NhnCloudCliError(`\uB85C\uADF8 \uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${opts.file} (${reason})`, EXIT_PARAM_ERROR);
|
|
3529
4161
|
}
|
|
3530
|
-
if (!
|
|
4162
|
+
if (!stat4.isFile()) {
|
|
3531
4163
|
throw new NhnCloudCliError(`\uB85C\uADF8 \uD30C\uC77C\uC774 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4: ${opts.file}`, EXIT_PARAM_ERROR);
|
|
3532
4164
|
}
|
|
3533
|
-
if (
|
|
4165
|
+
if (stat4.size > MAX_LOG_BYTES) {
|
|
3534
4166
|
throw new NhnCloudCliError(
|
|
3535
|
-
`\uB85C\uADF8 \uD30C\uC77C\uC774 \uB108\uBB34 \uD07D\uB2C8\uB2E4: ${
|
|
4167
|
+
`\uB85C\uADF8 \uD30C\uC77C\uC774 \uB108\uBB34 \uD07D\uB2C8\uB2E4: ${stat4.size} \uBC14\uC774\uD2B8 (\uD55C\uB3C4 ${MAX_LOG_BYTES} \uBC14\uC774\uD2B8).`,
|
|
3536
4168
|
EXIT_PARAM_ERROR
|
|
3537
4169
|
);
|
|
3538
4170
|
}
|
|
@@ -3603,22 +4235,22 @@ credentials.json \uC5D0 "appkey": "<appkey>" \uB97C \uCD94\uAC00\uD558\uC138\uC6
|
|
|
3603
4235
|
|
|
3604
4236
|
// src/commands/logncrash/export.ts
|
|
3605
4237
|
var import_commander7 = require("commander");
|
|
3606
|
-
var
|
|
4238
|
+
var import_promises4 = require("fs/promises");
|
|
3607
4239
|
var import_node_fs4 = require("fs");
|
|
3608
4240
|
var import_node_crypto4 = require("crypto");
|
|
3609
4241
|
var MAX_TOTAL = 1e5;
|
|
3610
|
-
var defaultExportFileOps = { appendFile:
|
|
3611
|
-
function assertWritable(
|
|
4242
|
+
var defaultExportFileOps = { appendFile: import_promises4.appendFile, rename: import_promises4.rename };
|
|
4243
|
+
function assertWritable(path4, force) {
|
|
3612
4244
|
if (force) return;
|
|
3613
4245
|
try {
|
|
3614
|
-
(0, import_node_fs4.statSync)(
|
|
4246
|
+
(0, import_node_fs4.statSync)(path4);
|
|
3615
4247
|
} catch (e) {
|
|
3616
4248
|
if (e.code === "ENOENT") return;
|
|
3617
4249
|
const reason = e.code ?? (e instanceof Error ? e.message : String(e));
|
|
3618
|
-
throw new NhnCloudCliError(`--output \uACBD\uB85C\uB97C \uD655\uC778\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${
|
|
4250
|
+
throw new NhnCloudCliError(`--output \uACBD\uB85C\uB97C \uD655\uC778\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${path4} (${reason})`, EXIT_PARAM_ERROR);
|
|
3619
4251
|
}
|
|
3620
4252
|
throw new NhnCloudCliError(
|
|
3621
|
-
`--output \uB300\uC0C1\uC774 \uC774\uBBF8 \uC874\uC7AC\uD569\uB2C8\uB2E4: ${
|
|
4253
|
+
`--output \uB300\uC0C1\uC774 \uC774\uBBF8 \uC874\uC7AC\uD569\uB2C8\uB2E4: ${path4}. \uB36E\uC5B4\uC4F0\uB824\uBA74 --force \uB97C \uC4F0\uC138\uC694.`,
|
|
3622
4254
|
EXIT_PARAM_ERROR
|
|
3623
4255
|
);
|
|
3624
4256
|
}
|
|
@@ -3729,7 +4361,7 @@ function createExportCommand(finalizeOps) {
|
|
|
3729
4361
|
} catch (err) {
|
|
3730
4362
|
if (failureOrigin !== "search" || !(err instanceof LogncrashServerError)) throw err;
|
|
3731
4363
|
await endAndClose(stream);
|
|
3732
|
-
await (0,
|
|
4364
|
+
await (0, import_promises4.truncate)(tmp, checkpoint.bytesWritten);
|
|
3733
4365
|
stream = (0, import_node_fs4.createWriteStream)(tmp, { encoding: "utf-8", flags: "a" });
|
|
3734
4366
|
bytePosition = checkpoint.bytesWritten;
|
|
3735
4367
|
count = checkpoint.count;
|
|
@@ -3756,14 +4388,14 @@ function createExportCommand(finalizeOps) {
|
|
|
3756
4388
|
stream.end();
|
|
3757
4389
|
});
|
|
3758
4390
|
if (count === 0) {
|
|
3759
|
-
await (0,
|
|
4391
|
+
await (0, import_promises4.rm)(tmp, { force: true }).catch(() => {
|
|
3760
4392
|
});
|
|
3761
4393
|
throw failure;
|
|
3762
4394
|
}
|
|
3763
4395
|
const partial = `${opts.output}.partial`;
|
|
3764
4396
|
try {
|
|
3765
|
-
if (format === "json") await (0,
|
|
3766
|
-
await (0,
|
|
4397
|
+
if (format === "json") await (0, import_promises4.appendFile)(tmp, "]\n");
|
|
4398
|
+
await (0, import_promises4.rename)(tmp, partial);
|
|
3767
4399
|
} catch {
|
|
3768
4400
|
process.stderr.write(
|
|
3769
4401
|
`\uACBD\uACE0: \uBD80\uBD84 \uACB0\uACFC\uB97C ${partial} \uC5D0 \uB0A8\uAE30\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uC784\uC2DC \uD30C\uC77C: ${tmp}
|
|
@@ -3805,7 +4437,7 @@ function createExportCommand(finalizeOps) {
|
|
|
3805
4437
|
throw new NhnCloudCliError(message, EXIT_PARAM_ERROR);
|
|
3806
4438
|
}
|
|
3807
4439
|
stopSpinner(true, `${count}\uAC74 \uCD94\uCD9C \uC644\uB8CC`);
|
|
3808
|
-
await (0,
|
|
4440
|
+
await (0, import_promises4.rm)(`${opts.output}.partial`, { force: true }).catch(() => {
|
|
3809
4441
|
});
|
|
3810
4442
|
if (count >= MAX_TOTAL && (total > MAX_TOTAL || hasUnqueriedWindows)) {
|
|
3811
4443
|
const totalDescription = hasUnqueriedWindows ? `\uC870\uD68C\uD55C \uCC3D\uC5D0\uC11C ${total}\uAC74\uC744 \uD655\uC778\uD588\uACE0 \uB0A8\uC740 \uCC3D\uC744 \uC870\uD68C\uD558\uC9C0 \uC54A\uC740 \uCC44` : `\uC804\uCCB4 ${total}\uAC74 \uC911`;
|
|
@@ -4423,7 +5055,7 @@ var binariesCommand = new import_commander15.Command("binaries").description("\u
|
|
|
4423
5055
|
// src/commands/deploy/upload.ts
|
|
4424
5056
|
var import_commander16 = require("commander");
|
|
4425
5057
|
var import_node_fs5 = require("fs");
|
|
4426
|
-
var
|
|
5058
|
+
var import_node_path6 = require("path");
|
|
4427
5059
|
var MAX_UPLOAD_BYTES = 512 * 1024 * 1024;
|
|
4428
5060
|
function parsePositiveInt2(value, flag) {
|
|
4429
5061
|
if (value === void 0) return void 0;
|
|
@@ -4443,9 +5075,9 @@ var uploadCommand = new import_commander16.Command("upload").description("\uB85C
|
|
|
4443
5075
|
}
|
|
4444
5076
|
const artifactId = requireCoordinate(opts.artifactId, "--artifact-id");
|
|
4445
5077
|
const filePath = opts.file;
|
|
4446
|
-
let
|
|
5078
|
+
let stat4;
|
|
4447
5079
|
try {
|
|
4448
|
-
|
|
5080
|
+
stat4 = (0, import_node_fs5.statSync)(filePath);
|
|
4449
5081
|
} catch (e) {
|
|
4450
5082
|
const reason = e.code ?? (e instanceof Error ? e.message : String(e));
|
|
4451
5083
|
throw new NhnCloudCliError(
|
|
@@ -4453,17 +5085,17 @@ var uploadCommand = new import_commander16.Command("upload").description("\uB85C
|
|
|
4453
5085
|
EXIT_PARAM_ERROR
|
|
4454
5086
|
);
|
|
4455
5087
|
}
|
|
4456
|
-
if (!
|
|
5088
|
+
if (!stat4.isFile()) {
|
|
4457
5089
|
throw new NhnCloudCliError(`--file \uC774 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4: ${filePath}`, EXIT_PARAM_ERROR);
|
|
4458
5090
|
}
|
|
4459
|
-
if (
|
|
5091
|
+
if (stat4.size > MAX_UPLOAD_BYTES) {
|
|
4460
5092
|
throw new NhnCloudCliError(
|
|
4461
|
-
`--file \uC774 \uB108\uBB34 \uD07D\uB2C8\uB2E4 (${
|
|
5093
|
+
`--file \uC774 \uB108\uBB34 \uD07D\uB2C8\uB2E4 (${stat4.size} \uBC14\uC774\uD2B8). \uC5C5\uB85C\uB4DC \uD55C\uB3C4 ${MAX_UPLOAD_BYTES} \uBC14\uC774\uD2B8.`,
|
|
4462
5094
|
EXIT_PARAM_ERROR
|
|
4463
5095
|
);
|
|
4464
5096
|
}
|
|
4465
5097
|
const fileBuffer = (0, import_node_fs5.readFileSync)(filePath);
|
|
4466
|
-
const fileName = (0,
|
|
5098
|
+
const fileName = (0, import_node_path6.basename)(filePath);
|
|
4467
5099
|
const { client, profileName } = await createDeployClient(opts.profile);
|
|
4468
5100
|
const appKey = await resolveDeployAppKey(profileName);
|
|
4469
5101
|
startSpinner("\uBC14\uC774\uB108\uB9AC \uC5C5\uB85C\uB4DC \uC911...");
|
|
@@ -4509,20 +5141,20 @@ function parsePositiveInt3(value, flag) {
|
|
|
4509
5141
|
}
|
|
4510
5142
|
return Number(value);
|
|
4511
5143
|
}
|
|
4512
|
-
function assertWritable2(
|
|
5144
|
+
function assertWritable2(path4, force) {
|
|
4513
5145
|
if (force) return;
|
|
4514
5146
|
try {
|
|
4515
|
-
(0, import_node_fs6.statSync)(
|
|
5147
|
+
(0, import_node_fs6.statSync)(path4);
|
|
4516
5148
|
} catch (e) {
|
|
4517
5149
|
if (e.code === "ENOENT") return;
|
|
4518
5150
|
const reason = e.code ?? (e instanceof Error ? e.message : String(e));
|
|
4519
5151
|
throw new NhnCloudCliError(
|
|
4520
|
-
`-o \uACBD\uB85C\uB97C \uD655\uC778\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${
|
|
5152
|
+
`-o \uACBD\uB85C\uB97C \uD655\uC778\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${path4} (${reason})`,
|
|
4521
5153
|
EXIT_PARAM_ERROR
|
|
4522
5154
|
);
|
|
4523
5155
|
}
|
|
4524
5156
|
throw new NhnCloudCliError(
|
|
4525
|
-
`-o \uB300\uC0C1\uC774 \uC774\uBBF8 \uC874\uC7AC\uD569\uB2C8\uB2E4: ${
|
|
5157
|
+
`-o \uB300\uC0C1\uC774 \uC774\uBBF8 \uC874\uC7AC\uD569\uB2C8\uB2E4: ${path4}. \uB36E\uC5B4\uC4F0\uB824\uBA74 --force \uB97C \uC4F0\uC138\uC694.`,
|
|
4526
5158
|
EXIT_PARAM_ERROR
|
|
4527
5159
|
);
|
|
4528
5160
|
}
|
|
@@ -4865,8 +5497,8 @@ var InstanceClient = class {
|
|
|
4865
5497
|
return this.serverAction(id, { revertResize: null });
|
|
4866
5498
|
}
|
|
4867
5499
|
async listFlavors(params = {}) {
|
|
4868
|
-
const
|
|
4869
|
-
const url = `${this.computeEndpoint}${
|
|
5500
|
+
const path4 = params.detail ? "/flavors/detail" : "/flavors";
|
|
5501
|
+
const url = `${this.computeEndpoint}${path4}`;
|
|
4870
5502
|
const searchParams = {};
|
|
4871
5503
|
if (params.minDisk !== void 0) searchParams["minDisk"] = params.minDisk;
|
|
4872
5504
|
if (params.minRam !== void 0) searchParams["minRam"] = params.minRam;
|
|
@@ -5405,13 +6037,10 @@ async function toNetworkWriteError(err) {
|
|
|
5405
6037
|
return base;
|
|
5406
6038
|
}
|
|
5407
6039
|
let reason = null;
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
if (typeof message === "string") reason = message;
|
|
5413
|
-
} catch {
|
|
5414
|
-
}
|
|
6040
|
+
const body = await readHttpErrorBody(err);
|
|
6041
|
+
const neutron = typeof body === "object" && body !== null ? body["NeutronError"] : void 0;
|
|
6042
|
+
const message = typeof neutron === "object" && neutron !== null ? neutron["message"] : void 0;
|
|
6043
|
+
if (typeof message === "string") reason = message;
|
|
5415
6044
|
if (reason === null) return base;
|
|
5416
6045
|
return new NhnCloudCliError(
|
|
5417
6046
|
`${base.message}
|
|
@@ -6549,9 +7178,9 @@ var createCommand5 = new import_commander33.Command("create").description("\uC77
|
|
|
6549
7178
|
}
|
|
6550
7179
|
let userDataBase64;
|
|
6551
7180
|
if (opts.userData !== void 0) {
|
|
6552
|
-
let
|
|
7181
|
+
let stat4;
|
|
6553
7182
|
try {
|
|
6554
|
-
|
|
7183
|
+
stat4 = (0, import_node_fs7.statSync)(opts.userData);
|
|
6555
7184
|
} catch (e) {
|
|
6556
7185
|
const reason = e.code ?? (e instanceof Error ? e.message : String(e));
|
|
6557
7186
|
throw new NhnCloudCliError(
|
|
@@ -6559,15 +7188,15 @@ var createCommand5 = new import_commander33.Command("create").description("\uC77
|
|
|
6559
7188
|
EXIT_PARAM_ERROR
|
|
6560
7189
|
);
|
|
6561
7190
|
}
|
|
6562
|
-
if (!
|
|
7191
|
+
if (!stat4.isFile()) {
|
|
6563
7192
|
throw new NhnCloudCliError(
|
|
6564
7193
|
`--user-data \uAC00 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4: ${opts.userData}`,
|
|
6565
7194
|
EXIT_PARAM_ERROR
|
|
6566
7195
|
);
|
|
6567
7196
|
}
|
|
6568
|
-
if (
|
|
7197
|
+
if (stat4.size > 49149) {
|
|
6569
7198
|
throw new NhnCloudCliError(
|
|
6570
|
-
`--user-data \uAC00 \uB108\uBB34 \uD07D\uB2C8\uB2E4 (${
|
|
7199
|
+
`--user-data \uAC00 \uB108\uBB34 \uD07D\uB2C8\uB2E4 (${stat4.size} \uBC14\uC774\uD2B8). base64 \uC778\uCF54\uB529 \uD6C4 65535 \uBC14\uC774\uD2B8 \uD55C\uB3C4\uB77C raw 49149 \uBC14\uC774\uD2B8\uAE4C\uC9C0\uB9CC \uD5C8\uC6A9\uB429\uB2C8\uB2E4.`,
|
|
6571
7200
|
EXIT_PARAM_ERROR
|
|
6572
7201
|
);
|
|
6573
7202
|
}
|
|
@@ -6852,9 +7481,9 @@ var import_node_fs8 = require("fs");
|
|
|
6852
7481
|
var import_node_crypto5 = require("crypto");
|
|
6853
7482
|
var import_chalk12 = __toESM(require("chalk"));
|
|
6854
7483
|
function resolvePublicKey(value) {
|
|
6855
|
-
let
|
|
7484
|
+
let stat4;
|
|
6856
7485
|
try {
|
|
6857
|
-
|
|
7486
|
+
stat4 = (0, import_node_fs8.statSync)(value);
|
|
6858
7487
|
} catch (e) {
|
|
6859
7488
|
const err = e;
|
|
6860
7489
|
if (err.code && err.code !== "ENOENT") {
|
|
@@ -6865,7 +7494,7 @@ function resolvePublicKey(value) {
|
|
|
6865
7494
|
}
|
|
6866
7495
|
return value;
|
|
6867
7496
|
}
|
|
6868
|
-
if (!
|
|
7497
|
+
if (!stat4.isFile()) {
|
|
6869
7498
|
throw new NhnCloudCliError(`--public-key \uAC00 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4: ${value}`, EXIT_PARAM_ERROR);
|
|
6870
7499
|
}
|
|
6871
7500
|
return (0, import_node_fs8.readFileSync)(value, "utf-8").trim();
|
|
@@ -7172,12 +7801,12 @@ var HarborClient = class {
|
|
|
7172
7801
|
* ky.get() 이 Response 를 반환하므로 .json() 과 .headers.get("link") 를 함께 사용한다
|
|
7173
7802
|
* (체이닝하면 헤더를 못 본다 — 기존 NCR client 의 .json<T>() 체이닝 패턴과 다름).
|
|
7174
7803
|
*/
|
|
7175
|
-
async getAllPages(
|
|
7804
|
+
async getAllPages(path4) {
|
|
7176
7805
|
const acc = [];
|
|
7177
7806
|
let page = 1;
|
|
7178
7807
|
try {
|
|
7179
7808
|
for (; ; ) {
|
|
7180
|
-
const url = `https://${this.host}${
|
|
7809
|
+
const url = `https://${this.host}${path4}?page=${page}&page_size=${PAGE_SIZE}`;
|
|
7181
7810
|
const res = await import_ky13.default.get(url, {
|
|
7182
7811
|
headers: this.basicAuthHeaders(),
|
|
7183
7812
|
retry: 0,
|
|
@@ -7417,15 +8046,15 @@ function commandPath(command) {
|
|
|
7417
8046
|
return names.join(" ");
|
|
7418
8047
|
}
|
|
7419
8048
|
function collectCommand(command) {
|
|
7420
|
-
const
|
|
7421
|
-
if (!
|
|
8049
|
+
const path4 = commandPath(command);
|
|
8050
|
+
if (!path4 || path4 === "help") return null;
|
|
7422
8051
|
return {
|
|
7423
|
-
path:
|
|
8052
|
+
path: path4,
|
|
7424
8053
|
description: command.description() || command.summary() || "",
|
|
7425
8054
|
arguments: command.registeredArguments.map((arg) => arg.name()),
|
|
7426
8055
|
options: command.options.filter((option) => !option.hidden).map((option) => option.flags),
|
|
7427
8056
|
subcommands: command.commands.map((subcommand) => subcommand.name()).filter((name) => name !== "help"),
|
|
7428
|
-
...
|
|
8057
|
+
...path4 === "commands" ? { metadata: true } : {}
|
|
7429
8058
|
};
|
|
7430
8059
|
}
|
|
7431
8060
|
function collectCommandCatalog(program2) {
|
|
@@ -7464,7 +8093,7 @@ function createCommandsCommand(program2) {
|
|
|
7464
8093
|
var import_commander48 = require("commander");
|
|
7465
8094
|
|
|
7466
8095
|
// src/commands/nks/helpers.ts
|
|
7467
|
-
var
|
|
8096
|
+
var import_promises5 = require("fs/promises");
|
|
7468
8097
|
|
|
7469
8098
|
// src/services/nks/client.ts
|
|
7470
8099
|
var import_ky14 = __toESM(require("ky"));
|
|
@@ -7914,15 +8543,15 @@ var NksClient = class {
|
|
|
7914
8543
|
throw toNhnCloudCliError(err);
|
|
7915
8544
|
}
|
|
7916
8545
|
}
|
|
7917
|
-
async getFlatNamedResource(
|
|
7918
|
-
const raw = await this.getJson(
|
|
8546
|
+
async getFlatNamedResource(path4, errorMessage) {
|
|
8547
|
+
const raw = await this.getJson(path4);
|
|
7919
8548
|
if (!isNksNamedResource(raw)) {
|
|
7920
8549
|
throw new NhnCloudCliError(errorMessage, EXIT_API_ERROR);
|
|
7921
8550
|
}
|
|
7922
8551
|
return raw;
|
|
7923
8552
|
}
|
|
7924
|
-
async getJson(
|
|
7925
|
-
const url = `${this.nksEndpoint}${
|
|
8553
|
+
async getJson(path4, searchParams) {
|
|
8554
|
+
const url = `${this.nksEndpoint}${path4}`;
|
|
7926
8555
|
try {
|
|
7927
8556
|
return await import_ky14.default.get(url, {
|
|
7928
8557
|
headers: this.authHeaders(),
|
|
@@ -7934,15 +8563,15 @@ var NksClient = class {
|
|
|
7934
8563
|
throw toNhnCloudCliError(err);
|
|
7935
8564
|
}
|
|
7936
8565
|
}
|
|
7937
|
-
async requestUuid(method,
|
|
7938
|
-
const raw = await this.requestJson(method,
|
|
8566
|
+
async requestUuid(method, path4, payload, errorMessage) {
|
|
8567
|
+
const raw = await this.requestJson(method, path4, payload);
|
|
7939
8568
|
if (!isNksUuidResponse(raw)) {
|
|
7940
8569
|
throw new NhnCloudCliError(errorMessage, EXIT_API_ERROR);
|
|
7941
8570
|
}
|
|
7942
8571
|
return raw;
|
|
7943
8572
|
}
|
|
7944
|
-
async requestNoBody(method,
|
|
7945
|
-
const url = `${this.nksEndpoint}${
|
|
8573
|
+
async requestNoBody(method, path4, payload) {
|
|
8574
|
+
const url = `${this.nksEndpoint}${path4}`;
|
|
7946
8575
|
try {
|
|
7947
8576
|
if (method === "delete") {
|
|
7948
8577
|
await import_ky14.default.delete(url, { headers: this.authHeaders(), retry: 0, timeout: DEFAULT_TIMEOUT_MS });
|
|
@@ -7953,8 +8582,8 @@ var NksClient = class {
|
|
|
7953
8582
|
throw toNhnCloudCliError(err);
|
|
7954
8583
|
}
|
|
7955
8584
|
}
|
|
7956
|
-
async requestJson(method,
|
|
7957
|
-
const url = `${this.nksEndpoint}${
|
|
8585
|
+
async requestJson(method, path4, payload) {
|
|
8586
|
+
const url = `${this.nksEndpoint}${path4}`;
|
|
7958
8587
|
try {
|
|
7959
8588
|
const options = { headers: this.authHeaders(), json: payload, retry: 0, timeout: DEFAULT_TIMEOUT_MS };
|
|
7960
8589
|
return method === "post" ? await import_ky14.default.post(url, options).json() : await import_ky14.default.patch(url, options).json();
|
|
@@ -7993,13 +8622,13 @@ async function resolveClusterUuid(client, cluster) {
|
|
|
7993
8622
|
}
|
|
7994
8623
|
return uuid;
|
|
7995
8624
|
}
|
|
7996
|
-
async function readJsonFile(
|
|
8625
|
+
async function readJsonFile(path4) {
|
|
7997
8626
|
let raw;
|
|
7998
8627
|
try {
|
|
7999
|
-
raw = await (0,
|
|
8628
|
+
raw = await (0, import_promises5.readFile)(path4, "utf-8");
|
|
8000
8629
|
} catch (err) {
|
|
8001
8630
|
const message = err instanceof Error ? err.message : String(err);
|
|
8002
|
-
throw new NhnCloudCliError(`JSON \uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${
|
|
8631
|
+
throw new NhnCloudCliError(`JSON \uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${path4} (${message})`, EXIT_PARAM_ERROR);
|
|
8003
8632
|
}
|
|
8004
8633
|
try {
|
|
8005
8634
|
const parsed = JSON.parse(raw);
|
|
@@ -8009,15 +8638,15 @@ async function readJsonFile(path5) {
|
|
|
8009
8638
|
return parsed;
|
|
8010
8639
|
} catch (err) {
|
|
8011
8640
|
const message = err instanceof Error ? err.message : String(err);
|
|
8012
|
-
throw new NhnCloudCliError(`JSON \uD30C\uC77C \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: ${
|
|
8641
|
+
throw new NhnCloudCliError(`JSON \uD30C\uC77C \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: ${path4} (${message})`, EXIT_PARAM_ERROR);
|
|
8013
8642
|
}
|
|
8014
8643
|
}
|
|
8015
|
-
async function readTextFile(
|
|
8644
|
+
async function readTextFile(path4) {
|
|
8016
8645
|
try {
|
|
8017
|
-
return await (0,
|
|
8646
|
+
return await (0, import_promises5.readFile)(path4, "utf-8");
|
|
8018
8647
|
} catch (err) {
|
|
8019
8648
|
const message = err instanceof Error ? err.message : String(err);
|
|
8020
|
-
throw new NhnCloudCliError(`\uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${
|
|
8649
|
+
throw new NhnCloudCliError(`\uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${path4} (${message})`, EXIT_PARAM_ERROR);
|
|
8021
8650
|
}
|
|
8022
8651
|
}
|
|
8023
8652
|
function parsePositiveInteger(value, optionName) {
|
|
@@ -8058,7 +8687,7 @@ var supportsCommand = new import_commander48.Command("supports").description("NK
|
|
|
8058
8687
|
});
|
|
8059
8688
|
|
|
8060
8689
|
// src/commands/nks/cluster.ts
|
|
8061
|
-
var
|
|
8690
|
+
var import_promises6 = require("fs/promises");
|
|
8062
8691
|
var import_commander49 = require("commander");
|
|
8063
8692
|
var import_chalk14 = __toESM(require("chalk"));
|
|
8064
8693
|
var listCommand8 = new import_commander49.Command("list").description("NKS \uD074\uB7EC\uC2A4\uD130 \uBAA9\uB85D\uC744 \uC870\uD68C\uD55C\uB2E4").option("--region <region>", "region override (\uAE30\uBCF8: iaas \uC790\uACA9\uC99D\uBA85\uC758 region)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (_opts, cmd) => {
|
|
@@ -8149,18 +8778,18 @@ async function confirmDangerousAction(message, yes) {
|
|
|
8149
8778
|
}
|
|
8150
8779
|
return ok;
|
|
8151
8780
|
}
|
|
8152
|
-
async function writeKubeconfigFile(
|
|
8781
|
+
async function writeKubeconfigFile(path4, contents, force) {
|
|
8153
8782
|
try {
|
|
8154
|
-
await (0,
|
|
8783
|
+
await (0, import_promises6.writeFile)(path4, contents, {
|
|
8155
8784
|
encoding: "utf-8",
|
|
8156
8785
|
mode: 384,
|
|
8157
8786
|
flag: force ? "w" : "wx"
|
|
8158
8787
|
});
|
|
8159
|
-
await (0,
|
|
8788
|
+
await (0, import_promises6.chmod)(path4, 384);
|
|
8160
8789
|
} catch (err) {
|
|
8161
8790
|
if (err instanceof Error && "code" in err && err.code === "EEXIST") {
|
|
8162
8791
|
throw new NhnCloudCliError(
|
|
8163
|
-
`\uD30C\uC77C\uC774 \uC774\uBBF8 \uC874\uC7AC\uD569\uB2C8\uB2E4: ${
|
|
8792
|
+
`\uD30C\uC77C\uC774 \uC774\uBBF8 \uC874\uC7AC\uD569\uB2C8\uB2E4: ${path4}. \uB36E\uC5B4\uC4F0\uB824\uBA74 --force \uB97C \uC9C0\uC815\uD558\uC138\uC694.`,
|
|
8164
8793
|
EXIT_PARAM_ERROR
|
|
8165
8794
|
);
|
|
8166
8795
|
}
|
|
@@ -8979,9 +9608,9 @@ async function resolveNcsClient(opts) {
|
|
|
8979
9608
|
return { client: new NcsClient(accessToken, region, appKey), profileName };
|
|
8980
9609
|
}
|
|
8981
9610
|
function readJsonPayload(filePath) {
|
|
8982
|
-
let
|
|
9611
|
+
let stat4;
|
|
8983
9612
|
try {
|
|
8984
|
-
|
|
9613
|
+
stat4 = (0, import_node_fs9.statSync)(filePath);
|
|
8985
9614
|
} catch (err) {
|
|
8986
9615
|
const reason = err.code ?? (err instanceof Error ? err.message : String(err));
|
|
8987
9616
|
throw new NhnCloudCliError(
|
|
@@ -8989,12 +9618,12 @@ function readJsonPayload(filePath) {
|
|
|
8989
9618
|
EXIT_PARAM_ERROR
|
|
8990
9619
|
);
|
|
8991
9620
|
}
|
|
8992
|
-
if (!
|
|
9621
|
+
if (!stat4.isFile()) {
|
|
8993
9622
|
throw new NhnCloudCliError(`--file \uC774 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4: ${filePath}`, EXIT_PARAM_ERROR);
|
|
8994
9623
|
}
|
|
8995
|
-
if (
|
|
9624
|
+
if (stat4.size > MAX_JSON_INPUT_BYTES) {
|
|
8996
9625
|
throw new NhnCloudCliError(
|
|
8997
|
-
`--file \uC774 \uB108\uBB34 \uD07D\uB2C8\uB2E4 (${
|
|
9626
|
+
`--file \uC774 \uB108\uBB34 \uD07D\uB2C8\uB2E4 (${stat4.size} \uBC14\uC774\uD2B8). JSON spec \uD55C\uB3C4 ${MAX_JSON_INPUT_BYTES} \uBC14\uC774\uD2B8.`,
|
|
8998
9627
|
EXIT_PARAM_ERROR
|
|
8999
9628
|
);
|
|
9000
9629
|
}
|
|
@@ -9725,7 +10354,7 @@ var malwareCommand = new import_commander54.Command("malware").description("NCS
|
|
|
9725
10354
|
var import_commander55 = require("commander");
|
|
9726
10355
|
|
|
9727
10356
|
// src/commands/apigateway/helpers.ts
|
|
9728
|
-
var
|
|
10357
|
+
var import_promises7 = require("fs/promises");
|
|
9729
10358
|
|
|
9730
10359
|
// src/services/apigateway/client.ts
|
|
9731
10360
|
var import_ky15 = __toESM(require("ky"));
|
|
@@ -10336,21 +10965,21 @@ function requireYes2(yes, operation) {
|
|
|
10336
10965
|
}
|
|
10337
10966
|
return true;
|
|
10338
10967
|
}
|
|
10339
|
-
async function readPluginConfigFile(
|
|
10968
|
+
async function readPluginConfigFile(path4) {
|
|
10340
10969
|
let fileStat;
|
|
10341
10970
|
try {
|
|
10342
|
-
fileStat = await (0,
|
|
10971
|
+
fileStat = await (0, import_promises7.stat)(path4);
|
|
10343
10972
|
} catch (error) {
|
|
10344
10973
|
const reason = fileErrorReason(error);
|
|
10345
10974
|
throw new NhnCloudCliError(
|
|
10346
|
-
`\uD50C\uB7EC\uADF8\uC778 \uC124\uC815 \uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${JSON.stringify(
|
|
10975
|
+
`\uD50C\uB7EC\uADF8\uC778 \uC124\uC815 \uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${JSON.stringify(path4)} (${JSON.stringify(reason)}).`,
|
|
10347
10976
|
EXIT_PARAM_ERROR
|
|
10348
10977
|
);
|
|
10349
10978
|
}
|
|
10350
10979
|
if (!fileStat.isFile()) {
|
|
10351
10980
|
const reason = fileStat.isDirectory() ? "EISDIR" : "EINVAL";
|
|
10352
10981
|
throw new NhnCloudCliError(
|
|
10353
|
-
`\uD50C\uB7EC\uADF8\uC778 \uC124\uC815 \uACBD\uB85C\uAC00 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4: ${JSON.stringify(
|
|
10982
|
+
`\uD50C\uB7EC\uADF8\uC778 \uC124\uC815 \uACBD\uB85C\uAC00 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4: ${JSON.stringify(path4)} (${reason}).`,
|
|
10354
10983
|
EXIT_PARAM_ERROR
|
|
10355
10984
|
);
|
|
10356
10985
|
}
|
|
@@ -10362,11 +10991,11 @@ async function readPluginConfigFile(path5) {
|
|
|
10362
10991
|
}
|
|
10363
10992
|
let raw;
|
|
10364
10993
|
try {
|
|
10365
|
-
raw = await (0,
|
|
10994
|
+
raw = await (0, import_promises7.readFile)(path4, "utf-8");
|
|
10366
10995
|
} catch (error) {
|
|
10367
10996
|
const reason = fileErrorReason(error);
|
|
10368
10997
|
throw new NhnCloudCliError(
|
|
10369
|
-
`\uD50C\uB7EC\uADF8\uC778 \uC124\uC815 \uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${JSON.stringify(
|
|
10998
|
+
`\uD50C\uB7EC\uADF8\uC778 \uC124\uC815 \uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${JSON.stringify(path4)} (${JSON.stringify(reason)}).`,
|
|
10370
10999
|
EXIT_PARAM_ERROR
|
|
10371
11000
|
);
|
|
10372
11001
|
}
|
|
@@ -10377,7 +11006,7 @@ async function readPluginConfigFile(path5) {
|
|
|
10377
11006
|
error instanceof Error ? error.message : String(error)
|
|
10378
11007
|
);
|
|
10379
11008
|
throw new NhnCloudCliError(
|
|
10380
|
-
`\uD50C\uB7EC\uADF8\uC778 \uC124\uC815 JSON \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: ${JSON.stringify(
|
|
11009
|
+
`\uD50C\uB7EC\uADF8\uC778 \uC124\uC815 JSON \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: ${JSON.stringify(path4)} (${reason}).`,
|
|
10381
11010
|
EXIT_PARAM_ERROR
|
|
10382
11011
|
);
|
|
10383
11012
|
}
|
|
@@ -10821,7 +11450,7 @@ var setMethodPluginCommand = addApiGatewayOptions(
|
|
|
10821
11450
|
var resourceCommand = new import_commander56.Command("resource").description("API Gateway resource \uC870\uD68C \uBC0F \uBCC0\uACBD \uBA85\uB839").addCommand(listCommand13).addCommand(parametersCommand).addCommand(responsesCommand).addCommand(setPathPluginCommand).addCommand(setMethodPluginCommand);
|
|
10822
11451
|
|
|
10823
11452
|
// src/commands/apigateway/stage.ts
|
|
10824
|
-
var
|
|
11453
|
+
var import_promises8 = require("fs/promises");
|
|
10825
11454
|
var import_commander58 = require("commander");
|
|
10826
11455
|
|
|
10827
11456
|
// src/commands/apigateway/deploy.ts
|
|
@@ -11028,9 +11657,9 @@ function fileErrorReason2(error) {
|
|
|
11028
11657
|
}
|
|
11029
11658
|
return error instanceof Error ? error.message : String(error);
|
|
11030
11659
|
}
|
|
11031
|
-
async function writeStageSwaggerFile(
|
|
11660
|
+
async function writeStageSwaggerFile(path4, swagger, force) {
|
|
11032
11661
|
try {
|
|
11033
|
-
await (0,
|
|
11662
|
+
await (0, import_promises8.writeFile)(path4, JSON.stringify(swagger, null, 2) + "\n", {
|
|
11034
11663
|
encoding: "utf-8",
|
|
11035
11664
|
flag: force ? "w" : "wx"
|
|
11036
11665
|
});
|
|
@@ -11038,7 +11667,7 @@ async function writeStageSwaggerFile(path5, swagger, force) {
|
|
|
11038
11667
|
const reason = fileErrorReason2(error);
|
|
11039
11668
|
const guidance = reason === "EEXIST" ? " \uB36E\uC5B4\uC4F0\uB824\uBA74 --force \uB97C \uC9C0\uC815\uD558\uC138\uC694." : "";
|
|
11040
11669
|
throw new NhnCloudCliError(
|
|
11041
|
-
`Swagger \uD30C\uC77C \uC800\uC7A5 \uC2E4\uD328: ${JSON.stringify(
|
|
11670
|
+
`Swagger \uD30C\uC77C \uC800\uC7A5 \uC2E4\uD328: ${JSON.stringify(path4)} (${JSON.stringify(reason)}).${guidance}`,
|
|
11042
11671
|
EXIT_PARAM_ERROR
|
|
11043
11672
|
);
|
|
11044
11673
|
}
|
|
@@ -11200,19 +11829,1343 @@ var importResourcesCommand = addApiGatewayOptions3(
|
|
|
11200
11829
|
});
|
|
11201
11830
|
var stageCommand = new import_commander58.Command("stage").description("API Gateway stage \uC870\uD68C \uBC0F \uBCC0\uACBD \uBA85\uB839").addCommand(listCommand15).addCommand(swaggerCommand).addCommand(resourcesCommand).addCommand(updateCommand3).addCommand(importResourcesCommand).addCommand(deployCommand);
|
|
11202
11831
|
|
|
11203
|
-
// src/commands/
|
|
11832
|
+
// src/commands/skm/confirm.ts
|
|
11204
11833
|
var import_commander59 = require("commander");
|
|
11205
11834
|
|
|
11206
|
-
// src/commands/
|
|
11835
|
+
// src/commands/skm/helpers.ts
|
|
11207
11836
|
var import_node_net2 = require("net");
|
|
11208
11837
|
|
|
11209
|
-
// src/services/
|
|
11838
|
+
// src/services/skm/client.ts
|
|
11210
11839
|
var import_ky16 = __toESM(require("ky"));
|
|
11211
11840
|
|
|
11212
|
-
// src/services/
|
|
11841
|
+
// src/services/skm/types.ts
|
|
11213
11842
|
function isRecord3(value) {
|
|
11214
11843
|
return typeof value === "object" && value !== null;
|
|
11215
11844
|
}
|
|
11845
|
+
function hasStrings(obj, keys) {
|
|
11846
|
+
return keys.every((key) => typeof obj[key] === "string");
|
|
11847
|
+
}
|
|
11848
|
+
function hasNumbers(obj, keys) {
|
|
11849
|
+
return keys.every((key) => typeof obj[key] === "number");
|
|
11850
|
+
}
|
|
11851
|
+
function hasOptional(obj, keys, type) {
|
|
11852
|
+
return keys.every((key) => obj[key] === void 0 || obj[key] === null || typeof obj[key] === type);
|
|
11853
|
+
}
|
|
11854
|
+
var AUDIT_FIELDS = ["creationUser", "creationDatetime", "lastChangeUser", "lastChangeDatetime"];
|
|
11855
|
+
function isSkmClientInfo(value) {
|
|
11856
|
+
if (!isRecord3(value)) return false;
|
|
11857
|
+
return typeof value["clientIp"] === "string" && typeof value["clientSentCertificate"] === "boolean" && hasOptional(value, ["clientMacHeader"], "string");
|
|
11858
|
+
}
|
|
11859
|
+
function isSkmKeyStore(value) {
|
|
11860
|
+
if (!isRecord3(value)) return false;
|
|
11861
|
+
return typeof value["keyStoreId"] === "number" && hasStrings(value, ["name", "ip4AuthUse", "macAuthUse", "certificateAuthUse"]) && hasOptional(value, ["description", ...AUDIT_FIELDS], "string");
|
|
11862
|
+
}
|
|
11863
|
+
function isSkmKey(value) {
|
|
11864
|
+
if (!isRecord3(value)) return false;
|
|
11865
|
+
return hasStrings(value, ["keyId", "name", "keyType"]) && typeof value["currentKeyValueVersion"] === "number" && hasOptional(value, ["autoRotationPeriod"], "number") && hasOptional(
|
|
11866
|
+
value,
|
|
11867
|
+
["description", "nextAutoRotationDate", "lastAccessDatetime", "deletionDatetime", ...AUDIT_FIELDS],
|
|
11868
|
+
"string"
|
|
11869
|
+
);
|
|
11870
|
+
}
|
|
11871
|
+
function isSkmAuthDetail(value) {
|
|
11872
|
+
if (!isRecord3(value)) return false;
|
|
11873
|
+
return (typeof value["value"] === "string" || typeof value["name"] === "string") && hasOptional(
|
|
11874
|
+
value,
|
|
11875
|
+
[
|
|
11876
|
+
"value",
|
|
11877
|
+
"name",
|
|
11878
|
+
"password",
|
|
11879
|
+
"description",
|
|
11880
|
+
"expirationDate",
|
|
11881
|
+
"lastAccessDatetime",
|
|
11882
|
+
"deletionDatetime",
|
|
11883
|
+
...AUDIT_FIELDS
|
|
11884
|
+
],
|
|
11885
|
+
"string"
|
|
11886
|
+
);
|
|
11887
|
+
}
|
|
11888
|
+
function isSkmEncryptResult(value) {
|
|
11889
|
+
return isRecord3(value) && hasStrings(value, ["ciphertext"]) && hasNumbers(value, ["keyVersion"]);
|
|
11890
|
+
}
|
|
11891
|
+
function isSkmDecryptResult(value) {
|
|
11892
|
+
return isRecord3(value) && hasStrings(value, ["plaintext"]) && hasNumbers(value, ["keyVersion"]);
|
|
11893
|
+
}
|
|
11894
|
+
function isSkmLocalKey(value) {
|
|
11895
|
+
return isRecord3(value) && hasStrings(value, ["localKeyPlaintext", "localKeyCiphertext"]) && hasNumbers(value, ["keyVersion"]);
|
|
11896
|
+
}
|
|
11897
|
+
function isSkmSymmetricKey(value) {
|
|
11898
|
+
return isRecord3(value) && hasStrings(value, ["symmetricKey"]) && hasNumbers(value, ["keyVersion"]);
|
|
11899
|
+
}
|
|
11900
|
+
function isSkmSignResult(value) {
|
|
11901
|
+
return isRecord3(value) && hasStrings(value, ["signature"]) && hasNumbers(value, ["keyVersion"]);
|
|
11902
|
+
}
|
|
11903
|
+
function isSkmStandardSignResult(value) {
|
|
11904
|
+
return isRecord3(value) && hasStrings(value, ["signature", "algorithm", "hashAlgorithm", "mgfAlgorithm"]) && hasNumbers(value, ["keyVersion", "saltLength"]);
|
|
11905
|
+
}
|
|
11906
|
+
function isSkmVerifyResult(value) {
|
|
11907
|
+
return isRecord3(value) && typeof value["result"] === "boolean" && hasNumbers(value, ["keyVersion"]);
|
|
11908
|
+
}
|
|
11909
|
+
function isSkmAsymmetricKeyMaterial(value) {
|
|
11910
|
+
return isRecord3(value) && hasStrings(value, ["keyType", "key", "encodedKey"]) && hasOptional(value, ["standardEncodedKey"], "string") && hasNumbers(value, ["keyVersion"]);
|
|
11911
|
+
}
|
|
11912
|
+
function isSkmCreatedKey(value) {
|
|
11913
|
+
return isRecord3(value) && hasStrings(value, ["keyId", "keyStatus"]);
|
|
11914
|
+
}
|
|
11915
|
+
function isSkmCreatedKeyStore(value) {
|
|
11916
|
+
if (!isRecord3(value)) return false;
|
|
11917
|
+
return typeof value["keyStoreId"] === "number" && hasStrings(value, ["name", "ip4AuthUse", "macAuthUse", "certificateAuthUse"]) && hasOptional(value, ["description", "authMode"], "string");
|
|
11918
|
+
}
|
|
11919
|
+
function isSkmUpdatedSecret(value) {
|
|
11920
|
+
if (!isRecord3(value)) return false;
|
|
11921
|
+
return hasStrings(value, ["keyId", "name"]) && hasOptional(value, ["description", "secretValue", ...AUDIT_FIELDS], "string");
|
|
11922
|
+
}
|
|
11923
|
+
function isSkmDeletion(value) {
|
|
11924
|
+
return isRecord3(value) && hasStrings(value, ["keyId", "deletionDateTime"]);
|
|
11925
|
+
}
|
|
11926
|
+
function hasAuthIdentifier(obj) {
|
|
11927
|
+
return (typeof obj["value"] === "string" || typeof obj["name"] === "string") && hasOptional(obj, ["value", "name"], "string");
|
|
11928
|
+
}
|
|
11929
|
+
function isSkmAuthAdded(value) {
|
|
11930
|
+
return isRecord3(value) && hasAuthIdentifier(value) && hasOptional(value, ["description"], "string");
|
|
11931
|
+
}
|
|
11932
|
+
function isSkmAuthDeletion(value) {
|
|
11933
|
+
return isRecord3(value) && hasAuthIdentifier(value) && hasStrings(value, ["deletionDateTime"]);
|
|
11934
|
+
}
|
|
11935
|
+
|
|
11936
|
+
// src/services/skm/client.ts
|
|
11937
|
+
var KEY_PAGE_SIZE = 100;
|
|
11938
|
+
var STANDARD_SIGN_ALGORITHM = "RSASSA-PSS";
|
|
11939
|
+
var AUTH_PATHS = {
|
|
11940
|
+
ipv4: { path: "ips", field: "ipv4List" },
|
|
11941
|
+
mac: { path: "macs", field: "macList" },
|
|
11942
|
+
certificate: { path: "certificates", field: "certificateList" }
|
|
11943
|
+
};
|
|
11944
|
+
var AUTH_WRITE_PATH = {
|
|
11945
|
+
ipv4: "ipv4s",
|
|
11946
|
+
mac: "macs",
|
|
11947
|
+
certificate: "certificates"
|
|
11948
|
+
};
|
|
11949
|
+
function isRecord4(value) {
|
|
11950
|
+
return typeof value === "object" && value !== null;
|
|
11951
|
+
}
|
|
11952
|
+
function isEnvelope(value) {
|
|
11953
|
+
if (!isRecord4(value)) return false;
|
|
11954
|
+
const header = value["header"];
|
|
11955
|
+
return isRecord4(header) && typeof header["isSuccessful"] === "boolean";
|
|
11956
|
+
}
|
|
11957
|
+
function arrayOf(guard) {
|
|
11958
|
+
return (value) => Array.isArray(value) && value.every(guard);
|
|
11959
|
+
}
|
|
11960
|
+
function isString(value) {
|
|
11961
|
+
return typeof value === "string";
|
|
11962
|
+
}
|
|
11963
|
+
function withDescription(body, description) {
|
|
11964
|
+
return description === void 0 ? body : { ...body, description };
|
|
11965
|
+
}
|
|
11966
|
+
function authDeletionBody(type, keyStoreName, value) {
|
|
11967
|
+
return type === "certificate" ? { keyStoreName, name: value } : { keyStoreName, value };
|
|
11968
|
+
}
|
|
11969
|
+
function keyStoreBody(input) {
|
|
11970
|
+
const { name, description, ip4AuthUse, macAuthUse, certificateAuthUse, authMode } = input;
|
|
11971
|
+
return withDescription({ name, ip4AuthUse, macAuthUse, certificateAuthUse, authMode }, description);
|
|
11972
|
+
}
|
|
11973
|
+
function keyVersionParams(keyVersion) {
|
|
11974
|
+
return keyVersion === void 0 ? {} : { searchParams: { keyVersion } };
|
|
11975
|
+
}
|
|
11976
|
+
async function toSkmError(err) {
|
|
11977
|
+
if (!(err instanceof import_ky16.HTTPError)) return toNhnCloudCliError(err);
|
|
11978
|
+
let resultMessage = null;
|
|
11979
|
+
const body = await readHttpErrorBody(err);
|
|
11980
|
+
const header = isRecord4(body) ? body["header"] : void 0;
|
|
11981
|
+
const message = isRecord4(header) ? header["resultMessage"] : void 0;
|
|
11982
|
+
if (typeof message === "string") resultMessage = message;
|
|
11983
|
+
if (resultMessage === null) return toNhnCloudCliError(err);
|
|
11984
|
+
const status = err.response.status;
|
|
11985
|
+
return new NhnCloudCliError(
|
|
11986
|
+
`API \uD638\uCD9C \uC2E4\uD328 (${status}): ${sanitizeForTerminal(resultMessage)}`,
|
|
11987
|
+
status === 401 || status === 403 ? EXIT_AUTH_ERROR : EXIT_API_ERROR
|
|
11988
|
+
);
|
|
11989
|
+
}
|
|
11990
|
+
var SkmClient = class {
|
|
11991
|
+
baseUrl;
|
|
11992
|
+
headers;
|
|
11993
|
+
constructor(accessToken, environment, appKey, macAddress) {
|
|
11994
|
+
this.baseUrl = `${endpointFor("skm", environment)}/keymanager/v1.3/appkey/${encodeURIComponent(appKey)}`;
|
|
11995
|
+
this.headers = { "X-NHN-Authorization": `Bearer ${accessToken}` };
|
|
11996
|
+
if (macAddress !== void 0) {
|
|
11997
|
+
this.headers["X-TOAST-CLIENT-MAC-ADDR"] = macAddress;
|
|
11998
|
+
}
|
|
11999
|
+
}
|
|
12000
|
+
/**
|
|
12001
|
+
* 요청을 보내고 봉투 형태인지만 확인해 반환한다. 성공 판정은 호출부가 한다.
|
|
12002
|
+
* 쓰기 요청도 중복 실행을 막으려고 재시도하지 않는다.
|
|
12003
|
+
*/
|
|
12004
|
+
async send(method, path4, options) {
|
|
12005
|
+
let response;
|
|
12006
|
+
try {
|
|
12007
|
+
response = await import_ky16.default[method](`${this.baseUrl}${path4}`, {
|
|
12008
|
+
headers: this.headers,
|
|
12009
|
+
...options,
|
|
12010
|
+
retry: 0,
|
|
12011
|
+
timeout: DEFAULT_TIMEOUT_MS
|
|
12012
|
+
}).json();
|
|
12013
|
+
} catch (err) {
|
|
12014
|
+
throw await toSkmError(err);
|
|
12015
|
+
}
|
|
12016
|
+
if (!isEnvelope(response)) {
|
|
12017
|
+
throw new NhnCloudCliError("Secure Key Manager \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: header", EXIT_API_ERROR);
|
|
12018
|
+
}
|
|
12019
|
+
return response;
|
|
12020
|
+
}
|
|
12021
|
+
/**
|
|
12022
|
+
* 요청을 보내고 봉투를 벗긴 뒤 body 또는 body[field] 를 가드로 검사해 반환한다.
|
|
12023
|
+
* field 가 null 이면 body 전체를 검사한다.
|
|
12024
|
+
*/
|
|
12025
|
+
async request(method, path4, field, guard, options = {}) {
|
|
12026
|
+
const body = unwrap(await this.send(method, path4, options));
|
|
12027
|
+
const value = field === null ? body : isRecord4(body) ? body[field] : void 0;
|
|
12028
|
+
if (!guard(value)) {
|
|
12029
|
+
throw new NhnCloudCliError(`Secure Key Manager \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: ${field ?? "body"}`, EXIT_API_ERROR);
|
|
12030
|
+
}
|
|
12031
|
+
return value;
|
|
12032
|
+
}
|
|
12033
|
+
/**
|
|
12034
|
+
* body 가 null 이거나 없는 응답(키 저장소 수정·삭제)은 검사할 필드가 없어 헤더만 본다 (ADR-040).
|
|
12035
|
+
* isSuccessful 이 false 면 unwrapHeader 가 NhnEnvelopeError 를 던진다.
|
|
12036
|
+
*/
|
|
12037
|
+
async requestHeaderOnly(method, path4, options = {}) {
|
|
12038
|
+
unwrapHeader(await this.send(method, path4, options));
|
|
12039
|
+
}
|
|
12040
|
+
keyPath(prefix, keyId, action) {
|
|
12041
|
+
return `/${prefix}/${encodeURIComponent(keyId)}/${action}`;
|
|
12042
|
+
}
|
|
12043
|
+
/** 호출 클라이언트의 IP·MAC·인증서 전송 여부를 확인한다. */
|
|
12044
|
+
confirm() {
|
|
12045
|
+
return this.request("get", "/confirm", null, isSkmClientInfo);
|
|
12046
|
+
}
|
|
12047
|
+
listKeyStores() {
|
|
12048
|
+
return this.request("get", "/keystores", "keyStoreList", arrayOf(isSkmKeyStore), {
|
|
12049
|
+
searchParams: { detail: "true" }
|
|
12050
|
+
});
|
|
12051
|
+
}
|
|
12052
|
+
getKeyStore(keyStoreId) {
|
|
12053
|
+
return this.request("get", `/keystores/${keyStoreId}`, null, isSkmKeyStore);
|
|
12054
|
+
}
|
|
12055
|
+
/**
|
|
12056
|
+
* 모든 페이지의 키를 모은다.
|
|
12057
|
+
* 서버가 pageNumber 를 무시하면 같은 페이지가 반복되므로, 첫 keyId 가 직전 페이지와 같으면 중단한다.
|
|
12058
|
+
*/
|
|
12059
|
+
async listKeys(keyStoreId, filter = {}) {
|
|
12060
|
+
const keys = [];
|
|
12061
|
+
let previousFirstKeyId;
|
|
12062
|
+
for (let pageNumber = 1; ; pageNumber++) {
|
|
12063
|
+
const searchParams = { detail: "true", pageNumber, pageSize: KEY_PAGE_SIZE };
|
|
12064
|
+
if (filter.type) searchParams["type"] = filter.type;
|
|
12065
|
+
if (filter.name) searchParams["name"] = filter.name;
|
|
12066
|
+
if (filter.status) searchParams["status"] = filter.status;
|
|
12067
|
+
const page = await this.request("get", `/keystores/${keyStoreId}/keys`, "keyList", arrayOf(isSkmKey), {
|
|
12068
|
+
searchParams
|
|
12069
|
+
});
|
|
12070
|
+
const firstKeyId = page[0]?.keyId;
|
|
12071
|
+
if (firstKeyId !== void 0 && firstKeyId === previousFirstKeyId) {
|
|
12072
|
+
throw new NhnCloudCliError(
|
|
12073
|
+
`Secure Key Manager \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: ${pageNumber} \uD398\uC774\uC9C0\uAC00 \uC9C1\uC804 \uD398\uC774\uC9C0\uC640 \uAC19\uC740 \uD0A4\uB85C \uC2DC\uC791\uD569\uB2C8\uB2E4.`,
|
|
12074
|
+
EXIT_API_ERROR
|
|
12075
|
+
);
|
|
12076
|
+
}
|
|
12077
|
+
keys.push(...page);
|
|
12078
|
+
if (page.length < KEY_PAGE_SIZE) return keys;
|
|
12079
|
+
previousFirstKeyId = firstKeyId;
|
|
12080
|
+
}
|
|
12081
|
+
}
|
|
12082
|
+
getKey(keyStoreId, keyId) {
|
|
12083
|
+
return this.request("get", `/keystores/${keyStoreId}/keys/${encodeURIComponent(keyId)}`, null, isSkmKey);
|
|
12084
|
+
}
|
|
12085
|
+
listAuths(keyStoreId, type) {
|
|
12086
|
+
const { path: path4, field } = AUTH_PATHS[type];
|
|
12087
|
+
return this.request("get", `/keystores/${keyStoreId}/${path4}`, field, arrayOf(isString));
|
|
12088
|
+
}
|
|
12089
|
+
getAuth(keyStoreId, type, value) {
|
|
12090
|
+
const { path: path4, field } = AUTH_PATHS[type];
|
|
12091
|
+
return this.request("get", `/keystores/${keyStoreId}/${path4}`, field, arrayOf(isSkmAuthDetail), {
|
|
12092
|
+
searchParams: { value }
|
|
12093
|
+
});
|
|
12094
|
+
}
|
|
12095
|
+
getSecret(keyId) {
|
|
12096
|
+
return this.request("get", `/secrets/${encodeURIComponent(keyId)}`, "secret", isString);
|
|
12097
|
+
}
|
|
12098
|
+
encrypt(keyId, plaintext) {
|
|
12099
|
+
return this.request("post", this.keyPath("symmetric-keys", keyId, "encrypt"), null, isSkmEncryptResult, {
|
|
12100
|
+
json: { plaintext }
|
|
12101
|
+
});
|
|
12102
|
+
}
|
|
12103
|
+
decrypt(keyId, ciphertext) {
|
|
12104
|
+
return this.request("post", this.keyPath("symmetric-keys", keyId, "decrypt"), null, isSkmDecryptResult, {
|
|
12105
|
+
json: { ciphertext }
|
|
12106
|
+
});
|
|
12107
|
+
}
|
|
12108
|
+
createLocalKey(keyId) {
|
|
12109
|
+
return this.request("post", this.keyPath("symmetric-keys", keyId, "create-local-key"), null, isSkmLocalKey);
|
|
12110
|
+
}
|
|
12111
|
+
getSymmetricKey(keyId, keyVersion) {
|
|
12112
|
+
return this.request(
|
|
12113
|
+
"get",
|
|
12114
|
+
this.keyPath("symmetric-keys", keyId, "symmetric-key"),
|
|
12115
|
+
null,
|
|
12116
|
+
isSkmSymmetricKey,
|
|
12117
|
+
keyVersionParams(keyVersion)
|
|
12118
|
+
);
|
|
12119
|
+
}
|
|
12120
|
+
sign(keyId, plaintext) {
|
|
12121
|
+
return this.request("post", this.keyPath("asymmetric-keys", keyId, "sign"), null, isSkmSignResult, {
|
|
12122
|
+
json: { plaintext }
|
|
12123
|
+
});
|
|
12124
|
+
}
|
|
12125
|
+
verify(keyId, plaintext, signature) {
|
|
12126
|
+
return this.request("post", this.keyPath("asymmetric-keys", keyId, "verify"), null, isSkmVerifyResult, {
|
|
12127
|
+
json: { plaintext, signature }
|
|
12128
|
+
});
|
|
12129
|
+
}
|
|
12130
|
+
signStandard(keyId, plaintextBase64) {
|
|
12131
|
+
return this.request(
|
|
12132
|
+
"post",
|
|
12133
|
+
this.keyPath("asymmetric-keys", keyId, "sign-standard"),
|
|
12134
|
+
null,
|
|
12135
|
+
isSkmStandardSignResult,
|
|
12136
|
+
{ json: { plaintext: plaintextBase64, algorithm: STANDARD_SIGN_ALGORITHM } }
|
|
12137
|
+
);
|
|
12138
|
+
}
|
|
12139
|
+
verifyStandard(keyId, plaintextBase64, signature, keyVersion) {
|
|
12140
|
+
return this.request("post", this.keyPath("asymmetric-keys", keyId, "verify-standard"), null, isSkmVerifyResult, {
|
|
12141
|
+
json: { plaintext: plaintextBase64, signature, algorithm: STANDARD_SIGN_ALGORITHM, keyVersion }
|
|
12142
|
+
});
|
|
12143
|
+
}
|
|
12144
|
+
getPrivateKey(keyId, keyVersion) {
|
|
12145
|
+
return this.request(
|
|
12146
|
+
"get",
|
|
12147
|
+
this.keyPath("asymmetric-keys", keyId, "privateKey"),
|
|
12148
|
+
null,
|
|
12149
|
+
isSkmAsymmetricKeyMaterial,
|
|
12150
|
+
keyVersionParams(keyVersion)
|
|
12151
|
+
);
|
|
12152
|
+
}
|
|
12153
|
+
getPublicKey(keyId, keyVersion) {
|
|
12154
|
+
return this.request(
|
|
12155
|
+
"get",
|
|
12156
|
+
this.keyPath("asymmetric-keys", keyId, "publicKey"),
|
|
12157
|
+
null,
|
|
12158
|
+
isSkmAsymmetricKeyMaterial,
|
|
12159
|
+
keyVersionParams(keyVersion)
|
|
12160
|
+
);
|
|
12161
|
+
}
|
|
12162
|
+
createSecret(keyStoreName, name, description, secretValue) {
|
|
12163
|
+
return this.request("post", "/keys/secrets/create", null, isSkmCreatedKey, {
|
|
12164
|
+
json: withDescription({ keyStoreName, name, secretValue }, description)
|
|
12165
|
+
});
|
|
12166
|
+
}
|
|
12167
|
+
/** 자동 회전 주기의 단위가 문서에 없어 항상 0(자동 회전 안 함)을 보낸다 (ADR-040). */
|
|
12168
|
+
createSymmetricKey(keyStoreName, name, description) {
|
|
12169
|
+
return this.request("post", "/keys/symmetric-keys/create", null, isSkmCreatedKey, {
|
|
12170
|
+
json: withDescription({ keyStoreName, name, autoRotationPeriod: 0 }, description)
|
|
12171
|
+
});
|
|
12172
|
+
}
|
|
12173
|
+
/** 자동 회전 주기의 단위가 문서에 없어 항상 0(자동 회전 안 함)을 보낸다 (ADR-040). */
|
|
12174
|
+
createAsymmetricKey(keyStoreName, name, description) {
|
|
12175
|
+
return this.request("post", "/keys/asymmetric-keys/create", null, isSkmCreatedKey, {
|
|
12176
|
+
json: withDescription({ keyStoreName, name, autoRotationPeriod: 0 }, description)
|
|
12177
|
+
});
|
|
12178
|
+
}
|
|
12179
|
+
updateSecret(keyId, secretValue) {
|
|
12180
|
+
return this.request("put", `/secrets/${encodeURIComponent(keyId)}`, null, isSkmUpdatedSecret, {
|
|
12181
|
+
json: { secretValue }
|
|
12182
|
+
});
|
|
12183
|
+
}
|
|
12184
|
+
/** 7일 뒤 삭제를 예약한다. */
|
|
12185
|
+
scheduleKeyDeletion(keyId) {
|
|
12186
|
+
return this.request("put", this.keyPath("keys", keyId, "delete"), null, isSkmDeletion);
|
|
12187
|
+
}
|
|
12188
|
+
/** 삭제 예약된 키를 즉시 삭제한다. 되돌릴 수 없다. */
|
|
12189
|
+
deleteKeyNow(keyId) {
|
|
12190
|
+
return this.request("delete", `/keys/${encodeURIComponent(keyId)}`, null, isSkmDeletion);
|
|
12191
|
+
}
|
|
12192
|
+
createKeyStore(input) {
|
|
12193
|
+
return this.request("post", "/keystores", null, isSkmCreatedKeyStore, { json: keyStoreBody(input) });
|
|
12194
|
+
}
|
|
12195
|
+
/** 전체 교체 API 라 주지 않은 값은 호출부가 현재 값으로 채워 넘긴다 (ADR-040). */
|
|
12196
|
+
updateKeyStore(keyStoreId, input) {
|
|
12197
|
+
return this.requestHeaderOnly("put", `/keystores/${keyStoreId}`, { json: keyStoreBody(input) });
|
|
12198
|
+
}
|
|
12199
|
+
deleteKeyStore(keyStoreId) {
|
|
12200
|
+
return this.requestHeaderOnly("delete", `/keystores/${keyStoreId}`);
|
|
12201
|
+
}
|
|
12202
|
+
addAuth(type, keyStoreName, value, description) {
|
|
12203
|
+
return this.request("post", `/auths/${AUTH_WRITE_PATH[type]}`, null, isSkmAuthAdded, {
|
|
12204
|
+
json: withDescription({ keyStoreName, value }, description)
|
|
12205
|
+
});
|
|
12206
|
+
}
|
|
12207
|
+
addCertificate(keyStoreName, name, password, lifeTime, description) {
|
|
12208
|
+
return this.request("post", `/auths/${AUTH_WRITE_PATH.certificate}`, null, isSkmAuthAdded, {
|
|
12209
|
+
json: withDescription({ keyStoreName, name, password, lifeTime }, description)
|
|
12210
|
+
});
|
|
12211
|
+
}
|
|
12212
|
+
/** 7일 뒤 삭제를 예약한다. */
|
|
12213
|
+
scheduleAuthDeletion(type, keyStoreName, value) {
|
|
12214
|
+
return this.request("put", `/auths/${AUTH_WRITE_PATH[type]}/delete`, null, isSkmAuthDeletion, {
|
|
12215
|
+
json: authDeletionBody(type, keyStoreName, value)
|
|
12216
|
+
});
|
|
12217
|
+
}
|
|
12218
|
+
/** 삭제 예약된 인증 정보를 즉시 삭제한다. 되돌릴 수 없다. */
|
|
12219
|
+
deleteAuthNow(type, keyStoreName, value) {
|
|
12220
|
+
return this.request("post", `/auths/${AUTH_WRITE_PATH[type]}/delete`, null, isSkmAuthDeletion, {
|
|
12221
|
+
json: authDeletionBody(type, keyStoreName, value)
|
|
12222
|
+
});
|
|
12223
|
+
}
|
|
12224
|
+
};
|
|
12225
|
+
|
|
12226
|
+
// src/commands/skm/helpers.ts
|
|
12227
|
+
var MAC_ADDRESS_PATTERN = /^[0-9A-Fa-f]{2}(:[0-9A-Fa-f]{2}){5}$/;
|
|
12228
|
+
var KEY_NAME_MAX_LENGTH = 100;
|
|
12229
|
+
var KEY_TYPES = {
|
|
12230
|
+
secret: "SECRET",
|
|
12231
|
+
"symmetric-key": "SYMMETRIC_KEY",
|
|
12232
|
+
"asymmetric-key": "ASYMMETRIC_KEY"
|
|
12233
|
+
};
|
|
12234
|
+
var AUTH_TYPES = ["ipv4", "mac", "certificate"];
|
|
12235
|
+
function withSkmOptions(command) {
|
|
12236
|
+
return command.option("--mac-address <mac>", "\uD0A4 \uC800\uC7A5\uC18C MAC \uC778\uC99D\uC5D0 \uC4F8 \uD074\uB77C\uC774\uC5B8\uD2B8 MAC \uC8FC\uC18C (X-TOAST-CLIENT-MAC-ADDR)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984");
|
|
12237
|
+
}
|
|
12238
|
+
function withTypeOption(command) {
|
|
12239
|
+
return command.requiredOption("--type <type>", "\uC778\uC99D \uC815\uBCF4 \uC885\uB958 (ipv4|mac|certificate)");
|
|
12240
|
+
}
|
|
12241
|
+
function parseMacAddressOption(value) {
|
|
12242
|
+
if (value === void 0) return void 0;
|
|
12243
|
+
if (!MAC_ADDRESS_PATTERN.test(value)) {
|
|
12244
|
+
throw new NhnCloudCliError(
|
|
12245
|
+
`--mac-address\uB294 aa:bb:cc:dd:ee:ff \uD615\uC2DD\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4 (\uC785\uB825: ${JSON.stringify(value)}).`,
|
|
12246
|
+
EXIT_PARAM_ERROR
|
|
12247
|
+
);
|
|
12248
|
+
}
|
|
12249
|
+
return value.toLowerCase();
|
|
12250
|
+
}
|
|
12251
|
+
function parseKeyStoreId(value) {
|
|
12252
|
+
return parseNonNegativeIntegerOption(parseRequiredArgument(value, "keystore-id"), "<keystore-id>");
|
|
12253
|
+
}
|
|
12254
|
+
function parseAuthTypeOption(value) {
|
|
12255
|
+
const found = AUTH_TYPES.find((type) => type === value);
|
|
12256
|
+
if (!found) {
|
|
12257
|
+
throw new NhnCloudCliError(
|
|
12258
|
+
`--type\uC740 ipv4, mac, certificate \uC911 \uD558\uB098\uC5EC\uC57C \uD569\uB2C8\uB2E4 (\uC785\uB825: ${JSON.stringify(value)}).`,
|
|
12259
|
+
EXIT_PARAM_ERROR
|
|
12260
|
+
);
|
|
12261
|
+
}
|
|
12262
|
+
return found;
|
|
12263
|
+
}
|
|
12264
|
+
function parseAuthListOption(value) {
|
|
12265
|
+
const items = value.split(",").map((item) => item.trim());
|
|
12266
|
+
if (items.some((item) => !AUTH_TYPES.some((type) => type === item))) {
|
|
12267
|
+
throw new NhnCloudCliError(
|
|
12268
|
+
`--auth\uB294 ipv4, mac, certificate\uB97C \uC27C\uD45C\uB85C \uB098\uC5F4\uD574\uC57C \uD569\uB2C8\uB2E4 (\uC785\uB825: ${JSON.stringify(value)}).`,
|
|
12269
|
+
EXIT_PARAM_ERROR
|
|
12270
|
+
);
|
|
12271
|
+
}
|
|
12272
|
+
const flag = (type) => items.includes(type) ? "Y" : "N";
|
|
12273
|
+
return { ip4AuthUse: flag("ipv4"), macAuthUse: flag("mac"), certificateAuthUse: flag("certificate") };
|
|
12274
|
+
}
|
|
12275
|
+
function parseAuthModeOption(value) {
|
|
12276
|
+
const upper = value.toUpperCase();
|
|
12277
|
+
if (upper !== "AND" && upper !== "OR") {
|
|
12278
|
+
throw new NhnCloudCliError(
|
|
12279
|
+
`--auth-mode\uB294 and \uB610\uB294 or\uC5EC\uC57C \uD569\uB2C8\uB2E4 (\uC785\uB825: ${JSON.stringify(value)}).`,
|
|
12280
|
+
EXIT_PARAM_ERROR
|
|
12281
|
+
);
|
|
12282
|
+
}
|
|
12283
|
+
return upper;
|
|
12284
|
+
}
|
|
12285
|
+
function parseDescriptionOption(value, maxLength) {
|
|
12286
|
+
const trimmed = value?.trim();
|
|
12287
|
+
if (!trimmed) return void 0;
|
|
12288
|
+
if (trimmed.length > maxLength) {
|
|
12289
|
+
throw new NhnCloudCliError(`--description\uC740 ${maxLength}\uC790 \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4.`, EXIT_PARAM_ERROR);
|
|
12290
|
+
}
|
|
12291
|
+
return trimmed;
|
|
12292
|
+
}
|
|
12293
|
+
function isIpv4OrCidr2(value) {
|
|
12294
|
+
const [address, prefix, ...rest] = value.split("/");
|
|
12295
|
+
if (rest.length > 0 || address === void 0 || (0, import_node_net2.isIP)(address) !== 4) return false;
|
|
12296
|
+
return prefix === void 0 || /^(\d|[12]\d|3[0-2])$/.test(prefix);
|
|
12297
|
+
}
|
|
12298
|
+
function parseAuthValue(type, value) {
|
|
12299
|
+
if (type === "ipv4") {
|
|
12300
|
+
if (!isIpv4OrCidr2(value)) {
|
|
12301
|
+
throw new NhnCloudCliError(
|
|
12302
|
+
`IPv4 \uC8FC\uC18C\uB098 CIDR \uB300\uC5ED \uD615\uC2DD\uC774 \uC544\uB2D9\uB2C8\uB2E4 (\uC785\uB825: ${JSON.stringify(value)}).`,
|
|
12303
|
+
EXIT_PARAM_ERROR
|
|
12304
|
+
);
|
|
12305
|
+
}
|
|
12306
|
+
return value;
|
|
12307
|
+
}
|
|
12308
|
+
if (type === "mac") {
|
|
12309
|
+
if (!MAC_ADDRESS_PATTERN.test(value)) {
|
|
12310
|
+
throw new NhnCloudCliError(
|
|
12311
|
+
`MAC \uC8FC\uC18C\uB294 aa:bb:cc:dd:ee:ff \uD615\uC2DD\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4 (\uC785\uB825: ${JSON.stringify(value)}).`,
|
|
12312
|
+
EXIT_PARAM_ERROR
|
|
12313
|
+
);
|
|
12314
|
+
}
|
|
12315
|
+
return value.toLowerCase();
|
|
12316
|
+
}
|
|
12317
|
+
const name = value.trim();
|
|
12318
|
+
if (!name) {
|
|
12319
|
+
throw new NhnCloudCliError("\uC778\uC99D\uC11C \uC774\uB984\uC774 \uBE44\uC5B4 \uC788\uC2B5\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
12320
|
+
}
|
|
12321
|
+
return name;
|
|
12322
|
+
}
|
|
12323
|
+
function parseKeyTypeOption(value) {
|
|
12324
|
+
if (value === void 0) return void 0;
|
|
12325
|
+
const found = Object.hasOwn(KEY_TYPES, value) ? KEY_TYPES[value] : void 0;
|
|
12326
|
+
if (!found) {
|
|
12327
|
+
throw new NhnCloudCliError(
|
|
12328
|
+
`--type\uC740 secret, symmetric-key, asymmetric-key \uC911 \uD558\uB098\uC5EC\uC57C \uD569\uB2C8\uB2E4 (\uC785\uB825: ${JSON.stringify(value)}).`,
|
|
12329
|
+
EXIT_PARAM_ERROR
|
|
12330
|
+
);
|
|
12331
|
+
}
|
|
12332
|
+
return found;
|
|
12333
|
+
}
|
|
12334
|
+
function parseKeyStatusOption(value) {
|
|
12335
|
+
if (value === void 0) return void 0;
|
|
12336
|
+
if (value !== "active" && value !== "inactive") {
|
|
12337
|
+
throw new NhnCloudCliError(
|
|
12338
|
+
`--status\uB294 active \uB610\uB294 inactive\uC5EC\uC57C \uD569\uB2C8\uB2E4 (\uC785\uB825: ${JSON.stringify(value)}).`,
|
|
12339
|
+
EXIT_PARAM_ERROR
|
|
12340
|
+
);
|
|
12341
|
+
}
|
|
12342
|
+
return value;
|
|
12343
|
+
}
|
|
12344
|
+
function parseKeyNameOption(value) {
|
|
12345
|
+
if (value === void 0) return void 0;
|
|
12346
|
+
const trimmed = value.trim();
|
|
12347
|
+
if (!trimmed) {
|
|
12348
|
+
throw new NhnCloudCliError("--name\uC740 \uBE44\uC5B4 \uC788\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
12349
|
+
}
|
|
12350
|
+
if (trimmed.length > KEY_NAME_MAX_LENGTH) {
|
|
12351
|
+
throw new NhnCloudCliError(`--name\uC740 ${KEY_NAME_MAX_LENGTH}\uC790 \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4.`, EXIT_PARAM_ERROR);
|
|
12352
|
+
}
|
|
12353
|
+
return trimmed;
|
|
12354
|
+
}
|
|
12355
|
+
async function resolveSkmClient(opts) {
|
|
12356
|
+
const profileName = await resolveProfileName(opts.profile);
|
|
12357
|
+
const appKey = await resolveServiceAppKey(
|
|
12358
|
+
"skm",
|
|
12359
|
+
profileName,
|
|
12360
|
+
"Secure Key Manager appkey\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. nhncloud configure --skm-appkey <key>\uB85C \uC124\uC815\uD558\uC138\uC694."
|
|
12361
|
+
);
|
|
12362
|
+
const uak = await getUserAccessKey(profileName);
|
|
12363
|
+
const environment = await getProfileEnvironment(profileName);
|
|
12364
|
+
const accessToken = await getAccessToken(profileName, uak.id, uak.secret, false, environment);
|
|
12365
|
+
return { client: new SkmClient(accessToken, environment, appKey, opts.macAddress), profileName };
|
|
12366
|
+
}
|
|
12367
|
+
function maskAuthDetail(detail) {
|
|
12368
|
+
if (typeof detail.password !== "string") return detail;
|
|
12369
|
+
return { ...detail, password: "***" };
|
|
12370
|
+
}
|
|
12371
|
+
function formatCell(value) {
|
|
12372
|
+
if (value === null || value === void 0) return "-";
|
|
12373
|
+
return sanitizeForTerminal(String(value));
|
|
12374
|
+
}
|
|
12375
|
+
function printSkmValue(opts, value, raw) {
|
|
12376
|
+
if (opts.json) {
|
|
12377
|
+
printJson(raw);
|
|
12378
|
+
} else if (opts.quiet) {
|
|
12379
|
+
process.stdout.write(value + "\n");
|
|
12380
|
+
} else {
|
|
12381
|
+
process.stdout.write(sanitizeMultilineForTerminal(value) + "\n");
|
|
12382
|
+
}
|
|
12383
|
+
}
|
|
12384
|
+
async function resolveKeyStoreName(client, keyStoreId) {
|
|
12385
|
+
const keyStore = await client.getKeyStore(keyStoreId);
|
|
12386
|
+
return keyStore.name;
|
|
12387
|
+
}
|
|
12388
|
+
function outputSkmWriteResult(opts, result, ids) {
|
|
12389
|
+
output(opts, {
|
|
12390
|
+
headers: ["field", "value"],
|
|
12391
|
+
rows: Object.entries(result).map(([key, value]) => [key, formatCell(value)]),
|
|
12392
|
+
raw: result,
|
|
12393
|
+
ids
|
|
12394
|
+
});
|
|
12395
|
+
}
|
|
12396
|
+
function parseKeyVersionOption(value) {
|
|
12397
|
+
return parseNonNegativeIntegerOption(value, "--key-version");
|
|
12398
|
+
}
|
|
12399
|
+
async function withSkmSpinner(text, call) {
|
|
12400
|
+
startSpinner(text);
|
|
12401
|
+
let result;
|
|
12402
|
+
try {
|
|
12403
|
+
result = await call();
|
|
12404
|
+
} catch (err) {
|
|
12405
|
+
stopSpinner(false);
|
|
12406
|
+
throw err;
|
|
12407
|
+
}
|
|
12408
|
+
stopSpinner(true);
|
|
12409
|
+
return result;
|
|
12410
|
+
}
|
|
12411
|
+
|
|
12412
|
+
// src/commands/skm/confirm.ts
|
|
12413
|
+
var confirmCommand = withSkmOptions(
|
|
12414
|
+
new import_commander59.Command("confirm").description("SKM \uC11C\uBC84\uAC00 \uBCF8 \uD074\uB77C\uC774\uC5B8\uD2B8 IP, MAC \uD5E4\uB354\uC640 \uC778\uC99D\uC11C \uC0AC\uC6A9 \uC5EC\uBD80\uB97C \uC870\uD68C\uD55C\uB2E4")
|
|
12415
|
+
).action(async (_opts, command) => {
|
|
12416
|
+
const opts = command.optsWithGlobals();
|
|
12417
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12418
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12419
|
+
const info = await withSkmSpinner("SKM \uD074\uB77C\uC774\uC5B8\uD2B8 \uC815\uBCF4 \uC870\uD68C \uC911...", () => client.confirm());
|
|
12420
|
+
output(opts, {
|
|
12421
|
+
headers: ["field", "value"],
|
|
12422
|
+
rows: [
|
|
12423
|
+
["clientIp", formatCell(info.clientIp)],
|
|
12424
|
+
["clientMacHeader", formatCell(info.clientMacHeader)],
|
|
12425
|
+
["clientSentCertificate", formatCell(info.clientSentCertificate)]
|
|
12426
|
+
],
|
|
12427
|
+
raw: info,
|
|
12428
|
+
ids: [formatCell(info.clientIp)]
|
|
12429
|
+
});
|
|
12430
|
+
});
|
|
12431
|
+
|
|
12432
|
+
// src/commands/skm/keystore.ts
|
|
12433
|
+
var import_commander61 = require("commander");
|
|
12434
|
+
|
|
12435
|
+
// src/commands/skm/keystore-manage.ts
|
|
12436
|
+
var import_commander60 = require("commander");
|
|
12437
|
+
|
|
12438
|
+
// src/commands/skm/input.ts
|
|
12439
|
+
var import_node_fs10 = require("fs");
|
|
12440
|
+
var processStdin = {
|
|
12441
|
+
get isTTY() {
|
|
12442
|
+
return process.stdin.isTTY;
|
|
12443
|
+
},
|
|
12444
|
+
read: () => (0, import_node_fs10.readFileSync)(0)
|
|
12445
|
+
};
|
|
12446
|
+
function assertWithinLimit(size, spec) {
|
|
12447
|
+
if (size > spec.maxBytes) {
|
|
12448
|
+
throw new NhnCloudCliError(
|
|
12449
|
+
`${spec.label}\uAC00 \uB108\uBB34 \uD07D\uB2C8\uB2E4: ${size}\uBC14\uC774\uD2B8 (\uD55C\uB3C4 ${spec.maxBytes}\uBC14\uC774\uD2B8).`,
|
|
12450
|
+
EXIT_PARAM_ERROR
|
|
12451
|
+
);
|
|
12452
|
+
}
|
|
12453
|
+
}
|
|
12454
|
+
function readInputFile(file, spec) {
|
|
12455
|
+
let stat4;
|
|
12456
|
+
try {
|
|
12457
|
+
stat4 = (0, import_node_fs10.statSync)(file);
|
|
12458
|
+
} catch (e) {
|
|
12459
|
+
const reason = e.code ?? (e instanceof Error ? e.message : String(e));
|
|
12460
|
+
throw new NhnCloudCliError(`${spec.label} \uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${file} (${reason})`, EXIT_PARAM_ERROR);
|
|
12461
|
+
}
|
|
12462
|
+
if (!stat4.isFile()) {
|
|
12463
|
+
throw new NhnCloudCliError(`${spec.label} \uD30C\uC77C\uC774 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4: ${file}`, EXIT_PARAM_ERROR);
|
|
12464
|
+
}
|
|
12465
|
+
assertWithinLimit(stat4.size, spec);
|
|
12466
|
+
return (0, import_node_fs10.readFileSync)(file);
|
|
12467
|
+
}
|
|
12468
|
+
function readStdin(stdin, spec) {
|
|
12469
|
+
try {
|
|
12470
|
+
return stdin.read();
|
|
12471
|
+
} catch (e) {
|
|
12472
|
+
const reason = e.code ?? (e instanceof Error ? e.message : String(e));
|
|
12473
|
+
throw new NhnCloudCliError(`${spec.label}\uB97C \uD45C\uC900 \uC785\uB825\uC5D0\uC11C \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (${reason}).`, EXIT_PARAM_ERROR);
|
|
12474
|
+
}
|
|
12475
|
+
}
|
|
12476
|
+
function readSkmInput(source, spec, stdin = processStdin) {
|
|
12477
|
+
const fileFlag = spec.fileFlag ?? "--file";
|
|
12478
|
+
if (source.text !== void 0 && source.file !== void 0) {
|
|
12479
|
+
throw new NhnCloudCliError(`${spec.textFlag}\uC640 ${fileFlag}\uC740 \uD568\uAED8 \uC9C0\uC815\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`, EXIT_PARAM_ERROR);
|
|
12480
|
+
}
|
|
12481
|
+
let input;
|
|
12482
|
+
if (source.text !== void 0) {
|
|
12483
|
+
input = Buffer.from(source.text, "utf-8");
|
|
12484
|
+
} else if (source.file !== void 0) {
|
|
12485
|
+
input = readInputFile(source.file, spec);
|
|
12486
|
+
} else if (!stdin.isTTY) {
|
|
12487
|
+
input = readStdin(stdin, spec);
|
|
12488
|
+
} else {
|
|
12489
|
+
throw new NhnCloudCliError(
|
|
12490
|
+
`${spec.label}\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. ${spec.textFlag} <\uAC12>, ${fileFlag} <\uACBD\uB85C>, \uD45C\uC900 \uC785\uB825(\uD30C\uC774\uD504) \uC911 \uD558\uB098\uB85C \uC804\uB2EC\uD558\uC138\uC694.`,
|
|
12491
|
+
EXIT_PARAM_ERROR
|
|
12492
|
+
);
|
|
12493
|
+
}
|
|
12494
|
+
assertWithinLimit(input.length, spec);
|
|
12495
|
+
if (input.length === 0) {
|
|
12496
|
+
throw new NhnCloudCliError(`${spec.label}\uAC00 \uBE44\uC5B4 \uC788\uC2B5\uB2C8\uB2E4.`, EXIT_PARAM_ERROR);
|
|
12497
|
+
}
|
|
12498
|
+
return input;
|
|
12499
|
+
}
|
|
12500
|
+
function decodeUtf8Input(input, label, hint) {
|
|
12501
|
+
try {
|
|
12502
|
+
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(input);
|
|
12503
|
+
} catch {
|
|
12504
|
+
throw new NhnCloudCliError(`${label}\uB294 UTF-8 \uD14D\uC2A4\uD2B8\uC5EC\uC57C \uD569\uB2C8\uB2E4. ${hint}`, EXIT_PARAM_ERROR);
|
|
12505
|
+
}
|
|
12506
|
+
}
|
|
12507
|
+
|
|
12508
|
+
// src/commands/skm/keystore-manage.ts
|
|
12509
|
+
var DESCRIPTION_MAX_LENGTH = 1e3;
|
|
12510
|
+
var PASSWORD_MAX_BYTES = 1024;
|
|
12511
|
+
var LOCKOUT_WARNING = "(\uC2E4\uD589 \uC704\uCE58\uAC00 \uD0A4\uB97C \uC4F0\uC9C0 \uBABB\uD558\uAC8C \uB420 \uC218 \uC788\uC74C, \uBA3C\uC800 skm confirm\uC73C\uB85C \uD655\uC778)";
|
|
12512
|
+
var createCommand11 = withSkmOptions(
|
|
12513
|
+
new import_commander60.Command("create").description("\uD0A4 \uC800\uC7A5\uC18C\uB97C \uB9CC\uB4E0\uB2E4").requiredOption("--name <name>", "\uD0A4 \uC800\uC7A5\uC18C \uC774\uB984 (100\uC790 \uC774\uD558)").requiredOption("--auth <list>", "\uC0AC\uC6A9\uD560 \uC778\uC99D (ipv4,mac,certificate \uC911 \uD558\uB098 \uC774\uC0C1\uC744 \uC27C\uD45C\uB85C)").option("--auth-mode <mode>", "\uC778\uC99D \uACB0\uD569 \uBC29\uC2DD (and|or)", "and").option("--description <text>", "\uD0A4 \uC800\uC7A5\uC18C \uC124\uBA85 (1000\uC790 \uC774\uD558)")
|
|
12514
|
+
).action(async (_opts, command) => {
|
|
12515
|
+
const opts = command.optsWithGlobals();
|
|
12516
|
+
const name = parseKeyNameOption(opts.name);
|
|
12517
|
+
const auths = parseAuthListOption(opts.auth);
|
|
12518
|
+
const authMode = parseAuthModeOption(opts.authMode);
|
|
12519
|
+
const description = parseDescriptionOption(opts.description, DESCRIPTION_MAX_LENGTH);
|
|
12520
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12521
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12522
|
+
const input = { name, ...auths, authMode };
|
|
12523
|
+
if (description !== void 0) input.description = description;
|
|
12524
|
+
const created = await withSkmSpinner(
|
|
12525
|
+
`SKM \uD0A4 \uC800\uC7A5\uC18C ${formatCell(name)} \uC0DD\uC131 \uC911...`,
|
|
12526
|
+
() => client.createKeyStore(input)
|
|
12527
|
+
);
|
|
12528
|
+
outputSkmWriteResult(opts, { ...created }, [String(created.keyStoreId)]);
|
|
12529
|
+
});
|
|
12530
|
+
var updateCommand4 = withSkmOptions(
|
|
12531
|
+
new import_commander60.Command("update").description(`\uD0A4 \uC800\uC7A5\uC18C\uB97C \uC218\uC815\uD55C\uB2E4. \uC8FC\uC9C0 \uC54A\uC740 \uD56D\uBAA9\uC740 \uD604\uC7AC \uAC12\uC744 \uC720\uC9C0\uD55C\uB2E4 ${LOCKOUT_WARNING}`).argument("<keystore-id>", "\uD0A4 \uC800\uC7A5\uC18C ID").requiredOption("--auth-mode <mode>", "\uC778\uC99D \uACB0\uD569 \uBC29\uC2DD (and|or). \uC870\uD68C \uC751\uB2F5\uC5D0 \uC5C6\uC5B4 \uB9E4\uBC88 \uC9C0\uC815\uD55C\uB2E4").option("--name <name>", "\uD0A4 \uC800\uC7A5\uC18C \uC774\uB984 (100\uC790 \uC774\uD558)").option("--description <text>", "\uD0A4 \uC800\uC7A5\uC18C \uC124\uBA85 (1000\uC790 \uC774\uD558)").option("--auth <list>", "\uC0AC\uC6A9\uD560 \uC778\uC99D (ipv4,mac,certificate \uC911 \uD558\uB098 \uC774\uC0C1\uC744 \uC27C\uD45C\uB85C)")
|
|
12532
|
+
).action(async (keyStoreId, _opts, command) => {
|
|
12533
|
+
const opts = command.optsWithGlobals();
|
|
12534
|
+
const parsedId = parseKeyStoreId(keyStoreId);
|
|
12535
|
+
const authMode = parseAuthModeOption(opts.authMode);
|
|
12536
|
+
const name = parseKeyNameOption(opts.name);
|
|
12537
|
+
const description = parseDescriptionOption(opts.description, DESCRIPTION_MAX_LENGTH);
|
|
12538
|
+
const auths = opts.auth === void 0 ? void 0 : parseAuthListOption(opts.auth);
|
|
12539
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12540
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12541
|
+
const current2 = await withSkmSpinner(`SKM \uD0A4 \uC800\uC7A5\uC18C ${parsedId} \uC870\uD68C \uC911...`, () => client.getKeyStore(parsedId));
|
|
12542
|
+
const currentDescription = typeof current2.description === "string" ? current2.description : void 0;
|
|
12543
|
+
const yesNo = (value) => value === "Y" ? "Y" : "N";
|
|
12544
|
+
const input = {
|
|
12545
|
+
name: name ?? current2.name,
|
|
12546
|
+
...auths ?? {
|
|
12547
|
+
ip4AuthUse: yesNo(current2.ip4AuthUse),
|
|
12548
|
+
macAuthUse: yesNo(current2.macAuthUse),
|
|
12549
|
+
certificateAuthUse: yesNo(current2.certificateAuthUse)
|
|
12550
|
+
},
|
|
12551
|
+
authMode
|
|
12552
|
+
};
|
|
12553
|
+
const nextDescription = description ?? currentDescription;
|
|
12554
|
+
if (nextDescription !== void 0) input.description = nextDescription;
|
|
12555
|
+
if (input.ip4AuthUse === "N" && input.macAuthUse === "N" && input.certificateAuthUse === "N") {
|
|
12556
|
+
throw new NhnCloudCliError("\uD0A4 \uC800\uC7A5\uC18C \uC778\uC99D\uC740 \uD558\uB098 \uC774\uC0C1 \uCF1C\uC57C \uD569\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
12557
|
+
}
|
|
12558
|
+
await withSkmSpinner(`SKM \uD0A4 \uC800\uC7A5\uC18C ${parsedId} \uC218\uC815 \uC911...`, () => client.updateKeyStore(parsedId, input));
|
|
12559
|
+
outputSkmWriteResult(
|
|
12560
|
+
opts,
|
|
12561
|
+
{ operation: "keystore-update", status: "succeeded", keyStoreId: parsedId, ...input },
|
|
12562
|
+
[String(parsedId)]
|
|
12563
|
+
);
|
|
12564
|
+
});
|
|
12565
|
+
var deleteCommand9 = withSkmOptions(
|
|
12566
|
+
new import_commander60.Command("delete").description("\uD0A4 \uC800\uC7A5\uC18C\uB97C \uC0AD\uC81C(\uBE44\uD65C\uC131\uD654)\uD55C\uB2E4").argument("<keystore-id>", "\uD0A4 \uC800\uC7A5\uC18C ID").option("--yes", "\uC0AD\uC81C \uD655\uC778")
|
|
12567
|
+
).action(async (keyStoreId, _opts, command) => {
|
|
12568
|
+
const opts = command.optsWithGlobals();
|
|
12569
|
+
requireYes(opts.yes, "\uD0A4 \uC800\uC7A5\uC18C \uC0AD\uC81C");
|
|
12570
|
+
const parsedId = parseKeyStoreId(keyStoreId);
|
|
12571
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12572
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12573
|
+
await withSkmSpinner(`SKM \uD0A4 \uC800\uC7A5\uC18C ${parsedId} \uC0AD\uC81C \uC911...`, () => client.deleteKeyStore(parsedId));
|
|
12574
|
+
outputSkmWriteResult(
|
|
12575
|
+
opts,
|
|
12576
|
+
{ operation: "keystore-delete", status: "succeeded", keyStoreId: parsedId },
|
|
12577
|
+
[String(parsedId)]
|
|
12578
|
+
);
|
|
12579
|
+
});
|
|
12580
|
+
function readCertificateOptions(opts) {
|
|
12581
|
+
if (opts.lifeTime === void 0) {
|
|
12582
|
+
throw new NhnCloudCliError("\uC778\uC99D\uC11C \uCD94\uAC00\uC5D0\uB294 --life-time\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
12583
|
+
}
|
|
12584
|
+
const lifeTime = parsePositiveIntegerOption(opts.lifeTime, "--life-time");
|
|
12585
|
+
const input = readSkmInput(
|
|
12586
|
+
{ text: opts.password, file: opts.passwordFile },
|
|
12587
|
+
{ textFlag: "--password", fileFlag: "--password-file", label: "\uC778\uC99D\uC11C \uBE44\uBC00\uBC88\uD638", maxBytes: PASSWORD_MAX_BYTES }
|
|
12588
|
+
);
|
|
12589
|
+
const password = decodeUtf8Input(input, "\uC778\uC99D\uC11C \uBE44\uBC00\uBC88\uD638", "\uD30C\uC77C \uC778\uCF54\uB529\uC744 \uD655\uC778\uD558\uC138\uC694.").replace(/\r?\n$/, "");
|
|
12590
|
+
if (!password) {
|
|
12591
|
+
throw new NhnCloudCliError("\uC778\uC99D\uC11C \uBE44\uBC00\uBC88\uD638\uAC00 \uBE44\uC5B4 \uC788\uC2B5\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
12592
|
+
}
|
|
12593
|
+
return { lifeTime, password };
|
|
12594
|
+
}
|
|
12595
|
+
function rejectCertificateOptions(opts) {
|
|
12596
|
+
if (opts.lifeTime !== void 0 || opts.password !== void 0 || opts.passwordFile !== void 0) {
|
|
12597
|
+
throw new NhnCloudCliError("--life-time\uACFC --password\uB294 --type certificate\uC5D0\uC11C\uB9CC \uC501\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
12598
|
+
}
|
|
12599
|
+
}
|
|
12600
|
+
function authAddedFields(added) {
|
|
12601
|
+
return { value: added.value, name: added.name, description: added.description };
|
|
12602
|
+
}
|
|
12603
|
+
var authAddCommand = withTypeOption(
|
|
12604
|
+
withSkmOptions(
|
|
12605
|
+
new import_commander60.Command("add").description("\uD0A4 \uC800\uC7A5\uC18C\uC5D0 \uC778\uC99D \uC815\uBCF4\uB97C \uCD94\uAC00\uD55C\uB2E4 (\uC778\uC99D\uC11C \uBE44\uBC00\uBC88\uD638\uB294 --password, --password-file, \uD45C\uC900 \uC785\uB825 \uC911 \uD558\uB098)").argument("<keystore-id>", "\uD0A4 \uC800\uC7A5\uC18C ID").argument("<value>", "IPv4\xB7MAC \uAC12 \uB610\uB294 \uC778\uC99D\uC11C \uC774\uB984").option("--description <text>", "\uC778\uC99D \uC815\uBCF4 \uC124\uBA85 (1000\uC790 \uC774\uD558)").option("--life-time <days>", "\uC778\uC99D\uC11C \uC720\uD6A8 \uAE30\uAC04(\uC77C) (--type certificate \uC804\uC6A9, \uD544\uC218)").option("--password <pw>", "\uC778\uC99D\uC11C \uBE44\uBC00\uBC88\uD638 (--type certificate \uC804\uC6A9)").option("--password-file <path>", "\uC778\uC99D\uC11C \uBE44\uBC00\uBC88\uD638\uB97C \uC77D\uC744 \uD30C\uC77C (--type certificate \uC804\uC6A9)")
|
|
12606
|
+
)
|
|
12607
|
+
).action(async (keyStoreId, value, _opts, command) => {
|
|
12608
|
+
const opts = command.optsWithGlobals();
|
|
12609
|
+
const parsedId = parseKeyStoreId(keyStoreId);
|
|
12610
|
+
const type = parseAuthTypeOption(opts.type);
|
|
12611
|
+
const parsedValue = parseAuthValue(type, value);
|
|
12612
|
+
const description = parseDescriptionOption(opts.description, DESCRIPTION_MAX_LENGTH);
|
|
12613
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12614
|
+
if (type !== "certificate") rejectCertificateOptions(opts);
|
|
12615
|
+
const target = type === "certificate" ? { type, ...readCertificateOptions(opts) } : { type };
|
|
12616
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12617
|
+
const added = await withSkmSpinner(`SKM ${type} \uC778\uC99D \uC815\uBCF4 ${formatCell(parsedValue)} \uCD94\uAC00 \uC911...`, async () => {
|
|
12618
|
+
const keyStoreName = await resolveKeyStoreName(client, parsedId);
|
|
12619
|
+
if (target.type === "certificate") {
|
|
12620
|
+
return client.addCertificate(keyStoreName, parsedValue, target.password, target.lifeTime, description);
|
|
12621
|
+
}
|
|
12622
|
+
return client.addAuth(target.type, keyStoreName, parsedValue, description);
|
|
12623
|
+
});
|
|
12624
|
+
outputSkmWriteResult(
|
|
12625
|
+
opts,
|
|
12626
|
+
{ operation: "auth-add", type, keyStoreId: parsedId, ...authAddedFields(added) },
|
|
12627
|
+
[formatCell(parsedValue)]
|
|
12628
|
+
);
|
|
12629
|
+
});
|
|
12630
|
+
var authDeleteCommand = withTypeOption(
|
|
12631
|
+
withSkmOptions(
|
|
12632
|
+
new import_commander60.Command("delete").description(`\uC778\uC99D \uC815\uBCF4 \uC0AD\uC81C\uB97C \uC608\uC57D\uD55C\uB2E4 (7\uC77C \uB4A4 \uC0AD\uC81C) ${LOCKOUT_WARNING}`).argument("<keystore-id>", "\uD0A4 \uC800\uC7A5\uC18C ID").argument("<value>", "IPv4\xB7MAC \uAC12 \uB610\uB294 \uC778\uC99D\uC11C \uC774\uB984").option("--yes", "\uC0AD\uC81C \uC608\uC57D \uD655\uC778")
|
|
12633
|
+
)
|
|
12634
|
+
).action(async (keyStoreId, value, _opts, command) => {
|
|
12635
|
+
const opts = command.optsWithGlobals();
|
|
12636
|
+
requireYes(opts.yes, "\uC778\uC99D \uC815\uBCF4 \uC0AD\uC81C \uC608\uC57D");
|
|
12637
|
+
const parsedId = parseKeyStoreId(keyStoreId);
|
|
12638
|
+
const type = parseAuthTypeOption(opts.type);
|
|
12639
|
+
const parsedValue = parseAuthValue(type, value);
|
|
12640
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12641
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12642
|
+
const deletion = await withSkmSpinner(`SKM ${type} \uC778\uC99D \uC815\uBCF4 ${formatCell(parsedValue)} \uC0AD\uC81C \uC608\uC57D \uC911...`, async () => {
|
|
12643
|
+
const keyStoreName = await resolveKeyStoreName(client, parsedId);
|
|
12644
|
+
return client.scheduleAuthDeletion(type, keyStoreName, parsedValue);
|
|
12645
|
+
});
|
|
12646
|
+
outputSkmWriteResult(
|
|
12647
|
+
opts,
|
|
12648
|
+
{
|
|
12649
|
+
operation: "auth-delete-scheduled",
|
|
12650
|
+
type,
|
|
12651
|
+
keyStoreId: parsedId,
|
|
12652
|
+
value: deletion.value,
|
|
12653
|
+
name: deletion.name,
|
|
12654
|
+
deletionDateTime: deletion.deletionDateTime
|
|
12655
|
+
},
|
|
12656
|
+
[formatCell(parsedValue)]
|
|
12657
|
+
);
|
|
12658
|
+
});
|
|
12659
|
+
var authPurgeCommand = withTypeOption(
|
|
12660
|
+
withSkmOptions(
|
|
12661
|
+
new import_commander60.Command("purge").description(`\uC778\uC99D \uC815\uBCF4\uB97C \uC989\uC2DC \uC0AD\uC81C\uD55C\uB2E4 (\uC0AD\uC81C \uC608\uC57D\uB41C \uAC83\uB9CC, \uB418\uB3CC\uB9B4 \uC218 \uC5C6\uC74C) ${LOCKOUT_WARNING}`).argument("<keystore-id>", "\uD0A4 \uC800\uC7A5\uC18C ID").argument("<value>", "IPv4\xB7MAC \uAC12 \uB610\uB294 \uC778\uC99D\uC11C \uC774\uB984").option("--yes", "\uC989\uC2DC \uC0AD\uC81C \uD655\uC778")
|
|
12662
|
+
)
|
|
12663
|
+
).action(async (keyStoreId, value, _opts, command) => {
|
|
12664
|
+
const opts = command.optsWithGlobals();
|
|
12665
|
+
requireYes(opts.yes, "\uC778\uC99D \uC815\uBCF4 \uC989\uC2DC \uC0AD\uC81C");
|
|
12666
|
+
const parsedId = parseKeyStoreId(keyStoreId);
|
|
12667
|
+
const type = parseAuthTypeOption(opts.type);
|
|
12668
|
+
const parsedValue = parseAuthValue(type, value);
|
|
12669
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12670
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12671
|
+
const deletion = await withSkmSpinner(`SKM ${type} \uC778\uC99D \uC815\uBCF4 ${formatCell(parsedValue)} \uC989\uC2DC \uC0AD\uC81C \uC911...`, async () => {
|
|
12672
|
+
const keyStoreName = await resolveKeyStoreName(client, parsedId);
|
|
12673
|
+
return client.deleteAuthNow(type, keyStoreName, parsedValue);
|
|
12674
|
+
});
|
|
12675
|
+
outputSkmWriteResult(
|
|
12676
|
+
opts,
|
|
12677
|
+
{
|
|
12678
|
+
operation: "auth-purge",
|
|
12679
|
+
type,
|
|
12680
|
+
keyStoreId: parsedId,
|
|
12681
|
+
value: deletion.value,
|
|
12682
|
+
name: deletion.name,
|
|
12683
|
+
deletionDateTime: deletion.deletionDateTime
|
|
12684
|
+
},
|
|
12685
|
+
[formatCell(parsedValue)]
|
|
12686
|
+
);
|
|
12687
|
+
});
|
|
12688
|
+
|
|
12689
|
+
// src/commands/skm/keystore.ts
|
|
12690
|
+
var KEYSTORE_FIELDS = [
|
|
12691
|
+
"keyStoreId",
|
|
12692
|
+
"name",
|
|
12693
|
+
"description",
|
|
12694
|
+
"ip4AuthUse",
|
|
12695
|
+
"macAuthUse",
|
|
12696
|
+
"certificateAuthUse",
|
|
12697
|
+
"creationUser",
|
|
12698
|
+
"creationDatetime",
|
|
12699
|
+
"lastChangeUser",
|
|
12700
|
+
"lastChangeDatetime"
|
|
12701
|
+
];
|
|
12702
|
+
var listCommand16 = withSkmOptions(new import_commander61.Command("list").description("\uD0A4 \uC800\uC7A5\uC18C \uBAA9\uB85D\uC744 \uC870\uD68C\uD55C\uB2E4 (\uC804\uCCB4 \uD544\uB4DC\uB294 --json)")).action(async (_opts, command) => {
|
|
12703
|
+
const opts = command.optsWithGlobals();
|
|
12704
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12705
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12706
|
+
const stores = await withSkmSpinner("SKM \uD0A4 \uC800\uC7A5\uC18C \uBAA9\uB85D \uC870\uD68C \uC911...", () => client.listKeyStores());
|
|
12707
|
+
output(opts, {
|
|
12708
|
+
headers: ["keyStoreId", "name", "ip4AuthUse", "macAuthUse", "certificateAuthUse", "lastChangeDatetime"],
|
|
12709
|
+
rows: stores.map((s) => [
|
|
12710
|
+
formatCell(s.keyStoreId),
|
|
12711
|
+
formatCell(s.name),
|
|
12712
|
+
formatCell(s.ip4AuthUse),
|
|
12713
|
+
formatCell(s.macAuthUse),
|
|
12714
|
+
formatCell(s.certificateAuthUse),
|
|
12715
|
+
formatCell(s.lastChangeDatetime)
|
|
12716
|
+
]),
|
|
12717
|
+
raw: stores,
|
|
12718
|
+
ids: stores.map((s) => String(s.keyStoreId))
|
|
12719
|
+
});
|
|
12720
|
+
});
|
|
12721
|
+
var getCommand11 = withSkmOptions(
|
|
12722
|
+
new import_commander61.Command("get").description("\uD0A4 \uC800\uC7A5\uC18C \uD55C \uAC74\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<keystore-id>", "\uD0A4 \uC800\uC7A5\uC18C ID")
|
|
12723
|
+
).action(async (keyStoreId, _opts, command) => {
|
|
12724
|
+
const opts = command.optsWithGlobals();
|
|
12725
|
+
const parsedId = parseKeyStoreId(keyStoreId);
|
|
12726
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12727
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12728
|
+
const store = await withSkmSpinner(`SKM \uD0A4 \uC800\uC7A5\uC18C ${parsedId} \uC870\uD68C \uC911...`, () => client.getKeyStore(parsedId));
|
|
12729
|
+
output(opts, {
|
|
12730
|
+
headers: ["field", "value"],
|
|
12731
|
+
rows: KEYSTORE_FIELDS.map((field) => [field, formatCell(store[field])]),
|
|
12732
|
+
raw: store,
|
|
12733
|
+
ids: [String(store.keyStoreId)]
|
|
12734
|
+
});
|
|
12735
|
+
});
|
|
12736
|
+
var authListCommand = withTypeOption(
|
|
12737
|
+
withSkmOptions(
|
|
12738
|
+
new import_commander61.Command("list").description("\uD0A4 \uC800\uC7A5\uC18C \uC778\uC99D \uC815\uBCF4 \uAC12 \uBAA9\uB85D\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<keystore-id>", "\uD0A4 \uC800\uC7A5\uC18C ID")
|
|
12739
|
+
)
|
|
12740
|
+
).action(async (keyStoreId, _opts, command) => {
|
|
12741
|
+
const opts = command.optsWithGlobals();
|
|
12742
|
+
const parsedId = parseKeyStoreId(keyStoreId);
|
|
12743
|
+
const type = parseAuthTypeOption(opts.type);
|
|
12744
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12745
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12746
|
+
const values = await withSkmSpinner(`SKM ${type} \uC778\uC99D \uC815\uBCF4 \uBAA9\uB85D \uC870\uD68C \uC911...`, () => client.listAuths(parsedId, type));
|
|
12747
|
+
output(opts, {
|
|
12748
|
+
headers: ["value"],
|
|
12749
|
+
rows: values.map((v) => [formatCell(v)]),
|
|
12750
|
+
raw: values,
|
|
12751
|
+
ids: values.map((v) => formatCell(v))
|
|
12752
|
+
});
|
|
12753
|
+
});
|
|
12754
|
+
var authGetCommand = withTypeOption(
|
|
12755
|
+
withSkmOptions(
|
|
12756
|
+
new import_commander61.Command("get").description("\uD0A4 \uC800\uC7A5\uC18C \uC778\uC99D \uC815\uBCF4 \uC0C1\uC138\uB97C \uC870\uD68C\uD55C\uB2E4 (\uC778\uC99D\uC11C \uBE44\uBC00\uBC88\uD638\uB294 \uAC00\uB9B0\uB2E4)").argument("<keystore-id>", "\uD0A4 \uC800\uC7A5\uC18C ID").argument("<value>", "IPv4\xB7MAC \uAC12 \uB610\uB294 \uC778\uC99D\uC11C \uC774\uB984")
|
|
12757
|
+
)
|
|
12758
|
+
).action(async (keyStoreId, value, _opts, command) => {
|
|
12759
|
+
const opts = command.optsWithGlobals();
|
|
12760
|
+
const parsedId = parseKeyStoreId(keyStoreId);
|
|
12761
|
+
const parsedValue = parseRequiredArgument(value, "value");
|
|
12762
|
+
const type = parseAuthTypeOption(opts.type);
|
|
12763
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12764
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12765
|
+
const details = await withSkmSpinner(
|
|
12766
|
+
`SKM ${type} \uC778\uC99D \uC815\uBCF4 \uC870\uD68C \uC911...`,
|
|
12767
|
+
() => client.getAuth(parsedId, type, parsedValue)
|
|
12768
|
+
);
|
|
12769
|
+
const masked = details.map(maskAuthDetail);
|
|
12770
|
+
const keys = masked.map((d) => formatCell(d.value ?? d.name));
|
|
12771
|
+
output(opts, {
|
|
12772
|
+
headers: ["value", "description", "expirationDate", "lastAccessDatetime", "deletionDatetime", "lastChangeDatetime"],
|
|
12773
|
+
rows: masked.map((d, i) => [
|
|
12774
|
+
keys[i] ?? "-",
|
|
12775
|
+
formatCell(d.description),
|
|
12776
|
+
formatCell(d.expirationDate),
|
|
12777
|
+
formatCell(d.lastAccessDatetime),
|
|
12778
|
+
formatCell(d.deletionDatetime),
|
|
12779
|
+
formatCell(d.lastChangeDatetime)
|
|
12780
|
+
]),
|
|
12781
|
+
raw: masked,
|
|
12782
|
+
ids: keys
|
|
12783
|
+
});
|
|
12784
|
+
});
|
|
12785
|
+
var authCommand = new import_commander61.Command("auth").description("\uD0A4 \uC800\uC7A5\uC18C IPv4\xB7MAC\xB7\uC778\uC99D\uC11C \uC778\uC99D \uC815\uBCF4 \uC870\uD68C\xB7\uAD00\uB9AC").addCommand(authListCommand).addCommand(authGetCommand).addCommand(authAddCommand).addCommand(authDeleteCommand).addCommand(authPurgeCommand);
|
|
12786
|
+
var keystoreCommand = new import_commander61.Command("keystore").description("SKM \uD0A4 \uC800\uC7A5\uC18C\uC640 \uC778\uC99D \uC815\uBCF4 \uC870\uD68C\xB7\uAD00\uB9AC").addCommand(listCommand16).addCommand(getCommand11).addCommand(createCommand11).addCommand(updateCommand4).addCommand(deleteCommand9).addCommand(authCommand);
|
|
12787
|
+
|
|
12788
|
+
// src/commands/skm/key.ts
|
|
12789
|
+
var import_commander63 = require("commander");
|
|
12790
|
+
|
|
12791
|
+
// src/commands/skm/key-manage.ts
|
|
12792
|
+
var import_commander62 = require("commander");
|
|
12793
|
+
var createCommand12 = withSkmOptions(
|
|
12794
|
+
new import_commander62.Command("create").description("\uD0A4 \uC800\uC7A5\uC18C\uC5D0 \uD0A4\uB97C \uB9CC\uB4E0\uB2E4 (\uAE30\uBC00 \uB370\uC774\uD130 \uAC12\uC740 --value, --file, \uD45C\uC900 \uC785\uB825 \uC911 \uD558\uB098)").argument("<keystore-id>", "\uD0A4 \uC800\uC7A5\uC18C ID").requiredOption("--type <type>", "\uD0A4 \uC885\uB958 (secret|symmetric-key|asymmetric-key)").requiredOption("--name <name>", "\uD0A4 \uC774\uB984 (100\uC790 \uC774\uD558)").option("--description <text>", "\uD0A4 \uC124\uBA85").option("--value <value>", "\uAE30\uBC00 \uB370\uC774\uD130 \uAC12 (--type secret \uC804\uC6A9)").option("--file <path>", "\uAE30\uBC00 \uB370\uC774\uD130 \uAC12\uC744 \uC77D\uC744 \uD30C\uC77C (--type secret \uC804\uC6A9)")
|
|
12795
|
+
).action(async (keyStoreId, _opts, command) => {
|
|
12796
|
+
const opts = command.optsWithGlobals();
|
|
12797
|
+
const parsedId = parseKeyStoreId(keyStoreId);
|
|
12798
|
+
const type = parseKeyTypeOption(opts.type);
|
|
12799
|
+
const name = parseKeyNameOption(opts.name);
|
|
12800
|
+
const description = opts.description?.trim() || void 0;
|
|
12801
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12802
|
+
let secretValue;
|
|
12803
|
+
if (type === "SECRET") {
|
|
12804
|
+
const input = readSkmInput(
|
|
12805
|
+
{ text: opts.value, file: opts.file },
|
|
12806
|
+
{ textFlag: "--value", label: "\uAE30\uBC00 \uB370\uC774\uD130", maxBytes: MAX_JSON_INPUT_BYTES }
|
|
12807
|
+
);
|
|
12808
|
+
secretValue = decodeUtf8Input(input, "\uAE30\uBC00 \uB370\uC774\uD130", "\uBC14\uC774\uB108\uB9AC\uB294 base64\uB85C \uC778\uCF54\uB529\uD574 \uC804\uB2EC\uD558\uC138\uC694.");
|
|
12809
|
+
} else if (opts.value !== void 0 || opts.file !== void 0) {
|
|
12810
|
+
throw new NhnCloudCliError("--value\uC640 --file\uC740 --type secret\uC5D0\uC11C\uB9CC \uC501\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
12811
|
+
}
|
|
12812
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12813
|
+
const created = await withSkmSpinner(`SKM \uD0A4 ${formatCell(name)} \uC0DD\uC131 \uC911...`, async () => {
|
|
12814
|
+
const keyStoreName = await resolveKeyStoreName(client, parsedId);
|
|
12815
|
+
if (secretValue !== void 0) {
|
|
12816
|
+
return client.createSecret(keyStoreName, name, description, secretValue);
|
|
12817
|
+
}
|
|
12818
|
+
if (type === "SYMMETRIC_KEY") {
|
|
12819
|
+
return client.createSymmetricKey(keyStoreName, name, description);
|
|
12820
|
+
}
|
|
12821
|
+
return client.createAsymmetricKey(keyStoreName, name, description);
|
|
12822
|
+
});
|
|
12823
|
+
outputSkmWriteResult(
|
|
12824
|
+
opts,
|
|
12825
|
+
{ keyId: created.keyId, keyStatus: created.keyStatus, keyStoreId: parsedId, name },
|
|
12826
|
+
[formatCell(created.keyId)]
|
|
12827
|
+
);
|
|
12828
|
+
});
|
|
12829
|
+
var deleteCommand10 = withSkmOptions(
|
|
12830
|
+
new import_commander62.Command("delete").description("\uD0A4 \uC0AD\uC81C\uB97C \uC608\uC57D\uD55C\uB2E4 (7\uC77C \uB4A4 \uC0AD\uC81C, \uADF8 \uC804\uC5D0\uB294 \uCF58\uC194\uC5D0\uC11C \uCDE8\uC18C \uAC00\uB2A5)").argument("<key-id>", "\uD0A4 ID").option("--yes", "\uC0AD\uC81C \uC608\uC57D \uD655\uC778")
|
|
12831
|
+
).action(async (keyId, _opts, command) => {
|
|
12832
|
+
const opts = command.optsWithGlobals();
|
|
12833
|
+
requireYes(opts.yes, "\uD0A4 \uC0AD\uC81C \uC608\uC57D");
|
|
12834
|
+
const parsedKeyId = parseRequiredArgument(keyId, "key-id");
|
|
12835
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12836
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12837
|
+
const deletion = await withSkmSpinner(
|
|
12838
|
+
`SKM \uD0A4 ${formatCell(parsedKeyId)} \uC0AD\uC81C \uC608\uC57D \uC911...`,
|
|
12839
|
+
() => client.scheduleKeyDeletion(parsedKeyId)
|
|
12840
|
+
);
|
|
12841
|
+
outputSkmWriteResult(
|
|
12842
|
+
opts,
|
|
12843
|
+
{
|
|
12844
|
+
operation: "key-delete-scheduled",
|
|
12845
|
+
status: "succeeded",
|
|
12846
|
+
keyId: deletion.keyId,
|
|
12847
|
+
deletionDateTime: deletion.deletionDateTime
|
|
12848
|
+
},
|
|
12849
|
+
[formatCell(deletion.keyId)]
|
|
12850
|
+
);
|
|
12851
|
+
});
|
|
12852
|
+
var purgeCommand = withSkmOptions(
|
|
12853
|
+
new import_commander62.Command("purge").description("\uD0A4\uB97C \uC989\uC2DC \uC0AD\uC81C\uD55C\uB2E4 (\uC0AD\uC81C \uC608\uC57D\uB41C \uD0A4\uB9CC, \uB418\uB3CC\uB9B4 \uC218 \uC5C6\uC74C)").argument("<key-id>", "\uD0A4 ID").option("--yes", "\uC989\uC2DC \uC0AD\uC81C \uD655\uC778")
|
|
12854
|
+
).action(async (keyId, _opts, command) => {
|
|
12855
|
+
const opts = command.optsWithGlobals();
|
|
12856
|
+
requireYes(opts.yes, "\uD0A4 \uC989\uC2DC \uC0AD\uC81C");
|
|
12857
|
+
const parsedKeyId = parseRequiredArgument(keyId, "key-id");
|
|
12858
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12859
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12860
|
+
const deletion = await withSkmSpinner(
|
|
12861
|
+
`SKM \uD0A4 ${formatCell(parsedKeyId)} \uC989\uC2DC \uC0AD\uC81C \uC911...`,
|
|
12862
|
+
() => client.deleteKeyNow(parsedKeyId)
|
|
12863
|
+
);
|
|
12864
|
+
outputSkmWriteResult(
|
|
12865
|
+
opts,
|
|
12866
|
+
{ operation: "key-purge", status: "succeeded", keyId: deletion.keyId, deletionDateTime: deletion.deletionDateTime },
|
|
12867
|
+
[formatCell(deletion.keyId)]
|
|
12868
|
+
);
|
|
12869
|
+
});
|
|
12870
|
+
|
|
12871
|
+
// src/commands/skm/key.ts
|
|
12872
|
+
var KEY_FIELDS = [
|
|
12873
|
+
"keyId",
|
|
12874
|
+
"name",
|
|
12875
|
+
"description",
|
|
12876
|
+
"keyType",
|
|
12877
|
+
"currentKeyValueVersion",
|
|
12878
|
+
"autoRotationPeriod",
|
|
12879
|
+
"nextAutoRotationDate",
|
|
12880
|
+
"lastAccessDatetime",
|
|
12881
|
+
"deletionDatetime",
|
|
12882
|
+
"creationUser",
|
|
12883
|
+
"creationDatetime",
|
|
12884
|
+
"lastChangeUser",
|
|
12885
|
+
"lastChangeDatetime"
|
|
12886
|
+
];
|
|
12887
|
+
var listCommand17 = withSkmOptions(
|
|
12888
|
+
new import_commander63.Command("list").description("\uD0A4 \uC800\uC7A5\uC18C\uC758 \uD0A4 \uBAA9\uB85D\uC744 \uC870\uD68C\uD55C\uB2E4 (\uC804\uCCB4 \uD544\uB4DC\uB294 --json)").argument("<keystore-id>", "\uD0A4 \uC800\uC7A5\uC18C ID").option("--type <type>", "\uD0A4 \uC885\uB958 (secret|symmetric-key|asymmetric-key)").option("--name <name>", "\uD0A4 \uC774\uB984 \uD544\uD130 (100\uC790 \uC774\uD558)").option("--status <status>", "\uD0A4 \uC0C1\uD0DC \uD544\uD130 (active|inactive)")
|
|
12889
|
+
).action(async (keyStoreId, _opts, command) => {
|
|
12890
|
+
const opts = command.optsWithGlobals();
|
|
12891
|
+
const parsedId = parseKeyStoreId(keyStoreId);
|
|
12892
|
+
const type = parseKeyTypeOption(opts.type);
|
|
12893
|
+
const name = parseKeyNameOption(opts.name);
|
|
12894
|
+
const status = parseKeyStatusOption(opts.status);
|
|
12895
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12896
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12897
|
+
const filter = {
|
|
12898
|
+
...type !== void 0 && { type },
|
|
12899
|
+
...name !== void 0 && { name },
|
|
12900
|
+
...status !== void 0 && { status }
|
|
12901
|
+
};
|
|
12902
|
+
const keys = await withSkmSpinner(
|
|
12903
|
+
`SKM \uD0A4 \uC800\uC7A5\uC18C ${parsedId} \uD0A4 \uBAA9\uB85D \uC870\uD68C \uC911...`,
|
|
12904
|
+
() => client.listKeys(parsedId, filter)
|
|
12905
|
+
);
|
|
12906
|
+
output(opts, {
|
|
12907
|
+
headers: ["keyId", "name", "keyType", "currentKeyValueVersion", "lastAccessDatetime", "deletionDatetime"],
|
|
12908
|
+
rows: keys.map((k) => [
|
|
12909
|
+
formatCell(k.keyId),
|
|
12910
|
+
formatCell(k.name),
|
|
12911
|
+
formatCell(k.keyType),
|
|
12912
|
+
formatCell(k.currentKeyValueVersion),
|
|
12913
|
+
formatCell(k.lastAccessDatetime),
|
|
12914
|
+
formatCell(k.deletionDatetime)
|
|
12915
|
+
]),
|
|
12916
|
+
raw: keys,
|
|
12917
|
+
ids: keys.map((k) => formatCell(k.keyId))
|
|
12918
|
+
});
|
|
12919
|
+
});
|
|
12920
|
+
var getCommand12 = withSkmOptions(
|
|
12921
|
+
new import_commander63.Command("get").description("\uD0A4 \uD55C \uAC74\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<keystore-id>", "\uD0A4 \uC800\uC7A5\uC18C ID").argument("<key-id>", "\uD0A4 ID")
|
|
12922
|
+
).action(async (keyStoreId, keyId, _opts, command) => {
|
|
12923
|
+
const opts = command.optsWithGlobals();
|
|
12924
|
+
const parsedId = parseKeyStoreId(keyStoreId);
|
|
12925
|
+
const parsedKeyId = parseRequiredArgument(keyId, "key-id");
|
|
12926
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12927
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12928
|
+
const key = await withSkmSpinner(
|
|
12929
|
+
`SKM \uD0A4 ${formatCell(parsedKeyId)} \uC870\uD68C \uC911...`,
|
|
12930
|
+
() => client.getKey(parsedId, parsedKeyId)
|
|
12931
|
+
);
|
|
12932
|
+
output(opts, {
|
|
12933
|
+
headers: ["field", "value"],
|
|
12934
|
+
rows: KEY_FIELDS.map((field) => [field, formatCell(key[field])]),
|
|
12935
|
+
raw: key,
|
|
12936
|
+
ids: [formatCell(key.keyId)]
|
|
12937
|
+
});
|
|
12938
|
+
});
|
|
12939
|
+
var keyCommand = new import_commander63.Command("key").description("SKM \uD0A4 \uC870\uD68C\uC640 \uAD00\uB9AC").addCommand(listCommand17).addCommand(getCommand12).addCommand(createCommand12).addCommand(deleteCommand10).addCommand(purgeCommand);
|
|
12940
|
+
|
|
12941
|
+
// src/commands/skm/secret.ts
|
|
12942
|
+
var import_commander64 = require("commander");
|
|
12943
|
+
var getCommand13 = withSkmOptions(
|
|
12944
|
+
new import_commander64.Command("get").description("\uAE30\uBC00 \uB370\uC774\uD130\uB97C \uC870\uD68C\uD55C\uB2E4 (\uC6D0\uBB38\uC744 stdout\uC5D0 \uCD9C\uB825)").argument("<key-id>", "\uD0A4 ID")
|
|
12945
|
+
).action(async (keyId, _opts, command) => {
|
|
12946
|
+
const opts = command.optsWithGlobals();
|
|
12947
|
+
const parsedKeyId = parseRequiredArgument(keyId, "key-id");
|
|
12948
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12949
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12950
|
+
const secret = await withSkmSpinner(
|
|
12951
|
+
`SKM \uAE30\uBC00 \uB370\uC774\uD130 ${formatCell(parsedKeyId)} \uC870\uD68C \uC911...`,
|
|
12952
|
+
() => client.getSecret(parsedKeyId)
|
|
12953
|
+
);
|
|
12954
|
+
printSkmValue(opts, secret, { secret });
|
|
12955
|
+
});
|
|
12956
|
+
var updateCommand5 = withSkmOptions(
|
|
12957
|
+
new import_commander64.Command("update").description("\uAE30\uBC00 \uB370\uC774\uD130 \uAC12\uC744 \uBC14\uAFBC\uB2E4 (\uAC12\uC740 --value, --file, \uD45C\uC900 \uC785\uB825 \uC911 \uD558\uB098)").argument("<key-id>", "\uD0A4 ID").option("--value <value>", "\uC0C8 \uAE30\uBC00 \uB370\uC774\uD130 \uAC12").option("--file <path>", "\uC0C8 \uAE30\uBC00 \uB370\uC774\uD130 \uAC12\uC744 \uC77D\uC744 \uD30C\uC77C")
|
|
12958
|
+
).action(async (keyId, _opts, command) => {
|
|
12959
|
+
const opts = command.optsWithGlobals();
|
|
12960
|
+
const parsedKeyId = parseRequiredArgument(keyId, "key-id");
|
|
12961
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12962
|
+
const input = readSkmInput(
|
|
12963
|
+
{ text: opts.value, file: opts.file },
|
|
12964
|
+
{ textFlag: "--value", label: "\uAE30\uBC00 \uB370\uC774\uD130", maxBytes: MAX_JSON_INPUT_BYTES }
|
|
12965
|
+
);
|
|
12966
|
+
const secretValue = decodeUtf8Input(input, "\uAE30\uBC00 \uB370\uC774\uD130", "\uBC14\uC774\uB108\uB9AC\uB294 base64\uB85C \uC778\uCF54\uB529\uD574 \uC804\uB2EC\uD558\uC138\uC694.");
|
|
12967
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12968
|
+
const updated = await withSkmSpinner(
|
|
12969
|
+
`SKM \uAE30\uBC00 \uB370\uC774\uD130 ${formatCell(parsedKeyId)} \uC218\uC815 \uC911...`,
|
|
12970
|
+
() => client.updateSecret(parsedKeyId, secretValue)
|
|
12971
|
+
);
|
|
12972
|
+
const { secretValue: _omitted, ...result } = updated;
|
|
12973
|
+
outputSkmWriteResult(opts, result, [formatCell(updated.keyId)]);
|
|
12974
|
+
});
|
|
12975
|
+
var secretCommand = new import_commander64.Command("secret").description("SKM \uAE30\uBC00 \uB370\uC774\uD130 \uC870\uD68C\uC640 \uC218\uC815").addCommand(getCommand13).addCommand(updateCommand5);
|
|
12976
|
+
|
|
12977
|
+
// src/commands/skm/symmetric-key.ts
|
|
12978
|
+
var import_commander65 = require("commander");
|
|
12979
|
+
var MAX_ENCRYPT_BYTES = 32768;
|
|
12980
|
+
var encryptCommand = withSkmOptions(
|
|
12981
|
+
new import_commander65.Command("encrypt").description("\uB300\uCE6D\uD0A4\uB85C \uB370\uC774\uD130\uB97C \uC554\uD638\uD654\uD55C\uB2E4 (--plaintext / --file / stdin, UTF-8 \uD14D\uC2A4\uD2B8 32KB \uC774\uD558)").argument("<key-id>", "\uD0A4 ID").option("--plaintext <text>", "\uC554\uD638\uD654\uD560 \uB370\uC774\uD130").option("--file <path>", "\uC554\uD638\uD654\uD560 \uB370\uC774\uD130\uB97C \uC77D\uC744 \uD30C\uC77C \uACBD\uB85C")
|
|
12982
|
+
).action(async (keyId, _opts, command) => {
|
|
12983
|
+
const opts = command.optsWithGlobals();
|
|
12984
|
+
const parsedKeyId = parseRequiredArgument(keyId, "key-id");
|
|
12985
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
12986
|
+
const label = "\uC554\uD638\uD654\uD560 \uB370\uC774\uD130";
|
|
12987
|
+
const input = readSkmInput(
|
|
12988
|
+
{ text: opts.plaintext, file: opts.file },
|
|
12989
|
+
{ textFlag: "--plaintext", label, maxBytes: MAX_ENCRYPT_BYTES }
|
|
12990
|
+
);
|
|
12991
|
+
const plaintext = decodeUtf8Input(input, label, "\uBC14\uC774\uB108\uB9AC\uB294 base64\uB85C \uC778\uCF54\uB529\uD574 \uC804\uB2EC\uD558\uC138\uC694.");
|
|
12992
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
12993
|
+
const body = await withSkmSpinner(
|
|
12994
|
+
`SKM \uB300\uCE6D\uD0A4 ${formatCell(parsedKeyId)}\uB85C \uC554\uD638\uD654 \uC911...`,
|
|
12995
|
+
() => client.encrypt(parsedKeyId, plaintext)
|
|
12996
|
+
);
|
|
12997
|
+
printSkmValue(opts, body.ciphertext, body);
|
|
12998
|
+
});
|
|
12999
|
+
var decryptCommand = withSkmOptions(
|
|
13000
|
+
new import_commander65.Command("decrypt").description("\uB300\uCE6D\uD0A4\uB85C \uC554\uD638\uBB38\uC744 \uBCF5\uD638\uD654\uD55C\uB2E4 (--ciphertext / --file / stdin, \uD3C9\uBB38\uC744 stdout\uC5D0 \uCD9C\uB825)").argument("<key-id>", "\uD0A4 ID").option("--ciphertext <text>", "\uBCF5\uD638\uD654\uD560 \uC554\uD638\uBB38 (base64)").option("--file <path>", "\uBCF5\uD638\uD654\uD560 \uC554\uD638\uBB38\uC744 \uC77D\uC744 \uD30C\uC77C \uACBD\uB85C")
|
|
13001
|
+
).action(async (keyId, _opts, command) => {
|
|
13002
|
+
const opts = command.optsWithGlobals();
|
|
13003
|
+
const parsedKeyId = parseRequiredArgument(keyId, "key-id");
|
|
13004
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
13005
|
+
const label = "\uBCF5\uD638\uD654\uD560 \uC554\uD638\uBB38";
|
|
13006
|
+
const input = readSkmInput(
|
|
13007
|
+
{ text: opts.ciphertext, file: opts.file },
|
|
13008
|
+
{ textFlag: "--ciphertext", label, maxBytes: MAX_JSON_INPUT_BYTES }
|
|
13009
|
+
);
|
|
13010
|
+
const ciphertext = decodeUtf8Input(input, label, "\uC554\uD638\uBB38\uC740 base64 \uBB38\uC790\uC5F4\uC785\uB2C8\uB2E4.").trim();
|
|
13011
|
+
if (!ciphertext) {
|
|
13012
|
+
throw new NhnCloudCliError(`${label}\uC774 \uBE44\uC5B4 \uC788\uC2B5\uB2C8\uB2E4.`, EXIT_PARAM_ERROR);
|
|
13013
|
+
}
|
|
13014
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
13015
|
+
const body = await withSkmSpinner(
|
|
13016
|
+
`SKM \uB300\uCE6D\uD0A4 ${formatCell(parsedKeyId)}\uB85C \uBCF5\uD638\uD654 \uC911...`,
|
|
13017
|
+
() => client.decrypt(parsedKeyId, ciphertext)
|
|
13018
|
+
);
|
|
13019
|
+
printSkmValue(opts, body.plaintext, body);
|
|
13020
|
+
});
|
|
13021
|
+
var getCommand14 = withSkmOptions(
|
|
13022
|
+
new import_commander65.Command("get").description("\uB300\uCE6D\uD0A4 \uC6D0\uBB38\uC744 \uC870\uD68C\uD55C\uB2E4 (\uC6D0\uBB38\uC744 stdout\uC5D0 \uCD9C\uB825)").argument("<key-id>", "\uD0A4 ID").option("--key-version <n>", "\uC870\uD68C\uD560 \uD0A4 \uBC84\uC804 (0 \uC774\uC0C1, \uC0DD\uB7B5\uD558\uBA74 \uBC84\uC804\uC744 \uC9C0\uC815\uD558\uC9C0 \uC54A\uACE0 \uC694\uCCAD)")
|
|
13023
|
+
).action(async (keyId, _opts, command) => {
|
|
13024
|
+
const opts = command.optsWithGlobals();
|
|
13025
|
+
const parsedKeyId = parseRequiredArgument(keyId, "key-id");
|
|
13026
|
+
const keyVersion = parseKeyVersionOption(opts.keyVersion);
|
|
13027
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
13028
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
13029
|
+
const body = await withSkmSpinner(
|
|
13030
|
+
`SKM \uB300\uCE6D\uD0A4 ${formatCell(parsedKeyId)} \uC870\uD68C \uC911...`,
|
|
13031
|
+
() => client.getSymmetricKey(parsedKeyId, keyVersion)
|
|
13032
|
+
);
|
|
13033
|
+
printSkmValue(opts, body.symmetricKey, body);
|
|
13034
|
+
});
|
|
13035
|
+
var createLocalKeyCommand = withSkmOptions(
|
|
13036
|
+
new import_commander65.Command("create-local-key").description("\uB85C\uCEEC \uC554\uD638\uD654\uC5D0 \uC4F8 \uB370\uC774\uD130 \uD0A4\uB97C \uB9CC\uB4E0\uB2E4 (\uD3C9\uBB38 \uD0A4\uB294 \uC774 \uC751\uB2F5\uC5D0\uC11C\uB9CC \uBC1B\uC744 \uC218 \uC788\uB2E4)").argument("<key-id>", "\uD0A4 ID")
|
|
13037
|
+
).action(async (keyId, _opts, command) => {
|
|
13038
|
+
const opts = command.optsWithGlobals();
|
|
13039
|
+
const parsedKeyId = parseRequiredArgument(keyId, "key-id");
|
|
13040
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
13041
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
13042
|
+
const body = await withSkmSpinner(
|
|
13043
|
+
`SKM \uB300\uCE6D\uD0A4 ${formatCell(parsedKeyId)}\uB85C \uB85C\uCEEC \uD0A4 \uC0DD\uC131 \uC911...`,
|
|
13044
|
+
() => client.createLocalKey(parsedKeyId)
|
|
13045
|
+
);
|
|
13046
|
+
output(opts, {
|
|
13047
|
+
headers: ["field", "value"],
|
|
13048
|
+
rows: [
|
|
13049
|
+
["localKeyPlaintext", formatCell(body.localKeyPlaintext)],
|
|
13050
|
+
["localKeyCiphertext", formatCell(body.localKeyCiphertext)],
|
|
13051
|
+
["keyVersion", formatCell(body.keyVersion)]
|
|
13052
|
+
],
|
|
13053
|
+
raw: body,
|
|
13054
|
+
ids: [body.localKeyPlaintext, body.localKeyCiphertext]
|
|
13055
|
+
});
|
|
13056
|
+
});
|
|
13057
|
+
var symmetricKeyCommand = new import_commander65.Command("symmetric-key").description("SKM \uB300\uCE6D\uD0A4 \uC554\uBCF5\uD638\uD654\uC640 \uD0A4 \uC870\uD68C").addCommand(encryptCommand).addCommand(decryptCommand).addCommand(getCommand14).addCommand(createLocalKeyCommand);
|
|
13058
|
+
|
|
13059
|
+
// src/commands/skm/asymmetric-key.ts
|
|
13060
|
+
var import_commander66 = require("commander");
|
|
13061
|
+
var MAX_SIGN_BYTES = 245;
|
|
13062
|
+
var MAX_STANDARD_SIGN_BYTES = 65536;
|
|
13063
|
+
function readSignPayload(opts, label) {
|
|
13064
|
+
const input = readSkmInput(
|
|
13065
|
+
{ text: opts.plaintext, file: opts.file },
|
|
13066
|
+
{ textFlag: "--plaintext", label, maxBytes: opts.standard ? MAX_STANDARD_SIGN_BYTES : MAX_SIGN_BYTES }
|
|
13067
|
+
);
|
|
13068
|
+
if (opts.standard) return input.toString("base64");
|
|
13069
|
+
return decodeUtf8Input(input, label, "\uBC14\uC774\uB108\uB9AC\uB294 --standard\uB85C \uC11C\uBA85\uD558\uC138\uC694.");
|
|
13070
|
+
}
|
|
13071
|
+
function withSignInputOptions(command) {
|
|
13072
|
+
return command.argument("<key-id>", "\uD0A4 ID").option("--plaintext <text>", "\uB370\uC774\uD130 (\uBBF8\uC9C0\uC815 \uC2DC --file \uB610\uB294 stdin)").option("--file <path>", "\uB370\uC774\uD130\uB97C \uC77D\uC744 \uD30C\uC77C \uACBD\uB85C").option("--standard", "\uD45C\uC900 \uC2A4\uD0B4(RSASSA-PSS)\uC73C\uB85C \uCC98\uB9AC\uD55C\uB2E4 (\uBC14\uC774\uB108\uB9AC \uAC00\uB2A5, 64KB \uC774\uD558)");
|
|
13073
|
+
}
|
|
13074
|
+
var signCommand = withSkmOptions(
|
|
13075
|
+
withSignInputOptions(
|
|
13076
|
+
new import_commander66.Command("sign").description("\uBE44\uB300\uCE6D\uD0A4\uB85C \uB370\uC774\uD130\uC5D0 \uC11C\uBA85\uD55C\uB2E4 (\uC77C\uBC18 \uC11C\uBA85\uC740 UTF-8 \uD14D\uC2A4\uD2B8 245\uBC14\uC774\uD2B8 \uC774\uD558)")
|
|
13077
|
+
)
|
|
13078
|
+
).action(async (keyId, _opts, command) => {
|
|
13079
|
+
const opts = command.optsWithGlobals();
|
|
13080
|
+
const parsedKeyId = parseRequiredArgument(keyId, "key-id");
|
|
13081
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
13082
|
+
const payload = readSignPayload(opts, "\uC11C\uBA85\uD560 \uB370\uC774\uD130");
|
|
13083
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
13084
|
+
const body = await withSkmSpinner(
|
|
13085
|
+
`SKM \uBE44\uB300\uCE6D\uD0A4 ${formatCell(parsedKeyId)}\uB85C \uC11C\uBA85 \uC911...`,
|
|
13086
|
+
() => opts.standard ? client.signStandard(parsedKeyId, payload) : client.sign(parsedKeyId, payload)
|
|
13087
|
+
);
|
|
13088
|
+
printSkmValue(opts, body.signature, body);
|
|
13089
|
+
});
|
|
13090
|
+
var verifyCommand = withSkmOptions(
|
|
13091
|
+
withSignInputOptions(
|
|
13092
|
+
new import_commander66.Command("verify").description("\uBE44\uB300\uCE6D\uD0A4\uB85C \uC11C\uBA85\uC744 \uAC80\uC99D\uD55C\uB2E4 (\uAC80\uC99D \uC2E4\uD328\uB294 \uC885\uB8CC \uCF54\uB4DC 1)")
|
|
13093
|
+
).requiredOption("--signature <sig>", "\uAC80\uC99D\uD560 \uC11C\uBA85\uAC12 (base64)").option("--key-version <n>", "\uC11C\uBA85\uD55C \uD0A4 \uBC84\uC804 (--standard \uAC80\uC99D\uC5D0 \uD544\uC218)")
|
|
13094
|
+
).action(async (keyId, _opts, command) => {
|
|
13095
|
+
const opts = command.optsWithGlobals();
|
|
13096
|
+
const parsedKeyId = parseRequiredArgument(keyId, "key-id");
|
|
13097
|
+
const signature = opts.signature.trim();
|
|
13098
|
+
if (!signature) {
|
|
13099
|
+
throw new NhnCloudCliError("--signature\uAC00 \uBE44\uC5B4 \uC788\uC2B5\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
13100
|
+
}
|
|
13101
|
+
const keyVersion = parseKeyVersionOption(opts.keyVersion);
|
|
13102
|
+
if (opts.standard && keyVersion === void 0) {
|
|
13103
|
+
throw new NhnCloudCliError("--standard \uAC80\uC99D\uC5D0\uB294 --key-version\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
13104
|
+
}
|
|
13105
|
+
if (!opts.standard && keyVersion !== void 0) {
|
|
13106
|
+
throw new NhnCloudCliError("--key-version\uC740 --standard\uC640 \uD568\uAED8 \uC9C0\uC815\uD569\uB2C8\uB2E4.", EXIT_PARAM_ERROR);
|
|
13107
|
+
}
|
|
13108
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
13109
|
+
const payload = readSignPayload(opts, "\uAC80\uC99D\uD560 \uB370\uC774\uD130");
|
|
13110
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
13111
|
+
const body = await withSkmSpinner(
|
|
13112
|
+
`SKM \uBE44\uB300\uCE6D\uD0A4 ${formatCell(parsedKeyId)}\uB85C \uC11C\uBA85 \uAC80\uC99D \uC911...`,
|
|
13113
|
+
() => keyVersion !== void 0 ? client.verifyStandard(parsedKeyId, payload, signature, keyVersion) : client.verify(parsedKeyId, payload, signature)
|
|
13114
|
+
);
|
|
13115
|
+
if (opts.json) {
|
|
13116
|
+
printJson(body);
|
|
13117
|
+
} else if (!opts.quiet) {
|
|
13118
|
+
const verdict = body.result ? "\uAC80\uC99D \uC131\uACF5" : "\uAC80\uC99D \uC2E4\uD328";
|
|
13119
|
+
process.stdout.write(`${verdict} (keyVersion ${body.keyVersion})
|
|
13120
|
+
`);
|
|
13121
|
+
}
|
|
13122
|
+
if (!body.result) {
|
|
13123
|
+
throw new NhnCloudCliError("\uC11C\uBA85 \uAC80\uC99D\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.", EXIT_API_ERROR);
|
|
13124
|
+
}
|
|
13125
|
+
});
|
|
13126
|
+
function keyMaterialCommand(name, description, fetch, spinnerLabel) {
|
|
13127
|
+
return withSkmOptions(
|
|
13128
|
+
new import_commander66.Command(name).description(description).argument("<key-id>", "\uD0A4 ID").option("--key-version <n>", "\uC870\uD68C\uD560 \uD0A4 \uBC84\uC804 (0 \uC774\uC0C1, \uC0DD\uB7B5\uD558\uBA74 \uBC84\uC804\uC744 \uC9C0\uC815\uD558\uC9C0 \uC54A\uACE0 \uC694\uCCAD)")
|
|
13129
|
+
).action(async (keyId, _opts, command) => {
|
|
13130
|
+
const opts = command.optsWithGlobals();
|
|
13131
|
+
const parsedKeyId = parseRequiredArgument(keyId, "key-id");
|
|
13132
|
+
const keyVersion = parseKeyVersionOption(opts.keyVersion);
|
|
13133
|
+
const macAddress = parseMacAddressOption(opts.macAddress);
|
|
13134
|
+
const { client } = await resolveSkmClient({ profile: opts.profile, macAddress });
|
|
13135
|
+
const body = await withSkmSpinner(
|
|
13136
|
+
`SKM \uBE44\uB300\uCE6D\uD0A4 ${formatCell(parsedKeyId)} ${spinnerLabel} \uC870\uD68C \uC911...`,
|
|
13137
|
+
() => fetch(client, parsedKeyId, keyVersion)
|
|
13138
|
+
);
|
|
13139
|
+
printSkmValue(opts, body.standardEncodedKey ?? body.encodedKey, body);
|
|
13140
|
+
});
|
|
13141
|
+
}
|
|
13142
|
+
var publicKeyCommand = keyMaterialCommand(
|
|
13143
|
+
"public-key",
|
|
13144
|
+
"\uACF5\uAC1C\uD0A4\uB97C \uC870\uD68C\uD55C\uB2E4 (standardEncodedKey\uB97C, \uC5C6\uC73C\uBA74 encodedKey\uB97C stdout\uC5D0 \uCD9C\uB825)",
|
|
13145
|
+
(client, keyId, keyVersion) => client.getPublicKey(keyId, keyVersion),
|
|
13146
|
+
"\uACF5\uAC1C\uD0A4"
|
|
13147
|
+
);
|
|
13148
|
+
var privateKeyCommand = keyMaterialCommand(
|
|
13149
|
+
"private-key",
|
|
13150
|
+
"\uAC1C\uC778\uD0A4 \uC6D0\uBB38\uC744 \uC870\uD68C\uD55C\uB2E4 (standardEncodedKey\uB97C, \uC5C6\uC73C\uBA74 encodedKey\uB97C stdout\uC5D0 \uCD9C\uB825)",
|
|
13151
|
+
(client, keyId, keyVersion) => client.getPrivateKey(keyId, keyVersion),
|
|
13152
|
+
"\uAC1C\uC778\uD0A4"
|
|
13153
|
+
);
|
|
13154
|
+
var asymmetricKeyCommand = new import_commander66.Command("asymmetric-key").description("SKM \uBE44\uB300\uCE6D\uD0A4 \uC11C\uBA85\xB7\uAC80\uC99D\uACFC \uD0A4 \uC870\uD68C").addCommand(signCommand).addCommand(verifyCommand).addCommand(publicKeyCommand).addCommand(privateKeyCommand);
|
|
13155
|
+
|
|
13156
|
+
// src/commands/loadbalancer/list.ts
|
|
13157
|
+
var import_commander67 = require("commander");
|
|
13158
|
+
|
|
13159
|
+
// src/commands/loadbalancer/helpers.ts
|
|
13160
|
+
var import_node_net3 = require("net");
|
|
13161
|
+
|
|
13162
|
+
// src/services/loadbalancer/client.ts
|
|
13163
|
+
var import_ky17 = __toESM(require("ky"));
|
|
13164
|
+
|
|
13165
|
+
// src/services/loadbalancer/types.ts
|
|
13166
|
+
function isRecord5(value) {
|
|
13167
|
+
return typeof value === "object" && value !== null;
|
|
13168
|
+
}
|
|
11216
13169
|
function isNonEmptyString(value) {
|
|
11217
13170
|
return typeof value === "string" && value.length > 0;
|
|
11218
13171
|
}
|
|
@@ -11220,29 +13173,29 @@ function isIpAclAction(value) {
|
|
|
11220
13173
|
return value === "ALLOW" || value === "DENY";
|
|
11221
13174
|
}
|
|
11222
13175
|
function isLoadBalancerIpAclGroup(value) {
|
|
11223
|
-
return
|
|
13176
|
+
return isRecord5(value) && isNonEmptyString(value["ipacl_group_id"]);
|
|
11224
13177
|
}
|
|
11225
13178
|
function isIpAclGroupLoadBalancer(value) {
|
|
11226
|
-
return
|
|
13179
|
+
return isRecord5(value) && isNonEmptyString(value["loadbalancer_id"]);
|
|
11227
13180
|
}
|
|
11228
13181
|
function isLoadBalancer(value) {
|
|
11229
|
-
if (!
|
|
13182
|
+
if (!isRecord5(value)) return false;
|
|
11230
13183
|
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);
|
|
11231
13184
|
}
|
|
11232
13185
|
function isIpAclGroup(value) {
|
|
11233
|
-
if (!
|
|
13186
|
+
if (!isRecord5(value)) return false;
|
|
11234
13187
|
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);
|
|
11235
13188
|
}
|
|
11236
13189
|
function isIpAclTarget(value) {
|
|
11237
|
-
if (!
|
|
13190
|
+
if (!isRecord5(value)) return false;
|
|
11238
13191
|
return isNonEmptyString(value["id"]) && typeof value["cidr_address"] === "string" && typeof value["description"] === "string" && isNonEmptyString(value["ipacl_group_id"]);
|
|
11239
13192
|
}
|
|
11240
13193
|
function isIpAclBinding(value) {
|
|
11241
|
-
return
|
|
13194
|
+
return isRecord5(value) && isNonEmptyString(value["loadbalancer_id"]) && isNonEmptyString(value["ipacl_group_id"]);
|
|
11242
13195
|
}
|
|
11243
13196
|
|
|
11244
13197
|
// src/services/loadbalancer/client.ts
|
|
11245
|
-
function
|
|
13198
|
+
function isRecord6(value) {
|
|
11246
13199
|
return typeof value === "object" && value !== null;
|
|
11247
13200
|
}
|
|
11248
13201
|
function requireNonEmptyId(id, label) {
|
|
@@ -11253,7 +13206,7 @@ function requireNonEmptyId(id, label) {
|
|
|
11253
13206
|
return normalized;
|
|
11254
13207
|
}
|
|
11255
13208
|
function readArrayField(response, key, itemGuard, missingKeyMessage, invalidItemMessage) {
|
|
11256
|
-
if (!
|
|
13209
|
+
if (!isRecord6(response) || !Array.isArray(response[key])) {
|
|
11257
13210
|
throw new NhnCloudCliError(missingKeyMessage, EXIT_API_ERROR);
|
|
11258
13211
|
}
|
|
11259
13212
|
const items = response[key];
|
|
@@ -11263,7 +13216,7 @@ function readArrayField(response, key, itemGuard, missingKeyMessage, invalidItem
|
|
|
11263
13216
|
return items;
|
|
11264
13217
|
}
|
|
11265
13218
|
function readObjectField(response, key, itemGuard, missingKeyMessage, invalidItemMessage) {
|
|
11266
|
-
if (!
|
|
13219
|
+
if (!isRecord6(response) || !(key in response)) {
|
|
11267
13220
|
throw new NhnCloudCliError(missingKeyMessage, EXIT_API_ERROR);
|
|
11268
13221
|
}
|
|
11269
13222
|
const item = response[key];
|
|
@@ -11401,10 +13354,10 @@ var LoadBalancerClient = class {
|
|
|
11401
13354
|
}
|
|
11402
13355
|
return raw;
|
|
11403
13356
|
}
|
|
11404
|
-
async getJson(
|
|
11405
|
-
const url = `${this.endpoint}${
|
|
13357
|
+
async getJson(path4, searchParams) {
|
|
13358
|
+
const url = `${this.endpoint}${path4}`;
|
|
11406
13359
|
try {
|
|
11407
|
-
return await
|
|
13360
|
+
return await import_ky17.default.get(url, {
|
|
11408
13361
|
headers: this.authHeaders(),
|
|
11409
13362
|
searchParams,
|
|
11410
13363
|
retry: 0,
|
|
@@ -11414,10 +13367,10 @@ var LoadBalancerClient = class {
|
|
|
11414
13367
|
throw toNhnCloudCliError(error);
|
|
11415
13368
|
}
|
|
11416
13369
|
}
|
|
11417
|
-
async postJson(
|
|
11418
|
-
const url = `${this.endpoint}${
|
|
13370
|
+
async postJson(path4, json) {
|
|
13371
|
+
const url = `${this.endpoint}${path4}`;
|
|
11419
13372
|
try {
|
|
11420
|
-
return await
|
|
13373
|
+
return await import_ky17.default.post(url, {
|
|
11421
13374
|
headers: this.authHeaders(),
|
|
11422
13375
|
json,
|
|
11423
13376
|
retry: 0,
|
|
@@ -11427,10 +13380,10 @@ var LoadBalancerClient = class {
|
|
|
11427
13380
|
throw toNhnCloudCliError(error);
|
|
11428
13381
|
}
|
|
11429
13382
|
}
|
|
11430
|
-
async putJson(
|
|
11431
|
-
const url = `${this.endpoint}${
|
|
13383
|
+
async putJson(path4, json) {
|
|
13384
|
+
const url = `${this.endpoint}${path4}`;
|
|
11432
13385
|
try {
|
|
11433
|
-
return await
|
|
13386
|
+
return await import_ky17.default.put(url, {
|
|
11434
13387
|
headers: this.authHeaders(),
|
|
11435
13388
|
json,
|
|
11436
13389
|
retry: 0,
|
|
@@ -11440,10 +13393,10 @@ var LoadBalancerClient = class {
|
|
|
11440
13393
|
throw toNhnCloudCliError(error);
|
|
11441
13394
|
}
|
|
11442
13395
|
}
|
|
11443
|
-
async deleteNoContent(
|
|
11444
|
-
const url = `${this.endpoint}${
|
|
13396
|
+
async deleteNoContent(path4) {
|
|
13397
|
+
const url = `${this.endpoint}${path4}`;
|
|
11445
13398
|
try {
|
|
11446
|
-
await
|
|
13399
|
+
await import_ky17.default.delete(url, {
|
|
11447
13400
|
headers: this.authHeaders(),
|
|
11448
13401
|
retry: 0,
|
|
11449
13402
|
timeout: DEFAULT_TIMEOUT_MS
|
|
@@ -11481,7 +13434,7 @@ function parseIpOrCidr(value) {
|
|
|
11481
13434
|
const normalized = value.trim();
|
|
11482
13435
|
const parts = normalized.split("/");
|
|
11483
13436
|
const address = parts[0] ?? "";
|
|
11484
|
-
const version = (0,
|
|
13437
|
+
const version = (0, import_node_net3.isIP)(address);
|
|
11485
13438
|
if (version === 0 || parts.length > 2) {
|
|
11486
13439
|
throw new NhnCloudCliError(
|
|
11487
13440
|
`--cidr\uC740 IP \uC8FC\uC18C \uB610\uB294 CIDR\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4: ${JSON.stringify(value)}`,
|
|
@@ -11534,7 +13487,7 @@ async function resolveLoadBalancerClient(opts) {
|
|
|
11534
13487
|
}
|
|
11535
13488
|
|
|
11536
13489
|
// src/commands/loadbalancer/list.ts
|
|
11537
|
-
var
|
|
13490
|
+
var listCommand18 = new import_commander67.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) => {
|
|
11538
13491
|
const opts = cmd.optsWithGlobals();
|
|
11539
13492
|
const { client } = await resolveLoadBalancerClient(opts);
|
|
11540
13493
|
startSpinner("Load Balancer \uBAA9\uB85D \uC870\uD68C \uC911...");
|
|
@@ -11572,8 +13525,8 @@ var listCommand16 = new import_commander59.Command("list").description("Load Bal
|
|
|
11572
13525
|
});
|
|
11573
13526
|
|
|
11574
13527
|
// src/commands/loadbalancer/get.ts
|
|
11575
|
-
var
|
|
11576
|
-
var
|
|
13528
|
+
var import_commander68 = require("commander");
|
|
13529
|
+
var getCommand15 = new import_commander68.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) => {
|
|
11577
13530
|
const opts = cmd.optsWithGlobals();
|
|
11578
13531
|
const input = requireResourceInput(loadBalancerInput, "Load Balancer");
|
|
11579
13532
|
const { client } = await resolveLoadBalancerClient(opts);
|
|
@@ -11610,10 +13563,10 @@ var getCommand11 = new import_commander60.Command("get").description("Load Balan
|
|
|
11610
13563
|
});
|
|
11611
13564
|
|
|
11612
13565
|
// src/commands/loadbalancer/ipacl.ts
|
|
11613
|
-
var
|
|
13566
|
+
var import_commander70 = require("commander");
|
|
11614
13567
|
|
|
11615
13568
|
// src/commands/loadbalancer/target.ts
|
|
11616
|
-
var
|
|
13569
|
+
var import_commander69 = require("commander");
|
|
11617
13570
|
|
|
11618
13571
|
// src/commands/loadbalancer/rebind.ts
|
|
11619
13572
|
function shellQuote(value) {
|
|
@@ -11744,7 +13697,7 @@ function targetWriteResult(operation, target, rebind) {
|
|
|
11744
13697
|
rebind
|
|
11745
13698
|
};
|
|
11746
13699
|
}
|
|
11747
|
-
var
|
|
13700
|
+
var listCommand19 = new import_commander69.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) => {
|
|
11748
13701
|
const opts = cmd.optsWithGlobals();
|
|
11749
13702
|
const input = requireResourceInput(groupInput, "IP ACL \uADF8\uB8F9");
|
|
11750
13703
|
const { client } = await resolveLoadBalancerClient(opts);
|
|
@@ -11773,7 +13726,7 @@ var listCommand17 = new import_commander61.Command("list").description("IP ACL \
|
|
|
11773
13726
|
ids: targets.map((target) => target.id)
|
|
11774
13727
|
});
|
|
11775
13728
|
});
|
|
11776
|
-
var addCommand = new
|
|
13729
|
+
var addCommand = new import_commander69.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) => {
|
|
11777
13730
|
const opts = cmd.optsWithGlobals();
|
|
11778
13731
|
requireYes(opts.yes, "IP ACL \uB300\uC0C1 \uCD94\uAC00");
|
|
11779
13732
|
const parsedGroup = requireResourceInput(groupInput, "IP ACL \uADF8\uB8F9");
|
|
@@ -11810,7 +13763,7 @@ var addCommand = new import_commander61.Command("add").description("IP ACL \uB30
|
|
|
11810
13763
|
writeTargetWarnings(group, result);
|
|
11811
13764
|
if (result.status === "partial") process.exitCode = EXIT_API_ERROR;
|
|
11812
13765
|
});
|
|
11813
|
-
var removeCommand = new
|
|
13766
|
+
var removeCommand = new import_commander69.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) => {
|
|
11814
13767
|
const opts = cmd.optsWithGlobals();
|
|
11815
13768
|
requireYes(opts.yes, "IP ACL \uB300\uC0C1 \uC0AD\uC81C");
|
|
11816
13769
|
const parsedTargetId = requireResourceInput(targetInput, "IP ACL \uB300\uC0C1");
|
|
@@ -11841,13 +13794,13 @@ var removeCommand = new import_commander61.Command("remove").description("IP ACL
|
|
|
11841
13794
|
writeTargetWarnings(group, result);
|
|
11842
13795
|
if (result.status === "partial") process.exitCode = EXIT_API_ERROR;
|
|
11843
13796
|
});
|
|
11844
|
-
var targetCommand = new
|
|
11845
|
-
targetCommand.addCommand(
|
|
13797
|
+
var targetCommand = new import_commander69.Command("target").description("IP ACL \uB300\uC0C1 \uC870\uD68C\xB7\uAD00\uB9AC");
|
|
13798
|
+
targetCommand.addCommand(listCommand19);
|
|
11846
13799
|
targetCommand.addCommand(addCommand);
|
|
11847
13800
|
targetCommand.addCommand(removeCommand);
|
|
11848
13801
|
|
|
11849
13802
|
// src/commands/loadbalancer/ipacl.ts
|
|
11850
|
-
var
|
|
13803
|
+
var listCommand20 = new import_commander70.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) => {
|
|
11851
13804
|
const opts = cmd.optsWithGlobals();
|
|
11852
13805
|
const { client } = await resolveLoadBalancerClient(opts);
|
|
11853
13806
|
startSpinner("IP ACL \uADF8\uB8F9 \uBAA9\uB85D \uC870\uD68C \uC911...");
|
|
@@ -11875,7 +13828,7 @@ var listCommand18 = new import_commander62.Command("list").description("IP ACL \
|
|
|
11875
13828
|
ids: groups.map((group) => group.id)
|
|
11876
13829
|
});
|
|
11877
13830
|
});
|
|
11878
|
-
var
|
|
13831
|
+
var getCommand16 = new import_commander70.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) => {
|
|
11879
13832
|
const opts = cmd.optsWithGlobals();
|
|
11880
13833
|
const input = requireResourceInput(groupInput, "IP ACL \uADF8\uB8F9");
|
|
11881
13834
|
const { client } = await resolveLoadBalancerClient(opts);
|
|
@@ -11908,7 +13861,7 @@ var getCommand12 = new import_commander62.Command("get").description("IP ACL \uA
|
|
|
11908
13861
|
ids: [group.id]
|
|
11909
13862
|
});
|
|
11910
13863
|
});
|
|
11911
|
-
var
|
|
13864
|
+
var createCommand13 = new import_commander70.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) => {
|
|
11912
13865
|
const opts = cmd.optsWithGlobals();
|
|
11913
13866
|
const parsedName = requireResourceInput(opts.name ?? "", "IP ACL \uADF8\uB8F9");
|
|
11914
13867
|
const parsedAction = parseIpAclAction(opts.action ?? "");
|
|
@@ -11939,7 +13892,7 @@ var createCommand11 = new import_commander62.Command("create").description("IP A
|
|
|
11939
13892
|
ids: [group.id]
|
|
11940
13893
|
});
|
|
11941
13894
|
});
|
|
11942
|
-
var
|
|
13895
|
+
var deleteCommand11 = new import_commander70.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) => {
|
|
11943
13896
|
const opts = cmd.optsWithGlobals();
|
|
11944
13897
|
const confirmedYes = requireYes(opts.yes, "IP ACL \uADF8\uB8F9 \uC0AD\uC81C");
|
|
11945
13898
|
const parsedGroup = requireResourceInput(groupInput, "IP ACL \uADF8\uB8F9");
|
|
@@ -11971,23 +13924,15 @@ var deleteCommand9 = new import_commander62.Command("delete").description("IP AC
|
|
|
11971
13924
|
ids: [groupId]
|
|
11972
13925
|
});
|
|
11973
13926
|
});
|
|
11974
|
-
var ipaclCommand = new
|
|
11975
|
-
ipaclCommand.addCommand(
|
|
11976
|
-
ipaclCommand.addCommand(
|
|
11977
|
-
ipaclCommand.addCommand(
|
|
11978
|
-
ipaclCommand.addCommand(
|
|
13927
|
+
var ipaclCommand = new import_commander70.Command("ipacl").description("IP ACL \uADF8\uB8F9\xB7\uB300\uC0C1 \uC870\uD68C");
|
|
13928
|
+
ipaclCommand.addCommand(listCommand20);
|
|
13929
|
+
ipaclCommand.addCommand(getCommand16);
|
|
13930
|
+
ipaclCommand.addCommand(createCommand13);
|
|
13931
|
+
ipaclCommand.addCommand(deleteCommand11);
|
|
11979
13932
|
ipaclCommand.addCommand(targetCommand);
|
|
11980
13933
|
|
|
11981
|
-
// src/commands/loadbalancer/help.ts
|
|
11982
|
-
function configureLoadBalancerHelp(command) {
|
|
11983
|
-
command.configureHelp({ showGlobalOptions: true });
|
|
11984
|
-
for (const child of command.commands) {
|
|
11985
|
-
configureLoadBalancerHelp(child);
|
|
11986
|
-
}
|
|
11987
|
-
}
|
|
11988
|
-
|
|
11989
13934
|
// src/commands/loadbalancer/binding.ts
|
|
11990
|
-
var
|
|
13935
|
+
var import_commander71 = require("commander");
|
|
11991
13936
|
function bindingResult(operation, loadBalancerId, groupIds) {
|
|
11992
13937
|
return {
|
|
11993
13938
|
operation,
|
|
@@ -12009,7 +13954,7 @@ function outputBindingResult(opts, result) {
|
|
|
12009
13954
|
ids: [result.loadbalancer_id]
|
|
12010
13955
|
});
|
|
12011
13956
|
}
|
|
12012
|
-
var setIpAclCommand2 = new
|
|
13957
|
+
var setIpAclCommand2 = new import_commander71.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(
|
|
12013
13958
|
"--group <group>",
|
|
12014
13959
|
"\uC801\uC6A9\uD560 IP ACL \uADF8\uB8F9 \uC774\uB984 \uB610\uB294 UUID (\uBC18\uBCF5 \uAC00\uB2A5)",
|
|
12015
13960
|
collectOption
|
|
@@ -12049,7 +13994,7 @@ var setIpAclCommand2 = new import_commander63.Command("set-ipacl").description("
|
|
|
12049
13994
|
bindingResult("loadbalancer-set-ipacl", loadBalancerId, groupIds)
|
|
12050
13995
|
);
|
|
12051
13996
|
});
|
|
12052
|
-
var clearIpAclCommand = new
|
|
13997
|
+
var clearIpAclCommand = new import_commander71.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) => {
|
|
12053
13998
|
const opts = cmd.optsWithGlobals();
|
|
12054
13999
|
const confirmedYes = requireYes(opts.yes, "Load Balancer IP ACL \uC5F0\uACB0 \uD574\uC81C");
|
|
12055
14000
|
const parsedLoadBalancer = requireResourceInput(loadBalancerInput, "Load Balancer");
|
|
@@ -12140,8 +14085,8 @@ Agent workflow:
|
|
|
12140
14085
|
2. nhncloud ncs workload list --json
|
|
12141
14086
|
3. nhncloud ncs workload get <id> --json
|
|
12142
14087
|
`;
|
|
12143
|
-
var program = new
|
|
12144
|
-
program.name("nhncloud").description("NHN Cloud CLI \u2014 AI agent & terminal friendly").version(
|
|
14088
|
+
var program = new import_commander72.Command();
|
|
14089
|
+
program.name("nhncloud").description("NHN Cloud CLI \u2014 AI agent & terminal friendly").version(CLI_VERSION).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").option("--request-timeout <sec>", "HTTP \uC694\uCCAD \uD0C0\uC784\uC544\uC6C3 (\uCD08, \uAE30\uBCF8 30, \uBC94\uC704 1~3600). NHNCLOUD_REQUEST_TIMEOUT \uB85C\uB3C4 \uC9C0\uC815").addHelpText("after", rootAgentHints);
|
|
12145
14090
|
program.hook("preAction", () => {
|
|
12146
14091
|
const opts = program.opts();
|
|
12147
14092
|
const rawTimeout = opts.requestTimeout ?? process.env["NHNCLOUD_REQUEST_TIMEOUT"];
|
|
@@ -12162,13 +14107,13 @@ program.hook("preAction", () => {
|
|
|
12162
14107
|
}
|
|
12163
14108
|
});
|
|
12164
14109
|
program.addCommand(configureCommand);
|
|
12165
|
-
var logncrashCommand = new
|
|
14110
|
+
var logncrashCommand = new import_commander72.Command("logncrash").description("Log & Crash \uAD00\uB828 \uBA85\uB839").addHelpText("after", logncrashAgentWorkflow);
|
|
12166
14111
|
logncrashCommand.addCommand(availableTokenCommand);
|
|
12167
14112
|
logncrashCommand.addCommand(searchCommand);
|
|
12168
14113
|
logncrashCommand.addCommand(sendCommand);
|
|
12169
14114
|
logncrashCommand.addCommand(exportCommand);
|
|
12170
14115
|
program.addCommand(logncrashCommand);
|
|
12171
|
-
var deployCommand2 = new
|
|
14116
|
+
var deployCommand2 = new import_commander72.Command("deploy").description("NHN Cloud Deploy \uAD00\uB828 \uBA85\uB839").addHelpText("after", deployAgentWorkflow);
|
|
12172
14117
|
deployCommand2.hook("preSubcommand", async () => {
|
|
12173
14118
|
await warnLegacyDeployTargets();
|
|
12174
14119
|
});
|
|
@@ -12182,7 +14127,7 @@ deployCommand2.addCommand(binariesCommand);
|
|
|
12182
14127
|
deployCommand2.addCommand(uploadCommand);
|
|
12183
14128
|
deployCommand2.addCommand(downloadCommand);
|
|
12184
14129
|
program.addCommand(deployCommand2);
|
|
12185
|
-
var instanceCommand = new
|
|
14130
|
+
var instanceCommand = new import_commander72.Command("instance").description("Compute \uC778\uC2A4\uD134\uC2A4 \uAD00\uB828 \uBA85\uB839").addHelpText("after", instanceAgentWorkflow);
|
|
12186
14131
|
instanceCommand.addCommand(listCommand);
|
|
12187
14132
|
instanceCommand.addCommand(flavorsCommand);
|
|
12188
14133
|
instanceCommand.addCommand(availabilityZonesCommand);
|
|
@@ -12202,60 +14147,68 @@ instanceCommand.addCommand(volumeCommand);
|
|
|
12202
14147
|
instanceCommand.addCommand(volumesCommand);
|
|
12203
14148
|
instanceCommand.addCommand(securityGroupCommand2);
|
|
12204
14149
|
program.addCommand(instanceCommand);
|
|
12205
|
-
var networkCommand = new
|
|
14150
|
+
var networkCommand = new import_commander72.Command("network").description("VPC\xB7\uC11C\uBE0C\uB137 \uC870\uD68C\uC640 \uBCF4\uC548\uADF8\uB8F9 \uAD00\uB9AC").addHelpText("after", networkAgentWorkflow);
|
|
12206
14151
|
networkCommand.addCommand(listCommand3);
|
|
12207
14152
|
networkCommand.addCommand(subnetCommand);
|
|
12208
14153
|
networkCommand.addCommand(securityGroupCommand);
|
|
12209
14154
|
program.addCommand(networkCommand);
|
|
12210
|
-
var volumeCommand2 = new
|
|
14155
|
+
var volumeCommand2 = new import_commander72.Command("volume").description("Block Storage \uBCFC\uB968 \uAD00\uB828 \uBA85\uB839").addHelpText("after", volumeAgentWorkflow);
|
|
12211
14156
|
volumeCommand2.addCommand(listCommand2);
|
|
12212
14157
|
volumeCommand2.addCommand(getCommand);
|
|
12213
14158
|
volumeCommand2.addCommand(createCommand);
|
|
12214
14159
|
program.addCommand(volumeCommand2);
|
|
12215
|
-
var floatingipCommand = new
|
|
14160
|
+
var floatingipCommand = new import_commander72.Command("floatingip").description(
|
|
12216
14161
|
"Floating IP(\uC778\uC2A4\uD134\uC2A4 \uACF5\uC778 IP) \uAD00\uB9AC"
|
|
12217
14162
|
).addHelpText("after", floatingIpAgentWorkflow);
|
|
12218
14163
|
floatingipCommand.addCommand(listCommand6);
|
|
12219
14164
|
floatingipCommand.addCommand(createCommand4);
|
|
12220
14165
|
floatingipCommand.addCommand(deleteCommand3);
|
|
12221
14166
|
program.addCommand(floatingipCommand);
|
|
12222
|
-
var loadbalancerCommand = new
|
|
12223
|
-
loadbalancerCommand.addCommand(
|
|
12224
|
-
loadbalancerCommand.addCommand(
|
|
14167
|
+
var loadbalancerCommand = new import_commander72.Command("loadbalancer").description("Load Balancer\xB7IP ACL \uC870\uD68C\xB7\uAD00\uB9AC").addHelpText("after", loadbalancerAgentWorkflow);
|
|
14168
|
+
loadbalancerCommand.addCommand(listCommand18);
|
|
14169
|
+
loadbalancerCommand.addCommand(getCommand15);
|
|
12225
14170
|
loadbalancerCommand.addCommand(ipaclCommand);
|
|
12226
14171
|
loadbalancerCommand.addCommand(setIpAclCommand2);
|
|
12227
14172
|
loadbalancerCommand.addCommand(clearIpAclCommand);
|
|
12228
|
-
configureLoadBalancerHelp(loadbalancerCommand);
|
|
12229
14173
|
program.addCommand(loadbalancerCommand);
|
|
12230
|
-
var ncrCommand = new
|
|
14174
|
+
var ncrCommand = new import_commander72.Command("ncr").description("NHN Container Registry \uAD00\uB828 \uBA85\uB839").addHelpText("after", ncrAgentWorkflow);
|
|
12231
14175
|
ncrCommand.addCommand(listCommand7);
|
|
12232
14176
|
ncrCommand.addCommand(getCommand5);
|
|
12233
14177
|
ncrCommand.addCommand(imagesCommand2);
|
|
12234
14178
|
ncrCommand.addCommand(tagsCommand);
|
|
12235
14179
|
program.addCommand(ncrCommand);
|
|
12236
|
-
var nksCommand = new
|
|
14180
|
+
var nksCommand = new import_commander72.Command("nks").description("NHN Kubernetes Service \uAD00\uB828 \uBA85\uB839").addHelpText("after", nksAgentWorkflow);
|
|
12237
14181
|
nksCommand.addCommand(supportsCommand);
|
|
12238
14182
|
nksCommand.addCommand(clusterCommand);
|
|
12239
14183
|
nksCommand.addCommand(nodegroupCommand);
|
|
12240
14184
|
nksCommand.addCommand(addonTypeCommand);
|
|
12241
14185
|
nksCommand.addCommand(addonCommand);
|
|
12242
14186
|
program.addCommand(nksCommand);
|
|
12243
|
-
var ncsCommand = new
|
|
14187
|
+
var ncsCommand = new import_commander72.Command("ncs").description("NHN Container Service \uAD00\uB828 \uBA85\uB839").addHelpText("after", ncsAgentWorkflow);
|
|
12244
14188
|
ncsCommand.addCommand(templateCommand);
|
|
12245
14189
|
ncsCommand.addCommand(workloadCommand);
|
|
12246
14190
|
ncsCommand.addCommand(malwareCommand);
|
|
12247
14191
|
program.addCommand(ncsCommand);
|
|
12248
|
-
var apiGatewayCommand = new
|
|
14192
|
+
var apiGatewayCommand = new import_commander72.Command("apigateway").description("NHN API Gateway \uC870\uD68C \uBA85\uB839");
|
|
12249
14193
|
apiGatewayCommand.addCommand(serviceCommand);
|
|
12250
14194
|
apiGatewayCommand.addCommand(resourceCommand);
|
|
12251
14195
|
apiGatewayCommand.addCommand(stageCommand);
|
|
12252
14196
|
program.addCommand(apiGatewayCommand);
|
|
14197
|
+
var skmCommand = new import_commander72.Command("skm").description("NHN Secure Key Manager \uD0A4 \uC800\uC7A5\uC18C\xB7\uD0A4 \uAD00\uB9AC\uC640 \uAE30\uBC00 \uB370\uC774\uD130\xB7\uC554\uBCF5\uD638\uD654\xB7\uC11C\uBA85 \uBA85\uB839");
|
|
14198
|
+
skmCommand.addCommand(confirmCommand);
|
|
14199
|
+
skmCommand.addCommand(keystoreCommand);
|
|
14200
|
+
skmCommand.addCommand(keyCommand);
|
|
14201
|
+
skmCommand.addCommand(secretCommand);
|
|
14202
|
+
skmCommand.addCommand(symmetricKeyCommand);
|
|
14203
|
+
skmCommand.addCommand(asymmetricKeyCommand);
|
|
14204
|
+
program.addCommand(skmCommand);
|
|
12253
14205
|
program.addCommand(skillsCommand);
|
|
12254
14206
|
program.addCommand(doctorCommand);
|
|
12255
14207
|
program.addCommand(createCommandsCommand(program));
|
|
12256
14208
|
configureCommanderExitCodes(program);
|
|
14209
|
+
configureGlobalOptionsHelp(program);
|
|
12257
14210
|
program.parseAsync().catch((err) => {
|
|
12258
|
-
if (err instanceof
|
|
14211
|
+
if (err instanceof import_commander72.CommanderError) {
|
|
12259
14212
|
process.exit(err.exitCode);
|
|
12260
14213
|
}
|
|
12261
14214
|
const message = sanitizeMultilineForTerminal(
|