Create ExchangeOpts struct for selector values (#941)

## Description

Consolidate function parameters by passing them as a single struct instead of a bunch of parameters. Helps keep function signatures shorter and also makes it easier to modify in the future (just change the struct rather than all call sites).

## Type of change

<!--- Please check the type of change your PR introduces: --->
- [ ] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Test
- [ ] 💻 CI/Deployment
- [x] 🐹 Trivial/Minor

## Issue(s)

* #913 

## Test Plan

<!-- How will this be tested prior to merging.-->
- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
ashmrtn 2022-09-22 15:51:25 -07:00 committed by GitHub
parent 8c674fa17b
commit 744eadfd2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 306 additions and 235 deletions

View File

@ -358,28 +358,29 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
return Only(ctx, errors.Wrap(err, "Failed to get backup details in the repository")) return Only(ctx, errors.Wrap(err, "Failed to get backup details in the repository"))
} }
opts := utils.ExchangeOpts{
Contacts: contact,
ContactFolders: contactFolder,
Emails: email,
EmailFolders: emailFolder,
Events: event,
EventCalendars: eventCalendar,
Users: user,
ContactName: contactName,
EmailReceivedAfter: emailReceivedAfter,
EmailReceivedBefore: emailReceivedBefore,
EmailSender: emailSender,
EmailSubject: emailSubject,
EventOrganizer: eventOrganizer,
EventRecurs: eventRecurs,
EventStartsAfter: eventStartsAfter,
EventStartsBefore: eventStartsBefore,
EventSubject: eventSubject,
}
sel := selectors.NewExchangeRestore() sel := selectors.NewExchangeRestore()
utils.IncludeExchangeRestoreDataSelectors( utils.IncludeExchangeRestoreDataSelectors(sel, opts)
sel, utils.FilterExchangeRestoreInfoSelectors(sel, opts)
contact,
contactFolder,
email,
emailFolder,
event,
eventCalendar,
user)
utils.FilterExchangeRestoreInfoSelectors(
sel,
contactName,
emailReceivedAfter,
emailReceivedBefore,
emailSender,
emailSubject,
eventOrganizer,
eventRecurs,
eventStartsAfter,
eventStartsBefore,
eventSubject)
// if no selector flags were specified, get all data in the service. // if no selector flags were specified, get all data in the service.
if len(sel.Scopes()) == 0 { if len(sel.Scopes()) == 0 {

View File

@ -163,28 +163,29 @@ func restoreExchangeCmd(cmd *cobra.Command, args []string) error {
defer utils.CloseRepo(ctx, r) defer utils.CloseRepo(ctx, r)
opts := utils.ExchangeOpts{
Contacts: contact,
ContactFolders: contactFolder,
Emails: email,
EmailFolders: emailFolder,
Events: event,
EventCalendars: eventCalendar,
Users: user,
ContactName: contactName,
EmailReceivedAfter: emailReceivedAfter,
EmailReceivedBefore: emailReceivedBefore,
EmailSender: emailSender,
EmailSubject: emailSubject,
EventOrganizer: eventOrganizer,
EventRecurs: eventRecurs,
EventStartsAfter: eventStartsAfter,
EventStartsBefore: eventStartsBefore,
EventSubject: eventSubject,
}
sel := selectors.NewExchangeRestore() sel := selectors.NewExchangeRestore()
utils.IncludeExchangeRestoreDataSelectors( utils.IncludeExchangeRestoreDataSelectors(sel, opts)
sel, utils.FilterExchangeRestoreInfoSelectors(sel, opts)
contact,
contactFolder,
email,
emailFolder,
event,
eventCalendar,
user)
utils.FilterExchangeRestoreInfoSelectors(
sel,
contactName,
emailReceivedAfter,
emailReceivedBefore,
emailSender,
emailSubject,
eventOrganizer,
eventRecurs,
eventStartsAfter,
eventStartsBefore,
eventSubject)
// if no selector flags were specified, get all data in the service. // if no selector flags were specified, get all data in the service.
if len(sel.Scopes()) == 0 { if len(sel.Scopes()) == 0 {

View File

@ -6,6 +6,26 @@ import (
"github.com/alcionai/corso/src/pkg/selectors" "github.com/alcionai/corso/src/pkg/selectors"
) )
type ExchangeOpts struct {
Contacts []string
ContactFolders []string
Emails []string
EmailFolders []string
Events []string
EventCalendars []string
Users []string
ContactName string
EmailReceivedAfter string
EmailReceivedBefore string
EmailSender string
EmailSubject string
EventOrganizer string
EventRecurs string
EventStartsAfter string
EventStartsBefore string
EventSubject string
}
// AddExchangeInclude adds the scope of the provided values to the selector's // AddExchangeInclude adds the scope of the provided values to the selector's
// inclusion set. Any unpopulated slice will be replaced with selectors.Any() // inclusion set. Any unpopulated slice will be replaced with selectors.Any()
// to act as a wildcard. // to act as a wildcard.
@ -64,43 +84,41 @@ func ValidateExchangeRestoreFlags(backupID string) error {
// inclusions for exchange commands. // inclusions for exchange commands.
func IncludeExchangeRestoreDataSelectors( func IncludeExchangeRestoreDataSelectors(
sel *selectors.ExchangeRestore, sel *selectors.ExchangeRestore,
contacts, contactFolders, emails, emailFolders, events, eventCalendars, users []string, opts ExchangeOpts,
) { ) {
lc, lcf := len(contacts), len(contactFolders) lc, lcf := len(opts.Contacts), len(opts.ContactFolders)
le, lef := len(emails), len(emailFolders) le, lef := len(opts.Emails), len(opts.EmailFolders)
lev, lec := len(events), len(eventCalendars) lev, lec := len(opts.Events), len(opts.EventCalendars)
// either scope the request to a set of users // either scope the request to a set of users
if lc+lcf+le+lef+lev+lec == 0 { if lc+lcf+le+lef+lev+lec == 0 {
if len(users) == 0 { if len(opts.Users) == 0 {
users = selectors.Any() opts.Users = selectors.Any()
} }
sel.Include(sel.Users(users)) sel.Include(sel.Users(opts.Users))
return return
} }
// or add selectors for each type of data // or add selectors for each type of data
AddExchangeInclude(sel, users, contactFolders, contacts, sel.Contacts) AddExchangeInclude(sel, opts.Users, opts.ContactFolders, opts.Contacts, sel.Contacts)
AddExchangeInclude(sel, users, emailFolders, emails, sel.Mails) AddExchangeInclude(sel, opts.Users, opts.EmailFolders, opts.Emails, sel.Mails)
AddExchangeInclude(sel, users, eventCalendars, events, sel.Events) AddExchangeInclude(sel, opts.Users, opts.EventCalendars, opts.Events, sel.Events)
} }
// FilterExchangeRestoreInfoSelectors builds the common info-selector filters. // FilterExchangeRestoreInfoSelectors builds the common info-selector filters.
func FilterExchangeRestoreInfoSelectors( func FilterExchangeRestoreInfoSelectors(
sel *selectors.ExchangeRestore, sel *selectors.ExchangeRestore,
contactName, opts ExchangeOpts,
emailReceivedAfter, emailReceivedBefore, emailSender, emailSubject,
eventOrganizer, eventRecurs, eventStartsAfter, eventStartsBefore, eventSubject string,
) { ) {
AddExchangeFilter(sel, contactName, sel.ContactName) AddExchangeFilter(sel, opts.ContactName, sel.ContactName)
AddExchangeFilter(sel, emailReceivedAfter, sel.MailReceivedAfter) AddExchangeFilter(sel, opts.EmailReceivedAfter, sel.MailReceivedAfter)
AddExchangeFilter(sel, emailReceivedBefore, sel.MailReceivedBefore) AddExchangeFilter(sel, opts.EmailReceivedBefore, sel.MailReceivedBefore)
AddExchangeFilter(sel, emailSender, sel.MailSender) AddExchangeFilter(sel, opts.EmailSender, sel.MailSender)
AddExchangeFilter(sel, emailSubject, sel.MailSubject) AddExchangeFilter(sel, opts.EmailSubject, sel.MailSubject)
AddExchangeFilter(sel, eventOrganizer, sel.EventOrganizer) AddExchangeFilter(sel, opts.EventOrganizer, sel.EventOrganizer)
AddExchangeFilter(sel, eventRecurs, sel.EventRecurs) AddExchangeFilter(sel, opts.EventRecurs, sel.EventRecurs)
AddExchangeFilter(sel, eventStartsAfter, sel.EventStartsAfter) AddExchangeFilter(sel, opts.EventStartsAfter, sel.EventStartsAfter)
AddExchangeFilter(sel, eventStartsBefore, sel.EventStartsBefore) AddExchangeFilter(sel, opts.EventStartsBefore, sel.EventStartsBefore)
AddExchangeFilter(sel, eventSubject, sel.EventSubject) AddExchangeFilter(sel, opts.EventSubject, sel.EventSubject)
} }

View File

@ -47,207 +47,247 @@ func (suite *ExchangeUtilsSuite) TestIncludeExchangeBackupDetailDataSelectors()
a := []string{utils.Wildcard} a := []string{utils.Wildcard}
table := []struct { table := []struct {
name string name string
contacts, contactFolders, emails, emailFolders, events, eventCalendars, users []string opts utils.ExchangeOpts
expectIncludeLen int expectIncludeLen int
}{ }{
{ {
name: "no selectors", name: "no selectors",
expectIncludeLen: 3, expectIncludeLen: 3,
}, },
{ {
name: "any users", name: "any users",
users: a, opts: utils.ExchangeOpts{
Users: a,
},
expectIncludeLen: 3, expectIncludeLen: 3,
}, },
{ {
name: "single user", name: "single user",
users: stub, opts: utils.ExchangeOpts{
Users: stub,
},
expectIncludeLen: 3, expectIncludeLen: 3,
}, },
{ {
name: "multiple users", name: "multiple users",
users: many, opts: utils.ExchangeOpts{
Users: many,
},
expectIncludeLen: 3, expectIncludeLen: 3,
}, },
{ {
name: "any users, any data", name: "any users, any data",
contacts: a, opts: utils.ExchangeOpts{
contactFolders: a, Contacts: a,
emails: a, ContactFolders: a,
emailFolders: a, Emails: a,
events: a, EmailFolders: a,
eventCalendars: a, Events: a,
users: a, EventCalendars: a,
Users: a,
},
expectIncludeLen: 3, expectIncludeLen: 3,
}, },
{ {
name: "any users, any folders", name: "any users, any folders",
contactFolders: a, opts: utils.ExchangeOpts{
emailFolders: a, ContactFolders: a,
eventCalendars: a, EmailFolders: a,
users: a, EventCalendars: a,
Users: a,
},
expectIncludeLen: 3, expectIncludeLen: 3,
}, },
{ {
name: "single user, single of each data", name: "single user, single of each data",
contacts: stub, opts: utils.ExchangeOpts{
contactFolders: stub, Contacts: stub,
emails: stub, ContactFolders: stub,
emailFolders: stub, Emails: stub,
events: stub, EmailFolders: stub,
eventCalendars: stub, Events: stub,
users: stub, EventCalendars: stub,
Users: stub,
},
expectIncludeLen: 3, expectIncludeLen: 3,
}, },
{ {
name: "single user, single of each folder", name: "single user, single of each folder",
contactFolders: stub, opts: utils.ExchangeOpts{
emailFolders: stub, ContactFolders: stub,
eventCalendars: stub, EmailFolders: stub,
users: stub, EventCalendars: stub,
Users: stub,
},
expectIncludeLen: 3, expectIncludeLen: 3,
}, },
{ {
name: "any users, contacts", name: "any users, contacts",
contacts: a, opts: utils.ExchangeOpts{
contactFolders: stub, Contacts: a,
users: a, ContactFolders: stub,
Users: a,
},
expectIncludeLen: 1, expectIncludeLen: 1,
}, },
{ {
name: "single user, contacts", name: "single user, contacts",
contacts: stub, opts: utils.ExchangeOpts{
contactFolders: stub, Contacts: stub,
users: stub, ContactFolders: stub,
Users: stub,
},
expectIncludeLen: 1, expectIncludeLen: 1,
}, },
{ {
name: "any users, emails", name: "any users, emails",
emails: a, opts: utils.ExchangeOpts{
emailFolders: stub, Emails: a,
users: a, EmailFolders: stub,
Users: a,
},
expectIncludeLen: 1, expectIncludeLen: 1,
}, },
{ {
name: "single user, emails", name: "single user, emails",
emails: stub, opts: utils.ExchangeOpts{
emailFolders: stub, Emails: stub,
users: stub, EmailFolders: stub,
Users: stub,
},
expectIncludeLen: 1, expectIncludeLen: 1,
}, },
{ {
name: "any users, events", name: "any users, events",
events: a, opts: utils.ExchangeOpts{
eventCalendars: a, Events: a,
users: a, EventCalendars: a,
Users: a,
},
expectIncludeLen: 1, expectIncludeLen: 1,
}, },
{ {
name: "single user, events", name: "single user, events",
events: stub, opts: utils.ExchangeOpts{
eventCalendars: stub, Events: stub,
users: stub, EventCalendars: stub,
Users: stub,
},
expectIncludeLen: 1, expectIncludeLen: 1,
}, },
{ {
name: "any users, contacts + email", name: "any users, contacts + email",
contacts: a, opts: utils.ExchangeOpts{
contactFolders: a, Contacts: a,
emails: a, ContactFolders: a,
emailFolders: a, Emails: a,
users: a, EmailFolders: a,
Users: a,
},
expectIncludeLen: 2, expectIncludeLen: 2,
}, },
{ {
name: "single users, contacts + email", name: "single users, contacts + email",
contacts: stub, opts: utils.ExchangeOpts{
contactFolders: stub, Contacts: stub,
emails: stub, ContactFolders: stub,
emailFolders: stub, Emails: stub,
users: stub, EmailFolders: stub,
Users: stub,
},
expectIncludeLen: 2, expectIncludeLen: 2,
}, },
{ {
name: "any users, email + event", name: "any users, email + event",
emails: a, opts: utils.ExchangeOpts{
emailFolders: a, Emails: a,
events: a, EmailFolders: a,
eventCalendars: a, Events: a,
users: a, EventCalendars: a,
Users: a,
},
expectIncludeLen: 2, expectIncludeLen: 2,
}, },
{ {
name: "single users, email + event", name: "single users, email + event",
emails: stub, opts: utils.ExchangeOpts{
emailFolders: stub, Emails: stub,
events: stub, EmailFolders: stub,
eventCalendars: stub, Events: stub,
users: stub, EventCalendars: stub,
Users: stub,
},
expectIncludeLen: 2, expectIncludeLen: 2,
}, },
{ {
name: "any users, event + contact", name: "any users, event + contact",
contacts: a, opts: utils.ExchangeOpts{
contactFolders: a, Contacts: a,
events: a, ContactFolders: a,
eventCalendars: a, Events: a,
users: a, EventCalendars: a,
Users: a,
},
expectIncludeLen: 2, expectIncludeLen: 2,
}, },
{ {
name: "single users, event + contact", name: "single users, event + contact",
contacts: stub, opts: utils.ExchangeOpts{
contactFolders: stub, Contacts: stub,
events: stub, ContactFolders: stub,
eventCalendars: stub, Events: stub,
users: stub, EventCalendars: stub,
Users: stub,
},
expectIncludeLen: 2, expectIncludeLen: 2,
}, },
{ {
name: "many users, events", name: "many users, events",
events: many, opts: utils.ExchangeOpts{
eventCalendars: many, Events: many,
users: many, EventCalendars: many,
Users: many,
},
expectIncludeLen: 1, expectIncludeLen: 1,
}, },
{ {
name: "many users, events + contacts", name: "many users, events + contacts",
contacts: many, opts: utils.ExchangeOpts{
contactFolders: many, Contacts: many,
events: many, ContactFolders: many,
eventCalendars: many, Events: many,
users: many, EventCalendars: many,
Users: many,
},
expectIncludeLen: 2, expectIncludeLen: 2,
}, },
{ {
name: "mail, no folder or user", name: "mail, no folder or user",
emails: stub, opts: utils.ExchangeOpts{
Emails: stub,
},
expectIncludeLen: 1, expectIncludeLen: 1,
}, },
{ {
name: "contacts, no folder or user", name: "contacts, no folder or user",
contacts: stub, opts: utils.ExchangeOpts{
Contacts: stub,
},
expectIncludeLen: 1, expectIncludeLen: 1,
}, },
{ {
name: "event, no folder or user", name: "event, no folder or user",
events: stub, opts: utils.ExchangeOpts{
Events: stub,
},
expectIncludeLen: 1, expectIncludeLen: 1,
}, },
} }
for _, test := range table { for _, test := range table {
suite.T().Run(test.name, func(t *testing.T) { suite.T().Run(test.name, func(t *testing.T) {
sel := selectors.NewExchangeRestore() sel := selectors.NewExchangeRestore()
utils.IncludeExchangeRestoreDataSelectors( utils.IncludeExchangeRestoreDataSelectors(sel, test.opts)
sel,
test.contacts,
test.contactFolders,
test.emails,
test.emailFolders,
test.events,
test.eventCalendars,
test.users)
assert.Len(t, sel.Includes, test.expectIncludeLen) assert.Len(t, sel.Includes, test.expectIncludeLen)
}) })
} }
@ -257,101 +297,112 @@ func (suite *ExchangeUtilsSuite) TestFilterExchangeBackupDetailInfoSelectors() {
stub := "id-stub" stub := "id-stub"
table := []struct { table := []struct {
name string name string
contactName string opts utils.ExchangeOpts
after, before, sender, subject string expectFilterLen int
organizer, recurs, startsAfter, startsBefore, eventSubject string
expectFilterLen int
}{ }{
{ {
name: "no selectors", name: "no selectors",
expectFilterLen: 0, expectFilterLen: 0,
}, },
{ {
name: "contactName", name: "contactName",
contactName: stub, opts: utils.ExchangeOpts{
ContactName: stub,
},
expectFilterLen: 1, expectFilterLen: 1,
}, },
{ {
name: "receivedAfter", name: "receivedAfter",
after: stub, opts: utils.ExchangeOpts{
EmailReceivedAfter: stub,
},
expectFilterLen: 1, expectFilterLen: 1,
}, },
{ {
name: "receivedAfter", name: "receivedAfter",
after: stub, opts: utils.ExchangeOpts{
EmailReceivedAfter: stub,
},
expectFilterLen: 1, expectFilterLen: 1,
}, },
{ {
name: "receivedBefore", name: "receivedBefore",
before: stub, opts: utils.ExchangeOpts{
EmailReceivedBefore: stub,
},
expectFilterLen: 1, expectFilterLen: 1,
}, },
{ {
name: "sender", name: "sender",
sender: stub, opts: utils.ExchangeOpts{
EmailSender: stub,
},
expectFilterLen: 1, expectFilterLen: 1,
}, },
{ {
name: "subject", name: "subject",
subject: stub, opts: utils.ExchangeOpts{
EmailSubject: stub,
},
expectFilterLen: 1, expectFilterLen: 1,
}, },
{ {
name: "organizer", name: "organizer",
organizer: stub, opts: utils.ExchangeOpts{
EventOrganizer: stub,
},
expectFilterLen: 1, expectFilterLen: 1,
}, },
{ {
name: "recurs", name: "recurs",
recurs: stub, opts: utils.ExchangeOpts{
EventRecurs: stub,
},
expectFilterLen: 1, expectFilterLen: 1,
}, },
{ {
name: "startsAfter", name: "startsAfter",
startsAfter: stub, opts: utils.ExchangeOpts{
EventStartsAfter: stub,
},
expectFilterLen: 1, expectFilterLen: 1,
}, },
{ {
name: "startsBefore", name: "startsBefore",
startsBefore: stub, opts: utils.ExchangeOpts{
EventStartsBefore: stub,
},
expectFilterLen: 1, expectFilterLen: 1,
}, },
{ {
name: "eventSubject", name: "eventSubject",
eventSubject: stub, opts: utils.ExchangeOpts{
EventSubject: stub,
},
expectFilterLen: 1, expectFilterLen: 1,
}, },
{ {
name: "one of each", name: "one of each",
contactName: stub, opts: utils.ExchangeOpts{
after: stub, ContactName: stub,
before: stub, EmailReceivedAfter: stub,
sender: stub, EmailReceivedBefore: stub,
subject: stub, EmailSender: stub,
organizer: stub, EmailSubject: stub,
recurs: stub, EventOrganizer: stub,
startsAfter: stub, EventRecurs: stub,
startsBefore: stub, EventStartsAfter: stub,
eventSubject: stub, EventStartsBefore: stub,
EventSubject: stub,
},
expectFilterLen: 10, expectFilterLen: 10,
}, },
} }
for _, test := range table { for _, test := range table {
suite.T().Run(test.name, func(t *testing.T) { suite.T().Run(test.name, func(t *testing.T) {
sel := selectors.NewExchangeRestore() sel := selectors.NewExchangeRestore()
utils.FilterExchangeRestoreInfoSelectors( utils.FilterExchangeRestoreInfoSelectors(sel, test.opts)
sel,
test.contactName,
test.after,
test.before,
test.sender,
test.subject,
test.organizer,
test.recurs,
test.startsAfter,
test.startsBefore,
test.eventSubject)
assert.Len(t, sel.Filters, test.expectFilterLen) assert.Len(t, sel.Filters, test.expectFilterLen)
}) })
} }