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  }