github.com/verrazzano/verrazzano-monitoring-operator@v0.0.30/pkg/vmo/pvc_update_test.go (about) 1 // Copyright (C) 2022, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 package vmo 5 6 import ( 7 "github.com/stretchr/testify/assert" 8 vmcontrollerv1 "github.com/verrazzano/verrazzano-monitoring-operator/pkg/apis/vmcontroller/v1" 9 "github.com/verrazzano/verrazzano-monitoring-operator/pkg/constants" 10 appsv1 "k8s.io/api/apps/v1" 11 corev1 "k8s.io/api/core/v1" 12 storagev1 "k8s.io/api/storage/v1" 13 "k8s.io/apimachinery/pkg/api/resource" 14 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 15 "k8s.io/client-go/kubernetes/fake" 16 "testing" 17 ) 18 19 var testvmo = vmcontrollerv1.VerrazzanoMonitoringInstance{ 20 ObjectMeta: metav1.ObjectMeta{ 21 Name: "system", 22 Namespace: constants.VerrazzanoSystemNamespace, 23 }, 24 Spec: vmcontrollerv1.VerrazzanoMonitoringInstanceSpec{ 25 Elasticsearch: vmcontrollerv1.Elasticsearch{ 26 DataNode: vmcontrollerv1.ElasticsearchNode{ 27 Replicas: 3, 28 }, 29 IngestNode: vmcontrollerv1.ElasticsearchNode{ 30 Replicas: 1, 31 }, 32 MasterNode: vmcontrollerv1.ElasticsearchNode{ 33 Replicas: 1, 34 }, 35 }, 36 }, 37 } 38 39 func makePVC(name, quantity string) *corev1.PersistentVolumeClaim { 40 q, _ := resource.ParseQuantity(quantity) 41 return &corev1.PersistentVolumeClaim{ 42 ObjectMeta: metav1.ObjectMeta{ 43 Name: name, 44 Namespace: constants.VerrazzanoSystemNamespace, 45 }, 46 Spec: corev1.PersistentVolumeClaimSpec{ 47 AccessModes: []corev1.PersistentVolumeAccessMode{ 48 "ReadWriteOnce", 49 }, 50 Resources: corev1.ResourceRequirements{ 51 Requests: corev1.ResourceList{ 52 "storage": q, 53 }, 54 }, 55 }, 56 } 57 } 58 59 func makeDeploymentWithPVC(pvc *corev1.PersistentVolumeClaim) *appsv1.Deployment { 60 d := &appsv1.Deployment{ 61 ObjectMeta: metav1.ObjectMeta{ 62 Name: "deploy", 63 }, 64 Spec: appsv1.DeploymentSpec{ 65 Template: corev1.PodTemplateSpec{ 66 Spec: corev1.PodSpec{}, 67 }, 68 }, 69 } 70 if pvc != nil { 71 d.Spec.Template.Spec.Volumes = []corev1.Volume{ 72 { 73 Name: pvc.Name, 74 VolumeSource: corev1.VolumeSource{ 75 PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ 76 ClaimName: pvc.Name, 77 }, 78 }, 79 }, 80 } 81 } 82 return d 83 } 84 85 func TestGetUnboundPVCs(t *testing.T) { 86 pvcs := []*corev1.PersistentVolumeClaim{ 87 makePVC("pvc1", "1Gi"), 88 makePVC("pvc2", "1Gi"), 89 makePVC("pvc3", "1Gi"), 90 makePVC("pvc4", "1Gi"), 91 } 92 boundPVCNames := map[string]bool{ 93 "pvc2": true, 94 "pvc4": true, 95 } 96 97 unboundPVCNames := getUnboundPVCs(pvcs, boundPVCNames) 98 assert.Equal(t, 2, len(unboundPVCNames)) 99 assert.Equal(t, "pvc1", unboundPVCNames[0].Name) 100 assert.Equal(t, "pvc3", unboundPVCNames[1].Name) 101 } 102 103 func TestGetInUsePVCNames(t *testing.T) { 104 deployments := []*appsv1.Deployment{ 105 makeDeploymentWithPVC(makePVC("pvc1", "1Gi")), 106 makeDeploymentWithPVC(makePVC("pvc2", "1Gi")), 107 makeDeploymentWithPVC(nil), 108 } 109 110 isUsePVCNames := getInUsePVCNames(deployments, &vmcontrollerv1.VerrazzanoMonitoringInstance{}) 111 assert.Equal(t, 2, len(isUsePVCNames)) 112 assert.Equal(t, isUsePVCNames["pvc1"], true) 113 assert.Equal(t, isUsePVCNames["pvc2"], true) 114 } 115 116 func TestNewPVCName(t *testing.T) { 117 prefixSize := 5 118 var tests = []struct { 119 name string 120 resizedName bool 121 }{ 122 { 123 constants.VMOServiceNamePrefix + "pvc", 124 true, 125 }, 126 { 127 constants.VMOServiceNamePrefix + "pvc-abcde", 128 false, 129 }, 130 } 131 132 for _, tt := range tests { 133 t.Run(tt.name, func(t *testing.T) { 134 newName, err := newPVCName(tt.name, prefixSize) 135 assert.NoError(t, err) 136 assert.NotEqual(t, tt.name, newName) 137 if tt.resizedName { 138 assert.Equal(t, len(tt.name)+1+prefixSize, len(newName)) 139 } else { 140 assert.Equal(t, len(tt.name), len(newName)) 141 } 142 }) 143 } 144 } 145 146 func TestPVCNeedsResize(t *testing.T) { 147 var tests = []struct { 148 name string 149 old *corev1.PersistentVolumeClaim 150 new *corev1.PersistentVolumeClaim 151 needsResize bool 152 }{ 153 { 154 "equal PVCs don't need resize", 155 makePVC("pvc", "1Gi"), 156 makePVC("pvc", "1Gi"), 157 false, 158 }, 159 { 160 "don't resize PVCs smaller than they already are", 161 makePVC("pvc", "2Gi"), 162 makePVC("pvc", "1Gi"), 163 false, 164 }, 165 { 166 "needs resize when new PVC is larger than the old PVC", 167 makePVC("pvc", "1Gi"), 168 makePVC("pvc", "2Gi"), 169 true, 170 }, 171 } 172 173 for _, tt := range tests { 174 t.Run(tt.name, func(t *testing.T) { 175 assert.Equal(t, tt.needsResize, pvcNeedsResize(tt.old, tt.new)) 176 }) 177 } 178 } 179 180 func TestUpdateVMOStorageForPVC(t *testing.T) { 181 vmo := &vmcontrollerv1.VerrazzanoMonitoringInstance{ 182 Spec: vmcontrollerv1.VerrazzanoMonitoringInstanceSpec{ 183 Elasticsearch: vmcontrollerv1.Elasticsearch{ 184 DataNode: vmcontrollerv1.ElasticsearchNode{ 185 Storage: &vmcontrollerv1.Storage{ 186 PvcNames: []string{ 187 "some other pvc", 188 "oldpvc", 189 }, 190 }, 191 }, 192 }, 193 }, 194 } 195 196 updateVMOStorageForPVC(vmo, "oldpvc", "newpvc") 197 assert.Equal(t, "newpvc", vmo.Spec.Elasticsearch.DataNode.Storage.PvcNames[1]) 198 } 199 200 func TestIsOpenSearchPVC(t *testing.T) { 201 assert.True(t, isOpenSearchPVC(makePVC("vmi-system-es-data-0", "1Gi"))) 202 assert.False(t, isOpenSearchPVC(makePVC("vmi-system-grafana", "1Gi"))) 203 } 204 205 func TestSetPerNodeStorage(t *testing.T) { 206 pvcNames := []string{ 207 "some other pvc", 208 "oldpvc", 209 } 210 vmo := &vmcontrollerv1.VerrazzanoMonitoringInstance{ 211 Spec: vmcontrollerv1.VerrazzanoMonitoringInstanceSpec{ 212 Elasticsearch: vmcontrollerv1.Elasticsearch{ 213 DataNode: vmcontrollerv1.ElasticsearchNode{ 214 Replicas: 1, 215 }, 216 MasterNode: vmcontrollerv1.ElasticsearchNode{ 217 Replicas: 1, 218 }, 219 Storage: vmcontrollerv1.Storage{ 220 Size: "1Gi", 221 PvcNames: pvcNames, 222 }, 223 }, 224 }, 225 } 226 227 setPerNodeStorage(vmo) 228 dataNode := vmo.Spec.Elasticsearch.DataNode 229 assert.NotNil(t, dataNode.Storage) 230 assert.Equal(t, dataNode.Storage.Size, "1Gi") 231 assert.ElementsMatch(t, pvcNames, dataNode.Storage.PvcNames) 232 masterNode := vmo.Spec.Elasticsearch.MasterNode 233 assert.NotNil(t, masterNode.Storage) 234 assert.Equal(t, masterNode.Storage.Size, "1Gi") 235 } 236 237 func TestResizePVC(t *testing.T) { 238 allowVolumeExpansion := true 239 disableVolumeExpansion := false 240 pvcName := "pvc" 241 var tests = []struct { 242 name string 243 storageClass *storagev1.StorageClass 244 createdPVC bool 245 }{ 246 { 247 "should not create a new PVC when volume expansion is allowed", 248 &storagev1.StorageClass{AllowVolumeExpansion: &allowVolumeExpansion}, 249 false, 250 }, 251 { 252 "should create a new PVC when volume expansion is not allowed", 253 &storagev1.StorageClass{AllowVolumeExpansion: &disableVolumeExpansion}, 254 true, 255 }, 256 } 257 258 for _, tt := range tests { 259 t.Run(tt.name, func(t *testing.T) { 260 existingPVC := makePVC(pvcName, "1Gi") 261 expectedPVC := makePVC(pvcName, "2Gi") 262 c := &Controller{ 263 kubeclientset: fake.NewSimpleClientset(existingPVC), 264 } 265 newName, err := resizePVC(c, &testvmo, existingPVC, expectedPVC, tt.storageClass) 266 assert.NoError(t, err) 267 if tt.createdPVC { 268 assert.NotNil(t, newName) 269 assert.NotEqual(t, *newName, pvcName) 270 } 271 }) 272 } 273 }