puls-dev 0.3.4 → 0.3.6
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 +165 -54
- package/dist/bin/install-shell.d.ts +2 -0
- package/dist/bin/install-shell.js +136 -0
- package/dist/bin/puls.js +32 -10
- package/dist/core/checker.js +74 -0
- package/dist/core/decorators.js +17 -1
- package/dist/core/resource.d.ts +35 -0
- package/dist/core/resource.js +57 -1
- package/dist/core/stack.d.ts +11 -0
- package/dist/core/stack.js +88 -1
- package/dist/index.d.ts +1 -0
- package/dist/providers/aws/api.js +3 -0
- package/dist/providers/aws/ec2.d.ts +5 -0
- package/dist/providers/aws/ec2.js +7 -0
- package/dist/providers/aws/lambda.d.ts +5 -0
- package/dist/providers/aws/lambda.js +24 -0
- package/dist/providers/aws/list.js +15 -3
- package/dist/providers/aws/rds.d.ts +9 -0
- package/dist/providers/aws/rds.js +19 -0
- package/dist/providers/do/database.d.ts +9 -0
- package/dist/providers/do/database.js +19 -0
- package/dist/providers/do/domain.js +1 -1
- package/dist/providers/do/droplet.d.ts +5 -0
- package/dist/providers/do/droplet.js +10 -0
- package/dist/providers/do/list.js +25 -2
- package/dist/providers/do/load_balancer.d.ts +5 -0
- package/dist/providers/do/load_balancer.js +7 -0
- package/dist/providers/do/vpc.d.ts +5 -0
- package/dist/providers/do/vpc.js +8 -0
- package/dist/providers/firebase/functions.d.ts +9 -0
- package/dist/providers/firebase/functions.js +28 -0
- package/dist/providers/firebase/list.js +34 -2
- package/dist/providers/gcp/api.js +6 -0
- package/dist/providers/gcp/cloudrun.d.ts +13 -0
- package/dist/providers/gcp/cloudrun.js +30 -0
- package/dist/providers/gcp/cloudsql.d.ts +9 -0
- package/dist/providers/gcp/cloudsql.js +20 -0
- package/dist/providers/gcp/list.js +12 -2
- package/dist/providers/gcp/vm.d.ts +5 -0
- package/dist/providers/gcp/vm.js +8 -0
- package/dist/providers/proxmox/list.js +8 -1
- package/dist/providers/proxmox/vm.d.ts +13 -0
- package/dist/providers/proxmox/vm.js +16 -0
- package/dist/types/diff.d.ts +17 -0
- package/dist/types/diff.js +1 -0
- package/dist/types/inventory.d.ts +65 -0
- package/package.json +2 -2
|
@@ -79,6 +79,34 @@ export class FirebaseFunctionsBuilder extends BaseBuilder {
|
|
|
79
79
|
this._env = vars;
|
|
80
80
|
return this;
|
|
81
81
|
}
|
|
82
|
+
getDiff(existing) {
|
|
83
|
+
const diffs = [];
|
|
84
|
+
const liveRuntime = existing.buildConfig?.runtime;
|
|
85
|
+
if (liveRuntime !== undefined && liveRuntime !== this._runtime) {
|
|
86
|
+
diffs.push({ field: "runtime", declared: this._runtime, live: liveRuntime });
|
|
87
|
+
}
|
|
88
|
+
const liveEntryPoint = existing.buildConfig?.entryPoint;
|
|
89
|
+
if (liveEntryPoint !== undefined && liveEntryPoint !== this._entryPoint) {
|
|
90
|
+
diffs.push({ field: "entryPoint", declared: this._entryPoint, live: liveEntryPoint });
|
|
91
|
+
}
|
|
92
|
+
const liveMemory = existing.serviceConfig?.availableMemory;
|
|
93
|
+
if (liveMemory !== undefined && liveMemory !== this._memory) {
|
|
94
|
+
diffs.push({ field: "memory", declared: this._memory, live: liveMemory });
|
|
95
|
+
}
|
|
96
|
+
const liveTimeout = existing.serviceConfig?.timeoutSeconds;
|
|
97
|
+
if (liveTimeout !== undefined && liveTimeout !== this._timeout) {
|
|
98
|
+
diffs.push({ field: "timeout", declared: `${this._timeout}s`, live: `${liveTimeout}s` });
|
|
99
|
+
}
|
|
100
|
+
const liveMax = existing.serviceConfig?.maxInstanceCount;
|
|
101
|
+
if (liveMax !== undefined && liveMax !== this._maxInstances) {
|
|
102
|
+
diffs.push({ field: "maxInstances", declared: this._maxInstances, live: liveMax });
|
|
103
|
+
}
|
|
104
|
+
const liveMin = existing.serviceConfig?.minInstanceCount ?? 0;
|
|
105
|
+
if (liveMin !== this._minInstances) {
|
|
106
|
+
diffs.push({ field: "minInstances", declared: this._minInstances, live: liveMin });
|
|
107
|
+
}
|
|
108
|
+
return diffs;
|
|
109
|
+
}
|
|
82
110
|
fnPath() {
|
|
83
111
|
return `/projects/${getProjectId()}/locations/${this._region}/functions/${this.name}`;
|
|
84
112
|
}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { getProjectId, hostingFetch, cloudFetch } from "./api.js";
|
|
2
2
|
export async function listFirebaseResources() {
|
|
3
3
|
const project = getProjectId();
|
|
4
|
-
const [hostRes, fnRes] = await Promise.all([
|
|
4
|
+
const [hostRes, fnRes, firestoreRes, storageRes, authRes, rcRes] = await Promise.all([
|
|
5
5
|
hostingFetch(`/projects/${project}/sites`).catch(() => ({})),
|
|
6
6
|
cloudFetch("https://cloudfunctions.googleapis.com/v2", `/projects/${project}/locations/-/functions`).catch(() => ({})),
|
|
7
|
+
cloudFetch("https://firestore.googleapis.com/v1", `/projects/${project}/databases`).catch(() => ({})),
|
|
8
|
+
cloudFetch("https://storage.googleapis.com/storage/v1", `/b?project=${project}`).catch(() => ({})),
|
|
9
|
+
cloudFetch("https://identitytoolkit.googleapis.com/admin/v2", `/projects/${project}/config`).catch(() => ({})),
|
|
10
|
+
cloudFetch("https://firebaseremoteconfig.googleapis.com/v1", `/projects/${project}/remoteConfig`).catch(() => ({})),
|
|
7
11
|
]);
|
|
8
12
|
// 1. Map Hosting Sites
|
|
9
13
|
const hostingSites = (hostRes.sites ?? []).map((s) => ({
|
|
@@ -21,5 +25,33 @@ export async function listFirebaseResources() {
|
|
|
21
25
|
runtime: f.buildConfig?.runtime ?? "unknown",
|
|
22
26
|
};
|
|
23
27
|
});
|
|
24
|
-
|
|
28
|
+
// 3. Map Firestore Databases
|
|
29
|
+
const firestoreDbs = (firestoreRes.databases ?? []).map((d) => ({
|
|
30
|
+
name: d.name.split("/").pop() ?? d.name,
|
|
31
|
+
type: d.type ?? "FIRESTORE_NATIVE",
|
|
32
|
+
state: d.state ?? "unknown",
|
|
33
|
+
}));
|
|
34
|
+
// 4. Map Storage Buckets (filter to project-owned buckets)
|
|
35
|
+
const storageBuckets = (storageRes.items ?? [])
|
|
36
|
+
.filter((b) => b.name?.includes(project))
|
|
37
|
+
.map((b) => ({
|
|
38
|
+
name: b.name,
|
|
39
|
+
location: b.location ?? "unknown",
|
|
40
|
+
}));
|
|
41
|
+
// 5. Map Auth Sign-in Providers from Identity Toolkit config
|
|
42
|
+
const signIn = authRes.signIn ?? {};
|
|
43
|
+
const authProviders = [
|
|
44
|
+
...(signIn.email?.enabled ? [{ providerId: "email/password" }] : []),
|
|
45
|
+
...(signIn.phoneNumber?.enabled ? [{ providerId: "phone" }] : []),
|
|
46
|
+
...(signIn.anonymous?.enabled ? [{ providerId: "anonymous" }] : []),
|
|
47
|
+
];
|
|
48
|
+
// 6. Map RemoteConfig
|
|
49
|
+
let remoteConfig;
|
|
50
|
+
if (rcRes.parameters !== undefined || rcRes.version) {
|
|
51
|
+
remoteConfig = {
|
|
52
|
+
parameterCount: Object.keys(rcRes.parameters ?? {}).length,
|
|
53
|
+
version: rcRes.version?.versionNumber ?? "unknown",
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return { hostingSites, functions, firestoreDbs, storageBuckets, authProviders, remoteConfig };
|
|
25
57
|
}
|
|
@@ -113,6 +113,12 @@ function createGcpOfflineMock(base, path, opts) {
|
|
|
113
113
|
};
|
|
114
114
|
}
|
|
115
115
|
if (path.includes("/instances")) {
|
|
116
|
+
// Specific instance GET (discovery path: /instances/{name}) - return not-found so
|
|
117
|
+
// builders plan creation rather than treating the mock VM as already existing
|
|
118
|
+
const afterInstances = path.split("/instances")[1] ?? "";
|
|
119
|
+
if (afterInstances.startsWith("/") && afterInstances.length > 1) {
|
|
120
|
+
throw new Error(`GCP API GET ${path} → 404: Not Found`);
|
|
121
|
+
}
|
|
116
122
|
return {
|
|
117
123
|
status: "RUNNING",
|
|
118
124
|
id: "mock-gcp-instance-id",
|
|
@@ -20,6 +20,19 @@ export declare class GCPCloudRunBuilder extends BaseBuilder {
|
|
|
20
20
|
env(vars: Record<string, string | GCPSecretBuilder>): this;
|
|
21
21
|
region(reg: string): this;
|
|
22
22
|
public(enabled?: boolean): this;
|
|
23
|
+
getDiff(existing: any): ({
|
|
24
|
+
field: string;
|
|
25
|
+
declared: string | undefined;
|
|
26
|
+
live: any;
|
|
27
|
+
} | {
|
|
28
|
+
field: string;
|
|
29
|
+
declared: number;
|
|
30
|
+
live: any;
|
|
31
|
+
} | {
|
|
32
|
+
field: string;
|
|
33
|
+
declared: boolean;
|
|
34
|
+
live: boolean;
|
|
35
|
+
})[];
|
|
23
36
|
private discoverService;
|
|
24
37
|
deploy(): Promise<{
|
|
25
38
|
serviceId: string;
|
|
@@ -60,6 +60,36 @@ export class GCPCloudRunBuilder extends BaseBuilder {
|
|
|
60
60
|
this._public = enabled;
|
|
61
61
|
return this;
|
|
62
62
|
}
|
|
63
|
+
getDiff(existing) {
|
|
64
|
+
const diffs = [];
|
|
65
|
+
const container = existing.template?.containers?.[0];
|
|
66
|
+
const scaling = existing.template?.scaling ?? {};
|
|
67
|
+
const targetIngress = this._public ? "INGRESS_TRAFFIC_ALL" : "INGRESS_TRAFFIC_INTERNAL_ONLY";
|
|
68
|
+
if (container?.image !== this._image) {
|
|
69
|
+
diffs.push({ field: "image", declared: this._image, live: container?.image });
|
|
70
|
+
}
|
|
71
|
+
if (container?.ports?.[0]?.containerPort !== this._port) {
|
|
72
|
+
diffs.push({ field: "port", declared: this._port, live: container?.ports?.[0]?.containerPort });
|
|
73
|
+
}
|
|
74
|
+
if (container?.resources?.limits?.cpu !== formatCpu(this._cpu)) {
|
|
75
|
+
diffs.push({ field: "cpu", declared: formatCpu(this._cpu), live: container?.resources?.limits?.cpu });
|
|
76
|
+
}
|
|
77
|
+
if (container?.resources?.limits?.memory !== formatMemory(this._memory)) {
|
|
78
|
+
diffs.push({ field: "memory", declared: formatMemory(this._memory), live: container?.resources?.limits?.memory });
|
|
79
|
+
}
|
|
80
|
+
const minDeclared = this._minInstances ?? 0;
|
|
81
|
+
const maxDeclared = this._maxInstances ?? 100;
|
|
82
|
+
if ((scaling.minInstanceCount ?? 0) !== minDeclared) {
|
|
83
|
+
diffs.push({ field: "minInstances", declared: minDeclared, live: scaling.minInstanceCount ?? 0 });
|
|
84
|
+
}
|
|
85
|
+
if ((scaling.maxInstanceCount ?? 100) !== maxDeclared) {
|
|
86
|
+
diffs.push({ field: "maxInstances", declared: maxDeclared, live: scaling.maxInstanceCount ?? 100 });
|
|
87
|
+
}
|
|
88
|
+
if (existing.ingress !== targetIngress) {
|
|
89
|
+
diffs.push({ field: "public", declared: this._public, live: existing.ingress === "INGRESS_TRAFFIC_ALL" });
|
|
90
|
+
}
|
|
91
|
+
return diffs;
|
|
92
|
+
}
|
|
63
93
|
async discoverService() {
|
|
64
94
|
try {
|
|
65
95
|
const project = getProjectId();
|
|
@@ -23,6 +23,15 @@ export declare class GCPCloudSQLBuilder extends BaseBuilder {
|
|
|
23
23
|
database(name: string): this;
|
|
24
24
|
publicAccess(enabled?: boolean): this;
|
|
25
25
|
region(reg: string): this;
|
|
26
|
+
getDiff(existing: any): ({
|
|
27
|
+
field: string;
|
|
28
|
+
declared: string;
|
|
29
|
+
live: any;
|
|
30
|
+
} | {
|
|
31
|
+
field: string;
|
|
32
|
+
declared: boolean;
|
|
33
|
+
live: boolean;
|
|
34
|
+
})[];
|
|
26
35
|
private discoverInstance;
|
|
27
36
|
private waitForOperation;
|
|
28
37
|
deploy(): Promise<{
|
|
@@ -64,6 +64,26 @@ export class GCPCloudSQLBuilder extends BaseBuilder {
|
|
|
64
64
|
this.discoveryPromise = this.discoverInstance();
|
|
65
65
|
return this;
|
|
66
66
|
}
|
|
67
|
+
getDiff(existing) {
|
|
68
|
+
const diffs = [];
|
|
69
|
+
const declaredDbVersion = `${this._engine.toUpperCase()}_${this._engineVersion}`;
|
|
70
|
+
if (existing.databaseVersion !== declaredDbVersion) {
|
|
71
|
+
diffs.push({ field: "databaseVersion", declared: declaredDbVersion, live: existing.databaseVersion });
|
|
72
|
+
}
|
|
73
|
+
const liveTier = existing.settings?.tier;
|
|
74
|
+
if (liveTier !== undefined && liveTier !== this._tier) {
|
|
75
|
+
diffs.push({ field: "tier", declared: this._tier, live: liveTier });
|
|
76
|
+
}
|
|
77
|
+
const liveDiskSize = existing.settings?.dataDiskSizeGb;
|
|
78
|
+
if (liveDiskSize !== undefined && Number(liveDiskSize) !== this._storage) {
|
|
79
|
+
diffs.push({ field: "storage", declared: `${this._storage} GB`, live: `${liveDiskSize} GB` });
|
|
80
|
+
}
|
|
81
|
+
const isPublic = (existing.settings?.ipConfiguration?.authorizedNetworks ?? []).length > 0;
|
|
82
|
+
if (isPublic !== this._publicAccess) {
|
|
83
|
+
diffs.push({ field: "publicAccess", declared: this._publicAccess, live: isPublic });
|
|
84
|
+
}
|
|
85
|
+
return diffs;
|
|
86
|
+
}
|
|
67
87
|
async discoverInstance() {
|
|
68
88
|
try {
|
|
69
89
|
const project = getProjectId();
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { gcpFetch, getProjectId } from "./api.js";
|
|
2
2
|
export async function listGcpResources() {
|
|
3
3
|
const project = getProjectId();
|
|
4
|
-
const [vmRes, sqlRes, runRes, dnsRes] = await Promise.all([
|
|
4
|
+
const [vmRes, sqlRes, runRes, dnsRes, pubsubRes, secretsRes] = await Promise.all([
|
|
5
5
|
gcpFetch("https://compute.googleapis.com", `/compute/v1/projects/${project}/aggregated/instances`).catch(() => ({})),
|
|
6
6
|
gcpFetch("https://sqladmin.googleapis.com", `/v1/projects/${project}/instances`).catch(() => ({})),
|
|
7
7
|
gcpFetch("https://run.googleapis.com", `/v2/projects/${project}/locations/-/services`).catch(() => ({})),
|
|
8
8
|
gcpFetch("https://dns.googleapis.com", `/dns/v1/projects/${project}/managedZones`).catch(() => ({})),
|
|
9
|
+
gcpFetch("https://pubsub.googleapis.com", `/v1/projects/${project}/topics`).catch(() => ({})),
|
|
10
|
+
gcpFetch("https://secretmanager.googleapis.com", `/v1/projects/${project}/secrets`).catch(() => ({})),
|
|
9
11
|
]);
|
|
10
12
|
// 1. Map VM Instances
|
|
11
13
|
const vms = [];
|
|
@@ -51,5 +53,13 @@ export async function listGcpResources() {
|
|
|
51
53
|
name: z.name,
|
|
52
54
|
dnsName: z.dnsName ?? "",
|
|
53
55
|
}));
|
|
54
|
-
|
|
56
|
+
// 5. Map Pub/Sub Topics
|
|
57
|
+
const pubSubTopics = (pubsubRes.topics ?? []).map((t) => ({
|
|
58
|
+
name: t.name.split("/").pop() ?? t.name,
|
|
59
|
+
}));
|
|
60
|
+
// 6. Map Secret Manager Secrets
|
|
61
|
+
const secrets = (secretsRes.secrets ?? []).map((s) => ({
|
|
62
|
+
name: s.name.split("/").pop() ?? s.name,
|
|
63
|
+
}));
|
|
64
|
+
return { vms, rdsInstances, distributions, hostedZones, pubSubTopics, secrets };
|
|
55
65
|
}
|
|
@@ -28,6 +28,11 @@ export declare class GCPVMBuilder extends BaseBuilder {
|
|
|
28
28
|
private resolveUser;
|
|
29
29
|
provision(...playbookPaths: (string | string[])[]): this;
|
|
30
30
|
forceConfigCheck(): this;
|
|
31
|
+
getDiff(existing: any): {
|
|
32
|
+
field: string;
|
|
33
|
+
declared: string;
|
|
34
|
+
live: any;
|
|
35
|
+
}[];
|
|
31
36
|
protected checkPort(ip: string, port: number): Promise<boolean>;
|
|
32
37
|
protected runProvisioner(ip: string, script: string): Promise<void>;
|
|
33
38
|
private discoverVM;
|
package/dist/providers/gcp/vm.js
CHANGED
|
@@ -71,6 +71,14 @@ export class GCPVMBuilder extends BaseBuilder {
|
|
|
71
71
|
this._forceConfigCheck = true;
|
|
72
72
|
return this;
|
|
73
73
|
}
|
|
74
|
+
getDiff(existing) {
|
|
75
|
+
const diffs = [];
|
|
76
|
+
const liveMachineType = existing.machineType?.split("/").pop();
|
|
77
|
+
if (liveMachineType !== undefined && liveMachineType !== this._machineType) {
|
|
78
|
+
diffs.push({ field: "machineType", declared: this._machineType, live: liveMachineType });
|
|
79
|
+
}
|
|
80
|
+
return diffs;
|
|
81
|
+
}
|
|
74
82
|
async checkPort(ip, port) {
|
|
75
83
|
return checkPort(ip, port);
|
|
76
84
|
}
|
|
@@ -11,5 +11,12 @@ export async function listProxmoxVMs() {
|
|
|
11
11
|
maxmem: r.maxmem ?? 0,
|
|
12
12
|
maxdisk: r.maxdisk ?? 0,
|
|
13
13
|
}));
|
|
14
|
-
|
|
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
|
}
|
|
@@ -38,6 +38,19 @@ export declare class VMBuilder extends ProxmoxBaseBuilder {
|
|
|
38
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;
|
|
@@ -38,6 +38,9 @@ export class VMBuilder extends ProxmoxBaseBuilder {
|
|
|
38
38
|
try {
|
|
39
39
|
const config = await pm.get(`/nodes/${match.node}/qemu/${match.vmid}/config`);
|
|
40
40
|
match.description = config.description ?? "";
|
|
41
|
+
match.cfgCores = config.cores;
|
|
42
|
+
match.cfgMemory = config.memory;
|
|
43
|
+
match.cfgMachine = config.machine ?? "q35";
|
|
41
44
|
}
|
|
42
45
|
catch (err) {
|
|
43
46
|
console.warn(` ⚠️ Could not fetch VM config for ${match.vmid}: ${err.message}`);
|
|
@@ -105,6 +108,19 @@ export class VMBuilder extends ProxmoxBaseBuilder {
|
|
|
105
108
|
this._forceConfigCheck = true;
|
|
106
109
|
return this;
|
|
107
110
|
}
|
|
111
|
+
getDiff(existing) {
|
|
112
|
+
const diffs = [];
|
|
113
|
+
if (existing.cfgCores !== undefined && existing.cfgCores !== this._cores) {
|
|
114
|
+
diffs.push({ field: "cores", declared: this._cores, live: existing.cfgCores });
|
|
115
|
+
}
|
|
116
|
+
if (existing.cfgMemory !== undefined && existing.cfgMemory !== this._memory) {
|
|
117
|
+
diffs.push({ field: "memory", declared: `${this._memory} MB`, live: `${existing.cfgMemory} MB` });
|
|
118
|
+
}
|
|
119
|
+
if (existing.cfgMachine !== undefined && this._machine !== existing.cfgMachine) {
|
|
120
|
+
diffs.push({ field: "machine", declared: this._machine, live: existing.cfgMachine });
|
|
121
|
+
}
|
|
122
|
+
return diffs;
|
|
123
|
+
}
|
|
108
124
|
async deploy() {
|
|
109
125
|
try {
|
|
110
126
|
return await this._deploy();
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface FieldDiff {
|
|
2
|
+
field: string;
|
|
3
|
+
declared: any;
|
|
4
|
+
live: any;
|
|
5
|
+
}
|
|
6
|
+
export type ResourceStatus = "missing" | "in-sync" | "drift" | "adopted";
|
|
7
|
+
export interface ResourceDiff {
|
|
8
|
+
prop: string;
|
|
9
|
+
resource: string;
|
|
10
|
+
status: ResourceStatus;
|
|
11
|
+
changes: FieldDiff[];
|
|
12
|
+
}
|
|
13
|
+
export interface StackDiff {
|
|
14
|
+
stackName: string;
|
|
15
|
+
resources: ResourceDiff[];
|
|
16
|
+
hasDrift: boolean;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -6,8 +6,14 @@ export interface ProxmoxVm {
|
|
|
6
6
|
maxmem: number;
|
|
7
7
|
maxdisk: number;
|
|
8
8
|
}
|
|
9
|
+
export interface ProxmoxTemplate {
|
|
10
|
+
name: string;
|
|
11
|
+
vmid: number;
|
|
12
|
+
node: string;
|
|
13
|
+
}
|
|
9
14
|
export interface ProxmoxInventory {
|
|
10
15
|
vms: ProxmoxVm[];
|
|
16
|
+
templates: ProxmoxTemplate[];
|
|
11
17
|
}
|
|
12
18
|
export interface DoDroplet {
|
|
13
19
|
id: number;
|
|
@@ -34,11 +40,34 @@ export interface DoDomain {
|
|
|
34
40
|
name: string;
|
|
35
41
|
ttl: number;
|
|
36
42
|
}
|
|
43
|
+
export interface DoDatabase {
|
|
44
|
+
id: string;
|
|
45
|
+
name: string;
|
|
46
|
+
engine: string;
|
|
47
|
+
region: string;
|
|
48
|
+
status: string;
|
|
49
|
+
nodeCount: number;
|
|
50
|
+
}
|
|
51
|
+
export interface DoApp {
|
|
52
|
+
id: string;
|
|
53
|
+
name: string;
|
|
54
|
+
liveUrl: string;
|
|
55
|
+
status: string;
|
|
56
|
+
}
|
|
57
|
+
export interface DoVpc {
|
|
58
|
+
id: string;
|
|
59
|
+
name: string;
|
|
60
|
+
region: string;
|
|
61
|
+
ipRange: string;
|
|
62
|
+
}
|
|
37
63
|
export interface DoInventory {
|
|
38
64
|
droplets: DoDroplet[];
|
|
39
65
|
firewalls: DoFirewall[];
|
|
40
66
|
loadBalancers: DoLoadBalancer[];
|
|
41
67
|
domains: DoDomain[];
|
|
68
|
+
databases: DoDatabase[];
|
|
69
|
+
apps: DoApp[];
|
|
70
|
+
vpcs: DoVpc[];
|
|
42
71
|
totalMonthlyCost: number;
|
|
43
72
|
}
|
|
44
73
|
export interface AwsDistribution {
|
|
@@ -67,6 +96,13 @@ export interface AwsHostedZone {
|
|
|
67
96
|
id: string;
|
|
68
97
|
recordCount: number;
|
|
69
98
|
}
|
|
99
|
+
export interface AwsEc2Instance {
|
|
100
|
+
id: string;
|
|
101
|
+
name: string;
|
|
102
|
+
type: string;
|
|
103
|
+
state: string;
|
|
104
|
+
publicIp?: string;
|
|
105
|
+
}
|
|
70
106
|
export interface AwsInventory {
|
|
71
107
|
region: string;
|
|
72
108
|
distributions: AwsDistribution[];
|
|
@@ -74,6 +110,7 @@ export interface AwsInventory {
|
|
|
74
110
|
lambdas: AwsLambdaFn[];
|
|
75
111
|
rdsInstances: AwsRdsInstance[];
|
|
76
112
|
hostedZones: AwsHostedZone[];
|
|
113
|
+
ec2Instances: AwsEc2Instance[];
|
|
77
114
|
}
|
|
78
115
|
export interface GcpVM {
|
|
79
116
|
name: string;
|
|
@@ -97,11 +134,19 @@ export interface GcpCloudDNS {
|
|
|
97
134
|
name: string;
|
|
98
135
|
dnsName: string;
|
|
99
136
|
}
|
|
137
|
+
export interface GcpPubSubTopic {
|
|
138
|
+
name: string;
|
|
139
|
+
}
|
|
140
|
+
export interface GcpSecret {
|
|
141
|
+
name: string;
|
|
142
|
+
}
|
|
100
143
|
export interface GcpInventory {
|
|
101
144
|
vms: GcpVM[];
|
|
102
145
|
rdsInstances: GcpCloudSQL[];
|
|
103
146
|
distributions: GcpCloudRun[];
|
|
104
147
|
hostedZones: GcpCloudDNS[];
|
|
148
|
+
pubSubTopics: GcpPubSubTopic[];
|
|
149
|
+
secrets: GcpSecret[];
|
|
105
150
|
}
|
|
106
151
|
export interface FirebaseHosting {
|
|
107
152
|
site: string;
|
|
@@ -112,9 +157,29 @@ export interface FirebaseFunction {
|
|
|
112
157
|
entryPoint: string;
|
|
113
158
|
runtime: string;
|
|
114
159
|
}
|
|
160
|
+
export interface FirebaseFirestoreDb {
|
|
161
|
+
name: string;
|
|
162
|
+
type: string;
|
|
163
|
+
state: string;
|
|
164
|
+
}
|
|
165
|
+
export interface FirebaseStorageBucket {
|
|
166
|
+
name: string;
|
|
167
|
+
location: string;
|
|
168
|
+
}
|
|
169
|
+
export interface FirebaseAuthProvider {
|
|
170
|
+
providerId: string;
|
|
171
|
+
}
|
|
172
|
+
export interface FirebaseRemoteConfig {
|
|
173
|
+
parameterCount: number;
|
|
174
|
+
version: string;
|
|
175
|
+
}
|
|
115
176
|
export interface FirebaseInventory {
|
|
116
177
|
hostingSites: FirebaseHosting[];
|
|
117
178
|
functions: FirebaseFunction[];
|
|
179
|
+
firestoreDbs: FirebaseFirestoreDb[];
|
|
180
|
+
storageBuckets: FirebaseStorageBucket[];
|
|
181
|
+
authProviders: FirebaseAuthProvider[];
|
|
182
|
+
remoteConfig?: FirebaseRemoteConfig;
|
|
118
183
|
}
|
|
119
184
|
export interface InventoryError {
|
|
120
185
|
provider: "proxmox" | "do" | "aws" | "gcp" | "firebase";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "puls-dev",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"description": "Intent-driven infrastructure-as-code with eager discovery and no state files.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@types/node": "^25.6.2",
|
|
62
62
|
"ts-node": "^10.9.2",
|
|
63
|
-
"tsx": "^4.
|
|
63
|
+
"tsx": "^4.22.4",
|
|
64
64
|
"typescript": "^6.0.3"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|