add --backup flag to list (#1117)
## Description Allows listing individual backups, instead of always listing the entire set. Could be expanded to accept multiple backup IDs in the future. ## Type of change - [x] 🌻 Feature ## Issue(s) * #1077 ## Test Plan - [x] 💪 Manual - [x] 💚 E2E
This commit is contained in:
parent
1cbb34e403
commit
5ee4ceb5a6
@ -119,7 +119,11 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
|
||||
options.AddOperationFlags(c)
|
||||
|
||||
case listCommand:
|
||||
c, _ = utils.AddCommand(parent, exchangeListCmd())
|
||||
c, fs = utils.AddCommand(parent, exchangeListCmd())
|
||||
|
||||
fs.StringVar(&backupID,
|
||||
"backup", "",
|
||||
"ID of the backup to retrieve.")
|
||||
|
||||
case detailsCommand:
|
||||
c, fs = utils.AddCommand(parent, exchangeDetailsCmd())
|
||||
@ -350,6 +354,21 @@ func listExchangeCmd(cmd *cobra.Command, args []string) error {
|
||||
|
||||
defer utils.CloseRepo(ctx, r)
|
||||
|
||||
if len(backupID) > 0 {
|
||||
b, err := r.Backup(ctx, model.StableID(backupID))
|
||||
if err != nil {
|
||||
if errors.Is(err, kopia.ErrNotFound) {
|
||||
return Only(ctx, errors.Errorf("No backup exists with the id %s", backupID))
|
||||
}
|
||||
|
||||
return Only(ctx, errors.Wrap(err, "Failed to find backup "+backupID))
|
||||
}
|
||||
|
||||
b.Print(ctx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
bs, err := r.Backups(ctx)
|
||||
if err != nil {
|
||||
return Only(ctx, errors.Wrap(err, "Failed to list backups in the repository"))
|
||||
@ -443,7 +462,7 @@ func runDetailsExchangeCmd(
|
||||
d, _, err := r.BackupDetails(ctx, backupID)
|
||||
if err != nil {
|
||||
if errors.Is(err, kopia.ErrNotFound) {
|
||||
return nil, errors.Errorf("no backup exists with the id %s", backupID)
|
||||
return nil, errors.Errorf("No backup exists with the id %s", backupID)
|
||||
}
|
||||
|
||||
return nil, errors.Wrap(err, "Failed to get backup details in the repository")
|
||||
|
||||
@ -140,7 +140,8 @@ type PreparedBackupExchangeIntegrationSuite struct {
|
||||
cfgFP string
|
||||
repo repository.Repository
|
||||
m365UserID string
|
||||
backupOps map[path.CategoryType]operations.BackupOperation
|
||||
backupOps map[path.CategoryType]string
|
||||
recorder strings.Builder
|
||||
}
|
||||
|
||||
func TestPreparedBackupExchangeIntegrationSuite(t *testing.T) {
|
||||
@ -165,6 +166,7 @@ func (suite *PreparedBackupExchangeIntegrationSuite) SetupSuite() {
|
||||
// prepare common details
|
||||
suite.acct = tester.NewM365Account(t)
|
||||
suite.st = tester.NewPrefixedS3Storage(t)
|
||||
suite.recorder = strings.Builder{}
|
||||
|
||||
cfg, err := suite.st.S3Config()
|
||||
require.NoError(t, err)
|
||||
@ -188,7 +190,7 @@ func (suite *PreparedBackupExchangeIntegrationSuite) SetupSuite() {
|
||||
suite.repo, err = repository.Initialize(ctx, suite.acct, suite.st, control.Options{})
|
||||
require.NoError(t, err)
|
||||
|
||||
suite.backupOps = make(map[path.CategoryType]operations.BackupOperation)
|
||||
suite.backupOps = make(map[path.CategoryType]string)
|
||||
|
||||
for _, set := range backupDataSets {
|
||||
var (
|
||||
@ -213,21 +215,23 @@ func (suite *PreparedBackupExchangeIntegrationSuite) SetupSuite() {
|
||||
require.NoError(t, bop.Run(ctx))
|
||||
require.NoError(t, err)
|
||||
|
||||
suite.backupOps[set] = bop
|
||||
bIDs := string(bop.Results.BackupID)
|
||||
|
||||
// sanity check, ensure we can find the backup and its details immediately
|
||||
_, err = suite.repo.Backup(ctx, bop.Results.BackupID)
|
||||
b, err := suite.repo.Backup(ctx, bop.Results.BackupID)
|
||||
require.NoError(t, err, "retrieving recent backup by ID")
|
||||
_, _, err = suite.repo.BackupDetails(ctx, string(bop.Results.BackupID))
|
||||
require.Equal(t, bIDs, string(b.ID), "repo backup matches results id")
|
||||
_, b, err = suite.repo.BackupDetails(ctx, bIDs)
|
||||
require.NoError(t, err, "retrieving recent backup details by ID")
|
||||
require.Equal(t, bIDs, string(b.ID), "repo details matches results id")
|
||||
|
||||
suite.backupOps[set] = string(b.ID)
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeListCmd() {
|
||||
recorder := strings.Builder{}
|
||||
|
||||
for _, set := range backupDataSets {
|
||||
recorder.Reset()
|
||||
suite.recorder.Reset()
|
||||
|
||||
suite.T().Run(set.String(), func(t *testing.T) {
|
||||
ctx, flush := tester.NewContext()
|
||||
@ -239,7 +243,7 @@ func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeListCmd() {
|
||||
"--config-file", suite.cfgFP)
|
||||
cli.BuildCommandTree(cmd)
|
||||
|
||||
cmd.SetOut(&recorder)
|
||||
cmd.SetOut(&suite.recorder)
|
||||
|
||||
ctx = print.SetRootCmd(ctx, cmd)
|
||||
|
||||
@ -247,24 +251,74 @@ func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeListCmd() {
|
||||
require.NoError(t, cmd.ExecuteContext(ctx))
|
||||
|
||||
// compare the output
|
||||
result := recorder.String()
|
||||
assert.Contains(t, result, suite.backupOps[set].Results.BackupID)
|
||||
result := suite.recorder.String()
|
||||
assert.Contains(t, result, suite.backupOps[set])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeDetailsCmd() {
|
||||
recorder := strings.Builder{}
|
||||
|
||||
func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeListCmd_singleID() {
|
||||
for _, set := range backupDataSets {
|
||||
recorder.Reset()
|
||||
suite.recorder.Reset()
|
||||
|
||||
suite.T().Run(set.String(), func(t *testing.T) {
|
||||
ctx, flush := tester.NewContext()
|
||||
ctx = config.SetViper(ctx, suite.vpr)
|
||||
defer flush()
|
||||
|
||||
bID := suite.backupOps[set].Results.BackupID
|
||||
bID := suite.backupOps[set]
|
||||
|
||||
cmd := tester.StubRootCmd(
|
||||
"backup", "list", "exchange",
|
||||
"--config-file", suite.cfgFP,
|
||||
"--backup", string(bID))
|
||||
cli.BuildCommandTree(cmd)
|
||||
|
||||
cmd.SetOut(&suite.recorder)
|
||||
|
||||
ctx = print.SetRootCmd(ctx, cmd)
|
||||
|
||||
// run the command
|
||||
require.NoError(t, cmd.ExecuteContext(ctx))
|
||||
|
||||
// compare the output
|
||||
result := suite.recorder.String()
|
||||
assert.Contains(t, result, bID)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeListCmd_badID() {
|
||||
for _, set := range backupDataSets {
|
||||
suite.T().Run(set.String(), func(t *testing.T) {
|
||||
ctx, flush := tester.NewContext()
|
||||
ctx = config.SetViper(ctx, suite.vpr)
|
||||
defer flush()
|
||||
|
||||
cmd := tester.StubRootCmd(
|
||||
"backup", "list", "exchange",
|
||||
"--config-file", suite.cfgFP,
|
||||
"--backup", "smarfs")
|
||||
cli.BuildCommandTree(cmd)
|
||||
|
||||
ctx = print.SetRootCmd(ctx, cmd)
|
||||
|
||||
// run the command
|
||||
require.Error(t, cmd.ExecuteContext(ctx))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeDetailsCmd() {
|
||||
for _, set := range backupDataSets {
|
||||
suite.recorder.Reset()
|
||||
|
||||
suite.T().Run(set.String(), func(t *testing.T) {
|
||||
ctx, flush := tester.NewContext()
|
||||
ctx = config.SetViper(ctx, suite.vpr)
|
||||
defer flush()
|
||||
|
||||
bID := suite.backupOps[set]
|
||||
|
||||
// fetch the details from the repo first
|
||||
deets, _, err := suite.repo.BackupDetails(ctx, string(bID))
|
||||
@ -276,7 +330,7 @@ func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeDetailsCmd() {
|
||||
"--backup", string(bID))
|
||||
cli.BuildCommandTree(cmd)
|
||||
|
||||
cmd.SetOut(&recorder)
|
||||
cmd.SetOut(&suite.recorder)
|
||||
|
||||
ctx = print.SetRootCmd(ctx, cmd)
|
||||
|
||||
@ -284,7 +338,7 @@ func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeDetailsCmd() {
|
||||
require.NoError(t, cmd.ExecuteContext(ctx))
|
||||
|
||||
// compare the output
|
||||
result := recorder.String()
|
||||
result := suite.recorder.String()
|
||||
|
||||
i := 0
|
||||
foundFolders := 0
|
||||
|
||||
@ -84,7 +84,11 @@ func addOneDriveCommands(parent *cobra.Command) *cobra.Command {
|
||||
options.AddOperationFlags(c)
|
||||
|
||||
case listCommand:
|
||||
c, _ = utils.AddCommand(parent, oneDriveListCmd())
|
||||
c, fs = utils.AddCommand(parent, oneDriveListCmd())
|
||||
|
||||
fs.StringVar(&backupID,
|
||||
"backup", "",
|
||||
"ID of the backup to retrieve.")
|
||||
|
||||
case detailsCommand:
|
||||
c, fs = utils.AddCommand(parent, oneDriveDetailsCmd())
|
||||
@ -246,6 +250,21 @@ func listOneDriveCmd(cmd *cobra.Command, args []string) error {
|
||||
|
||||
defer utils.CloseRepo(ctx, r)
|
||||
|
||||
if len(backupID) > 0 {
|
||||
b, err := r.Backup(ctx, model.StableID(backupID))
|
||||
if err != nil {
|
||||
if errors.Is(err, kopia.ErrNotFound) {
|
||||
return Only(ctx, errors.Errorf("No backup exists with the id %s", backupID))
|
||||
}
|
||||
|
||||
return Only(ctx, errors.Wrap(err, "Failed to find backup "+backupID))
|
||||
}
|
||||
|
||||
b.Print(ctx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
bs, err := r.Backups(ctx)
|
||||
if err != nil {
|
||||
return Only(ctx, errors.Wrap(err, "Failed to list backups in the repository"))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user