puls-dev 0.3.3 → 0.3.5

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.
Files changed (64) hide show
  1. package/dist/bin/install-shell.d.ts +2 -0
  2. package/dist/bin/install-shell.js +136 -0
  3. package/dist/bin/puls.d.ts +1 -0
  4. package/dist/bin/puls.js +145 -0
  5. package/dist/core/checker.js +74 -0
  6. package/dist/core/config.d.ts +3 -0
  7. package/dist/core/context.d.ts +1 -0
  8. package/dist/core/decorators.d.ts +1 -0
  9. package/dist/core/decorators.js +39 -5
  10. package/dist/core/output.js +8 -1
  11. package/dist/core/production.test.js +1 -0
  12. package/dist/core/resource.d.ts +35 -0
  13. package/dist/core/resource.js +57 -1
  14. package/dist/core/secret.d.ts +1 -0
  15. package/dist/core/secret.js +5 -0
  16. package/dist/core/stack.d.ts +11 -0
  17. package/dist/core/stack.js +141 -90
  18. package/dist/index.d.ts +2 -1
  19. package/dist/index.js +1 -1
  20. package/dist/providers/aws/api.js +3 -0
  21. package/dist/providers/aws/ec2.d.ts +5 -0
  22. package/dist/providers/aws/ec2.js +7 -0
  23. package/dist/providers/aws/lambda.d.ts +5 -0
  24. package/dist/providers/aws/lambda.js +24 -0
  25. package/dist/providers/aws/list.js +15 -3
  26. package/dist/providers/aws/rds.d.ts +9 -0
  27. package/dist/providers/aws/rds.js +19 -0
  28. package/dist/providers/do/database.d.ts +9 -0
  29. package/dist/providers/do/database.js +19 -0
  30. package/dist/providers/do/domain.js +1 -1
  31. package/dist/providers/do/droplet.d.ts +10 -0
  32. package/dist/providers/do/droplet.js +28 -3
  33. package/dist/providers/do/droplet.test.js +1 -1
  34. package/dist/providers/do/list.js +25 -2
  35. package/dist/providers/do/load_balancer.d.ts +5 -0
  36. package/dist/providers/do/load_balancer.js +7 -0
  37. package/dist/providers/do/vpc.d.ts +5 -0
  38. package/dist/providers/do/vpc.js +8 -0
  39. package/dist/providers/firebase/functions.d.ts +9 -0
  40. package/dist/providers/firebase/functions.js +28 -0
  41. package/dist/providers/firebase/list.js +34 -2
  42. package/dist/providers/gcp/api.js +6 -0
  43. package/dist/providers/gcp/cloudrun.d.ts +13 -0
  44. package/dist/providers/gcp/cloudrun.js +30 -0
  45. package/dist/providers/gcp/cloudsql.d.ts +9 -0
  46. package/dist/providers/gcp/cloudsql.js +20 -0
  47. package/dist/providers/gcp/list.js +12 -2
  48. package/dist/providers/gcp/template.d.ts +3 -0
  49. package/dist/providers/gcp/template.js +13 -1
  50. package/dist/providers/gcp/vm.d.ts +8 -0
  51. package/dist/providers/gcp/vm.js +22 -2
  52. package/dist/providers/proxmox/api.d.ts +1 -0
  53. package/dist/providers/proxmox/api.js +18 -3
  54. package/dist/providers/proxmox/base.d.ts +16 -0
  55. package/dist/providers/proxmox/base.js +121 -0
  56. package/dist/providers/proxmox/list.js +8 -1
  57. package/dist/providers/proxmox/template.d.ts +3 -10
  58. package/dist/providers/proxmox/template.js +51 -139
  59. package/dist/providers/proxmox/vm.d.ts +18 -10
  60. package/dist/providers/proxmox/vm.js +73 -152
  61. package/dist/types/diff.d.ts +17 -0
  62. package/dist/types/diff.js +1 -0
  63. package/dist/types/inventory.d.ts +65 -0
  64. package/package.json +7 -22
@@ -0,0 +1,121 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { spawn } from "node:child_process";
4
+ import { BaseBuilder } from "../../core/resource.js";
5
+ import { Config } from "../../core/config.js";
6
+ import { checkPort, runProvisioner } from "../../core/provisioner.js";
7
+ export class ProxmoxBaseBuilder extends BaseBuilder {
8
+ _sshKeys;
9
+ _sshUser;
10
+ sshKey(keys) {
11
+ this._sshKeys = Array.isArray(keys) ? [...keys] : keys;
12
+ return this;
13
+ }
14
+ sshUser(user) {
15
+ this._sshUser = user;
16
+ return this;
17
+ }
18
+ resolveUser() {
19
+ return (this._sshUser ??
20
+ process.env.PROXMOX_SSH_USER ??
21
+ Config.get().providers.proxmox?.sshUser ??
22
+ "root");
23
+ }
24
+ async selectBestNode(pm) {
25
+ try {
26
+ const nodesList = await pm.get("/nodes");
27
+ const configuredNodes = Config.get().providers.proxmox?.nodes;
28
+ const onlineNodes = (nodesList ?? []).filter((n) => {
29
+ if (n.status !== "online")
30
+ return false;
31
+ if (configuredNodes && configuredNodes.length > 0) {
32
+ return configuredNodes.includes(n.node);
33
+ }
34
+ return true;
35
+ });
36
+ if (onlineNodes.length > 0) {
37
+ onlineNodes.sort((a, b) => {
38
+ const freeA = (a.maxmem ?? 0) - (a.mem ?? 0);
39
+ const freeB = (b.maxmem ?? 0) - (b.mem ?? 0);
40
+ return freeB - freeA;
41
+ });
42
+ const best = onlineNodes[0];
43
+ const freeGb = Math.round((((best.maxmem ?? 0) - (best.mem ?? 0)) / 1024 / 1024 / 1024) * 10) / 10;
44
+ console.log(` 🧠 Cluster-aware node selection: picked "${best.node}" with the most free RAM (${freeGb} GB free)`);
45
+ return best.node;
46
+ }
47
+ }
48
+ catch {
49
+ // Fallback to configured nodes or template node
50
+ }
51
+ return undefined;
52
+ }
53
+ async waitForTask(node, upid, pm) {
54
+ const encoded = encodeURIComponent(upid);
55
+ await this.waitFor(`clone task to complete`, async () => {
56
+ const status = await pm.get(`/nodes/${node}/tasks/${encoded}/status`);
57
+ if (status?.status !== "stopped")
58
+ return false;
59
+ if (status.exitstatus && status.exitstatus !== "OK") {
60
+ throw new Error(`Clone task failed: ${status.exitstatus}`);
61
+ }
62
+ return true;
63
+ }, { intervalMs: 5_000, timeoutMs: 300_000 });
64
+ }
65
+ resolvePublicKeys() {
66
+ const input = this._sshKeys;
67
+ if (!input) {
68
+ try {
69
+ return [readFileSync(`${homedir()}/.ssh/id_ed25519.pub`, "utf-8").trim()];
70
+ }
71
+ catch {
72
+ return [];
73
+ }
74
+ }
75
+ if (Array.isArray(input))
76
+ return input.map((k) => k.trim()).filter(Boolean);
77
+ if (input.startsWith("ssh-") ||
78
+ input.startsWith("ecdsa-") ||
79
+ input.startsWith("sk-")) {
80
+ return [input.trim()];
81
+ }
82
+ try {
83
+ return [readFileSync(input.replace(/^~/, homedir()), "utf-8").trim()];
84
+ }
85
+ catch {
86
+ return [];
87
+ }
88
+ }
89
+ sshKeyPath() {
90
+ const keyInput = Array.isArray(this._sshKeys) ? null : this._sshKeys;
91
+ return (keyInput &&
92
+ !keyInput.startsWith("ssh-") &&
93
+ !keyInput.startsWith("ecdsa-") &&
94
+ !keyInput.startsWith("sk-")
95
+ ? keyInput.replace(/\.pub$/, "")
96
+ : `${homedir()}/.ssh/id_ed25519`).replace(/^~/, homedir());
97
+ }
98
+ checkCloudInit(ip) {
99
+ const keyPath = this.sshKeyPath();
100
+ return new Promise((resolve) => {
101
+ const proc = spawn("ssh", [
102
+ "-i", keyPath,
103
+ "-o", "StrictHostKeyChecking=no",
104
+ "-o", "ConnectTimeout=10",
105
+ "-o", "BatchMode=yes",
106
+ `root@${ip}`,
107
+ "cloud-init status",
108
+ ], { stdio: ["ignore", "pipe", "ignore"] });
109
+ let out = "";
110
+ proc.stdout.on("data", (d) => (out += d.toString()));
111
+ proc.on("close", () => resolve(out.includes("done") || out.includes("error")));
112
+ proc.on("error", () => resolve(false));
113
+ });
114
+ }
115
+ async checkPort(ip, port) {
116
+ return checkPort(ip, port);
117
+ }
118
+ async runProvisioner(ip, script) {
119
+ return runProvisioner(ip, this.resolveUser(), this._sshKeys, script);
120
+ }
121
+ }
@@ -11,5 +11,12 @@ export async function listProxmoxVMs() {
11
11
  maxmem: r.maxmem ?? 0,
12
12
  maxdisk: r.maxdisk ?? 0,
13
13
  }));
14
- return { vms };
14
+ const templates = (resources ?? [])
15
+ .filter((r) => r.template === 1)
16
+ .map((r) => ({
17
+ name: r.name,
18
+ vmid: r.vmid,
19
+ node: r.node,
20
+ }));
21
+ return { vms, templates };
15
22
  }
@@ -1,7 +1,7 @@
1
- import { BaseBuilder } from "../../core/resource.js";
1
+ import { ProxmoxBaseBuilder } from "./base.js";
2
2
  import { Output } from "../../core/output.js";
3
3
  import type { OSImage } from "../../types/proxmox.js";
4
- export declare class TemplateBuilder extends BaseBuilder {
4
+ export declare class TemplateBuilder extends ProxmoxBaseBuilder {
5
5
  readonly out: {
6
6
  vmid: Output<number>;
7
7
  };
@@ -12,14 +12,12 @@ export declare class TemplateBuilder extends BaseBuilder {
12
12
  private _memory;
13
13
  private _provision;
14
14
  private _storage?;
15
- private _sshKeys?;
16
15
  constructor(name: string);
17
16
  private discoverTemplate;
18
17
  baseImage(os: OSImage): this;
19
18
  cores(n: number): this;
20
19
  memory(mb: number): this;
21
20
  storage(pool: string): this;
22
- sshKey(keys: string | readonly string[]): this;
23
21
  provision(...playbookPaths: (string | string[])[]): this;
24
22
  deploy(): Promise<{
25
23
  name: string;
@@ -30,15 +28,10 @@ export declare class TemplateBuilder extends BaseBuilder {
30
28
  vmid: string;
31
29
  node?: undefined;
32
30
  }>;
31
+ private _deploy;
33
32
  destroy(): Promise<{
34
33
  destroyed: boolean;
35
34
  } | {
36
35
  destroyed: string;
37
36
  }>;
38
- private waitForTask;
39
- private resolvePublicKeys;
40
- private checkCloudInit;
41
- protected checkPort(ip: string, port: number): Promise<boolean>;
42
- protected runProvisioner(ip: string, script: string): Promise<void>;
43
- private sshKeyPath;
44
37
  }
@@ -1,13 +1,9 @@
1
- import { readFileSync } from "node:fs";
2
- import { homedir } from "node:os";
3
- import { spawn } from "node:child_process";
4
- import { BaseBuilder } from "../../core/resource.js";
1
+ import { ProxmoxBaseBuilder } from "./base.js";
5
2
  import { Config } from "../../core/config.js";
6
3
  import { Output } from "../../core/output.js";
7
- import { getPMClient } from "./api.js";
4
+ import { getPMClient, withVmidAllocation } from "./api.js";
8
5
  import { getFileHash, parseProvisionMetadata, mergeProvisionMetadata } from "./hash.js";
9
- import { checkPort, runProvisioner } from "../../core/provisioner.js";
10
- export class TemplateBuilder extends BaseBuilder {
6
+ export class TemplateBuilder extends ProxmoxBaseBuilder {
11
7
  out = {
12
8
  vmid: new Output(),
13
9
  };
@@ -18,7 +14,6 @@ export class TemplateBuilder extends BaseBuilder {
18
14
  _memory = 2048;
19
15
  _provision = [];
20
16
  _storage;
21
- _sshKeys;
22
17
  constructor(name) {
23
18
  super(name);
24
19
  this.discoveryPromise = this.discoverTemplate(name);
@@ -61,22 +56,24 @@ export class TemplateBuilder extends BaseBuilder {
61
56
  this._storage = pool;
62
57
  return this;
63
58
  }
64
- sshKey(keys) {
65
- this._sshKeys = Array.isArray(keys) ? [...keys] : keys;
66
- return this;
67
- }
68
59
  provision(...playbookPaths) {
69
60
  this._provision.push(...playbookPaths.flat());
70
61
  return this;
71
62
  }
72
63
  async deploy() {
64
+ try {
65
+ return await this._deploy();
66
+ }
67
+ catch (err) {
68
+ this.out.vmid.reject(err);
69
+ throw err;
70
+ }
71
+ }
72
+ async _deploy() {
73
73
  const dryRun = this.isDryRunActive();
74
74
  const existing = await this.discoveryPromise;
75
75
  const pm = getPMClient();
76
76
  if (existing) {
77
- this.resolvedVmid = existing.vmid;
78
- this.resolvedNode = existing.node;
79
- this.out.vmid.resolve(existing.vmid);
80
77
  // Check if playbook hashes differ
81
78
  const appliedHashes = parseProvisionMetadata(existing.description ?? "");
82
79
  const declaredPlaybooksWithHashes = this._provision.map((p) => {
@@ -88,6 +85,9 @@ export class TemplateBuilder extends BaseBuilder {
88
85
  return !appliedHash || appliedHash !== p.hash;
89
86
  });
90
87
  if (!hasChanges) {
88
+ this.resolvedVmid = existing.vmid;
89
+ this.resolvedNode = existing.node;
90
+ this.out.vmid.resolve(existing.vmid);
91
91
  console.log(`\n🖥️ Finalizing Proxmox Template "${this.name}"...`);
92
92
  console.log(` ✅ Template "${this.name}" already exists and matches defined state.`);
93
93
  return { name: this.name, vmid: this.resolvedVmid, node: this.resolvedNode };
@@ -96,11 +96,11 @@ export class TemplateBuilder extends BaseBuilder {
96
96
  console.log(` 🔄 Template playbook hashes changed. Purging old template...`);
97
97
  if (dryRun) {
98
98
  console.log(` 📝 [PLAN] Would purge template "${this.name}" (vmid=${existing.vmid}) and rebuild.`);
99
+ this.out.vmid.resolve(-1);
99
100
  return { name: this.name, vmid: "PENDING" };
100
101
  }
101
- else {
102
- await pm.delete(`/nodes/${existing.node}/qemu/${existing.vmid}?purge=1&destroy-unreferenced-disks=1`);
103
- }
102
+ await pm.delete(`/nodes/${existing.node}/qemu/${existing.vmid}?purge=1&destroy-unreferenced-disks=1`);
103
+ // Fall through to rebuild
104
104
  }
105
105
  console.log(`\n🖥️ Finalizing Proxmox Template "${this.name}"...`);
106
106
  if (dryRun) {
@@ -115,31 +115,7 @@ export class TemplateBuilder extends BaseBuilder {
115
115
  return { name: this.name, vmid: "PENDING" };
116
116
  }
117
117
  // Pick target node (cluster-aware)
118
- let node;
119
- try {
120
- const nodesList = await pm.get("/nodes");
121
- const configuredNodes = Config.get().providers.proxmox?.nodes;
122
- const onlineNodes = (nodesList ?? []).filter((n) => {
123
- if (n.status !== "online")
124
- return false;
125
- if (configuredNodes && configuredNodes.length > 0) {
126
- return configuredNodes.includes(n.node);
127
- }
128
- return true;
129
- });
130
- if (onlineNodes.length > 0) {
131
- onlineNodes.sort((a, b) => {
132
- const freeA = (a.maxmem ?? 0) - (a.mem ?? 0);
133
- const freeB = (b.maxmem ?? 0) - (b.mem ?? 0);
134
- return freeB - freeA;
135
- });
136
- node = onlineNodes[0].node;
137
- console.log(` 🧠 Cluster-aware node selection: picked "${node}" with the most free RAM (${Math.round((((onlineNodes[0].maxmem ?? 0) - (onlineNodes[0].mem ?? 0)) / 1024 / 1024 / 1024) * 10) / 10} GB free)`);
138
- }
139
- }
140
- catch (err) {
141
- // Fallback
142
- }
118
+ let node = await this.selectBestNode(pm);
143
119
  if (!node) {
144
120
  const configuredNodes = Config.get().providers.proxmox?.nodes;
145
121
  node = configuredNodes?.[0];
@@ -150,8 +126,6 @@ export class TemplateBuilder extends BaseBuilder {
150
126
  }
151
127
  if (!node)
152
128
  throw new Error("No Proxmox nodes available");
153
- const newVmid = await pm.get("/cluster/nextid");
154
- const storage = this._storage ?? "rbd_pool";
155
129
  // Lookup base image template
156
130
  const resources = await pm.get("/cluster/resources?type=vm");
157
131
  const isVmid = this._baseImage && /^\d+$/.test(this._baseImage);
@@ -164,28 +138,38 @@ export class TemplateBuilder extends BaseBuilder {
164
138
  if (this._baseImage && !baseTemplate) {
165
139
  throw new Error(`No Proxmox base template found matching "${this._baseImage}".`);
166
140
  }
167
- if (baseTemplate) {
168
- console.log(` 📋 Cloning base template "${baseTemplate.name}" (vmid=${baseTemplate.vmid}) "${this.name}" (vmid=${newVmid})`);
169
- const taskId = await pm.post(`/nodes/${baseTemplate.node || node}/qemu/${baseTemplate.vmid}/clone`, {
170
- newid: newVmid,
171
- name: this.name,
172
- full: 1,
173
- storage,
174
- format: "raw",
175
- target: node,
176
- });
177
- await this.waitForTask(baseTemplate.node || node, taskId, pm);
178
- }
179
- else {
180
- console.log(` 🆕 Creating blank VM "${this.name}" (vmid=${newVmid})`);
181
- await pm.post(`/nodes/${node}/qemu`, {
182
- vmid: newVmid,
183
- name: this.name,
184
- cores: this._cores,
185
- memory: this._memory,
186
- net0: "virtio,bridge=vmbr1",
187
- ostype: "l26",
188
- });
141
+ const storage = this._storage ?? "rbd_pool";
142
+ // Allocate VMID and immediately issue the create/clone request while holding the lock
143
+ // to prevent parallel templates from claiming the same VMID.
144
+ const { newVmid, cloneTaskId, cloneNode } = await withVmidAllocation(async () => {
145
+ const vmid = await pm.get("/cluster/nextid");
146
+ if (baseTemplate) {
147
+ console.log(` 📋 Cloning base template "${baseTemplate.name}" (vmid=${baseTemplate.vmid}) → "${this.name}" (vmid=${vmid})`);
148
+ const taskId = await pm.post(`/nodes/${baseTemplate.node || node}/qemu/${baseTemplate.vmid}/clone`, {
149
+ newid: vmid,
150
+ name: this.name,
151
+ full: 1,
152
+ storage,
153
+ format: "raw",
154
+ target: node,
155
+ });
156
+ return { newVmid: vmid, cloneTaskId: taskId, cloneNode: baseTemplate.node || node };
157
+ }
158
+ else {
159
+ console.log(` 🆕 Creating blank VM "${this.name}" (vmid=${vmid})`);
160
+ await pm.post(`/nodes/${node}/qemu`, {
161
+ vmid,
162
+ name: this.name,
163
+ cores: this._cores,
164
+ memory: this._memory,
165
+ net0: "virtio,bridge=vmbr1",
166
+ ostype: "l26",
167
+ });
168
+ return { newVmid: vmid, cloneTaskId: null, cloneNode: null };
169
+ }
170
+ });
171
+ if (cloneTaskId && cloneNode) {
172
+ await this.waitForTask(cloneNode, cloneTaskId, pm);
189
173
  }
190
174
  this.resolvedVmid = newVmid;
191
175
  this.resolvedNode = node;
@@ -275,76 +259,4 @@ export class TemplateBuilder extends BaseBuilder {
275
259
  console.log(` 🗑️ Removed Template "${this.name}" (vmid=${existing.vmid})`);
276
260
  return { destroyed: this.name };
277
261
  }
278
- async waitForTask(node, upid, pm) {
279
- const encoded = encodeURIComponent(upid);
280
- await this.waitFor(`clone task to complete`, async () => {
281
- const status = await pm.get(`/nodes/${node}/tasks/${encoded}/status`);
282
- if (status?.status !== "stopped")
283
- return false;
284
- if (status.exitstatus && status.exitstatus !== "OK") {
285
- throw new Error(`Clone task failed: ${status.exitstatus}`);
286
- }
287
- return true;
288
- }, { intervalMs: 5_000, timeoutMs: 300_000 });
289
- }
290
- resolvePublicKeys() {
291
- const input = this._sshKeys;
292
- if (!input) {
293
- try {
294
- return [readFileSync(`${homedir()}/.ssh/id_ed25519.pub`, "utf-8").trim()];
295
- }
296
- catch {
297
- return [];
298
- }
299
- }
300
- if (Array.isArray(input))
301
- return input.map((k) => k.trim()).filter(Boolean);
302
- if (input.startsWith("ssh-") ||
303
- input.startsWith("ecdsa-") ||
304
- input.startsWith("sk-")) {
305
- return [input.trim()];
306
- }
307
- try {
308
- return [readFileSync(input.replace(/^~/, homedir()), "utf-8").trim()];
309
- }
310
- catch {
311
- return [];
312
- }
313
- }
314
- checkCloudInit(ip) {
315
- const keyPath = this.sshKeyPath();
316
- return new Promise((resolve) => {
317
- const proc = spawn("ssh", [
318
- "-i",
319
- keyPath,
320
- "-o",
321
- "StrictHostKeyChecking=no",
322
- "-o",
323
- "ConnectTimeout=10",
324
- "-o",
325
- "BatchMode=yes",
326
- `root@${ip}`,
327
- "cloud-init status",
328
- ], { stdio: ["ignore", "pipe", "ignore"] });
329
- let out = "";
330
- proc.stdout.on("data", (d) => (out += d.toString()));
331
- proc.on("close", () => resolve(out.includes("done") || out.includes("error")));
332
- proc.on("error", () => resolve(false));
333
- });
334
- }
335
- async checkPort(ip, port) {
336
- return checkPort(ip, port);
337
- }
338
- async runProvisioner(ip, script) {
339
- return runProvisioner(ip, "root", this._sshKeys, script);
340
- }
341
- sshKeyPath() {
342
- const keyInput = Array.isArray(this._sshKeys) ? null : this._sshKeys;
343
- return (keyInput &&
344
- !keyInput.startsWith("ssh-") &&
345
- !keyInput.startsWith("ecdsa-") &&
346
- !keyInput.startsWith("sk-")
347
- ? keyInput.replace(/\.pub$/, "")
348
- : `${homedir()}/.ssh/id_ed25519`).replace(/^~/, homedir());
349
- }
350
262
  }
@@ -1,8 +1,8 @@
1
- import { BaseBuilder } from "../../core/resource.js";
1
+ import { ProxmoxBaseBuilder } from "./base.js";
2
2
  import { Output } from "../../core/output.js";
3
3
  import type { OSImage } from "../../types/proxmox.js";
4
4
  import { TemplateBuilder } from "./template.js";
5
- export declare class VMBuilder extends BaseBuilder {
5
+ export declare class VMBuilder extends ProxmoxBaseBuilder {
6
6
  readonly out: {
7
7
  ip: Output<string>;
8
8
  vmid: Output<number>;
@@ -20,7 +20,7 @@ export declare class VMBuilder extends BaseBuilder {
20
20
  private _storage?;
21
21
  private _vlan?;
22
22
  private _ip?;
23
- private _sshKeys?;
23
+ private _gateway?;
24
24
  private _machine;
25
25
  private _forceConfigCheck;
26
26
  constructor(name: string);
@@ -35,9 +35,22 @@ export declare class VMBuilder extends BaseBuilder {
35
35
  storage(pool: string): this;
36
36
  vlan(tag: number): this;
37
37
  ip(address: string): this;
38
- sshKey(keys: string | readonly string[]): this;
38
+ gateway(gw: string): this;
39
39
  machine(type: "q35" | "i440fx"): this;
40
40
  forceConfigCheck(): this;
41
+ getDiff(existing: any): ({
42
+ field: string;
43
+ declared: number;
44
+ live: any;
45
+ } | {
46
+ field: string;
47
+ declared: string;
48
+ live: string;
49
+ } | {
50
+ field: string;
51
+ declared: "q35" | "i440fx";
52
+ live: any;
53
+ })[];
41
54
  deploy(): Promise<{
42
55
  name: string;
43
56
  vmid: number | null;
@@ -54,14 +67,9 @@ export declare class VMBuilder extends BaseBuilder {
54
67
  ip: string | null;
55
68
  node?: undefined;
56
69
  }>;
70
+ private _deploy;
57
71
  private resolveExistingIp;
58
72
  private registerHost;
59
73
  destroy(): Promise<any>;
60
- private waitForTask;
61
74
  private destroyVmByName;
62
- private resolvePublicKeys;
63
- private checkCloudInit;
64
- protected checkPort(ip: string, port: number): Promise<boolean>;
65
- protected runProvisioner(ip: string, script: string): Promise<void>;
66
- private sshKeyPath;
67
75
  }