summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@pm.me>2020-08-04 15:51:13 -0400
committerMatthew Heon <matthew.heon@pm.me>2020-08-10 10:15:51 -0400
commit569854d6348e1cd74e8d654c88720e5517898f1a (patch)
tree8eaf3233da1ce1a4d1c3d39dc502a08e60307e2d /libpod
parentda00482ef29e0a04a690f1538391e38b0b951dd0 (diff)
downloadpodman-569854d6348e1cd74e8d654c88720e5517898f1a.tar.gz
podman-569854d6348e1cd74e8d654c88720e5517898f1a.tar.bz2
podman-569854d6348e1cd74e8d654c88720e5517898f1a.zip
Unconditionally retrieve pod names via API
The ListContainers API previously had a Pod parameter, which determined if pod name was returned (but, notably, not Pod ID, which was returned unconditionally). This was fairly confusing, so we decided to deprecate/remove the parameter and return it unconditionally. To do this without serious performance implications, we need to avoid expensive JSON decodes of pod configuration in the DB. The way our Bolt tables are structured, retrieving name given ID is actually quite cheap, but we did not expose this via the Libpod API. Add a new GetName API to do this. Fixes #7214 Signed-off-by: Matthew Heon <matthew.heon@pm.me>
Diffstat (limited to 'libpod')
-rw-r--r--libpod/boltdb_state.go55
-rw-r--r--libpod/in_memory_state.go30
-rw-r--r--libpod/runtime.go16
-rw-r--r--libpod/state.go6
4 files changed, 107 insertions, 0 deletions
diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go
index 2575f0e86..9dd5ca465 100644
--- a/libpod/boltdb_state.go
+++ b/libpod/boltdb_state.go
@@ -424,6 +424,61 @@ func (s *BoltState) SetNamespace(ns string) error {
return nil
}
+// GetName returns the name associated with a given ID. Since IDs are globally
+// unique, it works for both containers and pods.
+// Returns ErrNoSuchCtr if the ID does not exist.
+func (s *BoltState) GetName(id string) (string, error) {
+ if id == "" {
+ return "", define.ErrEmptyID
+ }
+
+ if !s.valid {
+ return "", define.ErrDBClosed
+ }
+
+ idBytes := []byte(id)
+
+ db, err := s.getDBCon()
+ if err != nil {
+ return "", err
+ }
+ defer s.deferredCloseDBCon(db)
+
+ name := ""
+
+ err = db.View(func(tx *bolt.Tx) error {
+ idBkt, err := getIDBucket(tx)
+ if err != nil {
+ return err
+ }
+
+ nameBytes := idBkt.Get(idBytes)
+ if nameBytes == nil {
+ return define.ErrNoSuchCtr
+ }
+
+ if s.namespaceBytes != nil {
+ nsBkt, err := getNSBucket(tx)
+ if err != nil {
+ return err
+ }
+
+ idNs := nsBkt.Get(idBytes)
+ if !bytes.Equal(idNs, s.namespaceBytes) {
+ return define.ErrNoSuchCtr
+ }
+ }
+
+ name = string(nameBytes)
+ return nil
+ })
+ if err != nil {
+ return "", err
+ }
+
+ return name, nil
+}
+
// Container retrieves a single container from the state by its full ID
func (s *BoltState) Container(id string) (*Container, error) {
if id == "" {
diff --git a/libpod/in_memory_state.go b/libpod/in_memory_state.go
index 2ac05e88d..0de25a6ef 100644
--- a/libpod/in_memory_state.go
+++ b/libpod/in_memory_state.go
@@ -106,6 +106,36 @@ func (s *InMemoryState) SetNamespace(ns string) error {
return nil
}
+// GetName retrieves the name associated with a given ID.
+// Works with both Container and Pod IDs.
+func (s *InMemoryState) GetName(id string) (string, error) {
+ if id == "" {
+ return "", define.ErrEmptyID
+ }
+
+ var idIndex *truncindex.TruncIndex
+ if s.namespace != "" {
+ nsIndex, ok := s.namespaceIndexes[s.namespace]
+ if !ok {
+ // We have no containers in the namespace
+ // Return false
+ return "", define.ErrNoSuchCtr
+ }
+ idIndex = nsIndex.idIndex
+ } else {
+ idIndex = s.idIndex
+ }
+
+ fullID, err := idIndex.Get(id)
+ if err != nil {
+ if err == truncindex.ErrNotExist {
+ return "", define.ErrNoSuchCtr
+ }
+ return "", errors.Wrapf(err, "error performing truncindex lookup for ID %s", id)
+ }
+ return fullID, nil
+}
+
// Container retrieves a container from its full ID
func (s *InMemoryState) Container(id string) (*Container, error) {
if id == "" {
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 3021ef3f4..8a7053e33 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -732,6 +732,22 @@ func (r *Runtime) GetStore() storage.Store {
return r.store
}
+// GetName retrieves the name associated with a given full ID.
+// This works for both containers and pods, and does not distinguish between the
+// two.
+// If the given ID does not correspond to any existing Pod or Container,
+// ErrNoSuchCtr is returned.
+func (r *Runtime) GetName(id string) (string, error) {
+ r.lock.RLock()
+ defer r.lock.RUnlock()
+
+ if !r.valid {
+ return "", define.ErrRuntimeStopped
+ }
+
+ return r.state.GetName(id)
+}
+
// DBConfig is a set of Libpod runtime configuration settings that are saved in
// a State when it is first created, and can subsequently be retrieved.
type DBConfig struct {
diff --git a/libpod/state.go b/libpod/state.go
index 6206a2994..44632b02f 100644
--- a/libpod/state.go
+++ b/libpod/state.go
@@ -43,6 +43,12 @@ type State interface {
// containers and pods in all namespaces will be returned.
SetNamespace(ns string) error
+ // Resolve an ID into a Name. Since Podman names and IDs are globally
+ // unique between Pods and Containers, the ID may belong to either a pod
+ // or container. Despite this, we will always return ErrNoSuchCtr if the
+ // ID does not exist.
+ GetName(id string) (string, error)
+
// Return a container from the database from its full ID.
// If the container is not in the set namespace, an error will be
// returned.