k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/scheduler/framework/plugins/volumebinding/test_utils.go (about) 1 /* 2 Copyright 2021 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package volumebinding 18 19 import ( 20 "fmt" 21 22 v1 "k8s.io/api/core/v1" 23 "k8s.io/apimachinery/pkg/api/resource" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "k8s.io/component-helpers/storage/volume" 26 "k8s.io/utils/ptr" 27 ) 28 29 type nodeBuilder struct { 30 *v1.Node 31 } 32 33 func makeNode(name string) nodeBuilder { 34 return nodeBuilder{Node: &v1.Node{ 35 ObjectMeta: metav1.ObjectMeta{ 36 Name: name, 37 Labels: map[string]string{ 38 v1.LabelHostname: name, 39 }, 40 }, 41 }} 42 } 43 44 func (nb nodeBuilder) withLabel(key, value string) nodeBuilder { 45 if nb.Node.ObjectMeta.Labels == nil { 46 nb.Node.ObjectMeta.Labels = map[string]string{} 47 } 48 nb.Node.ObjectMeta.Labels[key] = value 49 return nb 50 } 51 52 type pvBuilder struct { 53 *v1.PersistentVolume 54 } 55 56 func makePV(name, className string) pvBuilder { 57 return pvBuilder{PersistentVolume: &v1.PersistentVolume{ 58 ObjectMeta: metav1.ObjectMeta{ 59 Name: name, 60 }, 61 Spec: v1.PersistentVolumeSpec{ 62 StorageClassName: className, 63 }, 64 }} 65 } 66 67 func (pvb pvBuilder) withNodeAffinity(keyValues map[string][]string) pvBuilder { 68 matchExpressions := make([]v1.NodeSelectorRequirement, 0) 69 for key, values := range keyValues { 70 matchExpressions = append(matchExpressions, v1.NodeSelectorRequirement{ 71 Key: key, 72 Operator: v1.NodeSelectorOpIn, 73 Values: values, 74 }) 75 } 76 pvb.PersistentVolume.Spec.NodeAffinity = &v1.VolumeNodeAffinity{ 77 Required: &v1.NodeSelector{ 78 NodeSelectorTerms: []v1.NodeSelectorTerm{ 79 { 80 MatchExpressions: matchExpressions, 81 }, 82 }, 83 }, 84 } 85 return pvb 86 } 87 88 func (pvb pvBuilder) withVersion(version string) pvBuilder { 89 pvb.PersistentVolume.ObjectMeta.ResourceVersion = version 90 return pvb 91 } 92 93 func (pvb pvBuilder) withCapacity(capacity resource.Quantity) pvBuilder { 94 pvb.PersistentVolume.Spec.Capacity = v1.ResourceList{ 95 v1.ResourceName(v1.ResourceStorage): capacity, 96 } 97 return pvb 98 } 99 100 func (pvb pvBuilder) withPhase(phase v1.PersistentVolumePhase) pvBuilder { 101 pvb.PersistentVolume.Status = v1.PersistentVolumeStatus{ 102 Phase: phase, 103 } 104 return pvb 105 } 106 107 type pvcBuilder struct { 108 *v1.PersistentVolumeClaim 109 } 110 111 func makePVC(name string, storageClassName string) pvcBuilder { 112 return pvcBuilder{PersistentVolumeClaim: &v1.PersistentVolumeClaim{ 113 ObjectMeta: metav1.ObjectMeta{ 114 Name: name, 115 Namespace: v1.NamespaceDefault, 116 }, 117 Spec: v1.PersistentVolumeClaimSpec{ 118 StorageClassName: ptr.To(storageClassName), 119 }, 120 }} 121 } 122 123 func (pvcb pvcBuilder) withBoundPV(pvName string) pvcBuilder { 124 pvcb.PersistentVolumeClaim.Spec.VolumeName = pvName 125 metav1.SetMetaDataAnnotation(&pvcb.PersistentVolumeClaim.ObjectMeta, volume.AnnBindCompleted, "true") 126 return pvcb 127 } 128 129 func (pvcb pvcBuilder) withRequestStorage(request resource.Quantity) pvcBuilder { 130 pvcb.PersistentVolumeClaim.Spec.Resources = v1.VolumeResourceRequirements{ 131 Requests: v1.ResourceList{ 132 v1.ResourceName(v1.ResourceStorage): request, 133 }, 134 } 135 return pvcb 136 } 137 138 func (pvcb pvcBuilder) withPhase(phase v1.PersistentVolumeClaimPhase) pvcBuilder { 139 pvcb.PersistentVolumeClaim.Status = v1.PersistentVolumeClaimStatus{ 140 Phase: phase, 141 } 142 return pvcb 143 } 144 145 type podBuilder struct { 146 *v1.Pod 147 } 148 149 func makePod(name string) podBuilder { 150 pb := podBuilder{Pod: &v1.Pod{ 151 ObjectMeta: metav1.ObjectMeta{ 152 Name: name, 153 Namespace: v1.NamespaceDefault, 154 }, 155 }} 156 pb.Pod.Spec.Volumes = make([]v1.Volume, 0) 157 return pb 158 } 159 160 func (pb podBuilder) withNodeName(name string) podBuilder { 161 pb.Pod.Spec.NodeName = name 162 return pb 163 } 164 165 func (pb podBuilder) withNamespace(name string) podBuilder { 166 pb.Pod.ObjectMeta.Namespace = name 167 return pb 168 } 169 170 func (pb podBuilder) withPVCVolume(pvcName, name string) podBuilder { 171 pb.Pod.Spec.Volumes = append(pb.Pod.Spec.Volumes, v1.Volume{ 172 Name: name, 173 VolumeSource: v1.VolumeSource{ 174 PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ 175 ClaimName: pvcName, 176 }, 177 }, 178 }) 179 return pb 180 } 181 182 func (pb podBuilder) withPVCSVolume(pvcs []*v1.PersistentVolumeClaim) podBuilder { 183 for i, pvc := range pvcs { 184 pb.withPVCVolume(pvc.Name, fmt.Sprintf("vol%v", i)) 185 } 186 return pb 187 } 188 189 func (pb podBuilder) withEmptyDirVolume() podBuilder { 190 pb.Pod.Spec.Volumes = append(pb.Pod.Spec.Volumes, v1.Volume{ 191 VolumeSource: v1.VolumeSource{ 192 EmptyDir: &v1.EmptyDirVolumeSource{}, 193 }, 194 }) 195 return pb 196 } 197 198 func (pb podBuilder) withGenericEphemeralVolume(name string) podBuilder { 199 pb.Pod.Spec.Volumes = append(pb.Pod.Spec.Volumes, v1.Volume{ 200 Name: name, 201 VolumeSource: v1.VolumeSource{ 202 Ephemeral: &v1.EphemeralVolumeSource{}, 203 }, 204 }) 205 return pb 206 }