mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-14 23:17:29 +00:00
ipn/store: make StateStore.All optional (#16409)
This method is only needed to migrate between store.FileStore and tpm.tpmStore. We can make a runtime type assertion instead of implementing an unused method for every platform. Updates #15830 Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
This commit is contained in:
@@ -10,7 +10,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"iter"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -254,7 +253,3 @@ func (s *awsStore) persistState() error {
|
||||
_, err = s.ssmClient.PutParameter(context.TODO(), in)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *awsStore) All() iter.Seq2[ipn.StateKey, []byte] {
|
||||
return s.memory.All()
|
||||
}
|
||||
|
@@ -7,7 +7,6 @@ package kubestore
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"iter"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
@@ -429,7 +428,3 @@ func sanitizeKey[T ~string](k T) string {
|
||||
return '_'
|
||||
}, string(k))
|
||||
}
|
||||
|
||||
func (s *Store) All() iter.Seq2[ipn.StateKey, []byte] {
|
||||
return s.memory.All()
|
||||
}
|
||||
|
@@ -7,7 +7,6 @@ package mem
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"iter"
|
||||
"sync"
|
||||
|
||||
xmaps "golang.org/x/exp/maps"
|
||||
@@ -86,16 +85,3 @@ func (s *Store) ExportToJSON() ([]byte, error) {
|
||||
}
|
||||
return json.MarshalIndent(s.cache, "", " ")
|
||||
}
|
||||
|
||||
func (s *Store) All() iter.Seq2[ipn.StateKey, []byte] {
|
||||
return func(yield func(ipn.StateKey, []byte) bool) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
for k, v := range s.cache {
|
||||
if !yield(k, v) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -235,6 +235,23 @@ func (s *FileStore) All() iter.Seq2[ipn.StateKey, []byte] {
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure FileStore implements ExportableStore for migration to/from
|
||||
// tpm.tpmStore.
|
||||
var _ ExportableStore = (*FileStore)(nil)
|
||||
|
||||
// ExportableStore is an ipn.StateStore that can export all of its contents.
|
||||
// This interface is optional to implement, and used for migrating the state
|
||||
// between different store implementations.
|
||||
type ExportableStore interface {
|
||||
ipn.StateStore
|
||||
|
||||
// All returns an iterator over all store keys. Using ReadState or
|
||||
// WriteState is not safe while iterating and can lead to a deadlock. The
|
||||
// order of keys in the iterator is not specified and may change between
|
||||
// runs.
|
||||
All() iter.Seq2[ipn.StateKey, []byte]
|
||||
}
|
||||
|
||||
func maybeMigrateLocalStateFile(logf logger.Logf, path string) error {
|
||||
path, toTPM := strings.CutPrefix(path, TPMPrefix)
|
||||
|
||||
@@ -297,10 +314,15 @@ func maybeMigrateLocalStateFile(logf logger.Logf, path string) error {
|
||||
}
|
||||
defer os.Remove(tmpPath)
|
||||
|
||||
fromExp, ok := from.(ExportableStore)
|
||||
if !ok {
|
||||
return fmt.Errorf("%T does not implement the exportableStore interface", from)
|
||||
}
|
||||
|
||||
// Copy all the items. This is pretty inefficient, because both stores
|
||||
// write the file to disk for each WriteState, but that's ok for a one-time
|
||||
// migration.
|
||||
for k, v := range from.All() {
|
||||
for k, v := range fromExp.All() {
|
||||
if err := to.WriteState(k, v); err != nil {
|
||||
return err
|
||||
}
|
||||
|
Reference in New Issue
Block a user