File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -8,6 +8,11 @@ Newest first. `Unreleased` is what is on `main` and not yet tagged.
88
99## Unreleased
1010
11+ ### A bad ` COMPUTER_MEMORY_BYTES ` refuses to start the supervisor, instead of capping a computer at 512 bytes
12+
13+ ` COMPUTER_MEMORY_BYTES=512m ` used to parse as ` 512 ` via ` parseInt ` , which Docker accepts as a memory
14+ cap Chromium cannot live in. Empty ` COMPUTER_MEMORY_BYTES= ` is still unset (no cap). A value that is
15+ not a whole number of bytes now exits before any computer is created.
1116### An IPv6 address in ` AGENT_ENDPOINT_ALLOWED_HOSTS ` now matches however it is written
1217
1318The endpoint check compares the list against the address as the URL parser spells it, compressed
Original file line number Diff line number Diff line change 1+ /**
2+ * Optional Docker memory cap for each computer, from `COMPUTER_MEMORY_BYTES`.
3+ *
4+ * Unset or empty (compose blank, leftover `.env` line) means no cap. The same empty-string and
5+ * prefix traps as `listenPort`: `Number.parseInt("", 10)` is `NaN` (silently dropped) and
6+ * `Number.parseInt("512m", 10)` is `512` bytes, which Docker accepts and Chromium cannot live in.
7+ */
8+ export function computerMemoryBytes (
9+ raw : string | undefined ,
10+ ) : { ok : true ; bytes : number | undefined } | { ok : false ; reason : string } {
11+ const trimmed = raw ?. trim ( ) ;
12+ if ( ! trimmed ) return { ok : true , bytes : undefined } ;
13+ if ( ! / ^ \d + $ / . test ( trimmed ) ) {
14+ return {
15+ ok : false ,
16+ reason : `COMPUTER_MEMORY_BYTES must be a whole number of bytes (got ${ JSON . stringify ( raw ) } ).` ,
17+ } ;
18+ }
19+ const value = Number . parseInt ( trimmed , 10 ) ;
20+ if ( value < 1 ) {
21+ return {
22+ ok : false ,
23+ reason : `COMPUTER_MEMORY_BYTES must be a whole number of bytes (got ${ JSON . stringify ( raw ) } ).` ,
24+ } ;
25+ }
26+ return { ok : true , bytes : value } ;
27+ }
Original file line number Diff line number Diff line change @@ -12,6 +12,7 @@ import {
1212} from "./docker" ;
1313import { registerEntry } from "./identity" ;
1414import { namesFor } from "./names" ;
15+ import { computerMemoryBytes } from "./computer-memory-bytes" ;
1516import { listenPort } from "./listen-port" ;
1617
1718/**
@@ -60,9 +61,12 @@ if (!token) {
6061const image = process . env . COMPUTER_IMAGE ?? "openbot-agent-computer:latest" ;
6162const network = process . env . COMPUTER_NETWORK ;
6263const runtime = process . env . COMPUTER_RUNTIME ;
63- const memoryBytes = process . env . COMPUTER_MEMORY_BYTES
64- ? Number . parseInt ( process . env . COMPUTER_MEMORY_BYTES , 10 )
65- : undefined ;
64+ const resolvedMemory = computerMemoryBytes ( process . env . COMPUTER_MEMORY_BYTES ) ;
65+ if ( ! resolvedMemory . ok ) {
66+ console . error ( resolvedMemory . reason ) ;
67+ process . exit ( 1 ) ;
68+ }
69+ const memoryBytes = resolvedMemory . bytes ;
6670const spireSocketVolume = process . env . SPIRE_AGENT_SOCKET_VOLUME ;
6771
6872/**
Original file line number Diff line number Diff line change 1+ import { describe , expect , test } from "bun:test" ;
2+ import { computerMemoryBytes } from "../src/computer-memory-bytes" ;
3+
4+ describe ( "supervisor computer memory bytes" , ( ) => {
5+ test ( "unset and empty string mean no cap" , ( ) => {
6+ expect ( computerMemoryBytes ( undefined ) ) . toEqual ( {
7+ ok : true ,
8+ bytes : undefined ,
9+ } ) ;
10+ expect ( computerMemoryBytes ( "" ) ) . toEqual ( { ok : true , bytes : undefined } ) ;
11+ expect ( computerMemoryBytes ( " " ) ) . toEqual ( { ok : true , bytes : undefined } ) ;
12+ } ) ;
13+
14+ test ( "a whole number of bytes is accepted" , ( ) => {
15+ expect ( computerMemoryBytes ( "1073741824" ) ) . toEqual ( {
16+ ok : true ,
17+ bytes : 1_073_741_824 ,
18+ } ) ;
19+ expect ( computerMemoryBytes ( "1" ) ) . toEqual ( { ok : true , bytes : 1 } ) ;
20+ } ) ;
21+
22+ test ( "suffix units and non-digits are refused instead of parseInt prefixes" , ( ) => {
23+ expect ( computerMemoryBytes ( "512m" ) . ok ) . toBe ( false ) ;
24+ expect ( computerMemoryBytes ( "1e9" ) . ok ) . toBe ( false ) ;
25+ expect ( computerMemoryBytes ( "0" ) . ok ) . toBe ( false ) ;
26+ expect ( computerMemoryBytes ( "-1" ) . ok ) . toBe ( false ) ;
27+ expect ( computerMemoryBytes ( "1.5" ) . ok ) . toBe ( false ) ;
28+ } ) ;
29+ } ) ;
You can’t perform that action at this time.
0 commit comments