summaryrefslogtreecommitdiff
path: root/libpod/boltdb_state.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/boltdb_state.go')
-rw-r--r--libpod/boltdb_state.go632
1 files changed, 456 insertions, 176 deletions
diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go
index 9745121c7..81f11410b 100644
--- a/libpod/boltdb_state.go
+++ b/libpod/boltdb_state.go
@@ -2,16 +2,18 @@ package libpod
import (
"bytes"
+ "errors"
"fmt"
"net"
"os"
+ "strconv"
"strings"
"sync"
+ "time"
"github.com/containers/common/libnetwork/types"
"github.com/containers/podman/v4/libpod/define"
jsoniter "github.com/json-iterator/go"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
bolt "go.etcd.io/bbolt"
)
@@ -63,6 +65,13 @@ type BoltState struct {
// 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.
+// - exitCodeBucket/exitCodeTimeStampBucket: (#14559) exit codes must be part
+// of the database to resolve a previous race condition when one process waits
+// for the exit file to be written and another process removes it along with
+// the container during auto-removal. The same race would happen trying to
+// read the exit code from the containers bucket. Hence, exit codes go into
+// their own bucket. To avoid the rather expensive JSON (un)marshaling, we
+// have two buckets: one for the exit codes, the other for the timestamps.
// NewBoltState creates a new bolt-backed state database
func NewBoltState(path string, runtime *Runtime) (State, error) {
@@ -76,7 +85,7 @@ func NewBoltState(path string, runtime *Runtime) (State, error) {
db, err := bolt.Open(path, 0600, nil)
if err != nil {
- return nil, errors.Wrapf(err, "error opening database %s", path)
+ return nil, fmt.Errorf("error opening database %s: %w", path, err)
}
// Everywhere else, we use s.deferredCloseDBCon(db) to ensure the state's DB
// mutex is also unlocked.
@@ -98,6 +107,8 @@ func NewBoltState(path string, runtime *Runtime) (State, error) {
allVolsBkt,
execBkt,
runtimeConfigBkt,
+ exitCodeBkt,
+ exitCodeTimeStampBkt,
}
// Does the DB need an update?
@@ -112,7 +123,7 @@ func NewBoltState(path string, runtime *Runtime) (State, error) {
return nil
})
if err != nil {
- return nil, errors.Wrapf(err, "error checking DB schema")
+ return nil, fmt.Errorf("error checking DB schema: %w", err)
}
if !needsUpdate {
@@ -124,13 +135,13 @@ func NewBoltState(path string, runtime *Runtime) (State, error) {
err = db.Update(func(tx *bolt.Tx) error {
for _, bkt := range createBuckets {
if _, err := tx.CreateBucketIfNotExists(bkt); err != nil {
- return errors.Wrapf(err, "error creating bucket %s", string(bkt))
+ return fmt.Errorf("error creating bucket %s: %w", string(bkt), err)
}
}
return nil
})
if err != nil {
- return nil, errors.Wrapf(err, "error creating buckets for DB")
+ return nil, fmt.Errorf("error creating buckets for DB: %w", err)
}
state.valid = true
@@ -162,6 +173,11 @@ func (s *BoltState) Refresh() error {
return err
}
+ namesBucket, err := getNamesBucket(tx)
+ if err != nil {
+ return err
+ }
+
ctrsBucket, err := getCtrBucket(tx)
if err != nil {
return err
@@ -187,11 +203,51 @@ func (s *BoltState) Refresh() error {
return err
}
+ exitCodeBucket, err := getExitCodeBucket(tx)
+ if err != nil {
+ return err
+ }
+
+ timeStampBucket, err := getExitCodeTimeStampBucket(tx)
+ if err != nil {
+ return err
+ }
+
+ // Clear all exec exit codes
+ toRemoveExitCodes := []string{}
+ err = exitCodeBucket.ForEach(func(id, _ []byte) error {
+ toRemoveExitCodes = append(toRemoveExitCodes, string(id))
+ return nil
+ })
+ if err != nil {
+ return fmt.Errorf("error reading exit codes bucket: %w", err)
+ }
+ for _, id := range toRemoveExitCodes {
+ if err := exitCodeBucket.Delete([]byte(id)); err != nil {
+ return fmt.Errorf("error removing exit code for ID %s: %w", id, err)
+ }
+ }
+
+ toRemoveTimeStamps := []string{}
+ err = timeStampBucket.ForEach(func(id, _ []byte) error {
+ toRemoveTimeStamps = append(toRemoveTimeStamps, string(id))
+ return nil
+ })
+ if err != nil {
+ return fmt.Errorf("reading timestamps bucket: %w", err)
+ }
+ for _, id := range toRemoveTimeStamps {
+ if err := timeStampBucket.Delete([]byte(id)); err != nil {
+ return fmt.Errorf("removing timestamp for ID %s: %w", id, err)
+ }
+ }
+
// Iterate through all IDs. Check if they are containers.
// If they are, unmarshal their state, and then clear
// PID, mountpoint, and state for all of them
// Then save the modified state
// Also clear all network namespaces
+ toRemoveIDs := []string{}
err = idBucket.ForEach(func(id, name []byte) error {
ctrBkt := ctrsBucket.Bucket(id)
if ctrBkt == nil {
@@ -199,20 +255,28 @@ func (s *BoltState) Refresh() error {
podBkt := podsBucket.Bucket(id)
if podBkt == nil {
// This is neither a pod nor a container
- // Error out on the dangling ID
- return errors.Wrapf(define.ErrInternal, "id %s is not a pod or a container", string(id))
+ // Something is seriously wrong, but
+ // continue on and try to clean up the
+ // state and become consistent.
+ // Just note what needs to be removed
+ // for now - ForEach says you shouldn't
+ // remove things from the table during
+ // it.
+ logrus.Errorf("Database issue: dangling ID %s found (not a pod or container) - removing", string(id))
+ toRemoveIDs = append(toRemoveIDs, string(id))
+ return nil
}
// Get the state
stateBytes := podBkt.Get(stateKey)
if stateBytes == nil {
- return errors.Wrapf(define.ErrInternal, "pod %s missing state key", string(id))
+ return fmt.Errorf("pod %s missing state key: %w", string(id), define.ErrInternal)
}
state := new(podState)
if err := json.Unmarshal(stateBytes, state); err != nil {
- return errors.Wrapf(err, "error unmarshalling state for pod %s", string(id))
+ return fmt.Errorf("error unmarshalling state for pod %s: %w", string(id), err)
}
// Clear the Cgroup path
@@ -220,11 +284,11 @@ func (s *BoltState) Refresh() error {
newStateBytes, err := json.Marshal(state)
if err != nil {
- return errors.Wrapf(err, "error marshalling modified state for pod %s", string(id))
+ return fmt.Errorf("error marshalling modified state for pod %s: %w", string(id), err)
}
if err := podBkt.Put(stateKey, newStateBytes); err != nil {
- return errors.Wrapf(err, "error updating state for pod %s in DB", string(id))
+ return fmt.Errorf("error updating state for pod %s in DB: %w", string(id), err)
}
// It's not a container, nothing to do
@@ -233,30 +297,30 @@ func (s *BoltState) Refresh() error {
// First, delete the network namespace
if err := ctrBkt.Delete(netNSKey); err != nil {
- return errors.Wrapf(err, "error removing network namespace for container %s", string(id))
+ return fmt.Errorf("error removing network namespace for container %s: %w", string(id), err)
}
stateBytes := ctrBkt.Get(stateKey)
if stateBytes == nil {
// Badly formatted container bucket
- return errors.Wrapf(define.ErrInternal, "container %s missing state in DB", string(id))
+ return fmt.Errorf("container %s missing state in DB: %w", string(id), define.ErrInternal)
}
state := new(ContainerState)
if err := json.Unmarshal(stateBytes, state); err != nil {
- return errors.Wrapf(err, "error unmarshalling state for container %s", string(id))
+ return fmt.Errorf("error unmarshalling state for container %s: %w", string(id), err)
}
resetState(state)
newStateBytes, err := json.Marshal(state)
if err != nil {
- return errors.Wrapf(err, "error marshalling modified state for container %s", string(id))
+ return fmt.Errorf("error marshalling modified state for container %s: %w", string(id), err)
}
if err := ctrBkt.Put(stateKey, newStateBytes); err != nil {
- return errors.Wrapf(err, "error updating state for container %s in DB", string(id))
+ return fmt.Errorf("error updating state for container %s in DB: %w", string(id), err)
}
// Delete all exec sessions, if there are any
@@ -274,7 +338,7 @@ func (s *BoltState) Refresh() error {
}
for _, execID := range toRemove {
if err := ctrExecBkt.Delete([]byte(execID)); err != nil {
- return errors.Wrapf(err, "error removing exec session %s from container %s", execID, string(id))
+ return fmt.Errorf("error removing exec session %s from container %s: %w", execID, string(id), err)
}
}
}
@@ -285,11 +349,29 @@ func (s *BoltState) Refresh() error {
return err
}
+ // Remove dangling IDs.
+ for _, id := range toRemoveIDs {
+ // Look up the ID to see if we also have a dangling name
+ // in the DB.
+ name := idBucket.Get([]byte(id))
+ if name != nil {
+ if testID := namesBucket.Get(name); testID != nil {
+ logrus.Infof("Found dangling name %s (ID %s) in database", string(name), id)
+ if err := namesBucket.Delete(name); err != nil {
+ return fmt.Errorf("error removing dangling name %s (ID %s) from database: %w", string(name), id, err)
+ }
+ }
+ }
+ if err := idBucket.Delete([]byte(id)); err != nil {
+ return fmt.Errorf("error removing dangling ID %s from database: %w", id, err)
+ }
+ }
+
// Now refresh volumes
err = allVolsBucket.ForEach(func(id, name []byte) error {
dbVol := volBucket.Bucket(id)
if dbVol == nil {
- return errors.Wrapf(define.ErrInternal, "inconsistency in state - volume %s is in all volumes bucket but volume not found", string(id))
+ return fmt.Errorf("inconsistency in state - volume %s is in all volumes bucket but volume not found: %w", string(id), define.ErrInternal)
}
// Get the state
@@ -302,7 +384,7 @@ func (s *BoltState) Refresh() error {
oldState := new(VolumeState)
if err := json.Unmarshal(volStateBytes, oldState); err != nil {
- return errors.Wrapf(err, "error unmarshalling state for volume %s", string(id))
+ return fmt.Errorf("error unmarshalling state for volume %s: %w", string(id), err)
}
// Reset mount count to 0
@@ -311,11 +393,11 @@ func (s *BoltState) Refresh() error {
newState, err := json.Marshal(oldState)
if err != nil {
- return errors.Wrapf(err, "error marshalling state for volume %s", string(id))
+ return fmt.Errorf("error marshalling state for volume %s: %w", string(id), err)
}
if err := dbVol.Put(stateKey, newState); err != nil {
- return errors.Wrapf(err, "error storing new state for volume %s", string(id))
+ return fmt.Errorf("error storing new state for volume %s: %w", string(id), err)
}
return nil
@@ -339,7 +421,7 @@ func (s *BoltState) Refresh() error {
for _, execSession := range toRemoveExec {
if err := execBucket.Delete([]byte(execSession)); err != nil {
- return errors.Wrapf(err, "error deleting exec session %s registry from database", execSession)
+ return fmt.Errorf("error deleting exec session %s registry from database: %w", execSession, err)
}
}
@@ -561,7 +643,7 @@ func (s *BoltState) LookupContainerID(idOrName string) (string, error) {
if s.namespaceBytes != nil {
ns := nsBucket.Get(fullID)
if !bytes.Equal(ns, s.namespaceBytes) {
- return errors.Wrapf(define.ErrNoSuchCtr, "no container found with name or ID %s", idOrName)
+ return fmt.Errorf("no container found with name or ID %s: %w", idOrName, define.ErrNoSuchCtr)
}
}
id = fullID
@@ -686,7 +768,7 @@ func (s *BoltState) AddContainer(ctr *Container) error {
}
if ctr.config.Pod != "" {
- return errors.Wrapf(define.ErrInvalidArg, "cannot add a container that belongs to a pod with AddContainer - use AddContainerToPod")
+ return fmt.Errorf("cannot add a container that belongs to a pod with AddContainer - use AddContainerToPod: %w", define.ErrInvalidArg)
}
return s.addContainer(ctr, nil)
@@ -701,7 +783,7 @@ func (s *BoltState) RemoveContainer(ctr *Container) error {
}
if ctr.config.Pod != "" {
- return errors.Wrapf(define.ErrPodExists, "container %s is part of a pod, use RemoveContainerFromPod instead", ctr.ID())
+ return fmt.Errorf("container %s is part of a pod, use RemoveContainerFromPod instead: %w", ctr.ID(), define.ErrPodExists)
}
db, err := s.getDBCon()
@@ -727,7 +809,7 @@ func (s *BoltState) UpdateContainer(ctr *Container) error {
}
if s.namespace != "" && s.namespace != ctr.config.Namespace {
- return errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace)
+ return fmt.Errorf("container %s is in namespace %q, does not match our namespace %q: %w", ctr.ID(), ctr.config.Namespace, s.namespace, define.ErrNSMismatch)
}
newState := new(ContainerState)
@@ -750,16 +832,16 @@ func (s *BoltState) UpdateContainer(ctr *Container) error {
ctrToUpdate := ctrBucket.Bucket(ctrID)
if ctrToUpdate == nil {
ctr.valid = false
- return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in database", ctr.ID())
+ return fmt.Errorf("container %s does not exist in database: %w", ctr.ID(), define.ErrNoSuchCtr)
}
newStateBytes := ctrToUpdate.Get(stateKey)
if newStateBytes == nil {
- return errors.Wrapf(define.ErrInternal, "container %s does not have a state key in DB", ctr.ID())
+ return fmt.Errorf("container %s does not have a state key in DB: %w", ctr.ID(), define.ErrInternal)
}
if err := json.Unmarshal(newStateBytes, newState); err != nil {
- return errors.Wrapf(err, "error unmarshalling container %s state", ctr.ID())
+ return fmt.Errorf("error unmarshalling container %s state: %w", ctr.ID(), err)
}
netNSBytes := ctrToUpdate.Get(netNSKey)
@@ -799,12 +881,12 @@ func (s *BoltState) SaveContainer(ctr *Container) error {
}
if s.namespace != "" && s.namespace != ctr.config.Namespace {
- return errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace)
+ return fmt.Errorf("container %s is in namespace %q, does not match our namespace %q: %w", ctr.ID(), ctr.config.Namespace, s.namespace, define.ErrNSMismatch)
}
stateJSON, err := json.Marshal(ctr.state)
if err != nil {
- return errors.Wrapf(err, "error marshalling container %s state to JSON", ctr.ID())
+ return fmt.Errorf("error marshalling container %s state to JSON: %w", ctr.ID(), err)
}
netNSPath := getNetNSPath(ctr)
@@ -825,22 +907,22 @@ func (s *BoltState) SaveContainer(ctr *Container) error {
ctrToSave := ctrBucket.Bucket(ctrID)
if ctrToSave == nil {
ctr.valid = false
- return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in DB", ctr.ID())
+ return fmt.Errorf("container %s does not exist in DB: %w", ctr.ID(), define.ErrNoSuchCtr)
}
// Update the state
if err := ctrToSave.Put(stateKey, stateJSON); err != nil {
- return errors.Wrapf(err, "error updating container %s state in DB", ctr.ID())
+ return fmt.Errorf("error updating container %s state in DB: %w", ctr.ID(), err)
}
if netNSPath != "" {
if err := ctrToSave.Put(netNSKey, []byte(netNSPath)); err != nil {
- return errors.Wrapf(err, "error updating network namespace path for container %s in DB", ctr.ID())
+ return fmt.Errorf("error updating network namespace path for container %s in DB: %w", ctr.ID(), err)
}
} else {
// Delete the existing network namespace
if err := ctrToSave.Delete(netNSKey); err != nil {
- return errors.Wrapf(err, "error removing network namespace path for container %s in DB", ctr.ID())
+ return fmt.Errorf("error removing network namespace path for container %s in DB: %w", ctr.ID(), err)
}
}
@@ -862,7 +944,7 @@ func (s *BoltState) ContainerInUse(ctr *Container) ([]string, error) {
}
if s.namespace != "" && s.namespace != ctr.config.Namespace {
- return nil, errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace)
+ return nil, fmt.Errorf("container %s is in namespace %q, does not match our namespace %q: %w", ctr.ID(), ctr.config.Namespace, s.namespace, define.ErrNSMismatch)
}
depCtrs := []string{}
@@ -882,12 +964,12 @@ func (s *BoltState) ContainerInUse(ctr *Container) ([]string, error) {
ctrDB := ctrBucket.Bucket([]byte(ctr.ID()))
if ctrDB == nil {
ctr.valid = false
- return errors.Wrapf(define.ErrNoSuchCtr, "no container with ID %q found in DB", ctr.ID())
+ return fmt.Errorf("no container with ID %q found in DB: %w", ctr.ID(), define.ErrNoSuchCtr)
}
dependsBkt := ctrDB.Bucket(dependenciesBkt)
if dependsBkt == nil {
- return errors.Wrapf(define.ErrInternal, "container %s has no dependencies bucket", ctr.ID())
+ return fmt.Errorf("container %s has no dependencies bucket: %w", ctr.ID(), define.ErrInternal)
}
// Iterate through and add dependencies
@@ -940,7 +1022,7 @@ func (s *BoltState) AllContainers() ([]*Container, error) {
// be much less helpful.
ctrExists := ctrBucket.Bucket(id)
if ctrExists == nil {
- return errors.Wrapf(define.ErrInternal, "state is inconsistent - container ID %s in all containers, but container not found", string(id))
+ return fmt.Errorf("state is inconsistent - container ID %s in all containers, but container not found: %w", string(id), define.ErrInternal)
}
ctr := new(Container)
@@ -952,7 +1034,7 @@ func (s *BoltState) AllContainers() ([]*Container, error) {
// ignore it safely.
// We just won't include the container in the
// results.
- if errors.Cause(err) != define.ErrNSMismatch {
+ if !errors.Is(err, define.ErrNSMismatch) {
// Even if it's not an NS mismatch, it's
// not worth erroring over.
// If we do, a single bad container JSON
@@ -984,7 +1066,7 @@ func (s *BoltState) GetNetworks(ctr *Container) (map[string]types.PerNetworkOpti
}
if s.namespace != "" && s.namespace != ctr.config.Namespace {
- return nil, errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace)
+ return nil, fmt.Errorf("container %s is in namespace %q, does not match our namespace %q: %w", ctr.ID(), ctr.config.Namespace, s.namespace, define.ErrNSMismatch)
}
// if the network mode is not bridge return no networks
@@ -1013,7 +1095,7 @@ func (s *BoltState) GetNetworks(ctr *Container) (map[string]types.PerNetworkOpti
dbCtr := ctrBucket.Bucket(ctrID)
if dbCtr == nil {
ctr.valid = false
- return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in database", ctr.ID())
+ return fmt.Errorf("container %s does not exist in database: %w", ctr.ID(), define.ErrNoSuchCtr)
}
ctrNetworkBkt := dbCtr.Bucket(networksBkt)
@@ -1051,7 +1133,7 @@ func (s *BoltState) GetNetworks(ctr *Container) (map[string]types.PerNetworkOpti
dbCtr := ctrBucket.Bucket(ctrID)
if dbCtr == nil {
ctr.valid = false
- return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in database", ctr.ID())
+ return fmt.Errorf("container %s does not exist in database: %w", ctr.ID(), define.ErrNoSuchCtr)
}
var networkList []string
@@ -1060,7 +1142,7 @@ func (s *BoltState) GetNetworks(ctr *Container) (map[string]types.PerNetworkOpti
if ctrNetworkBkt == nil {
ctrNetworkBkt, err = dbCtr.CreateBucket(networksBkt)
if err != nil {
- return errors.Wrapf(err, "error creating networks bucket for container %s", ctr.ID())
+ return fmt.Errorf("error creating networks bucket for container %s: %w", ctr.ID(), err)
}
// the container has no networks in the db lookup config and write to the db
networkList = ctr.config.NetworksDeprecated
@@ -1084,7 +1166,7 @@ func (s *BoltState) GetNetworks(ctr *Container) (map[string]types.PerNetworkOpti
if ctr.state.NetInterfaceDescriptions != nil {
eth, exists := ctr.state.NetInterfaceDescriptions.getInterfaceByName(network)
if !exists {
- return errors.Errorf("no network interface name for container %s on network %s", ctr.config.ID, network)
+ return fmt.Errorf("no network interface name for container %s on network %s", ctr.config.ID, network)
}
intName = eth
} else {
@@ -1158,16 +1240,16 @@ func (s *BoltState) NetworkConnect(ctr *Container, network string, opts types.Pe
}
if network == "" {
- return errors.Wrapf(define.ErrInvalidArg, "network names must not be empty")
+ return fmt.Errorf("network names must not be empty: %w", define.ErrInvalidArg)
}
if s.namespace != "" && s.namespace != ctr.config.Namespace {
- return errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace)
+ return fmt.Errorf("container %s is in namespace %q, does not match our namespace %q: %w", ctr.ID(), ctr.config.Namespace, s.namespace, define.ErrNSMismatch)
}
optBytes, err := json.Marshal(opts)
if err != nil {
- return errors.Wrapf(err, "error marshalling network options JSON for container %s", ctr.ID())
+ return fmt.Errorf("error marshalling network options JSON for container %s: %w", ctr.ID(), err)
}
ctrID := []byte(ctr.ID())
@@ -1187,21 +1269,21 @@ func (s *BoltState) NetworkConnect(ctr *Container, network string, opts types.Pe
dbCtr := ctrBucket.Bucket(ctrID)
if dbCtr == nil {
ctr.valid = false
- return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in database", ctr.ID())
+ return fmt.Errorf("container %s does not exist in database: %w", ctr.ID(), define.ErrNoSuchCtr)
}
ctrNetworksBkt := dbCtr.Bucket(networksBkt)
if ctrNetworksBkt == nil {
- return errors.Wrapf(define.ErrNoSuchNetwork, "container %s does not have a network bucket", ctr.ID())
+ return fmt.Errorf("container %s does not have a network bucket: %w", ctr.ID(), define.ErrNoSuchNetwork)
}
netConnected := ctrNetworksBkt.Get([]byte(network))
if netConnected != nil {
- return errors.Wrapf(define.ErrNetworkExists, "container %s is already connected to network %q", ctr.ID(), network)
+ return fmt.Errorf("container %s is already connected to network %q: %w", ctr.ID(), network, define.ErrNetworkExists)
}
// Add the network
if err := ctrNetworksBkt.Put([]byte(network), optBytes); err != nil {
- return errors.Wrapf(err, "error adding container %s to network %s in DB", ctr.ID(), network)
+ return fmt.Errorf("error adding container %s to network %s in DB: %w", ctr.ID(), network, err)
}
return nil
@@ -1220,11 +1302,11 @@ func (s *BoltState) NetworkDisconnect(ctr *Container, network string) error {
}
if network == "" {
- return errors.Wrapf(define.ErrInvalidArg, "network names must not be empty")
+ return fmt.Errorf("network names must not be empty: %w", define.ErrInvalidArg)
}
if s.namespace != "" && s.namespace != ctr.config.Namespace {
- return errors.Wrapf(define.ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace)
+ return fmt.Errorf("container %s is in namespace %q, does not match our namespace %q: %w", ctr.ID(), ctr.config.Namespace, s.namespace, define.ErrNSMismatch)
}
ctrID := []byte(ctr.ID())
@@ -1244,21 +1326,21 @@ func (s *BoltState) NetworkDisconnect(ctr *Container, network string) error {
dbCtr := ctrBucket.Bucket(ctrID)
if dbCtr == nil {
ctr.valid = false
- return errors.Wrapf(define.ErrNoSuchCtr, "container %s does not exist in database", ctr.ID())
+ return fmt.Errorf("container %s does not exist in database: %w", ctr.ID(), define.ErrNoSuchCtr)
}
ctrAliasesBkt := dbCtr.Bucket(aliasesBkt)
ctrNetworksBkt := dbCtr.Bucket(networksBkt)
if ctrNetworksBkt == nil {
- return errors.Wrapf(define.ErrNoSuchNetwork, "container %s is not connected to any CNI networks, so cannot disconnect", ctr.ID())
+ return fmt.Errorf("container %s is not connected to any CNI networks, so cannot disconnect: %w", ctr.ID(), define.ErrNoSuchNetwork)
}
netConnected := ctrNetworksBkt.Get([]byte(network))
if netConnected == nil {
- return errors.Wrapf(define.ErrNoSuchNetwork, "container %s is not connected to CNI network %q", ctr.ID(), network)
+ return fmt.Errorf("container %s is not connected to CNI network %q: %w", ctr.ID(), network, define.ErrNoSuchNetwork)
}
if err := ctrNetworksBkt.Delete([]byte(network)); err != nil {
- return errors.Wrapf(err, "error removing container %s from network %s", ctr.ID(), network)
+ return fmt.Errorf("error removing container %s from network %s: %w", ctr.ID(), network, err)
}
if ctrAliasesBkt != nil {
@@ -1268,7 +1350,7 @@ func (s *BoltState) NetworkDisconnect(ctr *Container, network string) error {
}
if err := ctrAliasesBkt.DeleteBucket([]byte(network)); err != nil {
- return errors.Wrapf(err, "error removing container %s network aliases for network %s", ctr.ID(), network)
+ return fmt.Errorf("error removing container %s network aliases for network %s: %w", ctr.ID(), network, err)
}
}
@@ -1309,6 +1391,204 @@ func (s *BoltState) GetContainerConfig(id string) (*ContainerConfig, error) {
return config, nil
}
+// AddContainerExitCode adds the exit code for the specified container to the database.
+func (s *BoltState) AddContainerExitCode(id string, exitCode int32) error {
+ if len(id) == 0 {
+ return define.ErrEmptyID
+ }
+
+ if !s.valid {
+ return define.ErrDBClosed
+ }
+
+ db, err := s.getDBCon()
+ if err != nil {
+ return err
+ }
+ defer s.deferredCloseDBCon(db)
+
+ rawID := []byte(id)
+ rawExitCode := []byte(strconv.Itoa(int(exitCode)))
+ rawTimeStamp, err := time.Now().MarshalText()
+ if err != nil {
+ return fmt.Errorf("marshaling exit-code time stamp: %w", err)
+ }
+
+ return db.Update(func(tx *bolt.Tx) error {
+ exitCodeBucket, err := getExitCodeBucket(tx)
+ if err != nil {
+ return err
+ }
+ timeStampBucket, err := getExitCodeTimeStampBucket(tx)
+ if err != nil {
+ return err
+ }
+
+ if err := exitCodeBucket.Put(rawID, rawExitCode); err != nil {
+ return fmt.Errorf("adding exit code of container %s to DB: %w", id, err)
+ }
+ if err := timeStampBucket.Put(rawID, rawTimeStamp); err != nil {
+ if rmErr := exitCodeBucket.Delete(rawID); rmErr != nil {
+ logrus.Errorf("Removing exit code of container %s from DB: %v", id, rmErr)
+ }
+ return fmt.Errorf("adding exit-code time stamp of container %s to DB: %w", id, err)
+ }
+
+ return nil
+ })
+}
+
+// GetContainerExitCode returns the exit code for the specified container.
+func (s *BoltState) GetContainerExitCode(id string) (int32, error) {
+ if len(id) == 0 {
+ return -1, define.ErrEmptyID
+ }
+
+ if !s.valid {
+ return -1, define.ErrDBClosed
+ }
+
+ db, err := s.getDBCon()
+ if err != nil {
+ return -1, err
+ }
+ defer s.deferredCloseDBCon(db)
+
+ rawID := []byte(id)
+ result := int32(-1)
+ return result, db.View(func(tx *bolt.Tx) error {
+ exitCodeBucket, err := getExitCodeBucket(tx)
+ if err != nil {
+ return err
+ }
+
+ rawExitCode := exitCodeBucket.Get(rawID)
+ if rawExitCode == nil {
+ return fmt.Errorf("getting exit code of container %s from DB: %w", id, define.ErrNoSuchExitCode)
+ }
+
+ exitCode, err := strconv.Atoi(string(rawExitCode))
+ if err != nil {
+ return fmt.Errorf("converting raw exit code %v of container %s: %w", rawExitCode, id, err)
+ }
+
+ result = int32(exitCode)
+ return nil
+ })
+}
+
+// GetContainerExitCodeTimeStamp returns the time stamp when the exit code of
+// the specified container was added to the database.
+func (s *BoltState) GetContainerExitCodeTimeStamp(id string) (*time.Time, error) {
+ if len(id) == 0 {
+ return nil, define.ErrEmptyID
+ }
+
+ if !s.valid {
+ return nil, define.ErrDBClosed
+ }
+
+ db, err := s.getDBCon()
+ if err != nil {
+ return nil, err
+ }
+ defer s.deferredCloseDBCon(db)
+
+ rawID := []byte(id)
+ var result time.Time
+ return &result, db.View(func(tx *bolt.Tx) error {
+ timeStampBucket, err := getExitCodeTimeStampBucket(tx)
+ if err != nil {
+ return err
+ }
+
+ rawTimeStamp := timeStampBucket.Get(rawID)
+ if rawTimeStamp == nil {
+ return fmt.Errorf("getting exit-code time stamp of container %s from DB: %w", id, define.ErrNoSuchExitCode)
+ }
+
+ if err := result.UnmarshalText(rawTimeStamp); err != nil {
+ return fmt.Errorf("converting raw time stamp %v of container %s from DB: %w", rawTimeStamp, id, err)
+ }
+
+ return nil
+ })
+}
+
+// PruneExitCodes removes exit codes older than 5 minutes.
+func (s *BoltState) PruneContainerExitCodes() error {
+ if !s.valid {
+ return define.ErrDBClosed
+ }
+
+ db, err := s.getDBCon()
+ if err != nil {
+ return err
+ }
+ defer s.deferredCloseDBCon(db)
+
+ toRemoveIDs := []string{}
+
+ threshold := time.Minute * 5
+ err = db.View(func(tx *bolt.Tx) error {
+ timeStampBucket, err := getExitCodeTimeStampBucket(tx)
+ if err != nil {
+ return err
+ }
+
+ return timeStampBucket.ForEach(func(rawID, rawTimeStamp []byte) error {
+ var timeStamp time.Time
+ if err := timeStamp.UnmarshalText(rawTimeStamp); err != nil {
+ return fmt.Errorf("converting raw time stamp %v of container %s from DB: %w", rawTimeStamp, string(rawID), err)
+ }
+ if time.Since(timeStamp) > threshold {
+ toRemoveIDs = append(toRemoveIDs, string(rawID))
+ }
+ return nil
+ })
+ })
+ if err != nil {
+ return fmt.Errorf("reading exit codes to prune: %w", err)
+ }
+
+ if len(toRemoveIDs) > 0 {
+ err = db.Update(func(tx *bolt.Tx) error {
+ exitCodeBucket, err := getExitCodeBucket(tx)
+ if err != nil {
+ return err
+ }
+ timeStampBucket, err := getExitCodeTimeStampBucket(tx)
+ if err != nil {
+ return err
+ }
+
+ var finalErr error
+ for _, id := range toRemoveIDs {
+ rawID := []byte(id)
+ if err := exitCodeBucket.Delete(rawID); err != nil {
+ if finalErr != nil {
+ logrus.Error(finalErr)
+ }
+ finalErr = fmt.Errorf("removing exit code of container %s from DB: %w", id, err)
+ }
+ if err := timeStampBucket.Delete(rawID); err != nil {
+ if finalErr != nil {
+ logrus.Error(finalErr)
+ }
+ finalErr = fmt.Errorf("removing exit code timestamp of container %s from DB: %w", id, err)
+ }
+ }
+
+ return finalErr
+ })
+ if err != nil {
+ return fmt.Errorf("pruning exit codes: %w", err)
+ }
+ }
+
+ return nil
+}
+
// AddExecSession adds an exec session to the state.
func (s *BoltState) AddExecSession(ctr *Container, session *ExecSession) error {
if !s.valid {
@@ -1341,25 +1621,25 @@ func (s *BoltState) AddExecSession(ctr *Container, session *ExecSession) error {
dbCtr := ctrBucket.Bucket(ctrID)
if dbCtr == nil {
ctr.valid = false
- return errors.Wrapf(define.ErrNoSuchCtr, "container %s is not present in the database", ctr.ID())
+ return fmt.Errorf("container %s is not present in the database: %w", ctr.ID(), define.ErrNoSuchCtr)
}
ctrExecSessionBucket, err := dbCtr.CreateBucketIfNotExists(execBkt)
if err != nil {
- return errors.Wrapf(err, "error creating exec sessions bucket for container %s", ctr.ID())
+ return fmt.Errorf("error creating exec sessions bucket for container %s: %w", ctr.ID(), err)
}
execExists := execBucket.Get(sessionID)
if execExists != nil {
- return errors.Wrapf(define.ErrExecSessionExists, "an exec session with ID %s already exists", session.ID())
+ return fmt.Errorf("an exec session with ID %s already exists: %w", session.ID(), define.ErrExecSessionExists)
}
if err := execBucket.Put(sessionID, ctrID); err != nil {
- return errors.Wrapf(err, "error adding exec session %s to DB", session.ID())
+ return fmt.Errorf("error adding exec session %s to DB: %w", session.ID(), err)
}
if err := ctrExecSessionBucket.Put(sessionID, ctrID); err != nil {
- return errors.Wrapf(err, "error adding exec session %s to container %s in DB", session.ID(), ctr.ID())
+ return fmt.Errorf("error adding exec session %s to container %s in DB: %w", session.ID(), ctr.ID(), err)
}
return nil
@@ -1393,7 +1673,7 @@ func (s *BoltState) GetExecSession(id string) (string, error) {
ctr := execBucket.Get([]byte(id))
if ctr == nil {
- return errors.Wrapf(define.ErrNoSuchExecSession, "no exec session with ID %s found", id)
+ return fmt.Errorf("no exec session with ID %s found: %w", id, define.ErrNoSuchExecSession)
}
ctrID = string(ctr)
return nil
@@ -1432,11 +1712,11 @@ func (s *BoltState) RemoveExecSession(session *ExecSession) error {
}
// Check that container ID matches
if string(sessionExists) != session.ContainerID() {
- return errors.Wrapf(define.ErrInternal, "database inconsistency: exec session %s points to container %s in state but %s in database", session.ID(), session.ContainerID(), string(sessionExists))
+ return fmt.Errorf("database inconsistency: exec session %s points to container %s in state but %s in database: %w", session.ID(), session.ContainerID(), string(sessionExists), define.ErrInternal)
}
if err := execBucket.Delete(sessionID); err != nil {
- return errors.Wrapf(err, "error removing exec session %s from database", session.ID())
+ return fmt.Errorf("error removing exec session %s from database: %w", session.ID(), err)
}
dbCtr := ctrBucket.Bucket(containerID)
@@ -1459,7 +1739,7 @@ func (s *BoltState) RemoveExecSession(session *ExecSession) error {
ctrSessionExists := ctrExecBucket.Get(sessionID)
if ctrSessionExists != nil {
if err := ctrExecBucket.Delete(sessionID); err != nil {
- return errors.Wrapf(err, "error removing exec session %s from container %s in database", session.ID(), session.ContainerID())
+ return fmt.Errorf("error removing exec session %s from container %s in database: %w", session.ID(), session.ContainerID(), err)
}
}
@@ -1567,7 +1847,7 @@ func (s *BoltState) RemoveContainerExecSessions(ctr *Container) error {
for _, session := range sessions {
if err := ctrExecSessions.Delete([]byte(session)); err != nil {
- return errors.Wrapf(err, "error removing container %s exec session %s from database", ctr.ID(), session)
+ return fmt.Errorf("error removing container %s exec session %s from database: %w", ctr.ID(), session, err)
}
// Check if the session exists in the global table
// before removing. It should, but in cases where the DB
@@ -1578,10 +1858,10 @@ func (s *BoltState) RemoveContainerExecSessions(ctr *Container) error {
continue
}
if string(sessionExists) != ctr.ID() {
- return errors.Wrapf(define.ErrInternal, "database mismatch: exec session %s is associated with containers %s and %s", session, ctr.ID(), string(sessionExists))
+ return fmt.Errorf("database mismatch: exec session %s is associated with containers %s and %s: %w", session, ctr.ID(), string(sessionExists), define.ErrInternal)
}
if err := execBucket.Delete([]byte(session)); err != nil {
- return errors.Wrapf(err, "error removing container %s exec session %s from exec sessions", ctr.ID(), session)
+ return fmt.Errorf("error removing container %s exec session %s from exec sessions: %w", ctr.ID(), session, err)
}
}
@@ -1604,7 +1884,7 @@ func (s *BoltState) RewriteContainerConfig(ctr *Container, newCfg *ContainerConf
newCfgJSON, err := json.Marshal(newCfg)
if err != nil {
- return errors.Wrapf(err, "error marshalling new configuration JSON for container %s", ctr.ID())
+ return fmt.Errorf("error marshalling new configuration JSON for container %s: %w", ctr.ID(), err)
}
db, err := s.getDBCon()
@@ -1622,11 +1902,11 @@ func (s *BoltState) RewriteContainerConfig(ctr *Container, newCfg *ContainerConf
ctrDB := ctrBkt.Bucket([]byte(ctr.ID()))
if ctrDB == nil {
ctr.valid = false
- return errors.Wrapf(define.ErrNoSuchCtr, "no container with ID %q found in DB", ctr.ID())
+ return fmt.Errorf("no container with ID %q found in DB: %w", ctr.ID(), define.ErrNoSuchCtr)
}
if err := ctrDB.Put(configKey, newCfgJSON); err != nil {
- return errors.Wrapf(err, "error updating container %s config JSON", ctr.ID())
+ return fmt.Errorf("error updating container %s config JSON: %w", ctr.ID(), err)
}
return nil
@@ -1649,15 +1929,15 @@ func (s *BoltState) SafeRewriteContainerConfig(ctr *Container, oldName, newName
}
if newName != "" && newCfg.Name != newName {
- return errors.Wrapf(define.ErrInvalidArg, "new name %s for container %s must match name in given container config", newName, ctr.ID())
+ return fmt.Errorf("new name %s for container %s must match name in given container config: %w", newName, ctr.ID(), define.ErrInvalidArg)
}
if newName != "" && oldName == "" {
- return errors.Wrapf(define.ErrInvalidArg, "must provide old name for container if a new name is given")
+ return fmt.Errorf("must provide old name for container if a new name is given: %w", define.ErrInvalidArg)
}
newCfgJSON, err := json.Marshal(newCfg)
if err != nil {
- return errors.Wrapf(err, "error marshalling new configuration JSON for container %s", ctr.ID())
+ return fmt.Errorf("error marshalling new configuration JSON for container %s: %w", ctr.ID(), err)
}
db, err := s.getDBCon()
@@ -1689,7 +1969,7 @@ func (s *BoltState) SafeRewriteContainerConfig(ctr *Container, oldName, newName
// rename.
needsRename = false
} else {
- return errors.Wrapf(define.ErrCtrExists, "name %s already in use, cannot rename container %s", newName, ctr.ID())
+ return fmt.Errorf("name %s already in use, cannot rename container %s: %w", newName, ctr.ID(), define.ErrCtrExists)
}
}
@@ -1698,16 +1978,16 @@ func (s *BoltState) SafeRewriteContainerConfig(ctr *Container, oldName, newName
// buckets are ID-indexed so we just need to
// overwrite the values there.
if err := namesBkt.Delete([]byte(oldName)); err != nil {
- return errors.Wrapf(err, "error deleting container %s old name from DB for rename", ctr.ID())
+ return fmt.Errorf("error deleting container %s old name from DB for rename: %w", ctr.ID(), err)
}
if err := idBkt.Put([]byte(ctr.ID()), []byte(newName)); err != nil {
- return errors.Wrapf(err, "error renaming container %s in ID bucket in DB", ctr.ID())
+ return fmt.Errorf("error renaming container %s in ID bucket in DB: %w", ctr.ID(), err)
}
if err := namesBkt.Put([]byte(newName), []byte(ctr.ID())); err != nil {
- return errors.Wrapf(err, "error adding new name %s for container %s in DB", newName, ctr.ID())
+ return fmt.Errorf("error adding new name %s for container %s in DB: %w", newName, ctr.ID(), err)
}
if err := allCtrsBkt.Put([]byte(ctr.ID()), []byte(newName)); err != nil {
- return errors.Wrapf(err, "error renaming container %s in all containers bucket in DB", ctr.ID())
+ return fmt.Errorf("error renaming container %s in all containers bucket in DB: %w", ctr.ID(), err)
}
if ctr.config.Pod != "" {
podsBkt, err := getPodBucket(tx)
@@ -1716,14 +1996,14 @@ func (s *BoltState) SafeRewriteContainerConfig(ctr *Container, oldName, newName
}
podBkt := podsBkt.Bucket([]byte(ctr.config.Pod))
if podBkt == nil {
- return errors.Wrapf(define.ErrInternal, "bucket for pod %s does not exist", ctr.config.Pod)
+ return fmt.Errorf("bucket for pod %s does not exist: %w", ctr.config.Pod, define.ErrInternal)
}
podCtrBkt := podBkt.Bucket(containersBkt)
if podCtrBkt == nil {
- return errors.Wrapf(define.ErrInternal, "pod %s does not have a containers bucket", ctr.config.Pod)
+ return fmt.Errorf("pod %s does not have a containers bucket: %w", ctr.config.Pod, define.ErrInternal)
}
if err := podCtrBkt.Put([]byte(ctr.ID()), []byte(newName)); err != nil {
- return errors.Wrapf(err, "error renaming container %s in pod %s members bucket", ctr.ID(), ctr.config.Pod)
+ return fmt.Errorf("error renaming container %s in pod %s members bucket: %w", ctr.ID(), ctr.config.Pod, err)
}
}
}
@@ -1737,11 +2017,11 @@ func (s *BoltState) SafeRewriteContainerConfig(ctr *Container, oldName, newName
ctrDB := ctrBkt.Bucket([]byte(ctr.ID()))
if ctrDB == nil {
ctr.valid = false
- return errors.Wrapf(define.ErrNoSuchCtr, "no container with ID %q found in DB", ctr.ID())
+ return fmt.Errorf("no container with ID %q found in DB: %w", ctr.ID(), define.ErrNoSuchCtr)
}
if err := ctrDB.Put(configKey, newCfgJSON); err != nil {
- return errors.Wrapf(err, "error updating container %s config JSON", ctr.ID())
+ return fmt.Errorf("error updating container %s config JSON: %w", ctr.ID(), err)
}
return nil
@@ -1763,7 +2043,7 @@ func (s *BoltState) RewritePodConfig(pod *Pod, newCfg *PodConfig) error {
newCfgJSON, err := json.Marshal(newCfg)
if err != nil {
- return errors.Wrapf(err, "error marshalling new configuration JSON for pod %s", pod.ID())
+ return fmt.Errorf("error marshalling new configuration JSON for pod %s: %w", pod.ID(), err)
}
db, err := s.getDBCon()
@@ -1781,11 +2061,11 @@ func (s *BoltState) RewritePodConfig(pod *Pod, newCfg *PodConfig) error {
podDB := podBkt.Bucket([]byte(pod.ID()))
if podDB == nil {
pod.valid = false
- return errors.Wrapf(define.ErrNoSuchPod, "no pod with ID %s found in DB", pod.ID())
+ return fmt.Errorf("no pod with ID %s found in DB: %w", pod.ID(), define.ErrNoSuchPod)
}
if err := podDB.Put(configKey, newCfgJSON); err != nil {
- return errors.Wrapf(err, "error updating pod %s config JSON", pod.ID())
+ return fmt.Errorf("error updating pod %s config JSON: %w", pod.ID(), err)
}
return nil
@@ -1807,7 +2087,7 @@ func (s *BoltState) RewriteVolumeConfig(volume *Volume, newCfg *VolumeConfig) er
newCfgJSON, err := json.Marshal(newCfg)
if err != nil {
- return errors.Wrapf(err, "error marshalling new configuration JSON for volume %q", volume.Name())
+ return fmt.Errorf("error marshalling new configuration JSON for volume %q: %w", volume.Name(), err)
}
db, err := s.getDBCon()
@@ -1825,11 +2105,11 @@ func (s *BoltState) RewriteVolumeConfig(volume *Volume, newCfg *VolumeConfig) er
volDB := volBkt.Bucket([]byte(volume.Name()))
if volDB == nil {
volume.valid = false
- return errors.Wrapf(define.ErrNoSuchVolume, "no volume with name %q found in DB", volume.Name())
+ return fmt.Errorf("no volume with name %q found in DB: %w", volume.Name(), define.ErrNoSuchVolume)
}
if err := volDB.Put(configKey, newCfgJSON); err != nil {
- return errors.Wrapf(err, "error updating volume %q config JSON", volume.Name())
+ return fmt.Errorf("error updating volume %q config JSON: %w", volume.Name(), err)
}
return nil
@@ -1953,7 +2233,7 @@ func (s *BoltState) LookupPod(idOrName string) (*Pod, error) {
}
if strings.HasPrefix(string(checkID), idOrName) {
if exists {
- return errors.Wrapf(define.ErrPodExists, "more than one result for ID or name %s", idOrName)
+ return fmt.Errorf("more than one result for ID or name %s: %w", idOrName, define.ErrPodExists)
}
id = checkID
exists = true
@@ -1965,9 +2245,9 @@ func (s *BoltState) LookupPod(idOrName string) (*Pod, error) {
return err
} else if !exists {
if isCtr {
- return errors.Wrapf(define.ErrNoSuchPod, "%s is a container, not a pod", idOrName)
+ return fmt.Errorf("%s is a container, not a pod: %w", idOrName, define.ErrNoSuchPod)
}
- return errors.Wrapf(define.ErrNoSuchPod, "no pod with name or ID %s found", idOrName)
+ return fmt.Errorf("no pod with name or ID %s found: %w", idOrName, define.ErrNoSuchPod)
}
// We might have found a container ID, but it's OK
@@ -2043,7 +2323,7 @@ func (s *BoltState) PodHasContainer(pod *Pod, id string) (bool, error) {
}
if s.namespace != "" && s.namespace != pod.config.Namespace {
- return false, errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace)
+ return false, fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch)
}
ctrID := []byte(id)
@@ -2067,13 +2347,13 @@ func (s *BoltState) PodHasContainer(pod *Pod, id string) (bool, error) {
podDB := podBkt.Bucket(podID)
if podDB == nil {
pod.valid = false
- return errors.Wrapf(define.ErrNoSuchPod, "pod %s not found in database", pod.ID())
+ return fmt.Errorf("pod %s not found in database: %w", pod.ID(), define.ErrNoSuchPod)
}
// Get pod containers bucket
podCtrs := podDB.Bucket(containersBkt)
if podCtrs == nil {
- return errors.Wrapf(define.ErrInternal, "pod %s missing containers bucket in DB", pod.ID())
+ return fmt.Errorf("pod %s missing containers bucket in DB: %w", pod.ID(), define.ErrInternal)
}
// Don't bother with a namespace check on the container -
@@ -2106,7 +2386,7 @@ func (s *BoltState) PodContainersByID(pod *Pod) ([]string, error) {
}
if s.namespace != "" && s.namespace != pod.config.Namespace {
- return nil, errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace)
+ return nil, fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch)
}
podID := []byte(pod.ID())
@@ -2129,13 +2409,13 @@ func (s *BoltState) PodContainersByID(pod *Pod) ([]string, error) {
podDB := podBkt.Bucket(podID)
if podDB == nil {
pod.valid = false
- return errors.Wrapf(define.ErrNoSuchPod, "pod %s not found in database", pod.ID())
+ return fmt.Errorf("pod %s not found in database: %w", pod.ID(), define.ErrNoSuchPod)
}
// Get pod containers bucket
podCtrs := podDB.Bucket(containersBkt)
if podCtrs == nil {
- return errors.Wrapf(define.ErrInternal, "pod %s missing containers bucket in DB", pod.ID())
+ return fmt.Errorf("pod %s missing containers bucket in DB: %w", pod.ID(), define.ErrInternal)
}
// Iterate through all containers in the pod
@@ -2168,7 +2448,7 @@ func (s *BoltState) PodContainers(pod *Pod) ([]*Container, error) {
}
if s.namespace != "" && s.namespace != pod.config.Namespace {
- return nil, errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace)
+ return nil, fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch)
}
podID := []byte(pod.ID())
@@ -2196,13 +2476,13 @@ func (s *BoltState) PodContainers(pod *Pod) ([]*Container, error) {
podDB := podBkt.Bucket(podID)
if podDB == nil {
pod.valid = false
- return errors.Wrapf(define.ErrNoSuchPod, "pod %s not found in database", pod.ID())
+ return fmt.Errorf("pod %s not found in database: %w", pod.ID(), define.ErrNoSuchPod)
}
// Get pod containers bucket
podCtrs := podDB.Bucket(containersBkt)
if podCtrs == nil {
- return errors.Wrapf(define.ErrInternal, "pod %s missing containers bucket in DB", pod.ID())
+ return fmt.Errorf("pod %s missing containers bucket in DB: %w", pod.ID(), define.ErrInternal)
}
// Iterate through all containers in the pod
@@ -2242,7 +2522,7 @@ func (s *BoltState) AddVolume(volume *Volume) error {
volConfigJSON, err := json.Marshal(volume.config)
if err != nil {
- return errors.Wrapf(err, "error marshalling volume %s config to JSON", volume.Name())
+ return fmt.Errorf("error marshalling volume %s config to JSON: %w", volume.Name(), err)
}
// Volume state is allowed to not exist
@@ -2250,7 +2530,7 @@ func (s *BoltState) AddVolume(volume *Volume) error {
if volume.state != nil {
volStateJSON, err = json.Marshal(volume.state)
if err != nil {
- return errors.Wrapf(err, "error marshalling volume %s state to JSON", volume.Name())
+ return fmt.Errorf("error marshalling volume %s state to JSON: %w", volume.Name(), err)
}
}
@@ -2274,34 +2554,34 @@ func (s *BoltState) AddVolume(volume *Volume) error {
// Check if we already have a volume with the given name
volExists := allVolsBkt.Get(volName)
if volExists != nil {
- return errors.Wrapf(define.ErrVolumeExists, "name %s is in use", volume.Name())
+ return fmt.Errorf("name %s is in use: %w", volume.Name(), define.ErrVolumeExists)
}
// We are good to add the volume
// Make a bucket for it
newVol, err := volBkt.CreateBucket(volName)
if err != nil {
- return errors.Wrapf(err, "error creating bucket for volume %s", volume.Name())
+ return fmt.Errorf("error creating bucket for volume %s: %w", volume.Name(), err)
}
// Make a subbucket for the containers using the volume. Dependent container IDs will be addedremoved to
// this bucket in addcontainer/removeContainer
if _, err := newVol.CreateBucket(volDependenciesBkt); err != nil {
- return errors.Wrapf(err, "error creating bucket for containers using volume %s", volume.Name())
+ return fmt.Errorf("error creating bucket for containers using volume %s: %w", volume.Name(), err)
}
if err := newVol.Put(configKey, volConfigJSON); err != nil {
- return errors.Wrapf(err, "error storing volume %s configuration in DB", volume.Name())
+ return fmt.Errorf("error storing volume %s configuration in DB: %w", volume.Name(), err)
}
if volStateJSON != nil {
if err := newVol.Put(stateKey, volStateJSON); err != nil {
- return errors.Wrapf(err, "error storing volume %s state in DB", volume.Name())
+ return fmt.Errorf("error storing volume %s state in DB: %w", volume.Name(), err)
}
}
if err := allVolsBkt.Put(volName, volName); err != nil {
- return errors.Wrapf(err, "error storing volume %s in all volumes bucket in DB", volume.Name())
+ return fmt.Errorf("error storing volume %s in all volumes bucket in DB: %w", volume.Name(), err)
}
return nil
@@ -2343,7 +2623,7 @@ func (s *BoltState) RemoveVolume(volume *Volume) error {
volDB := volBkt.Bucket(volName)
if volDB == nil {
volume.valid = false
- return errors.Wrapf(define.ErrNoSuchVolume, "volume %s does not exist in DB", volume.Name())
+ return fmt.Errorf("volume %s does not exist in DB: %w", volume.Name(), define.ErrNoSuchVolume)
}
// Check if volume is not being used by any container
@@ -2370,20 +2650,20 @@ func (s *BoltState) RemoveVolume(volume *Volume) error {
return nil
})
if err != nil {
- return errors.Wrapf(err, "error getting list of dependencies from dependencies bucket for volumes %q", volume.Name())
+ return fmt.Errorf("error getting list of dependencies from dependencies bucket for volumes %q: %w", volume.Name(), err)
}
if len(deps) > 0 {
- return errors.Wrapf(define.ErrVolumeBeingUsed, "volume %s is being used by container(s) %s", volume.Name(), strings.Join(deps, ","))
+ return fmt.Errorf("volume %s is being used by container(s) %s: %w", volume.Name(), strings.Join(deps, ","), define.ErrVolumeBeingUsed)
}
}
// volume is ready for removal
// Let's kick it out
if err := allVolsBkt.Delete(volName); err != nil {
- return errors.Wrapf(err, "error removing volume %s from all volumes bucket in DB", volume.Name())
+ return fmt.Errorf("error removing volume %s from all volumes bucket in DB: %w", volume.Name(), err)
}
if err := volBkt.DeleteBucket(volName); err != nil {
- return errors.Wrapf(err, "error removing volume %s from DB", volume.Name())
+ return fmt.Errorf("error removing volume %s from DB: %w", volume.Name(), err)
}
return nil
@@ -2419,7 +2699,7 @@ func (s *BoltState) UpdateVolume(volume *Volume) error {
volToUpdate := volBucket.Bucket(volumeName)
if volToUpdate == nil {
volume.valid = false
- return errors.Wrapf(define.ErrNoSuchVolume, "no volume with name %s found in database", volume.Name())
+ return fmt.Errorf("no volume with name %s found in database: %w", volume.Name(), define.ErrNoSuchVolume)
}
stateBytes := volToUpdate.Get(stateKey)
@@ -2430,7 +2710,7 @@ func (s *BoltState) UpdateVolume(volume *Volume) error {
}
if err := json.Unmarshal(stateBytes, newState); err != nil {
- return errors.Wrapf(err, "error unmarshalling volume %s state", volume.Name())
+ return fmt.Errorf("error unmarshalling volume %s state: %w", volume.Name(), err)
}
return nil
@@ -2460,7 +2740,7 @@ func (s *BoltState) SaveVolume(volume *Volume) error {
if volume.state != nil {
stateJSON, err := json.Marshal(volume.state)
if err != nil {
- return errors.Wrapf(err, "error marshalling volume %s state to JSON", volume.Name())
+ return fmt.Errorf("error marshalling volume %s state to JSON: %w", volume.Name(), err)
}
newStateJSON = stateJSON
}
@@ -2480,7 +2760,7 @@ func (s *BoltState) SaveVolume(volume *Volume) error {
volToUpdate := volBucket.Bucket(volumeName)
if volToUpdate == nil {
volume.valid = false
- return errors.Wrapf(define.ErrNoSuchVolume, "no volume with name %s found in database", volume.Name())
+ return fmt.Errorf("no volume with name %s found in database: %w", volume.Name(), define.ErrNoSuchVolume)
}
return volToUpdate.Put(stateKey, newStateJSON)
@@ -2517,7 +2797,7 @@ func (s *BoltState) AllVolumes() ([]*Volume, error) {
// This check can be removed if performance becomes an
// issue, but much less helpful errors will be produced
if volExists == nil {
- return errors.Wrapf(define.ErrInternal, "inconsistency in state - volume %s is in all volumes bucket but volume not found", string(id))
+ return fmt.Errorf("inconsistency in state - volume %s is in all volumes bucket but volume not found: %w", string(id), define.ErrInternal)
}
volume := new(Volume)
@@ -2525,7 +2805,7 @@ func (s *BoltState) AllVolumes() ([]*Volume, error) {
volume.state = new(VolumeState)
if err := s.getVolumeFromDB(id, volume, volBucket); err != nil {
- if errors.Cause(err) != define.ErrNSMismatch {
+ if !errors.Is(err, define.ErrNSMismatch) {
logrus.Errorf("Retrieving volume %s from the database: %v", string(id), err)
}
} else {
@@ -2624,7 +2904,7 @@ func (s *BoltState) LookupVolume(name string) (*Volume, error) {
err = allVolsBkt.ForEach(func(checkName, checkName2 []byte) error {
if strings.HasPrefix(string(checkName), name) {
if foundMatch {
- return errors.Wrapf(define.ErrVolumeExists, "more than one result for volume name %q", name)
+ return fmt.Errorf("more than one result for volume name %q: %w", name, define.ErrVolumeExists)
}
foundMatch = true
volName = checkName
@@ -2636,7 +2916,7 @@ func (s *BoltState) LookupVolume(name string) (*Volume, error) {
}
if !foundMatch {
- return errors.Wrapf(define.ErrNoSuchVolume, "no volume with name %q found", name)
+ return fmt.Errorf("no volume with name %q found: %w", name, define.ErrNoSuchVolume)
}
return s.getVolumeFromDB(volName, volume, volBkt)
@@ -2722,12 +3002,12 @@ func (s *BoltState) VolumeInUse(volume *Volume) ([]string, error) {
volDB := volBucket.Bucket([]byte(volume.Name()))
if volDB == nil {
volume.valid = false
- return errors.Wrapf(define.ErrNoSuchVolume, "no volume with name %s found in DB", volume.Name())
+ return fmt.Errorf("no volume with name %s found in DB: %w", volume.Name(), define.ErrNoSuchVolume)
}
dependsBkt := volDB.Bucket(volDependenciesBkt)
if dependsBkt == nil {
- return errors.Wrapf(define.ErrInternal, "volume %s has no dependencies bucket", volume.Name())
+ return fmt.Errorf("volume %s has no dependencies bucket: %w", volume.Name(), define.ErrInternal)
}
// Iterate through and add dependencies
@@ -2767,7 +3047,7 @@ func (s *BoltState) AddPod(pod *Pod) error {
}
if s.namespace != "" && s.namespace != pod.config.Namespace {
- return errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace)
+ return fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch)
}
podID := []byte(pod.ID())
@@ -2780,12 +3060,12 @@ func (s *BoltState) AddPod(pod *Pod) error {
podConfigJSON, err := json.Marshal(pod.config)
if err != nil {
- return errors.Wrapf(err, "error marshalling pod %s config to JSON", pod.ID())
+ return fmt.Errorf("error marshalling pod %s config to JSON: %w", pod.ID(), err)
}
podStateJSON, err := json.Marshal(pod.state)
if err != nil {
- return errors.Wrapf(err, "error marshalling pod %s state to JSON", pod.ID())
+ return fmt.Errorf("error marshalling pod %s state to JSON: %w", pod.ID(), err)
}
db, err := s.getDBCon()
@@ -2827,7 +3107,7 @@ func (s *BoltState) AddPod(pod *Pod) error {
if allPodsBkt.Get(idExist) == nil {
err = define.ErrCtrExists
}
- return errors.Wrapf(err, "ID \"%s\" is in use", pod.ID())
+ return fmt.Errorf("ID \"%s\" is in use: %w", pod.ID(), err)
}
nameExist := namesBkt.Get(podName)
if nameExist != nil {
@@ -2835,47 +3115,47 @@ func (s *BoltState) AddPod(pod *Pod) error {
if allPodsBkt.Get(nameExist) == nil {
err = define.ErrCtrExists
}
- return errors.Wrapf(err, "name \"%s\" is in use", pod.Name())
+ return fmt.Errorf("name \"%s\" is in use: %w", pod.Name(), err)
}
// We are good to add the pod
// Make a bucket for it
newPod, err := podBkt.CreateBucket(podID)
if err != nil {
- return errors.Wrapf(err, "error creating bucket for pod %s", pod.ID())
+ return fmt.Errorf("error creating bucket for pod %s: %w", pod.ID(), err)
}
// Make a subbucket for pod containers
if _, err := newPod.CreateBucket(containersBkt); err != nil {
- return errors.Wrapf(err, "error creating bucket for pod %s containers", pod.ID())
+ return fmt.Errorf("error creating bucket for pod %s containers: %w", pod.ID(), err)
}
if err := newPod.Put(configKey, podConfigJSON); err != nil {
- return errors.Wrapf(err, "error storing pod %s configuration in DB", pod.ID())
+ return fmt.Errorf("error storing pod %s configuration in DB: %w", pod.ID(), err)
}
if err := newPod.Put(stateKey, podStateJSON); err != nil {
- return errors.Wrapf(err, "error storing pod %s state JSON in DB", pod.ID())
+ return fmt.Errorf("error storing pod %s state JSON in DB: %w", pod.ID(), err)
}
if podNamespace != nil {
if err := newPod.Put(namespaceKey, podNamespace); err != nil {
- return errors.Wrapf(err, "error storing pod %s namespace in DB", pod.ID())
+ return fmt.Errorf("error storing pod %s namespace in DB: %w", pod.ID(), err)
}
if err := nsBkt.Put(podID, podNamespace); err != nil {
- return errors.Wrapf(err, "error storing pod %s namespace in DB", pod.ID())
+ return fmt.Errorf("error storing pod %s namespace in DB: %w", pod.ID(), err)
}
}
// 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())
+ return fmt.Errorf("error storing pod %s ID in DB: %w", pod.ID(), err)
}
if err := namesBkt.Put(podName, podID); err != nil {
- return errors.Wrapf(err, "error storing pod %s name in DB", pod.Name())
+ return fmt.Errorf("error storing pod %s name in DB: %w", pod.Name(), err)
}
if err := allPodsBkt.Put(podID, podName); err != nil {
- return errors.Wrapf(err, "error storing pod %s in all pods bucket in DB", pod.ID())
+ return fmt.Errorf("error storing pod %s in all pods bucket in DB: %w", pod.ID(), err)
}
return nil
@@ -2899,7 +3179,7 @@ func (s *BoltState) RemovePod(pod *Pod) error {
}
if s.namespace != "" && s.namespace != pod.config.Namespace {
- return errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace)
+ return fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch)
}
podID := []byte(pod.ID())
@@ -2941,7 +3221,7 @@ func (s *BoltState) RemovePod(pod *Pod) error {
podDB := podBkt.Bucket(podID)
if podDB == nil {
pod.valid = false
- return errors.Wrapf(define.ErrNoSuchPod, "pod %s does not exist in DB", pod.ID())
+ return fmt.Errorf("pod %s does not exist in DB: %w", pod.ID(), define.ErrNoSuchPod)
}
// Check if pod is empty
@@ -2953,26 +3233,26 @@ func (s *BoltState) RemovePod(pod *Pod) error {
if podCtrsBkt != nil {
cursor := podCtrsBkt.Cursor()
if id, _ := cursor.First(); id != nil {
- return errors.Wrapf(define.ErrCtrExists, "pod %s is not empty", pod.ID())
+ return fmt.Errorf("pod %s is not empty: %w", pod.ID(), define.ErrCtrExists)
}
}
// Pod is empty, and ready for removal
// Let's kick it out
if err := idsBkt.Delete(podID); err != nil {
- return errors.Wrapf(err, "error removing pod %s ID from DB", pod.ID())
+ return fmt.Errorf("error removing pod %s ID from DB: %w", pod.ID(), err)
}
if err := namesBkt.Delete(podName); err != nil {
- return errors.Wrapf(err, "error removing pod %s name (%s) from DB", pod.ID(), pod.Name())
+ return fmt.Errorf("error removing pod %s name (%s) from DB: %w", pod.ID(), pod.Name(), err)
}
if err := nsBkt.Delete(podID); err != nil {
- return errors.Wrapf(err, "error removing pod %s namespace from DB", pod.ID())
+ return fmt.Errorf("error removing pod %s namespace from DB: %w", pod.ID(), err)
}
if err := allPodsBkt.Delete(podID); err != nil {
- return errors.Wrapf(err, "error removing pod %s ID from all pods bucket in DB", pod.ID())
+ return fmt.Errorf("error removing pod %s ID from all pods bucket in DB: %w", pod.ID(), err)
}
if err := podBkt.DeleteBucket(podID); err != nil {
- return errors.Wrapf(err, "error removing pod %s from DB", pod.ID())
+ return fmt.Errorf("error removing pod %s from DB: %w", pod.ID(), err)
}
return nil
@@ -2995,7 +3275,7 @@ func (s *BoltState) RemovePodContainers(pod *Pod) error {
}
if s.namespace != "" && s.namespace != pod.config.Namespace {
- return errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace)
+ return fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch)
}
podID := []byte(pod.ID())
@@ -3036,12 +3316,12 @@ func (s *BoltState) RemovePodContainers(pod *Pod) error {
podDB := podBkt.Bucket(podID)
if podDB == nil {
pod.valid = false
- return errors.Wrapf(define.ErrNoSuchPod, "pod %s does not exist in DB", pod.ID())
+ return fmt.Errorf("pod %s does not exist in DB: %w", pod.ID(), define.ErrNoSuchPod)
}
podCtrsBkt := podDB.Bucket(containersBkt)
if podCtrsBkt == nil {
- return errors.Wrapf(define.ErrInternal, "pod %s does not have a containers bucket", pod.ID())
+ return fmt.Errorf("pod %s does not have a containers bucket: %w", pod.ID(), define.ErrInternal)
}
// Traverse all containers in the pod with a cursor
@@ -3052,7 +3332,7 @@ func (s *BoltState) RemovePodContainers(pod *Pod) error {
if ctr == nil {
// This should never happen
// State is inconsistent
- return errors.Wrapf(define.ErrNoSuchCtr, "pod %s referenced nonexistent container %s", pod.ID(), string(id))
+ return fmt.Errorf("pod %s referenced nonexistent container %s: %w", pod.ID(), string(id), define.ErrNoSuchCtr)
}
ctrDeps := ctr.Bucket(dependenciesBkt)
// This should never be nil, but if it is, we're
@@ -3061,7 +3341,7 @@ func (s *BoltState) RemovePodContainers(pod *Pod) error {
err = ctrDeps.ForEach(func(depID, name []byte) error {
exists := podCtrsBkt.Get(depID)
if exists == nil {
- return errors.Wrapf(define.ErrCtrExists, "container %s has dependency %s outside of pod %s", string(id), string(depID), pod.ID())
+ return fmt.Errorf("container %s has dependency %s outside of pod %s: %w", string(id), string(depID), pod.ID(), define.ErrCtrExists)
}
return nil
})
@@ -3073,19 +3353,19 @@ func (s *BoltState) RemovePodContainers(pod *Pod) error {
// Dependencies are set, we're clear to remove
if err := ctrBkt.DeleteBucket(id); err != nil {
- return errors.Wrapf(define.ErrInternal, "error deleting container %s from DB", string(id))
+ return fmt.Errorf("error deleting container %s from DB: %w", string(id), define.ErrInternal)
}
if err := idsBkt.Delete(id); err != nil {
- return errors.Wrapf(err, "error deleting container %s ID in DB", string(id))
+ return fmt.Errorf("error deleting container %s ID in DB: %w", string(id), err)
}
if err := namesBkt.Delete(name); err != nil {
- return errors.Wrapf(err, "error deleting container %s name in DB", string(id))
+ return fmt.Errorf("error deleting container %s name in DB: %w", string(id), err)
}
if err := allCtrsBkt.Delete(id); err != nil {
- return errors.Wrapf(err, "error deleting container %s ID from all containers bucket in DB", string(id))
+ return fmt.Errorf("error deleting container %s ID from all containers bucket in DB: %w", string(id), err)
}
return nil
@@ -3096,10 +3376,10 @@ func (s *BoltState) RemovePodContainers(pod *Pod) error {
// Delete and recreate the bucket to empty it
if err := podDB.DeleteBucket(containersBkt); err != nil {
- return errors.Wrapf(err, "error removing pod %s containers bucket", pod.ID())
+ return fmt.Errorf("error removing pod %s containers bucket: %w", pod.ID(), err)
}
if _, err := podDB.CreateBucket(containersBkt); err != nil {
- return errors.Wrapf(err, "error recreating pod %s containers bucket", pod.ID())
+ return fmt.Errorf("error recreating pod %s containers bucket: %w", pod.ID(), err)
}
return nil
@@ -3127,7 +3407,7 @@ func (s *BoltState) AddContainerToPod(pod *Pod, ctr *Container) error {
}
if ctr.config.Pod != pod.ID() {
- return errors.Wrapf(define.ErrNoSuchCtr, "container %s is not part of pod %s", ctr.ID(), pod.ID())
+ return fmt.Errorf("container %s is not part of pod %s: %w", ctr.ID(), pod.ID(), define.ErrNoSuchCtr)
}
return s.addContainer(ctr, pod)
@@ -3146,19 +3426,19 @@ func (s *BoltState) RemoveContainerFromPod(pod *Pod, ctr *Container) error {
if s.namespace != "" {
if s.namespace != pod.config.Namespace {
- return errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace)
+ return fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch)
}
if s.namespace != ctr.config.Namespace {
- return errors.Wrapf(define.ErrNSMismatch, "container %s in in namespace %q but we are in namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace)
+ return fmt.Errorf("container %s in in namespace %q but we are in namespace %q: %w", ctr.ID(), ctr.config.Namespace, s.namespace, define.ErrNSMismatch)
}
}
if ctr.config.Pod == "" {
- return errors.Wrapf(define.ErrNoSuchPod, "container %s is not part of a pod, use RemoveContainer instead", ctr.ID())
+ return fmt.Errorf("container %s is not part of a pod, use RemoveContainer instead: %w", ctr.ID(), define.ErrNoSuchPod)
}
if ctr.config.Pod != pod.ID() {
- return errors.Wrapf(define.ErrInvalidArg, "container %s is not part of pod %s", ctr.ID(), pod.ID())
+ return fmt.Errorf("container %s is not part of pod %s: %w", ctr.ID(), pod.ID(), define.ErrInvalidArg)
}
db, err := s.getDBCon()
@@ -3184,7 +3464,7 @@ func (s *BoltState) UpdatePod(pod *Pod) error {
}
if s.namespace != "" && s.namespace != pod.config.Namespace {
- return errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace)
+ return fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch)
}
newState := new(podState)
@@ -3206,17 +3486,17 @@ func (s *BoltState) UpdatePod(pod *Pod) error {
podDB := podBkt.Bucket(podID)
if podDB == nil {
pod.valid = false
- return errors.Wrapf(define.ErrNoSuchPod, "no pod with ID %s found in database", pod.ID())
+ return fmt.Errorf("no pod with ID %s found in database: %w", pod.ID(), define.ErrNoSuchPod)
}
// Get the pod state JSON
podStateBytes := podDB.Get(stateKey)
if podStateBytes == nil {
- return errors.Wrapf(define.ErrInternal, "pod %s is missing state key in DB", pod.ID())
+ return fmt.Errorf("pod %s is missing state key in DB: %w", pod.ID(), define.ErrInternal)
}
if err := json.Unmarshal(podStateBytes, newState); err != nil {
- return errors.Wrapf(err, "error unmarshalling pod %s state JSON", pod.ID())
+ return fmt.Errorf("error unmarshalling pod %s state JSON: %w", pod.ID(), err)
}
return nil
@@ -3241,12 +3521,12 @@ func (s *BoltState) SavePod(pod *Pod) error {
}
if s.namespace != "" && s.namespace != pod.config.Namespace {
- return errors.Wrapf(define.ErrNSMismatch, "pod %s is in namespace %q but we are in namespace %q", pod.ID(), pod.config.Namespace, s.namespace)
+ return fmt.Errorf("pod %s is in namespace %q but we are in namespace %q: %w", pod.ID(), pod.config.Namespace, s.namespace, define.ErrNSMismatch)
}
stateJSON, err := json.Marshal(pod.state)
if err != nil {
- return errors.Wrapf(err, "error marshalling pod %s state to JSON", pod.ID())
+ return fmt.Errorf("error marshalling pod %s state to JSON: %w", pod.ID(), err)
}
db, err := s.getDBCon()
@@ -3266,12 +3546,12 @@ func (s *BoltState) SavePod(pod *Pod) error {
podDB := podBkt.Bucket(podID)
if podDB == nil {
pod.valid = false
- return errors.Wrapf(define.ErrNoSuchPod, "no pod with ID %s found in database", pod.ID())
+ return fmt.Errorf("no pod with ID %s found in database: %w", pod.ID(), define.ErrNoSuchPod)
}
// Set the pod state JSON
if err := podDB.Put(stateKey, stateJSON); err != nil {
- return errors.Wrapf(err, "error updating pod %s state in database", pod.ID())
+ return fmt.Errorf("error updating pod %s state in database: %w", pod.ID(), err)
}
return nil
@@ -3313,7 +3593,7 @@ func (s *BoltState) AllPods() ([]*Pod, error) {
// This check can be removed if performance becomes an
// issue, but much less helpful errors will be produced
if podExists == nil {
- return errors.Wrapf(define.ErrInternal, "inconsistency in state - pod %s is in all pods bucket but pod not found", string(id))
+ return fmt.Errorf("inconsistency in state - pod %s is in all pods bucket but pod not found: %w", string(id), define.ErrInternal)
}
pod := new(Pod)
@@ -3321,7 +3601,7 @@ func (s *BoltState) AllPods() ([]*Pod, error) {
pod.state = new(podState)
if err := s.getPodFromDB(id, pod, podBucket); err != nil {
- if errors.Cause(err) != define.ErrNSMismatch {
+ if !errors.Is(err, define.ErrNSMismatch) {
logrus.Errorf("Retrieving pod %s from the database: %v", string(id), err)
}
} else {