252 lines
5.5 KiB
Bash
252 lines
5.5 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
BASE_DIR="${BASE_DIR:-/usr/share/cockpit/fester}"
|
|
|
|
echo "🧠 Fester Full System Bootstrap Installer"
|
|
echo "Target: $BASE_DIR"
|
|
echo "------------------------------------------------"
|
|
|
|
mkdir -p "$BASE_DIR"
|
|
|
|
# ============================================================
|
|
# CONFIG WIZARD (FIRST RUN INTERFACE)
|
|
# ============================================================
|
|
|
|
echo ""
|
|
echo "⚙️ First-run configuration"
|
|
echo "------------------------------------------------"
|
|
|
|
read -rp "Cluster name [fester-cluster]: " CLUSTER_NAME
|
|
CLUSTER_NAME=${CLUSTER_NAME:-fester-cluster}
|
|
|
|
read -rp "Enable libvirt integration? (y/n) [y]: " LIBVIRT
|
|
LIBVIRT=${LIBVIRT:-y}
|
|
|
|
read -rp "Enable LXC integration? (y/n) [y]: " LXC
|
|
LXC=${LXC:-y}
|
|
|
|
read -rp "Enable distcc integration? (y/n) [y]: " DISTCC
|
|
DISTCC=${DISTCC:-y}
|
|
|
|
read -rp "Enable MinIO cache backend? (y/n) [y]: " MINIO
|
|
MINIO=${MINIO:-y}
|
|
|
|
echo ""
|
|
echo "📦 Writing configuration files..."
|
|
|
|
# ============================================================
|
|
# ROOT CONFIG
|
|
# ============================================================
|
|
|
|
cat > "$BASE_DIR/config.yaml" <<EOF
|
|
cluster:
|
|
name: $CLUSTER_NAME
|
|
|
|
integrations:
|
|
libvirt: $LIBVIRT
|
|
lxc: $LXC
|
|
distcc: $DISTCC
|
|
minio: $MINIO
|
|
|
|
observability:
|
|
prometheus: true
|
|
grafana: true
|
|
|
|
scheduler:
|
|
mode: weighted-thermal-aware
|
|
EOF
|
|
|
|
|
|
# ============================================================
|
|
# LICENSE (AGPL + AS-IS)
|
|
# ============================================================
|
|
|
|
cat > "$BASE_DIR/LICENSE" <<'EOF'
|
|
Fester Distributed Build System
|
|
|
|
Licensed under GNU AGPL v3
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License.
|
|
|
|
This software is provided "AS IS", without warranty of any kind.
|
|
EOF
|
|
|
|
|
|
# ============================================================
|
|
# CHEATSHEET
|
|
# ============================================================
|
|
|
|
cat > "$BASE_DIR/CHEATSHEET.md" <<'EOF'
|
|
# 🧠 Fester Cheatsheet
|
|
|
|
## Build
|
|
fester build <project>
|
|
|
|
## Node Control
|
|
fester node list
|
|
fester node set-policy <node> preferred|avoid
|
|
|
|
## Debug
|
|
/api/autopsy/<id>
|
|
/api/replay/<id>
|
|
|
|
## UI
|
|
- Live DAG: /ui/live_dag.html
|
|
- Replay: /ui/replay.html
|
|
EOF
|
|
|
|
|
|
# ============================================================
|
|
# INDEX PAGE (COCKPIT ENTRY)
|
|
# ============================================================
|
|
|
|
cat > "$BASE_DIR/index.html" <<'EOF'
|
|
<html>
|
|
<head><title>Fester Control Plane</title></head>
|
|
<body>
|
|
<h1>Fester Cluster Control</h1>
|
|
<ul>
|
|
<li><a href="/ui/live_dag.html">Live DAG</a></li>
|
|
<li><a href="/ui/replay.html">Replay</a></li>
|
|
</ul>
|
|
</body>
|
|
</html>
|
|
EOF
|
|
|
|
|
|
# ============================================================
|
|
# UI: LIVE DAG (FULL FILE)
|
|
# ============================================================
|
|
|
|
cat > "$BASE_DIR/ui_live_dag.html" <<'EOF'
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<style>
|
|
body { background:#0e0f12; color:#ddd; font-family:monospace; }
|
|
.node { padding:6px; margin:4px; background:#222; display:inline-block; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="graph"></div>
|
|
|
|
<script>
|
|
const ws = new WebSocket("ws://localhost:8080/ws");
|
|
|
|
ws.onmessage = (msg) => {
|
|
const e = JSON.parse(msg.data);
|
|
|
|
const g = document.getElementById("graph");
|
|
const d = document.createElement("div");
|
|
d.className = "node";
|
|
|
|
d.innerText =
|
|
(e.type || "event") + " | " +
|
|
(e.node || "") + " | " +
|
|
(e.state || "");
|
|
|
|
g.appendChild(d);
|
|
};
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|
|
EOF
|
|
|
|
|
|
# ============================================================
|
|
# PROMETHEUS CONFIG
|
|
# ============================================================
|
|
|
|
cat > "$BASE_DIR/add-to-prometheus-config.yml" <<'EOF'
|
|
scrape_configs:
|
|
- job_name: 'fester'
|
|
static_configs:
|
|
- targets: ['localhost:9100']
|
|
EOF
|
|
|
|
|
|
# ============================================================
|
|
# GRAFANA CONFIG
|
|
# ============================================================
|
|
|
|
cat > "$BASE_DIR/add-to-grafana-config.json" <<'EOF'
|
|
{
|
|
"dashboard": {
|
|
"title": "Fester Cluster Overview"
|
|
}
|
|
}
|
|
EOF
|
|
|
|
|
|
# ============================================================
|
|
# CLI TOOL (FULL FILE)
|
|
# ============================================================
|
|
|
|
mkdir -p "$BASE_DIR/cli"
|
|
|
|
cat > "$BASE_DIR/cli/fester.py" <<'EOF'
|
|
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
sub = parser.add_subparsers(dest="cmd")
|
|
|
|
build = sub.add_parser("build")
|
|
build.add_argument("project")
|
|
|
|
node = sub.add_parser("node")
|
|
node.add_argument("action")
|
|
node.add_argument("target", nargs="*")
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.cmd == "build":
|
|
print("Building:", args.project)
|
|
|
|
elif args.cmd == "node":
|
|
print("Node action:", args.action, args.target)
|
|
|
|
else:
|
|
print("Fester CLI ready")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
EOF
|
|
|
|
chmod +x "$BASE_DIR/cli/fester.py"
|
|
|
|
|
|
# ============================================================
|
|
# SIMPLE COCKPIT MANIFEST
|
|
# ============================================================
|
|
|
|
cat > "$BASE_DIR/manifest.json" <<'EOF'
|
|
{
|
|
"version": 1,
|
|
"name": "fester",
|
|
"label": "Fester Cluster Control",
|
|
"entrypoint": "index.html"
|
|
}
|
|
EOF
|
|
|
|
|
|
# ============================================================
|
|
# FINAL OUTPUT
|
|
# ============================================================
|
|
|
|
echo ""
|
|
echo "------------------------------------------------"
|
|
echo "✅ Fester installation complete"
|
|
echo "📍 Installed at: $BASE_DIR"
|
|
echo ""
|
|
echo "Next steps:"
|
|
echo " 1. Open Cockpit"
|
|
echo " 2. Select Fester module"
|
|
echo " 3. Open Live DAG"
|
|
echo "------------------------------------------------"
|