mirror of
https://github.com/containers/podman.git
synced 2025-06-18 15:39:08 +08:00
Fix bugs identified by unit tests
Signed-off-by: Matthew Heon <matthew.heon@gmail.com> Closes: #268 Approved by: rhatdan
This commit is contained in:
@ -123,6 +123,17 @@ func (s *InMemoryState) AddContainer(ctr *Container) error {
|
|||||||
return errors.Wrapf(ErrInvalidArg, "cannot add a container that is in a pod with AddContainer, use AddContainerToPod")
|
return errors.Wrapf(ErrInvalidArg, "cannot add a container that is in a pod with AddContainer, use AddContainerToPod")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// There are potential race conditions with this
|
||||||
|
// But in-memory state is intended purely for testing and not production
|
||||||
|
// use, so this should be fine.
|
||||||
|
depCtrs := ctr.Dependencies()
|
||||||
|
for _, depCtr := range depCtrs {
|
||||||
|
_, ok = s.containers[depCtr]
|
||||||
|
if !ok {
|
||||||
|
return errors.Wrapf(ErrNoSuchCtr, "cannot depend on nonexistent container %s", depCtr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := s.nameIndex.Reserve(ctr.Name(), ctr.ID()); err != nil {
|
if err := s.nameIndex.Reserve(ctr.Name(), ctr.ID()); err != nil {
|
||||||
return errors.Wrapf(err, "error registering container name %s", ctr.Name())
|
return errors.Wrapf(err, "error registering container name %s", ctr.Name())
|
||||||
}
|
}
|
||||||
@ -135,7 +146,6 @@ func (s *InMemoryState) AddContainer(ctr *Container) error {
|
|||||||
s.containers[ctr.ID()] = ctr
|
s.containers[ctr.ID()] = ctr
|
||||||
|
|
||||||
// Add containers this container depends on
|
// Add containers this container depends on
|
||||||
depCtrs := ctr.Dependencies()
|
|
||||||
for _, depCtr := range depCtrs {
|
for _, depCtr := range depCtrs {
|
||||||
s.addCtrToDependsMap(ctr.ID(), depCtr)
|
s.addCtrToDependsMap(ctr.ID(), depCtr)
|
||||||
}
|
}
|
||||||
@ -157,6 +167,7 @@ func (s *InMemoryState) RemoveContainer(ctr *Container) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := s.containers[ctr.ID()]; !ok {
|
if _, ok := s.containers[ctr.ID()]; !ok {
|
||||||
|
ctr.valid = false
|
||||||
return errors.Wrapf(ErrNoSuchCtr, "no container exists in state with ID %s", ctr.ID())
|
return errors.Wrapf(ErrNoSuchCtr, "no container exists in state with ID %s", ctr.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,6 +312,10 @@ func (s *InMemoryState) PodHasContainer(pod *Pod, ctrID string) (bool, error) {
|
|||||||
return false, errors.Wrapf(ErrPodRemoved, "pod %s is not valid")
|
return false, errors.Wrapf(ErrPodRemoved, "pod %s is not valid")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ctrID == "" {
|
||||||
|
return false, ErrEmptyID
|
||||||
|
}
|
||||||
|
|
||||||
podCtrs, ok := s.podContainers[pod.ID()]
|
podCtrs, ok := s.podContainers[pod.ID()]
|
||||||
if !ok {
|
if !ok {
|
||||||
pod.valid = false
|
pod.valid = false
|
||||||
@ -398,10 +413,12 @@ func (s *InMemoryState) RemovePod(pod *Pod) error {
|
|||||||
// pods out of the state
|
// pods out of the state
|
||||||
|
|
||||||
if _, ok := s.pods[pod.ID()]; !ok {
|
if _, ok := s.pods[pod.ID()]; !ok {
|
||||||
|
pod.valid = false
|
||||||
return errors.Wrapf(ErrNoSuchPod, "no pod exists in state with ID %s", pod.ID())
|
return errors.Wrapf(ErrNoSuchPod, "no pod exists in state with ID %s", pod.ID())
|
||||||
}
|
}
|
||||||
podCtrs, ok := s.podContainers[pod.ID()]
|
podCtrs, ok := s.podContainers[pod.ID()]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
pod.valid = false
|
||||||
return errors.Wrapf(ErrNoSuchPod, "no pod exists in state with ID %s", pod.ID())
|
return errors.Wrapf(ErrNoSuchPod, "no pod exists in state with ID %s", pod.ID())
|
||||||
}
|
}
|
||||||
if len(podCtrs) != 0 {
|
if len(podCtrs) != 0 {
|
||||||
@ -430,16 +447,14 @@ func (s *InMemoryState) RemovePodContainers(pod *Pod) error {
|
|||||||
// Get pod containers
|
// Get pod containers
|
||||||
podCtrs, ok := s.podContainers[pod.ID()]
|
podCtrs, ok := s.podContainers[pod.ID()]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
pod.valid = false
|
||||||
return errors.Wrapf(ErrNoSuchPod, "no pod exists in state with ID %s", pod.ID())
|
return errors.Wrapf(ErrNoSuchPod, "no pod exists in state with ID %s", pod.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go through container dependencies. Check to see if any are outside the pod.
|
// Go through container dependencies. Check to see if any are outside the pod.
|
||||||
for ctr := range podCtrs {
|
for ctr := range podCtrs {
|
||||||
ctrDeps, ok := s.ctrDepends[ctr]
|
ctrDeps, ok := s.ctrDepends[ctr]
|
||||||
if !ok {
|
if ok {
|
||||||
return errors.Wrapf(ErrInternal, "cannot find dependencies for container %s", ctr)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, dep := range ctrDeps {
|
for _, dep := range ctrDeps {
|
||||||
_, ok := podCtrs[dep]
|
_, ok := podCtrs[dep]
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -447,6 +462,7 @@ func (s *InMemoryState) RemovePodContainers(pod *Pod) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// All dependencies are OK to remove
|
// All dependencies are OK to remove
|
||||||
// Remove all containers
|
// Remove all containers
|
||||||
@ -490,6 +506,17 @@ func (s *InMemoryState) AddContainerToPod(pod *Pod, ctr *Container) error {
|
|||||||
return errors.Wrapf(ErrCtrExists, "container with ID %s already exists in pod %s", ctr.ID(), pod.ID())
|
return errors.Wrapf(ErrCtrExists, "container with ID %s already exists in pod %s", ctr.ID(), pod.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// There are potential race conditions with this
|
||||||
|
// But in-memory state is intended purely for testing and not production
|
||||||
|
// use, so this should be fine.
|
||||||
|
depCtrs := ctr.Dependencies()
|
||||||
|
for _, depCtr := range depCtrs {
|
||||||
|
_, ok = s.containers[depCtr]
|
||||||
|
if !ok {
|
||||||
|
return errors.Wrapf(ErrNoSuchCtr, "cannot depend on nonexistent container %s", depCtr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add container to state
|
// Add container to state
|
||||||
_, ok = s.containers[ctr.ID()]
|
_, ok = s.containers[ctr.ID()]
|
||||||
if ok {
|
if ok {
|
||||||
@ -510,6 +537,11 @@ func (s *InMemoryState) AddContainerToPod(pod *Pod, ctr *Container) error {
|
|||||||
// Add container to pod containers
|
// Add container to pod containers
|
||||||
podCtrs[ctr.ID()] = ctr
|
podCtrs[ctr.ID()] = ctr
|
||||||
|
|
||||||
|
// Add containers this container depends on
|
||||||
|
for _, depCtr := range depCtrs {
|
||||||
|
s.addCtrToDependsMap(ctr.ID(), depCtr)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -523,6 +555,13 @@ func (s *InMemoryState) RemoveContainerFromPod(pod *Pod, ctr *Container) error {
|
|||||||
return errors.Wrapf(ErrCtrRemoved, "container %s is not valid and cannot be removed from the pod", ctr.ID())
|
return errors.Wrapf(ErrCtrRemoved, "container %s is not valid and cannot be removed from the pod", ctr.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure we don't remove a container which other containers depend on
|
||||||
|
deps, ok := s.ctrDepends[ctr.ID()]
|
||||||
|
if ok && len(deps) != 0 {
|
||||||
|
depsStr := strings.Join(deps, ", ")
|
||||||
|
return errors.Wrapf(ErrCtrExists, "the following containers depend on container %s: %s", ctr.ID(), depsStr)
|
||||||
|
}
|
||||||
|
|
||||||
// Retrieve pod containers
|
// Retrieve pod containers
|
||||||
podCtrs, ok := s.podContainers[pod.ID()]
|
podCtrs, ok := s.podContainers[pod.ID()]
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -530,6 +569,12 @@ func (s *InMemoryState) RemoveContainerFromPod(pod *Pod, ctr *Container) error {
|
|||||||
return errors.Wrapf(ErrPodRemoved, "pod %s has been removed", pod.ID())
|
return errors.Wrapf(ErrPodRemoved, "pod %s has been removed", pod.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Does the container exist?
|
||||||
|
if _, ok := s.containers[ctr.ID()]; !ok {
|
||||||
|
ctr.valid = false
|
||||||
|
return errors.Wrapf(ErrNoSuchCtr, "container %s does not exist in state", ctr.ID())
|
||||||
|
}
|
||||||
|
|
||||||
// Is the container in the pod?
|
// Is the container in the pod?
|
||||||
if _, ok := podCtrs[ctr.ID()]; !ok {
|
if _, ok := podCtrs[ctr.ID()]; !ok {
|
||||||
return errors.Wrapf(ErrNoSuchCtr, "container with ID %s not found in pod %s", ctr.ID(), pod.ID())
|
return errors.Wrapf(ErrNoSuchCtr, "container with ID %s not found in pod %s", ctr.ID(), pod.ID())
|
||||||
@ -549,6 +594,12 @@ func (s *InMemoryState) RemoveContainerFromPod(pod *Pod, ctr *Container) error {
|
|||||||
// Remove the container from the pod
|
// Remove the container from the pod
|
||||||
delete(podCtrs, ctr.ID())
|
delete(podCtrs, ctr.ID())
|
||||||
|
|
||||||
|
// Remove us from container dependencies
|
||||||
|
depCtrs := ctr.Dependencies()
|
||||||
|
for _, depCtr := range depCtrs {
|
||||||
|
s.removeCtrFromDependsMap(ctr.ID(), depCtr)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ func newPod(lockDir string, runtime *Runtime) (*Pod, error) {
|
|||||||
pod := new(Pod)
|
pod := new(Pod)
|
||||||
pod.id = stringid.GenerateNonCryptoID()
|
pod.id = stringid.GenerateNonCryptoID()
|
||||||
pod.name = namesgenerator.GetRandomName(0)
|
pod.name = namesgenerator.GetRandomName(0)
|
||||||
|
pod.labels = make(map[string]string)
|
||||||
pod.runtime = runtime
|
pod.runtime = runtime
|
||||||
|
|
||||||
// Path our lock file will reside at
|
// Path our lock file will reside at
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
// DBSchema is the current DB schema version
|
// DBSchema is the current DB schema version
|
||||||
// Increments every time a change is made to the database's tables
|
// Increments every time a change is made to the database's tables
|
||||||
const DBSchema = 9
|
const DBSchema = 10
|
||||||
|
|
||||||
// SQLState is a state implementation backed by a persistent SQLite3 database
|
// SQLState is a state implementation backed by a persistent SQLite3 database
|
||||||
type SQLState struct {
|
type SQLState struct {
|
||||||
@ -252,7 +252,7 @@ func (s *SQLState) AddContainer(ctr *Container) (err error) {
|
|||||||
return errors.Wrapf(ErrPodExists, "cannot add container that belongs to a pod, use AddContainerToPod instead")
|
return errors.Wrapf(ErrPodExists, "cannot add container that belongs to a pod, use AddContainerToPod instead")
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.addContainer(ctr)
|
return s.addContainer(ctr, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateContainer updates a container's state from the database
|
// UpdateContainer updates a container's state from the database
|
||||||
@ -381,7 +381,7 @@ func (s *SQLState) UpdateContainer(ctr *Container) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SaveContainer updates a container's state in the database
|
// SaveContainer updates a container's state in the database
|
||||||
func (s *SQLState) SaveContainer(ctr *Container) error {
|
func (s *SQLState) SaveContainer(ctr *Container) (err error) {
|
||||||
const update = `UPDATE containerState SET
|
const update = `UPDATE containerState SET
|
||||||
State=?,
|
State=?,
|
||||||
ConfigPath=?,
|
ConfigPath=?,
|
||||||
@ -508,7 +508,7 @@ func (s *SQLState) RemoveContainer(ctr *Container) error {
|
|||||||
return errors.Wrapf(ErrPodExists, "container %s belongs to a pod, use RemoveContainerFromPod", ctr.ID())
|
return errors.Wrapf(ErrPodExists, "container %s belongs to a pod, use RemoveContainerFromPod", ctr.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.removeContainer(ctr)
|
return s.removeContainer(ctr, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllContainers retrieves all the containers presently in the state
|
// AllContainers retrieves all the containers presently in the state
|
||||||
@ -801,7 +801,7 @@ func (s *SQLState) AddPod(pod *Pod) (err error) {
|
|||||||
|
|
||||||
// RemovePod removes a pod from the state
|
// RemovePod removes a pod from the state
|
||||||
// Only empty pods can be removed
|
// Only empty pods can be removed
|
||||||
func (s *SQLState) RemovePod(pod *Pod) error {
|
func (s *SQLState) RemovePod(pod *Pod) (err error) {
|
||||||
const (
|
const (
|
||||||
removePod = "DELETE FROM pods WHERE ID=?;"
|
removePod = "DELETE FROM pods WHERE ID=?;"
|
||||||
removeRegistry = "DELETE FROM registry WHERE Id=?;"
|
removeRegistry = "DELETE FROM registry WHERE Id=?;"
|
||||||
@ -832,6 +832,7 @@ func (s *SQLState) RemovePod(pod *Pod) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error retrieving number of rows in transaction removing pod %s", pod.ID())
|
return errors.Wrapf(err, "error retrieving number of rows in transaction removing pod %s", pod.ID())
|
||||||
} else if rows == 0 {
|
} else if rows == 0 {
|
||||||
|
pod.valid = false
|
||||||
return ErrNoSuchPod
|
return ErrNoSuchPod
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -851,11 +852,11 @@ func (s *SQLState) RemovePod(pod *Pod) error {
|
|||||||
// This can avoid issues with dependencies within the pod
|
// This can avoid issues with dependencies within the pod
|
||||||
// The operation will fail if any container in the pod has a dependency from
|
// The operation will fail if any container in the pod has a dependency from
|
||||||
// outside the pod
|
// outside the pod
|
||||||
func (s *SQLState) RemovePodContainers(pod *Pod) error {
|
func (s *SQLState) RemovePodContainers(pod *Pod) (err error) {
|
||||||
const (
|
const (
|
||||||
getPodCtrs = "SELECT Id FROM containers WHERE pod=?;"
|
getPodCtrs = "SELECT Id FROM containers WHERE pod=?;"
|
||||||
removeCtr = "DELETE FROM containers WHERE pod=?;"
|
removeCtr = "DELETE FROM containers WHERE pod=?;"
|
||||||
removeCtrState = "DELETE FROM containerState WHERE ID=ANY(SELECT Id FROM containers WHERE pod=?);"
|
removeCtrState = "DELETE FROM containerState WHERE ID IN (SELECT Id FROM containers WHERE pod=?);"
|
||||||
)
|
)
|
||||||
|
|
||||||
if !s.valid {
|
if !s.valid {
|
||||||
@ -880,6 +881,16 @@ func (s *SQLState) RemovePodContainers(pod *Pod) error {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// Check if the pod exists
|
||||||
|
exists, err := podExistsTx(pod.ID(), tx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !exists {
|
||||||
|
pod.valid = false
|
||||||
|
return ErrNoSuchPod
|
||||||
|
}
|
||||||
|
|
||||||
// First get all containers in the pod
|
// First get all containers in the pod
|
||||||
rows, err := tx.Query(getPodCtrs, pod.ID())
|
rows, err := tx.Query(getPodCtrs, pod.ID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -920,7 +931,7 @@ func (s *SQLState) RemovePodContainers(pod *Pod) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := tx.Commit(); err != nil {
|
if err := tx.Commit(); err != nil {
|
||||||
return errors.Wrapf(err, "error committing transaction to add pod %s", pod.ID())
|
return errors.Wrapf(err, "error committing transaction remove pod %s containers", pod.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
committed = true
|
committed = true
|
||||||
@ -963,7 +974,7 @@ func (s *SQLState) AddContainerToPod(pod *Pod, ctr *Container) error {
|
|||||||
return errors.Wrapf(ErrInvalidArg, "container's pod ID does not match given pod's ID")
|
return errors.Wrapf(ErrInvalidArg, "container's pod ID does not match given pod's ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.addContainer(ctr)
|
return s.addContainer(ctr, pod)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveContainerFromPod removes a container from the given pod
|
// RemoveContainerFromPod removes a container from the given pod
|
||||||
@ -972,7 +983,7 @@ func (s *SQLState) RemoveContainerFromPod(pod *Pod, ctr *Container) error {
|
|||||||
return errors.Wrapf(ErrInvalidArg, "container %s is not in pod %s", ctr.ID(), pod.ID())
|
return errors.Wrapf(ErrInvalidArg, "container %s is not in pod %s", ctr.ID(), pod.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.removeContainer(ctr)
|
return s.removeContainer(ctr, pod)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllPods retrieves all pods presently in the state
|
// AllPods retrieves all pods presently in the state
|
||||||
|
@ -37,6 +37,7 @@ const (
|
|||||||
FROM containers
|
FROM containers
|
||||||
INNER JOIN
|
INNER JOIN
|
||||||
containerState ON containers.Id = containerState.Id `
|
containerState ON containers.Id = containerState.Id `
|
||||||
|
ExistsQuery = "SELECT 1 FROM pods WHERE Id=?;"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Checks that the DB configuration matches the runtime's configuration
|
// Checks that the DB configuration matches the runtime's configuration
|
||||||
@ -326,9 +327,7 @@ func prepareDB(db *sql.DB) (err error) {
|
|||||||
// Check if given pod exists
|
// Check if given pod exists
|
||||||
// Internal-only version of hasPod
|
// Internal-only version of hasPod
|
||||||
func (s *SQLState) podExists(id string) (bool, error) {
|
func (s *SQLState) podExists(id string) (bool, error) {
|
||||||
const query = "SELECT 1 FROM pods WHERE Id=?;"
|
row := s.db.QueryRow(ExistsQuery, id)
|
||||||
|
|
||||||
row := s.db.QueryRow(query, id)
|
|
||||||
|
|
||||||
var check int
|
var check int
|
||||||
err := row.Scan(&check)
|
err := row.Scan(&check)
|
||||||
@ -343,7 +342,26 @@ func (s *SQLState) podExists(id string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if given pod exists within a transaction
|
||||||
|
// Transaction-based version of podExists
|
||||||
|
func podExistsTx(id string, tx *sql.Tx) (bool, error) {
|
||||||
|
row := tx.QueryRow(ExistsQuery, id)
|
||||||
|
|
||||||
|
var check int
|
||||||
|
err := row.Scan(&check)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, errors.Wrapf(err, "error questing database for existence of pod %s", id)
|
||||||
|
} else if check != 1 {
|
||||||
|
return false, errors.Wrapf(ErrInternal, "check digit for podExists query incorrect")
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get filename for OCI spec on disk
|
// Get filename for OCI spec on disk
|
||||||
@ -717,7 +735,7 @@ func (s *SQLState) podFromScannable(row scannable) (*Pod, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Internal function for adding containers
|
// Internal function for adding containers
|
||||||
func (s *SQLState) addContainer(ctr *Container) (err error) {
|
func (s *SQLState) addContainer(ctr *Container, pod *Pod) (err error) {
|
||||||
const (
|
const (
|
||||||
addCtr = `INSERT INTO containers VALUES (
|
addCtr = `INSERT INTO containers VALUES (
|
||||||
?, ?, ?, ?, ?,
|
?, ?, ?, ?, ?,
|
||||||
@ -800,6 +818,19 @@ func (s *SQLState) addContainer(ctr *Container) (err error) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// First check if pod exists, if one is given
|
||||||
|
if pod != nil {
|
||||||
|
exists, err := podExistsTx(pod.ID(), tx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
pod.valid = false
|
||||||
|
return errors.Wrapf(ErrNoSuchPod, "pod %s does not exist in state, cannot add container to it", pod.ID())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add container to registry
|
// Add container to registry
|
||||||
if _, err := tx.Exec(addRegistry, ctr.ID(), ctr.Name()); err != nil {
|
if _, err := tx.Exec(addRegistry, ctr.ID(), ctr.Name()); err != nil {
|
||||||
return errors.Wrapf(err, "error adding container %s to name/ID registry", ctr.ID())
|
return errors.Wrapf(err, "error adding container %s to name/ID registry", ctr.ID())
|
||||||
@ -905,11 +936,13 @@ func (s *SQLState) addContainer(ctr *Container) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Internal functions for removing containers
|
// Internal functions for removing containers
|
||||||
func (s *SQLState) removeContainer(ctr *Container) error {
|
func (s *SQLState) removeContainer(ctr *Container, pod *Pod) (err error) {
|
||||||
const (
|
const (
|
||||||
removeCtr = "DELETE FROM containers WHERE Id=?;"
|
removeCtr = "DELETE FROM containers WHERE Id=?;"
|
||||||
removeState = "DELETE FROM containerState WHERE Id=?;"
|
removeState = "DELETE FROM containerState WHERE Id=?;"
|
||||||
removeRegistry = "DELETE FROM registry WHERE Id=?;"
|
removeRegistry = "DELETE FROM registry WHERE Id=?;"
|
||||||
|
existsInPod = "SELECT 1 FROM containers WHERE Id=? AND Pod=?;"
|
||||||
|
ctrExists = "SELECT 1 FROM containers WHERE Id=?;"
|
||||||
)
|
)
|
||||||
|
|
||||||
if !s.valid {
|
if !s.valid {
|
||||||
@ -930,6 +963,48 @@ func (s *SQLState) removeContainer(ctr *Container) error {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
if pod != nil {
|
||||||
|
// Check to see if the pod exists
|
||||||
|
exists, err := podExistsTx(pod.ID(), tx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
pod.valid = false
|
||||||
|
return errors.Wrapf(ErrNoSuchPod, "pod %s does not exist in state, cannot add container to it", pod.ID())
|
||||||
|
}
|
||||||
|
|
||||||
|
var check int
|
||||||
|
|
||||||
|
// Check to see if the container exists
|
||||||
|
row := tx.QueryRow(ctrExists, ctr.ID())
|
||||||
|
err = row.Scan(&check)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
ctr.valid = false
|
||||||
|
return errors.Wrapf(ErrNoSuchCtr, "container %s does not exist", ctr.ID())
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.Wrapf(err, "error querying database for container %s existence", ctr.ID())
|
||||||
|
} else if check != 1 {
|
||||||
|
return errors.Wrapf(ErrInternal, "check digit for ctr exists query incorrect")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to see if the container is in the pod
|
||||||
|
row = tx.QueryRow(existsInPod, ctr.ID(), pod.ID())
|
||||||
|
err = row.Scan(&check)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return errors.Wrapf(ErrNoSuchCtr, "container %s is not in pod %s", ctr.ID(), pod.ID())
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.Wrapf(err, "error querying database for container %s existence", ctr.ID())
|
||||||
|
} else if check != 1 {
|
||||||
|
return errors.Wrapf(ErrInternal, "check digit for ctr exists in pod query incorrect")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check rows acted on for the first transaction, verify we actually removed something
|
// Check rows acted on for the first transaction, verify we actually removed something
|
||||||
result, err := tx.Exec(removeCtr, ctr.ID())
|
result, err := tx.Exec(removeCtr, ctr.ID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -939,6 +1014,7 @@ func (s *SQLState) removeContainer(ctr *Container) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error retrieving number of rows in transaction removing container %s", ctr.ID())
|
return errors.Wrapf(err, "error retrieving number of rows in transaction removing container %s", ctr.ID())
|
||||||
} else if rows == 0 {
|
} else if rows == 0 {
|
||||||
|
ctr.valid = false
|
||||||
return ErrNoSuchCtr
|
return ErrNoSuchCtr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user