Progress output goes to stderr so --out - stays a clean pipe into restic, age or aws s3 cp. Archive names carry no colon, because these get copied onto Windows shares.
79 lines
2.2 KiB
Go
79 lines
2.2 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
"text/tabwriter"
|
|
|
|
"gitea.hostxtra.co.uk/mrhid6/vantage/shared/backup"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
func newInspectCmd() *cobra.Command {
|
|
return &cobra.Command{
|
|
Use: "inspect ARCHIVE",
|
|
Short: "Print an archive's manifest",
|
|
Long: "inspect reads an archive and prints what it holds. It contacts no\n" +
|
|
"database, so it is safe to run against an archive of unknown origin\n" +
|
|
"and is the fastest way to find out whether one is worth anything.",
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(c *cobra.Command, args []string) error {
|
|
archive, err := backup.Open(args[0])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer archive.Close()
|
|
renderManifest(c.OutOrStdout(), archive.Manifest())
|
|
return nil
|
|
},
|
|
}
|
|
}
|
|
|
|
// renderManifest prints a manifest for a human.
|
|
func renderManifest(w io.Writer, m backup.Manifest) {
|
|
fmt.Fprintf(w, "Created %s\n", m.CreatedAt.UTC().Format("2006-01-02 15:04:05 MST"))
|
|
fmt.Fprintf(w, "Database %s\n", m.MongoDB)
|
|
fmt.Fprintf(w, "MongoDB %s\n", m.MongoServerVersion)
|
|
fmt.Fprintf(w, "Written by vantagectl %s on %s\n", m.VantageVersion, m.Hostname)
|
|
fmt.Fprintf(w, "Format version %d\n", m.FormatVersion)
|
|
|
|
if m.KeyFingerprint == nil {
|
|
fmt.Fprintf(w, "Key none recorded — this archive cannot be checked "+
|
|
"against any KEY_ENCRYPTION_KEY\n")
|
|
} else {
|
|
fmt.Fprintf(w, "Key %s\n", *m.KeyFingerprint)
|
|
}
|
|
if len(m.Excluded) > 0 {
|
|
fmt.Fprintf(w, "Excluded %s\n", strings.Join(m.Excluded, ", "))
|
|
}
|
|
|
|
var docs, bytes int64
|
|
for _, c := range m.Collections {
|
|
docs += c.Documents
|
|
bytes += c.Bytes
|
|
}
|
|
fmt.Fprintf(w, "\n%d collections, %d documents, %s\n\n",
|
|
len(m.Collections), docs, humanBytes(bytes))
|
|
|
|
tw := tabwriter.NewWriter(w, 0, 0, 2, ' ', 0)
|
|
fmt.Fprintln(tw, "COLLECTION\tDOCUMENTS\tSIZE")
|
|
for _, c := range m.Collections {
|
|
fmt.Fprintf(tw, "%s\t%d\t%s\n", c.Name, c.Documents, humanBytes(c.Bytes))
|
|
}
|
|
tw.Flush()
|
|
}
|
|
|
|
func humanBytes(n int64) string {
|
|
const unit = 1024
|
|
if n < unit {
|
|
return fmt.Sprintf("%d B", n)
|
|
}
|
|
div, exp := int64(unit), 0
|
|
for v := n / unit; v >= unit; v /= unit {
|
|
div *= unit
|
|
exp++
|
|
}
|
|
return fmt.Sprintf("%.1f %cB", float64(n)/float64(div), "KMGTP"[exp])
|
|
}
|