print resource list metadata in velero backup describe --details (#1714)

* print resource list metadata in velero backup describe details

Signed-off-by: Adnan Abdulhussein <aadnan@vmware.com>

* rewrite TestGetDownloadURL to test more scenarios

Signed-off-by: Adnan Abdulhussein <aadnan@vmware.com>

* move backup printer helpers to backup_printer.go

Signed-off-by: Adnan Abdulhussein <aadnan@vmware.com>

* move describe printer helpers back to backup_describer

and rename to prefix with describe* to indicate that they are used for the describe command

Signed-off-by: Adnan Abdulhussein <aadnan@vmware.com>

* split backup and restore tests for TestGetDownloadURL

Signed-off-by: Adnan Abdulhussein <aadnan@vmware.com>

* friendlier error message when backup resource list missing

Signed-off-by: Adnan Abdulhussein <aadnan@vmware.com>
This commit is contained in:
Adnan Abdulhussein
2019-08-05 12:23:20 -06:00
committed by Steve Kriss
parent 07525bd593
commit 2254635bcb
5 changed files with 115 additions and 45 deletions
@@ -32,6 +32,10 @@ import (
velerov1client "github.com/heptio/velero/pkg/generated/clientset/versioned/typed/velero/v1"
)
// ErrNotFound is exported for external packages to check for when a file is
// not found
var ErrNotFound = errors.New("file not found")
func Stream(client velerov1client.DownloadRequestsGetter, namespace, name string, kind v1.DownloadTargetKind, w io.Writer, timeout time.Duration) error {
req := &v1.DownloadRequest{
ObjectMeta: metav1.ObjectMeta{
@@ -97,7 +101,7 @@ Loop:
}
if req.Status.DownloadURL == "" {
return errors.New("file not found")
return ErrNotFound
}
httpClient := new(http.Client)
@@ -124,6 +128,10 @@ Loop:
return errors.Wrapf(err, "request failed: unable to decode response body")
}
if resp.StatusCode == http.StatusNotFound {
return ErrNotFound
}
return errors.Errorf("request failed: %v", string(body))
}
+30 -2
View File
@@ -233,6 +233,11 @@ func DescribeBackupStatus(d *Describer, backup *velerov1api.Backup, details bool
d.Printf("Expiration:\t%s\n", status.Expiration.Time)
d.Println()
if details {
describeBackupResourceList(d, backup, veleroClient)
d.Println()
}
if status.VolumeSnapshotsAttempted > 0 {
if !details {
d.Printf("Persistent Volumes:\t%d of %d snapshots completed successfully (specify --details for more information)\n", status.VolumeSnapshotsCompleted, status.VolumeSnapshotsAttempted)
@@ -253,7 +258,7 @@ func DescribeBackupStatus(d *Describer, backup *velerov1api.Backup, details bool
d.Printf("Persistent Volumes:\n")
for _, snap := range snapshots {
printSnapshot(d, snap.Spec.PersistentVolumeName, snap.Status.ProviderSnapshotID, snap.Spec.VolumeType, snap.Spec.VolumeAZ, snap.Spec.VolumeIOPS)
describeSnapshot(d, snap.Spec.PersistentVolumeName, snap.Status.ProviderSnapshotID, snap.Spec.VolumeType, snap.Spec.VolumeAZ, snap.Spec.VolumeIOPS)
}
return
}
@@ -261,7 +266,30 @@ func DescribeBackupStatus(d *Describer, backup *velerov1api.Backup, details bool
d.Printf("Persistent Volumes: <none included>\n")
}
func printSnapshot(d *Describer, pvName, snapshotID, volumeType, volumeAZ string, iops *int64) {
func describeBackupResourceList(d *Describer, backup *velerov1api.Backup, veleroClient clientset.Interface) {
buf := new(bytes.Buffer)
if err := downloadrequest.Stream(veleroClient.VeleroV1(), backup.Namespace, backup.Name, velerov1api.DownloadTargetKindBackupResourceList, buf, downloadRequestTimeout); err != nil {
if err == downloadrequest.ErrNotFound {
d.Println("Resource List:\t<backup resource list not found, this could be because this backup was taken prior to Velero 1.1.0>")
} else {
d.Printf("Resource List:\t<error getting backup resource list: %v>\n", err)
}
return
}
var resourceList map[string][]string
if err := json.NewDecoder(buf).Decode(&resourceList); err != nil {
d.Printf("Resource List:\t<error reading backup resource list: %v>\n", err)
return
}
d.Println("Resource List:")
for gvk, items := range resourceList {
d.Printf("\t%s:\n\t\t- %s\n", gvk, strings.Join(items, "\n\t\t- "))
}
}
func describeSnapshot(d *Describer, pvName, snapshotID, volumeType, volumeAZ string, iops *int64) {
d.Printf("\t%s:\n", pvName)
d.Printf("\t\tSnapshot ID:\t%s\n", snapshotID)
d.Printf("\t\tType:\t%s\n", volumeType)