@homeflare/alchemy 0.38.0 → 0.40.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/README.md +32 -8
- package/dist/ceph/auth-entity.d.ts +34 -0
- package/dist/ceph/auth-entity.d.ts.map +1 -0
- package/dist/ceph/ceph-argv-config.d.ts +10 -0
- package/dist/ceph/ceph-argv-config.d.ts.map +1 -0
- package/dist/ceph/ceph-argv.d.ts +19 -0
- package/dist/ceph/ceph-argv.d.ts.map +1 -0
- package/dist/ceph/ceph-auth-form.d.ts +54 -0
- package/dist/ceph/ceph-auth-form.d.ts.map +1 -0
- package/dist/ceph/ceph-auth-parse.d.ts +56 -0
- package/dist/ceph/ceph-auth-parse.d.ts.map +1 -0
- package/dist/ceph/ceph-auth-reconcile.d.ts +35 -0
- package/dist/ceph/ceph-auth-reconcile.d.ts.map +1 -0
- package/dist/ceph/ceph-config-options.d.ts +23 -0
- package/dist/ceph/ceph-config-options.d.ts.map +1 -0
- package/dist/ceph/ceph-key-leak-assert.d.ts +25 -0
- package/dist/ceph/ceph-key-leak-assert.d.ts.map +1 -0
- package/dist/ceph/ceph-transport.d.ts +37 -0
- package/dist/ceph/ceph-transport.d.ts.map +1 -0
- package/dist/ceph/fake-ceph-dial.d.ts +35 -0
- package/dist/ceph/fake-ceph-dial.d.ts.map +1 -0
- package/dist/ceph/index.d.ts +13 -0
- package/dist/ceph/index.d.ts.map +1 -0
- package/dist/ceph/index.js +1609 -0
- package/dist/ceph/index.js.map +38 -0
- package/dist/forgejo/index.js +4 -2
- package/dist/forgejo/index.js.map +3 -3
- package/dist/forgejo/team-member.d.ts +25 -0
- package/dist/forgejo/team-member.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/proxmox/generated/constraints/index.d.ts +1 -1
- package/dist/proxmox/generated/constraints/index.d.ts.map +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-storage.d.ts +23 -0
- package/dist/proxmox/generated/constraints/pve-nodes-storage.d.ts.map +1 -0
- 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 +14 -3
- package/dist/proxmox/index.d.ts.map +1 -1
- package/dist/proxmox/index.js +574 -133
- package/dist/proxmox/index.js.map +33 -23
- package/dist/proxmox/qemu-form.d.ts +27 -18
- package/dist/proxmox/qemu-form.d.ts.map +1 -1
- package/dist/proxmox/qemu-judge.d.ts +30 -0
- package/dist/proxmox/qemu-judge.d.ts.map +1 -0
- package/dist/proxmox/qemu-lifecycle.d.ts +16 -2
- package/dist/proxmox/qemu-lifecycle.d.ts.map +1 -1
- package/dist/proxmox/qemu-net.d.ts +9 -0
- package/dist/proxmox/qemu-net.d.ts.map +1 -0
- package/dist/proxmox/qemu-props.d.ts +112 -0
- package/dist/proxmox/qemu-props.d.ts.map +1 -0
- package/dist/proxmox/qemu-volume.d.ts +27 -0
- package/dist/proxmox/qemu-volume.d.ts.map +1 -0
- package/dist/proxmox/qemu.d.ts +14 -27
- package/dist/proxmox/qemu.d.ts.map +1 -1
- package/dist/proxmox/storage-download-errors.d.ts +5 -0
- package/dist/proxmox/storage-download-errors.d.ts.map +1 -0
- package/dist/proxmox/storage-download-identity.d.ts +27 -0
- package/dist/proxmox/storage-download-identity.d.ts.map +1 -0
- package/dist/proxmox/storage-download-lifecycle.d.ts +97 -0
- package/dist/proxmox/storage-download-lifecycle.d.ts.map +1 -0
- package/dist/proxmox/storage-download-props.d.ts +36 -0
- package/dist/proxmox/storage-download-props.d.ts.map +1 -0
- package/dist/proxmox/storage-download-task.d.ts +17 -0
- package/dist/proxmox/storage-download-task.d.ts.map +1 -0
- package/dist/proxmox/storage-download.d.ts +44 -0
- package/dist/proxmox/storage-download.d.ts.map +1 -0
- package/dist/talos/credentials-write.d.ts +46 -0
- package/dist/talos/credentials-write.d.ts.map +1 -0
- package/dist/talos/credentials.d.ts +51 -9
- package/dist/talos/credentials.d.ts.map +1 -1
- package/dist/talos/fake-process.d.ts +56 -0
- package/dist/talos/fake-process.d.ts.map +1 -0
- package/dist/talos/index.d.ts +19 -4
- package/dist/talos/index.d.ts.map +1 -1
- package/dist/talos/index.js +357 -173
- package/dist/talos/index.js.map +16 -10
- package/dist/talos/kubeconfig-attrs.d.ts +4 -0
- package/dist/talos/kubeconfig-attrs.d.ts.map +1 -0
- package/dist/talos/kubeconfig.d.ts +41 -23
- package/dist/talos/kubeconfig.d.ts.map +1 -1
- package/dist/talos/machine-config-fixtures.d.ts +60 -0
- package/dist/talos/machine-config-fixtures.d.ts.map +1 -0
- package/dist/talos/machine-config-poll.d.ts +43 -0
- package/dist/talos/machine-config-poll.d.ts.map +1 -0
- package/dist/talos/machine-config-read.d.ts +49 -0
- package/dist/talos/machine-config-read.d.ts.map +1 -0
- package/dist/talos/resource.d.ts +18 -0
- package/dist/talos/resource.d.ts.map +1 -1
- package/dist/talos/talos-bootstrap-etcd.d.ts +38 -0
- package/dist/talos/talos-bootstrap-etcd.d.ts.map +1 -0
- package/dist/talos/talos-bootstrap.d.ts +87 -0
- package/dist/talos/talos-bootstrap.d.ts.map +1 -1
- package/dist/talos/talos-cluster-health.d.ts +43 -1
- package/dist/talos/talos-cluster-health.d.ts.map +1 -1
- package/dist/talos/talos-errors.d.ts +68 -0
- package/dist/talos/talos-errors.d.ts.map +1 -0
- package/dist/talos/talos-machine-config.d.ts +51 -15
- package/dist/talos/talos-machine-config.d.ts.map +1 -1
- package/dist/talos/talosctl.d.ts +7 -0
- package/dist/talos/talosctl.d.ts.map +1 -1
- package/dist/talos/values.d.ts +23 -3
- package/dist/talos/values.d.ts.map +1 -1
- package/dist/telemetry/fake-collector.d.ts +36 -0
- package/dist/telemetry/fake-collector.d.ts.map +1 -0
- package/dist/telemetry/index.d.ts +11 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +223 -0
- package/dist/telemetry/index.js.map +12 -0
- package/dist/telemetry/layer.d.ts +86 -0
- package/dist/telemetry/layer.d.ts.map +1 -0
- package/dist/telemetry/redact-serialization.d.ts +21 -0
- package/dist/telemetry/redact-serialization.d.ts.map +1 -0
- package/dist/telemetry/redact.d.ts +46 -0
- package/dist/telemetry/redact.d.ts.map +1 -0
- package/dist/unifi/acl-rule-drift.d.ts +22 -0
- package/dist/unifi/acl-rule-drift.d.ts.map +1 -0
- package/dist/unifi/acl-rule-form.d.ts +90 -0
- package/dist/unifi/acl-rule-form.d.ts.map +1 -0
- package/dist/unifi/acl-rule-ordering-form.d.ts +49 -0
- package/dist/unifi/acl-rule-ordering-form.d.ts.map +1 -0
- package/dist/unifi/acl-rule-ordering.d.ts +54 -0
- package/dist/unifi/acl-rule-ordering.d.ts.map +1 -0
- package/dist/unifi/acl-rule.d.ts +49 -0
- package/dist/unifi/acl-rule.d.ts.map +1 -0
- package/dist/unifi/dns-policy-drift.d.ts +21 -0
- package/dist/unifi/dns-policy-drift.d.ts.map +1 -0
- package/dist/unifi/dns-policy-form.d.ts +97 -0
- package/dist/unifi/dns-policy-form.d.ts.map +1 -0
- package/dist/unifi/dns-policy.d.ts +55 -0
- package/dist/unifi/dns-policy.d.ts.map +1 -0
- package/dist/unifi/drift.d.ts +27 -0
- package/dist/unifi/drift.d.ts.map +1 -0
- package/dist/unifi/fake-unifi.d.ts +5 -1
- package/dist/unifi/fake-unifi.d.ts.map +1 -1
- package/dist/unifi/firewall-policy-drift.d.ts +26 -0
- package/dist/unifi/firewall-policy-drift.d.ts.map +1 -0
- package/dist/unifi/firewall-policy-form.d.ts +102 -0
- package/dist/unifi/firewall-policy-form.d.ts.map +1 -0
- package/dist/unifi/firewall-policy-ordering-form.d.ts +66 -0
- package/dist/unifi/firewall-policy-ordering-form.d.ts.map +1 -0
- package/dist/unifi/firewall-policy-ordering.d.ts +57 -0
- package/dist/unifi/firewall-policy-ordering.d.ts.map +1 -0
- package/dist/unifi/firewall-policy.d.ts +57 -0
- package/dist/unifi/firewall-policy.d.ts.map +1 -0
- package/dist/unifi/firewall-zone-form.d.ts +6 -0
- package/dist/unifi/firewall-zone-form.d.ts.map +1 -1
- package/dist/unifi/firewall-zone.d.ts +1 -1
- package/dist/unifi/firewall-zone.d.ts.map +1 -1
- package/dist/unifi/index.d.ts +11 -3
- package/dist/unifi/index.d.ts.map +1 -1
- package/dist/unifi/index.js +725 -60
- package/dist/unifi/index.js.map +31 -9
- package/dist/unifi/network-drift.d.ts +26 -0
- package/dist/unifi/network-drift.d.ts.map +1 -0
- package/dist/unifi/network-form.d.ts +40 -7
- package/dist/unifi/network-form.d.ts.map +1 -1
- package/dist/unifi/network.d.ts +1 -0
- package/dist/unifi/network.d.ts.map +1 -1
- package/dist/unifi/paginate.d.ts +24 -0
- package/dist/unifi/paginate.d.ts.map +1 -0
- package/dist/unifi/providers.d.ts +1 -1
- package/dist/unifi/providers.d.ts.map +1 -1
- package/dist/unifi/resource.d.ts +36 -1
- package/dist/unifi/resource.d.ts.map +1 -1
- package/dist/unifi/scan-source.d.ts +11 -0
- package/dist/unifi/scan-source.d.ts.map +1 -0
- package/dist/unifi/traffic-matching-list-drift.d.ts +22 -0
- package/dist/unifi/traffic-matching-list-drift.d.ts.map +1 -0
- package/dist/unifi/traffic-matching-list-form.d.ts +56 -0
- package/dist/unifi/traffic-matching-list-form.d.ts.map +1 -0
- package/dist/unifi/traffic-matching-list.d.ts +51 -0
- package/dist/unifi/traffic-matching-list.d.ts.map +1 -0
- package/dist/unifi/wifi-broadcast-drift.d.ts +22 -0
- package/dist/unifi/wifi-broadcast-drift.d.ts.map +1 -0
- package/dist/unifi/wifi-broadcast-form.d.ts +127 -0
- package/dist/unifi/wifi-broadcast-form.d.ts.map +1 -0
- package/dist/unifi/wifi-broadcast.d.ts +73 -0
- package/dist/unifi/wifi-broadcast.d.ts.map +1 -0
- package/docs/telemetry-spike.md +94 -0
- package/docs/telemetry.md +109 -0
- package/docs/unifi-acl-rule.md +122 -0
- package/docs/unifi-dns-policy.md +75 -0
- package/docs/unifi-firewall-policy.md +109 -0
- package/docs/unifi-traffic-matching-list.md +82 -0
- package/docs/unifi-wifi.md +120 -0
- package/docs/unifi.md +64 -3
- package/package.json +10 -2
- package/src/ceph/auth-entity.ts +74 -0
- package/src/ceph/ceph-argv-config.ts +78 -0
- package/src/ceph/ceph-argv.test.ts +226 -0
- package/src/ceph/ceph-argv.ts +189 -0
- package/src/ceph/ceph-auth-form.test.ts +103 -0
- package/src/ceph/ceph-auth-form.ts +107 -0
- package/src/ceph/ceph-auth-parse.test.ts +155 -0
- package/src/ceph/ceph-auth-parse.ts +121 -0
- package/src/ceph/ceph-auth-reconcile-secrecy.test.ts +82 -0
- package/src/ceph/ceph-auth-reconcile.test.ts +233 -0
- package/src/ceph/ceph-auth-reconcile.ts +119 -0
- package/src/ceph/ceph-config-options.test.ts +44 -0
- package/src/ceph/ceph-config-options.ts +36 -0
- package/src/ceph/ceph-key-leak-assert.ts +35 -0
- package/src/ceph/ceph-no-output-logging.test.ts +52 -0
- package/src/ceph/ceph-transport.test.ts +125 -0
- package/src/ceph/ceph-transport.ts +117 -0
- package/src/ceph/fake-ceph-dial.ts +55 -0
- package/src/ceph/index.ts +12 -0
- package/src/forgejo/team-member.test.ts +14 -0
- package/src/forgejo/team-member.ts +28 -1
- package/src/index.ts +1 -0
- package/src/proxmox/constraints-required.test.ts +1 -0
- package/src/proxmox/generated/constraints/index.ts +3 -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 +1 -1
- package/src/proxmox/generated/constraints/pve-nodes-storage.ts +30 -0
- package/src/proxmox/generated/constraints/pve-pools.ts +1 -1
- package/src/proxmox/generated/constraints/pve-storage.ts +1 -1
- package/src/proxmox/index.test.ts +11 -6
- package/src/proxmox/index.ts +19 -3
- package/src/proxmox/qemu-form.ts +49 -13
- package/src/proxmox/qemu-identity.test.ts +30 -0
- package/src/proxmox/qemu-judge.test.ts +65 -0
- package/src/proxmox/qemu-judge.ts +84 -0
- package/src/proxmox/qemu-lifecycle.test.ts +78 -19
- package/src/proxmox/qemu-lifecycle.ts +131 -32
- package/src/proxmox/qemu-net.test.ts +48 -0
- package/src/proxmox/qemu-net.ts +78 -0
- package/src/proxmox/qemu-ownership.test.ts +44 -0
- package/src/proxmox/qemu-props.test.ts +87 -0
- package/src/proxmox/qemu-props.ts +157 -0
- package/src/proxmox/qemu-volume.test.ts +229 -0
- package/src/proxmox/qemu-volume.ts +178 -0
- package/src/proxmox/qemu.ts +15 -29
- package/src/proxmox/storage-download-errors.ts +7 -0
- package/src/proxmox/storage-download-identity.test.ts +54 -0
- package/src/proxmox/storage-download-identity.ts +50 -0
- package/src/proxmox/storage-download-lifecycle.ts +226 -0
- package/src/proxmox/storage-download-ownership.test.ts +50 -0
- package/src/proxmox/storage-download-props.ts +38 -0
- package/src/proxmox/storage-download-task.ts +72 -0
- package/src/proxmox/storage-download.test.ts +216 -0
- package/src/proxmox/storage-download.ts +58 -0
- package/src/talos/credentials-write.test.ts +81 -0
- package/src/talos/credentials-write.ts +95 -0
- package/src/talos/credentials.test.ts +157 -0
- package/src/talos/credentials.ts +160 -90
- package/src/talos/fake-process.ts +94 -0
- package/src/talos/index.ts +39 -4
- package/src/talos/kubeconfig-attrs.ts +55 -0
- package/src/talos/kubeconfig.test.ts +256 -0
- package/src/talos/kubeconfig.ts +170 -90
- package/src/talos/machine-config-fixtures.ts +86 -0
- package/src/talos/machine-config-poll.test.ts +57 -0
- package/src/talos/machine-config-poll.ts +82 -0
- package/src/talos/machine-config-read.ts +118 -0
- package/src/talos/resource.ts +19 -0
- package/src/talos/secrets-gate.test.ts +63 -0
- package/src/talos/talos-bootstrap-etcd.ts +71 -0
- package/src/talos/talos-bootstrap.test.ts +218 -0
- package/src/talos/talos-bootstrap.ts +151 -45
- package/src/talos/talos-cluster-health.test.ts +143 -0
- package/src/talos/talos-cluster-health.ts +91 -28
- package/src/talos/talos-errors.ts +85 -0
- package/src/talos/talos-machine-config.test.ts +189 -0
- package/src/talos/talos-machine-config.ts +102 -88
- package/src/talos/talosctl.ts +8 -0
- package/src/talos/values.test.ts +34 -6
- package/src/talos/values.ts +41 -7
- package/src/telemetry/fake-collector.ts +59 -0
- package/src/telemetry/http-client-sealing.test.ts +82 -0
- package/src/telemetry/index.ts +10 -0
- package/src/telemetry/layer.test.ts +204 -0
- package/src/telemetry/layer.ts +152 -0
- package/src/telemetry/redact-serialization.ts +178 -0
- package/src/telemetry/redact.test.ts +124 -0
- package/src/telemetry/redact.ts +147 -0
- package/src/unifi/acl-rule-drift.ts +57 -0
- package/src/unifi/acl-rule-form.ts +135 -0
- package/src/unifi/acl-rule-ordering-form.ts +79 -0
- package/src/unifi/acl-rule-ordering.test.ts +141 -0
- package/src/unifi/acl-rule-ordering.ts +70 -0
- package/src/unifi/acl-rule.test.ts +183 -0
- package/src/unifi/acl-rule.ts +61 -0
- package/src/unifi/discriminated-filter-decode.test.ts +134 -0
- package/src/unifi/dns-policy-drift.ts +48 -0
- package/src/unifi/dns-policy-form.ts +142 -0
- package/src/unifi/dns-policy.test.ts +154 -0
- package/src/unifi/dns-policy.ts +67 -0
- package/src/unifi/drift.test.ts +78 -0
- package/src/unifi/drift.ts +56 -0
- package/src/unifi/errors-and-secrets.test.ts +127 -0
- package/src/unifi/fake-unifi.ts +5 -1
- package/src/unifi/firewall-policy-drift.test.ts +151 -0
- package/src/unifi/firewall-policy-drift.ts +55 -0
- package/src/unifi/firewall-policy-filter-roundtrip.test.ts +143 -0
- package/src/unifi/firewall-policy-form.ts +146 -0
- package/src/unifi/firewall-policy-ordering-form.ts +111 -0
- package/src/unifi/firewall-policy-ordering.test.ts +185 -0
- package/src/unifi/firewall-policy-ordering.ts +87 -0
- package/src/unifi/firewall-policy.test.ts +183 -0
- package/src/unifi/firewall-policy.ts +73 -0
- package/src/unifi/firewall-zone-form.ts +31 -2
- package/src/unifi/firewall-zone.test.ts +21 -1
- package/src/unifi/firewall-zone.ts +1 -1
- package/src/unifi/get-only-guard.test.ts +165 -0
- package/src/unifi/index.ts +78 -1
- package/src/unifi/network-drift.test.ts +207 -0
- package/src/unifi/network-drift.ts +80 -0
- package/src/unifi/network-form.ts +11 -39
- package/src/unifi/network.test.ts +7 -82
- package/src/unifi/network.ts +6 -6
- package/src/unifi/paginate.test.ts +252 -0
- package/src/unifi/paginate.ts +141 -0
- package/src/unifi/providers.ts +19 -1
- package/src/unifi/resource.ts +73 -3
- package/src/unifi/scan-source.ts +64 -0
- package/src/unifi/traffic-matching-list-drift.ts +40 -0
- package/src/unifi/traffic-matching-list-form.ts +77 -0
- package/src/unifi/traffic-matching-list.test.ts +202 -0
- package/src/unifi/traffic-matching-list.ts +78 -0
- package/src/unifi/wifi-broadcast-details-call.test.ts +92 -0
- package/src/unifi/wifi-broadcast-drift.ts +69 -0
- package/src/unifi/wifi-broadcast-form.ts +211 -0
- package/src/unifi/wifi-broadcast-secrets.test.ts +145 -0
- package/src/unifi/wifi-broadcast.test.ts +155 -0
- package/src/unifi/wifi-broadcast.ts +90 -0
- package/src/unifi/write-op-reference.test.ts +190 -0
|
@@ -1,22 +1,31 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
/**
|
|
2
|
+
* QEMU create and update forms — declared keys only. Path identity stays out of the body.
|
|
3
|
+
*
|
|
4
|
+
* ⛔ NO DEFAULT IS EVER SUBSTITUTED FOR AN UNDECLARED FIELD. See qemu-props.ts's header for the
|
|
5
|
+
* "5-default PUT" this replaces: the old `shape()` sent `cores`/`memory`/`name`/`onboot`/
|
|
6
|
+
* `sockets` on every write, defaults included for whichever the declaration left out, so
|
|
7
|
+
* editing one field on an adopted VM silently reset every other to its factory value.
|
|
8
|
+
*/
|
|
9
|
+
import { type VmProps } from './qemu-props.ts';
|
|
10
|
+
/**
|
|
11
|
+
* Why a declared key cannot go on the wire, checked before every create and every update.
|
|
12
|
+
* ★ THE SAME RULE `lxc-create-form.ts` ENFORCES FOR `Proxmox.Lxc`: a key smuggled past the types
|
|
13
|
+
* (a cast, a JS caller) is refused here rather than silently dropped or silently sent.
|
|
14
|
+
*/
|
|
15
|
+
export declare const formRefusals: (props: VmProps) => string[];
|
|
16
|
+
/** The declared config, wire-spelled — every key `formRefusals` did not already refuse. */
|
|
17
|
+
export declare const form: (props: VmProps) => Record<string, string>;
|
|
18
|
+
/**
|
|
19
|
+
* The create body: the declared form plus the vmid a create needs.
|
|
20
|
+
* ⚠️ NO RETURN-TYPE ANNOTATION, ON PURPOSE. Annotating this `Record<string, string>` erases the
|
|
21
|
+
* object literal's own inferred shape, and with it the one thing `nodes.createNodeQemu({
|
|
22
|
+
* ...createForm(news), node: news.node })` (qemu-lifecycle.ts) needs: TypeScript only accepts a
|
|
23
|
+
* spread as satisfying `CreateNodeQemuRequest`'s required `vmid` when the spread's inferred type
|
|
24
|
+
* still carries `vmid` as a literal key, which an index-signature-only type cannot prove.
|
|
25
|
+
*/
|
|
13
26
|
export declare const createForm: (props: VmProps) => {
|
|
14
|
-
cores: string;
|
|
15
|
-
memory: string;
|
|
16
|
-
name: string;
|
|
17
|
-
onboot: string;
|
|
18
|
-
sockets: string;
|
|
19
|
-
net0?: string;
|
|
20
27
|
vmid: string;
|
|
21
28
|
};
|
|
29
|
+
/** The update body — identical construction to `createForm`, minus `vmid`, which PUT never sends. */
|
|
30
|
+
export declare const updateForm: typeof form;
|
|
22
31
|
//# sourceMappingURL=qemu-form.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qemu-form.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-form.ts"],"names":[],"mappings":"AAAA
|
|
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;AAEzB;;;;GAIG;AACH,eAAO,MAAM,YAAY,UAAW,OAAO,KAAG,MAAM,EAG6C,CAAC;AAElG,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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declared against live: what a `Proxmox.Vm` deploy would write, per key — the QEMU sibling of
|
|
3
|
+
* lxc-judge.ts, added 2026-09-26 (red-team C1/I1 on PR 297).
|
|
4
|
+
*
|
|
5
|
+
* ⛔ REPLACES A WHOLE-STRING, WHOLE-FORM COMPARISON. Before this, `matches` compared each declared
|
|
6
|
+
* key to live BYTE FOR BYTE and, on any drift, `formToSend` re-PUT every declared key at once
|
|
7
|
+
* (qemu-lifecycle.ts). A `scsi0`/`ide2`/`net0` declared in the "new" or MAC-less spelling then
|
|
8
|
+
* NEVER matched its own live volume/NIC (qemu-volume.ts / qemu-net.ts explain why), so every
|
|
9
|
+
* deploy re-sent all three -- reallocating the disk, re-importing it, and handing out a fresh MAC
|
|
10
|
+
* each time, even when nothing else changed. `judge` below decides per key, on the LIVE volume id
|
|
11
|
+
* and LIVE MAC, so an unrelated field's drift no longer drags the disk/NIC keys along with it.
|
|
12
|
+
*/
|
|
13
|
+
import { type VmProps } from './qemu-props.ts';
|
|
14
|
+
export type VmChange = {
|
|
15
|
+
/** Keys to `PUT …/config`, wire-spelled and built on live ids where one exists. */
|
|
16
|
+
readonly put: Record<string, string>;
|
|
17
|
+
/** Why a key cannot be written as an update. Non-empty means nothing is written. */
|
|
18
|
+
readonly refuse: readonly string[];
|
|
19
|
+
/** Every declared key that differs from live, refused or not. */
|
|
20
|
+
readonly drift: readonly string[];
|
|
21
|
+
};
|
|
22
|
+
export declare const judge: (props: VmProps, config: Record<string, string>) => VmChange;
|
|
23
|
+
/**
|
|
24
|
+
* What makes a `Proxmox.Vm` a DIFFERENT machine: a new vmid (red-team I1). Never planned as a
|
|
25
|
+
* replace -- see qemu.ts's header on why nothing here replaces a running VM.
|
|
26
|
+
* ⚠️ `was` PREFERS THE RECORDED ATTRIBUTE, so a `node` change (HA failover, a hand `qm migrate`)
|
|
27
|
+
* never reads as a vmid change: only `vmid` is judged here, mirroring lxc-identity.ts.
|
|
28
|
+
*/
|
|
29
|
+
export declare const identityRefusal: (vmid: number, was: number | undefined) => string | undefined;
|
|
30
|
+
//# sourceMappingURL=qemu-judge.d.ts.map
|
|
@@ -0,0 +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;AAInG,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,23 +1,37 @@
|
|
|
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 type
|
|
4
|
+
import { type VmAttributes, type VmProps } from './qemu-props.ts';
|
|
5
5
|
export declare const readQemu: (props: VmProps) => Effect.Effect<VmAttributes | undefined, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
6
6
|
/** No purge, no skiplock, no destroy-unreferenced-disks. A missing config is already gone. */
|
|
7
7
|
export declare const deleteQemu: (props: VmProps) => Effect.Effect<void | undefined, Error | import("./credential-errors.ts").PveCredentialDenied | nodes.ProxmoxOpError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
8
8
|
export declare const qemuHandlers: {
|
|
9
9
|
list: () => Effect.Effect<never[], never, never>;
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* ⛔ `Unowned` UNLESS STATE ALREADY VOUCHES FOR IT (C2). With no attributes this is Alchemy's
|
|
12
|
+
* adoption probe or the recovery read for an interrupted create (ownership/probe.ts); `settled`
|
|
13
|
+
* is the same `judge` reconcile uses, so "proven ours" and "reconcile would write nothing" are
|
|
14
|
+
* the same question asked once.
|
|
15
|
+
*/
|
|
16
|
+
read: (args_0: {
|
|
17
|
+
fqn: string;
|
|
18
|
+
instanceId: string;
|
|
11
19
|
olds: VmProps;
|
|
20
|
+
output: VmAttributes | undefined;
|
|
12
21
|
}) => Effect.Effect<VmAttributes | undefined, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
13
22
|
diff: (args_0: {
|
|
14
23
|
news: Input<VmProps>;
|
|
24
|
+
olds: VmProps;
|
|
15
25
|
output: VmAttributes | undefined;
|
|
16
26
|
}) => Effect.Effect<{
|
|
17
27
|
readonly action: "noop" | "update";
|
|
18
28
|
} | undefined, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
19
29
|
reconcile: (args_0: {
|
|
30
|
+
fqn: string;
|
|
31
|
+
instanceId: string;
|
|
20
32
|
news: VmProps;
|
|
33
|
+
olds: VmProps | undefined;
|
|
34
|
+
output: VmAttributes | undefined;
|
|
21
35
|
}) => Effect.Effect<VmAttributes, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
22
36
|
delete: ({ olds }: {
|
|
23
37
|
olds: VmProps;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qemu-lifecycle.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-lifecycle.ts"],"names":[],"mappings":"
|
|
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;AAOxC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,OAAO,EAMb,MAAM,iBAAiB,CAAC;AAwCzB,eAAO,MAAM,QAAQ,UAAW,OAAO,iOAapC,CAAC;AAEJ,8FAA8F;AAC9F,eAAO,MAAM,UAAU,UAAW,OAAO,+KAMyB,CAAC;AAmBnE,eAAO,MAAM,YAAY;IACvB,IAAI;IACJ;;;;;OAKG;IACH,IAAI;aAMG,MAAM;oBACC,MAAM;cACZ,OAAO;gBACL,YAAY,GAAG,SAAS;;IAQlC,IAAI;cAKI,KAAK,CAAC,OAAO,CAAC;cACd,OAAO;gBACL,YAAY,GAAG,SAAS;;;;IAwBlC,SAAS;aAOF,MAAM;oBACC,MAAM;cACZ,OAAO;cACP,OAAO,GAAG,SAAS;gBACjB,YAAY,GAAG,SAAS;;IAoDlC,MAAM,aAAa;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE;CACrC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** The MAC-substituted comparison maps: an undeclared/blank MAC is PVE's, not drift. */
|
|
2
|
+
export declare const netMaps: (declared: string, live: string) => {
|
|
3
|
+
have: Map<string, string>;
|
|
4
|
+
want: Map<string, string>;
|
|
5
|
+
};
|
|
6
|
+
export declare const sameNet: (declared: string, live: string) => boolean;
|
|
7
|
+
/** The value to PUT: the declaration, plus the live MAC when it names none. */
|
|
8
|
+
export declare const netWrite: (declared: string, live: string) => string;
|
|
9
|
+
//# sourceMappingURL=qemu-net.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qemu-net.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-net.ts"],"names":[],"mappings":"AAkDA,wFAAwF;AACxF,eAAO,MAAM,OAAO,aAAc,MAAM,QAAQ,MAAM;;;CASrD,CAAC;AAEF,eAAO,MAAM,OAAO,aAAc,MAAM,QAAQ,MAAM,KAAG,OAGxD,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,QAAQ,aAAc,MAAM,QAAQ,MAAM,KAAG,MASzD,CAAC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a `Proxmox.Vm` declaration says, and what its state keeps.
|
|
3
|
+
*
|
|
4
|
+
* ★ THE SAME "DECLARED KEYS" MODEL AS `Proxmox.Lxc` (lxc-props.ts, joined 2026-09-21): an
|
|
5
|
+
* undeclared key is UNMANAGED — never sent, never compared, never overwritten. Adopting a live
|
|
6
|
+
* VM is then a paste of its config, not a translation of it, and the wire spelling is PVE's own
|
|
7
|
+
* (`scsi0`, `net0`, `ipconfig0`, as `pvesh get .../qemu/{vmid}/config` prints them).
|
|
8
|
+
*
|
|
9
|
+
* ⛔ THIS REPLACES THE "5-DEFAULT PUT". Before 2026-09-26, `qemu-form.ts`'s `shape()` sent
|
|
10
|
+
* `cores`/`memory`/`name`/`onboot`/`sockets` on EVERY write with a hard default substituted for
|
|
11
|
+
* whichever of the five was left undeclared, so declaring only `memory: 4096` on an adopted VM
|
|
12
|
+
* still PUT `name: 'vm101'` and `sockets: '1'` over whatever the guest actually had. Harmless
|
|
13
|
+
* while `ProxmoxVm` stayed Provider-only (nothing declared it), load-bearing the moment Talos
|
|
14
|
+
* does. `declaredKeys` below is the fix: a field absent from the declaration is never read,
|
|
15
|
+
* never compared and never written — see qemu-form.ts's `form()`.
|
|
16
|
+
*
|
|
17
|
+
* ⛔ NO SECRET IS A PROP. `cipassword` (cloud-init's password) is write-only and Alchemy persists
|
|
18
|
+
* props in plaintext (this estate's state store is dumped nightly) — typed `never`, exactly
|
|
19
|
+
* like lxc-props.ts's `password`. A VM that needs a login uses `sshkeys`-free image defaults or
|
|
20
|
+
* an out-of-band secret; this resource never carries one.
|
|
21
|
+
* ⛔ `machine` IS NEVER A PROP EITHER. It pins the emulated chipset/firmware revision a guest boots
|
|
22
|
+
* against; PVE already resolves it from the node's installed QEMU version, and declaring it here
|
|
23
|
+
* would fight every future node upgrade instead of tracking it. Typed `never` for the same
|
|
24
|
+
* reason `cipassword` is: a cast is the only way in, and this file's helpers below never read
|
|
25
|
+
* an unmanaged key onto the wire regardless.
|
|
26
|
+
*/
|
|
27
|
+
import type { WithTarget } from './resource.ts';
|
|
28
|
+
/** A PVE boolean as pvesh prints it (`1`) or as TypeScript writes it (`true`). The same value. */
|
|
29
|
+
export type PveFlag = boolean | 0 | 1;
|
|
30
|
+
export interface VmProps extends WithTarget {
|
|
31
|
+
/** ⛔ This resource never migrates: qemu-read.ts refuses a VM found on another node. */
|
|
32
|
+
node: string;
|
|
33
|
+
/** ⛔ Cluster-wide, and shared with LXC. See qemu.ts's header. */
|
|
34
|
+
vmid: number;
|
|
35
|
+
name?: string;
|
|
36
|
+
/** MiB. */
|
|
37
|
+
memory?: number;
|
|
38
|
+
cores?: number;
|
|
39
|
+
sockets?: number;
|
|
40
|
+
/** Emulated CPU type, e.g. `host`. */
|
|
41
|
+
cpu?: string;
|
|
42
|
+
onboot?: PveFlag;
|
|
43
|
+
/** The QEMU guest agent. Talos reports its addresses through it once this is enabled. */
|
|
44
|
+
agent?: PveFlag;
|
|
45
|
+
/** `order=scsi0;ide2;net0`. */
|
|
46
|
+
boot?: string;
|
|
47
|
+
/** e.g. `virtio-scsi-single`. */
|
|
48
|
+
scsihw?: string;
|
|
49
|
+
/**
|
|
50
|
+
* `local-zfs:32` to create a new volume, or the live volume string as adopted —
|
|
51
|
+
* `cephtb4:vm-101-disk-0,size=32G` (n is 0 to 30, pve-qemu-server's own `$MAX_SCSI_DISKS`).
|
|
52
|
+
*/
|
|
53
|
+
[scsi: `scsi${number}`]: string | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* `virtio=<mac>,bridge=vmbr0,tag=<vlan>` — a VLAN-aware bridge with an 802.1q tag is a bridge
|
|
56
|
+
* plus this one sub-property; PVE's SDN stays out of it entirely (n is 0 to 31).
|
|
57
|
+
*/
|
|
58
|
+
[nic: `net${number}`]: string | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* The cloud-init drive, e.g. `cephtb4:cloudinit`. PVE's own web UI puts it on `ide2`, but any
|
|
61
|
+
* free `ide`/`sata`/`scsi` slot works; declaring one is what gives `ipconfig0` below somewhere
|
|
62
|
+
* to write the generated seed image (n is 0 to 3).
|
|
63
|
+
*/
|
|
64
|
+
[cloudinit: `ide${number}`]: string | undefined;
|
|
65
|
+
/** cloud-init network config: `ip=dhcp`, or `ip=<cidr>,gw=<gw>` (n is 0 to 31). */
|
|
66
|
+
[ipconfig: `ipconfig${number}`]: string | undefined;
|
|
67
|
+
/** `socket` — a serial console, the way Talos exposes its own (n is 0 to 3). */
|
|
68
|
+
[serial: `serial${number}`]: string | undefined;
|
|
69
|
+
/** ⛔ A secret. See the header. */
|
|
70
|
+
cipassword?: never;
|
|
71
|
+
/** ⛔ Machine config. See the header. */
|
|
72
|
+
machine?: never;
|
|
73
|
+
}
|
|
74
|
+
export interface VmAttributes {
|
|
75
|
+
node: string;
|
|
76
|
+
vmid: number;
|
|
77
|
+
/** The live config, MANAGED keys only — see `storedConfig`. An allowlist, not a mirror. */
|
|
78
|
+
config: Record<string, string>;
|
|
79
|
+
}
|
|
80
|
+
/** The indexed families this resource manages, with pve-qemu-server's own published range. */
|
|
81
|
+
export declare const INDEXED: {
|
|
82
|
+
readonly ide: 4;
|
|
83
|
+
readonly ipconfig: 32;
|
|
84
|
+
readonly net: 32;
|
|
85
|
+
readonly scsi: 31;
|
|
86
|
+
readonly serial: 4;
|
|
87
|
+
};
|
|
88
|
+
export type IndexedFamily = keyof typeof INDEXED;
|
|
89
|
+
/** `scsi3` → `['scsi', 3]`; anything else, including an out-of-range index, → undefined. */
|
|
90
|
+
export declare const indexedKey: (key: string) => readonly [IndexedFamily, number] | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* A key this resource compares and may write. ⛔ EVERYTHING ELSE IS REFUSED, NEVER SILENTLY
|
|
93
|
+
* DROPPED OR SILENTLY SENT — `qemu-form.ts`'s `formRefusals` is what a declared key smuggled
|
|
94
|
+
* past the types (a cast, a JS caller: `cipassword`, `machine`, `hookscript`) meets before any
|
|
95
|
+
* write, the same rule `lxc-create-form.ts` enforces for `Proxmox.Lxc`.
|
|
96
|
+
*/
|
|
97
|
+
export declare const isManagedKey: (key: string) => boolean;
|
|
98
|
+
/** A declaration read by key. ⚠️ The cast is the one place a template-literal index meets a plain string. */
|
|
99
|
+
export declare const declaredValue: (props: VmProps, key: string) => unknown;
|
|
100
|
+
/** The declared keys with a value, in a stable order — never `node`/`target`/`vmid`. */
|
|
101
|
+
export declare const declaredKeys: (props: VmProps) => string[];
|
|
102
|
+
/** One declared value as PVE's wire string. Booleans go as `1`/`0`, numbers as their decimal. */
|
|
103
|
+
export declare const wireValue: (value: unknown) => string;
|
|
104
|
+
/**
|
|
105
|
+
* The live config as strings: managed keys only.
|
|
106
|
+
* ⛔ AN ALLOWLIST, NOT "EVERYTHING BUT A DENYLIST" — same reasoning as `lxc-props.ts`'s
|
|
107
|
+
* `storedConfig`. `digest` covers the whole file, `lock`/`pending` are transient, and a future
|
|
108
|
+
* PVE release's new key does not land in this estate's unencrypted state store until this
|
|
109
|
+
* resource is taught to manage it.
|
|
110
|
+
*/
|
|
111
|
+
export declare const storedConfig: (live: Record<string, unknown>) => Record<string, string>;
|
|
112
|
+
//# sourceMappingURL=qemu-props.d.ts.map
|
|
@@ -0,0 +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;AAeF;;;;;GAKG;AACH,eAAO,MAAM,YAAY,QAAS,MAAM,KAAG,OACY,CAAC;AAExD,6GAA6G;AAC7G,eAAO,MAAM,aAAa,UAAW,OAAO,OAAO,MAAM,KAAG,OACR,CAAC;AAErD,wFAAwF;AACxF,eAAO,MAAM,YAAY,UAAW,OAAO,KAAG,MAAM,EAGzC,CAAC;AAEZ,iGAAiG;AACjG,eAAO,MAAM,SAAS,UAAW,OAAO,KAAG,MACmB,CAAC;AAE/D;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,SAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAQjF,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type Disk = {
|
|
2
|
+
/** `fresh`: a new-disk spelling (`storage:GiB`, `storage:cloudinit`, or `storage:0,import-from=...`
|
|
3
|
+
* possibly with more options). `volume`: an existing volume, `storage:volname,...`. */
|
|
4
|
+
readonly kind: 'fresh' | 'volume';
|
|
5
|
+
readonly source: string;
|
|
6
|
+
readonly volname: string;
|
|
7
|
+
readonly size: string | undefined;
|
|
8
|
+
readonly options: Map<string, string>;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* `storage:volname,k=v,...` (or one of the "fresh" spellings) into its comparable parts.
|
|
12
|
+
* ⚠️ THE IMPORT SPELLING IS DETECTED AFTER THE GENERAL SPLIT, NOT BY ITS OWN REGEX: `import-from`'s
|
|
13
|
+
* value can itself contain a colon (e.g. `cephfs-tb4:import/talos-factory.raw`) and other options
|
|
14
|
+
* can come before or after it, so a regex anchored on `:0,import-from=` right after the colon (as
|
|
15
|
+
* the first cut had) misses that ordering and swallows everything after it into one opaque match.
|
|
16
|
+
* Splitting on commas like any `volume` spelling first, THEN checking for a literal `"0"` volname
|
|
17
|
+
* plus an `import-from` key among the parsed options, catches every ordering and keeps every other
|
|
18
|
+
* declared option (`iothread=1`, `discard=on`, …) visible to `judgeDisk` instead of swallowed.
|
|
19
|
+
*/
|
|
20
|
+
export declare const parseDisk: (text: string) => Disk;
|
|
21
|
+
export type DiskVerdict = {
|
|
22
|
+
readonly refuse?: string;
|
|
23
|
+
/** The value to PUT, built on the LIVE volume id and LIVE size — never the declared spelling. */
|
|
24
|
+
readonly put?: string;
|
|
25
|
+
};
|
|
26
|
+
export declare const judgeDisk: (key: string, declared: string, live: string) => DiskVerdict;
|
|
27
|
+
//# sourceMappingURL=qemu-volume.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qemu-volume.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-volume.ts"],"names":[],"mappings":"AA+DA,MAAM,MAAM,IAAI,GAAG;IACjB;4FACwF;IACxF,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,SAAS,SAAU,MAAM,KAAG,IA4BxC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,iGAAiG;IACjG,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAmBF,eAAO,MAAM,SAAS,QAAS,MAAM,YAAY,MAAM,QAAQ,MAAM,KAAG,WAyCvE,CAAC"}
|
package/dist/proxmox/qemu.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `Proxmox.Vm` — a QEMU virtual machine, declared.
|
|
2
|
+
* `Proxmox.Vm` — a QEMU virtual machine, declared. Exported (not just Provider-only) since
|
|
3
|
+
* 2026-09-26 for Talos: see qemu-props.ts for what a declaration may say and why `cipassword`
|
|
4
|
+
* and `machine` may never be one of them.
|
|
3
5
|
*
|
|
4
6
|
* ⚠️ CREATE is `POST /nodes/{node}/qemu`. GET and PUT stay on `.../qemu/{vmid}/config`.
|
|
5
7
|
* ⛔ DELETE is `DELETE /nodes/{node}/qemu/{vmid}` (`destroy_vm` in qemu-server Qemu.pm). The
|
|
@@ -10,37 +12,22 @@
|
|
|
10
12
|
* collision Alchemy can see -- they are different resource types -- and PVE refuses the second
|
|
11
13
|
* with "already exists". Pick ids per cluster, not per kind.
|
|
12
14
|
*
|
|
13
|
-
*
|
|
14
|
-
* is
|
|
15
|
-
*
|
|
15
|
+
* ⛔ THIS RESOURCE NEVER MIGRATES. `qemu-read.ts` refuses the plan outright when the declared vmid
|
|
16
|
+
* is found running on a DIFFERENT node than the one declared ("A migration is not an update") --
|
|
17
|
+
* unchanged by the 2026-09-26 export, and exactly what keeps a node-pinned Talos VM pinned.
|
|
18
|
+
*
|
|
19
|
+
* ⚠️ POWER STATE IS NEITHER DECLARED NOR REPORTED. There is no `running` prop and `VmAttributes`
|
|
20
|
+
* carries no `status` field (qemu-props.ts) — starting and stopping a VM from a plan would make a
|
|
21
|
+
* deploy a maintenance window, and the estate has one of those already.
|
|
16
22
|
*/
|
|
17
23
|
import { Resource } from 'alchemy';
|
|
18
24
|
import * as Provider from 'alchemy/Provider';
|
|
19
|
-
import type { PveRequirements
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/** ⛔ Cluster-wide, and shared with LXC. See the ⛔ above. */
|
|
23
|
-
vmid: number;
|
|
24
|
-
name?: string;
|
|
25
|
-
/** MiB. */
|
|
26
|
-
memory?: number;
|
|
27
|
-
cores?: number;
|
|
28
|
-
sockets?: number;
|
|
29
|
-
/** e.g. `virtio=<mac>,bridge=vmbr0`. */
|
|
30
|
-
net0?: string;
|
|
31
|
-
onboot?: boolean;
|
|
32
|
-
}
|
|
33
|
-
export interface VmAttributes {
|
|
34
|
-
vmid: number;
|
|
35
|
-
node: string;
|
|
36
|
-
name: string;
|
|
37
|
-
memory: number;
|
|
38
|
-
cores: number;
|
|
39
|
-
sockets: number;
|
|
40
|
-
onboot: boolean;
|
|
41
|
-
}
|
|
25
|
+
import type { PveRequirements } from './resource.ts';
|
|
26
|
+
import type { VmAttributes, VmProps } from './qemu-props.ts';
|
|
27
|
+
export type { VmAttributes, VmProps } from './qemu-props.ts';
|
|
42
28
|
export interface ProxmoxVm extends Resource<'Proxmox.Vm', VmProps, VmAttributes, never, PveRequirements> {
|
|
43
29
|
}
|
|
30
|
+
/** ★ `retain` by default — a VM's disks cannot be rebuilt from a line. See resource.ts / lxc.ts. */
|
|
44
31
|
export declare const ProxmoxVm: import("alchemy").ResourceClass<ProxmoxVm>;
|
|
45
32
|
export { createForm } from './qemu-form.ts';
|
|
46
33
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qemu.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"qemu.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAG7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE7D,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE7D,MAAM,WAAW,SAAU,SAAQ,QAAQ,CACzC,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,oGAAoG;AACpG,eAAO,MAAM,SAAS,4CAAwE,CAAC;AAE/F,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;;GAGG;AACH,eAAO,MAAM,iBAAiB,+HACmD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-download-errors.d.ts","sourceRoot":"","sources":["../../src/proxmox/storage-download-errors.ts"],"names":[],"mappings":"AAAA,4GAA4G;AAC5G,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What makes a `Proxmox.StorageDownload` a DIFFERENT file, and what a changed pin on the SAME
|
|
3
|
+
* file means. (2026-09-26, red-team I1/I2 on PR 297.)
|
|
4
|
+
*
|
|
5
|
+
* ★ `filename` (WITH `storage`) IS THE IDENTITY. PVE does not record what a volume was downloaded
|
|
6
|
+
* from — `GET .../content` reports only `format`/`size`/`volid` (storage-download-props.ts) — so
|
|
7
|
+
* once the file exists there is nothing left to compare a new `url`/`checksum` against except the
|
|
8
|
+
* PREVIOUS DECLARATION. `storage-download-lifecycle.ts`'s `diff` asks `judgeIdentity` before
|
|
9
|
+
* touching the file; a genuine identity change plans `replace` (delete the old file, download the
|
|
10
|
+
* new one under its own name) rather than the silent `update` that used to orphan the old file
|
|
11
|
+
* forever, and a changed pin on the SAME filename refuses rather than silently planning `noop`.
|
|
12
|
+
*/
|
|
13
|
+
import type { StorageDownloadProps } from './storage-download-props.ts';
|
|
14
|
+
export type IdentityVerdict = {
|
|
15
|
+
readonly kind: 'same';
|
|
16
|
+
} | {
|
|
17
|
+
readonly kind: 'replace';
|
|
18
|
+
} | {
|
|
19
|
+
readonly kind: 'pin-changed';
|
|
20
|
+
readonly refuse: string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* `olds` is undefined for a resource with no prior declaration (a fresh create, or the recovery
|
|
24
|
+
* read for an interrupted one) — neither case has a pin to compare, so both are `same`.
|
|
25
|
+
*/
|
|
26
|
+
export declare const judgeIdentity: (news: StorageDownloadProps, olds: StorageDownloadProps | undefined) => IdentityVerdict;
|
|
27
|
+
//# sourceMappingURL=storage-download-identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-download-identity.d.ts","sourceRoot":"","sources":["../../src/proxmox/storage-download-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAWxE,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9D;;;GAGG;AACH,eAAO,MAAM,aAAa,SAClB,oBAAoB,QACpB,oBAAoB,GAAG,SAAS,KACrC,eAcF,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { Input } from 'alchemy/Input';
|
|
2
|
+
import * as nodes from '@distilled.cloud/proxmox/nodes';
|
|
3
|
+
import * as Effect from 'effect/Effect';
|
|
4
|
+
import type { StorageDownloadAttributes, StorageDownloadProps } from './storage-download-props.ts';
|
|
5
|
+
/**
|
|
6
|
+
* The wire form, PVE-spelled (`checksum-algorithm`, `verify-certificates`) — what the generated
|
|
7
|
+
* vendor table keys by, and what `formViolations` checks. ⚠️ NOT re-spelled for the SDK call:
|
|
8
|
+
* `nodes.downloadNodesStorageUrl` never declares these two hyphenated names as typed properties
|
|
9
|
+
* either (its schema names them `checksum_algorithm`/`verify_certificates`), so passing this
|
|
10
|
+
* object straight through relies on protocol-http.ts's own documented "unknown keys pass through
|
|
11
|
+
* as body fields" rule — the same spec-drift path qemu-props.ts leans on for `scsi0`/`net0`, and
|
|
12
|
+
* unlike storage-wire.ts's `underscored()` this family has no reason to translate: the schema's
|
|
13
|
+
* OWN property names would just be a second spelling of the same two fields.
|
|
14
|
+
*/
|
|
15
|
+
export declare const downloadForm: (props: StorageDownloadProps) => {
|
|
16
|
+
checksum: string;
|
|
17
|
+
'checksum-algorithm': import("./storage-download-props.ts").ChecksumAlgorithm;
|
|
18
|
+
compression?: string;
|
|
19
|
+
content: string;
|
|
20
|
+
filename: string;
|
|
21
|
+
node: string;
|
|
22
|
+
storage: string;
|
|
23
|
+
url: string;
|
|
24
|
+
'verify-certificates'?: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Why this declaration cannot be sent, checked before every diff and every reconcile.
|
|
28
|
+
* ⛔ `checksum` REQUIRED, EVEN THOUGH THE TYPE ALREADY SAYS SO — a JS caller or a cast can still
|
|
29
|
+
* leave it `''`; this is the runtime backstop storage-download.ts's header promises.
|
|
30
|
+
*/
|
|
31
|
+
export declare const createRefusals: (props: StorageDownloadProps) => string[];
|
|
32
|
+
/**
|
|
33
|
+
* `GET .../content?content=import`, matched by filename suffix — see storage-download-props.ts's
|
|
34
|
+
* `volid` doc for why a suffix match, not an assumed prefix. `content` is already server-filtered.
|
|
35
|
+
* ⛔ I3: THE `read` ROLE, NOT `provision` — this is a plain GET, and every caller (read/diff AND
|
|
36
|
+
* reconcile/delete, which mint their own `provision` credential for the actual write) may use the
|
|
37
|
+
* cheaper, longer-lived one, exactly as `qemu-read.ts`'s `readVm` already does for its own GET.
|
|
38
|
+
*/
|
|
39
|
+
export declare const readDownload: (props: StorageDownloadProps) => Effect.Effect<{
|
|
40
|
+
filename: string;
|
|
41
|
+
format: string;
|
|
42
|
+
node: string;
|
|
43
|
+
size: number;
|
|
44
|
+
storage: string;
|
|
45
|
+
volid: string;
|
|
46
|
+
} | undefined, Error | import("./distilled-pve.ts").PveClusterExhausted | import("./credential-errors.ts").PveCredentialDenied | import("effect/Cause").TimeoutError | nodes.ProxmoxOpError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
47
|
+
/** ⛔ IDEMPOTENT DELETE (distilled doctrine): a volume already gone is success, never a refusal. */
|
|
48
|
+
export declare const destroyDownload: (props: StorageDownloadProps) => Effect.Effect<void, Error | import("./distilled-pve.ts").PveClusterExhausted | import("./credential-errors.ts").PveCredentialDenied | import("effect/Cause").TimeoutError | nodes.ProxmoxOpError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
49
|
+
export declare const storageDownloadHandlers: {
|
|
50
|
+
list: () => Effect.Effect<never[], never, never>;
|
|
51
|
+
/**
|
|
52
|
+
* ⛔ C2: `Unowned` unless state already vouches for it. With no attributes this is the adoption
|
|
53
|
+
* probe or the recovery read for an interrupted download; `filename` (with `storage`) is the
|
|
54
|
+
* whole identity this family has (storage-download-identity.ts), so once the row's own instance
|
|
55
|
+
* is proven to hold the WHOLE declaration (`ownership/rows.ts`, inside `ownedRead`), a matching
|
|
56
|
+
* file is ours -- there is no further per-key drift to prove, unlike a config-bearing resource.
|
|
57
|
+
*/
|
|
58
|
+
read: (args_0: {
|
|
59
|
+
fqn: string;
|
|
60
|
+
instanceId: string;
|
|
61
|
+
olds: StorageDownloadProps;
|
|
62
|
+
output: StorageDownloadAttributes | undefined;
|
|
63
|
+
}) => Effect.Effect<{
|
|
64
|
+
filename: string;
|
|
65
|
+
format: string;
|
|
66
|
+
node: string;
|
|
67
|
+
size: number;
|
|
68
|
+
storage: string;
|
|
69
|
+
volid: string;
|
|
70
|
+
} | undefined, Error | import("./distilled-pve.ts").PveClusterExhausted | import("./credential-errors.ts").PveCredentialDenied | import("effect/Cause").TimeoutError | nodes.ProxmoxOpError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
71
|
+
diff: (args_0: {
|
|
72
|
+
news: Input<StorageDownloadProps>;
|
|
73
|
+
olds: StorageDownloadProps;
|
|
74
|
+
output: StorageDownloadAttributes | undefined;
|
|
75
|
+
}) => Effect.Effect<{
|
|
76
|
+
readonly action: 'replace';
|
|
77
|
+
} | {
|
|
78
|
+
readonly action: "noop" | "update";
|
|
79
|
+
} | undefined, Error | import("./distilled-pve.ts").PveClusterExhausted | import("./credential-errors.ts").PveCredentialDenied | import("effect/Cause").TimeoutError | nodes.ProxmoxOpError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
80
|
+
reconcile: (args_0: {
|
|
81
|
+
fqn: string;
|
|
82
|
+
instanceId: string;
|
|
83
|
+
news: StorageDownloadProps;
|
|
84
|
+
output: StorageDownloadAttributes | undefined;
|
|
85
|
+
}) => Effect.Effect<{
|
|
86
|
+
filename: string;
|
|
87
|
+
format: string;
|
|
88
|
+
node: string;
|
|
89
|
+
size: number;
|
|
90
|
+
storage: string;
|
|
91
|
+
volid: string;
|
|
92
|
+
}, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
93
|
+
delete: ({ olds }: {
|
|
94
|
+
olds: StorageDownloadProps;
|
|
95
|
+
}) => Effect.Effect<void, Error | import("./distilled-pve.ts").PveClusterExhausted | import("./credential-errors.ts").PveCredentialDenied | import("effect/Cause").TimeoutError | nodes.ProxmoxOpError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
96
|
+
};
|
|
97
|
+
//# sourceMappingURL=storage-download-lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-download-lifecycle.d.ts","sourceRoot":"","sources":["../../src/proxmox/storage-download-lifecycle.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,KAAK,MAAM,gCAAgC,CAAC;AACxD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAOxC,OAAO,KAAK,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAUnG;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,UAAW,oBAAoB;;;;;;;;;;CAYtD,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc,UAAW,oBAAoB,KAAG,MAAM,EAYlE,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,UAAW,oBAAoB;;;;;;;kPA6BpD,CAAC;AAEL,mGAAmG;AACnG,eAAO,MAAM,eAAe,UAAW,oBAAoB,4PAcvD,CAAC;AAEL,eAAO,MAAM,uBAAuB;IAClC,IAAI;IACJ;;;;;;OAMG;IACH,IAAI;aAMG,MAAM;oBACC,MAAM;cACZ,oBAAoB;gBAClB,yBAAyB,GAAG,SAAS;;;;;;;;;IAK/C,IAAI;cAKI,KAAK,CAAC,oBAAoB,CAAC;cAC3B,oBAAoB;gBAClB,yBAAyB,GAAG,SAAS;;yBAYK,SAAS;;;;IAW7D,SAAS;aAMF,MAAM;oBACC,MAAM;cACZ,oBAAoB;gBAClB,yBAAyB,GAAG,SAAS;;;;;;;;;IAkC/C,MAAM,aAAa;QAAE,IAAI,EAAE,oBAAoB,CAAA;KAAE;CAClD,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** What a `Proxmox.StorageDownload` declaration says, and what its state keeps. See storage-download.ts's header. */
|
|
2
|
+
import type { WithTarget } from './resource.ts';
|
|
3
|
+
export type ChecksumAlgorithm = 'md5' | 'sha1' | 'sha224' | 'sha256' | 'sha384' | 'sha512';
|
|
4
|
+
export interface StorageDownloadProps extends WithTarget {
|
|
5
|
+
/** The node this download runs on. Content lands on `storage`, shared or not — see the header. */
|
|
6
|
+
node: string;
|
|
7
|
+
storage: string;
|
|
8
|
+
/** The name PVE gives the file under `storage`'s `import` content. Normalized by PVE on write. */
|
|
9
|
+
filename: string;
|
|
10
|
+
/** Where to fetch the image from. ⚠️ Not re-verified after create — PVE does not store it. */
|
|
11
|
+
url: string;
|
|
12
|
+
/** ⛔ Required. See storage-download.ts's header on why this resource narrows the vendor's own optional field. */
|
|
13
|
+
checksum: string;
|
|
14
|
+
checksumAlgorithm: ChecksumAlgorithm;
|
|
15
|
+
/** Decompress the downloaded file with this algorithm before it lands on `storage`. */
|
|
16
|
+
compression?: string;
|
|
17
|
+
/** Verify the source's TLS certificate. PVE defaults this on; declare `false` for a self-signed mirror. */
|
|
18
|
+
verifyCertificates?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface StorageDownloadAttributes {
|
|
21
|
+
node: string;
|
|
22
|
+
storage: string;
|
|
23
|
+
filename: string;
|
|
24
|
+
/**
|
|
25
|
+
* ⚠️ REASONED, NOT MEASURED LIVE. PVE's file-based content types spell a volid
|
|
26
|
+
* `<storage>:<segment>/<filename>` — this codebase already relies on that shape for `iso` and
|
|
27
|
+
* `vztmpl` (lxc-create-form.ts's `existingVolume`, lxc-create.test.ts's own fixture) — but the
|
|
28
|
+
* exact `<segment>` spelling for `import` content is not independently confirmed against a
|
|
29
|
+
* live cluster. `storage-download-lifecycle.ts`'s `readDownload` does not depend on knowing
|
|
30
|
+
* it: it matches by filename SUFFIX within a list already server-filtered to `content=import`.
|
|
31
|
+
*/
|
|
32
|
+
volid: string;
|
|
33
|
+
size: number;
|
|
34
|
+
format: string;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=storage-download-props.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-download-props.d.ts","sourceRoot":"","sources":["../../src/proxmox/storage-download-props.ts"],"names":[],"mappings":"AAAA,qHAAqH;AACrH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE3F,MAAM,WAAW,oBAAqB,SAAQ,UAAU;IACtD,kGAAkG;IAClG,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,kGAAkG;IAClG,QAAQ,EAAE,MAAM,CAAC;IACjB,8FAA8F;IAC9F,GAAG,EAAE,MAAM,CAAC;IACZ,iHAAiH;IACjH,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,uFAAuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2GAA2G;IAC3G,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;OAOG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ProxmoxOpContext } from '@distilled.cloud/proxmox/Protocol';
|
|
2
|
+
import * as Effect from 'effect/Effect';
|
|
3
|
+
import type { PveTarget } from './credentials.ts';
|
|
4
|
+
export interface StorageDownloadWhere {
|
|
5
|
+
readonly node: string;
|
|
6
|
+
readonly target: PveTarget;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* ⛔ A CHECKSUM MISMATCH SURFACES HERE, NOT AS A DISTINCT TYPED ERROR. `download-url`'s POST
|
|
10
|
+
* answers 200 with a UPID regardless of whether the checksum will match — PVE validates the
|
|
11
|
+
* download itself, INSIDE the task, and reports the mismatch as that task's `exitstatus`. So
|
|
12
|
+
* the refusal below (`exit !== 'OK'`) IS the checksum-mismatch refusal: this poller fails the
|
|
13
|
+
* plan whenever the task did not report exactly `"OK"`, whatever the reason, without needing a
|
|
14
|
+
* new SDK tag to name it.
|
|
15
|
+
*/
|
|
16
|
+
export declare const storageDownloadTask: <E>(where: StorageDownloadWhere, operation: Effect.Effect<string, E, ProxmoxOpContext>, what: string, polls: number) => Effect.Effect<undefined, E | Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
17
|
+
//# sourceMappingURL=storage-download-task.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-download-task.d.ts","sourceRoot":"","sources":["../../src/proxmox/storage-download-task.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAKxC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,GAAI,CAAC,SAC5B,oBAAoB,aAChB,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,gBAAgB,CAAC,QAC/C,MAAM,SACL,MAAM,qJAsCX,CAAC"}
|