mirror of https://github.com/docker/docs.git
123 lines
3.1 KiB
Go
123 lines
3.1 KiB
Go
package cluster
|
|
|
|
import (
|
|
"strings"
|
|
|
|
dockerfilters "github.com/docker/engine-api/types/filters"
|
|
"github.com/samalba/dockerclient"
|
|
)
|
|
|
|
// Image is exported
|
|
type Image struct {
|
|
dockerclient.Image
|
|
|
|
Engine *Engine
|
|
}
|
|
|
|
// ParseRepositoryTag gets a repos name and returns the right reposName + tag|digest
|
|
// The tag can be confusing because of a port in a repository name.
|
|
// Ex: localhost.localdomain:5000/samalba/hipache:latest
|
|
// Digest ex: localhost:5000/foo/bar@sha256:bc8813ea7b3603864987522f02a76101c17ad122e1c46d790efc0fca78ca7bfb
|
|
func ParseRepositoryTag(repos string) (string, string) {
|
|
n := strings.Index(repos, "@")
|
|
if n >= 0 {
|
|
parts := strings.Split(repos, "@")
|
|
return parts[0], parts[1]
|
|
}
|
|
n = strings.LastIndex(repos, ":")
|
|
if n < 0 {
|
|
return repos, ""
|
|
}
|
|
if tag := repos[n+1:]; !strings.Contains(tag, "/") {
|
|
return repos[:n], tag
|
|
}
|
|
return repos, ""
|
|
}
|
|
|
|
// Match is exported
|
|
func (image *Image) Match(IDOrName string, matchTag bool) bool {
|
|
size := len(IDOrName)
|
|
|
|
// TODO: prefix match can cause false positives with image names
|
|
if image.Id == IDOrName || (size > 2 && strings.HasPrefix(image.Id, IDOrName)) {
|
|
return true
|
|
}
|
|
|
|
repoName, tag := ParseRepositoryTag(IDOrName)
|
|
|
|
// match repotag
|
|
for _, imageRepoTag := range image.RepoTags {
|
|
imageRepoName, imageTag := ParseRepositoryTag(imageRepoTag)
|
|
|
|
if matchTag == false && imageRepoName == repoName {
|
|
return true
|
|
}
|
|
if imageRepoName == repoName && (imageTag == tag || tag == "") {
|
|
return true
|
|
}
|
|
}
|
|
|
|
// match repodigests
|
|
for _, imageDigest := range image.RepoDigests {
|
|
imageRepoName, imageDigest := ParseRepositoryTag(imageDigest)
|
|
|
|
if matchTag == false && imageRepoName == repoName {
|
|
return true
|
|
}
|
|
if imageRepoName == repoName && (imageDigest == tag || tag == "") {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// ImageFilterOptions are the set of filtering options supported by
|
|
// Images.Filter()
|
|
type ImageFilterOptions struct {
|
|
All bool
|
|
NameFilter string
|
|
Filters dockerfilters.Args
|
|
}
|
|
|
|
// Images is a collection of Image objects that can be filtered
|
|
type Images []*Image
|
|
|
|
// Filter returns a new sequence of Images filtered to only the images that
|
|
// matched the filtering paramters
|
|
func (images Images) Filter(opts ImageFilterOptions) Images {
|
|
includeAll := func(image *Image) bool {
|
|
// TODO: this is wrong if RepoTags == []
|
|
return opts.All ||
|
|
(len(image.RepoTags) != 0 && image.RepoTags[0] != "<none>:<none>") ||
|
|
(len(image.RepoDigests) != 0 && image.RepoDigests[0] != "<none>@<none>")
|
|
}
|
|
|
|
includeFilter := func(image *Image) bool {
|
|
if opts.Filters.Len() == 0 {
|
|
return true
|
|
}
|
|
return opts.Filters.MatchKVList("label", image.Labels)
|
|
}
|
|
|
|
includeRepoFilter := func(image *Image) bool {
|
|
if opts.NameFilter == "" {
|
|
return true
|
|
}
|
|
for _, repoTag := range image.RepoTags {
|
|
repoName, _ := ParseRepositoryTag(repoTag)
|
|
if repoTag == opts.NameFilter || repoName == opts.NameFilter {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
filtered := make([]*Image, 0, len(images))
|
|
for _, image := range images {
|
|
if includeAll(image) && includeFilter(image) && includeRepoFilter(image) {
|
|
filtered = append(filtered, image)
|
|
}
|
|
}
|
|
return filtered
|
|
}
|