@fnndsc/stratus 0.0.0 → 0.2.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.
Files changed (134) hide show
  1. package/README.md +6 -1
  2. package/dist/args.d.ts +20 -6
  3. package/dist/args.js +45 -2
  4. package/dist/args.js.map +1 -1
  5. package/dist/backend.d.ts +35 -4
  6. package/dist/backend.js +77 -12
  7. package/dist/backend.js.map +1 -1
  8. package/dist/cloud/builder.d.ts +172 -0
  9. package/dist/cloud/builder.js +41 -0
  10. package/dist/cloud/builder.js.map +1 -0
  11. package/dist/cloud/driver.d.ts +149 -0
  12. package/dist/cloud/fake/builder.d.ts +147 -0
  13. package/dist/cloud/fake/builder.js +213 -0
  14. package/dist/cloud/fake/builder.js.map +1 -0
  15. package/dist/cloud/fake/driver.d.ts +73 -1
  16. package/dist/cloud/fake/driver.js +122 -0
  17. package/dist/cloud/fake/driver.js.map +1 -1
  18. package/dist/cloud/oci/api.d.ts +3 -2
  19. package/dist/cloud/oci/api.js +2 -0
  20. package/dist/cloud/oci/api.js.map +1 -1
  21. package/dist/cloud/oci/buildApi.d.ts +61 -0
  22. package/dist/cloud/oci/buildApi.js +132 -0
  23. package/dist/cloud/oci/buildApi.js.map +1 -0
  24. package/dist/cloud/oci/builder.d.ts +172 -0
  25. package/dist/cloud/oci/builder.js +370 -0
  26. package/dist/cloud/oci/builder.js.map +1 -0
  27. package/dist/cloud/oci/driver.d.ts +23 -2
  28. package/dist/cloud/oci/driver.js +107 -1
  29. package/dist/cloud/oci/driver.js.map +1 -1
  30. package/dist/cloud/oci/planRead.d.ts +38 -0
  31. package/dist/cloud/oci/planRead.js +67 -0
  32. package/dist/cloud/oci/planRead.js.map +1 -0
  33. package/dist/cloud/oci/prices.d.ts +22 -1
  34. package/dist/cloud/oci/prices.js +35 -0
  35. package/dist/cloud/oci/prices.js.map +1 -1
  36. package/dist/cloud/oci/resourceApi.d.ts +114 -0
  37. package/dist/cloud/oci/resourceApi.js +261 -0
  38. package/dist/cloud/oci/resourceApi.js.map +1 -0
  39. package/dist/cloud/oci/resourceMap.d.ts +44 -0
  40. package/dist/cloud/oci/resourceMap.js +70 -0
  41. package/dist/cloud/oci/resourceMap.js.map +1 -0
  42. package/dist/cloud/oci/rmApi.d.ts +74 -0
  43. package/dist/cloud/oci/rmApi.js +141 -0
  44. package/dist/cloud/oci/rmApi.js.map +1 -0
  45. package/dist/cloud/oci/stackVars.d.ts +49 -0
  46. package/dist/cloud/oci/stackVars.js +70 -0
  47. package/dist/cloud/oci/stackVars.js.map +1 -0
  48. package/dist/cluster/fakeKube.d.ts +43 -0
  49. package/dist/cluster/fakeKube.js +86 -0
  50. package/dist/cluster/fakeKube.js.map +1 -0
  51. package/dist/cluster/kube.d.ts +40 -0
  52. package/dist/cluster/kube.js +46 -0
  53. package/dist/cluster/kube.js.map +1 -0
  54. package/dist/cluster/kubeHttp.d.ts +16 -0
  55. package/dist/cluster/kubeHttp.js +86 -0
  56. package/dist/cluster/kubeHttp.js.map +1 -0
  57. package/dist/commands/build.d.ts +90 -0
  58. package/dist/commands/build.js +358 -0
  59. package/dist/commands/build.js.map +1 -0
  60. package/dist/commands/capacity.d.ts +37 -0
  61. package/dist/commands/capacity.js +93 -0
  62. package/dist/commands/capacity.js.map +1 -0
  63. package/dist/commands/domain.d.ts +45 -0
  64. package/dist/commands/domain.js +150 -0
  65. package/dist/commands/domain.js.map +1 -0
  66. package/dist/commands/spend.d.ts +22 -0
  67. package/dist/commands/spend.js +65 -0
  68. package/dist/commands/spend.js.map +1 -0
  69. package/dist/commands/teardown.d.ts +10 -0
  70. package/dist/commands/teardown.js +72 -0
  71. package/dist/commands/teardown.js.map +1 -0
  72. package/dist/commands/verify.d.ts +28 -0
  73. package/dist/commands/verify.js +98 -0
  74. package/dist/commands/verify.js.map +1 -0
  75. package/dist/domain/adopt.d.ts +60 -0
  76. package/dist/domain/adopt.js +143 -0
  77. package/dist/domain/adopt.js.map +1 -0
  78. package/dist/domain/sizing.d.ts +55 -0
  79. package/dist/domain/sizing.js +66 -0
  80. package/dist/domain/sizing.js.map +1 -0
  81. package/dist/domain/spec.d.ts +101 -0
  82. package/dist/domain/spec.js +191 -0
  83. package/dist/domain/spec.js.map +1 -0
  84. package/dist/domain/spend.d.ts +84 -0
  85. package/dist/domain/spend.js +109 -0
  86. package/dist/domain/spend.js.map +1 -0
  87. package/dist/domain/state.d.ts +149 -0
  88. package/dist/domain/state.js +182 -0
  89. package/dist/domain/state.js.map +1 -0
  90. package/dist/domain/steps.d.ts +82 -0
  91. package/dist/domain/steps.js +311 -0
  92. package/dist/domain/steps.js.map +1 -0
  93. package/dist/domain/teardown.d.ts +38 -0
  94. package/dist/domain/teardown.js +48 -0
  95. package/dist/domain/teardown.js.map +1 -0
  96. package/dist/domain/verify.d.ts +68 -0
  97. package/dist/domain/verify.js +216 -0
  98. package/dist/domain/verify.js.map +1 -0
  99. package/dist/domain/view.d.ts +24 -0
  100. package/dist/domain/view.js +38 -0
  101. package/dist/domain/view.js.map +1 -0
  102. package/dist/domains/harborOci.d.ts +75 -0
  103. package/dist/domains/harborOci.js +165 -0
  104. package/dist/domains/harborOci.js.map +1 -0
  105. package/dist/index.d.ts +7 -0
  106. package/dist/index.js +6 -0
  107. package/dist/index.js.map +1 -1
  108. package/dist/installer/assisted.d.ts +97 -0
  109. package/dist/installer/assisted.js +171 -0
  110. package/dist/installer/assisted.js.map +1 -0
  111. package/dist/installer/installer.d.ts +86 -0
  112. package/dist/installer/installer.js +15 -0
  113. package/dist/installer/installer.js.map +1 -0
  114. package/dist/prompt.d.ts +33 -0
  115. package/dist/prompt.js +46 -0
  116. package/dist/prompt.js.map +1 -0
  117. package/dist/session.d.ts +2 -0
  118. package/dist/session.js +4 -0
  119. package/dist/session.js.map +1 -1
  120. package/dist/stratus.js +75 -3
  121. package/dist/stratus.js.map +1 -1
  122. package/dist/vfs/domains.d.ts +39 -0
  123. package/dist/vfs/domains.js +128 -0
  124. package/dist/vfs/domains.js.map +1 -0
  125. package/dist/vfs/look.d.ts +10 -0
  126. package/dist/vfs/look.js +43 -8
  127. package/dist/vfs/look.js.map +1 -1
  128. package/dist/vfs/resources.d.ts +136 -0
  129. package/dist/vfs/resources.js +325 -0
  130. package/dist/vfs/resources.js.map +1 -0
  131. package/dist/vfs/tenancy.d.ts +15 -2
  132. package/dist/vfs/tenancy.js +53 -17
  133. package/dist/vfs/tenancy.js.map +1 -1
  134. package/package.json +14 -7
@@ -95,6 +95,8 @@ export interface CloudShape {
95
95
  readonly gpus: number;
96
96
  /** The limit names the shape draws on. */
97
97
  readonly quotaNames: ReadonlyArray<string>;
98
+ /** The limit service those names belong to (OCI: `compute`). */
99
+ readonly limitService: string;
98
100
  /** The whole record, for `info.json`. */
99
101
  readonly raw: unknown;
100
102
  }
@@ -109,6 +111,125 @@ export interface CloudPrice {
109
111
  /** The currency code. */
110
112
  readonly currency: string;
111
113
  }
114
+ /**
115
+ * What storage and load balancing cost, per the price list.
116
+ *
117
+ * @property volumeGibMonth - A GiB of block or boot volume, a month.
118
+ * @property vpuGibMonth - A volume performance unit on a GiB, a month.
119
+ * @property balancerHour - A flexible load balancer, an hour, before bandwidth.
120
+ * @property balancerMbpsHour - A megabit per second of its minimum bandwidth, an hour.
121
+ */
122
+ export interface ServicePrices {
123
+ readonly volumeGibMonth: number;
124
+ readonly vpuGibMonth: number;
125
+ readonly balancerHour: number;
126
+ readonly balancerMbpsHour: number;
127
+ readonly currency: string;
128
+ }
129
+ /**
130
+ * The resource kinds every cloud has, as the tree's folder names
131
+ * (docs/stratus.adoc, D4). Subnets and security groups nest under their
132
+ * network; the rest stand at a container's level.
133
+ */
134
+ export type ResourceKind = 'instances' | 'networks' | 'subnets' | 'securitygroups' | 'loadbalancers' | 'volumes' | 'buckets' | 'dns';
135
+ /** What every resource row carries: the fields every kind has. */
136
+ export interface CloudResource {
137
+ /** Its display name; the path segment. */
138
+ readonly name: string;
139
+ /** Its id (an OCID). */
140
+ readonly id: string;
141
+ /** Its lifecycle state, lower case (`running`, `available`). */
142
+ readonly state: string;
143
+ /** The region it lives in; for a global kind, the region it was asked in. */
144
+ readonly region: string;
145
+ /** When it was made, ISO 8601, or empty when the cloud does not say. */
146
+ readonly created: string;
147
+ /** Its tags, flattened: freeform as `key`, defined as `namespace.key`. */
148
+ readonly tags: Readonly<Record<string, string>>;
149
+ /** The whole record, for `info.json`. */
150
+ readonly raw: unknown;
151
+ }
152
+ /** A machine. */
153
+ export interface CloudInstance extends CloudResource {
154
+ /** The cloud's shape name. */
155
+ readonly shape: string;
156
+ /** The zone it runs in. */
157
+ readonly zone: string;
158
+ /** Its addresses, private first. */
159
+ readonly ips: ReadonlyArray<string>;
160
+ /** Its vCPUs and memory, when the cloud says. */
161
+ readonly vcpus?: number;
162
+ readonly memoryGib?: number;
163
+ }
164
+ /** A private network: a VCN, a VPC. */
165
+ export type CloudNetwork = CloudResource;
166
+ /** A subnet, inside a network. */
167
+ export interface CloudSubnet extends CloudResource {
168
+ /** The network it belongs to. */
169
+ readonly networkId: string;
170
+ }
171
+ /** A security group (OCI: a network security group), inside a network. */
172
+ export interface CloudSecurityGroup extends CloudResource {
173
+ /** The network it belongs to. */
174
+ readonly networkId: string;
175
+ }
176
+ /** A load balancer. */
177
+ export interface CloudLoadBalancer extends CloudResource {
178
+ /** Its addresses. */
179
+ readonly ips: ReadonlyArray<string>;
180
+ /** The cloud's shape name (`flexible`). */
181
+ readonly shape: string;
182
+ /** A flexible shape's minimum bandwidth, what it bills by. */
183
+ readonly minimumMbps?: number;
184
+ }
185
+ /** A block volume or a boot volume. */
186
+ export interface CloudVolume extends CloudResource {
187
+ /** Its size in GiB. */
188
+ readonly sizeGib: number;
189
+ /** The id of the instance it is attached to, or null. */
190
+ readonly attachedTo: string | null;
191
+ /** Whether it is an instance's boot volume. */
192
+ readonly boot: boolean;
193
+ /** Its performance, in volume performance units per GiB. */
194
+ readonly vpusPerGib?: number;
195
+ }
196
+ /** An object-storage bucket. */
197
+ export type CloudBucket = CloudResource;
198
+ /** One object in a bucket. */
199
+ export interface CloudObject {
200
+ /** Its name; may hold `/`, which the tree keeps flat. */
201
+ readonly name: string;
202
+ /** Its size in bytes. */
203
+ readonly size: number;
204
+ /** When it last changed, ISO 8601, or empty. */
205
+ readonly modified: string;
206
+ }
207
+ /** A pre-authenticated link to a bucket or one of its objects. */
208
+ export interface CloudLink {
209
+ /** The object it opens, or null for the whole bucket. */
210
+ readonly object: string | null;
211
+ /** Its name. */
212
+ readonly name: string;
213
+ /** What it allows (`ObjectRead`). */
214
+ readonly access: string;
215
+ /** When it stops working, ISO 8601. */
216
+ readonly expires: string;
217
+ }
218
+ /** A DNS zone. */
219
+ export type CloudDnsZone = CloudResource;
220
+ /** One DNS record. */
221
+ export interface CloudRecord {
222
+ /** The fully qualified name it answers for. */
223
+ readonly domain: string;
224
+ /** Its type (`A`, `CNAME`). */
225
+ readonly type: string;
226
+ /** Its time to live, in seconds. */
227
+ readonly ttl: number;
228
+ /** Its data, as a zone file writes it. */
229
+ readonly data: string;
230
+ }
231
+ /** How many of each kind a container holds in a region, as a search counts them. */
232
+ export type ResourceCounts = Readonly<Partial<Record<ResourceKind, number>>>;
112
233
  /**
113
234
  * A cloud, as stratus sees it. Every method answers for the region it is
114
235
  * given: the region is the session's, not the driver's (docs/stratus.adoc,
@@ -137,4 +258,32 @@ export interface CloudDriver {
137
258
  shapes_list(region: string): Promise<CloudShape[]>;
138
259
  /** List prices for the shapes, per hour. */
139
260
  prices_list(): Promise<CloudPrice[]>;
261
+ /** What storage and load balancing cost; null when the list does not say. */
262
+ servicePrices_get(): Promise<ServicePrices | null>;
263
+ /** The machines in a container, in a region. */
264
+ instances_list(containerId: string, region: string): Promise<CloudInstance[]>;
265
+ /** The private networks in a container, in a region. */
266
+ networks_list(containerId: string, region: string): Promise<CloudNetwork[]>;
267
+ /** The subnets in a container, in a region, each naming its network. */
268
+ subnets_list(containerId: string, region: string): Promise<CloudSubnet[]>;
269
+ /** The security groups in a container, in a region, each naming its network. */
270
+ securitygroups_list(containerId: string, region: string): Promise<CloudSecurityGroup[]>;
271
+ /** The load balancers in a container, in a region. */
272
+ loadbalancers_list(containerId: string, region: string): Promise<CloudLoadBalancer[]>;
273
+ /** The block and boot volumes in a container, in a region. */
274
+ volumes_list(containerId: string, region: string): Promise<CloudVolume[]>;
275
+ /** The buckets in a container, in a region. */
276
+ buckets_list(containerId: string, region: string): Promise<CloudBucket[]>;
277
+ /** The DNS zones in a container, public and private. */
278
+ dns_list(containerId: string, region: string): Promise<CloudDnsZone[]>;
279
+ /** A bucket's objects, every page. */
280
+ objects_list(bucket: string, region: string): Promise<CloudObject[]>;
281
+ /** A bucket's pre-authenticated links. */
282
+ links_list(bucket: string, region: string): Promise<CloudLink[]>;
283
+ /** One object's bytes. */
284
+ object_read(bucket: string, object: string, region: string): Promise<Buffer>;
285
+ /** A zone's records. */
286
+ records_list(zoneId: string, region: string): Promise<CloudRecord[]>;
287
+ /** How many of each kind a container holds in a region, in one search; live resources only. */
288
+ resources_search(containerId: string, region: string): Promise<ResourceCounts>;
140
289
  }
@@ -0,0 +1,147 @@
1
+ /**
2
+ * @file The fake cloud's build half and the fake installer, over one small
3
+ * world they share: an apply boots the machines, which register with the
4
+ * installer a moment later, and the install runs on a clock. Every wait is a
5
+ * tick (none in tests), so `stratus --fake` shows a build moving.
6
+ *
7
+ * @module
8
+ */
9
+ import type { DomainSpec } from '../../domain/spec.js';
10
+ import { type SpecNode } from '../../domain/spec.js';
11
+ import type { Installer, InstallerCredentials, InstallerHost, InstallerIds, InstallStatus, PlatformManifest } from '../../installer/installer.js';
12
+ import type { BuildCall, CloudBuilder, InfraOutputs, InfraPlan, PreflightCheck, TeardownRequest } from '../builder.js';
13
+ /** What the fake world keeps of one cluster. */
14
+ interface FakeCluster {
15
+ name: string;
16
+ hosts: InstallerHost[];
17
+ /** When each booted machine registers, epoch ms. */
18
+ pending: Array<{
19
+ host: InstallerHost;
20
+ at: number;
21
+ }>;
22
+ installStarted?: number;
23
+ }
24
+ /**
25
+ * The world the fake builder and installer share.
26
+ *
27
+ * @property tickMs - How long one tick of fake work takes.
28
+ */
29
+ export declare class FakeBuildWorld {
30
+ readonly tickMs: number;
31
+ private readonly clusters;
32
+ private serial;
33
+ constructor(tickMs?: number);
34
+ /**
35
+ * Waits one tick, or several, unless stopped.
36
+ *
37
+ * @param ticks - How many.
38
+ * @param signal - Stops the wait early.
39
+ */
40
+ tick(ticks?: number, signal?: AbortSignal): Promise<void>;
41
+ /** A new id of a kind. */
42
+ id_next(kind: string): string;
43
+ /** A cluster by name, made when first asked for. */
44
+ cluster_of(name: string): FakeCluster;
45
+ /**
46
+ * Boots a domain's machines: each registers with the installer a few ticks apart.
47
+ *
48
+ * @param domain - The domain.
49
+ * @param nodes - Its machines.
50
+ */
51
+ machines_boot(domain: string, nodes: ReadonlyArray<SpecNode>): void;
52
+ /**
53
+ * The hosts registered by now.
54
+ *
55
+ * @param domain - The domain.
56
+ * @returns The hosts.
57
+ */
58
+ hosts_now(domain: string): InstallerHost[];
59
+ }
60
+ /** The fake cloud's build half. */
61
+ export declare class FakeCloudBuilder implements CloudBuilder {
62
+ private readonly world;
63
+ readonly id: string;
64
+ constructor(world: FakeBuildWorld);
65
+ preflight(request: {
66
+ domain: string;
67
+ spec: DomainSpec;
68
+ region: string;
69
+ baseDomain: string;
70
+ compartmentId: string;
71
+ }, call: BuildCall): Promise<PreflightCheck[]>;
72
+ iso_store(request: {
73
+ domain: string;
74
+ url: string;
75
+ region: string;
76
+ compartmentId: string;
77
+ }, call: BuildCall): Promise<{
78
+ object: string;
79
+ expires: string;
80
+ link: string;
81
+ linkId: string;
82
+ }>;
83
+ infra_plan(request: {
84
+ domain: string;
85
+ spec: DomainSpec;
86
+ region: string;
87
+ isoObject: string;
88
+ stackRef?: string;
89
+ compartmentId?: string;
90
+ baseDomain?: string;
91
+ isoLink?: string;
92
+ }, call: BuildCall): Promise<InfraPlan>;
93
+ infra_apply(request: {
94
+ domain: string;
95
+ plan: InfraPlan;
96
+ region: string;
97
+ stackRef?: string;
98
+ }, call: BuildCall): Promise<InfraOutputs>;
99
+ dns_upsert(request: {
100
+ domain: string;
101
+ baseDomain: string;
102
+ outputs: InfraOutputs;
103
+ compartmentId: string;
104
+ region: string;
105
+ }, call: BuildCall): Promise<string[]>;
106
+ stackResources_count(_request: {
107
+ region: string;
108
+ stackRef: string;
109
+ }): Promise<number>;
110
+ teardown_run(request: TeardownRequest, call: BuildCall): Promise<string[]>;
111
+ stack_adopt(request: {
112
+ domain: string;
113
+ region: string;
114
+ compartmentId: string;
115
+ variables: Record<string, string>;
116
+ state: Buffer;
117
+ stackVersion: string;
118
+ }, call: BuildCall): Promise<string>;
119
+ }
120
+ /** The fake installer. */
121
+ export declare class FakeInstaller implements Installer {
122
+ private readonly world;
123
+ private readonly installTicks;
124
+ readonly id: string;
125
+ private readonly roles;
126
+ readonly deleted: string[];
127
+ constructor(world: FakeBuildWorld, installTicks?: number);
128
+ cluster_create(request: {
129
+ name: string;
130
+ baseDomain: string;
131
+ version: string;
132
+ controlPlaneCount: number;
133
+ }): Promise<InstallerIds>;
134
+ isoUrl_get(ids: InstallerIds): Promise<{
135
+ url: string;
136
+ expires: string;
137
+ }>;
138
+ manifests_upload(_ids: InstallerIds, _manifests: ReadonlyArray<PlatformManifest>): Promise<void>;
139
+ hosts_list(ids: InstallerIds): Promise<InstallerHost[]>;
140
+ role_set(_ids: InstallerIds, host: InstallerHost, role: 'master' | 'worker'): Promise<void>;
141
+ install_start(ids: InstallerIds): Promise<void>;
142
+ install_status(ids: InstallerIds): Promise<InstallStatus>;
143
+ kubeconfig_get(ids: InstallerIds): Promise<string>;
144
+ credentials_get(ids: InstallerIds): Promise<InstallerCredentials>;
145
+ cluster_delete(ids: InstallerIds): Promise<void>;
146
+ }
147
+ export {};
@@ -0,0 +1,213 @@
1
+ import { specNodes_of } from '../../domain/spec.js';
2
+ /** The zones the fake region has, as the fake driver names them. */
3
+ const FAKE_ZONES = ['AD-1', 'AD-2', 'AD-3'];
4
+ /**
5
+ * The world the fake builder and installer share.
6
+ *
7
+ * @property tickMs - How long one tick of fake work takes.
8
+ */
9
+ export class FakeBuildWorld {
10
+ tickMs;
11
+ clusters = new Map();
12
+ serial = 0;
13
+ constructor(tickMs = 0) {
14
+ this.tickMs = tickMs;
15
+ }
16
+ /**
17
+ * Waits one tick, or several, unless stopped.
18
+ *
19
+ * @param ticks - How many.
20
+ * @param signal - Stops the wait early.
21
+ */
22
+ async tick(ticks = 1, signal) {
23
+ if (this.tickMs <= 0 || signal?.aborted === true)
24
+ return;
25
+ await new Promise((resolve) => {
26
+ const timer = setTimeout(resolve, this.tickMs * ticks);
27
+ signal?.addEventListener('abort', () => { clearTimeout(timer); resolve(); }, { once: true });
28
+ });
29
+ }
30
+ /** A new id of a kind. */
31
+ id_next(kind) {
32
+ this.serial++;
33
+ return `fake-${kind}-${this.serial}`;
34
+ }
35
+ /** A cluster by name, made when first asked for. */
36
+ cluster_of(name) {
37
+ let cluster = this.clusters.get(name);
38
+ if (cluster === undefined) {
39
+ cluster = { name, hosts: [], pending: [] };
40
+ this.clusters.set(name, cluster);
41
+ }
42
+ return cluster;
43
+ }
44
+ /**
45
+ * Boots a domain's machines: each registers with the installer a few ticks apart.
46
+ *
47
+ * @param domain - The domain.
48
+ * @param nodes - Its machines.
49
+ */
50
+ machines_boot(domain, nodes) {
51
+ const cluster = this.cluster_of(domain);
52
+ const now = Date.now();
53
+ cluster.pending = nodes.map((node, index) => ({
54
+ host: { id: `host-${node.name}`, name: node.name, zone: FAKE_ZONES[node.zoneIndex] ?? 'AD-1', role: 'auto', registered: '', ready: true },
55
+ at: now + this.tickMs * (2 + index),
56
+ }));
57
+ }
58
+ /**
59
+ * The hosts registered by now.
60
+ *
61
+ * @param domain - The domain.
62
+ * @returns The hosts.
63
+ */
64
+ hosts_now(domain) {
65
+ const cluster = this.cluster_of(domain);
66
+ const now = Date.now();
67
+ for (const entry of cluster.pending.filter((p) => p.at <= now)) {
68
+ cluster.hosts.push({ ...entry.host, registered: new Date(entry.at).toISOString() });
69
+ }
70
+ cluster.pending = cluster.pending.filter((p) => p.at > now);
71
+ return cluster.hosts.map((host) => ({ ...host }));
72
+ }
73
+ }
74
+ /** The fake cloud's build half. */
75
+ export class FakeCloudBuilder {
76
+ world;
77
+ id = 'fake';
78
+ constructor(world) {
79
+ this.world = world;
80
+ }
81
+ async preflight(request, call) {
82
+ await this.world.tick(1, call.signal);
83
+ const checks = [
84
+ { name: 'credential', ok: true, note: 'the fake key answers' },
85
+ { name: 'tag namespace', ok: true, note: 'mise-domain exists' },
86
+ { name: 'load balancers', ok: true, note: '3 needed, 7 free' },
87
+ { name: 'zone', ok: true, note: `${request.baseDomain} answers` },
88
+ ];
89
+ for (const check of checks)
90
+ call.log(`${check.ok ? 'ok' : 'NO'} ${check.name}: ${check.note}`);
91
+ return checks;
92
+ }
93
+ async iso_store(request, call) {
94
+ await this.world.tick(2, call.signal);
95
+ const object = `${request.domain}-discovery.iso`;
96
+ call.log(`stored ${object} in stratus-iso, linked for 7 days`);
97
+ return { object, expires: new Date(Date.now() + 7 * 24 * 3600 * 1000).toISOString(), link: `https://objectstorage.example/p/fake/${object}`, linkId: this.world.id_next('link') };
98
+ }
99
+ async infra_plan(request, call) {
100
+ await this.world.tick(3, call.signal);
101
+ if (request.stackRef !== undefined) {
102
+ // A built stack re-planned: nothing to make, OCI's own tags to strip.
103
+ const drift = specNodes_of(request.domain, request.spec, FAKE_ZONES.length).map((node) => ({ action: 'change', kind: 'instances', name: node.name, drift: true }));
104
+ call.log(`plan job done: 0 to create, ${drift.length} to change, 0 to destroy`);
105
+ return { ref: this.world.id_next('plan'), rows: drift };
106
+ }
107
+ const nodes = specNodes_of(request.domain, request.spec, FAKE_ZONES.length);
108
+ const create = (kind, name) => ({ action: 'create', kind, name });
109
+ const rows = [
110
+ ...nodes.map((node) => create('instances', node.name)),
111
+ ...nodes.map((node) => create('volumes', `${node.name}-boot`)),
112
+ create('loadbalancers', `${request.domain}-api`), create('loadbalancers', `${request.domain}-api-int`), create('loadbalancers', `${request.domain}-apps`),
113
+ create('networks', `${request.domain}-vcn`),
114
+ create('subnets', 'private'), create('subnets', 'private-ocp'), create('subnets', 'public'),
115
+ create('securitygroups', 'cluster-lb'), create('securitygroups', 'cluster-controlplane'), create('securitygroups', 'cluster-compute'),
116
+ create('image', `${request.domain}-discovery`),
117
+ ];
118
+ call.log(`plan job done: ${rows.length} to create, 0 to change, 0 to destroy`);
119
+ return { ref: this.world.id_next('plan'), rows, stackRef: this.world.id_next('stack') };
120
+ }
121
+ async infra_apply(request, call) {
122
+ for (let i = 0; i < 4 && call.signal.aborted !== true; i++) {
123
+ await this.world.tick(1, call.signal);
124
+ call.log(`apply job: ${Math.round(((i + 1) / 4) * request.plan.rows.length)} of ${request.plan.rows.length} created`);
125
+ }
126
+ const nodes = request.plan.rows
127
+ .filter((row) => row.kind === 'instances')
128
+ .map((row, index) => ({ name: row.name, role: row.name.includes('-cp-') ? 'plane' : 'worker', vcpu: 0, ramGib: 0, zoneIndex: index % FAKE_ZONES.length }));
129
+ this.world.machines_boot(request.domain, nodes);
130
+ return {
131
+ apiIp: '10.0.0.10', apiIntIp: '10.0.0.11', appsIp: '10.0.0.12', stackRef: request.stackRef ?? request.plan.stackRef ?? this.world.id_next('stack'),
132
+ manifests: [{ name: 'oci-dynamic-custom-manifest.yml', content: '# the fake cloud controller and CSI driver\n' }],
133
+ };
134
+ }
135
+ async dns_upsert(request, call) {
136
+ await this.world.tick(1, call.signal);
137
+ const names = [`api.${request.domain}.${request.baseDomain}`, `api-int.${request.domain}.${request.baseDomain}`, `*.apps.${request.domain}.${request.baseDomain}`];
138
+ call.log(`upserted ${names.join(', ')}`);
139
+ return names;
140
+ }
141
+ async stackResources_count(_request) {
142
+ return 17;
143
+ }
144
+ async teardown_run(request, call) {
145
+ await this.world.tick(4, call.signal);
146
+ const gone = [];
147
+ if (request.stackRef !== undefined)
148
+ gone.push(`the stack's resources (${request.stackRef})`);
149
+ gone.push('3 DNS records');
150
+ if (request.isoObject !== undefined)
151
+ gone.push(`the image ${request.isoObject} and its link`);
152
+ if (request.volumeIds.length > 0)
153
+ gone.push(`${request.volumeIds.length} volumes the cluster made`);
154
+ for (const line of gone)
155
+ call.log(`removed ${line}`);
156
+ return gone;
157
+ }
158
+ async stack_adopt(request, call) {
159
+ await this.world.tick(2, call.signal);
160
+ call.log(`stack made for ${request.domain} with ${Object.keys(request.variables).length} variables; ${request.state.length} bytes of state imported`);
161
+ return this.world.id_next('stack');
162
+ }
163
+ }
164
+ /** The fake installer. */
165
+ export class FakeInstaller {
166
+ world;
167
+ installTicks;
168
+ id = 'fake';
169
+ roles = new Map();
170
+ deleted = [];
171
+ constructor(world, installTicks = 6) {
172
+ this.world = world;
173
+ this.installTicks = installTicks;
174
+ }
175
+ async cluster_create(request) {
176
+ await this.world.tick(1);
177
+ this.world.cluster_of(request.name);
178
+ return { clusterId: `cluster-${request.name}`, infraEnvId: `infraenv-${request.name}` };
179
+ }
180
+ async isoUrl_get(ids) {
181
+ return { url: `https://installer.example/${ids.infraEnvId}/discovery.iso`, expires: new Date(Date.now() + 7 * 24 * 3600 * 1000).toISOString() };
182
+ }
183
+ async manifests_upload(_ids, _manifests) {
184
+ await this.world.tick(1);
185
+ }
186
+ async hosts_list(ids) {
187
+ return this.world.hosts_now(ids.clusterId.replace(/^cluster-/, '')).map((host) => ({ ...host, role: this.roles.get(host.name) ?? host.role }));
188
+ }
189
+ async role_set(_ids, host, role) {
190
+ this.roles.set(host.name, role);
191
+ }
192
+ async install_start(ids) {
193
+ this.world.cluster_of(ids.clusterId.replace(/^cluster-/, '')).installStarted = Date.now();
194
+ }
195
+ async install_status(ids) {
196
+ const started = this.world.cluster_of(ids.clusterId.replace(/^cluster-/, '')).installStarted;
197
+ if (started === undefined)
198
+ return { state: 'ready', percent: 0, note: 'ready to install' };
199
+ const span = Math.max(this.world.tickMs * this.installTicks, 1);
200
+ const percent = this.world.tickMs <= 0 ? 100 : Math.min(100, Math.round(((Date.now() - started) / span) * 100));
201
+ return percent >= 100 ? { state: 'installed', percent: 100, note: 'installed' } : { state: 'installing', percent, note: percent < 50 ? 'writing the image to disk' : 'waiting for the control plane' };
202
+ }
203
+ async kubeconfig_get(ids) {
204
+ return `# the fake cluster ${ids.clusterId}'s kubeconfig\napiVersion: v1\nkind: Config\n`;
205
+ }
206
+ async credentials_get(ids) {
207
+ return { username: 'kubeadmin', password: 'fake-password', consoleUrl: `https://console.apps.${ids.clusterId}.fake.example` };
208
+ }
209
+ async cluster_delete(ids) {
210
+ this.deleted.push(ids.clusterId);
211
+ }
212
+ }
213
+ //# sourceMappingURL=builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builder.js","sourceRoot":"","sources":["../../../src/cloud/fake/builder.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,41 @@
7
7
  *
8
8
  * @module
9
9
  */
10
- import type { CloudAvailability, CloudContainer, CloudDriver, CloudIdentity, CloudLimit, CloudPrice, CloudShape, CloudZone } from '../driver.js';
10
+ import type { CloudAvailability, CloudBucket, CloudContainer, CloudDnsZone, CloudDriver, CloudIdentity, CloudInstance, CloudLimit, CloudLink, CloudLoadBalancer, CloudNetwork, CloudObject, CloudPrice, ServicePrices, CloudRecord, CloudSecurityGroup, CloudShape, CloudSubnet, CloudVolume, CloudZone, ResourceCounts } from '../driver.js';
11
+ /** A resource in the fake cloud: its kind, the container holding it, and its record. */
12
+ export type FakeResource = {
13
+ readonly kind: 'instances';
14
+ readonly containerId: string;
15
+ readonly record: CloudInstance;
16
+ } | {
17
+ readonly kind: 'networks';
18
+ readonly containerId: string;
19
+ readonly record: CloudNetwork;
20
+ } | {
21
+ readonly kind: 'subnets';
22
+ readonly containerId: string;
23
+ readonly record: CloudSubnet;
24
+ } | {
25
+ readonly kind: 'securitygroups';
26
+ readonly containerId: string;
27
+ readonly record: CloudSecurityGroup;
28
+ } | {
29
+ readonly kind: 'loadbalancers';
30
+ readonly containerId: string;
31
+ readonly record: CloudLoadBalancer;
32
+ } | {
33
+ readonly kind: 'volumes';
34
+ readonly containerId: string;
35
+ readonly record: CloudVolume;
36
+ } | {
37
+ readonly kind: 'buckets';
38
+ readonly containerId: string;
39
+ readonly record: CloudBucket;
40
+ } | {
41
+ readonly kind: 'dns';
42
+ readonly containerId: string;
43
+ readonly record: CloudDnsZone;
44
+ };
11
45
  /** What a fake cloud holds. */
12
46
  export interface FakeCloud {
13
47
  readonly identity: CloudIdentity;
@@ -23,6 +57,18 @@ export interface FakeCloud {
23
57
  /** Shapes by region. */
24
58
  readonly shapes: Readonly<Record<string, ReadonlyArray<CloudShape>>>;
25
59
  readonly prices: ReadonlyArray<CloudPrice>;
60
+ /** Storage and load-balancing prices; null when the list lacks them. */
61
+ readonly servicePrices?: ServicePrices | null;
62
+ /** Every resource, in any container and region. */
63
+ readonly resources: ReadonlyArray<FakeResource>;
64
+ /** Objects by bucket name. */
65
+ readonly objects: Readonly<Record<string, ReadonlyArray<CloudObject>>>;
66
+ /** Object bytes by `bucket/object`. */
67
+ readonly objectBytes: Readonly<Record<string, string>>;
68
+ /** Pre-authenticated links by bucket name. */
69
+ readonly links: Readonly<Record<string, ReadonlyArray<CloudLink>>>;
70
+ /** Records by zone id. */
71
+ readonly records: Readonly<Record<string, ReadonlyArray<CloudRecord>>>;
26
72
  }
27
73
  /** The key an availability is kept under. */
28
74
  export declare function availabilityKey_make(region: string, service: string, name: string, zone?: string): string;
@@ -44,6 +90,22 @@ export declare class FakeDriver implements CloudDriver {
44
90
  limitAvailability_get(region: string, service: string, name: string, zone?: string): Promise<CloudAvailability | null>;
45
91
  shapes_list(region: string): Promise<CloudShape[]>;
46
92
  prices_list(): Promise<CloudPrice[]>;
93
+ servicePrices_get(): Promise<ServicePrices | null>;
94
+ /** The records of one kind in a container and region, sorted by name; DNS is global. */
95
+ private resources_of;
96
+ instances_list(containerId: string, region: string): Promise<CloudInstance[]>;
97
+ networks_list(containerId: string, region: string): Promise<CloudNetwork[]>;
98
+ subnets_list(containerId: string, region: string): Promise<CloudSubnet[]>;
99
+ securitygroups_list(containerId: string, region: string): Promise<CloudSecurityGroup[]>;
100
+ loadbalancers_list(containerId: string, region: string): Promise<CloudLoadBalancer[]>;
101
+ volumes_list(containerId: string, region: string): Promise<CloudVolume[]>;
102
+ buckets_list(containerId: string, region: string): Promise<CloudBucket[]>;
103
+ dns_list(containerId: string, region: string): Promise<CloudDnsZone[]>;
104
+ objects_list(bucket: string): Promise<CloudObject[]>;
105
+ links_list(bucket: string): Promise<CloudLink[]>;
106
+ object_read(bucket: string, object: string): Promise<Buffer>;
107
+ records_list(zoneId: string): Promise<CloudRecord[]>;
108
+ resources_search(containerId: string, region: string): Promise<ResourceCounts>;
47
109
  }
48
110
  /**
49
111
  * A small cloud with the shape of the real one: a tenancy, two compartments
@@ -53,3 +115,13 @@ export declare class FakeDriver implements CloudDriver {
53
115
  * @returns The fixture.
54
116
  */
55
117
  export declare function fakeCloud_sample(tenancy?: string): FakeCloud;
118
+ /**
119
+ * The resources of a small Trusted Domain in one compartment: three nodes, a
120
+ * network with subnets and security groups, two load balancers, their
121
+ * volumes, a bucket holding an image, and a DNS zone.
122
+ *
123
+ * @param region - The region they live in.
124
+ * @param containerId - The compartment holding them.
125
+ * @returns The resource part of a fake cloud.
126
+ */
127
+ export declare function fakeResources_sample(region: string, containerId: string): Pick<FakeCloud, 'resources' | 'objects' | 'objectBytes' | 'links' | 'records'>;