Add more unit test cases for cmd/util/output

Signed-off-by: Daniel Jiang <jiangd@vmware.com>
This commit is contained in:
Daniel Jiang
2023-06-27 00:37:31 +08:00
parent cd68dd369b
commit 4cea533865
11 changed files with 1123 additions and 18 deletions
+236 -5
View File
@@ -6,6 +6,10 @@ import (
"text/tabwriter"
"time"
"github.com/vmware-tanzu/velero/pkg/itemoperation"
"github.com/stretchr/testify/require"
snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/core/v1"
@@ -46,7 +50,31 @@ func TestDescribeBackupSpec(t *testing.T) {
TTL(72 * time.Hour).
CSISnapshotTimeout(10 * time.Minute).
DataMover("mover").
Result().Spec
Hooks(velerov1api.BackupHooks{
Resources: []velerov1api.BackupResourceHookSpec{
{
Name: "hook-1",
PreHooks: []velerov1api.BackupResourceHook{
{
Exec: &velerov1api.ExecHook{
Container: "hook-container-1",
Command: []string{"pre"},
OnError: velerov1api.HookErrorModeContinue,
},
},
},
PostHooks: []velerov1api.BackupResourceHook{
{
Exec: &velerov1api.ExecHook{
Container: "hook-container-1",
Command: []string{"post"},
OnError: velerov1api.HookErrorModeContinue,
},
},
},
},
},
}).Result().Spec
expect1 := `Namespaces:
Included: inc-ns-1, inc-ns-2
@@ -70,7 +98,30 @@ TTL: 72h0m0s
CSISnapshotTimeout: 10m0s
ItemOperationTimeout: 0s
Hooks: <none>
Hooks:
Resources:
hook-1:
Namespaces:
Included: inc-ns-1, inc-ns-2
Excluded: exc-ns-1, exc-ns-2
Resources:
Included: inc-res-1, inc-res-2
Excluded: exc-res-1, exc-res-2
Label selector: <none>
Pre Exec Hook:
Container: hook-container-1
Command: pre
On Error: Continue
Timeout: 0s
Post Exec Hook:
Container: hook-container-1
Command: post
On Error: Continue
Timeout: 0s
`
input2 := builder.ForBackup("test-ns", "test-backup-2").
@@ -112,13 +163,94 @@ ItemOperationTimeout: 0s
Hooks: <none>
`
input3 := builder.ForBackup("test-ns", "test-backup-3").
StorageLocation("backup-location").
OrderedResources(map[string]string{
"kind1": "rs1-1, rs1-2",
}).Hooks(velerov1api.BackupHooks{
Resources: []velerov1api.BackupResourceHookSpec{
{
Name: "hook-1",
PreHooks: []velerov1api.BackupResourceHook{
{
Exec: &velerov1api.ExecHook{
Container: "hook-container-1",
Command: []string{"pre"},
OnError: velerov1api.HookErrorModeContinue,
},
},
},
PostHooks: []velerov1api.BackupResourceHook{
{
Exec: &velerov1api.ExecHook{
Container: "hook-container-1",
Command: []string{"post"},
OnError: velerov1api.HookErrorModeContinue,
},
},
},
},
},
}).Result().Spec
expect3 := `Namespaces:
Included: *
Excluded: <none>
Resources:
Included: *
Excluded: <none>
Cluster-scoped: auto
Label selector: <none>
Storage Location: backup-location
Velero-Native Snapshot PVs: auto
Snapshot Move Data: auto
Data Mover: <none>
TTL: 0s
CSISnapshotTimeout: 0s
ItemOperationTimeout: 0s
Hooks:
Resources:
hook-1:
Namespaces:
Included: *
Excluded: <none>
Resources:
Included: *
Excluded: <none>
Label selector: <none>
Pre Exec Hook:
Container: hook-container-1
Command: pre
On Error: Continue
Timeout: 0s
Post Exec Hook:
Container: hook-container-1
Command: post
On Error: Continue
Timeout: 0s
OrderedResources:
kind1: rs1-1, rs1-2
`
testcases := []struct {
name string
input velerov1api.BackupSpec
expect string
}{
{
name: "old resource filter",
name: "old resource filter with hooks",
input: input1,
expect: expect1,
},
@@ -127,6 +259,11 @@ Hooks: <none>
input: input2,
expect: expect2,
},
{
name: "old resource filter with hooks and ordered resources",
input: input3,
expect: expect3,
},
}
for _, tc := range testcases {
@@ -164,7 +301,6 @@ func TestDescribeSnapshot(t *testing.T) {
func TestDescribePodVolumeBackups(t *testing.T) {
pvb1 := builder.ForPodVolumeBackup("test-ns", "test-pvb1").
BackupStorageLocation("backup-location").
UploaderType("kopia").
Phase(velerov1api.PodVolumeBackupPhaseCompleted).
BackupStorageLocation("bsl-1").
@@ -173,7 +309,6 @@ func TestDescribePodVolumeBackups(t *testing.T) {
PodNamespace("pod-ns-1").
SnapshotID("snap-1").Result()
pvb2 := builder.ForPodVolumeBackup("test-ns1", "test-pvb2").
BackupStorageLocation("backup-location").
UploaderType("kopia").
Phase(velerov1api.PodVolumeBackupPhaseCompleted).
BackupStorageLocation("bsl-1").
@@ -289,3 +424,99 @@ Snapshot Content Name: vsc-1
})
}
}
func TestDescribeDeleteBackupRequests(t *testing.T) {
t1, err1 := time.Parse("2006-Jan-02", "2023-Jun-26")
require.Nil(t, err1)
dbr1 := builder.ForDeleteBackupRequest("velero", "dbr1").
ObjectMeta(builder.WithCreationTimestamp(t1)).
BackupName("bak-1").
Phase(velerov1api.DeleteBackupRequestPhaseProcessed).
Errors("some error").Result()
t2, err2 := time.Parse("2006-Jan-02", "2023-Jun-25")
require.Nil(t, err2)
dbr2 := builder.ForDeleteBackupRequest("velero", "dbr2").
ObjectMeta(builder.WithCreationTimestamp(t2)).
BackupName("bak-2").
Phase(velerov1api.DeleteBackupRequestPhaseInProgress).Result()
testcases := []struct {
name string
input []velerov1api.DeleteBackupRequest
expect string
}{
{
name: "empty list",
input: []velerov1api.DeleteBackupRequest{},
expect: `Deletion Attempts:
`,
},
{
name: "list with one failed and one in-progress request",
input: []velerov1api.DeleteBackupRequest{*dbr1, *dbr2},
expect: `Deletion Attempts (1 failed):
2023-06-26 00:00:00 +0000 UTC: Processed
Errors:
some error
2023-06-25 00:00:00 +0000 UTC: InProgress
`,
},
}
for _, tc := range testcases {
t.Run(tc.name, func(tt *testing.T) {
d := &Describer{
Prefix: "",
out: &tabwriter.Writer{},
buf: &bytes.Buffer{},
}
d.out.Init(d.buf, 0, 8, 2, ' ', 0)
DescribeDeleteBackupRequests(d, tc.input)
d.out.Flush()
assert.Equal(tt, tc.expect, d.buf.String())
})
}
}
func TestDescribeBackupItemOperation(t *testing.T) {
t1, err1 := time.Parse("2006-Jan-02", "2023-Jun-26")
require.Nil(t, err1)
t2, err2 := time.Parse("2006-Jan-02", "2023-Jun-25")
require.Nil(t, err2)
t3, err3 := time.Parse("2006-Jan-02", "2023-Jun-24")
require.Nil(t, err3)
input := builder.ForBackupOperation().
BackupName("backup-1").
OperationID("op-1").
BackupItemAction("action-1").
ResourceIdentifier("group", "rs-type", "ns", "rs-name").
Status(*builder.ForOperationStatus().
Phase(itemoperation.OperationPhaseFailed).
Error("operation error").
Progress(50, 100, "bytes").
Description("operation description").
Created(t3).
Started(t2).
Updated(t1).
Result()).Result()
expected := ` Operation for rs-type.group ns/rs-name:
Backup Item Action Plugin: action-1
Operation ID: op-1
Phase: Failed
Operation Error: operation error
Progress: 50 of 100 complete (bytes)
Progress description: operation description
Created: 2023-06-24 00:00:00 +0000 UTC
Started: 2023-06-25 00:00:00 +0000 UTC
Updated: 2023-06-26 00:00:00 +0000 UTC
`
d := &Describer{
Prefix: "",
out: &tabwriter.Writer{},
buf: &bytes.Buffer{},
}
d.out.Init(d.buf, 0, 8, 2, ' ', 0)
describeBackupItemOperation(d, input)
d.out.Flush()
assert.Equal(t, expected, d.buf.String())
}
@@ -5,6 +5,8 @@ import (
"testing"
"time"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
"github.com/vmware-tanzu/velero/pkg/features"
@@ -31,7 +33,32 @@ func TestDescribeBackupInSF(t *testing.T) {
StorageLocation("backup-location").
TTL(72 * time.Hour).
CSISnapshotTimeout(10 * time.Minute).
DataMover("mover")
DataMover("mover").
Hooks(velerov1api.BackupHooks{
Resources: []velerov1api.BackupResourceHookSpec{
{
Name: "hook-1",
PreHooks: []velerov1api.BackupResourceHook{
{
Exec: &velerov1api.ExecHook{
Container: "hook-container-1",
Command: []string{"pre"},
OnError: velerov1api.HookErrorModeContinue,
},
},
},
PostHooks: []velerov1api.BackupResourceHook{
{
Exec: &velerov1api.ExecHook{
Container: "hook-container-1",
Command: []string{"post"},
OnError: velerov1api.HookErrorModeContinue,
},
},
},
},
},
})
expect1 := map[string]interface{}{
"spec": map[string]interface{}{
@@ -51,13 +78,73 @@ func TestDescribeBackupInSF(t *testing.T) {
"TTL": "72h0m0s",
"CSISnapshotTimeout": "10m0s",
"veleroSnapshotMoveData": "auto",
"hooks": map[string]interface{}{
"resources": map[string]interface{}{
"hook-1": map[string]interface{}{
"labelSelector": emptyDisplay,
"namespaces": map[string]string{
"included": "inc-ns-1, inc-ns-2",
"excluded": "exc-ns-1, exc-ns-2",
},
"preExecHook": []map[string]interface{}{
{
"container": "hook-container-1",
"command": "pre",
"onError:": velerov1api.HookErrorModeContinue,
"timeout": "0s",
},
},
"postExecHook": []map[string]interface{}{
{
"container": "hook-container-1",
"command": "post",
"onError:": velerov1api.HookErrorModeContinue,
"timeout": "0s",
},
},
"resources": map[string]string{
"included": "inc-res-1, inc-res-2",
"excluded": "exc-res-1, exc-res-2",
},
},
},
},
},
}
DescribeBackupSpecInSF(sd, backupBuilder1.Result().Spec)
assert.True(t, reflect.DeepEqual(sd.output, expect1))
backupBuilder2 := builder.ForBackup("test-ns-2", "test-backup-2")
backupBuilder2.StorageLocation("backup-location")
backupBuilder2 := builder.ForBackup("test-ns-2", "test-backup-2").
StorageLocation("backup-location").
OrderedResources(map[string]string{
"kind1": "rs1-1, rs1-2",
"kind2": "rs2-1, rs2-2",
}).Hooks(velerov1api.BackupHooks{
Resources: []velerov1api.BackupResourceHookSpec{
{
Name: "hook-1",
PreHooks: []velerov1api.BackupResourceHook{
{
Exec: &velerov1api.ExecHook{
Container: "hook-container-1",
Command: []string{"pre"},
OnError: velerov1api.HookErrorModeContinue,
},
},
},
PostHooks: []velerov1api.BackupResourceHook{
{
Exec: &velerov1api.ExecHook{
Container: "hook-container-1",
Command: []string{"post"},
OnError: velerov1api.HookErrorModeContinue,
},
},
},
},
},
})
expect2 := map[string]interface{}{
"spec": map[string]interface{}{
"namespaces": map[string]interface{}{
@@ -76,6 +163,41 @@ func TestDescribeBackupInSF(t *testing.T) {
"TTL": "0s",
"CSISnapshotTimeout": "0s",
"veleroSnapshotMoveData": "auto",
"hooks": map[string]interface{}{
"resources": map[string]interface{}{
"hook-1": map[string]interface{}{
"labelSelector": emptyDisplay,
"namespaces": map[string]string{
"included": "*",
"excluded": emptyDisplay,
},
"preExecHook": []map[string]interface{}{
{
"container": "hook-container-1",
"command": "pre",
"onError:": velerov1api.HookErrorModeContinue,
"timeout": "0s",
},
},
"postExecHook": []map[string]interface{}{
{
"container": "hook-container-1",
"command": "post",
"onError:": velerov1api.HookErrorModeContinue,
"timeout": "0s",
},
},
"resources": map[string]string{
"included": "*",
"excluded": emptyDisplay,
},
},
},
},
"orderedResources": map[string]string{
"kind1": "rs1-1, rs1-2",
"kind2": "rs2-1, rs2-2",
},
},
}
DescribeBackupSpecInSF(sd, backupBuilder2.Result().Spec)
@@ -250,3 +372,83 @@ func TestDescribeBackupResultInSF(t *testing.T) {
describeResultInSF(got, input)
assert.True(t, reflect.DeepEqual(got, expect))
}
func TestDescribeDeleteBackupRequestsInSF(t *testing.T) {
t1, err1 := time.Parse("2006-Jan-02", "2023-Jun-26")
require.Nil(t, err1)
dbr1 := builder.ForDeleteBackupRequest("velero", "dbr1").
ObjectMeta(builder.WithCreationTimestamp(t1)).
BackupName("bak-1").
Phase(velerov1api.DeleteBackupRequestPhaseProcessed).
Errors("some error").Result()
t2, err2 := time.Parse("2006-Jan-02", "2023-Jun-25")
require.Nil(t, err2)
dbr2 := builder.ForDeleteBackupRequest("velero", "dbr2").
ObjectMeta(builder.WithCreationTimestamp(t2)).
BackupName("bak-2").
Phase(velerov1api.DeleteBackupRequestPhaseInProgress).Result()
testcases := []struct {
name string
input []velerov1api.DeleteBackupRequest
expect map[string]interface{}
}{
{
name: "empty list",
input: []velerov1api.DeleteBackupRequest{},
expect: map[string]interface{}{
"deletionAttempts": map[string]interface{}{
"deleteBackupRequests": []map[string]interface{}{},
},
},
},
{
name: "list with one failed and one in-progress request",
input: []velerov1api.DeleteBackupRequest{*dbr1, *dbr2},
expect: map[string]interface{}{
"deletionAttempts": map[string]interface{}{
"failed": int(1),
"deleteBackupRequests": []map[string]interface{}{
{
"creationTimestamp": t1.String(),
"phase": velerov1api.DeleteBackupRequestPhaseProcessed,
"errors": []string{
"some error",
},
},
{
"creationTimestamp": t2.String(),
"phase": velerov1api.DeleteBackupRequestPhaseInProgress,
},
},
},
},
},
}
for _, tc := range testcases {
t.Run(tc.name, func(tt *testing.T) {
sd := &StructuredDescriber{
output: make(map[string]interface{}),
format: "",
}
DescribeDeleteBackupRequestsInSF(sd, tc.input)
assert.True(tt, reflect.DeepEqual(sd.output, tc.expect))
})
}
}
func TestDescribeSnapshotInSF(t *testing.T) {
res := map[string]interface{}{}
iops := int64(100)
describeSnapshotInSF("pv-1", "snapshot-1", "ebs", "us-east-2", &iops, res)
expect := map[string]interface{}{
"pv-1": map[string]string{
"snapshotID": "snapshot-1",
"type": "ebs",
"availabilityZone": "us-east-2",
"IOPS": "100",
},
}
assert.True(t, reflect.DeepEqual(expect, res))
}
-9
View File
@@ -47,15 +47,6 @@ func Describe(fn func(d *Describer)) string {
return d.buf.String()
}
func NewDescriber(minwidth, tabwidth, padding int, padchar byte, flags uint) *Describer {
d := &Describer{
out: new(tabwriter.Writer),
buf: new(bytes.Buffer),
}
d.out.Init(d.buf, minwidth, tabwidth, padding, padchar, flags)
return d
}
func (d *Describer) Printf(msg string, args ...interface{}) {
fmt.Fprint(d.out, d.Prefix)
fmt.Fprintf(d.out, msg, args...)
+34
View File
@@ -3,6 +3,7 @@ package output
import (
"bytes"
"fmt"
"reflect"
"testing"
"text/tabwriter"
@@ -132,3 +133,36 @@ func TestStructuredDescriber_JSONEncode(t *testing.T) {
})
}
}
func TestStructuredDescriber_DescribeMetadata(t *testing.T) {
d := NewStructuredDescriber("")
input := metav1.ObjectMeta{
Name: "test",
Namespace: "test-ns",
Labels: map[string]string{
"label-1": "v1",
"label-2": "v2",
},
Annotations: map[string]string{
"annotation-1": "v1",
"annotation-2": "v2",
},
}
expect := map[string]interface{}{
"metadata": map[string]interface{}{
"name": "test",
"namespace": "test-ns",
"labels": map[string]string{
"label-1": "v1",
"label-2": "v2",
},
"annotations": map[string]string{
"annotation-1": "v1",
"annotation-2": "v2",
},
},
}
d.DescribeMetadata(input)
assert.True(t, reflect.DeepEqual(expect, d.output))
}
@@ -0,0 +1,183 @@
package output
import (
"bytes"
"testing"
"text/tabwriter"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/builder"
"github.com/vmware-tanzu/velero/pkg/itemoperation"
"github.com/vmware-tanzu/velero/pkg/util/results"
)
func TestDescribeResult(t *testing.T) {
testcases := []struct {
name string
inputName string
inputResult results.Result
expect string
}{
{
name: "result without ns warns",
inputName: "restore-1",
inputResult: results.Result{
Velero: []string{"velero-msg-1", "velero-msg-2"},
Cluster: []string{"cluster-msg-1", "cluster-msg-2"},
Namespaces: map[string][]string{},
},
expect: `restore-1:
Velero: velero-msg-1
velero-msg-2
Cluster: cluster-msg-1
cluster-msg-2
Namespaces: <none>
`,
},
{
name: "result with ns warns",
inputName: "restore-2",
inputResult: results.Result{
Velero: []string{"velero-msg-1", "velero-msg-2"},
Cluster: []string{"cluster-msg-1", "cluster-msg-2"},
Namespaces: map[string][]string{
"ns-1": {"ns-1-warn-1", "ns-1-warn-2"},
},
},
expect: `restore-2:
Velero: velero-msg-1
velero-msg-2
Cluster: cluster-msg-1
cluster-msg-2
Namespaces:
ns-1: ns-1-warn-1
ns-1-warn-2
`,
},
}
for _, tc := range testcases {
t.Run(tc.name, func(tt *testing.T) {
d := &Describer{
Prefix: "",
out: &tabwriter.Writer{},
buf: &bytes.Buffer{},
}
d.out.Init(d.buf, 0, 8, 2, ' ', 0)
describeResult(d, tc.inputName, tc.inputResult)
d.out.Flush()
assert.Equal(tt, tc.expect, d.buf.String())
})
}
}
func TestDescribeRestoreItemOperation(t *testing.T) {
t1, err1 := time.Parse("2006-Jan-02", "2023-Jun-26")
require.Nil(t, err1)
t2, err2 := time.Parse("2006-Jan-02", "2023-Jun-25")
require.Nil(t, err2)
t3, err3 := time.Parse("2006-Jan-02", "2023-Jun-24")
require.Nil(t, err3)
input := builder.ForRestoreOperation().
RestoreName("restore-1").
OperationID("op-1").
RestoreItemAction("action-1").
ResourceIdentifier("group", "rs-type", "ns", "rs-name").
Status(*builder.ForOperationStatus().
Phase(itemoperation.OperationPhaseFailed).
Error("operation error").
Progress(50, 100, "bytes").
Description("operation description").
Created(t3).
Started(t2).
Updated(t1).
Result()).Result()
expected := ` Operation for rs-type.group ns/rs-name:
Restore Item Action Plugin: action-1
Operation ID: op-1
Phase: Failed
Operation Error: operation error
Progress: 50 of 100 complete (bytes)
Progress description: operation description
Created: 2023-06-24 00:00:00 +0000 UTC
Started: 2023-06-25 00:00:00 +0000 UTC
Updated: 2023-06-26 00:00:00 +0000 UTC
`
d := &Describer{
Prefix: "",
out: &tabwriter.Writer{},
buf: &bytes.Buffer{},
}
d.out.Init(d.buf, 0, 8, 2, ' ', 0)
describeRestoreItemOperation(d, input)
d.out.Flush()
assert.Equal(t, expected, d.buf.String())
}
func TestDescribePodVolumeRestores(t *testing.T) {
pvr1 := builder.ForPodVolumeRestore("velero", "pvr-1").
UploaderType("kopia").
Phase(velerov1api.PodVolumeRestorePhaseCompleted).
BackupStorageLocation("bsl-1").
Volume("vol-1").
PodName("pod-1").
PodNamespace("pod-ns-1").
SnapshotID("snap-1").Result()
pvr2 := builder.ForPodVolumeRestore("velero", "pvr-2").
UploaderType("kopia").
Phase(velerov1api.PodVolumeRestorePhaseCompleted).
BackupStorageLocation("bsl-1").
Volume("vol-2").
PodName("pod-2").
PodNamespace("pod-ns-1").
SnapshotID("snap-2").Result()
testcases := []struct {
name string
inputPVRList []velerov1api.PodVolumeRestore
inputDetails bool
expect string
}{
{
name: "empty list",
inputPVRList: []velerov1api.PodVolumeRestore{},
inputDetails: true,
expect: ``,
},
{
name: "2 completed pvrs no details",
inputPVRList: []velerov1api.PodVolumeRestore{*pvr1, *pvr2},
inputDetails: false,
expect: `kopia Restores (specify --details for more information):
Completed: 2
`,
},
{
name: "2 completed pvrs with details",
inputPVRList: []velerov1api.PodVolumeRestore{*pvr1, *pvr2},
inputDetails: true,
expect: `kopia Restores:
Completed:
pod-ns-1/pod-1: vol-1
pod-ns-1/pod-2: vol-2
`,
},
}
for _, tc := range testcases {
t.Run(tc.name, func(tt *testing.T) {
d := &Describer{
Prefix: "",
out: &tabwriter.Writer{},
buf: &bytes.Buffer{},
}
d.out.Init(d.buf, 0, 8, 2, ' ', 0)
describePodVolumeRestores(d, tc.inputPVRList, tc.inputDetails)
d.out.Flush()
assert.Equal(tt, tc.expect, d.buf.String())
})
}
}
@@ -0,0 +1,123 @@
package output
import (
"testing"
"github.com/stretchr/testify/assert"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/builder"
)
func TestDescribeSchedule(t *testing.T) {
input1 := builder.ForSchedule("velero", "schedule-1").
Phase(velerov1api.SchedulePhaseFailedValidation).
ValidationError("validation failed").Result()
expect1 := `Name: schedule-1
Namespace: velero
Labels: <none>
Annotations: <none>
Phase: FailedValidation
Validation errors: validation failed
Paused: false
Schedule:
Backup Template:
Namespaces:
Included: *
Excluded: <none>
Resources:
Included: *
Excluded: <none>
Cluster-scoped: auto
Label selector: <none>
Storage Location:
Velero-Native Snapshot PVs: auto
Snapshot Move Data: auto
Data Mover: <none>
TTL: 0s
CSISnapshotTimeout: 0s
ItemOperationTimeout: 0s
Hooks: <none>
Last Backup: <never>
`
input2 := builder.ForSchedule("velero", "schedule-2").
Phase(velerov1api.SchedulePhaseEnabled).
CronSchedule("0 0 * * *").
Template(builder.ForBackup("velero", "backup-1").Result().Spec).
LastBackupTime("2023-06-25 15:04:05").Result()
expect2 := `Name: schedule-2
Namespace: velero
Labels: <none>
Annotations: <none>
Phase: Enabled
Paused: false
Schedule: 0 0 * * *
Backup Template:
Namespaces:
Included: *
Excluded: <none>
Resources:
Included: *
Excluded: <none>
Cluster-scoped: auto
Label selector: <none>
Storage Location:
Velero-Native Snapshot PVs: auto
Snapshot Move Data: auto
Data Mover: <none>
TTL: 0s
CSISnapshotTimeout: 0s
ItemOperationTimeout: 0s
Hooks: <none>
Last Backup: 2023-06-25 15:04:05 +0000 UTC
`
testcases := []struct {
name string
input *velerov1api.Schedule
expect string
}{
{
name: "schedule failed in validation",
input: input1,
expect: expect1,
},
{
name: "schedule enabled",
input: input2,
expect: expect2,
},
}
for _, tc := range testcases {
t.Run(tc.name, func(tt *testing.T) {
assert.Equal(tt, tc.expect, DescribeSchedule(tc.input))
})
}
}