forked from kubevirt/containerized-data-importer
-
Notifications
You must be signed in to change notification settings - Fork 2
/
pvc.go
142 lines (125 loc) · 4.87 KB
/
pvc.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
130
131
132
133
134
135
136
137
138
139
140
141
142
package utils
import (
"time"
"fmt"
k8sv1 "k8s.io/api/core/v1"
apierrs "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
)
const (
defaultPollInterval = 2 * time.Second
defaultPollPeriod = 30 * time.Second
// DefaultPvcMountPath is the default mount path used
DefaultPvcMountPath = "/pvc"
pvcPollInterval = defaultPollInterval
pvcCreateTime = defaultPollPeriod
pvcDeleteTime = defaultPollPeriod
pvcPhaseTime = defaultPollPeriod
)
// CreatePVCFromDefinition creates a PVC in the passed in namespace from the passed in PersistentVolumeClaim definition.
// An example of creating a PVC without annotations looks like this:
// CreatePVCFromDefinition(client, namespace, NewPVCDefinition(name, size, nil, nil))
func CreatePVCFromDefinition(clientSet *kubernetes.Clientset, namespace string, def *k8sv1.PersistentVolumeClaim) (*k8sv1.PersistentVolumeClaim, error) {
var pvc *k8sv1.PersistentVolumeClaim
err := wait.PollImmediate(pvcPollInterval, pvcCreateTime, func() (bool, error) {
var err error
pvc, err = clientSet.CoreV1().PersistentVolumeClaims(namespace).Create(def)
if err == nil || apierrs.IsAlreadyExists(err) {
return true, nil
}
return false, err
})
if err != nil {
return nil, err
}
return pvc, nil
}
// DeletePVC deletes the passed in PVC
func DeletePVC(clientSet *kubernetes.Clientset, namespace string, pvc *k8sv1.PersistentVolumeClaim) error {
return wait.PollImmediate(pvcPollInterval, pvcDeleteTime, func() (bool, error) {
err := clientSet.CoreV1().PersistentVolumeClaims(namespace).Delete(pvc.GetName(), nil)
if err == nil || apierrs.IsNotFound(err) {
return true, nil
}
return false, err
})
}
// FindPVC Fins the passed in PVC
func FindPVC(clientSet *kubernetes.Clientset, namespace, pvcName string) (*k8sv1.PersistentVolumeClaim, error) {
return clientSet.CoreV1().PersistentVolumeClaims(namespace).Get(pvcName, metav1.GetOptions{})
}
// WaitForPVCAnnotation waits for an anotation to appear on a PVC
func WaitForPVCAnnotation(clientSet *kubernetes.Clientset, namespace string, pvc *k8sv1.PersistentVolumeClaim, annotation string) (string, bool, error) {
var result string
var called bool
err := pollPVCAnnotation(clientSet, namespace, pvc, annotation, func(value string) bool {
called = true
result = value
return true
})
return result, called, err
}
// WaitForPVCAnnotationWithValue waits for an annotation with a specific value on a PVC
func WaitForPVCAnnotationWithValue(clientSet *kubernetes.Clientset, namespace string, pvc *k8sv1.PersistentVolumeClaim, annotation, expected string) (bool, error) {
var result bool
err := pollPVCAnnotation(clientSet, namespace, pvc, annotation, func(value string) bool {
result = (expected == value)
return result
})
return result, err
}
type pollPVCAnnotationFunc = func(string) bool
func pollPVCAnnotation(clientSet *kubernetes.Clientset, namespace string, pvc *k8sv1.PersistentVolumeClaim, annotation string, f pollPVCAnnotationFunc) error {
err := wait.PollImmediate(pvcPollInterval, pvcCreateTime, func() (bool, error) {
pvc, err := FindPVC(clientSet, namespace, pvc.Name)
if err != nil {
return false, err
}
value, ok := pvc.ObjectMeta.Annotations[annotation]
if ok {
return f(value), nil
}
return false, err
})
return err
}
// NewPVCDefinition creates a PVC definition using the passed in name and requested size.
// You can use the following annotation keys to request an import or clone. The values are defined in the controller package
// AnnEndpoint
// AnnSecret
// AnnCloneRequest
// You can also pass in any label you want.
func NewPVCDefinition(pvcName string, size string, annotations, labels map[string]string) *k8sv1.PersistentVolumeClaim {
return &k8sv1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: pvcName,
Annotations: annotations,
Labels: labels,
},
Spec: k8sv1.PersistentVolumeClaimSpec{
AccessModes: []k8sv1.PersistentVolumeAccessMode{k8sv1.ReadWriteOnce},
Resources: k8sv1.ResourceRequirements{
Requests: k8sv1.ResourceList{
k8sv1.ResourceName(k8sv1.ResourceStorage): resource.MustParse(size),
},
},
},
}
}
// WaitForPersistentVolumeClaimPhase waits for the PVC to be in a particular phase (Pending, Bound, or Lost)
func WaitForPersistentVolumeClaimPhase(clientSet *kubernetes.Clientset, namespace string, phase k8sv1.PersistentVolumeClaimPhase, pvcName string) error {
err := wait.PollImmediate(pvcPollInterval, pvcPhaseTime, func() (bool, error) {
pvc, err := clientSet.CoreV1().PersistentVolumeClaims(namespace).Get(pvcName, metav1.GetOptions{})
if err != nil || pvc.Status.Phase != phase {
return false, err
}
return true, nil
})
if err != nil {
return fmt.Errorf("PersistentVolumeClaim %s not in phase %s within %v", pvcName, phase, pvcPhaseTime)
}
return nil
}