Skip to content

Commit

Permalink
add auth in pouch search client
Browse files Browse the repository at this point in the history
Signed-off-by: Junjun Li <junjunli666@gmail.com>
  • Loading branch information
hellolijj committed May 17, 2019
1 parent db756bd commit 81f2f21
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 39 deletions.
12 changes: 11 additions & 1 deletion apis/server/image_bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,17 @@ func (s *Server) searchImages(ctx context.Context, rw http.ResponseWriter, req *
searchPattern := req.FormValue("term")
registry := req.FormValue("registry")

searchResultItem, err := s.ImageMgr.SearchImages(ctx, searchPattern, registry)
// get registry auth from Request header
authStr := req.Header.Get("X-Registry-Auth")
authConfig := types.AuthConfig{}
if authStr != "" {
data := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authStr))
if err := json.NewDecoder(data).Decode(&authConfig); err != nil {
return err
}
}

searchResultItem, err := s.ImageMgr.SearchImages(ctx, searchPattern, registry, &authConfig)
if err != nil {
logrus.Errorf("failed to search images from registry: %v", err)
return err
Expand Down
14 changes: 1 addition & 13 deletions apis/swagger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -380,19 +380,7 @@ paths:
in: "query"
description: "Search images from specified registry"
type: "string"

- name: "limit"
in: "query"
description: "Maximum number of results to return"
type: "integer"
- name: "filters"
in: "query"
description: |
A JSON encoded value of the filters (a `map[string][]string`) to process on the images list. Available filters:
- `is-automated=(true|false)`
- `is-official=(true|false)`
- `stars=<number>` Matches images that has at least 'number' stars.
type: "string"
# TODO: add limit and filters

/images/{imageid}/tag:
post:
Expand Down
11 changes: 8 additions & 3 deletions cli/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"
"fmt"

"github.com/alibaba/pouch/registry"

"github.com/spf13/cobra"
)

Expand All @@ -15,7 +17,7 @@ type SearchCommand struct {
registry string
}

// Init initialize start command.
// Init initialize search command.
func (s *SearchCommand) Init(c *Cli) {
s.cli = c

Expand Down Expand Up @@ -44,7 +46,11 @@ func (s *SearchCommand) runSearch(args []string) error {
apiClient := s.cli.Client()

term := args[0]
searchResults, err := apiClient.ImageSearch(ctx, term, s.registry)
if len(s.registry) == 0 {
s.registry = registry.DefaultRegistry
}

searchResults, err := apiClient.ImageSearch(ctx, term, s.registry, fetchRegistryAuth(s.registry))

if err != nil {
return err
Expand All @@ -61,7 +67,6 @@ func (s *SearchCommand) runSearch(args []string) error {
return nil
}

// chang bool value to ok or "" bool => "[OK]" false => ""
func boolToOKOrNot(isTrue bool) string {
if isTrue {
return "[OK]"
Expand Down
10 changes: 5 additions & 5 deletions client/image_search.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ import (
)

// ImageSearch requests daemon to search an image from registry.
func (client *APIClient) ImageSearch(ctx context.Context, term string, register string) ([]types.SearchResultItem, error) {
func (client *APIClient) ImageSearch(ctx context.Context, term, registry, encodedAuth string) ([]types.SearchResultItem, error) {
var results []types.SearchResultItem

q := url.Values{}
q.Set("term", term)
if len(register) > 0 {
q.Set("registry", register)
}
q.Set("registry", registry)

// todo: add some auth info
headers := map[string][]string{}
if encodedAuth != "" {
headers["X-Registry-Auth"] = []string{encodedAuth}
}

resp, err := client.post(ctx, "/images/search", q, nil, headers)

Expand Down
18 changes: 15 additions & 3 deletions client/image_search_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ import (
"testing"

"github.com/alibaba/pouch/apis/types"

"github.com/stretchr/testify/assert"
)

func TestImageSearchServerError(t *testing.T) {
client := &APIClient{
HTTPCli: newMockClient(errorMockResponse(http.StatusInternalServerError, "Server error")),
}
term, registry := "", "nginx"
_, err := client.ImageSearch(context.Background(), term, registry)
term, registry, auth := "", "nginx", ""
_, err := client.ImageSearch(context.Background(), term, registry, auth)
if err == nil || !strings.Contains(err.Error(), "Server error") {
t.Fatalf("expected a Server Error, got %v", err)
}
Expand Down Expand Up @@ -59,11 +60,22 @@ func TestImageSearchOK(t *testing.T) {
HTTPCli: httpClient,
}

searchResults, err := client.ImageSearch(context.Background(), "nginx", "")
searchResults, err := client.ImageSearch(context.Background(), "nginx", "", "")
if err != nil {
t.Fatal(err)
}

assert.Equal(t, searchResults[0].StarCount, int64(1233))
assert.Equal(t, searchResults[0].Name, "nginx")
}

func TestImageSearchStatusUnauthorizedError(t *testing.T) {
client := &APIClient{
HTTPCli: newMockClient(errorMockResponse(http.StatusUnauthorized, "Unauthorized Error")),
}
term, registry, auth := "", "nginx", "some-auth-code"
_, err := client.ImageSearch(context.Background(), term, registry, auth)
if err == nil || !strings.Contains(err.Error(), "Unauthorized Error") {
t.Fatalf("expected a Unauthorized Error, got %v", err)
}
}
2 changes: 1 addition & 1 deletion client/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ type ImageAPIClient interface {
ImageSave(ctx context.Context, imageName string) (io.ReadCloser, error)
ImageHistory(ctx context.Context, name string) ([]types.HistoryResultItem, error)
ImagePush(ctx context.Context, ref, encodedAuth string) (io.ReadCloser, error)
ImageSearch(ctx context.Context, term string, registry string) ([]types.SearchResultItem, error)
ImageSearch(ctx context.Context, term, registry, encodedAuth string) ([]types.SearchResultItem, error)
}

// VolumeAPIClient defines methods of Volume client.
Expand Down
25 changes: 16 additions & 9 deletions daemon/mgr/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/alibaba/pouch/pkg/reference"
"github.com/alibaba/pouch/pkg/utils"

registry2 "github.com/alibaba/pouch/registry"
"github.com/containerd/containerd"
"github.com/containerd/containerd/content"
ctrdmetaimages "github.com/containerd/containerd/images"
Expand Down Expand Up @@ -61,7 +62,7 @@ type ImageMgr interface {
ListImages(ctx context.Context, filter filters.Args) ([]types.ImageInfo, error)

// Search Images from specified registry.
SearchImages(ctx context.Context, name string, registry string) ([]types.SearchResultItem, error)
SearchImages(ctx context.Context, name, registry string, authConfig *types.AuthConfig) ([]types.SearchResultItem, error)

// RemoveImage deletes an image by reference.
RemoveImage(ctx context.Context, idOrRef string, force bool) error
Expand Down Expand Up @@ -327,28 +328,37 @@ func (mgr *ImageManager) ListImages(ctx context.Context, filter filters.Args) ([
}

// SearchImages searches imaged from specified registry.
func (mgr *ImageManager) SearchImages(ctx context.Context, name string, registry string) ([]types.SearchResultItem, error) {
func (mgr *ImageManager) SearchImages(ctx context.Context, name, registry string, auth *types.AuthConfig) ([]types.SearchResultItem, error) {
// Directly send API calls towards specified registry
if len(registry) == 0 {
registry = "https://index.docker.io/v1/"
registry = registry2.DefaultRegistry
}

u := registry + "search?q=" + url.QueryEscape(name)
res, err := http.Get(u)
req, err := http.NewRequest("GET", u, nil)
if err != nil {
return nil, err
}

if auth != nil && auth.IdentityToken != "" && auth.Username != "" {
req.SetBasicAuth(auth.Username, auth.Password)
}

res, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()

if res.StatusCode != 200 {
return nil, errtypes.ErrTimeout
return nil, fmt.Errorf("Unexepected status code %d", res.StatusCode)
}

rawData, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}

// todo: to move where it should be
type SearchResults struct {
Query string `json:"query"`
NumResults int `json:"num_results"`
Expand All @@ -360,9 +370,6 @@ func (mgr *ImageManager) SearchImages(ctx context.Context, name string, registry

return searchResults.Results, err

// todo: whether this code rebuild in ctrd ?
// todo: to add some session code and log info?
//return mgr.client.SearchImage(ctx, name, registry)
}

// RemoveImage deletes a reference.
Expand Down
2 changes: 1 addition & 1 deletion daemon/mgr/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func (mgr *SystemManager) Info() (types.SystemInfo, error) {
// ID: ,
CgroupDriver: mgr.config.GetCgroupDriver(),
Images: int64(len(images)),
IndexServerAddress: "https://index.docker.io/v1/",
IndexServerAddress: registry.DefaultRegistry,
DefaultRegistry: mgr.config.DefaultRegistry,
KernelVersion: kernelVersion,
Labels: mgr.config.Labels,
Expand Down
3 changes: 3 additions & 0 deletions registry/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ package registry

var (
defaultV2Registry = "registry-1.docker.io"

// DefaultRegistry set default registry value
DefaultRegistry = "https://index.docker.io/v1/"
)
4 changes: 2 additions & 2 deletions test/api_image_search_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package main

import (
"github.com/alibaba/pouch/test/environment"

"net/url"

"github.com/alibaba/pouch/apis/types"
"github.com/alibaba/pouch/test/environment"
"github.com/alibaba/pouch/test/request"
"github.com/alibaba/pouch/test/util"

"github.com/go-check/check"
)

Expand Down
2 changes: 1 addition & 1 deletion test/cli_search_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ func (suite *PouchSearchSuite) TestSearchWorks(c *check.C) {

// TestSearchInSpecificRegistry test search in specific registry
func (suite *PouchSearchSuite) TestSearchInSpecificRegistry(c *check.C) {
// TODO: Verification specific registry?
// TODO: Verification specific registry
}

0 comments on commit 81f2f21

Please sign in to comment.