kourou 0.21.1 → 0.22.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 +43 -21
- package/lib/commands/es/migrate.d.ts +5 -2
- package/lib/commands/es/migrate.js +48 -27
- package/lib/commands/paas/{publish.d.ts → deploy.d.ts} +3 -3
- package/lib/commands/paas/{publish.js → deploy.js} +25 -21
- package/lib/commands/paas/init.js +3 -13
- package/lib/commands/paas/login.d.ts +3 -2
- package/lib/commands/paas/login.js +32 -10
- package/lib/commands/paas/logs.d.ts +17 -0
- package/lib/commands/paas/logs.js +54 -0
- package/lib/common.js +7 -2
- package/lib/support/PaasKommand.d.ts +4 -4
- package/lib/support/PaasKommand.js +17 -11
- package/lib/support/kuzzle.d.ts +1 -1
- package/package.json +3 -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.
|
|
29
|
+
kourou/0.22.0 linux-x64 node-v16.15.0
|
|
30
30
|
$ kourou --help [COMMAND]
|
|
31
31
|
USAGE
|
|
32
32
|
$ kourou COMMAND
|
|
@@ -155,9 +155,10 @@ All other arguments and options will be passed as-is to the `sdk:query` method.
|
|
|
155
155
|
* [`kourou instance:list`](#kourou-instancelist)
|
|
156
156
|
* [`kourou instance:logs`](#kourou-instancelogs)
|
|
157
157
|
* [`kourou instance:spawn`](#kourou-instancespawn)
|
|
158
|
-
* [`kourou paas:
|
|
158
|
+
* [`kourou paas:deploy ENVIRONMENT IMAGE`](#kourou-paasdeploy-environment-image)
|
|
159
|
+
* [`kourou paas:init PROJECT`](#kourou-paasinit-project)
|
|
159
160
|
* [`kourou paas:login`](#kourou-paaslogin)
|
|
160
|
-
* [`kourou paas:
|
|
161
|
+
* [`kourou paas:logs ENVIRONMENT APPLICATION`](#kourou-paaslogs-environment-application)
|
|
161
162
|
* [`kourou profile:export`](#kourou-profileexport)
|
|
162
163
|
* [`kourou profile:import PATH`](#kourou-profileimport-path)
|
|
163
164
|
* [`kourou realtime:subscribe INDEX COLLECTION [FILTERS]`](#kourou-realtimesubscribe-index-collection-filters)
|
|
@@ -602,9 +603,12 @@ USAGE
|
|
|
602
603
|
OPTIONS
|
|
603
604
|
--batch-size=batch-size [default: 1000] How many documents to move in batch per operation
|
|
604
605
|
--dest=dest (required) Destination Elasticsearch server URL
|
|
606
|
+
--dry-run Print witch collections will be migrated
|
|
605
607
|
--help show CLI help
|
|
606
608
|
--no-interactive Skip confirmation interactive prompts (perfect for scripting)
|
|
609
|
+
--pattern=pattern Pattern to match indices to migrate
|
|
607
610
|
--reset Reset destination Elasticsearch server
|
|
611
|
+
--scroll=scroll [default: 30s] Scroll duration for Elasticsearch scrolling
|
|
608
612
|
--src=src (required) Source Elasticsearch server URL
|
|
609
613
|
|
|
610
614
|
EXAMPLES
|
|
@@ -915,17 +919,36 @@ OPTIONS
|
|
|
915
919
|
|
|
916
920
|
_See code: [src/commands/instance/spawn.ts](src/commands/instance/spawn.ts)_
|
|
917
921
|
|
|
918
|
-
## `kourou paas:
|
|
922
|
+
## `kourou paas:deploy ENVIRONMENT IMAGE`
|
|
919
923
|
|
|
920
|
-
|
|
924
|
+
Deploy a new version of the application in the PaaS
|
|
925
|
+
|
|
926
|
+
```
|
|
927
|
+
USAGE
|
|
928
|
+
$ kourou paas:deploy ENVIRONMENT IMAGE
|
|
929
|
+
|
|
930
|
+
ARGUMENTS
|
|
931
|
+
ENVIRONMENT Project environment name
|
|
932
|
+
IMAGE Image name and hash as myimage:mytag
|
|
933
|
+
|
|
934
|
+
OPTIONS
|
|
935
|
+
--help show CLI help
|
|
936
|
+
--project=project Current PaaS project
|
|
937
|
+
--token=token Authentication token
|
|
938
|
+
```
|
|
939
|
+
|
|
940
|
+
_See code: [src/commands/paas/deploy.ts](src/commands/paas/deploy.ts)_
|
|
941
|
+
|
|
942
|
+
## `kourou paas:init PROJECT`
|
|
943
|
+
|
|
944
|
+
Initialize a PaaS project in current directory
|
|
921
945
|
|
|
922
946
|
```
|
|
923
947
|
USAGE
|
|
924
|
-
$ kourou paas:init
|
|
948
|
+
$ kourou paas:init PROJECT
|
|
925
949
|
|
|
926
950
|
ARGUMENTS
|
|
927
|
-
|
|
928
|
-
NAMESPACE Namespace
|
|
951
|
+
PROJECT Kuzzle PaaS project name
|
|
929
952
|
|
|
930
953
|
OPTIONS
|
|
931
954
|
--help show CLI help
|
|
@@ -935,39 +958,38 @@ _See code: [src/commands/paas/init.ts](src/commands/paas/init.ts)_
|
|
|
935
958
|
|
|
936
959
|
## `kourou paas:login`
|
|
937
960
|
|
|
938
|
-
Login for a PaaS
|
|
961
|
+
Login for a PaaS project
|
|
939
962
|
|
|
940
963
|
```
|
|
941
964
|
USAGE
|
|
942
965
|
$ kourou paas:login
|
|
943
966
|
|
|
944
967
|
OPTIONS
|
|
945
|
-
--help
|
|
946
|
-
--
|
|
947
|
-
--username=username
|
|
968
|
+
--help show CLI help
|
|
969
|
+
--project=project Current PaaS project
|
|
970
|
+
--username=username PaaS username
|
|
948
971
|
```
|
|
949
972
|
|
|
950
973
|
_See code: [src/commands/paas/login.ts](src/commands/paas/login.ts)_
|
|
951
974
|
|
|
952
|
-
## `kourou paas:
|
|
975
|
+
## `kourou paas:logs ENVIRONMENT APPLICATION`
|
|
953
976
|
|
|
954
|
-
|
|
977
|
+
Show logs of the targeted application
|
|
955
978
|
|
|
956
979
|
```
|
|
957
980
|
USAGE
|
|
958
|
-
$ kourou paas:
|
|
981
|
+
$ kourou paas:logs ENVIRONMENT APPLICATION
|
|
959
982
|
|
|
960
983
|
ARGUMENTS
|
|
961
|
-
|
|
962
|
-
|
|
984
|
+
ENVIRONMENT Kuzzle PaaS environment
|
|
985
|
+
APPLICATION Kuzzle PaaS application
|
|
963
986
|
|
|
964
987
|
OPTIONS
|
|
965
|
-
--help
|
|
966
|
-
--
|
|
967
|
-
--token=token Authentication token
|
|
988
|
+
--help show CLI help
|
|
989
|
+
--project=project Current PaaS project
|
|
968
990
|
```
|
|
969
991
|
|
|
970
|
-
_See code: [src/commands/paas/
|
|
992
|
+
_See code: [src/commands/paas/logs.ts](src/commands/paas/logs.ts)_
|
|
971
993
|
|
|
972
994
|
## `kourou profile:export`
|
|
973
995
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { flags } from '@oclif/command';
|
|
2
|
+
import { Client } from '@elastic/elasticsearch';
|
|
2
3
|
import { Kommand } from '../../common';
|
|
3
4
|
export default class EsMigrate extends Kommand {
|
|
4
5
|
static initSdk: boolean;
|
|
@@ -10,11 +11,13 @@ export default class EsMigrate extends Kommand {
|
|
|
10
11
|
reset: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
|
11
12
|
'batch-size': import("@oclif/parser/lib/flags").IOptionFlag<number>;
|
|
12
13
|
'no-interactive': import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
|
14
|
+
'dry-run': import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
|
15
|
+
pattern: flags.IOptionFlag<string | undefined>;
|
|
16
|
+
scroll: flags.IOptionFlag<string>;
|
|
13
17
|
};
|
|
14
18
|
static examples: string[];
|
|
15
|
-
private src;
|
|
16
|
-
private dest;
|
|
17
19
|
private migrateMappings;
|
|
18
20
|
private migrateData;
|
|
21
|
+
runMigrate(index: string, src: Client, dest: Client): Promise<void>;
|
|
19
22
|
runSafe(): Promise<void>;
|
|
20
23
|
}
|
|
@@ -8,16 +8,16 @@ const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
|
8
8
|
const node_emoji_1 = tslib_1.__importDefault(require("node-emoji"));
|
|
9
9
|
const common_1 = require("../../common");
|
|
10
10
|
class EsMigrate extends common_1.Kommand {
|
|
11
|
-
async migrateMappings(index) {
|
|
12
|
-
const { body } = await
|
|
11
|
+
async migrateMappings(index, src, dest) {
|
|
12
|
+
const { body } = await src.indices.getMapping({ index });
|
|
13
13
|
const mappings = body[index];
|
|
14
|
-
await
|
|
14
|
+
await dest.indices.create({ index, body: { mappings: mappings.mappings } });
|
|
15
15
|
}
|
|
16
|
-
async migrateData(index, batch_size) {
|
|
16
|
+
async migrateData(index, batch_size, src, dest) {
|
|
17
17
|
const queue = [];
|
|
18
|
-
const { body } = await
|
|
18
|
+
const { body } = await src.search({
|
|
19
19
|
index,
|
|
20
|
-
scroll:
|
|
20
|
+
scroll: this.flags.scroll,
|
|
21
21
|
size: batch_size,
|
|
22
22
|
body: {
|
|
23
23
|
query: {
|
|
@@ -42,42 +42,52 @@ class EsMigrate extends common_1.Kommand {
|
|
|
42
42
|
bulk.push(doc._source);
|
|
43
43
|
count++;
|
|
44
44
|
}
|
|
45
|
-
await
|
|
45
|
+
await dest.bulk({ body: bulk });
|
|
46
46
|
progressBar.update(count);
|
|
47
|
-
const { body: { hits } } = await
|
|
48
|
-
scrollId,
|
|
49
|
-
scroll:
|
|
47
|
+
const { body: { hits } } = await src.scroll({
|
|
48
|
+
scroll_id: scrollId,
|
|
49
|
+
scroll: this.flags.scroll
|
|
50
50
|
});
|
|
51
51
|
queue.push(hits);
|
|
52
52
|
}
|
|
53
53
|
progressBar.stop();
|
|
54
54
|
return total;
|
|
55
55
|
}
|
|
56
|
+
async runMigrate(index, src, dest) {
|
|
57
|
+
this.logInfo(`Importing ${chalk_1.default.bold(index)} to ${chalk_1.default.bold(this.flags.dest)}`);
|
|
58
|
+
await this.migrateMappings(index, src, dest);
|
|
59
|
+
this.logOk('Mappings successfully imported!');
|
|
60
|
+
const count = await this.migrateData(index, this.flags['batch-size'], src, dest);
|
|
61
|
+
if (count === 0) {
|
|
62
|
+
this.logInfo('No documents to import\n');
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
this.logOk(`${chalk_1.default.bold(count)} document(s) imported!\n`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
56
68
|
async runSafe() {
|
|
57
|
-
|
|
58
|
-
|
|
69
|
+
const src = new elasticsearch_1.Client({ node: this.flags.src });
|
|
70
|
+
const dest = new elasticsearch_1.Client({ node: this.flags.dest });
|
|
59
71
|
if (this.flags.reset && !this.flags['no-interactive']) {
|
|
60
72
|
this.log(chalk_1.default.red(`${node_emoji_1.default.get('fire')} Are you sure you want to reset ${chalk_1.default.bold(this.flags.dest)}?`));
|
|
61
73
|
await cli_ux_1.default.confirm(chalk_1.default.redBright(` ${node_emoji_1.default.get('fire')} You will lose all the data stored in it (Type "yes" to confirm)`));
|
|
62
|
-
await
|
|
74
|
+
await dest.indices.delete({ index: '_all' });
|
|
63
75
|
}
|
|
64
76
|
this.logInfo(`Fetching indices list from ${chalk_1.default.bold(this.flags.src)}`);
|
|
65
|
-
const
|
|
66
|
-
const
|
|
77
|
+
const srcBody = await src.cat.indices({ format: 'json' });
|
|
78
|
+
const srcIndices = srcBody.body
|
|
67
79
|
.map(({ index }) => index)
|
|
80
|
+
.filter((index) => index.match(this.flags.pattern))
|
|
68
81
|
.sort();
|
|
69
|
-
this.logOk(`Found ${chalk_1.default.bold(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
this.logInfo(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
this.logOk(`${chalk_1.default.bold(count)} document(s) imported!\n`);
|
|
82
|
+
this.logOk(`Found ${chalk_1.default.bold(srcIndices.length)} indices in the source Elasticsearch server\n`);
|
|
83
|
+
if (this.flags['dry-run']) {
|
|
84
|
+
this.log(`${chalk_1.default.bold(srcIndices)}`);
|
|
85
|
+
this.logInfo(`${chalk_1.default.bold(srcIndices.length)} indices will be migrated`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
this.logInfo(`Starting indices migration from ${chalk_1.default.bold(this.flags.src)} to ${chalk_1.default.bold(this.flags.dest)}`);
|
|
89
|
+
for (const index of srcIndices) {
|
|
90
|
+
await this.runMigrate(index, src, dest);
|
|
81
91
|
}
|
|
82
92
|
}
|
|
83
93
|
}
|
|
@@ -109,6 +119,17 @@ EsMigrate.flags = {
|
|
|
109
119
|
description: 'Skip confirmation interactive prompts (perfect for scripting)',
|
|
110
120
|
default: false,
|
|
111
121
|
}),
|
|
122
|
+
'dry-run': command_1.flags.boolean({
|
|
123
|
+
description: 'Print witch collections will be migrated',
|
|
124
|
+
default: false,
|
|
125
|
+
}),
|
|
126
|
+
'pattern': command_1.flags.string({
|
|
127
|
+
description: 'Pattern to match indices to migrate'
|
|
128
|
+
}),
|
|
129
|
+
'scroll': command_1.flags.string({
|
|
130
|
+
description: 'Scroll duration for Elasticsearch scrolling',
|
|
131
|
+
default: '30s'
|
|
132
|
+
}),
|
|
112
133
|
};
|
|
113
134
|
EsMigrate.examples = [
|
|
114
135
|
'kourou es:migrate --src http://elasticsearch:9200 --dest http://otherElasticsearch:9200 --reset --batch-size 2000',
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { flags } from '@oclif/command';
|
|
2
2
|
import { PaasKommand } from '../../support/PaasKommand';
|
|
3
|
-
declare class
|
|
3
|
+
declare class PaasDeploy extends PaasKommand {
|
|
4
4
|
static description: string;
|
|
5
5
|
static flags: {
|
|
6
6
|
help: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
|
|
7
7
|
token: flags.IOptionFlag<string | undefined>;
|
|
8
|
-
|
|
8
|
+
project: flags.IOptionFlag<string | undefined>;
|
|
9
9
|
};
|
|
10
10
|
static args: {
|
|
11
11
|
name: string;
|
|
@@ -15,4 +15,4 @@ declare class PaasPublish extends PaasKommand {
|
|
|
15
15
|
runSafe(): Promise<void>;
|
|
16
16
|
getCredentials(): Promise<any>;
|
|
17
17
|
}
|
|
18
|
-
export default
|
|
18
|
+
export default PaasDeploy;
|
|
@@ -6,57 +6,61 @@ const command_1 = require("@oclif/command");
|
|
|
6
6
|
const cli_ux_1 = tslib_1.__importDefault(require("cli-ux"));
|
|
7
7
|
const login_1 = tslib_1.__importDefault(require("./login"));
|
|
8
8
|
const PaasKommand_1 = require("../../support/PaasKommand");
|
|
9
|
-
class
|
|
9
|
+
class PaasDeploy extends PaasKommand_1.PaasKommand {
|
|
10
10
|
async runSafe() {
|
|
11
11
|
const apiKey = await this.getCredentials();
|
|
12
12
|
await this.initPaasClient({ apiKey });
|
|
13
13
|
const user = await this.paas.auth.getCurrentUser();
|
|
14
|
-
this.logInfo(`Logged as "${user._id}" for project "${this.
|
|
14
|
+
this.logInfo(`Logged as "${user._id}" for project "${this.flags.project || this.getProject()}"`);
|
|
15
15
|
const [image, tag] = this.args.image.split(':');
|
|
16
16
|
this.logInfo(`Deploy application with image "${image}:${tag}"`);
|
|
17
17
|
await this.paas.query({
|
|
18
|
-
controller: '
|
|
19
|
-
action: '
|
|
18
|
+
controller: 'application',
|
|
19
|
+
action: 'deploy',
|
|
20
|
+
environmentId: this.args.environment,
|
|
21
|
+
projectId: this.flags.project || this.getProject(),
|
|
22
|
+
applicationId: 'kuzzle',
|
|
20
23
|
body: {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
image: {
|
|
25
|
+
name: image,
|
|
26
|
+
tag,
|
|
27
|
+
},
|
|
24
28
|
}
|
|
25
29
|
});
|
|
26
30
|
this.logOk('Deployment in progress');
|
|
27
31
|
}
|
|
28
32
|
async getCredentials() {
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
if (!fs_1.default.existsSync(
|
|
33
|
+
const project = this.getProject();
|
|
34
|
+
const projectFile = this.fileProjectCredentials(project);
|
|
35
|
+
if (!fs_1.default.existsSync(projectFile)) {
|
|
32
36
|
this.log('');
|
|
33
|
-
const nextStep = await cli_ux_1.default.prompt('Cannot find credentials for this
|
|
37
|
+
const nextStep = await cli_ux_1.default.prompt('Cannot find credentials for this project. Do you want to login first? [Y/N]', { type: 'single' });
|
|
34
38
|
this.log('');
|
|
35
39
|
if (nextStep.toLowerCase().startsWith('y')) {
|
|
36
|
-
await login_1.default.run(['--
|
|
40
|
+
await login_1.default.run(['--project', project]);
|
|
37
41
|
}
|
|
38
42
|
else {
|
|
39
43
|
this.logKo('Aborting.');
|
|
40
44
|
process.exit(1);
|
|
41
45
|
}
|
|
42
46
|
}
|
|
43
|
-
const credentials = JSON.parse(fs_1.default.readFileSync(
|
|
47
|
+
const credentials = JSON.parse(fs_1.default.readFileSync(projectFile, 'utf8'));
|
|
44
48
|
return credentials.apiKey;
|
|
45
49
|
}
|
|
46
50
|
}
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
PaasDeploy.description = 'Deploy a new version of the application in the PaaS';
|
|
52
|
+
PaasDeploy.flags = {
|
|
49
53
|
help: command_1.flags.help(),
|
|
50
54
|
token: command_1.flags.string({
|
|
51
55
|
default: process.env.KUZZLE_PAAS_TOKEN,
|
|
52
56
|
description: 'Authentication token'
|
|
53
57
|
}),
|
|
54
|
-
|
|
55
|
-
description: 'Current PaaS
|
|
58
|
+
project: command_1.flags.string({
|
|
59
|
+
description: 'Current PaaS project',
|
|
56
60
|
}),
|
|
57
61
|
};
|
|
58
|
-
|
|
59
|
-
{ name: '
|
|
60
|
-
{ name: 'image', description: 'Image name and hash', required: true },
|
|
62
|
+
PaasDeploy.args = [
|
|
63
|
+
{ name: 'environment', description: 'Project environment name', required: true },
|
|
64
|
+
{ name: 'image', description: 'Image name and hash as myimage:mytag', required: true },
|
|
61
65
|
];
|
|
62
|
-
exports.default =
|
|
66
|
+
exports.default = PaasDeploy;
|
|
@@ -3,9 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
5
5
|
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
6
|
-
const cli_ux_1 = require("cli-ux");
|
|
7
6
|
const command_1 = require("@oclif/command");
|
|
8
|
-
const login_1 = tslib_1.__importDefault(require("./login"));
|
|
9
7
|
const PaasKommand_1 = require("../../support/PaasKommand");
|
|
10
8
|
class PaasInit extends PaasKommand_1.PaasKommand {
|
|
11
9
|
async runSafe() {
|
|
@@ -17,25 +15,17 @@ class PaasInit extends PaasKommand_1.PaasKommand {
|
|
|
17
15
|
this.logInfo('Add the "kuzzle" property inside project package.json.');
|
|
18
16
|
packageJson.kuzzle = {
|
|
19
17
|
paas: {
|
|
20
|
-
|
|
21
|
-
namespace: this.args.namespace,
|
|
18
|
+
project: this.args.project,
|
|
22
19
|
},
|
|
23
20
|
};
|
|
24
21
|
fs_1.default.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
25
|
-
this.log('');
|
|
26
|
-
const nextStep = await cli_ux_1.cli.prompt('Do you want to login to the namespace? [Y/N]', { type: 'single' });
|
|
27
|
-
this.log('');
|
|
28
|
-
if (nextStep.toLowerCase().startsWith('y')) {
|
|
29
|
-
await login_1.default.run(['--username', this.args.username, '--namespace', this.args.namespace]);
|
|
30
|
-
}
|
|
31
22
|
}
|
|
32
23
|
}
|
|
33
|
-
PaasInit.description = 'Initialize a PaaS
|
|
24
|
+
PaasInit.description = 'Initialize a PaaS project in current directory';
|
|
34
25
|
PaasInit.flags = {
|
|
35
26
|
help: command_1.flags.help(),
|
|
36
27
|
};
|
|
37
28
|
PaasInit.args = [
|
|
38
|
-
{ name: '
|
|
39
|
-
{ name: 'namespace', description: 'Namespace', required: true },
|
|
29
|
+
{ name: 'project', description: 'Kuzzle PaaS project name', required: true },
|
|
40
30
|
];
|
|
41
31
|
exports.default = PaasInit;
|
|
@@ -5,10 +5,11 @@ declare class PaasLogin extends PaasKommand {
|
|
|
5
5
|
static description: string;
|
|
6
6
|
static flags: {
|
|
7
7
|
help: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
|
|
8
|
-
|
|
8
|
+
project: flags.IOptionFlag<string | undefined>;
|
|
9
9
|
username: flags.IOptionFlag<string | undefined>;
|
|
10
10
|
};
|
|
11
11
|
runSafe(): Promise<void>;
|
|
12
|
-
|
|
12
|
+
createProjectCredentials(apiKey: ApiKey): void;
|
|
13
|
+
authenticateNPM(username: string, password: string): Promise<void>;
|
|
13
14
|
}
|
|
14
15
|
export default PaasLogin;
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
5
|
+
const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
|
|
5
6
|
const command_1 = require("@oclif/command");
|
|
6
7
|
const cli_ux_1 = tslib_1.__importDefault(require("cli-ux"));
|
|
7
8
|
const PaasKommand_1 = require("../../support/PaasKommand");
|
|
9
|
+
const child_process_1 = require("child_process");
|
|
8
10
|
class PaasLogin extends PaasKommand_1.PaasKommand {
|
|
9
11
|
async runSafe() {
|
|
10
12
|
this.createKourouDir();
|
|
@@ -16,24 +18,44 @@ class PaasLogin extends PaasKommand_1.PaasKommand {
|
|
|
16
18
|
: await cli_ux_1.default.prompt(` Password`, { type: 'hide' });
|
|
17
19
|
await this.initPaasClient({ username, password });
|
|
18
20
|
const apiKey = await this.paas.auth.createApiKey('Kourou PaaS API Key');
|
|
19
|
-
this.
|
|
21
|
+
this.createProjectCredentials(apiKey);
|
|
22
|
+
await this.authenticateNPM(username, password);
|
|
23
|
+
this.logOk(`Successfully logged in as ${username}. Your Kuzzle Enterprise license is now enabled on this host.`);
|
|
20
24
|
}
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
const
|
|
25
|
+
createProjectCredentials(apiKey) {
|
|
26
|
+
const project = this.getProject();
|
|
27
|
+
const projectFile = this.fileProjectCredentials(project);
|
|
24
28
|
const credentials = {
|
|
25
29
|
apiKey: apiKey._source.token,
|
|
26
30
|
};
|
|
27
|
-
this.logInfo(`Saving credentials for
|
|
28
|
-
fs_1.default.writeFileSync(
|
|
29
|
-
fs_1.default.chmodSync(
|
|
31
|
+
this.logInfo(`Saving credentials for project "${project}" in "${projectFile}".`);
|
|
32
|
+
fs_1.default.writeFileSync(projectFile, JSON.stringify(credentials, null, 2));
|
|
33
|
+
fs_1.default.chmodSync(projectFile, 0o600);
|
|
34
|
+
}
|
|
35
|
+
async authenticateNPM(username, password) {
|
|
36
|
+
const options = {
|
|
37
|
+
method: 'PUT',
|
|
38
|
+
headers: {
|
|
39
|
+
'Content-Type': 'application/json',
|
|
40
|
+
'Accept': 'application/json',
|
|
41
|
+
'Authorization': `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}`
|
|
42
|
+
},
|
|
43
|
+
body: JSON.stringify({
|
|
44
|
+
name: username,
|
|
45
|
+
password,
|
|
46
|
+
})
|
|
47
|
+
};
|
|
48
|
+
const response = await (0, node_fetch_1.default)(`https://packages.paas.kuzzle.io/-/user/org.couchdb.user:${username}`, options);
|
|
49
|
+
const { token } = await response.json();
|
|
50
|
+
(0, child_process_1.spawnSync)('npm', ['config', 'set', '@kuzzleio:registry', 'https://packages.paas.kuzzle.io'], { stdio: 'inherit' });
|
|
51
|
+
(0, child_process_1.spawnSync)('npm', ['set', '//packages.paas.kuzzle.io/:_authToken', token], { stdio: 'inherit' });
|
|
30
52
|
}
|
|
31
53
|
}
|
|
32
|
-
PaasLogin.description = 'Login for a PaaS
|
|
54
|
+
PaasLogin.description = 'Login for a PaaS project';
|
|
33
55
|
PaasLogin.flags = {
|
|
34
56
|
help: command_1.flags.help(),
|
|
35
|
-
|
|
36
|
-
description: 'Current PaaS
|
|
57
|
+
project: command_1.flags.string({
|
|
58
|
+
description: 'Current PaaS project'
|
|
37
59
|
}),
|
|
38
60
|
username: command_1.flags.string({
|
|
39
61
|
description: 'PaaS username',
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { flags } from "@oclif/command";
|
|
2
|
+
import { PaasKommand } from "../../support/PaasKommand";
|
|
3
|
+
declare class PaasLogs 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
|
+
};
|
|
9
|
+
static args: {
|
|
10
|
+
name: string;
|
|
11
|
+
description: string;
|
|
12
|
+
required: boolean;
|
|
13
|
+
}[];
|
|
14
|
+
runSafe(): Promise<void>;
|
|
15
|
+
getCredentials(): Promise<any>;
|
|
16
|
+
}
|
|
17
|
+
export default PaasLogs;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const command_1 = require("@oclif/command");
|
|
5
|
+
const PaasKommand_1 = require("../../support/PaasKommand");
|
|
6
|
+
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
7
|
+
const login_1 = tslib_1.__importDefault(require("./login"));
|
|
8
|
+
const cli_ux_1 = require("cli-ux");
|
|
9
|
+
class PaasLogs extends PaasKommand_1.PaasKommand {
|
|
10
|
+
async runSafe() {
|
|
11
|
+
const apiKey = await this.getCredentials();
|
|
12
|
+
await this.initPaasClient({ apiKey });
|
|
13
|
+
const user = await this.paas.auth.getCurrentUser();
|
|
14
|
+
this.logInfo(`Logged as "${user._id}" for project "${this.flags.project || this.getProject()}"`);
|
|
15
|
+
const logs = await this.paas.query({
|
|
16
|
+
controller: 'application',
|
|
17
|
+
action: 'logs',
|
|
18
|
+
environmentId: this.args.environment,
|
|
19
|
+
projectId: this.flags.project || this.getProject(),
|
|
20
|
+
applicationId: this.args.application,
|
|
21
|
+
});
|
|
22
|
+
this.logOk(logs.result.join('\n '));
|
|
23
|
+
}
|
|
24
|
+
async getCredentials() {
|
|
25
|
+
const project = this.getProject();
|
|
26
|
+
const projectFile = this.fileProjectCredentials(project);
|
|
27
|
+
if (!fs_1.default.existsSync(projectFile)) {
|
|
28
|
+
this.log('');
|
|
29
|
+
const nextStep = await cli_ux_1.cli.prompt('Cannot find credentials for this project. Do you want to login first? [Y/N]', { type: 'single' });
|
|
30
|
+
this.log('');
|
|
31
|
+
if (nextStep.toLowerCase().startsWith('y')) {
|
|
32
|
+
await login_1.default.run(['--project', project]);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
this.logKo('Aborting.');
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const credentials = JSON.parse(fs_1.default.readFileSync(projectFile, 'utf8'));
|
|
40
|
+
return credentials.apiKey;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
PaasLogs.description = 'Show logs of the targeted application';
|
|
44
|
+
PaasLogs.flags = {
|
|
45
|
+
help: command_1.flags.help(),
|
|
46
|
+
project: command_1.flags.string({
|
|
47
|
+
description: 'Current PaaS project'
|
|
48
|
+
}),
|
|
49
|
+
};
|
|
50
|
+
PaasLogs.args = [
|
|
51
|
+
{ name: 'environment', description: 'Kuzzle PaaS environment', required: true },
|
|
52
|
+
{ name: 'application', description: 'Kuzzle PaaS application', required: true },
|
|
53
|
+
];
|
|
54
|
+
exports.default = PaasLogs;
|
package/lib/common.js
CHANGED
|
@@ -104,8 +104,13 @@ class Kommand extends command_1.Command {
|
|
|
104
104
|
? ` (https://docs.kuzzle.io/core/2/api/errors/error-codes/${error.id.split('.')[0]})`
|
|
105
105
|
: '';
|
|
106
106
|
this.logKo(`Error stack: \n${stack || error.message}\n\nError status: ${error.status}\n\nError id: ${error.id}${errorLink}`);
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
if (Array.isArray(error.errors)) {
|
|
108
|
+
for (const e of error.errors) {
|
|
109
|
+
this.logKo(`${e.document._id} : ${e.reason}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
this.logKo(JSON.stringify(error.reason));
|
|
109
114
|
}
|
|
110
115
|
err = true;
|
|
111
116
|
}
|
|
@@ -10,13 +10,13 @@ export declare class PaasKommand extends Kommand {
|
|
|
10
10
|
static initSdk: boolean;
|
|
11
11
|
protected host: string;
|
|
12
12
|
protected port: number;
|
|
13
|
-
protected ssl:
|
|
13
|
+
protected ssl: any;
|
|
14
14
|
protected paas: KuzzleSDK;
|
|
15
15
|
initPaasClient(credentials: PaaSClientCredentials): Promise<void>;
|
|
16
|
-
|
|
16
|
+
fileProjectCredentials(project: string): string;
|
|
17
17
|
/**
|
|
18
|
-
* Retrieve the current
|
|
18
|
+
* Retrieve the current project name from the command line or current package.json
|
|
19
19
|
*/
|
|
20
|
-
|
|
20
|
+
getProject(): any;
|
|
21
21
|
}
|
|
22
22
|
export {};
|
|
@@ -9,9 +9,15 @@ const kuzzle_1 = require("./kuzzle");
|
|
|
9
9
|
class PaasKommand extends common_1.Kommand {
|
|
10
10
|
constructor() {
|
|
11
11
|
super(...arguments);
|
|
12
|
-
this.host =
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
this.host = process.env.KUZZLE_PAAS_HOST
|
|
13
|
+
? process.env.KUZZLE_PAAS_HOST
|
|
14
|
+
: 'api.console.paas.kuzzle.io';
|
|
15
|
+
this.port = process.env.KUZZLE_PAAS_PORT
|
|
16
|
+
? parseInt(process.env.KUZZLE_PAAS_PORT)
|
|
17
|
+
: 443;
|
|
18
|
+
this.ssl = process.env.KUZZLE_PAAS_SSL
|
|
19
|
+
? JSON.parse(process.env.KUZZLE_PAAS_SSL)
|
|
20
|
+
: true;
|
|
15
21
|
// Instantiate a dummy SDK to avoid the this.paas? notation everywhere -_-
|
|
16
22
|
this.paas = new kuzzle_1.KuzzleSDK({});
|
|
17
23
|
}
|
|
@@ -28,24 +34,24 @@ class PaasKommand extends common_1.Kommand {
|
|
|
28
34
|
throw error;
|
|
29
35
|
}
|
|
30
36
|
}
|
|
31
|
-
|
|
32
|
-
return path_1.default.join(this.kourouDir, `${
|
|
37
|
+
fileProjectCredentials(project) {
|
|
38
|
+
return path_1.default.join(this.kourouDir, `${project}.paas.json`);
|
|
33
39
|
}
|
|
34
40
|
/**
|
|
35
|
-
* Retrieve the current
|
|
41
|
+
* Retrieve the current project name from the command line or current package.json
|
|
36
42
|
*/
|
|
37
|
-
|
|
43
|
+
getProject() {
|
|
38
44
|
const packageJsonPath = path_1.default.join(process.cwd(), 'package.json');
|
|
39
45
|
if (fs_1.default.existsSync(packageJsonPath)) {
|
|
40
46
|
const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf8'));
|
|
41
47
|
if (packageJson.kuzzle && packageJson.kuzzle.paas) {
|
|
42
|
-
return packageJson.kuzzle.paas.
|
|
48
|
+
return packageJson.kuzzle.paas.project;
|
|
43
49
|
}
|
|
44
50
|
}
|
|
45
|
-
if (!this.flags.
|
|
46
|
-
throw new Error('Cannot find PaaS
|
|
51
|
+
if (!this.flags.project) {
|
|
52
|
+
throw new Error('Cannot find PaaS project in package.json or command line');
|
|
47
53
|
}
|
|
48
|
-
return this.flags.
|
|
54
|
+
return this.flags.project;
|
|
49
55
|
}
|
|
50
56
|
}
|
|
51
57
|
exports.PaasKommand = PaasKommand;
|
package/lib/support/kuzzle.d.ts
CHANGED
|
@@ -44,7 +44,7 @@ export declare class KuzzleSDK {
|
|
|
44
44
|
get index(): import("kuzzle-sdk").IndexController;
|
|
45
45
|
get security(): import("kuzzle-sdk/src/controllers/Security").SecurityController;
|
|
46
46
|
get auth(): import("kuzzle-sdk").AuthController;
|
|
47
|
-
get server():
|
|
47
|
+
get server(): import("kuzzle-sdk").ServerController;
|
|
48
48
|
get realtime(): import("kuzzle-sdk").RealtimeController;
|
|
49
49
|
get ms(): any;
|
|
50
50
|
}
|
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.
|
|
4
|
+
"version": "0.22.0",
|
|
5
5
|
"author": "The Kuzzle Team <support@kuzzle.io>",
|
|
6
6
|
"bin": {
|
|
7
7
|
"kourou": "./bin/run"
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"lodash": "^4.17.21",
|
|
40
40
|
"ndjson": "^2.0.0",
|
|
41
41
|
"node-emoji": "^1.10.0",
|
|
42
|
+
"node-fetch": "^2.6.7",
|
|
42
43
|
"production": "0.0.2",
|
|
43
44
|
"strip-json-comments": "^3.1.1",
|
|
44
45
|
"tmp": "^0.2.1",
|
|
@@ -54,6 +55,7 @@
|
|
|
54
55
|
"@types/mocha": "^8.2.2",
|
|
55
56
|
"@types/node": "^14.14.41",
|
|
56
57
|
"@types/node-emoji": "^1.8.1",
|
|
58
|
+
"@types/node-fetch": "^2.6.1",
|
|
57
59
|
"@typescript-eslint/eslint-plugin": "^4.22.0",
|
|
58
60
|
"@typescript-eslint/parser": "^4.22.0",
|
|
59
61
|
"chai": "^4.3.4",
|