Browse code

Not every registry has library

Add 'library/' prefix only for images belonging to Docker Hub.

Signed-off-by: Michal Minar <miminar@redhat.com>

Michal Minar authored on 2016/01/20 17:44:26
Showing 5 changed files
... ...
@@ -21,12 +21,6 @@ import (
21 21
 	imageapi "github.com/openshift/origin/pkg/image/api"
22 22
 )
23 23
 
24
-const (
25
-	publicV1DockerHubHost = "index.docker.io"
26
-	// TODO: is there a better URL?
27
-	publicV2DockerHubHost = "registry-1.docker.io"
28
-)
29
-
30 24
 type Image struct {
31 25
 	docker.Image
32 26
 
... ...
@@ -40,16 +34,17 @@ type Client interface {
40 40
 	Connect(registry string, allowInsecure bool) (Connection, error)
41 41
 }
42 42
 
43
-// Connection allows you to retrieve data from a Docker V1 registry.
43
+// Connection allows you to retrieve data from a Docker V1/V2 registry.
44 44
 type Connection interface {
45
-	// ImageTags will return a map of the tags for the image by namespace (if not
46
-	// specified, will be "library") and name.
45
+	// ImageTags will return a map of the tags for the image by namespace and name.
46
+	// If namespace is not specified, will default to "library" for Docker hub.
47 47
 	ImageTags(namespace, name string) (map[string]string, error)
48
-	// ImageByID will return the requested image by namespace (if not specified,
49
-	// will be "library"), name, and ID.
48
+	// ImageByID will return the requested image by namespace, name, and ID.
49
+	// If namespace is not specified, will default to "library" for Docker hub.
50 50
 	ImageByID(namespace, name, id string) (*Image, error)
51
-	// ImageByTag will return the requested image by namespace (if not specified,
52
-	// will be "library"), name, and tag (if not specified, "latest").
51
+	// ImageByTag will return the requested image by namespace, name, and tag
52
+	// (if not specified, "latest").
53
+	// If namespace is not specified, will default to "library" for Docker hub.
53 54
 	ImageByTag(namespace, name, tag string) (*Image, error)
54 55
 }
55 56
 
... ...
@@ -91,11 +86,11 @@ func (c *client) Connect(name string, allowInsecure bool) (Connection, error) {
91 91
 // segment and docker API version.
92 92
 func normalizeDockerHubHost(host string, v2 bool) string {
93 93
 	switch host {
94
-	case "docker.io", "www.docker.io", publicV1DockerHubHost, publicV2DockerHubHost:
94
+	case imageapi.DockerDefaultRegistry, "www." + imageapi.DockerDefaultRegistry, imageapi.DockerDefaultV1Registry, imageapi.DockerDefaultV2Registry:
95 95
 		if v2 {
96
-			return publicV2DockerHubHost
96
+			return imageapi.DockerDefaultV2Registry
97 97
 		}
98
-		return publicV1DockerHubHost
98
+		return imageapi.DockerDefaultV1Registry
99 99
 	}
100 100
 	return host
101 101
 }
... ...
@@ -105,7 +100,7 @@ func normalizeDockerHubHost(host string, v2 bool) string {
105 105
 func normalizeRegistryName(name string) (*url.URL, error) {
106 106
 	prefix := name
107 107
 	if len(prefix) == 0 {
108
-		prefix = publicV1DockerHubHost
108
+		prefix = imageapi.DockerDefaultV1Registry
109 109
 	}
110 110
 	hadPrefix := false
111 111
 	switch {
... ...
@@ -209,7 +204,7 @@ func newConnection(url url.URL, dialTimeout time.Duration, allowInsecure, enable
209 209
 
210 210
 // ImageTags returns the tags for the named Docker image repository.
211 211
 func (c *connection) ImageTags(namespace, name string) (map[string]string, error) {
212
-	if len(namespace) == 0 {
212
+	if len(namespace) == 0 && imageapi.IsRegistryDockerHub(c.url.Host) {
213 213
 		namespace = imageapi.DockerDefaultNamespace
214 214
 	}
215 215
 	if len(name) == 0 {
... ...
@@ -226,7 +221,7 @@ func (c *connection) ImageTags(namespace, name string) (map[string]string, error
226 226
 
227 227
 // ImageByID returns the specified image within the named Docker image repository
228 228
 func (c *connection) ImageByID(namespace, name, imageID string) (*Image, error) {
229
-	if len(namespace) == 0 {
229
+	if len(namespace) == 0 && imageapi.IsRegistryDockerHub(c.url.Host) {
230 230
 		namespace = imageapi.DockerDefaultNamespace
231 231
 	}
232 232
 	if len(name) == 0 {
... ...
@@ -243,7 +238,7 @@ func (c *connection) ImageByID(namespace, name, imageID string) (*Image, error)
243 243
 
244 244
 // ImageByTag returns the specified image within the named Docker image repository
245 245
 func (c *connection) ImageByTag(namespace, name, tag string) (*Image, error) {
246
-	if len(namespace) == 0 {
246
+	if len(namespace) == 0 && imageapi.IsRegistryDockerHub(c.url.Host) {
247 247
 		namespace = imageapi.DockerDefaultNamespace
248 248
 	}
249 249
 	if len(name) == 0 {
... ...
@@ -18,6 +18,10 @@ const (
18 18
 	DockerDefaultNamespace = "library"
19 19
 	// DockerDefaultRegistry is the value for the registry when none was provided.
20 20
 	DockerDefaultRegistry = "docker.io"
21
+	// DockerDefaultV1Registry is the host name of the default v1 registry
22
+	DockerDefaultV1Registry = "index." + DockerDefaultRegistry
23
+	// DockerDefaultV2Registry is the host name of the default v2 registry
24
+	DockerDefaultV2Registry = "registry-1." + DockerDefaultRegistry
21 25
 )
22 26
 
23 27
 // TODO remove (base, tag, id)
... ...
@@ -47,6 +51,17 @@ func isRegistryName(str string) bool {
47 47
 	return false
48 48
 }
49 49
 
50
+// IsRegistryDockerHub returns true if the given registry name belongs to
51
+// Docker hub.
52
+func IsRegistryDockerHub(registry string) bool {
53
+	switch registry {
54
+	case DockerDefaultRegistry, DockerDefaultV1Registry, DockerDefaultV2Registry:
55
+		return true
56
+	default:
57
+		return false
58
+	}
59
+}
60
+
50 61
 // ParseDockerImageReference parses a Docker pull spec string into a
51 62
 // DockerImageReference.
52 63
 func ParseDockerImageReference(spec string) (DockerImageReference, error) {
... ...
@@ -60,8 +75,9 @@ func ParseDockerImageReference(spec string) (DockerImageReference, error) {
60 60
 		if isRegistryName(repoParts[0]) {
61 61
 			// registry/name
62 62
 			ref.Registry = repoParts[0]
63
-			// TODO: default this in all cases where Namespace ends up as ""?
64
-			ref.Namespace = DockerDefaultNamespace
63
+			if IsRegistryDockerHub(ref.Registry) {
64
+				ref.Namespace = DockerDefaultNamespace
65
+			}
65 66
 			if len(repoParts[1]) == 0 {
66 67
 				return ref, fmt.Errorf("the docker pull spec %q must be two or three segments separated by slashes", spec)
67 68
 			}
... ...
@@ -117,12 +133,12 @@ func (r DockerImageReference) Equal(other DockerImageReference) bool {
117 117
 
118 118
 // DockerClientDefaults sets the default values used by the Docker client.
119 119
 func (r DockerImageReference) DockerClientDefaults() DockerImageReference {
120
-	if len(r.Namespace) == 0 {
121
-		r.Namespace = DockerDefaultNamespace
122
-	}
123 120
 	if len(r.Registry) == 0 {
124 121
 		r.Registry = DockerDefaultRegistry
125 122
 	}
123
+	if len(r.Namespace) == 0 && IsRegistryDockerHub(r.Registry) {
124
+		r.Namespace = DockerDefaultNamespace
125
+	}
126 126
 	if len(r.Tag) == 0 {
127 127
 		r.Tag = DefaultImageTag
128 128
 	}
... ...
@@ -150,8 +166,8 @@ func (r DockerImageReference) DaemonMinimal() DockerImageReference {
150 150
 		r.Namespace = ""
151 151
 	}
152 152
 	switch r.Registry {
153
-	case "index.docker.io", "docker.io":
154
-		r.Registry = "docker.io"
153
+	case DockerDefaultV1Registry, DockerDefaultV2Registry:
154
+		r.Registry = DockerDefaultRegistry
155 155
 	}
156 156
 	return r.Minimal()
157 157
 }
... ...
@@ -198,7 +214,7 @@ func (r DockerImageReference) Exact() string {
198 198
 // String converts a DockerImageReference to a Docker pull spec (which implies a default namespace
199 199
 // according to V1 Docker registry rules). Use Exact() if you want no defaulting.
200 200
 func (r DockerImageReference) String() string {
201
-	if len(r.Namespace) == 0 {
201
+	if len(r.Namespace) == 0 && IsRegistryDockerHub(r.Registry) {
202 202
 		r.Namespace = DockerDefaultNamespace
203 203
 	}
204 204
 	return r.Exact()
... ...
@@ -56,6 +56,12 @@ func TestParseDockerImageReference(t *testing.T) {
56 56
 			Name:      "baz",
57 57
 		},
58 58
 		{
59
+			From:      "bar/library/baz",
60
+			Registry:  "bar",
61
+			Namespace: "library",
62
+			Name:      "baz",
63
+		},
64
+		{
59 65
 			From:      "bar/foo/baz:tag",
60 66
 			Registry:  "bar",
61 67
 			Namespace: "foo",
... ...
@@ -76,12 +82,17 @@ func TestParseDockerImageReference(t *testing.T) {
76 76
 			Name:      "baz",
77 77
 		},
78 78
 		{
79
-			From:      "bar:5000/baz",
79
+			From:      "bar:5000/library/baz",
80 80
 			Registry:  "bar:5000",
81
-			Namespace: DockerDefaultNamespace,
81
+			Namespace: "library",
82 82
 			Name:      "baz",
83 83
 		},
84 84
 		{
85
+			From:     "bar:5000/baz",
86
+			Registry: "bar:5000",
87
+			Name:     "baz",
88
+		},
89
+		{
85 90
 			From:      "bar:5000/foo/baz:tag",
86 91
 			Registry:  "bar:5000",
87 92
 			Namespace: "foo",
... ...
@@ -96,14 +107,36 @@ func TestParseDockerImageReference(t *testing.T) {
96 96
 			ID:        "sha256:3c87c572822935df60f0f5d3665bd376841a7fcfeb806b5f212de6a00e9a7b25",
97 97
 		},
98 98
 		{
99
-			From:      "myregistry.io/foo",
100
-			Registry:  "myregistry.io",
99
+			From:     "myregistry.io/foo",
100
+			Registry: "myregistry.io",
101
+			Name:     "foo",
102
+		},
103
+		{
104
+			From:     "localhost/bar",
105
+			Registry: "localhost",
106
+			Name:     "bar",
107
+		},
108
+		{
109
+			From:      "docker.io/library/myapp",
110
+			Registry:  "docker.io",
111
+			Namespace: "library",
112
+			Name:      "myapp",
113
+		},
114
+		{
115
+			From:      "docker.io/myapp",
116
+			Registry:  "docker.io",
101 117
 			Namespace: DockerDefaultNamespace,
102
-			Name:      "foo",
118
+			Name:      "myapp",
103 119
 		},
104 120
 		{
105
-			From:      "localhost/bar",
106
-			Registry:  "localhost",
121
+			From:      "docker.io/user/myapp",
122
+			Registry:  "docker.io",
123
+			Namespace: "user",
124
+			Name:      "myapp",
125
+		},
126
+		{
127
+			From:      "index.docker.io/bar",
128
+			Registry:  "index.docker.io",
107 129
 			Namespace: DockerDefaultNamespace,
108 130
 			Name:      "bar",
109 131
 		},
... ...
@@ -238,22 +271,22 @@ func TestDockerImageReferenceString(t *testing.T) {
238 238
 	}{
239 239
 		{
240 240
 			Name:     "foo",
241
-			Expected: "library/foo",
241
+			Expected: "foo",
242 242
 		},
243 243
 		{
244 244
 			Name:     "foo",
245 245
 			Tag:      "tag",
246
-			Expected: "library/foo:tag",
246
+			Expected: "foo:tag",
247 247
 		},
248 248
 		{
249 249
 			Name:     "foo",
250 250
 			ID:       "sha256:3c87c572822935df60f0f5d3665bd376841a7fcfeb806b5f212de6a00e9a7b25",
251
-			Expected: "library/foo@sha256:3c87c572822935df60f0f5d3665bd376841a7fcfeb806b5f212de6a00e9a7b25",
251
+			Expected: "foo@sha256:3c87c572822935df60f0f5d3665bd376841a7fcfeb806b5f212de6a00e9a7b25",
252 252
 		},
253 253
 		{
254 254
 			Name:     "foo",
255 255
 			ID:       "3c87c572822935df60f0f5d3665bd376841a7fcfeb806b5f212de6a00e9a7b25",
256
-			Expected: "library/foo:3c87c572822935df60f0f5d3665bd376841a7fcfeb806b5f212de6a00e9a7b25",
256
+			Expected: "foo:3c87c572822935df60f0f5d3665bd376841a7fcfeb806b5f212de6a00e9a7b25",
257 257
 		},
258 258
 		{
259 259
 			Namespace: "bar",
... ...
@@ -307,11 +340,36 @@ func TestDockerImageReferenceString(t *testing.T) {
307 307
 		},
308 308
 		{
309 309
 			Registry:  "bar:5000",
310
+			Namespace: "library",
311
+			Name:      "baz",
312
+			Tag:       "tag",
313
+			Expected:  "bar:5000/library/baz:tag",
314
+		},
315
+		{
316
+			Registry:  "bar:5000",
310 317
 			Namespace: "foo",
311 318
 			Name:      "baz",
312 319
 			ID:        "sha256:3c87c572822935df60f0f5d3665bd376841a7fcfeb806b5f212de6a00e9a7b25",
313 320
 			Expected:  "bar:5000/foo/baz@sha256:3c87c572822935df60f0f5d3665bd376841a7fcfeb806b5f212de6a00e9a7b25",
314 321
 		},
322
+		{
323
+			Registry:  "docker.io",
324
+			Namespace: "user",
325
+			Name:      "app",
326
+			Expected:  "docker.io/user/app",
327
+		},
328
+		{
329
+			Registry: "index.docker.io",
330
+			Name:     "foo",
331
+			Expected: "index.docker.io/library/foo",
332
+		},
333
+		{
334
+			Registry:  "index.docker.io",
335
+			Namespace: "library",
336
+			Name:      "bar",
337
+			ID:        "sha256:3c87c572822935df60f0f5d3665bd376841a7fcfeb806b5f212de6a00e9a7b25",
338
+			Expected:  "index.docker.io/library/bar@sha256:3c87c572822935df60f0f5d3665bd376841a7fcfeb806b5f212de6a00e9a7b25",
339
+		},
315 340
 	}
316 341
 
317 342
 	for i, testCase := range testCases {
... ...
@@ -36,7 +36,7 @@ os::cmd::expect_success 'oc delete is/binary-test bc/binary-test'
36 36
 
37 37
 # Build from Dockerfile with output to DockerImage
38 38
 os::cmd::expect_success "oc new-build -D \$'FROM openshift/origin:v1.1' --to-docker"
39
-os::cmd::expect_success_and_text "oc get bc/origin --template '${template}'" '^DockerImage library/origin:latest$'
39
+os::cmd::expect_success_and_text "oc get bc/origin --template '${template}'" '^DockerImage origin:latest$'
40 40
 
41 41
 os::cmd::expect_success 'oc delete is/origin'
42 42
 
... ...
@@ -15,13 +15,13 @@ os::cmd::expect_success_and_text 'oc new-app library/php mysql -o yaml' '3306'
15 15
 os::cmd::expect_success_and_text 'oc new-app library/php mysql --dry-run' "Image \"mysql\" runs as the 'root' user which may not be permitted by your cluster administrator"
16 16
 os::cmd::expect_failure 'oc new-app unknownhubimage -o yaml'
17 17
 # verify we can generate a Docker image based component "mongodb" directly
18
-os::cmd::expect_success_and_text 'oc new-app mongo -o yaml' 'library/mongo'
18
+os::cmd::expect_success_and_text 'oc new-app mongo -o yaml' 'image:\s*mongo'
19 19
 # the local image repository takes precedence over the Docker Hub "mysql" image
20 20
 os::cmd::expect_success 'oc create -f examples/image-streams/image-streams-centos7.json'
21 21
 os::cmd::try_until_success 'oc get imagestreamtags mysql:latest'
22 22
 os::cmd::try_until_success 'oc get imagestreamtags mysql:5.5'
23 23
 os::cmd::try_until_success 'oc get imagestreamtags mysql:5.6'
24
-os::cmd::expect_success_and_not_text 'oc new-app mysql -o yaml' 'library/mysql'
24
+os::cmd::expect_success_and_not_text 'oc new-app mysql -o yaml' 'image:\s*mysql'
25 25
 os::cmd::expect_success_and_not_text 'oc new-app mysql --dry-run' "runs as the 'root' user which may not be permitted by your cluster administrator"
26 26
 
27 27
 # docker strategy with repo that has no dockerfile