summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container.go17
-rw-r--r--libpod/container_exec.go4
-rw-r--r--libpod/container_inspect.go8
-rw-r--r--libpod/container_internal.go6
-rw-r--r--libpod/container_internal_linux.go26
-rw-r--r--libpod/container_internal_unsupported.go4
-rw-r--r--libpod/container_validate.go19
-rw-r--r--libpod/define/config.go2
-rw-r--r--libpod/define/container_inspect.go2
-rw-r--r--libpod/events/journal_linux.go7
-rw-r--r--libpod/events/logfile.go8
-rw-r--r--libpod/healthcheck.go5
-rw-r--r--libpod/options.go43
-rw-r--r--libpod/runtime.go4
14 files changed, 138 insertions, 17 deletions
diff --git a/libpod/container.go b/libpod/container.go
index 1ca38ae7e..8a69df685 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -262,6 +262,8 @@ type ContainerConfig struct {
Mounts []string `json:"mounts,omitempty"`
// NamedVolumes lists the named volumes to mount into the container.
NamedVolumes []*ContainerNamedVolume `json:"namedVolumes,omitempty"`
+ // OverlayVolumes lists the overlay volumes to mount into the container.
+ OverlayVolumes []*ContainerOverlayVolume `json:"overlayVolumes,omitempty"`
// Security Config
@@ -435,6 +437,9 @@ type ContainerConfig struct {
// Timezone is the timezone inside the container.
// Local means it has the same timezone as the host machine
Timezone string `json:"timezone,omitempty"`
+
+ // Umask is the umask inside the container.
+ Umask string `json:"umask,omitempty"`
}
// ContainerNamedVolume is a named volume that will be mounted into the
@@ -449,6 +454,15 @@ type ContainerNamedVolume struct {
Options []string `json:"options,omitempty"`
}
+// ContainerOverlayVolume is a overlay volume that will be mounted into the
+// container. Each volume is a libpod Volume present in the state.
+type ContainerOverlayVolume struct {
+ // Destination is the absolute path where the mount will be placed in the container.
+ Dest string `json:"dest"`
+ // Source specifies the source path of the mount.
+ Source string `json:"source,omitempty"`
+}
+
// Config accessors
// Unlocked
@@ -1265,5 +1279,8 @@ func (c *Container) AutoRemove() bool {
func (c *Container) Timezone() string {
return c.config.Timezone
+}
+func (c *Container) Umask() string {
+ return c.config.Umask
}
diff --git a/libpod/container_exec.go b/libpod/container_exec.go
index bd04ee9b9..a16aea06d 100644
--- a/libpod/container_exec.go
+++ b/libpod/container_exec.go
@@ -729,10 +729,6 @@ func (c *Container) Exec(config *ExecConfig, streams *define.AttachStreams, resi
return -1, err
}
- if exitCode != 0 {
- return exitCode, errors.Wrapf(define.ErrOCIRuntime, "exec session exited with non-zero exit code %d", exitCode)
- }
-
return exitCode, nil
}
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index 680776dba..a0d223c8c 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -325,6 +325,14 @@ func (c *Container) generateInspectContainerConfig(spec *spec.Spec) *define.Insp
ctrConfig.Timezone = c.config.Timezone
+ // Pad Umask to 4 characters
+ if len(c.config.Umask) < 4 {
+ pad := strings.Repeat("0", 4-len(c.config.Umask))
+ ctrConfig.Umask = pad + c.config.Umask
+ } else {
+ ctrConfig.Umask = c.config.Umask
+ }
+
return ctrConfig
}
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index a79b9e5a8..b2e23b3a8 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -1588,6 +1588,12 @@ func (c *Container) cleanupStorage() error {
}
}
+ if err := c.cleanupOverlayMounts(); err != nil {
+ // If the container can't remove content report the error
+ logrus.Errorf("Failed to cleanup overlay mounts for %s: %v", c.ID(), err)
+ cleanupErr = err
+ }
+
if c.config.Rootfs != "" {
return cleanupErr
}
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 255505416..edea62a0d 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -20,6 +20,7 @@ import (
cnitypes "github.com/containernetworking/cni/pkg/types/current"
"github.com/containernetworking/plugins/pkg/ns"
+ "github.com/containers/buildah/pkg/overlay"
"github.com/containers/buildah/pkg/secrets"
"github.com/containers/common/pkg/apparmor"
"github.com/containers/common/pkg/config"
@@ -319,6 +320,19 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
}
}
+ // Add overlay volumes
+ for _, overlayVol := range c.config.OverlayVolumes {
+ contentDir, err := overlay.TempDir(c.config.StaticDir, c.RootUID(), c.RootGID())
+ if err != nil {
+ return nil, errors.Wrapf(err, "failed to create TempDir in the %s directory", c.config.StaticDir)
+ }
+ overlayMount, err := overlay.Mount(contentDir, overlayVol.Source, overlayVol.Dest, c.RootUID(), c.RootGID(), c.runtime.store.GraphOptions())
+ if err != nil {
+ return nil, errors.Wrapf(err, "creating overlay failed %q", overlayVol.Source)
+ }
+ g.AddMount(overlayMount)
+ }
+
hasHomeSet := false
for _, s := range c.config.Spec.Process.Env {
if strings.HasPrefix(s, "HOME=") {
@@ -341,6 +355,14 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
g.SetProcessGID(uint32(execUser.Gid))
}
+ if c.config.Umask != "" {
+ decVal, err := strconv.ParseUint(c.config.Umask, 8, 32)
+ if err != nil {
+ return nil, errors.Wrapf(err, "Invalid Umask Value")
+ }
+ g.SetProcessUmask(uint32(decVal))
+ }
+
// Add addition groups if c.config.GroupAdd is not empty
if len(c.config.Groups) > 0 {
gids, err := lookup.GetContainerGroups(c.config.Groups, c.state.Mountpoint, overrides)
@@ -1642,3 +1664,7 @@ func (c *Container) copyTimezoneFile(zonePath string) (string, error) {
}
return localtimeCopy, err
}
+
+func (c *Container) cleanupOverlayMounts() error {
+ return overlay.CleanupContent(c.config.StaticDir)
+}
diff --git a/libpod/container_internal_unsupported.go b/libpod/container_internal_unsupported.go
index e6d94104c..b58a5116b 100644
--- a/libpod/container_internal_unsupported.go
+++ b/libpod/container_internal_unsupported.go
@@ -46,6 +46,10 @@ func (c *Container) getOCICgroupPath() (string, error) {
return "", define.ErrNotImplemented
}
+func (c *Container) cleanupOverlayMounts() error {
+ return nil
+}
+
func (c *Container) getUserOverrides() *lookup.Overrides {
return nil
}
diff --git a/libpod/container_validate.go b/libpod/container_validate.go
index c02833359..666ad0aca 100644
--- a/libpod/container_validate.go
+++ b/libpod/container_validate.go
@@ -99,5 +99,24 @@ func (c *Container) validate() error {
return errors.Wrapf(define.ErrInvalidArg, "cannot add to /etc/hosts if using image's /etc/hosts")
}
+ // Check named volume and overlay volumes destination conflits
+ destinations := make(map[string]bool)
+ for _, vol := range c.config.NamedVolumes {
+ // Don't check if they already exist.
+ // If they don't we will automatically create them.
+ if _, ok := destinations[vol.Dest]; ok {
+ return errors.Wrapf(define.ErrInvalidArg, "two volumes found with destination %s", vol.Dest)
+ }
+ destinations[vol.Dest] = true
+ }
+ for _, vol := range c.config.OverlayVolumes {
+ // Don't check if they already exist.
+ // If they don't we will automatically create them.
+ if _, ok := destinations[vol.Dest]; ok {
+ return errors.Wrapf(define.ErrInvalidArg, "two volumes found with destination %s", vol.Dest)
+ }
+ destinations[vol.Dest] = true
+ }
+
return nil
}
diff --git a/libpod/define/config.go b/libpod/define/config.go
index 64b24d9e2..6c426f2ec 100644
--- a/libpod/define/config.go
+++ b/libpod/define/config.go
@@ -20,6 +20,8 @@ var (
NameRegex = regexp.MustCompile("^[a-zA-Z0-9][a-zA-Z0-9_.-]*$")
// RegexError is thrown in presence of an invalid container/pod name.
RegexError = errors.Wrapf(ErrInvalidArg, "names must match [a-zA-Z0-9][a-zA-Z0-9_.-]*")
+ // UmaskRegex is a regular expression to validate Umask.
+ UmaskRegex = regexp.MustCompile(`^[0-7]{1,4}$`)
)
const (
diff --git a/libpod/define/container_inspect.go b/libpod/define/container_inspect.go
index fbd9da3e7..a08cb3de6 100644
--- a/libpod/define/container_inspect.go
+++ b/libpod/define/container_inspect.go
@@ -61,6 +61,8 @@ type InspectContainerConfig struct {
// systemd mode, the container configuration is customized to optimize
// running systemd in the container.
SystemdMode bool `json:"SystemdMode,omitempty"`
+ // Umask is the umask inside the container.
+ Umask string `json:"Umask,omitempty"`
}
// InspectRestartPolicy holds information about the container's restart policy.
diff --git a/libpod/events/journal_linux.go b/libpod/events/journal_linux.go
index d341ca7b5..7c2a3e0f2 100644
--- a/libpod/events/journal_linux.go
+++ b/libpod/events/journal_linux.go
@@ -90,6 +90,13 @@ func (e EventJournalD) Read(ctx context.Context, options ReadOptions) error {
return err
}
for {
+ select {
+ case <-ctx.Done():
+ // the consumer has cancelled
+ return nil
+ default:
+ // fallthrough
+ }
if _, err := j.Next(); err != nil {
return err
}
diff --git a/libpod/events/logfile.go b/libpod/events/logfile.go
index 28d0dc07e..b70102450 100644
--- a/libpod/events/logfile.go
+++ b/libpod/events/logfile.go
@@ -63,6 +63,14 @@ func (e EventLogFile) Read(ctx context.Context, options ReadOptions) error {
}
}()
for line := range t.Lines {
+ select {
+ case <-ctx.Done():
+ // the consumer has cancelled
+ return nil
+ default:
+ // fallthrough
+ }
+
event, err := newEventFromJSONString(line.Text)
if err != nil {
return err
diff --git a/libpod/healthcheck.go b/libpod/healthcheck.go
index b04742974..4818f8dc4 100644
--- a/libpod/healthcheck.go
+++ b/libpod/healthcheck.go
@@ -92,7 +92,7 @@ func (c *Container) runHealthCheck() (define.HealthCheckStatus, error) {
hcResult := define.HealthCheckSuccess
config := new(ExecConfig)
config.Command = newCommand
- _, hcErr := c.Exec(config, streams, nil)
+ exitCode, hcErr := c.Exec(config, streams, nil)
if hcErr != nil {
errCause := errors.Cause(hcErr)
hcResult = define.HealthCheckFailure
@@ -104,6 +104,9 @@ func (c *Container) runHealthCheck() (define.HealthCheckStatus, error) {
} else {
returnCode = 125
}
+ } else if exitCode != 0 {
+ hcResult = define.HealthCheckFailure
+ returnCode = 1
}
timeEnd := time.Now()
if c.HealthCheckConfig().StartPeriod > 0 {
diff --git a/libpod/options.go b/libpod/options.go
index 32748a3c1..41b0d7212 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -1380,17 +1380,7 @@ func WithNamedVolumes(volumes []*ContainerNamedVolume) CtrCreateOption {
return define.ErrCtrFinalized
}
- destinations := make(map[string]bool)
-
for _, vol := range volumes {
- // Don't check if they already exist.
- // If they don't we will automatically create them.
-
- if _, ok := destinations[vol.Dest]; ok {
- return errors.Wrapf(define.ErrInvalidArg, "two volumes found with destination %s", vol.Dest)
- }
- destinations[vol.Dest] = true
-
mountOpts, err := util.ProcessOptions(vol.Options, false, "")
if err != nil {
return errors.Wrapf(err, "error processing options for named volume %q mounted at %q", vol.Name, vol.Dest)
@@ -1407,6 +1397,25 @@ func WithNamedVolumes(volumes []*ContainerNamedVolume) CtrCreateOption {
}
}
+// WithOverlayVolumes adds the given overlay volumes to the container.
+func WithOverlayVolumes(volumes []*ContainerOverlayVolume) CtrCreateOption {
+ return func(ctr *Container) error {
+ if ctr.valid {
+ return define.ErrCtrFinalized
+ }
+
+ for _, vol := range volumes {
+
+ ctr.config.OverlayVolumes = append(ctr.config.OverlayVolumes, &ContainerOverlayVolume{
+ Dest: vol.Dest,
+ Source: vol.Source,
+ })
+ }
+
+ return nil
+ }
+}
+
// WithHealthCheck adds the healthcheck to the container config
func WithHealthCheck(healthCheck *manifest.Schema2HealthConfig) CtrCreateOption {
return func(ctr *Container) error {
@@ -1598,6 +1607,20 @@ func WithTimezone(path string) CtrCreateOption {
}
}
+// WithUmask sets the umask in the container
+func WithUmask(umask string) CtrCreateOption {
+ return func(ctr *Container) error {
+ if ctr.valid {
+ return define.ErrCtrFinalized
+ }
+ if !define.UmaskRegex.MatchString(umask) {
+ return errors.Wrapf(define.ErrInvalidArg, "Invalid umask string %s", umask)
+ }
+ ctr.config.Umask = umask
+ return nil
+ }
+}
+
// Pod Creation Options
// WithPodName sets the name of the pod.
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 0075c0e13..96243c808 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -84,7 +84,7 @@ type Runtime struct {
// SetXdgDirs ensures the XDG_RUNTIME_DIR env and XDG_CONFIG_HOME variables are set.
// containers/image uses XDG_RUNTIME_DIR to locate the auth file, XDG_CONFIG_HOME is
-// use for the libpod.conf configuration file.
+// use for the containers.conf configuration file.
func SetXdgDirs() error {
if !rootless.IsRootless() {
return nil
@@ -577,7 +577,7 @@ func (r *Runtime) Shutdown(force bool) error {
}
var lastError error
- // If no store was requested, it can bew nil and there is no need to
+ // If no store was requested, it can be nil and there is no need to
// attempt to shut it down
if r.store != nil {
if _, err := r.store.Shutdown(force); err != nil {