We are mistakenly seeing repos as registries.

Currently `podman pull rhel7/rhel-tools` is failing because it
sees rhel7 as a registry.  This change will verify that the returned
registry from the parser is actually a registry and not a repo,
if a repo it will return the correct content, and we will pull the image.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>

Closes: #1387
Approved by: mtrmac
This commit is contained in:
Daniel J Walsh 2018-08-31 07:38:59 -04:00 committed by Atomic Bot
parent 294c3f4cab
commit a917f8fa2a
4 changed files with 29 additions and 18 deletions

View File

@ -221,7 +221,7 @@ func TestNormalizeTag(t *testing.T) {
{"example.com/busybox" + digestSuffix, "example.com/busybox" + digestSuffix + ":none"}, // Qualified name@digest; FIXME: The result is not even syntactically valid! {"example.com/busybox" + digestSuffix, "example.com/busybox" + digestSuffix + ":none"}, // Qualified name@digest; FIXME: The result is not even syntactically valid!
{"example.com/busybox:notlatest" + digestSuffix, "example.com/busybox:notlatest" + digestSuffix}, // Qualified name:tag@digest {"example.com/busybox:notlatest" + digestSuffix, "example.com/busybox:notlatest" + digestSuffix}, // Qualified name:tag@digest
{"busybox:latest", "localhost/busybox:latest"}, // Unqualified name-only {"busybox:latest", "localhost/busybox:latest"}, // Unqualified name-only
{"ns/busybox:latest", "ns/busybox:latest"}, // Unqualified with a dot-less namespace FIXME: "ns" is treated as a registry {"ns/busybox:latest", "localhost/ns/busybox:latest"}, // Unqualified with a dot-less namespace
} { } {
res, err := normalizeTag(c.input) res, err := normalizeTag(c.input)
if c.expected == "" { if c.expected == "" {

View File

@ -2,6 +2,7 @@ package image
import ( import (
"fmt" "fmt"
"strings"
"github.com/containers/image/docker/reference" "github.com/containers/image/docker/reference"
) )
@ -16,6 +17,11 @@ type imageParts struct {
hasRegistry bool hasRegistry bool
} }
// Registries must contain a ":" or a "." or be localhost
func isRegistry(name string) bool {
return strings.ContainsAny(name, ".:") || name == "localhost"
}
// decompose breaks an input name into an imageParts description // decompose breaks an input name into an imageParts description
func decompose(input string) (imageParts, error) { func decompose(input string) (imageParts, error) {
var ( var (
@ -37,10 +43,16 @@ func decompose(input string) (imageParts, error) {
tag = ntag.Tag() tag = ntag.Tag()
} }
registry := reference.Domain(imgRef.(reference.Named)) registry := reference.Domain(imgRef.(reference.Named))
if registry != "" {
hasRegistry = true
}
imageName := reference.Path(imgRef.(reference.Named)) imageName := reference.Path(imgRef.(reference.Named))
// Is this a registry or a repo?
if isRegistry(registry) {
hasRegistry = true
} else {
if registry != "" {
imageName = registry + "/" + imageName
registry = ""
}
}
return imageParts{ return imageParts{
registry: registry, registry: registry,
hasRegistry: hasRegistry, hasRegistry: hasRegistry,
@ -53,10 +65,15 @@ func decompose(input string) (imageParts, error) {
// assemble concatenates an image's parts into a string // assemble concatenates an image's parts into a string
func (ip *imageParts) assemble() string { func (ip *imageParts) assemble() string {
return fmt.Sprintf("%s/%s:%s", ip.registry, ip.name, ip.tag) spec := fmt.Sprintf("%s:%s", ip.name, ip.tag)
if ip.registry != "" {
spec = fmt.Sprintf("%s/%s", ip.registry, spec)
}
return spec
} }
// assemble concatenates an image's parts with transport into a string // assemble concatenates an image's parts with transport into a string
func (ip *imageParts) assembleWithTransport() string { func (ip *imageParts) assembleWithTransport() string {
return fmt.Sprintf("%s%s/%s:%s", ip.transport, ip.registry, ip.name, ip.tag) return fmt.Sprintf("%s%s", ip.transport, ip.assemble())
} }

View File

@ -27,12 +27,10 @@ func TestDecompose(t *testing.T) {
}, },
{ // Unqualified single-name input { // Unqualified single-name input
"busybox", "docker://", "", "busybox", "latest", false, false, "busybox", "docker://", "", "busybox", "latest", false, false,
// FIXME? The [empty]/busybox syntax is surprising. "busybox:latest", "docker://busybox:latest",
"/busybox:latest", "docker:///busybox:latest",
}, },
{ // Unqualified namespaced input { // Unqualified namespaced input
// FIXME: .registry == "ns" !! "ns/busybox", "docker://", "", "ns/busybox", "latest", false, false,
"ns/busybox", "docker://", "ns", "busybox", "latest", false, true,
"ns/busybox:latest", "docker://ns/busybox:latest", "ns/busybox:latest", "docker://ns/busybox:latest",
}, },
{ // name:tag { // name:tag

View File

@ -98,9 +98,8 @@ func TestGetPullRefPair(t *testing.T) {
"example.com/from-directory" + digestSuffix, "example.com/from-directory" + digestSuffix, "example.com/from-directory" + digestSuffix, "example.com/from-directory" + digestSuffix,
}, },
{ // ns/name:tag, no registry: { // ns/name:tag, no registry:
// FIXME: This is interpreted as "registry == ns"
"dir:/dev/this-does-not-exist", "ns/from-directory:notlatest", "dir:/dev/this-does-not-exist", "ns/from-directory:notlatest",
"ns/from-directory:notlatest", "docker.io/ns/from-directory:notlatest", "localhost/ns/from-directory:notlatest", "localhost/ns/from-directory:notlatest",
}, },
{ // containers-storage image ID { // containers-storage image ID
"dir:/dev/this-does-not-exist", imageID, "dir:/dev/this-does-not-exist", imageID,
@ -218,9 +217,8 @@ func TestPullGoalFromImageReference(t *testing.T) {
false, false,
}, },
{ // Relative path, multiple elements. { // Relative path, multiple elements.
// FIXME: This does not add localhost/, so dstName is normalized to docker.io/testdata.
"dir:testdata/this-does-not-exist", "dir:testdata/this-does-not-exist",
[]expected{{"testdata/this-does-not-exist", "docker.io/testdata/this-does-not-exist:latest"}}, []expected{{"localhost/testdata/this-does-not-exist:latest", "localhost/testdata/this-does-not-exist:latest"}},
false, false,
}, },
@ -343,12 +341,10 @@ func TestPullGoalFromPossiblyUnqualifiedName(t *testing.T) {
}, },
{ // Unqualified, namespaced, name-only { // Unqualified, namespaced, name-only
"ns/busybox", "ns/busybox",
// FIXME: This is interpreted as "registry == ns", and actual pull happens from docker.io/ns/busybox:latest;
// example.com should be first in the list but isn't used at all.
[]pullRefStrings{ []pullRefStrings{
{"ns/busybox", "docker://ns/busybox:latest", "docker.io/ns/busybox:latest"}, {"example.com/ns/busybox:latest", "docker://example.com/ns/busybox:latest", "example.com/ns/busybox:latest"},
}, },
false, true,
}, },
{ // Unqualified, name:tag { // Unqualified, name:tag
"busybox:notlatest", "busybox:notlatest",