summaryrefslogtreecommitdiff
path: root/vendor/github.com
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com')
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/build.go2
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go10
-rw-r--r--vendor/github.com/containers/buildah/pkg/formats/formats.go171
-rw-r--r--vendor/github.com/containers/buildah/pkg/formats/templates.go78
-rw-r--r--vendor/github.com/containers/buildah/run.go90
-rw-r--r--vendor/github.com/containers/psgo/internal/dev/tty.go11
-rw-r--r--vendor/github.com/containers/psgo/internal/proc/status.go5
-rw-r--r--vendor/github.com/containers/psgo/internal/process/process.go13
-rw-r--r--vendor/github.com/containers/psgo/internal/types/types.go22
-rw-r--r--vendor/github.com/containers/psgo/psgo.go137
10 files changed, 390 insertions, 149 deletions
diff --git a/vendor/github.com/containers/buildah/imagebuildah/build.go b/vendor/github.com/containers/buildah/imagebuildah/build.go
index d69eab52f..4f0ffac1c 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/build.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/build.go
@@ -293,7 +293,7 @@ func (b *Executor) Preserve(path string) error {
// Try and resolve the symlink (if one exists)
// Set archivedPath and path based on whether a symlink is found or not
- if symLink, err := ResolveSymLink(b.mountPoint, path); err == nil {
+ if symLink, err := resolveSymlink(b.mountPoint, path); err == nil {
archivedPath = filepath.Join(b.mountPoint, symLink)
path = symLink
} else {
diff --git a/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go b/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go
index 6feedf6a5..86bf7653b 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go
@@ -24,9 +24,7 @@ func init() {
reexec.Register(symlinkModifiedTime, resolveSymlinkTimeModified)
}
-// main() for grandparent subprocess. Its main job is to shuttle stdio back
-// and forth, managing a pseudo-terminal if we want one, for our child, the
-// parent subprocess.
+// main() for resolveSymlink()'s subprocess.
func resolveChrootedSymlinks() {
status := 0
flag.Parse()
@@ -57,9 +55,9 @@ func resolveChrootedSymlinks() {
os.Exit(status)
}
-// ResolveSymLink (in the grandparent process) resolves any symlink in filename
+// resolveSymlink uses a child subprocess to resolve any symlinks in filename
// in the context of rootdir.
-func ResolveSymLink(rootdir, filename string) (string, error) {
+func resolveSymlink(rootdir, filename string) (string, error) {
// The child process expects a chroot and one path that
// will be consulted relative to the chroot directory and evaluated
// for any symbolic links present.
@@ -253,7 +251,7 @@ func hasSymlink(path string) (bool, string, error) {
}
// if the symlink points to a relative path, prepend the path till now to the resolved path
if !filepath.IsAbs(targetDir) {
- targetDir = filepath.Join(path, targetDir)
+ targetDir = filepath.Join(filepath.Dir(path), targetDir)
}
// run filepath.Clean to remove the ".." from relative paths
return true, filepath.Clean(targetDir), nil
diff --git a/vendor/github.com/containers/buildah/pkg/formats/formats.go b/vendor/github.com/containers/buildah/pkg/formats/formats.go
new file mode 100644
index 000000000..37f9b8a20
--- /dev/null
+++ b/vendor/github.com/containers/buildah/pkg/formats/formats.go
@@ -0,0 +1,171 @@
+package formats
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+ "text/tabwriter"
+ "text/template"
+
+ "github.com/ghodss/yaml"
+ "github.com/pkg/errors"
+ "golang.org/x/crypto/ssh/terminal"
+)
+
+const (
+ // JSONString const to save on duplicate variable names
+ JSONString = "json"
+ // IDString const to save on duplicates for Go templates
+ IDString = "{{.ID}}"
+
+ parsingErrorStr = "Template parsing error"
+)
+
+// Writer interface for outputs
+type Writer interface {
+ Out() error
+}
+
+// JSONStructArray for JSON output
+type JSONStructArray struct {
+ Output []interface{}
+}
+
+// StdoutTemplateArray for Go template output
+type StdoutTemplateArray struct {
+ Output []interface{}
+ Template string
+ Fields map[string]string
+}
+
+// JSONStruct for JSON output
+type JSONStruct struct {
+ Output interface{}
+}
+
+// StdoutTemplate for Go template output
+type StdoutTemplate struct {
+ Output interface{}
+ Template string
+ Fields map[string]string
+}
+
+// YAMLStruct for YAML output
+type YAMLStruct struct {
+ Output interface{}
+}
+
+func setJSONFormatEncoder(isTerminal bool, w io.Writer) *json.Encoder {
+ enc := json.NewEncoder(w)
+ enc.SetIndent("", " ")
+ if isTerminal {
+ enc.SetEscapeHTML(false)
+ }
+ return enc
+}
+
+// Out method for JSON Arrays
+func (j JSONStructArray) Out() error {
+ buf := bytes.NewBuffer(nil)
+ enc := setJSONFormatEncoder(terminal.IsTerminal(int(os.Stdout.Fd())), buf)
+ if err := enc.Encode(j.Output); err != nil {
+ return err
+ }
+ data := buf.Bytes()
+
+ // JSON returns a byte array with a literal null [110 117 108 108] in it
+ // if it is passed empty data. We used bytes.Compare to see if that is
+ // the case.
+ if diff := bytes.Compare(data, []byte("null")); diff == 0 {
+ data = []byte("[]")
+ }
+
+ // If the we did get NULL back, we should spit out {} which is
+ // at least valid JSON for the consumer.
+ fmt.Printf("%s", data)
+ humanNewLine()
+ return nil
+}
+
+// Out method for Go templates
+func (t StdoutTemplateArray) Out() error {
+ w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
+ if strings.HasPrefix(t.Template, "table") {
+ // replace any spaces with tabs in template so that tabwriter can align it
+ t.Template = strings.Replace(strings.TrimSpace(t.Template[5:]), " ", "\t", -1)
+ headerTmpl, err := template.New("header").Funcs(headerFunctions).Parse(t.Template)
+ if err != nil {
+ return errors.Wrapf(err, parsingErrorStr)
+ }
+ err = headerTmpl.Execute(w, t.Fields)
+ if err != nil {
+ return err
+ }
+ fmt.Fprintln(w, "")
+ }
+ t.Template = strings.Replace(t.Template, " ", "\t", -1)
+ tmpl, err := template.New("image").Funcs(basicFunctions).Parse(t.Template)
+ if err != nil {
+ return errors.Wrapf(err, parsingErrorStr)
+ }
+ for i, raw := range t.Output {
+ basicTmpl := tmpl.Funcs(basicFunctions)
+ if err := basicTmpl.Execute(w, raw); err != nil {
+ return errors.Wrapf(err, parsingErrorStr)
+ }
+ if i != len(t.Output)-1 {
+ fmt.Fprintln(w, "")
+ continue
+ }
+ }
+ fmt.Fprintln(w, "")
+ return w.Flush()
+}
+
+// Out method for JSON struct
+func (j JSONStruct) Out() error {
+ data, err := json.MarshalIndent(j.Output, "", " ")
+ if err != nil {
+ return err
+ }
+ fmt.Printf("%s", data)
+ humanNewLine()
+ return nil
+}
+
+//Out method for Go templates
+func (t StdoutTemplate) Out() error {
+ tmpl, err := template.New("image").Parse(t.Template)
+ if err != nil {
+ return errors.Wrapf(err, "template parsing error")
+ }
+ err = tmpl.Execute(os.Stdout, t.Output)
+ if err != nil {
+ return err
+ }
+ humanNewLine()
+ return nil
+}
+
+// Out method for YAML
+func (y YAMLStruct) Out() error {
+ var buf []byte
+ var err error
+ buf, err = yaml.Marshal(y.Output)
+ if err != nil {
+ return err
+ }
+ fmt.Printf("%s", string(buf))
+ humanNewLine()
+ return nil
+}
+
+// humanNewLine prints a new line at the end of the output only if stdout is the terminal
+func humanNewLine() {
+ if terminal.IsTerminal(int(os.Stdout.Fd())) {
+ fmt.Println()
+ }
+}
diff --git a/vendor/github.com/containers/buildah/pkg/formats/templates.go b/vendor/github.com/containers/buildah/pkg/formats/templates.go
new file mode 100644
index 000000000..c2582552a
--- /dev/null
+++ b/vendor/github.com/containers/buildah/pkg/formats/templates.go
@@ -0,0 +1,78 @@
+package formats
+
+import (
+ "bytes"
+ "encoding/json"
+ "strings"
+ "text/template"
+)
+
+// basicFunctions are the set of initial
+// functions provided to every template.
+var basicFunctions = template.FuncMap{
+ "json": func(v interface{}) string {
+ buf := &bytes.Buffer{}
+ enc := json.NewEncoder(buf)
+ enc.SetEscapeHTML(false)
+ _ = enc.Encode(v)
+ // Remove the trailing new line added by the encoder
+ return strings.TrimSpace(buf.String())
+ },
+ "split": strings.Split,
+ "join": strings.Join,
+ "title": strings.Title,
+ "lower": strings.ToLower,
+ "upper": strings.ToUpper,
+ "pad": padWithSpace,
+ "truncate": truncateWithLength,
+}
+
+// HeaderFunctions are used to created headers of a table.
+// This is a replacement of basicFunctions for header generation
+// because we want the header to remain intact.
+// Some functions like `split` are irrelevant so not added.
+var headerFunctions = template.FuncMap{
+ "json": func(v string) string {
+ return v
+ },
+ "title": func(v string) string {
+ return v
+ },
+ "lower": func(v string) string {
+ return v
+ },
+ "upper": func(v string) string {
+ return v
+ },
+ "truncate": func(v string, l int) string {
+ return v
+ },
+}
+
+// Parse creates a new anonymous template with the basic functions
+// and parses the given format.
+func Parse(format string) (*template.Template, error) {
+ return NewParse("", format)
+}
+
+// NewParse creates a new tagged template with the basic functions
+// and parses the given format.
+func NewParse(tag, format string) (*template.Template, error) {
+ return template.New(tag).Funcs(basicFunctions).Parse(format)
+}
+
+// padWithSpace adds whitespace to the input if the input is non-empty
+func padWithSpace(source string, prefix, suffix int) string {
+ if source == "" {
+ return source
+ }
+ return strings.Repeat(" ", prefix) + source + strings.Repeat(" ", suffix)
+}
+
+// truncateWithLength truncates the source string up to the length provided by the input
+func truncateWithLength(source string, length int) string {
+ if len(source) < length {
+ return source
+ }
+ return source[:length]
+}
diff --git a/vendor/github.com/containers/buildah/run.go b/vendor/github.com/containers/buildah/run.go
index 4d6d28380..f56ce30b1 100644
--- a/vendor/github.com/containers/buildah/run.go
+++ b/vendor/github.com/containers/buildah/run.go
@@ -1,7 +1,6 @@
package buildah
import (
- "bufio"
"bytes"
"encoding/json"
"fmt"
@@ -272,36 +271,6 @@ func addRlimits(ulimit []string, g *generate.Generator) error {
return nil
}
-func addHosts(hosts []string, w io.Writer) error {
- buf := bufio.NewWriter(w)
- for _, host := range hosts {
- values := strings.SplitN(host, ":", 2)
- if len(values) != 2 {
- return errors.Errorf("unable to parse host entry %q: incorrect format", host)
- }
- if values[0] == "" {
- return errors.Errorf("hostname in host entry %q is empty", host)
- }
- if values[1] == "" {
- return errors.Errorf("IP address in host entry %q is empty", host)
- }
- fmt.Fprintf(buf, "%s\t%s\n", values[1], values[0])
- }
- return buf.Flush()
-}
-
-func addHostsToFile(hosts []string, filename string) error {
- if len(hosts) == 0 {
- return nil
- }
- file, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
- if err != nil {
- return errors.Wrapf(err, "error creating hosts file %q", filename)
- }
- defer file.Close()
- return addHosts(hosts, file)
-}
-
func addCommonOptsToSpec(commonOpts *CommonBuildOptions, g *generate.Generator) error {
// Resources - CPU
if commonOpts.CPUPeriod != 0 {
@@ -638,6 +607,59 @@ func (b *Builder) addNetworkConfig(rdir, hostPath string, chownOpts *idtools.IDP
return cfile, nil
}
+// generateHosts creates a containers hosts file
+func (b *Builder) generateHosts(rdir, hostname string, addHosts []string, chownOpts *idtools.IDPair) (string, error) {
+ hostPath := "/etc/hosts"
+ stat, err := os.Stat(hostPath)
+ if err != nil {
+ return "", errors.Wrapf(err, "error statting %q for container %q", hostPath, b.ContainerID)
+ }
+
+ hosts := bytes.NewBufferString("# Generated by Buildah\n")
+ orig, err := ioutil.ReadFile(hostPath)
+ if err != nil {
+ return "", errors.Wrapf(err, "unable to read %s", hostPath)
+ }
+ hosts.Write(orig)
+ for _, host := range addHosts {
+ // verify the host format
+ values := strings.SplitN(host, ":", 2)
+ if len(values) != 2 {
+ return "", errors.Errorf("unable to parse host entry %q: incorrect format", host)
+ }
+ if values[0] == "" {
+ return "", errors.Errorf("hostname in host entry %q is empty", host)
+ }
+ if values[1] == "" {
+ return "", errors.Errorf("IP address in host entry %q is empty", host)
+ }
+ hosts.Write([]byte(fmt.Sprintf("%s\t%s\n", values[1], values[0])))
+ }
+
+ if hostname != "" {
+ hosts.Write([]byte(fmt.Sprintf("127.0.0.1 %s\n", hostname)))
+ hosts.Write([]byte(fmt.Sprintf("::1 %s\n", hostname)))
+ }
+ cfile := filepath.Join(rdir, filepath.Base(hostPath))
+ if err = ioutils.AtomicWriteFile(cfile, hosts.Bytes(), stat.Mode().Perm()); err != nil {
+ return "", errors.Wrapf(err, "error writing /etc/hosts into the container")
+ }
+ uid := int(stat.Sys().(*syscall.Stat_t).Uid)
+ gid := int(stat.Sys().(*syscall.Stat_t).Gid)
+ if chownOpts != nil {
+ uid = chownOpts.UID
+ gid = chownOpts.GID
+ }
+ if err = os.Chown(cfile, uid, gid); err != nil {
+ return "", errors.Wrapf(err, "error chowning file %q for container %q", cfile, b.ContainerID)
+ }
+ if err := label.Relabel(cfile, b.MountLabel, false); err != nil {
+ return "", errors.Wrapf(err, "error relabeling %q in container %q", cfile, b.ContainerID)
+ }
+
+ return cfile, nil
+}
+
func setupMaskedPaths(g *generate.Generator) {
for _, mp := range []string{
"/proc/acpi",
@@ -1081,15 +1103,11 @@ func (b *Builder) Run(command []string, options RunOptions) error {
volumes := b.Volumes()
if !contains(volumes, "/etc/hosts") {
- hostFile, err := b.addNetworkConfig(path, "/etc/hosts", rootIDPair)
+ hostFile, err := b.generateHosts(path, spec.Hostname, b.CommonBuildOpts.AddHost, rootIDPair)
if err != nil {
return err
}
bindFiles["/etc/hosts"] = hostFile
-
- if err := addHostsToFile(b.CommonBuildOpts.AddHost, hostFile); err != nil {
- return err
- }
}
if !contains(volumes, "/etc/resolv.conf") {
diff --git a/vendor/github.com/containers/psgo/internal/dev/tty.go b/vendor/github.com/containers/psgo/internal/dev/tty.go
index cc7d0a422..b7d6f28ac 100644
--- a/vendor/github.com/containers/psgo/internal/dev/tty.go
+++ b/vendor/github.com/containers/psgo/internal/dev/tty.go
@@ -31,12 +31,9 @@ type TTY struct {
Path string
}
-// cache TTYs to avoid redundant lookups
-var devices *[]TTY
-
// FindTTY return the corresponding TTY to the ttyNr or nil of non could be
// found.
-func FindTTY(ttyNr uint64) (*TTY, error) {
+func FindTTY(ttyNr uint64, devices *[]TTY) (*TTY, error) {
// (man 5 proc) The minor device number is contained in the combination
// of bits 31 to 20 and 7 to 0; the major device number is in bits 15
// to 8.
@@ -44,7 +41,7 @@ func FindTTY(ttyNr uint64) (*TTY, error) {
min := (ttyNr & 0xFF) | ((ttyNr >> 20) & 0xFFF)
if devices == nil {
- devs, err := getTTYs()
+ devs, err := TTYs()
if err != nil {
return nil, err
}
@@ -70,8 +67,8 @@ func minDevNum(rdev uint64) uint64 {
return (rdev & 0xff) | ((rdev >> 12) & 0xfff00)
}
-// getTTYs parses /dev for tty and pts devices.
-func getTTYs() (*[]TTY, error) {
+// TTYs parses /dev for tty and pts devices.
+func TTYs() (*[]TTY, error) {
devDir, err := os.Open("/dev/")
if err != nil {
return nil, err
diff --git a/vendor/github.com/containers/psgo/internal/proc/status.go b/vendor/github.com/containers/psgo/internal/proc/status.go
index 68e2acff6..29d059361 100644
--- a/vendor/github.com/containers/psgo/internal/proc/status.go
+++ b/vendor/github.com/containers/psgo/internal/proc/status.go
@@ -21,7 +21,6 @@ import (
"os/exec"
"strings"
- "github.com/containers/psgo/internal/types"
"github.com/pkg/errors"
)
@@ -207,11 +206,11 @@ func readStatusDefault(pid string) ([]string, error) {
}
// ParseStatus parses the /proc/$pid/status file and returns a *Status.
-func ParseStatus(ctx *types.PsContext, pid string) (*Status, error) {
+func ParseStatus(pid string, joinUserNS bool) (*Status, error) {
var lines []string
var err error
- if ctx.JoinUserNS {
+ if joinUserNS {
lines, err = readStatusUserNS(pid)
} else {
lines, err = readStatusDefault(pid)
diff --git a/vendor/github.com/containers/psgo/internal/process/process.go b/vendor/github.com/containers/psgo/internal/process/process.go
index 0afbf721d..2aebfe9cc 100644
--- a/vendor/github.com/containers/psgo/internal/process/process.go
+++ b/vendor/github.com/containers/psgo/internal/process/process.go
@@ -21,7 +21,6 @@ import (
"github.com/containers/psgo/internal/host"
"github.com/containers/psgo/internal/proc"
- "github.com/containers/psgo/internal/types"
"github.com/opencontainers/runc/libcontainer/user"
"github.com/pkg/errors"
)
@@ -76,13 +75,13 @@ func LookupUID(uid string) (string, error) {
// New returns a new Process with the specified pid and parses the relevant
// data from /proc and /dev.
-func New(ctx *types.PsContext, pid string) (*Process, error) {
+func New(pid string, joinUserNS bool) (*Process, error) {
p := Process{Pid: pid}
if err := p.parseStat(); err != nil {
return nil, err
}
- if err := p.parseStatus(ctx); err != nil {
+ if err := p.parseStatus(joinUserNS); err != nil {
return nil, err
}
if err := p.parseCmdLine(); err != nil {
@@ -103,10 +102,10 @@ func New(ctx *types.PsContext, pid string) (*Process, error) {
}
// FromPIDs creates a new Process for each pid.
-func FromPIDs(ctx *types.PsContext, pids []string) ([]*Process, error) {
+func FromPIDs(pids []string, joinUserNS bool) ([]*Process, error) {
processes := []*Process{}
for _, pid := range pids {
- p, err := New(ctx, pid)
+ p, err := New(pid, joinUserNS)
if err != nil {
if os.IsNotExist(errors.Cause(err)) {
// proc parsing is racy
@@ -131,8 +130,8 @@ func (p *Process) parseStat() error {
}
// parseStatus parses /proc/$pid/status.
-func (p *Process) parseStatus(ctx *types.PsContext) error {
- s, err := proc.ParseStatus(ctx, p.Pid)
+func (p *Process) parseStatus(joinUserNS bool) error {
+ s, err := proc.ParseStatus(p.Pid, joinUserNS)
if err != nil {
return err
}
diff --git a/vendor/github.com/containers/psgo/internal/types/types.go b/vendor/github.com/containers/psgo/internal/types/types.go
deleted file mode 100644
index 1f6fe0eaa..000000000
--- a/vendor/github.com/containers/psgo/internal/types/types.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2018 psgo authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package types
-
-// PsContext controls some internals of the psgo library.
-type PsContext struct {
- // JoinUserNS will force /proc and /dev parsing from within each PIDs
- // user namespace.
- JoinUserNS bool
-}
diff --git a/vendor/github.com/containers/psgo/psgo.go b/vendor/github.com/containers/psgo/psgo.go
index 47a50264f..e0f102735 100644
--- a/vendor/github.com/containers/psgo/psgo.go
+++ b/vendor/github.com/containers/psgo/psgo.go
@@ -39,14 +39,22 @@ import (
"github.com/containers/psgo/internal/dev"
"github.com/containers/psgo/internal/proc"
"github.com/containers/psgo/internal/process"
- "github.com/containers/psgo/internal/types"
"github.com/pkg/errors"
"golang.org/x/sys/unix"
)
+type psContext struct {
+ // Processes in the container.
+ containersProcesses []*process.Process
+ // Processes on the host. Used to map those to the ones running in the container.
+ hostProcesses []*process.Process
+ // tty and pty devices.
+ ttys *[]dev.TTY
+}
+
// processFunc is used to map a given aixFormatDescriptor to a corresponding
// function extracting the desired data from a process.
-type processFunc func(*process.Process) (string, error)
+type processFunc func(*process.Process, *psContext) (string, error)
// aixFormatDescriptor as mentioned in the ps(1) manpage. A given descriptor
// can either be specified via its code (e.g., "%C") or its normal representation
@@ -99,13 +107,6 @@ var (
// ErrUnkownDescriptor is returned when an unknown descriptor is parsed.
ErrUnkownDescriptor = errors.New("unknown descriptor")
- // hostProcesses are the processes on the host. It should only be used
- // in the context of containers and is meant to display data of the
- // container processes from the host's (i.e., calling process) view.
- // Currently, all host processes contain only the required data from
- // /proc/$pid/status.
- hostProcesses []*process.Process
-
aixFormatDescriptors = []aixFormatDescriptor{
{
code: "%C",
@@ -282,11 +283,16 @@ func JoinNamespaceAndProcessInfo(pid string, descriptors []string) ([][]string,
return nil, err
}
+ ctx := new(psContext)
+
// extract data from host processes only on-demand / when at least one
// of the specified descriptors requires host data
for _, d := range aixDescriptors {
if d.onHost {
- setHostProcesses(pid)
+ ctx.hostProcesses, err = hostProcesses(pid)
+ if err != nil {
+ return nil, err
+ }
break
}
}
@@ -330,18 +336,17 @@ func JoinNamespaceAndProcessInfo(pid string, descriptors []string) ([][]string,
return
}
- ctx := types.PsContext{
- // join the user NS if the pid's user NS is different
- // to the caller's user NS.
- JoinUserNS: currentUserNs != pidUserNs,
- }
- processes, err := process.FromPIDs(&ctx, pids)
+ // join the user NS if the pid's user NS is different
+ // to the caller's user NS.
+ joinUserNS := currentUserNs != pidUserNs
+
+ ctx.containersProcesses, err = process.FromPIDs(pids, joinUserNS)
if err != nil {
dataErr = err
return
}
- data, dataErr = processDescriptors(aixDescriptors, processes)
+ data, dataErr = processDescriptors(aixDescriptors, ctx)
}()
wg.Wait()
@@ -417,43 +422,41 @@ func ProcessInfoByPids(pids []string, descriptors []string) ([][]string, error)
return nil, err
}
- ctx := types.PsContext{JoinUserNS: false}
- processes, err := process.FromPIDs(&ctx, pids)
+ ctx := new(psContext)
+ ctx.containersProcesses, err = process.FromPIDs(pids, false)
if err != nil {
return nil, err
}
- return processDescriptors(aixDescriptors, processes)
+ return processDescriptors(aixDescriptors, ctx)
}
-// setHostProcesses sets `hostProcesses`.
-func setHostProcesses(pid string) error {
+// hostProcesses returns all processes running in the current namespace.
+func hostProcesses(pid string) ([]*process.Process, error) {
// get processes
pids, err := proc.GetPIDsFromCgroup(pid)
if err != nil {
- return err
+ return nil, err
}
- ctx := types.PsContext{JoinUserNS: false}
- processes, err := process.FromPIDs(&ctx, pids)
+ processes, err := process.FromPIDs(pids, false)
if err != nil {
- return err
+ return nil, err
}
// set the additional host data
for _, p := range processes {
if err := p.SetHostData(); err != nil {
- return err
+ return nil, err
}
}
- hostProcesses = processes
- return nil
+ return processes, nil
}
// processDescriptors calls each `procFn` of all formatDescriptors on each
// process and returns an array of tab-separated strings.
-func processDescriptors(formatDescriptors []aixFormatDescriptor, processes []*process.Process) ([][]string, error) {
+func processDescriptors(formatDescriptors []aixFormatDescriptor, ctx *psContext) ([][]string, error) {
data := [][]string{}
// create header
header := []string{}
@@ -463,10 +466,10 @@ func processDescriptors(formatDescriptors []aixFormatDescriptor, processes []*pr
data = append(data, header)
// dispatch all descriptor functions on each process
- for _, proc := range processes {
+ for _, proc := range ctx.containersProcesses {
pData := []string{}
for _, desc := range formatDescriptors {
- dataStr, err := desc.procFn(proc)
+ dataStr, err := desc.procFn(proc, ctx)
if err != nil {
return nil, err
}
@@ -480,8 +483,8 @@ func processDescriptors(formatDescriptors []aixFormatDescriptor, processes []*pr
// findHostProcess returns the corresponding process from `hostProcesses` or
// nil if non is found.
-func findHostProcess(p *process.Process) *process.Process {
- for _, hp := range hostProcesses {
+func findHostProcess(p *process.Process, ctx *psContext) *process.Process {
+ for _, hp := range ctx.hostProcesses {
// We expect the host process to be in another namespace, so
// /proc/$pid/status.NSpid must have at least two entries.
if len(hp.Status.NSpid) < 2 {
@@ -499,78 +502,78 @@ func findHostProcess(p *process.Process) *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
// otherwise.
-func processGROUP(p *process.Process) (string, error) {
+func processGROUP(p *process.Process, ctx *psContext) (string, error) {
return process.LookupGID(p.Status.Gids[1])
}
// 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
// otherwise.
-func processRGROUP(p *process.Process) (string, error) {
+func processRGROUP(p *process.Process, ctx *psContext) (string, error) {
return process.LookupGID(p.Status.Gids[0])
}
// processPPID returns the parent process ID of process p.
-func processPPID(p *process.Process) (string, error) {
+func processPPID(p *process.Process, ctx *psContext) (string, error) {
return p.Status.PPid, nil
}
// 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
// otherwise.
-func processUSER(p *process.Process) (string, error) {
+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
// otherwise.
-func processRUSER(p *process.Process) (string, error) {
+func processRUSER(p *process.Process, ctx *psContext) (string, error) {
return process.LookupUID(p.Status.Uids[0])
}
// processName returns the name of process p in the format "[$name]".
-func processName(p *process.Process) (string, error) {
+func processName(p *process.Process, ctx *psContext) (string, error) {
return fmt.Sprintf("[%s]", p.Status.Name), nil
}
// processARGS returns the command of p with all its arguments.
-func processARGS(p *process.Process) (string, error) {
+func processARGS(p *process.Process, ctx *psContext) (string, error) {
// ps (1) returns "[$name]" if command/args are empty
if p.CmdLine[0] == "" {
- return processName(p)
+ return processName(p, ctx)
}
return strings.Join(p.CmdLine, " "), nil
}
// processCOMM returns the command name (i.e., executable name) of process p.
-func processCOMM(p *process.Process) (string, error) {
+func processCOMM(p *process.Process, ctx *psContext) (string, error) {
// ps (1) returns "[$name]" if command/args are empty
if p.CmdLine[0] == "" {
- return processName(p)
+ return processName(p, ctx)
}
spl := strings.Split(p.CmdLine[0], "/")
return spl[len(spl)-1], nil
}
// processNICE returns the nice value of process p.
-func processNICE(p *process.Process) (string, error) {
+func processNICE(p *process.Process, ctx *psContext) (string, error) {
return p.Stat.Nice, nil
}
// processPID returns the process ID of process p.
-func processPID(p *process.Process) (string, error) {
+func processPID(p *process.Process, ctx *psContext) (string, error) {
return p.Pid, nil
}
// processPGID returns the process group ID of process p.
-func processPGID(p *process.Process) (string, error) {
+func processPGID(p *process.Process, ctx *psContext) (string, error) {
return p.Stat.Pgrp, nil
}
// processPCPU returns how many percent of the CPU time process p uses as
// a three digit float as string.
-func processPCPU(p *process.Process) (string, error) {
+func processPCPU(p *process.Process, ctx *psContext) (string, error) {
elapsed, err := p.ElapsedTime()
if err != nil {
return "", err
@@ -585,7 +588,7 @@ func processPCPU(p *process.Process) (string, error) {
}
// processETIME returns the elapsed time since the process was started.
-func processETIME(p *process.Process) (string, error) {
+func processETIME(p *process.Process, ctx *psContext) (string, error) {
elapsed, err := p.ElapsedTime()
if err != nil {
return "", nil
@@ -594,7 +597,7 @@ func processETIME(p *process.Process) (string, error) {
}
// processTIME returns the cumulative CPU time of process p.
-func processTIME(p *process.Process) (string, error) {
+func processTIME(p *process.Process, ctx *psContext) (string, error) {
cpu, err := p.CPUTime()
if err != nil {
return "", err
@@ -603,13 +606,13 @@ func processTIME(p *process.Process) (string, error) {
}
// processTTY returns the controlling tty (terminal) of process p.
-func processTTY(p *process.Process) (string, error) {
+func processTTY(p *process.Process, ctx *psContext) (string, error) {
ttyNr, err := strconv.ParseUint(p.Stat.TtyNr, 10, 64)
if err != nil {
return "", nil
}
- tty, err := dev.FindTTY(ttyNr)
+ tty, err := dev.FindTTY(ttyNr, ctx.ttys)
if err != nil {
return "", nil
}
@@ -623,7 +626,7 @@ func processTTY(p *process.Process) (string, error) {
// processVSZ returns the virtual memory size of process p in KiB (1024-byte
// units).
-func processVSZ(p *process.Process) (string, error) {
+func processVSZ(p *process.Process, ctx *psContext) (string, error) {
vmsize, err := strconv.Atoi(p.Stat.Vsize)
if err != nil {
return "", err
@@ -653,41 +656,41 @@ func parseCAP(cap string) (string, error) {
// processCAPAMB returns the set of ambient capabilties associated with
// process p. If all capabilties are set, "full" is returned. If no
// capability is enabled, "none" is returned.
-func processCAPAMB(p *process.Process) (string, error) {
+func processCAPAMB(p *process.Process, ctx *psContext) (string, error) {
return parseCAP(p.Status.CapAmb)
}
// processCAPINH returns the set of inheritable capabilties associated with
// process p. If all capabilties are set, "full" is returned. If no
// capability is enabled, "none" is returned.
-func processCAPINH(p *process.Process) (string, error) {
+func processCAPINH(p *process.Process, ctx *psContext) (string, error) {
return parseCAP(p.Status.CapInh)
}
// processCAPPRM returns the set of permitted capabilties associated with
// process p. If all capabilties are set, "full" is returned. If no
// capability is enabled, "none" is returned.
-func processCAPPRM(p *process.Process) (string, error) {
+func processCAPPRM(p *process.Process, ctx *psContext) (string, error) {
return parseCAP(p.Status.CapPrm)
}
// processCAPEFF returns the set of effective capabilties associated with
// process p. If all capabilties are set, "full" is returned. If no
// capability is enabled, "none" is returned.
-func processCAPEFF(p *process.Process) (string, error) {
+func processCAPEFF(p *process.Process, ctx *psContext) (string, error) {
return parseCAP(p.Status.CapEff)
}
// processCAPBND returns the set of bounding capabilties associated with
// process p. If all capabilties are set, "full" is returned. If no
// capability is enabled, "none" is returned.
-func processCAPBND(p *process.Process) (string, error) {
+func processCAPBND(p *process.Process, ctx *psContext) (string, error) {
return parseCAP(p.Status.CapBnd)
}
// processSECCOMP returns the seccomp mode of the process (i.e., disabled,
// strict or filter) or "?" if /proc/$pid/status.seccomp has a unknown value.
-func processSECCOMP(p *process.Process) (string, error) {
+func processSECCOMP(p *process.Process, ctx *psContext) (string, error) {
switch p.Status.Seccomp {
case "0":
return "disabled", nil
@@ -702,14 +705,14 @@ func processSECCOMP(p *process.Process) (string, error) {
// processLABEL returns the process label of process p or "?" if the system
// doesn't support labeling.
-func processLABEL(p *process.Process) (string, error) {
+func processLABEL(p *process.Process, ctx *psContext) (string, error) {
return p.Label, nil
}
// processHPID returns the PID of the corresponding host process of the
// (container) or "?" if no corresponding process could be found.
-func processHPID(p *process.Process) (string, error) {
- if hp := findHostProcess(p); hp != nil {
+func processHPID(p *process.Process, ctx *psContext) (string, error) {
+ if hp := findHostProcess(p, ctx); hp != nil {
return hp.Pid, nil
}
return "?", nil
@@ -717,8 +720,8 @@ func processHPID(p *process.Process) (string, error) {
// processHUSER returns the effective user ID of the corresponding host process
// of the (container) or "?" if no corresponding process could be found.
-func processHUSER(p *process.Process) (string, error) {
- if hp := findHostProcess(p); hp != nil {
+func processHUSER(p *process.Process, ctx *psContext) (string, error) {
+ if hp := findHostProcess(p, ctx); hp != nil {
return hp.Huser, nil
}
return "?", nil
@@ -727,14 +730,14 @@ func processHUSER(p *process.Process) (string, error) {
// processHGROUP returns the effective group ID of the corresponding host
// process of the (container) or "?" if no corresponding process could be
// found.
-func processHGROUP(p *process.Process) (string, error) {
- if hp := findHostProcess(p); hp != nil {
+func processHGROUP(p *process.Process, ctx *psContext) (string, error) {
+ if hp := findHostProcess(p, ctx); hp != nil {
return hp.Hgroup, nil
}
return "?", nil
}
// processState returns the process state of process p.
-func processState(p *process.Process) (string, error) {
+func processState(p *process.Process, ctx *psContext) (string, error) {
return p.Status.State, nil
}