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)
|
||||
|
||||
// If this is a tag reference and all the remaining references
|
||||
// to this image are digest references, delete the remaining
|
||||
// references so that they don't prevent removal of the image.
|
||||
// If a tag reference was removed and the only remaining
|
||||
// references to the same repository are digest references,
|
||||
// then clean up those digest references.
|
||||
if _, isCanonical := parsedRef.(reference.Canonical); !isCanonical {
|
||||
foundTagRef := false
|
||||
foundRepoTagRef := false
|
||||
for _, repoRef := range repoRefs {
|
||||
if _, repoRefIsCanonical := repoRef.(reference.Canonical); !repoRefIsCanonical {
|
||||
foundTagRef = true
|
||||
if _, repoRefIsCanonical := repoRef.(reference.Canonical); !repoRefIsCanonical && parsedRef.Name() == repoRef.Name() {
|
||||
foundRepoTagRef = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundTagRef {
|
||||
if !foundRepoTagRef {
|
||||
// Remove canonical references from same repository
|
||||
remainingRefs := []reference.Named{}
|
||||
for _, repoRef := range repoRefs {
|
||||
if _, repoRefIsCanonical := repoRef.(reference.Canonical); repoRefIsCanonical && parsedRef.Name() == repoRef.Name() {
|
||||
if _, err := daemon.removeImageRef(repoRef); err != nil {
|
||||
return records, err
|
||||
}
|
||||
|
||||
untaggedRecord := types.ImageDelete{Untagged: repoRef.String()}
|
||||
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
|
||||
} else {
|
||||
// If an ID reference was given AND there is exactly one
|
||||
// repository reference to the image then we will want to
|
||||
// remove that reference.
|
||||
// FIXME: Is this the behavior we want?
|
||||
if len(repoRefs) == 1 {
|
||||
// If an ID reference was given AND there is at most one tag
|
||||
// reference to the image AND all references are within one
|
||||
// repository, then remove all references.
|
||||
if isSingleReference(repoRefs) {
|
||||
c := conflictHard
|
||||
if !force {
|
||||
c |= conflictSoft &^ conflictActiveReference
|
||||
|
@ -148,7 +154,8 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I
|
|||
return nil, conflict
|
||||
}
|
||||
|
||||
parsedRef, err := daemon.removeImageRef(repoRefs[0])
|
||||
for _, repoRef := range repoRefs {
|
||||
parsedRef, err := daemon.removeImageRef(repoRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -159,10 +166,36 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I
|
|||
records = append(records, untaggedRecord)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// given imageID.
|
||||
func isImageIDPrefix(imageID, possiblePrefix string) bool {
|
||||
|
|
Loading…
Add table
Reference in a new issue