/
volumes.go
129 lines (109 loc) · 4.57 KB
/
volumes.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package kclient
import (
"fmt"
"github.com/openshift/odo/pkg/devfile/adapters/common"
"github.com/openshift/odo/pkg/util"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// constants for volumes
const (
PersistentVolumeClaimKind = "PersistentVolumeClaim"
PersistentVolumeClaimAPIVersion = "v1"
)
// CreatePVC creates a PVC resource in the cluster with the given name, size and labels
func (c *Client) CreatePVC(objectMeta metav1.ObjectMeta, pvcSpec corev1.PersistentVolumeClaimSpec) (*corev1.PersistentVolumeClaim, error) {
pvc := &corev1.PersistentVolumeClaim{
ObjectMeta: objectMeta,
Spec: pvcSpec,
}
createdPvc, err := c.KubeClient.CoreV1().PersistentVolumeClaims(c.Namespace).Create(pvc)
if err != nil {
return nil, errors.Wrap(err, "unable to create PVC")
}
return createdPvc, nil
}
// DeletePVC deletes the required PVC resource from the cluster
func (c *Client) DeletePVC(pvcName string) error {
return c.KubeClient.CoreV1().PersistentVolumeClaims(c.Namespace).Delete(pvcName, &metav1.DeleteOptions{})
}
// AddPVCToPodTemplateSpec adds the given PVC to the podTemplateSpec
func AddPVCToPodTemplateSpec(podTemplateSpec *corev1.PodTemplateSpec, volumeName, pvcName string) {
podTemplateSpec.Spec.Volumes = append(podTemplateSpec.Spec.Volumes, corev1.Volume{
Name: volumeName,
VolumeSource: corev1.VolumeSource{
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
ClaimName: pvcName,
},
},
})
}
// AddVolumeMountToPodTemplateSpec adds the Volume Mounts in containerNameToMountPaths to the podTemplateSpec containers for a given pvc and volumeName
// containerNameToMountPaths is a map of a container name to an array of its Mount Paths
func AddVolumeMountToPodTemplateSpec(podTemplateSpec *corev1.PodTemplateSpec, volumeName string, containerNameToMountPaths map[string][]string) error {
// Validating podTemplateSpec.Spec.Containers[] is present before dereferencing
if len(podTemplateSpec.Spec.Containers) == 0 {
return fmt.Errorf("podTemplateSpec %s doesn't have any Containers defined", podTemplateSpec.ObjectMeta.Name)
}
for containerName, mountPaths := range containerNameToMountPaths {
for i, container := range podTemplateSpec.Spec.Containers {
if container.Name == containerName {
for _, mountPath := range mountPaths {
container.VolumeMounts = append(container.VolumeMounts, corev1.VolumeMount{
Name: volumeName,
MountPath: mountPath,
SubPath: "",
},
)
}
podTemplateSpec.Spec.Containers[i] = container
}
}
}
return nil
}
// AddPVCAndVolumeMount adds PVC and volume mount to the pod template spec
// volumeNameToPVCName is a map of volume name to the PVC created
// containerNameToVolumes is a map of the Devfile container names to the Devfile Volumes
func AddPVCAndVolumeMount(podTemplateSpec *corev1.PodTemplateSpec, volumeNameToPVCName map[string]string, containerNameToVolumes map[string][]common.DevfileVolume) error {
for volName, pvcName := range volumeNameToPVCName {
generatedVolumeName, err := generateVolumeNameFromPVC(pvcName)
if err != nil {
return errors.Wrapf(err, "Unable to generate volume name from pvc name")
}
AddPVCToPodTemplateSpec(podTemplateSpec, generatedVolumeName, pvcName)
// containerNameToMountPaths is a map of the Devfile container name to their Devfile Volume Mount Paths for a given Volume Name
containerNameToMountPaths := make(map[string][]string)
for containerName, volumes := range containerNameToVolumes {
for _, volume := range volumes {
if volName == volume.Name {
containerNameToMountPaths[containerName] = append(containerNameToMountPaths[containerName], volume.ContainerPath)
}
}
}
err = AddVolumeMountToPodTemplateSpec(podTemplateSpec, generatedVolumeName, containerNameToMountPaths)
if err != nil {
return errors.Wrapf(err, "Unable to add volumes mounts to the pod")
}
}
return nil
}
// GetPVCsFromSelector returns the PVCs based on the given selector
func (c *Client) GetPVCsFromSelector(selector string) ([]corev1.PersistentVolumeClaim, error) {
pvcList, err := c.KubeClient.CoreV1().PersistentVolumeClaims(c.Namespace).List(metav1.ListOptions{
LabelSelector: selector,
})
if err != nil {
return nil, errors.Wrapf(err, "unable to get PVCs for selector: %v", selector)
}
return pvcList.Items, nil
}
// generateVolumeNameFromPVC generates a volume name based on the pvc name
func generateVolumeNameFromPVC(pvc string) (volumeName string, err error) {
volumeName, err = util.NamespaceOpenShiftObject(pvc, "vol")
if err != nil {
return "", err
}
return
}