kourou 0.25.1 → 0.25.2
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 +6 -1
- package/lib/commands/collection/export.d.ts +1 -0
- package/lib/commands/collection/export.js +12 -3
- package/lib/commands/index/export.d.ts +1 -0
- package/lib/commands/index/export.js +12 -2
- package/lib/commands/paas/logs.js +23 -8
- package/lib/support/dump-collection.js +1 -0
- package/lib/support/kuzzle.js +1 -1
- package/lib/support/restore-collection.js +6 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ $ npm install -g kourou
|
|
|
26
26
|
$ kourou COMMAND
|
|
27
27
|
running command...
|
|
28
28
|
$ kourou (-v|--version|version)
|
|
29
|
-
kourou/0.25.
|
|
29
|
+
kourou/0.25.2 linux-x64 node-v14.20.0
|
|
30
30
|
$ kourou --help [COMMAND]
|
|
31
31
|
USAGE
|
|
32
32
|
$ kourou COMMAND
|
|
@@ -506,6 +506,9 @@ OPTIONS
|
|
|
506
506
|
--ssl
|
|
507
507
|
Use SSL to connect to Kuzzle
|
|
508
508
|
|
|
509
|
+
--type=type
|
|
510
|
+
[default: all] Type of the export: all, mappings, data
|
|
511
|
+
|
|
509
512
|
--username=username
|
|
510
513
|
[default: anonymous] Kuzzle username (local strategy)
|
|
511
514
|
|
|
@@ -938,6 +941,8 @@ OPTIONS
|
|
|
938
941
|
|
|
939
942
|
--ssl Use SSL to connect to Kuzzle
|
|
940
943
|
|
|
944
|
+
--type=type [default: all] Type of the export: all, mappings, data
|
|
945
|
+
|
|
941
946
|
--username=username [default: anonymous] Kuzzle username (local strategy)
|
|
942
947
|
|
|
943
948
|
EXAMPLES
|
|
@@ -22,10 +22,16 @@ class CollectionExport extends common_1.Kommand {
|
|
|
22
22
|
}
|
|
23
23
|
const countAll = await this.sdk.document.count(this.args.index, this.args.collection);
|
|
24
24
|
const count = await this.sdk.document.count(this.args.index, this.args.collection, { query });
|
|
25
|
-
this.logInfo(`Dumping
|
|
25
|
+
this.logInfo(`Dumping collection "${this.args.index}:${this.args.collection}" in ${exportPath} ...`);
|
|
26
26
|
fs_1.default.mkdirSync(exportPath, { recursive: true });
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
if (this.flags.type === "all" || this.flags.type === "mappings") {
|
|
28
|
+
this.logInfo(`Dumping collection mappings ...`);
|
|
29
|
+
await (0, dump_collection_1.dumpCollectionMappings)(this.sdk, this.args.index, this.args.collection, exportPath, this.flags.format);
|
|
30
|
+
}
|
|
31
|
+
if (this.flags.type === "all" || this.flags.type === "data") {
|
|
32
|
+
this.logInfo(`Dumping collection ${count} of ${countAll} documents ...`);
|
|
33
|
+
await (0, dump_collection_1.dumpCollectionData)(this.sdk, this.args.index, this.args.collection, Number(this.flags["batch-size"]), exportPath, query, this.flags.format, fields, this.flags.scrollTTL);
|
|
34
|
+
}
|
|
29
35
|
this.logOk(`Collection ${this.args.index}:${this.args.collection} dumped`);
|
|
30
36
|
}
|
|
31
37
|
}
|
|
@@ -60,6 +66,9 @@ exportable fields in the mapping will be exported.`,
|
|
|
60
66
|
description: `The scroll TTL option to pass to the dump operation (which performs a document.search under the hood),
|
|
61
67
|
expressed in ms format, e.g. '2s', '1m', '3h'.`,
|
|
62
68
|
default: "20s",
|
|
69
|
+
}), type: command_1.flags.string({
|
|
70
|
+
description: "Type of the export: all, mappings, data",
|
|
71
|
+
default: "all",
|
|
63
72
|
}) }, kuzzle_1.kuzzleFlags), { protocol: command_1.flags.string({
|
|
64
73
|
description: "Kuzzle protocol (http or websocket)",
|
|
65
74
|
default: "ws",
|
|
@@ -5,6 +5,7 @@ export default class IndexExport extends Kommand {
|
|
|
5
5
|
static description: string;
|
|
6
6
|
static flags: {
|
|
7
7
|
protocol: flags.IOptionFlag<string>;
|
|
8
|
+
type: flags.IOptionFlag<string>;
|
|
8
9
|
host: flags.IOptionFlag<string>;
|
|
9
10
|
port: flags.IOptionFlag<string>;
|
|
10
11
|
ssl: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
|
@@ -19,11 +19,18 @@ class IndexExport extends common_1.Kommand {
|
|
|
19
19
|
const { collections } = await this.sdk.collection.list(this.args.index);
|
|
20
20
|
for (const collection of collections) {
|
|
21
21
|
try {
|
|
22
|
-
if (collection.type
|
|
22
|
+
if (collection.type === "realtime") {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (this.flags.type === "all" || this.flags.type === "mappings") {
|
|
26
|
+
this.logInfo(`Dumping collection "${collection.name}" mappings ...`);
|
|
23
27
|
await (0, dump_collection_1.dumpCollectionMappings)(this.sdk, this.args.index, collection.name, exportPath, this.flags.format);
|
|
28
|
+
}
|
|
29
|
+
if (this.flags.type === "all" || this.flags.type === "data") {
|
|
30
|
+
this.logInfo(`Dumping collection "${collection.name}" documents ...`);
|
|
24
31
|
await (0, dump_collection_1.dumpCollectionData)(this.sdk, this.args.index, collection.name, Number(this.flags["batch-size"]), exportPath, query, this.flags.format, this.flags.scrollTTL);
|
|
25
|
-
cli_ux_1.default.action.stop();
|
|
26
32
|
}
|
|
33
|
+
cli_ux_1.default.action.stop();
|
|
27
34
|
}
|
|
28
35
|
catch (error) {
|
|
29
36
|
this.logKo(`Error when exporting collection "${collection.name}": ${error}`);
|
|
@@ -53,6 +60,9 @@ expressed in ms format, e.g. '2s', '1m', '3h'.`,
|
|
|
53
60
|
}) }, kuzzle_1.kuzzleFlags), { protocol: command_1.flags.string({
|
|
54
61
|
description: "Kuzzle protocol (http or websocket)",
|
|
55
62
|
default: "ws",
|
|
63
|
+
}), type: command_1.flags.string({
|
|
64
|
+
description: "Type of the export: all, mappings, data",
|
|
65
|
+
default: "all",
|
|
56
66
|
}) });
|
|
57
67
|
IndexExport.args = [{ name: "index", description: "Index name", required: true }];
|
|
58
68
|
IndexExport.examples = [
|
|
@@ -15,7 +15,15 @@ class PaasLogs extends PaasKommand_1.PaasKommand {
|
|
|
15
15
|
/**
|
|
16
16
|
* Allowed colors for pod names.
|
|
17
17
|
*/
|
|
18
|
-
this.allColors = [
|
|
18
|
+
this.allColors = [
|
|
19
|
+
chalk_1.default.red,
|
|
20
|
+
chalk_1.default.green,
|
|
21
|
+
chalk_1.default.yellow,
|
|
22
|
+
chalk_1.default.blue,
|
|
23
|
+
chalk_1.default.magenta,
|
|
24
|
+
chalk_1.default.cyan,
|
|
25
|
+
chalk_1.default.gray,
|
|
26
|
+
];
|
|
19
27
|
/**
|
|
20
28
|
* Available colors for pod names.
|
|
21
29
|
*/
|
|
@@ -34,8 +42,12 @@ class PaasLogs extends PaasKommand_1.PaasKommand {
|
|
|
34
42
|
this.logInfo(`Logged as "${user._id}" for project "${this.flags.project || this.getProject()}"`);
|
|
35
43
|
const separator = "\t";
|
|
36
44
|
// Parse the time arguments
|
|
37
|
-
const since = this.flags.since
|
|
38
|
-
|
|
45
|
+
const since = this.flags.since
|
|
46
|
+
? chrono.parseDate(this.flags.since).toISOString()
|
|
47
|
+
: undefined;
|
|
48
|
+
const until = this.flags.until
|
|
49
|
+
? chrono.parseDate(this.flags.until).toISOString()
|
|
50
|
+
: undefined;
|
|
39
51
|
// Perform the streamed request
|
|
40
52
|
const incomingMessage = await this.paas.queryHttpStream({
|
|
41
53
|
controller: "application",
|
|
@@ -63,18 +75,19 @@ class PaasLogs extends PaasKommand_1.PaasKommand {
|
|
|
63
75
|
const data = JSON.parse(line);
|
|
64
76
|
// Exclude logs that are empty or that are not from a pod
|
|
65
77
|
if (!data.content || !data.podName) {
|
|
66
|
-
this.logKo(line);
|
|
67
78
|
continue;
|
|
68
79
|
}
|
|
69
80
|
// Get the pod color
|
|
70
81
|
const podColor = this.getPodColor(data.podName);
|
|
71
82
|
// Display the log
|
|
72
|
-
const timestamp = this.flags.timestamp
|
|
83
|
+
const timestamp = this.flags.timestamp
|
|
84
|
+
? `[${new Date(data.timeStamp).toLocaleString()}] `
|
|
85
|
+
: "";
|
|
73
86
|
const name = podColor(`${data.podName}${separator}`);
|
|
74
87
|
this.log(`${timestamp}${name}| ${data.content}`);
|
|
75
88
|
}
|
|
76
89
|
catch (error) {
|
|
77
|
-
this.logKo(`
|
|
90
|
+
this.logKo(`Error while parsing log: ${error} (Received: "${line}")`);
|
|
78
91
|
}
|
|
79
92
|
}
|
|
80
93
|
}
|
|
@@ -106,13 +119,15 @@ class PaasLogs extends PaasKommand_1.PaasKommand {
|
|
|
106
119
|
}
|
|
107
120
|
getNumberOfSpaces(names, currentName) {
|
|
108
121
|
const end = 10;
|
|
109
|
-
let max = { name:
|
|
122
|
+
let max = { name: "", length: 0 };
|
|
110
123
|
for (const name of names) {
|
|
111
124
|
if (max.length < name.length) {
|
|
112
125
|
max = { name: name, length: name.length };
|
|
113
126
|
}
|
|
114
127
|
}
|
|
115
|
-
return currentName === max.name
|
|
128
|
+
return currentName === max.name
|
|
129
|
+
? end
|
|
130
|
+
: end + (max.length - currentName.length);
|
|
116
131
|
}
|
|
117
132
|
/**
|
|
118
133
|
* Returns the color to use for a pod name.
|
|
@@ -81,6 +81,7 @@ class AbstractDumper {
|
|
|
81
81
|
* @returns a promise resolving when the dump is finished.
|
|
82
82
|
*/
|
|
83
83
|
async dump() {
|
|
84
|
+
fs_1.default.mkdirSync(this.collectionDir, { recursive: true });
|
|
84
85
|
this.filename = path_1.default.join(this.collectionDir, `documents.${this.fileExtension}`);
|
|
85
86
|
this.writeStream = fs_1.default.createWriteStream(this.filename);
|
|
86
87
|
const waitWrite = new Promise((resolve, reject) => this.writeStream ? this.writeStream.on("finish", resolve) : reject());
|
package/lib/support/kuzzle.js
CHANGED
|
@@ -164,7 +164,7 @@ class KuzzleSDK {
|
|
|
164
164
|
const options = {
|
|
165
165
|
method: "POST",
|
|
166
166
|
headers: {
|
|
167
|
-
|
|
167
|
+
Authorization: `Bearer ${this.sdk.jwt}`,
|
|
168
168
|
"Content-Length": Buffer.byteLength(body),
|
|
169
169
|
"Content-Type": "application/json",
|
|
170
170
|
},
|
|
@@ -6,18 +6,16 @@ const fs_1 = (0, tslib_1.__importDefault)(require("fs"));
|
|
|
6
6
|
const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
|
|
7
7
|
const ndjson_1 = (0, tslib_1.__importDefault)(require("ndjson"));
|
|
8
8
|
function handleError(log, dumpFile, error) {
|
|
9
|
-
if (error.
|
|
9
|
+
if (error.errors) {
|
|
10
10
|
const errorFile = `${dumpFile
|
|
11
11
|
.split(".")
|
|
12
12
|
.slice(0, -1)
|
|
13
13
|
.join(".")}-errors.jsonl`;
|
|
14
14
|
const writeStream = fs_1.default.createWriteStream(errorFile, { flags: "a" });
|
|
15
|
-
const serialize = ndjson_1.default.stringify().pipe(writeStream);
|
|
16
|
-
serialize.on("data", (line) => writeStream.write(line));
|
|
17
15
|
for (const partialError of error.errors) {
|
|
18
|
-
|
|
16
|
+
writeStream.write(JSON.stringify(partialError) + '\n');
|
|
19
17
|
}
|
|
20
|
-
|
|
18
|
+
writeStream.end();
|
|
21
19
|
log(chalk_1.default.red(`[X] Error importing ${dumpFile}. See errors in ${errorFile}`));
|
|
22
20
|
}
|
|
23
21
|
else {
|
|
@@ -31,6 +29,7 @@ async function restoreCollectionData(sdk, log, batchSize, dumpFile, index, colle
|
|
|
31
29
|
action: "mWrite",
|
|
32
30
|
index: "",
|
|
33
31
|
collection: "",
|
|
32
|
+
strict: true,
|
|
34
33
|
body: {
|
|
35
34
|
documents: [{}],
|
|
36
35
|
},
|
|
@@ -90,8 +89,8 @@ async function restoreCollectionData(sdk, log, batchSize, dumpFile, index, colle
|
|
|
90
89
|
mWriteRequest.body.documents = documents;
|
|
91
90
|
sdk
|
|
92
91
|
.query(mWriteRequest)
|
|
93
|
-
.then(() => {
|
|
94
|
-
total +=
|
|
92
|
+
.then((response) => {
|
|
93
|
+
total += response.result.successes.length;
|
|
95
94
|
process.stdout.write(` ${total} documents imported`);
|
|
96
95
|
process.stdout.write("\r");
|
|
97
96
|
resolve(undefined);
|