From 5070296e1897b3f6679581f354261907ca3f100e Mon Sep 17 00:00:00 2001 From: Keepers Date: Fri, 5 Aug 2022 13:05:45 -0600 Subject: [PATCH] add connect cli integration tests (#493) --- src/cli/backup/exchange.go | 42 ++++++----- src/cli/backup/exchange_test.go | 6 +- src/cli/config/config.go | 2 +- src/cli/repo/s3.go | 4 +- src/cli/repo/s3_integration_test.go | 111 +++++++++++++++++++++++++++- src/cli/restore/exchange.go | 14 ++-- src/cli/restore/exchange_test.go | 2 +- src/internal/tester/account.go | 2 +- src/internal/tester/config.go | 38 ++++++---- src/internal/tester/storage.go | 2 +- src/internal/tester/users.go | 2 +- 11 files changed, 175 insertions(+), 50 deletions(-) diff --git a/src/cli/backup/exchange.go b/src/cli/backup/exchange.go index a9689478e..1d79fdf13 100644 --- a/src/cli/backup/exchange.go +++ b/src/cli/backup/exchange.go @@ -53,7 +53,7 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command { switch parent.Use { case createCommand: - c, fs = utils.AddCommand(parent, exchangeCreateCmd) + c, fs = utils.AddCommand(parent, exchangeCreateCmd()) fs.StringSliceVar(&user, "user", nil, "Backup Exchange data by user ID; accepts "+utils.Wildcard+" to select all users") fs.BoolVar(&exchangeAll, "all", false, "Backup all Exchange data for all users") fs.StringSliceVar( @@ -64,10 +64,10 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command { options.AddOperationFlags(c) case listCommand: - c, _ = utils.AddCommand(parent, exchangeListCmd) + c, _ = utils.AddCommand(parent, exchangeListCmd()) case detailsCommand: - c, fs = utils.AddCommand(parent, exchangeDetailsCmd) + c, fs = utils.AddCommand(parent, exchangeDetailsCmd()) fs.StringVar(&backupID, "backup", "", "ID of the backup containing the details to be shown") cobra.CheckErr(c.MarkFlagRequired("backup")) @@ -107,11 +107,13 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command { // ------------------------------------------------------------------------------------------------ // `corso backup create exchange [...]` -var exchangeCreateCmd = &cobra.Command{ - Use: exchangeServiceCommand, - Short: "Backup M365 Exchange service data", - RunE: createExchangeCmd, - Args: cobra.NoArgs, +func exchangeCreateCmd() *cobra.Command { + return &cobra.Command{ + Use: exchangeServiceCommand, + Short: "Backup M365 Exchange service data", + RunE: createExchangeCmd, + Args: cobra.NoArgs, + } } // processes an exchange service backup. @@ -213,11 +215,13 @@ func validateExchangeBackupCreateFlags(all bool, users, data []string) error { // ------------------------------------------------------------------------------------------------ // `corso backup list exchange [...]` -var exchangeListCmd = &cobra.Command{ - Use: exchangeServiceCommand, - Short: "List the history of M365 Exchange service backups", - RunE: listExchangeCmd, - Args: cobra.NoArgs, +func exchangeListCmd() *cobra.Command { + return &cobra.Command{ + Use: exchangeServiceCommand, + Short: "List the history of M365 Exchange service backups", + RunE: listExchangeCmd, + Args: cobra.NoArgs, + } } // lists the history of backup operations @@ -258,11 +262,13 @@ func listExchangeCmd(cmd *cobra.Command, args []string) error { // ------------------------------------------------------------------------------------------------ // `corso backup details exchange [...]` -var exchangeDetailsCmd = &cobra.Command{ - Use: exchangeServiceCommand, - Short: "Shows the details of a M365 Exchange service backup", - RunE: detailsExchangeCmd, - Args: cobra.NoArgs, +func exchangeDetailsCmd() *cobra.Command { + return &cobra.Command{ + Use: exchangeServiceCommand, + Short: "Shows the details of a M365 Exchange service backup", + RunE: detailsExchangeCmd, + Args: cobra.NoArgs, + } } // lists the history of backup operations diff --git a/src/cli/backup/exchange_test.go b/src/cli/backup/exchange_test.go index 36379286d..185b3a19e 100644 --- a/src/cli/backup/exchange_test.go +++ b/src/cli/backup/exchange_test.go @@ -30,9 +30,9 @@ func (suite *ExchangeSuite) TestAddExchangeCommands() { expectShort string expectRunE func(*cobra.Command, []string) error }{ - {"create exchange", createCommand, expectUse, exchangeCreateCmd.Short, createExchangeCmd}, - {"list exchange", listCommand, expectUse, exchangeListCmd.Short, listExchangeCmd}, - {"details exchange", detailsCommand, expectUse, exchangeDetailsCmd.Short, detailsExchangeCmd}, + {"create exchange", createCommand, expectUse, exchangeCreateCmd().Short, createExchangeCmd}, + {"list exchange", listCommand, expectUse, exchangeListCmd().Short, listExchangeCmd}, + {"details exchange", detailsCommand, expectUse, exchangeDetailsCmd().Short, detailsExchangeCmd}, } for _, test := range table { suite.T().Run(test.name, func(t *testing.T) { diff --git a/src/cli/config/config.go b/src/cli/config/config.go index 9b8855a17..cf67cf831 100644 --- a/src/cli/config/config.go +++ b/src/cli/config/config.go @@ -90,7 +90,7 @@ func initWithViper(vpr *viper.Viper, configFP string) error { return errors.New("config file requires an extension e.g. `toml`") } fileName = strings.TrimSuffix(fileName, ext) - vpr.SetConfigType(ext[1:]) + vpr.SetConfigType(strings.TrimPrefix(ext, ".")) vpr.SetConfigName(fileName) return nil diff --git a/src/cli/repo/s3.go b/src/cli/repo/s3.go index e4601d2ee..b84c9c708 100644 --- a/src/cli/repo/s3.go +++ b/src/cli/repo/s3.go @@ -107,7 +107,7 @@ func initS3Cmd(cmd *cobra.Command, args []string) error { } defer utils.CloseRepo(ctx, r) - Infof("Initialized a S3 repository within bucket %s.\n", s3Cfg.Bucket) + Infof("Initialized a S3 repository within bucket %s.", s3Cfg.Bucket) if err = config.WriteRepoConfig(ctx, s3Cfg, m365); err != nil { return Only(errors.Wrap(err, "Failed to write repository configuration")) @@ -166,7 +166,7 @@ func connectS3Cmd(cmd *cobra.Command, args []string) error { } defer utils.CloseRepo(ctx, r) - Infof("Connected to S3 bucket %s.\n", s3Cfg.Bucket) + Infof("Connected to S3 bucket %s.", s3Cfg.Bucket) if err = config.WriteRepoConfig(ctx, s3Cfg, m365); err != nil { return Only(errors.Wrap(err, "Failed to write repository configuration")) diff --git a/src/cli/repo/s3_integration_test.go b/src/cli/repo/s3_integration_test.go index 307e155d9..eeea2c35d 100644 --- a/src/cli/repo/s3_integration_test.go +++ b/src/cli/repo/s3_integration_test.go @@ -9,6 +9,8 @@ import ( "github.com/alcionai/corso/cli" "github.com/alcionai/corso/cli/config" "github.com/alcionai/corso/internal/tester" + "github.com/alcionai/corso/pkg/account" + "github.com/alcionai/corso/pkg/repository" ) // --------------------------------------------------------------------------------------------------------- @@ -48,12 +50,10 @@ func (suite *S3IntegrationSuite) TestInitS3Cmd() { cfg, err := st.S3Config() require.NoError(t, err) - vpr, configFP, err := tester.MakeTempTestConfigClone(t) + vpr, configFP, err := tester.MakeTempTestConfigClone(t, nil) require.NoError(t, err) ctx = config.SetViper(ctx, vpr) - require.NoError(t, err) - cmd := tester.StubRootCmd( "repo", "init", "s3", "--config-file", configFP, @@ -64,3 +64,108 @@ func (suite *S3IntegrationSuite) TestInitS3Cmd() { // run the command require.NoError(t, cmd.ExecuteContext(ctx)) } + +func (suite *S3IntegrationSuite) TestInitS3Cmd_missingBucket() { + ctx := tester.NewContext() + t := suite.T() + + st, err := tester.NewPrefixedS3Storage(t) + require.NoError(t, err) + cfg, err := st.S3Config() + require.NoError(t, err) + + vpr, configFP, err := tester.MakeTempTestConfigClone(t, nil) + require.NoError(t, err) + ctx = config.SetViper(ctx, vpr) + + cmd := tester.StubRootCmd( + "repo", "init", "s3", + "--config-file", configFP, + "--prefix", cfg.Prefix) + cli.BuildCommandTree(cmd) + + // run the command + require.Error(t, cmd.ExecuteContext(ctx)) +} + +func (suite *S3IntegrationSuite) TestConnectS3Cmd() { + ctx := tester.NewContext() + t := suite.T() + + st, err := tester.NewPrefixedS3Storage(t) + require.NoError(t, err) + cfg, err := st.S3Config() + require.NoError(t, err) + + force := map[string]string{ + tester.TestCfgAccountProvider: "M365", + tester.TestCfgStorageProvider: "S3", + tester.TestCfgPrefix: cfg.Prefix, + } + vpr, configFP, err := tester.MakeTempTestConfigClone(t, force) + require.NoError(t, err) + ctx = config.SetViper(ctx, vpr) + + // init the repo first + _, err = repository.Initialize(ctx, account.Account{}, st) + require.NoError(t, err) + + // then connect to it + cmd := tester.StubRootCmd( + "repo", "connect", "s3", + "--config-file", configFP, + "--bucket", cfg.Bucket, + "--prefix", cfg.Prefix) + cli.BuildCommandTree(cmd) + + // run the command + require.NoError(t, cmd.ExecuteContext(ctx)) +} + +func (suite *S3IntegrationSuite) TestConnectS3Cmd_BadBucket() { + ctx := tester.NewContext() + t := suite.T() + + st, err := tester.NewPrefixedS3Storage(t) + require.NoError(t, err) + cfg, err := st.S3Config() + require.NoError(t, err) + + vpr, configFP, err := tester.MakeTempTestConfigClone(t, nil) + require.NoError(t, err) + ctx = config.SetViper(ctx, vpr) + + cmd := tester.StubRootCmd( + "repo", "connect", "s3", + "--config-file", configFP, + "--bucket", "wrong", + "--prefix", cfg.Prefix) + cli.BuildCommandTree(cmd) + + // run the command + require.Error(t, cmd.ExecuteContext(ctx)) +} + +func (suite *S3IntegrationSuite) TestConnectS3Cmd_BadPrefix() { + ctx := tester.NewContext() + t := suite.T() + + st, err := tester.NewPrefixedS3Storage(t) + require.NoError(t, err) + cfg, err := st.S3Config() + require.NoError(t, err) + + vpr, configFP, err := tester.MakeTempTestConfigClone(t, nil) + require.NoError(t, err) + ctx = config.SetViper(ctx, vpr) + + cmd := tester.StubRootCmd( + "repo", "connect", "s3", + "--config-file", configFP, + "--bucket", cfg.Bucket, + "--prefix", "wrong") + cli.BuildCommandTree(cmd) + + // run the command + require.Error(t, cmd.ExecuteContext(ctx)) +} diff --git a/src/cli/restore/exchange.go b/src/cli/restore/exchange.go index ab8ef0b1c..98c5ef80e 100644 --- a/src/cli/restore/exchange.go +++ b/src/cli/restore/exchange.go @@ -38,7 +38,7 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command { switch parent.Use { case restoreCommand: - c, fs = utils.AddCommand(parent, exchangeRestoreCmd) + c, fs = utils.AddCommand(parent, exchangeRestoreCmd()) fs.StringVar(&backupID, "backup", "", "ID of the backup to restore") cobra.CheckErr(c.MarkFlagRequired("backup")) @@ -78,11 +78,13 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command { const exchangeServiceCommand = "exchange" // `corso restore exchange [...]` -var exchangeRestoreCmd = &cobra.Command{ - Use: exchangeServiceCommand, - Short: "Restore M365 Exchange service data", - RunE: restoreExchangeCmd, - Args: cobra.NoArgs, +func exchangeRestoreCmd() *cobra.Command { + return &cobra.Command{ + Use: exchangeServiceCommand, + Short: "Restore M365 Exchange service data", + RunE: restoreExchangeCmd, + Args: cobra.NoArgs, + } } // processes an exchange service restore. diff --git a/src/cli/restore/exchange_test.go b/src/cli/restore/exchange_test.go index 1254963dd..0ad0571a1 100644 --- a/src/cli/restore/exchange_test.go +++ b/src/cli/restore/exchange_test.go @@ -30,7 +30,7 @@ func (suite *ExchangeSuite) TestAddExchangeCommands() { expectShort string expectRunE func(*cobra.Command, []string) error }{ - {"restore exchange", restoreCommand, expectUse, exchangeRestoreCmd.Short, restoreExchangeCmd}, + {"restore exchange", restoreCommand, expectUse, exchangeRestoreCmd().Short, restoreExchangeCmd}, } for _, test := range table { suite.T().Run(test.name, func(t *testing.T) { diff --git a/src/internal/tester/account.go b/src/internal/tester/account.go index c344e1d1f..4b693b697 100644 --- a/src/internal/tester/account.go +++ b/src/internal/tester/account.go @@ -24,7 +24,7 @@ func NewM365Account() (account.Account, error) { account.ProviderM365, account.M365Config{ M365: credentials.GetM365(), - TenantID: cfg[testCfgTenantID], + TenantID: cfg[TestCfgTenantID], }, ) } diff --git a/src/internal/tester/config.go b/src/internal/tester/config.go index d07665665..04cc2c5a9 100644 --- a/src/internal/tester/config.go +++ b/src/internal/tester/config.go @@ -14,13 +14,15 @@ import ( const ( // S3 config - testCfgBucket = "bucket" - testCfgEndpoint = "endpoint" - testCfgPrefix = "prefix" + TestCfgBucket = "bucket" + TestCfgEndpoint = "endpoint" + TestCfgPrefix = "prefix" + TestCfgStorageProvider = "provider" // M365 config - testCfgTenantID = "tenantid" - testCfgUserID = "m365userid" + TestCfgTenantID = "tenantid" + TestCfgUserID = "m365userid" + TestCfgAccountProvider = "account_provider" ) // test specific env vars @@ -90,11 +92,13 @@ func readTestConfig() (map[string]string, error) { } testEnv := map[string]string{} - fallbackTo(testEnv, testCfgBucket, vpr.GetString(testCfgBucket), "test-corso-repo-init") - fallbackTo(testEnv, testCfgEndpoint, vpr.GetString(testCfgEndpoint), "s3.amazonaws.com") - fallbackTo(testEnv, testCfgPrefix, vpr.GetString(testCfgPrefix)) - fallbackTo(testEnv, testCfgTenantID, os.Getenv(account.TenantID), vpr.GetString(testCfgTenantID)) - fallbackTo(testEnv, testCfgUserID, os.Getenv(EnvCorsoM365TestUserID), vpr.GetString(testCfgTenantID), "lidiah@8qzvrj.onmicrosoft.com") + fallbackTo(testEnv, TestCfgStorageProvider, vpr.GetString(TestCfgStorageProvider)) + fallbackTo(testEnv, TestCfgAccountProvider, vpr.GetString(TestCfgAccountProvider)) + fallbackTo(testEnv, TestCfgBucket, vpr.GetString(TestCfgBucket), "test-corso-repo-init") + fallbackTo(testEnv, TestCfgEndpoint, vpr.GetString(TestCfgEndpoint), "s3.amazonaws.com") + fallbackTo(testEnv, TestCfgPrefix, vpr.GetString(TestCfgPrefix)) + fallbackTo(testEnv, TestCfgTenantID, os.Getenv(account.TenantID), vpr.GetString(TestCfgTenantID)) + fallbackTo(testEnv, TestCfgUserID, os.Getenv(EnvCorsoM365TestUserID), vpr.GetString(TestCfgTenantID), "lidiah@8qzvrj.onmicrosoft.com") testEnv[EnvCorsoTestConfigFilePath] = os.Getenv(EnvCorsoTestConfigFilePath) testConfig = testEnv @@ -106,8 +110,11 @@ func readTestConfig() (map[string]string, error) { // (such as the CLI) to safely manipulate file contents without amending the user's // original file. // +// Attempts to copy values sourced from the caller's test config file. +// The overrides prop replaces config values with the provided value. +// // Returns a filepath string pointing to the location of the temp file. -func MakeTempTestConfigClone(t *testing.T) (*viper.Viper, string, error) { +func MakeTempTestConfigClone(t *testing.T, overrides map[string]string) (*viper.Viper, string, error) { cfg, err := readTestConfig() if err != nil { return nil, "", err @@ -125,15 +132,20 @@ func MakeTempTestConfigClone(t *testing.T) (*viper.Viper, string, error) { } vpr := viper.New() + ext := path.Ext(fName) vpr.SetConfigFile(tDirFp) vpr.AddConfigPath(tDir) - vpr.SetConfigType(path.Ext(fName)) - vpr.SetConfigName(fName) + vpr.SetConfigType(strings.TrimPrefix(ext, ".")) + vpr.SetConfigName(strings.TrimSuffix(fName, ext)) for k, v := range cfg { vpr.Set(k, v) } + for k, v := range overrides { + vpr.Set(k, v) + } + if err := vpr.WriteConfig(); err != nil { return nil, "", err } diff --git a/src/internal/tester/storage.go b/src/internal/tester/storage.go index 16c01ebbd..e3032efbb 100644 --- a/src/internal/tester/storage.go +++ b/src/internal/tester/storage.go @@ -29,7 +29,7 @@ func NewPrefixedS3Storage(t *testing.T) (storage.Storage, error) { storage.ProviderS3, storage.S3Config{ AWS: credentials.GetAWS(nil), - Bucket: cfg[testCfgBucket], + Bucket: cfg[TestCfgBucket], Prefix: t.Name() + "-" + now, }, storage.CommonConfig{ diff --git a/src/internal/tester/users.go b/src/internal/tester/users.go index 23f81c022..b9b9669f0 100644 --- a/src/internal/tester/users.go +++ b/src/internal/tester/users.go @@ -14,5 +14,5 @@ func M365UserID() (string, error) { return "", errors.Wrap(err, "retrieving m365 user id from test configuration") } - return cfg[testCfgUserID], nil + return cfg[TestCfgUserID], nil }