next-lxd 1.0.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,599 @@
1
+ import { Resource } from './Resource';
2
+ import type {
3
+ LxdInstanceResponse,
4
+ LxdInstanceDeleteResponse,
5
+ LxdInstanceConsoleResponse,
6
+ LxdInstanceExecRequest,
7
+ LxdInstanceExecResponse,
8
+ LxdBaseResponse,
9
+ LxdInstancePutRequest,
10
+ LxdInstancePost,
11
+ LxdInstanceRebuildPost,
12
+ LxdInstanceStateResponse,
13
+ LxdInstanceStatePut,
14
+ LxdInstanceSnapshotsResponse,
15
+ LxdInstanceSnapshotResponse,
16
+ LxdInstanceSnapshotsPost,
17
+ LxdInstanceSnapshotPut,
18
+ LxdInstanceSnapshotPost,
19
+ LxdInstanceBackupsResponse,
20
+ LxdInstanceBackupResponse,
21
+ LxdInstanceBackupsPost,
22
+ LxdInstanceBackupPost
23
+ } from '../types';
24
+ import { Client } from './Client';
25
+ import {
26
+ nextConnect,
27
+ nextDisconnect,
28
+ nextReadDir,
29
+ nextStat,
30
+ nextLstat,
31
+ nextReadLink,
32
+ nextRealPath,
33
+ nextGetwd,
34
+ nextGlob,
35
+ nextOpen,
36
+ nextOpenFile,
37
+ nextCreate,
38
+ nextRead,
39
+ nextWrite,
40
+ nextCloseFile,
41
+ nextRemove,
42
+ nextRemoveDir,
43
+ nextRename,
44
+ nextPosixRename,
45
+ nextMkdir,
46
+ nextMkdirAll,
47
+ nextChmod,
48
+ nextChown,
49
+ nextChtimes
50
+ } from 'next-lxd-sftp';
51
+
52
+ export class Instance extends Resource {
53
+ public name: string;
54
+ public status: string;
55
+ public metadata: LxdInstanceResponse['metadata'];
56
+ public project?: string;
57
+
58
+ constructor(client: Client, options: LxdInstanceResponse) {
59
+ super(client);
60
+
61
+ this.name = options.metadata.name;
62
+ this.status = options.status;
63
+ this.metadata = options.metadata;
64
+ this.project = options.metadata.project;
65
+ }
66
+
67
+ async delete(): Promise<LxdInstanceDeleteResponse> {
68
+ return this.client.request({
69
+ method: 'DELETE',
70
+ path: `/1.0/instances/${this.name}${this.project ? `?project=${this.project}` : ''}`
71
+ }) as Promise<LxdInstanceDeleteResponse>;
72
+ }
73
+
74
+ async put(data: LxdInstancePutRequest, project?: string): Promise<LxdBaseResponse<void>> {
75
+ return this.client.request({
76
+ method: 'PUT',
77
+ path: `/1.0/instances/${this.name}${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`,
78
+ body: data
79
+ }) as Promise<LxdBaseResponse<void>>;
80
+ }
81
+
82
+ async patch(data: LxdInstancePutRequest, project?: string): Promise<LxdBaseResponse<void>> {
83
+ return this.client.request({
84
+ method: 'PATCH',
85
+ path: `/1.0/instances/${this.name}${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`,
86
+ body: data
87
+ }) as Promise<LxdBaseResponse<void>>;
88
+ }
89
+
90
+ async post(data: LxdInstancePost, project?: string): Promise<LxdBaseResponse<void>> {
91
+ return this.client.request({
92
+ method: 'POST',
93
+ path: `/1.0/instances/${this.name}${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`,
94
+ body: data
95
+ }) as Promise<LxdBaseResponse<void>>;
96
+ }
97
+
98
+ async rebuild(data: LxdInstanceRebuildPost, project?: string): Promise<LxdBaseResponse<void>> {
99
+ return this.client.request({
100
+ method: 'POST',
101
+ path: `/1.0/instances/${this.name}/rebuild${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`,
102
+ body: data
103
+ }) as Promise<LxdBaseResponse<void>>;
104
+ }
105
+
106
+ console = {
107
+ get: async () => {
108
+ return this.client.request({
109
+ path: `/1.0/instances/${this.name}/console${this.project ? `?project=${this.project}` : ''}`
110
+ });
111
+ },
112
+
113
+ post: async (data: {
114
+ height: number;
115
+ width: number;
116
+ type: 'console' | string;
117
+ }): Promise<LxdInstanceConsoleResponse> => {
118
+ return this.client.request({
119
+ method: 'POST',
120
+ path: `/1.0/instances/${this.name}/console${this.project ? `?project=${this.project}` : ''}`,
121
+ body: data
122
+ }) as Promise<LxdInstanceConsoleResponse>;
123
+ }
124
+ };
125
+
126
+ exec = async (data: LxdInstanceExecRequest): Promise<LxdInstanceExecResponse> => {
127
+ return this.client.request({
128
+ method: 'POST',
129
+ path: `/1.0/instances/${this.name}/exec${this.project ? `?project=${this.project}` : ''}`,
130
+ body: data
131
+ }) as Promise<LxdInstanceExecResponse>;
132
+ };
133
+
134
+ logs = {
135
+ get: async () => {
136
+ return this.client.request({
137
+ path: `/1.0/instances/${this.name}/logs${this.project ? `?project=${this.project}` : ''}`
138
+ });
139
+ },
140
+ file: (filename: string) => ({
141
+ get: async () => {
142
+ return this.client.request({
143
+ path: `/1.0/instances/${this.name}/logs/${filename}${this.project ? `?project=${this.project}` : ''}`
144
+ });
145
+ },
146
+ delete: async () => {
147
+ return this.client.request({
148
+ method: 'DELETE',
149
+ path: `/1.0/instances/${this.name}/logs/${filename}${this.project ? `?project=${this.project}` : ''}`
150
+ });
151
+ }
152
+ }),
153
+ execOutput: {
154
+ get: async () => {
155
+ return this.client.request({
156
+ path: `/1.0/instances/${this.name}/logs/exec-output${this.project ? `?project=${this.project}` : ''}`
157
+ });
158
+ }
159
+ }
160
+ };
161
+
162
+ state = {
163
+ get: async (project?: string): Promise<LxdInstanceStateResponse> => {
164
+ return this.client.request({
165
+ path: `/1.0/instances/${this.name}/state${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`
166
+ }) as Promise<LxdInstanceStateResponse>;
167
+ },
168
+
169
+ put: async (data: LxdInstanceStatePut, project?: string): Promise<LxdBaseResponse<void>> => {
170
+ return this.client.request({
171
+ method: 'PUT',
172
+ path: `/1.0/instances/${this.name}/state${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`,
173
+ body: data
174
+ }) as Promise<LxdBaseResponse<void>>;
175
+ }
176
+ };
177
+
178
+ files = {
179
+ file: (path: string) => ({
180
+ get: async () => {
181
+ const file = await this.client.requestRaw({
182
+ path: `/1.0/instances/${this.name}/files?path=${path}${this.project ? `&project=${this.project}` : ''}`
183
+ });
184
+ return {
185
+ headers: file.headers,
186
+ body: file.body as LxdBaseResponse<string[]> | any
187
+ };
188
+ },
189
+ delete: async () => {
190
+ return this.client.request({
191
+ method: 'DELETE',
192
+ path: `/1.0/instances/${this.name}/files?path=${path}${this.project ? `&project=${this.project}` : ''}`
193
+ });
194
+ },
195
+ head: async () => {
196
+ const file = await this.client.requestRaw({
197
+ method: 'HEAD',
198
+ path: `/1.0/instances/${this.name}/files?path=${path}${this.project ? `&project=${this.project}` : ''}`
199
+ });
200
+ return {
201
+ headers: file.headers,
202
+ body: file.body as LxdBaseResponse<string[]> | any
203
+ };
204
+ },
205
+ post: async (
206
+ body: any,
207
+ headers?: {
208
+ 'X-LXD-uid': number;
209
+ 'X-LXD-gid': number;
210
+ 'X-LXD-mode': number;
211
+ 'X-LXD-type': string | 'file' | 'symlink' | 'directory';
212
+ 'X-LXD-modify-perm': string;
213
+ 'X-LXD-write': 'overwrite' | 'append';
214
+ }
215
+ ) => {
216
+ return this.client.request({
217
+ method: 'POST',
218
+ path: `/1.0/instances/${this.name}/files?path=${path}${this.project ? `&project=${this.project}` : ''}`,
219
+ headers,
220
+ body
221
+ });
222
+ }
223
+ })
224
+ };
225
+
226
+ snapshots = {
227
+ list: async (project?: string): Promise<LxdInstanceSnapshotsResponse> => {
228
+ return this.client.request({
229
+ path: `/1.0/instances/${this.name}/snapshots${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`
230
+ }) as Promise<LxdInstanceSnapshotsResponse>;
231
+ },
232
+
233
+ get: async (snapshotName: string, project?: string): Promise<LxdInstanceSnapshotResponse> => {
234
+ return this.client.request({
235
+ path: `/1.0/instances/${this.name}/snapshots/${snapshotName}${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`
236
+ }) as Promise<LxdInstanceSnapshotResponse>;
237
+ },
238
+
239
+ post: async (
240
+ data: LxdInstanceSnapshotsPost,
241
+ project?: string
242
+ ): Promise<LxdBaseResponse<void>> => {
243
+ return this.client.request({
244
+ method: 'POST',
245
+ path: `/1.0/instances/${this.name}/snapshots${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`,
246
+ body: data
247
+ }) as Promise<LxdBaseResponse<void>>;
248
+ },
249
+
250
+ snapshot: (snapshotName: string) => ({
251
+ put: async (
252
+ data: LxdInstanceSnapshotPut,
253
+ project?: string
254
+ ): Promise<LxdBaseResponse<void>> => {
255
+ return this.client.request({
256
+ method: 'PUT',
257
+ path: `/1.0/instances/${this.name}/snapshots/${snapshotName}${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`,
258
+ body: data
259
+ }) as Promise<LxdBaseResponse<void>>;
260
+ },
261
+
262
+ patch: async (
263
+ data: LxdInstanceSnapshotPut,
264
+ project?: string
265
+ ): Promise<LxdBaseResponse<void>> => {
266
+ return this.client.request({
267
+ method: 'PATCH',
268
+ path: `/1.0/instances/${this.name}/snapshots/${snapshotName}${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`,
269
+ body: data
270
+ }) as Promise<LxdBaseResponse<void>>;
271
+ },
272
+
273
+ delete: async (project?: string): Promise<LxdBaseResponse<void>> => {
274
+ return this.client.request({
275
+ method: 'DELETE',
276
+ path: `/1.0/instances/${this.name}/snapshots/${snapshotName}${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`
277
+ }) as Promise<LxdBaseResponse<void>>;
278
+ },
279
+
280
+ post: async (
281
+ data: LxdInstanceSnapshotPost,
282
+ project?: string
283
+ ): Promise<LxdBaseResponse<void>> => {
284
+ return this.client.request({
285
+ method: 'POST',
286
+ path: `/1.0/instances/${this.name}/snapshots/${snapshotName}${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`,
287
+ body: data
288
+ }) as Promise<LxdBaseResponse<void>>;
289
+ }
290
+ })
291
+ };
292
+
293
+ backups = {
294
+ list: async (project?: string): Promise<LxdInstanceBackupsResponse> => {
295
+ return this.client.request({
296
+ path: `/1.0/instances/${this.name}/backups${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`
297
+ }) as Promise<LxdInstanceBackupsResponse>;
298
+ },
299
+
300
+ get: async (backupName: string, project?: string): Promise<LxdInstanceBackupResponse> => {
301
+ return this.client.request({
302
+ path: `/1.0/instances/${this.name}/backups/${backupName}${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`
303
+ }) as Promise<LxdInstanceBackupResponse>;
304
+ },
305
+
306
+ post: async (
307
+ data: LxdInstanceBackupsPost,
308
+ project?: string
309
+ ): Promise<LxdBaseResponse<void>> => {
310
+ return this.client.request({
311
+ method: 'POST',
312
+ path: `/1.0/instances/${this.name}/backups${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`,
313
+ body: data
314
+ }) as Promise<LxdBaseResponse<void>>;
315
+ },
316
+
317
+ backup: (backupName: string) => ({
318
+ delete: async (project?: string): Promise<LxdBaseResponse<void>> => {
319
+ return this.client.request({
320
+ method: 'DELETE',
321
+ path: `/1.0/instances/${this.name}/backups/${backupName}${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`
322
+ }) as Promise<LxdBaseResponse<void>>;
323
+ },
324
+
325
+ post: async (
326
+ data: LxdInstanceBackupPost,
327
+ project?: string
328
+ ): Promise<LxdBaseResponse<void>> => {
329
+ return this.client.request({
330
+ method: 'POST',
331
+ path: `/1.0/instances/${this.name}/backups/${backupName}${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`,
332
+ body: data
333
+ }) as Promise<LxdBaseResponse<void>>;
334
+ },
335
+
336
+ export: async (project?: string) => {
337
+ return this.client.requestRaw({
338
+ method: 'GET',
339
+ path: `/1.0/instances/${this.name}/backups/${backupName}/export${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`
340
+ });
341
+ }
342
+ })
343
+ };
344
+
345
+ metaData = {
346
+ get: async () => {
347
+ const meta = await this.client.request({
348
+ method: 'GET',
349
+ path: `/1.0/instances/${this.name}/metadata${this.project ? `?project=${this.project}` : ''}`
350
+ });
351
+ return meta as LxdBaseResponse<unknown>;
352
+ },
353
+
354
+ put: async (
355
+ data: Record<string, unknown>,
356
+ project?: string
357
+ ): Promise<LxdBaseResponse<void>> => {
358
+ return this.client.request({
359
+ method: 'PUT',
360
+ path: `/1.0/instances/${this.name}/metadata${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`,
361
+ body: data
362
+ }) as Promise<LxdBaseResponse<void>>;
363
+ },
364
+
365
+ patch: async (
366
+ data: Record<string, unknown>,
367
+ project?: string
368
+ ): Promise<LxdBaseResponse<void>> => {
369
+ return this.client.request({
370
+ method: 'PATCH',
371
+ path: `/1.0/instances/${this.name}/metadata${(project ?? this.project) ? `?project=${project ?? this.project}` : ''}`,
372
+ body: data
373
+ }) as Promise<LxdBaseResponse<void>>;
374
+ }
375
+ };
376
+
377
+ sftp: Record<string, any> = {
378
+ connect: async (): Promise<{ sessionId: number }> => {
379
+ return nextConnect({
380
+ address: this.client.url.host,
381
+ cert: this.client.clientInfo.cert,
382
+ key: this.client.clientInfo.key,
383
+ instance: this.name,
384
+ insecure: this.client.clientInfo.allowInsecure
385
+ }) as { sessionId: number };
386
+ },
387
+
388
+ session: (sessionId: number): Record<string, any> => ({
389
+ disconnect: async () => {
390
+ return nextDisconnect({ sessionId });
391
+ },
392
+
393
+ readDir: async (path: string) => {
394
+ return nextReadDir({ sessionId, path });
395
+ },
396
+
397
+ stat: async (path: string) => {
398
+ return nextStat({ sessionId, path });
399
+ },
400
+
401
+ lStat: async (path: string) => {
402
+ return nextLstat({ sessionId, path });
403
+ },
404
+
405
+ readLink: async (path: string) => {
406
+ return nextReadLink({ sessionId, path });
407
+ },
408
+
409
+ realPath: async (path: string) => {
410
+ return nextRealPath({ sessionId, path });
411
+ },
412
+
413
+ getWd: async () => {
414
+ return nextGetwd({ sessionId });
415
+ },
416
+
417
+ glob: async (pattern: string) => {
418
+ return nextGlob({ sessionId, pattern });
419
+ },
420
+
421
+ open: async (path: string) => {
422
+ const result = (await nextOpen({
423
+ sessionId,
424
+ path
425
+ })) as { fileId: number };
426
+ const fileId = result.fileId;
427
+
428
+ return {
429
+ fileId,
430
+
431
+ read: async (length?: number): Promise<Buffer> => {
432
+ const result = (await nextRead({
433
+ fileId,
434
+ length
435
+ })) as { data: string };
436
+
437
+ return Buffer.from(result.data, 'base64');
438
+ },
439
+
440
+ write: async (data: Buffer | Uint8Array | string) => {
441
+ return nextWrite({
442
+ fileId,
443
+ data: Buffer.isBuffer(data)
444
+ ? data.toString('base64')
445
+ : Buffer.from(data).toString('base64')
446
+ });
447
+ },
448
+
449
+ close: async () => {
450
+ return nextCloseFile({ fileId });
451
+ }
452
+ };
453
+ },
454
+
455
+ openFile: async (path: string, flags?: number) => {
456
+ const result = (await nextOpenFile({
457
+ sessionId,
458
+ path,
459
+ flags
460
+ })) as { fileId: number };
461
+ const fileId = result.fileId;
462
+
463
+ return {
464
+ fileId,
465
+
466
+ read: async (length?: number): Promise<Buffer> => {
467
+ const result = (await nextRead({
468
+ fileId,
469
+ length
470
+ })) as { data: string };
471
+
472
+ return Buffer.from(result.data, 'base64');
473
+ },
474
+
475
+ write: async (data: Buffer | Uint8Array | string) => {
476
+ return nextWrite({
477
+ fileId,
478
+ data: Buffer.isBuffer(data)
479
+ ? data.toString('base64')
480
+ : Buffer.from(data).toString('base64')
481
+ });
482
+ },
483
+
484
+ close: async () => {
485
+ return nextCloseFile({ fileId });
486
+ }
487
+ };
488
+ },
489
+
490
+ create: async (path: string) => {
491
+ const result = (await nextCreate({
492
+ sessionId,
493
+ path
494
+ })) as { fileId: number };
495
+ const fileId = result.fileId;
496
+
497
+ return {
498
+ fileId,
499
+
500
+ read: async (length?: number): Promise<Buffer> => {
501
+ const result = (await nextRead({
502
+ fileId,
503
+ length
504
+ })) as { data: string };
505
+
506
+ return Buffer.from(result.data, 'base64');
507
+ },
508
+
509
+ write: async (data: Buffer | Uint8Array | string) => {
510
+ return nextWrite({
511
+ fileId,
512
+ data: Buffer.isBuffer(data)
513
+ ? data.toString('base64')
514
+ : Buffer.from(data).toString('base64')
515
+ });
516
+ },
517
+
518
+ close: async () => {
519
+ return nextCloseFile({ fileId });
520
+ }
521
+ };
522
+ },
523
+
524
+ closeFile: async (fileId: number) => {
525
+ return nextCloseFile({ fileId });
526
+ },
527
+
528
+ remove: async (path: string) => {
529
+ return nextRemove({
530
+ sessionId,
531
+ path
532
+ });
533
+ },
534
+
535
+ removeDir: async (path: string) => {
536
+ return nextRemoveDir({
537
+ sessionId,
538
+ path
539
+ });
540
+ },
541
+
542
+ rename: async (oldPath: string, newPath: string) => {
543
+ return nextRename({
544
+ sessionId,
545
+ oldPath,
546
+ newPath
547
+ });
548
+ },
549
+
550
+ posixRename: async (oldPath: string, newPath: string) => {
551
+ return nextPosixRename({
552
+ sessionId,
553
+ oldPath,
554
+ newPath
555
+ });
556
+ },
557
+
558
+ mkdir: async (path: string) => {
559
+ return nextMkdir({
560
+ sessionId,
561
+ path
562
+ });
563
+ },
564
+
565
+ mkdirAll: async (path: string) => {
566
+ return nextMkdirAll({
567
+ sessionId,
568
+ path
569
+ });
570
+ },
571
+
572
+ chmod: async (path: string, mode: number) => {
573
+ return nextChmod({
574
+ sessionId,
575
+ path,
576
+ mode
577
+ });
578
+ },
579
+
580
+ chown: async (path: string, uid: number, gid: number) => {
581
+ return nextChown({
582
+ sessionId,
583
+ path,
584
+ uid,
585
+ gid
586
+ });
587
+ },
588
+
589
+ chtimes: async (path: string, atime: Date | number, mtime: Date | number) => {
590
+ return nextChtimes({
591
+ sessionId,
592
+ path,
593
+ atime: typeof atime === 'object' ? atime.toISOString() : String(atime),
594
+ mtime: typeof mtime === 'object' ? mtime.toISOString() : String(mtime)
595
+ });
596
+ }
597
+ })
598
+ };
599
+ }
@@ -0,0 +1,44 @@
1
+ import { Resource } from './Resource';
2
+ import { Instance } from './Instance';
3
+
4
+ import type { LxdInstanceResponse, LxdInstancesResponse, InstanceCreateRequest } from '../types';
5
+
6
+ export class Instances extends Resource {
7
+ /**
8
+ * Get a list of all instances.
9
+ */
10
+ async list(project?: string): Promise<LxdInstancesResponse> {
11
+ return this.client.request({
12
+ method: 'GET',
13
+ path: `/1.0/instances${project ? `?project=${project}` : ''}`
14
+ });
15
+ }
16
+
17
+ /**
18
+ * Get the state and configuration of a specific instance.
19
+ */
20
+ async get(name: string, project?: string): Promise<Instance> {
21
+ const data = (await this.client.request({
22
+ method: 'GET',
23
+ path: `/1.0/instances/${name}${project ? `?project=${project}` : ''}`
24
+ })) as LxdInstanceResponse;
25
+ return new Instance(this.client, data);
26
+ }
27
+
28
+ async post(config: InstanceCreateRequest, project?: string, target?: string): Promise<Instance> {
29
+ const params = new URLSearchParams();
30
+
31
+ if (project) params.set('project', project);
32
+ if (target) params.set('target', target);
33
+
34
+ const query = params.toString();
35
+
36
+ await this.client.request({
37
+ method: 'POST',
38
+ path: `/1.0/instances${query ? `?${query}` : ''}`,
39
+ body: config
40
+ });
41
+
42
+ return this.get(config.name, project);
43
+ }
44
+ }