package runtime import ( "encoding/json" "fmt" "os/exec" "strings" ) type Podman struct{} func (p *Podman) Name() string { return "podman" } type podmanContainer struct { ID string `json:"Id"` Names []string `json:"Names"` Image string `json:"Image"` Command []string `json:"Command"` State string `json:"State"` } func (p *Podman) ListRunning() ([]Container, error) { bin, err := exec.LookPath("podman") if err != nil { return nil, nil // podman not installed — not an error } out, err := exec.Command(bin, "ps", "--format", "json").Output() if err != nil { // Podman installed but not usable — treat as no containers return nil, nil } var raw []podmanContainer if err := json.Unmarshal(out, &raw); err != nil { // Podman installed but output is not valid JSON (e.g. OCI runtime misconfigured) return nil, nil } var containers []Container for _, c := range raw { name := "" if len(c.Names) > 0 { name = c.Names[0] } // Fall back to short container ID if no name assigned if name == "" { if len(c.ID) >= 12 { name = c.ID[:12] } else if c.ID != "" { name = c.ID } else { continue } } containers = append(containers, Container{ Name: name, Image: c.Image, Command: strings.Join(c.Command, " "), Runtime: "podman", }) } return containers, nil } func (p *Podman) Exists(name string) (bool, error) { bin, err := exec.LookPath("podman") if err != nil { return false, nil } out, err := exec.Command(bin, "ps", "--format", "{{.Names}}").Output() if err != nil { return false, fmt.Errorf("podman ps: %w", err) } for _, line := range strings.Split(string(out), "\n") { if strings.TrimSpace(line) == name { return true, nil } } return false, nil }