add per-data type flags to backup details (#355)
* add per-data type flags to backup details Adds the contacts, contact folders, emails, email folders, events, and users flag support to `corso backup create exchange` to enable selector support.
This commit is contained in:
parent
746c88a233
commit
43c024f4b2
@ -19,6 +19,11 @@ var (
|
||||
backupDetailsID string
|
||||
exchangeAll bool
|
||||
exchangeData []string
|
||||
contact []string
|
||||
contactFolder []string
|
||||
email []string
|
||||
emailFolder []string
|
||||
event []string
|
||||
user []string
|
||||
)
|
||||
|
||||
@ -37,8 +42,8 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
|
||||
switch parent.Use {
|
||||
case createCommand:
|
||||
c, fs = utils.AddCommand(parent, exchangeCreateCmd)
|
||||
fs.StringArrayVar(&user, "user", nil, "Back up Exchange data by user ID; accepts "+utils.Wildcard+" to select all users")
|
||||
fs.BoolVar(&exchangeAll, "all", false, "Back up all Exchange data for all users")
|
||||
fs.StringArrayVar(&user, "user", nil, "Backup Exchange data by user ID; accepts "+utils.Wildcard+" to select all users")
|
||||
fs.BoolVar(&exchangeAll, "all", false, "Backup all Exchange data for all users")
|
||||
fs.StringArrayVar(
|
||||
&exchangeData,
|
||||
"data",
|
||||
@ -51,6 +56,25 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
|
||||
c, fs = utils.AddCommand(parent, exchangeDetailsCmd)
|
||||
fs.StringVar(&backupDetailsID, "backup-details", "", "ID of the backup details to be shown")
|
||||
cobra.CheckErr(c.MarkFlagRequired("backup-details"))
|
||||
fs.StringArrayVar(&contact, "contact", nil, "Select backup details by contact ID; accepts "+utils.Wildcard+" to select all contacts")
|
||||
fs.StringArrayVar(
|
||||
&contactFolder,
|
||||
"contact-folder",
|
||||
nil,
|
||||
"Select backup details by contact folder ID; accepts "+utils.Wildcard+" to select all contact folders")
|
||||
fs.StringArrayVar(&email, "email", nil, "Select backup details by emails ID; accepts "+utils.Wildcard+" to select all emails")
|
||||
fs.StringArrayVar(
|
||||
&emailFolder,
|
||||
"email-folder",
|
||||
nil,
|
||||
"Select backup details by email folder ID; accepts "+utils.Wildcard+" to select all email folderss")
|
||||
fs.StringArrayVar(&event, "event", nil, "Select backup details by event ID; accepts "+utils.Wildcard+" to select all events")
|
||||
fs.StringArrayVar(&user, "user", nil, "Select backup details by user ID; accepts "+utils.Wildcard+" to select all users")
|
||||
|
||||
// TODO: reveal these flags when their production is supported in GC
|
||||
cobra.CheckErr(fs.MarkHidden("contact"))
|
||||
cobra.CheckErr(fs.MarkHidden("contact-folder"))
|
||||
cobra.CheckErr(fs.MarkHidden("event"))
|
||||
}
|
||||
return c
|
||||
}
|
||||
@ -237,3 +261,89 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func exchangeBackupDetailSelectors(
|
||||
contacts, contactFolders, emails, emailFolders, events, users []string,
|
||||
) selectors.Selector {
|
||||
sel := selectors.NewExchangeBackup()
|
||||
// normalize the inputs
|
||||
lc, lcf := len(contacts), len(contactFolders)
|
||||
le, lef := len(emails), len(emailFolders)
|
||||
lev := len(events)
|
||||
lu := len(users)
|
||||
|
||||
// if only the backupID is provided, treat that as an --all query
|
||||
if lc+lcf+le+lef+lev+lu == 0 {
|
||||
sel.Include(sel.Users(selectors.All()))
|
||||
return sel.Selector
|
||||
}
|
||||
|
||||
// if only users are provided, we only get one selector
|
||||
if lc+lcf+le+lef+lev == 0 {
|
||||
sel.Include(sel.Users(users))
|
||||
return sel.Selector
|
||||
}
|
||||
|
||||
// otherwise, add selectors for each type of data
|
||||
includeExchangeContacts(sel, users, contactFolders, contacts)
|
||||
includeExchangeEmails(sel, users, emailFolders, email)
|
||||
includeExchangeEvents(sel, users, events)
|
||||
|
||||
return sel.Selector
|
||||
}
|
||||
|
||||
func includeExchangeContacts(sel *selectors.ExchangeBackup, users, contactFolders, contacts []string) {
|
||||
if len(contactFolders) == 0 {
|
||||
return
|
||||
}
|
||||
if len(contacts) > 0 {
|
||||
sel.Include(sel.Contacts(users, contactFolders, contacts))
|
||||
} else {
|
||||
sel.Include(sel.ContactFolders(users, contactFolders))
|
||||
}
|
||||
}
|
||||
|
||||
func includeExchangeEmails(sel *selectors.ExchangeBackup, users, emailFolders, emails []string) {
|
||||
if len(emailFolders) == 0 {
|
||||
return
|
||||
}
|
||||
if len(emails) > 0 {
|
||||
sel.Include(sel.Mails(users, emailFolders, emails))
|
||||
} else {
|
||||
sel.Include(sel.MailFolders(users, emailFolders))
|
||||
}
|
||||
}
|
||||
|
||||
func includeExchangeEvents(sel *selectors.ExchangeBackup, users, events []string) {
|
||||
if len(events) == 0 {
|
||||
return
|
||||
}
|
||||
sel.Include(sel.Events(users, events))
|
||||
}
|
||||
|
||||
func validateExchangeBackupDetailFlags(
|
||||
contacts, contactFolders, emails, emailFolders, events, users []string,
|
||||
backupID string,
|
||||
) error {
|
||||
if len(backupID) == 0 {
|
||||
return errors.New("a backup ID is requried")
|
||||
}
|
||||
lu := len(users)
|
||||
lc, lcf := len(contacts), len(contactFolders)
|
||||
le, lef := len(emails), len(emailFolders)
|
||||
lev := len(events)
|
||||
// if only the backupID is populated, that's the same as --all
|
||||
if lu+lc+lcf+le+lef+lev == 0 {
|
||||
return nil
|
||||
}
|
||||
if lu == 0 {
|
||||
return errors.New("requries one or more --user ids, the wildcard --user *, or the --all flag.")
|
||||
}
|
||||
if lc > 0 && lcf == 0 {
|
||||
return errors.New("one or more --contact-folder ids or the wildcard --contact-folder * must be included to specify a --contact")
|
||||
}
|
||||
if le > 0 && lef == 0 {
|
||||
return errors.New("one or more --email-folder ids or the wildcard --email-folder * must be included to specify a --email")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -212,3 +212,267 @@ func (suite *ExchangeSuite) TestExchangeBackupCreateSelectors() {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *ExchangeSuite) TestValidateBackupDetailFlags() {
|
||||
stub := []string{"id-stub"}
|
||||
table := []struct {
|
||||
name string
|
||||
contacts, contactFolders, emails, emailFolders, events, users []string
|
||||
backupID string
|
||||
expect assert.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "only backupid",
|
||||
backupID: "bid",
|
||||
expect: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "all values populated",
|
||||
backupID: "bid",
|
||||
contacts: stub,
|
||||
contactFolders: stub,
|
||||
emails: stub,
|
||||
emailFolders: stub,
|
||||
events: stub,
|
||||
users: stub,
|
||||
expect: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "nothing populated",
|
||||
expect: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "no backup id",
|
||||
contacts: stub,
|
||||
contactFolders: stub,
|
||||
emails: stub,
|
||||
emailFolders: stub,
|
||||
events: stub,
|
||||
users: stub,
|
||||
expect: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "no users",
|
||||
backupID: "bid",
|
||||
contacts: stub,
|
||||
contactFolders: stub,
|
||||
emails: stub,
|
||||
emailFolders: stub,
|
||||
events: stub,
|
||||
expect: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "no contact folders",
|
||||
backupID: "bid",
|
||||
contacts: stub,
|
||||
emails: stub,
|
||||
emailFolders: stub,
|
||||
events: stub,
|
||||
users: stub,
|
||||
expect: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "no email folders",
|
||||
backupID: "bid",
|
||||
contacts: stub,
|
||||
contactFolders: stub,
|
||||
emails: stub,
|
||||
events: stub,
|
||||
users: stub,
|
||||
expect: assert.Error,
|
||||
},
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
test.expect(t, validateExchangeBackupDetailFlags(
|
||||
test.contacts,
|
||||
test.contactFolders,
|
||||
test.emails,
|
||||
test.emailFolders,
|
||||
test.events,
|
||||
test.users,
|
||||
test.backupID,
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *ExchangeSuite) TestExchangeBackupDetailSelectors() {
|
||||
stub := []string{"id-stub"}
|
||||
all := []string{utils.Wildcard}
|
||||
table := []struct {
|
||||
name string
|
||||
contacts, contactFolders, emails, emailFolders, events, users []string
|
||||
expectIncludeLen int
|
||||
}{
|
||||
{
|
||||
name: "no selectors",
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "all users",
|
||||
users: all,
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "single user",
|
||||
users: stub,
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "multiple users",
|
||||
users: []string{"fnord", "smarf"},
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "all users, all data",
|
||||
contacts: all,
|
||||
contactFolders: all,
|
||||
emails: all,
|
||||
emailFolders: all,
|
||||
events: all,
|
||||
users: all,
|
||||
expectIncludeLen: 3,
|
||||
},
|
||||
{
|
||||
name: "all users, all folders",
|
||||
contactFolders: all,
|
||||
emailFolders: all,
|
||||
users: all,
|
||||
expectIncludeLen: 2,
|
||||
},
|
||||
{
|
||||
name: "single user, single of each data",
|
||||
contacts: stub,
|
||||
contactFolders: stub,
|
||||
emails: stub,
|
||||
emailFolders: stub,
|
||||
events: stub,
|
||||
users: stub,
|
||||
expectIncludeLen: 3,
|
||||
},
|
||||
{
|
||||
name: "single user, single of each folder",
|
||||
contactFolders: stub,
|
||||
emailFolders: stub,
|
||||
users: stub,
|
||||
expectIncludeLen: 2,
|
||||
},
|
||||
{
|
||||
name: "all users, contacts",
|
||||
contacts: all,
|
||||
contactFolders: stub,
|
||||
users: all,
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "single user, contacts",
|
||||
contacts: stub,
|
||||
contactFolders: stub,
|
||||
users: stub,
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "all users, emails",
|
||||
emails: all,
|
||||
emailFolders: stub,
|
||||
users: all,
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "single user, emails",
|
||||
emails: stub,
|
||||
emailFolders: stub,
|
||||
users: stub,
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "all users, events",
|
||||
events: all,
|
||||
users: all,
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "single user, events",
|
||||
events: stub,
|
||||
users: stub,
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "all users, contacts + email",
|
||||
contacts: all,
|
||||
contactFolders: all,
|
||||
emails: all,
|
||||
emailFolders: all,
|
||||
users: all,
|
||||
expectIncludeLen: 2,
|
||||
},
|
||||
{
|
||||
name: "single users, contacts + email",
|
||||
contacts: stub,
|
||||
contactFolders: stub,
|
||||
emails: stub,
|
||||
emailFolders: stub,
|
||||
users: stub,
|
||||
expectIncludeLen: 2,
|
||||
},
|
||||
{
|
||||
name: "all users, email + event",
|
||||
emails: all,
|
||||
emailFolders: all,
|
||||
events: all,
|
||||
users: all,
|
||||
expectIncludeLen: 2,
|
||||
},
|
||||
{
|
||||
name: "single users, email + event",
|
||||
emails: stub,
|
||||
emailFolders: stub,
|
||||
events: stub,
|
||||
users: stub,
|
||||
expectIncludeLen: 2,
|
||||
},
|
||||
{
|
||||
name: "all users, event + contact",
|
||||
contacts: all,
|
||||
contactFolders: all,
|
||||
events: all,
|
||||
users: all,
|
||||
expectIncludeLen: 2,
|
||||
},
|
||||
{
|
||||
name: "single users, event + contact",
|
||||
contacts: stub,
|
||||
contactFolders: stub,
|
||||
events: stub,
|
||||
users: stub,
|
||||
expectIncludeLen: 2,
|
||||
},
|
||||
{
|
||||
name: "many users, events",
|
||||
events: []string{"foo", "bar"},
|
||||
users: []string{"fnord", "smarf"},
|
||||
expectIncludeLen: 2,
|
||||
},
|
||||
{
|
||||
name: "many users, events + contacts",
|
||||
contacts: []string{"foo", "bar"},
|
||||
contactFolders: []string{"foo", "bar"},
|
||||
events: []string{"foo", "bar"},
|
||||
users: []string{"fnord", "smarf"},
|
||||
expectIncludeLen: 6,
|
||||
},
|
||||
}
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
sel := exchangeBackupDetailSelectors(
|
||||
test.contacts,
|
||||
test.contactFolders,
|
||||
test.emails,
|
||||
test.emailFolders,
|
||||
test.events,
|
||||
test.users)
|
||||
assert.Equal(t, test.expectIncludeLen, len(sel.Includes))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,9 +5,10 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/alcionai/corso/pkg/repository"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/alcionai/corso/pkg/repository"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user