mirror of https://github.com/docker/docs.git
				
				
				
			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) (cherry picked from commit a281be1c11d61deed7cb2853125e6d489f16aa2e)
This commit is contained in:
		
							parent
							
								
									8a93ff1ffb
								
							
						
					
					
						commit
						611bbed2df
					
				| 
						 | 
				
			
			@ -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 _, err := daemon.removeImageRef(repoRef); err != nil {
 | 
			
		||||
						return records, err
 | 
			
		||||
					}
 | 
			
		||||
					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)
 | 
			
		||||
						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,21 +154,48 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I
 | 
			
		|||
				return nil, conflict
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			parsedRef, err := daemon.removeImageRef(repoRefs[0])
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			for _, repoRef := range repoRefs {
 | 
			
		||||
				parsedRef, err := daemon.removeImageRef(repoRef)
 | 
			
		||||
				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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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…
	
		Reference in New Issue