From 7f429e0cebf9f7d0b203191646f2afa7b4bee35b Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Fri, 11 Oct 2013 19:27:04 -0700 Subject: [PATCH] Do not allow image to be deleted when containers are dependent --- server.go | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/server.go b/server.go index 30025fcaae..45d8bbf9cf 100644 --- a/server.go +++ b/server.go @@ -996,6 +996,14 @@ func (srv *Server) ContainerDestroy(name string, removeVolume bool) error { var ErrImageReferenced = errors.New("Image referenced by a repository") +func (srv *Server) getChildImages(id string) ([]*Image, error) { + byParents, err := srv.runtime.graph.ByParent() + if err != nil { + return nil, err + } + return byParents[id], nil +} + func (srv *Server) deleteImageAndChildren(id string, imgs *[]APIRmi) error { // If the image is referenced by a repo, do not delete if len(srv.runtime.repositories.ByID()[id]) != 0 { @@ -1101,6 +1109,33 @@ func (srv *Server) ImageDelete(name string, autoPrune bool) ([]APIRmi, error) { if err != nil { return nil, fmt.Errorf("No such image: %s", name) } + images := make(map[string]bool) + images[img.ID] = true + + children, err := srv.getChildImages(img.ID) + if err != nil { + return nil, err + } + + for _, i := range children { + images[i.ID] = true + } + + // Check for any containers referencing the image or children of the image + referencedContainers := []string{} + + for e := srv.runtime.containers.Front(); e != nil; e = e.Next() { + c := e.Value.(*Container) + if images[c.Image] { + referencedContainers = append(referencedContainers, c.ID) + } + } + + if len(referencedContainers) > 0 { + return nil, fmt.Errorf("Cannot delete image with existing containers. Please remove %s before deleting image.", + strings.Join(referencedContainers, ", ")) + } + if !autoPrune { if err := srv.runtime.DeleteImage(img.ID); err != nil { return nil, fmt.Errorf("Error deleting image %s: %s", name, err)