// Package inspect reports local prerequisite observations without executing // commands, connecting to Docker or altering configuration. package inspect import ( "errors" "io/fs" "os" "runtime" ) type Report struct { ProtocolVersion int `json:"protocolVersion"` OS string `json:"os"` Architecture string `json:"architecture"` SupportedPlatform bool `json:"supportedPlatform"` SystemdRuntime string `json:"systemdRuntime"` DockerClient string `json:"dockerClient"` DockerDaemon string `json:"dockerDaemon"` Compose string `json:"compose"` Unchecked []string `json:"unchecked"` DeploymentReady bool `json:"deploymentReady"` } func Collect() Report { return Probe(runtime.GOOS, runtime.GOARCH, os.DirFS("/")) } // Probe observes filesystem metadata only. "present" is not an assertion that // systemd is responsive or the Docker executable is authentic or operational. func Probe(goos, arch string, files fs.FS) Report { r := Report{ProtocolVersion: 1, OS: goos, Architecture: arch, SupportedPlatform: goos == "linux" && (arch == "amd64" || arch == "arm64"), SystemdRuntime: "not_checked", DockerClient: "not_checked", DockerDaemon: "not_checked", Compose: "not_checked", Unchecked: []string{"docker_daemon", "compose_version", "host_identity", "distribution_support", "permissions", "disk_space", "ports", "dns", "firewall", "gateway"}} if goos != "linux" { return r } r.SystemdRuntime = observe(files, "run/systemd/system", true) r.DockerClient = observe(files, "usr/bin/docker", false) if r.DockerClient != "present" { alternate := observe(files, "usr/local/bin/docker", false) // Either known executable establishes presence. Otherwise retain any // uncertainty instead of reporting absence from an incomplete check. switch { case alternate == "present": r.DockerClient = "present" case r.DockerClient == "unknown" || alternate == "unknown": r.DockerClient = "unknown" case r.DockerClient == "invalid" || alternate == "invalid": r.DockerClient = "invalid" } } return r } func observe(files fs.FS, path string, directory bool) string { info, err := fs.Stat(files, path) if errors.Is(err, fs.ErrNotExist) { return "missing" } if err != nil { return "unknown" } if directory { if info.IsDir() { return "present" } return "invalid" } if !info.Mode().IsRegular() || info.Mode().Perm()&0111 == 0 { return "invalid" } return "present" }