From bb9b5deb621353b075674c5a1fd2b686a28619b9 Mon Sep 17 00:00:00 2001 From: jester Date: Tue, 7 Apr 2026 12:28:22 +0000 Subject: [PATCH] updates 4-6-26 --- internal/handlers/files.go | 6 + internal/handlers/minecraft_policy.go | 28 ++ internal/handlers/mods.go | 10 + internal/http/agent.go | 2 +- internal/provcommon/common.go | 2 +- .../provision/addons/codeserver/install.go | 2 +- .../provision/addons/codeserver/verify.go | 2 +- internal/provision/common.go | 59 ++- internal/provision/files.go | 12 +- internal/provision/minecraft/fabric_proxy.go | 417 ++++++++++++++++++ .../provision/minecraft/fabric_proxy_test.go | 78 ++++ internal/provision/minecraft/vanilla.go | 63 +-- internal/provision/minecraft/verify.go | 22 +- internal/provision/provision.go | 46 +- internal/state/state.go | 5 +- internal/system/process.go | 74 +++- internal/update/update.go | 17 +- logs/agent.log | 310 +++++++++++++ logs/lifecycle.log | 0 scripts/addons/codeserver/install.sh | 4 +- scripts/devcontainer/dotnet/install.sh | 2 +- scripts/devcontainer/lib/common.sh | 2 +- state/update.json | 6 + 23 files changed, 1087 insertions(+), 82 deletions(-) create mode 100644 internal/handlers/minecraft_policy.go create mode 100644 internal/provision/minecraft/fabric_proxy.go create mode 100644 internal/provision/minecraft/fabric_proxy_test.go create mode 100644 logs/lifecycle.log create mode 100644 state/update.json diff --git a/internal/handlers/files.go b/internal/handlers/files.go index d10d29d..9e6c773 100644 --- a/internal/handlers/files.go +++ b/internal/handlers/files.go @@ -131,6 +131,12 @@ func HandleGameFilesUpload(w http.ResponseWriter, r *http.Request) { writeFilesError(w, err) return } + if isVanillaModLocked(cfg) && isModsPath(normalizedPath) { + filesLogf(cfg, "action=upload path=%s overwrite=%t status=denied reason=vanilla_mod_policy", normalizedPath, strings.EqualFold(r.URL.Query().Get("overwrite"), "true")) + log.Printf("[mods] vmid=%d enforcement=vanilla user_mods_blocked=true", cfg.VMID) + writeJSONError(w, http.StatusForbidden, "Vanilla servers do not support user-installed mods") + return + } overwrite := strings.EqualFold(r.URL.Query().Get("overwrite"), "true") mr, err := r.MultipartReader() diff --git a/internal/handlers/minecraft_policy.go b/internal/handlers/minecraft_policy.go new file mode 100644 index 0000000..c522fc7 --- /dev/null +++ b/internal/handlers/minecraft_policy.go @@ -0,0 +1,28 @@ +package handlers + +import ( + "strings" + + "zlh-agent/internal/state" +) + +func isVanillaModLocked(cfg *state.Config) bool { + if cfg == nil { + return false + } + if !strings.EqualFold(cfg.ContainerType, "game") { + return false + } + if !strings.EqualFold(cfg.Game, "minecraft") { + return false + } + if strings.EqualFold(cfg.InternalProfile, "vanilla-fabric") { + return true + } + return strings.EqualFold(cfg.Variant, "vanilla") +} + +func isModsPath(rel string) bool { + rel = strings.TrimSpace(rel) + return rel == "mods" || strings.HasPrefix(rel, "mods/") +} diff --git a/internal/handlers/mods.go b/internal/handlers/mods.go index de9b096..34ad9ad 100644 --- a/internal/handlers/mods.go +++ b/internal/handlers/mods.go @@ -51,6 +51,11 @@ func HandleGameModsInstall(w http.ResponseWriter, r *http.Request) { if !ok { return } + if isVanillaModLocked(cfg) { + modsLogf(cfg, "enforcement=vanilla user_mods_blocked=true action=install status=denied") + writeJSONError(w, http.StatusForbidden, "Vanilla servers do not support user-installed mods") + return + } var req mods.InstallRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { @@ -148,6 +153,11 @@ func HandleGameModByID(w http.ResponseWriter, r *http.Request) { if !ok { return } + if isVanillaModLocked(cfg) { + modsLogf(cfg, "enforcement=vanilla user_mods_blocked=true action=%s status=denied", strings.ToLower(r.Method)) + writeJSONError(w, http.StatusForbidden, "Vanilla servers do not support user-installed mods") + return + } modID := strings.TrimPrefix(r.URL.Path, "/game/mods/") if modID == "" || strings.Contains(modID, "/") || !mods.IsValidModID(modID) { diff --git a/internal/http/agent.go b/internal/http/agent.go index 191fa55..896b3d7 100755 --- a/internal/http/agent.go +++ b/internal/http/agent.go @@ -179,7 +179,7 @@ func ensureProvisioned(cfg *state.Config) error { return runProvisionPipeline(cfg) } - jar := filepath.Join(dir, "server.jar") + jar := filepath.Join(dir, provision.ExpectedMinecraftJar(*cfg)) if fileExists(jar) { return nil } diff --git a/internal/provcommon/common.go b/internal/provcommon/common.go index f5d856e..0a5cd01 100644 --- a/internal/provcommon/common.go +++ b/internal/provcommon/common.go @@ -58,7 +58,7 @@ func BuildArtifactURL(path string) string { base := os.Getenv("ZLH_ARTIFACT_BASE_URL") if base == "" { - base = "http://10.60.0.251:8080/" + base = "http://zlh-artifacts.internal.zlh:8080/" } return strings.TrimRight(base, "/") + "/" + strings.TrimLeft(path, "/") diff --git a/internal/provision/addons/codeserver/install.go b/internal/provision/addons/codeserver/install.go index 857396f..f4094bf 100644 --- a/internal/provision/addons/codeserver/install.go +++ b/internal/provision/addons/codeserver/install.go @@ -10,7 +10,7 @@ import ( func launchEnv(cfg state.Config) []string { extraEnv := []string{ - "CODE_SERVER_PORT=8080", + "CODE_SERVER_PORT=6000", "CODE_SERVER_WORKSPACE=/home/dev/workspace", } if cfg.VMID != 0 { diff --git a/internal/provision/addons/codeserver/verify.go b/internal/provision/addons/codeserver/verify.go index ce3f083..493655b 100644 --- a/internal/provision/addons/codeserver/verify.go +++ b/internal/provision/addons/codeserver/verify.go @@ -79,7 +79,7 @@ func findRunningPID() (int, error) { if !strings.Contains(cmdline, "code-server") { continue } - if !strings.Contains(cmdline, "--bind-addr 0.0.0.0:8080") { + if !strings.Contains(cmdline, "--bind-addr 0.0.0.0:6000") { continue } diff --git a/internal/provision/common.go b/internal/provision/common.go index 55be35a..6ab12d1 100755 --- a/internal/provision/common.go +++ b/internal/provision/common.go @@ -1,50 +1,61 @@ package provision import ( - "os" - "strings" + "os" + "strings" - "zlh-agent/internal/provcommon" - "zlh-agent/internal/state" + "zlh-agent/internal/provcommon" + "zlh-agent/internal/state" ) const ( - ServersRoot = provcommon.ServersRoot - JavaRoot = provcommon.JavaRoot - SteamCMDPath = provcommon.SteamCMDPath + ServersRoot = provcommon.ServersRoot + JavaRoot = provcommon.JavaRoot + SteamCMDPath = provcommon.SteamCMDPath ) func ServerDir(cfg state.Config) string { - return provcommon.ServerDir(cfg) + return provcommon.ServerDir(cfg) } func JavaDir(cfg state.Config) string { - return provcommon.JavaDir(cfg) + return provcommon.JavaDir(cfg) } func BuildArtifactURL(path string) string { - return provcommon.BuildArtifactURL(path) + return provcommon.BuildArtifactURL(path) +} + +func ExpectedMinecraftJar(cfg state.Config) string { + return "server.jar" +} + +func MinecraftRuntime(cfg state.Config) string { + if runtime := strings.ToLower(strings.TrimSpace(cfg.Runtime)); runtime != "" { + return runtime + } + return strings.ToLower(strings.TrimSpace(cfg.Variant)) } // Local fallback used ONLY inside this package — NOT exported. func buildArtifactURL(path string) string { - if strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://") { - return path - } + if strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://") { + return path + } - base := os.Getenv("ZLH_ARTIFACT_BASE_URL") - if base == "" { - base = "http://10.60.0.251:8080/" // fallback - } + base := os.Getenv("ZLH_ARTIFACT_BASE_URL") + if base == "" { + base = "http://zlh-artifacts.internal.zlh:8080/" // fallback + } - return strings.TrimRight(base, "/") + "/" + strings.TrimLeft(path, "/") + return strings.TrimRight(base, "/") + "/" + strings.TrimLeft(path, "/") } func IsSteamGame(game string) bool { - g := strings.ToLower(game) - switch g { - case "valheim", "rust", "terraria", "projectzomboid": - return true - } - return false + g := strings.ToLower(game) + switch g { + case "valheim", "rust", "terraria", "projectzomboid": + return true + } + return false } diff --git a/internal/provision/files.go b/internal/provision/files.go index 49e3382..d47da5b 100755 --- a/internal/provision/files.go +++ b/internal/provision/files.go @@ -10,7 +10,7 @@ import ( ) /* - WriteEula writes eula.txt for all Minecraft variants. +WriteEula writes eula.txt for all Minecraft variants. */ func WriteEula(cfg state.Config) error { dir := ServerDir(cfg) @@ -23,9 +23,9 @@ func WriteEula(cfg state.Config) error { } /* - WriteServerProperties writes server.properties for jar-based Minecraft servers. +WriteServerProperties writes server.properties for jar-based Minecraft servers. - Forge/NeoForge generate their own, so they are skipped. +Forge/NeoForge generate their own, so they are skipped. */ func WriteServerProperties(cfg state.Config) error { variant := strings.ToLower(cfg.Variant) @@ -68,9 +68,9 @@ max-players=20 } /* - WriteStartScript creates start.sh for all supported games. - - Vanilla/Paper/Purpur/Fabric: exec java -jar server.jar - - Forge/NeoForge: use JAVA_TOOL_OPTIONS and run.sh +WriteStartScript creates start.sh for all supported games. +- Vanilla/Paper/Purpur/Fabric: exec java -jar server.jar +- Forge/NeoForge: use JAVA_TOOL_OPTIONS and run.sh */ func WriteStartScript(cfg state.Config) error { dir := ServerDir(cfg) diff --git a/internal/provision/minecraft/fabric_proxy.go b/internal/provision/minecraft/fabric_proxy.go new file mode 100644 index 0000000..737c802 --- /dev/null +++ b/internal/provision/minecraft/fabric_proxy.go @@ -0,0 +1,417 @@ +package minecraft + +import ( + "crypto/sha256" + "encoding/json" + "fmt" + "io" + "log" + "net/http" + "os" + "path/filepath" + "strconv" + "strings" + "sync" + "syscall" + + "zlh-agent/internal/provcommon" + "zlh-agent/internal/state" +) + +var ( + fabricProxyArtifactRoot = "minecraft/fabric/fabric-proxy-lite" + fabricAPIArtifactPath = "minecraft/fabric/fabric-api/fabric-api.jar" + fabricProxyConfigPath = "minecraft/fabric/FabricProxy-Lite.toml" +) + +var ( + fabricProxyMapOnce sync.Once + fabricProxyMap map[string]string + fabricProxyMapErr error +) + +func resolveProxyVersion(mcVersion string) (string, error) { + mappings, err := loadFabricProxyMap() + if err != nil { + return "", err + } + + mcVersion = strings.TrimSpace(mcVersion) + if mcVersion == "" { + return "", fmt.Errorf("empty minecraft version") + } + + compareVersion, err := parseVersion(mcVersion) + if err != nil { + return "", fmt.Errorf("invalid minecraft version %q: %w", mcVersion, err) + } + + if version, ok := mappings[mcVersion]; ok { + return version, nil + } + + for spec, version := range mappings { + start, end, ok := parseVersionRange(spec) + if !ok { + continue + } + if compareVersionSlices(compareVersion, start) >= 0 && compareVersionSlices(compareVersion, end) <= 0 { + return version, nil + } + } + + return "", fmt.Errorf("no fabricproxy-lite mapping for minecraft version %q", mcVersion) +} + +func InjectFabricProxyLite(cfg state.Config) error { + if !shouldInjectFabricProxyLite(cfg) { + return nil + } + + modsDir, targetPath, err := ensureSystemModsDir(cfg) + if err != nil { + log.Printf("[mods] vmid=%d type=system name=fabricproxy-lite error=%v", cfg.VMID, err) + return err + } + + version, err := resolveProxyVersion(cfg.Version) + if err != nil { + log.Printf("[mods] vmid=%d type=system name=fabricproxy-lite error=%v", cfg.VMID, err) + return err + } + + source := proxyArtifactURL(version) + log.Printf("[mods] vmid=%d type=system name=fabricproxy-lite source=artifact version=%s", cfg.VMID, version) + if err := installSystemMod(source, targetPath, modsDir); err != nil { + err = fmt.Errorf("install fabricproxy-lite: %w", err) + log.Printf("[mods] vmid=%d type=system name=fabricproxy-lite error=%v", cfg.VMID, err) + return err + } + log.Printf("[mods] vmid=%d type=system name=fabricproxy-lite installed=true", cfg.VMID) + + fabricAPIPath := filepath.Join(modsDir, "fabric-api.jar") + log.Printf("[mods] vmid=%d type=system name=fabric-api source=artifact", cfg.VMID) + if err := installSystemMod(provcommon.BuildArtifactURL(fabricAPIArtifactPath), fabricAPIPath, modsDir); err != nil { + err = fmt.Errorf("install fabric-api: %w", err) + log.Printf("[mods] vmid=%d type=system name=fabric-api error=%v", cfg.VMID, err) + return err + } + log.Printf("[mods] vmid=%d type=system name=fabric-api installed=true", cfg.VMID) + + if err := installFabricProxyConfig(cfg); err != nil { + log.Printf("[mods] vmid=%d type=system name=fabricproxy-lite-config error=%v", cfg.VMID, err) + return err + } + + return nil +} + +func shouldInjectFabricProxyLite(cfg state.Config) bool { + if !strings.EqualFold(cfg.ContainerType, "game") { + return false + } + if !strings.EqualFold(cfg.Game, "minecraft") { + return false + } + + return strings.EqualFold(cfg.InternalProfile, "vanilla-fabric") +} + +func loadFabricProxyMap() (map[string]string, error) { + fabricProxyMapOnce.Do(func() { + raw, err := fetchArtifact(proxyMapURL()) + if err != nil { + fabricProxyMapErr = fmt.Errorf("read fabricproxy-lite map: %w", err) + return + } + + var mappings map[string]string + if err := json.Unmarshal(raw, &mappings); err != nil { + fabricProxyMapErr = fmt.Errorf("parse fabricproxy-lite map: %w", err) + return + } + if len(mappings) == 0 { + fabricProxyMapErr = fmt.Errorf("fabricproxy-lite map is empty") + return + } + + for spec, version := range mappings { + spec = strings.TrimSpace(spec) + version = strings.TrimSpace(version) + if spec == "" || version == "" { + fabricProxyMapErr = fmt.Errorf("fabricproxy-lite map contains empty key or value") + return + } + if start, end, ok := parseVersionRange(spec); ok { + if compareVersionSlices(start, end) > 0 { + fabricProxyMapErr = fmt.Errorf("invalid fabricproxy-lite range %q", spec) + return + } + continue + } + if _, err := parseVersion(spec); err != nil { + fabricProxyMapErr = fmt.Errorf("invalid fabricproxy-lite version key %q: %w", spec, err) + return + } + } + + fabricProxyMap = mappings + }) + + if fabricProxyMapErr != nil { + return nil, fabricProxyMapErr + } + return fabricProxyMap, nil +} + +func proxyMapURL() string { + return provcommon.BuildArtifactURL(filepath.ToSlash(filepath.Join(fabricProxyArtifactRoot, "map.json"))) +} + +func proxyArtifactURL(version string) string { + rel := filepath.ToSlash(filepath.Join( + fabricProxyArtifactRoot, + version, + fmt.Sprintf("FabricProxy-Lite-%s.jar", version), + )) + return provcommon.BuildArtifactURL(rel) +} + +func ensureSystemModsDir(cfg state.Config) (string, string, error) { + serverDir := provcommon.ServerDir(cfg) + info, err := os.Stat(serverDir) + if err != nil { + return "", "", fmt.Errorf("stat server dir: %w", err) + } + + modsDir := filepath.Join(serverDir, "mods") + created := false + if _, err := os.Stat(modsDir); err != nil { + if !os.IsNotExist(err) { + return "", "", fmt.Errorf("stat mods dir: %w", err) + } + created = true + } + if err := os.MkdirAll(modsDir, info.Mode().Perm()); err != nil { + return "", "", fmt.Errorf("create mods dir: %w", err) + } + if err := syncOwnershipAndPerms(modsDir, info); err != nil { + return "", "", fmt.Errorf("sync mods dir ownership: %w", err) + } + + log.Printf("[provision] vmid=%d profile=vanilla-fabric step=mods_dir created=%t", cfg.VMID, created) + return modsDir, filepath.Join(modsDir, "fabricproxy-lite.jar"), nil +} + +func installFabricProxyConfig(cfg state.Config) error { + serverDir := provcommon.ServerDir(cfg) + info, err := os.Stat(serverDir) + if err != nil { + return fmt.Errorf("stat server dir: %w", err) + } + + configDir := filepath.Join(serverDir, "config") + created := false + if _, err := os.Stat(configDir); err != nil { + if !os.IsNotExist(err) { + return fmt.Errorf("stat config dir: %w", err) + } + created = true + } + if err := os.MkdirAll(configDir, info.Mode().Perm()); err != nil { + return fmt.Errorf("create config dir: %w", err) + } + if err := syncOwnershipAndPerms(configDir, info); err != nil { + return fmt.Errorf("sync config dir ownership: %w", err) + } + + targetPath := filepath.Join(configDir, "FabricProxy-Lite.toml") + if err := installSystemFile(provcommon.BuildArtifactURL(fabricProxyConfigPath), targetPath, configDir, 0o644); err != nil { + return fmt.Errorf("install FabricProxy-Lite.toml: %w", err) + } + log.Printf("[provision] vmid=%d profile=vanilla-fabric step=config_dir created=%t", cfg.VMID, created) + log.Printf("[mods] vmid=%d type=system name=FabricProxy-Lite.toml installed=true", cfg.VMID) + return nil +} + +func parseVersionRange(spec string) ([]int, []int, bool) { + parts := strings.Split(spec, "-") + if len(parts) != 2 { + return nil, nil, false + } + + start, err := parseVersion(parts[0]) + if err != nil { + return nil, nil, false + } + end, err := parseVersion(parts[1]) + if err != nil { + return nil, nil, false + } + return start, end, true +} + +func parseVersion(raw string) ([]int, error) { + raw = strings.TrimSpace(raw) + if raw == "" { + return nil, fmt.Errorf("empty version") + } + + parts := strings.Split(raw, ".") + out := make([]int, 0, len(parts)) + for _, part := range parts { + part = strings.TrimSpace(part) + if part == "" { + return nil, fmt.Errorf("invalid version %q", raw) + } + n, err := strconv.Atoi(part) + if err != nil { + return nil, fmt.Errorf("invalid version segment %q", part) + } + out = append(out, n) + } + return out, nil +} + +func compareVersionSlices(a, b []int) int { + maxLen := len(a) + if len(b) > maxLen { + maxLen = len(b) + } + + for i := 0; i < maxLen; i++ { + ai := 0 + if i < len(a) { + ai = a[i] + } + bi := 0 + if i < len(b) { + bi = b[i] + } + switch { + case ai < bi: + return -1 + case ai > bi: + return 1 + } + } + return 0 +} + +func fetchArtifact(url string) ([]byte, error) { + client := &http.Client{} + resp, err := client.Get(url) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("status %d", resp.StatusCode) + } + return io.ReadAll(resp.Body) +} + +func installSystemMod(url, dst, modsDir string) error { + payload, err := fetchArtifact(url) + if err != nil { + return err + } + + if same, err := sameFileChecksum(dst, payload); err == nil && same { + return syncFileOwnership(dst, modsDir) + } + + tmp, err := os.CreateTemp(filepath.Dir(dst), "fabricproxy-lite-*.jar") + if err != nil { + return err + } + tmpPath := tmp.Name() + defer func() { + _ = os.Remove(tmpPath) + }() + + if _, err := tmp.Write(payload); err != nil { + _ = tmp.Close() + return err + } + if err := tmp.Close(); err != nil { + return err + } + if err := os.Rename(tmpPath, dst); err != nil { + return err + } + return syncFileOwnership(dst, modsDir) +} + +func installSystemFile(url, dst, referenceDir string, mode os.FileMode) error { + payload, err := fetchArtifact(url) + if err != nil { + return err + } + + if same, err := sameFileChecksum(dst, payload); err == nil && same { + return syncFileOwnershipWithMode(dst, referenceDir, mode) + } + + tmp, err := os.CreateTemp(filepath.Dir(dst), "zlh-system-file-*") + if err != nil { + return err + } + tmpPath := tmp.Name() + defer func() { + _ = os.Remove(tmpPath) + }() + + if _, err := tmp.Write(payload); err != nil { + _ = tmp.Close() + return err + } + if err := tmp.Close(); err != nil { + return err + } + if err := os.Rename(tmpPath, dst); err != nil { + return err + } + return syncFileOwnershipWithMode(dst, referenceDir, mode) +} + +func sameFileChecksum(path string, payload []byte) (bool, error) { + current, err := os.ReadFile(path) + if err != nil { + return false, err + } + currentSum := sha256.Sum256(current) + newSum := sha256.Sum256(payload) + return currentSum == newSum, nil +} + +func syncOwnershipAndPerms(path string, info os.FileInfo) error { + if err := os.Chmod(path, info.Mode().Perm()); err != nil { + return err + } + stat, ok := info.Sys().(*syscall.Stat_t) + if !ok { + return nil + } + return os.Chown(path, int(stat.Uid), int(stat.Gid)) +} + +func syncFileOwnership(path, referenceDir string) error { + return syncFileOwnershipWithMode(path, referenceDir, 0o644) +} + +func syncFileOwnershipWithMode(path, referenceDir string, mode os.FileMode) error { + info, err := os.Stat(referenceDir) + if err != nil { + return err + } + if err := os.Chmod(path, mode); err != nil { + return err + } + stat, ok := info.Sys().(*syscall.Stat_t) + if !ok { + return nil + } + return os.Chown(path, int(stat.Uid), int(stat.Gid)) +} diff --git a/internal/provision/minecraft/fabric_proxy_test.go b/internal/provision/minecraft/fabric_proxy_test.go new file mode 100644 index 0000000..1e10646 --- /dev/null +++ b/internal/provision/minecraft/fabric_proxy_test.go @@ -0,0 +1,78 @@ +package minecraft + +import ( + "net/http" + "net/http/httptest" + "strings" + "sync" + "testing" +) + +func TestResolveProxyVersion(t *testing.T) { + data := `{ + "1.20.1": "2.6.0", + "1.20.2-1.20.4": "2.7.0", + "1.20.5": "2.8.0", + "1.21.0-1.21.8": "2.9.0" + }` + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/zpacks/minecraft/fabric/fabric-proxy-lite/map.json" { + http.NotFound(w, r) + return + } + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(data)) + })) + defer server.Close() + + t.Setenv("ZLH_ARTIFACT_BASE_URL", server.URL) + origRoot := fabricProxyArtifactRoot + origMap := fabricProxyMap + origErr := fabricProxyMapErr + origOnce := fabricProxyMapOnce + fabricProxyArtifactRoot = "zpacks/minecraft/fabric/fabric-proxy-lite" + fabricProxyMap = nil + fabricProxyMapErr = nil + fabricProxyMapOnce = sync.Once{} + t.Cleanup(func() { + fabricProxyArtifactRoot = origRoot + fabricProxyMap = origMap + fabricProxyMapErr = origErr + fabricProxyMapOnce = origOnce + }) + + tests := []struct { + name string + version string + want string + wantErr string + }{ + {name: "exact match", version: "1.20.1", want: "2.6.0"}, + {name: "range lower bound", version: "1.20.2", want: "2.7.0"}, + {name: "range middle", version: "1.20.3", want: "2.7.0"}, + {name: "range upper bound", version: "1.21.8", want: "2.9.0"}, + {name: "missing", version: "1.19.4", wantErr: "no fabricproxy-lite mapping"}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + fabricProxyMap = nil + fabricProxyMapErr = nil + fabricProxyMapOnce = sync.Once{} + + got, err := resolveProxyVersion(tc.version) + if tc.wantErr != "" { + if err == nil || !strings.Contains(err.Error(), tc.wantErr) { + t.Fatalf("expected error containing %q, got %v", tc.wantErr, err) + } + return + } + if err != nil { + t.Fatalf("resolveProxyVersion(%q) error = %v", tc.version, err) + } + if got != tc.want { + t.Fatalf("resolveProxyVersion(%q) = %q, want %q", tc.version, got, tc.want) + } + }) + } +} diff --git a/internal/provision/minecraft/vanilla.go b/internal/provision/minecraft/vanilla.go index 9299b4d..cb7e8af 100644 --- a/internal/provision/minecraft/vanilla.go +++ b/internal/provision/minecraft/vanilla.go @@ -7,44 +7,49 @@ import ( "os" "path/filepath" - "zlh-agent/internal/state" "zlh-agent/internal/provcommon" + "zlh-agent/internal/state" ) -func InstallMinecraftVanilla(cfg state.Config) error { - dir := provcommon.ServerDir(cfg) - if err := os.MkdirAll(dir, 0o755); err != nil { - return fmt.Errorf("mkdir server dir: %w", err) - } +func InstallMinecraftJar(cfg state.Config) error { + dir := provcommon.ServerDir(cfg) + if err := os.MkdirAll(dir, 0o755); err != nil { + return fmt.Errorf("mkdir server dir: %w", err) + } - url := provcommon.BuildArtifactURL(cfg.ArtifactPath) - dest := filepath.Join(dir, "server.jar") + url := provcommon.BuildArtifactURL(cfg.ArtifactPath) + dest := filepath.Join(dir, "server.jar") - resp, err := http.Get(url) - if err != nil { - return fmt.Errorf("download vanilla: %w", err) - } - defer resp.Body.Close() + resp, err := http.Get(url) + if err != nil { + return fmt.Errorf("download server jar: %w", err) + } + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("bad status %s", resp.Status) - } + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("bad status %s", resp.Status) + } - out, err := os.Create(dest) - if err != nil { - return fmt.Errorf("create server.jar: %w", err) - } - defer out.Close() + out, err := os.Create(dest) + if err != nil { + return fmt.Errorf("create server.jar: %w", err) + } + defer out.Close() - if _, err := io.Copy(out, resp.Body); err != nil { - return fmt.Errorf("write server.jar: %w", err) - } + if _, err := io.Copy(out, resp.Body); err != nil { + return fmt.Errorf("write server.jar: %w", err) + } - // 🔹 NEW: verify + self-repair (java, server.jar, start.sh, etc.) - if err := VerifyMinecraftInstallWithRepair(cfg); err != nil { - return fmt.Errorf("vanilla install verification failed: %w", err) - } + if err := VerifyMinecraftInstallWithRepair(cfg); err != nil { + return fmt.Errorf("jar install verification failed: %w", err) + } - return nil + return nil } +func InstallFabric(cfg state.Config) error { + if err := InstallMinecraftJar(cfg); err != nil { + return fmt.Errorf("fabric install failed: %w", err) + } + return nil +} diff --git a/internal/provision/minecraft/verify.go b/internal/provision/minecraft/verify.go index d5ebb95..a23edff 100644 --- a/internal/provision/minecraft/verify.go +++ b/internal/provision/minecraft/verify.go @@ -64,12 +64,24 @@ func VerifyMinecraftInstallWithRepair(cfg state.Config) error { func verifyMinecraftInstallOnce(cfg state.Config) error { dir := provcommon.ServerDir(cfg) variant := strings.ToLower(cfg.Variant) + runtime := strings.ToLower(strings.TrimSpace(cfg.Runtime)) + if runtime == "" { + runtime = variant + } + fmt.Printf("[verify] runtime=%s\n", runtime) // Java symlink must exist if err := verifyJavaSymlink(); err != nil { return err } + if runtime == "fabric" { + if err := verifyServerJar(cfg, dir); err != nil { + return err + } + return nil + } + // --------------------------------------------------------------------- // VANILLA / PAPER / PURPUR / FABRIC / QUILT → *ONLY REQUIRE server.jar* // --------------------------------------------------------------------- @@ -79,7 +91,7 @@ func verifyMinecraftInstallOnce(cfg state.Config) error { variant == "fabric" || variant == "quilt" { - if err := verifyServerJar(dir); err != nil { + if err := verifyServerJar(cfg, dir); err != nil { return err } @@ -137,11 +149,13 @@ func verifyJavaSymlink() error { // Vanilla-like variants: require ONLY server.jar // ----------------------------------------------------------------------------- -func verifyServerJar(dir string) error { - jar := filepath.Join(dir, "server.jar") +func verifyServerJar(cfg state.Config, dir string) error { + jarName := "server.jar" + jar := filepath.Join(dir, jarName) if _, err := os.Stat(jar); err != nil { - return fmt.Errorf("server.jar missing in %s: %w", dir, err) + return fmt.Errorf("%s missing in %s: %w", jarName, dir, err) } + fmt.Printf("[verify] found=%s\n", jarName) return nil } diff --git a/internal/provision/provision.go b/internal/provision/provision.go index 50e9e31..27a5312 100644 --- a/internal/provision/provision.go +++ b/internal/provision/provision.go @@ -2,6 +2,7 @@ package provision import ( "fmt" + "log" "strings" "zlh-agent/internal/provision/addons" @@ -19,6 +20,7 @@ IMPORTANT: - state.Config is treated as immutable desired state. */ func ProvisionAll(cfg state.Config) error { + normalizeMinecraftConfig(&cfg) /* --------------------------------------------------------- BASE ROLE PROVISIONING @@ -34,6 +36,7 @@ func ProvisionAll(cfg state.Config) error { // Legacy / default behavior assumes game containers game := strings.ToLower(cfg.Game) variant := strings.ToLower(cfg.Variant) + runtime := strings.ToLower(cfg.Runtime) /* --------------------------------------------------------- MINECRAFT @@ -47,10 +50,25 @@ func ProvisionAll(cfg state.Config) error { // 2. Game variant install switch variant { + case "vanilla": + if runtime != "fabric" { + return fmt.Errorf("unsupported runtime: %s", cfg.Runtime) + } + if err := minecraft.InstallFabric(cfg); err != nil { + return err + } + if err := minecraft.InjectFabricProxyLite(cfg); err != nil { + return fmt.Errorf("fabricproxy-lite injection failed: %w", err) + } - case "vanilla", "paper", "purpur", "fabric", "quilt": - if err := minecraft.InstallMinecraftVanilla(cfg); err != nil { - return fmt.Errorf("minecraft vanilla install failed: %w", err) + case "fabric": + if err := minecraft.InstallFabric(cfg); err != nil { + return err + } + + case "paper", "purpur", "quilt": + if err := minecraft.InstallMinecraftJar(cfg); err != nil { + return fmt.Errorf("minecraft jar install failed: %w", err) } case "forge": @@ -154,3 +172,25 @@ func ProvisionAll(cfg state.Config) error { return nil } + +func normalizeMinecraftConfig(cfg *state.Config) { + if cfg == nil { + return + } + if !strings.EqualFold(cfg.ContainerType, "game") { + return + } + if !strings.EqualFold(cfg.Game, "minecraft") { + return + } + if !strings.EqualFold(cfg.Variant, "vanilla") { + return + } + + cfg.Runtime = "fabric" + cfg.InternalProfile = "vanilla-fabric" + cfg.ArtifactPath = fmt.Sprintf("minecraft/fabric/%s/server.jar", strings.TrimSpace(cfg.Version)) + log.Printf("[provision] vmid=%d action=normalize original_variant=vanilla runtime=fabric profile=vanilla-fabric", cfg.VMID) + log.Printf("[provision] vmid=%d variant=vanilla normalized_runtime=fabric", cfg.VMID) + log.Printf("[provision] vmid=%d artifact_override=true source=fabric path=%s", cfg.VMID, cfg.ArtifactPath) +} diff --git a/internal/state/state.go b/internal/state/state.go index 5468251..b845ca6 100755 --- a/internal/state/state.go +++ b/internal/state/state.go @@ -21,8 +21,9 @@ type Config struct { ContainerType string `json:"container_type,omitempty"` // Dev runtime (only for dev containers) - Runtime string `json:"runtime,omitempty"` - Version string `json:"version"` + Runtime string `json:"runtime,omitempty"` + InternalProfile string `json:"internal_profile,omitempty"` + Version string `json:"version"` // OPTIONAL addons (role-agnostic) Addons []string `json:"addons,omitempty"` diff --git a/internal/system/process.go b/internal/system/process.go index 83a64ea..5a20676 100755 --- a/internal/system/process.go +++ b/internal/system/process.go @@ -9,6 +9,7 @@ import ( "os/exec" "os/user" "path/filepath" + "sort" "strconv" "strings" "sync" @@ -62,8 +63,10 @@ func StartServer(cfg *state.Config) error { startScript := filepath.Join(dir, "start.sh") log.Printf("[process] vmid=%d server start requested dir=%s", cfg.VMID, dir) - cmd := exec.Command("/bin/bash", startScript) - cmd.Dir = dir + cmd, err := buildServerCommand(cfg, dir, startScript) + if err != nil { + return err + } ptmx, err := runtime.CreatePTY(cmd) if err != nil { @@ -88,6 +91,73 @@ func StartServer(cfg *state.Config) error { return nil } +func buildServerCommand(cfg *state.Config, dir, startScript string) (*exec.Cmd, error) { + variant := strings.ToLower(strings.TrimSpace(cfg.Variant)) + if variant == "forge" || variant == "neoforge" { + cmd := exec.Command("/bin/bash", startScript) + cmd.Dir = dir + return cmd, nil + } + + if strings.EqualFold(cfg.Game, "minecraft") { + runtimeType := provision.MinecraftRuntime(*cfg) + jarPath, err := resolveMinecraftRuntimeJar(runtimeType, dir) + if err != nil { + return nil, err + } + + xms, xmx := minecraftHeap(cfg.MemoryMB) + javaBin := filepath.Join(provision.JavaRoot, "java") + cmd := exec.Command(javaBin, + fmt.Sprintf("-Xms%dM", xms), + fmt.Sprintf("-Xmx%dM", xmx), + "-jar", jarPath, "nogui", + ) + cmd.Dir = dir + return cmd, nil + } + + cmd := exec.Command("/bin/bash", startScript) + cmd.Dir = dir + return cmd, nil +} + +func resolveMinecraftRuntimeJar(runtimeType, dir string) (string, error) { + if runtimeType == "fabric" { + matches, err := filepath.Glob(filepath.Join(dir, ".fabric", "server", "fabric-loader-server-*.jar")) + if err != nil { + return "", fmt.Errorf("fabric runtime selected but loader scan failed: %w", err) + } + if len(matches) == 0 { + log.Printf("[runtime] ERROR missing fabric loader jar") + return "", fmt.Errorf("fabric runtime selected but no fabric loader jar found") + } + sort.Strings(matches) + loader := matches[len(matches)-1] + log.Printf("[runtime] type=fabric loader=%s", loader) + return loader, nil + } + + log.Printf("[runtime] type=%s jar=server.jar", runtimeType) + return filepath.Join(dir, "server.jar"), nil +} + +func minecraftHeap(memoryMB int) (xms int, xmx int) { + mem := memoryMB + if mem <= 0 { + mem = 2048 + } + xmx = mem + xms = mem / 2 + if xms < 512 { + xms = 512 + } + if xms > xmx { + xms = xmx + } + return xms, xmx +} + /* -------------------------------------------------------------------------- StopServer ----------------------------------------------------------------------------*/ diff --git a/internal/update/update.go b/internal/update/update.go index 69dfc94..f0d0dd7 100644 --- a/internal/update/update.go +++ b/internal/update/update.go @@ -20,7 +20,7 @@ import ( ) const ( - artifactBaseURL = "http://10.60.0.251:8080/agents/" + defaultArtifactBaseURL = "http://zlh-artifacts.internal.zlh:8080" releasesDir = "/opt/zlh-agent/releases" currentLink = "/opt/zlh-agent/current" previousLink = "/opt/zlh-agent/previous" @@ -54,6 +54,14 @@ type Result struct { CheckedAtUTC string `json:"checked_at_utc,omitempty"` } +func artifactBaseURL() string { + base := strings.TrimSpace(os.Getenv("ZLH_ARTIFACT_BASE_URL")) + if base == "" { + base = defaultArtifactBaseURL + } + return strings.TrimRight(base, "/") + "/agents/" +} + func CheckAvailable(currentVersion string) Result { currentVersion = normalizeVersion(currentVersion) result := Result{ @@ -248,8 +256,9 @@ func CheckAndUpdate(currentVersion string) Result { tmpPath := filepath.Join(releasesDir, target, "zlh-agent.new") finalPath := filepath.Join(releasesDir, target, "zlh-agent") - binURL := artifactBaseURL + binPath - shaURL := artifactBaseURL + shaPath + baseURL := artifactBaseURL() + binURL := baseURL + binPath + shaURL := baseURL + shaPath if err := downloadFile(binURL, tmpPath); err != nil { result.Error = fmt.Sprintf("download binary: %v", err) @@ -326,7 +335,7 @@ func CheckAndUpdate(currentVersion string) Result { } func fetchManifest() (Manifest, error) { - url := artifactBaseURL + "manifest.json" + url := artifactBaseURL() + "manifest.json" client := &http.Client{Timeout: 10 * time.Second} resp, err := client.Get(url) if err != nil { diff --git a/logs/agent.log b/logs/agent.log index e69de29..d1c2a79 100644 --- a/logs/agent.log +++ b/logs/agent.log @@ -0,0 +1,310 @@ +2026/04/01 12:50:51 [agent] file logging enabled +2026/04/01 12:50:51 [agent] lifecycle logging enabled +2026/04/01 12:50:51 [agent] routes registered +2026/04/01 12:50:51 [autostart] disabled (ok) +2026/04/01 12:50:51 [update] periodic checks enabled (mode=notify interval=30m0s) +2026/04/01 12:50:51 [agent] listening on :18888 +2026/04/01 12:51:04 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 13:21:07 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 13:51:08 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 14:02:16 [agent] shutdown signal received +2026/04/01 14:02:16 [agent] http server stopped gracefully +2026/04/01 14:02:16 [agent] exiting +2026/04/01 14:02:26 [agent] file logging enabled +2026/04/01 14:02:26 [agent] lifecycle logging enabled +2026/04/01 14:02:26 [agent] routes registered +2026/04/01 14:02:26 [autostart] disabled (ok) +2026/04/01 14:02:26 [update] periodic checks enabled (mode=notify interval=30m0s) +2026/04/01 14:02:26 [agent] listening on :18888 +2026/04/01 14:02:39 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 14:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 15:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 15:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 16:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 16:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 17:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 17:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 18:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 18:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 19:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 19:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 20:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 20:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 21:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 21:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 22:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 22:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 23:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/01 23:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 00:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 00:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 01:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 01:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 02:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 02:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 03:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 03:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 04:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 04:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 05:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 05:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 06:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 06:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 07:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 07:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 08:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 08:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 09:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 09:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 10:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 10:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 11:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 11:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 12:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 12:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 13:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 13:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 14:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 14:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 15:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 15:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 16:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 16:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 17:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 17:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 18:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 18:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 19:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 19:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 20:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 20:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 21:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 21:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 22:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 22:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 23:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/02 23:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 00:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 00:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 01:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 01:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 02:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 02:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 03:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 03:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 04:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 04:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 05:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 05:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 06:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 06:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 07:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 07:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 08:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 08:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 09:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 09:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 10:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 10:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 11:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 11:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 12:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 12:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 13:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 13:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 14:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 14:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 15:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 15:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 16:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 16:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 17:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 17:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 18:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 18:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 19:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 19:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 20:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 20:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 21:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 21:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 22:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 22:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 23:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/03 23:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 00:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 00:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 01:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 01:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 02:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 02:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 03:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 03:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 04:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 04:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 05:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 05:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 06:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 06:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 07:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 07:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 08:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 08:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 09:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 09:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 10:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 10:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 11:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 11:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 12:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 12:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 13:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 13:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 14:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 14:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 15:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 15:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 16:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 16:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 17:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 17:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 18:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 18:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 19:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 19:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 20:02:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 20:32:42 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 21:02:43 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 21:23:54 [agent] file logging enabled +2026/04/04 21:23:54 [agent] lifecycle logging enabled +2026/04/04 21:23:54 [agent] routes registered +2026/04/04 21:23:54 [autostart] disabled (ok) +2026/04/04 21:23:54 [update] periodic checks enabled (mode=notify interval=30m0s) +2026/04/04 21:23:54 [agent] listening on :18888 +2026/04/04 21:24:07 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 21:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 22:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 22:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 23:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/04 23:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 00:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 00:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 01:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 01:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 02:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 02:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 03:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 03:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 04:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 04:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 05:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 05:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 06:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 06:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 07:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 07:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 08:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 08:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 09:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 09:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 10:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 10:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 11:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 11:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 12:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 12:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 13:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 13:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 14:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 14:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 15:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 15:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 16:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 16:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 17:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 17:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 18:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 18:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 19:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 19:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 20:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 20:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 21:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 21:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 22:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 22:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 23:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/05 23:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 00:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 00:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 01:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 01:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 02:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 02:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 03:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 03:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 04:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 04:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 05:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 05:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 06:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 06:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 07:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 07:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 08:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 08:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 09:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 09:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 10:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 10:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 11:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 11:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 12:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 12:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 13:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 13:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 14:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 14:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 15:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 15:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 16:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 16:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 17:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 17:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 18:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 18:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 19:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 19:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 20:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 20:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 21:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 21:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 22:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 22:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 23:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/06 23:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 00:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 00:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 01:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 01:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 02:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 02:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 03:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 03:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 04:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 04:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 05:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 05:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 06:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 06:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 07:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 07:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 08:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 08:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 09:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 09:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 10:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 10:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 11:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 11:54:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host +2026/04/07 12:24:10 [update] notify check failed status=error current=0.0.0-dev target= err=Get "http://10.60.0.251:8080/agents/manifest.json": dial tcp 10.60.0.251:8080: connect: no route to host diff --git a/logs/lifecycle.log b/logs/lifecycle.log new file mode 100644 index 0000000..e69de29 diff --git a/scripts/addons/codeserver/install.sh b/scripts/addons/codeserver/install.sh index 2b5d7f5..be48f4b 100644 --- a/scripts/addons/codeserver/install.sh +++ b/scripts/addons/codeserver/install.sh @@ -7,7 +7,7 @@ echo "[code-server] starting install" # Config # ---------------------------------------------------------- SERVICE_ROOT="/opt/zlh/services/code-server" -ZLH_ARTIFACT_BASE_URL="${ZLH_ARTIFACT_BASE_URL:-http://10.60.0.251:8080}" +ZLH_ARTIFACT_BASE_URL="${ZLH_ARTIFACT_BASE_URL:-http://zlh-artifacts.internal.zlh:8080}" ARTIFACT_NAME="${ZLH_CODESERVER_ARTIFACT:-code-server.tar.gz}" ARTIFACT_URL="${ZLH_ARTIFACT_BASE_URL%/}/addons/code-server/${ARTIFACT_NAME}" ARTIFACT_TMP="/tmp/${ARTIFACT_NAME}" @@ -15,7 +15,7 @@ MARKER="/opt/zlh/.zlh/addons/code-server.installed" PID_FILE="/opt/zlh/.zlh/addons/code-server.pid" LOG_FILE="/opt/zlh/logs/code-server.log" WORKSPACE_DIR="${CODE_SERVER_WORKSPACE:-/home/dev/workspace}" -PORT="${CODE_SERVER_PORT:-8080}" +PORT="${CODE_SERVER_PORT:-6000}" BIN="${SERVICE_ROOT}/bin/code-server" LINK_PATH="/usr/local/bin/code-server" CONFIG_DIR="/home/dev/.config/code-server" diff --git a/scripts/devcontainer/dotnet/install.sh b/scripts/devcontainer/dotnet/install.sh index 585e718..722a12c 100644 --- a/scripts/devcontainer/dotnet/install.sh +++ b/scripts/devcontainer/dotnet/install.sh @@ -7,7 +7,7 @@ RUNTIME="dotnet" RUNTIME_ROOT="/opt/zlh/runtimes/${RUNTIME}" DEST_DIR="${RUNTIME_ROOT}/${RUNTIME_VERSION}" CURRENT_LINK="${RUNTIME_ROOT}/current" -ZLH_ARTIFACT_BASE_URL="${ZLH_ARTIFACT_BASE_URL:-http://10.60.0.251:8080}" +ZLH_ARTIFACT_BASE_URL="${ZLH_ARTIFACT_BASE_URL:-http://zlh-artifacts.internal.zlh:8080}" INSTALLER_URL="${ZLH_ARTIFACT_BASE_URL%/}/devcontainer/dotnet/dotnet-install.sh" INSTALLER_TMP="/tmp/dotnet-install.sh" diff --git a/scripts/devcontainer/lib/common.sh b/scripts/devcontainer/lib/common.sh index da08d60..c61ff23 100644 --- a/scripts/devcontainer/lib/common.sh +++ b/scripts/devcontainer/lib/common.sh @@ -13,7 +13,7 @@ set -euo pipefail # Optional env ############################################ -ZLH_ARTIFACT_BASE_URL="${ZLH_ARTIFACT_BASE_URL:-http://10.60.0.251:8080}" +ZLH_ARTIFACT_BASE_URL="${ZLH_ARTIFACT_BASE_URL:-http://zlh-artifacts.internal.zlh:8080}" ZLH_RUNTIME_ROOT="${ZLH_RUNTIME_ROOT:-/opt/zlh/runtimes}" ARCHIVE_PREFIX="${ARCHIVE_PREFIX:-${RUNTIME}}" diff --git a/state/update.json b/state/update.json new file mode 100644 index 0000000..53bb100 --- /dev/null +++ b/state/update.json @@ -0,0 +1,6 @@ +{ + "status": "error", + "current": "0.0.0-dev", + "error": "Get \"http://10.60.0.251:8080/agents/manifest.json\": dial tcp 10.60.0.251:8080: connect: no route to host", + "checked_at_utc": "2026-04-07T12:24:07Z" +} \ No newline at end of file