Agent fixed for dev provision 12-24-25

This commit is contained in:
jester 2025-12-24 19:31:39 +00:00
parent 8645548c4a
commit 3078112498
12 changed files with 155 additions and 142 deletions

View File

@ -17,6 +17,9 @@ func Install(cfg state.Config) error {
if err := executil.RunEmbeddedScript(
"devcontainer/go/install.sh",
"RUNTIME=go",
"ARCHIVE_EXT=tar.gz",
"RUNTIME_VERSION="+cfg.Version,
); err != nil {
return fmt.Errorf("go devcontainer install failed: %w", err)
}

View File

@ -17,6 +17,9 @@ func Install(cfg state.Config) error {
if err := executil.RunEmbeddedScript(
"devcontainer/java/install.sh",
"RUNTIME=java",
"ARCHIVE_EXT=tar.gz",
"RUNTIME_VERSION="+cfg.Version,
); err != nil {
return fmt.Errorf("java devcontainer install failed: %w", err)
}

View File

@ -15,9 +15,11 @@ func Install(cfg state.Config) error {
return nil
}
// Execute embedded installer (mirrors game server model)
if err := executil.RunEmbeddedScript(
"devcontainer/node/install.sh",
"RUNTIME=node",
"ARCHIVE_EXT=tar.xz",
"RUNTIME_VERSION="+cfg.Version,
); err != nil {
return fmt.Errorf("node devcontainer install failed: %w", err)
}

View File

@ -17,6 +17,9 @@ func Install(cfg state.Config) error {
if err := executil.RunEmbeddedScript(
"devcontainer/python/install.sh",
"RUNTIME=python",
"ARCHIVE_EXT=tar.xz",
"RUNTIME_VERSION="+cfg.Version,
); err != nil {
return fmt.Errorf("python devcontainer install failed: %w", err)
}

View File

@ -5,22 +5,30 @@ import (
"fmt"
"os"
"os/exec"
"path"
"strings"
"zlh-agent/scripts"
)
// RunEmbeddedScript executes an embedded script via bash by piping its contents to stdin.
// This mirrors RunScript's stdout/stderr behavior without requiring any files on disk.
func RunEmbeddedScript(path string) error {
normalized := normalizeEmbeddedPath(path)
data, err := scripts.FS.ReadFile(normalized)
// If the script is a devcontainer installer, this automatically prepends the shared common.sh
// so that tiny per-runtime installers can call install_runtime in the same shell session.
func RunEmbeddedScript(scriptPath string, extraEnv ...string) error {
normalized := normalizeEmbeddedPath(scriptPath)
payload, err := loadEmbeddedPayload(normalized)
if err != nil {
return fmt.Errorf("embedded script not found: %s", path)
return err
}
cmd := exec.Command("bash")
cmd.Stdin = bytes.NewReader(data)
cmd.Stdin = bytes.NewReader(payload)
// Inherit current env and overlay any provided vars (e.g., RUNTIME_VERSION=24).
if len(extraEnv) > 0 {
cmd.Env = append(os.Environ(), extraEnv...)
}
// Match RunScript behavior (executil.go)
cmd.Stdout = os.Stdout
@ -29,6 +37,33 @@ func RunEmbeddedScript(path string) error {
return cmd.Run()
}
func normalizeEmbeddedPath(path string) string {
return strings.TrimPrefix(path, "scripts/")
func loadEmbeddedPayload(normalized string) ([]byte, error) {
// If this is a devcontainer installer, prepend the shared library.
if strings.HasPrefix(normalized, "devcontainer/") {
commonPath := "devcontainer/lib/common.sh"
common, err := scripts.FS.ReadFile(commonPath)
if err != nil {
return nil, fmt.Errorf("embedded script missing: %s: %w", commonPath, err)
}
body, err := scripts.FS.ReadFile(normalized)
if err != nil {
return nil, fmt.Errorf("embedded script missing: %s: %w", normalized, err)
}
// Ensure bash sees common first, then runtime installer.
return append(append(common, '\n'), body...), nil
}
data, err := scripts.FS.ReadFile(normalized)
if err != nil {
return nil, fmt.Errorf("embedded script missing: %s: %w", normalized, err)
}
return data, nil
}
func normalizeEmbeddedPath(p string) string {
p = strings.TrimPrefix(p, "scripts/")
p = path.Clean(p)
return strings.TrimPrefix(p, "/")
}

0
logs/agent.log Normal file
View File

View File

@ -1,27 +1,5 @@
#!/usr/bin/env bash
set -euo pipefail
RUNTIME="go"
ARCHIVE_FILE="go-${DEST_VERSION}.tar.gz"
ARCHIVE_EXT="tar.gz"
ARCHIVE_PREFIX="go"
ARTIFACT_BASE_URL="${ZLH_ARTIFACT_BASE_URL:-http://10.60.0.251:8080}"
DEST_DIR="${RUNTIME_ROOT}/${DEST_VERSION}"
ARCHIVE_FILE="go-${DEST_VERSION}.tar.gz"
URL="${ARTIFACT_BASE_URL%/}/devcontainer/go/${DEST_VERSION}/${ARCHIVE_FILE}"
mkdir -p "${RUNTIME_ROOT}"
if [ ! -d "${DEST_DIR}" ]; then
curl -fL "${URL}" -o /tmp/${ARCHIVE_FILE}
mkdir -p "${DEST_DIR}"
tar -xf /tmp/${ARCHIVE_FILE} -C "${DEST_DIR}" --strip-components=1
fi
ln -sfn "${DEST_DIR}" "${RUNTIME_ROOT}/current"
ln -sfn "${DEST_DIR}/bin" "${RUNTIME_ROOT}/bin"
cat >/etc/profile.d/zlh-go.sh <<'EOF'
export PATH="/opt/zlh/runtime/go/bin:$PATH"
EOF
chmod +x /etc/profile.d/zlh-go.sh
install_runtime

View File

@ -1,26 +1,5 @@
#!/usr/bin/env bash
set -euo pipefail
RUNTIME="java"
ARCHIVE_FILE="jdk-${DEST_VERSION}.tar.gz"
ARCHIVE_EXT="tar.gz"
ARCHIVE_PREFIX="jdk"
ARTIFACT_BASE_URL="${ZLH_ARTIFACT_BASE_URL:-http://10.60.0.251:8080}"
DEST_DIR="${RUNTIME_ROOT}/${DEST_VERSION}"
ARCHIVE_FILE="jdk-${DEST_VERSION}.tar.gz"
URL="${ARTIFACT_BASE_URL%/}/devcontainer/java/${DEST_VERSION}/${ARCHIVE_FILE}"
mkdir -p "${RUNTIME_ROOT}"
if [ ! -d "${DEST_DIR}" ]; then
curl -fL "${URL}" -o /tmp/${ARCHIVE_FILE}
mkdir -p "${DEST_DIR}"
tar -xf /tmp/${ARCHIVE_FILE} -C "${DEST_DIR}" --strip-components=1
fi
ln -sfn "${DEST_DIR}" "${RUNTIME_ROOT}/current"
ln -sfn "${DEST_DIR}/bin" "${RUNTIME_ROOT}/bin"
cat >/etc/profile.d/zlh-java.sh <<'EOF'
export PATH="/opt/zlh/runtime/java/bin:$PATH"
EOF
chmod +x /etc/profile.d/zlh-java.sh
install_runtime

View File

@ -0,0 +1,88 @@
#!/usr/bin/env bash
set -euo pipefail
: "${RUNTIME:?RUNTIME required}"
: "${RUNTIME_VERSION:?RUNTIME_VERSION required}"
: "${ARCHIVE_EXT:?ARCHIVE_EXT required}"
ZLH_ARTIFACT_BASE_URL="${ZLH_ARTIFACT_BASE_URL:-http://10.60.0.251:8080}"
ZLH_RUNTIME_ROOT="${ZLH_RUNTIME_ROOT:-/opt/zlh/runtime}"
ARCHIVE_PREFIX="${ARCHIVE_PREFIX:-${RUNTIME}}"
RUNTIME_ROOT="${ZLH_RUNTIME_ROOT}/${RUNTIME}"
DEST_DIR="${RUNTIME_ROOT}/${RUNTIME_VERSION}"
CURRENT_LINK="${RUNTIME_ROOT}/current"
log() { echo "[zlh-installer:${RUNTIME}] $*"; }
fail() { echo "[zlh-installer:${RUNTIME}] ERROR: $*" >&2; exit 1; }
artifact_name() {
echo "${ARCHIVE_PREFIX}-${RUNTIME_VERSION}.${ARCHIVE_EXT}"
}
artifact_url() {
echo "${ZLH_ARTIFACT_BASE_URL%/}/devcontainer/${RUNTIME}/${RUNTIME_VERSION}/$(artifact_name)"
}
download_artifact() {
local url out
url="$(artifact_url)"
out="/tmp/$(artifact_name)"
log "Downloading ${url}"
if command -v curl >/dev/null 2>&1; then
curl -fL "${url}" -o "${out}"
elif command -v wget >/dev/null 2>&1; then
wget -O "${out}" "${url}"
else
fail "curl or wget is required"
fi
}
extract_artifact() {
local out
out="/tmp/$(artifact_name)"
log "Extracting to ${DEST_DIR}"
mkdir -p "${DEST_DIR}"
case "${ARCHIVE_EXT}" in
tar.xz|tar.gz)
tar -xf "${out}" -C "${DEST_DIR}" --strip-components=1
;;
*)
fail "Unsupported archive type: ${ARCHIVE_EXT}"
;;
esac
}
update_symlinks() {
ln -sfn "${DEST_DIR}" "${CURRENT_LINK}"
ln -sfn "${CURRENT_LINK}/bin" "${RUNTIME_ROOT}/bin"
}
write_profile() {
cat >/etc/profile.d/zlh-${RUNTIME}.sh <<EOF
export PATH="${RUNTIME_ROOT}/bin:\$PATH"
EOF
chmod +x /etc/profile.d/zlh-${RUNTIME}.sh
}
install_runtime() {
log "Installing ${RUNTIME} ${RUNTIME_VERSION}"
mkdir -p "${RUNTIME_ROOT}"
if [[ -d "${DEST_DIR}" ]]; then
log "Version already installed at ${DEST_DIR}"
else
download_artifact
extract_artifact
fi
update_symlinks
write_profile
chmod -R 755 "${DEST_DIR}"
log "Install complete"
}

View File

@ -1,33 +1,5 @@
#!/usr/bin/env bash
set -euo pipefail
RUNTIME="node"
RUNTIME_ROOT="/opt/zlh/runtime/${RUNTIME}"
DEST_VERSION="${RUNTIME_VERSION:?RUNTIME_VERSION required}"
ARCHIVE_EXT="tar.xz"
ARCHIVE_PREFIX="node"
ARTIFACT_BASE_URL="${ZLH_ARTIFACT_BASE_URL:-http://10.60.0.251:8080}"
ARCHIVE_FILE="${RUNTIME}-${DEST_VERSION}.tar.xz"
URL="${ARTIFACT_BASE_URL%/}/devcontainer/${RUNTIME}/${DEST_VERSION}/${ARCHIVE_FILE}"
DEST_DIR="${RUNTIME_ROOT}/${DEST_VERSION}"
echo "[${RUNTIME}] Installing ${RUNTIME} ${DEST_VERSION}"
mkdir -p "${RUNTIME_ROOT}"
if [ ! -d "${DEST_DIR}" ]; then
curl -fL "${URL}" -o /tmp/${ARCHIVE_FILE}
mkdir -p "${DEST_DIR}"
tar -xf /tmp/${ARCHIVE_FILE} -C "${DEST_DIR}" --strip-components=1
fi
ln -sfn "${DEST_DIR}" "${RUNTIME_ROOT}/current"
ln -sfn "${DEST_DIR}/bin" "${RUNTIME_ROOT}/bin"
cat >/etc/profile.d/zlh-${RUNTIME}.sh <<EOF
export PATH="/opt/zlh/runtime/${RUNTIME}/bin:\$PATH"
EOF
chmod +x /etc/profile.d/zlh-${RUNTIME}.sh
chmod -R 755 "${DEST_DIR}"
install_runtime

View File

@ -1,55 +1,5 @@
#!/usr/bin/env bash
set -euo pipefail
RUNTIME="python"
ARCHIVE_FILE="python-${DEST_VERSION}.tar.xz"
ARCHIVE_EXT="tar.xz"
ARCHIVE_PREFIX="python"
ARTIFACT_BASE_URL="${ZLH_ARTIFACT_BASE_URL:-http://10.60.0.251:8080}"
DEST_DIR="${RUNTIME_ROOT}/${DEST_VERSION}"
TMP_DIR="/tmp/zlh-python-install"
ARCHIVE_FILE="python-${DEST_VERSION}.tar.xz"
URL="${ARTIFACT_BASE_URL%/}/devcontainer/python/${DEST_VERSION}/${ARCHIVE_FILE}"
echo "[python] Installing Python ${DEST_VERSION}"
mkdir -p "${RUNTIME_ROOT}"
# Idempotency
if [ -d "${DEST_DIR}" ]; then
echo "[python] Python ${DEST_VERSION} already installed at ${DEST_DIR}"
else
echo "[python] Downloading ${URL}"
rm -rf "${TMP_DIR}"
mkdir -p "${TMP_DIR}"
if command -v curl >/dev/null 2>&1; then
curl -fL "${URL}" -o "${TMP_DIR}/${ARCHIVE_FILE}"
elif command -v wget >/dev/null 2>&1; then
wget -O "${TMP_DIR}/${ARCHIVE_FILE}" "${URL}"
else
echo "[python][ERROR] curl or wget is required"
exit 1
fi
echo "[python] Extracting ${ARCHIVE_FILE} -> ${DEST_DIR}"
mkdir -p "${DEST_DIR}"
tar -xf "${TMP_DIR}/${ARCHIVE_FILE}" -C "${DEST_DIR}" --strip-components=1
fi
# Stable symlinks (same model as Node)
ln -sfn "${DEST_DIR}" "${RUNTIME_ROOT}/current"
ln -sfn "${DEST_DIR}/bin" "${RUNTIME_ROOT}/bin"
# System-wide PATH export
cat >/etc/profile.d/zlh-python.sh <<'EOF'
export PATH="/opt/zlh/runtime/python/bin:$PATH"
EOF
chmod +x /etc/profile.d/zlh-python.sh
# Permissions sanity
chmod -R 755 "${DEST_DIR}"
echo "[python] Python ${DEST_VERSION} installed successfully"
install_runtime

BIN
zlh-agent

Binary file not shown.