kuzzle 2.15.2 → 2.16.3
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/lib/api/controllers/serverController.js +24 -4
- package/lib/api/funnel.js +19 -0
- package/lib/{config → api}/httpRoutes.js +29 -14
- package/lib/api/openApiGenerator.d.ts +6 -0
- package/lib/api/openApiGenerator.js +167 -126
- package/lib/api/openapi/document/count.yaml +47 -0
- package/lib/api/openapi/document/create.yaml +46 -0
- package/lib/api/openapi/document/createOrReplace.yaml +61 -0
- package/lib/api/openapi/document/delete.yaml +67 -0
- package/lib/api/openapi/document/deleteByQuery.yaml +90 -0
- package/lib/api/openapi/document/exists.yaml +35 -0
- package/lib/api/openapi/document/get.yaml +68 -0
- package/lib/api/openapi/document/index.d.ts +20 -0
- package/lib/api/openapi/document/index.js +55 -0
- package/lib/api/openapi/document/replace.yaml +66 -0
- package/lib/api/openapi/document/scroll.yaml +49 -0
- package/lib/api/openapi/document/update.yaml +78 -0
- package/lib/api/openapi/index.d.ts +2 -0
- package/lib/api/openapi/index.js +18 -0
- package/lib/api/openapi/payloads.yaml +32 -0
- package/lib/api/request/kuzzleRequest.d.ts +32 -0
- package/lib/api/request/kuzzleRequest.js +34 -0
- package/lib/api/request/requestInput.d.ts +2 -0
- package/lib/api/request/requestInput.js +2 -0
- package/lib/config/default.config.js +1 -1
- package/lib/core/network/router.js +33 -0
- package/lib/core/realtime/hotelClerk.d.ts +7 -0
- package/lib/core/realtime/hotelClerk.js +14 -0
- package/lib/util/readYamlFile.d.ts +2 -0
- package/lib/util/readYamlFile.js +10 -0
- package/package-lock.json +160 -175
- package/package.json +11 -25
- package/.kuzzlerc.sample +0 -988
- package/CONTRIBUTING.md +0 -116
- package/bin/.lib/colorOutput.js +0 -71
- package/bin/.upgrades/connectors/es.js +0 -90
- package/bin/.upgrades/connectors/redis.js +0 -112
- package/bin/.upgrades/lib/connectorContext.js +0 -38
- package/bin/.upgrades/lib/context.js +0 -142
- package/bin/.upgrades/lib/formatters.js +0 -103
- package/bin/.upgrades/lib/inquirerExtended.js +0 -46
- package/bin/.upgrades/lib/logger.js +0 -99
- package/bin/.upgrades/lib/progressBar.js +0 -70
- package/bin/.upgrades/versions/v1/checkConfiguration.js +0 -85
- package/bin/.upgrades/versions/v1/index.js +0 -35
- package/bin/.upgrades/versions/v1/upgradeCache.js +0 -149
- package/bin/.upgrades/versions/v1/upgradeStorage.js +0 -450
- package/protocols/available/.gitignore +0 -4
- package/protocols/enabled/.gitignore +0 -4
|
@@ -1,450 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Kuzzle, a backend software, self-hostable and ready to use
|
|
3
|
-
* to power modern apps
|
|
4
|
-
*
|
|
5
|
-
* Copyright 2015-2020 Kuzzle
|
|
6
|
-
* mailto: support AT kuzzle.io
|
|
7
|
-
* website: http://kuzzle.io
|
|
8
|
-
*
|
|
9
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
10
|
-
* you may not use this file except in compliance with the License.
|
|
11
|
-
* You may obtain a copy of the License at
|
|
12
|
-
*
|
|
13
|
-
* https://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
-
*
|
|
15
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
16
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
17
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
18
|
-
* See the License for the specific language governing permissions and
|
|
19
|
-
* limitations under the License.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
'use strict';
|
|
23
|
-
|
|
24
|
-
const _ = require('lodash');
|
|
25
|
-
|
|
26
|
-
const getESConnector = require('../../connectors/es');
|
|
27
|
-
const ProgressBar = require('../../lib/progressBar');
|
|
28
|
-
|
|
29
|
-
const INTERNAL_PREFIX = '%';
|
|
30
|
-
const PUBLIC_PREFIX = '&';
|
|
31
|
-
const NAME_SEPARATOR = '.';
|
|
32
|
-
|
|
33
|
-
function transformProfile (profile) {
|
|
34
|
-
if (!Array.isArray(profile.policies)) {
|
|
35
|
-
return profile;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
for (const policy of profile.policies.filter(p => p.restrictedTo)) {
|
|
39
|
-
for (const restriction of policy.restrictedTo.filter(r => r.collections)) {
|
|
40
|
-
restriction.collections =
|
|
41
|
-
restriction.collections.map(c => c.toLowerCase());
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return profile;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function getNewIndexName (index, collection) {
|
|
48
|
-
const prefix = index[0] === '%' ? '' : PUBLIC_PREFIX;
|
|
49
|
-
|
|
50
|
-
return `${prefix}${index}${NAME_SEPARATOR}${collection}`;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function fixIndexName (context, index, collection, newIndex) {
|
|
54
|
-
const lowercased = newIndex.toLowerCase();
|
|
55
|
-
|
|
56
|
-
if (lowercased !== newIndex) {
|
|
57
|
-
// uppercase letters were already forbidden in index names
|
|
58
|
-
context.log.warn(`Index "${index}": collection "${collection}" has been renamed to "${collection.toLowerCase()}"`);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return lowercased;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
async function moveData (context, index, collection, newIndex, transform) {
|
|
65
|
-
let page = await context.source.search({
|
|
66
|
-
body: { sort: [ '_doc' ] },
|
|
67
|
-
index,
|
|
68
|
-
scroll: '1m',
|
|
69
|
-
size: context.argv.storagePageSize,
|
|
70
|
-
type: collection
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
const total = page.body.hits.total;
|
|
74
|
-
const progressBar = new ProgressBar(
|
|
75
|
-
context,
|
|
76
|
-
`Importing: ${index}/${collection}`,
|
|
77
|
-
total);
|
|
78
|
-
let moved = 0;
|
|
79
|
-
|
|
80
|
-
while (moved < total) {
|
|
81
|
-
const bulk = [];
|
|
82
|
-
|
|
83
|
-
for (let i = 0; i < page.body.hits.hits.length; i++) {
|
|
84
|
-
const doc = page.body.hits.hits[i];
|
|
85
|
-
|
|
86
|
-
if (doc._source._kuzzle_info) {
|
|
87
|
-
delete doc._source._kuzzle_info.active;
|
|
88
|
-
delete doc._source._kuzzle_info.deletedAt;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (transform) {
|
|
92
|
-
doc._source = transform(doc._source);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
bulk.push({
|
|
96
|
-
create: {
|
|
97
|
-
_id: doc._id,
|
|
98
|
-
_index: newIndex,
|
|
99
|
-
_type: context._type
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
bulk.push(doc._source);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
await context.target.bulk({ _source: false, body: bulk });
|
|
106
|
-
|
|
107
|
-
moved += page.body.hits.hits.length;
|
|
108
|
-
|
|
109
|
-
progressBar.update(moved);
|
|
110
|
-
|
|
111
|
-
if (moved < total) {
|
|
112
|
-
page = await context.source.scroll({
|
|
113
|
-
scroll: '1m',
|
|
114
|
-
scroll_id: page.body._scroll_id
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
progressBar.destroy();
|
|
120
|
-
return total;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async function upgradeMappings (context, index, collection, newIndex) {
|
|
124
|
-
const mappingsResponse = await context.source.indices.getMapping({
|
|
125
|
-
index,
|
|
126
|
-
type: collection
|
|
127
|
-
});
|
|
128
|
-
const mappings = mappingsResponse.body[index].mappings[collection];
|
|
129
|
-
|
|
130
|
-
// replace obsolete mapping properties
|
|
131
|
-
if (mappings.properties && mappings.properties._kuzzle_info) {
|
|
132
|
-
mappings.properties._kuzzle_info =
|
|
133
|
-
context.config.services.storageEngine.commonMapping.properties._kuzzle_info;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
await context.target.indices.putMapping({
|
|
137
|
-
body: {
|
|
138
|
-
_meta: mappings._meta,
|
|
139
|
-
dynamic: mappings.dynamic || false,
|
|
140
|
-
properties: mappings.properties
|
|
141
|
-
},
|
|
142
|
-
index: newIndex,
|
|
143
|
-
type: context._type,
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
async function createNewIndex (context, newIndex) {
|
|
148
|
-
const exists = await context.target.indices.exists({ index: newIndex });
|
|
149
|
-
|
|
150
|
-
if (exists.body) {
|
|
151
|
-
await context.target.indices.delete({ index: newIndex });
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
await context.target.indices.create({ index: newIndex });
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
async function upgrade (context, index, collection, newIndex) {
|
|
158
|
-
const fixedIndexName = fixIndexName(context, index, collection, newIndex);
|
|
159
|
-
|
|
160
|
-
await createNewIndex(context, fixedIndexName);
|
|
161
|
-
await upgradeMappings(context, index, collection, fixedIndexName);
|
|
162
|
-
|
|
163
|
-
return await moveData(context, index, collection, fixedIndexName);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
async function upgradeInternalStorage (context) {
|
|
167
|
-
const config = context.config.services.storageEngine.internalIndex;
|
|
168
|
-
const index = `${INTERNAL_PREFIX}${config.name}`;
|
|
169
|
-
const mapconfig = config.collections;
|
|
170
|
-
const collections = {
|
|
171
|
-
config: mapconfig.config,
|
|
172
|
-
profiles: mapconfig.profiles,
|
|
173
|
-
roles: mapconfig.roles,
|
|
174
|
-
users: null,
|
|
175
|
-
validations: mapconfig.validations,
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
for (const [collection, mappings] of Object.entries(collections)) {
|
|
179
|
-
const newIndex = getNewIndexName(index, collection);
|
|
180
|
-
let total;
|
|
181
|
-
|
|
182
|
-
if (mappings) {
|
|
183
|
-
await createNewIndex(context, newIndex);
|
|
184
|
-
await context.target.indices.putMapping({
|
|
185
|
-
body: mappings,
|
|
186
|
-
index: newIndex,
|
|
187
|
-
type: context._type
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
total = await moveData(
|
|
191
|
-
context,
|
|
192
|
-
index,
|
|
193
|
-
collection,
|
|
194
|
-
newIndex,
|
|
195
|
-
collection === 'profiles' && transformProfile);
|
|
196
|
-
}
|
|
197
|
-
else {
|
|
198
|
-
total = await upgrade(context, index, collection, newIndex);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
context.log.ok(`... migrated internal data: ${collection} (${total} documents)`);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// bootstrap document
|
|
205
|
-
await context.target.create({
|
|
206
|
-
body: { version: '2.0.0' },
|
|
207
|
-
id: 'internalIndex.dataModelVersion',
|
|
208
|
-
index: `${index}.config`,
|
|
209
|
-
type: context._type,
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
await context.target.create({
|
|
213
|
-
body: { timestamp: Date.now() },
|
|
214
|
-
id: `${config.name}.done`,
|
|
215
|
-
index: `${index}.config`,
|
|
216
|
-
type: context._type,
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
async function upgradePluginsStorage (context) {
|
|
221
|
-
const { body } = await context.source.cat.indices({ format: 'json' });
|
|
222
|
-
const indexes = body.map(b => b.index).filter(n => n.startsWith('%plugin:'));
|
|
223
|
-
|
|
224
|
-
for (const index of indexes) {
|
|
225
|
-
const plugin = index.split(':')[1];
|
|
226
|
-
const newIndexBase = `%plugin-${plugin}${NAME_SEPARATOR}`;
|
|
227
|
-
const mappings = await context.source.indices.getMapping({ index });
|
|
228
|
-
const collections = Object.keys(mappings.body[index].mappings);
|
|
229
|
-
|
|
230
|
-
for (const collection of collections) {
|
|
231
|
-
const newIndex = newIndexBase + collection;
|
|
232
|
-
const total = await upgrade(context, index, collection, newIndex);
|
|
233
|
-
|
|
234
|
-
context.log.ok(`... migrated storage for plugin ${plugin}: ${collection} (${total} documents)`);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
async function upgradeAliases (context, upgraded) {
|
|
240
|
-
const response = await context.source.indices.getAlias({
|
|
241
|
-
index: Object.keys(upgraded)
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
const aliases = {};
|
|
245
|
-
for (const [index, obj] of Object.entries(response.body)) {
|
|
246
|
-
if (Object.keys(obj.aliases).length > 0) {
|
|
247
|
-
for (const newIndex of upgraded[index].targets) {
|
|
248
|
-
aliases[newIndex] = obj.aliases;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
if (Object.keys(aliases).length === 0) {
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
context.log.notice(`
|
|
258
|
-
Index aliases detected. This script can import them to the new structure, but
|
|
259
|
-
due to the removal of native collections in Elasticsearch, future aliases will
|
|
260
|
-
be duplicated across all of an index upgraded collections.`);
|
|
261
|
-
|
|
262
|
-
const choice = await context.inquire.direct({
|
|
263
|
-
default: false,
|
|
264
|
-
message: 'Upgrade aliases?',
|
|
265
|
-
type: 'confirm'
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
if (!choice) {
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
for (const [index, obj] of Object.entries(aliases)) {
|
|
273
|
-
for (const [name, body] of Object.entries(obj)) {
|
|
274
|
-
await context.target.indices.putAlias({
|
|
275
|
-
_type: context._type,
|
|
276
|
-
body,
|
|
277
|
-
index,
|
|
278
|
-
name,
|
|
279
|
-
});
|
|
280
|
-
context.log.ok(`...... alias ${name} on index ${index} upgraded`);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
async function upgradeDataStorage (context) {
|
|
286
|
-
const { body } = await context.source.cat.indices({ format: 'json' });
|
|
287
|
-
const upgraded = {};
|
|
288
|
-
let indexes = body
|
|
289
|
-
.map(b => b.index)
|
|
290
|
-
.filter(n => !n.startsWith(INTERNAL_PREFIX));
|
|
291
|
-
|
|
292
|
-
context.log.notice(`There are ${indexes.length} data indexes that can be upgraded`);
|
|
293
|
-
const choices = {
|
|
294
|
-
all: 'upgrade all indexes',
|
|
295
|
-
askCollection: 'choose which collections can be upgraded',
|
|
296
|
-
askIndex: 'choose which indexes can be upgraded',
|
|
297
|
-
skip: 'skip all data index upgrades'
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
const action = await context.inquire.direct({
|
|
301
|
-
choices: Object.values(choices),
|
|
302
|
-
default: choices.all,
|
|
303
|
-
message: 'You want to',
|
|
304
|
-
type: 'list'
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
if (action === choices.skip) {
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
if (action === choices.askIndex) {
|
|
312
|
-
indexes = await context.inquire.direct({
|
|
313
|
-
choices: indexes.map(i => ({ checked: true, name: i })),
|
|
314
|
-
message: 'Select the indexes to upgrade:',
|
|
315
|
-
type: 'checkbox'
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
for (const index of indexes) {
|
|
320
|
-
const mappings = await context.source.indices.getMapping({ index });
|
|
321
|
-
const allCollections = Object.keys(mappings.body[index].mappings);
|
|
322
|
-
let collections = allCollections;
|
|
323
|
-
|
|
324
|
-
if (action === choices.askCollection) {
|
|
325
|
-
context.log.notice(`Starting to upgrade the index ${index}`);
|
|
326
|
-
collections = await context.inquire.direct({
|
|
327
|
-
choices: collections.map(c => ({ checked: true, name: c })),
|
|
328
|
-
message: 'Select the collections to upgrade:',
|
|
329
|
-
type: 'checkbox'
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
upgraded[index] = {
|
|
334
|
-
canBeRemoved: collections.length === allCollections.length,
|
|
335
|
-
targets: []
|
|
336
|
-
};
|
|
337
|
-
|
|
338
|
-
for (const collection of collections) {
|
|
339
|
-
const newIndex = getNewIndexName(index, collection);
|
|
340
|
-
const total = await upgrade(context, index, collection, newIndex);
|
|
341
|
-
|
|
342
|
-
upgraded[index].targets.push(newIndex);
|
|
343
|
-
context.log.ok(`... migrated data index ${index}: ${collection} (${total} documents)`);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
await upgradeAliases(context, upgraded);
|
|
348
|
-
|
|
349
|
-
return upgraded;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
async function destroyPreviousStructure (context, upgraded) {
|
|
353
|
-
// there is no point in destroying the previous structure if not performing
|
|
354
|
-
// an in-place migration
|
|
355
|
-
if (!context.inPlace) {
|
|
356
|
-
return;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
const { body } = await context.source.cat.indices({ format: 'json' });
|
|
360
|
-
const plugins = body.map(b => b.index).filter(n => n.startsWith('%plugin:'));
|
|
361
|
-
|
|
362
|
-
let indexes = [
|
|
363
|
-
'%kuzzle',
|
|
364
|
-
...plugins,
|
|
365
|
-
...Object.keys(upgraded).filter(i => upgraded[i].canBeRemoved),
|
|
366
|
-
];
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
context.log.notice('Since this is an in-place migration, the previous structure can be removed.');
|
|
370
|
-
context.log.notice('(only data indexes with ALL their collections upgraded can be deleted)');
|
|
371
|
-
|
|
372
|
-
const choices = {
|
|
373
|
-
everything: 'Yes - remove all upgraded structures',
|
|
374
|
-
internal: 'Remove only Kuzzle internal data',
|
|
375
|
-
kuzzleAndPlugins: 'Remove Kuzzle internal data and plugins storages',
|
|
376
|
-
no: 'No - keep everything as is'
|
|
377
|
-
};
|
|
378
|
-
|
|
379
|
-
const action = await context.inquire.direct({
|
|
380
|
-
choices: Object.values(choices),
|
|
381
|
-
default: choices[0],
|
|
382
|
-
message: 'Destroy? (THIS CANNOT BE REVERTED)',
|
|
383
|
-
type: 'list'
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
if (action === choices.no) {
|
|
387
|
-
context.log.ok('Previous structure left intact.');
|
|
388
|
-
return;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
if (action === choices.kuzzleAndPlugins) {
|
|
392
|
-
indexes = [ '%kuzzle', ...plugins ];
|
|
393
|
-
}
|
|
394
|
-
else if (action === choices.internal) {
|
|
395
|
-
indexes = [ '%kuzzle' ];
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
await context.source.indices.delete({ index: indexes });
|
|
399
|
-
context.log.ok('Previous structure destroyed.');
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
module.exports = async function upgradeStorage (context) {
|
|
403
|
-
const storageContext = await getESConnector(context);
|
|
404
|
-
const targetInfo = await storageContext.target.info();
|
|
405
|
-
const targetMajor = targetInfo.body.version.number.split('.')[0];
|
|
406
|
-
|
|
407
|
-
storageContext._type = storageContext.inPlace && targetMajor === '5'
|
|
408
|
-
? 'default'
|
|
409
|
-
: undefined;
|
|
410
|
-
|
|
411
|
-
context.log.notice(`
|
|
412
|
-
This script will now start *COPYING* the existing data to the target storage
|
|
413
|
-
space.
|
|
414
|
-
If the upgrade is interrupted, this script can be replayed any number of times.
|
|
415
|
-
Existing data from the older version of Kuzzle will be unaffected, but if
|
|
416
|
-
Kuzzle indexes already exist in the target storage space, they will be
|
|
417
|
-
overwritten without notice.`);
|
|
418
|
-
|
|
419
|
-
const confirm = await context.inquire.direct({
|
|
420
|
-
default: true,
|
|
421
|
-
message: 'Continue?',
|
|
422
|
-
type: 'confirm'
|
|
423
|
-
});
|
|
424
|
-
|
|
425
|
-
if (!confirm) {
|
|
426
|
-
context.log.error('Aborted by user.');
|
|
427
|
-
process.exit(0);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
try {
|
|
431
|
-
await upgradeInternalStorage(storageContext);
|
|
432
|
-
await upgradePluginsStorage(storageContext);
|
|
433
|
-
const upgraded = await upgradeDataStorage(storageContext);
|
|
434
|
-
|
|
435
|
-
storageContext.log.ok('Storage migration complete.');
|
|
436
|
-
await destroyPreviousStructure(storageContext, upgraded);
|
|
437
|
-
}
|
|
438
|
-
catch (e) {
|
|
439
|
-
storageContext.log.error(`Storage upgrade failure: ${e.message}`);
|
|
440
|
-
|
|
441
|
-
const reason = _.get(e, 'meta.body.error.reason');
|
|
442
|
-
if (reason) {
|
|
443
|
-
storageContext.log.error(`Reason: ${reason}`);
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
storageContext.log.print(e.stack);
|
|
447
|
-
storageContext.log.error('Aborted.');
|
|
448
|
-
process.exit(1);
|
|
449
|
-
}
|
|
450
|
-
};
|