That function was needlessly complex. Instead of relying on a struct and
a sub-struct, it now just takes two string params: a path and a bucket
name.
Libnetwork config is now initialized with default values. A new struct
is introduced in libnetwork/config to let tests customize the path and
bucket name.
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
| ... | ... |
@@ -39,7 +39,7 @@ type Config struct {
|
| 39 | 39 |
ClusterProvider cluster.Provider |
| 40 | 40 |
NetworkControlPlaneMTU int |
| 41 | 41 |
DefaultAddressPool []*ipamutils.NetworkToSplit |
| 42 |
- Scope datastore.ScopeCfg |
|
| 42 |
+ DatastoreBucket string |
|
| 43 | 43 |
ActiveSandboxes map[string]interface{}
|
| 44 | 44 |
PluginGetter plugingetter.PluginGetter |
| 45 | 45 |
} |
| ... | ... |
@@ -47,7 +47,8 @@ type Config struct {
|
| 47 | 47 |
// New creates a new Config and initializes it with the given Options. |
| 48 | 48 |
func New(opts ...Option) *Config {
|
| 49 | 49 |
cfg := &Config{
|
| 50 |
- driverCfg: make(map[string]map[string]any), |
|
| 50 |
+ driverCfg: make(map[string]map[string]any), |
|
| 51 |
+ DatastoreBucket: datastore.DefaultBucket, |
|
| 51 | 52 |
} |
| 52 | 53 |
|
| 53 | 54 |
for _, opt := range opts {
|
| ... | ... |
@@ -56,10 +57,6 @@ func New(opts ...Option) *Config {
|
| 56 | 56 |
} |
| 57 | 57 |
} |
| 58 | 58 |
|
| 59 |
- // load default scope configs which don't have explicit user specified configs. |
|
| 60 |
- if cfg.Scope == (datastore.ScopeCfg{}) {
|
|
| 61 |
- cfg.Scope = datastore.DefaultScope(cfg.DataDir) |
|
| 62 |
- } |
|
| 63 | 59 |
return cfg |
| 64 | 60 |
} |
| 65 | 61 |
|
| ... | ... |
@@ -108,7 +108,7 @@ type Controller struct {
|
| 108 | 108 |
// New creates a new instance of network controller. |
| 109 | 109 |
func New(cfgOptions ...config.Option) (*Controller, error) {
|
| 110 | 110 |
cfg := config.New(cfgOptions...) |
| 111 |
- store, err := datastore.New(cfg.Scope) |
|
| 111 |
+ store, err := datastore.New(cfg.DataDir, cfg.DatastoreBucket) |
|
| 112 | 112 |
if err != nil {
|
| 113 | 113 |
return nil, fmt.Errorf("libnet controller initialization: %w", err)
|
| 114 | 114 |
} |
| ... | ... |
@@ -333,7 +333,9 @@ func (c *Controller) makeDriverConfig(ntype string) map[string]interface{} {
|
| 333 | 333 |
return nil |
| 334 | 334 |
} |
| 335 | 335 |
|
| 336 |
- cfg := map[string]interface{}{}
|
|
| 336 |
+ cfg := map[string]interface{}{
|
|
| 337 |
+ netlabel.LocalKVClient: c.store, |
|
| 338 |
+ } |
|
| 337 | 339 |
for _, label := range c.cfg.Labels {
|
| 338 | 340 |
key, val, _ := strings.Cut(label, "=") |
| 339 | 341 |
if !strings.HasPrefix(key, netlabel.DriverPrefix+"."+ntype) {
|
| ... | ... |
@@ -348,10 +350,6 @@ func (c *Controller) makeDriverConfig(ntype string) map[string]interface{} {
|
| 348 | 348 |
cfg[k] = v |
| 349 | 349 |
} |
| 350 | 350 |
|
| 351 |
- if c.cfg.Scope.IsValid() {
|
|
| 352 |
- cfg[netlabel.LocalKVClient] = c.store |
|
| 353 |
- } |
|
| 354 |
- |
|
| 355 | 351 |
return cfg |
| 356 | 352 |
} |
| 357 | 353 |
|
| ... | ... |
@@ -1,10 +1,10 @@ |
| 1 | 1 |
package datastore |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "fmt" |
|
| 4 |
+ "errors" |
|
| 5 |
+ "path" |
|
| 5 | 6 |
"strings" |
| 6 | 7 |
"sync" |
| 7 |
- "time" |
|
| 8 | 8 |
|
| 9 | 9 |
store "github.com/docker/docker/libnetwork/internal/kvstore" |
| 10 | 10 |
"github.com/docker/docker/libnetwork/internal/kvstore/boltdb" |
| ... | ... |
@@ -50,18 +50,6 @@ type KVObject interface {
|
| 50 | 50 |
CopyTo(KVObject) error |
| 51 | 51 |
} |
| 52 | 52 |
|
| 53 |
-// ScopeCfg represents Datastore configuration. |
|
| 54 |
-type ScopeCfg struct {
|
|
| 55 |
- Client ScopeClientCfg |
|
| 56 |
-} |
|
| 57 |
- |
|
| 58 |
-// ScopeClientCfg represents Datastore Client-only mode configuration |
|
| 59 |
-type ScopeClientCfg struct {
|
|
| 60 |
- Provider string |
|
| 61 |
- Address string |
|
| 62 |
- Config *store.Config |
|
| 63 |
-} |
|
| 64 |
- |
|
| 65 | 53 |
const ( |
| 66 | 54 |
// NetworkKeyPrefix is the prefix for network key in the kv store |
| 67 | 55 |
NetworkKeyPrefix = "network" |
| ... | ... |
@@ -74,37 +62,7 @@ var ( |
| 74 | 74 |
rootChain = defaultRootChain |
| 75 | 75 |
) |
| 76 | 76 |
|
| 77 |
-const defaultPrefix = "/var/lib/docker/network/files" |
|
| 78 |
- |
|
| 79 |
-// DefaultScope returns a default scope config for clients to use. |
|
| 80 |
-func DefaultScope(dataDir string) ScopeCfg {
|
|
| 81 |
- var dbpath string |
|
| 82 |
- if dataDir == "" {
|
|
| 83 |
- dbpath = defaultPrefix + "/local-kv.db" |
|
| 84 |
- } else {
|
|
| 85 |
- dbpath = dataDir + "/network/files/local-kv.db" |
|
| 86 |
- } |
|
| 87 |
- |
|
| 88 |
- return ScopeCfg{
|
|
| 89 |
- Client: ScopeClientCfg{
|
|
| 90 |
- Provider: string(store.BOLTDB), |
|
| 91 |
- Address: dbpath, |
|
| 92 |
- Config: &store.Config{
|
|
| 93 |
- Bucket: "libnetwork", |
|
| 94 |
- ConnectionTimeout: time.Minute, |
|
| 95 |
- }, |
|
| 96 |
- }, |
|
| 97 |
- } |
|
| 98 |
-} |
|
| 99 |
- |
|
| 100 |
-// IsValid checks if the scope config has valid configuration. |
|
| 101 |
-func (cfg *ScopeCfg) IsValid() bool {
|
|
| 102 |
- if cfg == nil || strings.TrimSpace(cfg.Client.Provider) == "" || strings.TrimSpace(cfg.Client.Address) == "" {
|
|
| 103 |
- return false |
|
| 104 |
- } |
|
| 105 |
- |
|
| 106 |
- return true |
|
| 107 |
-} |
|
| 77 |
+const DefaultBucket = "libnetwork" |
|
| 108 | 78 |
|
| 109 | 79 |
// Key provides convenient method to create a Key |
| 110 | 80 |
func Key(key ...string) string {
|
| ... | ... |
@@ -118,17 +76,16 @@ func Key(key ...string) string {
|
| 118 | 118 |
return b.String() |
| 119 | 119 |
} |
| 120 | 120 |
|
| 121 |
-// newClient used to connect to KV Store |
|
| 122 |
-func newClient(kv string, addr string, config *store.Config) (*Store, error) {
|
|
| 123 |
- if kv != string(store.BOLTDB) {
|
|
| 124 |
- return nil, fmt.Errorf("unsupported KV store")
|
|
| 121 |
+// New creates a new Store instance. |
|
| 122 |
+func New(dir, bucket string) (*Store, error) {
|
|
| 123 |
+ if dir == "" {
|
|
| 124 |
+ return nil, errors.New("empty dir")
|
|
| 125 | 125 |
} |
| 126 |
- |
|
| 127 |
- if config == nil {
|
|
| 128 |
- config = &store.Config{}
|
|
| 126 |
+ if bucket == "" {
|
|
| 127 |
+ return nil, errors.New("empty bucket")
|
|
| 129 | 128 |
} |
| 130 | 129 |
|
| 131 |
- s, err := boltdb.New(addr, config) |
|
| 130 |
+ s, err := boltdb.New(path.Join(dir, "local-kv.db"), bucket) |
|
| 132 | 131 |
if err != nil {
|
| 133 | 132 |
return nil, err |
| 134 | 133 |
} |
| ... | ... |
@@ -136,15 +93,6 @@ func newClient(kv string, addr string, config *store.Config) (*Store, error) {
|
| 136 | 136 |
return &Store{store: s, cache: newCache(s)}, nil
|
| 137 | 137 |
} |
| 138 | 138 |
|
| 139 |
-// New creates a new Store instance. |
|
| 140 |
-func New(cfg ScopeCfg) (*Store, error) {
|
|
| 141 |
- if cfg.Client.Provider == "" || cfg.Client.Address == "" {
|
|
| 142 |
- cfg = DefaultScope("")
|
|
| 143 |
- } |
|
| 144 |
- |
|
| 145 |
- return newClient(cfg.Client.Provider, cfg.Client.Address, cfg.Client.Config) |
|
| 146 |
-} |
|
| 147 |
- |
|
| 148 | 139 |
// Close closes the data store. |
| 149 | 140 |
func (ds *Store) Close() {
|
| 150 | 141 |
ds.store.Close() |
| ... | ... |
@@ -23,16 +23,6 @@ func TestKey(t *testing.T) {
|
| 23 | 23 |
assert.Check(t, is.Equal(sKey, expected)) |
| 24 | 24 |
} |
| 25 | 25 |
|
| 26 |
-func TestInvalidDataStore(t *testing.T) {
|
|
| 27 |
- _, err := New(ScopeCfg{
|
|
| 28 |
- Client: ScopeClientCfg{
|
|
| 29 |
- Provider: "invalid", |
|
| 30 |
- Address: "localhost:8500", |
|
| 31 |
- }, |
|
| 32 |
- }) |
|
| 33 |
- assert.Check(t, is.Error(err, "unsupported KV store")) |
|
| 34 |
-} |
|
| 35 |
- |
|
| 36 | 26 |
func TestKVObjectFlatKey(t *testing.T) {
|
| 37 | 27 |
store := NewTestDataStore() |
| 38 | 28 |
expected := dummyKVObject("1000", true)
|
| ... | ... |
@@ -3,19 +3,16 @@ package boltdb |
| 3 | 3 |
import ( |
| 4 | 4 |
"bytes" |
| 5 | 5 |
"encoding/binary" |
| 6 |
- "errors" |
|
| 7 | 6 |
"os" |
| 8 | 7 |
"path/filepath" |
| 9 | 8 |
"sync" |
| 10 | 9 |
"sync/atomic" |
| 10 |
+ "time" |
|
| 11 | 11 |
|
| 12 | 12 |
store "github.com/docker/docker/libnetwork/internal/kvstore" |
| 13 | 13 |
bolt "go.etcd.io/bbolt" |
| 14 | 14 |
) |
| 15 | 15 |
|
| 16 |
-// ErrBoltBucketOptionMissing is thrown when boltBucket config option is missing |
|
| 17 |
-var ErrBoltBucketOptionMissing = errors.New("boltBucket config option missing")
|
|
| 18 |
- |
|
| 19 | 16 |
const filePerm = 0o644 |
| 20 | 17 |
|
| 21 | 18 |
// BoltDB type implements the Store interface |
| ... | ... |
@@ -30,18 +27,14 @@ type BoltDB struct {
|
| 30 | 30 |
const libkvmetadatalen = 8 |
| 31 | 31 |
|
| 32 | 32 |
// New opens a new BoltDB connection to the specified path and bucket |
| 33 |
-func New(endpoint string, options *store.Config) (store.Store, error) {
|
|
| 34 |
- if (options == nil) || (len(options.Bucket) == 0) {
|
|
| 35 |
- return nil, ErrBoltBucketOptionMissing |
|
| 36 |
- } |
|
| 37 |
- |
|
| 38 |
- dir, _ := filepath.Split(endpoint) |
|
| 33 |
+func New(path, bucket string) (store.Store, error) {
|
|
| 34 |
+ dir, _ := filepath.Split(path) |
|
| 39 | 35 |
if err := os.MkdirAll(dir, 0o750); err != nil {
|
| 40 | 36 |
return nil, err |
| 41 | 37 |
} |
| 42 | 38 |
|
| 43 |
- db, err := bolt.Open(endpoint, filePerm, &bolt.Options{
|
|
| 44 |
- Timeout: options.ConnectionTimeout, |
|
| 39 |
+ db, err := bolt.Open(path, filePerm, &bolt.Options{
|
|
| 40 |
+ Timeout: time.Minute, |
|
| 45 | 41 |
}) |
| 46 | 42 |
if err != nil {
|
| 47 | 43 |
return nil, err |
| ... | ... |
@@ -49,8 +42,8 @@ func New(endpoint string, options *store.Config) (store.Store, error) {
|
| 49 | 49 |
|
| 50 | 50 |
b := &BoltDB{
|
| 51 | 51 |
client: db, |
| 52 |
- path: endpoint, |
|
| 53 |
- boltBucket: []byte(options.Bucket), |
|
| 52 |
+ path: path, |
|
| 53 |
+ boltBucket: []byte(bucket), |
|
| 54 | 54 |
} |
| 55 | 55 |
|
| 56 | 56 |
return b, nil |
| ... | ... |
@@ -2,7 +2,6 @@ package kvstore |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"errors" |
| 5 |
- "time" |
|
| 6 | 5 |
) |
| 7 | 6 |
|
| 8 | 7 |
// Backend represents a KV Store Backend |
| ... | ... |
@@ -24,12 +23,6 @@ var ( |
| 24 | 24 |
ErrKeyExists = errors.New("Previous K/V pair exists, cannot complete Atomic operation")
|
| 25 | 25 |
) |
| 26 | 26 |
|
| 27 |
-// Config contains the options for a storage client |
|
| 28 |
-type Config struct {
|
|
| 29 |
- ConnectionTimeout time.Duration |
|
| 30 |
- Bucket string |
|
| 31 |
-} |
|
| 32 |
- |
|
| 33 | 27 |
// Store represents the backend K/V storage |
| 34 | 28 |
// Each store should support every call listed |
| 35 | 29 |
// here. Or it couldn't be implemented as a K/V |
| ... | ... |
@@ -21,7 +21,6 @@ import ( |
| 21 | 21 |
"github.com/docker/docker/internal/testutils/netnsutils" |
| 22 | 22 |
"github.com/docker/docker/libnetwork" |
| 23 | 23 |
"github.com/docker/docker/libnetwork/config" |
| 24 |
- "github.com/docker/docker/libnetwork/datastore" |
|
| 25 | 24 |
"github.com/docker/docker/libnetwork/driverapi" |
| 26 | 25 |
"github.com/docker/docker/libnetwork/ipams/defaultipam" |
| 27 | 26 |
"github.com/docker/docker/libnetwork/ipams/null" |
| ... | ... |
@@ -45,7 +44,7 @@ const ( |
| 45 | 45 |
|
| 46 | 46 |
func TestMain(m *testing.M) {
|
| 47 | 47 |
// Cleanup local datastore file |
| 48 |
- _ = os.Remove(datastore.DefaultScope("").Client.Address)
|
|
| 48 |
+ _ = os.Remove("/var/lib/docker/network/files/local-kv.db")
|
|
| 49 | 49 |
|
| 50 | 50 |
os.Exit(m.Run()) |
| 51 | 51 |
} |
| ... | ... |
@@ -12,9 +12,7 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
func TestBoltdbBackend(t *testing.T) {
|
| 14 | 14 |
tmpPath := filepath.Join(t.TempDir(), "boltdb.db") |
| 15 |
- testLocalBackend(t, "boltdb", tmpPath, &store.Config{
|
|
| 16 |
- Bucket: "testBackend", |
|
| 17 |
- }) |
|
| 15 |
+ testLocalBackend(t, tmpPath, "testBackend") |
|
| 18 | 16 |
} |
| 19 | 17 |
|
| 20 | 18 |
func TestNoPersist(t *testing.T) {
|
| ... | ... |
@@ -5,21 +5,18 @@ import ( |
| 5 | 5 |
"testing" |
| 6 | 6 |
|
| 7 | 7 |
"github.com/docker/docker/libnetwork/config" |
| 8 |
- store "github.com/docker/docker/libnetwork/internal/kvstore" |
|
| 9 | 8 |
"github.com/docker/docker/libnetwork/netlabel" |
| 10 | 9 |
"github.com/docker/docker/libnetwork/options" |
| 11 | 10 |
) |
| 12 | 11 |
|
| 13 |
-func testLocalBackend(t *testing.T, provider, url string, storeConfig *store.Config) {
|
|
| 14 |
- cfgOptions := []config.Option{func(c *config.Config) {
|
|
| 15 |
- c.Scope.Client.Provider = provider |
|
| 16 |
- c.Scope.Client.Address = url |
|
| 17 |
- c.Scope.Client.Config = storeConfig |
|
| 18 |
- }} |
|
| 19 |
- |
|
| 20 |
- cfgOptions = append(cfgOptions, config.OptionDriverConfig("host", map[string]interface{}{
|
|
| 21 |
- netlabel.GenericData: options.Generic{},
|
|
| 22 |
- })) |
|
| 12 |
+func testLocalBackend(t *testing.T, path, bucket string) {
|
|
| 13 |
+ cfgOptions := []config.Option{
|
|
| 14 |
+ config.OptionDataDir(path), |
|
| 15 |
+ func(c *config.Config) { c.DatastoreBucket = bucket },
|
|
| 16 |
+ config.OptionDriverConfig("host", map[string]interface{}{
|
|
| 17 |
+ netlabel.GenericData: options.Generic{},
|
|
| 18 |
+ }), |
|
| 19 |
+ } |
|
| 23 | 20 |
|
| 24 | 21 |
testController, err := New(cfgOptions...) |
| 25 | 22 |
if err != nil {
|