feat(cli): flag to allow placing the upgrade lock without doing anything else (#2329)

Co-authored-by: Shikhar Mall <small@kopia.io>
This commit is contained in:
Shikhar MallandShikhar Mall authored and GitHub committed 2022-08-19 13:48:08 -07:00
1 parent 5ad8f1cf38
commit 11c7bf533c
2 files changed
+12 -24

No files matched your search

+7
View File
@@ -20,6 +20,7 @@ type commandRepositoryUpgrade struct {
forceRollback bool
skip bool
force bool
lockOnly bool
// lock settings
ioDrainTimeout time.Duration
@@ -58,6 +59,7 @@ func (c *commandRepositoryUpgrade) setup(svc advancedAppServices, parent command
beginCmd.Flag("io-drain-timeout", "Max time it should take all other Kopia clients to drop repository connections").Default(format.DefaultRepositoryBlobCacheDuration.String()).DurationVar(&c.ioDrainTimeout)
beginCmd.Flag("allow-unsafe-upgrade", "Force using an unsafe io-drain-timeout for the upgrade lock").Default("false").Hidden().BoolVar(&c.force)
beginCmd.Flag("status-poll-interval", "An advisory polling interval to check for the status of upgrade").Default("60s").DurationVar(&c.statusPollInterval)
beginCmd.Flag("lock-only", "Advertise the upgrade lock and exit without actually performing the drain or upgrade").Default("false").Hidden().BoolVar(&c.lockOnly) // this is used by tests
// upgrade phases
@@ -158,6 +160,11 @@ func (c *commandRepositoryUpgrade) setLockIntent(ctx context.Context, rep repo.D
log(ctx).Infof("Repository upgrade lock intent has been placed.")
// skip all other phases after this step
if c.lockOnly {
c.skip = true
}
return nil
}
+5 -24
View File
@@ -1,7 +1,6 @@
package cli_test
import (
"strings"
"testing"
"time"
@@ -53,32 +52,14 @@ func (s *formatSpecificTestSuite) TestRepositoryUpgrade(t *testing.T) {
require.Contains(t, out, "Format version: 3")
}
func lockAndKill(t *testing.T, env *testenv.CLITest) {
func lockRepositoryForUpgrade(t *testing.T, env *testenv.CLITest) {
t.Helper()
t.Log("Placing upgrade lock ...")
wait, kill := env.RunAndProcessStderr(t, func(line string) bool { return false }, "repository", "upgrade",
env.RunAndExpectSuccess(t, "repository", "upgrade",
"--upgrade-owner-id", "owner",
"--io-drain-timeout", "30s", "--allow-unsafe-upgrade",
"--status-poll-interval", "1s")
go func() {
for {
t.Log("Waiting for the repository to be locked ...")
out := env.RunAndExpectSuccess(t, "repository", "status", "--upgrade-no-block", "--upgrade-owner-id", "owner")
if strings.Contains(strings.Join(out, "\n"), "Lock status: Draining") {
t.Log("Repository is locked, interrupting upgrade drain.")
kill()
break
}
time.Sleep(200 * time.Millisecond)
}
}()
require.EqualError(t, wait(), "failed to upgrade the repository, lock is not released: upgrade drain interrupted")
"--status-poll-interval", "1s", "--lock-only")
}
func (s *formatSpecificTestSuite) TestRepositoryUpgradeStatusWhileLocked(t *testing.T) {
@@ -94,7 +75,7 @@ func (s *formatSpecificTestSuite) TestRepositoryUpgradeStatusWhileLocked(t *test
switch s.formatVersion {
case format.FormatVersion1:
require.Contains(t, out, "Format version: 1")
lockAndKill(t, env)
lockRepositoryForUpgrade(t, env)
// verify that non-owner clients will fail to connect/upgrade
env.RunAndExpectFailure(t, "repository", "upgrade",
@@ -111,7 +92,7 @@ func (s *formatSpecificTestSuite) TestRepositoryUpgradeStatusWhileLocked(t *test
// attempt to rollback the upgrade and restart
env.RunAndExpectSuccess(t, "repository", "upgrade", "rollback", "--force", "--upgrade-owner-id", "owner")
lockAndKill(t, env)
lockRepositoryForUpgrade(t, env)
// drain all clients
t.Log("Waiting to drain all clients ...")