summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@gmail.com>2018-06-25 13:27:57 -0400
committerMatthew Heon <matthew.heon@gmail.com>2018-07-24 16:12:31 -0400
commitab9bc2187795b61a41dfa825ddf173ff92d531d1 (patch)
tree9c47bd939d6a28a11c827ebe65c95a0a5a5507c4
parent24457873366bbd23d71b364a63037f34c652c04a (diff)
downloadpodman-ab9bc2187795b61a41dfa825ddf173ff92d531d1.tar.gz
podman-ab9bc2187795b61a41dfa825ddf173ff92d531d1.tar.bz2
podman-ab9bc2187795b61a41dfa825ddf173ff92d531d1.zip
Add namespaces and initial constraints to database
Add basic awareness of namespaces to the database. As part of this, add constraints so containers can only be added to pods in the same namespace. Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
-rw-r--r--libpod/boltdb_state.go11
-rw-r--r--libpod/boltdb_state_internal.go19
-rw-r--r--libpod/errors.go4
-rw-r--r--libpod/in_memory_state.go5
-rw-r--r--libpod/state_test.go91
5 files changed, 130 insertions, 0 deletions
diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go
index 45d09348e..648c14267 100644
--- a/libpod/boltdb_state.go
+++ b/libpod/boltdb_state.go
@@ -964,6 +964,11 @@ func (s *BoltState) AddPod(pod *Pod) error {
podID := []byte(pod.ID())
podName := []byte(pod.Name())
+ var podNamespace []byte
+ if pod.config.Namespace != "" {
+ podNamespace = []byte(pod.config.Namespace)
+ }
+
podConfigJSON, err := json.Marshal(pod.config)
if err != nil {
return errors.Wrapf(err, "error marshalling pod %s config to JSON", pod.ID())
@@ -1031,6 +1036,12 @@ func (s *BoltState) AddPod(pod *Pod) error {
return errors.Wrapf(err, "error storing pod %s state JSON in DB", pod.ID())
}
+ if podNamespace != nil {
+ if err := newPod.Put(namespaceKey, podNamespace); err != nil {
+ return errors.Wrapf(err, "error storing pod %s namespace in DB", pod.ID())
+ }
+ }
+
// Add us to the ID and names buckets
if err := idsBkt.Put(podID, podName); err != nil {
return errors.Wrapf(err, "error storing pod %s ID in DB", pod.ID())
diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go
index 69e7bee21..5661c5b7f 100644
--- a/libpod/boltdb_state_internal.go
+++ b/libpod/boltdb_state_internal.go
@@ -1,6 +1,7 @@
package libpod
import (
+ "bytes"
"encoding/json"
"path/filepath"
"runtime"
@@ -27,6 +28,7 @@ const (
netNSName = "netns"
containersName = "containers"
podIDName = "pod-id"
+ namespaceName = "namespace"
)
var (
@@ -44,6 +46,7 @@ var (
netNSKey = []byte(netNSName)
containersBkt = []byte(containersName)
podIDKey = []byte(podIDName)
+ namespaceKey = []byte(namespaceName)
)
// Check if the configuration of the database is compatible with the
@@ -262,6 +265,11 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error {
ctrID := []byte(ctr.ID())
ctrName := []byte(ctr.Name())
+ var ctrNamespace []byte
+ if ctr.config.Namespace != "" {
+ ctrNamespace = []byte(ctr.config.Namespace)
+ }
+
db, err := s.getDBCon()
if err != nil {
return err
@@ -309,6 +317,12 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error {
if podCtrs == nil {
return errors.Wrapf(ErrInternal, "pod %s does not have a containers bucket", pod.ID())
}
+
+ podNS := podDB.Get(namespaceKey)
+ if !bytes.Equal(podNS, ctrNamespace) {
+ return errors.Wrapf(ErrNSMismatch, "container %s is in namespace %s and pod %s is in namespace %s",
+ ctr.ID(), ctr.config.Namespace, pod.ID(), pod.config.Namespace)
+ }
}
// Check if we already have a container with the given ID and name
@@ -344,6 +358,11 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error {
if err := newCtrBkt.Put(stateKey, stateJSON); err != nil {
return errors.Wrapf(err, "error adding container %s state to DB", ctr.ID())
}
+ if ctrNamespace != nil {
+ if err := newCtrBkt.Put(namespaceKey, ctrNamespace); err != nil {
+ return errors.Wrapf(err, "error adding container %s namespace to DB", ctr.ID())
+ }
+ }
if pod != nil {
if err := newCtrBkt.Put(podIDKey, []byte(pod.ID())); err != nil {
return errors.Wrapf(err, "error adding container %s pod to DB", ctr.ID())
diff --git a/libpod/errors.go b/libpod/errors.go
index ddd586e29..75b4928da 100644
--- a/libpod/errors.go
+++ b/libpod/errors.go
@@ -63,6 +63,10 @@ var (
// was created by a libpod with a different config
ErrDBBadConfig = errors.New("database configuration mismatch")
+ // ErrNSMismatch indicates that the requested pod or container is in a
+ // different namespace and cannot be accessed or modified.
+ ErrNSMismatch = errors.New("target is in a different namespace")
+
// ErrNotImplemented indicates that the requested functionality is not
// yet present
ErrNotImplemented = errors.New("not yet implemented")
diff --git a/libpod/in_memory_state.go b/libpod/in_memory_state.go
index 36077b9d1..cf2f43477 100644
--- a/libpod/in_memory_state.go
+++ b/libpod/in_memory_state.go
@@ -494,6 +494,11 @@ func (s *InMemoryState) AddContainerToPod(pod *Pod, ctr *Container) error {
return errors.Wrapf(ErrInvalidArg, "container %s is not in pod %s", ctr.ID(), pod.ID())
}
+ if ctr.config.Namespace != pod.config.Namespace {
+ return errors.Wrapf(ErrNSMismatch, "container %s is in namespace %s and pod %s is in namespace %s",
+ ctr.ID(), ctr.config.Namespace, pod.ID(), pod.config.Namespace)
+ }
+
// Retrieve pod containers list
podCtrs, ok := s.podContainers[pod.ID()]
if !ok {
diff --git a/libpod/state_test.go b/libpod/state_test.go
index 4d5eb9713..7174bbf2a 100644
--- a/libpod/state_test.go
+++ b/libpod/state_test.go
@@ -2224,6 +2224,97 @@ func TestAddContainerToPodDependencyOutsidePodFails(t *testing.T) {
})
}
+func TestAddContainerToPodSameNamespaceSucceeds(t *testing.T) {
+ runForAllStates(t, func(t *testing.T, state State, lockPath string) {
+ testPod, err := getTestPod1(lockPath)
+ assert.NoError(t, err)
+ testPod.config.Namespace = "test1"
+
+ testCtr, err := getTestCtr2(lockPath)
+ assert.NoError(t, err)
+ testCtr.config.Namespace = "test1"
+ testCtr.config.Pod = testPod.ID()
+
+ err = state.AddPod(testPod)
+ assert.NoError(t, err)
+
+ err = state.AddContainerToPod(testPod, testCtr)
+ assert.NoError(t, err)
+
+ allCtrs, err := state.AllContainers()
+ assert.NoError(t, err)
+ assert.Equal(t, 1, len(allCtrs))
+ testContainersEqual(t, testCtr, allCtrs[0])
+ })
+}
+
+func TestAddContainerToPodDifferentNamespaceFails(t *testing.T) {
+ runForAllStates(t, func(t *testing.T, state State, lockPath string) {
+ testPod, err := getTestPod1(lockPath)
+ assert.NoError(t, err)
+ testPod.config.Namespace = "test1"
+
+ testCtr, err := getTestCtr2(lockPath)
+ assert.NoError(t, err)
+ testCtr.config.Namespace = "test2"
+ testCtr.config.Pod = testPod.ID()
+
+ err = state.AddPod(testPod)
+ assert.NoError(t, err)
+
+ err = state.AddContainerToPod(testPod, testCtr)
+ assert.Error(t, err)
+
+ allCtrs, err := state.AllContainers()
+ assert.NoError(t, err)
+ assert.Equal(t, 0, len(allCtrs))
+ })
+}
+
+func TestAddContainerToPodNamespaceOnCtrFails(t *testing.T) {
+ runForAllStates(t, func(t *testing.T, state State, lockPath string) {
+ testPod, err := getTestPod1(lockPath)
+ assert.NoError(t, err)
+
+ testCtr, err := getTestCtr2(lockPath)
+ assert.NoError(t, err)
+ testCtr.config.Namespace = "test1"
+ testCtr.config.Pod = testPod.ID()
+
+ err = state.AddPod(testPod)
+ assert.NoError(t, err)
+
+ err = state.AddContainerToPod(testPod, testCtr)
+ assert.Error(t, err)
+
+ allCtrs, err := state.AllContainers()
+ assert.NoError(t, err)
+ assert.Equal(t, 0, len(allCtrs))
+ })
+}
+
+func TestAddContainerToPodNamespaceOnPodFails(t *testing.T) {
+ runForAllStates(t, func(t *testing.T, state State, lockPath string) {
+ testPod, err := getTestPod1(lockPath)
+ assert.NoError(t, err)
+ testPod.config.Namespace = "test1"
+
+ testCtr, err := getTestCtr2(lockPath)
+ assert.NoError(t, err)
+ testCtr.config.Pod = testPod.ID()
+
+ err = state.AddPod(testPod)
+ assert.NoError(t, err)
+
+ err = state.AddContainerToPod(testPod, testCtr)
+ assert.Error(t, err)
+
+ allCtrs, err := state.AllContainers()
+ assert.NoError(t, err)
+ assert.Equal(t, 0, len(allCtrs))
+ })
+}
+
func TestRemoveContainerFromPodBadPodFails(t *testing.T) {
runForAllStates(t, func(t *testing.T, state State, lockPath string) {
testCtr, err := getTestCtr1(lockPath)