@bifos/nhncloud-cli 0.7.0 → 0.8.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 +76 -2
- package/dist/index.js +1688 -68
- package/package.json +1 -1
- package/skills/nhncloud-cli/SKILL.md +3 -1
- package/skills/nhncloud-cli/references/ncs.md +167 -0
package/dist/index.js
CHANGED
|
@@ -24,8 +24,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// src/index.ts
|
|
27
|
-
var
|
|
28
|
-
var
|
|
27
|
+
var import_commander46 = require("commander");
|
|
28
|
+
var import_chalk16 = __toESM(require("chalk"));
|
|
29
29
|
|
|
30
30
|
// src/utils/spinner.ts
|
|
31
31
|
var import_ora = __toESM(require("ora"));
|
|
@@ -567,6 +567,20 @@ function nksHost(region) {
|
|
|
567
567
|
}
|
|
568
568
|
return host;
|
|
569
569
|
}
|
|
570
|
+
var NCS_HOST = {
|
|
571
|
+
kr1: "kr1-ncs.api.nhncloudservice.com",
|
|
572
|
+
kr3: "kr3-ncs.api.nhncloudservice.com"
|
|
573
|
+
};
|
|
574
|
+
function ncsHost(region) {
|
|
575
|
+
const host = NCS_HOST[region];
|
|
576
|
+
if (!host) {
|
|
577
|
+
throw new NhnCloudCliError(
|
|
578
|
+
`\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 NCS region \uC785\uB2C8\uB2E4: "${region}". \uC0AC\uC6A9 \uAC00\uB2A5\uD55C region: ${Object.keys(NCS_HOST).join(", ")}`,
|
|
579
|
+
EXIT_PARAM_ERROR
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
return host;
|
|
583
|
+
}
|
|
570
584
|
|
|
571
585
|
// src/api/keystone.ts
|
|
572
586
|
function isKeystoneTokenResponse(val) {
|
|
@@ -4315,7 +4329,13 @@ var import_ky11 = __toESM(require("ky"));
|
|
|
4315
4329
|
function isNksClusterSummary(val) {
|
|
4316
4330
|
if (typeof val !== "object" || val === null) return false;
|
|
4317
4331
|
const obj = val;
|
|
4318
|
-
return typeof obj["uuid"] === "string" && typeof obj["name"] === "string" && typeof obj["status"] === "string" && typeof obj["health_status"] === "string" && (typeof obj["node_count"] === "number" || typeof obj["node_count"] === "string")
|
|
4332
|
+
return typeof obj["uuid"] === "string" && typeof obj["name"] === "string" && typeof obj["status"] === "string" && typeof obj["health_status"] === "string" && (typeof obj["node_count"] === "number" || typeof obj["node_count"] === "string");
|
|
4333
|
+
}
|
|
4334
|
+
function nksClusterKubeTag(cluster) {
|
|
4335
|
+
const fromLabels = cluster.labels?.["kube_tag"];
|
|
4336
|
+
if (typeof fromLabels === "string") return fromLabels;
|
|
4337
|
+
if (typeof cluster.kube_tag === "string") return cluster.kube_tag;
|
|
4338
|
+
return "-";
|
|
4319
4339
|
}
|
|
4320
4340
|
function isNksSupports(val) {
|
|
4321
4341
|
if (typeof val !== "object" || val === null) return false;
|
|
@@ -4893,7 +4913,7 @@ var listCommand6 = new import_commander40.Command("list").description("NKS \uD07
|
|
|
4893
4913
|
cluster.status,
|
|
4894
4914
|
cluster.health_status,
|
|
4895
4915
|
String(cluster.node_count),
|
|
4896
|
-
cluster
|
|
4916
|
+
nksClusterKubeTag(cluster)
|
|
4897
4917
|
]),
|
|
4898
4918
|
raw: clusters,
|
|
4899
4919
|
ids: clusters.map((cluster) => cluster.uuid)
|
|
@@ -5645,77 +5665,1672 @@ var addonGetCommand = new import_commander42.Command("get").description("NKS \uC
|
|
|
5645
5665
|
});
|
|
5646
5666
|
var addonCommand = new import_commander42.Command("addon").description("NKS \uC560\uB4DC\uC628 \uAD00\uB828 \uBA85\uB839").addCommand(addonListCommand).addCommand(addonGetCommand);
|
|
5647
5667
|
|
|
5648
|
-
// src/
|
|
5649
|
-
var
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5668
|
+
// src/commands/ncs/template.ts
|
|
5669
|
+
var import_commander43 = require("commander");
|
|
5670
|
+
var import_chalk14 = __toESM(require("chalk"));
|
|
5671
|
+
|
|
5672
|
+
// src/commands/ncs/helpers.ts
|
|
5673
|
+
var import_node_fs7 = require("fs");
|
|
5674
|
+
|
|
5675
|
+
// src/services/ncs/client.ts
|
|
5676
|
+
var import_ky12 = __toESM(require("ky"));
|
|
5677
|
+
|
|
5678
|
+
// src/services/ncs/types.ts
|
|
5679
|
+
function isNcsTemplateSummary(val) {
|
|
5680
|
+
if (typeof val !== "object" || val === null) return false;
|
|
5681
|
+
const obj = val;
|
|
5682
|
+
return typeof obj["id"] === "string" && typeof obj["name"] === "string";
|
|
5683
|
+
}
|
|
5684
|
+
function isNcsTemplateDetail(val) {
|
|
5685
|
+
return isNcsTemplateSummary(val);
|
|
5686
|
+
}
|
|
5687
|
+
function isNcsTemplateVersionSummary(val) {
|
|
5688
|
+
if (typeof val !== "object" || val === null) return false;
|
|
5689
|
+
const obj = val;
|
|
5690
|
+
return typeof obj["id"] === "string" && typeof obj["version"] === "string";
|
|
5691
|
+
}
|
|
5692
|
+
function isNcsTemplateVersionDetail(val) {
|
|
5693
|
+
return isNcsTemplateVersionSummary(val);
|
|
5694
|
+
}
|
|
5695
|
+
function isNcsWorkloadSummary(val) {
|
|
5696
|
+
if (typeof val !== "object" || val === null) return false;
|
|
5697
|
+
const obj = val;
|
|
5698
|
+
return typeof obj["id"] === "string" && typeof obj["name"] === "string" && typeof obj["status"] === "string";
|
|
5699
|
+
}
|
|
5700
|
+
function isNcsWorkloadDetail(val) {
|
|
5701
|
+
return isNcsWorkloadSummary(val);
|
|
5702
|
+
}
|
|
5703
|
+
function isNcsWorkloadLog(val) {
|
|
5704
|
+
if (typeof val !== "object" || val === null) return false;
|
|
5705
|
+
const obj = val;
|
|
5706
|
+
return typeof obj["log"] === "string" && typeof obj["time"] === "string";
|
|
5707
|
+
}
|
|
5708
|
+
function isNcsWorkloadEvent(val) {
|
|
5709
|
+
if (typeof val !== "object" || val === null) return false;
|
|
5710
|
+
const obj = val;
|
|
5711
|
+
return typeof obj["type"] === "string" && typeof obj["reason"] === "string" && typeof obj["message"] === "string";
|
|
5712
|
+
}
|
|
5713
|
+
function isNcsWorkloadHistorySummary(val) {
|
|
5714
|
+
if (typeof val !== "object" || val === null) return false;
|
|
5715
|
+
const obj = val;
|
|
5716
|
+
return typeof obj["id"] === "number" && typeof obj["status"] === "string";
|
|
5717
|
+
}
|
|
5718
|
+
function isNcsWorkloadHistoryDetail(val) {
|
|
5719
|
+
return isNcsWorkloadHistorySummary(val);
|
|
5720
|
+
}
|
|
5721
|
+
function isNcsWorkloadScheduleHistory(val) {
|
|
5722
|
+
if (typeof val !== "object" || val === null) return false;
|
|
5723
|
+
const obj = val;
|
|
5724
|
+
return typeof obj["id"] === "string" && typeof obj["status"] === "string";
|
|
5725
|
+
}
|
|
5726
|
+
function isNcsMalwareConfig(val) {
|
|
5727
|
+
if (typeof val !== "object" || val === null) return false;
|
|
5728
|
+
const obj = val;
|
|
5729
|
+
return typeof obj["enabled"] === "boolean";
|
|
5730
|
+
}
|
|
5731
|
+
function isNcsMalwareReport(val) {
|
|
5732
|
+
if (typeof val !== "object" || val === null) return false;
|
|
5733
|
+
const obj = val;
|
|
5734
|
+
return typeof obj["image"] === "string" && typeof obj["result"] === "string";
|
|
5735
|
+
}
|
|
5736
|
+
|
|
5737
|
+
// src/services/ncs/client.ts
|
|
5738
|
+
var DEFAULT_TIMEOUT_MS8 = 3e4;
|
|
5739
|
+
var DEFAULT_WAIT_POLL_INTERVAL_MS = 5e3;
|
|
5740
|
+
var NcsClient = class {
|
|
5741
|
+
accessToken;
|
|
5742
|
+
baseUrl;
|
|
5743
|
+
constructor(accessToken, region, appKey) {
|
|
5744
|
+
this.accessToken = accessToken;
|
|
5745
|
+
this.baseUrl = `https://${ncsHost(region)}/ncs/v1.0/appkeys/${encodeURIComponent(appKey)}`;
|
|
5746
|
+
}
|
|
5747
|
+
authHeaders() {
|
|
5748
|
+
return { "x-nhn-authorization": `Bearer ${this.accessToken}` };
|
|
5749
|
+
}
|
|
5750
|
+
/**
|
|
5751
|
+
* 설계도(template) 목록을 반환한다.
|
|
5752
|
+
* GET /ncs/v1.0/appkeys/{appKey}/templates
|
|
5753
|
+
* 응답: { header, templates: [...] } — body 가 아니라 named 필드(docs 예제 확정).
|
|
5754
|
+
*
|
|
5755
|
+
* pagination: 기본 page size 10(docs 확정). 목록이 앞부분만 조용히 반환(silent truncation)하지
|
|
5756
|
+
* 않도록 page/size 를 그대로 노출한다. 총 개수는 응답 헤더 X-Total-Count 로 온다(docs 확정) —
|
|
5757
|
+
* body/JSON 필드가 아니므로 ky Response 에서 header 를 직접 읽는다(harbor-client.ts 의
|
|
5758
|
+
* .json()+.headers.get() 분리 패턴과 동일 — .json<T>() 체이닝으로는 헤더를 못 본다).
|
|
5759
|
+
*/
|
|
5760
|
+
async listTemplates(query = {}) {
|
|
5761
|
+
const url = `${this.baseUrl}/templates`;
|
|
5762
|
+
const searchParams = {};
|
|
5763
|
+
if (query.page !== void 0) searchParams["page"] = query.page;
|
|
5764
|
+
if (query.size !== void 0) searchParams["size"] = query.size;
|
|
5765
|
+
if (query.disableContainers !== void 0) {
|
|
5766
|
+
searchParams["disable_containers"] = query.disableContainers;
|
|
5767
|
+
}
|
|
5768
|
+
try {
|
|
5769
|
+
const res = await import_ky12.default.get(url, {
|
|
5770
|
+
headers: this.authHeaders(),
|
|
5771
|
+
searchParams,
|
|
5772
|
+
retry: 0,
|
|
5773
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
5774
|
+
});
|
|
5775
|
+
const body = await res.json();
|
|
5776
|
+
unwrapHeader(body);
|
|
5777
|
+
if (!Array.isArray(body.templates)) {
|
|
5778
|
+
if (body.templates === void 0) return { totalCount: 0, templates: [] };
|
|
5779
|
+
throw new NhnCloudCliError(
|
|
5780
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: templates \uAC00 \uBC30\uC5F4\uC774 \uC544\uB2D9\uB2C8\uB2E4.",
|
|
5781
|
+
EXIT_API_ERROR
|
|
5782
|
+
);
|
|
5783
|
+
}
|
|
5784
|
+
const templates = body.templates.filter(isNcsTemplateSummary);
|
|
5785
|
+
const headerTotal = res.headers.get("x-total-count");
|
|
5786
|
+
const totalCount = headerTotal !== null && /^\d+$/.test(headerTotal) ? Number(headerTotal) : templates.length;
|
|
5787
|
+
return { totalCount, templates };
|
|
5788
|
+
} catch (err) {
|
|
5789
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
5790
|
+
throw toNhnCloudCliError(err);
|
|
5791
|
+
}
|
|
5792
|
+
}
|
|
5793
|
+
/**
|
|
5794
|
+
* 설계도(template) 단건을 반환한다.
|
|
5795
|
+
* GET /ncs/v1.0/appkeys/{appKey}/templates/{id}
|
|
5796
|
+
* 응답: { header, template: {...} } — named 필드(listTemplates 와 같은 패턴).
|
|
5797
|
+
*/
|
|
5798
|
+
async getTemplate(id) {
|
|
5799
|
+
const url = `${this.baseUrl}/templates/${encodeURIComponent(id)}`;
|
|
5800
|
+
try {
|
|
5801
|
+
const res = await import_ky12.default.get(url, {
|
|
5802
|
+
headers: this.authHeaders(),
|
|
5803
|
+
retry: 0,
|
|
5804
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
5805
|
+
});
|
|
5806
|
+
const body = await res.json();
|
|
5807
|
+
unwrapHeader(body);
|
|
5808
|
+
if (!isNcsTemplateDetail(body.template)) {
|
|
5809
|
+
throw new NhnCloudCliError(
|
|
5810
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: template \uD544\uB4DC\uAC00 \uC5C6\uAC70\uB098 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
5811
|
+
EXIT_API_ERROR
|
|
5812
|
+
);
|
|
5813
|
+
}
|
|
5814
|
+
return body.template;
|
|
5815
|
+
} catch (err) {
|
|
5816
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
5817
|
+
throw toNhnCloudCliError(err);
|
|
5818
|
+
}
|
|
5819
|
+
}
|
|
5820
|
+
/**
|
|
5821
|
+
* 설계도(template) 의 버전 목록을 반환한다.
|
|
5822
|
+
* GET /ncs/v1.0/appkeys/{appKey}/templates/{id}/versions
|
|
5823
|
+
* 응답: { header, versions: [...] } — named 필드. pagination 은 listTemplates 와 동일하게
|
|
5824
|
+
* X-Total-Count 응답 헤더 + page/size 노출(silent truncation 방지).
|
|
5825
|
+
*/
|
|
5826
|
+
async listTemplateVersions(id, query = {}) {
|
|
5827
|
+
const url = `${this.baseUrl}/templates/${encodeURIComponent(id)}/versions`;
|
|
5828
|
+
const searchParams = {};
|
|
5829
|
+
if (query.q !== void 0) searchParams["q"] = query.q;
|
|
5830
|
+
if (query.sort !== void 0) searchParams["sort"] = query.sort;
|
|
5831
|
+
if (query.page !== void 0) searchParams["page"] = query.page;
|
|
5832
|
+
if (query.size !== void 0) searchParams["size"] = query.size;
|
|
5833
|
+
try {
|
|
5834
|
+
const res = await import_ky12.default.get(url, {
|
|
5835
|
+
headers: this.authHeaders(),
|
|
5836
|
+
searchParams,
|
|
5837
|
+
retry: 0,
|
|
5838
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
5839
|
+
});
|
|
5840
|
+
const body = await res.json();
|
|
5841
|
+
unwrapHeader(body);
|
|
5842
|
+
if (!Array.isArray(body.versions)) {
|
|
5843
|
+
if (body.versions === void 0) return { totalCount: 0, versions: [] };
|
|
5844
|
+
throw new NhnCloudCliError(
|
|
5845
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: versions \uAC00 \uBC30\uC5F4\uC774 \uC544\uB2D9\uB2C8\uB2E4.",
|
|
5846
|
+
EXIT_API_ERROR
|
|
5847
|
+
);
|
|
5848
|
+
}
|
|
5849
|
+
const versions = body.versions.filter(isNcsTemplateVersionSummary);
|
|
5850
|
+
const headerTotal = res.headers.get("x-total-count");
|
|
5851
|
+
const totalCount = headerTotal !== null && /^\d+$/.test(headerTotal) ? Number(headerTotal) : versions.length;
|
|
5852
|
+
return { totalCount, versions };
|
|
5853
|
+
} catch (err) {
|
|
5854
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
5855
|
+
throw toNhnCloudCliError(err);
|
|
5856
|
+
}
|
|
5857
|
+
}
|
|
5858
|
+
/**
|
|
5859
|
+
* 설계도(template) 버전 단건을 반환한다.
|
|
5860
|
+
* GET /ncs/v1.0/appkeys/{appKey}/templates/{id}/versions/{version}
|
|
5861
|
+
* 응답: { header, version: {...} } — named 필드.
|
|
5862
|
+
*/
|
|
5863
|
+
async getTemplateVersion(id, version) {
|
|
5864
|
+
const url = `${this.baseUrl}/templates/${encodeURIComponent(id)}/versions/${encodeURIComponent(version)}`;
|
|
5865
|
+
try {
|
|
5866
|
+
const res = await import_ky12.default.get(url, {
|
|
5867
|
+
headers: this.authHeaders(),
|
|
5868
|
+
retry: 0,
|
|
5869
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
5870
|
+
});
|
|
5871
|
+
const body = await res.json();
|
|
5872
|
+
unwrapHeader(body);
|
|
5873
|
+
if (!isNcsTemplateVersionDetail(body.version)) {
|
|
5874
|
+
throw new NhnCloudCliError(
|
|
5875
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: version \uD544\uB4DC\uAC00 \uC5C6\uAC70\uB098 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
5876
|
+
EXIT_API_ERROR
|
|
5877
|
+
);
|
|
5878
|
+
}
|
|
5879
|
+
return body.version;
|
|
5880
|
+
} catch (err) {
|
|
5881
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
5882
|
+
throw toNhnCloudCliError(err);
|
|
5883
|
+
}
|
|
5884
|
+
}
|
|
5885
|
+
/**
|
|
5886
|
+
* workload(런타임 실행) 목록을 반환한다.
|
|
5887
|
+
* GET /ncs/v1.0/appkeys/{appKey}/workloads
|
|
5888
|
+
* 응답: { header, workloads: [...] } — named 필드(listTemplates 와 동일 패턴).
|
|
5889
|
+
* pagination: X-Total-Count 응답 헤더 + page/size 노출(listTemplates 와 동일 규약).
|
|
5890
|
+
*/
|
|
5891
|
+
async listWorkloads(query = {}) {
|
|
5892
|
+
const url = `${this.baseUrl}/workloads`;
|
|
5893
|
+
const searchParams = {};
|
|
5894
|
+
if (query.q !== void 0) searchParams["q"] = query.q;
|
|
5895
|
+
if (query.page !== void 0) searchParams["page"] = query.page;
|
|
5896
|
+
if (query.size !== void 0) searchParams["size"] = query.size;
|
|
5897
|
+
try {
|
|
5898
|
+
const res = await import_ky12.default.get(url, {
|
|
5899
|
+
headers: this.authHeaders(),
|
|
5900
|
+
searchParams,
|
|
5901
|
+
retry: 0,
|
|
5902
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
5903
|
+
});
|
|
5904
|
+
const body = await res.json();
|
|
5905
|
+
unwrapHeader(body);
|
|
5906
|
+
if (!Array.isArray(body.workloads)) {
|
|
5907
|
+
if (body.workloads === void 0) return { totalCount: 0, workloads: [] };
|
|
5908
|
+
throw new NhnCloudCliError(
|
|
5909
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: workloads \uAC00 \uBC30\uC5F4\uC774 \uC544\uB2D9\uB2C8\uB2E4.",
|
|
5910
|
+
EXIT_API_ERROR
|
|
5911
|
+
);
|
|
5912
|
+
}
|
|
5913
|
+
const workloads = body.workloads.filter(isNcsWorkloadSummary);
|
|
5914
|
+
const headerTotal = res.headers.get("x-total-count");
|
|
5915
|
+
const totalCount = headerTotal !== null && /^\d+$/.test(headerTotal) ? Number(headerTotal) : workloads.length;
|
|
5916
|
+
return { totalCount, workloads };
|
|
5917
|
+
} catch (err) {
|
|
5918
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
5919
|
+
throw toNhnCloudCliError(err);
|
|
5920
|
+
}
|
|
5921
|
+
}
|
|
5922
|
+
/**
|
|
5923
|
+
* workload 단건을 반환한다 (tasks[] 런타임 상태 포함).
|
|
5924
|
+
* GET /ncs/v1.0/appkeys/{appKey}/workloads/{workloadId}
|
|
5925
|
+
* 응답: { header, workload: {...} } — named 필드.
|
|
5926
|
+
*/
|
|
5927
|
+
async getWorkload(id) {
|
|
5928
|
+
const url = `${this.baseUrl}/workloads/${encodeURIComponent(id)}`;
|
|
5929
|
+
try {
|
|
5930
|
+
const res = await import_ky12.default.get(url, {
|
|
5931
|
+
headers: this.authHeaders(),
|
|
5932
|
+
retry: 0,
|
|
5933
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
5934
|
+
});
|
|
5935
|
+
const body = await res.json();
|
|
5936
|
+
unwrapHeader(body);
|
|
5937
|
+
if (!isNcsWorkloadDetail(body.workload)) {
|
|
5938
|
+
throw new NhnCloudCliError(
|
|
5939
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: workload \uD544\uB4DC\uAC00 \uC5C6\uAC70\uB098 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
5940
|
+
EXIT_API_ERROR
|
|
5941
|
+
);
|
|
5942
|
+
}
|
|
5943
|
+
return body.workload;
|
|
5944
|
+
} catch (err) {
|
|
5945
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
5946
|
+
throw toNhnCloudCliError(err);
|
|
5947
|
+
}
|
|
5948
|
+
}
|
|
5949
|
+
/**
|
|
5950
|
+
* workload task 의 컨테이너 로그를 반환한다.
|
|
5951
|
+
* GET /ncs/v1.0/appkeys/{appKey}/workloads/{workloadId}/tasks/{taskId}/logs
|
|
5952
|
+
* docs 확정 필수 쿼리는 `containerName` — CLI 시그니처 일관성을 위해 `container` 로 받고 여기서 매핑한다.
|
|
5953
|
+
* container 누락(빈 문자열 포함) 시 EXIT_PARAM_ERROR — API 호출 전 파라미터 검증(1-3 회피).
|
|
5954
|
+
* 응답: { header, logs: [...] } — named 필드. docs 에 X-Total-Count 헤더가 없어 totalCount 는 반환하지 않는다.
|
|
5955
|
+
*/
|
|
5956
|
+
async getWorkloadLogs(id, taskId, query) {
|
|
5957
|
+
if (!query.container || !query.container.trim()) {
|
|
5958
|
+
throw new NhnCloudCliError(
|
|
5959
|
+
"container \uCFFC\uB9AC\uAC00 \uBE44\uC5B4\uC788\uC2B5\uB2C8\uB2E4. \uCEE8\uD14C\uC774\uB108 \uC774\uB984\uC744 \uC9C0\uC815\uD558\uC138\uC694.",
|
|
5960
|
+
EXIT_PARAM_ERROR
|
|
5961
|
+
);
|
|
5962
|
+
}
|
|
5963
|
+
const url = `${this.baseUrl}/workloads/${encodeURIComponent(id)}/tasks/${encodeURIComponent(taskId)}/logs`;
|
|
5964
|
+
const searchParams = { containerName: query.container };
|
|
5965
|
+
if (query.from !== void 0) searchParams["from"] = query.from;
|
|
5966
|
+
if (query.to !== void 0) searchParams["to"] = query.to;
|
|
5967
|
+
if (query.page !== void 0) searchParams["page"] = query.page;
|
|
5968
|
+
if (query.size !== void 0) searchParams["size"] = query.size;
|
|
5969
|
+
try {
|
|
5970
|
+
const res = await import_ky12.default.get(url, {
|
|
5971
|
+
headers: this.authHeaders(),
|
|
5972
|
+
searchParams,
|
|
5973
|
+
retry: 0,
|
|
5974
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
5975
|
+
});
|
|
5976
|
+
const body = await res.json();
|
|
5977
|
+
unwrapHeader(body);
|
|
5978
|
+
if (!Array.isArray(body.logs)) {
|
|
5979
|
+
if (body.logs === void 0) return { logs: [] };
|
|
5980
|
+
throw new NhnCloudCliError(
|
|
5981
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: logs \uAC00 \uBC30\uC5F4\uC774 \uC544\uB2D9\uB2C8\uB2E4.",
|
|
5982
|
+
EXIT_API_ERROR
|
|
5983
|
+
);
|
|
5984
|
+
}
|
|
5985
|
+
return { logs: body.logs.filter(isNcsWorkloadLog) };
|
|
5986
|
+
} catch (err) {
|
|
5987
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
5988
|
+
throw toNhnCloudCliError(err);
|
|
5989
|
+
}
|
|
5990
|
+
}
|
|
5991
|
+
/**
|
|
5992
|
+
* workload task 의 이벤트 목록을 반환한다.
|
|
5993
|
+
* GET /ncs/v1.0/appkeys/{appKey}/workloads/{workloadId}/tasks/{taskId}/events
|
|
5994
|
+
* 응답: { header, events: [...] } — named 필드.
|
|
5995
|
+
* pagination: X-Total-Count 헤더가 docs 에 명시되진 않았으나, 있으면 정확히 반영하고 없으면
|
|
5996
|
+
* 현재 페이지 길이로 fallback(listTemplates 와 동일한 방어적 패턴 — 실제 헤더 부재와도 호환).
|
|
5997
|
+
*/
|
|
5998
|
+
async getWorkloadEvents(id, taskId, query = {}) {
|
|
5999
|
+
const url = `${this.baseUrl}/workloads/${encodeURIComponent(id)}/tasks/${encodeURIComponent(taskId)}/events`;
|
|
6000
|
+
const searchParams = {};
|
|
6001
|
+
if (query.type !== void 0) searchParams["type"] = query.type;
|
|
6002
|
+
if (query.q !== void 0) searchParams["q"] = query.q;
|
|
6003
|
+
if (query.from !== void 0) searchParams["from"] = query.from;
|
|
6004
|
+
if (query.to !== void 0) searchParams["to"] = query.to;
|
|
6005
|
+
if (query.page !== void 0) searchParams["page"] = query.page;
|
|
6006
|
+
if (query.size !== void 0) searchParams["size"] = query.size;
|
|
6007
|
+
try {
|
|
6008
|
+
const res = await import_ky12.default.get(url, {
|
|
6009
|
+
headers: this.authHeaders(),
|
|
6010
|
+
searchParams,
|
|
6011
|
+
retry: 0,
|
|
6012
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6013
|
+
});
|
|
6014
|
+
const body = await res.json();
|
|
6015
|
+
unwrapHeader(body);
|
|
6016
|
+
if (!Array.isArray(body.events)) {
|
|
6017
|
+
if (body.events === void 0) return { totalCount: 0, events: [] };
|
|
6018
|
+
throw new NhnCloudCliError(
|
|
6019
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: events \uAC00 \uBC30\uC5F4\uC774 \uC544\uB2D9\uB2C8\uB2E4.",
|
|
6020
|
+
EXIT_API_ERROR
|
|
6021
|
+
);
|
|
6022
|
+
}
|
|
6023
|
+
const events = body.events.filter(isNcsWorkloadEvent);
|
|
6024
|
+
const headerTotal = res.headers.get("x-total-count");
|
|
6025
|
+
const totalCount = headerTotal !== null && /^\d+$/.test(headerTotal) ? Number(headerTotal) : events.length;
|
|
6026
|
+
return { totalCount, events };
|
|
6027
|
+
} catch (err) {
|
|
6028
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6029
|
+
throw toNhnCloudCliError(err);
|
|
6030
|
+
}
|
|
6031
|
+
}
|
|
6032
|
+
/**
|
|
6033
|
+
* workload 의 실행 히스토리 목록을 반환한다.
|
|
6034
|
+
* GET /ncs/v1.0/appkeys/{appKey}/workloads/{workloadId}/history
|
|
6035
|
+
* 응답: { header, history: [...] } — named 필드.
|
|
6036
|
+
* pagination: getWorkloadEvents 와 동일한 방어적 X-Total-Count fallback 패턴.
|
|
6037
|
+
*/
|
|
6038
|
+
async listWorkloadHistory(id, query = {}) {
|
|
6039
|
+
const url = `${this.baseUrl}/workloads/${encodeURIComponent(id)}/history`;
|
|
6040
|
+
const searchParams = {};
|
|
6041
|
+
if (query.page !== void 0) searchParams["page"] = query.page;
|
|
6042
|
+
if (query.size !== void 0) searchParams["size"] = query.size;
|
|
6043
|
+
if (query.sort !== void 0) searchParams["sort"] = query.sort;
|
|
6044
|
+
try {
|
|
6045
|
+
const res = await import_ky12.default.get(url, {
|
|
6046
|
+
headers: this.authHeaders(),
|
|
6047
|
+
searchParams,
|
|
6048
|
+
retry: 0,
|
|
6049
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6050
|
+
});
|
|
6051
|
+
const body = await res.json();
|
|
6052
|
+
unwrapHeader(body);
|
|
6053
|
+
if (!Array.isArray(body.history)) {
|
|
6054
|
+
if (body.history === void 0) return { totalCount: 0, history: [] };
|
|
6055
|
+
throw new NhnCloudCliError(
|
|
6056
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: history \uAC00 \uBC30\uC5F4\uC774 \uC544\uB2D9\uB2C8\uB2E4.",
|
|
6057
|
+
EXIT_API_ERROR
|
|
6058
|
+
);
|
|
6059
|
+
}
|
|
6060
|
+
const history = body.history.filter(isNcsWorkloadHistorySummary);
|
|
6061
|
+
const headerTotal = res.headers.get("x-total-count");
|
|
6062
|
+
const totalCount = headerTotal !== null && /^\d+$/.test(headerTotal) ? Number(headerTotal) : history.length;
|
|
6063
|
+
return { totalCount, history };
|
|
6064
|
+
} catch (err) {
|
|
6065
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6066
|
+
throw toNhnCloudCliError(err);
|
|
6067
|
+
}
|
|
6068
|
+
}
|
|
6069
|
+
/**
|
|
6070
|
+
* workload 실행 히스토리 단건을 반환한다 (당시 사용한 template 스냅샷 포함).
|
|
6071
|
+
* GET /ncs/v1.0/appkeys/{appKey}/workloads/{workloadId}/history/{historyId}
|
|
6072
|
+
* 응답: { header, history: {...}, template: {...} } — history/template 이 sibling named 필드(docs 예제 확정).
|
|
6073
|
+
*/
|
|
6074
|
+
async getWorkloadHistory(id, historyId) {
|
|
6075
|
+
const url = `${this.baseUrl}/workloads/${encodeURIComponent(id)}/history/${encodeURIComponent(historyId)}`;
|
|
6076
|
+
try {
|
|
6077
|
+
const res = await import_ky12.default.get(url, {
|
|
6078
|
+
headers: this.authHeaders(),
|
|
6079
|
+
retry: 0,
|
|
6080
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6081
|
+
});
|
|
6082
|
+
const body = await res.json();
|
|
6083
|
+
unwrapHeader(body);
|
|
6084
|
+
if (!isNcsWorkloadHistoryDetail(body.history)) {
|
|
6085
|
+
throw new NhnCloudCliError(
|
|
6086
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: history \uD544\uB4DC\uAC00 \uC5C6\uAC70\uB098 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
6087
|
+
EXIT_API_ERROR
|
|
6088
|
+
);
|
|
6089
|
+
}
|
|
6090
|
+
return { ...body.history, template: body.template };
|
|
6091
|
+
} catch (err) {
|
|
6092
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6093
|
+
throw toNhnCloudCliError(err);
|
|
6094
|
+
}
|
|
6095
|
+
}
|
|
6096
|
+
/**
|
|
6097
|
+
* workload 의 예약 실행 히스토리 목록을 반환한다.
|
|
6098
|
+
* GET /ncs/v1.0/appkeys/{appKey}/workloads/{workloadId}/schedulehistory
|
|
6099
|
+
* 응답: { header, schedulehistory: [...] } — named 필드. docs 에 X-Total-Count 헤더가 없어
|
|
6100
|
+
* totalCount 는 반환하지 않는다(phase 범위 — page/size 는 후속 필요 시 추가, ADR-020 표 갱신 불필요한 범위 내 결정).
|
|
6101
|
+
*/
|
|
6102
|
+
async getWorkloadScheduleHistory(id) {
|
|
6103
|
+
const url = `${this.baseUrl}/workloads/${encodeURIComponent(id)}/schedulehistory`;
|
|
6104
|
+
try {
|
|
6105
|
+
const res = await import_ky12.default.get(url, {
|
|
6106
|
+
headers: this.authHeaders(),
|
|
6107
|
+
retry: 0,
|
|
6108
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6109
|
+
});
|
|
6110
|
+
const body = await res.json();
|
|
6111
|
+
unwrapHeader(body);
|
|
6112
|
+
if (!Array.isArray(body.schedulehistory)) {
|
|
6113
|
+
if (body.schedulehistory === void 0) return { scheduleHistory: [] };
|
|
6114
|
+
throw new NhnCloudCliError(
|
|
6115
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: schedulehistory \uAC00 \uBC30\uC5F4\uC774 \uC544\uB2D9\uB2C8\uB2E4.",
|
|
6116
|
+
EXIT_API_ERROR
|
|
6117
|
+
);
|
|
6118
|
+
}
|
|
6119
|
+
return { scheduleHistory: body.schedulehistory.filter(isNcsWorkloadScheduleHistory) };
|
|
6120
|
+
} catch (err) {
|
|
6121
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6122
|
+
throw toNhnCloudCliError(err);
|
|
6123
|
+
}
|
|
6124
|
+
}
|
|
6125
|
+
/**
|
|
6126
|
+
* 설계도(template) 를 생성한다.
|
|
6127
|
+
* POST /ncs/v1.0/appkeys/{appKey}/templates
|
|
6128
|
+
* 요청 body 는 `--file <json>` 로 읽은 값을 그대로 전달한다(필수값 검증은 API 오류에 위임).
|
|
6129
|
+
* 응답: { header, template: {...} } — named 필드(getTemplate 과 동일 패턴).
|
|
6130
|
+
*/
|
|
6131
|
+
async createTemplate(body) {
|
|
6132
|
+
const url = `${this.baseUrl}/templates`;
|
|
6133
|
+
try {
|
|
6134
|
+
const res = await import_ky12.default.post(url, {
|
|
6135
|
+
headers: this.authHeaders(),
|
|
6136
|
+
json: body,
|
|
6137
|
+
retry: 0,
|
|
6138
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6139
|
+
});
|
|
6140
|
+
const resBody = await res.json();
|
|
6141
|
+
unwrapHeader(resBody);
|
|
6142
|
+
if (!isNcsTemplateDetail(resBody.template)) {
|
|
6143
|
+
throw new NhnCloudCliError(
|
|
6144
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: template \uD544\uB4DC\uAC00 \uC5C6\uAC70\uB098 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
6145
|
+
EXIT_API_ERROR
|
|
6146
|
+
);
|
|
6147
|
+
}
|
|
6148
|
+
return resBody.template;
|
|
6149
|
+
} catch (err) {
|
|
6150
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6151
|
+
throw toNhnCloudCliError(err);
|
|
6152
|
+
}
|
|
6153
|
+
}
|
|
6154
|
+
/**
|
|
6155
|
+
* 설계도(template) 를 삭제한다.
|
|
6156
|
+
* DELETE /ncs/v1.0/appkeys/{appKey}/templates/{id}
|
|
6157
|
+
*/
|
|
6158
|
+
async deleteTemplate(id) {
|
|
6159
|
+
const url = `${this.baseUrl}/templates/${encodeURIComponent(id)}`;
|
|
6160
|
+
try {
|
|
6161
|
+
const res = await import_ky12.default.delete(url, {
|
|
6162
|
+
headers: this.authHeaders(),
|
|
6163
|
+
retry: 0,
|
|
6164
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6165
|
+
});
|
|
6166
|
+
unwrapHeader(await res.json());
|
|
6167
|
+
} catch (err) {
|
|
6168
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6169
|
+
throw toNhnCloudCliError(err);
|
|
6170
|
+
}
|
|
6171
|
+
}
|
|
6172
|
+
/**
|
|
6173
|
+
* 설계도(template) 의 새 버전을 생성한다.
|
|
6174
|
+
* POST /ncs/v1.0/appkeys/{appKey}/templates/{id}/versions
|
|
6175
|
+
* body 에 `sourceVersion` 이 필수(docs 확정)이나 클라이언트는 그대로 전달하고
|
|
6176
|
+
* 필수값 검증은 API 응답 오류에 위임한다(1-3 회피 — API 경로에서 EXIT_PARAM_ERROR 를 만들지 않음).
|
|
6177
|
+
* 응답: { header, version: {...} } — named 필드(getTemplateVersion 과 동일 패턴).
|
|
6178
|
+
*/
|
|
6179
|
+
async createTemplateVersion(id, body) {
|
|
6180
|
+
const url = `${this.baseUrl}/templates/${encodeURIComponent(id)}/versions`;
|
|
6181
|
+
try {
|
|
6182
|
+
const res = await import_ky12.default.post(url, {
|
|
6183
|
+
headers: this.authHeaders(),
|
|
6184
|
+
json: body,
|
|
6185
|
+
retry: 0,
|
|
6186
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6187
|
+
});
|
|
6188
|
+
const resBody = await res.json();
|
|
6189
|
+
unwrapHeader(resBody);
|
|
6190
|
+
if (!isNcsTemplateVersionDetail(resBody.version)) {
|
|
6191
|
+
throw new NhnCloudCliError(
|
|
6192
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: version \uD544\uB4DC\uAC00 \uC5C6\uAC70\uB098 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
6193
|
+
EXIT_API_ERROR
|
|
6194
|
+
);
|
|
6195
|
+
}
|
|
6196
|
+
return resBody.version;
|
|
6197
|
+
} catch (err) {
|
|
6198
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6199
|
+
throw toNhnCloudCliError(err);
|
|
6200
|
+
}
|
|
6201
|
+
}
|
|
6202
|
+
/**
|
|
6203
|
+
* 설계도(template) 버전을 삭제한다.
|
|
6204
|
+
* DELETE /ncs/v1.0/appkeys/{appKey}/templates/{id}/versions/{version}
|
|
6205
|
+
*/
|
|
6206
|
+
async deleteTemplateVersion(id, version) {
|
|
6207
|
+
const url = `${this.baseUrl}/templates/${encodeURIComponent(id)}/versions/${encodeURIComponent(version)}`;
|
|
6208
|
+
try {
|
|
6209
|
+
const res = await import_ky12.default.delete(url, {
|
|
6210
|
+
headers: this.authHeaders(),
|
|
6211
|
+
retry: 0,
|
|
6212
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6213
|
+
});
|
|
6214
|
+
unwrapHeader(await res.json());
|
|
6215
|
+
} catch (err) {
|
|
6216
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6217
|
+
throw toNhnCloudCliError(err);
|
|
6218
|
+
}
|
|
6219
|
+
}
|
|
6220
|
+
/**
|
|
6221
|
+
* workload 를 일시정지한다.
|
|
6222
|
+
* POST /ncs/v1.0/appkeys/{appKey}/workloads/{id}/pause
|
|
6223
|
+
*/
|
|
6224
|
+
async pauseWorkload(id) {
|
|
6225
|
+
const url = `${this.baseUrl}/workloads/${encodeURIComponent(id)}/pause`;
|
|
6226
|
+
try {
|
|
6227
|
+
const res = await import_ky12.default.post(url, {
|
|
6228
|
+
headers: this.authHeaders(),
|
|
6229
|
+
retry: 0,
|
|
6230
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6231
|
+
});
|
|
6232
|
+
unwrapHeader(await res.json());
|
|
6233
|
+
} catch (err) {
|
|
6234
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6235
|
+
throw toNhnCloudCliError(err);
|
|
6236
|
+
}
|
|
6237
|
+
}
|
|
6238
|
+
/**
|
|
6239
|
+
* workload 를 재개한다.
|
|
6240
|
+
* POST /ncs/v1.0/appkeys/{appKey}/workloads/{id}/resume
|
|
6241
|
+
*/
|
|
6242
|
+
async resumeWorkload(id) {
|
|
6243
|
+
const url = `${this.baseUrl}/workloads/${encodeURIComponent(id)}/resume`;
|
|
6244
|
+
try {
|
|
6245
|
+
const res = await import_ky12.default.post(url, {
|
|
6246
|
+
headers: this.authHeaders(),
|
|
6247
|
+
retry: 0,
|
|
6248
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6249
|
+
});
|
|
6250
|
+
unwrapHeader(await res.json());
|
|
6251
|
+
} catch (err) {
|
|
6252
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6253
|
+
throw toNhnCloudCliError(err);
|
|
6254
|
+
}
|
|
6255
|
+
}
|
|
6256
|
+
/**
|
|
6257
|
+
* workload task 를 재시작한다.
|
|
6258
|
+
* POST /ncs/v1.0/appkeys/{appKey}/workloads/{id}/tasks/{taskId}/restart
|
|
6259
|
+
*/
|
|
6260
|
+
async restartWorkloadTask(id, taskId) {
|
|
6261
|
+
const url = `${this.baseUrl}/workloads/${encodeURIComponent(id)}/tasks/${encodeURIComponent(taskId)}/restart`;
|
|
6262
|
+
try {
|
|
6263
|
+
const res = await import_ky12.default.post(url, {
|
|
6264
|
+
headers: this.authHeaders(),
|
|
6265
|
+
retry: 0,
|
|
6266
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6267
|
+
});
|
|
6268
|
+
unwrapHeader(await res.json());
|
|
6269
|
+
} catch (err) {
|
|
6270
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6271
|
+
throw toNhnCloudCliError(err);
|
|
6272
|
+
}
|
|
6273
|
+
}
|
|
6274
|
+
/**
|
|
6275
|
+
* workload 를 생성한다.
|
|
6276
|
+
* POST /ncs/v1.0/appkeys/{appKey}/workloads
|
|
6277
|
+
* 요청 body 는 `--file <json>` 로 읽은 값을 그대로 전달한다(필수값 검증은 API 오류에 위임 — createTemplate 과 동일).
|
|
6278
|
+
* 응답: { header, workload: {...} } — 생성된 workload 전체 객체(id 만 반환하는 축약 응답 아님, docs 예제 실측 확정).
|
|
6279
|
+
*/
|
|
6280
|
+
async createWorkload(body) {
|
|
6281
|
+
const url = `${this.baseUrl}/workloads`;
|
|
6282
|
+
try {
|
|
6283
|
+
const res = await import_ky12.default.post(url, {
|
|
6284
|
+
headers: this.authHeaders(),
|
|
6285
|
+
json: body,
|
|
6286
|
+
retry: 0,
|
|
6287
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6288
|
+
});
|
|
6289
|
+
const resBody = await res.json();
|
|
6290
|
+
unwrapHeader(resBody);
|
|
6291
|
+
if (!isNcsWorkloadDetail(resBody.workload)) {
|
|
6292
|
+
throw new NhnCloudCliError(
|
|
6293
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: workload \uD544\uB4DC\uAC00 \uC5C6\uAC70\uB098 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
6294
|
+
EXIT_API_ERROR
|
|
6295
|
+
);
|
|
6296
|
+
}
|
|
6297
|
+
return resBody.workload;
|
|
6298
|
+
} catch (err) {
|
|
6299
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6300
|
+
throw toNhnCloudCliError(err);
|
|
6301
|
+
}
|
|
6302
|
+
}
|
|
6303
|
+
/**
|
|
6304
|
+
* workload 를 전체 교체한다.
|
|
6305
|
+
* PUT /ncs/v1.0/appkeys/{appKey}/workloads/{id}
|
|
6306
|
+
* 응답: { header, workload: {...} } — createWorkload 와 동일한 전체 객체 응답(docs 예제 실측 확정).
|
|
6307
|
+
*/
|
|
6308
|
+
async updateWorkload(id, body) {
|
|
6309
|
+
const url = `${this.baseUrl}/workloads/${encodeURIComponent(id)}`;
|
|
6310
|
+
try {
|
|
6311
|
+
const res = await import_ky12.default.put(url, {
|
|
6312
|
+
headers: this.authHeaders(),
|
|
6313
|
+
json: body,
|
|
6314
|
+
retry: 0,
|
|
6315
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6316
|
+
});
|
|
6317
|
+
const resBody = await res.json();
|
|
6318
|
+
unwrapHeader(resBody);
|
|
6319
|
+
if (!isNcsWorkloadDetail(resBody.workload)) {
|
|
6320
|
+
throw new NhnCloudCliError(
|
|
6321
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: workload \uD544\uB4DC\uAC00 \uC5C6\uAC70\uB098 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
6322
|
+
EXIT_API_ERROR
|
|
6323
|
+
);
|
|
6324
|
+
}
|
|
6325
|
+
return resBody.workload;
|
|
6326
|
+
} catch (err) {
|
|
6327
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6328
|
+
throw toNhnCloudCliError(err);
|
|
6329
|
+
}
|
|
6330
|
+
}
|
|
6331
|
+
/**
|
|
6332
|
+
* workload 를 부분 변경한다 (JSON Patch 배열, RFC 6902).
|
|
6333
|
+
* PATCH /ncs/v1.0/appkeys/{appKey}/workloads/{id}
|
|
6334
|
+
* Content-Type 이 application/json-patch+json 이어야 한다(docs 확정) — authHeaders() 에 덮어써서 명시 지정.
|
|
6335
|
+
* 응답: { header, workload: {...} } — createWorkload 와 동일한 전체 객체 응답(docs 예제 실측 확정).
|
|
6336
|
+
* redirect/status 분기 불필요 — 공통 봉투 응답(HTTP 200 고정, ADR-006).
|
|
6337
|
+
*/
|
|
6338
|
+
async patchWorkload(id, patch) {
|
|
6339
|
+
const url = `${this.baseUrl}/workloads/${encodeURIComponent(id)}`;
|
|
6340
|
+
try {
|
|
6341
|
+
const res = await import_ky12.default.patch(url, {
|
|
6342
|
+
headers: { ...this.authHeaders(), "Content-Type": "application/json-patch+json" },
|
|
6343
|
+
json: patch,
|
|
6344
|
+
retry: 0,
|
|
6345
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6346
|
+
});
|
|
6347
|
+
const resBody = await res.json();
|
|
6348
|
+
unwrapHeader(resBody);
|
|
6349
|
+
if (!isNcsWorkloadDetail(resBody.workload)) {
|
|
6350
|
+
throw new NhnCloudCliError(
|
|
6351
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: workload \uD544\uB4DC\uAC00 \uC5C6\uAC70\uB098 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
6352
|
+
EXIT_API_ERROR
|
|
6353
|
+
);
|
|
6354
|
+
}
|
|
6355
|
+
return resBody.workload;
|
|
6356
|
+
} catch (err) {
|
|
6357
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6358
|
+
throw toNhnCloudCliError(err);
|
|
6359
|
+
}
|
|
6360
|
+
}
|
|
6361
|
+
/**
|
|
6362
|
+
* workload 가 `Running` 상태에 도달할 때까지 폴링한다 (instance client 의 waitForActive 선례, ADR-011).
|
|
6363
|
+
* 데드라인을 고정해두고 매 반복 남은 시간만큼만 대기해 timeoutMs 를 초과하지 않는다.
|
|
6364
|
+
* 타임아웃 시 마지막으로 조회한 상태를 메시지에 포함해 NhnCloudCliError(EXIT_API_ERROR) 를 던진다.
|
|
6365
|
+
*/
|
|
6366
|
+
async waitForRunning(id, opts) {
|
|
6367
|
+
const intervalMs = opts.intervalMs ?? DEFAULT_WAIT_POLL_INTERVAL_MS;
|
|
6368
|
+
const deadline = Date.now() + opts.timeoutMs;
|
|
6369
|
+
let lastWorkload = null;
|
|
6370
|
+
while (Date.now() < deadline) {
|
|
6371
|
+
const workload = await this.getWorkload(id);
|
|
6372
|
+
lastWorkload = workload;
|
|
6373
|
+
if (workload.status === "Running") {
|
|
6374
|
+
return workload;
|
|
6375
|
+
}
|
|
6376
|
+
const remaining = deadline - Date.now();
|
|
6377
|
+
if (remaining <= 0) break;
|
|
6378
|
+
await new Promise((resolve) => setTimeout(resolve, Math.min(intervalMs, remaining)));
|
|
6379
|
+
}
|
|
6380
|
+
const lastStatus = lastWorkload ? lastWorkload.status : "unknown";
|
|
6381
|
+
throw new NhnCloudCliError(
|
|
6382
|
+
`NCS workload ${id} \uAC00 Running \uC0C1\uD0DC\uAC00 \uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4 (\uB9C8\uC9C0\uB9C9 \uC0C1\uD0DC: ${lastStatus}). --wait \uD0C0\uC784\uC544\uC6C3(${Math.round(opts.timeoutMs / 1e3)}\uCD08) \uCD08\uACFC.`,
|
|
6383
|
+
EXIT_API_ERROR
|
|
6384
|
+
);
|
|
6385
|
+
}
|
|
6386
|
+
/**
|
|
6387
|
+
* workload 를 삭제한다.
|
|
6388
|
+
* DELETE /ncs/v1.0/appkeys/{appKey}/workloads/{id}
|
|
6389
|
+
*/
|
|
6390
|
+
async deleteWorkload(id) {
|
|
6391
|
+
const url = `${this.baseUrl}/workloads/${encodeURIComponent(id)}`;
|
|
6392
|
+
try {
|
|
6393
|
+
const res = await import_ky12.default.delete(url, {
|
|
6394
|
+
headers: this.authHeaders(),
|
|
6395
|
+
retry: 0,
|
|
6396
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6397
|
+
});
|
|
6398
|
+
unwrapHeader(await res.json());
|
|
6399
|
+
} catch (err) {
|
|
6400
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6401
|
+
throw toNhnCloudCliError(err);
|
|
6402
|
+
}
|
|
6403
|
+
}
|
|
6404
|
+
/**
|
|
6405
|
+
* 악성코드 검사 설정을 조회한다.
|
|
6406
|
+
* GET /ncs/v1.0/appkeys/{appKey}/malware/config (appkey-scoped, docs 예제 실측 확정 — 계정 레벨 아님)
|
|
6407
|
+
* 응답: { header, enabled: true|false } — named 필드 없이 header 와 나란히 flat 필드(docs 예제 실측 확정).
|
|
6408
|
+
*/
|
|
6409
|
+
async getMalwareConfig() {
|
|
6410
|
+
const url = `${this.baseUrl}/malware/config`;
|
|
6411
|
+
try {
|
|
6412
|
+
const res = await import_ky12.default.get(url, {
|
|
6413
|
+
headers: this.authHeaders(),
|
|
6414
|
+
retry: 0,
|
|
6415
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6416
|
+
});
|
|
6417
|
+
const body = await res.json();
|
|
6418
|
+
unwrapHeader(body);
|
|
6419
|
+
if (!isNcsMalwareConfig(body)) {
|
|
6420
|
+
throw new NhnCloudCliError(
|
|
6421
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: enabled \uD544\uB4DC\uAC00 \uC5C6\uAC70\uB098 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
6422
|
+
EXIT_API_ERROR
|
|
6423
|
+
);
|
|
6424
|
+
}
|
|
6425
|
+
return { enabled: body.enabled };
|
|
6426
|
+
} catch (err) {
|
|
6427
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6428
|
+
throw toNhnCloudCliError(err);
|
|
6429
|
+
}
|
|
6430
|
+
}
|
|
6431
|
+
/**
|
|
6432
|
+
* 악성코드 검사 설정을 변경한다.
|
|
6433
|
+
* POST /ncs/v1.0/appkeys/{appKey}/malware/config (method 는 POST — docs 예제 실측 확정, PUT 아님)
|
|
6434
|
+
* 요청 body: { enabled: boolean } — docs 필드 표기는 "String" 이나 예제 JSON 이 quote 없는 boolean
|
|
6435
|
+
* 리터럴이라 실제 wire 타입은 boolean(malware.enabled 실측 확정, ADR-020 트레이드오프 절 참조).
|
|
6436
|
+
* 응답: { header, enabled: true|false } — getMalwareConfig 와 동일한 flat 패턴.
|
|
6437
|
+
*/
|
|
6438
|
+
async setMalwareConfig(enabled) {
|
|
6439
|
+
const url = `${this.baseUrl}/malware/config`;
|
|
6440
|
+
try {
|
|
6441
|
+
const res = await import_ky12.default.post(url, {
|
|
6442
|
+
headers: this.authHeaders(),
|
|
6443
|
+
json: { enabled },
|
|
6444
|
+
retry: 0,
|
|
6445
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6446
|
+
});
|
|
6447
|
+
const body = await res.json();
|
|
6448
|
+
unwrapHeader(body);
|
|
6449
|
+
if (!isNcsMalwareConfig(body)) {
|
|
6450
|
+
throw new NhnCloudCliError(
|
|
6451
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: enabled \uD544\uB4DC\uAC00 \uC5C6\uAC70\uB098 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
6452
|
+
EXIT_API_ERROR
|
|
6453
|
+
);
|
|
6454
|
+
}
|
|
6455
|
+
return { enabled: body.enabled };
|
|
6456
|
+
} catch (err) {
|
|
6457
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6458
|
+
throw toNhnCloudCliError(err);
|
|
6459
|
+
}
|
|
6460
|
+
}
|
|
6461
|
+
/**
|
|
6462
|
+
* workload 실행 히스토리의 악성코드 검사 결과를 조회한다.
|
|
6463
|
+
* GET /ncs/v1.0/appkeys/{appKey}/workloads/{workloadId}/history/{historyId}/malware
|
|
6464
|
+
* 응답: { header, scannedAt, infectedFiles, scannedDirectories, scannedFiles, reports: [...] } —
|
|
6465
|
+
* named 필드로 감싸지 않고 header 와 나란히 flat 필드(docs 예제 실측 확정, malware config 와 동일 패턴).
|
|
6466
|
+
* 모든 top-level 필드가 docs 상 optional(미검사 워크로드는 누락 가능) — 존재하면 그대로 통과시킨다.
|
|
6467
|
+
*/
|
|
6468
|
+
async getMalwareResult(workloadId, historyId) {
|
|
6469
|
+
const url = `${this.baseUrl}/workloads/${encodeURIComponent(workloadId)}/history/${encodeURIComponent(historyId)}/malware`;
|
|
6470
|
+
try {
|
|
6471
|
+
const res = await import_ky12.default.get(url, {
|
|
6472
|
+
headers: this.authHeaders(),
|
|
6473
|
+
retry: 0,
|
|
6474
|
+
timeout: DEFAULT_TIMEOUT_MS8
|
|
6475
|
+
});
|
|
6476
|
+
const body = await res.json();
|
|
6477
|
+
unwrapHeader(body);
|
|
6478
|
+
if (body.reports !== void 0 && !Array.isArray(body.reports)) {
|
|
6479
|
+
throw new NhnCloudCliError(
|
|
6480
|
+
"NCS API \uC751\uB2F5 \uD615\uC2DD \uC624\uB958: reports \uAC00 \uBC30\uC5F4\uC774 \uC544\uB2D9\uB2C8\uB2E4.",
|
|
6481
|
+
EXIT_API_ERROR
|
|
6482
|
+
);
|
|
6483
|
+
}
|
|
6484
|
+
return {
|
|
6485
|
+
scannedAt: body.scannedAt,
|
|
6486
|
+
infectedFiles: body.infectedFiles,
|
|
6487
|
+
scannedDirectories: body.scannedDirectories,
|
|
6488
|
+
scannedFiles: body.scannedFiles,
|
|
6489
|
+
reports: body.reports?.filter(isNcsMalwareReport) ?? []
|
|
6490
|
+
};
|
|
6491
|
+
} catch (err) {
|
|
6492
|
+
if (err instanceof NhnCloudCliError) throw err;
|
|
6493
|
+
throw toNhnCloudCliError(err);
|
|
6494
|
+
}
|
|
6495
|
+
}
|
|
6496
|
+
};
|
|
6497
|
+
|
|
6498
|
+
// src/commands/ncs/helpers.ts
|
|
6499
|
+
var MAX_JSON_PAYLOAD_BYTES = 1e6;
|
|
6500
|
+
async function resolveNcsAppKey(profileName, appKeyOpt) {
|
|
6501
|
+
if (appKeyOpt) return appKeyOpt;
|
|
6502
|
+
let cred;
|
|
6503
|
+
try {
|
|
6504
|
+
cred = await getServiceCredential("ncs", profileName);
|
|
6505
|
+
} catch (err) {
|
|
6506
|
+
if (!(err instanceof NhnCloudCliError) || err.exitCode !== EXIT_CONFIG_ERROR) {
|
|
6507
|
+
throw err;
|
|
6508
|
+
}
|
|
6509
|
+
}
|
|
6510
|
+
if (!cred?.appkey) {
|
|
6511
|
+
throw new NhnCloudCliError(
|
|
6512
|
+
"NCS appKey \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. --app-key \uC635\uC158\uC73C\uB85C \uC9C0\uC815\uD558\uAC70\uB098\n~/.nhncloud/credentials.json \uC758 profiles.<profile>.ncs.appkey \uB97C \uC9C1\uC811 \uCD94\uAC00\uD558\uC138\uC694.\n(nhncloud configure \uB294 \uC544\uC9C1 ncs \uB97C \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.)",
|
|
6513
|
+
EXIT_CONFIG_ERROR
|
|
6514
|
+
);
|
|
6515
|
+
}
|
|
6516
|
+
return cred.appkey;
|
|
6517
|
+
}
|
|
6518
|
+
async function resolveNcsClient(opts) {
|
|
6519
|
+
const profileName = await resolveProfileName(opts.profile);
|
|
6520
|
+
const uak = await getUserAccessKey(profileName);
|
|
6521
|
+
const accessToken = await getAccessToken(profileName, uak.id, uak.secret);
|
|
6522
|
+
const appKey = await resolveNcsAppKey(profileName, opts.appKey);
|
|
6523
|
+
const region = opts.region ?? "kr1";
|
|
6524
|
+
return { client: new NcsClient(accessToken, region, appKey), profileName };
|
|
6525
|
+
}
|
|
6526
|
+
function readJsonPayload(filePath) {
|
|
6527
|
+
let stat;
|
|
6528
|
+
try {
|
|
6529
|
+
stat = (0, import_node_fs7.statSync)(filePath);
|
|
6530
|
+
} catch (err) {
|
|
6531
|
+
const reason = err.code ?? (err instanceof Error ? err.message : String(err));
|
|
6532
|
+
throw new NhnCloudCliError(
|
|
6533
|
+
`\uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${filePath} (${reason})`,
|
|
6534
|
+
EXIT_PARAM_ERROR
|
|
6535
|
+
);
|
|
6536
|
+
}
|
|
6537
|
+
if (!stat.isFile()) {
|
|
6538
|
+
throw new NhnCloudCliError(`--file \uC774 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4: ${filePath}`, EXIT_PARAM_ERROR);
|
|
6539
|
+
}
|
|
6540
|
+
if (stat.size > MAX_JSON_PAYLOAD_BYTES) {
|
|
6541
|
+
throw new NhnCloudCliError(
|
|
6542
|
+
`--file \uC774 \uB108\uBB34 \uD07D\uB2C8\uB2E4 (${stat.size} \uBC14\uC774\uD2B8). JSON spec \uD55C\uB3C4 ${MAX_JSON_PAYLOAD_BYTES} \uBC14\uC774\uD2B8.`,
|
|
6543
|
+
EXIT_PARAM_ERROR
|
|
6544
|
+
);
|
|
6545
|
+
}
|
|
6546
|
+
const raw = (0, import_node_fs7.readFileSync)(filePath, "utf-8");
|
|
6547
|
+
try {
|
|
6548
|
+
return JSON.parse(raw);
|
|
6549
|
+
} catch (err) {
|
|
6550
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
6551
|
+
throw new NhnCloudCliError(
|
|
6552
|
+
`JSON \uD30C\uC2F1\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4: ${filePath} (${detail})`,
|
|
6553
|
+
EXIT_PARAM_ERROR
|
|
6554
|
+
);
|
|
6555
|
+
}
|
|
6556
|
+
}
|
|
6557
|
+
function requireNonEmpty(value, label) {
|
|
6558
|
+
if (!value.trim()) {
|
|
6559
|
+
throw new NhnCloudCliError(`${label} \uC778\uC218\uAC00 \uBE44\uC5B4\uC788\uC2B5\uB2C8\uB2E4.`, EXIT_PARAM_ERROR);
|
|
6560
|
+
}
|
|
6561
|
+
}
|
|
6562
|
+
async function confirmDestructive(message, yes) {
|
|
6563
|
+
const isTTY = process.stdin.isTTY;
|
|
6564
|
+
if (!isTTY && !yes) {
|
|
6565
|
+
throw new NhnCloudCliError(
|
|
6566
|
+
"\uBE44\uB300\uD654\uD615 \uD658\uACBD\uC5D0\uC11C\uB294 --yes \uD50C\uB798\uADF8\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
6567
|
+
EXIT_PARAM_ERROR
|
|
6568
|
+
);
|
|
6569
|
+
}
|
|
6570
|
+
if (isTTY && !yes) {
|
|
6571
|
+
const { confirm } = await import("@inquirer/prompts");
|
|
6572
|
+
return confirm({ message, default: false });
|
|
6573
|
+
}
|
|
6574
|
+
return true;
|
|
6575
|
+
}
|
|
6576
|
+
|
|
6577
|
+
// src/commands/ncs/template.ts
|
|
6578
|
+
var listCommand8 = new import_commander43.Command("list").description("NCS \uC124\uACC4\uB3C4(template) \uBAA9\uB85D\uC744 \uC870\uD68C\uD55C\uB2E4").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").option("--page <page>", "\uC870\uD68C\uD560 page \uBC88\uD638").option("--size <size>", "page \uB2F9 \uD56D\uBAA9 \uC218 (\uAE30\uBCF8: API \uAE30\uBCF8\uAC12 10)").action(async (_opts, cmd) => {
|
|
6579
|
+
const opts = cmd.optsWithGlobals();
|
|
6580
|
+
const { client } = await resolveNcsClient(opts);
|
|
6581
|
+
startSpinner("NCS \uC124\uACC4\uB3C4 \uBAA9\uB85D \uC870\uD68C \uC911...");
|
|
6582
|
+
let totalCount;
|
|
6583
|
+
let templates;
|
|
6584
|
+
try {
|
|
6585
|
+
const result = await client.listTemplates({
|
|
6586
|
+
page: parsePositiveIntegerOption(opts.page, "--page"),
|
|
6587
|
+
size: parsePositiveIntegerOption(opts.size, "--size")
|
|
6588
|
+
});
|
|
6589
|
+
totalCount = result.totalCount;
|
|
6590
|
+
templates = result.templates;
|
|
6591
|
+
} catch (err) {
|
|
6592
|
+
stopSpinner(false);
|
|
6593
|
+
throw err;
|
|
6594
|
+
}
|
|
6595
|
+
stopSpinner(true);
|
|
6596
|
+
output(opts, {
|
|
6597
|
+
headers: ["id", "name", "version", "versionCount", "workloadCount"],
|
|
6598
|
+
rows: templates.map((t) => [
|
|
6599
|
+
t.id,
|
|
6600
|
+
t.name,
|
|
6601
|
+
t.version ?? "",
|
|
6602
|
+
String(t.versionCount ?? ""),
|
|
6603
|
+
String(t.workloadCount ?? "")
|
|
6604
|
+
]),
|
|
6605
|
+
raw: { totalCount, templates },
|
|
6606
|
+
ids: templates.map((t) => t.id)
|
|
6607
|
+
});
|
|
6608
|
+
});
|
|
6609
|
+
var getCommand6 = new import_commander43.Command("get").description("NCS \uC124\uACC4\uB3C4(template) \uB2E8\uAC74\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<id>", "template ID").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (id, _opts, cmd) => {
|
|
6610
|
+
const opts = cmd.optsWithGlobals();
|
|
6611
|
+
requireNonEmpty(id, "id");
|
|
6612
|
+
const { client } = await resolveNcsClient(opts);
|
|
6613
|
+
startSpinner(`NCS \uC124\uACC4\uB3C4 "${id}" \uC870\uD68C \uC911...`);
|
|
6614
|
+
let template;
|
|
6615
|
+
try {
|
|
6616
|
+
template = await client.getTemplate(id);
|
|
6617
|
+
} catch (err) {
|
|
6618
|
+
stopSpinner(false);
|
|
6619
|
+
throw err;
|
|
6620
|
+
}
|
|
6621
|
+
stopSpinner(true);
|
|
6622
|
+
output(opts, {
|
|
6623
|
+
headers: ["id", "name", "version", "versionCount", "workloadCount"],
|
|
6624
|
+
rows: [
|
|
6625
|
+
[
|
|
6626
|
+
template.id,
|
|
6627
|
+
template.name,
|
|
6628
|
+
template.version ?? "",
|
|
6629
|
+
String(template.versionCount ?? ""),
|
|
6630
|
+
String(template.workloadCount ?? "")
|
|
6631
|
+
]
|
|
6632
|
+
],
|
|
6633
|
+
raw: template,
|
|
6634
|
+
ids: [template.id]
|
|
6635
|
+
});
|
|
6636
|
+
});
|
|
6637
|
+
var createCommand6 = new import_commander43.Command("create").description("NCS \uC124\uACC4\uB3C4(template) \uB97C \uC0DD\uC131\uD55C\uB2E4 (--file \uB85C JSON spec \uC804\uB2EC)").requiredOption("--file <path>", "template \uC0DD\uC131 spec \uC774 \uB2F4\uAE34 JSON \uD30C\uC77C \uACBD\uB85C").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (_opts, cmd) => {
|
|
6638
|
+
const opts = cmd.optsWithGlobals();
|
|
6639
|
+
const payload = readJsonPayload(opts.file);
|
|
6640
|
+
const { client } = await resolveNcsClient(opts);
|
|
6641
|
+
startSpinner("NCS \uC124\uACC4\uB3C4 \uC0DD\uC131 \uC911...");
|
|
6642
|
+
let template;
|
|
6643
|
+
try {
|
|
6644
|
+
template = await client.createTemplate(payload);
|
|
6645
|
+
} catch (err) {
|
|
6646
|
+
stopSpinner(false);
|
|
6647
|
+
throw err;
|
|
6648
|
+
}
|
|
6649
|
+
stopSpinner(true);
|
|
6650
|
+
output(opts, {
|
|
6651
|
+
headers: ["id", "name", "version", "versionCount", "workloadCount"],
|
|
6652
|
+
rows: [
|
|
6653
|
+
[
|
|
6654
|
+
template.id,
|
|
6655
|
+
template.name,
|
|
6656
|
+
template.version ?? "",
|
|
6657
|
+
String(template.versionCount ?? ""),
|
|
6658
|
+
String(template.workloadCount ?? "")
|
|
6659
|
+
]
|
|
6660
|
+
],
|
|
6661
|
+
raw: template,
|
|
6662
|
+
ids: [template.id]
|
|
6663
|
+
});
|
|
6664
|
+
});
|
|
6665
|
+
var deleteCommand5 = new import_commander43.Command("delete").description("NCS \uC124\uACC4\uB3C4(template) \uB97C \uC0AD\uC81C\uD55C\uB2E4").argument("<id>", "template ID").option("--yes", "\uD655\uC778 \uD504\uB86C\uD504\uD2B8 \uC0DD\uB7B5 (CI/\uBE44\uB300\uD654\uD615 \uD544\uC218)").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (id, _opts, cmd) => {
|
|
6666
|
+
const opts = cmd.optsWithGlobals();
|
|
6667
|
+
requireNonEmpty(id, "id");
|
|
6668
|
+
const ok = await confirmDestructive(`NCS \uC124\uACC4\uB3C4 "${id}" \uB97C \uC0AD\uC81C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?`, opts.yes);
|
|
6669
|
+
if (!ok) {
|
|
6670
|
+
process.stderr.write(import_chalk14.default.yellow("\uC0AD\uC81C\uAC00 \uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\n"));
|
|
6671
|
+
return;
|
|
6672
|
+
}
|
|
6673
|
+
const { client } = await resolveNcsClient(opts);
|
|
6674
|
+
startSpinner(`NCS \uC124\uACC4\uB3C4 \uC0AD\uC81C \uC911... (id: ${id})`);
|
|
6675
|
+
try {
|
|
6676
|
+
await client.deleteTemplate(id);
|
|
6677
|
+
} catch (err) {
|
|
6678
|
+
stopSpinner(false);
|
|
6679
|
+
throw err;
|
|
6680
|
+
}
|
|
6681
|
+
stopSpinner(true);
|
|
6682
|
+
process.stderr.write(import_chalk14.default.green(`\u2713 NCS \uC124\uACC4\uB3C4 "${id}" \uAC00 \uC0AD\uC81C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
|
|
6683
|
+
`));
|
|
6684
|
+
});
|
|
6685
|
+
var versionListCommand = new import_commander43.Command("list").description("NCS \uC124\uACC4\uB3C4(template) \uC758 \uBC84\uC804 \uBAA9\uB85D\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<id>", "template ID").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").option("--q <query>", "\uAC80\uC0C9\uC5B4").option("--sort <sort>", "\uC815\uB82C \uC870\uAC74").option("--page <page>", "\uC870\uD68C\uD560 page \uBC88\uD638").option("--size <size>", "page \uB2F9 \uD56D\uBAA9 \uC218 (\uAE30\uBCF8: API \uAE30\uBCF8\uAC12 10)").action(async (id, _opts, cmd) => {
|
|
6686
|
+
const opts = cmd.optsWithGlobals();
|
|
6687
|
+
requireNonEmpty(id, "id");
|
|
6688
|
+
const { client } = await resolveNcsClient(opts);
|
|
6689
|
+
startSpinner(`NCS \uC124\uACC4\uB3C4 "${id}" \uBC84\uC804 \uBAA9\uB85D \uC870\uD68C \uC911...`);
|
|
6690
|
+
let totalCount;
|
|
6691
|
+
let versions;
|
|
6692
|
+
try {
|
|
6693
|
+
const result = await client.listTemplateVersions(id, {
|
|
6694
|
+
q: opts.q,
|
|
6695
|
+
sort: opts.sort,
|
|
6696
|
+
page: parsePositiveIntegerOption(opts.page, "--page"),
|
|
6697
|
+
size: parsePositiveIntegerOption(opts.size, "--size")
|
|
6698
|
+
});
|
|
6699
|
+
totalCount = result.totalCount;
|
|
6700
|
+
versions = result.versions;
|
|
6701
|
+
} catch (err) {
|
|
6702
|
+
stopSpinner(false);
|
|
6703
|
+
throw err;
|
|
6704
|
+
}
|
|
6705
|
+
stopSpinner(true);
|
|
6706
|
+
output(opts, {
|
|
6707
|
+
headers: ["id", "version", "workloadCount", "createdAt"],
|
|
6708
|
+
rows: versions.map((v) => [
|
|
6709
|
+
v.id,
|
|
6710
|
+
v.version,
|
|
6711
|
+
String(v.workloadCount ?? ""),
|
|
6712
|
+
v.createdAt ?? ""
|
|
6713
|
+
]),
|
|
6714
|
+
raw: { totalCount, versions },
|
|
6715
|
+
ids: versions.map((v) => v.id)
|
|
6716
|
+
});
|
|
6717
|
+
});
|
|
6718
|
+
var versionGetCommand = new import_commander43.Command("get").description("NCS \uC124\uACC4\uB3C4(template) \uBC84\uC804 \uB2E8\uAC74\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<id>", "template ID").argument("<version>", "\uBC84\uC804 \uAC12").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (id, version, _opts, cmd) => {
|
|
6719
|
+
const opts = cmd.optsWithGlobals();
|
|
6720
|
+
requireNonEmpty(id, "id");
|
|
6721
|
+
requireNonEmpty(version, "version");
|
|
6722
|
+
const { client } = await resolveNcsClient(opts);
|
|
6723
|
+
startSpinner(`NCS \uC124\uACC4\uB3C4 "${id}" \uBC84\uC804 "${version}" \uC870\uD68C \uC911...`);
|
|
6724
|
+
let detail;
|
|
6725
|
+
try {
|
|
6726
|
+
detail = await client.getTemplateVersion(id, version);
|
|
6727
|
+
} catch (err) {
|
|
6728
|
+
stopSpinner(false);
|
|
6729
|
+
throw err;
|
|
6730
|
+
}
|
|
6731
|
+
stopSpinner(true);
|
|
6732
|
+
output(opts, {
|
|
6733
|
+
headers: ["id", "version", "workloadCount", "createdAt"],
|
|
6734
|
+
rows: [[detail.id, detail.version, String(detail.workloadCount ?? ""), detail.createdAt ?? ""]],
|
|
6735
|
+
raw: detail,
|
|
6736
|
+
ids: [detail.id]
|
|
6737
|
+
});
|
|
6738
|
+
});
|
|
6739
|
+
var versionCreateCommand = new import_commander43.Command("create").description("NCS \uC124\uACC4\uB3C4(template) \uC758 \uC0C8 \uBC84\uC804\uC744 \uC0DD\uC131\uD55C\uB2E4 (--file \uB85C JSON spec \uC804\uB2EC, sourceVersion \uD544\uC218)").argument("<id>", "template ID").requiredOption("--file <path>", "\uBC84\uC804 \uC0DD\uC131 spec \uC774 \uB2F4\uAE34 JSON \uD30C\uC77C \uACBD\uB85C (sourceVersion \uD544\uB4DC \uD544\uC218)").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (id, _opts, cmd) => {
|
|
6740
|
+
const opts = cmd.optsWithGlobals();
|
|
6741
|
+
requireNonEmpty(id, "id");
|
|
6742
|
+
const payload = readJsonPayload(opts.file);
|
|
6743
|
+
const { client } = await resolveNcsClient(opts);
|
|
6744
|
+
startSpinner(`NCS \uC124\uACC4\uB3C4 "${id}" \uBC84\uC804 \uC0DD\uC131 \uC911...`);
|
|
6745
|
+
let version;
|
|
6746
|
+
try {
|
|
6747
|
+
version = await client.createTemplateVersion(id, payload);
|
|
6748
|
+
} catch (err) {
|
|
6749
|
+
stopSpinner(false);
|
|
6750
|
+
throw err;
|
|
6751
|
+
}
|
|
6752
|
+
stopSpinner(true);
|
|
6753
|
+
output(opts, {
|
|
6754
|
+
headers: ["id", "version", "workloadCount", "createdAt"],
|
|
6755
|
+
rows: [[version.id, version.version, String(version.workloadCount ?? ""), version.createdAt ?? ""]],
|
|
6756
|
+
raw: version,
|
|
6757
|
+
ids: [version.id]
|
|
6758
|
+
});
|
|
6759
|
+
});
|
|
6760
|
+
var versionDeleteCommand = new import_commander43.Command("delete").description("NCS \uC124\uACC4\uB3C4(template) \uBC84\uC804\uC744 \uC0AD\uC81C\uD55C\uB2E4").argument("<id>", "template ID").argument("<version>", "\uBC84\uC804 \uAC12").option("--yes", "\uD655\uC778 \uD504\uB86C\uD504\uD2B8 \uC0DD\uB7B5 (CI/\uBE44\uB300\uD654\uD615 \uD544\uC218)").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (id, version, _opts, cmd) => {
|
|
6761
|
+
const opts = cmd.optsWithGlobals();
|
|
6762
|
+
requireNonEmpty(id, "id");
|
|
6763
|
+
requireNonEmpty(version, "version");
|
|
6764
|
+
const ok = await confirmDestructive(
|
|
6765
|
+
`NCS \uC124\uACC4\uB3C4 "${id}" \uBC84\uC804 "${version}" \uC744 \uC0AD\uC81C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?`,
|
|
6766
|
+
opts.yes
|
|
6767
|
+
);
|
|
6768
|
+
if (!ok) {
|
|
6769
|
+
process.stderr.write(import_chalk14.default.yellow("\uC0AD\uC81C\uAC00 \uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\n"));
|
|
6770
|
+
return;
|
|
6771
|
+
}
|
|
6772
|
+
const { client } = await resolveNcsClient(opts);
|
|
6773
|
+
startSpinner(`NCS \uC124\uACC4\uB3C4 "${id}" \uBC84\uC804 "${version}" \uC0AD\uC81C \uC911...`);
|
|
6774
|
+
try {
|
|
6775
|
+
await client.deleteTemplateVersion(id, version);
|
|
6776
|
+
} catch (err) {
|
|
6777
|
+
stopSpinner(false);
|
|
6778
|
+
throw err;
|
|
6779
|
+
}
|
|
6780
|
+
stopSpinner(true);
|
|
6781
|
+
process.stderr.write(
|
|
6782
|
+
import_chalk14.default.green(`\u2713 NCS \uC124\uACC4\uB3C4 "${id}" \uBC84\uC804 "${version}" \uC774 \uC0AD\uC81C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
|
|
6783
|
+
`)
|
|
6784
|
+
);
|
|
6785
|
+
});
|
|
6786
|
+
var versionCommand = new import_commander43.Command("version").description("NCS \uC124\uACC4\uB3C4(template) \uBC84\uC804 \uAD00\uB9AC").addCommand(versionListCommand).addCommand(versionGetCommand).addCommand(versionCreateCommand).addCommand(versionDeleteCommand);
|
|
6787
|
+
var templateCommand = new import_commander43.Command("template").description("NCS \uC124\uACC4\uB3C4(template) \uAD00\uB9AC").addCommand(listCommand8).addCommand(getCommand6).addCommand(createCommand6).addCommand(deleteCommand5).addCommand(versionCommand);
|
|
6788
|
+
|
|
6789
|
+
// src/commands/ncs/workload.ts
|
|
6790
|
+
var import_commander44 = require("commander");
|
|
6791
|
+
var import_chalk15 = __toESM(require("chalk"));
|
|
6792
|
+
function workloadRows(w) {
|
|
6793
|
+
return [
|
|
6794
|
+
[
|
|
6795
|
+
w.id,
|
|
6796
|
+
w.name,
|
|
6797
|
+
w.type ?? "",
|
|
6798
|
+
w.status,
|
|
6799
|
+
String(w.desired ?? ""),
|
|
6800
|
+
String(w.available ?? "")
|
|
6801
|
+
]
|
|
6802
|
+
];
|
|
6803
|
+
}
|
|
6804
|
+
var WORKLOAD_HEADERS = ["id", "name", "type", "status", "desired", "available"];
|
|
6805
|
+
var listCommand9 = new import_commander44.Command("list").description("NCS workload(\uB7F0\uD0C0\uC784 \uC2E4\uD589) \uBAA9\uB85D\uC744 \uC870\uD68C\uD55C\uB2E4").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").option("--q <query>", "\uC6CC\uD06C\uB85C\uB4DC \uC774\uB984\xB7\uD15C\uD50C\uB9BF ID\xB7\uD15C\uD50C\uB9BF \uBC84\uC804\uC73C\uB85C \uD544\uD130\uB9C1").option("--page <page>", "\uC870\uD68C\uD560 page \uBC88\uD638").option("--size <size>", "page \uB2F9 \uD56D\uBAA9 \uC218 (\uAE30\uBCF8: API \uAE30\uBCF8\uAC12 10)").action(async (_opts, cmd) => {
|
|
6806
|
+
const opts = cmd.optsWithGlobals();
|
|
6807
|
+
const { client } = await resolveNcsClient(opts);
|
|
6808
|
+
startSpinner("NCS workload \uBAA9\uB85D \uC870\uD68C \uC911...");
|
|
6809
|
+
let totalCount;
|
|
6810
|
+
let workloads;
|
|
6811
|
+
try {
|
|
6812
|
+
const result = await client.listWorkloads({
|
|
6813
|
+
q: opts.q,
|
|
6814
|
+
page: parsePositiveIntegerOption(opts.page, "--page"),
|
|
6815
|
+
size: parsePositiveIntegerOption(opts.size, "--size")
|
|
6816
|
+
});
|
|
6817
|
+
totalCount = result.totalCount;
|
|
6818
|
+
workloads = result.workloads;
|
|
6819
|
+
} catch (err) {
|
|
6820
|
+
stopSpinner(false);
|
|
6821
|
+
throw err;
|
|
6822
|
+
}
|
|
6823
|
+
stopSpinner(true);
|
|
6824
|
+
output(opts, {
|
|
6825
|
+
headers: ["id", "name", "type", "status", "desired", "available"],
|
|
6826
|
+
rows: workloads.map((w) => [
|
|
6827
|
+
w.id,
|
|
6828
|
+
w.name,
|
|
6829
|
+
w.type ?? "",
|
|
6830
|
+
w.status,
|
|
6831
|
+
String(w.desired ?? ""),
|
|
6832
|
+
String(w.available ?? "")
|
|
6833
|
+
]),
|
|
6834
|
+
raw: { totalCount, workloads },
|
|
6835
|
+
ids: workloads.map((w) => w.id)
|
|
6836
|
+
});
|
|
6837
|
+
});
|
|
6838
|
+
var getCommand7 = new import_commander44.Command("get").description("NCS workload \uB2E8\uAC74\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<id>", "workload ID").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (id, _opts, cmd) => {
|
|
6839
|
+
const opts = cmd.optsWithGlobals();
|
|
6840
|
+
requireNonEmpty(id, "id");
|
|
6841
|
+
const { client } = await resolveNcsClient(opts);
|
|
6842
|
+
startSpinner(`NCS workload "${id}" \uC870\uD68C \uC911...`);
|
|
6843
|
+
let workload;
|
|
6844
|
+
try {
|
|
6845
|
+
workload = await client.getWorkload(id);
|
|
6846
|
+
} catch (err) {
|
|
6847
|
+
stopSpinner(false);
|
|
6848
|
+
throw err;
|
|
6849
|
+
}
|
|
6850
|
+
stopSpinner(true);
|
|
6851
|
+
output(opts, {
|
|
6852
|
+
headers: ["id", "name", "type", "status", "desired", "available", "tasks"],
|
|
6853
|
+
rows: [
|
|
6854
|
+
[
|
|
6855
|
+
workload.id,
|
|
6856
|
+
workload.name,
|
|
6857
|
+
workload.type ?? "",
|
|
6858
|
+
workload.status,
|
|
6859
|
+
String(workload.desired ?? ""),
|
|
6860
|
+
String(workload.available ?? ""),
|
|
6861
|
+
String(workload.tasks?.length ?? 0)
|
|
6862
|
+
]
|
|
6863
|
+
],
|
|
6864
|
+
raw: workload,
|
|
6865
|
+
ids: [workload.id]
|
|
6866
|
+
});
|
|
6867
|
+
});
|
|
6868
|
+
var logsCommand = new import_commander44.Command("logs").description("NCS workload task \uC758 \uCEE8\uD14C\uC774\uB108 \uB85C\uADF8\uB97C \uC870\uD68C\uD55C\uB2E4").argument("<id>", "workload ID").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").option("--task <taskId>", "task ID (\uD544\uC218)").option("--container <name>", "\uCEE8\uD14C\uC774\uB108 \uC774\uB984 (\uD544\uC218)").option("--from <time>", "\uB85C\uADF8 \uC2DC\uC791 \uC2DC\uAC04 (\uAE30\uBCF8: \uD604\uC7AC\uB85C\uBD80\uD130 5\uBD84 \uC804)").option("--to <time>", "\uB85C\uADF8 \uC885\uB8CC \uC2DC\uAC04 (\uAE30\uBCF8: \uD604\uC7AC \uC2DC\uAC04)").option("--page <page>", "\uC870\uD68C\uD560 page \uBC88\uD638").option("--size <size>", "page \uB2F9 \uD56D\uBAA9 \uC218 (\uAE30\uBCF8: API \uAE30\uBCF8\uAC12 100)").action(async (id, _opts, cmd) => {
|
|
6869
|
+
const opts = cmd.optsWithGlobals();
|
|
6870
|
+
requireNonEmpty(id, "id");
|
|
6871
|
+
if (!opts.task || !opts.task.trim()) {
|
|
6872
|
+
throw new NhnCloudCliError(
|
|
6873
|
+
"--task \uC635\uC158\uC774 \uBE44\uC5B4\uC788\uC2B5\uB2C8\uB2E4. task ID \uB97C \uC9C0\uC815\uD558\uC138\uC694.",
|
|
6874
|
+
EXIT_PARAM_ERROR
|
|
6875
|
+
);
|
|
6876
|
+
}
|
|
6877
|
+
if (!opts.container || !opts.container.trim()) {
|
|
6878
|
+
throw new NhnCloudCliError(
|
|
6879
|
+
"--container \uC635\uC158\uC774 \uBE44\uC5B4\uC788\uC2B5\uB2C8\uB2E4. \uCEE8\uD14C\uC774\uB108 \uC774\uB984\uC744 \uC9C0\uC815\uD558\uC138\uC694.",
|
|
6880
|
+
EXIT_PARAM_ERROR
|
|
6881
|
+
);
|
|
6882
|
+
}
|
|
6883
|
+
const { client } = await resolveNcsClient(opts);
|
|
6884
|
+
startSpinner(`NCS workload "${id}" task "${opts.task}" \uB85C\uADF8 \uC870\uD68C \uC911...`);
|
|
6885
|
+
let logs;
|
|
6886
|
+
try {
|
|
6887
|
+
const result = await client.getWorkloadLogs(id, opts.task, {
|
|
6888
|
+
container: opts.container,
|
|
6889
|
+
from: opts.from,
|
|
6890
|
+
to: opts.to,
|
|
6891
|
+
page: parsePositiveIntegerOption(opts.page, "--page"),
|
|
6892
|
+
size: parsePositiveIntegerOption(opts.size, "--size")
|
|
6893
|
+
});
|
|
6894
|
+
logs = result.logs;
|
|
6895
|
+
} catch (err) {
|
|
6896
|
+
stopSpinner(false);
|
|
6897
|
+
throw err;
|
|
6898
|
+
}
|
|
6899
|
+
stopSpinner(true);
|
|
6900
|
+
output(opts, {
|
|
6901
|
+
headers: ["time", "log"],
|
|
6902
|
+
rows: logs.map((l) => [l.time, l.log]),
|
|
6903
|
+
raw: { logs },
|
|
6904
|
+
ids: []
|
|
6905
|
+
});
|
|
6906
|
+
});
|
|
6907
|
+
var eventsCommand2 = new import_commander44.Command("events").description("NCS workload task \uC758 \uC774\uBCA4\uD2B8\uB97C \uC870\uD68C\uD55C\uB2E4").argument("<id>", "workload ID").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").option("--task <taskId>", "task ID (\uD544\uC218)").option("--type <type>", "\uC774\uBCA4\uD2B8 \uD0C0\uC785 (Normal | Warning)").option("--q <query>", "\uC774\uBCA4\uD2B8 \uB0B4\uC6A9 \uD544\uD130\uB9C1").option("--from <time>", "\uC774\uBCA4\uD2B8 \uB9C8\uC9C0\uB9C9 \uBC1C\uC0DD \uC2DC\uC791 \uC2DC\uAC04 (\uAE30\uBCF8: \uD604\uC7AC\uB85C\uBD80\uD130 1\uC2DC\uAC04 \uC804)").option("--to <time>", "\uC774\uBCA4\uD2B8 \uB9C8\uC9C0\uB9C9 \uBC1C\uC0DD \uC885\uB8CC \uC2DC\uAC04 (\uAE30\uBCF8: \uD604\uC7AC \uC2DC\uAC04)").option("--page <page>", "\uC870\uD68C\uD560 page \uBC88\uD638").option("--size <size>", "page \uB2F9 \uD56D\uBAA9 \uC218 (\uAE30\uBCF8: API \uAE30\uBCF8\uAC12 10)").action(async (id, _opts, cmd) => {
|
|
6908
|
+
const opts = cmd.optsWithGlobals();
|
|
6909
|
+
requireNonEmpty(id, "id");
|
|
6910
|
+
if (!opts.task || !opts.task.trim()) {
|
|
6911
|
+
throw new NhnCloudCliError(
|
|
6912
|
+
"--task \uC635\uC158\uC774 \uBE44\uC5B4\uC788\uC2B5\uB2C8\uB2E4. task ID \uB97C \uC9C0\uC815\uD558\uC138\uC694.",
|
|
6913
|
+
EXIT_PARAM_ERROR
|
|
6914
|
+
);
|
|
6915
|
+
}
|
|
6916
|
+
const { client } = await resolveNcsClient(opts);
|
|
6917
|
+
startSpinner(`NCS workload "${id}" task "${opts.task}" \uC774\uBCA4\uD2B8 \uC870\uD68C \uC911...`);
|
|
6918
|
+
let totalCount;
|
|
6919
|
+
let events;
|
|
6920
|
+
try {
|
|
6921
|
+
const result = await client.getWorkloadEvents(id, opts.task, {
|
|
6922
|
+
type: opts.type,
|
|
6923
|
+
q: opts.q,
|
|
6924
|
+
from: opts.from,
|
|
6925
|
+
to: opts.to,
|
|
6926
|
+
page: parsePositiveIntegerOption(opts.page, "--page"),
|
|
6927
|
+
size: parsePositiveIntegerOption(opts.size, "--size")
|
|
6928
|
+
});
|
|
6929
|
+
totalCount = result.totalCount;
|
|
6930
|
+
events = result.events;
|
|
6931
|
+
} catch (err) {
|
|
6932
|
+
stopSpinner(false);
|
|
6933
|
+
throw err;
|
|
6934
|
+
}
|
|
6935
|
+
stopSpinner(true);
|
|
6936
|
+
output(opts, {
|
|
6937
|
+
headers: ["type", "reason", "message", "count", "lastTimestamp"],
|
|
6938
|
+
rows: events.map((e) => [e.type, e.reason, e.message, String(e.count), e.lastTimestamp]),
|
|
6939
|
+
raw: { totalCount, events },
|
|
6940
|
+
ids: []
|
|
6941
|
+
});
|
|
6942
|
+
});
|
|
6943
|
+
var historyGetCommand = new import_commander44.Command("get").description("NCS workload \uC2E4\uD589 \uD788\uC2A4\uD1A0\uB9AC \uB2E8\uAC74\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<id>", "workload ID").argument("<historyId>", "\uD788\uC2A4\uD1A0\uB9AC ID").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (id, historyId, _opts, cmd) => {
|
|
6944
|
+
const opts = cmd.optsWithGlobals();
|
|
6945
|
+
requireNonEmpty(id, "id");
|
|
6946
|
+
requireNonEmpty(historyId, "historyId");
|
|
6947
|
+
const { client } = await resolveNcsClient(opts);
|
|
6948
|
+
startSpinner(`NCS workload "${id}" \uD788\uC2A4\uD1A0\uB9AC "${historyId}" \uC870\uD68C \uC911...`);
|
|
6949
|
+
let detail;
|
|
6950
|
+
try {
|
|
6951
|
+
detail = await client.getWorkloadHistory(id, historyId);
|
|
6952
|
+
} catch (err) {
|
|
6953
|
+
stopSpinner(false);
|
|
6954
|
+
throw err;
|
|
6955
|
+
}
|
|
6956
|
+
stopSpinner(true);
|
|
6957
|
+
output(opts, {
|
|
6958
|
+
headers: ["id", "status", "templateId", "createdAt", "deletedAt"],
|
|
6959
|
+
rows: [
|
|
6960
|
+
[
|
|
6961
|
+
String(detail.id),
|
|
6962
|
+
detail.status,
|
|
6963
|
+
detail.templateId ?? "",
|
|
6964
|
+
detail.createdAt,
|
|
6965
|
+
detail.deletedAt ?? ""
|
|
6966
|
+
]
|
|
6967
|
+
],
|
|
6968
|
+
raw: detail,
|
|
6969
|
+
ids: [String(detail.id)]
|
|
6970
|
+
});
|
|
6971
|
+
});
|
|
6972
|
+
var historyCommand = new import_commander44.Command("history").description("NCS workload \uC2E4\uD589 \uD788\uC2A4\uD1A0\uB9AC \uBAA9\uB85D\uC744 \uC870\uD68C\uD55C\uB2E4").argument("<id>", "workload ID").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").option("--page <page>", "\uC870\uD68C\uD560 page \uBC88\uD638").option("--size <size>", "page \uB2F9 \uD56D\uBAA9 \uC218 (\uAE30\uBCF8: API \uAE30\uBCF8\uAC12 10)").option("--sort <sort>", "\uC815\uB82C \uAE30\uC900 \uD544\uB4DC\uBA85 (\uC5ED\uC21C\uC740 \uD544\uB4DC\uBA85 \uC55E\uC5D0 - \uB97C \uBD99\uC784, \uC608: -id)").action(async (id, _opts, cmd) => {
|
|
6973
|
+
const opts = cmd.optsWithGlobals();
|
|
6974
|
+
requireNonEmpty(id, "id");
|
|
6975
|
+
const { client } = await resolveNcsClient(opts);
|
|
6976
|
+
startSpinner(`NCS workload "${id}" \uD788\uC2A4\uD1A0\uB9AC \uBAA9\uB85D \uC870\uD68C \uC911...`);
|
|
6977
|
+
let totalCount;
|
|
6978
|
+
let history;
|
|
6979
|
+
try {
|
|
6980
|
+
const result = await client.listWorkloadHistory(id, {
|
|
6981
|
+
page: parsePositiveIntegerOption(opts.page, "--page"),
|
|
6982
|
+
size: parsePositiveIntegerOption(opts.size, "--size"),
|
|
6983
|
+
sort: opts.sort
|
|
6984
|
+
});
|
|
6985
|
+
totalCount = result.totalCount;
|
|
6986
|
+
history = result.history;
|
|
6987
|
+
} catch (err) {
|
|
6988
|
+
stopSpinner(false);
|
|
6989
|
+
throw err;
|
|
6990
|
+
}
|
|
6991
|
+
stopSpinner(true);
|
|
6992
|
+
output(opts, {
|
|
6993
|
+
headers: ["id", "status", "templateId", "createdAt", "deletedAt"],
|
|
6994
|
+
rows: history.map((h) => [
|
|
6995
|
+
String(h.id),
|
|
6996
|
+
h.status,
|
|
6997
|
+
h.templateId ?? "",
|
|
6998
|
+
h.createdAt,
|
|
6999
|
+
h.deletedAt ?? ""
|
|
7000
|
+
]),
|
|
7001
|
+
raw: { totalCount, history },
|
|
7002
|
+
ids: history.map((h) => String(h.id))
|
|
7003
|
+
});
|
|
7004
|
+
}).addCommand(historyGetCommand);
|
|
7005
|
+
var scheduleHistoryCommand = new import_commander44.Command("schedule-history").description("NCS workload \uC608\uC57D \uC2E4\uD589 \uD788\uC2A4\uD1A0\uB9AC\uB97C \uC870\uD68C\uD55C\uB2E4").argument("<id>", "workload ID").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (id, _opts, cmd) => {
|
|
7006
|
+
const opts = cmd.optsWithGlobals();
|
|
7007
|
+
requireNonEmpty(id, "id");
|
|
7008
|
+
const { client } = await resolveNcsClient(opts);
|
|
7009
|
+
startSpinner(`NCS workload "${id}" \uC608\uC57D \uC2E4\uD589 \uD788\uC2A4\uD1A0\uB9AC \uC870\uD68C \uC911...`);
|
|
7010
|
+
let scheduleHistory;
|
|
7011
|
+
try {
|
|
7012
|
+
const result = await client.getWorkloadScheduleHistory(id);
|
|
7013
|
+
scheduleHistory = result.scheduleHistory;
|
|
7014
|
+
} catch (err) {
|
|
7015
|
+
stopSpinner(false);
|
|
7016
|
+
throw err;
|
|
7017
|
+
}
|
|
7018
|
+
stopSpinner(true);
|
|
7019
|
+
output(opts, {
|
|
7020
|
+
headers: ["id", "status", "createdAt", "finishedAt"],
|
|
7021
|
+
rows: scheduleHistory.map((s) => [s.id, s.status, s.createdAt, s.finishedAt ?? ""]),
|
|
7022
|
+
raw: { scheduleHistory },
|
|
7023
|
+
ids: scheduleHistory.map((s) => s.id)
|
|
7024
|
+
});
|
|
7025
|
+
});
|
|
7026
|
+
var createCommand7 = new import_commander44.Command("create").description("NCS workload(\uB7F0\uD0C0\uC784 \uC2E4\uD589) \uB97C \uC0DD\uC131\uD55C\uB2E4 (--file \uB85C JSON spec \uC804\uB2EC)").requiredOption("--file <path>", "workload \uC0DD\uC131 spec \uC774 \uB2F4\uAE34 JSON \uD30C\uC77C \uACBD\uB85C").option("--wait", "workload \uAC00 Running \uC0C1\uD0DC\uAC00 \uB420 \uB54C\uAE4C\uC9C0 \uB300\uAE30").option("--timeout <sec>", "wait \uD0C0\uC784\uC544\uC6C3 (\uCD08, \uAE30\uBCF8 300)", "300").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (_opts, cmd) => {
|
|
7027
|
+
const opts = cmd.optsWithGlobals();
|
|
7028
|
+
const payload = readJsonPayload(opts.file);
|
|
7029
|
+
const timeoutMs = parsePositiveIntegerOption(opts.timeout ?? "300", "--timeout") * 1e3;
|
|
7030
|
+
const { client } = await resolveNcsClient(opts);
|
|
7031
|
+
startSpinner("NCS workload \uC0DD\uC131 \uC911...");
|
|
7032
|
+
let workload;
|
|
7033
|
+
try {
|
|
7034
|
+
workload = await client.createWorkload(payload);
|
|
7035
|
+
} catch (err) {
|
|
7036
|
+
stopSpinner(false);
|
|
7037
|
+
throw err;
|
|
7038
|
+
}
|
|
7039
|
+
stopSpinner(true);
|
|
7040
|
+
if (opts.wait) {
|
|
7041
|
+
startSpinner(`NCS workload "${workload.id}" Running \uB300\uAE30 \uC911...`);
|
|
7042
|
+
try {
|
|
7043
|
+
workload = await client.waitForRunning(workload.id, { timeoutMs });
|
|
7044
|
+
} catch (err) {
|
|
7045
|
+
stopSpinner(false);
|
|
7046
|
+
throw err;
|
|
7047
|
+
}
|
|
7048
|
+
stopSpinner(true, `Running \uD655\uC778 (id: ${workload.id})`);
|
|
7049
|
+
}
|
|
7050
|
+
output(opts, {
|
|
7051
|
+
headers: WORKLOAD_HEADERS,
|
|
7052
|
+
rows: workloadRows(workload),
|
|
7053
|
+
raw: workload,
|
|
7054
|
+
ids: [workload.id]
|
|
7055
|
+
});
|
|
7056
|
+
});
|
|
7057
|
+
var updateCommand = new import_commander44.Command("update").description("NCS workload \uB97C \uC804\uCCB4 \uAD50\uCCB4\uD55C\uB2E4 (--file \uB85C JSON spec \uC804\uB2EC, PUT)").argument("<id>", "workload ID").requiredOption("--file <path>", "workload \uAD50\uCCB4 spec \uC774 \uB2F4\uAE34 JSON \uD30C\uC77C \uACBD\uB85C").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (id, _opts, cmd) => {
|
|
7058
|
+
const opts = cmd.optsWithGlobals();
|
|
7059
|
+
requireNonEmpty(id, "id");
|
|
7060
|
+
const payload = readJsonPayload(opts.file);
|
|
7061
|
+
const { client } = await resolveNcsClient(opts);
|
|
7062
|
+
startSpinner(`NCS workload "${id}" \uAD50\uCCB4 \uC911...`);
|
|
7063
|
+
let workload;
|
|
7064
|
+
try {
|
|
7065
|
+
workload = await client.updateWorkload(id, payload);
|
|
7066
|
+
} catch (err) {
|
|
7067
|
+
stopSpinner(false);
|
|
7068
|
+
throw err;
|
|
7069
|
+
}
|
|
7070
|
+
stopSpinner(true);
|
|
7071
|
+
output(opts, {
|
|
7072
|
+
headers: WORKLOAD_HEADERS,
|
|
7073
|
+
rows: workloadRows(workload),
|
|
7074
|
+
raw: workload,
|
|
7075
|
+
ids: [workload.id]
|
|
7076
|
+
});
|
|
7077
|
+
});
|
|
7078
|
+
var patchCommand = new import_commander44.Command("patch").description("NCS workload \uB97C \uBD80\uBD84 \uBCC0\uACBD\uD55C\uB2E4 (--file \uB85C JSON Patch \uBC30\uC5F4 \uC804\uB2EC, RFC 6902)").argument("<id>", "workload ID").requiredOption("--file <path>", "JSON Patch \uBC30\uC5F4(op/path/value)\uC774 \uB2F4\uAE34 \uD30C\uC77C \uACBD\uB85C").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (id, _opts, cmd) => {
|
|
7079
|
+
const opts = cmd.optsWithGlobals();
|
|
7080
|
+
requireNonEmpty(id, "id");
|
|
7081
|
+
const payload = readJsonPayload(opts.file);
|
|
7082
|
+
const { client } = await resolveNcsClient(opts);
|
|
7083
|
+
startSpinner(`NCS workload "${id}" \uBD80\uBD84 \uBCC0\uACBD \uC911...`);
|
|
7084
|
+
let workload;
|
|
7085
|
+
try {
|
|
7086
|
+
workload = await client.patchWorkload(id, payload);
|
|
7087
|
+
} catch (err) {
|
|
7088
|
+
stopSpinner(false);
|
|
7089
|
+
throw err;
|
|
7090
|
+
}
|
|
7091
|
+
stopSpinner(true);
|
|
7092
|
+
output(opts, {
|
|
7093
|
+
headers: WORKLOAD_HEADERS,
|
|
7094
|
+
rows: workloadRows(workload),
|
|
7095
|
+
raw: workload,
|
|
7096
|
+
ids: [workload.id]
|
|
7097
|
+
});
|
|
7098
|
+
});
|
|
7099
|
+
var pauseCommand = new import_commander44.Command("pause").description("NCS workload \uB97C \uC77C\uC2DC\uC815\uC9C0\uD55C\uB2E4").argument("<id>", "workload ID").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (id, _opts, cmd) => {
|
|
7100
|
+
const opts = cmd.optsWithGlobals();
|
|
7101
|
+
requireNonEmpty(id, "id");
|
|
7102
|
+
const { client } = await resolveNcsClient(opts);
|
|
7103
|
+
startSpinner(`NCS workload "${id}" \uC77C\uC2DC\uC815\uC9C0 \uC911...`);
|
|
7104
|
+
try {
|
|
7105
|
+
await client.pauseWorkload(id);
|
|
7106
|
+
} catch (err) {
|
|
7107
|
+
stopSpinner(false);
|
|
7108
|
+
throw err;
|
|
7109
|
+
}
|
|
7110
|
+
stopSpinner(true);
|
|
7111
|
+
process.stderr.write(import_chalk15.default.green(`\u2713 NCS workload "${id}" \uAC00 \uC77C\uC2DC\uC815\uC9C0\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
|
|
7112
|
+
`));
|
|
7113
|
+
});
|
|
7114
|
+
var resumeCommand = new import_commander44.Command("resume").description("NCS workload \uB97C \uC7AC\uAC1C\uD55C\uB2E4").argument("<id>", "workload ID").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (id, _opts, cmd) => {
|
|
7115
|
+
const opts = cmd.optsWithGlobals();
|
|
7116
|
+
requireNonEmpty(id, "id");
|
|
7117
|
+
const { client } = await resolveNcsClient(opts);
|
|
7118
|
+
startSpinner(`NCS workload "${id}" \uC7AC\uAC1C \uC911...`);
|
|
7119
|
+
try {
|
|
7120
|
+
await client.resumeWorkload(id);
|
|
7121
|
+
} catch (err) {
|
|
7122
|
+
stopSpinner(false);
|
|
7123
|
+
throw err;
|
|
7124
|
+
}
|
|
7125
|
+
stopSpinner(true);
|
|
7126
|
+
process.stderr.write(import_chalk15.default.green(`\u2713 NCS workload "${id}" \uAC00 \uC7AC\uAC1C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
|
|
7127
|
+
`));
|
|
7128
|
+
});
|
|
7129
|
+
var restartCommand = new import_commander44.Command("restart").description("NCS workload task \uB97C \uC7AC\uC2DC\uC791\uD55C\uB2E4").argument("<id>", "workload ID").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").option("--task <taskId>", "task ID (\uD544\uC218)").action(async (id, _opts, cmd) => {
|
|
7130
|
+
const opts = cmd.optsWithGlobals();
|
|
7131
|
+
requireNonEmpty(id, "id");
|
|
7132
|
+
if (!opts.task || !opts.task.trim()) {
|
|
7133
|
+
throw new NhnCloudCliError(
|
|
7134
|
+
"--task \uC635\uC158\uC774 \uBE44\uC5B4\uC788\uC2B5\uB2C8\uB2E4. task ID \uB97C \uC9C0\uC815\uD558\uC138\uC694.",
|
|
7135
|
+
EXIT_PARAM_ERROR
|
|
7136
|
+
);
|
|
7137
|
+
}
|
|
7138
|
+
const { client } = await resolveNcsClient(opts);
|
|
7139
|
+
startSpinner(`NCS workload "${id}" task "${opts.task}" \uC7AC\uC2DC\uC791 \uC911...`);
|
|
7140
|
+
try {
|
|
7141
|
+
await client.restartWorkloadTask(id, opts.task);
|
|
7142
|
+
} catch (err) {
|
|
7143
|
+
stopSpinner(false);
|
|
7144
|
+
throw err;
|
|
7145
|
+
}
|
|
7146
|
+
stopSpinner(true);
|
|
7147
|
+
process.stderr.write(
|
|
7148
|
+
import_chalk15.default.green(`\u2713 NCS workload "${id}" task "${opts.task}" \uAC00 \uC7AC\uC2DC\uC791\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
|
|
7149
|
+
`)
|
|
7150
|
+
);
|
|
7151
|
+
});
|
|
7152
|
+
var deleteCommand6 = new import_commander44.Command("delete").description("NCS workload \uB97C \uC0AD\uC81C\uD55C\uB2E4").argument("<id>", "workload ID").option("--yes", "\uD655\uC778 \uD504\uB86C\uD504\uD2B8 \uC0DD\uB7B5 (CI/\uBE44\uB300\uD654\uD615 \uD544\uC218)").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (id, _opts, cmd) => {
|
|
7153
|
+
const opts = cmd.optsWithGlobals();
|
|
7154
|
+
requireNonEmpty(id, "id");
|
|
7155
|
+
const ok = await confirmDestructive(`NCS workload "${id}" \uB97C \uC0AD\uC81C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?`, opts.yes);
|
|
7156
|
+
if (!ok) {
|
|
7157
|
+
process.stderr.write(import_chalk15.default.yellow("\uC0AD\uC81C\uAC00 \uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\n"));
|
|
7158
|
+
return;
|
|
7159
|
+
}
|
|
7160
|
+
const { client } = await resolveNcsClient(opts);
|
|
7161
|
+
startSpinner(`NCS workload \uC0AD\uC81C \uC911... (id: ${id})`);
|
|
7162
|
+
try {
|
|
7163
|
+
await client.deleteWorkload(id);
|
|
7164
|
+
} catch (err) {
|
|
7165
|
+
stopSpinner(false);
|
|
7166
|
+
throw err;
|
|
7167
|
+
}
|
|
7168
|
+
stopSpinner(true);
|
|
7169
|
+
process.stderr.write(import_chalk15.default.green(`\u2713 NCS workload "${id}" \uAC00 \uC0AD\uC81C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
|
|
7170
|
+
`));
|
|
7171
|
+
});
|
|
7172
|
+
var workloadCommand = new import_commander44.Command("workload").description("NCS workload(\uB7F0\uD0C0\uC784 \uC2E4\uD589) \uAD00\uB9AC").addCommand(listCommand9).addCommand(getCommand7).addCommand(logsCommand).addCommand(eventsCommand2).addCommand(historyCommand).addCommand(scheduleHistoryCommand).addCommand(createCommand7).addCommand(updateCommand).addCommand(patchCommand).addCommand(pauseCommand).addCommand(resumeCommand).addCommand(restartCommand).addCommand(deleteCommand6);
|
|
7173
|
+
|
|
7174
|
+
// src/commands/ncs/malware.ts
|
|
7175
|
+
var import_commander45 = require("commander");
|
|
7176
|
+
function parseEnabledOption(value) {
|
|
7177
|
+
if (value === "true") return true;
|
|
7178
|
+
if (value === "false") return false;
|
|
7179
|
+
throw new NhnCloudCliError(
|
|
7180
|
+
`--enabled \uB294 true \uB610\uB294 false \uC5EC\uC57C \uD569\uB2C8\uB2E4 (\uC785\uB825: ${JSON.stringify(value)}).`,
|
|
7181
|
+
EXIT_PARAM_ERROR
|
|
7182
|
+
);
|
|
7183
|
+
}
|
|
7184
|
+
var configGetCommand = new import_commander45.Command("get").description("NCS \uC545\uC131\uCF54\uB4DC \uAC80\uC0AC \uC124\uC815\uC744 \uC870\uD68C\uD55C\uB2E4").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (_opts, cmd) => {
|
|
7185
|
+
const opts = cmd.optsWithGlobals();
|
|
7186
|
+
const { client } = await resolveNcsClient(opts);
|
|
7187
|
+
startSpinner("NCS \uC545\uC131\uCF54\uB4DC \uAC80\uC0AC \uC124\uC815 \uC870\uD68C \uC911...");
|
|
7188
|
+
let config;
|
|
7189
|
+
try {
|
|
7190
|
+
config = await client.getMalwareConfig();
|
|
7191
|
+
} catch (err) {
|
|
7192
|
+
stopSpinner(false);
|
|
7193
|
+
throw err;
|
|
7194
|
+
}
|
|
7195
|
+
stopSpinner(true);
|
|
7196
|
+
output(opts, {
|
|
7197
|
+
headers: ["enabled"],
|
|
7198
|
+
rows: [[String(config.enabled)]],
|
|
7199
|
+
raw: config,
|
|
7200
|
+
ids: []
|
|
7201
|
+
});
|
|
7202
|
+
});
|
|
7203
|
+
var configSetCommand = new import_commander45.Command("set").description("NCS \uC545\uC131\uCF54\uB4DC \uAC80\uC0AC \uC124\uC815\uC744 \uBCC0\uACBD\uD55C\uB2E4").requiredOption("--enabled <true|false>", "\uC545\uC131\uCF54\uB4DC \uAC80\uC0AC \uC0AC\uC6A9 \uC5EC\uBD80").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (_opts, cmd) => {
|
|
7204
|
+
const opts = cmd.optsWithGlobals();
|
|
7205
|
+
const enabled = parseEnabledOption(opts.enabled);
|
|
7206
|
+
const { client } = await resolveNcsClient(opts);
|
|
7207
|
+
startSpinner("NCS \uC545\uC131\uCF54\uB4DC \uAC80\uC0AC \uC124\uC815 \uBCC0\uACBD \uC911...");
|
|
7208
|
+
let config;
|
|
7209
|
+
try {
|
|
7210
|
+
config = await client.setMalwareConfig(enabled);
|
|
7211
|
+
} catch (err) {
|
|
7212
|
+
stopSpinner(false);
|
|
7213
|
+
throw err;
|
|
7214
|
+
}
|
|
7215
|
+
stopSpinner(true);
|
|
7216
|
+
output(opts, {
|
|
7217
|
+
headers: ["enabled"],
|
|
7218
|
+
rows: [[String(config.enabled)]],
|
|
7219
|
+
raw: config,
|
|
7220
|
+
ids: []
|
|
7221
|
+
});
|
|
7222
|
+
});
|
|
7223
|
+
var configCommand = new import_commander45.Command("config").description("NCS \uC545\uC131\uCF54\uB4DC \uAC80\uC0AC \uC124\uC815 \uAD00\uB9AC").addCommand(configGetCommand).addCommand(configSetCommand);
|
|
7224
|
+
var resultCommand = new import_commander45.Command("result").description("NCS workload \uC2E4\uD589 \uD788\uC2A4\uD1A0\uB9AC\uC758 \uC545\uC131\uCF54\uB4DC \uAC80\uC0AC \uACB0\uACFC\uB97C \uC870\uD68C\uD55C\uB2E4").argument("<workloadId>", "workload ID").argument("<historyId>", "\uD788\uC2A4\uD1A0\uB9AC ID").option("--region <region>", "NCS region (\uAE30\uBCF8: kr1, kr1/kr3 \uB9CC \uC9C0\uC6D0)", "kr1").option("--app-key <key>", "NCS appKey (profile \uC758 ncs.appkey \uBCF4\uB2E4 \uC6B0\uC120)").option("--profile <name>", "\uC0AC\uC6A9\uD560 profile \uC774\uB984").action(async (workloadId, historyId, _opts, cmd) => {
|
|
7225
|
+
const opts = cmd.optsWithGlobals();
|
|
7226
|
+
requireNonEmpty(workloadId, "workloadId");
|
|
7227
|
+
requireNonEmpty(historyId, "historyId");
|
|
7228
|
+
const { client } = await resolveNcsClient(opts);
|
|
7229
|
+
startSpinner(
|
|
7230
|
+
`NCS workload "${workloadId}" \uD788\uC2A4\uD1A0\uB9AC "${historyId}" \uC545\uC131\uCF54\uB4DC \uAC80\uC0AC \uACB0\uACFC \uC870\uD68C \uC911...`
|
|
7231
|
+
);
|
|
7232
|
+
let result;
|
|
7233
|
+
try {
|
|
7234
|
+
result = await client.getMalwareResult(workloadId, historyId);
|
|
7235
|
+
} catch (err) {
|
|
7236
|
+
stopSpinner(false);
|
|
7237
|
+
throw err;
|
|
7238
|
+
}
|
|
7239
|
+
stopSpinner(true);
|
|
7240
|
+
output(opts, {
|
|
7241
|
+
headers: ["scannedAt", "infectedFiles", "scannedDirectories", "scannedFiles", "reports"],
|
|
7242
|
+
rows: [
|
|
7243
|
+
[
|
|
7244
|
+
result.scannedAt ?? "",
|
|
7245
|
+
String(result.infectedFiles ?? ""),
|
|
7246
|
+
String(result.scannedDirectories ?? ""),
|
|
7247
|
+
String(result.scannedFiles ?? ""),
|
|
7248
|
+
String(result.reports?.length ?? 0)
|
|
7249
|
+
]
|
|
7250
|
+
],
|
|
7251
|
+
raw: result,
|
|
7252
|
+
ids: []
|
|
7253
|
+
});
|
|
7254
|
+
});
|
|
7255
|
+
var malwareCommand = new import_commander45.Command("malware").description("NCS \uC545\uC131\uCF54\uB4DC \uAC80\uC0AC \uAD00\uB9AC").addCommand(configCommand).addCommand(resultCommand);
|
|
7256
|
+
|
|
7257
|
+
// src/index.ts
|
|
7258
|
+
var rootAgentHints = `
|
|
7259
|
+
Agent hints:
|
|
7260
|
+
- Prefer --json for structured output.
|
|
7261
|
+
- Use --quiet only when the command documents an identifier output.
|
|
7262
|
+
- Use --profile <name> to avoid relying on default profile.
|
|
7263
|
+
- For IaaS/NKS commands, use --region <region> when region matters.
|
|
7264
|
+
- Run "nhncloud commands --json" to inspect command paths and options.
|
|
7265
|
+
`;
|
|
7266
|
+
var logncrashAgentWorkflow = `
|
|
7267
|
+
Agent workflow:
|
|
7268
|
+
1. nhncloud logncrash search --query '*' --from 1h --to now --json
|
|
7269
|
+
2. nhncloud logncrash export --query '<lucene>' --from 1h --to now --output logs.jsonl
|
|
7270
|
+
`;
|
|
7271
|
+
var deployAgentWorkflow = `
|
|
7272
|
+
Agent workflow:
|
|
7273
|
+
1. nhncloud deploy artifacts <target> --json
|
|
7274
|
+
2. nhncloud deploy server-groups <target> --json
|
|
7275
|
+
3. nhncloud deploy run <target>
|
|
7276
|
+
`;
|
|
7277
|
+
var instanceAgentWorkflow = `
|
|
7278
|
+
Agent workflow:
|
|
7279
|
+
1. nhncloud instance images --json
|
|
7280
|
+
2. nhncloud instance flavors --detail --json
|
|
7281
|
+
3. nhncloud instance list --json
|
|
7282
|
+
`;
|
|
7283
|
+
var networkAgentWorkflow = `
|
|
7284
|
+
Agent workflow:
|
|
7285
|
+
1. nhncloud network list --json
|
|
7286
|
+
2. nhncloud network subnet list --json
|
|
7287
|
+
`;
|
|
7288
|
+
var volumeAgentWorkflow = `
|
|
7289
|
+
Agent workflow:
|
|
7290
|
+
1. nhncloud volume list --json
|
|
7291
|
+
2. nhncloud volume get <volume-id> --json
|
|
7292
|
+
`;
|
|
7293
|
+
var floatingIpAgentWorkflow = `
|
|
7294
|
+
Agent workflow:
|
|
7295
|
+
1. nhncloud floatingip list --json
|
|
7296
|
+
2. nhncloud floatingip create --json
|
|
7297
|
+
`;
|
|
7298
|
+
var ncrAgentWorkflow = `
|
|
7299
|
+
Agent workflow:
|
|
7300
|
+
1. nhncloud ncr list --json
|
|
7301
|
+
2. nhncloud ncr images <registry> --json
|
|
7302
|
+
3. nhncloud ncr tags <registry> <repository> --json
|
|
7303
|
+
`;
|
|
7304
|
+
var nksAgentWorkflow = `
|
|
7305
|
+
Agent workflow:
|
|
7306
|
+
1. nhncloud nks supports --json
|
|
7307
|
+
2. nhncloud nks cluster list --json
|
|
7308
|
+
3. nhncloud nks cluster get <cluster> --json
|
|
7309
|
+
`;
|
|
7310
|
+
var ncsAgentWorkflow = `
|
|
7311
|
+
Agent workflow:
|
|
7312
|
+
1. nhncloud ncs template list --json
|
|
7313
|
+
2. nhncloud ncs workload list --json
|
|
7314
|
+
3. nhncloud ncs workload get <id> --json
|
|
5700
7315
|
`;
|
|
5701
|
-
var program = new
|
|
5702
|
-
program.name("nhncloud").description("NHN Cloud CLI \u2014 AI agent & terminal friendly").version("0.
|
|
7316
|
+
var program = new import_commander46.Command();
|
|
7317
|
+
program.name("nhncloud").description("NHN Cloud CLI \u2014 AI agent & terminal friendly").version("0.8.0").option("--json", "JSON \uD615\uC2DD\uC73C\uB85C \uCD9C\uB825").option("--quiet", "\uCD5C\uC18C \uCD9C\uB825 (\uC790\uB3D9\uD654\uC6A9)").option("--no-color", "\uC0C9\uC0C1 \uBE44\uD65C\uC131\uD654").addHelpText("after", rootAgentHints);
|
|
5703
7318
|
program.hook("preAction", () => {
|
|
5704
7319
|
const opts = program.opts();
|
|
5705
7320
|
if (!opts.color || process.env["NO_COLOR"]) {
|
|
5706
|
-
|
|
7321
|
+
import_chalk16.default.level = 0;
|
|
5707
7322
|
}
|
|
5708
7323
|
if (opts.json || opts.quiet) {
|
|
5709
7324
|
setQuiet(true);
|
|
5710
7325
|
}
|
|
5711
7326
|
});
|
|
5712
7327
|
program.addCommand(configureCommand);
|
|
5713
|
-
var logncrashCommand = new
|
|
7328
|
+
var logncrashCommand = new import_commander46.Command("logncrash").description("Log & Crash \uAD00\uB828 \uBA85\uB839").addHelpText("after", logncrashAgentWorkflow);
|
|
5714
7329
|
logncrashCommand.addCommand(searchCommand);
|
|
5715
7330
|
logncrashCommand.addCommand(sendCommand);
|
|
5716
7331
|
logncrashCommand.addCommand(exportCommand);
|
|
5717
7332
|
program.addCommand(logncrashCommand);
|
|
5718
|
-
var deployCommand = new
|
|
7333
|
+
var deployCommand = new import_commander46.Command("deploy").description("NHN Cloud Deploy \uAD00\uB828 \uBA85\uB839").addHelpText("after", deployAgentWorkflow);
|
|
5719
7334
|
deployCommand.addCommand(runCommand);
|
|
5720
7335
|
deployCommand.addCommand(artifactsCommand);
|
|
5721
7336
|
deployCommand.addCommand(serverGroupsCommand);
|
|
@@ -5725,7 +7340,7 @@ deployCommand.addCommand(binariesCommand);
|
|
|
5725
7340
|
deployCommand.addCommand(uploadCommand);
|
|
5726
7341
|
deployCommand.addCommand(downloadCommand);
|
|
5727
7342
|
program.addCommand(deployCommand);
|
|
5728
|
-
var instanceCommand = new
|
|
7343
|
+
var instanceCommand = new import_commander46.Command("instance").description("Compute \uC778\uC2A4\uD134\uC2A4 \uAD00\uB828 \uBA85\uB839").addHelpText("after", instanceAgentWorkflow);
|
|
5729
7344
|
instanceCommand.addCommand(listCommand);
|
|
5730
7345
|
instanceCommand.addCommand(flavorsCommand);
|
|
5731
7346
|
instanceCommand.addCommand(availabilityZonesCommand);
|
|
@@ -5744,39 +7359,44 @@ instanceCommand.addCommand(keypairCommand);
|
|
|
5744
7359
|
instanceCommand.addCommand(volumeCommand);
|
|
5745
7360
|
instanceCommand.addCommand(volumesCommand);
|
|
5746
7361
|
program.addCommand(instanceCommand);
|
|
5747
|
-
var networkCommand = new
|
|
7362
|
+
var networkCommand = new import_commander46.Command("network").description("VPC\xB7\uC11C\uBE0C\uB137 \uC870\uD68C").addHelpText("after", networkAgentWorkflow);
|
|
5748
7363
|
networkCommand.addCommand(listCommand3);
|
|
5749
7364
|
networkCommand.addCommand(subnetCommand);
|
|
5750
7365
|
program.addCommand(networkCommand);
|
|
5751
|
-
var volumeCommand2 = new
|
|
7366
|
+
var volumeCommand2 = new import_commander46.Command("volume").description("Block Storage \uBCFC\uB968 \uAD00\uB828 \uBA85\uB839").addHelpText("after", volumeAgentWorkflow);
|
|
5752
7367
|
volumeCommand2.addCommand(listCommand2);
|
|
5753
7368
|
volumeCommand2.addCommand(getCommand);
|
|
5754
7369
|
volumeCommand2.addCommand(createCommand);
|
|
5755
7370
|
program.addCommand(volumeCommand2);
|
|
5756
|
-
var floatingipCommand = new
|
|
7371
|
+
var floatingipCommand = new import_commander46.Command("floatingip").description(
|
|
5757
7372
|
"Floating IP(\uC778\uC2A4\uD134\uC2A4 \uACF5\uC778 IP) \uAD00\uB9AC"
|
|
5758
7373
|
).addHelpText("after", floatingIpAgentWorkflow);
|
|
5759
7374
|
floatingipCommand.addCommand(listCommand4);
|
|
5760
7375
|
floatingipCommand.addCommand(createCommand2);
|
|
5761
7376
|
floatingipCommand.addCommand(deleteCommand);
|
|
5762
7377
|
program.addCommand(floatingipCommand);
|
|
5763
|
-
var ncrCommand = new
|
|
7378
|
+
var ncrCommand = new import_commander46.Command("ncr").description("NHN Container Registry \uAD00\uB828 \uBA85\uB839").addHelpText("after", ncrAgentWorkflow);
|
|
5764
7379
|
ncrCommand.addCommand(listCommand5);
|
|
5765
7380
|
ncrCommand.addCommand(getCommand3);
|
|
5766
7381
|
ncrCommand.addCommand(imagesCommand2);
|
|
5767
7382
|
ncrCommand.addCommand(tagsCommand);
|
|
5768
7383
|
program.addCommand(ncrCommand);
|
|
5769
|
-
var nksCommand = new
|
|
7384
|
+
var nksCommand = new import_commander46.Command("nks").description("NHN Kubernetes Service \uAD00\uB828 \uBA85\uB839").addHelpText("after", nksAgentWorkflow);
|
|
5770
7385
|
nksCommand.addCommand(supportsCommand);
|
|
5771
7386
|
nksCommand.addCommand(clusterCommand);
|
|
5772
7387
|
nksCommand.addCommand(nodegroupCommand);
|
|
5773
7388
|
nksCommand.addCommand(addonTypeCommand);
|
|
5774
7389
|
nksCommand.addCommand(addonCommand);
|
|
5775
7390
|
program.addCommand(nksCommand);
|
|
7391
|
+
var ncsCommand = new import_commander46.Command("ncs").description("NHN Container Service \uAD00\uB828 \uBA85\uB839").addHelpText("after", ncsAgentWorkflow);
|
|
7392
|
+
ncsCommand.addCommand(templateCommand);
|
|
7393
|
+
ncsCommand.addCommand(workloadCommand);
|
|
7394
|
+
ncsCommand.addCommand(malwareCommand);
|
|
7395
|
+
program.addCommand(ncsCommand);
|
|
5776
7396
|
program.addCommand(createCommandsCommand(program));
|
|
5777
7397
|
program.parseAsync().catch((err) => {
|
|
5778
7398
|
const message = err instanceof Error ? err.message : String(err);
|
|
5779
7399
|
const exitCode = err instanceof NhnCloudCliError ? err.exitCode : 1;
|
|
5780
|
-
process.stderr.write(
|
|
7400
|
+
process.stderr.write(import_chalk16.default.red(`\uC624\uB958: ${message}`) + "\n");
|
|
5781
7401
|
process.exit(exitCode);
|
|
5782
7402
|
});
|