github.com/banzaicloud/operator-tools@v0.28.10/pkg/volume/volume_types.go (about)

     1  // Copyright © 2020 Banzai Cloud
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package volume
    16  
    17  import (
    18  	"emperror.dev/errors"
    19  	v1 "k8s.io/api/apps/v1"
    20  	corev1 "k8s.io/api/core/v1"
    21  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    22  )
    23  
    24  //nolint:unused,deadcode
    25  // +docName:"Kubernetes volume abstraction"
    26  // Refers to different types of volumes to be mounted to pods: emptyDir, hostPath, pvc
    27  //
    28  // Leverages core types from kubernetes/api/core/v1
    29  type _docKubernetesVolume interface{}
    30  
    31  //nolint:unused,deadcode
    32  // +name:"KubernetesVolume"
    33  // +description:"Kubernetes volume abstraction"
    34  type _metaKubernetesVolume interface{}
    35  
    36  // +kubebuilder:object:generate=true
    37  
    38  type KubernetesVolume struct {
    39  	// Deprecated, use hostPath
    40  	HostPathLegacy *corev1.HostPathVolumeSource `json:"host_path,omitempty"`
    41  	HostPath       *corev1.HostPathVolumeSource `json:"hostPath,omitempty"`
    42  	EmptyDir       *corev1.EmptyDirVolumeSource `json:"emptyDir,omitempty"`
    43  	// PersistentVolumeClaim defines the Spec and the Source at the same time.
    44  	// The PVC will be created with the configured spec and the name defined in the source.
    45  	PersistentVolumeClaim *PersistentVolumeClaim `json:"pvc,omitempty"`
    46  }
    47  
    48  // +kubebuilder:object:generate=true
    49  
    50  type PersistentVolumeClaim struct {
    51  	PersistentVolumeClaimSpec corev1.PersistentVolumeClaimSpec         `json:"spec,omitempty"`
    52  	PersistentVolumeSource    corev1.PersistentVolumeClaimVolumeSource `json:"source,omitempty"`
    53  }
    54  
    55  // `path` is the path in case the hostPath volume type is used and no path has been defined explicitly
    56  func (v *KubernetesVolume) WithDefaultHostPath(path string) {
    57  	if v.HostPath != nil {
    58  		if v.HostPath.Path == "" {
    59  			v.HostPath.Path = path
    60  		}
    61  	}
    62  }
    63  
    64  // GetVolume returns a default emptydir volume if none configured
    65  //
    66  // `name`    will be the name of the volume and the lowest level directory in case a hostPath mount is used
    67  func (v *KubernetesVolume) GetVolume(name string) (corev1.Volume, error) {
    68  	volume := corev1.Volume{
    69  		Name: name,
    70  	}
    71  	if v.HostPathLegacy != nil {
    72  		return volume, errors.New("legacy host_path field is not supported anymore, please migrate to hostPath")
    73  	}
    74  	if v.HostPath != nil {
    75  		volume.VolumeSource = corev1.VolumeSource{
    76  			HostPath: v.HostPath,
    77  		}
    78  		return volume, nil
    79  	} else if v.EmptyDir != nil {
    80  		volume.VolumeSource = corev1.VolumeSource{
    81  			EmptyDir: v.EmptyDir,
    82  		}
    83  		return volume, nil
    84  	} else if v.PersistentVolumeClaim != nil {
    85  		volume.VolumeSource = corev1.VolumeSource{
    86  			PersistentVolumeClaim: &v.PersistentVolumeClaim.PersistentVolumeSource,
    87  		}
    88  		return volume, nil
    89  	}
    90  	// return a default emptydir volume if none configured
    91  	volume.VolumeSource = corev1.VolumeSource{
    92  		EmptyDir: &corev1.EmptyDirVolumeSource{},
    93  	}
    94  	return volume, nil
    95  }
    96  
    97  func (v *KubernetesVolume) ApplyPVCForStatefulSet(containerName string, path string, spec *v1.StatefulSetSpec, meta func(name string) metav1.ObjectMeta) error {
    98  	if v.PersistentVolumeClaim == nil {
    99  		return errors.New("PVC definition is missing, unable to apply on statefulset")
   100  	}
   101  	pvc := corev1.PersistentVolumeClaim{
   102  		ObjectMeta: meta(v.PersistentVolumeClaim.PersistentVolumeSource.ClaimName),
   103  		Spec:       v.PersistentVolumeClaim.PersistentVolumeClaimSpec,
   104  		Status: corev1.PersistentVolumeClaimStatus{
   105  			Phase: corev1.ClaimPending,
   106  		},
   107  	}
   108  
   109  	spec.VolumeClaimTemplates = append(spec.VolumeClaimTemplates, pvc)
   110  
   111  	found := false
   112  	for i, c := range spec.Template.Spec.Containers {
   113  		if c.Name == containerName {
   114  			found = true
   115  			c.VolumeMounts = append(c.VolumeMounts, corev1.VolumeMount{
   116  				Name:      pvc.Name,
   117  				MountPath: path,
   118  			})
   119  			spec.Template.Spec.Containers[i] = c
   120  			break
   121  		}
   122  	}
   123  	if !found {
   124  		return errors.Errorf("failed to find container %s to configure volume mount for the given PVC", containerName)
   125  	}
   126  	return nil
   127  }
   128  
   129  func (v *KubernetesVolume) ApplyVolumeForPodSpec(volumeName, containerName string, path string, spec *corev1.PodSpec) error {
   130  	vol, err := v.GetVolume(volumeName)
   131  	if err != nil {
   132  		return errors.WrapIf(err, "failed to create volume definition for statefulset")
   133  	}
   134  
   135  	spec.Volumes = append(spec.Volumes, vol)
   136  
   137  	found := false
   138  	for i, c := range spec.Containers {
   139  		if c.Name == containerName {
   140  			found = true
   141  			c.VolumeMounts = append(c.VolumeMounts, corev1.VolumeMount{
   142  				Name:      volumeName,
   143  				MountPath: path,
   144  			})
   145  			spec.Containers[i] = c
   146  			break
   147  		}
   148  	}
   149  	if !found {
   150  		return errors.Errorf("failed to find container %s to configure volume mount", containerName)
   151  	}
   152  	return nil
   153  }