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] != ":") || (len(image.RepoDigests) != 0 && image.RepoDigests[0] != "@") } 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 }