Skip to content

Commit

Permalink
VAULT-8631 Make upgrade synchronous when no keys to upgrade (#66)
Browse files Browse the repository at this point in the history
  • Loading branch information
VioletHynes committed Sep 29, 2022
1 parent 562a5be commit cc06d01
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 37 deletions.
2 changes: 1 addition & 1 deletion backend.go
Expand Up @@ -90,7 +90,7 @@ func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend,
return b, nil
}

// Factory returns a new backend as logical.Backend.
// VersionedKVFactory returns a new KVV2 backend as logical.Backend.
func VersionedKVFactory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) {
upgradeCtx, upgradeCancelFunc := context.WithCancel(ctx)

Expand Down
1 change: 0 additions & 1 deletion path_config_test.go
Expand Up @@ -157,5 +157,4 @@ func TestVersionedKV_Config_DeleteVersionAfter(t *testing.T) {
}
})
}

}
45 changes: 16 additions & 29 deletions path_data_test.go
Expand Up @@ -30,36 +30,23 @@ func getBackend(t *testing.T) (logical.Backend, logical.Storage) {
t.Fatalf("unable to create backend: %v", err)
}

// Wait for the upgrade to finish
timeout := time.After(20 * time.Second)
ticker := time.Tick(time.Second)

for {
select {
case <-timeout:
t.Fatal("timeout expired waiting for upgrade")
case <-ticker:
req := &logical.Request{
Operation: logical.ReadOperation,
Path: "config",
Storage: config.StorageView,
}

resp, err := b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatalf("unable to read config: %s", err.Error())
return nil, nil
}

if resp != nil && !resp.IsError() {
return b, config.StorageView
}

if resp == nil || (resp.IsError() && strings.Contains(resp.Error().Error(), "Upgrading from non-versioned to versioned")) {
t.Log("waiting for upgrade to complete")
}
}
req := &logical.Request{
Operation: logical.ReadOperation,
Path: "config",
Storage: config.StorageView,
}

resp, err := b.HandleRequest(context.Background(), req)
if err != nil {
t.Fatalf("unable to read config: %s", err.Error())
return nil, nil
}

if resp == nil || resp.IsError() {
t.Fatalf("Error during mount creation: %x", resp.Error().Error())
}

return b, config.StorageView
}

// getKeySet will produce a set of the keys that exist in m
Expand Down
29 changes: 23 additions & 6 deletions upgrade.go
Expand Up @@ -118,6 +118,18 @@ func (b *versionedKVBackend) Upgrade(ctx context.Context, s logical.Storage) err
return nil
}

// If we have 0 keys, it's either a new mount or one that's trivial to upgrade,
// so we should do the upgrade synchronously
upgradeSynchronously := false
keys, err := logical.CollectKeys(ctx, s)
if err != nil {
b.Logger().Error("upgrading resulted in error", "error", err)
return err
}
if len(keys) == 0 {
upgradeSynchronously = true
}

upgradeInfo := &UpgradeInfo{
StartedTime: ptypes.TimestampNow(),
}
Expand All @@ -128,7 +140,7 @@ func (b *versionedKVBackend) Upgrade(ctx context.Context, s logical.Storage) err
return err
}

// Because this is a long running process we need a new context.
// Because this is a long-running process we need a new context.
ctx = context.Background()

upgradeKey := func(key string) error {
Expand Down Expand Up @@ -189,10 +201,7 @@ func (b *versionedKVBackend) Upgrade(ctx context.Context, s logical.Storage) err
return nil
}

// Run the actual upgrade in a go routine so we don't block the client on a
// potentially long process.
go func() {

upgradeFunc := func() {
// Write the canary value and if we are read only wait until the setup
// process has finished.
READONLY_LOOP:
Expand Down Expand Up @@ -257,7 +266,15 @@ func (b *versionedKVBackend) Upgrade(ctx context.Context, s logical.Storage) err
}

atomic.StoreUint32(b.upgrading, 0)
}()
}

if upgradeSynchronously {
upgradeFunc()
} else {
// We run the actual upgrade in a go routine, so we don't block the client on a
// potentially long process.
go upgradeFunc()
}

return nil
}

0 comments on commit cc06d01

Please sign in to comment.