Beispiel #1
0
func TestRoundTrip(t *testing.T) {
	server := test.NewServer(
		&test.RequestHandlerMapping{
			Method:  "GET",
			Pattern: "/",
			Handler: test.Handler(nil),
		})
	transport := NewTransport(&http.Transport{}, &simpleModifier{})
	client := &http.Client{
		Transport: transport,
	}

	req, err := http.NewRequest("GET", fmt.Sprintf("%s/", server.URL), nil)
	if err != nil {
		t.Fatalf("failed to create request: %v", err)
	}

	if _, err := client.Do(req); err != nil {
		t.Fatalf("failed to send request: %s", err)
	}

	header := req.Header.Get("Authorization")
	if header != "token" {
		t.Errorf("unexpected header: %s != %s", header, "token")
	}

}
Beispiel #2
0
func TestListTag(t *testing.T) {
	handler := test.Handler(&test.Response{
		Headers: map[string]string{
			"Content-Type": "application/json",
		},
		Body: []byte(fmt.Sprintf("{\"name\": \"%s\",\"tags\": [\"%s\"]}", repository, tag)),
	})

	server := test.NewServer(
		&test.RequestHandlerMapping{
			Method:  "GET",
			Pattern: fmt.Sprintf("/v2/%s/tags/list", repository),
			Handler: handler,
		})
	defer server.Close()

	client, err := newRepository(server.URL)
	if err != nil {
		t.Fatalf("failed to create client for repository: %v", err)
	}

	tags, err := client.ListTag()
	if err != nil {
		t.Fatalf("failed to list tags: %v", err)
	}

	if len(tags) != 1 {
		t.Fatalf("unexpected length of tags: %d != %d", len(tags), 1)
	}

	if tags[0] != tag {
		t.Errorf("unexpected tag: %s != %s", tags[0], tag)
	}
}
Beispiel #3
0
func TestPushManifest(t *testing.T) {
	handler := test.Handler(&test.Response{
		StatusCode: http.StatusCreated,
		Headers: map[string]string{
			"Content-Length":        "0",
			"Docker-Content-Digest": digest,
			"Location":              "",
		},
	})

	server := test.NewServer(
		&test.RequestHandlerMapping{
			Method:  "PUT",
			Pattern: fmt.Sprintf("/v2/%s/manifests/%s", repository, tag),
			Handler: handler,
		})
	defer server.Close()

	client, err := newRepository(server.URL)
	if err != nil {
		t.Fatalf("failed to create client for repository: %v", err)
	}

	d, err := client.PushManifest(tag, mediaType, manifest)
	if err != nil {
		t.Fatalf("failed to pull manifest: %v", err)
	}

	if d != digest {
		t.Errorf("unexpected digest of manifest: %s != %s", d, digest)
	}
}
Beispiel #4
0
func TestDeleteTag(t *testing.T) {
	manifestExistHandler := test.Handler(&test.Response{
		Headers: map[string]string{
			"Docker-Content-Digest": digest,
			"Content-Type":          mediaType,
		},
	})

	deleteManifestandler := test.Handler(&test.Response{
		StatusCode: http.StatusAccepted,
	})

	server := test.NewServer(
		&test.RequestHandlerMapping{
			Method:  "HEAD",
			Pattern: fmt.Sprintf("/v2/%s/manifests/", repository),
			Handler: manifestExistHandler,
		},
		&test.RequestHandlerMapping{
			Method:  "DELETE",
			Pattern: fmt.Sprintf("/v2/%s/manifests/%s", repository, digest),
			Handler: deleteManifestandler,
		})
	defer server.Close()

	client, err := newRepository(server.URL)
	if err != nil {
		t.Fatalf("failed to create client for repository: %v", err)
	}

	if err = client.DeleteTag(tag); err != nil {
		t.Fatalf("failed to delete tag: %v", err)
	}
}
Beispiel #5
0
func TestBlobExist(t *testing.T) {
	handler := func(w http.ResponseWriter, r *http.Request) {
		path := r.URL.Path
		dgt := path[strings.LastIndex(path, "/")+1 : len(path)]
		if dgt == digest {
			w.Header().Add(http.CanonicalHeaderKey("Content-Length"), strconv.Itoa(len(blob)))
			w.Header().Add(http.CanonicalHeaderKey("Docker-Content-Digest"), digest)
			w.Header().Add(http.CanonicalHeaderKey("Content-Type"), "application/octet-stream")
			return
		}

		w.WriteHeader(http.StatusNotFound)
	}

	server := test.NewServer(
		&test.RequestHandlerMapping{
			Method:  "HEAD",
			Pattern: fmt.Sprintf("/v2/%s/blobs/", repository),
			Handler: handler,
		})
	defer server.Close()

	client, err := newRepository(server.URL)
	if err != nil {
		err = parseError(err)
		t.Fatalf("failed to create client for repository: %v", err)
	}

	exist, err := client.BlobExist(digest)
	if err != nil {
		t.Fatalf("failed to check the existence of blob: %v", err)
	}

	if !exist {
		t.Errorf("blob should exist on registry, but it does not exist")
	}

	exist, err = client.BlobExist("invalid_digest")
	if err != nil {
		t.Fatalf("failed to check the existence of blob: %v", err)
	}

	if exist {
		t.Errorf("blob should not exist on registry, but it exists")
	}
}
Beispiel #6
0
func TestPing(t *testing.T) {
	server := test.NewServer(
		&test.RequestHandlerMapping{
			Method:  "GET",
			Pattern: "/v2/",
			Handler: test.Handler(nil),
		})
	defer server.Close()

	client, err := newRegistryClient(server.URL)
	if err != nil {
		t.Fatalf("failed to create client for registry: %v", err)
	}

	if err = client.Ping(); err != nil {
		t.Errorf("failed to ping registry: %v", err)
	}
}
Beispiel #7
0
func TestManifestExist(t *testing.T) {
	handler := func(w http.ResponseWriter, r *http.Request) {
		path := r.URL.Path
		tg := path[strings.LastIndex(path, "/")+1 : len(path)]
		if tg == tag {
			w.Header().Add(http.CanonicalHeaderKey("Docker-Content-Digest"), digest)
			w.Header().Add(http.CanonicalHeaderKey("Content-Type"), mediaType)
			return
		}

		w.WriteHeader(http.StatusNotFound)
	}

	server := test.NewServer(
		&test.RequestHandlerMapping{
			Method:  "HEAD",
			Pattern: fmt.Sprintf("/v2/%s/manifests/%s", repository, tag),
			Handler: handler,
		})
	defer server.Close()

	client, err := newRepository(server.URL)
	if err != nil {
		t.Fatalf("failed to create client for repository: %v", err)
	}

	d, exist, err := client.ManifestExist(tag)
	if err != nil {
		t.Fatalf("failed to check the existence of manifest: %v", err)
	}

	if !exist || d != digest {
		t.Errorf("manifest should exist on registry, but it does not exist")
	}

	_, exist, err = client.ManifestExist("invalid_tag")
	if err != nil {
		t.Fatalf("failed to check the existence of manifest: %v", err)
	}

	if exist {
		t.Errorf("manifest should not exist on registry, but it exists")
	}
}
Beispiel #8
0
func TestPushBlob(t *testing.T) {
	location := ""
	initUploadHandler := func(w http.ResponseWriter, r *http.Request) {
		w.Header().Add(http.CanonicalHeaderKey("Content-Length"), "0")
		w.Header().Add(http.CanonicalHeaderKey("Location"), location)
		w.Header().Add(http.CanonicalHeaderKey("Range"), "0-0")
		w.Header().Add(http.CanonicalHeaderKey("Docker-Upload-UUID"), uuid)
		w.WriteHeader(http.StatusAccepted)
	}

	monolithicUploadHandler := test.Handler(&test.Response{
		StatusCode: http.StatusCreated,
		Headers: map[string]string{
			"Content-Length":        "0",
			"Location":              fmt.Sprintf("/v2/%s/blobs/%s", repository, digest),
			"Docker-Content-Digest": digest,
		},
	})

	server := test.NewServer(
		&test.RequestHandlerMapping{
			Method:  "POST",
			Pattern: fmt.Sprintf("/v2/%s/blobs/uploads/", repository),
			Handler: initUploadHandler,
		},
		&test.RequestHandlerMapping{
			Method:  "PUT",
			Pattern: fmt.Sprintf("/v2/%s/blobs/uploads/%s", repository, uuid),
			Handler: monolithicUploadHandler,
		})
	defer server.Close()
	location = fmt.Sprintf("%s/v2/%s/blobs/uploads/%s", server.URL, repository, uuid)

	client, err := newRepository(server.URL)
	if err != nil {
		t.Fatalf("failed to create client for repository: %v", err)
	}

	if err = client.PushBlob(digest, int64(len(blob)), bytes.NewReader(blob)); err != nil {
		t.Fatalf("failed to push blob: %v", err)
	}
}
Beispiel #9
0
func TestNewAuthorizerStore(t *testing.T) {
	handler := test.Handler(&test.Response{
		StatusCode: http.StatusUnauthorized,
		Headers: map[string]string{
			"Www-Authenticate": "Bearer realm=\"https://auth.docker.io/token\",service=\"registry.docker.io\"",
		},
	})

	server := test.NewServer(&test.RequestHandlerMapping{
		Method:  "GET",
		Pattern: "/v2/",
		Handler: handler,
	})
	defer server.Close()

	_, err := NewAuthorizerStore(server.URL, false, nil)
	if err != nil {
		t.Fatalf("failed to create authorizer store: %v", err)
	}
}
Beispiel #10
0
func TestPullBlob(t *testing.T) {
	handler := test.Handler(&test.Response{
		Headers: map[string]string{
			"Content-Length":        strconv.Itoa(len(blob)),
			"Docker-Content-Digest": digest,
			"Content-Type":          "application/octet-stream",
		},
		Body: blob,
	})

	server := test.NewServer(
		&test.RequestHandlerMapping{
			Method:  "GET",
			Pattern: fmt.Sprintf("/v2/%s/blobs/%s", repository, digest),
			Handler: handler,
		})
	defer server.Close()

	client, err := newRepository(server.URL)
	if err != nil {
		t.Fatalf("failed to create client for repository: %v", err)
	}

	size, reader, err := client.PullBlob(digest)
	if err != nil {
		t.Fatalf("failed to pull blob: %v", err)
	}

	if size != int64(len(blob)) {
		t.Errorf("unexpected size of blob: %d != %d", size, len(blob))
	}

	b, err := ioutil.ReadAll(reader)
	if err != nil {
		t.Fatalf("failed to read from reader: %v", err)
	}

	if bytes.Compare(b, blob) != 0 {
		t.Errorf("unexpected blob: %s != %s", string(b), string(blob))
	}
}
Beispiel #11
0
func TestPullManifest(t *testing.T) {
	handler := test.Handler(&test.Response{
		Headers: map[string]string{
			"Docker-Content-Digest": digest,
			"Content-Type":          mediaType,
		},
		Body: manifest,
	})

	server := test.NewServer(
		&test.RequestHandlerMapping{
			Method:  "GET",
			Pattern: fmt.Sprintf("/v2/%s/manifests/%s", repository, tag),
			Handler: handler,
		})
	defer server.Close()

	client, err := newRepository(server.URL)
	if err != nil {
		t.Fatalf("failed to create client for repository: %v", err)
	}

	d, md, payload, err := client.PullManifest(tag, []string{mediaType})
	if err != nil {
		t.Fatalf("failed to pull manifest: %v", err)
	}

	if d != digest {
		t.Errorf("unexpected digest of manifest: %s != %s", d, digest)
	}

	if md != mediaType {
		t.Errorf("unexpected media type of manifest: %s != %s", md, mediaType)
	}

	if bytes.Compare(payload, manifest) != 0 {
		t.Errorf("unexpected manifest: %s != %s", string(payload), string(manifest))
	}
}
Beispiel #12
0
func TestDeleteBlob(t *testing.T) {
	handler := test.Handler(&test.Response{
		StatusCode: http.StatusAccepted,
	})

	server := test.NewServer(
		&test.RequestHandlerMapping{
			Method:  "DELETE",
			Pattern: fmt.Sprintf("/v2/%s/blobs/%s", repository, digest),
			Handler: handler,
		})
	defer server.Close()

	client, err := newRepository(server.URL)
	if err != nil {
		t.Fatalf("failed to create client for repository: %v", err)
	}

	if err = client.DeleteBlob(digest); err != nil {
		t.Fatalf("failed to delete blob: %v", err)
	}
}
Beispiel #13
0
func TestAuthorizeOfStandardTokenAuthorizer(t *testing.T) {
	handler := test.Handler(&test.Response{
		Body: []byte(`
		{
			"token":"token",
			"expires_in":300,
			"issued_at":"2016-08-17T23:17:58+08:00"
		}
		`),
	})

	server := test.NewServer(&test.RequestHandlerMapping{
		Method:  "GET",
		Pattern: "/token",
		Handler: handler,
	})
	defer server.Close()

	authorizer := NewStandardTokenAuthorizer(nil, false, "repository", "library/ubuntu", "pull")
	req, err := http.NewRequest("GET", "http://registry", nil)
	if err != nil {
		t.Fatalf("failed to create request: %v", err)
	}

	params := map[string]string{
		"realm": server.URL + "/token",
	}

	if err := authorizer.Authorize(req, params); err != nil {
		t.Fatalf("failed to authorize request: %v", err)
	}

	tk := req.Header.Get("Authorization")
	if tk != "Bearer token" {
		t.Errorf("unexpected token: %s != %s", tk, "Bearer token")
	}
}
Beispiel #14
0
func TestCatalog(t *testing.T) {
	repositories := make([]string, 0, 1001)
	for i := 0; i < 1001; i++ {
		repositories = append(repositories, strconv.Itoa(i))
	}

	handler := func(w http.ResponseWriter, r *http.Request) {
		q := r.URL.Query()
		last := q.Get("last")
		n, err := strconv.Atoi(q.Get("n"))
		if err != nil || n <= 0 {
			n = 1000
		}

		length := len(repositories)

		begin := length
		if len(last) == 0 {
			begin = 0
		} else {
			for i, repository := range repositories {
				if repository == last {
					begin = i + 1
					break
				}
			}
		}

		end := begin + n
		if end > length {
			end = length
		}

		w.Header().Set(http.CanonicalHeaderKey("Content-Type"), "application/json")
		if end < length {
			u, err := url.Parse("/v2/_catalog")
			if err != nil {
				w.WriteHeader(http.StatusInternalServerError)
				return
			}
			values := u.Query()
			values.Add("last", repositories[end-1])
			values.Add("n", strconv.Itoa(n))

			u.RawQuery = values.Encode()

			link := fmt.Sprintf("<%s>; rel=\"next\"", u.String())
			w.Header().Set(http.CanonicalHeaderKey("link"), link)
		}

		repos := struct {
			Repositories []string `json:"repositories"`
		}{
			Repositories: []string{},
		}

		if begin < length {
			repos.Repositories = repositories[begin:end]
		}

		b, err := json.Marshal(repos)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		w.Write(b)

	}

	server := test.NewServer(
		&test.RequestHandlerMapping{
			Method:  "GET",
			Pattern: "/v2/_catalog",
			Handler: handler,
		})
	defer server.Close()

	client, err := newRegistryClient(server.URL)
	if err != nil {
		t.Fatalf("failed to create client for registry: %v", err)
	}

	repos, err := client.Catalog()
	if err != nil {
		t.Fatalf("failed to catalog repositories: %v", err)
	}

	if len(repos) != len(repositories) {
		t.Errorf("unexpected length of repositories: %d != %d", len(repos), len(repositories))
	}
}