Merge pull request #19266 from tonistiigi/fix-untag-on-rmi-by-id

Fix rmi by ID untagging image on error
This commit is contained in:
Tibor Vass 2016-01-12 18:56:25 -05:00
commit 1e1a3c9508
2 changed files with 26 additions and 5 deletions

View File

@ -128,6 +128,10 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I
// remove that reference.
// FIXME: Is this the behavior we want?
if len(repoRefs) == 1 {
if conflict := daemon.checkImageDeleteConflict(imgID, force, true); conflict != nil {
return nil, conflict
}
parsedRef, err := daemon.removeImageRef(repoRefs[0])
if err != nil {
return nil, err
@ -241,7 +245,7 @@ func (idc *imageDeleteConflict) Error() string {
func (daemon *Daemon) imageDeleteHelper(imgID image.ID, records *[]types.ImageDelete, force, prune, quiet bool) error {
// First, determine if this image has any conflicts. Ignore soft conflicts
// if force is true.
if conflict := daemon.checkImageDeleteConflict(imgID, force); conflict != nil {
if conflict := daemon.checkImageDeleteConflict(imgID, force, false); conflict != nil {
if quiet && (!daemon.imageIsDangling(imgID) || conflict.used) {
// Ignore conflicts UNLESS the image is "dangling" or not being used in
// which case we want the user to know.
@ -293,7 +297,7 @@ func (daemon *Daemon) imageDeleteHelper(imgID image.ID, records *[]types.ImageDe
// using the image. A soft conflict is any tags/digest referencing the given
// image or any stopped container using the image. If ignoreSoftConflicts is
// true, this function will not check for soft conflict conditions.
func (daemon *Daemon) checkImageDeleteConflict(imgID image.ID, ignoreSoftConflicts bool) *imageDeleteConflict {
func (daemon *Daemon) checkImageDeleteConflict(imgID image.ID, ignoreSoftConflicts bool, ignoreRefConflict bool) *imageDeleteConflict {
// Check for hard conflicts first.
if conflict := daemon.checkImageDeleteHardConflict(imgID); conflict != nil {
return conflict
@ -305,7 +309,7 @@ func (daemon *Daemon) checkImageDeleteConflict(imgID image.ID, ignoreSoftConflic
return nil
}
return daemon.checkImageDeleteSoftConflict(imgID)
return daemon.checkImageDeleteSoftConflict(imgID, ignoreRefConflict)
}
func (daemon *Daemon) checkImageDeleteHardConflict(imgID image.ID) *imageDeleteConflict {
@ -338,9 +342,9 @@ func (daemon *Daemon) checkImageDeleteHardConflict(imgID image.ID) *imageDeleteC
return nil
}
func (daemon *Daemon) checkImageDeleteSoftConflict(imgID image.ID) *imageDeleteConflict {
func (daemon *Daemon) checkImageDeleteSoftConflict(imgID image.ID, ignoreRefConflict bool) *imageDeleteConflict {
// Check if any repository tags/digest reference this image.
if len(daemon.referenceStore.References(imgID)) > 0 {
if !ignoreRefConflict && len(daemon.referenceStore.References(imgID)) > 0 {
return &imageDeleteConflict{
imgID: imgID,
message: "image is referenced in one or more repositories",

View File

@ -337,3 +337,20 @@ func (s *DockerSuite) TestRmiWithParentInUse(c *check.C) {
dockerCmd(c, "rmi", imageID)
}
// #18873
func (s *DockerSuite) TestRmiByIDHardConflict(c *check.C) {
testRequires(c, DaemonIsLinux)
dockerCmd(c, "create", "busybox")
imgID, err := inspectField("busybox:latest", "Id")
c.Assert(err, checker.IsNil)
_, _, err = dockerCmdWithError("rmi", imgID[:12])
c.Assert(err, checker.NotNil)
// check that tag was not removed
imgID2, err := inspectField("busybox:latest", "Id")
c.Assert(err, checker.IsNil)
c.Assert(imgID, checker.Equals, imgID2)
}