Files
felhom-controller/controller/internal/mediawire/docker.go
T

87 lines
2.5 KiB
Go

package mediawire
import (
"database/sql"
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
_ "modernc.org/sqlite"
"gitea.dooplex.hu/admin/felhom-controller/internal/appbackup"
"gitea.dooplex.hu/admin/felhom-controller/internal/dockerexec"
)
// DockerBox is the production Box: the docker CLI on this guest.
type DockerBox struct{}
func (DockerBox) Running(c string) bool {
out, err := dockerexec.Command("docker", "inspect", "-f", "{{.State.Running}}", c).Output()
return err == nil && strings.TrimSpace(string(out)) == "true"
}
func (DockerBox) Env(c, name string) (string, error) {
out, err := dockerexec.Command("docker", "exec", c, "printenv", name).Output()
if err != nil {
return "", fmt.Errorf("%s: reading %s: %w", c, name, err)
}
return strings.TrimRight(string(out), "\n"), nil
}
func (DockerBox) ReadFile(c, path string) ([]byte, error) {
out, err := dockerexec.Command("docker", "exec", c, "cat", path).Output()
if err != nil {
return nil, fmt.Errorf("%s: reading %s: %w", c, path, err)
}
return out, nil
}
func (DockerBox) EnsureDir(p string) error { return appbackup.EnsureUserdataDir(p) }
func (DockerBox) Mounts(c string) map[string]string {
out, err := dockerexec.Command("docker", "inspect", "-f", "{{json .Mounts}}", c).Output()
res := map[string]string{}
if err != nil {
return res
}
var ms []struct {
Source string `json:"Source"`
Destination string `json:"Destination"`
}
if json.Unmarshal(out, &ms) == nil {
for _, m := range ms {
res[filepath.Clean(m.Destination)] = m.Source
}
}
return res
}
// JellyfinKey copies Jellyfin's database (with its -wal/-shm, R-286's lesson) into a 0700 temp dir, reads the API key
// with this name read-only, and removes the copy at once. The key is returned to the caller only.
func (DockerBox) JellyfinKey(name string) (string, error) {
dir, err := os.MkdirTemp("", "felhom-jf-")
if err != nil {
return "", err
}
defer os.RemoveAll(dir)
for _, f := range []string{"jellyfin.db", "jellyfin.db-wal", "jellyfin.db-shm"} {
err := dockerexec.Command("docker", "cp", "jellyfin:/config/data/"+f, filepath.Join(dir, f)).Run()
if err != nil && f == "jellyfin.db" {
return "", fmt.Errorf("copying Jellyfin's database: %w", err)
}
}
db, err := sql.Open("sqlite", "file:"+filepath.Join(dir, "jellyfin.db"))
if err != nil {
return "", err
}
defer db.Close()
var key string
err = db.QueryRow(`SELECT AccessToken FROM ApiKeys WHERE Name = ? ORDER BY DateCreated DESC LIMIT 1`, name).Scan(&key)
if err == sql.ErrNoRows {
return "", nil
}
return key, err
}