From a90195f1c8a51945e1a230a2b6af7a1fb5ef1b55 Mon Sep 17 00:00:00 2001 From: Josh Hawn Date: Tue, 20 Jan 2015 19:37:21 -0800 Subject: [PATCH 1/2] Resolve ambiguity on registry v2 ping v2 ping now checks for a Docker-Distribution-API-Version header that identifies the endpoint as "registry/2.0" Docker-DCO-1.1-Signed-off-by: Josh Hawn (github: jlhawn) Upstream-commit: f46923be8eba81dd9e261554128b26a1c83ce398 Component: engine --- components/engine/Dockerfile | 2 +- components/engine/registry/endpoint.go | 15 +++++ components/engine/registry/endpoint_test.go | 63 ++++++++++++++++++++- 3 files changed, 78 insertions(+), 2 deletions(-) diff --git a/components/engine/Dockerfile b/components/engine/Dockerfile index ae3b23b35c..49887f8720 100644 --- a/components/engine/Dockerfile +++ b/components/engine/Dockerfile @@ -149,7 +149,7 @@ RUN set -x \ COPY pkg/tarsum /go/src/github.com/docker/docker/pkg/tarsum # REGISTRY_COMMIT gives us the repeatability guarantees we need # (so that we're all testing the same version of the registry) -ENV REGISTRY_COMMIT 21a69f53b5c7986b831f33849d551cd59ec8cbd1 +ENV REGISTRY_COMMIT c448e0416925a9876d5576e412703c9b8b865e19 RUN set -x \ && git clone https://github.com/docker/distribution.git /go/src/github.com/docker/distribution \ && (cd /go/src/github.com/docker/distribution && git checkout -q $REGISTRY_COMMIT) \ diff --git a/components/engine/registry/endpoint.go b/components/engine/registry/endpoint.go index 9ca9ed8b9a..72bcce4aae 100644 --- a/components/engine/registry/endpoint.go +++ b/components/engine/registry/endpoint.go @@ -227,6 +227,21 @@ func (e *Endpoint) pingV2() (RegistryInfo, error) { } defer resp.Body.Close() + // The endpoint may have multiple supported versions. + // Ensure it supports the v2 Registry API. + var supportsV2 bool + + for _, versionName := range resp.Header[http.CanonicalHeaderKey("Docker-Distribution-API-Version")] { + if versionName == "registry/2.0" { + supportsV2 = true + break + } + } + + if !supportsV2 { + return RegistryInfo{}, fmt.Errorf("%s does not appear to be a v2 registry endpoint", e) + } + if resp.StatusCode == http.StatusOK { // It would seem that no authentication/authorization is required. // So we don't need to parse/add any authorization schemes. diff --git a/components/engine/registry/endpoint_test.go b/components/engine/registry/endpoint_test.go index f6489034fe..ef2589994a 100644 --- a/components/engine/registry/endpoint_test.go +++ b/components/engine/registry/endpoint_test.go @@ -1,6 +1,11 @@ package registry -import "testing" +import ( + "net/http" + "net/http/httptest" + "net/url" + "testing" +) func TestEndpointParse(t *testing.T) { testData := []struct { @@ -27,3 +32,59 @@ func TestEndpointParse(t *testing.T) { } } } + +// Ensure that a registry endpoint that responds with a 401 only is determined +// to be a v1 registry unless it includes a valid v2 API header. +func TestValidateEndpointAmbiguousAPIVersion(t *testing.T) { + requireBasicAuthHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Add("WWW-Authenticate", `Basic realm="localhost"`) + w.WriteHeader(http.StatusUnauthorized) + }) + + requireBasicAuthHandlerV2 := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Add("Docker-Distribution-API-Version", "registry/2.0") + requireBasicAuthHandler.ServeHTTP(w, r) + }) + + // Make a test server which should validate as a v1 server. + testServer := httptest.NewServer(requireBasicAuthHandler) + defer testServer.Close() + + testServerURL, err := url.Parse(testServer.URL) + if err != nil { + t.Fatal(err) + } + + testEndpoint := Endpoint{ + URL: testServerURL, + Version: APIVersionUnknown, + } + + if err = validateEndpoint(&testEndpoint); err != nil { + t.Fatal(err) + } + + if testEndpoint.Version != APIVersion1 { + t.Fatalf("expected endpoint to validate to %s, got %s", APIVersion1, testEndpoint.Version) + } + + // Make a test server which should validate as a v2 server. + testServer = httptest.NewServer(requireBasicAuthHandlerV2) + defer testServer.Close() + + testServerURL, err = url.Parse(testServer.URL) + if err != nil { + t.Fatal(err) + } + + testEndpoint.URL = testServerURL + testEndpoint.Version = APIVersionUnknown + + if err = validateEndpoint(&testEndpoint); err != nil { + t.Fatal(err) + } + + if testEndpoint.Version != APIVersion2 { + t.Fatalf("expected endpoint to validate to %s, got %s", APIVersion2, testEndpoint.Version) + } +} From 7d2e2990e3bfed9762cf23f365decd7df26a6d90 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Tue, 20 Jan 2015 20:40:19 -0700 Subject: [PATCH 2/2] Update Dockerfile to use Godeps for distribution Update our "registry" install to use the included Godeps libraries so that it doesn't require anything from our current source (hence moving it up for better caching too) Signed-off-by: Andrew "Tianon" Page Upstream-commit: 681f4d84ae05a98b7096d52a168222bae362d9e1 Component: engine --- components/engine/Dockerfile | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/components/engine/Dockerfile b/components/engine/Dockerfile index 49887f8720..c452a6ad9d 100644 --- a/components/engine/Dockerfile +++ b/components/engine/Dockerfile @@ -113,6 +113,14 @@ RUN git clone -b buildroot-2014.02 https://github.com/jpetazzo/docker-busybox.gi # Get the "cirros" image source so we can import it instead of fetching it during tests RUN curl -sSL -o /cirros.tar.gz https://github.com/ewindisch/docker-cirros/raw/1cded459668e8b9dbf4ef976c94c05add9bbd8e9/cirros-0.3.0-x86_64-lxc.tar.gz +# Install registry +ENV REGISTRY_COMMIT c448e0416925a9876d5576e412703c9b8b865e19 +RUN set -x \ + && git clone https://github.com/docker/distribution.git /go/src/github.com/docker/distribution \ + && (cd /go/src/github.com/docker/distribution && git checkout -q $REGISTRY_COMMIT) \ + && GOPATH=/go/src/github.com/docker/distribution/Godeps/_workspace:/go \ + go build -o /go/bin/registry-v2 github.com/docker/distribution/cmd/registry + # Get the "docker-py" source so we can run their integration tests ENV DOCKER_PY_COMMIT aa19d7b6609c6676e8258f6b900dea2eda1dbe95 RUN git clone https://github.com/docker/docker-py.git /docker-py \ @@ -145,17 +153,6 @@ RUN set -x \ && git clone -b v1.2 https://github.com/russross/blackfriday.git /go/src/github.com/russross/blackfriday \ && go install -v github.com/cpuguy83/go-md2man -# Install registry -COPY pkg/tarsum /go/src/github.com/docker/docker/pkg/tarsum -# REGISTRY_COMMIT gives us the repeatability guarantees we need -# (so that we're all testing the same version of the registry) -ENV REGISTRY_COMMIT c448e0416925a9876d5576e412703c9b8b865e19 -RUN set -x \ - && git clone https://github.com/docker/distribution.git /go/src/github.com/docker/distribution \ - && (cd /go/src/github.com/docker/distribution && git checkout -q $REGISTRY_COMMIT) \ - && go get -d github.com/docker/distribution/cmd/registry \ - && go build -o /go/bin/registry-v2 github.com/docker/distribution/cmd/registry - # Wrap all commands in the "docker-in-docker" script to allow nested containers ENTRYPOINT ["hack/dind"]