Added support for multiple endpoints in X-Docker-Endpoints header

Docker-DCO-1.1-Signed-off-by: Joffrey F <joffrey@docker.com> (github: shin-)
This commit is contained in:
shin- 2014-04-14 20:32:47 +02:00
parent c7c51058ce
commit 52893cae73
3 changed files with 40 additions and 10 deletions

View file

@ -297,6 +297,25 @@ func (r *Registry) GetRemoteTags(registries []string, repository string, token [
return nil, fmt.Errorf("Could not reach any registry endpoint") 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) { func (r *Registry) GetRepositoryData(remote string) (*RepositoryData, error) {
indexEp := r.indexEndpoint indexEp := r.indexEndpoint
repositoryTarget := fmt.Sprintf("%srepositories/%s/images", indexEp, remote) repositoryTarget := fmt.Sprintf("%srepositories/%s/images", indexEp, remote)
@ -332,11 +351,10 @@ func (r *Registry) GetRepositoryData(remote string) (*RepositoryData, error) {
} }
var endpoints []string var endpoints []string
var urlScheme = indexEp[:strings.Index(indexEp, ":")]
if res.Header.Get("X-Docker-Endpoints") != "" { if res.Header.Get("X-Docker-Endpoints") != "" {
// The Registry's URL scheme has to match the Index' endpoints, err = buildEndpointsList(res.Header["X-Docker-Endpoints"], indexEp)
for _, ep := range res.Header["X-Docker-Endpoints"] { if err != nil {
endpoints = append(endpoints, fmt.Sprintf("%s://%s/v1/", urlScheme, ep)) return nil, err
} }
} else { } else {
return nil, fmt.Errorf("Index response didn't contain any endpoints") 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 tokens, endpoints []string
var urlScheme = indexEp[:strings.Index(indexEp, ":")]
if !validate { if !validate {
if res.StatusCode != 200 && res.StatusCode != 201 { if res.StatusCode != 200 && res.StatusCode != 201 {
errBody, err := ioutil.ReadAll(res.Body) 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") != "" { if res.Header.Get("X-Docker-Endpoints") != "" {
// The Registry's URL scheme has to match the Index' endpoints, err = buildEndpointsList(res.Header["X-Docker-Endpoints"], indexEp)
for _, ep := range res.Header["X-Docker-Endpoints"] { if err != nil {
endpoints = append(endpoints, fmt.Sprintf("%s://%s/v1/", urlScheme, ep)) return nil, err
} }
} else { } else {
return nil, fmt.Errorf("Index response didn't contain any endpoints") return nil, fmt.Errorf("Index response didn't contain any endpoints")

View file

@ -291,7 +291,7 @@ func handlerUsers(w http.ResponseWriter, r *http.Request) {
func handlerImages(w http.ResponseWriter, r *http.Request) { func handlerImages(w http.ResponseWriter, r *http.Request) {
u, _ := url.Parse(testHttpServer.URL) 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())) w.Header().Add("X-Docker-Token", fmt.Sprintf("FAKE-SESSION-%d", time.Now().UnixNano()))
if r.Method == "PUT" { if r.Method == "PUT" {
if strings.HasSuffix(r.URL.Path, "images") { if strings.HasSuffix(r.URL.Path, "images") {

View file

@ -1,7 +1,9 @@
package registry package registry
import ( import (
"fmt"
"github.com/dotcloud/docker/utils" "github.com/dotcloud/docker/utils"
"net/url"
"strings" "strings"
"testing" "testing"
) )
@ -99,12 +101,23 @@ func TestGetRemoteTags(t *testing.T) {
func TestGetRepositoryData(t *testing.T) { func TestGetRepositoryData(t *testing.T) {
r := spawnTestRegistry(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") data, err := r.GetRepositoryData("foo42/bar")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
assertEqual(t, len(data.ImgList), 2, "Expected 2 images in ImgList") 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) { func TestPushImageJSONRegistry(t *testing.T) {