diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/adapter/client.go | 3 | ||||
-rw-r--r-- | pkg/adapter/containers.go | 45 | ||||
-rw-r--r-- | pkg/adapter/pods.go | 14 | ||||
-rw-r--r-- | pkg/adapter/runtime.go | 26 | ||||
-rw-r--r-- | pkg/adapter/runtime_remote.go | 24 | ||||
-rw-r--r-- | pkg/netns/netns_linux.go | 30 | ||||
-rw-r--r-- | pkg/spec/createconfig.go | 5 | ||||
-rw-r--r-- | pkg/spec/storage.go | 106 | ||||
-rw-r--r-- | pkg/util/utils_supported.go | 4 | ||||
-rw-r--r-- | pkg/varlinkapi/system.go | 1 |
10 files changed, 109 insertions, 149 deletions
diff --git a/pkg/adapter/client.go b/pkg/adapter/client.go index 694d9f961..da6ff5fd0 100644 --- a/pkg/adapter/client.go +++ b/pkg/adapter/client.go @@ -16,7 +16,7 @@ var remoteEndpoint *Endpoint func (r RemoteRuntime) RemoteEndpoint() (remoteEndpoint *Endpoint, err error) { remoteConfigConnections, err := remoteclientconfig.ReadRemoteConfig(r.config) - if errors.Cause(err) != remoteclientconfig.ErrNoConfigationFile { + if err != nil && errors.Cause(err) != remoteclientconfig.ErrNoConfigationFile { return nil, err } // If the user defines an env variable for podman_varlink_bridge @@ -68,7 +68,6 @@ func (r RemoteRuntime) Connect() (*varlink.Connection, error) { if err != nil { return nil, err } - switch ep.Type { case DirectConnection: return varlink.NewConnection(ep.Connection) diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index 967c79505..b712bd9aa 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -9,7 +9,6 @@ import ( "io" "io/ioutil" "os" - "path/filepath" "strconv" "strings" "sync" @@ -23,6 +22,7 @@ import ( "github.com/containers/libpod/cmd/podman/shared/parse" "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/libpod/events" "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/libpod/logs" "github.com/containers/libpod/pkg/adapter/shortcuts" @@ -418,14 +418,13 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode if ecode, err := ctr.Wait(); err != nil { if errors.Cause(err) == define.ErrNoSuchCtr { - // The container may have been removed - // Go looking for an exit file - ctrExitCode, err := ReadExitFile(config.TmpDir, ctr.ID()) + // Check events + event, err := r.Runtime.GetLastContainerEvent(ctr.ID(), events.Exited) if err != nil { logrus.Errorf("Cannot get exit code: %v", err) exitCode = 127 } else { - exitCode = ctrExitCode + exitCode = event.ContainerExitCode } } } else { @@ -441,31 +440,6 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode return exitCode, nil } -// ReadExitFile reads a container's exit file -func ReadExitFile(runtimeTmp, ctrID string) (int, error) { - exitFile := filepath.Join(runtimeTmp, "exits", fmt.Sprintf("%s-old", ctrID)) - - logrus.Debugf("Attempting to read container %s exit code from file %s", ctrID, exitFile) - - // Check if it exists - if _, err := os.Stat(exitFile); err != nil { - return 0, errors.Wrapf(err, "error getting exit file for container %s", ctrID) - } - - // File exists, read it in and convert to int - statusStr, err := ioutil.ReadFile(exitFile) - if err != nil { - return 0, errors.Wrapf(err, "error reading exit file for container %s", ctrID) - } - - exitCode, err := strconv.Atoi(string(statusStr)) - if err != nil { - return 0, errors.Wrapf(err, "error parsing exit code for container %s", ctrID) - } - - return exitCode, nil -} - // Ps ... func (r *LocalRuntime) Ps(c *cliconfig.PsValues, opts shared.PsOptions) ([]shared.PsContainerOutput, error) { maxWorkers := shared.Parallelize("ps") @@ -656,18 +630,13 @@ func (r *LocalRuntime) Start(ctx context.Context, c *cliconfig.StartValues, sigP if ecode, err := ctr.Wait(); err != nil { if errors.Cause(err) == define.ErrNoSuchCtr { - // The container may have been removed - // Go looking for an exit file - rtc, err := r.GetConfig() - if err != nil { - return 0, err - } - ctrExitCode, err := ReadExitFile(rtc.TmpDir, ctr.ID()) + // Check events + event, err := r.Runtime.GetLastContainerEvent(ctr.ID(), events.Exited) if err != nil { logrus.Errorf("Cannot get exit code: %v", err) exitCode = 127 } else { - exitCode = ctrExitCode + exitCode = event.ContainerExitCode } } } else { diff --git a/pkg/adapter/pods.go b/pkg/adapter/pods.go index b9d7fcd9b..e25238956 100644 --- a/pkg/adapter/pods.go +++ b/pkg/adapter/pods.go @@ -10,6 +10,7 @@ import ( "os" "strings" + "github.com/containers/buildah/pkg/parse" "github.com/containers/image/types" "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/shared" @@ -570,7 +571,7 @@ func (r *LocalRuntime) PlayKubeYAML(ctx context.Context, c *cliconfig.KubePlayVa } } - if err := createconfig.ValidateVolumeHostDir(hostPath.Path); err != nil { + if err := parse.ValidateVolumeHostDir(hostPath.Path); err != nil { return nil, errors.Wrapf(err, "Error in parsing HostPath in YAML") } volumes[volume.Name] = hostPath.Path @@ -682,6 +683,15 @@ func kubeContainerToCreateConfig(ctx context.Context, containerYAML v1.Container if containerYAML.SecurityContext.AllowPrivilegeEscalation != nil { containerConfig.NoNewPrivs = !*containerYAML.SecurityContext.AllowPrivilegeEscalation } + + } + if caps := containerYAML.SecurityContext.Capabilities; caps != nil { + for _, capability := range caps.Add { + containerConfig.CapAdd = append(containerConfig.CapAdd, string(capability)) + } + for _, capability := range caps.Drop { + containerConfig.CapDrop = append(containerConfig.CapDrop, string(capability)) + } } containerConfig.Command = []string{} @@ -728,7 +738,7 @@ func kubeContainerToCreateConfig(ctx context.Context, containerYAML v1.Container if !exists { return nil, errors.Errorf("Volume mount %s specified for container but not configured in volumes", volume.Name) } - if err := createconfig.ValidateVolumeCtrDir(volume.MountPath); err != nil { + if err := parse.ValidateVolumeCtrDir(volume.MountPath); err != nil { return nil, errors.Wrapf(err, "error in parsing MountPath") } containerConfig.Volumes = append(containerConfig.Volumes, fmt.Sprintf("%s:%s", hostPath, volume.MountPath)) diff --git a/pkg/adapter/runtime.go b/pkg/adapter/runtime.go index ee6913cc0..4a3b41297 100644 --- a/pkg/adapter/runtime.go +++ b/pkg/adapter/runtime.go @@ -5,22 +5,22 @@ package adapter import ( "bufio" "context" - "github.com/containers/libpod/libpod/define" "io" "io/ioutil" "os" "text/template" - "github.com/containers/libpod/cmd/podman/shared" - "github.com/containers/buildah" "github.com/containers/buildah/imagebuildah" + "github.com/containers/buildah/pkg/formats" "github.com/containers/buildah/pkg/parse" "github.com/containers/image/docker/reference" "github.com/containers/image/types" "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/libpodruntime" + "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/events" "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/pkg/rootless" @@ -351,9 +351,13 @@ func (r *LocalRuntime) Events(c *cliconfig.EventValues) error { fromStart bool eventsError error ) - tmpl, err := template.New("events").Parse(c.Format) - if err != nil { - return err + var tmpl *template.Template + if c.Format != formats.JSONString { + template, err := template.New("events").Parse(c.Format) + if err != nil { + return err + } + tmpl = template } if len(c.Since) > 0 || len(c.Until) > 0 { fromStart = true @@ -369,7 +373,15 @@ func (r *LocalRuntime) Events(c *cliconfig.EventValues) error { } w := bufio.NewWriter(os.Stdout) for event := range eventChannel { - if len(c.Format) > 0 { + if c.Format == formats.JSONString { + jsonStr, err := event.ToJSONString() + if err != nil { + return errors.Wrapf(err, "unable to format json") + } + if _, err := w.Write([]byte(jsonStr)); err != nil { + return err + } + } else if len(c.Format) > 0 { if err := tmpl.Execute(w, event); err != nil { return err } diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go index 9fae39df0..828838bde 100644 --- a/pkg/adapter/runtime_remote.go +++ b/pkg/adapter/runtime_remote.go @@ -14,9 +14,8 @@ import ( "text/template" "time" - v1 "k8s.io/api/core/v1" - "github.com/containers/buildah/imagebuildah" + "github.com/containers/buildah/pkg/formats" "github.com/containers/image/docker/reference" "github.com/containers/image/types" "github.com/containers/libpod/cmd/podman/cliconfig" @@ -32,6 +31,7 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/varlink/go/varlink" + v1 "k8s.io/api/core/v1" ) // ImageRuntime is wrapper for image runtime @@ -820,9 +820,13 @@ func (r *LocalRuntime) Events(c *cliconfig.EventValues) error { } w := bufio.NewWriter(os.Stdout) - tmpl, err := template.New("events").Parse(c.Format) - if err != nil { - return err + var tmpl *template.Template + if c.Format != formats.JSONString { + template, err := template.New("events").Parse(c.Format) + if err != nil { + return err + } + tmpl = template } for { @@ -856,7 +860,15 @@ func (r *LocalRuntime) Events(c *cliconfig.EventValues) error { Time: eTime, Type: eType, } - if len(c.Format) > 0 { + if c.Format == formats.JSONString { + jsonStr, err := event.ToJSONString() + if err != nil { + return errors.Wrapf(err, "unable to format json") + } + if _, err := w.Write([]byte(jsonStr)); err != nil { + return err + } + } else if len(c.Format) > 0 { if err := tmpl.Execute(w, event); err != nil { return err } diff --git a/pkg/netns/netns_linux.go b/pkg/netns/netns_linux.go index 1d6fb873c..e8388055a 100644 --- a/pkg/netns/netns_linux.go +++ b/pkg/netns/netns_linux.go @@ -23,23 +23,42 @@ import ( "fmt" "os" "path" + "path/filepath" "runtime" "strings" "sync" "github.com/containernetworking/plugins/pkg/ns" + "github.com/containers/libpod/pkg/rootless" + "github.com/containers/libpod/pkg/util" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) -const nsRunDir = "/var/run/netns" +// get NSRunDir returns the dir of where to create the netNS. When running +// rootless, it needs to be at a location writable by user. +func getNSRunDir() (string, error) { + if rootless.IsRootless() { + rootlessDir, err := util.GetRootlessRuntimeDir() + if err != nil { + return "", err + } + return filepath.Join(rootlessDir, "netns"), nil + } + return "/var/run/netns", nil +} // NewNS creates a new persistent (bind-mounted) network namespace and returns // an object representing that namespace, without switching to it. func NewNS() (ns.NetNS, error) { + nsRunDir, err := getNSRunDir() + if err != nil { + return nil, err + } + b := make([]byte, 16) - _, err := rand.Reader.Read(b) + _, err = rand.Reader.Read(b) if err != nil { return nil, fmt.Errorf("failed to generate random netns name: %v", err) } @@ -127,7 +146,7 @@ func NewNS() (ns.NetNS, error) { // Put this thread back to the orig ns, since it might get reused (pre go1.10) defer func() { if err := origNS.Set(); err != nil { - logrus.Errorf("unable to set namespace: %q", err) + logrus.Warnf("unable to set namespace: %q", err) } }() @@ -150,6 +169,11 @@ func NewNS() (ns.NetNS, error) { // UnmountNS unmounts the NS held by the netns object func UnmountNS(ns ns.NetNS) error { + nsRunDir, err := getNSRunDir() + if err != nil { + return err + } + nsPath := ns.Path() // Only unmount if it's been bind-mounted (don't touch namespaces in /proc...) if strings.HasPrefix(nsPath, nsRunDir) { diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 214a3c5ed..289634a0d 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -168,6 +168,9 @@ func (c *CreateConfig) createExitCommand(runtime *libpod.Runtime) ([]string, err for _, opt := range config.StorageConfig.GraphDriverOptions { command = append(command, []string{"--storage-opt", opt}...) } + if config.EventsLogger != "" { + command = append(command, []string{"--events-backend", config.EventsLogger}...) + } if c.Syslog { command = append(command, "--syslog", "true") @@ -267,7 +270,7 @@ func (c *CreateConfig) getContainerCreateOptions(runtime *libpod.Runtime, pod *l options = append(options, libpod.WithNetNSFrom(connectedCtr)) } else if !c.NetMode.IsHost() && !c.NetMode.IsNone() { hasUserns := c.UsernsMode.IsContainer() || c.UsernsMode.IsNS() || len(c.IDMappings.UIDMap) > 0 || len(c.IDMappings.GIDMap) > 0 - postConfigureNetNS := c.NetMode.IsSlirp4netns() || (hasUserns && !c.UsernsMode.IsHost()) + postConfigureNetNS := hasUserns && !c.UsernsMode.IsHost() options = append(options, libpod.WithNetNS(portBindings, postConfigureNetNS, string(c.NetMode), networks)) } diff --git a/pkg/spec/storage.go b/pkg/spec/storage.go index 88f1f6dc1..ac7a2c30f 100644 --- a/pkg/spec/storage.go +++ b/pkg/spec/storage.go @@ -7,6 +7,7 @@ import ( "path/filepath" "strings" + "github.com/containers/buildah/pkg/parse" "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/util" "github.com/containers/storage/pkg/stringid" @@ -248,8 +249,11 @@ func (config *CreateConfig) getVolumesFrom(runtime *libpod.Runtime) (map[string] finalNamedVolumes := make(map[string]*libpod.ContainerNamedVolume) for _, vol := range config.VolumesFrom { - options := []string{} - splitVol := strings.SplitN(vol, ":", 2) + var ( + options = []string{} + err error + splitVol = strings.SplitN(vol, ":", 2) + ) if len(splitVol) == 2 { if strings.Contains(splitVol[1], "Z") || strings.Contains(splitVol[1], "private") || @@ -257,12 +261,10 @@ func (config *CreateConfig) getVolumesFrom(runtime *libpod.Runtime) (map[string] strings.Contains(splitVol[1], "shared") { return nil, nil, errors.Errorf("invalid options %q, can only specify 'ro', 'rw', and 'z", splitVol[1]) } - options = strings.Split(splitVol[1], ",") - opts, err := ValidateVolumeOpts(options) - if err != nil { + + if options, err = parse.ValidateVolumeOpts(strings.Split(splitVol[1], ",")); err != nil { return nil, nil, err } - options = opts } ctr, err := runtime.LookupContainer(splitVol[0]) if err != nil { @@ -429,7 +431,7 @@ func getBindMount(args []string) (spec.Mount, error) { if len(kv) == 1 { return newMount, errors.Wrapf(optionArgError, kv[0]) } - if err := ValidateVolumeHostDir(kv[1]); err != nil { + if err := parse.ValidateVolumeHostDir(kv[1]); err != nil { return newMount, err } newMount.Source = kv[1] @@ -438,7 +440,7 @@ func getBindMount(args []string) (spec.Mount, error) { if len(kv) == 1 { return newMount, errors.Wrapf(optionArgError, kv[0]) } - if err := ValidateVolumeCtrDir(kv[1]); err != nil { + if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil { return newMount, err } newMount.Destination = kv[1] @@ -456,12 +458,11 @@ func getBindMount(args []string) (spec.Mount, error) { newMount.Source = newMount.Destination } - opts, err := ValidateVolumeOpts(newMount.Options) + options, err := parse.ValidateVolumeOpts(newMount.Options) if err != nil { return newMount, err } - newMount.Options = opts - + newMount.Options = options return newMount, nil } @@ -495,7 +496,7 @@ func getTmpfsMount(args []string) (spec.Mount, error) { if len(kv) == 1 { return newMount, errors.Wrapf(optionArgError, kv[0]) } - if err := ValidateVolumeCtrDir(kv[1]); err != nil { + if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil { return newMount, err } newMount.Destination = kv[1] @@ -539,7 +540,7 @@ func getNamedVolume(args []string) (*libpod.ContainerNamedVolume, error) { if len(kv) == 1 { return nil, errors.Wrapf(optionArgError, kv[0]) } - if err := ValidateVolumeCtrDir(kv[1]); err != nil { + if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil { return nil, err } newVolume.Dest = kv[1] @@ -559,75 +560,6 @@ func getNamedVolume(args []string) (*libpod.ContainerNamedVolume, error) { return newVolume, nil } -// ValidateVolumeHostDir validates a volume mount's source directory -func ValidateVolumeHostDir(hostDir string) error { - if len(hostDir) == 0 { - return errors.Errorf("host directory cannot be empty") - } - if filepath.IsAbs(hostDir) { - if _, err := os.Stat(hostDir); err != nil { - return errors.Wrapf(err, "error checking path %q", hostDir) - } - } - // If hostDir is not an absolute path, that means the user wants to create a - // named volume. This will be done later on in the code. - return nil -} - -// ValidateVolumeCtrDir validates a volume mount's destination directory. -func ValidateVolumeCtrDir(ctrDir string) error { - if len(ctrDir) == 0 { - return errors.Errorf("container directory cannot be empty") - } - if !filepath.IsAbs(ctrDir) { - return errors.Errorf("invalid container path %q, must be an absolute path", ctrDir) - } - return nil -} - -// ValidateVolumeOpts validates a volume's options -func ValidateVolumeOpts(options []string) ([]string, error) { - var foundRootPropagation, foundRWRO, foundLabelChange, bindType int - finalOpts := make([]string, 0, len(options)) - for _, opt := range options { - switch opt { - case "rw", "ro": - foundRWRO++ - if foundRWRO > 1 { - return nil, errors.Errorf("invalid options %q, can only specify 1 'rw' or 'ro' option", strings.Join(options, ", ")) - } - case "z", "Z": - foundLabelChange++ - if foundLabelChange > 1 { - return nil, errors.Errorf("invalid options %q, can only specify 1 'z' or 'Z' option", strings.Join(options, ", ")) - } - case "private", "rprivate", "shared", "rshared", "slave", "rslave": - foundRootPropagation++ - if foundRootPropagation > 1 { - return nil, errors.Errorf("invalid options %q, can only specify 1 '[r]shared', '[r]private' or '[r]slave' option", strings.Join(options, ", ")) - } - case "bind", "rbind": - bindType++ - if bindType > 1 { - return nil, errors.Errorf("invalid options %q, can only specify 1 '[r]bind' option", strings.Join(options, ", ")) - } - case "cached", "delegated": - // The discarded ops are OS X specific volume options - // introduced in a recent Docker version. - // They have no meaning on Linux, so here we silently - // drop them. This matches Docker's behavior (the options - // are intended to be always safe to use, even not on OS - // X). - continue - default: - return nil, errors.Errorf("invalid mount option %q", opt) - } - finalOpts = append(finalOpts, opt) - } - return finalOpts, nil -} - -// GetVolumeMounts takes user provided input for bind mounts and creates Mount structs func (config *CreateConfig) getVolumeMounts() (map[string]spec.Mount, map[string]*libpod.ContainerNamedVolume, error) { mounts := make(map[string]spec.Mount) volumes := make(map[string]*libpod.ContainerNamedVolume) @@ -639,6 +571,7 @@ func (config *CreateConfig) getVolumeMounts() (map[string]spec.Mount, map[string options []string src string dest string + err error ) splitVol := strings.Split(vol, ":") @@ -653,18 +586,15 @@ func (config *CreateConfig) getVolumeMounts() (map[string]spec.Mount, map[string dest = splitVol[1] } if len(splitVol) > 2 { - options = strings.Split(splitVol[2], ",") - opts, err := ValidateVolumeOpts(options) - if err != nil { + if options, err = parse.ValidateVolumeOpts(strings.Split(splitVol[2], ",")); err != nil { return nil, nil, err } - options = opts } - if err := ValidateVolumeHostDir(src); err != nil { + if err := parse.ValidateVolumeHostDir(src); err != nil { return nil, nil, err } - if err := ValidateVolumeCtrDir(dest); err != nil { + if err := parse.ValidateVolumeCtrDir(dest); err != nil { return nil, nil, err } diff --git a/pkg/util/utils_supported.go b/pkg/util/utils_supported.go index af55689a6..6449c6f85 100644 --- a/pkg/util/utils_supported.go +++ b/pkg/util/utils_supported.go @@ -26,7 +26,7 @@ func GetRootlessRuntimeDir() (string, error) { if runtimeDir == "" { tmpDir := filepath.Join("/run", "user", uid) if err := os.MkdirAll(tmpDir, 0700); err != nil { - logrus.Errorf("unable to make temp dir %s", tmpDir) + logrus.Debugf("unable to make temp dir %s", tmpDir) } st, err := os.Stat(tmpDir) if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 { @@ -36,7 +36,7 @@ func GetRootlessRuntimeDir() (string, error) { if runtimeDir == "" { tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("run-%s", uid)) if err := os.MkdirAll(tmpDir, 0700); err != nil { - logrus.Errorf("unable to make temp dir %s", tmpDir) + logrus.Debugf("unable to make temp dir %s", tmpDir) } st, err := os.Stat(tmpDir) if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 { diff --git a/pkg/varlinkapi/system.go b/pkg/varlinkapi/system.go index 9b5b3a5b1..2de785b79 100644 --- a/pkg/varlinkapi/system.go +++ b/pkg/varlinkapi/system.go @@ -61,6 +61,7 @@ func (i *LibpodAPI) GetInfo(call iopodman.VarlinkCall) error { Kernel: host["kernel"].(string), Os: host["os"].(string), Uptime: host["uptime"].(string), + Eventlogger: host["eventlogger"].(string), } podmanInfo.Host = infoHost store := info[1].Data |