kourou 0.27.1 → 0.28.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 CHANGED
@@ -27,7 +27,7 @@ $ npm install -g kourou
27
27
  $ kourou COMMAND
28
28
  running command...
29
29
  $ kourou (-v|--version|version)
30
- kourou/0.27.1 darwin-arm64 node-v18.17.1
30
+ kourou/0.28.0 darwin-arm64 node-v20.10.0
31
31
  $ kourou --help [COMMAND]
32
32
  USAGE
33
33
  $ kourou COMMAND
@@ -161,6 +161,7 @@ All other arguments and options will be passed as-is to the `sdk:query` method.
161
161
  * [`kourou instance:logs`](#kourou-instancelogs)
162
162
  * [`kourou instance:spawn`](#kourou-instancespawn)
163
163
  * [`kourou paas:deploy ENVIRONMENT APPLICATIONID IMAGE`](#kourou-paasdeploy-environment-applicationid-image)
164
+ * [`kourou paas:elasticsearch:dump ENVIRONMENT APPLICATIONID DUMPDIRECTORY`](#kourou-paaselasticsearchdump-environment-applicationid-dumpdirectory)
164
165
  * [`kourou paas:init PROJECT`](#kourou-paasinit-project)
165
166
  * [`kourou paas:login`](#kourou-paaslogin)
166
167
  * [`kourou paas:logs ENVIRONMENT APPLICATION`](#kourou-paaslogs-environment-application)
@@ -1064,6 +1065,25 @@ OPTIONS
1064
1065
 
1065
1066
  _See code: [lib/commands/paas/deploy.js](lib/commands/paas/deploy.js)_
1066
1067
 
1068
+ ## `kourou paas:elasticsearch:dump ENVIRONMENT APPLICATIONID DUMPDIRECTORY`
1069
+
1070
+ Dump data from the Elasticsearch of a PaaS application
1071
+
1072
+ ```
1073
+ USAGE
1074
+ $ kourou paas:elasticsearch:dump ENVIRONMENT APPLICATIONID DUMPDIRECTORY
1075
+
1076
+ ARGUMENTS
1077
+ ENVIRONMENT Project environment name
1078
+ APPLICATIONID Application Identifier
1079
+ DUMPDIRECTORY Directory where to store dump files
1080
+
1081
+ OPTIONS
1082
+ --batch-size=batch-size [default: 2000] Maximum batch size
1083
+ --help show CLI help
1084
+ --project=project Current PaaS project
1085
+ ```
1086
+
1067
1087
  ## `kourou paas:init PROJECT`
1068
1088
 
1069
1089
  Initialize a PaaS project in current directory
@@ -0,0 +1,35 @@
1
+ import { flags } from "@oclif/command";
2
+ import { PaasKommand } from "../../../support/PaasKommand";
3
+ declare class PaasEsDump extends PaasKommand {
4
+ static description: string;
5
+ static flags: {
6
+ help: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
7
+ project: flags.IOptionFlag<string | undefined>;
8
+ "batch-size": import("@oclif/parser/lib/flags").IOptionFlag<number>;
9
+ };
10
+ static args: {
11
+ name: string;
12
+ description: string;
13
+ required: boolean;
14
+ }[];
15
+ runSafe(): Promise<void>;
16
+ /**
17
+ * @description Get all indexes from the Elasticsearch of the PaaS application.
18
+ * @returns The indexes.
19
+ */
20
+ private getAllIndexes;
21
+ /**
22
+ * @description Dump documents from the Elasticsearch of the PaaS application.
23
+ * @param pitId ID of the PIT opened on Elasticsearch.
24
+ * @param searchAfter Cursor for dumping documents after a certain one.
25
+ * @returns The dumped documents.
26
+ */
27
+ private dumpDocuments;
28
+ private dumpAllDocuments;
29
+ /**
30
+ * @description Finish the document dumping session.
31
+ * @param pitId ID of the PIT opened on Elasticsearch.
32
+ */
33
+ private finishDump;
34
+ }
35
+ export default PaasEsDump;
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const path_1 = (0, tslib_1.__importDefault)(require("path"));
5
+ const promises_1 = (0, tslib_1.__importDefault)(require("node:fs/promises"));
6
+ const ndjson_1 = (0, tslib_1.__importDefault)(require("ndjson"));
7
+ const command_1 = require("@oclif/command");
8
+ const PaasKommand_1 = require("../../../support/PaasKommand");
9
+ class PaasEsDump extends PaasKommand_1.PaasKommand {
10
+ async runSafe() {
11
+ // Check that the batch size is positive
12
+ if (this.flags["batch-size"] <= 0) {
13
+ this.logKo(`The batch size must be greater than zero. (Specified batch size: ${this.flags["batch-size"]})`);
14
+ process.exit(1);
15
+ }
16
+ // Log in to the PaaS
17
+ const apiKey = await this.getCredentials();
18
+ await this.initPaasClient({ apiKey });
19
+ const user = await this.paas.auth.getCurrentUser();
20
+ this.logInfo(`Logged as "${user._id}" for project "${this.flags.project || this.getProject()}"`);
21
+ // Create the dump directory
22
+ await promises_1.default.mkdir(this.args.dumpDirectory, { recursive: true });
23
+ // Dump the indexes
24
+ this.logInfo("Dumping Elasticsearch indexes...");
25
+ const indexesResult = await this.getAllIndexes();
26
+ await promises_1.default.writeFile(path_1.default.join(this.args.dumpDirectory, "indexes.json"), JSON.stringify(indexesResult));
27
+ this.logOk("Elasticsearch indexes dumped!");
28
+ // Dump all the documents
29
+ this.logInfo("Dumping Elasticsearch documents...");
30
+ await this.dumpAllDocuments();
31
+ this.logOk("Elasticsearch documents dumped!");
32
+ this.logOk(`The dumped files are available under "${path_1.default.resolve(this.args.dumpDirectory)}"`);
33
+ }
34
+ /**
35
+ * @description Get all indexes from the Elasticsearch of the PaaS application.
36
+ * @returns The indexes.
37
+ */
38
+ async getAllIndexes() {
39
+ const { result } = await this.paas.query({
40
+ controller: "application/storage",
41
+ action: "getIndexes",
42
+ environmentId: this.args.environment,
43
+ projectId: this.flags.project || this.getProject(),
44
+ applicationId: this.args.applicationId,
45
+ body: {},
46
+ });
47
+ return result;
48
+ }
49
+ /**
50
+ * @description Dump documents from the Elasticsearch of the PaaS application.
51
+ * @param pitId ID of the PIT opened on Elasticsearch.
52
+ * @param searchAfter Cursor for dumping documents after a certain one.
53
+ * @returns The dumped documents.
54
+ */
55
+ async dumpDocuments(pitId, searchAfter) {
56
+ const { result } = await this.paas.query({
57
+ controller: "application/storage",
58
+ action: "dumpDocuments",
59
+ environmentId: this.args.environment,
60
+ projectId: this.flags.project || this.getProject(),
61
+ applicationId: this.args.applicationId,
62
+ body: {
63
+ pitId,
64
+ searchAfter: JSON.stringify(searchAfter),
65
+ size: this.flags["batch-size"],
66
+ },
67
+ });
68
+ return result;
69
+ }
70
+ async dumpAllDocuments() {
71
+ // Prepare dumping all documents
72
+ let pitId = "";
73
+ let searchAfter = [];
74
+ let dumpedDocuments = 0;
75
+ let totalDocuments = 0;
76
+ const fd = await promises_1.default.open(path_1.default.join(this.args.dumpDirectory, "documents.jsonl"), "w");
77
+ const writeStream = fd.createWriteStream();
78
+ const ndjsonStream = ndjson_1.default.stringify();
79
+ writeStream.on("error", (error) => {
80
+ throw error;
81
+ });
82
+ ndjsonStream.on("data", (line) => {
83
+ writeStream.write(line);
84
+ });
85
+ const teardown = async () => {
86
+ // Finish the dump session if a PIT ID is set
87
+ if (pitId.length > 0) {
88
+ await this.finishDump(pitId);
89
+ }
90
+ // Close the open streams/file
91
+ writeStream.close();
92
+ await fd.close();
93
+ };
94
+ try {
95
+ // Dump the first batch
96
+ let result = await this.dumpDocuments(pitId, searchAfter);
97
+ let hits = result.hits.hits;
98
+ while (hits.length > 0) {
99
+ // Update the PIT ID and the cursor for the next dump
100
+ pitId = result.pit_id;
101
+ searchAfter = hits[hits.length - 1].sort;
102
+ // Save the documents
103
+ for (let i = 0; i < hits.length; ++i) {
104
+ ndjsonStream.write(hits[i]);
105
+ }
106
+ dumpedDocuments += hits.length;
107
+ totalDocuments = result.hits.total.value;
108
+ this.logInfo(`Dumping Elasticsearch documents: ${Math.floor(dumpedDocuments / totalDocuments * 100)}% (${dumpedDocuments}/${totalDocuments})`);
109
+ // Dump the next batch
110
+ result = await this.dumpDocuments(pitId, searchAfter);
111
+ hits = result.hits.hits;
112
+ }
113
+ }
114
+ catch (error) {
115
+ teardown();
116
+ this.logKo(`Error while dumping the documents: ${error}`);
117
+ process.exit(1);
118
+ }
119
+ // Finish the dump
120
+ teardown();
121
+ }
122
+ /**
123
+ * @description Finish the document dumping session.
124
+ * @param pitId ID of the PIT opened on Elasticsearch.
125
+ */
126
+ async finishDump(pitId) {
127
+ try {
128
+ await this.paas.query({
129
+ controller: "application/storage",
130
+ action: "finishDumpDocuments",
131
+ environmentId: this.args.environment,
132
+ projectId: this.flags.project || this.getProject(),
133
+ applicationId: this.args.applicationId,
134
+ body: {
135
+ pitId,
136
+ },
137
+ });
138
+ }
139
+ catch (error) {
140
+ this.logInfo(`Unable to cleanly finish the dump session: ${error}`);
141
+ }
142
+ }
143
+ }
144
+ PaasEsDump.description = "Dump data from the Elasticsearch of a PaaS application";
145
+ PaasEsDump.flags = {
146
+ help: command_1.flags.help(),
147
+ project: command_1.flags.string({
148
+ description: "Current PaaS project",
149
+ }),
150
+ "batch-size": command_1.flags.integer({
151
+ description: "Maximum batch size",
152
+ default: 2000,
153
+ }),
154
+ };
155
+ PaasEsDump.args = [
156
+ {
157
+ name: "environment",
158
+ description: "Project environment name",
159
+ required: true,
160
+ },
161
+ {
162
+ name: "applicationId",
163
+ description: "Application Identifier",
164
+ required: true,
165
+ },
166
+ {
167
+ name: "dumpDirectory",
168
+ description: "Directory where to store dump files",
169
+ required: true,
170
+ }
171
+ ];
172
+ exports.default = PaasEsDump;
@@ -14,10 +14,7 @@ class PaasSnapshotsRestore extends PaasKommand_1.PaasKommand {
14
14
  environmentId: this.args.environment,
15
15
  projectId: this.flags.project || this.getProject(),
16
16
  applicationId: this.args.applicationId,
17
- body: {
18
- repository: "automated",
19
- snapshot: this.args.snapshotId,
20
- },
17
+ snapshotId: this.args.snapshotId
21
18
  });
22
19
  this.logInfo("Ok");
23
20
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kourou",
3
3
  "description": "The CLI that helps you manage your Kuzzle instances",
4
- "version": "0.27.1",
4
+ "version": "0.28.0",
5
5
  "author": "The Kuzzle Team <support@kuzzle.io>",
6
6
  "bin": {
7
7
  "kourou": "./bin/run"
@@ -56,7 +56,7 @@
56
56
  "@types/listr": "^0.14.2",
57
57
  "@types/mocha": "^8.2.2",
58
58
  "@types/ndjson": "^2.0.0",
59
- "@types/node": "^14.14.41",
59
+ "@types/node": "^18.19.0",
60
60
  "@types/node-emoji": "^1.8.1",
61
61
  "@types/node-fetch": "^2.6.1",
62
62
  "@types/tar": "^6.1.3",