Skip to content

Commit 6a48258

Browse files
committed
fix: recognize rootless docker resource rejection
1 parent d24510f commit 6a48258

3 files changed

Lines changed: 128 additions & 0 deletions

File tree

scripts/lib/docker-e2e-container.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,12 @@ docker_e2e_resource_limit_error_file() {
200200
esac
201201
case "$text" in
202202
*cgroup*controller* | *cgroup*controllers* | *cgroup*not*supported* | \
203+
*cgroup*is*not*mounted* | *cgroup*not*mounted* | \
203204
*Cgroup*controller* | *Cgroup*controllers* | *Cgroup*not*supported* | \
205+
*Cgroup*is*not*mounted* | *Cgroup*not*mounted* | \
204206
*pids*not*available* | *pids*not*supported* | *cannot*set*pids*limit* | \
205207
*PIDs*not*available* | *PIDs*not*supported* | *cannot*set*PIDs*limit* | \
208+
*NanoCPUs*can*not*be*set* | *CPU*CFS*scheduler* | \
206209
*cpu*controller* | *CPU*controller* | *memory*controller* | *Memory*controller* | \
207210
*resource*limit*not*supported* | *Resource*limit*not*supported* | \
208211
*oci*runtime*cgroup* | *OCI*runtime*cgroup*)

scripts/lib/docker-e2e-package.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,12 @@ if ! declare -F docker_e2e_docker_run_resource_args >/dev/null 2>&1; then
5555
esac
5656
case "$text" in
5757
*cgroup*controller* | *cgroup*controllers* | *cgroup*not*supported* | \
58+
*cgroup*is*not*mounted* | *cgroup*not*mounted* | \
5859
*Cgroup*controller* | *Cgroup*controllers* | *Cgroup*not*supported* | \
60+
*Cgroup*is*not*mounted* | *Cgroup*not*mounted* | \
5961
*pids*not*available* | *pids*not*supported* | *cannot*set*pids*limit* | \
6062
*PIDs*not*available* | *PIDs*not*supported* | *cannot*set*PIDs*limit* | \
63+
*NanoCPUs*can*not*be*set* | *CPU*CFS*scheduler* | \
6164
*cpu*controller* | *CPU*controller* | *memory*controller* | *Memory*controller* | \
6265
*resource*limit*not*supported* | *Resource*limit*not*supported* | \
6366
*oci*runtime*cgroup* | *OCI*runtime*cgroup*)

test/scripts/docker-build-helper.test.ts

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,6 +1298,62 @@ docker_e2e_docker_cmd run second
12981298
}
12991299
});
13001300

1301+
it("retries Docker runs when rootless daemons reject NanoCPUs", () => {
1302+
const workDir = mkdtempSync(join(tmpdir(), "openclaw-docker-rootless-nanocpus-"));
1303+
1304+
try {
1305+
const binDir = join(workDir, "bin");
1306+
mkdirSync(binDir);
1307+
writeFileSync(
1308+
join(binDir, "timeout"),
1309+
`#!/bin/bash
1310+
set -euo pipefail
1311+
if [[ "$1" = "--kill-after=1s" ]]; then
1312+
exit 0
1313+
fi
1314+
shift 2
1315+
"$@"
1316+
`,
1317+
);
1318+
chmodSync(join(binDir, "timeout"), 0o755);
1319+
const rootDir = process.cwd();
1320+
const script = `
1321+
set -euo pipefail
1322+
ROOT_DIR=${shellQuote(rootDir)}
1323+
TMPDIR=${shellQuote(workDir)}
1324+
export ROOT_DIR TMPDIR
1325+
export PATH="$TMPDIR/bin:$PATH"
1326+
unset OPENCLAW_DOCKER_E2E_DISABLE_RESOURCE_LIMITS
1327+
unset OPENCLAW_DOCKER_E2E_MEMORY OPENCLAW_DOCKER_E2E_CPUS OPENCLAW_DOCKER_E2E_PIDS_LIMIT
1328+
export OPENCLAW_DOCKER_E2E_AVAILABLE_CPUS=32
1329+
1330+
docker() {
1331+
printf "%s\\n" "$*" >>"$TMPDIR/docker-seen"
1332+
if [[ "$*" == *"--cpus"* ]]; then
1333+
echo "docker: Error response from daemon: NanoCPUs can not be set, as your kernel does not support CPU CFS scheduler or the cgroup is not mounted" >&2
1334+
return 125
1335+
fi
1336+
}
1337+
export -f docker
1338+
1339+
source "$ROOT_DIR/scripts/lib/docker-e2e-container.sh"
1340+
1341+
docker_e2e_docker_cmd run demo 2>"$TMPDIR/stderr"
1342+
1343+
mapfile -t docker_seen <"$TMPDIR/docker-seen"
1344+
[[ "\${docker_seen[0]}" = "run --memory 8g --cpus 16 --pids-limit 2048 demo" ]]
1345+
[[ "\${docker_seen[1]}" = "run demo" ]]
1346+
[[ "\${#docker_seen[@]}" = "2" ]]
1347+
grep -Fq "NanoCPUs can not be set" "$TMPDIR/stderr"
1348+
grep -Fq "retrying without default" "$TMPDIR/stderr"
1349+
`;
1350+
1351+
execFileSync("bash", ["-lc", script], { encoding: "utf8" });
1352+
} finally {
1353+
rmSync(workDir, { recursive: true, force: true });
1354+
}
1355+
});
1356+
13011357
it("ignores Docker-like command arguments after the image when cleaning up a resource-limit retry", () => {
13021358
const workDir = mkdtempSync(join(tmpdir(), "openclaw-docker-cgroup-image-boundary-"));
13031359

@@ -1884,6 +1940,72 @@ mapfile -t docker_seen <"$TMPDIR/docker-seen"
18841940
}
18851941
});
18861942

1943+
it("retries package-backed Docker runs when rootless daemons reject NanoCPUs", () => {
1944+
const workDir = mkdtempSync(join(tmpdir(), "openclaw-docker-package-rootless-nanocpus-"));
1945+
1946+
try {
1947+
const binDir = join(workDir, "bin");
1948+
mkdirSync(binDir);
1949+
writeFileSync(
1950+
join(binDir, "gtimeout"),
1951+
`#!/bin/bash
1952+
set -euo pipefail
1953+
if [[ "$1" = "--kill-after=1s" ]]; then
1954+
exit 0
1955+
fi
1956+
shift 2
1957+
"$@"
1958+
`,
1959+
);
1960+
chmodSync(join(binDir, "gtimeout"), 0o755);
1961+
const rootDir = process.cwd();
1962+
const script = `
1963+
set -euo pipefail
1964+
ROOT_DIR=${shellQuote(rootDir)}
1965+
TMPDIR=${shellQuote(workDir)}
1966+
export ROOT_DIR TMPDIR
1967+
export PATH="$TMPDIR/bin"
1968+
export OPENCLAW_DOCKER_E2E_RUN_TIMEOUT=15s
1969+
export OPENCLAW_DOCKER_E2E_AVAILABLE_CPUS=8
1970+
unset OPENCLAW_DOCKER_E2E_DISABLE_RESOURCE_LIMITS
1971+
unset OPENCLAW_DOCKER_E2E_MEMORY OPENCLAW_DOCKER_E2E_CPUS OPENCLAW_DOCKER_E2E_PIDS_LIMIT
1972+
1973+
dirname() {
1974+
/usr/bin/dirname "$@"
1975+
}
1976+
1977+
docker_e2e_docker_cmd() {
1978+
return 0
1979+
}
1980+
1981+
docker() {
1982+
printf "%s\\n" "$*" >>"$TMPDIR/docker-seen"
1983+
if [[ "$*" == *"--cpus"* ]]; then
1984+
echo "docker: Error response from daemon: NanoCPUs can not be set, as your kernel does not support CPU CFS scheduler or the cgroup is not mounted" >&2
1985+
return 125
1986+
fi
1987+
}
1988+
export -f docker_e2e_docker_cmd docker
1989+
1990+
source "$ROOT_DIR/scripts/lib/docker-e2e-package.sh"
1991+
1992+
docker_e2e_docker_run_cmd run demo 2>"$TMPDIR/stderr"
1993+
1994+
mapfile -t docker_seen <"$TMPDIR/docker-seen"
1995+
[[ "\${docker_seen[0]}" = "run --memory 8g --cpus 8 --pids-limit 2048 demo" ]]
1996+
[[ "\${docker_seen[1]}" = "run demo" ]]
1997+
[[ "\${#docker_seen[@]}" = "2" ]]
1998+
stderr="$(<"$TMPDIR/stderr")"
1999+
[[ "$stderr" = *"NanoCPUs can not be set"* ]]
2000+
[[ "$stderr" = *"retrying without default"* ]]
2001+
`;
2002+
2003+
execFileSync("bash", ["-lc", script], { encoding: "utf8" });
2004+
} finally {
2005+
rmSync(workDir, { recursive: true, force: true });
2006+
}
2007+
});
2008+
18872009
it("ignores package-backed Docker-like command arguments after the image when cleaning up a resource-limit retry", () => {
18882010
const workDir = mkdtempSync(join(tmpdir(), "openclaw-docker-package-image-boundary-"));
18892011

0 commit comments

Comments
 (0)