diff --git a/src/cli/backup/exchange.go b/src/cli/backup/exchange.go index 49b7a6714..a08c19bfb 100644 --- a/src/cli/backup/exchange.go +++ b/src/cli/backup/exchange.go @@ -160,8 +160,12 @@ func createExchangeCmd(cmd *cobra.Command, args []string) error { return errors.Wrap(err, "Failed to run Exchange backup") } - // todo: revive when backups are hooked up to backupOperation results - // fmt.Printf("Created backup %s in %s for Exchange user %s.\n", result.SnapshotID, s.Provider, user) + bu, err := r.Backup(ctx, bo.Results.BackupID) + if err != nil { + return errors.Wrap(err, "Unable to retrieve backup results from storage") + } + print.Backup(*bu) + return nil } diff --git a/src/cli/print/print.go b/src/cli/print/print.go index e112ee280..1c67a74dd 100644 --- a/src/cli/print/print.go +++ b/src/cli/print/print.go @@ -36,6 +36,36 @@ type Printable interface { Values() []string } +func print(p Printable) { + if outputAsJSON || outputAsJSONDebug { + outputJSON(p, outputAsJSONDebug) + return + } + outputTable([]Printable{p}) +} + +// printAll prints the slice of printable items, +// according to the caller's requested format. +func printAll(ps []Printable) { + if len(ps) == 0 { + return + } + if outputAsJSON || outputAsJSONDebug { + outputJSONArr(ps, outputAsJSONDebug) + return + } + outputTable(ps) +} + +// ------------------------------------------------------------------------------------------ +// Type Formatters (TODO: migrate to owning packages) +// ------------------------------------------------------------------------------------------ + +// Prints the backup to the terminal with stdout. +func Backup(b backup.Backup) { + print(b) +} + // Prints the backups to the terminal with stdout. func Backups(bs []backup.Backup) { ps := []Printable{} @@ -54,37 +84,9 @@ func Entries(des []details.DetailsEntry) { printAll(ps) } -// printAll prints the slice of printable items, -// according to the caller's requested format. -func printAll(ps []Printable) { - if len(ps) == 0 { - return - } - if outputAsJSON || outputAsJSONDebug { - outputJSON(ps, outputAsJSONDebug) - return - } - outputTable(ps) -} - -// output to stdout the list of printable structs as json. -// if debug is false, calls ps.Printable() first -func outputJSON(ps []Printable, debug bool) { - sl := make([]any, 0, len(ps)) - for _, p := range ps { - if debug { - sl = append(sl, p) - } else { - sl = append(sl, p.MinimumPrintable()) - } - } - bs, err := json.Marshal(sl) - if err != nil { - fmt.Fprintf(os.Stderr, "error formatting results to json: %v\n", err) - return - } - fmt.Println(string(pretty.Pretty(bs))) -} +// ------------------------------------------------------------------------------------------ +// Tabular +// ------------------------------------------------------------------------------------------ // output to stdout the list of printable structs in a table func outputTable(ps []Printable) { @@ -103,3 +105,37 @@ func outputTable(ps []Printable) { AlternateColors: false, }) } + +// ------------------------------------------------------------------------------------------ +// JSON +// ------------------------------------------------------------------------------------------ + +func outputJSON(p Printable, debug bool) { + if debug { + printJSON(p) + return + } + printJSON(p.MinimumPrintable()) +} + +func outputJSONArr(ps []Printable, debug bool) { + sl := make([]any, 0, len(ps)) + for _, p := range ps { + if debug { + sl = append(sl, p) + } else { + sl = append(sl, p.MinimumPrintable()) + } + } + printJSON(sl) +} + +// output to stdout the list of printable structs as json. +func printJSON(a any) { + bs, err := json.Marshal(a) + if err != nil { + fmt.Fprintf(os.Stderr, "error formatting results to json: %v\n", err) + return + } + fmt.Println(string(pretty.Pretty(bs))) +} diff --git a/src/internal/operations/operation.go b/src/internal/operations/operation.go index 78dd415c7..7175914e5 100644 --- a/src/internal/operations/operation.go +++ b/src/internal/operations/operation.go @@ -3,7 +3,6 @@ package operations import ( "time" - "github.com/google/uuid" "github.com/pkg/errors" "github.com/alcionai/corso/internal/kopia" @@ -28,7 +27,6 @@ const ( // Specific processes (eg: backups, restores, etc) are expected to wrap operation // with process specific details. type operation struct { - ID uuid.UUID `json:"id"` // system generated identifier CreatedAt time.Time `json:"createdAt"` // datetime of the operation's creation Options Options `json:"options"` Status opStatus `json:"status"` @@ -55,7 +53,6 @@ func newOperation( sw *store.Wrapper, ) operation { return operation{ - ID: uuid.New(), CreatedAt: time.Now(), Options: opts, kopia: kw, diff --git a/src/internal/operations/operation_test.go b/src/internal/operations/operation_test.go index 4f44b1614..1fcbc5031 100644 --- a/src/internal/operations/operation_test.go +++ b/src/internal/operations/operation_test.go @@ -2,6 +2,7 @@ package operations import ( "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" @@ -21,7 +22,7 @@ func TestOperationSuite(t *testing.T) { func (suite *OperationSuite) TestNewOperation() { t := suite.T() op := newOperation(Options{}, nil, nil) - assert.NotNil(t, op.ID) + assert.Greater(t, op.CreatedAt, time.Time{}) } func (suite *OperationSuite) TestOperation_Validate() { diff --git a/src/pkg/repository/repository.go b/src/pkg/repository/repository.go index 19bf9f297..1a816b3c6 100644 --- a/src/pkg/repository/repository.go +++ b/src/pkg/repository/repository.go @@ -156,6 +156,12 @@ func (r Repository) NewRestore( sel) } +// backups lists a backup by id +func (r Repository) Backup(ctx context.Context, id model.StableID) (*backup.Backup, error) { + sw := store.NewKopiaStore(r.modelStore) + return sw.GetBackup(ctx, id) +} + // backups lists backups in a repository func (r Repository) Backups(ctx context.Context) ([]backup.Backup, error) { sw := store.NewKopiaStore(r.modelStore)