package runtime import ( "path/filepath" "strings" ) // Compose labels set by podman-compose on every container it creates. const ( LabelPodmanComposeProject = "io.podman.compose.project" LabelComposeWorkingDir = "com.docker.compose.project.working_dir" LabelComposeConfigFiles = "com.docker.compose.project.config_files" ) // Container represents a discovered running container. type Container struct { Name string Image string Command string Runtime string // "podman" or "docker" User string // empty = root/system scope Labels map[string]string } // Project returns the podman-compose project the container belongs to, or "". func (c Container) Project() string { return c.Labels[LabelPodmanComposeProject] } // WorkingDir returns the compose project working directory, or "". func (c Container) WorkingDir() string { return c.Labels[LabelComposeWorkingDir] } // ComposeFiles returns the compose files used to create the container. // Relative paths are relative to WorkingDir. func (c Container) ComposeFiles() []string { raw := c.Labels[LabelComposeConfigFiles] if raw == "" { return nil } var files []string for _, f := range strings.Split(raw, ",") { if f = strings.TrimSpace(f); f != "" { files = append(files, filepath.Clean(f)) } } return files } // Runtime is the interface all container runtimes must implement. // user selects the scope: "" = root/system, otherwise a rootless user. type Runtime interface { Name() string ListRunning(user string) ([]Container, error) Exists(user, name string) (bool, error) } // Available returns all supported runtimes in priority order: podman first, // docker as fallback (callers skip those with no binary). func Available() []Runtime { return []Runtime{&Podman{}, &Docker{}} } // Get returns a runtime by name ("podman" or "docker"). func Get(name string) Runtime { switch name { case "podman": return &Podman{} case "docker": return &Docker{} default: return nil } }