Compare commits
10 Commits
main
...
fileSystem
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf50ed0192 | ||
|
|
1ee148554d | ||
|
|
23cbb7ca33 | ||
|
|
76fbbb19ea | ||
|
|
328a84ed9f | ||
|
|
a32bcfdb87 | ||
|
|
585a394367 | ||
|
|
a8001f2aa9 | ||
|
|
1b1ddcc713 | ||
|
|
ae66673492 |
@ -13,6 +13,7 @@ const (
|
|||||||
|
|
||||||
// Corso Flags
|
// Corso Flags
|
||||||
CorsoPassphraseFN = "passphrase"
|
CorsoPassphraseFN = "passphrase"
|
||||||
|
UpdateCorsoPassphraseFN = "update-passphrase"
|
||||||
SucceedIfExistsFN = "succeed-if-exists"
|
SucceedIfExistsFN = "succeed-if-exists"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -23,6 +24,7 @@ var (
|
|||||||
AWSSecretAccessKeyFV string
|
AWSSecretAccessKeyFV string
|
||||||
AWSSessionTokenFV string
|
AWSSessionTokenFV string
|
||||||
CorsoPassphraseFV string
|
CorsoPassphraseFV string
|
||||||
|
UpdateCorsoPhasephraseFV string
|
||||||
SucceedIfExistsFV bool
|
SucceedIfExistsFV bool
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -73,6 +75,15 @@ func AddCorsoPassphaseFlags(cmd *cobra.Command) {
|
|||||||
"Passphrase to protect encrypted repository contents")
|
"Passphrase to protect encrypted repository contents")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// M365 flags
|
||||||
|
func AddCorsoUpdatePassphraseFlags(cmd *cobra.Command) {
|
||||||
|
fs := cmd.Flags()
|
||||||
|
fs.StringVar(&UpdateCorsoPhasephraseFV,
|
||||||
|
UpdateCorsoPassphraseFN,
|
||||||
|
"",
|
||||||
|
"update Corso passphrase for repo")
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Provider
|
// Provider
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
@ -38,6 +38,11 @@ func addFilesystemCommands(cmd *cobra.Command) *cobra.Command {
|
|||||||
|
|
||||||
case connectCommand:
|
case connectCommand:
|
||||||
c, _ = utils.AddCommand(cmd, filesystemConnectCmd())
|
c, _ = utils.AddCommand(cmd, filesystemConnectCmd())
|
||||||
|
|
||||||
|
case updateCommand:
|
||||||
|
update := filesystemUpdateCmd()
|
||||||
|
flags.AddCorsoUpdatePassphraseFlags(update)
|
||||||
|
c, _ = utils.AddCommand(cmd, update)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Use = c.Use + " " + fsProviderCmdUseSuffix
|
c.Use = c.Use + " " + fsProviderCmdUseSuffix
|
||||||
@ -229,3 +234,65 @@ func connectFilesystemCmd(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------------
|
||||||
|
// Update
|
||||||
|
// ---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// `corso repo update filesystem [<flag>...]`
|
||||||
|
func filesystemUpdateCmd() *cobra.Command {
|
||||||
|
return &cobra.Command{
|
||||||
|
Use: fsProviderCommand,
|
||||||
|
Short: "Update to a filesystem repository",
|
||||||
|
Long: `Update to an existing repository on local or network storage.`,
|
||||||
|
RunE: updateFilesystemCmd,
|
||||||
|
Args: cobra.NoArgs,
|
||||||
|
Example: fsProviderCmdConnectExamples,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// updates to an existing filesystem repo.
|
||||||
|
func updateFilesystemCmd(cmd *cobra.Command, args []string) error {
|
||||||
|
ctx := cmd.Context()
|
||||||
|
overrides := flags.FilesystemFlagOverrides(cmd)
|
||||||
|
|
||||||
|
// TODO(pandeyabs): Move filepath conversion to FilesystemConfig scope.
|
||||||
|
abs, err := utils.MakeAbsoluteFilePath(overrides[flags.FilesystemPathFN])
|
||||||
|
if err != nil {
|
||||||
|
return Only(ctx, clues.Wrap(err, "getting absolute repo path"))
|
||||||
|
}
|
||||||
|
|
||||||
|
overrides[flags.FilesystemPathFN] = abs
|
||||||
|
|
||||||
|
cfg, err := config.GetConfigRepoDetails(
|
||||||
|
ctx,
|
||||||
|
storage.ProviderFilesystem,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
overrides)
|
||||||
|
if err != nil {
|
||||||
|
return Only(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
opts := utils.ControlWithConfig(cfg)
|
||||||
|
|
||||||
|
r, err := repository.New(
|
||||||
|
ctx,
|
||||||
|
cfg.Account,
|
||||||
|
cfg.Storage,
|
||||||
|
opts,
|
||||||
|
cfg.RepoID)
|
||||||
|
if err != nil {
|
||||||
|
return Only(ctx, clues.Wrap(err, "Failed to create a repository controller"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.UpdatePassword(ctx, flags.UpdateCorsoPhasephraseFV); err != nil {
|
||||||
|
return Only(ctx, clues.Wrap(err, "Failed to update s3"))
|
||||||
|
}
|
||||||
|
|
||||||
|
defer utils.CloseRepo(ctx, r)
|
||||||
|
|
||||||
|
Infof(ctx, "Updated repo password.")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@ -153,3 +153,81 @@ func (suite *FilesystemE2ESuite) TestConnectFilesystemCmd() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *FilesystemE2ESuite) TestUpdateFilesystemCmd() {
|
||||||
|
t := suite.T()
|
||||||
|
|
||||||
|
ctx, flush := tester.NewContext(t)
|
||||||
|
defer flush()
|
||||||
|
|
||||||
|
st := storeTD.NewFilesystemStorage(t)
|
||||||
|
cfg, err := st.ToFilesystemConfig()
|
||||||
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
|
force := map[string]string{
|
||||||
|
tconfig.TestCfgAccountProvider: account.ProviderM365.String(),
|
||||||
|
tconfig.TestCfgStorageProvider: storage.ProviderFilesystem.String(),
|
||||||
|
tconfig.TestCfgFilesystemPath: cfg.Path,
|
||||||
|
}
|
||||||
|
vpr, configFP := tconfig.MakeTempTestConfigClone(t, force)
|
||||||
|
|
||||||
|
ctx = config.SetViper(ctx, vpr)
|
||||||
|
|
||||||
|
// init the repo first
|
||||||
|
r, err := repository.New(
|
||||||
|
ctx,
|
||||||
|
tconfig.NewM365Account(t),
|
||||||
|
st,
|
||||||
|
control.DefaultOptions(),
|
||||||
|
repository.NewRepoID)
|
||||||
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
|
err = r.Initialize(ctx, repository.InitConfig{})
|
||||||
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
|
// then connect it
|
||||||
|
cmd := cliTD.StubRootCmd(
|
||||||
|
"repo", "connect", "filesystem",
|
||||||
|
"--config-file", configFP,
|
||||||
|
"--path", cfg.Path)
|
||||||
|
cli.BuildCommandTree(cmd)
|
||||||
|
|
||||||
|
// run the command
|
||||||
|
err = cmd.ExecuteContext(ctx)
|
||||||
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
|
// test update
|
||||||
|
cmd = cliTD.StubRootCmd(
|
||||||
|
"repo", "update", "filesystem",
|
||||||
|
"--config-file", configFP,
|
||||||
|
"--path", cfg.Path,
|
||||||
|
"--update-passphrase", "newpass")
|
||||||
|
cli.BuildCommandTree(cmd)
|
||||||
|
|
||||||
|
// run the command
|
||||||
|
err = cmd.ExecuteContext(ctx)
|
||||||
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
|
// try connecting with new password
|
||||||
|
cmd = cliTD.StubRootCmd(
|
||||||
|
"repo", "connect", "filesystem",
|
||||||
|
"--config-file", configFP,
|
||||||
|
"--path", cfg.Path,
|
||||||
|
"--passphrase", "newpass")
|
||||||
|
cli.BuildCommandTree(cmd)
|
||||||
|
|
||||||
|
// run the command
|
||||||
|
err = cmd.ExecuteContext(ctx)
|
||||||
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
|
// try connecting with old password
|
||||||
|
cmd = cliTD.StubRootCmd(
|
||||||
|
"repo", "connect", "filesystem",
|
||||||
|
"--config-file", configFP,
|
||||||
|
"--path", cfg.Path)
|
||||||
|
cli.BuildCommandTree(cmd)
|
||||||
|
|
||||||
|
// run the command
|
||||||
|
err = cmd.ExecuteContext(ctx)
|
||||||
|
require.Error(t, err, clues.ToCore(err))
|
||||||
|
}
|
||||||
|
|||||||
@ -31,6 +31,7 @@ func (suite *FilesystemSuite) TestAddFilesystemCommands() {
|
|||||||
}{
|
}{
|
||||||
{"init filesystem", initCommand, expectUse, filesystemInitCmd().Short, initFilesystemCmd},
|
{"init filesystem", initCommand, expectUse, filesystemInitCmd().Short, initFilesystemCmd},
|
||||||
{"connect filesystem", connectCommand, expectUse, filesystemConnectCmd().Short, connectFilesystemCmd},
|
{"connect filesystem", connectCommand, expectUse, filesystemConnectCmd().Short, connectFilesystemCmd},
|
||||||
|
{"update filesystem", updateCommand, expectUse, filesystemUpdateCmd().Short, updateFilesystemCmd},
|
||||||
}
|
}
|
||||||
for _, test := range table {
|
for _, test := range table {
|
||||||
suite.Run(test.name, func() {
|
suite.Run(test.name, func() {
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
initCommand = "init"
|
initCommand = "init"
|
||||||
connectCommand = "connect"
|
connectCommand = "connect"
|
||||||
|
updateCommand = "update"
|
||||||
maintenanceCommand = "maintenance"
|
maintenanceCommand = "maintenance"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,12 +40,14 @@ func AddCommands(cmd *cobra.Command) {
|
|||||||
initCmd = initCmd()
|
initCmd = initCmd()
|
||||||
connectCmd = connectCmd()
|
connectCmd = connectCmd()
|
||||||
maintenanceCmd = maintenanceCmd()
|
maintenanceCmd = maintenanceCmd()
|
||||||
|
updateCmd = updateCmd()
|
||||||
)
|
)
|
||||||
|
|
||||||
cmd.AddCommand(repoCmd)
|
cmd.AddCommand(repoCmd)
|
||||||
repoCmd.AddCommand(initCmd)
|
repoCmd.AddCommand(initCmd)
|
||||||
repoCmd.AddCommand(connectCmd)
|
repoCmd.AddCommand(connectCmd)
|
||||||
repoCmd.AddCommand(maintenanceCmd)
|
repoCmd.AddCommand(maintenanceCmd)
|
||||||
|
repoCmd.AddCommand(updateCmd)
|
||||||
|
|
||||||
flags.AddMaintenanceModeFlag(maintenanceCmd)
|
flags.AddMaintenanceModeFlag(maintenanceCmd)
|
||||||
flags.AddForceMaintenanceFlag(maintenanceCmd)
|
flags.AddForceMaintenanceFlag(maintenanceCmd)
|
||||||
@ -54,6 +57,7 @@ func AddCommands(cmd *cobra.Command) {
|
|||||||
for _, addRepoTo := range repoCommands {
|
for _, addRepoTo := range repoCommands {
|
||||||
addRepoTo(initCmd)
|
addRepoTo(initCmd)
|
||||||
addRepoTo(connectCmd)
|
addRepoTo(connectCmd)
|
||||||
|
addRepoTo(updateCmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +67,7 @@ func repoCmd() *cobra.Command {
|
|||||||
return &cobra.Command{
|
return &cobra.Command{
|
||||||
Use: "repo",
|
Use: "repo",
|
||||||
Short: "Manage your repositories",
|
Short: "Manage your repositories",
|
||||||
Long: `Initialize, configure, and connect to your account backup repositories.`,
|
Long: `Initialize, configure, connect and update to your account backup repositories.`,
|
||||||
RunE: handleRepoCmd,
|
RunE: handleRepoCmd,
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
}
|
}
|
||||||
@ -175,3 +179,20 @@ func getMaintenanceType(t string) (repository.MaintenanceType, error) {
|
|||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The repo update subcommand.
|
||||||
|
// `corso repo update <repository> [<flag>...]`
|
||||||
|
func updateCmd() *cobra.Command {
|
||||||
|
return &cobra.Command{
|
||||||
|
Use: updateCommand,
|
||||||
|
Short: "Update a repository.",
|
||||||
|
Long: `Update repository configuration and behavior.`,
|
||||||
|
RunE: handleUpdateCmd,
|
||||||
|
Args: cobra.NoArgs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler for calls to `corso repo init`.
|
||||||
|
func handleUpdateCmd(cmd *cobra.Command, args []string) error {
|
||||||
|
return cmd.Help()
|
||||||
|
}
|
||||||
|
|||||||
@ -28,6 +28,11 @@ func addS3Commands(cmd *cobra.Command) *cobra.Command {
|
|||||||
|
|
||||||
case connectCommand:
|
case connectCommand:
|
||||||
c, _ = utils.AddCommand(cmd, s3ConnectCmd())
|
c, _ = utils.AddCommand(cmd, s3ConnectCmd())
|
||||||
|
|
||||||
|
case updateCommand:
|
||||||
|
update := s3UpdateCmd()
|
||||||
|
flags.AddCorsoUpdatePassphraseFlags(update)
|
||||||
|
c, _ = utils.AddCommand(cmd, update)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Use = c.Use + " " + s3ProviderCommandUseSuffix
|
c.Use = c.Use + " " + s3ProviderCommandUseSuffix
|
||||||
@ -237,3 +242,62 @@ func connectS3Cmd(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------------
|
||||||
|
// Update Password
|
||||||
|
// ---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// `corso repo update s3 [<flag>...]`
|
||||||
|
func s3UpdateCmd() *cobra.Command {
|
||||||
|
return &cobra.Command{
|
||||||
|
Use: s3ProviderCommand,
|
||||||
|
Short: "Update to a S3 repository",
|
||||||
|
Long: `Update to an existing S3 repository.`,
|
||||||
|
RunE: updateS3Cmd,
|
||||||
|
Args: cobra.NoArgs,
|
||||||
|
Example: s3ProviderCommandConnectExamples,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// updates to an existing s3 repo.
|
||||||
|
// currently just updating Kopia password
|
||||||
|
func updateS3Cmd(cmd *cobra.Command, args []string) error {
|
||||||
|
ctx := cmd.Context()
|
||||||
|
|
||||||
|
cfg, err := config.GetConfigRepoDetails(
|
||||||
|
ctx,
|
||||||
|
storage.ProviderS3,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
flags.S3FlagOverrides(cmd))
|
||||||
|
if err != nil {
|
||||||
|
return Only(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
repoID := cfg.RepoID
|
||||||
|
if len(repoID) == 0 {
|
||||||
|
repoID = events.RepoIDNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
opts := utils.ControlWithConfig(cfg)
|
||||||
|
|
||||||
|
r, err := repository.New(
|
||||||
|
ctx,
|
||||||
|
cfg.Account,
|
||||||
|
cfg.Storage,
|
||||||
|
opts,
|
||||||
|
repoID)
|
||||||
|
if err != nil {
|
||||||
|
return Only(ctx, clues.Wrap(err, "Failed to create a repository controller"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.UpdatePassword(ctx, flags.UpdateCorsoPhasephraseFV); err != nil {
|
||||||
|
return Only(ctx, clues.Wrap(err, "Failed to update s3"))
|
||||||
|
}
|
||||||
|
|
||||||
|
defer utils.CloseRepo(ctx, r)
|
||||||
|
|
||||||
|
Infof(ctx, "Updated repo password.")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@ -291,3 +291,80 @@ func (suite *S3E2ESuite) TestConnectS3Cmd_badInputs() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *S3E2ESuite) TestUpdateS3Cmd() {
|
||||||
|
t := suite.T()
|
||||||
|
ctx, flush := tester.NewContext(t)
|
||||||
|
|
||||||
|
defer flush()
|
||||||
|
|
||||||
|
st := storeTD.NewPrefixedS3Storage(t)
|
||||||
|
sc, err := st.StorageConfig()
|
||||||
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
|
cfg := sc.(*storage.S3Config)
|
||||||
|
|
||||||
|
vpr, configFP := tconfig.MakeTempTestConfigClone(t, nil)
|
||||||
|
|
||||||
|
ctx = config.SetViper(ctx, vpr)
|
||||||
|
|
||||||
|
cmd := cliTD.StubRootCmd(
|
||||||
|
"repo", "init", "s3",
|
||||||
|
"--config-file", configFP,
|
||||||
|
"--prefix", cfg.Prefix)
|
||||||
|
|
||||||
|
cli.BuildCommandTree(cmd)
|
||||||
|
|
||||||
|
// run the command
|
||||||
|
err = cmd.ExecuteContext(ctx)
|
||||||
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
|
// connect with old passphrase
|
||||||
|
cmd = cliTD.StubRootCmd(
|
||||||
|
"repo", "connect", "s3",
|
||||||
|
"--config-file", configFP,
|
||||||
|
"--bucket", cfg.Bucket,
|
||||||
|
"--prefix", cfg.Prefix)
|
||||||
|
cli.BuildCommandTree(cmd)
|
||||||
|
|
||||||
|
// run the command
|
||||||
|
err = cmd.ExecuteContext(ctx)
|
||||||
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
|
cmd = cliTD.StubRootCmd(
|
||||||
|
"repo", "update", "s3",
|
||||||
|
"--config-file", configFP,
|
||||||
|
"--bucket", cfg.Bucket,
|
||||||
|
"--prefix", cfg.Prefix,
|
||||||
|
"--update-passphrase", "newpass")
|
||||||
|
cli.BuildCommandTree(cmd)
|
||||||
|
|
||||||
|
// run the command
|
||||||
|
err = cmd.ExecuteContext(ctx)
|
||||||
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
|
// connect again with new passphrase
|
||||||
|
cmd = cliTD.StubRootCmd(
|
||||||
|
"repo", "connect", "s3",
|
||||||
|
"--config-file", configFP,
|
||||||
|
"--bucket", cfg.Bucket,
|
||||||
|
"--prefix", cfg.Prefix,
|
||||||
|
"--passphrase", "newpass")
|
||||||
|
cli.BuildCommandTree(cmd)
|
||||||
|
|
||||||
|
// run the command
|
||||||
|
err = cmd.ExecuteContext(ctx)
|
||||||
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
|
// connect with old passphrase - it will fail
|
||||||
|
cmd = cliTD.StubRootCmd(
|
||||||
|
"repo", "connect", "s3",
|
||||||
|
"--config-file", configFP,
|
||||||
|
"--bucket", cfg.Bucket,
|
||||||
|
"--prefix", cfg.Prefix)
|
||||||
|
cli.BuildCommandTree(cmd)
|
||||||
|
|
||||||
|
// run the command
|
||||||
|
err = cmd.ExecuteContext(ctx)
|
||||||
|
require.Error(t, err, clues.ToCore(err))
|
||||||
|
}
|
||||||
|
|||||||
@ -31,6 +31,7 @@ func (suite *S3Suite) TestAddS3Commands() {
|
|||||||
}{
|
}{
|
||||||
{"init s3", initCommand, expectUse, s3InitCmd().Short, initS3Cmd},
|
{"init s3", initCommand, expectUse, s3InitCmd().Short, initS3Cmd},
|
||||||
{"connect s3", connectCommand, expectUse, s3ConnectCmd().Short, connectS3Cmd},
|
{"connect s3", connectCommand, expectUse, s3ConnectCmd().Short, connectS3Cmd},
|
||||||
|
{"update s3", updateCommand, expectUse, s3UpdateCmd().Short, updateS3Cmd},
|
||||||
}
|
}
|
||||||
for _, test := range table {
|
for _, test := range table {
|
||||||
suite.Run(test.name, func() {
|
suite.Run(test.name, func() {
|
||||||
|
|||||||
@ -31,6 +31,7 @@ const (
|
|||||||
CorsoStart = "Corso Start"
|
CorsoStart = "Corso Start"
|
||||||
RepoInit = "Repo Init"
|
RepoInit = "Repo Init"
|
||||||
RepoConnect = "Repo Connect"
|
RepoConnect = "Repo Connect"
|
||||||
|
RepoUpdate = "Repo Update"
|
||||||
BackupStart = "Backup Start"
|
BackupStart = "Backup Start"
|
||||||
BackupEnd = "Backup End"
|
BackupEnd = "Backup End"
|
||||||
RestoreStart = "Restore Start"
|
RestoreStart = "Restore Start"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user