github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/pkg/specgen/generate/kube/volume.go (about) 1 package kube 2 3 import ( 4 "os" 5 6 "github.com/containers/buildah/pkg/parse" 7 "github.com/containers/podman/v2/libpod" 8 "github.com/pkg/errors" 9 "github.com/sirupsen/logrus" 10 v1 "k8s.io/api/core/v1" 11 ) 12 13 const ( 14 // https://kubernetes.io/docs/concepts/storage/volumes/#hostpath 15 kubeDirectoryPermission = 0755 16 // https://kubernetes.io/docs/concepts/storage/volumes/#hostpath 17 kubeFilePermission = 0644 18 ) 19 20 type KubeVolumeType int 21 22 const ( 23 KubeVolumeTypeBindMount KubeVolumeType = iota 24 KubeVolumeTypeNamed KubeVolumeType = iota 25 ) 26 27 type KubeVolume struct { 28 // Type of volume to create 29 Type KubeVolumeType 30 // Path for bind mount or volume name for named volume 31 Source string 32 } 33 34 // Create a KubeVolume from an HostPathVolumeSource 35 func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error) { 36 if hostPath.Type != nil { 37 switch *hostPath.Type { 38 case v1.HostPathDirectoryOrCreate: 39 if _, err := os.Stat(hostPath.Path); os.IsNotExist(err) { 40 if err := os.Mkdir(hostPath.Path, kubeDirectoryPermission); err != nil { 41 return nil, err 42 } 43 } 44 // Label a newly created volume 45 if err := libpod.LabelVolumePath(hostPath.Path); err != nil { 46 return nil, errors.Wrapf(err, "error giving %s a label", hostPath.Path) 47 } 48 case v1.HostPathFileOrCreate: 49 if _, err := os.Stat(hostPath.Path); os.IsNotExist(err) { 50 f, err := os.OpenFile(hostPath.Path, os.O_RDONLY|os.O_CREATE, kubeFilePermission) 51 if err != nil { 52 return nil, errors.Wrap(err, "error creating HostPath") 53 } 54 if err := f.Close(); err != nil { 55 logrus.Warnf("Error in closing newly created HostPath file: %v", err) 56 } 57 } 58 // unconditionally label a newly created volume 59 if err := libpod.LabelVolumePath(hostPath.Path); err != nil { 60 return nil, errors.Wrapf(err, "error giving %s a label", hostPath.Path) 61 } 62 case v1.HostPathSocket: 63 st, err := os.Stat(hostPath.Path) 64 if err != nil { 65 return nil, errors.Wrap(err, "error checking HostPathSocket") 66 } 67 if st.Mode()&os.ModeSocket != os.ModeSocket { 68 return nil, errors.Errorf("error checking HostPathSocket: path %s is not a socket", hostPath.Path) 69 } 70 71 case v1.HostPathDirectory: 72 case v1.HostPathFile: 73 case v1.HostPathUnset: 74 // do nothing here because we will verify the path exists in validateVolumeHostDir 75 break 76 default: 77 return nil, errors.Errorf("Invalid HostPath type %v", hostPath.Type) 78 } 79 } 80 81 if err := parse.ValidateVolumeHostDir(hostPath.Path); err != nil { 82 return nil, errors.Wrapf(err, "error in parsing HostPath in YAML") 83 } 84 85 return &KubeVolume{ 86 Type: KubeVolumeTypeBindMount, 87 Source: hostPath.Path, 88 }, nil 89 } 90 91 // Create a KubeVolume from a PersistentVolumeClaimVolumeSource 92 func VolumeFromPersistentVolumeClaim(claim *v1.PersistentVolumeClaimVolumeSource) (*KubeVolume, error) { 93 return &KubeVolume{ 94 Type: KubeVolumeTypeNamed, 95 Source: claim.ClaimName, 96 }, nil 97 } 98 99 // Create a KubeVolume from one of the supported VolumeSource 100 func VolumeFromSource(volumeSource v1.VolumeSource) (*KubeVolume, error) { 101 if volumeSource.HostPath != nil { 102 return VolumeFromHostPath(volumeSource.HostPath) 103 } else if volumeSource.PersistentVolumeClaim != nil { 104 return VolumeFromPersistentVolumeClaim(volumeSource.PersistentVolumeClaim) 105 } else { 106 return nil, errors.Errorf("HostPath and PersistentVolumeClaim are currently the conly supported VolumeSource") 107 } 108 } 109 110 // Create a map of volume name to KubeVolume 111 func InitializeVolumes(specVolumes []v1.Volume) (map[string]*KubeVolume, error) { 112 volumes := make(map[string]*KubeVolume) 113 114 for _, specVolume := range specVolumes { 115 volume, err := VolumeFromSource(specVolume.VolumeSource) 116 if err != nil { 117 return nil, err 118 } 119 120 volumes[specVolume.Name] = volume 121 } 122 123 return volumes, nil 124 }