summaryrefslogtreecommitdiff
path: root/pkg/specgen
diff options
context:
space:
mode:
authorjortkoopmans <jort@jabo-solutions.eu>2020-11-30 15:58:23 +0100
committerGitHub <noreply@github.com>2020-11-30 15:58:23 +0100
commit84e8b2afa795ca060f4d2c5206f47d320292ed9b (patch)
treeea0e985d3f50d389b33fdb403d240e817251fd8c /pkg/specgen
parent5cfbe0b78e3672dd67cd028b85d816fc19d6a614 (diff)
parentfc85ec942ee3273f5ad56381a0f6b9e78aea59bf (diff)
downloadpodman-84e8b2afa795ca060f4d2c5206f47d320292ed9b.tar.gz
podman-84e8b2afa795ca060f4d2c5206f47d320292ed9b.tar.bz2
podman-84e8b2afa795ca060f4d2c5206f47d320292ed9b.zip
Merge branch 'master' into patch-1
Diffstat (limited to 'pkg/specgen')
-rw-r--r--pkg/specgen/generate/kube/kube.go40
-rw-r--r--pkg/specgen/generate/kube/volume.go124
-rw-r--r--pkg/specgen/volumes.go4
3 files changed, 153 insertions, 15 deletions
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/volumes.go b/pkg/specgen/volumes.go
index 1178f9960..a4f42d715 100644
--- a/pkg/specgen/volumes.go
+++ b/pkg/specgen/volumes.go
@@ -87,8 +87,8 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na
// Do not check source dir for anonymous volumes
if len(splitVol) > 1 {
- if err := parse.ValidateVolumeHostDir(src); err != nil {
- return nil, nil, nil, err
+ if len(src) == 0 {
+ return nil, nil, nil, errors.New("host directory cannot be empty")
}
}
if err := parse.ValidateVolumeCtrDir(dest); err != nil {