mirror of
https://github.com/containers/podman.git
synced 2025-07-04 10:10:32 +08:00
Add ability to rewrite pod configs in the database
Necessary for rewriting lock IDs as part of renumber. Signed-off-by: Matthew Heon <matthew.heon@pm.me>
This commit is contained in:
@ -827,6 +827,50 @@ func (s *BoltState) RewriteContainerConfig(ctr *Container, newCfg *ContainerConf
|
||||
return err
|
||||
}
|
||||
|
||||
// RewritePodConfig rewrites a pod's configuration.
|
||||
// WARNING: This function is DANGEROUS. Do not use without reading the full
|
||||
// comment on this function in state.go.
|
||||
func (s *BoltState) RewritePodConfig(pod *Pod, newCfg *PodConfig) error {
|
||||
if !s.valid {
|
||||
return ErrDBClosed
|
||||
}
|
||||
|
||||
if !pod.valid {
|
||||
return ErrPodRemoved
|
||||
}
|
||||
|
||||
newCfgJSON, err := json.Marshal(newCfg)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error marshalling new configuration JSON for container %s", pod.ID())
|
||||
}
|
||||
|
||||
db, err := s.getDBCon()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.closeDBCon(db)
|
||||
|
||||
err = db.Update(func(tx *bolt.Tx) error {
|
||||
podBkt, err := getPodBucket(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
podDB := podBkt.Bucket([]byte(pod.ID()))
|
||||
if podDB == nil {
|
||||
pod.valid = false
|
||||
return errors.Wrapf(ErrNoSuchPod, "no pod with ID %s found in DB", pod.ID())
|
||||
}
|
||||
|
||||
if err := podDB.Put(configKey, newCfgJSON); err != nil {
|
||||
return errors.Wrapf(err, "error updating pod %s config JSON", pod.ID())
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// Pod retrieves a pod given its full ID
|
||||
func (s *BoltState) Pod(id string) (*Pod, error) {
|
||||
if id == "" {
|
||||
|
@ -410,6 +410,26 @@ func (s *InMemoryState) RewriteContainerConfig(ctr *Container, newCfg *Container
|
||||
return nil
|
||||
}
|
||||
|
||||
// RewritePodConfig rewrites a pod's configuration.
|
||||
// This function is DANGEROUS, even with in-memory state.
|
||||
// Please read the full comment on it in state.go before using it.
|
||||
func (s *InMemoryState) RewritePodConfig(pod *Pod, newCfg *PodConfig) error {
|
||||
if !pod.valid {
|
||||
return ErrPodRemoved
|
||||
}
|
||||
|
||||
// If the pod does not exist, return error
|
||||
statePod, ok := s.pods[pod.ID()]
|
||||
if !ok {
|
||||
pod.valid = false
|
||||
return errors.Wrapf(ErrNoSuchPod, "pod with ID %s not found in state", pod.ID())
|
||||
}
|
||||
|
||||
statePod.config = newCfg
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Volume retrieves a volume from its full name
|
||||
func (s *InMemoryState) Volume(name string) (*Volume, error) {
|
||||
if name == "" {
|
||||
|
@ -107,10 +107,19 @@ type State interface {
|
||||
// newer, but identical, configuration fields), or during libpod init
|
||||
// WHILE HOLDING THE ALIVE LOCK (to prevent other libpod instances from
|
||||
// being initialized).
|
||||
// Most things in config can be changed by this, but container ID and
|
||||
// name ABSOLUTELY CANNOT BE ALTERED. If you do so, there is a high
|
||||
// potential for database corruption.
|
||||
// There are a lot of capital letters and conditions here, but the short
|
||||
// answer is this: use this only very sparingly, and only if you really
|
||||
// know what you're doing.
|
||||
RewriteContainerConfig(ctr *Container, newCfg *ContainerConfig) error
|
||||
// PLEASE READ THE ABOVE DESCRIPTION BEFORE USING.
|
||||
// This function is identical to RewriteContainerConfig, save for the
|
||||
// fact that it is used with pods instead.
|
||||
// It is subject to the same conditions as RewriteContainerConfig.
|
||||
// Please do not use this unless you know what you're doing.
|
||||
RewritePodConfig(pod *Pod, newCfg *PodConfig) error
|
||||
|
||||
// Accepts full ID of pod.
|
||||
// If the pod given is not in the set namespace, an error will be
|
||||
|
@ -1334,6 +1334,42 @@ func TestRewriteContainerConfigRewritesConfig(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestRewritePodConfigDoesNotExist(t *testing.T) {
|
||||
runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) {
|
||||
err := state.RewritePodConfig(&Pod{}, &PodConfig{})
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestRewritePodConfigNotInState(t *testing.T) {
|
||||
runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) {
|
||||
testPod, err := getTestPod1(manager)
|
||||
assert.NoError(t, err)
|
||||
err = state.RewritePodConfig(testPod, &PodConfig{})
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestRewritePodConfigRewritesConfig(t *testing.T) {
|
||||
runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) {
|
||||
testPod, err := getTestPod1(manager)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = state.AddPod(testPod)
|
||||
assert.NoError(t, err)
|
||||
|
||||
testPod.config.CgroupParent = "/another_cgroup_parent"
|
||||
|
||||
err = state.RewritePodConfig(testPod, testPod.config)
|
||||
assert.NoError(t, err)
|
||||
|
||||
testPodFromState, err := state.Pod(testPod.ID())
|
||||
assert.NoError(t, err)
|
||||
|
||||
testPodsEqual(t, testPodFromState, testPod, true)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetPodDoesNotExist(t *testing.T) {
|
||||
runForAllStates(t, func(t *testing.T, state State, manager lock.Manager) {
|
||||
_, err := state.Pod("doesnotexist")
|
||||
|
Reference in New Issue
Block a user