No One Can Stop Me Now
This commit is contained in:
272
services/setec-manager/internal/handlers/autarch.go
Normal file
272
services/setec-manager/internal/handlers/autarch.go
Normal file
@@ -0,0 +1,272 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"setec-manager/internal/deploy"
|
||||
)
|
||||
|
||||
type autarchStatus struct {
|
||||
Installed bool `json:"installed"`
|
||||
InstallDir string `json:"install_dir"`
|
||||
GitCommit string `json:"git_commit"`
|
||||
VenvReady bool `json:"venv_ready"`
|
||||
PipPackages int `json:"pip_packages"`
|
||||
WebRunning bool `json:"web_running"`
|
||||
WebStatus string `json:"web_status"`
|
||||
DNSRunning bool `json:"dns_running"`
|
||||
DNSStatus string `json:"dns_status"`
|
||||
}
|
||||
|
||||
func (h *Handler) AutarchStatus(w http.ResponseWriter, r *http.Request) {
|
||||
status := h.getAutarchStatus()
|
||||
h.render(w, "autarch.html", status)
|
||||
}
|
||||
|
||||
func (h *Handler) AutarchStatusAPI(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, h.getAutarchStatus())
|
||||
}
|
||||
|
||||
func (h *Handler) getAutarchStatus() autarchStatus {
|
||||
dir := h.Config.Autarch.InstallDir
|
||||
status := autarchStatus{InstallDir: dir}
|
||||
|
||||
// Check if installed
|
||||
if _, err := os.Stat(filepath.Join(dir, ".git")); err == nil {
|
||||
status.Installed = true
|
||||
}
|
||||
|
||||
// Git commit
|
||||
if hash, message, err := deploy.CurrentCommit(dir); err == nil {
|
||||
status.GitCommit = hash + " " + message
|
||||
}
|
||||
|
||||
// Venv
|
||||
status.VenvReady = deploy.VenvExists(dir)
|
||||
|
||||
// Pip packages
|
||||
venvDir := filepath.Join(dir, "venv")
|
||||
if pkgs, err := deploy.ListPackages(venvDir); err == nil {
|
||||
status.PipPackages = len(pkgs)
|
||||
}
|
||||
|
||||
// Web service
|
||||
webActive, _ := deploy.IsActive("autarch-web")
|
||||
status.WebRunning = webActive
|
||||
if webActive {
|
||||
status.WebStatus = "active"
|
||||
} else {
|
||||
status.WebStatus = "inactive"
|
||||
}
|
||||
|
||||
// DNS service
|
||||
dnsActive, _ := deploy.IsActive("autarch-dns")
|
||||
status.DNSRunning = dnsActive
|
||||
if dnsActive {
|
||||
status.DNSStatus = "active"
|
||||
} else {
|
||||
status.DNSStatus = "inactive"
|
||||
}
|
||||
|
||||
return status
|
||||
}
|
||||
|
||||
func (h *Handler) AutarchInstall(w http.ResponseWriter, r *http.Request) {
|
||||
dir := h.Config.Autarch.InstallDir
|
||||
repo := h.Config.Autarch.GitRepo
|
||||
branch := h.Config.Autarch.GitBranch
|
||||
|
||||
if _, err := os.Stat(filepath.Join(dir, ".git")); err == nil {
|
||||
writeError(w, http.StatusConflict, "AUTARCH already installed at "+dir)
|
||||
return
|
||||
}
|
||||
|
||||
depID, _ := h.DB.CreateDeployment(nil, "autarch_install")
|
||||
var output strings.Builder
|
||||
|
||||
steps := []struct {
|
||||
label string
|
||||
fn func() error
|
||||
}{
|
||||
{"Clone from GitHub", func() error {
|
||||
os.MkdirAll(filepath.Dir(dir), 0755)
|
||||
out, err := deploy.Clone(repo, branch, dir)
|
||||
output.WriteString(out)
|
||||
return err
|
||||
}},
|
||||
{"Create Python venv", func() error {
|
||||
return deploy.CreateVenv(dir)
|
||||
}},
|
||||
{"Upgrade pip", func() error {
|
||||
venvDir := filepath.Join(dir, "venv")
|
||||
deploy.UpgradePip(venvDir)
|
||||
return nil
|
||||
}},
|
||||
{"Install pip packages", func() error {
|
||||
reqFile := filepath.Join(dir, "requirements.txt")
|
||||
if _, err := os.Stat(reqFile); err != nil {
|
||||
return nil
|
||||
}
|
||||
venvDir := filepath.Join(dir, "venv")
|
||||
out, err := deploy.InstallRequirements(venvDir, reqFile)
|
||||
output.WriteString(out)
|
||||
return err
|
||||
}},
|
||||
{"Install npm packages", func() error {
|
||||
out, _ := deploy.NpmInstall(dir)
|
||||
output.WriteString(out)
|
||||
return nil
|
||||
}},
|
||||
{"Set permissions", func() error {
|
||||
exec.Command("chown", "-R", "root:root", dir).Run()
|
||||
exec.Command("chmod", "-R", "755", dir).Run()
|
||||
for _, d := range []string{"data", "data/certs", "data/dns", "results", "dossiers", "models"} {
|
||||
os.MkdirAll(filepath.Join(dir, d), 0755)
|
||||
}
|
||||
confPath := filepath.Join(dir, "autarch_settings.conf")
|
||||
if _, err := os.Stat(confPath); err == nil {
|
||||
exec.Command("chmod", "600", confPath).Run()
|
||||
}
|
||||
return nil
|
||||
}},
|
||||
{"Install systemd units", func() error {
|
||||
h.installAutarchUnits(dir)
|
||||
return nil
|
||||
}},
|
||||
}
|
||||
|
||||
for _, step := range steps {
|
||||
output.WriteString(fmt.Sprintf("\n=== %s ===\n", step.label))
|
||||
if err := step.fn(); err != nil {
|
||||
h.DB.FinishDeployment(depID, "failed", output.String())
|
||||
writeError(w, http.StatusInternalServerError, fmt.Sprintf("%s failed: %v", step.label, err))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
h.DB.FinishDeployment(depID, "success", output.String())
|
||||
writeJSON(w, http.StatusOK, map[string]string{"status": "installed"})
|
||||
}
|
||||
|
||||
func (h *Handler) AutarchUpdate(w http.ResponseWriter, r *http.Request) {
|
||||
dir := h.Config.Autarch.InstallDir
|
||||
|
||||
depID, _ := h.DB.CreateDeployment(nil, "autarch_update")
|
||||
var output strings.Builder
|
||||
|
||||
// Git pull
|
||||
out, err := deploy.Pull(dir)
|
||||
output.WriteString(out)
|
||||
if err != nil {
|
||||
h.DB.FinishDeployment(depID, "failed", output.String())
|
||||
writeError(w, http.StatusInternalServerError, "git pull failed")
|
||||
return
|
||||
}
|
||||
|
||||
// Reinstall pip packages
|
||||
reqFile := filepath.Join(dir, "requirements.txt")
|
||||
if _, err := os.Stat(reqFile); err == nil {
|
||||
venvDir := filepath.Join(dir, "venv")
|
||||
pipOut, _ := deploy.InstallRequirements(venvDir, reqFile)
|
||||
output.WriteString(pipOut)
|
||||
}
|
||||
|
||||
// Restart services
|
||||
deploy.Restart("autarch-web")
|
||||
deploy.Restart("autarch-dns")
|
||||
|
||||
h.DB.FinishDeployment(depID, "success", output.String())
|
||||
writeJSON(w, http.StatusOK, map[string]string{"status": "updated"})
|
||||
}
|
||||
|
||||
func (h *Handler) AutarchStart(w http.ResponseWriter, r *http.Request) {
|
||||
deploy.Start("autarch-web")
|
||||
deploy.Start("autarch-dns")
|
||||
writeJSON(w, http.StatusOK, map[string]string{"status": "started"})
|
||||
}
|
||||
|
||||
func (h *Handler) AutarchStop(w http.ResponseWriter, r *http.Request) {
|
||||
deploy.Stop("autarch-web")
|
||||
deploy.Stop("autarch-dns")
|
||||
writeJSON(w, http.StatusOK, map[string]string{"status": "stopped"})
|
||||
}
|
||||
|
||||
func (h *Handler) AutarchRestart(w http.ResponseWriter, r *http.Request) {
|
||||
deploy.Restart("autarch-web")
|
||||
deploy.Restart("autarch-dns")
|
||||
writeJSON(w, http.StatusOK, map[string]string{"status": "restarted"})
|
||||
}
|
||||
|
||||
func (h *Handler) AutarchConfig(w http.ResponseWriter, r *http.Request) {
|
||||
confPath := filepath.Join(h.Config.Autarch.InstallDir, "autarch_settings.conf")
|
||||
data, err := os.ReadFile(confPath)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusNotFound, "config not found")
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]string{"config": string(data)})
|
||||
}
|
||||
|
||||
func (h *Handler) AutarchConfigUpdate(w http.ResponseWriter, r *http.Request) {
|
||||
var body struct {
|
||||
Config string `json:"config"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||
writeError(w, http.StatusBadRequest, "invalid body")
|
||||
return
|
||||
}
|
||||
|
||||
confPath := filepath.Join(h.Config.Autarch.InstallDir, "autarch_settings.conf")
|
||||
if err := os.WriteFile(confPath, []byte(body.Config), 0600); err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]string{"status": "saved"})
|
||||
}
|
||||
|
||||
func (h *Handler) AutarchDNSBuild(w http.ResponseWriter, r *http.Request) {
|
||||
dnsDir := filepath.Join(h.Config.Autarch.InstallDir, "services", "dns-server")
|
||||
|
||||
depID, _ := h.DB.CreateDeployment(nil, "dns_build")
|
||||
|
||||
cmd := exec.Command("go", "build", "-o", "autarch-dns", ".")
|
||||
cmd.Dir = dnsDir
|
||||
out, err := cmd.CombinedOutput()
|
||||
|
||||
if err != nil {
|
||||
h.DB.FinishDeployment(depID, "failed", string(out))
|
||||
writeError(w, http.StatusInternalServerError, "build failed: "+string(out))
|
||||
return
|
||||
}
|
||||
|
||||
h.DB.FinishDeployment(depID, "success", string(out))
|
||||
writeJSON(w, http.StatusOK, map[string]string{"status": "built"})
|
||||
}
|
||||
|
||||
func (h *Handler) installAutarchUnits(dir string) {
|
||||
webUnit := deploy.GenerateUnit(deploy.UnitConfig{
|
||||
Name: "autarch-web",
|
||||
Description: "AUTARCH Web Dashboard",
|
||||
ExecStart: filepath.Join(dir, "venv", "bin", "python3") + " " + filepath.Join(dir, "autarch_web.py"),
|
||||
WorkingDirectory: dir,
|
||||
User: "root",
|
||||
Environment: map[string]string{"PYTHONUNBUFFERED": "1"},
|
||||
})
|
||||
|
||||
dnsUnit := deploy.GenerateUnit(deploy.UnitConfig{
|
||||
Name: "autarch-dns",
|
||||
Description: "AUTARCH DNS Server",
|
||||
ExecStart: filepath.Join(dir, "services", "dns-server", "autarch-dns") + " --config " + filepath.Join(dir, "data", "dns", "config.json"),
|
||||
WorkingDirectory: dir,
|
||||
User: "root",
|
||||
})
|
||||
|
||||
deploy.InstallUnit("autarch-web", webUnit)
|
||||
deploy.InstallUnit("autarch-dns", dnsUnit)
|
||||
}
|
||||
Reference in New Issue
Block a user