Fix wsl errors in cmd and cli packages (#651)
This commit is contained in:
parent
f24ad6ccbd
commit
88a318a7c0
@ -18,6 +18,7 @@ var serviceCommands = []func(parent *cobra.Command) *cobra.Command{
|
|||||||
// AddCommands attaches all `corso backup * *` commands to the parent.
|
// AddCommands attaches all `corso backup * *` commands to the parent.
|
||||||
func AddCommands(parent *cobra.Command) {
|
func AddCommands(parent *cobra.Command) {
|
||||||
parent.AddCommand(backupCmd)
|
parent.AddCommand(backupCmd)
|
||||||
|
|
||||||
for _, sc := range subCommands {
|
for _, sc := range subCommands {
|
||||||
backupCmd.AddCommand(sc)
|
backupCmd.AddCommand(sc)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,7 +53,6 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
|
|||||||
)
|
)
|
||||||
|
|
||||||
switch parent.Use {
|
switch parent.Use {
|
||||||
|
|
||||||
case createCommand:
|
case createCommand:
|
||||||
c, fs = utils.AddCommand(parent, exchangeCreateCmd())
|
c, fs = utils.AddCommand(parent, exchangeCreateCmd())
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
@ -191,6 +190,7 @@ func createExchangeCmd(cmd *cobra.Command, args []string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return Only(ctx, errors.Wrapf(err, "Failed to connect to the %s repository", s.Provider))
|
return Only(ctx, errors.Wrapf(err, "Failed to connect to the %s repository", s.Provider))
|
||||||
}
|
}
|
||||||
|
|
||||||
defer utils.CloseRepo(ctx, r)
|
defer utils.CloseRepo(ctx, r)
|
||||||
|
|
||||||
sel := exchangeBackupCreateSelectors(exchangeAll, user, exchangeData)
|
sel := exchangeBackupCreateSelectors(exchangeAll, user, exchangeData)
|
||||||
@ -211,6 +211,7 @@ func createExchangeCmd(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bu.Print(ctx)
|
bu.Print(ctx)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,11 +221,13 @@ func exchangeBackupCreateSelectors(all bool, users, data []string) selectors.Sel
|
|||||||
sel.Include(sel.Users(selectors.Any()))
|
sel.Include(sel.Users(selectors.Any()))
|
||||||
return sel.Selector
|
return sel.Selector
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
sel.Include(sel.ContactFolders(user, selectors.Any()))
|
sel.Include(sel.ContactFolders(user, selectors.Any()))
|
||||||
sel.Include(sel.MailFolders(user, selectors.Any()))
|
sel.Include(sel.MailFolders(user, selectors.Any()))
|
||||||
sel.Include(sel.Events(user, selectors.Any()))
|
sel.Include(sel.Events(user, selectors.Any()))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, d := range data {
|
for _, d := range data {
|
||||||
switch d {
|
switch d {
|
||||||
case dataContacts:
|
case dataContacts:
|
||||||
@ -235,6 +238,7 @@ func exchangeBackupCreateSelectors(all bool, users, data []string) selectors.Sel
|
|||||||
sel.Include(sel.Events(users, selectors.Any()))
|
sel.Include(sel.Events(users, selectors.Any()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sel.Selector
|
return sel.Selector
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,15 +246,18 @@ func validateExchangeBackupCreateFlags(all bool, users, data []string) error {
|
|||||||
if len(users) == 0 && !all {
|
if len(users) == 0 && !all {
|
||||||
return errors.New("requires one or more --user ids, the wildcard --user *, or the --all flag")
|
return errors.New("requires one or more --user ids, the wildcard --user *, or the --all flag")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(data) > 0 && all {
|
if len(data) > 0 && all {
|
||||||
return errors.New("--all does a backup on all data, and cannot be reduced with --data")
|
return errors.New("--all does a backup on all data, and cannot be reduced with --data")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, d := range data {
|
for _, d := range data {
|
||||||
if d != dataContacts && d != dataEmail && d != dataEvents {
|
if d != dataContacts && d != dataEmail && d != dataEvents {
|
||||||
return errors.New(
|
return errors.New(
|
||||||
d + " is an unrecognized data type; must be one of " + dataContacts + ", " + dataEmail + ", or " + dataEvents)
|
d + " is an unrecognized data type; must be one of " + dataContacts + ", " + dataEmail + ", or " + dataEvents)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,6 +297,7 @@ func listExchangeCmd(cmd *cobra.Command, args []string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return Only(ctx, errors.Wrapf(err, "Failed to connect to the %s repository", s.Provider))
|
return Only(ctx, errors.Wrapf(err, "Failed to connect to the %s repository", s.Provider))
|
||||||
}
|
}
|
||||||
|
|
||||||
defer utils.CloseRepo(ctx, r)
|
defer utils.CloseRepo(ctx, r)
|
||||||
|
|
||||||
bs, err := r.Backups(ctx)
|
bs, err := r.Backups(ctx)
|
||||||
@ -298,6 +306,7 @@ func listExchangeCmd(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
backup.PrintAll(ctx, bs)
|
backup.PrintAll(ctx, bs)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,6 +362,7 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return Only(ctx, errors.Wrapf(err, "Failed to connect to the %s repository", s.Provider))
|
return Only(ctx, errors.Wrapf(err, "Failed to connect to the %s repository", s.Provider))
|
||||||
}
|
}
|
||||||
|
|
||||||
defer utils.CloseRepo(ctx, r)
|
defer utils.CloseRepo(ctx, r)
|
||||||
|
|
||||||
d, _, err := r.BackupDetails(ctx, backupID)
|
d, _, err := r.BackupDetails(ctx, backupID)
|
||||||
@ -387,6 +397,7 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ds.PrintEntries(ctx)
|
ds.PrintEntries(ctx)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,6 +431,7 @@ func includeExchangeContacts(sel *selectors.ExchangeRestore, users, contactFolde
|
|||||||
if len(contactFolders) == 0 {
|
if len(contactFolders) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(contacts) > 0 {
|
if len(contacts) > 0 {
|
||||||
sel.Include(sel.Contacts(users, contactFolders, contacts))
|
sel.Include(sel.Contacts(users, contactFolders, contacts))
|
||||||
} else {
|
} else {
|
||||||
@ -431,6 +443,7 @@ func includeExchangeEmails(sel *selectors.ExchangeRestore, users, emailFolders,
|
|||||||
if len(emailFolders) == 0 {
|
if len(emailFolders) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(emails) > 0 {
|
if len(emails) > 0 {
|
||||||
sel.Include(sel.Mails(users, emailFolders, emails))
|
sel.Include(sel.Mails(users, emailFolders, emails))
|
||||||
} else {
|
} else {
|
||||||
@ -442,6 +455,7 @@ func includeExchangeEvents(sel *selectors.ExchangeRestore, users, events []strin
|
|||||||
if len(events) == 0 {
|
if len(events) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sel.Include(sel.Events(users, events))
|
sel.Include(sel.Events(users, events))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,6 +474,7 @@ func filterExchangeInfoMailReceivedAfter(sel *selectors.ExchangeRestore, receive
|
|||||||
if len(receivedAfter) == 0 {
|
if len(receivedAfter) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sel.Filter(sel.MailReceivedAfter(receivedAfter))
|
sel.Filter(sel.MailReceivedAfter(receivedAfter))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,6 +482,7 @@ func filterExchangeInfoMailReceivedBefore(sel *selectors.ExchangeRestore, receiv
|
|||||||
if len(receivedBefore) == 0 {
|
if len(receivedBefore) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sel.Filter(sel.MailReceivedBefore(receivedBefore))
|
sel.Filter(sel.MailReceivedBefore(receivedBefore))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,6 +490,7 @@ func filterExchangeInfoMailSender(sel *selectors.ExchangeRestore, sender string)
|
|||||||
if len(sender) == 0 {
|
if len(sender) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sel.Filter(sel.MailSender([]string{sender}))
|
sel.Filter(sel.MailSender([]string{sender}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,6 +498,7 @@ func filterExchangeInfoMailSubject(sel *selectors.ExchangeRestore, subject strin
|
|||||||
if len(subject) == 0 {
|
if len(subject) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sel.Filter(sel.MailSubject([]string{subject}))
|
sel.Filter(sel.MailSubject([]string{subject}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,24 +510,30 @@ func validateExchangeBackupDetailFlags(
|
|||||||
if len(backupID) == 0 {
|
if len(backupID) == 0 {
|
||||||
return errors.New("a backup ID is required")
|
return errors.New("a backup ID is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
lu := len(users)
|
lu := len(users)
|
||||||
lc, lcf := len(contacts), len(contactFolders)
|
lc, lcf := len(contacts), len(contactFolders)
|
||||||
le, lef := len(emails), len(emailFolders)
|
le, lef := len(emails), len(emailFolders)
|
||||||
lev := len(events)
|
lev := len(events)
|
||||||
|
|
||||||
if lu+lc+lcf+le+lef+lev == 0 {
|
if lu+lc+lcf+le+lef+lev == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if lu == 0 {
|
if lu == 0 {
|
||||||
return errors.New("requires one or more --user ids, the wildcard --user *, or the --all flag")
|
return errors.New("requires one or more --user ids, the wildcard --user *, or the --all flag")
|
||||||
}
|
}
|
||||||
|
|
||||||
if lc > 0 && lcf == 0 {
|
if lc > 0 && lcf == 0 {
|
||||||
return errors.New(
|
return errors.New(
|
||||||
"one or more --contact-folder ids or the wildcard --contact-folder * must be included to specify a --contact")
|
"one or more --contact-folder ids or the wildcard --contact-folder * must be included to specify a --contact")
|
||||||
}
|
}
|
||||||
|
|
||||||
if le > 0 && lef == 0 {
|
if le > 0 && lef == 0 {
|
||||||
return errors.New(
|
return errors.New(
|
||||||
"one or more --email-folder ids or the wildcard --email-folder * must be included to specify a --email")
|
"one or more --email-folder ids or the wildcard --email-folder * must be included to specify a --email")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -555,6 +579,7 @@ func deleteExchangeCmd(cmd *cobra.Command, args []string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return Only(ctx, errors.Wrapf(err, "Failed to connect to the %s repository", s.Provider))
|
return Only(ctx, errors.Wrapf(err, "Failed to connect to the %s repository", s.Provider))
|
||||||
}
|
}
|
||||||
|
|
||||||
defer utils.CloseRepo(ctx, r)
|
defer utils.CloseRepo(ctx, r)
|
||||||
|
|
||||||
if err := r.DeleteBackup(ctx, model.StableID(backupID)); err != nil {
|
if err := r.DeleteBackup(ctx, model.StableID(backupID)); err != nil {
|
||||||
|
|||||||
@ -46,6 +46,7 @@ func TestBackupExchangeIntegrationSuite(t *testing.T) {
|
|||||||
); err != nil {
|
); err != nil {
|
||||||
t.Skip(err)
|
t.Skip(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Run(t, new(BackupExchangeIntegrationSuite))
|
suite.Run(t, new(BackupExchangeIntegrationSuite))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,8 +71,8 @@ func (suite *BackupExchangeIntegrationSuite) SetupSuite() {
|
|||||||
}
|
}
|
||||||
suite.vpr, suite.cfgFP, err = tester.MakeTempTestConfigClone(t, force)
|
suite.vpr, suite.cfgFP, err = tester.MakeTempTestConfigClone(t, force)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
ctx := config.SetViper(tester.NewContext(), suite.vpr)
|
|
||||||
|
|
||||||
|
ctx := config.SetViper(tester.NewContext(), suite.vpr)
|
||||||
suite.m365UserID = tester.M365UserID(t)
|
suite.m365UserID = tester.M365UserID(t)
|
||||||
|
|
||||||
// init the repo first
|
// init the repo first
|
||||||
@ -89,8 +90,10 @@ func (suite *BackupExchangeIntegrationSuite) TestExchangeBackupCmd() {
|
|||||||
"--user", suite.m365UserID,
|
"--user", suite.m365UserID,
|
||||||
"--data", "email")
|
"--data", "email")
|
||||||
cli.BuildCommandTree(cmd)
|
cli.BuildCommandTree(cmd)
|
||||||
var recorder strings.Builder
|
|
||||||
|
recorder := strings.Builder{}
|
||||||
cmd.SetOut(&recorder)
|
cmd.SetOut(&recorder)
|
||||||
|
|
||||||
ctx = print.SetRootCmd(ctx, cmd)
|
ctx = print.SetRootCmd(ctx, cmd)
|
||||||
|
|
||||||
// run the command
|
// run the command
|
||||||
@ -126,6 +129,7 @@ func TestPreparedBackupExchangeIntegrationSuite(t *testing.T) {
|
|||||||
); err != nil {
|
); err != nil {
|
||||||
t.Skip(err)
|
t.Skip(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Run(t, new(PreparedBackupExchangeIntegrationSuite))
|
suite.Run(t, new(PreparedBackupExchangeIntegrationSuite))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,8 +154,8 @@ func (suite *PreparedBackupExchangeIntegrationSuite) SetupSuite() {
|
|||||||
}
|
}
|
||||||
suite.vpr, suite.cfgFP, err = tester.MakeTempTestConfigClone(t, force)
|
suite.vpr, suite.cfgFP, err = tester.MakeTempTestConfigClone(t, force)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
ctx := config.SetViper(tester.NewContext(), suite.vpr)
|
|
||||||
|
|
||||||
|
ctx := config.SetViper(tester.NewContext(), suite.vpr)
|
||||||
suite.m365UserID = tester.M365UserID(t)
|
suite.m365UserID = tester.M365UserID(t)
|
||||||
|
|
||||||
// init the repo first
|
// init the repo first
|
||||||
@ -178,8 +182,10 @@ func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeListCmd() {
|
|||||||
"backup", "list", "exchange",
|
"backup", "list", "exchange",
|
||||||
"--config-file", suite.cfgFP)
|
"--config-file", suite.cfgFP)
|
||||||
cli.BuildCommandTree(cmd)
|
cli.BuildCommandTree(cmd)
|
||||||
var recorder strings.Builder
|
|
||||||
|
recorder := strings.Builder{}
|
||||||
cmd.SetOut(&recorder)
|
cmd.SetOut(&recorder)
|
||||||
|
|
||||||
ctx = print.SetRootCmd(ctx, cmd)
|
ctx = print.SetRootCmd(ctx, cmd)
|
||||||
|
|
||||||
// run the command
|
// run the command
|
||||||
@ -203,8 +209,10 @@ func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeDetailsCmd() {
|
|||||||
"--config-file", suite.cfgFP,
|
"--config-file", suite.cfgFP,
|
||||||
"--backup", string(suite.backupOp.Results.BackupID))
|
"--backup", string(suite.backupOp.Results.BackupID))
|
||||||
cli.BuildCommandTree(cmd)
|
cli.BuildCommandTree(cmd)
|
||||||
var recorder strings.Builder
|
|
||||||
|
recorder := strings.Builder{}
|
||||||
cmd.SetOut(&recorder)
|
cmd.SetOut(&recorder)
|
||||||
|
|
||||||
ctx = print.SetRootCmd(ctx, cmd)
|
ctx = print.SetRootCmd(ctx, cmd)
|
||||||
|
|
||||||
// run the command
|
// run the command
|
||||||
@ -212,6 +220,7 @@ func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeDetailsCmd() {
|
|||||||
|
|
||||||
// compare the output
|
// compare the output
|
||||||
result := recorder.String()
|
result := recorder.String()
|
||||||
|
|
||||||
for i, ent := range deets.Entries {
|
for i, ent := range deets.Entries {
|
||||||
t.Run(fmt.Sprintf("detail %d", i), func(t *testing.T) {
|
t.Run(fmt.Sprintf("detail %d", i), func(t *testing.T) {
|
||||||
assert.Contains(t, result, ent.RepoRef)
|
assert.Contains(t, result, ent.RepoRef)
|
||||||
@ -241,6 +250,7 @@ func TestBackupDeleteExchangeIntegrationSuite(t *testing.T) {
|
|||||||
); err != nil {
|
); err != nil {
|
||||||
t.Skip(err)
|
t.Skip(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Run(t, new(BackupDeleteExchangeIntegrationSuite))
|
suite.Run(t, new(BackupDeleteExchangeIntegrationSuite))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,6 +275,7 @@ func (suite *BackupDeleteExchangeIntegrationSuite) SetupSuite() {
|
|||||||
}
|
}
|
||||||
suite.vpr, suite.cfgFP, err = tester.MakeTempTestConfigClone(t, force)
|
suite.vpr, suite.cfgFP, err = tester.MakeTempTestConfigClone(t, force)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ctx := config.SetViper(tester.NewContext(), suite.vpr)
|
ctx := config.SetViper(tester.NewContext(), suite.vpr)
|
||||||
|
|
||||||
// init the repo first
|
// init the repo first
|
||||||
|
|||||||
@ -23,6 +23,7 @@ func TestExchangeSuite(t *testing.T) {
|
|||||||
|
|
||||||
func (suite *ExchangeSuite) TestAddExchangeCommands() {
|
func (suite *ExchangeSuite) TestAddExchangeCommands() {
|
||||||
expectUse := exchangeServiceCommand
|
expectUse := exchangeServiceCommand
|
||||||
|
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
use string
|
use string
|
||||||
@ -217,6 +218,7 @@ func (suite *ExchangeSuite) TestExchangeBackupCreateSelectors() {
|
|||||||
|
|
||||||
func (suite *ExchangeSuite) TestValidateBackupDetailFlags() {
|
func (suite *ExchangeSuite) TestValidateBackupDetailFlags() {
|
||||||
stub := []string{"id-stub"}
|
stub := []string{"id-stub"}
|
||||||
|
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
contacts, contactFolders, emails, emailFolders, events, users []string
|
contacts, contactFolders, emails, emailFolders, events, users []string
|
||||||
@ -302,6 +304,7 @@ func (suite *ExchangeSuite) TestValidateBackupDetailFlags() {
|
|||||||
func (suite *ExchangeSuite) TestIncludeExchangeBackupDetailDataSelectors() {
|
func (suite *ExchangeSuite) TestIncludeExchangeBackupDetailDataSelectors() {
|
||||||
stub := []string{"id-stub"}
|
stub := []string{"id-stub"}
|
||||||
a := []string{utils.Wildcard}
|
a := []string{utils.Wildcard}
|
||||||
|
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
contacts, contactFolders, emails, emailFolders, events, users []string
|
contacts, contactFolders, emails, emailFolders, events, users []string
|
||||||
@ -484,6 +487,7 @@ func (suite *ExchangeSuite) TestIncludeExchangeBackupDetailDataSelectors() {
|
|||||||
func (suite *ExchangeSuite) TestFilterExchangeBackupDetailInfoSelectors() {
|
func (suite *ExchangeSuite) TestFilterExchangeBackupDetailInfoSelectors() {
|
||||||
stub := "id-stub"
|
stub := "id-stub"
|
||||||
a := utils.Wildcard
|
a := utils.Wildcard
|
||||||
|
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
after, before, sender, subject string
|
after, before, sender, subject string
|
||||||
|
|||||||
@ -41,6 +41,7 @@ func handleCorsoCmd(cmd *cobra.Command, args []string) error {
|
|||||||
print.Infof(cmd.Context(), "Corso\nversion:\tpre-alpha\n")
|
print.Infof(cmd.Context(), "Corso\nversion:\tpre-alpha\n")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmd.Help()
|
return cmd.Help()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,6 +51,7 @@ func CorsoCommand() *cobra.Command {
|
|||||||
c := &cobra.Command{}
|
c := &cobra.Command{}
|
||||||
*c = *corsoCmd
|
*c = *corsoCmd
|
||||||
BuildCommandTree(c)
|
BuildCommandTree(c)
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,7 @@ func m365ConfigsFromViper(vpr *viper.Viper) (account.M365Config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
m365.TenantID = vpr.GetString(TenantIDKey)
|
m365.TenantID = vpr.GetString(TenantIDKey)
|
||||||
|
|
||||||
return m365, nil
|
return m365, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -34,10 +34,12 @@ var configFilePath string
|
|||||||
// adds the persistent flag --config-file to the provided command.
|
// adds the persistent flag --config-file to the provided command.
|
||||||
func AddConfigFlags(cmd *cobra.Command) {
|
func AddConfigFlags(cmd *cobra.Command) {
|
||||||
fs := cmd.PersistentFlags()
|
fs := cmd.PersistentFlags()
|
||||||
|
|
||||||
homeDir, err := os.UserHomeDir()
|
homeDir, err := os.UserHomeDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Err(cmd.Context(), "finding $HOME directory (default) for config file")
|
Err(cmd.Context(), "finding $HOME directory (default) for config file")
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&configFilePath,
|
&configFilePath,
|
||||||
"config-file",
|
"config-file",
|
||||||
@ -57,6 +59,7 @@ func InitFunc() func(*cobra.Command, []string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return Read(cmd.Context())
|
return Read(cmd.Context())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,6 +79,7 @@ func initWithViper(vpr *viper.Viper, configFP string) error {
|
|||||||
vpr.AddConfigPath(home)
|
vpr.AddConfigPath(home)
|
||||||
vpr.SetConfigType("toml")
|
vpr.SetConfigType("toml")
|
||||||
vpr.SetConfigName(".corso")
|
vpr.SetConfigName(".corso")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,11 +89,12 @@ func initWithViper(vpr *viper.Viper, configFP string) error {
|
|||||||
// work correctly (it does not use the configured file)
|
// work correctly (it does not use the configured file)
|
||||||
vpr.AddConfigPath(path.Dir(configFP))
|
vpr.AddConfigPath(path.Dir(configFP))
|
||||||
|
|
||||||
fileName := path.Base(configFP)
|
|
||||||
ext := path.Ext(configFP)
|
ext := path.Ext(configFP)
|
||||||
if len(ext) == 0 {
|
if len(ext) == 0 {
|
||||||
return errors.New("config file requires an extension e.g. `toml`")
|
return errors.New("config file requires an extension e.g. `toml`")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileName := path.Base(configFP)
|
||||||
fileName = strings.TrimSuffix(fileName, ext)
|
fileName = strings.TrimSuffix(fileName, ext)
|
||||||
vpr.SetConfigType(strings.TrimPrefix(ext, "."))
|
vpr.SetConfigType(strings.TrimPrefix(ext, "."))
|
||||||
vpr.SetConfigName(fileName)
|
vpr.SetConfigName(fileName)
|
||||||
@ -110,6 +115,7 @@ func SetViper(ctx context.Context, vpr *viper.Viper) context.Context {
|
|||||||
if vpr == nil {
|
if vpr == nil {
|
||||||
vpr = viper.GetViper()
|
vpr = viper.GetViper()
|
||||||
}
|
}
|
||||||
|
|
||||||
return context.WithValue(ctx, viperCtx{}, vpr)
|
return context.WithValue(ctx, viperCtx{}, vpr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,10 +124,12 @@ func SetViper(ctx context.Context, vpr *viper.Viper) context.Context {
|
|||||||
// (global) viper instance.
|
// (global) viper instance.
|
||||||
func GetViper(ctx context.Context) *viper.Viper {
|
func GetViper(ctx context.Context) *viper.Viper {
|
||||||
vprIface := ctx.Value(viperCtx{})
|
vprIface := ctx.Value(viperCtx{})
|
||||||
|
|
||||||
vpr, ok := vprIface.(*viper.Viper)
|
vpr, ok := vprIface.(*viper.Viper)
|
||||||
if vpr == nil || !ok {
|
if vpr == nil || !ok {
|
||||||
return viper.GetViper()
|
return viper.GetViper()
|
||||||
}
|
}
|
||||||
|
|
||||||
return vpr
|
return vpr
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,6 +145,7 @@ func Read(ctx context.Context) error {
|
|||||||
logger.Ctx(ctx).Debugw("found config file", "configFile", viper.ConfigFileUsed())
|
logger.Ctx(ctx).Debugw("found config file", "configFile", viper.ConfigFileUsed())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,8 +172,10 @@ func writeRepoConfigWithViper(vpr *viper.Viper, s3Config storage.S3Config, m365C
|
|||||||
if _, ok := err.(viper.ConfigFileAlreadyExistsError); ok {
|
if _, ok := err.(viper.ConfigFileAlreadyExistsError); ok {
|
||||||
return vpr.WriteConfig()
|
return vpr.WriteConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,6 +211,7 @@ func getStorageAndAccountWithViper(
|
|||||||
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
|
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
|
||||||
return store, acct, errors.Wrap(err, "reading corso config file: "+vpr.ConfigFileUsed())
|
return store, acct, errors.Wrap(err, "reading corso config file: "+vpr.ConfigFileUsed())
|
||||||
}
|
}
|
||||||
|
|
||||||
readConfigFromViper = false
|
readConfigFromViper = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,14 +250,17 @@ func mustMatchConfig(vpr *viper.Viper, m map[string]string) error {
|
|||||||
if len(v) == 0 {
|
if len(v) == 0 {
|
||||||
continue // empty variables will get caught by configuration validators, if necessary
|
continue // empty variables will get caught by configuration validators, if necessary
|
||||||
}
|
}
|
||||||
|
|
||||||
tomlK, ok := constToTomlKeyMap[k]
|
tomlK, ok := constToTomlKeyMap[k]
|
||||||
if !ok {
|
if !ok {
|
||||||
continue // m may declare values which aren't stored in the config file
|
continue // m may declare values which aren't stored in the config file
|
||||||
}
|
}
|
||||||
|
|
||||||
vv := vpr.GetString(tomlK)
|
vv := vpr.GetString(tomlK)
|
||||||
if v != vv {
|
if v != vv {
|
||||||
return errors.New("value of " + k + " (" + v + ") does not match corso configuration value (" + vv + ")")
|
return errors.New("value of " + k + " (" + v + ") does not match corso configuration value (" + vv + ")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -190,6 +190,7 @@ func TestConfigIntegrationSuite(t *testing.T) {
|
|||||||
); err != nil {
|
); err != nil {
|
||||||
t.Skip(err)
|
t.Skip(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Run(t, new(ConfigIntegrationSuite))
|
suite.Run(t, new(ConfigIntegrationSuite))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@ func s3ConfigsFromViper(vpr *viper.Viper) (storage.S3Config, error) {
|
|||||||
s3Config.Bucket = vpr.GetString(BucketNameKey)
|
s3Config.Bucket = vpr.GetString(BucketNameKey)
|
||||||
s3Config.Endpoint = vpr.GetString(EndpointKey)
|
s3Config.Endpoint = vpr.GetString(EndpointKey)
|
||||||
s3Config.Prefix = vpr.GetString(PrefixKey)
|
s3Config.Prefix = vpr.GetString(PrefixKey)
|
||||||
|
|
||||||
return s3Config, nil
|
return s3Config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,6 +79,7 @@ func configureStorage(
|
|||||||
if err := corso.Validate(); err != nil {
|
if err := corso.Validate(); err != nil {
|
||||||
return store, errors.Wrap(err, "validating corso credentials")
|
return store, errors.Wrap(err, "validating corso credentials")
|
||||||
}
|
}
|
||||||
|
|
||||||
cCfg := storage.CommonConfig{
|
cCfg := storage.CommonConfig{
|
||||||
Corso: corso,
|
Corso: corso,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,7 @@ func envCmd() *cobra.Command {
|
|||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
}
|
}
|
||||||
envCmd.SetHelpFunc(envGuide)
|
envCmd.SetHelpFunc(envGuide)
|
||||||
|
|
||||||
return envCmd
|
return envCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,6 +82,7 @@ func toPrintable(evs []envVar) []Printable {
|
|||||||
for _, ev := range evs {
|
for _, ev := range evs {
|
||||||
ps = append(ps, ev)
|
ps = append(ps, ev)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ps
|
return ps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,7 @@ func (suite *EnvSuite) TestAddEnvCommands() {
|
|||||||
cmd := &cobra.Command{Use: "root"}
|
cmd := &cobra.Command{Use: "root"}
|
||||||
|
|
||||||
AddCommands(cmd)
|
AddCommands(cmd)
|
||||||
|
|
||||||
c := envCmd()
|
c := envCmd()
|
||||||
require.NotNil(t, c)
|
require.NotNil(t, c)
|
||||||
|
|
||||||
|
|||||||
@ -30,9 +30,11 @@ func SetRootCmd(ctx context.Context, root *cobra.Command) context.Context {
|
|||||||
func getRootCmd(ctx context.Context) *cobra.Command {
|
func getRootCmd(ctx context.Context) *cobra.Command {
|
||||||
cmdIface := ctx.Value(rootCmdCtx{})
|
cmdIface := ctx.Value(rootCmdCtx{})
|
||||||
cmd, ok := cmdIface.(*cobra.Command)
|
cmd, ok := cmdIface.(*cobra.Command)
|
||||||
|
|
||||||
if cmd == nil || !ok {
|
if cmd == nil || !ok {
|
||||||
return &cobra.Command{}
|
return &cobra.Command{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,6 +69,7 @@ func err(w io.Writer, s ...any) {
|
|||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := append([]any{"Error: "}, s...)
|
msg := append([]any{"Error: "}, s...)
|
||||||
fmt.Fprint(w, msg...)
|
fmt.Fprint(w, msg...)
|
||||||
}
|
}
|
||||||
@ -82,6 +85,7 @@ func info(w io.Writer, s ...any) {
|
|||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprint(w, s...)
|
fmt.Fprint(w, s...)
|
||||||
fmt.Fprintf(w, "\n")
|
fmt.Fprintf(w, "\n")
|
||||||
}
|
}
|
||||||
@ -97,6 +101,7 @@ func infof(w io.Writer, t string, s ...any) {
|
|||||||
if len(t) == 0 {
|
if len(t) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(w, t, s...)
|
fmt.Fprintf(w, t, s...)
|
||||||
fmt.Fprintf(w, "\n")
|
fmt.Fprintf(w, "\n")
|
||||||
}
|
}
|
||||||
@ -129,6 +134,7 @@ func print(w io.Writer, p Printable) {
|
|||||||
outputJSON(w, p, outputAsJSONDebug)
|
outputJSON(w, p, outputAsJSONDebug)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
outputTable(w, []Printable{p})
|
outputTable(w, []Printable{p})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,10 +150,12 @@ func printAll(w io.Writer, ps []Printable) {
|
|||||||
if len(ps) == 0 {
|
if len(ps) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if outputAsJSON || outputAsJSONDebug {
|
if outputAsJSON || outputAsJSONDebug {
|
||||||
outputJSONArr(w, ps, outputAsJSONDebug)
|
outputJSONArr(w, ps, outputAsJSONDebug)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
outputTable(w, ps)
|
outputTable(w, ps)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,9 +175,11 @@ func outputTable(w io.Writer, ps []Printable) {
|
|||||||
Headers: ps[0].Headers(),
|
Headers: ps[0].Headers(),
|
||||||
Rows: [][]string{},
|
Rows: [][]string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, p := range ps {
|
for _, p := range ps {
|
||||||
t.Rows = append(t.Rows, p.Values())
|
t.Rows = append(t.Rows, p.Values())
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = t.WriteTable(
|
_ = t.WriteTable(
|
||||||
w,
|
w,
|
||||||
&table.Config{
|
&table.Config{
|
||||||
@ -188,11 +198,13 @@ func outputJSON(w io.Writer, p Printable, debug bool) {
|
|||||||
printJSON(w, p)
|
printJSON(w, p)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
printJSON(w, p.MinimumPrintable())
|
printJSON(w, p.MinimumPrintable())
|
||||||
}
|
}
|
||||||
|
|
||||||
func outputJSONArr(w io.Writer, ps []Printable, debug bool) {
|
func outputJSONArr(w io.Writer, ps []Printable, debug bool) {
|
||||||
sl := make([]any, 0, len(ps))
|
sl := make([]any, 0, len(ps))
|
||||||
|
|
||||||
for _, p := range ps {
|
for _, p := range ps {
|
||||||
if debug {
|
if debug {
|
||||||
sl = append(sl, p)
|
sl = append(sl, p)
|
||||||
@ -200,6 +212,7 @@ func outputJSONArr(w io.Writer, ps []Printable, debug bool) {
|
|||||||
sl = append(sl, p.MinimumPrintable())
|
sl = append(sl, p.MinimumPrintable())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printJSON(w, sl)
|
printJSON(w, sl)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,5 +223,6 @@ func printJSON(w io.Writer, a any) {
|
|||||||
fmt.Fprintf(w, "error formatting results to json: %v\n", err)
|
fmt.Fprintf(w, "error formatting results to json: %v\n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintln(w, string(pretty.Pretty(bs)))
|
fmt.Fprintln(w, string(pretty.Pretty(bs)))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,8 +30,9 @@ func (suite *PrintUnitSuite) TestOnly() {
|
|||||||
|
|
||||||
func (suite *PrintUnitSuite) TestErr() {
|
func (suite *PrintUnitSuite) TestErr() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
var b bytes.Buffer
|
b := bytes.Buffer{}
|
||||||
msg := "I have seen the fnords!"
|
msg := "I have seen the fnords!"
|
||||||
|
|
||||||
err(&b, msg)
|
err(&b, msg)
|
||||||
assert.Contains(t, b.String(), "Error: ")
|
assert.Contains(t, b.String(), "Error: ")
|
||||||
assert.Contains(t, b.String(), msg)
|
assert.Contains(t, b.String(), msg)
|
||||||
@ -39,17 +40,19 @@ func (suite *PrintUnitSuite) TestErr() {
|
|||||||
|
|
||||||
func (suite *PrintUnitSuite) TestInfo() {
|
func (suite *PrintUnitSuite) TestInfo() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
var b bytes.Buffer
|
b := bytes.Buffer{}
|
||||||
msg := "I have seen the fnords!"
|
msg := "I have seen the fnords!"
|
||||||
|
|
||||||
info(&b, msg)
|
info(&b, msg)
|
||||||
assert.Contains(t, b.String(), msg)
|
assert.Contains(t, b.String(), msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *PrintUnitSuite) TestInfof() {
|
func (suite *PrintUnitSuite) TestInfof() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
var b bytes.Buffer
|
b := bytes.Buffer{}
|
||||||
msg := "I have seen the fnords!"
|
msg := "I have seen the fnords!"
|
||||||
msg2 := "smarf"
|
msg2 := "smarf"
|
||||||
|
|
||||||
infof(&b, msg, msg2)
|
infof(&b, msg, msg2)
|
||||||
bs := b.String()
|
bs := b.String()
|
||||||
assert.Contains(t, bs, msg)
|
assert.Contains(t, bs, msg)
|
||||||
|
|||||||
@ -31,6 +31,7 @@ func addS3Commands(parent *cobra.Command) *cobra.Command {
|
|||||||
c *cobra.Command
|
c *cobra.Command
|
||||||
fs *pflag.FlagSet
|
fs *pflag.FlagSet
|
||||||
)
|
)
|
||||||
|
|
||||||
switch parent.Use {
|
switch parent.Use {
|
||||||
case initCommand:
|
case initCommand:
|
||||||
c, fs = utils.AddCommand(parent, s3InitCmd())
|
c, fs = utils.AddCommand(parent, s3InitCmd())
|
||||||
@ -47,6 +48,7 @@ func addS3Commands(parent *cobra.Command) *cobra.Command {
|
|||||||
// In general, we don't want to expose this flag to users and have them mistake it
|
// In general, we don't want to expose this flag to users and have them mistake it
|
||||||
// for a broad-scale idempotency solution. We can un-hide it later the need arises.
|
// for a broad-scale idempotency solution. We can un-hide it later the need arises.
|
||||||
cobra.CheckErr(fs.MarkHidden("succeed-if-exists"))
|
cobra.CheckErr(fs.MarkHidden("succeed-if-exists"))
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,6 +82,7 @@ func initS3Cmd(cmd *cobra.Command, args []string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return Only(ctx, err)
|
return Only(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s3Cfg, err := s.S3Config()
|
s3Cfg, err := s.S3Config()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Only(ctx, errors.Wrap(err, "Retrieving s3 configuration"))
|
return Only(ctx, errors.Wrap(err, "Retrieving s3 configuration"))
|
||||||
@ -103,8 +106,10 @@ func initS3Cmd(cmd *cobra.Command, args []string) error {
|
|||||||
if succeedIfExists && kopia.IsRepoAlreadyExistsError(err) {
|
if succeedIfExists && kopia.IsRepoAlreadyExistsError(err) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return Only(ctx, errors.Wrap(err, "Failed to initialize a new S3 repository"))
|
return Only(ctx, errors.Wrap(err, "Failed to initialize a new S3 repository"))
|
||||||
}
|
}
|
||||||
|
|
||||||
defer utils.CloseRepo(ctx, r)
|
defer utils.CloseRepo(ctx, r)
|
||||||
|
|
||||||
Infof(ctx, "Initialized a S3 repository within bucket %s.", s3Cfg.Bucket)
|
Infof(ctx, "Initialized a S3 repository within bucket %s.", s3Cfg.Bucket)
|
||||||
@ -112,6 +117,7 @@ func initS3Cmd(cmd *cobra.Command, args []string) error {
|
|||||||
if err = config.WriteRepoConfig(ctx, s3Cfg, m365); err != nil {
|
if err = config.WriteRepoConfig(ctx, s3Cfg, m365); err != nil {
|
||||||
return Only(ctx, errors.Wrap(err, "Failed to write repository configuration"))
|
return Only(ctx, errors.Wrap(err, "Failed to write repository configuration"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,10 +149,12 @@ func connectS3Cmd(cmd *cobra.Command, args []string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return Only(ctx, err)
|
return Only(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s3Cfg, err := s.S3Config()
|
s3Cfg, err := s.S3Config()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Only(ctx, errors.Wrap(err, "Retrieving s3 configuration"))
|
return Only(ctx, errors.Wrap(err, "Retrieving s3 configuration"))
|
||||||
}
|
}
|
||||||
|
|
||||||
m365, err := a.M365Config()
|
m365, err := a.M365Config()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Only(ctx, errors.Wrap(err, "Failed to parse m365 account config"))
|
return Only(ctx, errors.Wrap(err, "Failed to parse m365 account config"))
|
||||||
@ -164,6 +172,7 @@ func connectS3Cmd(cmd *cobra.Command, args []string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return Only(ctx, errors.Wrap(err, "Failed to connect to the S3 repository"))
|
return Only(ctx, errors.Wrap(err, "Failed to connect to the S3 repository"))
|
||||||
}
|
}
|
||||||
|
|
||||||
defer utils.CloseRepo(ctx, r)
|
defer utils.CloseRepo(ctx, r)
|
||||||
|
|
||||||
Infof(ctx, "Connected to S3 bucket %s.", s3Cfg.Bucket)
|
Infof(ctx, "Connected to S3 bucket %s.", s3Cfg.Bucket)
|
||||||
@ -171,6 +180,7 @@ func connectS3Cmd(cmd *cobra.Command, args []string) error {
|
|||||||
if err = config.WriteRepoConfig(ctx, s3Cfg, m365); err != nil {
|
if err = config.WriteRepoConfig(ctx, s3Cfg, m365); err != nil {
|
||||||
return Only(ctx, errors.Wrap(err, "Failed to write repository configuration"))
|
return Only(ctx, errors.Wrap(err, "Failed to write repository configuration"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@ func TestS3IntegrationSuite(t *testing.T) {
|
|||||||
); err != nil {
|
); err != nil {
|
||||||
t.Skip(err)
|
t.Skip(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Run(t, new(S3IntegrationSuite))
|
suite.Run(t, new(S3IntegrationSuite))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,6 +46,7 @@ func (suite *S3IntegrationSuite) TestInitS3Cmd() {
|
|||||||
|
|
||||||
vpr, configFP, err := tester.MakeTempTestConfigClone(t, nil)
|
vpr, configFP, err := tester.MakeTempTestConfigClone(t, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ctx = config.SetViper(ctx, vpr)
|
ctx = config.SetViper(ctx, vpr)
|
||||||
|
|
||||||
cmd := tester.StubRootCmd(
|
cmd := tester.StubRootCmd(
|
||||||
@ -68,6 +70,7 @@ func (suite *S3IntegrationSuite) TestInitS3Cmd_missingBucket() {
|
|||||||
|
|
||||||
vpr, configFP, err := tester.MakeTempTestConfigClone(t, nil)
|
vpr, configFP, err := tester.MakeTempTestConfigClone(t, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ctx = config.SetViper(ctx, vpr)
|
ctx = config.SetViper(ctx, vpr)
|
||||||
|
|
||||||
cmd := tester.StubRootCmd(
|
cmd := tester.StubRootCmd(
|
||||||
@ -95,6 +98,7 @@ func (suite *S3IntegrationSuite) TestConnectS3Cmd() {
|
|||||||
}
|
}
|
||||||
vpr, configFP, err := tester.MakeTempTestConfigClone(t, force)
|
vpr, configFP, err := tester.MakeTempTestConfigClone(t, force)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ctx = config.SetViper(ctx, vpr)
|
ctx = config.SetViper(ctx, vpr)
|
||||||
|
|
||||||
// init the repo first
|
// init the repo first
|
||||||
@ -123,6 +127,7 @@ func (suite *S3IntegrationSuite) TestConnectS3Cmd_BadBucket() {
|
|||||||
|
|
||||||
vpr, configFP, err := tester.MakeTempTestConfigClone(t, nil)
|
vpr, configFP, err := tester.MakeTempTestConfigClone(t, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ctx = config.SetViper(ctx, vpr)
|
ctx = config.SetViper(ctx, vpr)
|
||||||
|
|
||||||
cmd := tester.StubRootCmd(
|
cmd := tester.StubRootCmd(
|
||||||
@ -146,6 +151,7 @@ func (suite *S3IntegrationSuite) TestConnectS3Cmd_BadPrefix() {
|
|||||||
|
|
||||||
vpr, configFP, err := tester.MakeTempTestConfigClone(t, nil)
|
vpr, configFP, err := tester.MakeTempTestConfigClone(t, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ctx = config.SetViper(ctx, vpr)
|
ctx = config.SetViper(ctx, vpr)
|
||||||
|
|
||||||
cmd := tester.StubRootCmd(
|
cmd := tester.StubRootCmd(
|
||||||
|
|||||||
@ -21,6 +21,7 @@ func TestS3Suite(t *testing.T) {
|
|||||||
|
|
||||||
func (suite *S3Suite) TestAddS3Commands() {
|
func (suite *S3Suite) TestAddS3Commands() {
|
||||||
expectUse := s3ProviderCommand
|
expectUse := s3ProviderCommand
|
||||||
|
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
use string
|
use string
|
||||||
|
|||||||
@ -88,6 +88,7 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
|
|||||||
// others
|
// others
|
||||||
options.AddOperationFlags(c)
|
options.AddOperationFlags(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,6 +145,7 @@ func restoreExchangeCmd(cmd *cobra.Command, args []string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return Only(ctx, errors.Wrapf(err, "Failed to connect to the %s repository", s.Provider))
|
return Only(ctx, errors.Wrapf(err, "Failed to connect to the %s repository", s.Provider))
|
||||||
}
|
}
|
||||||
|
|
||||||
defer utils.CloseRepo(ctx, r)
|
defer utils.CloseRepo(ctx, r)
|
||||||
|
|
||||||
sel := selectors.NewExchangeRestore()
|
sel := selectors.NewExchangeRestore()
|
||||||
@ -177,6 +179,7 @@ func restoreExchangeCmd(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Infof(ctx, "Restored Exchange in %s for user %s.\n", s.Provider, user)
|
Infof(ctx, "Restored Exchange in %s for user %s.\n", s.Provider, user)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,6 +213,7 @@ func includeExchangeContacts(sel *selectors.ExchangeRestore, users, contactFolde
|
|||||||
if len(contactFolders) == 0 {
|
if len(contactFolders) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(contacts) > 0 {
|
if len(contacts) > 0 {
|
||||||
sel.Include(sel.Contacts(users, contactFolders, contacts))
|
sel.Include(sel.Contacts(users, contactFolders, contacts))
|
||||||
} else {
|
} else {
|
||||||
@ -221,6 +225,7 @@ func includeExchangeEmails(sel *selectors.ExchangeRestore, users, emailFolders,
|
|||||||
if len(emailFolders) == 0 {
|
if len(emailFolders) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(emails) > 0 {
|
if len(emails) > 0 {
|
||||||
sel.Include(sel.Mails(users, emailFolders, emails))
|
sel.Include(sel.Mails(users, emailFolders, emails))
|
||||||
} else {
|
} else {
|
||||||
@ -232,6 +237,7 @@ func includeExchangeEvents(sel *selectors.ExchangeRestore, users, events []strin
|
|||||||
if len(events) == 0 {
|
if len(events) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sel.Include(sel.Events(users, events))
|
sel.Include(sel.Events(users, events))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,6 +256,7 @@ func filterExchangeInfoMailReceivedAfter(sel *selectors.ExchangeRestore, receive
|
|||||||
if len(receivedAfter) == 0 {
|
if len(receivedAfter) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sel.Filter(sel.MailReceivedAfter(receivedAfter))
|
sel.Filter(sel.MailReceivedAfter(receivedAfter))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,6 +264,7 @@ func filterExchangeInfoMailReceivedBefore(sel *selectors.ExchangeRestore, receiv
|
|||||||
if len(receivedBefore) == 0 {
|
if len(receivedBefore) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sel.Filter(sel.MailReceivedBefore(receivedBefore))
|
sel.Filter(sel.MailReceivedBefore(receivedBefore))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,6 +272,7 @@ func filterExchangeInfoMailSender(sel *selectors.ExchangeRestore, sender string)
|
|||||||
if len(sender) == 0 {
|
if len(sender) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sel.Filter(sel.MailSender([]string{sender}))
|
sel.Filter(sel.MailSender([]string{sender}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,6 +280,7 @@ func filterExchangeInfoMailSubject(sel *selectors.ExchangeRestore, subject strin
|
|||||||
if len(subject) == 0 {
|
if len(subject) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sel.Filter(sel.MailSubject([]string{subject}))
|
sel.Filter(sel.MailSubject([]string{subject}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,24 +292,30 @@ func validateExchangeRestoreFlags(
|
|||||||
if len(backupID) == 0 {
|
if len(backupID) == 0 {
|
||||||
return errors.New("a backup ID is required")
|
return errors.New("a backup ID is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
lu := len(users)
|
lu := len(users)
|
||||||
lc, lcf := len(contacts), len(contactFolders)
|
lc, lcf := len(contacts), len(contactFolders)
|
||||||
le, lef := len(emails), len(emailFolders)
|
le, lef := len(emails), len(emailFolders)
|
||||||
lev := len(events)
|
lev := len(events)
|
||||||
|
|
||||||
// if only the backupID is populated, that's the same as --all
|
// if only the backupID is populated, that's the same as --all
|
||||||
if lu+lc+lcf+le+lef+lev == 0 {
|
if lu+lc+lcf+le+lef+lev == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if lu == 0 {
|
if lu == 0 {
|
||||||
return errors.New("requires one or more --user ids, the wildcard --user *, or the --all flag")
|
return errors.New("requires one or more --user ids, the wildcard --user *, or the --all flag")
|
||||||
}
|
}
|
||||||
|
|
||||||
if lc > 0 && lcf == 0 {
|
if lc > 0 && lcf == 0 {
|
||||||
return errors.New(
|
return errors.New(
|
||||||
"one or more --contact-folder ids or the wildcard --contact-folder * must be included to specify a --contact")
|
"one or more --contact-folder ids or the wildcard --contact-folder * must be included to specify a --contact")
|
||||||
}
|
}
|
||||||
|
|
||||||
if le > 0 && lef == 0 {
|
if le > 0 && lef == 0 {
|
||||||
return errors.New(
|
return errors.New(
|
||||||
"one or more --email-folder ids or the wildcard --email-folder * must be included to specify a --email")
|
"one or more --email-folder ids or the wildcard --email-folder * must be included to specify a --email")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,6 +37,7 @@ func TestRestoreExchangeIntegrationSuite(t *testing.T) {
|
|||||||
); err != nil {
|
); err != nil {
|
||||||
t.Skip(err)
|
t.Skip(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Run(t, new(RestoreExchangeIntegrationSuite))
|
suite.Run(t, new(RestoreExchangeIntegrationSuite))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,8 +63,8 @@ func (suite *RestoreExchangeIntegrationSuite) SetupSuite() {
|
|||||||
}
|
}
|
||||||
suite.vpr, suite.cfgFP, err = tester.MakeTempTestConfigClone(t, force)
|
suite.vpr, suite.cfgFP, err = tester.MakeTempTestConfigClone(t, force)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
ctx := config.SetViper(tester.NewContext(), suite.vpr)
|
|
||||||
|
|
||||||
|
ctx := config.SetViper(tester.NewContext(), suite.vpr)
|
||||||
suite.m365UserID = tester.M365UserID(t)
|
suite.m365UserID = tester.M365UserID(t)
|
||||||
|
|
||||||
// init the repo first
|
// init the repo first
|
||||||
|
|||||||
@ -23,6 +23,7 @@ func TestExchangeSuite(t *testing.T) {
|
|||||||
|
|
||||||
func (suite *ExchangeSuite) TestAddExchangeCommands() {
|
func (suite *ExchangeSuite) TestAddExchangeCommands() {
|
||||||
expectUse := exchangeServiceCommand
|
expectUse := exchangeServiceCommand
|
||||||
|
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
use string
|
use string
|
||||||
@ -52,6 +53,7 @@ func (suite *ExchangeSuite) TestAddExchangeCommands() {
|
|||||||
|
|
||||||
func (suite *ExchangeSuite) TestValidateExchangeRestoreFlags() {
|
func (suite *ExchangeSuite) TestValidateExchangeRestoreFlags() {
|
||||||
stub := []string{"id-stub"}
|
stub := []string{"id-stub"}
|
||||||
|
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
contacts, contactFolders, emails, emailFolders, events, users []string
|
contacts, contactFolders, emails, emailFolders, events, users []string
|
||||||
@ -137,6 +139,7 @@ func (suite *ExchangeSuite) TestValidateExchangeRestoreFlags() {
|
|||||||
func (suite *ExchangeSuite) TestIncludeExchangeRestoreDataSelectors() {
|
func (suite *ExchangeSuite) TestIncludeExchangeRestoreDataSelectors() {
|
||||||
stub := []string{"id-stub"}
|
stub := []string{"id-stub"}
|
||||||
a := []string{utils.Wildcard}
|
a := []string{utils.Wildcard}
|
||||||
|
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
contacts, contactFolders, emails, emailFolders, events, users []string
|
contacts, contactFolders, emails, emailFolders, events, users []string
|
||||||
@ -319,6 +322,7 @@ func (suite *ExchangeSuite) TestIncludeExchangeRestoreDataSelectors() {
|
|||||||
func (suite *ExchangeSuite) TestFilterExchangeRestoreInfoSelectors() {
|
func (suite *ExchangeSuite) TestFilterExchangeRestoreInfoSelectors() {
|
||||||
stub := "id-stub"
|
stub := "id-stub"
|
||||||
a := utils.Wildcard
|
a := utils.Wildcard
|
||||||
|
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
after, before, sender, subject string
|
after, before, sender, subject string
|
||||||
|
|||||||
@ -23,6 +23,7 @@ func RequireProps(props map[string]string) error {
|
|||||||
return errors.New(name + " is required to perform this command")
|
return errors.New(name + " is required to perform this command")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,6 +44,7 @@ func HasNoFlagsAndShownHelp(cmd *cobra.Command) bool {
|
|||||||
cobra.CheckErr(cmd.Help())
|
cobra.CheckErr(cmd.Help())
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -34,6 +34,7 @@ func main() {
|
|||||||
"cli-folder",
|
"cli-folder",
|
||||||
"./cmd/mdgen/cli_markdown",
|
"./cmd/mdgen/cli_markdown",
|
||||||
"relative path to the folder where cli docs will be generated (default: ./cmd/mdgen/cli_markdown)")
|
"relative path to the folder where cli docs will be generated (default: ./cmd/mdgen/cli_markdown)")
|
||||||
|
|
||||||
if err := cmd.Execute(); err != nil {
|
if err := cmd.Execute(); err != nil {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
@ -43,6 +44,7 @@ func genDocs(cmd *cobra.Command, args []string) {
|
|||||||
if err := makeDir(cliMarkdownDir); err != nil {
|
if err := makeDir(cliMarkdownDir); err != nil {
|
||||||
fatal(errors.Wrap(err, "preparing directory for markdown generation"))
|
fatal(errors.Wrap(err, "preparing directory for markdown generation"))
|
||||||
}
|
}
|
||||||
|
|
||||||
err := doc.GenMarkdownTree(cli.CorsoCommand(), cliMarkdownDir)
|
err := doc.GenMarkdownTree(cli.CorsoCommand(), cliMarkdownDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal(errors.Wrap(err, "generating the Corso CLI markdown"))
|
fatal(errors.Wrap(err, "generating the Corso CLI markdown"))
|
||||||
|
|||||||
@ -42,6 +42,7 @@ func doFolderPurge(cmd *cobra.Command, args []string) error {
|
|||||||
M365: credentials.GetM365(),
|
M365: credentials.GetM365(),
|
||||||
TenantID: common.First(tenant, os.Getenv(account.TenantID)),
|
TenantID: common.First(tenant, os.Getenv(account.TenantID)),
|
||||||
}
|
}
|
||||||
|
|
||||||
acct, err := account.NewAccount(account.ProviderM365, m365Cfg)
|
acct, err := account.NewAccount(account.ProviderM365, m365Cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Only(ctx, errors.Wrap(err, "finding m365 account details"))
|
return Only(ctx, errors.Wrap(err, "finding m365 account details"))
|
||||||
@ -67,21 +68,26 @@ func doFolderPurge(cmd *cobra.Command, args []string) error {
|
|||||||
return Only(ctx, errors.Wrap(err, "parsing before flag to time"))
|
return Only(ctx, errors.Wrap(err, "parsing before flag to time"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stLen := len(common.SimpleDateTimeFormat)
|
stLen := len(common.SimpleDateTimeFormat)
|
||||||
|
|
||||||
// delete files
|
// delete files
|
||||||
for _, mf := range mfs {
|
for _, mf := range mfs {
|
||||||
|
|
||||||
// compare the folder time to the deletion boundary time first
|
// compare the folder time to the deletion boundary time first
|
||||||
var del bool
|
var (
|
||||||
dnLen := len(mf.DisplayName)
|
del bool
|
||||||
|
dnLen = len(mf.DisplayName)
|
||||||
|
)
|
||||||
|
|
||||||
if dnLen > stLen {
|
if dnLen > stLen {
|
||||||
dnSuff := mf.DisplayName[dnLen-stLen:]
|
dnSuff := mf.DisplayName[dnLen-stLen:]
|
||||||
|
|
||||||
dnTime, err := common.ParseTime(dnSuff)
|
dnTime, err := common.ParseTime(dnSuff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Info(ctx, errors.Wrapf(err, "Error: deleting folder [%s]", mf.DisplayName))
|
Info(ctx, errors.Wrapf(err, "Error: deleting folder [%s]", mf.DisplayName))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
del = dnTime.Before(beforeTime)
|
del = dnTime.Before(beforeTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +96,7 @@ func doFolderPurge(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Info(ctx, "Deleting folder: ", mf.DisplayName)
|
Info(ctx, "Deleting folder: ", mf.DisplayName)
|
||||||
|
|
||||||
err = exchange.DeleteMailFolder(gc.Service(), user, mf.ID)
|
err = exchange.DeleteMailFolder(gc.Service(), user, mf.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Info(ctx, errors.Wrapf(err, "Error: deleting folder [%s]", mf.DisplayName))
|
Info(ctx, errors.Wrapf(err, "Error: deleting folder [%s]", mf.DisplayName))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user