mirror of
https://github.com/containers/podman.git
synced 2025-10-16 18:53:19 +08:00
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>
This commit is contained in:
@ -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())
|
||||
|
@ -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())
|
||||
|
@ -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")
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user