Merge pull request #46040 from thaJeztah/datastore_no_interfaces

libnetwork/datastore: remove DataStore interface, and rename constructor
This commit is contained in:
Sebastiaan van Stijn
2023-07-25 10:41:43 +02:00
committed by GitHub
14 changed files with 50 additions and 97 deletions

View File

@@ -91,7 +91,7 @@ type Controller struct {
ipamRegistry drvregistry.IPAMs
sandboxes sandboxTable
cfg *config.Config
store datastore.DataStore
store *datastore.Store
extKeyListener net.Listener
watchCh chan *Endpoint
unWatchCh chan *Endpoint

View File

@@ -13,10 +13,10 @@ type kvMap map[string]KVObject
type cache struct {
sync.Mutex
kmm map[string]kvMap
ds *datastore
ds *Store
}
func newCache(ds *datastore) *cache {
func newCache(ds *Store) *cache {
return &cache{kmm: make(map[string]kvMap), ds: ds}
}

View File

@@ -2,7 +2,6 @@ package datastore
import (
"fmt"
"reflect"
"strings"
"sync"
"time"
@@ -12,42 +11,20 @@ import (
"github.com/docker/docker/libnetwork/types"
)
// DataStore exported
type DataStore interface {
// GetObject gets data from datastore and unmarshals to the specified object
GetObject(key string, o KVObject) error
// PutObjectAtomic provides an atomic add and update operation for a Record
PutObjectAtomic(kvObject KVObject) error
// DeleteObjectAtomic performs an atomic delete operation
DeleteObjectAtomic(kvObject KVObject) error
// List returns of a list of KVObjects belonging to the parent
// key. The caller must pass a KVObject of the same type as
// the objects that need to be listed
List(string, KVObject) ([]KVObject, error)
// Map returns a Map of KVObjects
Map(key string, kvObject KVObject) (map[string]KVObject, error)
// Scope returns the scope of the store
Scope() string
// KVStore returns access to the KV Store
KVStore() store.Store
// Close closes the data store
Close()
}
// ErrKeyModified is raised for an atomic update when the update is working on a stale state
var (
ErrKeyModified = store.ErrKeyModified
ErrKeyNotFound = store.ErrKeyNotFound
)
type datastore struct {
type Store struct {
mu sync.Mutex
scope string
store store.Store
cache *cache
}
// KVObject is Key/Value interface used by objects to be part of the DataStore
// KVObject is Key/Value interface used by objects to be part of the Store.
type KVObject interface {
// Key method lets an object provide the Key to be used in KV Store
Key() []string
@@ -61,7 +38,7 @@ type KVObject interface {
Index() uint64
// SetIndex method allows the datastore to store the latest DB Index into the object
SetIndex(uint64)
// True if the object exists in the datastore, false if it hasn't been stored yet.
// Exists returns true if the object exists in the datastore, false if it hasn't been stored yet.
// When SetIndex() is called, the object has been stored.
Exists() bool
// DataScope indicates the storage scope of the KV object
@@ -159,19 +136,8 @@ func Key(key ...string) string {
return b.String()
}
// ParseKey provides convenient method to unpack the key to complement the Key function
func ParseKey(key string) ([]string, error) {
chain := strings.Split(strings.Trim(key, "/"), "/")
// The key must at least be equal to the rootChain in order to be considered as valid
if len(chain) <= len(rootChain) || !reflect.DeepEqual(chain[0:len(rootChain)], rootChain) {
return nil, types.BadRequestErrorf("invalid Key : %s", key)
}
return chain[len(rootChain):], nil
}
// newClient used to connect to KV Store
func newClient(kv string, addr string, config *store.Config) (DataStore, error) {
func newClient(kv string, addr string, config *store.Config) (*Store, error) {
if config == nil {
config = &store.Config{}
}
@@ -197,14 +163,14 @@ func newClient(kv string, addr string, config *store.Config) (DataStore, error)
return nil, err
}
ds := &datastore{scope: LocalScope, store: s}
ds := &Store{scope: LocalScope, store: s}
ds.cache = newCache(ds)
return ds, nil
}
// NewDataStore creates a new instance of LibKV data store
func NewDataStore(cfg ScopeCfg) (DataStore, error) {
// New creates a new Store instance.
func New(cfg ScopeCfg) (*Store, error) {
if cfg.Client.Provider == "" || cfg.Client.Address == "" {
cfg = DefaultScope("")
}
@@ -212,8 +178,8 @@ func NewDataStore(cfg ScopeCfg) (DataStore, error) {
return newClient(cfg.Client.Provider, cfg.Client.Address, cfg.Client.Config)
}
// NewDataStoreFromConfig creates a new instance of LibKV data store starting from the datastore config data
func NewDataStoreFromConfig(dsc discoverapi.DatastoreConfigData) (DataStore, error) {
// FromConfig creates a new instance of LibKV data store starting from the datastore config data.
func FromConfig(dsc discoverapi.DatastoreConfigData) (*Store, error) {
var (
ok bool
sCfgP *store.Config
@@ -224,15 +190,13 @@ func NewDataStoreFromConfig(dsc discoverapi.DatastoreConfigData) (DataStore, err
return nil, fmt.Errorf("cannot parse store configuration: %v", dsc.Config)
}
scopeCfg := ScopeCfg{
ds, err := New(ScopeCfg{
Client: ScopeClientCfg{
Address: dsc.Address,
Provider: dsc.Provider,
Config: sCfgP,
},
}
ds, err := NewDataStore(scopeCfg)
})
if err != nil {
return nil, fmt.Errorf("failed to construct datastore client from datastore configuration %v: %v", dsc, err)
}
@@ -240,20 +204,23 @@ func NewDataStoreFromConfig(dsc discoverapi.DatastoreConfigData) (DataStore, err
return ds, err
}
func (ds *datastore) Close() {
// Close closes the data store.
func (ds *Store) Close() {
ds.store.Close()
}
func (ds *datastore) Scope() string {
// Scope returns the scope of the store.
func (ds *Store) Scope() string {
return ds.scope
}
func (ds *datastore) KVStore() store.Store {
// KVStore returns access to the KV Store.
func (ds *Store) KVStore() store.Store {
return ds.store
}
// PutObjectAtomic adds a new Record based on an object into the datastore
func (ds *datastore) PutObjectAtomic(kvObject KVObject) error {
// PutObjectAtomic provides an atomic add and update operation for a Record.
func (ds *Store) PutObjectAtomic(kvObject KVObject) error {
var (
previous *store.KVPair
pair *store.KVPair
@@ -302,8 +269,8 @@ add_cache:
return nil
}
// GetObject returns a record matching the key
func (ds *datastore) GetObject(key string, o KVObject) error {
// GetObject gets data from the store and unmarshals to the specified object.
func (ds *Store) GetObject(key string, o KVObject) error {
ds.mu.Lock()
defer ds.mu.Unlock()
@@ -326,7 +293,7 @@ func (ds *datastore) GetObject(key string, o KVObject) error {
return nil
}
func (ds *datastore) ensureParent(parent string) error {
func (ds *Store) ensureParent(parent string) error {
exists, err := ds.store.Exists(parent)
if err != nil {
return err
@@ -337,7 +304,9 @@ func (ds *datastore) ensureParent(parent string) error {
return ds.store.Put(parent, []byte{})
}
func (ds *datastore) List(key string, kvObject KVObject) ([]KVObject, error) {
// List returns of a list of KVObjects belonging to the parent key. The caller
// must pass a KVObject of the same type as the objects that need to be listed.
func (ds *Store) List(key string, kvObject KVObject) ([]KVObject, error) {
ds.mu.Lock()
defer ds.mu.Unlock()
@@ -356,7 +325,7 @@ func (ds *datastore) List(key string, kvObject KVObject) ([]KVObject, error) {
return kvol, nil
}
func (ds *datastore) iterateKVPairsFromStore(key string, kvObject KVObject, callback func(string, KVObject)) error {
func (ds *Store) iterateKVPairsFromStore(key string, kvObject KVObject, callback func(string, KVObject)) error {
// Bail out right away if the kvObject does not implement KVConstructor
ctor, ok := kvObject.(KVConstructor)
if !ok {
@@ -392,7 +361,8 @@ func (ds *datastore) iterateKVPairsFromStore(key string, kvObject KVObject, call
return nil
}
func (ds *datastore) Map(key string, kvObject KVObject) (map[string]KVObject, error) {
// Map returns a Map of KVObjects.
func (ds *Store) Map(key string, kvObject KVObject) (map[string]KVObject, error) {
ds.mu.Lock()
defer ds.mu.Unlock()
@@ -408,8 +378,8 @@ func (ds *datastore) Map(key string, kvObject KVObject) (map[string]KVObject, er
return kvol, nil
}
// DeleteObjectAtomic performs atomic delete on a record
func (ds *datastore) DeleteObjectAtomic(kvObject KVObject) error {
// DeleteObjectAtomic performs atomic delete on a record.
func (ds *Store) DeleteObjectAtomic(kvObject KVObject) error {
ds.mu.Lock()
defer ds.mu.Unlock()

View File

@@ -2,7 +2,6 @@ package datastore
import (
"encoding/json"
"reflect"
"testing"
"github.com/docker/docker/libnetwork/options"
@@ -11,9 +10,9 @@ import (
var dummyKey = "dummy"
// NewCustomDataStore can be used by other Tests in order to use custom datastore
func NewTestDataStore() DataStore {
return &datastore{scope: LocalScope, store: NewMockStore()}
// NewTestDataStore can be used by other Tests in order to use custom datastore
func NewTestDataStore() *Store {
return &Store{scope: LocalScope, store: NewMockStore()}
}
func TestKey(t *testing.T) {
@@ -24,25 +23,13 @@ func TestKey(t *testing.T) {
}
}
func TestParseKey(t *testing.T) {
keySlice, err := ParseKey("/docker/network/v1.0/hello/world/")
if err != nil {
t.Fatal(err)
}
eKey := []string{"hello", "world"}
if len(keySlice) < 2 || !reflect.DeepEqual(eKey, keySlice) {
t.Fatalf("unexpected unkey : %s", keySlice)
}
}
func TestInvalidDataStore(t *testing.T) {
config := ScopeCfg{
_, err := New(ScopeCfg{
Client: ScopeClientCfg{
Provider: "invalid",
Address: "localhost:8500",
},
}
_, err := NewDataStore(config)
})
if err == nil {
t.Fatal("Invalid Datastore connection configuration must result in a failure")
}

View File

@@ -7,9 +7,6 @@ import (
"github.com/docker/docker/libnetwork/types"
)
// ErrNotImplemented exported
var ErrNotImplemented = errors.New("Functionality not implemented")
// MockData exported
type MockData struct {
Data []byte
@@ -23,8 +20,7 @@ type MockStore struct {
// NewMockStore creates a Map backed Datastore that is useful for mocking
func NewMockStore() *MockStore {
db := make(map[string]*MockData)
return &MockStore{db}
return &MockStore{db: make(map[string]*MockData)}
}
// Get the value at "key", returns the last modified index
@@ -56,7 +52,7 @@ func (s *MockStore) Exists(key string) (bool, error) {
// List gets a range of values at "directory"
func (s *MockStore) List(prefix string) ([]*store.KVPair, error) {
return nil, ErrNotImplemented
return nil, errors.New("not implemented")
}
// AtomicPut put a value at "key" if the key has not been

View File

@@ -153,7 +153,7 @@ type driver struct {
isolationChain1V6 *iptables.ChainInfo
isolationChain2V6 *iptables.ChainInfo
networks map[string]*bridgeNetwork
store datastore.DataStore
store *datastore.Store
nlh *netlink.Handle
configNetwork sync.Mutex
portAllocator *portallocator.PortAllocator // Overridable for tests.

View File

@@ -30,7 +30,7 @@ func (d *driver) initStore(option map[string]interface{}) error {
if !ok {
return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
}
d.store, err = datastore.NewDataStoreFromConfig(dsc)
d.store, err = datastore.FromConfig(dsc)
if err != nil {
return types.InternalErrorf("bridge driver failed to initialize data store: %v", err)
}

View File

@@ -40,7 +40,7 @@ type driver struct {
networks networkTable
sync.Once
sync.Mutex
store datastore.DataStore
store *datastore.Store
}
type endpoint struct {

View File

@@ -50,7 +50,7 @@ func (d *driver) initStore(option map[string]interface{}) error {
if !ok {
return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
}
d.store, err = datastore.NewDataStoreFromConfig(dsc)
d.store, err = datastore.FromConfig(dsc)
if err != nil {
return types.InternalErrorf("ipvlan driver failed to initialize data store: %v", err)
}

View File

@@ -34,7 +34,7 @@ type driver struct {
networks networkTable
sync.Once
sync.Mutex
store datastore.DataStore
store *datastore.Store
}
type endpoint struct {

View File

@@ -49,7 +49,7 @@ func (d *driver) initStore(option map[string]interface{}) error {
if !ok {
return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
}
d.store, err = datastore.NewDataStoreFromConfig(dsc)
d.store, err = datastore.FromConfig(dsc)
if err != nil {
return types.InternalErrorf("macvlan driver failed to initialize data store: %v", err)
}

View File

@@ -101,7 +101,7 @@ type hnsNetwork struct {
type driver struct {
name string
networks map[string]*hnsNetwork
store datastore.DataStore
store *datastore.Store
sync.Mutex
}

View File

@@ -27,7 +27,7 @@ func (d *driver) initStore(option map[string]interface{}) error {
if !ok {
return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
}
d.store, err = datastore.NewDataStoreFromConfig(dsc)
d.store, err = datastore.FromConfig(dsc)
if err != nil {
return types.InternalErrorf("windows driver failed to initialize data store: %v", err)
}

View File

@@ -24,7 +24,7 @@ func (c *Controller) initStores() error {
return nil
}
var err error
c.store, err = datastore.NewDataStore(c.cfg.Scope)
c.store, err = datastore.New(c.cfg.Scope)
if err != nil {
return err
}
@@ -39,7 +39,7 @@ func (c *Controller) closeStores() {
}
}
func (c *Controller) getStore() datastore.DataStore {
func (c *Controller) getStore() *datastore.Store {
c.mu.Lock()
defer c.mu.Unlock()