- syncup: podman first, docker only as fallback (podman wins on name clash;
existing docker units found in podman switch to podman)
- syncup: group podman-compose containers into one `kind: stack` unit per
project (project, working_dir, compose_files, compose_bin from labels);
disable existing member units ("part of stack <project>")
- generator: compose mode (podman-compose up/stop, WorkingDirectory) with
pod start/stop fallback when compose binary/dir/files are missing
- reconcile: stacks disabled with "stack not found" when neither compose
files nor pod exist
- root: scan root + rootless users listed in `users:` (podman only)
- non-root: config ~/.config/unitdore/units.yaml, own user units only
- sysuser package: runuser with XDG_RUNTIME_DIR/DBUS env, home/linger lookup
- install: warn when linger is not enabled for user units
- testdata/stack: podman-compose test stack and captured podman ps fixture
- docs: README, generated-units, man page, AGENTS, PLAN
76 lines
1.9 KiB
Go
76 lines
1.9 KiB
Go
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
|
|
}
|
|
}
|