package apply import ( "errors" "os" "path/filepath" "git.novox.be/novox/mesh-sdk/go/declaration" ) // declaredFiles is the path of every file a declaration declares. func declaredFiles(resources []declaration.Resource) map[string]bool { out := map[string]bool{} for _, r := range resources { if f, ok := r.(*declaration.File); ok { out[filepath.Clean(f.Path)] = true } } return out } // mountsAFileNotThere is the first mount source of a container that is a file the declaration declares and is not // on the machine yet, or "" (novox/hq issue 1873): the runtime makes a missing source a directory. func mountsAFileNotThere(c *declaration.Container, files map[string]bool) string { for _, v := range c.Volumes { src := mountSource(v) if !filepath.IsAbs(src) || !files[filepath.Clean(src)] { continue } if _, err := os.Lstat(src); errors.Is(err, os.ErrNotExist) { return src } } return "" } // clearRuntimesEmptyDirectory removes what a container runtime leaves at a file's path when it mounted the file before // it was there (novox/hq issue 1873): an empty directory, in the mesh's own tree by its path and by where its path // leads, owned by the engine's own account. It says what it removed, or "" when nothing was. Anything else at the path // is left for the write to meet as before: a directory with anything in it, or one outside the tree, is never removed. func clearRuntimesEmptyDirectory(path string) (string, error) { info, err := os.Lstat(path) if err != nil || !info.IsDir() || !inTheMeshsTree(path) { return "", nil } if uid, _, ok := ownerOf(info); !ok || uid != os.Geteuid() { return "", nil } entries, err := os.ReadDir(path) if err != nil || len(entries) > 0 { return "", nil } if err := os.Remove(path); err != nil { return "", err } return "removed the empty directory a container runtime left at " + path + ", where this file belongs " + "(novox/hq issue 1873)", nil }