mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Update rmi logic for canonical references
Updates the rmi code to treat canonical references as related to tagged references from the same repository during deletion. Canonical references with a different repository name will be treated as separate references. Updates the remove by ID logic to still remove an image if there is a single tag reference and only canonical references to the same repository remaining. Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
This commit is contained in:
parent
8f9c7fab24
commit
a281be1c11
1 changed files with 59 additions and 26 deletions
|
@ -104,27 +104,34 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I
|
||||||
|
|
||||||
repoRefs = daemon.referenceStore.References(imgID)
|
repoRefs = daemon.referenceStore.References(imgID)
|
||||||
|
|
||||||
// If this is a tag reference and all the remaining references
|
// If a tag reference was removed and the only remaining
|
||||||
// to this image are digest references, delete the remaining
|
// references to the same repository are digest references,
|
||||||
// references so that they don't prevent removal of the image.
|
// then clean up those digest references.
|
||||||
if _, isCanonical := parsedRef.(reference.Canonical); !isCanonical {
|
if _, isCanonical := parsedRef.(reference.Canonical); !isCanonical {
|
||||||
foundTagRef := false
|
foundRepoTagRef := false
|
||||||
for _, repoRef := range repoRefs {
|
for _, repoRef := range repoRefs {
|
||||||
if _, repoRefIsCanonical := repoRef.(reference.Canonical); !repoRefIsCanonical {
|
if _, repoRefIsCanonical := repoRef.(reference.Canonical); !repoRefIsCanonical && parsedRef.Name() == repoRef.Name() {
|
||||||
foundTagRef = true
|
foundRepoTagRef = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !foundTagRef {
|
if !foundRepoTagRef {
|
||||||
|
// Remove canonical references from same repository
|
||||||
|
remainingRefs := []reference.Named{}
|
||||||
for _, repoRef := range repoRefs {
|
for _, repoRef := range repoRefs {
|
||||||
if _, err := daemon.removeImageRef(repoRef); err != nil {
|
if _, repoRefIsCanonical := repoRef.(reference.Canonical); repoRefIsCanonical && parsedRef.Name() == repoRef.Name() {
|
||||||
return records, err
|
if _, err := daemon.removeImageRef(repoRef); err != nil {
|
||||||
}
|
return records, err
|
||||||
|
}
|
||||||
|
|
||||||
untaggedRecord := types.ImageDelete{Untagged: repoRef.String()}
|
untaggedRecord := types.ImageDelete{Untagged: repoRef.String()}
|
||||||
records = append(records, untaggedRecord)
|
records = append(records, untaggedRecord)
|
||||||
|
} else {
|
||||||
|
remainingRefs = append(remainingRefs, repoRef)
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
repoRefs = []reference.Named{}
|
repoRefs = remainingRefs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,11 +142,10 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I
|
||||||
|
|
||||||
removedRepositoryRef = true
|
removedRepositoryRef = true
|
||||||
} else {
|
} else {
|
||||||
// If an ID reference was given AND there is exactly one
|
// If an ID reference was given AND there is at most one tag
|
||||||
// repository reference to the image then we will want to
|
// reference to the image AND all references are within one
|
||||||
// remove that reference.
|
// repository, then remove all references.
|
||||||
// FIXME: Is this the behavior we want?
|
if isSingleReference(repoRefs) {
|
||||||
if len(repoRefs) == 1 {
|
|
||||||
c := conflictHard
|
c := conflictHard
|
||||||
if !force {
|
if !force {
|
||||||
c |= conflictSoft &^ conflictActiveReference
|
c |= conflictSoft &^ conflictActiveReference
|
||||||
|
@ -148,21 +154,48 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I
|
||||||
return nil, conflict
|
return nil, conflict
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedRef, err := daemon.removeImageRef(repoRefs[0])
|
for _, repoRef := range repoRefs {
|
||||||
if err != nil {
|
parsedRef, err := daemon.removeImageRef(repoRef)
|
||||||
return nil, err
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
untaggedRecord := types.ImageDelete{Untagged: parsedRef.String()}
|
||||||
|
|
||||||
|
daemon.LogImageEvent(imgID.String(), imgID.String(), "untag")
|
||||||
|
records = append(records, untaggedRecord)
|
||||||
}
|
}
|
||||||
|
|
||||||
untaggedRecord := types.ImageDelete{Untagged: parsedRef.String()}
|
|
||||||
|
|
||||||
daemon.LogImageEvent(imgID.String(), imgID.String(), "untag")
|
|
||||||
records = append(records, untaggedRecord)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return records, daemon.imageDeleteHelper(imgID, &records, force, prune, removedRepositoryRef)
|
return records, daemon.imageDeleteHelper(imgID, &records, force, prune, removedRepositoryRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isSingleReference returns true when all references are from one repository
|
||||||
|
// and there is at most one tag. Returns false for empty input.
|
||||||
|
func isSingleReference(repoRefs []reference.Named) bool {
|
||||||
|
if len(repoRefs) <= 1 {
|
||||||
|
return len(repoRefs) == 1
|
||||||
|
}
|
||||||
|
var singleRef reference.Named
|
||||||
|
canonicalRefs := map[string]struct{}{}
|
||||||
|
for _, repoRef := range repoRefs {
|
||||||
|
if _, isCanonical := repoRef.(reference.Canonical); isCanonical {
|
||||||
|
canonicalRefs[repoRef.Name()] = struct{}{}
|
||||||
|
} else if singleRef == nil {
|
||||||
|
singleRef = repoRef
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if singleRef == nil {
|
||||||
|
// Just use first canonical ref
|
||||||
|
singleRef = repoRefs[0]
|
||||||
|
}
|
||||||
|
_, ok := canonicalRefs[singleRef.Name()]
|
||||||
|
return len(canonicalRefs) == 1 && ok
|
||||||
|
}
|
||||||
|
|
||||||
// isImageIDPrefix returns whether the given possiblePrefix is a prefix of the
|
// isImageIDPrefix returns whether the given possiblePrefix is a prefix of the
|
||||||
// given imageID.
|
// given imageID.
|
||||||
func isImageIDPrefix(imageID, possiblePrefix string) bool {
|
func isImageIDPrefix(imageID, possiblePrefix string) bool {
|
||||||
|
|
Loading…
Add table
Reference in a new issue