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 }