summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/api/handlers/libpod/images.go6
-rw-r--r--pkg/api/handlers/libpod/images_pull.go3
-rw-r--r--pkg/domain/entities/container_ps.go5
-rw-r--r--pkg/domain/infra/abi/play.go67
-rw-r--r--pkg/domain/infra/tunnel/containers.go2
-rw-r--r--pkg/domain/infra/tunnel/images.go4
-rw-r--r--pkg/ps/ps.go6
-rw-r--r--pkg/specgen/generate/container.go14
-rw-r--r--pkg/specgen/generate/kube/kube.go40
-rw-r--r--pkg/specgen/generate/kube/volume.go124
-rw-r--r--pkg/specgen/namespaces.go22
-rw-r--r--pkg/specgen/volumes.go1
12 files changed, 197 insertions, 97 deletions
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index 55264b3b6..be5a394de 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -422,8 +422,7 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
source := strings.TrimSuffix(utils.GetName(r), "/push") // GetName returns the entire path
if _, err := utils.ParseStorageReference(source); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- errors.Wrapf(err, "image source %q is not a containers-storage-transport reference", source))
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
return
}
@@ -433,8 +432,7 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
}
if _, err := utils.ParseDockerReference(destination); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- errors.Wrapf(err, "image destination %q is not a docker-transport reference", destination))
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
return
}
diff --git a/pkg/api/handlers/libpod/images_pull.go b/pkg/api/handlers/libpod/images_pull.go
index 05e4b8258..5e2727e95 100644
--- a/pkg/api/handlers/libpod/images_pull.go
+++ b/pkg/api/handlers/libpod/images_pull.go
@@ -53,8 +53,7 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
imageRef, err := utils.ParseDockerReference(query.Reference)
if err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- errors.Wrapf(err, "image destination %q is not a docker-transport reference", query.Reference))
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
return
}
diff --git a/pkg/domain/entities/container_ps.go b/pkg/domain/entities/container_ps.go
index ed40a37ab..b4e8446cb 100644
--- a/pkg/domain/entities/container_ps.go
+++ b/pkg/domain/entities/container_ps.go
@@ -3,6 +3,7 @@ package entities
import (
"sort"
"strings"
+ "time"
"github.com/containers/podman/v2/pkg/ps/define"
"github.com/cri-o/ocicni/pkg/ocicni"
@@ -14,7 +15,7 @@ type ListContainer struct {
// Container command
Command []string
// Container creation time
- Created int64
+ Created time.Time
// Human readable container creation time.
CreatedAt string
// If container has exited/stopped
@@ -137,7 +138,7 @@ func (a psSortedSize) Less(i, j int) bool {
type PsSortedCreateTime struct{ SortListContainers }
func (a PsSortedCreateTime) Less(i, j int) bool {
- return a.SortListContainers[i].Created < a.SortListContainers[j].Created
+ return a.SortListContainers[i].Created.Before(a.SortListContainers[j].Created)
}
func SortPsOutput(sortBy string, psOutput SortListContainers) (SortListContainers, error) {
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index 4bcc6469c..3aeb6a2ee 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -8,7 +8,6 @@ import (
"os"
"strings"
- "github.com/containers/buildah/pkg/parse"
"github.com/containers/image/v5/types"
"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/libpod/image"
@@ -24,13 +23,6 @@ import (
v1 "k8s.io/api/core/v1"
)
-const (
- // https://kubernetes.io/docs/concepts/storage/volumes/#hostpath
- kubeDirectoryPermission = 0755
- // https://kubernetes.io/docs/concepts/storage/volumes/#hostpath
- kubeFilePermission = 0644
-)
-
func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
var (
kubeObject v1.ObjectReference
@@ -168,62 +160,9 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
DockerInsecureSkipTLSVerify: options.SkipTLSVerify,
}
- // map from name to mount point
- volumes := make(map[string]string)
- for _, volume := range podYAML.Spec.Volumes {
- hostPath := volume.VolumeSource.HostPath
- if hostPath == nil {
- return nil, errors.Errorf("HostPath is currently the only supported VolumeSource")
- }
- if hostPath.Type != nil {
- switch *hostPath.Type {
- case v1.HostPathDirectoryOrCreate:
- if _, err := os.Stat(hostPath.Path); os.IsNotExist(err) {
- if err := os.Mkdir(hostPath.Path, kubeDirectoryPermission); err != nil {
- return nil, err
- }
- }
- // Label a newly created volume
- if err := libpod.LabelVolumePath(hostPath.Path); err != nil {
- return nil, errors.Wrapf(err, "error giving %s a label", hostPath.Path)
- }
- case v1.HostPathFileOrCreate:
- if _, err := os.Stat(hostPath.Path); os.IsNotExist(err) {
- f, err := os.OpenFile(hostPath.Path, os.O_RDONLY|os.O_CREATE, kubeFilePermission)
- if err != nil {
- return nil, errors.Wrap(err, "error creating HostPath")
- }
- if err := f.Close(); err != nil {
- logrus.Warnf("Error in closing newly created HostPath file: %v", err)
- }
- }
- // unconditionally label a newly created volume
- if err := libpod.LabelVolumePath(hostPath.Path); err != nil {
- return nil, errors.Wrapf(err, "error giving %s a label", hostPath.Path)
- }
- case v1.HostPathSocket:
- st, err := os.Stat(hostPath.Path)
- if err != nil {
- return nil, errors.Wrap(err, "error checking HostPathSocket")
- }
- if st.Mode()&os.ModeSocket != os.ModeSocket {
- return nil, errors.Errorf("error checking HostPathSocket: path %s is not a socket", hostPath.Path)
- }
-
- case v1.HostPathDirectory:
- case v1.HostPathFile:
- case v1.HostPathUnset:
- // do nothing here because we will verify the path exists in validateVolumeHostDir
- break
- default:
- return nil, errors.Errorf("Invalid HostPath type %v", hostPath.Type)
- }
- }
-
- if err := parse.ValidateVolumeHostDir(hostPath.Path); err != nil {
- return nil, errors.Wrapf(err, "error in parsing HostPath in YAML")
- }
- volumes[volume.Name] = hostPath.Path
+ volumes, err := kube.InitializeVolumes(podYAML.Spec.Volumes)
+ if err != nil {
+ return nil, err
}
seccompPaths, err := kube.InitializeSeccompPaths(podYAML.ObjectMeta.Annotations, options.SeccompProfileRoot)
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 1aa5afbe7..63677719b 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -235,7 +235,7 @@ func (ic *ContainerEngine) ContainerCommit(ctx context.Context, nameOrID string,
if len(options.ImageName) > 0 {
ref, err := reference.Parse(options.ImageName)
if err != nil {
- return nil, err
+ return nil, errors.Wrapf(err, "error parsing reference %q", options.ImageName)
}
if t, ok := ref.(reference.Tagged); ok {
tag = t.Tag()
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index 61ac2141c..09931de12 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -119,7 +119,7 @@ func (ir *ImageEngine) Tag(ctx context.Context, nameOrID string, tags []string,
)
ref, err := reference.Parse(newTag)
if err != nil {
- return err
+ return errors.Wrapf(err, "error parsing reference %q", newTag)
}
if t, ok := ref.(reference.Tagged); ok {
tag = t.Tag()
@@ -148,7 +148,7 @@ func (ir *ImageEngine) Untag(ctx context.Context, nameOrID string, tags []string
)
ref, err := reference.Parse(newTag)
if err != nil {
- return err
+ return errors.Wrapf(err, "error parsing reference %q", newTag)
}
if t, ok := ref.(reference.Tagged); ok {
tag = t.Tag()
diff --git a/pkg/ps/ps.go b/pkg/ps/ps.go
index 3dd7eb0c6..cfdf3ee49 100644
--- a/pkg/ps/ps.go
+++ b/pkg/ps/ps.go
@@ -180,7 +180,7 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities
ps := entities.ListContainer{
Command: conConfig.Command,
- Created: conConfig.CreatedTime.Unix(),
+ Created: conConfig.CreatedTime,
Exited: exited,
ExitCode: exitCode,
ExitedAt: exitedTime.Unix(),
@@ -231,7 +231,7 @@ func ListStorageContainer(rt *libpod.Runtime, ctr storage.Container, opts entiti
ps := entities.ListContainer{
ID: ctr.ID,
- Created: ctr.Created.Unix(),
+ Created: ctr.Created,
ImageID: ctr.ImageID,
State: "storage",
Names: []string{name},
@@ -301,5 +301,5 @@ func (a SortPSContainers) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
type SortPSCreateTime struct{ SortPSContainers }
func (a SortPSCreateTime) Less(i, j int) bool {
- return a.SortPSContainers[i].Created > a.SortPSContainers[j].Created
+ return a.SortPSContainers[i].Created.Before(a.SortPSContainers[j].Created)
}
diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go
index 2ee8f2441..c7e62d185 100644
--- a/pkg/specgen/generate/container.go
+++ b/pkg/specgen/generate/container.go
@@ -257,7 +257,19 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
}
}
- return verifyContainerResources(s)
+ warnings, err := verifyContainerResources(s)
+ if err != nil {
+ return warnings, err
+ }
+
+ // Warn on net=host/container/pod/none and port mappings.
+ if (s.NetNS.NSMode == specgen.Host || s.NetNS.NSMode == specgen.FromContainer ||
+ s.NetNS.NSMode == specgen.FromPod || s.NetNS.NSMode == specgen.NoNetwork) &&
+ len(s.PortMappings) > 0 {
+ warnings = append(warnings, "Port mappings have been discarded as one of the Host, Container, Pod, and None network modes are in use")
+ }
+
+ return warnings, nil
}
// finishThrottleDevices takes the temporary representation of the throttle
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go
index e1202956c..5f72d28bb 100644
--- a/pkg/specgen/generate/kube/kube.go
+++ b/pkg/specgen/generate/kube/kube.go
@@ -47,7 +47,7 @@ func ToPodGen(ctx context.Context, podName string, podYAML *v1.PodTemplateSpec)
return p, nil
}
-func ToSpecGen(ctx context.Context, containerYAML v1.Container, iid string, newImage *image.Image, volumes map[string]string, podID, podName, infraID string, configMaps []v1.ConfigMap, seccompPaths *KubeSeccompPaths, restartPolicy string) (*specgen.SpecGenerator, error) {
+func ToSpecGen(ctx context.Context, containerYAML v1.Container, iid string, newImage *image.Image, volumes map[string]*KubeVolume, podID, podName, infraID string, configMaps []v1.ConfigMap, seccompPaths *KubeSeccompPaths, restartPolicy string) (*specgen.SpecGenerator, error) {
s := specgen.NewSpecGenerator(iid, false)
// podName should be non-empty for Deployment objects to be able to create
@@ -163,22 +163,36 @@ func ToSpecGen(ctx context.Context, containerYAML v1.Container, iid string, newI
s.Env = envs
for _, volume := range containerYAML.VolumeMounts {
- hostPath, exists := volumes[volume.Name]
+ volumeSource, exists := volumes[volume.Name]
if !exists {
return nil, errors.Errorf("Volume mount %s specified for container but not configured in volumes", volume.Name)
}
- if err := parse.ValidateVolumeCtrDir(volume.MountPath); err != nil {
- return nil, errors.Wrapf(err, "error in parsing MountPath")
- }
- mount := spec.Mount{
- Destination: volume.MountPath,
- Source: hostPath,
- Type: "bind",
- }
- if volume.ReadOnly {
- mount.Options = []string{"ro"}
+ switch volumeSource.Type {
+ case KubeVolumeTypeBindMount:
+ if err := parse.ValidateVolumeCtrDir(volume.MountPath); err != nil {
+ return nil, errors.Wrapf(err, "error in parsing MountPath")
+ }
+ mount := spec.Mount{
+ Destination: volume.MountPath,
+ Source: volumeSource.Source,
+ Type: "bind",
+ }
+ if volume.ReadOnly {
+ mount.Options = []string{"ro"}
+ }
+ s.Mounts = append(s.Mounts, mount)
+ case KubeVolumeTypeNamed:
+ namedVolume := specgen.NamedVolume{
+ Dest: volume.MountPath,
+ Name: volumeSource.Source,
+ }
+ if volume.ReadOnly {
+ namedVolume.Options = []string{"ro"}
+ }
+ s.Volumes = append(s.Volumes, &namedVolume)
+ default:
+ return nil, errors.Errorf("Unsupported volume source type")
}
- s.Mounts = append(s.Mounts, mount)
}
s.RestartPolicy = restartPolicy
diff --git a/pkg/specgen/generate/kube/volume.go b/pkg/specgen/generate/kube/volume.go
new file mode 100644
index 000000000..2ef0f4c23
--- /dev/null
+++ b/pkg/specgen/generate/kube/volume.go
@@ -0,0 +1,124 @@
+package kube
+
+import (
+ "os"
+
+ "github.com/containers/buildah/pkg/parse"
+ "github.com/containers/podman/v2/libpod"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+ v1 "k8s.io/api/core/v1"
+)
+
+const (
+ // https://kubernetes.io/docs/concepts/storage/volumes/#hostpath
+ kubeDirectoryPermission = 0755
+ // https://kubernetes.io/docs/concepts/storage/volumes/#hostpath
+ kubeFilePermission = 0644
+)
+
+type KubeVolumeType int
+
+const (
+ KubeVolumeTypeBindMount KubeVolumeType = iota
+ KubeVolumeTypeNamed KubeVolumeType = iota
+)
+
+type KubeVolume struct {
+ // Type of volume to create
+ Type KubeVolumeType
+ // Path for bind mount or volume name for named volume
+ Source string
+}
+
+// Create a KubeVolume from an HostPathVolumeSource
+func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error) {
+ if hostPath.Type != nil {
+ switch *hostPath.Type {
+ case v1.HostPathDirectoryOrCreate:
+ if _, err := os.Stat(hostPath.Path); os.IsNotExist(err) {
+ if err := os.Mkdir(hostPath.Path, kubeDirectoryPermission); err != nil {
+ return nil, err
+ }
+ }
+ // Label a newly created volume
+ if err := libpod.LabelVolumePath(hostPath.Path); err != nil {
+ return nil, errors.Wrapf(err, "error giving %s a label", hostPath.Path)
+ }
+ case v1.HostPathFileOrCreate:
+ if _, err := os.Stat(hostPath.Path); os.IsNotExist(err) {
+ f, err := os.OpenFile(hostPath.Path, os.O_RDONLY|os.O_CREATE, kubeFilePermission)
+ if err != nil {
+ return nil, errors.Wrap(err, "error creating HostPath")
+ }
+ if err := f.Close(); err != nil {
+ logrus.Warnf("Error in closing newly created HostPath file: %v", err)
+ }
+ }
+ // unconditionally label a newly created volume
+ if err := libpod.LabelVolumePath(hostPath.Path); err != nil {
+ return nil, errors.Wrapf(err, "error giving %s a label", hostPath.Path)
+ }
+ case v1.HostPathSocket:
+ st, err := os.Stat(hostPath.Path)
+ if err != nil {
+ return nil, errors.Wrap(err, "error checking HostPathSocket")
+ }
+ if st.Mode()&os.ModeSocket != os.ModeSocket {
+ return nil, errors.Errorf("error checking HostPathSocket: path %s is not a socket", hostPath.Path)
+ }
+
+ case v1.HostPathDirectory:
+ case v1.HostPathFile:
+ case v1.HostPathUnset:
+ // do nothing here because we will verify the path exists in validateVolumeHostDir
+ break
+ default:
+ return nil, errors.Errorf("Invalid HostPath type %v", hostPath.Type)
+ }
+ }
+
+ if err := parse.ValidateVolumeHostDir(hostPath.Path); err != nil {
+ return nil, errors.Wrapf(err, "error in parsing HostPath in YAML")
+ }
+
+ return &KubeVolume{
+ Type: KubeVolumeTypeBindMount,
+ Source: hostPath.Path,
+ }, nil
+}
+
+// Create a KubeVolume from a PersistentVolumeClaimVolumeSource
+func VolumeFromPersistentVolumeClaim(claim *v1.PersistentVolumeClaimVolumeSource) (*KubeVolume, error) {
+ return &KubeVolume{
+ Type: KubeVolumeTypeNamed,
+ Source: claim.ClaimName,
+ }, nil
+}
+
+// Create a KubeVolume from one of the supported VolumeSource
+func VolumeFromSource(volumeSource v1.VolumeSource) (*KubeVolume, error) {
+ if volumeSource.HostPath != nil {
+ return VolumeFromHostPath(volumeSource.HostPath)
+ } else if volumeSource.PersistentVolumeClaim != nil {
+ return VolumeFromPersistentVolumeClaim(volumeSource.PersistentVolumeClaim)
+ } else {
+ return nil, errors.Errorf("HostPath and PersistentVolumeClaim are currently the conly supported VolumeSource")
+ }
+}
+
+// Create a map of volume name to KubeVolume
+func InitializeVolumes(specVolumes []v1.Volume) (map[string]*KubeVolume, error) {
+ volumes := make(map[string]*KubeVolume)
+
+ for _, specVolume := range specVolumes {
+ volume, err := VolumeFromSource(specVolume.VolumeSource)
+ if err != nil {
+ return nil, err
+ }
+
+ volumes[specVolume.Name] = volume
+ }
+
+ return volumes, nil
+}
diff --git a/pkg/specgen/namespaces.go b/pkg/specgen/namespaces.go
index 11108a5c1..d15745fa0 100644
--- a/pkg/specgen/namespaces.go
+++ b/pkg/specgen/namespaces.go
@@ -27,19 +27,25 @@ const (
// Private indicates the namespace is private
Private NamespaceMode = "private"
// NoNetwork indicates no network namespace should
- // be joined. loopback should still exists
+ // be joined. loopback should still exists.
+ // Only used with the network namespace, invalid otherwise.
NoNetwork NamespaceMode = "none"
// Bridge indicates that a CNI network stack
- // should be used
+ // should be used.
+ // Only used with the network namespace, invalid otherwise.
Bridge NamespaceMode = "bridge"
// Slirp indicates that a slirp4netns network stack should
- // be used
+ // be used.
+ // Only used with the network namespace, invalid otherwise.
Slirp NamespaceMode = "slirp4netns"
// KeepId indicates a user namespace to keep the owner uid inside
- // of the namespace itself
+ // of the namespace itself.
+ // Only used with the user namespace, invalid otherwise.
KeepID NamespaceMode = "keep-id"
- // KeepId indicates to automatically create a user namespace
+ // Auto indicates to automatically create a user namespace.
+ // Only used with the user namespace, invalid otherwise.
Auto NamespaceMode = "auto"
+
// DefaultKernelNamespaces is a comma-separated list of default kernel
// namespaces.
DefaultKernelNamespaces = "cgroup,ipc,net,uts"
@@ -272,10 +278,16 @@ func ParseNetworkNamespace(ns string) (Namespace, []string, error) {
toReturn.NSMode = Private
case strings.HasPrefix(ns, "ns:"):
split := strings.SplitN(ns, ":", 2)
+ if len(split) != 2 {
+ return toReturn, nil, errors.Errorf("must provide a path to a namespace when specifying ns:")
+ }
toReturn.NSMode = Path
toReturn.Value = split[1]
case strings.HasPrefix(ns, "container:"):
split := strings.SplitN(ns, ":", 2)
+ if len(split) != 2 {
+ return toReturn, nil, errors.Errorf("must provide name or ID or a container when specifying container:")
+ }
toReturn.NSMode = FromContainer
toReturn.Value = split[1]
default:
diff --git a/pkg/specgen/volumes.go b/pkg/specgen/volumes.go
index 41efee3b3..a4f42d715 100644
--- a/pkg/specgen/volumes.go
+++ b/pkg/specgen/volumes.go
@@ -84,6 +84,7 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na
return nil, nil, nil, err
}
}
+
// Do not check source dir for anonymous volumes
if len(splitVol) > 1 {
if len(src) == 0 {