mirror of
https://github.com/containers/podman.git
synced 2025-07-01 00:01:02 +08:00
Merge pull request #72 from mheon/file_locking
Move containers to file locks from c/storage
This commit is contained in:
@ -8,7 +8,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -64,9 +63,8 @@ type Container struct {
|
|||||||
|
|
||||||
state *containerRuntimeInfo
|
state *containerRuntimeInfo
|
||||||
|
|
||||||
// TODO move to storage.Locker from sync.Mutex
|
|
||||||
valid bool
|
valid bool
|
||||||
lock sync.Mutex
|
lock storage.Locker
|
||||||
runtime *Runtime
|
runtime *Runtime
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,6 +317,8 @@ func (c *Container) attachSocketPath() string {
|
|||||||
|
|
||||||
// Sync this container with on-disk state and runc status
|
// Sync this container with on-disk state and runc status
|
||||||
// Should only be called with container lock held
|
// Should only be called with container lock held
|
||||||
|
// This function should suffice to ensure a container's state is accurate and
|
||||||
|
// it is valid for use.
|
||||||
func (c *Container) syncContainer() error {
|
func (c *Container) syncContainer() error {
|
||||||
if err := c.runtime.state.UpdateContainer(c); err != nil {
|
if err := c.runtime.state.UpdateContainer(c); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -343,7 +343,7 @@ func (c *Container) syncContainer() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make a new container
|
// Make a new container
|
||||||
func newContainer(rspec *spec.Spec) (*Container, error) {
|
func newContainer(rspec *spec.Spec, lockDir string) (*Container, error) {
|
||||||
if rspec == nil {
|
if rspec == nil {
|
||||||
return nil, errors.Wrapf(ErrInvalidArg, "must provide a valid runtime spec to create container")
|
return nil, errors.Wrapf(ErrInvalidArg, "must provide a valid runtime spec to create container")
|
||||||
}
|
}
|
||||||
@ -360,6 +360,20 @@ func newContainer(rspec *spec.Spec) (*Container, error) {
|
|||||||
|
|
||||||
ctr.config.CreatedTime = time.Now()
|
ctr.config.CreatedTime = time.Now()
|
||||||
|
|
||||||
|
// Path our lock file will reside at
|
||||||
|
lockPath := filepath.Join(lockDir, ctr.config.ID)
|
||||||
|
// Ensure there is no conflict - file does not exist
|
||||||
|
_, err := os.Stat(lockPath)
|
||||||
|
if err == nil || !os.IsNotExist(err) {
|
||||||
|
return nil, errors.Wrapf(ErrCtrExists, "lockfile for container ID %s already exists", ctr.config.ID)
|
||||||
|
}
|
||||||
|
// Grab a lockfile at the given path
|
||||||
|
lock, err := storage.GetLockfile(lockPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "error creating lockfile for new container")
|
||||||
|
}
|
||||||
|
ctr.lock = lock
|
||||||
|
|
||||||
return ctr, nil
|
return ctr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -904,11 +918,7 @@ func (c *Container) mountStorage() (err error) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err := c.runtime.state.SaveContainer(c); err != nil {
|
return c.save()
|
||||||
return errors.Wrapf(err, "error saving container %s state", c.ID())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanupStorage unmounts all mount points in container and cleans up container storage
|
// CleanupStorage unmounts all mount points in container and cleans up container storage
|
||||||
@ -944,9 +954,5 @@ func (c *Container) cleanupStorage() error {
|
|||||||
c.state.Mountpoint = ""
|
c.state.Mountpoint = ""
|
||||||
c.state.Mounted = false
|
c.state.Mounted = false
|
||||||
|
|
||||||
if err := c.runtime.state.SaveContainer(c); err != nil {
|
return c.save()
|
||||||
return errors.Wrapf(err, "error saving container %s state", c.ID())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ type Runtime struct {
|
|||||||
storageService *storageService
|
storageService *storageService
|
||||||
imageContext *types.SystemContext
|
imageContext *types.SystemContext
|
||||||
ociRuntime *OCIRuntime
|
ociRuntime *OCIRuntime
|
||||||
|
lockDir string
|
||||||
valid bool
|
valid bool
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
@ -136,6 +137,17 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make a directory to hold container lockfiles
|
||||||
|
lockDir := filepath.Join(runtime.config.StaticDir, "lock")
|
||||||
|
if err := os.MkdirAll(lockDir, 0755); err != nil {
|
||||||
|
// The directory is allowed to exist
|
||||||
|
if !os.IsExist(err) {
|
||||||
|
return nil, errors.Wrapf(err, "error creating runtime lockfiles directory %s",
|
||||||
|
lockDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
runtime.lockDir = lockDir
|
||||||
|
|
||||||
// Make the per-boot files directory if it does not exist
|
// Make the per-boot files directory if it does not exist
|
||||||
if err := os.MkdirAll(runtime.config.TmpDir, 0755); err != nil {
|
if err := os.MkdirAll(runtime.config.TmpDir, 0755); err != nil {
|
||||||
// The directory is allowed to exist
|
// The directory is allowed to exist
|
||||||
@ -154,7 +166,6 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
runtime.state = state
|
runtime.state = state
|
||||||
} else {
|
} else {
|
||||||
dbPath := filepath.Join(runtime.config.StaticDir, "state.sql")
|
dbPath := filepath.Join(runtime.config.StaticDir, "state.sql")
|
||||||
lockPath := filepath.Join(runtime.config.TmpDir, "state.lck")
|
|
||||||
specsDir := filepath.Join(runtime.config.StaticDir, "ocispec")
|
specsDir := filepath.Join(runtime.config.StaticDir, "ocispec")
|
||||||
|
|
||||||
// Make a directory to hold JSON versions of container OCI specs
|
// Make a directory to hold JSON versions of container OCI specs
|
||||||
@ -166,7 +177,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state, err := NewSQLState(dbPath, lockPath, specsDir, runtime)
|
state, err := NewSQLState(dbPath, specsDir, runtime.lockDir, runtime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ func (r *Runtime) NewContainer(spec *spec.Spec, options ...CtrCreateOption) (c *
|
|||||||
return nil, ErrRuntimeStopped
|
return nil, ErrRuntimeStopped
|
||||||
}
|
}
|
||||||
|
|
||||||
ctr, err := newContainer(spec)
|
ctr, err := newContainer(spec, r.lockDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/containers/storage"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
@ -22,24 +21,17 @@ const DBSchema = 2
|
|||||||
type SQLState struct {
|
type SQLState struct {
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
specsDir string
|
specsDir string
|
||||||
|
lockDir string
|
||||||
runtime *Runtime
|
runtime *Runtime
|
||||||
lock storage.Locker
|
|
||||||
valid bool
|
valid bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSQLState initializes a SQL-backed state, created the database if necessary
|
// NewSQLState initializes a SQL-backed state, created the database if necessary
|
||||||
func NewSQLState(dbPath, lockPath, specsDir string, runtime *Runtime) (State, error) {
|
func NewSQLState(dbPath, specsDir, lockDir string, runtime *Runtime) (State, error) {
|
||||||
state := new(SQLState)
|
state := new(SQLState)
|
||||||
|
|
||||||
state.runtime = runtime
|
state.runtime = runtime
|
||||||
|
|
||||||
// Make our lock file
|
|
||||||
lock, err := storage.GetLockfile(lockPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "error creating lockfile for state")
|
|
||||||
}
|
|
||||||
state.lock = lock
|
|
||||||
|
|
||||||
// Make the directory that will hold JSON copies of container runtime specs
|
// Make the directory that will hold JSON copies of container runtime specs
|
||||||
if err := os.MkdirAll(specsDir, 0750); err != nil {
|
if err := os.MkdirAll(specsDir, 0750); err != nil {
|
||||||
// The directory is allowed to exist
|
// The directory is allowed to exist
|
||||||
@ -49,9 +41,14 @@ func NewSQLState(dbPath, lockPath, specsDir string, runtime *Runtime) (State, er
|
|||||||
}
|
}
|
||||||
state.specsDir = specsDir
|
state.specsDir = specsDir
|
||||||
|
|
||||||
// Acquire the lock while we open the database and perform initial setup
|
// Make the directory that will hold container lockfiles
|
||||||
state.lock.Lock()
|
if err := os.MkdirAll(lockDir, 0750); err != nil {
|
||||||
defer state.lock.Unlock()
|
// The directory is allowed to exist
|
||||||
|
if !os.IsExist(err) {
|
||||||
|
return nil, errors.Wrapf(err, "error creating lockfiles dir %s", lockDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.lockDir = lockDir
|
||||||
|
|
||||||
// TODO add a separate temporary database for per-boot container
|
// TODO add a separate temporary database for per-boot container
|
||||||
// state
|
// state
|
||||||
@ -87,9 +84,6 @@ func NewSQLState(dbPath, lockPath, specsDir string, runtime *Runtime) (State, er
|
|||||||
|
|
||||||
// Close the state's database connection
|
// Close the state's database connection
|
||||||
func (s *SQLState) Close() error {
|
func (s *SQLState) Close() error {
|
||||||
s.lock.Lock()
|
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
if !s.valid {
|
if !s.valid {
|
||||||
return ErrDBClosed
|
return ErrDBClosed
|
||||||
}
|
}
|
||||||
@ -176,7 +170,7 @@ func (s *SQLState) Container(id string) (*Container, error) {
|
|||||||
|
|
||||||
row := s.db.QueryRow(query, id)
|
row := s.db.QueryRow(query, id)
|
||||||
|
|
||||||
ctr, err := ctrFromScannable(row, s.runtime, s.specsDir)
|
ctr, err := ctrFromScannable(row, s.runtime, s.specsDir, s.lockDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "error retrieving container %s from database", id)
|
return nil, errors.Wrapf(err, "error retrieving container %s from database", id)
|
||||||
}
|
}
|
||||||
@ -223,7 +217,7 @@ func (s *SQLState) LookupContainer(idOrName string) (*Container, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
ctr, err = ctrFromScannable(rows, s.runtime, s.specsDir)
|
ctr, err = ctrFromScannable(rows, s.runtime, s.specsDir, s.lockDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "error retrieving container %s from database", idOrName)
|
return nil, errors.Wrapf(err, "error retrieving container %s from database", idOrName)
|
||||||
}
|
}
|
||||||
@ -296,9 +290,6 @@ func (s *SQLState) AddContainer(ctr *Container) (err error) {
|
|||||||
return errors.Wrapf(err, "error marshaling container %s labels to JSON", ctr.ID())
|
return errors.Wrapf(err, "error marshaling container %s labels to JSON", ctr.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
s.lock.Lock()
|
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
tx, err := s.db.Begin()
|
tx, err := s.db.Begin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error beginning database transaction")
|
return errors.Wrapf(err, "error beginning database transaction")
|
||||||
@ -477,9 +468,6 @@ func (s *SQLState) SaveContainer(ctr *Container) error {
|
|||||||
Pid=?
|
Pid=?
|
||||||
WHERE Id=?;`
|
WHERE Id=?;`
|
||||||
|
|
||||||
s.lock.Lock()
|
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
if !s.valid {
|
if !s.valid {
|
||||||
return ErrDBClosed
|
return ErrDBClosed
|
||||||
}
|
}
|
||||||
@ -537,9 +525,6 @@ func (s *SQLState) RemoveContainer(ctr *Container) error {
|
|||||||
removeState = "DELETE FROM containerState WHERE ID=?;"
|
removeState = "DELETE FROM containerState WHERE ID=?;"
|
||||||
)
|
)
|
||||||
|
|
||||||
s.lock.Lock()
|
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
if !s.valid {
|
if !s.valid {
|
||||||
return ErrDBClosed
|
return ErrDBClosed
|
||||||
}
|
}
|
||||||
@ -622,7 +607,7 @@ func (s *SQLState) AllContainers() ([]*Container, error) {
|
|||||||
containers := []*Container{}
|
containers := []*Container{}
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
ctr, err := ctrFromScannable(rows, s.runtime, s.specsDir)
|
ctr, err := ctrFromScannable(rows, s.runtime, s.specsDir, s.lockDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/containers/storage"
|
||||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -266,7 +267,7 @@ type scannable interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read a single container from a single row result in the database
|
// Read a single container from a single row result in the database
|
||||||
func ctrFromScannable(row scannable, runtime *Runtime, specsDir string) (*Container, error) {
|
func ctrFromScannable(row scannable, runtime *Runtime, specsDir string, lockDir string) (*Container, error) {
|
||||||
var (
|
var (
|
||||||
id string
|
id string
|
||||||
name string
|
name string
|
||||||
@ -384,6 +385,14 @@ func ctrFromScannable(row scannable, runtime *Runtime, specsDir string) (*Contai
|
|||||||
ctr.valid = true
|
ctr.valid = true
|
||||||
ctr.runtime = runtime
|
ctr.runtime = runtime
|
||||||
|
|
||||||
|
// Open and set the lockfile
|
||||||
|
lockPath := filepath.Join(lockDir, id)
|
||||||
|
lock, err := storage.GetLockfile(lockPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "error retrieving lockfile for container %s", id)
|
||||||
|
}
|
||||||
|
ctr.lock = lock
|
||||||
|
|
||||||
// Retrieve the spec from disk
|
// Retrieve the spec from disk
|
||||||
ociSpec := new(spec.Spec)
|
ociSpec := new(spec.Spec)
|
||||||
specPath := getSpecPath(specsDir, id)
|
specPath := getSpecPath(specsDir, id)
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getTestContainer(id, name string) *Container {
|
func getTestContainer(id, name, locksDir string) (*Container, error) {
|
||||||
ctr := &Container{
|
ctr := &Container{
|
||||||
config: &ContainerConfig{
|
config: &ContainerConfig{
|
||||||
ID: id,
|
ID: id,
|
||||||
@ -44,7 +44,15 @@ func getTestContainer(id, name string) *Container {
|
|||||||
|
|
||||||
ctr.config.Labels["test"] = "testing"
|
ctr.config.Labels["test"] = "testing"
|
||||||
|
|
||||||
return ctr
|
// Must make lockfile or container will error on being retrieved from DB
|
||||||
|
lockPath := filepath.Join(locksDir, id)
|
||||||
|
lock, err := storage.GetLockfile(lockPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ctr.lock = lock
|
||||||
|
|
||||||
|
return ctr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// This horrible hack tests if containers are equal in a way that should handle
|
// This horrible hack tests if containers are equal in a way that should handle
|
||||||
@ -89,10 +97,10 @@ func testContainersEqual(a, b *Container) bool {
|
|||||||
|
|
||||||
// Get an empty state for use in tests
|
// Get an empty state for use in tests
|
||||||
// An empty Runtime is provided
|
// An empty Runtime is provided
|
||||||
func getEmptyState() (s State, p string, err error) {
|
func getEmptyState() (s State, p string, p2 string, err error) {
|
||||||
tmpDir, err := ioutil.TempDir("", "libpod_state_test_")
|
tmpDir, err := ioutil.TempDir("", "libpod_state_test_")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", "", err
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -101,27 +109,29 @@ func getEmptyState() (s State, p string, err error) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
dbPath := filepath.Join(tmpDir, "db.sql")
|
dbPath := filepath.Join(tmpDir, "db.sql")
|
||||||
lockPath := filepath.Join(tmpDir, "db.lck")
|
specsDir := filepath.Join(tmpDir, "specs")
|
||||||
|
lockDir := filepath.Join(tmpDir, "locks")
|
||||||
|
|
||||||
runtime := new(Runtime)
|
runtime := new(Runtime)
|
||||||
runtime.config = new(RuntimeConfig)
|
runtime.config = new(RuntimeConfig)
|
||||||
runtime.config.StorageConfig = storage.StoreOptions{}
|
runtime.config.StorageConfig = storage.StoreOptions{}
|
||||||
|
|
||||||
state, err := NewSQLState(dbPath, lockPath, tmpDir, runtime)
|
state, err := NewSQLState(dbPath, specsDir, lockDir, runtime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return state, tmpDir, nil
|
return state, tmpDir, lockDir, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddAndGetContainer(t *testing.T) {
|
func TestAddAndGetContainer(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, lockPath, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
|
||||||
testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = state.AddContainer(testCtr)
|
err = state.AddContainer(testCtr)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -137,13 +147,15 @@ func TestAddAndGetContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAddAndGetContainerFromMultiple(t *testing.T) {
|
func TestAddAndGetContainerFromMultiple(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, lockPath, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
|
||||||
testCtr1 := getTestContainer("11111111111111111111111111111111", "test1")
|
testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath)
|
||||||
testCtr2 := getTestContainer("22222222222222222222222222222222", "test2")
|
assert.NoError(t, err)
|
||||||
|
testCtr2, err := getTestContainer("22222222222222222222222222222222", "test2", lockPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = state.AddContainer(testCtr1)
|
err = state.AddContainer(testCtr1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -162,7 +174,7 @@ func TestAddAndGetContainerFromMultiple(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAddInvalidContainerFails(t *testing.T) {
|
func TestAddInvalidContainerFails(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, _, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
@ -172,13 +184,15 @@ func TestAddInvalidContainerFails(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAddDuplicateIDFails(t *testing.T) {
|
func TestAddDuplicateIDFails(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, lockPath, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
|
||||||
testCtr1 := getTestContainer("11111111111111111111111111111111", "test1")
|
testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath)
|
||||||
testCtr2 := getTestContainer(testCtr1.ID(), "test2")
|
assert.NoError(t, err)
|
||||||
|
testCtr2, err := getTestContainer(testCtr1.ID(), "test2", lockPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = state.AddContainer(testCtr1)
|
err = state.AddContainer(testCtr1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -188,13 +202,15 @@ func TestAddDuplicateIDFails(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAddDuplicateNameFails(t *testing.T) {
|
func TestAddDuplicateNameFails(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, lockPath, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
|
||||||
testCtr1 := getTestContainer("11111111111111111111111111111111", "test1")
|
testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath)
|
||||||
testCtr2 := getTestContainer("22222222222222222222222222222222", testCtr1.Name())
|
assert.NoError(t, err)
|
||||||
|
testCtr2, err := getTestContainer("22222222222222222222222222222222", testCtr1.Name(), lockPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = state.AddContainer(testCtr1)
|
err = state.AddContainer(testCtr1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -204,7 +220,7 @@ func TestAddDuplicateNameFails(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetNonexistantContainerFails(t *testing.T) {
|
func TestGetNonexistantContainerFails(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, _, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
@ -214,7 +230,7 @@ func TestGetNonexistantContainerFails(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetContainerWithEmptyIDFails(t *testing.T) {
|
func TestGetContainerWithEmptyIDFails(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, _, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
@ -224,7 +240,7 @@ func TestGetContainerWithEmptyIDFails(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLookupContainerWithEmptyIDFails(t *testing.T) {
|
func TestLookupContainerWithEmptyIDFails(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, _, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
@ -234,7 +250,7 @@ func TestLookupContainerWithEmptyIDFails(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLookupNonexistantContainerFails(t *testing.T) {
|
func TestLookupNonexistantContainerFails(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, _, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
|
|
||||||
@ -243,12 +259,13 @@ func TestLookupNonexistantContainerFails(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLookupContainerByFullID(t *testing.T) {
|
func TestLookupContainerByFullID(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, lockPath, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
|
||||||
testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = state.AddContainer(testCtr)
|
err = state.AddContainer(testCtr)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -264,12 +281,13 @@ func TestLookupContainerByFullID(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLookupContainerByUniquePartialID(t *testing.T) {
|
func TestLookupContainerByUniquePartialID(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, lockPath, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
|
||||||
testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = state.AddContainer(testCtr)
|
err = state.AddContainer(testCtr)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -285,13 +303,15 @@ func TestLookupContainerByUniquePartialID(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLookupContainerByNonUniquePartialIDFails(t *testing.T) {
|
func TestLookupContainerByNonUniquePartialIDFails(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, lockPath, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
|
||||||
testCtr1 := getTestContainer("00000000000000000000000000000000", "test1")
|
testCtr1, err := getTestContainer("00000000000000000000000000000000", "test1", lockPath)
|
||||||
testCtr2 := getTestContainer("00000000000000000000000000000001", "test2")
|
assert.NoError(t, err)
|
||||||
|
testCtr2, err := getTestContainer("00000000000000000000000000000001", "test2", lockPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = state.AddContainer(testCtr1)
|
err = state.AddContainer(testCtr1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -304,12 +324,13 @@ func TestLookupContainerByNonUniquePartialIDFails(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLookupContainerByName(t *testing.T) {
|
func TestLookupContainerByName(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, lockPath, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
|
||||||
testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = state.AddContainer(testCtr)
|
err = state.AddContainer(testCtr)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -325,7 +346,7 @@ func TestLookupContainerByName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHasContainerEmptyIDFails(t *testing.T) {
|
func TestHasContainerEmptyIDFails(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, _, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
@ -335,7 +356,7 @@ func TestHasContainerEmptyIDFails(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHasContainerNoSuchContainerReturnsFalse(t *testing.T) {
|
func TestHasContainerNoSuchContainerReturnsFalse(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, _, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
@ -346,12 +367,13 @@ func TestHasContainerNoSuchContainerReturnsFalse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHasContainerFindsContainer(t *testing.T) {
|
func TestHasContainerFindsContainer(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, lockPath, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
|
||||||
testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = state.AddContainer(testCtr)
|
err = state.AddContainer(testCtr)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -362,12 +384,13 @@ func TestHasContainerFindsContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSaveAndUpdateContainer(t *testing.T) {
|
func TestSaveAndUpdateContainer(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, lockPath, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
|
||||||
testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = state.AddContainer(testCtr)
|
err = state.AddContainer(testCtr)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -393,12 +416,13 @@ func TestSaveAndUpdateContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateContainerNotInDatabaseReturnsError(t *testing.T) {
|
func TestUpdateContainerNotInDatabaseReturnsError(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, lockPath, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
|
||||||
testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = state.UpdateContainer(testCtr)
|
err = state.UpdateContainer(testCtr)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
@ -406,7 +430,7 @@ func TestUpdateContainerNotInDatabaseReturnsError(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateInvalidContainerReturnsError(t *testing.T) {
|
func TestUpdateInvalidContainerReturnsError(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, _, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
@ -416,7 +440,7 @@ func TestUpdateInvalidContainerReturnsError(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSaveInvalidContainerReturnsError(t *testing.T) {
|
func TestSaveInvalidContainerReturnsError(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, _, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
@ -426,24 +450,26 @@ func TestSaveInvalidContainerReturnsError(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSaveContainerNotInStateReturnsError(t *testing.T) {
|
func TestSaveContainerNotInStateReturnsError(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, lockPath, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
|
||||||
testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = state.SaveContainer(testCtr)
|
err = state.SaveContainer(testCtr)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoveContainer(t *testing.T) {
|
func TestRemoveContainer(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, lockPath, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
|
||||||
testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = state.AddContainer(testCtr)
|
err = state.AddContainer(testCtr)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -461,19 +487,20 @@ func TestRemoveContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoveNonexistantContainerFails(t *testing.T) {
|
func TestRemoveNonexistantContainerFails(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, lockPath, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
|
||||||
testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = state.RemoveContainer(testCtr)
|
err = state.RemoveContainer(testCtr)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetAllContainersOnNewStateIsEmpty(t *testing.T) {
|
func TestGetAllContainersOnNewStateIsEmpty(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, _, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
@ -484,12 +511,13 @@ func TestGetAllContainersOnNewStateIsEmpty(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetAllContainersWithOneContainer(t *testing.T) {
|
func TestGetAllContainersWithOneContainer(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, lockPath, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
|
||||||
testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = state.AddContainer(testCtr)
|
err = state.AddContainer(testCtr)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -506,13 +534,15 @@ func TestGetAllContainersWithOneContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetAllContainersTwoContainers(t *testing.T) {
|
func TestGetAllContainersTwoContainers(t *testing.T) {
|
||||||
state, path, err := getEmptyState()
|
state, path, lockPath, err := getEmptyState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
|
|
||||||
testCtr1 := getTestContainer("11111111111111111111111111111111", "test1")
|
testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath)
|
||||||
testCtr2 := getTestContainer("22222222222222222222222222222222", "test2")
|
assert.NoError(t, err)
|
||||||
|
testCtr2, err := getTestContainer("22222222222222222222222222222222", "test2", lockPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = state.AddContainer(testCtr1)
|
err = state.AddContainer(testCtr1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
Reference in New Issue
Block a user