@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.
@@ -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 };
@@ -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({ maybePromise: this.#getMissingPatchesInfo(), path: 'missingPatches', stream }),
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',