Skip to content

Commit

Permalink
add pouch search cli
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 21, 2019
1 parent 7235f82 commit a44a8fe
Show file tree
Hide file tree
Showing 11 changed files with 459 additions and 21 deletions.
16 changes: 15 additions & 1 deletion apis/server/image_bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/alibaba/pouch/daemon/mgr"
"github.com/alibaba/pouch/pkg/httputils"
util_metrics "github.com/alibaba/pouch/pkg/utils/metrics"
"github.com/go-openapi/strfmt"

"github.com/gorilla/mux"
"github.com/opencontainers/go-digest"
Expand Down Expand Up @@ -93,7 +94,20 @@ 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
}
if err := authConfig.Validate(strfmt.NewFormats()); 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
57 changes: 42 additions & 15 deletions apis/swagger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,17 @@ paths:
$ref: "#/definitions/SearchResultItem"
500:
$ref: "#/responses/500ErrorResponse"
parameters:
- name: "term"
in: "query"
description: "Term to search"
type: "string"
required: true
- name: "registry"
in: "query"
description: "Search images from specified registry"
type: "string"
# TODO: add limit and filters

/images/{imageid}/tag:
post:
Expand Down Expand Up @@ -3165,25 +3176,41 @@ definitions:
format: "int64"
x-nullable: false

SearchResultItem:
SearchResults:
type: "object"
description: "search result item in search results."
description: "search results from specified registry."
properties:
description:
type: "string"
description: "description just shows the description of this image"
is_official:
type: "boolean"
description: "is_official shows if this image is marked official."
is_automated:
type: "boolean"
description: "is_automated means whether this image is automated."
name:
query:
type: "string"
description: "name represents the name of this image"
star_count:
description: "query contains the query string that generated the search results"
num_results:
type: "integer"
description: "star_count refers to the star count of this image."
description: "NumResults indicates the number of results the query return"
results:
type: "array"
description: "Results is a slice containing the actual results for the search"
items:
$ref: "#/definitions/SearchResultItem"

SearchResultItem:
type: "object"
description: "search result item in search results."
properties:
description:
type: "string"
description: "description just shows the description of this image"
is_official:
type: "boolean"
description: "is_official shows if this image is marked official."
is_automated:
type: "boolean"
description: "is_automated means whether this image is automated."
name:
type: "string"
description: "name represents the name of this image"
star_count:
type: "integer"
description: "star_count refers to the star count of this image."

VolumeInfo:
type: "object"
Expand Down
86 changes: 86 additions & 0 deletions apis/types/search_results.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func main() {
cli.AddCommand(base, &LoadCommand{})
cli.AddCommand(base, &SaveCommand{})
cli.AddCommand(base, &HistoryCommand{})
cli.AddCommand(base, &SearchCommand{})

cli.AddCommand(base, &InspectCommand{})
cli.AddCommand(base, &RenameCommand{})
Expand Down
101 changes: 101 additions & 0 deletions cli/search.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package main

import (
"context"
"fmt"

"github.com/spf13/cobra"
)

var searchDescription = "\nSearch the images from specific registry."

// SearchCommand implements search images.
type SearchCommand struct {
baseCommand
registry string
}

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

s.cmd = &cobra.Command{
Use: "search [OPTIONS] TERM",
Short: "Search the images from specific registry",
Long: searchDescription,
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return s.runSearch(args)
},
Example: searchExample(),
}
s.addFlags()
}

// addFlags adds flags for specific command.
func (s *SearchCommand) addFlags() {
flagSet := s.cmd.Flags()

flagSet.StringVarP(&s.registry, "registry", "r", "", "set registry name")
}

func (s *SearchCommand) runSearch(args []string) error {
ctx := context.Background()
apiClient := s.cli.Client()

term := args[0]

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

if err != nil {
return err
}

display := s.cli.NewTableDisplay()
display.AddRow([]string{"NAME", "DESCRIPTION", "STARS", "OFFICIAL", "AUTOMATED"})

for _, result := range searchResults {
display.AddRow([]string{result.Name, result.Description, fmt.Sprint(result.StarCount), boolToOKOrNot(result.IsOfficial), boolToOKOrNot(result.IsAutomated)})
}

display.Flush()
return nil
}

func boolToOKOrNot(isTrue bool) string {
if isTrue {
return "[OK]"
}
return ""
}

func searchExample() string {
return `$ pouch search nginx
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
nginx Official build of Nginx. 11403 [OK]
jwilder/nginx-proxy Automated Nginx reverse proxy for docker con… 1600 [OK]
richarvey/nginx-php-fpm Container running Nginx + PHP-FPM capable of… 712 [OK]
jrcs/letsencrypt-nginx-proxy-companion LetsEncrypt container to use with nginx as p… 509 [OK]
webdevops/php-nginx Nginx with PHP-FPM 127 [OK]
zabbix/zabbix-web-nginx-mysql Zabbix frontend based on Nginx web-server wi… 101 [OK]
bitnami/nginx Bitnami nginx Docker Image 66 [OK]
linuxserver/nginx An Nginx container, brought to you by LinuxS… 61
1and1internet/ubuntu-16-nginx-php-phpmyadmin-mysql-5 ubuntu-16-nginx-php-phpmyadmin-mysql-5 50 [OK]
zabbix/zabbix-web-nginx-pgsql Zabbix frontend based on Nginx with PostgreS… 33 [OK]
tobi312/rpi-nginx NGINX on Raspberry Pi / ARM 26 [OK]
nginx/nginx-ingress NGINX Ingress Controller for Kubernetes 20
schmunk42/nginx-redirect A very simple container to redirect HTTP tra… 15 [OK]
nginxdemos/hello NGINX webserver that serves a simple page co… 14 [OK]
blacklabelops/nginx Dockerized Nginx Reverse Proxy Server. 12 [OK]
wodby/drupal-nginx Nginx for Drupal container image 12 [OK]
centos/nginx-18-centos7 Platform for running nginx 1.8 or building n… 10
centos/nginx-112-centos7 Platform for running nginx 1.12 or building … 9
nginxinc/nginx-unprivileged Unprivileged NGINX Dockerfiles 4
1science/nginx Nginx Docker images that include Consul Temp… 4 [OK]
nginx/nginx-prometheus-exporter NGINX Prometheus Exporter 4
mailu/nginx Mailu nginx frontend 3 [OK]
toccoag/openshift-nginx Nginx reverse proxy for Nice running on same… 1 [OK]
ansibleplaybookbundle/nginx-apb An APB to deploy NGINX 0 [OK]
wodby/nginx Generic nginx 0 [OK]
`
}
32 changes: 32 additions & 0 deletions client/image_search.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package client

import (
"context"
"encoding/json"
"net/url"

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

// ImageSearch requests daemon to search an image from registry.
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)
q.Set("registry", registry)

headers := map[string][]string{}
if encodedAuth != "" {
headers["X-Registry-Auth"] = []string{encodedAuth}
}

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

if err != nil {
return nil, err
}

err = json.NewDecoder(resp.Body).Decode(&results)
return results, err
}
Loading

0 comments on commit a44a8fe

Please sign in to comment.