2022-12-08 13:05:19 -03:00

92 lines
2.1 KiB
Go

// Copyright (c) 2020 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License.AGPL.txt in the project root for license information.
package container
import (
"bufio"
"os"
"strings"
"golang.org/x/xerrors"
)
// NewNodeMountsLookup produces a new node mounts lookup after validating the configuration
func NewNodeMountsLookup(cfg *NodeMountsLookupConfig) (*NodeMountsLookup, error) {
if cfg == nil {
return nil, xerrors.Errorf("config must not be nil")
}
return &NodeMountsLookup{cfg}, nil
}
// NodeMountsLookup interogates the node-level (root mount namespace) mount table and maps
// those paths to the container running this process.
type NodeMountsLookup struct {
Config *NodeMountsLookupConfig
}
// GetMountpoint scans the mount table for a mount point and returns one if found
func (n *NodeMountsLookup) GetMountpoint(matcher func(mountPoint string) bool) (mountPoint string, err error) {
entry, err := n.getEntry(matcher)
if err != nil {
return
}
return entry[1], nil
}
// GetUpperdir finds the upperdir of an overlayfs mount by matching the mountpoint.
// The returned path exists in the node's root mount namespace.
func (n *NodeMountsLookup) GetUpperdir(matcher func(mountPoint string) bool) (upperdir string, err error) {
entry, err := n.getEntry(matcher)
if err != nil {
return
}
var pth string
segs := strings.Split(entry[3], ",")
for _, seg := range segs {
if !strings.HasPrefix(seg, "upperdir=") {
continue
}
pth = strings.TrimSpace(strings.TrimPrefix(seg, "upperdir="))
break
}
if pth == "" {
return "", ErrNoUpperdir
}
return pth, nil
}
func (n *NodeMountsLookup) getEntry(matcher func(mountPoint string) bool) (entry []string, err error) {
f, err := os.Open(n.Config.ProcLoc)
if err != nil {
return nil, xerrors.Errorf("cannot load node mounts: %w", err)
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
fields := strings.Fields(line)
if len(fields) < 4 {
continue
}
if fields[0] != "overlay" {
continue
}
if !matcher(fields[1]) {
continue
}
return fields, nil
}
return nil, ErrNotFound
}