From 3ae0c80806b68f712756fd660d06449e71eb41b7 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Thu, 19 Jul 2018 14:24:22 -0400 Subject: Add --namespace flag to Podman Allows joining libpod to a specific namespace when running a Podman command. Signed-off-by: Matthew Heon --- docs/podman.1.md | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'docs') diff --git a/docs/podman.1.md b/docs/podman.1.md index 5581e0569..ffc2669a4 100644 --- a/docs/podman.1.md +++ b/docs/podman.1.md @@ -39,6 +39,11 @@ Path to where the cpu performance results should be written log messages above specified level: debug, info, warn, error (default), fatal or panic +**--namespace** + +set namespace libpod namespace. Namespaces are used to separate groups of containers and pods in libpod's state. +When namespace is set, created containers and pods will join the given namespace, and only containers and pods in the given namespace will be visible to Podman. + **--root**=**value** Path to the root directory in which data, including images, is stored -- cgit v1.2.3-54-g00ecf From 7a358e427738294180a14b1298dfc3a569f0e0fc Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Thu, 19 Jul 2018 17:21:27 -0400 Subject: Address first round of review comments Signed-off-by: Matthew Heon --- cmd/podman/main.go | 2 +- docs/podman.1.md | 2 +- libpod/boltdb_state.go | 66 ++++++++++++++++------------------------------- libpod/in_memory_state.go | 36 ++++++-------------------- 4 files changed, 32 insertions(+), 74 deletions(-) (limited to 'docs') diff --git a/cmd/podman/main.go b/cmd/podman/main.go index 9ae45e056..dbd7c1155 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -174,7 +174,7 @@ func main() { }, cli.StringFlag{ Name: "namespace", - Usage: "set the libpod namespace, used create separate views of the containers and pods on the system", + Usage: "set the libpod namespace, used to create separate views of the containers and pods on the system", Value: "", }, cli.StringFlag{ diff --git a/docs/podman.1.md b/docs/podman.1.md index ffc2669a4..41c427ec6 100644 --- a/docs/podman.1.md +++ b/docs/podman.1.md @@ -41,7 +41,7 @@ log messages above specified level: debug, info, warn, error (default), fatal or **--namespace** -set namespace libpod namespace. Namespaces are used to separate groups of containers and pods in libpod's state. +set libpod namespace. Namespaces are used to separate groups of containers and pods in libpod's state. When namespace is set, created containers and pods will join the given namespace, and only containers and pods in the given namespace will be visible to Podman. **--root**=**value** diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go index b2a246ca8..24785248f 100644 --- a/libpod/boltdb_state.go +++ b/libpod/boltdb_state.go @@ -443,10 +443,8 @@ func (s *BoltState) UpdateContainer(ctr *Container) error { return ErrCtrRemoved } - if s.namespace != "" { - if s.namespace != ctr.config.Namespace { - return errors.Wrapf(ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace) - } + if s.namespace != "" && s.namespace != ctr.config.Namespace { + return errors.Wrapf(ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace) } newState := new(containerState) @@ -511,10 +509,8 @@ func (s *BoltState) SaveContainer(ctr *Container) error { return ErrCtrRemoved } - if s.namespace != "" { - if s.namespace != ctr.config.Namespace { - return errors.Wrapf(ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace) - } + if s.namespace != "" && s.namespace != ctr.config.Namespace { + return errors.Wrapf(ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace) } stateJSON, err := json.Marshal(ctr.state) @@ -576,10 +572,8 @@ func (s *BoltState) ContainerInUse(ctr *Container) ([]string, error) { return nil, ErrCtrRemoved } - if s.namespace != "" { - if s.namespace != ctr.config.Namespace { - return nil, errors.Wrapf(ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace) - } + if s.namespace != "" && s.namespace != ctr.config.Namespace { + return nil, errors.Wrapf(ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace) } depCtrs := []string{} @@ -876,10 +870,8 @@ func (s *BoltState) PodHasContainer(pod *Pod, id string) (bool, error) { return false, ErrPodRemoved } - if s.namespace != "" { - if s.namespace != pod.config.Namespace { - return false, errors.Wrapf(ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) - } + if s.namespace != "" && s.namespace != pod.config.Namespace { + return false, errors.Wrapf(ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) } ctrID := []byte(id) @@ -941,10 +933,8 @@ func (s *BoltState) PodContainersByID(pod *Pod) ([]string, error) { return nil, ErrPodRemoved } - if s.namespace != "" { - if s.namespace != pod.config.Namespace { - return nil, errors.Wrapf(ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) - } + if s.namespace != "" && s.namespace != pod.config.Namespace { + return nil, errors.Wrapf(ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) } podID := []byte(pod.ID()) @@ -1005,10 +995,8 @@ func (s *BoltState) PodContainers(pod *Pod) ([]*Container, error) { return nil, ErrPodRemoved } - if s.namespace != "" { - if s.namespace != pod.config.Namespace { - return nil, errors.Wrapf(ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) - } + if s.namespace != "" && s.namespace != pod.config.Namespace { + return nil, errors.Wrapf(ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) } podID := []byte(pod.ID()) @@ -1077,10 +1065,8 @@ func (s *BoltState) AddPod(pod *Pod) error { return ErrPodRemoved } - if s.namespace != "" { - if s.namespace != pod.config.Namespace { - return errors.Wrapf(ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) - } + if s.namespace != "" && s.namespace != pod.config.Namespace { + return errors.Wrapf(ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) } podID := []byte(pod.ID()) @@ -1203,10 +1189,8 @@ func (s *BoltState) RemovePod(pod *Pod) error { return ErrPodRemoved } - if s.namespace != "" { - if s.namespace != pod.config.Namespace { - return errors.Wrapf(ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) - } + if s.namespace != "" && s.namespace != pod.config.Namespace { + return errors.Wrapf(ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) } podID := []byte(pod.ID()) @@ -1301,10 +1285,8 @@ func (s *BoltState) RemovePodContainers(pod *Pod) error { return ErrPodRemoved } - if s.namespace != "" { - if s.namespace != pod.config.Namespace { - return errors.Wrapf(ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) - } + if s.namespace != "" && s.namespace != pod.config.Namespace { + return errors.Wrapf(ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) } podID := []byte(pod.ID()) @@ -1492,10 +1474,8 @@ func (s *BoltState) UpdatePod(pod *Pod) error { return ErrPodRemoved } - if s.namespace != "" { - if s.namespace != pod.config.Namespace { - return errors.Wrapf(ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) - } + if s.namespace != "" && s.namespace != pod.config.Namespace { + return errors.Wrapf(ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) } newState := new(podState) @@ -1551,10 +1531,8 @@ func (s *BoltState) SavePod(pod *Pod) error { return ErrPodRemoved } - if s.namespace != "" { - if s.namespace != pod.config.Namespace { - return errors.Wrapf(ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) - } + if s.namespace != "" && s.namespace != pod.config.Namespace { + return errors.Wrapf(ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace) } stateJSON, err := json.Marshal(pod.state) diff --git a/libpod/in_memory_state.go b/libpod/in_memory_state.go index e323b069c..d421a5e8b 100644 --- a/libpod/in_memory_state.go +++ b/libpod/in_memory_state.go @@ -144,17 +144,11 @@ func (s *InMemoryState) HasContainer(id string) (bool, error) { } ctr, ok := s.containers[id] - if ok { - if s.namespace != "" { - if s.namespace != ctr.config.Namespace { - return false, nil - } - return true, nil - } - return true, nil + if !ok || (s.namespace != "" && s.namespace != ctr.config.Namespace) { + return false, nil } - return false, nil + return true, nil } // AddContainer adds a container to the state @@ -295,11 +289,7 @@ func (s *InMemoryState) UpdateContainer(ctr *Container) error { return errors.Wrapf(ErrNoSuchCtr, "container with ID %s not found in state", ctr.ID()) } - if err := s.checkNSMatch(ctr.ID(), ctr.Namespace()); err != nil { - return err - } - - return nil + return s.checkNSMatch(ctr.ID(), ctr.Namespace()) } // SaveContainer saves a container's state @@ -318,11 +308,7 @@ func (s *InMemoryState) SaveContainer(ctr *Container) error { return errors.Wrapf(ErrNoSuchCtr, "container with ID %s not found in state", ctr.ID()) } - if err := s.checkNSMatch(ctr.ID(), ctr.Namespace()); err != nil { - return err - } - - return nil + return s.checkNSMatch(ctr.ID(), ctr.Namespace()) } // ContainerInUse checks if the given container is being used by other containers @@ -441,17 +427,11 @@ func (s *InMemoryState) HasPod(id string) (bool, error) { } pod, ok := s.pods[id] - if ok { - if s.namespace != "" { - if s.namespace != pod.config.Namespace { - return false, nil - } - return true, nil - } - return true, nil + if !ok || (s.namespace != "" && s.namespace != pod.config.Namespace) { + return false, nil } - return false, nil + return true, nil } // PodHasContainer checks if the given pod has a container with the given ID -- cgit v1.2.3-54-g00ecf From 1b51e88098e0c77cddd8de3484ef56965352bcf3 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Tue, 24 Jul 2018 16:11:26 -0400 Subject: Update comments in BoltDB and In-Memory states Better explain the inner workings of both state types in comments to make reviews and changes easier. Signed-off-by: Matthew Heon --- docs/podman.1.md | 4 ++-- libpod/boltdb_state.go | 36 ++++++++++++++++++++++++++++++++++-- libpod/in_memory_state.go | 31 +++++++++++++++++++------------ 3 files changed, 55 insertions(+), 16 deletions(-) (limited to 'docs') diff --git a/docs/podman.1.md b/docs/podman.1.md index 41c427ec6..1ca420d12 100644 --- a/docs/podman.1.md +++ b/docs/podman.1.md @@ -37,11 +37,11 @@ Path to where the cpu performance results should be written **--log-level** -log messages above specified level: debug, info, warn, error (default), fatal or panic +Log messages above specified level: debug, info, warn, error (default), fatal or panic **--namespace** -set libpod namespace. Namespaces are used to separate groups of containers and pods in libpod's state. +Set libpod namespace. Namespaces are used to separate groups of containers and pods in libpod's state. When namespace is set, created containers and pods will join the given namespace, and only containers and pods in the given namespace will be visible to Podman. **--root**=**value** diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go index 24785248f..afbaecffb 100644 --- a/libpod/boltdb_state.go +++ b/libpod/boltdb_state.go @@ -21,6 +21,34 @@ type BoltState struct { runtime *Runtime } +// A brief description of the format of the BoltDB state: +// At the top level, the following buckets are created: +// - idRegistryBkt: Maps ID to Name for containers and pods. +// Used to ensure container and pod IDs are globally unique. +// - nameRegistryBkt: Maps Name to ID for containers and pods. +// Used to ensure container and pod names are globally unique. +// - nsRegistryBkt: Maps ID to namespace for all containers and pods. +// Used during lookup operations to determine if a given ID is in the same +// namespace as the state. +// - ctrBkt: Contains a sub-bucket for each container in the state. +// Each sub-bucket has config and state keys holding the container's JSON +// encoded configuration and state (respectively), an optional netNS key +// containing the path to the container's network namespace, a dependencies +// bucket containing the container's dependencies, and an optional pod key +// containing the ID of the pod the container is joined to. +// - allCtrsBkt: Map of ID to name containing only containers. Used for +// container lookup operations. +// - podBkt: Contains a sub-bucket for each pod in the state. +// Each sub-bucket has config and state keys holding the pod's JSON encoded +// configuration and state, plus a containers sub bucket holding the IDs of +// containers in the pod. +// - allPodsBkt: Map of ID to name containing only pods. Used for pod lookup +// operations. +// - runtimeConfigBkt: Contains configuration of the libpod instance that +// initially created the database. This must match for any further instances +// that access the database, to ensure that state mismatches with +// containers/storage do not occur. + // NewBoltState creates a new bolt-backed state database func NewBoltState(path, lockDir string, runtime *Runtime) (State, error) { state := new(BoltState) @@ -296,7 +324,9 @@ func (s *BoltState) LookupContainer(idOrName string) (*Container, error) { var id []byte ctrExists := ctrBucket.Bucket([]byte(idOrName)) if ctrExists != nil { - // A full container ID was given + // A full container ID was given. + // It might not be in our namespace, but + // getContainerFromDB() will handle that case. id = []byte(idOrName) } else { // They did not give us a full container ID. @@ -759,7 +789,9 @@ func (s *BoltState) LookupPod(idOrName string) (*Pod, error) { var id []byte podExists := podBkt.Bucket([]byte(idOrName)) if podExists != nil { - // A full pod ID was given + // A full pod ID was given. + // It might not be in our namespace, but getPodFromDB() + // will handle that case. id = []byte(idOrName) } else { // They did not give us a full pod ID. diff --git a/libpod/in_memory_state.go b/libpod/in_memory_state.go index d421a5e8b..8bdd0881c 100644 --- a/libpod/in_memory_state.go +++ b/libpod/in_memory_state.go @@ -14,16 +14,27 @@ import ( // An InMemoryState is a purely in-memory state store type InMemoryState struct { - pods map[string]*Pod - containers map[string]*Container - ctrDepends map[string][]string - podContainers map[string]map[string]*Container - nameIndex *registrar.Registrar - idIndex *truncindex.TruncIndex - namespace string + // Maps pod ID to pod struct. + pods map[string]*Pod + // Maps container ID to container struct. + containers map[string]*Container + // Maps container ID to a list of IDs of dependencies. + ctrDepends map[string][]string + // Maps pod ID to a map of container ID to container struct. + podContainers map[string]map[string]*Container + // Global name registry - ensures name uniqueness and performs lookups. + nameIndex *registrar.Registrar + // Global ID registry - ensures ID uniqueness and performs lookups. + idIndex *truncindex.TruncIndex + // Namespace the state is joined to. + namespace string + // Maps namespace name to local ID and name registries for looking up + // pods and containers in a specific namespace. namespaceIndexes map[string]*namespaceIndex } +// namespaceIndex contains name and ID registries for a specific namespace. +// This is used for namespaces lookup operations. type namespaceIndex struct { nameIndex *registrar.Registrar idIndex *truncindex.TruncIndex @@ -339,11 +350,7 @@ func (s *InMemoryState) ContainerInUse(ctr *Container) ([]string, error) { func (s *InMemoryState) AllContainers() ([]*Container, error) { ctrs := make([]*Container, 0, len(s.containers)) for _, ctr := range s.containers { - if s.namespace != "" { - if ctr.config.Namespace == s.namespace { - ctrs = append(ctrs, ctr) - } - } else { + if s.namespace == "" || ctr.config.Namespace == s.namespace { ctrs = append(ctrs, ctr) } } -- cgit v1.2.3-54-g00ecf