@xen-orchestra/rest-api 0.14.0 → 0.15.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/dist/helpers/error.helper.mjs +10 -0
- package/dist/hosts/host.controller.mjs +24 -4
- package/dist/hosts/host.service.mjs +6 -7
- package/dist/hosts/host.type.mjs +1 -0
- package/dist/index.mjs +4 -0
- package/dist/middlewares/generic-error-handler.middleware.mjs +5 -1
- package/dist/open-api/common/response.common.mjs +4 -0
- package/dist/open-api/oa-examples/host.oa-example.mjs +30 -0
- package/dist/open-api/oa-examples/pool.oa-example.mjs +30 -0
- package/dist/open-api/oa-examples/task.oa-example.mjs +46 -0
- package/dist/open-api/routes/routes.js +153 -6
- package/dist/pools/pool.controller.mjs +16 -1
- package/dist/pools/pool.service.mjs +18 -8
- package/dist/tasks/task.controller.mjs +121 -0
- package/dist/xoa/xoa.service.mjs +14 -4
- package/open-api/spec/swagger.json +871 -114
- package/package.json +5 -4
- package/tsconfig.json +1 -0
- package/tsoa.json +12 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
8
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
|
+
};
|
|
10
|
+
import * as CM from 'complex-matcher';
|
|
11
|
+
import { XoController } from '../abstract-classes/xo-controller.mjs';
|
|
12
|
+
import { Get, Path, Query, Request, Route, Security, Tags, Response, Example } from 'tsoa';
|
|
13
|
+
import { badRequestResp, notFoundResp, unauthorizedResp } from '../open-api/common/response.common.mjs';
|
|
14
|
+
import { provide } from 'inversify-binding-decorators';
|
|
15
|
+
import { partialTasks, task, taskIds } from '../open-api/oa-examples/task.oa-example.mjs';
|
|
16
|
+
import pDefer from 'promise-toolbox/defer';
|
|
17
|
+
import { ApiError } from '../helpers/error.helper.mjs';
|
|
18
|
+
import { Transform } from 'node:stream';
|
|
19
|
+
import { makeObjectMapper } from '../helpers/object-wrapper.helper.mjs';
|
|
20
|
+
let TaskController = class TaskController extends XoController {
|
|
21
|
+
async getAllCollectionObjects() {
|
|
22
|
+
const result = [];
|
|
23
|
+
for await (const task of this.restApi.tasks.list()) {
|
|
24
|
+
result.push(task);
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
getCollectionObject(id) {
|
|
29
|
+
return this.restApi.tasks.get(id);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* If watch is true, ndjson must also be true
|
|
34
|
+
*
|
|
35
|
+
* @example fields "status,id,properties"
|
|
36
|
+
* @example filter "status:failure"
|
|
37
|
+
* @example limit 42
|
|
38
|
+
*/
|
|
39
|
+
async getTasks(req, fields, ndjson, watch, filter, limit) {
|
|
40
|
+
if (watch) {
|
|
41
|
+
if (!ndjson) {
|
|
42
|
+
throw new ApiError('watch=true requires ndjson=true', 400);
|
|
43
|
+
}
|
|
44
|
+
const userFilter = filter === undefined ? undefined : CM.parse(filter).createPredicate();
|
|
45
|
+
const stream = new Transform({
|
|
46
|
+
objectMode: true,
|
|
47
|
+
transform([event, object], encoding, callback) {
|
|
48
|
+
const mapper = makeObjectMapper(req);
|
|
49
|
+
callback(null, JSON.stringify([event, mapper(object)]) + '\n');
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
stream.on('close', () => {
|
|
53
|
+
this.restApi.tasks.off('update', update).off('remove', remove);
|
|
54
|
+
});
|
|
55
|
+
req.on('close', () => {
|
|
56
|
+
stream.destroy();
|
|
57
|
+
});
|
|
58
|
+
process.on('SIGTERM', () => {
|
|
59
|
+
req.destroy();
|
|
60
|
+
});
|
|
61
|
+
function update(task) {
|
|
62
|
+
if (userFilter === undefined || userFilter(task)) {
|
|
63
|
+
stream.write(['update', task]);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function remove(taskId) {
|
|
67
|
+
stream.write(['remove', { id: taskId }]);
|
|
68
|
+
}
|
|
69
|
+
this.restApi.tasks.on('update', update).on('remove', remove);
|
|
70
|
+
return stream;
|
|
71
|
+
}
|
|
72
|
+
const tasks = Object.values(await this.getObjects({ filter, limit }));
|
|
73
|
+
return this.sendObjects(tasks, req);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* @example id "0mdd1basu"
|
|
77
|
+
*/
|
|
78
|
+
async getTask(req, id, wait) {
|
|
79
|
+
const taskId = id;
|
|
80
|
+
if (wait) {
|
|
81
|
+
const { promise, resolve } = pDefer();
|
|
82
|
+
const stopWatch = await this.restApi.tasks.watch(taskId, task => {
|
|
83
|
+
if (task.status !== 'pending') {
|
|
84
|
+
stopWatch();
|
|
85
|
+
resolve(task);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
req.on('close', stopWatch);
|
|
89
|
+
return promise;
|
|
90
|
+
}
|
|
91
|
+
return this.getObject(taskId);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
__decorate([
|
|
95
|
+
Example(taskIds),
|
|
96
|
+
Example(partialTasks),
|
|
97
|
+
Get(''),
|
|
98
|
+
Response(badRequestResp.status, badRequestResp.description),
|
|
99
|
+
__param(0, Request()),
|
|
100
|
+
__param(1, Query()),
|
|
101
|
+
__param(2, Query()),
|
|
102
|
+
__param(3, Query()),
|
|
103
|
+
__param(4, Query()),
|
|
104
|
+
__param(5, Query())
|
|
105
|
+
], TaskController.prototype, "getTasks", null);
|
|
106
|
+
__decorate([
|
|
107
|
+
Example(task),
|
|
108
|
+
Get('{id}'),
|
|
109
|
+
Response(notFoundResp.status, notFoundResp.description),
|
|
110
|
+
__param(0, Request()),
|
|
111
|
+
__param(1, Path()),
|
|
112
|
+
__param(2, Query())
|
|
113
|
+
], TaskController.prototype, "getTask", null);
|
|
114
|
+
TaskController = __decorate([
|
|
115
|
+
Route('tasks'),
|
|
116
|
+
Security('*'),
|
|
117
|
+
Response(unauthorizedResp.status, unauthorizedResp.description),
|
|
118
|
+
Tags('tasks'),
|
|
119
|
+
provide(TaskController)
|
|
120
|
+
], TaskController);
|
|
121
|
+
export { TaskController };
|
package/dist/xoa/xoa.service.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import groupBy from 'lodash/groupBy.js';
|
|
2
|
+
import { featureUnauthorized } from 'xo-common/api-errors.js';
|
|
2
3
|
import semver from 'semver';
|
|
3
4
|
import { BACKUP_TYPE, VM_POWER_STATE, } from '@vates/types';
|
|
4
5
|
import { createLogger } from '@xen-orchestra/log';
|
|
@@ -167,11 +168,11 @@ export class XoaService {
|
|
|
167
168
|
}
|
|
168
169
|
return nHostsEol;
|
|
169
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Throw if no authorization
|
|
173
|
+
*/
|
|
170
174
|
async #getMissingPatchesInfo() {
|
|
171
175
|
const missingPatchesInfo = await this.#hostService.getMissingPatchesInfo();
|
|
172
|
-
if (!missingPatchesInfo.hasAuthorization) {
|
|
173
|
-
return { hasAuthorization: false };
|
|
174
|
-
}
|
|
175
176
|
const { hasAuthorization, nHostsFailed, nHostsWithMissingPatches, nPoolsWithMissingPatches } = missingPatchesInfo;
|
|
176
177
|
return {
|
|
177
178
|
hasAuthorization,
|
|
@@ -437,7 +438,16 @@ export class XoaService {
|
|
|
437
438
|
handleError: true,
|
|
438
439
|
}),
|
|
439
440
|
promiseWriteInStream({ maybePromise: this.#getPoolsStatus(), path: 'poolsStatus', stream }),
|
|
440
|
-
promiseWriteInStream({
|
|
441
|
+
promiseWriteInStream({
|
|
442
|
+
maybePromise: this.#getMissingPatchesInfo().catch(err => {
|
|
443
|
+
if (featureUnauthorized.is(err)) {
|
|
444
|
+
return { hasAuthorization: false };
|
|
445
|
+
}
|
|
446
|
+
throw err;
|
|
447
|
+
}),
|
|
448
|
+
path: 'missingPatches',
|
|
449
|
+
stream,
|
|
450
|
+
}),
|
|
441
451
|
promiseWriteInStream({
|
|
442
452
|
maybePromise: this.#getBackupRepositoriesSizeInfo(),
|
|
443
453
|
path: 'backupRepositories',
|