vendor c/psgo@v1.7.1

psgo added support for listing supplementary groups via
two new descriptors:

* `groups` for supplementary groups inside the container
* `hgroups` for the counterpart on the host

Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
Valentin Rothberg 2021-09-20 14:48:58 +02:00
parent b906ecbb5b
commit 5875e409e2
17 changed files with 116 additions and 66 deletions

2
go.mod
View file

@ -16,7 +16,7 @@ require (
github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.16.0
github.com/containers/ocicrypt v1.1.2
github.com/containers/psgo v1.6.0
github.com/containers/psgo v1.7.1
github.com/containers/storage v1.36.0
github.com/coreos/go-systemd/v22 v22.3.2
github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3

4
go.sum
View file

@ -259,8 +259,8 @@ github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgU
github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
github.com/containers/ocicrypt v1.1.2 h1:Ez+GAMP/4GLix5Ywo/fL7O0nY771gsBIigiqUm1aXz0=
github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
github.com/containers/psgo v1.6.0 h1:jkl/5kndKmJ/bnSFq8in6xRDAzgW26GnNuTxoycNFvk=
github.com/containers/psgo v1.6.0/go.mod h1:ggVhB2KQi9qGZdqSlczqN0BwcJdotmpRru87S1anRO8=
github.com/containers/psgo v1.7.1 h1:2N6KADeFvBm1aI2iXxu6+/Xh7CCkdh8p8F3F/cpIU5I=
github.com/containers/psgo v1.7.1/go.mod h1:mWGpFzW73qWFA+blhF6l7GuKzbrACkYgr/ajiNQR+RM=
github.com/containers/storage v1.23.5/go.mod h1:ha26Q6ngehFNhf3AWoXldvAvwI4jFe3ETQAf/CeZPyM=
github.com/containers/storage v1.35.0/go.mod h1:qzYhasQP2/V9D9XdO+vRwkHBhsBO0oznMLzzRDQ8s20=
github.com/containers/storage v1.36.0 h1:OelxllCW19tnNngYuZw2ty/zLabVMG5rSs3KSwO1Lzc=

View file

@ -73,6 +73,12 @@ var _ = Describe("Podman top", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
Expect(len(result.OutputToStringArray())).To(BeNumerically(">", 1))
// Just a smoke test since groups may change over time.
result = podmanTest.Podman([]string{"container", "top", "test", "groups", "hgroups"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
Expect(len(result.OutputToStringArray())).To(BeNumerically(">", 1))
})
It("podman top with options", func() {

2
vendor/github.com/containers/psgo/.codespellrc generated vendored Normal file
View file

@ -0,0 +1,2 @@
[codespell]
skip = ./vendor,./.git

6
vendor/github.com/containers/psgo/.golangci.yml generated vendored Normal file
View file

@ -0,0 +1,6 @@
# For documentation, see https://golangci-lint.run/usage/configuration/
linters:
enable:
- errorlint
- gofumpt

View file

@ -1,19 +0,0 @@
language: go
sudo: required
servics:
- docker
go:
- tip
before_install:
- sudo add-apt-repository ppa:duggan/bats --yes
- sudo apt-get update -qq
- sudo apt-get install -qq bats
script:
- make validate
- make build
- make test

View file

@ -1,28 +1,25 @@
export GO111MODULE=off
export GOPROXY=https://proxy.golang.org
SHELL= /bin/bash
GO ?= go
BUILD_DIR := ./bin
BIN_DIR := /usr/local/bin
NAME := psgo
PROJECT := github.com/containers/psgo
BATS_TESTS := *.bats
GO_SRC=$(shell find . -name \*.go)
GO_BUILD=$(GO) build
# Go module support: set `-mod=vendor` to use the vendored sources
ifeq ($(shell go help mod >/dev/null 2>&1 && echo true), true)
GO_BUILD=GO111MODULE=on $(GO) build -mod=vendor
# Not all platforms support -buildmode=pie, plus it's incompatible with -race.
ifeq ($(shell $(GO) env GOOS),linux)
ifeq (,$(filter $(shell $(GO) env GOARCH),mips mipsle mips64 mips64le ppc64 riscv64))
ifeq (,$(findstring -race,$(EXTRA_BUILD_FLAGS)))
GO_BUILDMODE := "-buildmode=pie"
endif
endif
endif
GOBIN ?= $(GO)/bin
GO_BUILD := $(GO) build $(GO_BUILDMODE)
all: validate build
.PHONY: build
build: $(GO_SRC)
$(GO_BUILD) -buildmode=pie -o $(BUILD_DIR)/$(NAME) $(PROJECT)/sample
build:
$(GO_BUILD) $(EXTRA_BUILD_FLAGS) -o $(BUILD_DIR)/$(NAME) ./sample
.PHONY: clean
clean:
@ -30,13 +27,13 @@ clean:
.PHONY: vendor
vendor:
GO111MODULE=on go mod tidy
GO111MODULE=on go mod vendor
GO111MODULE=on go mod verify
go mod tidy
go mod vendor
go mod verify
.PHONY: validate
validate: .install.lint
$(GOBIN)/golangci-lint run
validate:
golangci-lint run
.PHONY: test
test: test-unit test-integration
@ -47,17 +44,12 @@ test-integration:
.PHONY: test-unit
test-unit:
go test -v $(PROJECT)
go test -v $(PROJECT)/internal/...
$(GO) test -v $(EXTRA_TEST_FLAGS) ./...
.PHONY: install
install:
sudo install -D -m755 $(BUILD_DIR)/$(NAME) $(BIN_DIR)
.PHONY: .install.lint
.install.lint:
VERSION=1.24.0 GOBIN=$(GOBIN) sh ./hack/install_golangci.sh
.PHONY: uninstall
uninstall:
sudo rm $(BIN_DIR)/$(NAME)

View file

@ -73,8 +73,12 @@ The ps library is compatible with all AIX format descriptors of the ps command-l
- Set of inheritable capabilities. See capabilities(7) for more information.
- **capprm**
- Set of permitted capabilities. See capabilities(7) for more information.
- **groups**
- Supplmentary groups inside the container.
- **hgroup**
- The corresponding effective group of a container process on the host.
- **hgroups**
- Supplmentary groups on the host.
- **hpid**
- The corresponding host PID of a container process.
- **huser**

View file

@ -1,10 +1,9 @@
module github.com/containers/psgo
go 1.13
go 1.14
require (
github.com/opencontainers/runc v1.0.2
github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.0
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2
)

View file

@ -39,7 +39,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=

View file

@ -54,7 +54,7 @@ func BootTime() (int64, error) {
btimeSec, err := strconv.ParseInt(btimeStr, 10, 64)
if err != nil {
return 0, fmt.Errorf("error parsing boot time from /proc/stat: %s", err)
return 0, fmt.Errorf("error parsing boot time from /proc/stat: %w", err)
}
bootTime = &btimeSec
return btimeSec, nil

View file

@ -59,7 +59,7 @@ func ReadMappings(path string) ([]IDMap, error) {
for {
line, _, err := buf.ReadLine()
if err != nil {
if err == io.EOF {
if err == io.EOF { //nolint:errorlint // False positive, see https://github.com/polyfloyd/go-errorlint/pull/12
return mappings, nil
}
return nil, fmt.Errorf("cannot read line from %s: %w", path, err)

View file

@ -52,7 +52,7 @@ func GetPIDs() ([]string, error) {
return pids, nil
}
// GetPIDsFromCgroup returns a strings slice of all pids listesd in pid's pids
// GetPIDsFromCgroup returns a strings slice of all pids listed in pid's pids
// cgroup. It automatically detects if we're running in unified mode or not.
func GetPIDsFromCgroup(pid string) ([]string, error) {
unified, err := cgroups.IsCgroup2UnifiedMode()
@ -65,11 +65,12 @@ func GetPIDsFromCgroup(pid string) ([]string, error) {
return getPIDsFromCgroupV1(pid)
}
// getPIDsFromCgroupV1 returns a strings slice of all pids listesd in pid's pids
// getPIDsFromCgroupV1 returns a strings slice of all pids listed in pid's pids
// cgroup.
func getPIDsFromCgroupV1(pid string) ([]string, error) {
// First, find the corresponding path to the PID cgroup.
f, err := os.Open(fmt.Sprintf("/proc/%s/cgroup", pid))
pidPath := fmt.Sprintf("/proc/%s/cgroup", pid)
f, err := os.Open(pidPath)
if err != nil {
return nil, err
}
@ -83,7 +84,8 @@ func getPIDsFromCgroupV1(pid string) ([]string, error) {
continue
}
if fields[1] == "pids" {
cgroupPath = fmt.Sprintf("/sys/fs/cgroup/pids/%s/cgroup.procs", fields[2])
cgroupPath = filepath.Join(cgroups.CgroupRoot, "pids", fields[2], "cgroup.procs")
break
}
}
@ -94,7 +96,18 @@ func getPIDsFromCgroupV1(pid string) ([]string, error) {
// Second, extract the PIDs inside the cgroup.
f, err = os.Open(cgroupPath)
if err != nil {
return nil, err
if os.IsNotExist(err) {
// OCI runtimes might mount the container cgroup at the root, breaking what it showed
// in /proc/$PID/cgroup and the path.
// Check if the PID still exists to make sure the process is still alive.
if _, errStat := os.Stat(pidPath); errStat == nil {
cgroupPath = filepath.Join(cgroups.CgroupRoot, "pids", "cgroup.procs")
f, err = os.Open(cgroupPath)
}
}
if err != nil {
return nil, err
}
}
defer f.Close()
@ -107,7 +120,7 @@ func getPIDsFromCgroupV1(pid string) ([]string, error) {
return pids, nil
}
// getPIDsFromCgroupV2 returns a strings slice of all pids listesd in pid's pids
// getPIDsFromCgroupV2 returns a strings slice of all pids listed in pid's pids
// cgroup.
func getPIDsFromCgroupV2(pid string) ([]string, error) {
// First, find the corresponding path to the PID cgroup.
@ -124,8 +137,10 @@ func getPIDsFromCgroupV2(pid string) ([]string, error) {
if len(fields) != 3 {
continue
}
cgroupSlice = fields[2]
break
if fields[1] == "" {
cgroupSlice = fields[2]
break
}
}
if cgroupSlice == "" {

View file

@ -182,7 +182,7 @@ func readStatusUserNS(pid string) ([]string, error) {
c := exec.Command(args[0], args[1:]...)
output, err := c.CombinedOutput()
if err != nil {
return nil, fmt.Errorf("error executing %q: %v", strings.Join(args, " "), err)
return nil, fmt.Errorf("error executing %q: %w", strings.Join(args, " "), err)
}
return strings.Split(string(output), "\n"), nil

View file

@ -215,7 +215,7 @@ func (p *Process) StartTime() (time.Time, error) {
return time.Unix(sinceBoot+bootTime, 0), nil
}
// CPUTime returns the cumlative CPU time of process p as a time.Duration.
// CPUTime returns the cumulative CPU time of process p as a time.Duration.
func (p *Process) CPUTime() (time.Duration, error) {
user, err := strconv.ParseInt(p.Stat.Utime, 10, 64)
if err != nil {

View file

@ -174,6 +174,11 @@ var (
header: "GROUP",
procFn: processGROUP,
},
{
normal: "groups",
header: "GROUPS",
procFn: processGROUPS,
},
{
code: "%P",
normal: "ppid",
@ -305,6 +310,12 @@ var (
onHost: true,
procFn: processHGROUP,
},
{
normal: "hgroups",
header: "HGROUPS",
onHost: true,
procFn: processHGROUPS,
},
{
normal: "rss",
header: "RSS",
@ -620,14 +631,29 @@ func findHostProcess(p *process.Process, ctx *psContext) *process.Process {
}
// processGROUP returns the effective group ID of the process. This will be
// the textual group ID, if it can be optained, or a decimal representation
// the textual group ID, if it can be obtained, or a decimal representation
// otherwise.
func processGROUP(p *process.Process, ctx *psContext) (string, error) {
return process.LookupGID(p.Status.Gids[1])
}
// processGROUPS returns the supplementary groups of the process separated by
// comma. This will be the textual group ID, if it can be obtained, or a
// decimal representation otherwise.
func processGROUPS(p *process.Process, ctx *psContext) (string, error) {
var err error
groups := make([]string, len(p.Status.Groups))
for i, g := range p.Status.Groups {
groups[i], err = process.LookupGID(g)
if err != nil {
return "", err
}
}
return strings.Join(groups, ","), nil
}
// processRGROUP returns the real group ID of the process. This will be
// the textual group ID, if it can be optained, or a decimal representation
// the textual group ID, if it can be obtained, or a decimal representation
// otherwise.
func processRGROUP(p *process.Process, ctx *psContext) (string, error) {
return process.LookupGID(p.Status.Gids[0])
@ -639,14 +665,14 @@ func processPPID(p *process.Process, ctx *psContext) (string, error) {
}
// processUSER returns the effective user name of the process. This will be
// the textual user ID, if it can be optained, or a decimal representation
// the textual user ID, if it can be obtained, or a decimal representation
// otherwise.
func processUSER(p *process.Process, ctx *psContext) (string, error) {
return process.LookupUID(p.Status.Uids[1])
}
// processRUSER returns the effective user name of the process. This will be
// the textual user ID, if it can be optained, or a decimal representation
// the textual user ID, if it can be obtained, or a decimal representation
// otherwise.
func processRUSER(p *process.Process, ctx *psContext) (string, error) {
return process.LookupUID(p.Status.Uids[0])
@ -867,6 +893,26 @@ func processHGROUP(p *process.Process, ctx *psContext) (string, error) {
return "?", nil
}
// processHGROUPS returns the supplementary groups of the corresponding host
// process of the (container) or "?" if no corresponding process could be
// found.
func processHGROUPS(p *process.Process, ctx *psContext) (string, error) {
if hp := findHostProcess(p, ctx); hp != nil {
groups := hp.Status.Groups
if ctx.opts != nil && len(ctx.opts.GIDMap) > 0 {
var err error
for i, g := range groups {
groups[i], err = findID(g, ctx.opts.GIDMap, process.LookupGID, "/proc/sys/fs/overflowgid")
if err != nil {
return "", err
}
}
}
return strings.Join(groups, ","), nil
}
return "?", nil
}
// processRSS returns the resident set size of process p in KiB (1024-byte
// units).
func processRSS(p *process.Process, ctx *psContext) (string, error) {

2
vendor/modules.txt vendored
View file

@ -191,7 +191,7 @@ github.com/containers/ocicrypt/keywrap/pkcs7
github.com/containers/ocicrypt/spec
github.com/containers/ocicrypt/utils
github.com/containers/ocicrypt/utils/keyprovider
# github.com/containers/psgo v1.6.0
# github.com/containers/psgo v1.7.1
github.com/containers/psgo
github.com/containers/psgo/internal/capabilities
github.com/containers/psgo/internal/cgroups