kourou 1.0.1 → 1.1.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 +7 -1
- package/lib/commands/app/scaffold.js +7 -6
- package/lib/commands/es/migrate.d.ts +1 -0
- package/lib/commands/es/migrate.js +13 -0
- package/lib/support/migrate/providers/elasticsearch.d.ts +1 -0
- package/lib/support/migrate/providers/elasticsearch.js +36 -3
- package/package.json +1 -1
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/1.0
|
|
30
|
+
kourou/1.1.0 linux-x64 node-v22.14.0
|
|
31
31
|
$ kourou --help [COMMAND]
|
|
32
32
|
USAGE
|
|
33
33
|
$ kourou COMMAND
|
|
@@ -719,12 +719,18 @@ OPTIONS
|
|
|
719
719
|
--dry-run Print witch collections will be migrated
|
|
720
720
|
--help show CLI help
|
|
721
721
|
--no-interactive Skip confirmation interactive prompts (perfect for scripting)
|
|
722
|
+
--only-mappings Only migrate mappings
|
|
722
723
|
--pattern=pattern Pattern to match indices to migrate
|
|
723
724
|
--reset Reset destination Elasticsearch server
|
|
724
725
|
--scroll=scroll [default: 30s] Scroll duration for Elasticsearch scrolling
|
|
725
726
|
--src=src (required) Migration source provider
|
|
726
727
|
|
|
727
728
|
EXAMPLES
|
|
729
|
+
kourou es:migrate --src http://elasticsearch:9200 --dest ./my-backup
|
|
730
|
+
kourou es:migrate --src ./my-backup --dest http://elasticsearch:9200
|
|
731
|
+
kourou es:migrate --src ./my-backup --dest http://username:password@elasticsearch:9200 --reset
|
|
732
|
+
kourou es:migrate --src ./my-backup --dest http://nologin:api-key@elasticsearch:9200 --reset // nologin is a special
|
|
733
|
+
username that allows you to use an API key as password
|
|
728
734
|
kourou es:migrate --src http://elasticsearch:9200 --dest ./my-backup --batch-size 2000 --pattern
|
|
729
735
|
'&myindexes.collection-*'
|
|
730
736
|
kourou es:migrate --src ./my-backup --dest http://elasticsearch:9200 --reset --batch-size 2000 --no-interactive
|
|
@@ -25,15 +25,16 @@ class AppScaffold extends common_1.Kommand {
|
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
title: "Cloning template repository",
|
|
28
|
-
task: async () => this.cloneTemplate(flavor)
|
|
29
|
-
},
|
|
28
|
+
task: async () => this.cloneTemplate(flavor),
|
|
29
|
+
},
|
|
30
|
+
{
|
|
30
31
|
title: "Copying template files",
|
|
31
|
-
task: async () => this.copyTemplate(destination)
|
|
32
|
+
task: async () => this.copyTemplate(destination),
|
|
32
33
|
},
|
|
33
34
|
{
|
|
34
35
|
title: "Cleaning up",
|
|
35
|
-
task: async () => this.cleanup(destination)
|
|
36
|
-
}
|
|
36
|
+
task: async () => this.cleanup(destination),
|
|
37
|
+
},
|
|
37
38
|
]);
|
|
38
39
|
await tasks.run();
|
|
39
40
|
this.log("");
|
|
@@ -70,7 +71,7 @@ class AppScaffold extends common_1.Kommand {
|
|
|
70
71
|
}
|
|
71
72
|
async cloneTemplate(flavor) {
|
|
72
73
|
const repo = this.getRepo(flavor);
|
|
73
|
-
await (0, execute_1.execute)("git", "clone", "--depth=1", `https://github.com/kuzzleio/${repo}`, "--branch", "
|
|
74
|
+
await (0, execute_1.execute)("git", "clone", "--depth=1", `https://github.com/kuzzleio/${repo}`, "--branch", "main", "--single-branch", this.templatesDir);
|
|
74
75
|
}
|
|
75
76
|
async copyTemplate(destination) {
|
|
76
77
|
await (0, execute_1.execute)("cp", "-r", `${this.templatesDir}/`, `${destination}/`);
|
|
@@ -13,6 +13,7 @@ export default class EsMigrate extends Kommand {
|
|
|
13
13
|
"dry-run": import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
|
14
14
|
pattern: flags.IOptionFlag<string | undefined>;
|
|
15
15
|
scroll: flags.IOptionFlag<string>;
|
|
16
|
+
"only-mappings": import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
|
16
17
|
};
|
|
17
18
|
static examples: string[];
|
|
18
19
|
private src;
|
|
@@ -65,6 +65,11 @@ class EsMigrate extends common_1.Kommand {
|
|
|
65
65
|
this.logInfo(`Importing ${chalk_1.default.bold(index)} to ${chalk_1.default.bold(this.flags.dest)}`);
|
|
66
66
|
await this.migrateIndex(index);
|
|
67
67
|
this.logOk("Mappings successfully imported!");
|
|
68
|
+
if (this.flags["only-mappings"]) {
|
|
69
|
+
this.logInfo("Skipping data import");
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
this.logInfo("Importing data...");
|
|
68
73
|
const count = await this.migrateData(index);
|
|
69
74
|
if (count === 0) {
|
|
70
75
|
this.logInfo("No documents to import\n");
|
|
@@ -134,8 +139,16 @@ EsMigrate.flags = {
|
|
|
134
139
|
description: "Scroll duration for Elasticsearch scrolling",
|
|
135
140
|
default: "30s",
|
|
136
141
|
}),
|
|
142
|
+
"only-mappings": command_1.flags.boolean({
|
|
143
|
+
description: "Only migrate mappings",
|
|
144
|
+
default: false,
|
|
145
|
+
}),
|
|
137
146
|
};
|
|
138
147
|
EsMigrate.examples = [
|
|
148
|
+
"kourou es:migrate --src http://elasticsearch:9200 --dest ./my-backup",
|
|
149
|
+
"kourou es:migrate --src ./my-backup --dest http://elasticsearch:9200",
|
|
150
|
+
"kourou es:migrate --src ./my-backup --dest http://username:password@elasticsearch:9200 --reset",
|
|
151
|
+
"kourou es:migrate --src ./my-backup --dest http://nologin:api-key@elasticsearch:9200 --reset // nologin is a special username that allows you to use an API key as password",
|
|
139
152
|
"kourou es:migrate --src http://elasticsearch:9200 --dest ./my-backup --batch-size 2000 --pattern '&myindexes.collection-*'",
|
|
140
153
|
"kourou es:migrate --src ./my-backup --dest http://elasticsearch:9200 --reset --batch-size 2000 --no-interactive",
|
|
141
154
|
];
|
|
@@ -7,6 +7,7 @@ export declare class Elasticsearch implements Provider {
|
|
|
7
7
|
private readonly client;
|
|
8
8
|
private readonly options;
|
|
9
9
|
constructor(url: string, options: ElasticsearchProviderOptions);
|
|
10
|
+
private extractCredentials;
|
|
10
11
|
listIndices(pattern?: string): Promise<string[]>;
|
|
11
12
|
getIndex(index: string): Promise<any>;
|
|
12
13
|
createIndex(index: string, specifications: any): Promise<void>;
|
|
@@ -4,9 +4,42 @@ exports.Elasticsearch = void 0;
|
|
|
4
4
|
const elasticsearch_1 = require("@elastic/elasticsearch");
|
|
5
5
|
class Elasticsearch {
|
|
6
6
|
constructor(url, options) {
|
|
7
|
-
|
|
7
|
+
const { auth, url: cleanedUrl } = this.extractCredentials(url);
|
|
8
|
+
this.client = new elasticsearch_1.Client({
|
|
9
|
+
node: cleanedUrl,
|
|
10
|
+
auth,
|
|
11
|
+
});
|
|
8
12
|
this.options = options;
|
|
9
13
|
}
|
|
14
|
+
extractCredentials(url) {
|
|
15
|
+
let auth = undefined;
|
|
16
|
+
if (url.includes("@")) {
|
|
17
|
+
const urlCleaned = url.replace(/https?:\/\//, "");
|
|
18
|
+
const [credentials] = urlCleaned.split("@");
|
|
19
|
+
const [username, password] = credentials.split(":");
|
|
20
|
+
if (!username || !password) {
|
|
21
|
+
throw new Error("Invalid credentials format. Expected format: username:password@url");
|
|
22
|
+
}
|
|
23
|
+
if (username === "nologin" && password) {
|
|
24
|
+
auth = {
|
|
25
|
+
apiKey: password,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
else if (username && password) {
|
|
29
|
+
auth = {
|
|
30
|
+
username,
|
|
31
|
+
password,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if (url.startsWith("http://")) {
|
|
35
|
+
url = url.replace(/https?:\/\/[^@]+@/, "http://");
|
|
36
|
+
}
|
|
37
|
+
else if (url.startsWith("https://")) {
|
|
38
|
+
url = url.replace(/https?:\/\/[^@]+@/, "https://");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return { auth, url };
|
|
42
|
+
}
|
|
10
43
|
async listIndices(pattern) {
|
|
11
44
|
const { body } = await this.client.cat.indices({ format: "json" });
|
|
12
45
|
return body
|
|
@@ -48,13 +81,13 @@ class Elasticsearch {
|
|
|
48
81
|
return {
|
|
49
82
|
documents: body.hits.hits,
|
|
50
83
|
total: body.hits.total.value,
|
|
51
|
-
scrollId: body._scroll_id
|
|
84
|
+
scrollId: body._scroll_id,
|
|
52
85
|
};
|
|
53
86
|
}
|
|
54
87
|
else {
|
|
55
88
|
const { body: { hits }, } = await this.client.scroll({
|
|
56
89
|
scroll_id: args.scrollId,
|
|
57
|
-
scroll: this.options.scrollDuration
|
|
90
|
+
scroll: this.options.scrollDuration,
|
|
58
91
|
});
|
|
59
92
|
return hits.hits;
|
|
60
93
|
}
|