From 52893cae738b64dee20a435a68ab37cc4b84b9a8 Mon Sep 17 00:00:00 2001 From: shin- Date: Mon, 14 Apr 2014 20:32:47 +0200 Subject: [PATCH] Added support for multiple endpoints in X-Docker-Endpoints header Docker-DCO-1.1-Signed-off-by: Joffrey F (github: shin-) --- docs/registry.go | 33 +++++++++++++++++++++++++-------- docs/registry_mock_test.go | 2 +- docs/registry_test.go | 15 ++++++++++++++- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/docs/registry.go b/docs/registry.go index 817c08af..3656032e 100644 --- a/docs/registry.go +++ b/docs/registry.go @@ -297,6 +297,25 @@ func (r *Registry) GetRemoteTags(registries []string, repository string, token [ return nil, fmt.Errorf("Could not reach any registry endpoint") } +func buildEndpointsList(headers []string, indexEp string) ([]string, error) { + var endpoints []string + parsedUrl, err := url.Parse(indexEp) + if err != nil { + return nil, err + } + var urlScheme = parsedUrl.Scheme + // The Registry's URL scheme has to match the Index' + for _, ep := range headers { + epList := strings.Split(ep, ",") + for _, epListElement := range epList { + endpoints = append( + endpoints, + fmt.Sprintf("%s://%s/v1/", urlScheme, strings.TrimSpace(epListElement))) + } + } + return endpoints, nil +} + func (r *Registry) GetRepositoryData(remote string) (*RepositoryData, error) { indexEp := r.indexEndpoint repositoryTarget := fmt.Sprintf("%srepositories/%s/images", indexEp, remote) @@ -332,11 +351,10 @@ func (r *Registry) GetRepositoryData(remote string) (*RepositoryData, error) { } var endpoints []string - var urlScheme = indexEp[:strings.Index(indexEp, ":")] if res.Header.Get("X-Docker-Endpoints") != "" { - // The Registry's URL scheme has to match the Index' - for _, ep := range res.Header["X-Docker-Endpoints"] { - endpoints = append(endpoints, fmt.Sprintf("%s://%s/v1/", urlScheme, ep)) + endpoints, err = buildEndpointsList(res.Header["X-Docker-Endpoints"], indexEp) + if err != nil { + return nil, err } } else { return nil, fmt.Errorf("Index response didn't contain any endpoints") @@ -565,7 +583,6 @@ func (r *Registry) PushImageJSONIndex(remote string, imgList []*ImgData, validat } var tokens, endpoints []string - var urlScheme = indexEp[:strings.Index(indexEp, ":")] if !validate { if res.StatusCode != 200 && res.StatusCode != 201 { errBody, err := ioutil.ReadAll(res.Body) @@ -582,9 +599,9 @@ func (r *Registry) PushImageJSONIndex(remote string, imgList []*ImgData, validat } if res.Header.Get("X-Docker-Endpoints") != "" { - // The Registry's URL scheme has to match the Index' - for _, ep := range res.Header["X-Docker-Endpoints"] { - endpoints = append(endpoints, fmt.Sprintf("%s://%s/v1/", urlScheme, ep)) + endpoints, err = buildEndpointsList(res.Header["X-Docker-Endpoints"], indexEp) + if err != nil { + return nil, err } } else { return nil, fmt.Errorf("Index response didn't contain any endpoints") diff --git a/docs/registry_mock_test.go b/docs/registry_mock_test.go index dd5da6bd..6b007513 100644 --- a/docs/registry_mock_test.go +++ b/docs/registry_mock_test.go @@ -291,7 +291,7 @@ func handlerUsers(w http.ResponseWriter, r *http.Request) { func handlerImages(w http.ResponseWriter, r *http.Request) { u, _ := url.Parse(testHttpServer.URL) - w.Header().Add("X-Docker-Endpoints", u.Host) + w.Header().Add("X-Docker-Endpoints", fmt.Sprintf("%s , %s ", u.Host, "test.example.com")) w.Header().Add("X-Docker-Token", fmt.Sprintf("FAKE-SESSION-%d", time.Now().UnixNano())) if r.Method == "PUT" { if strings.HasSuffix(r.URL.Path, "images") { diff --git a/docs/registry_test.go b/docs/registry_test.go index c072da41..ad64fb1f 100644 --- a/docs/registry_test.go +++ b/docs/registry_test.go @@ -1,7 +1,9 @@ package registry import ( + "fmt" "github.com/dotcloud/docker/utils" + "net/url" "strings" "testing" ) @@ -99,12 +101,23 @@ func TestGetRemoteTags(t *testing.T) { func TestGetRepositoryData(t *testing.T) { r := spawnTestRegistry(t) + parsedUrl, err := url.Parse(makeURL("/v1/")) + if err != nil { + t.Fatal(err) + } + host := "http://" + parsedUrl.Host + "/v1/" data, err := r.GetRepositoryData("foo42/bar") if err != nil { t.Fatal(err) } assertEqual(t, len(data.ImgList), 2, "Expected 2 images in ImgList") - assertEqual(t, len(data.Endpoints), 1, "Expected one endpoint in Endpoints") + assertEqual(t, len(data.Endpoints), 2, + fmt.Sprintf("Expected 2 endpoints in Endpoints, found %d instead", len(data.Endpoints))) + assertEqual(t, data.Endpoints[0], host, + fmt.Sprintf("Expected first endpoint to be %s but found %s instead", host, data.Endpoints[0])) + assertEqual(t, data.Endpoints[1], "http://test.example.com/v1/", + fmt.Sprintf("Expected first endpoint to be http://test.example.com/v1/ but found %s instead", data.Endpoints[1])) + } func TestPushImageJSONRegistry(t *testing.T) {