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  }