rightsize 0.1.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 (216) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +4 -0
  3. package/README.md +255 -0
  4. package/dist/backend-docker/backend.d.ts +53 -0
  5. package/dist/backend-docker/backend.d.ts.map +1 -0
  6. package/dist/backend-docker/backend.js +336 -0
  7. package/dist/backend-docker/backend.js.map +1 -0
  8. package/dist/backend-docker/client.d.ts +82 -0
  9. package/dist/backend-docker/client.d.ts.map +1 -0
  10. package/dist/backend-docker/client.js +190 -0
  11. package/dist/backend-docker/client.js.map +1 -0
  12. package/dist/backend-docker/frames.d.ts +44 -0
  13. package/dist/backend-docker/frames.d.ts.map +1 -0
  14. package/dist/backend-docker/frames.js +105 -0
  15. package/dist/backend-docker/frames.js.map +1 -0
  16. package/dist/backend-docker/index.d.ts +5 -0
  17. package/dist/backend-docker/index.d.ts.map +1 -0
  18. package/dist/backend-docker/index.js +20 -0
  19. package/dist/backend-docker/index.js.map +1 -0
  20. package/dist/backend-docker/json.d.ts +13 -0
  21. package/dist/backend-docker/json.d.ts.map +1 -0
  22. package/dist/backend-docker/json.js +47 -0
  23. package/dist/backend-docker/json.js.map +1 -0
  24. package/dist/backend-docker/labels.d.ts +11 -0
  25. package/dist/backend-docker/labels.d.ts.map +1 -0
  26. package/dist/backend-docker/labels.js +13 -0
  27. package/dist/backend-docker/labels.js.map +1 -0
  28. package/dist/backend-docker/port-conflict.d.ts +9 -0
  29. package/dist/backend-docker/port-conflict.d.ts.map +1 -0
  30. package/dist/backend-docker/port-conflict.js +12 -0
  31. package/dist/backend-docker/port-conflict.js.map +1 -0
  32. package/dist/backend-docker/provider.d.ts +22 -0
  33. package/dist/backend-docker/provider.d.ts.map +1 -0
  34. package/dist/backend-docker/provider.js +36 -0
  35. package/dist/backend-docker/provider.js.map +1 -0
  36. package/dist/backend-msb/backend.d.ts +169 -0
  37. package/dist/backend-msb/backend.d.ts.map +1 -0
  38. package/dist/backend-msb/backend.js +664 -0
  39. package/dist/backend-msb/backend.js.map +1 -0
  40. package/dist/backend-msb/commands.d.ts +28 -0
  41. package/dist/backend-msb/commands.d.ts.map +1 -0
  42. package/dist/backend-msb/commands.js +67 -0
  43. package/dist/backend-msb/commands.js.map +1 -0
  44. package/dist/backend-msb/exec-tunnel.d.ts +33 -0
  45. package/dist/backend-msb/exec-tunnel.d.ts.map +1 -0
  46. package/dist/backend-msb/exec-tunnel.js +163 -0
  47. package/dist/backend-msb/exec-tunnel.js.map +1 -0
  48. package/dist/backend-msb/follow-replay.d.ts +14 -0
  49. package/dist/backend-msb/follow-replay.d.ts.map +1 -0
  50. package/dist/backend-msb/follow-replay.js +20 -0
  51. package/dist/backend-msb/follow-replay.js.map +1 -0
  52. package/dist/backend-msb/image-cache.d.ts +25 -0
  53. package/dist/backend-msb/image-cache.d.ts.map +1 -0
  54. package/dist/backend-msb/image-cache.js +27 -0
  55. package/dist/backend-msb/image-cache.js.map +1 -0
  56. package/dist/backend-msb/index.d.ts +6 -0
  57. package/dist/backend-msb/index.d.ts.map +1 -0
  58. package/dist/backend-msb/index.js +21 -0
  59. package/dist/backend-msb/index.js.map +1 -0
  60. package/dist/backend-msb/invoke.d.ts +24 -0
  61. package/dist/backend-msb/invoke.d.ts.map +1 -0
  62. package/dist/backend-msb/invoke.js +73 -0
  63. package/dist/backend-msb/invoke.js.map +1 -0
  64. package/dist/backend-msb/ls-json.d.ts +23 -0
  65. package/dist/backend-msb/ls-json.d.ts.map +1 -0
  66. package/dist/backend-msb/ls-json.js +113 -0
  67. package/dist/backend-msb/ls-json.js.map +1 -0
  68. package/dist/backend-msb/network-links.d.ts +7 -0
  69. package/dist/backend-msb/network-links.d.ts.map +1 -0
  70. package/dist/backend-msb/network-links.js +31 -0
  71. package/dist/backend-msb/network-links.js.map +1 -0
  72. package/dist/backend-msb/platform.d.ts +29 -0
  73. package/dist/backend-msb/platform.d.ts.map +1 -0
  74. package/dist/backend-msb/platform.js +128 -0
  75. package/dist/backend-msb/platform.js.map +1 -0
  76. package/dist/backend-msb/port-conflict.d.ts +10 -0
  77. package/dist/backend-msb/port-conflict.d.ts.map +1 -0
  78. package/dist/backend-msb/port-conflict.js +16 -0
  79. package/dist/backend-msb/port-conflict.js.map +1 -0
  80. package/dist/backend-msb/provider.d.ts +10 -0
  81. package/dist/backend-msb/provider.d.ts.map +1 -0
  82. package/dist/backend-msb/provider.js +40 -0
  83. package/dist/backend-msb/provider.js.map +1 -0
  84. package/dist/backend-msb/provisioner.d.ts +19 -0
  85. package/dist/backend-msb/provisioner.d.ts.map +1 -0
  86. package/dist/backend-msb/provisioner.js +332 -0
  87. package/dist/backend-msb/provisioner.js.map +1 -0
  88. package/dist/backend-msb/reaper.d.ts +10 -0
  89. package/dist/backend-msb/reaper.d.ts.map +1 -0
  90. package/dist/backend-msb/reaper.js +73 -0
  91. package/dist/backend-msb/reaper.js.map +1 -0
  92. package/dist/core/backend.d.ts +98 -0
  93. package/dist/core/backend.d.ts.map +1 -0
  94. package/dist/core/backend.js +2 -0
  95. package/dist/core/backend.js.map +1 -0
  96. package/dist/core/backends.d.ts +37 -0
  97. package/dist/core/backends.d.ts.map +1 -0
  98. package/dist/core/backends.js +127 -0
  99. package/dist/core/backends.js.map +1 -0
  100. package/dist/core/cleanup.d.ts +37 -0
  101. package/dist/core/cleanup.d.ts.map +1 -0
  102. package/dist/core/cleanup.js +86 -0
  103. package/dist/core/cleanup.js.map +1 -0
  104. package/dist/core/errors.d.ts +51 -0
  105. package/dist/core/errors.d.ts.map +1 -0
  106. package/dist/core/errors.js +66 -0
  107. package/dist/core/errors.js.map +1 -0
  108. package/dist/core/free-ports.d.ts +23 -0
  109. package/dist/core/free-ports.d.ts.map +1 -0
  110. package/dist/core/free-ports.js +63 -0
  111. package/dist/core/free-ports.js.map +1 -0
  112. package/dist/core/generic-container.d.ts +145 -0
  113. package/dist/core/generic-container.d.ts.map +1 -0
  114. package/dist/core/generic-container.js +385 -0
  115. package/dist/core/generic-container.js.map +1 -0
  116. package/dist/core/model.d.ts +60 -0
  117. package/dist/core/model.d.ts.map +1 -0
  118. package/dist/core/model.js +2 -0
  119. package/dist/core/model.js.map +1 -0
  120. package/dist/core/mountable-file.d.ts +25 -0
  121. package/dist/core/mountable-file.d.ts.map +1 -0
  122. package/dist/core/mountable-file.js +64 -0
  123. package/dist/core/mountable-file.js.map +1 -0
  124. package/dist/core/network.d.ts +58 -0
  125. package/dist/core/network.d.ts.map +1 -0
  126. package/dist/core/network.js +84 -0
  127. package/dist/core/network.js.map +1 -0
  128. package/dist/core/run-id.d.ts +18 -0
  129. package/dist/core/run-id.d.ts.map +1 -0
  130. package/dist/core/run-id.js +18 -0
  131. package/dist/core/run-id.js.map +1 -0
  132. package/dist/core/wait.d.ts +59 -0
  133. package/dist/core/wait.d.ts.map +1 -0
  134. package/dist/core/wait.js +239 -0
  135. package/dist/core/wait.js.map +1 -0
  136. package/dist/index.d.ts +26 -0
  137. package/dist/index.d.ts.map +1 -0
  138. package/dist/index.js +22 -0
  139. package/dist/index.js.map +1 -0
  140. package/dist/modules/arango.d.ts +14 -0
  141. package/dist/modules/arango.d.ts.map +1 -0
  142. package/dist/modules/arango.js +37 -0
  143. package/dist/modules/arango.js.map +1 -0
  144. package/dist/modules/clickhouse.d.ts +37 -0
  145. package/dist/modules/clickhouse.d.ts.map +1 -0
  146. package/dist/modules/clickhouse.js +69 -0
  147. package/dist/modules/clickhouse.js.map +1 -0
  148. package/dist/modules/flink.d.ts +65 -0
  149. package/dist/modules/flink.d.ts.map +1 -0
  150. package/dist/modules/flink.js +125 -0
  151. package/dist/modules/flink.js.map +1 -0
  152. package/dist/modules/floci.d.ts +46 -0
  153. package/dist/modules/floci.d.ts.map +1 -0
  154. package/dist/modules/floci.js +62 -0
  155. package/dist/modules/floci.js.map +1 -0
  156. package/dist/modules/index.d.ts +31 -0
  157. package/dist/modules/index.d.ts.map +1 -0
  158. package/dist/modules/index.js +31 -0
  159. package/dist/modules/index.js.map +1 -0
  160. package/dist/modules/kafka.d.ts +11 -0
  161. package/dist/modules/kafka.d.ts.map +1 -0
  162. package/dist/modules/kafka.js +41 -0
  163. package/dist/modules/kafka.js.map +1 -0
  164. package/dist/modules/keycloak.d.ts +40 -0
  165. package/dist/modules/keycloak.d.ts.map +1 -0
  166. package/dist/modules/keycloak.js +67 -0
  167. package/dist/modules/keycloak.js.map +1 -0
  168. package/dist/modules/mariadb.d.ts +56 -0
  169. package/dist/modules/mariadb.d.ts.map +1 -0
  170. package/dist/modules/mariadb.js +89 -0
  171. package/dist/modules/mariadb.js.map +1 -0
  172. package/dist/modules/memcached.d.ts +24 -0
  173. package/dist/modules/memcached.d.ts.map +1 -0
  174. package/dist/modules/memcached.js +105 -0
  175. package/dist/modules/memcached.js.map +1 -0
  176. package/dist/modules/mongodb.d.ts +19 -0
  177. package/dist/modules/mongodb.d.ts.map +1 -0
  178. package/dist/modules/mongodb.js +69 -0
  179. package/dist/modules/mongodb.js.map +1 -0
  180. package/dist/modules/mysql.d.ts +61 -0
  181. package/dist/modules/mysql.d.ts.map +1 -0
  182. package/dist/modules/mysql.js +101 -0
  183. package/dist/modules/mysql.js.map +1 -0
  184. package/dist/modules/neo4j.d.ts +60 -0
  185. package/dist/modules/neo4j.d.ts.map +1 -0
  186. package/dist/modules/neo4j.js +83 -0
  187. package/dist/modules/neo4j.js.map +1 -0
  188. package/dist/modules/pinot.d.ts +30 -0
  189. package/dist/modules/pinot.d.ts.map +1 -0
  190. package/dist/modules/pinot.js +49 -0
  191. package/dist/modules/pinot.js.map +1 -0
  192. package/dist/modules/postgres.d.ts +29 -0
  193. package/dist/modules/postgres.d.ts.map +1 -0
  194. package/dist/modules/postgres.js +73 -0
  195. package/dist/modules/postgres.js.map +1 -0
  196. package/dist/modules/rabbitmq.d.ts +46 -0
  197. package/dist/modules/rabbitmq.d.ts.map +1 -0
  198. package/dist/modules/rabbitmq.js +68 -0
  199. package/dist/modules/rabbitmq.js.map +1 -0
  200. package/dist/modules/redis.d.ts +15 -0
  201. package/dist/modules/redis.d.ts.map +1 -0
  202. package/dist/modules/redis.js +24 -0
  203. package/dist/modules/redis.js.map +1 -0
  204. package/dist/modules/redpanda.d.ts +27 -0
  205. package/dist/modules/redpanda.d.ts.map +1 -0
  206. package/dist/modules/redpanda.js +58 -0
  207. package/dist/modules/redpanda.js.map +1 -0
  208. package/dist/modules/spring-cloud-config.d.ts +18 -0
  209. package/dist/modules/spring-cloud-config.d.ts.map +1 -0
  210. package/dist/modules/spring-cloud-config.js +28 -0
  211. package/dist/modules/spring-cloud-config.js.map +1 -0
  212. package/dist/modules/wiremock.d.ts +21 -0
  213. package/dist/modules/wiremock.d.ts.map +1 -0
  214. package/dist/modules/wiremock.js +32 -0
  215. package/dist/modules/wiremock.js.map +1 -0
  216. package/package.json +104 -0
@@ -0,0 +1,69 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ import { Wait } from "../core/wait.js";
3
+ const HTTP_PORT = 8123;
4
+ const NATIVE_PORT = 9000;
5
+ /**
6
+ * A single-node ClickHouse container, ready-checked via `/ping` (returns
7
+ * the literal body `Ok.` on 200 — `Wait.forHttp`'s status-code check is all
8
+ * that's needed here). Exposes both the HTTP interface (8123, what the
9
+ * helpers here use) and the native protocol port (9000) for consumers that
10
+ * want a native-protocol client instead.
11
+ *
12
+ * `CLICKHOUSE_USER`/`CLICKHOUSE_PASSWORD`/`CLICKHOUSE_DB` (verified against
13
+ * the entrypoint's own logging: `create new user 'test' instead 'default'`,
14
+ * `create database 'test'`) replace the image's default `default` user
15
+ * entirely — once set, the unauthenticated `default` user's usual
16
+ * passwordless access is gone, and every query needs the configured
17
+ * credentials.
18
+ */
19
+ export class ClickHouseContainer extends GenericContainer {
20
+ usernameState = "test";
21
+ passwordState = "test";
22
+ databaseState = "test";
23
+ constructor(image = "clickhouse/clickhouse-server:25.8") {
24
+ super(image);
25
+ this.withExposedPorts(HTTP_PORT, NATIVE_PORT)
26
+ .withEnv("CLICKHOUSE_USER", this.usernameState)
27
+ .withEnv("CLICKHOUSE_PASSWORD", this.passwordState)
28
+ .withEnv("CLICKHOUSE_DB", this.databaseState)
29
+ .waitingFor(Wait.forHttp("/ping").forPort(HTTP_PORT));
30
+ // No withMemoryLimit override: measured ~524MB resident at rest well
31
+ // under msb's default ~450MB-and-up microVM sizing headroom in
32
+ // practice (verified booting and answering /ping on msb's default).
33
+ }
34
+ static async start(image = "clickhouse/clickhouse-server:25.8") {
35
+ return (await new ClickHouseContainer(image).start());
36
+ }
37
+ /** Overrides `CLICKHOUSE_USER` (default `test`). */
38
+ withUsername(username) {
39
+ this.usernameState = username;
40
+ return this.withEnv("CLICKHOUSE_USER", username);
41
+ }
42
+ /** Overrides `CLICKHOUSE_PASSWORD` (default `test`). */
43
+ withPassword(password) {
44
+ this.passwordState = password;
45
+ return this.withEnv("CLICKHOUSE_PASSWORD", password);
46
+ }
47
+ /** Overrides `CLICKHOUSE_DB` (default `test`). */
48
+ withDatabase(database) {
49
+ this.databaseState = database;
50
+ return this.withEnv("CLICKHOUSE_DB", database);
51
+ }
52
+ /** The configured user (default `test`). */
53
+ get username() {
54
+ return this.usernameState;
55
+ }
56
+ /** The configured password (default `test`). */
57
+ get password() {
58
+ return this.passwordState;
59
+ }
60
+ /** The configured database name (default `test`). */
61
+ get databaseName() {
62
+ return this.databaseState;
63
+ }
64
+ /** The HTTP interface's base URL for the running container. */
65
+ get httpUrl() {
66
+ return `http://${this.host}:${this.getMappedPort(HTTP_PORT)}`;
67
+ }
68
+ }
69
+ //# sourceMappingURL=clickhouse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clickhouse.js","sourceRoot":"","sources":["../../src/modules/clickhouse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,MAAM,SAAS,GAAG,IAAI,CAAC;AACvB,MAAM,WAAW,GAAG,IAAI,CAAC;AAEzB;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,mBAAoB,SAAQ,gBAAgB;IAC/C,aAAa,GAAG,MAAM,CAAC;IACvB,aAAa,GAAG,MAAM,CAAC;IACvB,aAAa,GAAG,MAAM,CAAC;IAE/B,YAAY,KAAK,GAAG,mCAAmC;QACrD,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,WAAW,CAAC;aAC1C,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC,aAAa,CAAC;aAC9C,OAAO,CAAC,qBAAqB,EAAE,IAAI,CAAC,aAAa,CAAC;aAClD,OAAO,CAAC,eAAe,EAAE,IAAI,CAAC,aAAa,CAAC;aAC5C,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;QACxD,qEAAqE;QACrE,+DAA+D;QAC/D,oEAAoE;IACtE,CAAC;IAED,MAAM,CAAU,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,mCAAmC;QACrE,OAAO,CAAC,MAAM,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAwB,CAAC;IAC/E,CAAC;IAED,oDAAoD;IACpD,YAAY,CAAC,QAAgB;QAC3B,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;IACnD,CAAC;IAED,wDAAwD;IACxD,YAAY,CAAC,QAAgB;QAC3B,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,QAAQ,CAAC,CAAC;IACvD,CAAC;IAED,kDAAkD;IAClD,YAAY,CAAC,QAAgB;QAC3B,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;IACjD,CAAC;IAED,4CAA4C;IAC5C,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,gDAAgD;IAChD,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,qDAAqD;IACrD,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,+DAA+D;IAC/D,IAAI,OAAO;QACT,OAAO,UAAU,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;IAChE,CAAC;CACF"}
@@ -0,0 +1,65 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ import type { SandboxBackend } from "../core/backend.js";
3
+ /**
4
+ * A Flink JobManager container (REST 8081, RPC 6123), with an optional
5
+ * companion TaskManager on Docker only — see `withTaskManager()`.
6
+ *
7
+ * `FLINK_PROPERTIES` must set `jobmanager.rpc.address` on the JobManager
8
+ * itself (not just the TaskManager): the JobManager's own Pekko/Akka actor
9
+ * system binds its external address from this property too, and the image's
10
+ * default (`localhost`) doesn't resolve to anything reachable from a sibling
11
+ * container. Both roles get `withMemoryLimit(1024)` — verified booting
12
+ * cleanly on this machine at that floor for a bare JobManager and for the
13
+ * two-container topology on docker.
14
+ *
15
+ * ### `withTaskManager()` — docker-only (KNOWN, adjudicated msb limitation)
16
+ *
17
+ * A real Flink session cluster needs a TaskManager to actually run
18
+ * anything; it registers with the JobManager over a **persistent
19
+ * bidirectional Pekko/Akka RPC connection**. msb's network-link emulation
20
+ * (`ExecTunnel`) only carries **client-speaks-first, one-exchange-at-a-time**
21
+ * traffic through an in-guest `nc` listener — and the `flink` image ships
22
+ * neither `nc` nor `busybox` at all (confirmed: `command -v nc` and
23
+ * `command -v busybox` both exit 127 in `flink:1.20.5`), so the tunnel's
24
+ * `installNetworkLinks` step can't even probe for the listener it would
25
+ * need, let alone carry Pekko's long-lived duplex traffic if it somehow
26
+ * could. `withTaskManager()` therefore throws `UnsupportedByBackendError`
27
+ * from `containerIsStarting()` — the instant `start()` has resolved the msb
28
+ * backend, before `ensureNetwork`, port allocation, or the JobManager
29
+ * container is created/booted at all — rather than attempting a boot that
30
+ * would hang or fail deep inside Flink's own registration timeout. On
31
+ * docker, the same builder produces a real two-container session cluster on
32
+ * a shared `Network`, and the TaskManager registers successfully (verified:
33
+ * `/taskmanagers` reports one registered TM with a live heartbeat).
34
+ */
35
+ export declare class FlinkContainer extends GenericContainer {
36
+ private readonly imageTag;
37
+ private taskManagerRequested;
38
+ private taskManagerContainer;
39
+ private taskManagerNetwork;
40
+ private ownedNetwork;
41
+ constructor(image?: string);
42
+ static start(image?: string): Promise<FlinkContainer>;
43
+ /**
44
+ * Requests a companion TaskManager, started on a shared `Network` once
45
+ * the JobManager is ready. Docker only — see the class doc for why msb
46
+ * can't carry this topology; calling `start()` after this on msb throws
47
+ * `UnsupportedByBackendError` from `containerIsStarting()`, before any
48
+ * boot work (network, ports, or the JobManager container itself) begins.
49
+ */
50
+ withTaskManager(): this;
51
+ /**
52
+ * Fires the instant `start()` resolves a backend — before `ensureNetwork`,
53
+ * port allocation, or the JobManager container is created/booted at all.
54
+ * Rejecting an msb + withTaskManager() combination here, instead of in
55
+ * `containerIsStarted()` after the JobManager has already fully booted,
56
+ * means the caller never pays for (or has to clean up after) a boot this
57
+ * backend was never going to be able to complete.
58
+ */
59
+ protected containerIsStarting(backend: SandboxBackend): Promise<void>;
60
+ protected containerIsStarted(): Promise<void>;
61
+ stop(): Promise<void>;
62
+ /** The REST base URL for the running JobManager. */
63
+ get restUrl(): string;
64
+ }
65
+ //# sourceMappingURL=flink.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flink.d.ts","sourceRoot":"","sources":["../../src/modules/flink.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAIhE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAQzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,qBAAa,cAAe,SAAQ,gBAAgB;IAClD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,oBAAoB,CAA+B;IAC3D,OAAO,CAAC,kBAAkB,CAAsB;IAChD,OAAO,CAAC,YAAY,CAAsB;gBAE9B,KAAK,SAAiB;WAWZ,KAAK,CAAC,KAAK,SAAiB,GAAG,OAAO,CAAC,cAAc,CAAC;IAI5E;;;;;;OAMG;IACH,eAAe,IAAI,IAAI;IASvB;;;;;;;OAOG;cACsB,mBAAmB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;cAU3D,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB7C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAYpC,oDAAoD;IACpD,IAAI,OAAO,IAAI,MAAM,CAEpB;CACF"}
@@ -0,0 +1,125 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ import { Network } from "../core/network.js";
3
+ import { Wait } from "../core/wait.js";
4
+ import { UnsupportedByBackendError } from "../core/errors.js";
5
+ const RPC_PORT = 6123;
6
+ const REST_PORT = 8081;
7
+ const JOBMANAGER_MEMORY_MB = 1024;
8
+ const TASKMANAGER_MEMORY_MB = 1024;
9
+ const JOBMANAGER_ALIAS = "flink-jobmanager";
10
+ /**
11
+ * A Flink JobManager container (REST 8081, RPC 6123), with an optional
12
+ * companion TaskManager on Docker only — see `withTaskManager()`.
13
+ *
14
+ * `FLINK_PROPERTIES` must set `jobmanager.rpc.address` on the JobManager
15
+ * itself (not just the TaskManager): the JobManager's own Pekko/Akka actor
16
+ * system binds its external address from this property too, and the image's
17
+ * default (`localhost`) doesn't resolve to anything reachable from a sibling
18
+ * container. Both roles get `withMemoryLimit(1024)` — verified booting
19
+ * cleanly on this machine at that floor for a bare JobManager and for the
20
+ * two-container topology on docker.
21
+ *
22
+ * ### `withTaskManager()` — docker-only (KNOWN, adjudicated msb limitation)
23
+ *
24
+ * A real Flink session cluster needs a TaskManager to actually run
25
+ * anything; it registers with the JobManager over a **persistent
26
+ * bidirectional Pekko/Akka RPC connection**. msb's network-link emulation
27
+ * (`ExecTunnel`) only carries **client-speaks-first, one-exchange-at-a-time**
28
+ * traffic through an in-guest `nc` listener — and the `flink` image ships
29
+ * neither `nc` nor `busybox` at all (confirmed: `command -v nc` and
30
+ * `command -v busybox` both exit 127 in `flink:1.20.5`), so the tunnel's
31
+ * `installNetworkLinks` step can't even probe for the listener it would
32
+ * need, let alone carry Pekko's long-lived duplex traffic if it somehow
33
+ * could. `withTaskManager()` therefore throws `UnsupportedByBackendError`
34
+ * from `containerIsStarting()` — the instant `start()` has resolved the msb
35
+ * backend, before `ensureNetwork`, port allocation, or the JobManager
36
+ * container is created/booted at all — rather than attempting a boot that
37
+ * would hang or fail deep inside Flink's own registration timeout. On
38
+ * docker, the same builder produces a real two-container session cluster on
39
+ * a shared `Network`, and the TaskManager registers successfully (verified:
40
+ * `/taskmanagers` reports one registered TM with a live heartbeat).
41
+ */
42
+ export class FlinkContainer extends GenericContainer {
43
+ imageTag;
44
+ taskManagerRequested = false;
45
+ taskManagerContainer;
46
+ taskManagerNetwork;
47
+ ownedNetwork;
48
+ constructor(image = "flink:1.20.5") {
49
+ super(image);
50
+ this.imageTag = image;
51
+ this.withExposedPorts(RPC_PORT, REST_PORT)
52
+ .withEnv("FLINK_PROPERTIES", `jobmanager.rpc.address: ${JOBMANAGER_ALIAS}`)
53
+ .withCommand("jobmanager")
54
+ .withMemoryLimit(JOBMANAGER_MEMORY_MB)
55
+ .withNetworkAliases(JOBMANAGER_ALIAS)
56
+ .waitingFor(Wait.forHttp("/overview").forPort(REST_PORT).withStartupTimeout(120_000));
57
+ }
58
+ static async start(image = "flink:1.20.5") {
59
+ return (await new FlinkContainer(image).start());
60
+ }
61
+ /**
62
+ * Requests a companion TaskManager, started on a shared `Network` once
63
+ * the JobManager is ready. Docker only — see the class doc for why msb
64
+ * can't carry this topology; calling `start()` after this on msb throws
65
+ * `UnsupportedByBackendError` from `containerIsStarting()`, before any
66
+ * boot work (network, ports, or the JobManager container itself) begins.
67
+ */
68
+ withTaskManager() {
69
+ this.taskManagerRequested = true;
70
+ const net = Network.newNetwork();
71
+ this.ownedNetwork = net;
72
+ this.taskManagerNetwork = net;
73
+ this.withNetwork(net);
74
+ return this;
75
+ }
76
+ /**
77
+ * Fires the instant `start()` resolves a backend — before `ensureNetwork`,
78
+ * port allocation, or the JobManager container is created/booted at all.
79
+ * Rejecting an msb + withTaskManager() combination here, instead of in
80
+ * `containerIsStarted()` after the JobManager has already fully booted,
81
+ * means the caller never pays for (or has to clean up after) a boot this
82
+ * backend was never going to be able to complete.
83
+ */
84
+ async containerIsStarting(backend) {
85
+ if (this.taskManagerRequested && backend.name === "microsandbox") {
86
+ throw new UnsupportedByBackendError("Flink TaskManager registration", backend.name, "the flink image ships no nc/busybox for the network-link exec-tunnel, and TaskManager registration is a persistent bidirectional RPC the tunnel can't carry anyway — run this with RIGHTSIZE_BACKEND=docker instead");
87
+ }
88
+ }
89
+ async containerIsStarted() {
90
+ if (!this.taskManagerRequested) {
91
+ return;
92
+ }
93
+ const backend = this.currentBackend();
94
+ const network = this.taskManagerNetwork;
95
+ if (network === undefined) {
96
+ throw new Error("withTaskManager() requires a network, but none was set");
97
+ }
98
+ const taskManager = new GenericContainer(this.imageTag)
99
+ .withEnv("FLINK_PROPERTIES", `jobmanager.rpc.address: ${JOBMANAGER_ALIAS}`)
100
+ .withCommand("taskmanager")
101
+ .withMemoryLimit(TASKMANAGER_MEMORY_MB)
102
+ .withNetwork(network)
103
+ // Use the SAME backend this JobManager actually resolved (test
104
+ // doubles and an explicit RIGHTSIZE_BACKEND override must both carry
105
+ // through to the companion container, not re-resolve independently).
106
+ .withBackend(backend);
107
+ this.taskManagerContainer = await taskManager.start();
108
+ }
109
+ async stop() {
110
+ if (this.taskManagerContainer !== undefined) {
111
+ await this.taskManagerContainer.stop();
112
+ this.taskManagerContainer = undefined;
113
+ }
114
+ await super.stop();
115
+ if (this.ownedNetwork !== undefined) {
116
+ await this.ownedNetwork.close();
117
+ this.ownedNetwork = undefined;
118
+ }
119
+ }
120
+ /** The REST base URL for the running JobManager. */
121
+ get restUrl() {
122
+ return `http://${this.host}:${this.getMappedPort(REST_PORT)}`;
123
+ }
124
+ }
125
+ //# sourceMappingURL=flink.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flink.js","sourceRoot":"","sources":["../../src/modules/flink.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ /**
3
+ * A [floci.io](https://floci.io) cloud emulator — one native Quarkus image
4
+ * per cloud provider, each speaking that provider's REST APIs against an
5
+ * in-memory backing store. One module type covers all three variants; pick
6
+ * one via the `FlociContainer.aws()`/`.azure()`/`.gcp()` factory functions
7
+ * (there is no bare `new FlociContainer(...)` or `static start()` — each
8
+ * factory pins the provider's own image and guest port, so it's the only
9
+ * entry point) and call `.start()` on the result, e.g. `await
10
+ * FlociContainer.aws().start()`.
11
+ *
12
+ * ### Readiness — `/health` works uniformly, unlike the AWS-flavored `/_localstack/health`
13
+ *
14
+ * All three variants answer a plain `GET /health` with `200` and a small
15
+ * JSON status body the moment the embedded Quarkus HTTP listener is up
16
+ * (verified against real boots of `floci/floci:1.5.30`,
17
+ * `floci/floci-az:0.8.0`, and `floci/floci-gcp:0.4.0`) — pinned as the one
18
+ * wait path that works across all three; no log-wait fallback was needed.
19
+ *
20
+ * ### No signing needed — verified against the AWS variant's S3 surface
21
+ *
22
+ * The AWS variant's S3-shaped REST endpoints accept unsigned requests with
23
+ * no `Authorization` header at all: `PUT /<bucket>` (create-bucket), `PUT
24
+ * /<bucket>/<key>` (put-object), and `GET /<bucket>/<key>` (get-object) all
25
+ * round-trip successfully with a bare HTTP client call — no SigV4, no AWS
26
+ * SDK dependency required.
27
+ *
28
+ * ### Memory — tiny, no ladder needed
29
+ *
30
+ * All three images are native (GraalVM) Quarkus binaries; a real boot
31
+ * settles under 150MiB RSS, and each variant boots and answers `/health`
32
+ * under msb's default microVM RAM with no `withMemoryLimit` override.
33
+ */
34
+ export declare class FlociContainer extends GenericContainer {
35
+ private readonly guestPort;
36
+ private constructor();
37
+ /** The AWS emulator (`floci/floci:1.5.30`), guest port 4566 — S3, DynamoDB, SQS, etc. */
38
+ static aws(image?: string): FlociContainer;
39
+ /** The Azure emulator (`floci/floci-az:0.8.0`), guest port 4577. */
40
+ static azure(image?: string): FlociContainer;
41
+ /** The GCP emulator (`floci/floci-gcp:0.4.0`), guest port 4588. */
42
+ static gcp(image?: string): FlociContainer;
43
+ /** This variant's REST endpoint — the base URL for every emulated API call. */
44
+ get endpointUrl(): string;
45
+ }
46
+ //# sourceMappingURL=floci.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"floci.d.ts","sourceRoot":"","sources":["../../src/modules/floci.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAOhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,qBAAa,cAAe,SAAQ,gBAAgB;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC,OAAO;IAMP,yFAAyF;IACzF,MAAM,CAAC,GAAG,CAAC,KAAK,SAAuB,GAAG,cAAc;IAIxD,oEAAoE;IACpE,MAAM,CAAC,KAAK,CAAC,KAAK,SAAyB,GAAG,cAAc;IAI5D,mEAAmE;IACnE,MAAM,CAAC,GAAG,CAAC,KAAK,SAA0B,GAAG,cAAc;IAI3D,+EAA+E;IAC/E,IAAI,WAAW,IAAI,MAAM,CAExB;CACF"}
@@ -0,0 +1,62 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ import { Wait } from "../core/wait.js";
3
+ const AWS_PORT = 4566;
4
+ const AZURE_PORT = 4577;
5
+ const GCP_PORT = 4588;
6
+ /**
7
+ * A [floci.io](https://floci.io) cloud emulator — one native Quarkus image
8
+ * per cloud provider, each speaking that provider's REST APIs against an
9
+ * in-memory backing store. One module type covers all three variants; pick
10
+ * one via the `FlociContainer.aws()`/`.azure()`/`.gcp()` factory functions
11
+ * (there is no bare `new FlociContainer(...)` or `static start()` — each
12
+ * factory pins the provider's own image and guest port, so it's the only
13
+ * entry point) and call `.start()` on the result, e.g. `await
14
+ * FlociContainer.aws().start()`.
15
+ *
16
+ * ### Readiness — `/health` works uniformly, unlike the AWS-flavored `/_localstack/health`
17
+ *
18
+ * All three variants answer a plain `GET /health` with `200` and a small
19
+ * JSON status body the moment the embedded Quarkus HTTP listener is up
20
+ * (verified against real boots of `floci/floci:1.5.30`,
21
+ * `floci/floci-az:0.8.0`, and `floci/floci-gcp:0.4.0`) — pinned as the one
22
+ * wait path that works across all three; no log-wait fallback was needed.
23
+ *
24
+ * ### No signing needed — verified against the AWS variant's S3 surface
25
+ *
26
+ * The AWS variant's S3-shaped REST endpoints accept unsigned requests with
27
+ * no `Authorization` header at all: `PUT /<bucket>` (create-bucket), `PUT
28
+ * /<bucket>/<key>` (put-object), and `GET /<bucket>/<key>` (get-object) all
29
+ * round-trip successfully with a bare HTTP client call — no SigV4, no AWS
30
+ * SDK dependency required.
31
+ *
32
+ * ### Memory — tiny, no ladder needed
33
+ *
34
+ * All three images are native (GraalVM) Quarkus binaries; a real boot
35
+ * settles under 150MiB RSS, and each variant boots and answers `/health`
36
+ * under msb's default microVM RAM with no `withMemoryLimit` override.
37
+ */
38
+ export class FlociContainer extends GenericContainer {
39
+ guestPort;
40
+ constructor(image, port) {
41
+ super(image);
42
+ this.guestPort = port;
43
+ this.withExposedPorts(port).waitingFor(Wait.forHttp("/health").forPort(port));
44
+ }
45
+ /** The AWS emulator (`floci/floci:1.5.30`), guest port 4566 — S3, DynamoDB, SQS, etc. */
46
+ static aws(image = "floci/floci:1.5.30") {
47
+ return new FlociContainer(image, AWS_PORT);
48
+ }
49
+ /** The Azure emulator (`floci/floci-az:0.8.0`), guest port 4577. */
50
+ static azure(image = "floci/floci-az:0.8.0") {
51
+ return new FlociContainer(image, AZURE_PORT);
52
+ }
53
+ /** The GCP emulator (`floci/floci-gcp:0.4.0`), guest port 4588. */
54
+ static gcp(image = "floci/floci-gcp:0.4.0") {
55
+ return new FlociContainer(image, GCP_PORT);
56
+ }
57
+ /** This variant's REST endpoint — the base URL for every emulated API call. */
58
+ get endpointUrl() {
59
+ return `http://${this.host}:${this.getMappedPort(this.guestPort)}`;
60
+ }
61
+ }
62
+ //# sourceMappingURL=floci.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"floci.js","sourceRoot":"","sources":["../../src/modules/floci.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,MAAM,QAAQ,GAAG,IAAI,CAAC;AACtB,MAAM,UAAU,GAAG,IAAI,CAAC;AACxB,MAAM,QAAQ,GAAG,IAAI,CAAC;AAEtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,OAAO,cAAe,SAAQ,gBAAgB;IACjC,SAAS,CAAS;IAEnC,YAAoB,KAAa,EAAE,IAAY;QAC7C,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAChF,CAAC;IAED,yFAAyF;IACzF,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,oBAAoB;QACrC,OAAO,IAAI,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAED,oEAAoE;IACpE,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,sBAAsB;QACzC,OAAO,IAAI,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAC/C,CAAC;IAED,mEAAmE;IACnE,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,uBAAuB;QACxC,OAAO,IAAI,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAED,+EAA+E;IAC/E,IAAI,WAAW;QACb,OAAO,UAAU,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;IACrE,CAAC;CACF"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * `rightsize/modules` — eighteen preconfigured containers.
3
+ *
4
+ * Each module is a `GenericContainer` subclass with sensible defaults (image
5
+ * tag, exposed ports, wait strategy, and any memory floor its image needs)
6
+ * plus typed connection helpers, so `await using redis = await RedisContainer.start()`
7
+ * is immediately usable without hand-assembling a `GenericContainer`. Every
8
+ * builder method from the base class (`withEnv`, `withExposedPorts`,
9
+ * `waitingFor`, …) remains available on every module.
10
+ *
11
+ * @packageDocumentation
12
+ */
13
+ export { RedisContainer } from "./redis.js";
14
+ export { MemcachedContainer, MemcachedRespondsStrategy } from "./memcached.js";
15
+ export { ArangoContainer } from "./arango.js";
16
+ export { MongoDBContainer } from "./mongodb.js";
17
+ export { RedpandaContainer } from "./redpanda.js";
18
+ export { KafkaContainer } from "./kafka.js";
19
+ export { SpringCloudConfigContainer } from "./spring-cloud-config.js";
20
+ export { PostgresContainer } from "./postgres.js";
21
+ export { MySQLContainer } from "./mysql.js";
22
+ export { PinotContainer } from "./pinot.js";
23
+ export { RabbitMQContainer } from "./rabbitmq.js";
24
+ export { MariaDBContainer } from "./mariadb.js";
25
+ export { FlinkContainer } from "./flink.js";
26
+ export { WireMockContainer } from "./wiremock.js";
27
+ export { KeycloakContainer } from "./keycloak.js";
28
+ export { ClickHouseContainer } from "./clickhouse.js";
29
+ export { Neo4jContainer } from "./neo4j.js";
30
+ export { FlociContainer } from "./floci.js";
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/modules/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * `rightsize/modules` — eighteen preconfigured containers.
3
+ *
4
+ * Each module is a `GenericContainer` subclass with sensible defaults (image
5
+ * tag, exposed ports, wait strategy, and any memory floor its image needs)
6
+ * plus typed connection helpers, so `await using redis = await RedisContainer.start()`
7
+ * is immediately usable without hand-assembling a `GenericContainer`. Every
8
+ * builder method from the base class (`withEnv`, `withExposedPorts`,
9
+ * `waitingFor`, …) remains available on every module.
10
+ *
11
+ * @packageDocumentation
12
+ */
13
+ export { RedisContainer } from "./redis.js";
14
+ export { MemcachedContainer, MemcachedRespondsStrategy } from "./memcached.js";
15
+ export { ArangoContainer } from "./arango.js";
16
+ export { MongoDBContainer } from "./mongodb.js";
17
+ export { RedpandaContainer } from "./redpanda.js";
18
+ export { KafkaContainer } from "./kafka.js";
19
+ export { SpringCloudConfigContainer } from "./spring-cloud-config.js";
20
+ export { PostgresContainer } from "./postgres.js";
21
+ export { MySQLContainer } from "./mysql.js";
22
+ export { PinotContainer } from "./pinot.js";
23
+ export { RabbitMQContainer } from "./rabbitmq.js";
24
+ export { MariaDBContainer } from "./mariadb.js";
25
+ export { FlinkContainer } from "./flink.js";
26
+ export { WireMockContainer } from "./wiremock.js";
27
+ export { KeycloakContainer } from "./keycloak.js";
28
+ export { ClickHouseContainer } from "./clickhouse.js";
29
+ export { Neo4jContainer } from "./neo4j.js";
30
+ export { FlociContainer } from "./floci.js";
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/modules/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ import type { ContainerSpec } from "../core/model.js";
3
+ /** A single-node Kafka broker (KRaft mode, no ZooKeeper). */
4
+ export declare class KafkaContainer extends GenericContainer {
5
+ constructor(image?: string);
6
+ static start(image?: string): Promise<KafkaContainer>;
7
+ protected customizeSpec(spec: ContainerSpec, mapped: (guest: number) => number): ContainerSpec;
8
+ /** The `PLAINTEXT://` bootstrap-servers address for the running broker. */
9
+ get bootstrapServers(): string;
10
+ }
11
+ //# sourceMappingURL=kafka.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kafka.d.ts","sourceRoot":"","sources":["../../src/modules/kafka.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAItD,6DAA6D;AAC7D,qBAAa,cAAe,SAAQ,gBAAgB;gBACtC,KAAK,SAAuB;WAoBlB,KAAK,CAAC,KAAK,SAAuB,GAAG,OAAO,CAAC,cAAc,CAAC;cAM/D,aAAa,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,aAAa;IAOvG,2EAA2E;IAC3E,IAAI,gBAAgB,IAAI,MAAM,CAE7B;CACF"}
@@ -0,0 +1,41 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ import { Wait } from "../core/wait.js";
3
+ const GUEST_PORT = 9092;
4
+ /** A single-node Kafka broker (KRaft mode, no ZooKeeper). */
5
+ export class KafkaContainer extends GenericContainer {
6
+ constructor(image = "apache/kafka:4.0.0") {
7
+ super(image);
8
+ this.withExposedPorts(GUEST_PORT)
9
+ .withEnv("KAFKA_NODE_ID", "1")
10
+ .withEnv("KAFKA_PROCESS_ROLES", "broker,controller")
11
+ .withEnv("KAFKA_CONTROLLER_QUORUM_VOTERS", "1@localhost:9091")
12
+ .withEnv("KAFKA_LISTENERS", "PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9091")
13
+ .withEnv("KAFKA_CONTROLLER_LISTENER_NAMES", "CONTROLLER")
14
+ .withEnv("KAFKA_LISTENER_SECURITY_PROTOCOL_MAP", "PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT")
15
+ .withEnv("KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR", "1")
16
+ .withEnv("KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS", "0")
17
+ // The apache/kafka image defaults KAFKA_HEAP_OPTS to -Xmx1G, which
18
+ // exceeds the microsandbox microVM's default RAM and aborts the JVM
19
+ // ("insufficient memory"). A single-node KRaft dev broker runs
20
+ // comfortably in a 256M heap; harmless on the Docker backend, which
21
+ // is not memory-constrained here.
22
+ .withEnv("KAFKA_HEAP_OPTS", "-Xmx256M -Xms256M")
23
+ .waitingFor(Wait.forLogMessage(".*Kafka Server started.*"));
24
+ }
25
+ static async start(image = "apache/kafka:4.0.0") {
26
+ return (await new KafkaContainer(image).start());
27
+ }
28
+ // Rewrites the advertised listener to carry the mapped host port; see
29
+ // RedpandaContainer.customizeSpec for why this needs the mapped callback.
30
+ customizeSpec(spec, mapped) {
31
+ return {
32
+ ...spec,
33
+ env: [...spec.env, ["KAFKA_ADVERTISED_LISTENERS", `PLAINTEXT://127.0.0.1:${mapped(GUEST_PORT)}`]],
34
+ };
35
+ }
36
+ /** The `PLAINTEXT://` bootstrap-servers address for the running broker. */
37
+ get bootstrapServers() {
38
+ return `PLAINTEXT://${this.host}:${this.getMappedPort(GUEST_PORT)}`;
39
+ }
40
+ }
41
+ //# sourceMappingURL=kafka.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kafka.js","sourceRoot":"","sources":["../../src/modules/kafka.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAGvC,MAAM,UAAU,GAAG,IAAI,CAAC;AAExB,6DAA6D;AAC7D,MAAM,OAAO,cAAe,SAAQ,gBAAgB;IAClD,YAAY,KAAK,GAAG,oBAAoB;QACtC,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC;aAC9B,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC;aAC7B,OAAO,CAAC,qBAAqB,EAAE,mBAAmB,CAAC;aACnD,OAAO,CAAC,gCAAgC,EAAE,kBAAkB,CAAC;aAC7D,OAAO,CAAC,iBAAiB,EAAE,oDAAoD,CAAC;aAChF,OAAO,CAAC,iCAAiC,EAAE,YAAY,CAAC;aACxD,OAAO,CAAC,sCAAsC,EAAE,0CAA0C,CAAC;aAC3F,OAAO,CAAC,wCAAwC,EAAE,GAAG,CAAC;aACtD,OAAO,CAAC,wCAAwC,EAAE,GAAG,CAAC;YACvD,mEAAmE;YACnE,oEAAoE;YACpE,+DAA+D;YAC/D,oEAAoE;YACpE,kCAAkC;aACjC,OAAO,CAAC,iBAAiB,EAAE,mBAAmB,CAAC;aAC/C,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,0BAA0B,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,CAAU,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,oBAAoB;QACtD,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAmB,CAAC;IACrE,CAAC;IAED,sEAAsE;IACtE,0EAA0E;IACvD,aAAa,CAAC,IAAmB,EAAE,MAAiC;QACrF,OAAO;YACL,GAAG,IAAI;YACP,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,4BAA4B,EAAE,yBAAyB,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;SAClG,CAAC;IACJ,CAAC;IAED,2EAA2E;IAC3E,IAAI,gBAAgB;QAClB,OAAO,eAAe,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC;IACtE,CAAC;CACF"}
@@ -0,0 +1,40 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ /**
3
+ * A single-node Keycloak container started with `start-dev` (an
4
+ * in-memory/dev-mode boot — no external database wiring needed for tests).
5
+ *
6
+ * Two pins here are version-sensitive and were verified against 26.0.8
7
+ * specifically:
8
+ *
9
+ * - **Env var names**: 26.x renamed the bootstrap-admin variables to
10
+ * `KC_BOOTSTRAP_ADMIN_USERNAME`/`KC_BOOTSTRAP_ADMIN_PASSWORD` (older
11
+ * releases used `KEYCLOAK_ADMIN`/`KEYCLOAK_ADMIN_PASSWORD`, which 26.x
12
+ * does not recognize). Confirmed by the boot log: `KC-SERVICES0077:
13
+ * Created temporary admin user with username admin`.
14
+ * - **Health lives on the management port, not the app port.** 26.x splits
15
+ * HTTP (8080) from a separate management interface (9000, confirmed by
16
+ * the boot log: "Management interface listening on http://0.0.0.0:9000")
17
+ * that serves `/health/ready`; `KC_HEALTH_ENABLED=true` is required for
18
+ * that endpoint to exist at all.
19
+ *
20
+ * A four-JVM-adjacent Quarkus boot (Keycloak on Quarkus, with Infinispan +
21
+ * an embedded H2) fits comfortably in `withMemoryLimit(1024)` (measured
22
+ * ~55% utilization at rest) — set by default here.
23
+ */
24
+ export declare class KeycloakContainer extends GenericContainer {
25
+ private adminUsernameState;
26
+ private adminPasswordState;
27
+ constructor(image?: string);
28
+ static start(image?: string): Promise<KeycloakContainer>;
29
+ /** Overrides `KC_BOOTSTRAP_ADMIN_USERNAME` (default `admin`). */
30
+ withAdminUsername(username: string): this;
31
+ /** Overrides `KC_BOOTSTRAP_ADMIN_PASSWORD` (default `admin`). */
32
+ withAdminPassword(password: string): this;
33
+ /** The configured bootstrap admin username (default `admin`). */
34
+ get adminUsername(): string;
35
+ /** The configured bootstrap admin password (default `admin`). */
36
+ get adminPassword(): string;
37
+ /** The auth server's base URL (the app HTTP port, 8080). */
38
+ get authServerUrl(): string;
39
+ }
40
+ //# sourceMappingURL=keycloak.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keycloak.d.ts","sourceRoot":"","sources":["../../src/modules/keycloak.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAOhE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,iBAAkB,SAAQ,gBAAgB;IACrD,OAAO,CAAC,kBAAkB,CAAW;IACrC,OAAO,CAAC,kBAAkB,CAAW;gBAEzB,KAAK,SAAmC;WAW9B,KAAK,CAAC,KAAK,SAAmC,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAIjG,iEAAiE;IACjE,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKzC,iEAAiE;IACjE,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKzC,iEAAiE;IACjE,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,iEAAiE;IACjE,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,4DAA4D;IAC5D,IAAI,aAAa,IAAI,MAAM,CAE1B;CACF"}