Use string.Builder to concatenate string in loop.

* Fix TestFindVolumeRestoresForPodLegacy error.
* Stablize the TestExecute case in pvc_action_test.go
* Use toolchain to set the specific version for go.

Signed-off-by: Xun Jiang <xun.jiang@broadcom.com>
This commit is contained in:
Xun Jiang
2026-05-11 15:33:34 +08:00
parent 5de7f612c6
commit ce360b4033
6 changed files with 48 additions and 29 deletions
+3 -1
View File
@@ -1,6 +1,8 @@
module github.com/vmware-tanzu/velero
go 1.25.9
go 1.25.0
toolchain go1.25.10
require (
cloud.google.com/go/storage v1.57.2
+25 -12
View File
@@ -227,33 +227,42 @@ func TestExecute(t *testing.T) {
pvcMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&tc.pvc)
require.NoError(t, err)
var reconcileErrCh chan error
if tc.pvc != nil && !tc.failVSCreate && !tc.skipVSReadyUpdate {
reconcileErrCh = make(chan error, 1)
go func() {
var vsList snapshotv1api.VolumeSnapshotList
err := wait.PollUntilContextTimeout(t.Context(), 1*time.Second, 10*time.Second, true, func(ctx context.Context) (bool, error) {
err = pvcBIA.crClient.List(ctx, &vsList, &crclient.ListOptions{Namespace: tc.pvc.Namespace})
require.NoError(t, err)
if err != nil || len(vsList.Items) == 0 {
err := wait.PollUntilContextTimeout(t.Context(), 100*time.Millisecond, 10*time.Second, true, func(ctx context.Context) (bool, error) {
if err := pvcBIA.crClient.List(ctx, &vsList, &crclient.ListOptions{Namespace: tc.pvc.Namespace}); err != nil {
return false, err
}
if len(vsList.Items) == 0 {
return false, nil
}
return true, nil
})
if err != nil {
reconcileErrCh <- err
return
}
require.NoError(t, err)
vscName := "testVSC"
handleName := "testHandle"
vsc := builder.ForVolumeSnapshotContent(vscName).Status(&snapshotv1api.VolumeSnapshotContentStatus{SnapshotHandle: &handleName}).Result()
err = pvcBIA.crClient.Create(t.Context(), vsc)
if err != nil {
reconcileErrCh <- err
return
}
// Update VS status only after VSC exists to avoid racing with Execute's VSC lookup.
readyToUse := true
vsList.Items[0].Status = &snapshotv1api.VolumeSnapshotStatus{
BoundVolumeSnapshotContentName: &vscName,
ReadyToUse: &readyToUse,
}
err = pvcBIA.crClient.Update(t.Context(), &vsList.Items[0])
require.NoError(t, err)
handleName := "testHandle"
vsc := builder.ForVolumeSnapshotContent("testVSC").Status(&snapshotv1api.VolumeSnapshotContentStatus{SnapshotHandle: &handleName}).Result()
err = pvcBIA.crClient.Create(t.Context(), vsc)
require.NoError(t, err)
reconcileErrCh <- err
}()
}
@@ -274,6 +283,10 @@ func TestExecute(t *testing.T) {
require.NoError(t, err)
}
if reconcileErrCh != nil {
require.NoError(t, <-reconcileErrCh)
}
if tc.expectedDataUpload != nil {
dataUploadList := new(velerov2alpha1.DataUploadList)
err := crClient.List(t.Context(), dataUploadList, &crclient.ListOptions{LabelSelector: labels.SelectorFromSet(map[string]string{velerov1api.BackupNameLabel: tc.backup.Name})})
@@ -35,18 +35,17 @@ func TestFindVolumeRestoresForPodLegacy(t *testing.T) {
scheme := runtime.NewScheme()
scheme.AddKnownTypes(velerov1api.SchemeGroupVersion, &velerov1api.PodVolumeRestore{}, &velerov1api.PodVolumeRestoreList{})
clientBuilder := fake.NewClientBuilder().WithScheme(scheme)
// no matching PVR
reconciler := &PodVolumeRestoreReconcilerLegacy{
Client: clientBuilder.Build(),
Client: fake.NewClientBuilder().WithScheme(scheme).Build(),
logger: logrus.New(),
}
requests := reconciler.findVolumeRestoresForPod(t.Context(), pod)
assert.Empty(t, requests)
// contain one matching PVR
reconciler.Client = clientBuilder.WithLists(&velerov1api.PodVolumeRestoreList{
reconciler.Client = fake.NewClientBuilder().WithScheme(scheme).WithLists(&velerov1api.PodVolumeRestoreList{
Items: []velerov1api.PodVolumeRestore{
{
ObjectMeta: metav1.ObjectMeta{
+4 -3
View File
@@ -740,17 +740,18 @@ func DiagnoseVS(vs *snapshotv1api.VolumeSnapshot, events *corev1api.EventList) s
}
}
diag := fmt.Sprintf("VS %s/%s, bind to %s, readyToUse %v, errMessage %s\n", vs.Namespace, vs.Name, vscName, readyToUse, errMessage)
var diag strings.Builder
_, _ = fmt.Fprintf(&diag, "VS %s/%s, bind to %s, readyToUse %v, errMessage %s\n", vs.Namespace, vs.Name, vscName, readyToUse, errMessage)
if events != nil {
for _, e := range events.Items {
if e.InvolvedObject.UID == vs.UID && e.Type == corev1api.EventTypeWarning {
diag += fmt.Sprintf("VS event reason %s, message %s\n", e.Reason, e.Message)
_, _ = fmt.Fprintf(&diag, "VS event reason %s, message %s\n", e.Reason, e.Message)
}
}
}
return diag
return diag.String()
}
func DiagnoseVSC(vsc *snapshotv1api.VolumeSnapshotContent) string {
+10 -7
View File
@@ -20,6 +20,7 @@ import (
"fmt"
"io"
"os"
"strings"
"time"
"github.com/pkg/errors"
@@ -183,16 +184,17 @@ func GetPodContainerTerminateMessage(pod *corev1api.Pod, container string) strin
// GetPodTerminateMessage returns the terminate message for all containers of a pod
func GetPodTerminateMessage(pod *corev1api.Pod) string {
message := ""
//message := ""
var message strings.Builder
for _, containerStatus := range pod.Status.ContainerStatuses {
if containerStatus.State.Terminated != nil {
if containerStatus.State.Terminated.Message != "" {
message += containerStatus.State.Terminated.Message + "/"
_, _ = fmt.Fprintf(&message, "%s/", containerStatus.State.Terminated.Message)
}
}
}
return message
return message.String()
}
func getPodLogReader(ctx context.Context, podGetter corev1client.CoreV1Interface, pod string, namespace string, logOptions *corev1api.PodLogOptions) (io.ReadCloser, error) {
@@ -272,21 +274,22 @@ func ToSystemAffinity(loadAffinity *LoadAffinity, volumeTopology *corev1api.Node
}
func DiagnosePod(pod *corev1api.Pod, events *corev1api.EventList) string {
diag := fmt.Sprintf("Pod %s/%s, phase %s, node name %s, message %s\n", pod.Namespace, pod.Name, pod.Status.Phase, pod.Spec.NodeName, pod.Status.Message)
var diag strings.Builder
_, _ = fmt.Fprintf(&diag, "Pod %s/%s, phase %s, node name %s, message %s\n", pod.Namespace, pod.Name, pod.Status.Phase, pod.Spec.NodeName, pod.Status.Message)
for _, condition := range pod.Status.Conditions {
diag += fmt.Sprintf("Pod condition %s, status %s, reason %s, message %s\n", condition.Type, condition.Status, condition.Reason, condition.Message)
_, _ = fmt.Fprintf(&diag, "Pod condition %s, status %s, reason %s, message %s\n", condition.Type, condition.Status, condition.Reason, condition.Message)
}
if events != nil {
for _, e := range events.Items {
if e.InvolvedObject.UID == pod.UID && e.Type == corev1api.EventTypeWarning {
diag += fmt.Sprintf("Pod event reason %s, message %s\n", e.Reason, e.Message)
_, _ = fmt.Fprintf(&diag, "Pod event reason %s, message %s\n", e.Reason, e.Message)
}
}
}
return diag
return diag.String()
}
var funcExit = os.Exit
+4 -3
View File
@@ -464,17 +464,18 @@ func GetPVCForPodVolume(vol *corev1api.Volume, pod *corev1api.Pod, crClient crcl
}
func DiagnosePVC(pvc *corev1api.PersistentVolumeClaim, events *corev1api.EventList) string {
diag := fmt.Sprintf("PVC %s/%s, phase %s, binding to %s\n", pvc.Namespace, pvc.Name, pvc.Status.Phase, pvc.Spec.VolumeName)
var diag strings.Builder
_, _ = fmt.Fprintf(&diag, "PVC %s/%s, phase %s, binding to %s\n", pvc.Namespace, pvc.Name, pvc.Status.Phase, pvc.Spec.VolumeName)
if events != nil {
for _, e := range events.Items {
if e.InvolvedObject.UID == pvc.UID && e.Type == corev1api.EventTypeWarning {
diag += fmt.Sprintf("PVC event reason %s, message %s\n", e.Reason, e.Message)
_, _ = fmt.Fprintf(&diag, "PVC event reason %s, message %s\n", e.Reason, e.Message)
}
}
}
return diag
return diag.String()
}
func DiagnosePV(pv *corev1api.PersistentVolume) string {