diff --git a/src/cli/config/config.go b/src/cli/config/config.go index 0d4391dc9..44dcbf1e7 100644 --- a/src/cli/config/config.go +++ b/src/cli/config/config.go @@ -10,7 +10,9 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + "github.com/alcionai/corso/src/cli/flags" . "github.com/alcionai/corso/src/cli/print" + "github.com/alcionai/corso/src/internal/common/str" "github.com/alcionai/corso/src/pkg/account" "github.com/alcionai/corso/src/pkg/logger" "github.com/alcionai/corso/src/pkg/storage" @@ -38,6 +40,8 @@ const ( // Corso passphrase in config CorsoPassphrase = "passphrase" + CorsoUser = "corso_user" + CorsoHost = "corso_host" ) var ( @@ -50,9 +54,11 @@ var ( // RepoDetails holds the repository configuration retrieved from // the .corso.toml configuration file. type RepoDetails struct { - Storage storage.Storage - Account account.Account - RepoID string + Storage storage.Storage + Account account.Account + RepoID string + RepoUser string + RepoHost string } // Attempts to set the default dir and config file path. @@ -294,9 +300,20 @@ func getStorageAndAccountWithViper( return config, clues.Wrap(err, "retrieving storage provider details") } + config.RepoUser, config.RepoHost = getUserHost(vpr, readConfigFromViper) + return config, nil } +func getUserHost(vpr *viper.Viper, readConfigFromViper bool) (string, string) { + user := str.First(flags.UserMaintenanceFV, vpr.GetString(CorsoUser)) + host := str.First(flags.HostnameMaintenanceFV, vpr.GetString(CorsoHost)) + + // Fine if these are empty; later code will assign a meaningful default if + // needed. + return user, host +} + // --------------------------------------------------------------------------- // Helper funcs // --------------------------------------------------------------------------- diff --git a/src/cli/flags/maintenance.go b/src/cli/flags/maintenance.go index 2c512603a..f1ae253ae 100644 --- a/src/cli/flags/maintenance.go +++ b/src/cli/flags/maintenance.go @@ -7,13 +7,17 @@ import ( ) const ( - MaintenanceModeFN = "mode" - ForceMaintenanceFN = "force" + MaintenanceModeFN = "mode" + ForceMaintenanceFN = "force" + UserMaintenanceFN = "user" + HostnameMaintenanceFN = "host" ) var ( - MaintenanceModeFV string - ForceMaintenanceFV bool + MaintenanceModeFV string + ForceMaintenanceFV bool + UserMaintenanceFV string + HostnameMaintenanceFV string ) func AddMaintenanceModeFlag(cmd *cobra.Command) { @@ -39,3 +43,21 @@ func AddForceMaintenanceFlag(cmd *cobra.Command) { "Force maintenance. Caution: user must ensure this is not run concurrently on a single repo") cobra.CheckErr(fs.MarkHidden(ForceMaintenanceFN)) } + +func AddMaintenanceUserFlag(cmd *cobra.Command) { + fs := cmd.Flags() + fs.StringVar( + &UserMaintenanceFV, + UserMaintenanceFN, + "", + "Attempt to run maintenance as the specified user for the repo owner user") +} + +func AddMaintenanceHostnameFlag(cmd *cobra.Command) { + fs := cmd.Flags() + fs.StringVar( + &HostnameMaintenanceFV, + HostnameMaintenanceFN, + "", + "Attempt to run maintenance with the specified hostname for the repo owner hostname") +} diff --git a/src/cli/repo/repo.go b/src/cli/repo/repo.go index b25096d26..d9822c33e 100644 --- a/src/cli/repo/repo.go +++ b/src/cli/repo/repo.go @@ -46,6 +46,8 @@ func AddCommands(cmd *cobra.Command) { utils.MarkPreReleaseCommand()) flags.AddMaintenanceModeFlag(maintenanceCmd) flags.AddForceMaintenanceFlag(maintenanceCmd) + flags.AddMaintenanceUserFlag(maintenanceCmd) + flags.AddMaintenanceHostnameFlag(maintenanceCmd) for _, addRepoTo := range repoCommands { addRepoTo(initCmd) diff --git a/src/cli/repo/s3.go b/src/cli/repo/s3.go index 63fb7d5b4..86a241748 100644 --- a/src/cli/repo/s3.go +++ b/src/cli/repo/s3.go @@ -130,6 +130,8 @@ func initS3Cmd(cmd *cobra.Command, args []string) error { return Only(ctx, err) } + opt := utils.ControlWithConfig(cfg) + // SendStartCorsoEvent uses distict ID as tenant ID because repoID is still not generated utils.SendStartCorsoEvent( ctx, @@ -137,7 +139,7 @@ func initS3Cmd(cmd *cobra.Command, args []string) error { cfg.Account.ID(), map[string]any{"command": "init repo"}, cfg.Account.ID(), - utils.Control()) + opt) s3Cfg, err := cfg.Storage.S3Config() if err != nil { @@ -156,7 +158,7 @@ func initS3Cmd(cmd *cobra.Command, args []string) error { return Only(ctx, clues.Wrap(err, "Failed to parse m365 account config")) } - r, err := repository.Initialize(ctx, cfg.Account, cfg.Storage, utils.Control()) + r, err := repository.Initialize(ctx, cfg.Account, cfg.Storage, opt) if err != nil { if succeedIfExists && errors.Is(err, repository.ErrorRepoAlreadyExists) { return nil @@ -226,7 +228,12 @@ func connectS3Cmd(cmd *cobra.Command, args []string) error { return Only(ctx, clues.New(invalidEndpointErr)) } - r, err := repository.ConnectAndSendConnectEvent(ctx, cfg.Account, cfg.Storage, repoID, utils.Control()) + r, err := repository.ConnectAndSendConnectEvent( + ctx, + cfg.Account, + cfg.Storage, + repoID, + utils.ControlWithConfig(cfg)) if err != nil { return Only(ctx, clues.Wrap(err, "Failed to connect to the S3 repository")) } diff --git a/src/cli/utils/options.go b/src/cli/utils/options.go index 72bfac0a1..0cc44c839 100644 --- a/src/cli/utils/options.go +++ b/src/cli/utils/options.go @@ -1,6 +1,7 @@ package utils import ( + "github.com/alcionai/corso/src/cli/config" "github.com/alcionai/corso/src/cli/flags" "github.com/alcionai/corso/src/pkg/control" ) @@ -24,3 +25,12 @@ func Control() control.Options { return opt } + +func ControlWithConfig(cfg config.RepoDetails) control.Options { + opt := Control() + + opt.Repo.User = cfg.RepoUser + opt.Repo.Host = cfg.RepoHost + + return opt +} diff --git a/src/cli/utils/utils.go b/src/cli/utils/utils.go index 0c23a5af5..3b0e8d86b 100644 --- a/src/cli/utils/utils.go +++ b/src/cli/utils/utils.go @@ -34,7 +34,7 @@ func GetAccountAndConnect( repoID = events.RepoIDNotFound } - r, err := repository.Connect(ctx, cfg.Account, cfg.Storage, repoID, Control()) + r, err := repository.Connect(ctx, cfg.Account, cfg.Storage, repoID, ControlWithConfig(cfg)) if err != nil { return nil, nil, nil, clues.Wrap(err, "connecting to the "+cfg.Storage.Provider.String()+" repository") }