automation-tests/common/libimage/normalize.go

93 lines
2.4 KiB
Go

package libimage
import (
"strings"
"github.com/containers/image/v5/docker/reference"
"github.com/pkg/errors"
)
// NormalizeName normalizes the provided name according to the conventions by
// Podman and Buildah. If tag and digest are missing, the "latest" tag will be
// used. If it's a short name, it will be prefixed with "localhost/".
//
// References to docker.io are normalized according to the Docker conventions.
// For instance, "docker.io/foo" turns into "docker.io/library/foo".
func NormalizeName(name string) (reference.Named, error) {
// NOTE: this code is in symmetrie with containers/image/pkg/shortnames.
ref, err := reference.Parse(name)
if err != nil {
return nil, errors.Wrapf(err, "error normalizing name %q", name)
}
named, ok := ref.(reference.Named)
if !ok {
return nil, errors.Errorf("%q is not a named reference", name)
}
// Enforce "localhost" if needed.
registry := reference.Domain(named)
if !(strings.ContainsAny(registry, ".:") || registry == "localhost") {
name = toLocalImageName(ref.String())
}
// Another parse which also makes sure that docker.io references are
// correctly normalized (e.g., docker.io/alpine to
// docker.io/library/alpine).
named, err = reference.ParseNormalizedNamed(name)
if err != nil {
return nil, err
}
if _, hasTag := named.(reference.NamedTagged); hasTag {
return named, nil
}
if _, hasDigest := named.(reference.Digested); hasDigest {
return named, nil
}
// Make sure to tag "latest".
return reference.TagNameOnly(named), nil
}
// prefix the specified name with "localhost/".
func toLocalImageName(name string) string {
return "localhost/" + strings.TrimLeft(name, "/")
}
// NameTagPair represents a RepoTag of an image.
type NameTagPair struct {
// Name of the RepoTag. Maybe "<none>".
Name string
// Tag of the RepoTag. Maybe "<none>".
Tag string
// for internal use
named reference.Named
}
// ToNameTagsPairs splits repoTags into name&tag pairs.
// Guaranteed to return at least one pair.
func ToNameTagPairs(repoTags []reference.Named) ([]NameTagPair, error) {
none := "<none>"
var pairs []NameTagPair
for i, named := range repoTags {
pair := NameTagPair{
Name: named.Name(),
Tag: none,
named: repoTags[i],
}
if tagged, isTagged := named.(reference.NamedTagged); isTagged {
pair.Tag = tagged.Tag()
}
pairs = append(pairs, pair)
}
if len(pairs) == 0 {
pairs = append(pairs, NameTagPair{Name: none, Tag: none})
}
return pairs, nil
}