@homeflare/alchemy 0.45.0 → 0.46.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/proxmox/generated/constraints/index.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-access.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-backup.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-ceph.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-firewall.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-ha.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-metrics.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-notifications.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-replication.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-sdn.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-ceph.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-disks.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-lxc.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-network.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-qemu.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-qemu.d.ts.map +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-storage.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-pools.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-storage.d.ts +1 -1
- package/dist/proxmox/index.d.ts +1 -0
- package/dist/proxmox/index.d.ts.map +1 -1
- package/dist/proxmox/index.js +283 -130
- package/dist/proxmox/index.js.map +31 -27
- package/dist/proxmox/qemu-dns.d.ts +2 -0
- package/dist/proxmox/qemu-dns.d.ts.map +1 -0
- package/dist/proxmox/qemu-errors.d.ts +1 -0
- package/dist/proxmox/qemu-errors.d.ts.map +1 -1
- package/dist/proxmox/qemu-form.d.ts.map +1 -1
- package/dist/proxmox/qemu-judge.d.ts.map +1 -1
- package/dist/proxmox/qemu-lifecycle.d.ts +15 -10
- package/dist/proxmox/qemu-lifecycle.d.ts.map +1 -1
- package/dist/proxmox/qemu-props.d.ts +10 -0
- package/dist/proxmox/qemu-props.d.ts.map +1 -1
- package/dist/proxmox/qemu-resize.d.ts +10 -0
- package/dist/proxmox/qemu-resize.d.ts.map +1 -0
- package/dist/proxmox/qemu-size.d.ts +20 -0
- package/dist/proxmox/qemu-size.d.ts.map +1 -0
- package/dist/proxmox/qemu-spec.d.ts +25 -0
- package/dist/proxmox/qemu-spec.d.ts.map +1 -0
- package/dist/verify/fake-engine.d.ts +4 -2
- package/dist/verify/fake-engine.d.ts.map +1 -1
- package/docs/proxmox-qemu-resize.md +62 -0
- package/package.json +1 -1
- package/src/proxmox/generated/constraints/index.ts +1 -1
- package/src/proxmox/generated/constraints/pve-access.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-backup.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-ceph.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-firewall.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-ha.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-metrics.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-notifications.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-replication.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-sdn.ts +1 -1
- package/src/proxmox/generated/constraints/pve-nodes-ceph.ts +1 -1
- package/src/proxmox/generated/constraints/pve-nodes-disks.ts +1 -1
- package/src/proxmox/generated/constraints/pve-nodes-lxc.ts +1 -1
- package/src/proxmox/generated/constraints/pve-nodes-network.ts +1 -1
- package/src/proxmox/generated/constraints/pve-nodes-qemu.ts +6 -1
- package/src/proxmox/generated/constraints/pve-nodes-storage.ts +1 -1
- package/src/proxmox/generated/constraints/pve-pools.ts +1 -1
- package/src/proxmox/generated/constraints/pve-storage.ts +1 -1
- package/src/proxmox/index.ts +1 -0
- package/src/proxmox/qemu-dns.test.ts +73 -0
- package/src/proxmox/qemu-dns.ts +32 -0
- package/src/proxmox/qemu-errors.ts +1 -0
- package/src/proxmox/qemu-form.ts +6 -3
- package/src/proxmox/qemu-judge.ts +2 -1
- package/src/proxmox/qemu-lifecycle.ts +28 -47
- package/src/proxmox/qemu-props.ts +14 -2
- package/src/proxmox/qemu-resize-lock.test.ts +121 -0
- package/src/proxmox/qemu-resize-recovery.test.ts +81 -0
- package/src/proxmox/qemu-resize.test.ts +199 -0
- package/src/proxmox/qemu-resize.ts +86 -0
- package/src/proxmox/qemu-size.test.ts +64 -0
- package/src/proxmox/qemu-size.ts +95 -0
- package/src/proxmox/qemu-spec.ts +44 -0
- package/src/proxmox/qemu-volume.ts +5 -5
- package/src/verify/fake-engine.ts +6 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qemu-dns.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-dns.ts"],"names":[],"mappings":"AAuBA,eAAO,MAAM,WAAW,eAAgB,OAAO,KAAG,MAAM,EAQvD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qemu-errors.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-errors.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF"}
|
|
1
|
+
{"version":3,"file":"qemu-errors.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-errors.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,sBAAsB;IACnC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qemu-form.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-form.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,KAAK,OAAO,EAKb,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"qemu-form.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-form.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,KAAK,OAAO,EAKb,MAAM,iBAAiB,CAAC;AAGzB;;;;GAIG;AACH,eAAO,MAAM,YAAY,UAAW,OAAO,KAAG,MAAM,EAKnD,CAAC;AAEF,2FAA2F;AAC3F,eAAO,MAAM,IAAI,UAAW,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAO1D,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,UAAW,OAAO;;CAGvC,CAAC;AAEH,qGAAqG;AACrG,eAAO,MAAM,UAAU,aAAO,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qemu-judge.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-judge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,KAAK,OAAO,EAAsD,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"qemu-judge.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-judge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,KAAK,OAAO,EAAsD,MAAM,iBAAiB,CAAC;AAKnG,MAAM,MAAM,QAAQ,GAAG;IACrB,mFAAmF;IACnF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC,CAAC;AAEF,eAAO,MAAM,KAAK,UAAW,OAAO,UAAU,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,QA8CtE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,SAAU,MAAM,OAAO,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,SAI1B,CAAC"}
|
|
@@ -1,40 +1,45 @@
|
|
|
1
1
|
import type { Input } from 'alchemy/Input';
|
|
2
2
|
import * as nodes from '@distilled.cloud/proxmox/nodes';
|
|
3
3
|
import * as Effect from 'effect/Effect';
|
|
4
|
-
import
|
|
5
|
-
|
|
4
|
+
import type * as HttpClient from 'effect/unstable/http/HttpClient';
|
|
5
|
+
import { QemuRefusedError } from './qemu-errors.ts';
|
|
6
|
+
import type { VmAttributes, VmProps } from './qemu-props.ts';
|
|
7
|
+
import { type QemuDiskResizeRefused } from './qemu-size.ts';
|
|
8
|
+
type QemuLifecycleError = Effect.Error<ReturnType<typeof readQemu>> | nodes.PutNodeQemuResizeError | QemuRefusedError | QemuDiskResizeRefused;
|
|
9
|
+
export declare const readQemu: (props: VmProps) => Effect.Effect<VmAttributes | undefined, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied, HttpClient.HttpClient>;
|
|
6
10
|
/** No purge, no skiplock, no destroy-unreferenced-disks. A missing config is already gone. */
|
|
7
|
-
export declare const deleteQemu: (props: VmProps) => Effect.Effect<void | undefined, Error | import("./credential-errors.ts").PveCredentialDenied | nodes.ProxmoxOpError,
|
|
11
|
+
export declare const deleteQemu: (props: VmProps) => Effect.Effect<void | undefined, Error | import("./credential-errors.ts").PveCredentialDenied | nodes.ProxmoxOpError, HttpClient.HttpClient>;
|
|
8
12
|
export declare const qemuHandlers: {
|
|
9
13
|
list: () => Effect.Effect<never[], never, never>;
|
|
10
14
|
/**
|
|
11
15
|
* ⛔ `Unowned` UNLESS STATE ALREADY VOUCHES FOR IT (C2). With no attributes this is Alchemy's
|
|
12
16
|
* adoption probe or the recovery read for an interrupted create (ownership/probe.ts); `settled`
|
|
13
|
-
*
|
|
14
|
-
*
|
|
17
|
+
* uses the same config comparison as reconcile. Disk growth is a post-create step, so its
|
|
18
|
+
* drift cannot disown a VM after an interrupted/failed resize (measured 2026-10-05).
|
|
15
19
|
*/
|
|
16
20
|
read: (args_0: {
|
|
17
21
|
fqn: string;
|
|
18
22
|
instanceId: string;
|
|
19
23
|
olds: VmProps;
|
|
20
24
|
output: VmAttributes | undefined;
|
|
21
|
-
}) => Effect.Effect<VmAttributes | undefined, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied,
|
|
25
|
+
}) => Effect.Effect<VmAttributes | undefined, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied, HttpClient.HttpClient>;
|
|
22
26
|
diff: (args_0: {
|
|
23
27
|
news: Input<VmProps>;
|
|
24
28
|
olds: VmProps;
|
|
25
29
|
output: VmAttributes | undefined;
|
|
26
30
|
}) => Effect.Effect<{
|
|
27
|
-
readonly action:
|
|
28
|
-
} | undefined,
|
|
31
|
+
readonly action: 'noop' | 'update';
|
|
32
|
+
} | undefined, QemuLifecycleError, HttpClient.HttpClient>;
|
|
29
33
|
reconcile: (args_0: {
|
|
30
34
|
fqn: string;
|
|
31
35
|
instanceId: string;
|
|
32
36
|
news: VmProps;
|
|
33
37
|
olds: VmProps | undefined;
|
|
34
38
|
output: VmAttributes | undefined;
|
|
35
|
-
}) => Effect.Effect<VmAttributes,
|
|
39
|
+
}) => Effect.Effect<VmAttributes, QemuLifecycleError, HttpClient.HttpClient>;
|
|
36
40
|
delete: ({ olds }: {
|
|
37
41
|
olds: VmProps;
|
|
38
|
-
}) => Effect.Effect<void | undefined, Error | import("./credential-errors.ts").PveCredentialDenied | nodes.ProxmoxOpError,
|
|
42
|
+
}) => Effect.Effect<void | undefined, Error | import("./credential-errors.ts").PveCredentialDenied | nodes.ProxmoxOpError, HttpClient.HttpClient>;
|
|
39
43
|
};
|
|
44
|
+
export {};
|
|
40
45
|
//# sourceMappingURL=qemu-lifecycle.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qemu-lifecycle.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-lifecycle.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,KAAK,MAAM,gCAAgC,CAAC;AACxD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"qemu-lifecycle.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-lifecycle.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,KAAK,MAAM,gCAAgC,CAAC;AACxD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,UAAU,MAAM,iCAAiC,CAAC;AAKnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAI7D,OAAO,EAAE,KAAK,qBAAqB,EAAyC,MAAM,gBAAgB,CAAC;AAOnG,KAAK,kBAAkB,GACnB,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,GACzC,KAAK,CAAC,sBAAsB,GAC5B,gBAAgB,GAChB,qBAAqB,CAAC;AAE1B,eAAO,MAAM,QAAQ,UAAW,OAAO,kMAapC,CAAC;AAEJ,8FAA8F;AAC9F,eAAO,MAAM,UAAU,UAAW,OAAO,gJAMyB,CAAC;AAmBnE,eAAO,MAAM,YAAY;IACvB,IAAI;IACJ;;;;;OAKG;IACH,IAAI;aAMG,MAAM;oBACC,MAAM;cACZ,OAAO;gBACL,YAAY,GAAG,SAAS;;IAUlC,IAAI;cAKI,KAAK,CAAC,OAAO,CAAC;cACd,OAAO;gBACL,YAAY,GAAG,SAAS;;yBAEb,MAAM,GAAG,QAAQ;;IA4BtC,SAAS;aAOF,MAAM;oBACC,MAAM;cACZ,OAAO;cACP,OAAO,GAAG,SAAS;gBACjB,YAAY,GAAG,SAAS;;IAuDlC,MAAM,aAAa;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE;CACrC,CAAC"}
|
|
@@ -46,6 +46,16 @@ export interface VmProps extends WithTarget {
|
|
|
46
46
|
boot?: string;
|
|
47
47
|
/** e.g. `virtio-scsi-single`. */
|
|
48
48
|
scsihw?: string;
|
|
49
|
+
/** Cloud-init DNS servers: PVE's `address-list` (IP addresses or DNS names). */
|
|
50
|
+
nameserver?: string;
|
|
51
|
+
/** Cloud-init DNS search domains, in PVE's wire spelling. */
|
|
52
|
+
searchdomain?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Minimum disk sizes in GiB, e.g. `{ scsi0: 64 }`, grown after import completes.
|
|
55
|
+
* Existing larger disks are left alone. Lowering a previously declared target is refused.
|
|
56
|
+
* These are resize targets, never config fields; declare the corresponding disk slot too.
|
|
57
|
+
*/
|
|
58
|
+
diskSizesGiB?: Partial<Record<`scsi${number}` | `ide${number}`, number>>;
|
|
49
59
|
/**
|
|
50
60
|
* `local-zfs:32` to create a new volume, or the live volume string as adopted —
|
|
51
61
|
* `cephtb4:vm-101-disk-0,size=32G` (n is 0 to 30, pve-qemu-server's own `$MAX_SCSI_DISKS`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qemu-props.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-props.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,kGAAkG;AAClG,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;AAEtC,MAAM,WAAW,OAAQ,SAAQ,UAAU;IACzC,uFAAuF;IACvF,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,yFAAyF;IACzF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,CAAC,IAAI,EAAE,OAAO,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;IAC5C;;;OAGG;IACH,CAAC,GAAG,EAAE,MAAM,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;IAC1C;;;;OAIG;IACH,CAAC,SAAS,EAAE,MAAM,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;IAChD,mFAAmF;IACnF,CAAC,QAAQ,EAAE,WAAW,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;IACpD,gFAAgF;IAChF,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;IAChD,kCAAkC;IAClC,UAAU,CAAC,EAAE,KAAK,CAAC;IACnB,wCAAwC;IACxC,OAAO,CAAC,EAAE,KAAK,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,2FAA2F;IAC3F,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAKD,8FAA8F;AAC9F,eAAO,MAAM,OAAO;aAClB,GAAG,EAAE,CAAC;aACN,QAAQ,EAAE,EAAE;aACZ,GAAG,EAAE,EAAE;aACP,IAAI,EAAE,EAAE;aACR,MAAM,EAAE,CAAC;CACD,CAAC;AACX,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,OAAO,CAAC;AAEjD,4FAA4F;AAC5F,eAAO,MAAM,UAAU,QAAS,MAAM,KAAG,SAAS,CAAC,aAAa,EAAE,MAAM,CAAC,GAAG,SAM3E,CAAC;
|
|
1
|
+
{"version":3,"file":"qemu-props.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-props.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as Effect from 'effect/Effect';
|
|
2
|
+
import { type VmProps } from './qemu-props.ts';
|
|
3
|
+
/**
|
|
4
|
+
* ⛔ Observe the unlocked, allocated disk before each resize, including recovery after import.
|
|
5
|
+
* Absolute targets make retries safe; `+60G` would grow again after interrupted state writes.
|
|
6
|
+
* This resource never starts a guest. Its caller can power on only after reconcile returns.
|
|
7
|
+
* SDK failures retain their generated tags; provider refusals are QemuDiskResizeRefused.
|
|
8
|
+
*/
|
|
9
|
+
export declare const resizeDisks: (props: VmProps) => Effect.Effect<undefined, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
10
|
+
//# sourceMappingURL=qemu-resize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qemu-resize.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-resize.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,KAAK,OAAO,EAAgB,MAAM,iBAAiB,CAAC;AAqC7D;;;;;GAKG;AACH,eAAO,MAAM,WAAW,UAAW,OAAO,kNAuCtC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as Effect from 'effect/Effect';
|
|
2
|
+
import { type VmProps } from './qemu-props.ts';
|
|
3
|
+
declare const QemuDiskResizeRefused_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
4
|
+
readonly _tag: "QemuDiskResizeRefused";
|
|
5
|
+
} & Readonly<A>;
|
|
6
|
+
export declare class QemuDiskResizeRefused extends QemuDiskResizeRefused_base<{
|
|
7
|
+
readonly disk: string;
|
|
8
|
+
readonly message: string;
|
|
9
|
+
}> {
|
|
10
|
+
}
|
|
11
|
+
/** PVE config reports binary sizes, including fractional G and integer M/K for imported images. */
|
|
12
|
+
export declare const diskBytes: (config: string | undefined) => number | undefined;
|
|
13
|
+
/** Validate the whole declaration before any write, including a later attempted target decrease. */
|
|
14
|
+
export declare const validateDiskSizes: (props: VmProps, olds?: VmProps) => Effect.Effect<undefined, QemuDiskResizeRefused, never>;
|
|
15
|
+
/** Capacity drift drives reconcile; recovery ownership ignores it because resize follows create. */
|
|
16
|
+
export declare const diskSizeDrift: (props: VmProps, config: Record<string, string>) => string[];
|
|
17
|
+
/** Missing slots may be imported by the upcoming config write; unreadable existing sizes fail closed. */
|
|
18
|
+
export declare const checkLiveDiskSizes: (props: VmProps, config: Record<string, string>, allowMissing?: boolean) => Effect.Effect<undefined, QemuDiskResizeRefused, never>;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=qemu-size.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qemu-size.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-size.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,KAAK,OAAO,EAA6B,MAAM,iBAAiB,CAAC;;;;AAG1E,qBAAa,qBAAsB,SAAQ,2BAA0C;IACnF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;AAEL,mGAAmG;AACnG,eAAO,MAAM,SAAS,WAAY,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,SAO/D,CAAC;AAEF,oGAAoG;AACpG,eAAO,MAAM,iBAAiB,UAAW,OAAO,SAAS,OAAO,2DAwC5D,CAAC;AAEL,oGAAoG;AACpG,eAAO,MAAM,aAAa,UAAW,OAAO,UAAU,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,MAAM,EAKzC,CAAC;AAE7C,yGAAyG;AACzG,eAAO,MAAM,kBAAkB,UACtB,OAAO,UACN,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,mFAmB5B,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** QEMU config forms and vendor guards, separated from lifecycle to keep both reviewable. */
|
|
2
|
+
import { createForm } from './qemu-form.ts';
|
|
3
|
+
import { type VmAttributes, type VmProps } from './qemu-props.ts';
|
|
4
|
+
export declare const attributesOf: (live: Record<string, unknown>, props: VmProps) => VmAttributes;
|
|
5
|
+
/**
|
|
6
|
+
* ⚠️ KEPT ONLY TO SATISFY `PveSpec`'S REQUIRED FIELD — `qemu-judge.ts`'s `judge` is what diff and
|
|
7
|
+
* reconcile actually decide by, since a plain string compare is exactly the bug C1 found (it
|
|
8
|
+
* never matches the "new disk" or MAC-less spellings a declaration may use).
|
|
9
|
+
*/
|
|
10
|
+
declare const matches: (attributes: VmAttributes, props: VmProps) => boolean;
|
|
11
|
+
export declare const spec: {
|
|
12
|
+
attributes: typeof attributesOf;
|
|
13
|
+
collection: (props: VmProps) => string;
|
|
14
|
+
createForm: typeof createForm;
|
|
15
|
+
endpoint: {
|
|
16
|
+
create: string;
|
|
17
|
+
update: string;
|
|
18
|
+
};
|
|
19
|
+
matches: typeof matches;
|
|
20
|
+
path: (props: VmProps) => string;
|
|
21
|
+
updateForm: typeof import("./qemu-form.ts").form;
|
|
22
|
+
};
|
|
23
|
+
export declare const guardCreate: (props: VmProps, presence: boolean) => import("effect/Effect").Effect<void>, guardUpdate: (props: VmProps) => import("effect/Effect").Effect<void>;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=qemu-spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qemu-spec.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-spec.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,OAAO,EAAE,UAAU,EAAc,MAAM,gBAAgB,CAAC;AACxD,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,OAAO,EAMb,MAAM,iBAAiB,CAAC;AAIzB,eAAO,MAAM,YAAY,SAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,OAAO,KAAG,YAI3E,CAAC;AAEH;;;;GAIG;AACH,QAAA,MAAM,OAAO,eAAgB,YAAY,SAAS,OAAO,YAG2B,CAAC;AAErF,eAAO,MAAM,IAAI;;wBAEK,OAAO;;;QAGzB,MAAM;QACN,MAAM;;;kBAGM,OAAO;;CAEmB,CAAC;AAE3C,eAAO,MAAQ,WAAW,+EAAE,WAAW,0DAAqB,CAAC"}
|
|
@@ -53,7 +53,7 @@ export type DriftRow = {
|
|
|
53
53
|
readonly action: string;
|
|
54
54
|
};
|
|
55
55
|
export interface FakeEngine {
|
|
56
|
-
/** Plan and apply `body
|
|
56
|
+
/** Plan and apply `body` with the configured adoption policy; resolves to planned actions. */
|
|
57
57
|
readonly deploy: (body: Body) => Promise<Record<string, string>>;
|
|
58
58
|
/** Verify `body` against what the earlier deploys recorded. */
|
|
59
59
|
readonly verify: (body: Body, options?: VerifyOptions) => Promise<AdoptReport>;
|
|
@@ -78,7 +78,9 @@ export interface FakeEngine {
|
|
|
78
78
|
* hands in its real provider over a fake transport (proxmox/ceph-pool-adopt.test.ts).
|
|
79
79
|
* ⚠️ THE CASTS ARE AT THE ENGINE'S TYPED BOUNDARY — openbao/fake-stack.ts has the reasoning.
|
|
80
80
|
*/
|
|
81
|
-
export declare const engineOver: <ROut, E, RIn>(layer: Layer.Layer<ROut, E, RIn
|
|
81
|
+
export declare const engineOver: <ROut, E, RIn>(layer: Layer.Layer<ROut, E, RIn>, options?: {
|
|
82
|
+
readonly adopt?: boolean;
|
|
83
|
+
}) => FakeEngine;
|
|
82
84
|
/** The fake family over `cloud`. */
|
|
83
85
|
export declare const fakeEngine: (cloud: Cloud) => FakeEngine;
|
|
84
86
|
//# sourceMappingURL=fake-engine.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fake-engine.d.ts","sourceRoot":"","sources":["../../src/verify/fake-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAKnC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAiB,MAAM,aAAa,CAAC;AAElF,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,KAAM,SAAQ,OAAO,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AAC7F,eAAO,MAAM,KAAK,8BAAwC,CAAC;AAE3D,4EAA4E;AAC5E,MAAM,WAAW,KAAM,SAAQ,OAAO,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AAC7F,eAAO,MAAM,KAAK,8BAAwC,CAAC;AAE3D;;;;GAIG;AACH,MAAM,WAAW,QAAS,SAAQ,OAAO,CAAC,QAAQ,CAAC,eAAe,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AACnG,eAAO,MAAM,QAAQ,iCAA8C,CAAC;AAEpE,gGAAgG;AAChG,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,eAAO,MAAM,OAAO,UAAU,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAQ,KAI1D,CAAC;AAEH,8CAA8C;AAC9C,eAAO,MAAM,QAAQ,UAAW,KAAK,KAAG,MAAM,EAC2C,CAAC;AAyB1F,4FAA4F;AAC5F,eAAO,MAAM,cAAc,UAAW,KAAK,8GAmCxC,CAAC;AAEJ,oFAAoF;AACpF,MAAM,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAK5D,gGAAgG;AAChG,MAAM,MAAM,QAAQ,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,MAAM,WAAW,UAAU;IACzB,
|
|
1
|
+
{"version":3,"file":"fake-engine.d.ts","sourceRoot":"","sources":["../../src/verify/fake-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAKnC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAiB,MAAM,aAAa,CAAC;AAElF,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,KAAM,SAAQ,OAAO,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AAC7F,eAAO,MAAM,KAAK,8BAAwC,CAAC;AAE3D,4EAA4E;AAC5E,MAAM,WAAW,KAAM,SAAQ,OAAO,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AAC7F,eAAO,MAAM,KAAK,8BAAwC,CAAC;AAE3D;;;;GAIG;AACH,MAAM,WAAW,QAAS,SAAQ,OAAO,CAAC,QAAQ,CAAC,eAAe,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AACnG,eAAO,MAAM,QAAQ,iCAA8C,CAAC;AAEpE,gGAAgG;AAChG,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,eAAO,MAAM,OAAO,UAAU,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAQ,KAI1D,CAAC;AAEH,8CAA8C;AAC9C,eAAO,MAAM,QAAQ,UAAW,KAAK,KAAG,MAAM,EAC2C,CAAC;AAyB1F,4FAA4F;AAC5F,eAAO,MAAM,cAAc,UAAW,KAAK,8GAmCxC,CAAC;AAEJ,oFAAoF;AACpF,MAAM,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAK5D,gGAAgG;AAChG,MAAM,MAAM,QAAQ,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,MAAM,WAAW,UAAU;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACjE,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/E;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAClE;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC;CAC/B;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,IAAI,EAAE,CAAC,EAAE,GAAG,SAC9B,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,YACvB;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,KACpC,UAmDF,CAAC;AAEF,oCAAoC;AACpC,eAAO,MAAM,UAAU,UAAW,KAAK,KAAG,UAA+C,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Cloud-init DNS and imported disk growth
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
Proxmox.Vm('talos', {
|
|
5
|
+
target,
|
|
6
|
+
node: 'n2',
|
|
7
|
+
vmid: 10000,
|
|
8
|
+
scsi0: 'cephtb4:0,import-from=cephfs-tb4:import/talos.raw',
|
|
9
|
+
diskSizesGiB: { scsi0: 64 },
|
|
10
|
+
ide2: 'cephtb4:cloudinit',
|
|
11
|
+
ipconfig0: 'ip=10.20.16.20/24,gw=10.20.16.254',
|
|
12
|
+
nameserver: '10.20.16.254',
|
|
13
|
+
searchdomain: 'example.internal',
|
|
14
|
+
});
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`diskSizesGiB` declares minimum capacity in positive integer GiB. Declare the disk
|
|
18
|
+
slot alongside its target. Equal or larger live disks need no resize; lowering a
|
|
19
|
+
previously declared target is refused with `QemuDiskResizeRefused`, which callers
|
|
20
|
+
can handle with `Effect.catchTag`. Removing a target leaves capacity unmanaged.
|
|
21
|
+
Unsupported slots, CD-ROM/cloud-init drives and unreadable live sizes are refused.
|
|
22
|
+
|
|
23
|
+
The provider waits for import, reads the allocated disk, sends an absolute target
|
|
24
|
+
through the generated `putNodeQemuResize` operation, waits for its task, and verifies
|
|
25
|
+
the resulting capacity. An interrupted create resumes without `--adopt` when its
|
|
26
|
+
config matches, even if disk growth remains unfinished. Each resize checks the raw
|
|
27
|
+
VM lock first; lock waits and resize task polling share a 60-observation budget per
|
|
28
|
+
disk. A persistent lock raises `QemuDiskResizeRefused` without a resize write.
|
|
29
|
+
Absolute targets let retries finish growth without adding capacity twice.
|
|
30
|
+
`size=` in a volume config string is still observed metadata: omit it when
|
|
31
|
+
using a resize target. An unrelated update never resends the import source.
|
|
32
|
+
|
|
33
|
+
This resource never starts a VM. Complete its reconciliation before the separate
|
|
34
|
+
power-on step. Resizing an existing guest does not grow its partitions/filesystems.
|
|
35
|
+
|
|
36
|
+
DNS keys use the same declared-key comparison as `ipconfig0`: omitted keys remain
|
|
37
|
+
unmanaged. `nameserver` enforces the generated `address-list` constraint; PVE permits
|
|
38
|
+
IP addresses or DNS names, separated by whitespace, commas or semicolons. The provider
|
|
39
|
+
preserves the supplied spelling. `searchdomain` has no extra schema constraint.
|
|
40
|
+
|
|
41
|
+
Schema provenance: `codegen/manifest.json`, pve-manager **9.2.11/f6997e698c7933ea**,
|
|
42
|
+
SHA-256 `9def8f13611184ee1c7d0399713130dfc4a065701d0d91a69b9c03df929344e9`.
|
|
43
|
+
QEMU resize already exists in both generated surfaces: distilled's `nodes.ts` and
|
|
44
|
+
the legacy generator's packed `nodes-node-qemu-vmid-mtunnel.ts`. A filename search
|
|
45
|
+
for `qemu-vmid-resize.ts` misses the latter; neither output needs hand editing.
|
|
46
|
+
Both caches were recovered byte-for-byte from public vendor sources, then
|
|
47
|
+
`bun codegen/constraints.ts` generated the resize guard. The existing type generator
|
|
48
|
+
already supports the operation. No generated file was edited by hand.
|
|
49
|
+
|
|
50
|
+
Recovery used the vendor Makefile's concatenation order: `api-viewer/apidata.js`
|
|
51
|
+
and `api-viewer/PVEAPI.js` from proxmox/pve-docs
|
|
52
|
+
`4e7ff22c70eb35c63e65b0ba65c98980cb4d7bf5`, then `src/api-viewer/APIViewer.js`
|
|
53
|
+
from proxmox/proxmox-widget-toolkit `9204a77880eb31aff6ffc8bcf65ca48539685ab1`.
|
|
54
|
+
The result is exactly 4,337,847 bytes and the manifest SHA-256 above. PBS's 1,508,860
|
|
55
|
+
bytes were recovered from the public `proxmox-backup-docs_4.2.3-1_all.deb`, matching
|
|
56
|
+
the manifest's full SHA-256 (the recorded server version is 4.2.6-1, running 4.2.3).
|
|
57
|
+
No host was contacted. Tests cover generated constraints/types and fake SDK transport.
|
|
58
|
+
|
|
59
|
+
The named format's semantics come from
|
|
60
|
+
[PVE::JSONSchema](https://github.com/proxmox/pve-common/blob/defd246f31f327463f901a2daaf8dc52efcc5a97/src/PVE/JSONSchema.pm)
|
|
61
|
+
and `PVE::ParseUtils` at the same commit, inspected 2026-10-05. This is vendor-source
|
|
62
|
+
and fake-transport evidence; no live PVE call or Talos boot was performed.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@homeflare/alchemy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.46.0",
|
|
4
4
|
"description": "Custom Alchemy providers for Cloudflare, Proxmox, OpenBao, Forgejo, Talos, launchd and Caddy, and a verifier that proves adoptions are no-ops.",
|
|
5
5
|
"homepage": "https://github.com/taslabs-net/homeflare-kit/tree/main/packages/alchemy#readme",
|
|
6
6
|
"bugs": "https://github.com/taslabs-net/homeflare-kit/issues",
|
|
@@ -54,4 +54,4 @@ export const PROXMOX_CONSTRAINTS: Readonly<Record<string, EndpointConstraints>>
|
|
|
54
54
|
* ★ A DIGEST OF THE DATA, NOT OF THE FILE TEXT, so reformatting is not a stale generation while
|
|
55
55
|
* changing a 128 to a 129 by hand is. `tests/schema-manifest.test.ts` recomputes it.
|
|
56
56
|
*/
|
|
57
|
-
export const PROXMOX_CONSTRAINTS_DIGEST = '
|
|
57
|
+
export const PROXMOX_CONSTRAINTS_DIGEST = 'cbf63b7bac0500ef';
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* sha256 9def8f13611184ee, read on a PVE cluster node from
|
|
7
7
|
* /usr/share/pve-docs/api-viewer/apidoc.js
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
|
|
10
10
|
* this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
|
|
11
11
|
* and therefore unchecked at plan time.
|
|
12
12
|
*
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* sha256 9def8f13611184ee, read on a PVE cluster node from
|
|
7
7
|
* /usr/share/pve-docs/api-viewer/apidoc.js
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
|
|
10
10
|
* this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
|
|
11
11
|
* and therefore unchecked at plan time.
|
|
12
12
|
*
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* sha256 9def8f13611184ee, read on a PVE cluster node from
|
|
7
7
|
* /usr/share/pve-docs/api-viewer/apidoc.js
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
|
|
10
10
|
* this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
|
|
11
11
|
* and therefore unchecked at plan time.
|
|
12
12
|
*
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* sha256 9def8f13611184ee, read on a PVE cluster node from
|
|
7
7
|
* /usr/share/pve-docs/api-viewer/apidoc.js
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
|
|
10
10
|
* this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
|
|
11
11
|
* and therefore unchecked at plan time.
|
|
12
12
|
*
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* sha256 9def8f13611184ee, read on a PVE cluster node from
|
|
7
7
|
* /usr/share/pve-docs/api-viewer/apidoc.js
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
|
|
10
10
|
* this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
|
|
11
11
|
* and therefore unchecked at plan time.
|
|
12
12
|
*
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* sha256 9def8f13611184ee, read on a PVE cluster node from
|
|
7
7
|
* /usr/share/pve-docs/api-viewer/apidoc.js
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
|
|
10
10
|
* this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
|
|
11
11
|
* and therefore unchecked at plan time.
|
|
12
12
|
*
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* sha256 9def8f13611184ee, read on a PVE cluster node from
|
|
7
7
|
* /usr/share/pve-docs/api-viewer/apidoc.js
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
|
|
10
10
|
* this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
|
|
11
11
|
* and therefore unchecked at plan time.
|
|
12
12
|
*
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* sha256 9def8f13611184ee, read on a PVE cluster node from
|
|
7
7
|
* /usr/share/pve-docs/api-viewer/apidoc.js
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
|
|
10
10
|
* this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
|
|
11
11
|
* and therefore unchecked at plan time.
|
|
12
12
|
*
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* sha256 9def8f13611184ee, read on a PVE cluster node from
|
|
7
7
|
* /usr/share/pve-docs/api-viewer/apidoc.js
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
|
|
10
10
|
* this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
|
|
11
11
|
* and therefore unchecked at plan time.
|
|
12
12
|
*
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* sha256 9def8f13611184ee, read on a PVE cluster node from
|
|
7
7
|
* /usr/share/pve-docs/api-viewer/apidoc.js
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
|
|
10
10
|
* this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
|
|
11
11
|
* and therefore unchecked at plan time.
|
|
12
12
|
*
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* sha256 9def8f13611184ee, read on a PVE cluster node from
|
|
7
7
|
* /usr/share/pve-docs/api-viewer/apidoc.js
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
|
|
10
10
|
* this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
|
|
11
11
|
* and therefore unchecked at plan time.
|
|
12
12
|
*
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* sha256 9def8f13611184ee, read on a PVE cluster node from
|
|
7
7
|
* /usr/share/pve-docs/api-viewer/apidoc.js
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
|
|
10
10
|
* this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
|
|
11
11
|
* and therefore unchecked at plan time.
|
|
12
12
|
*
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* sha256 9def8f13611184ee, read on a PVE cluster node from
|
|
7
7
|
* /usr/share/pve-docs/api-viewer/apidoc.js
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
|
|
10
10
|
* this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
|
|
11
11
|
* and therefore unchecked at plan time.
|
|
12
12
|
*
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* sha256 9def8f13611184ee, read on a PVE cluster node from
|
|
7
7
|
* /usr/share/pve-docs/api-viewer/apidoc.js
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
|
|
10
10
|
* this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
|
|
11
11
|
* and therefore unchecked at plan time.
|
|
12
12
|
*
|
|
@@ -122,4 +122,9 @@ export const PVE_NODES_QEMU_CONSTRAINTS: Readonly<Record<string, EndpointConstra
|
|
|
122
122
|
"vmstatestorage": {"format":"pve-storage-id","type":"string"},
|
|
123
123
|
"watchdog": {"format":"pve-qm-watchdog","type":"string"},
|
|
124
124
|
},
|
|
125
|
+
"pve:PUT /nodes/{node}/qemu/{vmid}/resize": {
|
|
126
|
+
"digest": {"maxLength":40,"type":"string"},
|
|
127
|
+
"disk": {"enum":["ide0","ide1","ide2","ide3","scsi0","scsi1","scsi2","scsi3","scsi4","scsi5","scsi6","scsi7","scsi8","scsi9","scsi10","scsi11","scsi12","scsi13","scsi14","scsi15","scsi16","scsi17","scsi18","scsi19","scsi20","scsi21","scsi22","scsi23","scsi24","scsi25","scsi26","scsi27","scsi28","scsi29","scsi30","virtio0","virtio1","virtio2","virtio3","virtio4","virtio5","virtio6","virtio7","virtio8","virtio9","virtio10","virtio11","virtio12","virtio13","virtio14","virtio15","sata0","sata1","sata2","sata3","sata4","sata5","efidisk0","tpmstate0"],"required":true,"type":"string"},
|
|
128
|
+
"size": {"pattern":"^\\+?\\d+(\\.\\d+)?[KMGT]?\\n?$","patternSource":"\\+?\\d+(\\.\\d+)?[KMGT]?","required":true,"type":"string"},
|
|
129
|
+
},
|
|
125
130
|
};
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* sha256 9def8f13611184ee, read on a PVE cluster node from
|
|
7
7
|
* /usr/share/pve-docs/api-viewer/apidoc.js
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
|
|
10
10
|
* this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
|
|
11
11
|
* and therefore unchecked at plan time.
|
|
12
12
|
*
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* sha256 9def8f13611184ee, read on a PVE cluster node from
|
|
7
7
|
* /usr/share/pve-docs/api-viewer/apidoc.js
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
|
|
10
10
|
* this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
|
|
11
11
|
* and therefore unchecked at plan time.
|
|
12
12
|
*
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* sha256 9def8f13611184ee, read on a PVE cluster node from
|
|
7
7
|
* /usr/share/pve-docs/api-viewer/apidoc.js
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
|
|
10
10
|
* this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
|
|
11
11
|
* and therefore unchecked at plan time.
|
|
12
12
|
*
|
package/src/proxmox/index.ts
CHANGED
|
@@ -113,6 +113,7 @@ export {
|
|
|
113
113
|
export { provisionBootstrap } from './provision-bootstrap.ts';
|
|
114
114
|
export { type DeclareProvisionOptions, declareProvisionBaseline } from './provision-declare.ts';
|
|
115
115
|
export { ProxmoxVm, ProxmoxVmProvider, type VmAttributes, type VmProps } from './qemu.ts';
|
|
116
|
+
export { QemuDiskResizeRefused } from './qemu-size.ts';
|
|
116
117
|
export {
|
|
117
118
|
ProxmoxStorageDownload,
|
|
118
119
|
ProxmoxStorageDownloadProvider,
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { expect, test } from 'bun:test';
|
|
2
|
+
import * as Effect from 'effect/Effect';
|
|
3
|
+
import { FAKE_TARGET, fakePve, withoutBao } from './fake-pve.ts';
|
|
4
|
+
import { createForm, formRefusals, updateForm } from './qemu-form.ts';
|
|
5
|
+
import { judge } from './qemu-judge.ts';
|
|
6
|
+
import { qemuHandlers } from './qemu-lifecycle.ts';
|
|
7
|
+
import { storedConfig } from './qemu-props.ts';
|
|
8
|
+
|
|
9
|
+
const base = { target: FAKE_TARGET, node: 'n2', vmid: 10000 };
|
|
10
|
+
const props = { ...base, nameserver: '10.20.16.254', searchdomain: 'example.internal' };
|
|
11
|
+
|
|
12
|
+
test('cloud-init DNS survives form rendering, stored attributes and per-key diff', () => {
|
|
13
|
+
const config = { nameserver: props.nameserver, searchdomain: props.searchdomain };
|
|
14
|
+
expect(createForm(props)).toEqual({ ...config, vmid: '10000' });
|
|
15
|
+
expect(updateForm(props)).toEqual(config);
|
|
16
|
+
expect(storedConfig(config)).toEqual(config);
|
|
17
|
+
expect(judge(props, config)).toEqual({ drift: [], put: {}, refuse: [] });
|
|
18
|
+
expect(judge({ ...props, nameserver: '10.20.16.1' }, config)).toEqual({
|
|
19
|
+
drift: ['nameserver'],
|
|
20
|
+
put: { nameserver: '10.20.16.1' },
|
|
21
|
+
refuse: [],
|
|
22
|
+
});
|
|
23
|
+
expect(judge({ ...props, searchdomain: 'new.internal' }, config).put).toEqual({
|
|
24
|
+
searchdomain: 'new.internal',
|
|
25
|
+
});
|
|
26
|
+
expect(judge(base, config).drift).toEqual([]);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('address-list follows PVE: IPs, DNS names, separators and empty lists', () => {
|
|
30
|
+
for (const nameserver of [
|
|
31
|
+
'',
|
|
32
|
+
'10.20.16.254',
|
|
33
|
+
'2001:db8::53',
|
|
34
|
+
'dns.example.internal',
|
|
35
|
+
'10.20.16.254, 2001:db8::53;dns.example.internal',
|
|
36
|
+
'10.20.16.254\0dns.example.internal',
|
|
37
|
+
]) {
|
|
38
|
+
expect(formRefusals({ ...base, nameserver }), nameserver).toEqual([]);
|
|
39
|
+
}
|
|
40
|
+
for (const nameserver of [
|
|
41
|
+
'https://dns.example',
|
|
42
|
+
'10.20.16.254/24',
|
|
43
|
+
'[2001:db8::53]',
|
|
44
|
+
'-bad.example',
|
|
45
|
+
'bad_.example',
|
|
46
|
+
'2001:db8::broken',
|
|
47
|
+
'dns.example.',
|
|
48
|
+
]) {
|
|
49
|
+
expect(formRefusals({ ...base, nameserver })[0], nameserver).toContain('address-list');
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('invalid DNS fails with a typed refusal before any live read or write', async () => {
|
|
54
|
+
const fake = fakePve(() => {
|
|
55
|
+
throw new Error('unexpected API call');
|
|
56
|
+
});
|
|
57
|
+
await withoutBao(async () => {
|
|
58
|
+
const refusal = await Effect.runPromise(
|
|
59
|
+
qemuHandlers
|
|
60
|
+
.diff({
|
|
61
|
+
news: { ...props, nameserver: 'dns://invalid' },
|
|
62
|
+
olds: base,
|
|
63
|
+
output: undefined,
|
|
64
|
+
})
|
|
65
|
+
.pipe(
|
|
66
|
+
Effect.catchTag('QemuRefusedError', (error) => Effect.succeed(error.message)),
|
|
67
|
+
Effect.provide(fake.layer),
|
|
68
|
+
),
|
|
69
|
+
);
|
|
70
|
+
expect(refusal).toBe('nameserver: must satisfy the vendor address-list format');
|
|
71
|
+
});
|
|
72
|
+
expect(fake.calls).toEqual([]);
|
|
73
|
+
});
|