Copilot commented on code in PR #712:
URL: https://github.com/apache/solr-operator/pull/712#discussion_r3010598439


##########
controllers/solrcloud_controller.go:
##########
@@ -1018,6 +1027,46 @@ func (r *SolrCloudReconciler) reconcileZk(ctx 
context.Context, logger logr.Logge
        return nil
 }
 
+func (r *SolrCloudReconciler) expandPVCs(ctx context.Context, cloud 
*solrv1beta1.SolrCloud, pvcLabelSelector map[string]string, newSize 
resource.Quantity, logger logr.Logger) (expansionComplete bool, err error) {
+       var pvcList corev1.PersistentVolumeClaimList
+       pvcList, err = r.getPVCList(ctx, cloud, pvcLabelSelector)
+       if err != nil {
+               return
+       }
+       expansionCompleteCount := 0
+       for _, pvcItem := range pvcList.Items {
+               if pvcExpansionComplete, e := r.expandPVC(ctx, &pvcItem, 
newSize, logger); e != nil {
+                       err = e
+               } else if pvcExpansionComplete {
+                       expansionCompleteCount += 1
+               }
+       }
+       // If all PVCs have been expanded, then we are done
+       expansionComplete = err == nil && expansionCompleteCount == 
len(pvcList.Items)
+       return
+}
+
+func (r *SolrCloudReconciler) expandPVC(ctx context.Context, pvc 
*corev1.PersistentVolumeClaim, newSize resource.Quantity, logger logr.Logger) 
(expansionComplete bool, err error) {
+       // If the current capacity is >= the new size, then there is nothing to 
do, expansion is complete
+       if pvc.Status.Capacity.Storage().Cmp(newSize) >= 0 {
+               // TODO: Eventually use the pvc.Status.AllocatedResources and 
pvc.Status.AllocatedResourceStatuses to determine the status of PVC Expansion 
and react to failures
+               expansionComplete = true
+       } else if !pvc.Spec.Resources.Requests.Storage().Equal(newSize) {
+               // Update the pvc if the capacity request is different.
+               // The newSize might be smaller than the current size, but this 
is supported as the last size might have been too
+               // big for the storage quota, so it was lowered.
+               // As long as the PVCs current capacity is lower than the new 
size, we are still good to update the PVC.
+               originalPvc := pvc.DeepCopy()
+               pvc.Spec.Resources.Requests[corev1.ResourceStorage] = newSize
+               if err = r.Patch(ctx, pvc, 
client.StrategicMergeFrom(originalPvc)); err != nil {
+                       logger.Error(err, "Error while expanding 
PersistentVolumeClaim size", "persistentVolumeClaim", pvc.Name, "size", newSize)
+               } else {
+                       logger.Info("Expanded PersistentVolumeClaim size", 
"persistentVolumeClaim", pvc.Name, "size", newSize)

Review Comment:
   expandPVC assumes pvc.Status.Capacity.Storage() and 
pvc.Spec.Resources.Requests.Storage() are non-nil. For Pending/unbound PVCs (or 
unusual provisioners), these can be nil, leading to a nil dereference when 
calling Cmp/Equal. Guard against nil (treat missing capacity as 0, and handle 
missing requests) before comparing quantities.
   ```suggestion
        // If the current capacity is >= the new size, then there is nothing to 
do, expansion is complete.
        // Treat missing capacity as zero.
        capacityQty, hasCapacity := pvc.Status.Capacity[corev1.ResourceStorage]
        if !hasCapacity {
                capacityQty = resource.Quantity{}
        }
        if capacityQty.Cmp(newSize) >= 0 {
                // TODO: Eventually use the pvc.Status.AllocatedResources and 
pvc.Status.AllocatedResourceStatuses to determine the status of PVC Expansion 
and react to failures
                expansionComplete = true
        } else {
                // Determine if the current request already matches the desired 
size.
                requestQty, hasRequest := 
pvc.Spec.Resources.Requests[corev1.ResourceStorage]
                sameRequest := hasRequest && requestQty.Equal(newSize)
                if !sameRequest {
                        // Update the pvc if the capacity request is different.
                        // The newSize might be smaller than the current size, 
but this is supported as the last size might have been too
                        // big for the storage quota, so it was lowered.
                        // As long as the PVCs current capacity is lower than 
the new size, we are still good to update the PVC.
                        originalPvc := pvc.DeepCopy()
                        if pvc.Spec.Resources.Requests == nil {
                                pvc.Spec.Resources.Requests = 
corev1.ResourceList{}
                        }
                        pvc.Spec.Resources.Requests[corev1.ResourceStorage] = 
newSize
                        if err = r.Patch(ctx, pvc, 
client.StrategicMergeFrom(originalPvc)); err != nil {
                                logger.Error(err, "Error while expanding 
PersistentVolumeClaim size", "persistentVolumeClaim", pvc.Name, "size", newSize)
                        } else {
                                logger.Info("Expanded PersistentVolumeClaim 
size", "persistentVolumeClaim", pvc.Name, "size", newSize)
                        }
   ```



##########
controllers/solrcloud_controller.go:
##########
@@ -560,6 +563,12 @@ func (r *SolrCloudReconciler) Reconcile(ctx 
context.Context, req ctrl.Request) (
                                clusterOpQueue[queueIdx] = *clusterOp
                                clusterOp = nil
                        }
+                       clusterOp, retryLaterDuration, err = 
determinePvcExpansionClusterOpLockIfNecessary(instance, statefulSet)
+                       // If the new clusterOperation is an update to a queued 
clusterOp, just change the operation that is already queued
+                       if queueIdx, opIsQueued := queuedRetryOps[UpdateLock]; 
clusterOp != nil && opIsQueued {

Review Comment:
   This queued-op replacement check uses queuedRetryOps[UpdateLock] even though 
the new operation being considered is a PVC expansion. This can incorrectly 
overwrite a queued RollingUpdate op (or fail to update an already-queued 
PVCExpansion op). Use queuedRetryOps[PvcExpansionLock] here instead of 
UpdateLock.
   ```suggestion
                        // If the new clusterOperation is an update to a queued 
PVC expansion clusterOp, just change the operation that is already queued
                        if queueIdx, opIsQueued := 
queuedRetryOps[PvcExpansionLock]; clusterOp != nil && opIsQueued {
   ```



##########
tests/e2e/suite_test.go:
##########
@@ -489,22 +530,18 @@ func writePodLogsToFile(ctx context.Context, filename 
string, podName string, po
        Expect(logsErr).ToNot(HaveOccurred(), "Could not open stream to fetch 
pod logs. namespace: %s, pod: %s", podNamespace, podName)
        defer podLogs.Close()
 
-       var logReader io.Reader
-       logReader = podLogs
-
        if filterLinesWithString != "" {
-               filteredWriter := bytes.NewBufferString("")
                scanner := bufio.NewScanner(podLogs)
                for scanner.Scan() {
                        line := scanner.Text()
                        if strings.Contains(line, filterLinesWithString) {
-                               io.WriteString(filteredWriter, line)
-                               io.WriteString(filteredWriter, "\n")
+                               io.WriteString(logFile, line)
+                               io.WriteString(logFile, "\n")
                        }
                }
-               logReader = filteredWriter
+       } else {
+               _, err = io.Copy(logFile, podLogs)
        }
 
-       _, err = io.Copy(logFile, logReader)
        Expect(err).ToNot(HaveOccurred(), "Could not write podLogs to file: 
%s", filename)
 }

Review Comment:
   When filterLinesWithString != "", the function never assigns to err and does 
not check scanner.Err() / io.WriteString errors. As a result, read/write 
failures (including bufio.Scanner token-too-long) can be silently ignored and 
the final Expect(err) will still pass. Capture and assert scanner.Err(), and 
propagate write errors so the test output reflects failures.



##########
docs/solr-cloud/solr-cloud-crd.md:
##########
@@ -61,8 +61,9 @@ These options can be found in `SolrCloud.spec.dataStorage`
   - **`pvcTemplate`** - The template of the PVC to use for the solr data PVCs. 
By default the name will be "data".
     Only the `pvcTemplate.spec` field is required, metadata is optional.
     
-    Note: This template cannot be changed unless the SolrCloud is deleted and 
recreated.
-    This is a [limitation of StatefulSets and PVCs in 
Kubernetes](https://github.com/kubernetes/enhancements/issues/661).
+    Note: Currently, [Kubernetes does not support PVC resizing (expanding) in 
StatefulSets](https://github.com/kubernetes/enhancements/issues/661).
+    However, The Solr Operator will manage the PVC expansion for users until 
this is supported by default in Kubernetes.

Review Comment:
   Grammar/capitalization: "However, The Solr Operator" should be "However, the 
Solr Operator".
   ```suggestion
       However, the Solr Operator will manage the PVC expansion for users until 
this is supported by default in Kubernetes.
   ```



##########
tests/e2e/suite_test.go:
##########
@@ -408,6 +423,32 @@ func writeAllStatefulSetInfoToFiles(baseFilename string, 
statefulSet *appsv1.Sta
        Expect(writeErr).ToNot(HaveOccurred(), "Could not write statefulSet 
events json to file")
 }
 
+// writeAllPvcInfoToFiles writes the following each to a separate file with 
the given base name & directory.
+//   - PVC Spec/Status
+//   - PVC Events
+func writeAllPvcInfoToFiles(baseFilename string, pvc 
*corev1.PersistentVolumeClaim) {
+       // Write PVC to a file
+       statusFile, err := os.Create(baseFilename + ".status.json")
+       defer statusFile.Close()
+       Expect(err).ToNot(HaveOccurred(), "Could not open file to save PVC 
status: %s", baseFilename+".status.json")

Review Comment:
   In writeAllPvcInfoToFiles, statusFile/eventsFile are deferred closed before 
checking the os.Create error. If Create fails, the deferred Close will panic on 
a nil file handle. Move the defer until after verifying err == nil (and 
consider handling Close errors consistently).



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to