Fix most remaining wsl lint errors (#656)
* Fix wsl lint errors in pkg package * Fix wsl lint errors in most of internal package Leave some sub-packages out that have higher churn at the moment.
This commit is contained in:
parent
02c2b0b4d6
commit
09cc2769d9
@ -8,14 +8,17 @@ type StringConfigurer interface {
|
||||
// map[string]string matching type.
|
||||
func UnionStringConfigs(cfgs ...StringConfigurer) (map[string]string, error) {
|
||||
union := map[string]string{}
|
||||
|
||||
for _, cfg := range cfgs {
|
||||
c, err := cfg.StringConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for k, v := range c {
|
||||
union[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return union, nil
|
||||
}
|
||||
|
||||
@ -43,6 +43,7 @@ func (e Err) Format(s fmt.State, verb rune) {
|
||||
f.Format(s, verb)
|
||||
return
|
||||
}
|
||||
|
||||
// Formatting magic courtesy of github.com/pkg/errors.
|
||||
switch verb {
|
||||
case 'v':
|
||||
@ -50,6 +51,7 @@ func (e Err) Format(s fmt.State, verb rune) {
|
||||
fmt.Fprintf(s, "%+v\n", e.Cause())
|
||||
return
|
||||
}
|
||||
|
||||
fallthrough
|
||||
case 's', 'q':
|
||||
// nolint:errcheck
|
||||
|
||||
@ -39,6 +39,7 @@ func (suite *ErrorsUnitSuite) TestPropagatesIs() {
|
||||
err := assert.AnError
|
||||
te := testErr{*common.EncapsulateError(err)}
|
||||
te2 := testErr2{*common.EncapsulateError(te)}
|
||||
|
||||
assert.True(suite.T(), errors.Is(te2, err))
|
||||
}
|
||||
|
||||
@ -46,7 +47,8 @@ func (suite *ErrorsUnitSuite) TestPropagatesAs() {
|
||||
err := assert.AnError
|
||||
te := testErr{*common.EncapsulateError(err)}
|
||||
te2 := testErr2{*common.EncapsulateError(te)}
|
||||
var tmp testErr
|
||||
|
||||
tmp := testErr{}
|
||||
assert.True(suite.T(), errors.As(te2, &tmp))
|
||||
}
|
||||
|
||||
@ -54,14 +56,16 @@ func (suite *ErrorsUnitSuite) TestAs() {
|
||||
err := assert.AnError
|
||||
te := testErr{*common.EncapsulateError(err)}
|
||||
te2 := testErr2{*common.EncapsulateError(te)}
|
||||
var tmp testErr2
|
||||
|
||||
tmp := testErr2{}
|
||||
assert.True(suite.T(), errors.As(te2, &tmp))
|
||||
}
|
||||
|
||||
func (suite *ErrorsUnitSuite) TestAsIsUnique() {
|
||||
err := assert.AnError
|
||||
te := testErr{*common.EncapsulateError(err)}
|
||||
var tmp testErr2
|
||||
|
||||
tmp := testErr2{}
|
||||
assert.False(suite.T(), errors.As(te, &tmp))
|
||||
}
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ func ContainsString(super []string, sub string) bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@ -16,5 +17,6 @@ func First(vs ...string) string {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ func (suite *CommonSlicesSuite) TestContainsString() {
|
||||
target := "fnords"
|
||||
good := []string{"fnords"}
|
||||
bad := []string{"foo", "bar"}
|
||||
|
||||
assert.True(t, common.ContainsString(good, target))
|
||||
assert.False(t, common.ContainsString(bad, target))
|
||||
}
|
||||
|
||||
@ -34,13 +34,16 @@ func ParseTime(s string) (time.Time, error) {
|
||||
if len(s) == 0 {
|
||||
return time.Time{}, errors.New("cannot interpret an empty string as time.Time")
|
||||
}
|
||||
|
||||
t, err := time.Parse(StandardTimeFormat, s)
|
||||
if err == nil {
|
||||
return t.UTC(), nil
|
||||
}
|
||||
|
||||
t, err = time.Parse(SimpleDateTimeFormat, s)
|
||||
if err == nil {
|
||||
return t.UTC(), nil
|
||||
}
|
||||
|
||||
return time.Time{}, errors.New("unable to format time string: " + s)
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@ import (
|
||||
|
||||
"github.com/alcionai/corso/internal/connector"
|
||||
"github.com/alcionai/corso/internal/connector/support"
|
||||
"github.com/alcionai/corso/internal/data"
|
||||
"github.com/alcionai/corso/internal/kopia"
|
||||
"github.com/alcionai/corso/internal/model"
|
||||
"github.com/alcionai/corso/internal/stats"
|
||||
@ -78,13 +77,13 @@ type backupStats struct {
|
||||
|
||||
// Run begins a synchronous backup operation.
|
||||
func (op *BackupOperation) Run(ctx context.Context) (err error) {
|
||||
// TODO: persist initial state of backupOperation in modelstore
|
||||
|
||||
// persist operation results to the model store on exit
|
||||
var (
|
||||
opStats backupStats
|
||||
backupDetails *details.Details
|
||||
)
|
||||
// TODO: persist initial state of backupOperation in modelstore
|
||||
|
||||
// persist operation results to the model store on exit
|
||||
defer func() {
|
||||
err = op.persistResults(time.Now(), &opStats)
|
||||
if err != nil {
|
||||
@ -93,8 +92,8 @@ func (op *BackupOperation) Run(ctx context.Context) (err error) {
|
||||
|
||||
err = op.createBackupModels(ctx, opStats.k.SnapshotID, backupDetails)
|
||||
if err != nil {
|
||||
// todo: we're not persisting this yet, except for the error shown to the user.
|
||||
opStats.writeErr = err
|
||||
// todo: ^ we're not persisting this yet, except for the error shown to the user.
|
||||
}
|
||||
}()
|
||||
|
||||
@ -103,14 +102,15 @@ func (op *BackupOperation) Run(ctx context.Context) (err error) {
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "connecting to graph api")
|
||||
opStats.readErr = err
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var cs []data.Collection
|
||||
cs, err = gc.ExchangeDataCollection(ctx, op.Selectors)
|
||||
cs, err := gc.ExchangeDataCollection(ctx, op.Selectors)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "retrieving service data")
|
||||
opStats.readErr = err
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@ -119,8 +119,10 @@ func (op *BackupOperation) Run(ctx context.Context) (err error) {
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "backing up service data")
|
||||
opStats.writeErr = err
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
opStats.started = true
|
||||
opStats.gc = gc.AwaitStatus()
|
||||
|
||||
@ -139,6 +141,7 @@ func (op *BackupOperation) persistResults(
|
||||
op.Status = Completed
|
||||
if !opStats.started {
|
||||
op.Status = Failed
|
||||
|
||||
return multierror.Append(
|
||||
errors.New("errors prevented the operation from processing"),
|
||||
opStats.readErr,
|
||||
@ -174,10 +177,12 @@ func (op *BackupOperation) createBackupModels(
|
||||
op.Results.ReadWrites,
|
||||
op.Results.StartAndEndTime,
|
||||
)
|
||||
|
||||
err = op.store.Put(ctx, model.BackupSchema, b)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "creating backup model")
|
||||
}
|
||||
|
||||
op.Results.BackupID = b.ID
|
||||
|
||||
return nil
|
||||
|
||||
@ -82,6 +82,7 @@ func TestBackupOpIntegrationSuite(t *testing.T) {
|
||||
); err != nil {
|
||||
t.Skip(err)
|
||||
}
|
||||
|
||||
suite.Run(t, new(BackupOpIntegrationSuite))
|
||||
}
|
||||
|
||||
@ -164,7 +165,6 @@ func (suite *BackupOpIntegrationSuite) TestBackup_Run() {
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
// need to initialize the repository before we can test connecting to it.
|
||||
|
||||
@ -63,8 +63,10 @@ func (op operation) validate() error {
|
||||
if op.kopia == nil {
|
||||
return errors.New("missing kopia connection")
|
||||
}
|
||||
|
||||
if op.store == nil {
|
||||
return errors.New("missing modelstore")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@ func (suite *OperationSuite) TestNewOperation() {
|
||||
func (suite *OperationSuite) TestOperation_Validate() {
|
||||
kwStub := &kopia.Wrapper{}
|
||||
swStub := &store.Wrapper{}
|
||||
|
||||
table := []struct {
|
||||
name string
|
||||
kw *kopia.Wrapper
|
||||
|
||||
@ -81,16 +81,14 @@ type restoreStats struct {
|
||||
// Run begins a synchronous restore operation.
|
||||
func (op *RestoreOperation) Run(ctx context.Context) (err error) {
|
||||
// TODO: persist initial state of restoreOperation in modelstore
|
||||
|
||||
// persist operation results to the model store on exit
|
||||
opStats := restoreStats{}
|
||||
// TODO: persist results?
|
||||
defer func() {
|
||||
err = op.persistResults(time.Now(), &opStats)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: persist results?
|
||||
}()
|
||||
|
||||
// retrieve the restore point details
|
||||
@ -98,6 +96,7 @@ func (op *RestoreOperation) Run(ctx context.Context) (err error) {
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "getting backup details for restore")
|
||||
opStats.readErr = err
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@ -116,15 +115,19 @@ func (op *RestoreOperation) Run(ctx context.Context) (err error) {
|
||||
// todo: use path pkg for this
|
||||
fdsPaths := fds.Paths()
|
||||
paths := make([][]string, len(fdsPaths))
|
||||
|
||||
for i := range fdsPaths {
|
||||
paths[i] = strings.Split(fdsPaths[i], "/")
|
||||
}
|
||||
|
||||
dcs, err := op.kopia.RestoreMultipleItems(ctx, b.SnapshotID, paths)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "retrieving service data")
|
||||
opStats.readErr = err
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
opStats.cs = dcs
|
||||
|
||||
// restore those collections using graph
|
||||
@ -132,6 +135,7 @@ func (op *RestoreOperation) Run(ctx context.Context) (err error) {
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "connecting to graph api")
|
||||
opStats.writeErr = err
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@ -139,8 +143,10 @@ func (op *RestoreOperation) Run(ctx context.Context) (err error) {
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "restoring service data")
|
||||
opStats.writeErr = err
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
opStats.started = true
|
||||
opStats.gc = gc.AwaitStatus()
|
||||
logger.Ctx(ctx).Debug(gc.PrintableStatus())
|
||||
@ -157,8 +163,10 @@ func (op *RestoreOperation) persistResults(
|
||||
op.Results.CompletedAt = time.Now()
|
||||
|
||||
op.Status = Completed
|
||||
|
||||
if !opStats.started {
|
||||
op.Status = Failed
|
||||
|
||||
return multierror.Append(
|
||||
errors.New("errors prevented the operation from processing"),
|
||||
opStats.readErr,
|
||||
|
||||
@ -92,6 +92,7 @@ func TestRestoreOpIntegrationSuite(t *testing.T) {
|
||||
); err != nil {
|
||||
t.Skip(err)
|
||||
}
|
||||
|
||||
suite.Run(t, new(RestoreOpIntegrationSuite))
|
||||
}
|
||||
|
||||
@ -110,16 +111,19 @@ func (suite *RestoreOpIntegrationSuite) SetupSuite() {
|
||||
|
||||
k := kopia.NewConn(st)
|
||||
require.NoError(t, k.Initialize(ctx))
|
||||
|
||||
suite.kopiaCloser = func(ctx context.Context) {
|
||||
k.Close(ctx)
|
||||
}
|
||||
|
||||
kw, err := kopia.NewWrapper(k)
|
||||
require.NoError(t, err)
|
||||
|
||||
suite.kw = kw
|
||||
|
||||
ms, err := kopia.NewModelStore(k)
|
||||
require.NoError(t, err)
|
||||
|
||||
suite.ms = ms
|
||||
|
||||
sw := store.NewKopiaStore(ms)
|
||||
@ -148,9 +152,11 @@ func (suite *RestoreOpIntegrationSuite) TearDownSuite() {
|
||||
if suite.ms != nil {
|
||||
suite.ms.Close(ctx)
|
||||
}
|
||||
|
||||
if suite.kw != nil {
|
||||
suite.kw.Close(ctx)
|
||||
}
|
||||
|
||||
if suite.kopiaCloser != nil {
|
||||
suite.kopiaCloser(ctx)
|
||||
}
|
||||
|
||||
@ -28,5 +28,6 @@ func NewM365Account(t *testing.T) account.Account {
|
||||
},
|
||||
)
|
||||
require.NoError(t, err, "initializing account")
|
||||
|
||||
return acc
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ func StubRootCmd(args ...string) *cobra.Command {
|
||||
},
|
||||
}
|
||||
c.SetArgs(args)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
|
||||
@ -39,10 +39,12 @@ func cloneTestConfig() map[string]string {
|
||||
if testConfig == nil {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
clone := map[string]string{}
|
||||
for k, v := range testConfig {
|
||||
clone[k] = v
|
||||
}
|
||||
|
||||
return clone
|
||||
}
|
||||
|
||||
@ -55,7 +57,6 @@ func NewTestViper() (*viper.Viper, error) {
|
||||
}
|
||||
|
||||
// Or use a custom file location
|
||||
fileName := path.Base(configFilePath)
|
||||
ext := path.Ext(configFilePath)
|
||||
if len(ext) == 0 {
|
||||
return nil, errors.New("corso_test requires an extension")
|
||||
@ -64,6 +65,8 @@ func NewTestViper() (*viper.Viper, error) {
|
||||
vpr.SetConfigFile(configFilePath)
|
||||
vpr.AddConfigPath(path.Dir(configFilePath))
|
||||
vpr.SetConfigType(ext[1:])
|
||||
|
||||
fileName := path.Base(configFilePath)
|
||||
fileName = strings.TrimSuffix(fileName, ext)
|
||||
vpr.SetConfigName(fileName)
|
||||
|
||||
@ -105,9 +108,10 @@ func readTestConfig() (map[string]string, error) {
|
||||
vpr.GetString(TestCfgUserID),
|
||||
"lidiah@8qzvrj.onmicrosoft.com",
|
||||
)
|
||||
testEnv[EnvCorsoTestConfigFilePath] = os.Getenv(EnvCorsoTestConfigFilePath)
|
||||
|
||||
testEnv[EnvCorsoTestConfigFilePath] = os.Getenv(EnvCorsoTestConfigFilePath)
|
||||
testConfig = testEnv
|
||||
|
||||
return cloneTestConfig(), nil
|
||||
}
|
||||
|
||||
@ -130,6 +134,7 @@ func MakeTempTestConfigClone(t *testing.T, overrides map[string]string) (*viper.
|
||||
if len(fName) == 0 || fName == "." || fName == "/" {
|
||||
fName = ".corso_test.toml"
|
||||
}
|
||||
|
||||
tDir := t.TempDir()
|
||||
tDirFp := path.Join(tDir, fName)
|
||||
|
||||
@ -137,8 +142,8 @@ func MakeTempTestConfigClone(t *testing.T, overrides map[string]string) (*viper.
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
vpr := viper.New()
|
||||
ext := path.Ext(fName)
|
||||
vpr := viper.New()
|
||||
vpr.SetConfigFile(tDirFp)
|
||||
vpr.AddConfigPath(tDir)
|
||||
vpr.SetConfigType(strings.TrimPrefix(ext, "."))
|
||||
|
||||
@ -10,13 +10,16 @@ import (
|
||||
// If any of the env values are zero length, returns an error.
|
||||
func GetRequiredEnvVars(evs ...string) (map[string]string, error) {
|
||||
vals := map[string]string{}
|
||||
|
||||
for _, ev := range evs {
|
||||
ge := os.Getenv(ev)
|
||||
if len(ge) == 0 {
|
||||
return nil, errors.New(ev + " env var required for test suite")
|
||||
}
|
||||
|
||||
vals[ev] = ge
|
||||
}
|
||||
|
||||
return vals, nil
|
||||
}
|
||||
|
||||
@ -25,14 +28,17 @@ func GetRequiredEnvVars(evs ...string) (map[string]string, error) {
|
||||
// If any of the env values are zero length, returns an error.
|
||||
func GetRequiredEnvSls(evs ...[]string) (map[string]string, error) {
|
||||
vals := map[string]string{}
|
||||
|
||||
for _, ev := range evs {
|
||||
r, err := GetRequiredEnvVars(ev...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for k, v := range r {
|
||||
vals[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return vals, nil
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ func TestEnvvarsSuite(t *testing.T) {
|
||||
func (suite *EnvvarsTestSuite) TestRunOnAny() {
|
||||
envVariable := "TEST_ENVVARS_SUITE"
|
||||
os.Setenv(envVariable, "1")
|
||||
|
||||
table := []struct {
|
||||
name string
|
||||
param string
|
||||
@ -41,5 +42,6 @@ func (suite *EnvvarsTestSuite) TestRunOnAny() {
|
||||
test.function(suite.T(), result)
|
||||
})
|
||||
}
|
||||
|
||||
os.Unsetenv(envVariable)
|
||||
}
|
||||
|
||||
@ -35,11 +35,13 @@ func RunOnAny(tests ...string) error {
|
||||
for _, test := range tests {
|
||||
l += len(os.Getenv(test))
|
||||
}
|
||||
|
||||
if l == 0 {
|
||||
return fmt.Errorf(
|
||||
"%s env vars are not flagged for testing",
|
||||
strings.Join(tests, ", "))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -47,10 +49,13 @@ func RunOnAny(tests ...string) error {
|
||||
func LogTimeOfTest(t *testing.T) string {
|
||||
now := time.Now().UTC().Format(time.RFC3339Nano)
|
||||
name := t.Name()
|
||||
|
||||
if name == "" {
|
||||
t.Logf("Test run at %s.", now)
|
||||
return now
|
||||
}
|
||||
|
||||
t.Logf("%s run at %s", name, now)
|
||||
|
||||
return now
|
||||
}
|
||||
|
||||
@ -13,18 +13,24 @@ func LoadAFile(aFile string) ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
buffer := make([]byte, 0)
|
||||
reader := bufio.NewScanner(f)
|
||||
|
||||
for reader.Scan() {
|
||||
temp := reader.Bytes()
|
||||
buffer = append(buffer, temp...)
|
||||
}
|
||||
|
||||
aErr := reader.Err()
|
||||
if aErr != nil {
|
||||
return nil, aErr
|
||||
}
|
||||
|
||||
return buffer, nil
|
||||
}
|
||||
|
||||
return bytes, nil
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@ var AWSStorageCredEnvs = []string{
|
||||
// configs.
|
||||
func NewPrefixedS3Storage(t *testing.T) storage.Storage {
|
||||
now := LogTimeOfTest(t)
|
||||
|
||||
cfg, err := readTestConfig()
|
||||
require.NoError(t, err, "configuring storage from test file")
|
||||
|
||||
@ -39,5 +40,6 @@ func NewPrefixedS3Storage(t *testing.T) storage.Storage {
|
||||
},
|
||||
)
|
||||
require.NoError(t, err, "creating storage")
|
||||
|
||||
return st
|
||||
}
|
||||
|
||||
@ -13,5 +13,6 @@ import (
|
||||
func M365UserID(t *testing.T) string {
|
||||
cfg, err := readTestConfig()
|
||||
require.NoError(t, err, "retrieving m365 user id from test configuration")
|
||||
|
||||
return cfg[TestCfgUserID]
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@ type Account struct {
|
||||
// NewAccount aggregates all the supplied configurations into a single configuration
|
||||
func NewAccount(p accountProvider, cfgs ...common.StringConfigurer) (Account, error) {
|
||||
cs, err := common.UnionStringConfigs(cfgs...)
|
||||
|
||||
return Account{
|
||||
Provider: p,
|
||||
Config: cs,
|
||||
|
||||
@ -32,6 +32,7 @@ func (c M365Config) StringConfig() (map[string]string, error) {
|
||||
keyM365ClientSecret: c.ClientSecret,
|
||||
keyM365TenantID: c.TenantID,
|
||||
}
|
||||
|
||||
return cfg, c.validate()
|
||||
}
|
||||
|
||||
@ -43,6 +44,7 @@ func (a Account) M365Config() (M365Config, error) {
|
||||
c.ClientSecret = a.Config[keyM365ClientSecret]
|
||||
c.TenantID = a.Config[keyM365TenantID]
|
||||
}
|
||||
|
||||
return c, c.validate()
|
||||
}
|
||||
|
||||
@ -52,10 +54,12 @@ func (c M365Config) validate() error {
|
||||
credentials.ClientSecret: c.ClientSecret,
|
||||
TenantID: c.TenantID,
|
||||
}
|
||||
|
||||
for k, v := range check {
|
||||
if len(v) == 0 {
|
||||
return errors.Wrap(errMissingRequired, k)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -71,6 +71,7 @@ func PrintAll(ctx context.Context, bs []Backup) {
|
||||
for _, b := range bs {
|
||||
ps = append(ps, print.Printable(b))
|
||||
}
|
||||
|
||||
print.All(ctx, ps...)
|
||||
}
|
||||
|
||||
@ -111,6 +112,7 @@ func (b Backup) Headers() []string {
|
||||
func (b Backup) Values() []string {
|
||||
errCount := support.GetNumberOfErrors(b.ReadErrors) + support.GetNumberOfErrors(b.WriteErrors)
|
||||
status := fmt.Sprintf("%s (%d errors)", b.Status, errCount)
|
||||
|
||||
return []string{
|
||||
common.FormatTime(b.StartedAt),
|
||||
string(b.ID),
|
||||
|
||||
@ -27,6 +27,7 @@ func TestBackupSuite(t *testing.T) {
|
||||
func stubBackup(t time.Time) backup.Backup {
|
||||
sel := selectors.NewExchangeBackup()
|
||||
sel.Include(sel.Users(selectors.Any()))
|
||||
|
||||
return backup.Backup{
|
||||
BaseModel: model.BaseModel{
|
||||
ID: model.StableID("id"),
|
||||
@ -62,14 +63,15 @@ func (suite *BackupSuite) TestBackup_HeadersValues() {
|
||||
}
|
||||
hs := b.Headers()
|
||||
assert.Equal(t, expectHs, hs)
|
||||
nowFmt := common.FormatTime(now)
|
||||
|
||||
nowFmt := common.FormatTime(now)
|
||||
expectVs := []string{
|
||||
nowFmt,
|
||||
"id",
|
||||
"status (2 errors)",
|
||||
selectors.All,
|
||||
}
|
||||
|
||||
vs := b.Values()
|
||||
assert.Equal(t, expectVs, vs)
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ func (dm DetailsModel) PrintEntries(ctx context.Context) {
|
||||
for _, de := range dm.Entries {
|
||||
ps = append(ps, de)
|
||||
}
|
||||
|
||||
print.All(ctx, ps...)
|
||||
}
|
||||
|
||||
@ -33,9 +34,11 @@ func (dm DetailsModel) PrintEntries(ctx context.Context) {
|
||||
func (dm DetailsModel) Paths() []string {
|
||||
ents := dm.Entries
|
||||
r := make([]string, len(ents))
|
||||
|
||||
for i := range ents {
|
||||
r[i] = ents[i].RepoRef
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
@ -88,30 +91,38 @@ func (de DetailsEntry) MinimumPrintable() any {
|
||||
// for printing out to a terminal in a columnar display.
|
||||
func (de DetailsEntry) Headers() []string {
|
||||
hs := []string{"Repo Ref"}
|
||||
|
||||
if de.ItemInfo.Exchange != nil {
|
||||
hs = append(hs, de.ItemInfo.Exchange.Headers()...)
|
||||
}
|
||||
|
||||
if de.ItemInfo.Sharepoint != nil {
|
||||
hs = append(hs, de.ItemInfo.Sharepoint.Headers()...)
|
||||
}
|
||||
|
||||
if de.ItemInfo.OneDrive != nil {
|
||||
hs = append(hs, de.ItemInfo.OneDrive.Headers()...)
|
||||
}
|
||||
|
||||
return hs
|
||||
}
|
||||
|
||||
// Values returns the values matching the Headers list.
|
||||
func (de DetailsEntry) Values() []string {
|
||||
vs := []string{de.RepoRef}
|
||||
|
||||
if de.ItemInfo.Exchange != nil {
|
||||
vs = append(vs, de.ItemInfo.Exchange.Values()...)
|
||||
}
|
||||
|
||||
if de.ItemInfo.Sharepoint != nil {
|
||||
vs = append(vs, de.ItemInfo.Sharepoint.Values()...)
|
||||
}
|
||||
|
||||
if de.ItemInfo.OneDrive != nil {
|
||||
vs = append(vs, de.ItemInfo.OneDrive.Values()...)
|
||||
}
|
||||
|
||||
return vs
|
||||
}
|
||||
|
||||
|
||||
@ -19,8 +19,10 @@ func TestOptionsSuite(t *testing.T) {
|
||||
|
||||
func (suite *OptionsSuite) TestNewOptions() {
|
||||
t := suite.T()
|
||||
|
||||
o1 := control.NewOptions(true)
|
||||
assert.True(t, o1.FailFast, "failFast")
|
||||
|
||||
o2 := control.NewOptions(false)
|
||||
assert.False(t, o2.FailFast, "failFast")
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ func GetAWS(override map[string]string) AWS {
|
||||
if ovr, ok := override[AWSAccessKeyID]; ok && ovr != "" {
|
||||
accessKey = ovr
|
||||
}
|
||||
|
||||
secretKey := os.Getenv(AWSSecretAccessKey)
|
||||
sessToken := os.Getenv(AWSSessionToken)
|
||||
|
||||
@ -44,10 +45,12 @@ func (c AWS) Validate() error {
|
||||
AWSSecretAccessKey: c.SecretKey,
|
||||
AWSSessionToken: c.SessionToken,
|
||||
}
|
||||
|
||||
for k, v := range check {
|
||||
if len(v) == 0 {
|
||||
return errors.Wrap(errMissingRequired, k)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ func GetCorso() Corso {
|
||||
// todo (rkeeprs): read from either corso config file or env vars.
|
||||
// https://github.com/alcionai/corso/issues/120
|
||||
corsoPasswd := os.Getenv(CorsoPassword)
|
||||
|
||||
return Corso{
|
||||
CorsoPassword: corsoPasswd,
|
||||
}
|
||||
@ -30,10 +31,12 @@ func (c Corso) Validate() error {
|
||||
check := map[string]string{
|
||||
CorsoPassword: c.CorsoPassword,
|
||||
}
|
||||
|
||||
for k, v := range check {
|
||||
if len(v) == 0 {
|
||||
return errors.Wrap(errMissingRequired, k)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -33,10 +33,12 @@ func (c M365) Validate() error {
|
||||
ClientID: c.ClientID,
|
||||
ClientSecret: c.ClientSecret,
|
||||
}
|
||||
|
||||
for k, v := range check {
|
||||
if len(v) == 0 {
|
||||
return errors.Wrap(errMissingRequired, k)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -83,6 +83,7 @@ func NewIn(negate bool, category any, substr string) Filter {
|
||||
// Checks whether the filter matches the input
|
||||
func (f Filter) Matches(input string) bool {
|
||||
var cmp func(string, string) bool
|
||||
|
||||
switch f.Comparator {
|
||||
case Equal:
|
||||
cmp = equals
|
||||
@ -97,10 +98,12 @@ func (f Filter) Matches(input string) bool {
|
||||
case In:
|
||||
cmp = in
|
||||
}
|
||||
|
||||
result := cmp(f.Target, norm(input))
|
||||
if f.Negate {
|
||||
result = !result
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@ -68,14 +68,17 @@ func singleton(level logLevel) *zap.SugaredLogger {
|
||||
lgr *zap.Logger
|
||||
err error
|
||||
)
|
||||
|
||||
if level != Production {
|
||||
cfg := zap.NewDevelopmentConfig()
|
||||
|
||||
switch level {
|
||||
case Info:
|
||||
cfg.Level = zap.NewAtomicLevelAt(zapcore.InfoLevel)
|
||||
case Warn:
|
||||
cfg.Level = zap.NewAtomicLevelAt(zapcore.WarnLevel)
|
||||
}
|
||||
|
||||
lgr, err = cfg.Build()
|
||||
} else {
|
||||
lgr, err = zap.NewProduction()
|
||||
@ -87,6 +90,7 @@ func singleton(level logLevel) *zap.SugaredLogger {
|
||||
}
|
||||
|
||||
loggerton = lgr.Sugar()
|
||||
|
||||
return loggerton
|
||||
}
|
||||
|
||||
@ -126,6 +130,7 @@ func Seed(ctx context.Context) (ctxOut context.Context, zsl *zap.SugaredLogger)
|
||||
}
|
||||
|
||||
level = levelOf(levelString)
|
||||
|
||||
return // return values handled in defer
|
||||
}
|
||||
|
||||
@ -135,6 +140,7 @@ func Ctx(ctx context.Context) *zap.SugaredLogger {
|
||||
if l == nil {
|
||||
return singleton(levelOf(llFlag))
|
||||
}
|
||||
|
||||
return l.(*zap.SugaredLogger)
|
||||
}
|
||||
|
||||
@ -148,5 +154,6 @@ func levelOf(lvl string) logLevel {
|
||||
case "error":
|
||||
return Production
|
||||
}
|
||||
|
||||
return Info
|
||||
}
|
||||
|
||||
@ -70,6 +70,7 @@ func Initialize(
|
||||
dataLayer: w,
|
||||
modelStore: ms,
|
||||
}
|
||||
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
@ -109,6 +110,7 @@ func Connect(
|
||||
dataLayer: w,
|
||||
modelStore: ms,
|
||||
}
|
||||
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
@ -116,6 +118,7 @@ func (r *Repository) Close(ctx context.Context) error {
|
||||
if r.dataLayer != nil {
|
||||
err := r.dataLayer.Close(ctx)
|
||||
r.dataLayer = nil
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "closing corso DataLayer")
|
||||
}
|
||||
@ -124,8 +127,10 @@ func (r *Repository) Close(ctx context.Context) error {
|
||||
if r.modelStore == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := r.modelStore.Close(ctx)
|
||||
r.modelStore = nil
|
||||
|
||||
return errors.Wrap(err, "closing corso ModelStore")
|
||||
}
|
||||
|
||||
@ -191,5 +196,6 @@ func (r Repository) DeleteBackup(ctx context.Context, id model.StableID) error {
|
||||
}
|
||||
|
||||
sw := store.NewKopiaStore(r.modelStore)
|
||||
|
||||
return sw.DeleteBackup(ctx, id)
|
||||
}
|
||||
|
||||
@ -97,6 +97,7 @@ func TestRepositoryIntegrationSuite(t *testing.T) {
|
||||
); err != nil {
|
||||
t.Skip(err)
|
||||
}
|
||||
|
||||
suite.Run(t, new(RepositoryIntegrationSuite))
|
||||
}
|
||||
|
||||
|
||||
@ -40,6 +40,7 @@ func NewExchangeBackup() *ExchangeBackup {
|
||||
newSelector(ServiceExchange),
|
||||
},
|
||||
}
|
||||
|
||||
return &src
|
||||
}
|
||||
|
||||
@ -49,7 +50,9 @@ func (s Selector) ToExchangeBackup() (*ExchangeBackup, error) {
|
||||
if s.Service != ServiceExchange {
|
||||
return nil, badCastErr(ServiceExchange, s.Service)
|
||||
}
|
||||
|
||||
src := ExchangeBackup{exchange{s}}
|
||||
|
||||
return &src, nil
|
||||
}
|
||||
|
||||
@ -60,6 +63,7 @@ func NewExchangeRestore() *ExchangeRestore {
|
||||
newSelector(ServiceExchange),
|
||||
},
|
||||
}
|
||||
|
||||
return &src
|
||||
}
|
||||
|
||||
@ -69,7 +73,9 @@ func (s Selector) ToExchangeRestore() (*ExchangeRestore, error) {
|
||||
if s.Service != ServiceExchange {
|
||||
return nil, badCastErr(ServiceExchange, s.Service)
|
||||
}
|
||||
|
||||
src := ExchangeRestore{exchange{s}}
|
||||
|
||||
return &src, nil
|
||||
}
|
||||
|
||||
@ -163,6 +169,7 @@ func (s *exchange) Contacts(users, folders, contacts []string) []ExchangeScope {
|
||||
folders = normalize(folders)
|
||||
contacts = normalize(contacts)
|
||||
scopes := []ExchangeScope{}
|
||||
|
||||
for _, u := range users {
|
||||
for _, f := range folders {
|
||||
scopes = append(
|
||||
@ -171,6 +178,7 @@ func (s *exchange) Contacts(users, folders, contacts []string) []ExchangeScope {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return scopes
|
||||
}
|
||||
|
||||
@ -183,12 +191,14 @@ func (s *exchange) ContactFolders(users, folders []string) []ExchangeScope {
|
||||
users = normalize(users)
|
||||
folders = normalize(folders)
|
||||
scopes := []ExchangeScope{}
|
||||
|
||||
for _, u := range users {
|
||||
scopes = append(
|
||||
scopes,
|
||||
makeScope[ExchangeScope](u, Group, ExchangeContactFolder, folders),
|
||||
)
|
||||
}
|
||||
|
||||
return scopes
|
||||
}
|
||||
|
||||
@ -201,12 +211,14 @@ func (s *exchange) Events(users, events []string) []ExchangeScope {
|
||||
users = normalize(users)
|
||||
events = normalize(events)
|
||||
scopes := []ExchangeScope{}
|
||||
|
||||
for _, u := range users {
|
||||
scopes = append(
|
||||
scopes,
|
||||
makeScope[ExchangeScope](u, Item, ExchangeEvent, events),
|
||||
)
|
||||
}
|
||||
|
||||
return scopes
|
||||
}
|
||||
|
||||
@ -220,6 +232,7 @@ func (s *exchange) Mails(users, folders, mails []string) []ExchangeScope {
|
||||
folders = normalize(folders)
|
||||
mails = normalize(mails)
|
||||
scopes := []ExchangeScope{}
|
||||
|
||||
for _, u := range users {
|
||||
for _, f := range folders {
|
||||
scopes = append(
|
||||
@ -228,6 +241,7 @@ func (s *exchange) Mails(users, folders, mails []string) []ExchangeScope {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return scopes
|
||||
}
|
||||
|
||||
@ -240,12 +254,14 @@ func (s *exchange) MailFolders(users, folders []string) []ExchangeScope {
|
||||
users = normalize(users)
|
||||
folders = normalize(folders)
|
||||
scopes := []ExchangeScope{}
|
||||
|
||||
for _, u := range users {
|
||||
scopes = append(
|
||||
scopes,
|
||||
makeScope[ExchangeScope](u, Group, ExchangeMailFolder, folders),
|
||||
)
|
||||
}
|
||||
|
||||
return scopes
|
||||
}
|
||||
|
||||
@ -257,11 +273,13 @@ func (s *exchange) MailFolders(users, folders []string) []ExchangeScope {
|
||||
func (s *exchange) Users(users []string) []ExchangeScope {
|
||||
users = normalize(users)
|
||||
scopes := []ExchangeScope{}
|
||||
|
||||
for _, u := range users {
|
||||
scopes = append(scopes, makeScope[ExchangeScope](u, Group, ExchangeContactFolder, Any()))
|
||||
scopes = append(scopes, makeScope[ExchangeScope](u, Item, ExchangeEvent, Any()))
|
||||
scopes = append(scopes, makeScope[ExchangeScope](u, Group, ExchangeMailFolder, Any()))
|
||||
}
|
||||
|
||||
return scopes
|
||||
}
|
||||
|
||||
@ -327,6 +345,7 @@ func (d ExchangeDestination) GetOrDefault(cat exchangeCategory, current string)
|
||||
if !ok {
|
||||
return current
|
||||
}
|
||||
|
||||
return dest
|
||||
}
|
||||
|
||||
@ -336,11 +355,14 @@ func (d ExchangeDestination) Set(cat exchangeCategory, dest string) error {
|
||||
if len(dest) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
cs := cat.String()
|
||||
if curr, ok := d[cs]; ok {
|
||||
return existingDestinationErr(cs, curr)
|
||||
}
|
||||
|
||||
d[cs] = dest
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -424,6 +446,7 @@ func (ec exchangeCategory) leafCat() categorizer {
|
||||
case ExchangeMail, ExchangeMailFolder:
|
||||
return ExchangeMail
|
||||
}
|
||||
|
||||
return ec
|
||||
}
|
||||
|
||||
@ -451,6 +474,7 @@ func (ec exchangeCategory) pathValues(path []string) map[categorizer]string {
|
||||
if len(path) < 2 {
|
||||
return m
|
||||
}
|
||||
|
||||
m[ExchangeUser] = path[1]
|
||||
/*
|
||||
TODO/Notice:
|
||||
@ -465,20 +489,26 @@ func (ec exchangeCategory) pathValues(path []string) map[categorizer]string {
|
||||
if len(path) < 5 {
|
||||
return m
|
||||
}
|
||||
|
||||
m[ExchangeContactFolder] = path[3]
|
||||
m[ExchangeContact] = path[4]
|
||||
|
||||
case ExchangeEvent:
|
||||
if len(path) < 4 {
|
||||
return m
|
||||
}
|
||||
|
||||
m[ExchangeEvent] = path[3]
|
||||
|
||||
case ExchangeMail:
|
||||
if len(path) < 5 {
|
||||
return m
|
||||
}
|
||||
|
||||
m[ExchangeMailFolder] = path[3]
|
||||
m[ExchangeMail] = path[4]
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
@ -604,18 +634,23 @@ func (s ExchangeScope) matchesInfo(info *details.ExchangeInfo) bool {
|
||||
if info == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// the scope must define targets to match on
|
||||
filterCat := s.FilterCategory()
|
||||
targets := s.Get(filterCat)
|
||||
|
||||
if len(targets) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if targets[0] == AnyTgt {
|
||||
return true
|
||||
}
|
||||
|
||||
if targets[0] == NoneTgt {
|
||||
return false
|
||||
}
|
||||
|
||||
// any of the targets for a given info filter may succeed.
|
||||
for _, target := range targets {
|
||||
switch filterCat {
|
||||
@ -637,5 +672,6 @@ func (s ExchangeScope) matchesInfo(info *details.ExchangeInfo) bool {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@ -281,13 +281,16 @@ func (suite *ExchangeSelectorSuite) TestExchangeSelector_Exclude_Users() {
|
||||
|
||||
for _, scope := range scopes {
|
||||
assert.Contains(t, join(u1, u2), scope[ExchangeUser.String()])
|
||||
|
||||
if scope[scopeKeyCategory] == ExchangeContactFolder.String() {
|
||||
assert.Equal(t, scope[ExchangeContact.String()], AnyTgt)
|
||||
assert.Equal(t, scope[ExchangeContactFolder.String()], AnyTgt)
|
||||
}
|
||||
|
||||
if scope[scopeKeyCategory] == ExchangeEvent.String() {
|
||||
assert.Equal(t, scope[ExchangeEvent.String()], AnyTgt)
|
||||
}
|
||||
|
||||
if scope[scopeKeyCategory] == ExchangeMailFolder.String() {
|
||||
assert.Equal(t, scope[ExchangeMail.String()], AnyTgt)
|
||||
assert.Equal(t, scope[ExchangeMailFolder.String()], AnyTgt)
|
||||
@ -310,13 +313,16 @@ func (suite *ExchangeSelectorSuite) TestExchangeSelector_Include_Users() {
|
||||
|
||||
for _, scope := range scopes {
|
||||
assert.Contains(t, join(u1, u2), scope[ExchangeUser.String()])
|
||||
|
||||
if scope[scopeKeyCategory] == ExchangeContactFolder.String() {
|
||||
assert.Equal(t, scope[ExchangeContact.String()], AnyTgt)
|
||||
assert.Equal(t, scope[ExchangeContactFolder.String()], AnyTgt)
|
||||
}
|
||||
|
||||
if scope[scopeKeyCategory] == ExchangeEvent.String() {
|
||||
assert.Equal(t, scope[ExchangeEvent.String()], AnyTgt)
|
||||
}
|
||||
|
||||
if scope[scopeKeyCategory] == ExchangeMailFolder.String() {
|
||||
assert.Equal(t, scope[ExchangeMail.String()], AnyTgt)
|
||||
assert.Equal(t, scope[ExchangeMailFolder.String()], AnyTgt)
|
||||
@ -379,6 +385,7 @@ func (suite *ExchangeSelectorSuite) TestExchangeBackup_Scopes() {
|
||||
|
||||
scopes := eb.Scopes()
|
||||
assert.Len(suite.T(), scopes, 3)
|
||||
|
||||
for _, sc := range scopes {
|
||||
cat := sc.Category()
|
||||
suite.T().Run(cat.String(), func(t *testing.T) {
|
||||
@ -424,6 +431,7 @@ func (suite *ExchangeSelectorSuite) TestExchangeBackup_DiscreteScopes() {
|
||||
expect: Any(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
eb := NewExchangeBackup()
|
||||
@ -515,7 +523,6 @@ func (suite *ExchangeSelectorSuite) TestExchangeScope_Get() {
|
||||
ExchangeMailFolder,
|
||||
ExchangeUser,
|
||||
}
|
||||
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.String(), func(t *testing.T) {
|
||||
for _, sc := range scopes {
|
||||
@ -538,10 +545,12 @@ func (suite *ExchangeSelectorSuite) TestExchangeScope_Get() {
|
||||
|
||||
func (suite *ExchangeSelectorSuite) TestExchangeScope_MatchesInfo() {
|
||||
es := NewExchangeRestore()
|
||||
|
||||
const (
|
||||
sender = "smarf@2many.cooks"
|
||||
subject = "I have seen the fnords!"
|
||||
)
|
||||
|
||||
var (
|
||||
epoch = time.Time{}
|
||||
now = time.Now()
|
||||
@ -590,6 +599,7 @@ func (suite *ExchangeSelectorSuite) TestExchangeScope_MatchesPath() {
|
||||
fld = "mailFolder"
|
||||
mail = "mailID"
|
||||
)
|
||||
|
||||
var (
|
||||
path = []string{"tid", usr, "mail", fld, mail}
|
||||
es = NewExchangeRestore()
|
||||
@ -684,21 +694,26 @@ func (suite *ExchangeSelectorSuite) TestExchangeRestore_Reduce() {
|
||||
Entries: []details.DetailsEntry{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, r := range refs {
|
||||
deets.Entries = append(deets.Entries, details.DetailsEntry{
|
||||
RepoRef: r,
|
||||
})
|
||||
}
|
||||
|
||||
return deets
|
||||
}
|
||||
|
||||
const (
|
||||
contact = "tid/uid/contact/cfld/cid"
|
||||
event = "tid/uid/event/eid"
|
||||
mail = "tid/uid/mail/mfld/mid"
|
||||
)
|
||||
|
||||
arr := func(s ...string) []string {
|
||||
return s
|
||||
}
|
||||
|
||||
table := []struct {
|
||||
name string
|
||||
deets *details.Details
|
||||
@ -837,19 +852,24 @@ func (suite *ExchangeSelectorSuite) TestScopesByCategory() {
|
||||
events = es.Events(Any(), Any())
|
||||
mail = es.MailFolders(Any(), Any())
|
||||
)
|
||||
|
||||
type expect struct {
|
||||
contact int
|
||||
event int
|
||||
mail int
|
||||
}
|
||||
|
||||
type input []scope
|
||||
|
||||
makeInput := func(es ...[]ExchangeScope) []scope {
|
||||
mss := []scope{}
|
||||
|
||||
for _, sl := range es {
|
||||
for _, s := range sl {
|
||||
mss = append(mss, scope(s))
|
||||
}
|
||||
}
|
||||
|
||||
return mss
|
||||
}
|
||||
cats := map[pathType]exchangeCategory{
|
||||
@ -857,6 +877,7 @@ func (suite *ExchangeSelectorSuite) TestScopesByCategory() {
|
||||
exchangeEventPath: ExchangeEvent,
|
||||
exchangeMailPath: ExchangeMail,
|
||||
}
|
||||
|
||||
table := []struct {
|
||||
name string
|
||||
scopes input
|
||||
@ -880,10 +901,12 @@ func (suite *ExchangeSelectorSuite) TestScopesByCategory() {
|
||||
|
||||
func (suite *ExchangeSelectorSuite) TestPasses() {
|
||||
deets := details.DetailsEntry{}
|
||||
|
||||
const (
|
||||
mid = "mailID"
|
||||
cat = ExchangeMail
|
||||
)
|
||||
|
||||
var (
|
||||
es = NewExchangeRestore()
|
||||
anyUser = setScopesToDefault(es.Users(Any()))
|
||||
@ -934,6 +957,7 @@ func (suite *ExchangeSelectorSuite) TestPasses() {
|
||||
|
||||
func (suite *ExchangeSelectorSuite) TestContains() {
|
||||
target := "fnords"
|
||||
|
||||
var (
|
||||
es = NewExchangeRestore()
|
||||
anyUser = setScopesToDefault(es.Users(Any()))
|
||||
@ -943,6 +967,7 @@ func (suite *ExchangeSelectorSuite) TestContains() {
|
||||
wrongType = setScopesToDefault(es.Contacts(Any(), Any(), Any()))
|
||||
wrongTypeGoodTarget = setScopesToDefault(es.Contacts(Any(), Any(), Any()))
|
||||
)
|
||||
|
||||
table := []struct {
|
||||
name string
|
||||
scopes []ExchangeScope
|
||||
@ -977,6 +1002,7 @@ func (suite *ExchangeSelectorSuite) TestIsAny() {
|
||||
specificMail = setScopesToDefault(es.Mails(Any(), Any(), []string{"mail"}))
|
||||
anyMail = setScopesToDefault(es.Mails(Any(), Any(), Any()))
|
||||
)
|
||||
|
||||
table := []struct {
|
||||
name string
|
||||
scopes []ExchangeScope
|
||||
@ -1041,6 +1067,7 @@ func (suite *ExchangeSelectorSuite) TestExchangeCategory_PathValues() {
|
||||
ExchangeMailFolder: mailPath[3],
|
||||
ExchangeMail: mailPath[4],
|
||||
}
|
||||
|
||||
table := []struct {
|
||||
cat exchangeCategory
|
||||
path []string
|
||||
@ -1064,7 +1091,9 @@ func (suite *ExchangeSelectorSuite) TestExchangeCategory_PathKeys() {
|
||||
event := []categorizer{ExchangeUser, ExchangeEvent}
|
||||
mail := []categorizer{ExchangeUser, ExchangeMailFolder, ExchangeMail}
|
||||
user := []categorizer{ExchangeUser}
|
||||
|
||||
var empty []categorizer
|
||||
|
||||
table := []struct {
|
||||
cat exchangeCategory
|
||||
expect []categorizer
|
||||
|
||||
@ -24,6 +24,7 @@ func (mc mockCategorizer) String() string {
|
||||
case rootCatStub:
|
||||
return "root"
|
||||
}
|
||||
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
@ -70,6 +71,7 @@ func (ms mockScope) categorizer() categorizer {
|
||||
case leafCatStub.String():
|
||||
return leafCatStub
|
||||
}
|
||||
|
||||
return unknownCatStub
|
||||
}
|
||||
|
||||
@ -94,6 +96,7 @@ func stubScope(match string) mockScope {
|
||||
if len(match) > 0 {
|
||||
sm = match
|
||||
}
|
||||
|
||||
return mockScope{
|
||||
rootCatStub.String(): AnyTgt,
|
||||
scopeKeyCategory: rootCatStub.String(),
|
||||
@ -125,5 +128,6 @@ func setScopesToDefault[T scopeT](ts []T) []T {
|
||||
for _, s := range ts {
|
||||
s.setDefaults()
|
||||
}
|
||||
|
||||
return ts
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@ func NewOneDriveBackup() *OneDriveBackup {
|
||||
newSelector(ServiceOneDrive),
|
||||
},
|
||||
}
|
||||
|
||||
return &src
|
||||
}
|
||||
|
||||
@ -39,7 +40,9 @@ func (s Selector) ToOneDriveBackup() (*OneDriveBackup, error) {
|
||||
if s.Service != ServiceOneDrive {
|
||||
return nil, badCastErr(ServiceOneDrive, s.Service)
|
||||
}
|
||||
|
||||
src := OneDriveBackup{oneDrive{s}}
|
||||
|
||||
return &src, nil
|
||||
}
|
||||
|
||||
@ -110,9 +113,11 @@ func (s *oneDrive) Filter(scopes ...[]OneDriveScope) {
|
||||
func (s *oneDrive) Users(users []string) []OneDriveScope {
|
||||
users = normalize(users)
|
||||
scopes := []OneDriveScope{}
|
||||
|
||||
for _, u := range users {
|
||||
scopes = append(scopes, makeScope[OneDriveScope](u, Group, OneDriveUser, users))
|
||||
}
|
||||
|
||||
return scopes
|
||||
}
|
||||
|
||||
@ -197,6 +202,7 @@ func (c oneDriveCategory) pathValues(path []string) map[categorizer]string {
|
||||
if len(path) < 2 {
|
||||
return m
|
||||
}
|
||||
|
||||
m[OneDriveUser] = path[1]
|
||||
/*
|
||||
TODO/Notice:
|
||||
@ -306,12 +312,15 @@ func (s OneDriveScope) matchesInfo(info *details.OneDriveInfo) bool {
|
||||
// the scope must define targets to match on
|
||||
filterCat := s.FilterCategory()
|
||||
targets := s.Get(filterCat)
|
||||
|
||||
if len(targets) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if targets[0] == AnyTgt {
|
||||
return true
|
||||
}
|
||||
|
||||
if targets[0] == NoneTgt {
|
||||
return false
|
||||
}
|
||||
@ -323,5 +332,6 @@ func (s OneDriveScope) matchesInfo(info *details.OneDriveInfo) bool {
|
||||
return target != NoneTgt
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@ -60,6 +60,7 @@ func (suite *OneDriveSelectorSuite) TestOneDriveBackup_DiscreteScopes() {
|
||||
expect: Any(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range table {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
eb := NewOneDriveBackup()
|
||||
@ -82,6 +83,7 @@ func (suite *OneDriveSelectorSuite) TestOneDriveSelector_Users() {
|
||||
u1 = "u1"
|
||||
u2 = "u2"
|
||||
)
|
||||
|
||||
userScopes := sel.Users([]string{u1, u2})
|
||||
for _, scope := range userScopes {
|
||||
// Scope value is either u1 or u2
|
||||
|
||||
@ -128,6 +128,7 @@ func makeScope[T scopeT](
|
||||
cat.String(): join(vs...),
|
||||
cat.rootCat().String(): resource,
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
@ -157,19 +158,24 @@ func contains[T scopeT, C categoryT](s T, cat C, target string) bool {
|
||||
if !typeAndCategoryMatches(cat, s.categorizer()) {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(target) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
compare := s[cat.String()]
|
||||
if len(compare) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if compare == NoneTgt {
|
||||
return false
|
||||
}
|
||||
|
||||
if compare == AnyTgt {
|
||||
return true
|
||||
}
|
||||
|
||||
return strings.Contains(compare, target)
|
||||
}
|
||||
|
||||
@ -181,6 +187,7 @@ func getCatValue[T scopeT](s T, cat categorizer) []string {
|
||||
if !ok {
|
||||
return None()
|
||||
}
|
||||
|
||||
return split(v)
|
||||
}
|
||||
|
||||
@ -203,6 +210,7 @@ func isAnyTarget[T scopeT, C categoryT](s T, cat C) bool {
|
||||
if !typeAndCategoryMatches(cat, s.categorizer()) {
|
||||
return false
|
||||
}
|
||||
|
||||
return s[cat.String()] == AnyTgt
|
||||
}
|
||||
|
||||
@ -229,6 +237,7 @@ func reduce[T scopeT, C categoryT](
|
||||
for _, ent := range deets.Entries {
|
||||
// todo: use Path pkg for this
|
||||
path := strings.Split(ent.RepoRef, "/")
|
||||
|
||||
dc, ok := dataCategories[pathTypeIn(path)]
|
||||
if !ok {
|
||||
continue
|
||||
@ -249,6 +258,7 @@ func reduce[T scopeT, C categoryT](
|
||||
|
||||
reduced := &details.Details{DetailsModel: deets.DetailsModel}
|
||||
reduced.Entries = ents
|
||||
|
||||
return reduced
|
||||
}
|
||||
|
||||
@ -275,6 +285,7 @@ func pathTypeIn(path []string) pathType {
|
||||
if len(path) < 3 {
|
||||
return unknownPathType
|
||||
}
|
||||
|
||||
switch path[2] {
|
||||
case "mail":
|
||||
return exchangeMailPath
|
||||
@ -283,6 +294,7 @@ func pathTypeIn(path []string) pathType {
|
||||
case "event":
|
||||
return exchangeEventPath
|
||||
}
|
||||
|
||||
return unknownPathType
|
||||
}
|
||||
|
||||
@ -307,6 +319,7 @@ func scopesByCategory[T scopeT, C categoryT](
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
@ -328,12 +341,14 @@ func passes[T scopeT](
|
||||
if len(incs) > 0 {
|
||||
// at least one inclusion must apply.
|
||||
var included bool
|
||||
|
||||
for _, inc := range incs {
|
||||
if inc.matchesEntry(cat, pathValues, entry) {
|
||||
included = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !included {
|
||||
return false
|
||||
}
|
||||
@ -389,6 +404,7 @@ func matchesPathValues[T scopeT, C categoryT](
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@ -422,5 +438,6 @@ func typeAndCategoryMatches[C categoryT](a C, b categorizer) bool {
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return categoryMatches(a, bb)
|
||||
}
|
||||
|
||||
@ -226,6 +226,7 @@ func (suite *SelectorScopesSuite) TestReduce() {
|
||||
dataCats := map[pathType]mockCategorizer{
|
||||
unknownPathType: rootCatStub,
|
||||
}
|
||||
|
||||
for _, test := range reduceTestTable {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
ds := deets()
|
||||
@ -264,6 +265,7 @@ func (suite *SelectorScopesSuite) TestPasses() {
|
||||
cat := rootCatStub
|
||||
pathVals := map[categorizer]string{}
|
||||
entry := details.DetailsEntry{}
|
||||
|
||||
for _, test := range reduceTestTable {
|
||||
suite.T().Run(test.name, func(t *testing.T) {
|
||||
sel := test.sel()
|
||||
@ -284,10 +286,13 @@ func toMockScope(sc []scope) []mockScope {
|
||||
if len(sc) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
ms := []mockScope{}
|
||||
|
||||
for _, s := range sc {
|
||||
ms = append(ms, mockScope(s))
|
||||
}
|
||||
|
||||
return ms
|
||||
}
|
||||
|
||||
|
||||
@ -103,6 +103,7 @@ func (s Selector) String() string {
|
||||
if err != nil {
|
||||
return "error"
|
||||
}
|
||||
|
||||
return string(bs)
|
||||
}
|
||||
|
||||
@ -113,12 +114,14 @@ func appendScopes[T scopeT](to []scope, scopes ...[]T) []scope {
|
||||
if len(to) == 0 {
|
||||
to = []scope{}
|
||||
}
|
||||
|
||||
for _, scopeSl := range scopes {
|
||||
for _, s := range scopeSl {
|
||||
s.setDefaults()
|
||||
to = append(to, scope(s))
|
||||
}
|
||||
}
|
||||
|
||||
return to
|
||||
}
|
||||
|
||||
@ -126,9 +129,11 @@ func appendScopes[T scopeT](to []scope, scopes ...[]T) []scope {
|
||||
// future TODO: if Inclues is nil, return filters.
|
||||
func scopes[T scopeT](s Selector) []T {
|
||||
scopes := []T{}
|
||||
|
||||
for _, v := range s.Includes {
|
||||
scopes = append(scopes, T(v))
|
||||
}
|
||||
|
||||
return scopes
|
||||
}
|
||||
|
||||
@ -158,10 +163,11 @@ func discreteScopes[T scopeT, C categoryT](
|
||||
for k, v := range t {
|
||||
w[k] = v
|
||||
}
|
||||
|
||||
set(w, rootCat, jdid)
|
||||
t = w
|
||||
|
||||
}
|
||||
|
||||
sl = append(sl, t)
|
||||
}
|
||||
|
||||
@ -203,9 +209,11 @@ func (p Printable) Resources() string {
|
||||
if len(s) == 0 {
|
||||
s = resourcesShortFormat(p.Filters)
|
||||
}
|
||||
|
||||
if len(s) == 0 {
|
||||
s = "All"
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
@ -213,13 +221,16 @@ func (p Printable) Resources() string {
|
||||
// plus, if more exist, " (len-1 more)"
|
||||
func resourcesShortFormat(m map[string][]string) string {
|
||||
var s string
|
||||
|
||||
for k := range m {
|
||||
s = k
|
||||
break
|
||||
}
|
||||
|
||||
if len(s) > 0 && len(m) > 1 {
|
||||
s = fmt.Sprintf("%s (%d more)", s, len(m)-1)
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
@ -230,14 +241,18 @@ func toResourceTypeMap(ms []scope) map[string][]string {
|
||||
if len(ms) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
r := make(map[string][]string)
|
||||
|
||||
for _, m := range ms {
|
||||
res := m[scopeKeyResource]
|
||||
if res == AnyTgt {
|
||||
res = All
|
||||
}
|
||||
|
||||
r[res] = addToSet(r[res], m[scopeKeyDataType])
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
@ -248,11 +263,13 @@ func addToSet(set []string, v string) []string {
|
||||
if len(set) == 0 {
|
||||
return []string{v}
|
||||
}
|
||||
|
||||
for _, s := range set {
|
||||
if s == v {
|
||||
return set
|
||||
}
|
||||
}
|
||||
|
||||
return append(set, v)
|
||||
}
|
||||
|
||||
@ -293,13 +310,16 @@ func normalize(s []string) []string {
|
||||
if len(s) == 0 {
|
||||
return None()
|
||||
}
|
||||
|
||||
for _, e := range s {
|
||||
if e == AnyTgt {
|
||||
return Any()
|
||||
}
|
||||
|
||||
if e == NoneTgt {
|
||||
return None()
|
||||
}
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
@ -133,6 +133,7 @@ func (suite *SelectorSuite) TestContains() {
|
||||
does[key.String()] = target
|
||||
doesNot := stubScope("")
|
||||
doesNot[key.String()] = "smarf"
|
||||
|
||||
assert.True(t, contains(does, key, target), "does contain")
|
||||
assert.False(t, contains(doesNot, key, target), "does not contain")
|
||||
}
|
||||
|
||||
@ -26,16 +26,19 @@ func (c CommonConfig) StringConfig() (map[string]string, error) {
|
||||
keyCommonCorsoPassword: c.CorsoPassword,
|
||||
keyCommonKopiaCfgDir: c.KopiaCfgDir,
|
||||
}
|
||||
|
||||
return cfg, c.validate()
|
||||
}
|
||||
|
||||
// CommonConfig retrieves the CommonConfig details from the Storage config.
|
||||
func (s Storage) CommonConfig() (CommonConfig, error) {
|
||||
c := CommonConfig{}
|
||||
|
||||
if len(s.Config) > 0 {
|
||||
c.CorsoPassword = orEmptyString(s.Config[keyCommonCorsoPassword])
|
||||
c.KopiaCfgDir = orEmptyString(s.Config[keyCommonKopiaCfgDir])
|
||||
}
|
||||
|
||||
return c, c.validate()
|
||||
}
|
||||
|
||||
@ -44,6 +47,7 @@ func (c CommonConfig) validate() error {
|
||||
if len(c.CorsoPassword) == 0 {
|
||||
return errors.Wrap(errMissingRequired, credentials.CorsoPassword)
|
||||
}
|
||||
|
||||
// kopiaCfgFilePath is not required
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -43,12 +43,14 @@ func (c S3Config) StringConfig() (map[string]string, error) {
|
||||
keyS3SecretKey: c.SecretKey,
|
||||
keyS3SessionToken: c.SessionToken,
|
||||
}
|
||||
|
||||
return cfg, c.validate()
|
||||
}
|
||||
|
||||
// S3Config retrieves the S3Config details from the Storage config.
|
||||
func (s Storage) S3Config() (S3Config, error) {
|
||||
c := S3Config{}
|
||||
|
||||
if len(s.Config) > 0 {
|
||||
c.AccessKey = orEmptyString(s.Config[keyS3AccessKey])
|
||||
c.Bucket = orEmptyString(s.Config[keyS3Bucket])
|
||||
@ -57,6 +59,7 @@ func (s Storage) S3Config() (S3Config, error) {
|
||||
c.SecretKey = orEmptyString(s.Config[keyS3SecretKey])
|
||||
c.SessionToken = orEmptyString(s.Config[keyS3SessionToken])
|
||||
}
|
||||
|
||||
return c, c.validate()
|
||||
}
|
||||
|
||||
@ -72,5 +75,6 @@ func (c S3Config) validate() error {
|
||||
return errors.Wrap(errMissingRequired, k)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -38,6 +38,7 @@ type Storage struct {
|
||||
// NewStorage aggregates all the supplied configurations into a single configuration.
|
||||
func NewStorage(p storageProvider, cfgs ...common.StringConfigurer) (Storage, error) {
|
||||
cs, err := common.UnionStringConfigs(cfgs...)
|
||||
|
||||
return Storage{
|
||||
Provider: p,
|
||||
Config: cs,
|
||||
@ -53,8 +54,10 @@ func orEmptyString(v any) string {
|
||||
fmt.Printf("panic recovery casting %v to string\n", v)
|
||||
}
|
||||
}()
|
||||
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return v.(string)
|
||||
}
|
||||
|
||||
@ -14,10 +14,12 @@ import (
|
||||
// GetBackup gets a single backup by id.
|
||||
func (w Wrapper) GetBackup(ctx context.Context, backupID model.StableID) (*backup.Backup, error) {
|
||||
b := backup.Backup{}
|
||||
|
||||
err := w.Get(ctx, model.BackupSchema, backupID, &b)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getting backup")
|
||||
}
|
||||
|
||||
return &b, nil
|
||||
}
|
||||
|
||||
@ -27,15 +29,20 @@ func (w Wrapper) GetBackups(ctx context.Context) ([]backup.Backup, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bs := make([]backup.Backup, len(bms))
|
||||
|
||||
for i, bm := range bms {
|
||||
b := backup.Backup{}
|
||||
|
||||
err := w.GetWithModelStoreID(ctx, model.BackupSchema, bm.ModelStoreID, &b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bs[i] = b
|
||||
}
|
||||
|
||||
return bs, nil
|
||||
}
|
||||
|
||||
@ -45,19 +52,23 @@ func (w Wrapper) DeleteBackup(ctx context.Context, backupID model.StableID) erro
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := w.Delete(ctx, model.BackupDetailsSchema, deets.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return w.Delete(ctx, model.BackupSchema, backupID)
|
||||
}
|
||||
|
||||
// GetDetails gets the backup details by ID.
|
||||
func (w Wrapper) GetDetails(ctx context.Context, detailsID manifest.ID) (*details.Details, error) {
|
||||
d := details.Details{}
|
||||
|
||||
err := w.GetWithModelStoreID(ctx, model.BackupDetailsSchema, detailsID, &d)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getting details")
|
||||
}
|
||||
|
||||
return &d, nil
|
||||
}
|
||||
|
||||
|
||||
@ -65,6 +65,7 @@ func (mms *MockModelStore) Get(
|
||||
if mms.err != nil {
|
||||
return mms.err
|
||||
}
|
||||
|
||||
switch s {
|
||||
case model.BackupSchema:
|
||||
unmarshal(mms.backup, data)
|
||||
@ -73,6 +74,7 @@ func (mms *MockModelStore) Get(
|
||||
default:
|
||||
return errors.Errorf("schema %s not supported by mock Get", s)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -84,16 +86,20 @@ func (mms *MockModelStore) GetIDsForType(
|
||||
if mms.err != nil {
|
||||
return nil, mms.err
|
||||
}
|
||||
|
||||
switch s {
|
||||
case model.BackupSchema:
|
||||
b := backup.Backup{}
|
||||
unmarshal(mms.backup, &b)
|
||||
|
||||
return []*model.BaseModel{&b.BaseModel}, nil
|
||||
case model.BackupDetailsSchema:
|
||||
d := details.Details{}
|
||||
unmarshal(mms.backup, &d)
|
||||
|
||||
return []*model.BaseModel{&d.BaseModel}, nil
|
||||
}
|
||||
|
||||
return nil, errors.Errorf("schema %s not supported by mock GetIDsForType", s)
|
||||
}
|
||||
|
||||
@ -106,6 +112,7 @@ func (mms *MockModelStore) GetWithModelStoreID(
|
||||
if mms.err != nil {
|
||||
return mms.err
|
||||
}
|
||||
|
||||
switch s {
|
||||
case model.BackupSchema:
|
||||
unmarshal(mms.backup, data)
|
||||
@ -114,6 +121,7 @@ func (mms *MockModelStore) GetWithModelStoreID(
|
||||
default:
|
||||
return errors.Errorf("schema %s not supported by mock GetWithModelStoreID", s)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -130,6 +138,7 @@ func (mms *MockModelStore) Put(ctx context.Context, s model.Schema, m model.Mode
|
||||
default:
|
||||
return errors.Errorf("schema %s not supported by mock Put", s)
|
||||
}
|
||||
|
||||
return mms.err
|
||||
}
|
||||
|
||||
@ -142,5 +151,6 @@ func (mms *MockModelStore) Update(ctx context.Context, s model.Schema, m model.M
|
||||
default:
|
||||
return errors.Errorf("schema %s not supported by mock Update", s)
|
||||
}
|
||||
|
||||
return mms.err
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user