Files
Elydora-Open-Source/sdks/go/cmd/elydora/runtime_discovery.go
T

160 lines
4.2 KiB
Go

package main
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"github.com/Elydora-Infrastructure/Elydora-Go-SDK/cmd/elydora/plugins"
)
type installedAgentRuntime struct {
agentID string
agentName string
}
type runtimeIdentity struct {
AgentID string `json:"agent_id"`
AgentName string `json:"agent_name"`
}
func readInstalledAgentRuntime(directoryName string) (*installedAgentRuntime, error) {
agentDirectory, err := plugins.ResolveAgentRuntimeDirectory(directoryName)
if err != nil {
return nil, err
}
exists, err := plugins.RequirePhysicalDirectory(agentDirectory)
if err != nil || !exists {
return nil, err
}
configPath := filepath.Join(agentDirectory, "config.json")
configExists, err := plugins.RequirePhysicalFile(configPath)
if err != nil || !configExists {
return nil, err
}
data, err := os.ReadFile(configPath)
if err != nil {
return nil, fmt.Errorf("read agent config %s: %w", configPath, err)
}
var identity runtimeIdentity
if err := json.Unmarshal(data, &identity); err != nil {
return nil, fmt.Errorf("parse agent config %s: %w", configPath, err)
}
if identity.AgentID == "" || identity.AgentName == "" {
return nil, fmt.Errorf("agent config %s has an invalid runtime identity", configPath)
}
if identity.AgentID != directoryName {
return nil, fmt.Errorf("agent config %s crosses its runtime directory", configPath)
}
if _, err := plugins.ResolveAgentRuntimeDirectory(identity.AgentID); err != nil {
return nil, fmt.Errorf("validate agent config %s: %w", configPath, err)
}
return &installedAgentRuntime{
agentID: identity.AgentID, agentName: identity.AgentName,
}, nil
}
func discoverInstalledAgentRuntimes() ([]installedAgentRuntime, error) {
runtimeRoot, err := plugins.AgentRuntimeRoot()
if err != nil {
return nil, err
}
exists, err := plugins.RequirePhysicalDirectory(runtimeRoot)
if err != nil || !exists {
return nil, err
}
entries, err := os.ReadDir(runtimeRoot)
if err != nil {
return nil, fmt.Errorf("read Elydora runtime root %s: %w", runtimeRoot, err)
}
runtimes := make([]installedAgentRuntime, 0, len(entries))
for _, entry := range entries {
if entry.Type()&os.ModeSymlink != 0 {
return nil, fmt.Errorf(
"agent runtime path is not a physical directory: %s",
filepath.Join(runtimeRoot, entry.Name()),
)
}
if !entry.IsDir() {
continue
}
runtime, err := readInstalledAgentRuntime(entry.Name())
if err != nil {
return nil, err
}
if runtime != nil {
runtimes = append(runtimes, *runtime)
}
}
return runtimes, nil
}
// findAgentIDByName returns one validated runtime identity for an agent name.
func findAgentIDByName(agentName string) (string, error) {
runtimes, err := discoverInstalledAgentRuntimes()
if err != nil {
return "", err
}
foundAgentID := ""
for _, runtime := range runtimes {
if runtime.agentName != agentName {
continue
}
if foundAgentID != "" {
return "", fmt.Errorf(
"multiple %q agent runtimes found; pass --agent-id explicitly",
agentName,
)
}
foundAgentID = runtime.agentID
}
return foundAgentID, nil
}
func resolveAgentRuntimeForUninstall(
agentName, explicitAgentID string,
) (agentID, agentDirectory string, directoryExists bool, err error) {
runtimeRoot, err := plugins.AgentRuntimeRoot()
if err != nil {
return "", "", false, err
}
runtimeRootExists, err := plugins.RequirePhysicalDirectory(runtimeRoot)
if err != nil {
return "", "", false, err
}
agentID = explicitAgentID
if agentID == "" {
agentID, err = findAgentIDByName(agentName)
if err != nil || agentID == "" {
return agentID, "", false, err
}
}
agentDirectory, err = plugins.ResolveAgentRuntimeDirectory(agentID)
if err != nil {
return "", "", false, err
}
if runtimeRootExists {
directoryExists, err = plugins.RequirePhysicalDirectory(agentDirectory)
if err != nil {
return "", "", false, err
}
}
if directoryExists {
runtime, err := readInstalledAgentRuntime(agentID)
if err != nil {
return "", "", false, err
}
if runtime != nil && runtime.agentName != agentName {
return "", "", false, fmt.Errorf(
"agent runtime %q belongs to %q, not %q",
agentID, runtime.agentName, agentName,
)
}
}
return agentID, agentDirectory, directoryExists, nil
}