File size: 9,402 Bytes
a757bd3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | import unittest
from pathlib import Path
class RuntimeUserDefaultsTests(unittest.TestCase):
@staticmethod
def _repo_root() -> Path:
return Path(__file__).resolve().parents[1]
@classmethod
def _dockerfile_path(cls) -> Path:
return cls._repo_root() / "Dockerfile"
@classmethod
def _entrypoint_path(cls) -> Path:
return cls._repo_root() / "scripts" / "openclaw-entrypoint.sh"
def test_dockerfile_defaults_to_root_runtime_home(self):
dockerfile = self._dockerfile_path().read_text(encoding="utf-8")
self.assertIn("ARG OPENCLAW_VERSION", dockerfile)
self.assertIn("ENV OPENCLAW_VERSION=$OPENCLAW_VERSION", dockerfile)
self.assertIn('OPENCLAW_VERSION_VALUE="${OPENCLAW_VERSION:-latest}"', dockerfile)
self.assertIn("ENV HOME=/root", dockerfile)
self.assertIn("ENV OPENCLAW_HOME=/root", dockerfile)
self.assertIn("ENV OPENCLAW_USER=root", dockerfile)
self.assertIn("ENV OPENCLAW_GROUP=root", dockerfile)
self.assertIn("ENV OPENCLAW_BACKUP_SOURCE_DIR=/root/.openclaw", dockerfile)
self.assertIn("ENV OPENCLAW_BACKUP_ROOT_CONFIG_DIR=/root/.config", dockerfile)
self.assertIn("ENV OPENCLAW_BACKUP_ROOT_CODEX_DIR=/root/.codex", dockerfile)
self.assertIn("ENV OPENCLAW_BACKUP_ROOT_CLAUDE_DIR=/root/.claude", dockerfile)
self.assertIn("ENV OPENCLAW_BACKUP_ROOT_CARGO_DIR=/root/.cargo", dockerfile)
self.assertIn("ENV OPENCLAW_BACKUP_ROOT_PIP_DIR=/root/.pip", dockerfile)
self.assertIn("ENV OPENCLAW_BACKUP_ROOT_RUSTUP_DIR=/root/.rustup", dockerfile)
self.assertIn("ENV OPENCLAW_BACKUP_ROOT_AGENTS_DIR=/root/.agents", dockerfile)
self.assertIn("ENV OPENCLAW_BACKUP_ROOT_SSH_DIR=/root/.ssh", dockerfile)
self.assertIn("ENV OPENCLAW_BACKUP_ROOT_ENV_DIR=/root/.env.d", dockerfile)
self.assertIn("ENV OPENCLAW_BACKUP_ROOT_NPM_DIR=/root/.npm", dockerfile)
self.assertIn("ENV OPENCLAW_BACKUP_ROOT_LARK_CLI_DIR=/root/.lark-cli", dockerfile)
self.assertIn('OPENCLAW_BIN="$(command -v openclaw || true)"', dockerfile)
self.assertIn('if [[ -z "$OPENCLAW_BIN" ]] && [[ -x /root/.npm-global/bin/openclaw ]]; then', dockerfile)
self.assertIn('elif [[ -z "$OPENCLAW_BIN" ]] && [[ -x /root/.local/bin/openclaw ]]; then', dockerfile)
self.assertIn("if [ -x /root/.local/bin/sshx ]; then", dockerfile)
self.assertNotIn("/home/ubuntu/.npm-global/bin/openclaw", dockerfile)
self.assertNotIn("/home/ubuntu/.local/bin/sshx", dockerfile)
def test_dockerfile_does_not_create_ubuntu_user_or_sudoer(self):
dockerfile = self._dockerfile_path().read_text(encoding="utf-8")
self.assertNotIn("useradd --system --create-home --gid ubuntu --shell /bin/bash ubuntu", dockerfile)
self.assertNotIn("ubuntu ALL=(ALL) NOPASSWD:ALL", dockerfile)
self.assertNotIn("/etc/sudoers.d/90-ubuntu-nopasswd", dockerfile)
def test_dockerfile_preinstalls_common_cli_tools(self):
dockerfile = self._dockerfile_path().read_text(encoding="utf-8")
self.assertIn("python3", dockerfile)
self.assertIn("vim \\", dockerfile)
self.assertIn("neovim", dockerfile)
self.assertNotIn("apt-get install -y --no-install-recommends \\\n ca-certificates \\\n chromium-headless-shell", dockerfile)
self.assertIn("googlechromelabs.github.io/chrome-for-testing/LATEST_RELEASE_STABLE", dockerfile)
self.assertIn("chrome-${CFT_ARCH}.zip", dockerfile)
self.assertIn('CFT_DIR="chrome-${CFT_ARCH}"', dockerfile)
self.assertIn('ln -sf "/opt/${CFT_DIR}/chrome" /usr/local/bin/chromium', dockerfile)
self.assertIn("gh", dockerfile)
self.assertIn(
"npm install -g --no-audit --no-fund opencode-ai @openai/codex @anthropic-ai/claude-code",
dockerfile,
)
self.assertIn("for cmd in opencode codex claude; do", dockerfile)
self.assertIn('ln -sf "$CLI_BIN" "/usr/local/bin/$cmd"', dockerfile)
self.assertIn('"/usr/local/bin/$cmd" --help >/dev/null', dockerfile)
self.assertIn("npx skills add larksuite/cli -y -g", dockerfile)
self.assertIn('hf --help >/dev/null', dockerfile)
self.assertIn("uv --version >/dev/null", dockerfile)
def test_entrypoint_defaults_to_root_runtime_user(self):
entrypoint = self._entrypoint_path().read_text(encoding="utf-8")
self.assertIn('OPENCLAW_USER="${OPENCLAW_USER:-root}"', entrypoint)
self.assertIn('OPENCLAW_GROUP="${OPENCLAW_GROUP:-root}"', entrypoint)
self.assertIn('OPENCLAW_HOME="${OPENCLAW_HOME:-/root}"', entrypoint)
self.assertIn('OPENCLAW_BACKUP_SOURCE_DIR="${OPENCLAW_BACKUP_SOURCE_DIR:-${OPENCLAW_STATE_DIR}}"', entrypoint)
self.assertIn('OPENCLAW_BACKUP_ROOT_CONFIG_DIR="${OPENCLAW_BACKUP_ROOT_CONFIG_DIR:-/root/.config}"', entrypoint)
self.assertIn('OPENCLAW_BACKUP_ROOT_CODEX_DIR="${OPENCLAW_BACKUP_ROOT_CODEX_DIR:-/root/.codex}"', entrypoint)
self.assertIn('OPENCLAW_BACKUP_ROOT_CLAUDE_DIR="${OPENCLAW_BACKUP_ROOT_CLAUDE_DIR:-/root/.claude}"', entrypoint)
self.assertIn('OPENCLAW_BACKUP_ROOT_CARGO_DIR="${OPENCLAW_BACKUP_ROOT_CARGO_DIR:-/root/.cargo}"', entrypoint)
self.assertIn('OPENCLAW_BACKUP_ROOT_PIP_DIR="${OPENCLAW_BACKUP_ROOT_PIP_DIR:-/root/.pip}"', entrypoint)
self.assertIn('OPENCLAW_BACKUP_ROOT_RUSTUP_DIR="${OPENCLAW_BACKUP_ROOT_RUSTUP_DIR:-/root/.rustup}"', entrypoint)
self.assertIn('OPENCLAW_BACKUP_ROOT_AGENTS_DIR="${OPENCLAW_BACKUP_ROOT_AGENTS_DIR:-/root/.agents}"', entrypoint)
self.assertIn('OPENCLAW_BACKUP_ROOT_SSH_DIR="${OPENCLAW_BACKUP_ROOT_SSH_DIR:-/root/.ssh}"', entrypoint)
self.assertIn('OPENCLAW_BACKUP_ROOT_ENV_DIR="${OPENCLAW_BACKUP_ROOT_ENV_DIR:-/root/.env.d}"', entrypoint)
self.assertIn('OPENCLAW_BACKUP_ROOT_NPM_DIR="${OPENCLAW_BACKUP_ROOT_NPM_DIR:-/root/.npm}"', entrypoint)
self.assertIn('OPENCLAW_BACKUP_ROOT_LARK_CLI_DIR="${OPENCLAW_BACKUP_ROOT_LARK_CLI_DIR:-/root/.lark-cli}"', entrypoint)
def test_backup_cron_uses_openclaw_user(self):
entrypoint = self._entrypoint_path().read_text(encoding="utf-8")
self.assertIn(
'${OPENCLAW_BACKUP_CRON} ${OPENCLAW_USER} /usr/local/bin/openclaw-backup-cron.sh',
entrypoint,
)
self.assertNotIn(
"${OPENCLAW_BACKUP_CRON} root /usr/local/bin/openclaw-backup-cron.sh",
entrypoint,
)
def test_entrypoint_does_not_rechown_entire_openclaw_home(self):
entrypoint = self._entrypoint_path().read_text(encoding="utf-8")
self.assertNotIn('find "$OPENCLAW_HOME" -xdev -exec chown "$OPENCLAW_USER:$OPENCLAW_GROUP" {} +', entrypoint)
self.assertNotIn('chown -R "$OPENCLAW_USER:$OPENCLAW_GROUP" "$OPENCLAW_HOME"', entrypoint)
self.assertNotIn(' "$OPENCLAW_HOME" \\', entrypoint)
def test_backup_cron_setup_skips_when_not_root(self):
entrypoint = self._entrypoint_path().read_text(encoding="utf-8")
self.assertIn(
'setup_backup_cron() {\n if [[ "$(id -u)" -ne 0 ]]; then',
entrypoint,
)
def test_backup_env_file_includes_keep_count(self):
entrypoint = self._entrypoint_path().read_text(encoding="utf-8")
self.assertIn("OPENCLAW_BACKUP_KEEP_COUNT", entrypoint)
self.assertIn("OPENCLAW_BACKUP_ROOT_CONFIG_DIR", entrypoint)
self.assertIn("OPENCLAW_BACKUP_ROOT_CODEX_DIR", entrypoint)
self.assertIn("OPENCLAW_BACKUP_ROOT_CLAUDE_DIR", entrypoint)
self.assertIn("OPENCLAW_BACKUP_ROOT_CARGO_DIR", entrypoint)
self.assertIn("OPENCLAW_BACKUP_ROOT_PIP_DIR", entrypoint)
self.assertIn("OPENCLAW_BACKUP_ROOT_RUSTUP_DIR", entrypoint)
self.assertIn("OPENCLAW_BACKUP_ROOT_AGENTS_DIR", entrypoint)
self.assertIn("OPENCLAW_BACKUP_ROOT_SSH_DIR", entrypoint)
self.assertIn("OPENCLAW_BACKUP_ROOT_ENV_DIR", entrypoint)
self.assertIn("OPENCLAW_BACKUP_ROOT_NPM_DIR", entrypoint)
self.assertIn("OPENCLAW_BACKUP_ROOT_LARK_CLI_DIR", entrypoint)
def test_sshx_auto_start_does_not_use_command_substitution(self):
entrypoint = self._entrypoint_path().read_text(encoding="utf-8")
self.assertNotIn('OPENCLAW_SSHX_PID="$(run_as_node_background_stdout sshx)"', entrypoint)
def test_sshx_logs_directly_to_container_stdout_stderr(self):
entrypoint = self._entrypoint_path().read_text(encoding="utf-8")
self.assertIn('gosu "$OPENCLAW_USER:$OPENCLAW_GROUP" sshx >/proc/1/fd/1 2>/proc/1/fd/2 &', entrypoint)
self.assertIn("sshx >/proc/1/fd/1 2>/proc/1/fd/2 &", entrypoint)
self.assertNotIn('gosu "$OPENCLAW_USER:$OPENCLAW_GROUP" sshx >>"$OPENCLAW_STDOUT_LOG_PATH" 2>>"$OPENCLAW_STDERR_LOG_PATH" &', entrypoint)
self.assertNotIn('sshx >>"$OPENCLAW_STDOUT_LOG_PATH" 2>>"$OPENCLAW_STDERR_LOG_PATH" &', entrypoint)
def test_docker_healthcheck_does_not_send_gateway_token_header(self):
dockerfile = self._dockerfile_path().read_text(encoding="utf-8")
self.assertIn("HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3", dockerfile)
self.assertIn("curl -f http://localhost:7860", dockerfile)
self.assertNotIn("x-openclaw-token", dockerfile)
if __name__ == "__main__":
unittest.main()
|