summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container_internal_linux.go14
-rw-r--r--libpod/image/filters.go14
-rw-r--r--libpod/image/prune.go24
-rw-r--r--libpod/kube.go32
-rw-r--r--libpod/network/netconflist.go29
-rw-r--r--libpod/oci_conmon_linux.go5
-rw-r--r--libpod/options.go9
-rw-r--r--libpod/runtime_img.go18
-rw-r--r--libpod/volume_internal_linux.go10
9 files changed, 71 insertions, 84 deletions
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 24319f4b5..94c6c3840 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -1503,16 +1503,24 @@ func (c *Container) makeBindMounts() error {
}
// Make /etc/localtime
- if c.Timezone() != "" {
+ ctrTimezone := c.Timezone()
+ if ctrTimezone != "" {
+ // validate the format of the timezone specified if it's not "local"
+ if ctrTimezone != "local" {
+ _, err = time.LoadLocation(ctrTimezone)
+ if err != nil {
+ return errors.Wrapf(err, "error finding timezone for container %s", c.ID())
+ }
+ }
if _, ok := c.state.BindMounts["/etc/localtime"]; !ok {
var zonePath string
- if c.Timezone() == "local" {
+ if ctrTimezone == "local" {
zonePath, err = filepath.EvalSymlinks("/etc/localtime")
if err != nil {
return errors.Wrapf(err, "error finding local timezone for container %s", c.ID())
}
} else {
- zone := filepath.Join("/usr/share/zoneinfo", c.Timezone())
+ zone := filepath.Join("/usr/share/zoneinfo", ctrTimezone)
zonePath, err = filepath.EvalSymlinks(zone)
if err != nil {
return errors.Wrapf(err, "error setting timezone for container %s", c.ID())
diff --git a/libpod/image/filters.go b/libpod/image/filters.go
index 37d3cb6a5..d316c6956 100644
--- a/libpod/image/filters.go
+++ b/libpod/image/filters.go
@@ -9,6 +9,7 @@ import (
"time"
"github.com/containers/podman/v3/pkg/inspect"
+ "github.com/containers/podman/v3/pkg/util"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -78,23 +79,14 @@ func ReadOnlyFilter(readOnly bool) ResultFilter {
}
// LabelFilter allows you to filter by images labels key and/or value
-func LabelFilter(ctx context.Context, labelfilter string) ResultFilter {
+func LabelFilter(ctx context.Context, filter string) ResultFilter {
// We need to handle both label=key and label=key=value
return func(i *Image) bool {
- var value string
- splitFilter := strings.SplitN(labelfilter, "=", 2)
- key := splitFilter[0]
- if len(splitFilter) > 1 {
- value = splitFilter[1]
- }
labels, err := i.Labels(ctx)
if err != nil {
return false
}
- if len(strings.TrimSpace(labels[key])) > 0 && len(strings.TrimSpace(value)) == 0 {
- return true
- }
- return labels[key] == value
+ return util.MatchLabelFilters([]string{filter}, labels)
}
}
diff --git a/libpod/image/prune.go b/libpod/image/prune.go
index d6ae5feaf..7ee3e077e 100644
--- a/libpod/image/prune.go
+++ b/libpod/image/prune.go
@@ -3,11 +3,10 @@ package image
import (
"context"
"strings"
- "time"
"github.com/containers/podman/v3/libpod/events"
"github.com/containers/podman/v3/pkg/domain/entities/reports"
- "github.com/containers/podman/v3/pkg/timetype"
+ "github.com/containers/podman/v3/pkg/util"
"github.com/containers/storage"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -16,36 +15,19 @@ import (
func generatePruneFilterFuncs(filter, filterValue string) (ImageFilter, error) {
switch filter {
case "label":
- var filterArray = strings.SplitN(filterValue, "=", 2)
- var filterKey = filterArray[0]
- if len(filterArray) > 1 {
- filterValue = filterArray[1]
- } else {
- filterValue = ""
- }
return func(i *Image) bool {
labels, err := i.Labels(context.Background())
if err != nil {
return false
}
- for labelKey, labelValue := range labels {
- if labelKey == filterKey && (filterValue == "" || labelValue == filterValue) {
- return true
- }
- }
- return false
+ return util.MatchLabelFilters([]string{filterValue}, labels)
}, nil
case "until":
- ts, err := timetype.GetTimestamp(filterValue, time.Now())
- if err != nil {
- return nil, err
- }
- seconds, nanoseconds, err := timetype.ParseTimestamps(ts, 0)
+ until, err := util.ComputeUntilTimestamp([]string{filterValue})
if err != nil {
return nil, err
}
- until := time.Unix(seconds, nanoseconds)
return func(i *Image) bool {
if !until.IsZero() && i.Created().After((until)) {
return true
diff --git a/libpod/kube.go b/libpod/kube.go
index 407c4ae00..b4dd4f10a 100644
--- a/libpod/kube.go
+++ b/libpod/kube.go
@@ -330,8 +330,6 @@ func containerToV1Container(c *Container) (v1.Container, []v1.Volume, *v1.PodDNS
}
if len(c.config.UserVolumes) > 0 {
- // TODO When we until we can resolve what the volume name should be, this is disabled
- // Volume names need to be coordinated "globally" in the kube files.
volumeMounts, volumes, err := libpodMountsToKubeVolumeMounts(c)
if err != nil {
return kubeContainer, kubeVolumes, nil, err
@@ -493,8 +491,7 @@ func libpodEnvVarsToKubeEnvVars(envs []string) ([]v1.EnvVar, error) {
// libpodMountsToKubeVolumeMounts converts the containers mounts to a struct kube understands
func libpodMountsToKubeVolumeMounts(c *Container) ([]v1.VolumeMount, []v1.Volume, error) {
- // TODO when named volumes are supported in play kube, also parse named volumes here
- _, mounts := c.sortUserVolumes(c.config.Spec)
+ namedVolumes, mounts := c.sortUserVolumes(c.config.Spec)
vms := make([]v1.VolumeMount, 0, len(mounts))
vos := make([]v1.Volume, 0, len(mounts))
for _, m := range mounts {
@@ -505,9 +502,34 @@ func libpodMountsToKubeVolumeMounts(c *Container) ([]v1.VolumeMount, []v1.Volume
vms = append(vms, vm)
vos = append(vos, vo)
}
+ for _, v := range namedVolumes {
+ vm, vo := generateKubePersistentVolumeClaim(v)
+ vms = append(vms, vm)
+ vos = append(vos, vo)
+ }
return vms, vos, nil
}
+// generateKubePersistentVolumeClaim converts a ContainerNamedVolume to a Kubernetes PersistentVolumeClaim
+func generateKubePersistentVolumeClaim(v *ContainerNamedVolume) (v1.VolumeMount, v1.Volume) {
+ ro := util.StringInSlice("ro", v.Options)
+
+ // To avoid naming conflicts with any host path mounts, add a unique suffix to the volume's name.
+ name := v.Name + "-pvc"
+
+ vm := v1.VolumeMount{}
+ vm.Name = name
+ vm.MountPath = v.Dest
+ vm.ReadOnly = ro
+
+ pvc := v1.PersistentVolumeClaimVolumeSource{ClaimName: v.Name, ReadOnly: ro}
+ vs := v1.VolumeSource{}
+ vs.PersistentVolumeClaim = &pvc
+ vo := v1.Volume{Name: name, VolumeSource: vs}
+
+ return vm, vo
+}
+
// generateKubeVolumeMount takes a user specified mount and returns
// a kubernetes VolumeMount (to be added to the container) and a kubernetes Volume
// (to be added to the pod)
@@ -519,6 +541,8 @@ func generateKubeVolumeMount(m specs.Mount) (v1.VolumeMount, v1.Volume, error) {
if err != nil {
return vm, vo, err
}
+ // To avoid naming conflicts with any persistent volume mounts, add a unique suffix to the volume's name.
+ name += "-host"
vm.Name = name
vm.MountPath = m.Destination
if util.StringInSlice("ro", m.Options) {
diff --git a/libpod/network/netconflist.go b/libpod/network/netconflist.go
index b358bc530..08816f2bd 100644
--- a/libpod/network/netconflist.go
+++ b/libpod/network/netconflist.go
@@ -225,7 +225,7 @@ func IfPassesFilter(netconf *libcni.NetworkConfigList, filters map[string][]stri
case "label":
// matches all labels
- result = matchPruneLabelFilters(netconf, filterValues)
+ result = util.MatchLabelFilters(filterValues, GetNetworkLabels(netconf))
case "driver":
// matches only for the DefaultNetworkDriver
@@ -260,9 +260,9 @@ func IfPassesPruneFilter(config *config.Config, netconf *libcni.NetworkConfigLis
for key, filterValues := range f {
switch strings.ToLower(key) {
case "label":
- return matchPruneLabelFilters(netconf, filterValues), nil
+ return util.MatchLabelFilters(filterValues, GetNetworkLabels(netconf)), nil
case "until":
- until, err := util.ComputeUntilTimestamp(key, filterValues)
+ until, err := util.ComputeUntilTimestamp(filterValues)
if err != nil {
return false, err
}
@@ -280,29 +280,6 @@ func IfPassesPruneFilter(config *config.Config, netconf *libcni.NetworkConfigLis
return false, nil
}
-func matchPruneLabelFilters(netconf *libcni.NetworkConfigList, filterValues []string) bool {
- labels := GetNetworkLabels(netconf)
- result := true
-outer:
- for _, filterValue := range filterValues {
- filterArray := strings.SplitN(filterValue, "=", 2)
- filterKey := filterArray[0]
- if len(filterArray) > 1 {
- filterValue = filterArray[1]
- } else {
- filterValue = ""
- }
- for labelKey, labelValue := range labels {
- if labelKey == filterKey && (filterValue == "" || labelValue == filterValue) {
- result = true
- continue outer
- }
- }
- result = false
- }
- return result
-}
-
func getCreatedTimestamp(config *config.Config, netconf *libcni.NetworkConfigList) (*time.Time, error) {
networkConfigPath, err := GetCNIConfigPathByNameOrID(config, netconf.Name)
if err != nil {
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index ef5f6fb0c..1c7089e5d 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -1268,7 +1268,10 @@ func prepareProcessExec(c *Container, options *ExecOptions, env []string, sessio
return nil, err
}
- allCaps := capabilities.AllCapabilities()
+ allCaps, err := capabilities.BoundingSet()
+ if err != nil {
+ return nil, err
+ }
if options.Privileged {
pspec.Capabilities.Bounding = allCaps
} else {
diff --git a/libpod/options.go b/libpod/options.go
index ffdb5abbf..24e9d74f4 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -1577,8 +1577,6 @@ func WithVolumeLabels(labels map[string]string) VolumeCreateOption {
}
// WithVolumeOptions sets the options of the volume.
-// If the "local" driver has been selected, options will be validated. There are
-// currently 3 valid options for the "local" driver - o, type, and device.
func WithVolumeOptions(options map[string]string) VolumeCreateOption {
return func(volume *Volume) error {
if volume.valid {
@@ -1587,13 +1585,6 @@ func WithVolumeOptions(options map[string]string) VolumeCreateOption {
volume.config.Options = make(map[string]string)
for key, value := range options {
- switch key {
- case "type", "device", "o", "UID", "GID":
- volume.config.Options[key] = value
- default:
- return errors.Wrapf(define.ErrInvalidArg, "unrecognized volume option %q is not supported with local driver", key)
- }
-
volume.config.Options[key] = value
}
diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go
index 90b11f8ca..13ac42e7d 100644
--- a/libpod/runtime_img.go
+++ b/libpod/runtime_img.go
@@ -313,15 +313,23 @@ func (r *Runtime) LoadImageFromSingleImageArchive(ctx context.Context, writer io
func() (types.ImageReference, error) {
return layout.NewReference(inputFile, "")
},
+ func() (types.ImageReference, error) {
+ // This item needs to be last to break out of loop and report meaningful error message
+ return nil,
+ errors.New("payload does not match any of the supported image formats (oci-archive, oci-dir, docker-archive, docker-dir)")
+ },
} {
src, err := referenceFn()
- if err == nil && src != nil {
- newImages, err := r.ImageRuntime().LoadFromArchiveReference(ctx, src, signaturePolicy, writer)
- if err == nil {
- return getImageNames(newImages), nil
- }
+ if err != nil {
saveErr = err
+ continue
+ }
+
+ newImages, err := r.ImageRuntime().LoadFromArchiveReference(ctx, src, signaturePolicy, writer)
+ if err == nil {
+ return getImageNames(newImages), nil
}
+ saveErr = err
}
return "", errors.Wrapf(saveErr, "error pulling image")
}
diff --git a/libpod/volume_internal_linux.go b/libpod/volume_internal_linux.go
index 67ac41874..92391de1d 100644
--- a/libpod/volume_internal_linux.go
+++ b/libpod/volume_internal_linux.go
@@ -32,8 +32,10 @@ func (v *Volume) mount() error {
return nil
}
- // We cannot mount volumes as rootless.
- if rootless.IsRootless() {
+ // We cannot mount 'local' volumes as rootless.
+ if !v.UsesVolumeDriver() && rootless.IsRootless() {
+ // This check should only be applied to 'local' driver
+ // so Volume Drivers must be excluded
return errors.Wrapf(define.ErrRootless, "cannot mount volumes without root privileges")
}
@@ -137,8 +139,8 @@ func (v *Volume) unmount(force bool) error {
return nil
}
- // We cannot unmount volumes as rootless.
- if rootless.IsRootless() {
+ // We cannot unmount 'local' volumes as rootless.
+ if !v.UsesVolumeDriver() && rootless.IsRootless() {
// If force is set, just clear the counter and bail without
// error, so we can remove volumes from the state if they are in
// an awkward configuration.