Skip to content

Commit

Permalink
Add Unit test cases for pkg/cmd/util/output (#6359)
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Jiang <[email protected]>
  • Loading branch information
reasonerjt authored Jun 26, 2023
1 parent 433daa1 commit cd68dd3
Show file tree
Hide file tree
Showing 7 changed files with 1,073 additions and 9 deletions.
6 changes: 6 additions & 0 deletions pkg/builder/pod_volume_backup_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,9 @@ func (b *PodVolumeBackupBuilder) Volume(volume string) *PodVolumeBackupBuilder {
b.object.Spec.Volume = volume
return b
}

// UploaderType sets the type of uploader to use for this PodVolumeBackup.
func (b *PodVolumeBackupBuilder) UploaderType(uploaderType string) *PodVolumeBackupBuilder {
b.object.Spec.UploaderType = uploaderType
return b
}
4 changes: 2 additions & 2 deletions pkg/builder/volume_snapshot_content_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ func (v *VolumeSnapshotContentBuilder) Result() *snapshotv1api.VolumeSnapshotCon
}

// Status initiates VolumeSnapshotContent's status.
func (v *VolumeSnapshotContentBuilder) Status() *VolumeSnapshotContentBuilder {
v.object.Status = &snapshotv1api.VolumeSnapshotContentStatus{}
func (v *VolumeSnapshotContentBuilder) Status(status *snapshotv1api.VolumeSnapshotContentStatus) *VolumeSnapshotContentBuilder {
v.object.Status = status
return v
}

Expand Down
291 changes: 291 additions & 0 deletions pkg/cmd/util/output/backup_describer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,291 @@
package output

import (
"bytes"
"testing"
"text/tabwriter"
"time"

snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/core/v1"

"github.com/vmware-tanzu/velero/pkg/builder"
"github.com/vmware-tanzu/velero/pkg/features"

velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
)

func TestDescribeResourcePolicies(t *testing.T) {
input := &v1.TypedLocalObjectReference{
Kind: "configmap",
Name: "test-resource-policy",
}
d := &Describer{
Prefix: "",
out: &tabwriter.Writer{},
buf: &bytes.Buffer{},
}
d.out.Init(d.buf, 0, 8, 2, ' ', 0)
DescribeResourcePolicies(d, input)
d.out.Flush()
expect := `Resource policies:
Type: configmap
Name: test-resource-policy
`
assert.Equal(t, expect, d.buf.String())
}

func TestDescribeBackupSpec(t *testing.T) {
input1 := builder.ForBackup("test-ns", "test-backup-1").
IncludedNamespaces("inc-ns-1", "inc-ns-2").
ExcludedNamespaces("exc-ns-1", "exc-ns-2").
IncludedResources("inc-res-1", "inc-res-2").
ExcludedResources("exc-res-1", "exc-res-2").
StorageLocation("backup-location").
TTL(72 * time.Hour).
CSISnapshotTimeout(10 * time.Minute).
DataMover("mover").
Result().Spec

expect1 := `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
Cluster-scoped: auto
Label selector: <none>
Storage Location: backup-location
Velero-Native Snapshot PVs: auto
Snapshot Move Data: auto
Data Mover: mover
TTL: 72h0m0s
CSISnapshotTimeout: 10m0s
ItemOperationTimeout: 0s
Hooks: <none>
`

input2 := builder.ForBackup("test-ns", "test-backup-2").
IncludedNamespaces("inc-ns-1", "inc-ns-2").
ExcludedNamespaces("exc-ns-1", "exc-ns-2").
IncludedClusterScopedResources("inc-cluster-res-1", "inc-cluster-res-2").
IncludedNamespaceScopedResources("inc-ns-res-1", "inc-ns-res-2").
ExcludedClusterScopedResources("exc-cluster-res-1", "exc-cluster-res-2").
ExcludedNamespaceScopedResources("exc-ns-res-1", "exc-ns-res-2").
StorageLocation("backup-location").
TTL(72 * time.Hour).
CSISnapshotTimeout(10 * time.Minute).
DataMover("mover").
Result().Spec

expect2 := `Namespaces:
Included: inc-ns-1, inc-ns-2
Excluded: exc-ns-1, exc-ns-2
Resources:
Included cluster-scoped: inc-cluster-res-1, inc-cluster-res-2
Excluded cluster-scoped: exc-cluster-res-1, exc-cluster-res-2
Included namespace-scoped: inc-ns-res-1, inc-ns-res-2
Excluded namespace-scoped: exc-ns-res-1, exc-ns-res-2
Label selector: <none>
Storage Location: backup-location
Velero-Native Snapshot PVs: auto
Snapshot Move Data: auto
Data Mover: mover
TTL: 72h0m0s
CSISnapshotTimeout: 10m0s
ItemOperationTimeout: 0s
Hooks: <none>
`

testcases := []struct {
name string
input velerov1api.BackupSpec
expect string
}{
{
name: "old resource filter",
input: input1,
expect: expect1,
},
{
name: "new resource filter",
input: input2,
expect: expect2,
},
}

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)
DescribeBackupSpec(d, tc.input)
d.out.Flush()
assert.Equal(tt, tc.expect, d.buf.String())
})
}
}

func TestDescribeSnapshot(t *testing.T) {
d := &Describer{
Prefix: "",
out: &tabwriter.Writer{},
buf: &bytes.Buffer{},
}
d.out.Init(d.buf, 0, 8, 2, ' ', 0)
describeSnapshot(d, "pv-1", "snapshot-1", "ebs", "us-east-2", nil)
expect1 := ` pv-1:
Snapshot ID: snapshot-1
Type: ebs
Availability Zone: us-east-2
IOPS: <N/A>
`
d.out.Flush()
assert.Equal(t, expect1, d.buf.String())
}

func TestDescribePodVolumeBackups(t *testing.T) {
pvb1 := builder.ForPodVolumeBackup("test-ns", "test-pvb1").
BackupStorageLocation("backup-location").
UploaderType("kopia").
Phase(velerov1api.PodVolumeBackupPhaseCompleted).
BackupStorageLocation("bsl-1").
Volume("vol-1").
PodName("pod-1").
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").
Volume("vol-2").
PodName("pod-2").
PodNamespace("pod-ns-1").
SnapshotID("snap-2").Result()

testcases := []struct {
name string
inputPVBList []velerov1api.PodVolumeBackup
inputDetails bool
expect string
}{
{
name: "empty list",
inputPVBList: []velerov1api.PodVolumeBackup{},
inputDetails: true,
expect: ``,
},
{
name: "2 completed pvbs no details",
inputPVBList: []velerov1api.PodVolumeBackup{*pvb1, *pvb2},
inputDetails: false,
expect: `kopia Backups (specify --details for more information):
Completed: 2
`,
},
{
name: "2 completed pvbs with details",
inputPVBList: []velerov1api.PodVolumeBackup{*pvb1, *pvb2},
inputDetails: true,
expect: `kopia Backups:
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)
DescribePodVolumeBackups(d, tc.inputPVBList, tc.inputDetails)
d.out.Flush()
assert.Equal(tt, tc.expect, d.buf.String())
})
}
}

func TestDescribeCSIVolumeSnapshots(t *testing.T) {
features.Enable(velerov1api.CSIFeatureFlag)
defer func() {
features.Disable(velerov1api.CSIFeatureFlag)
}()
handle := "handle-1"
readyToUse := true
size := int64(1024)
vsc1 := builder.ForVolumeSnapshotContent("vsc-1").
Status(&snapshotv1api.VolumeSnapshotContentStatus{
SnapshotHandle: &handle,
ReadyToUse: &readyToUse,
RestoreSize: &size,
}).Result()
testcases := []struct {
name string
inputVSCList []snapshotv1api.VolumeSnapshotContent
inputDetails bool
expect string
}{
{
name: "empty list",
inputVSCList: []snapshotv1api.VolumeSnapshotContent{},
inputDetails: false,
expect: `CSI Volume Snapshots: <none included>
`,
},
{
name: "1 vsc no details",
inputVSCList: []snapshotv1api.VolumeSnapshotContent{*vsc1},
inputDetails: false,
expect: `CSI Volume Snapshots: 1 included (specify --details for more information)
`,
},
{
name: "1 vsc with details",
inputVSCList: []snapshotv1api.VolumeSnapshotContent{*vsc1},
inputDetails: true,
expect: `CSI Volume Snapshots:
Snapshot Content Name: vsc-1
Storage Snapshot ID: handle-1
Snapshot Size (bytes): 1024
Ready to use: true
`,
},
}
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)
DescribeCSIVolumeSnapshots(d, tc.inputDetails, tc.inputVSCList)
d.out.Flush()
assert.Equal(tt, tc.expect, d.buf.String())
})
}
}
13 changes: 6 additions & 7 deletions pkg/cmd/util/output/backup_structured_describer.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,14 +437,13 @@ func DescribeCSIVolumeSnapshotsInSF(d *StructuredDescriber, details bool, volume
// the field of 'CSI Volume Snapshots Details' displays the content of CSI Volume Snapshots
if !details {
CSIVolumeSnapshotsInfo["CSIVolumeSnapshotsCount"] = len(volumeSnapshotContents)
return
}

vscDetails := make(map[string]interface{})
for _, vsc := range volumeSnapshotContents {
DescribeVSCInSF(details, vsc, vscDetails)
} else {
vscDetails := make(map[string]interface{})
for _, vsc := range volumeSnapshotContents {
DescribeVSCInSF(details, vsc, vscDetails)
}
CSIVolumeSnapshotsInfo["CSIVolumeSnapshotsDetails"] = vscDetails
}
CSIVolumeSnapshotsInfo["CSIVolumeSnapshotsDetails"] = vscDetails
d.Describe("CSIVolumeSnapshots", CSIVolumeSnapshotsInfo)
}

Expand Down
Loading

0 comments on commit cd68dd3

Please sign in to comment.