virtcontainers: Add a Store manager

Each virtcontainers module/component should be able to get a handler on
a Store for loading component specific items. The Store manager is an
internal Store layer for tracking all created Stores.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
Samuel Ortiz 2018-12-20 12:54:34 +01:00
parent 4be76e9969
commit efd50ecac9
2 changed files with 110 additions and 2 deletions

View File

@ -7,6 +7,7 @@ package store
import (
"context"
"fmt"
"net/url"
"sync"
@ -87,6 +88,48 @@ type Store struct {
host string
}
type manager struct {
sync.RWMutex
stores map[string]*Store
}
var stores = &manager{stores: make(map[string]*Store)}
func (m *manager) addStore(s *Store) (err error) {
if s == nil {
return fmt.Errorf("Store can not be nil")
}
if s.url == "" {
return fmt.Errorf("Store URL can not be nil")
}
m.Lock()
defer m.Unlock()
if m.stores[s.url] != nil {
return fmt.Errorf("Store %s already added", s.url)
}
m.stores[s.url] = s
return nil
}
func (m *manager) removeStore(url string) {
m.Lock()
defer m.Unlock()
delete(m.stores, url)
}
func (m *manager) findStore(url string) *Store {
m.RLock()
defer m.RUnlock()
return m.stores[url]
}
// New will return a new virtcontainers Store.
// If there is already a Store for the URL, we will re-use it.
// Otherwise a new Store is created.

View File

@ -12,10 +12,75 @@ import (
"github.com/stretchr/testify/assert"
)
var storeRoot = "file:///root1/"
func TestNewStore(t *testing.T) {
s, err := New(context.Background(), "file:///root/")
s, err := New(context.Background(), storeRoot)
assert.Nil(t, err)
assert.Equal(t, s.scheme, "file")
assert.Equal(t, s.host, "")
assert.Equal(t, s.path, "/root/")
assert.Equal(t, s.path, "/root1/")
}
func TestManagerAddStore(t *testing.T) {
s, err := New(context.Background(), storeRoot)
assert.Nil(t, err)
err = stores.addStore(s)
defer stores.removeStore(storeRoot)
assert.Nil(t, err, "addStore failed")
// Duplicate, should fail
err = stores.addStore(s)
assert.NotNil(t, err, "addStore should have failed")
// Try with an empty URL
sEmpty, err := New(context.Background(), storeRoot)
assert.Nil(t, err)
sEmpty.url = ""
err = stores.addStore(sEmpty)
assert.NotNil(t, err, "addStore should have failed on an empty store URL")
}
func TestManagerRemoveStore(t *testing.T) {
s, err := New(context.Background(), storeRoot)
assert.Nil(t, err)
err = stores.addStore(s)
assert.Nil(t, err, "addStore failed")
// Positive find
newStore := stores.findStore(storeRoot)
assert.NotNil(t, newStore, "findStore failed")
// Negative removal
stores.removeStore(storeRoot + "foobar")
// We should still find storeRoot
newStore = stores.findStore(storeRoot)
assert.NotNil(t, newStore, "findStore failed")
// Positive removal
stores.removeStore(storeRoot)
// We should no longer find storeRoot
newStore = stores.findStore(storeRoot)
assert.Nil(t, newStore, "findStore should not have found %s", storeRoot)
}
func TestManagerFindStore(t *testing.T) {
s, err := New(context.Background(), storeRoot)
assert.Nil(t, err)
err = stores.addStore(s)
defer stores.removeStore(storeRoot)
assert.Nil(t, err, "addStore failed")
// Positive find
newStore := stores.findStore(storeRoot)
assert.NotNil(t, newStore, "findStore failed")
// Negative find
newStore = stores.findStore(storeRoot + "foobar")
assert.Nil(t, newStore, "findStore should not have found a new store")
}