mirror of https://github.com/docker/cli.git
feat: use engine API instead of Hub directly
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
This commit is contained in:
parent
5760a3d201
commit
5667a952c5
|
@ -1,12 +1,8 @@
|
|||
package completion
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
|
@ -14,7 +10,6 @@ import (
|
|||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
@ -194,122 +189,3 @@ var commonPlatforms = []string{
|
|||
func Platforms(_ *cobra.Command, _ []string, _ string) (platforms []string, _ cobra.ShellCompDirective) {
|
||||
return commonPlatforms, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
|
||||
type ImageSearchResult struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
Type string `json:"type"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ShortDesc string `json:"short_description"`
|
||||
Source string `json:"source"`
|
||||
StarCount int `json:"star_count"`
|
||||
}
|
||||
|
||||
type ImageSearch struct {
|
||||
Totals int `json:"totals"`
|
||||
Results []ImageSearchResult `json:"results"`
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
TagStatus string `json:"tag_status"`
|
||||
V2 bool `json:"v2"`
|
||||
Digest string `json:"digest"`
|
||||
LastUpdated time.Time `json:"last_updated"`
|
||||
LastUpdater int `json:"last_updater"`
|
||||
Creator int `json:"creator"`
|
||||
Repository int `json:"repository"`
|
||||
}
|
||||
|
||||
type ImageTags struct {
|
||||
Count int `json:"count"`
|
||||
Next string `json:"next"`
|
||||
Prev string `json:"prev"`
|
||||
Results []Image `json:"results"`
|
||||
}
|
||||
|
||||
func RemoteImages(cmd *cobra.Command, arg []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
ctx := cmd.Context()
|
||||
c := &http.Client{
|
||||
Timeout: 2 * time.Second,
|
||||
}
|
||||
|
||||
if imageName, imageTag, ok := strings.Cut(toComplete, ":"); ok {
|
||||
u, err := url.Parse("https://hub.docker.com/v2/repositories/library/" + imageName + "/tags/")
|
||||
if err != nil {
|
||||
logrus.Errorf("Error parsing hub image tags URL: %v", err)
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
q := u.Query()
|
||||
q.Set("ordering", "last_updated")
|
||||
q.Set("page_size", "25")
|
||||
q.Set("name", imageTag)
|
||||
u.RawQuery = q.Encode()
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error creating hub image tags request: %v", err)
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error sending hub image tags request: %v", err)
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var tags *ImageTags
|
||||
if err := json.NewDecoder(resp.Body).Decode(&tags); err != nil {
|
||||
logrus.Errorf("Error decoding hub image tags response: %v", err)
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
|
||||
names := make([]string, 0, len(tags.Results))
|
||||
for _, i := range tags.Results {
|
||||
names = append(names, imageName+":"+i.Name)
|
||||
}
|
||||
return names, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
|
||||
u, err := url.Parse("https://hub.docker.com/api/search/v3/catalog/search")
|
||||
if err != nil {
|
||||
logrus.Errorf("Error parsing hub image search URL: %v", err)
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
q := u.Query()
|
||||
q.Set("query", toComplete)
|
||||
q.Set("extension_reviewed", "")
|
||||
q.Set("from", "0")
|
||||
q.Set("size", "25")
|
||||
u.RawQuery = q.Encode()
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error creating hub image search request: %v", err)
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error sending hub image search request: %v", err)
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var images *ImageSearch
|
||||
if err := json.NewDecoder(resp.Body).Decode(&images); err != nil {
|
||||
logrus.Errorf("Error decoding hub image search response: %v", err)
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
|
||||
names := make([]string, 0, len(images.Results))
|
||||
for _, i := range images.Results {
|
||||
names = append(names, i.Name)
|
||||
}
|
||||
|
||||
return names, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/docker/cli/cli/command/completion"
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/hub"
|
||||
"github.com/moby/sys/signal"
|
||||
"github.com/moby/term"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -61,14 +62,44 @@ func NewRunCommand(dockerCli command.Cli) *cobra.Command {
|
|||
}
|
||||
}
|
||||
|
||||
remoteImages, shellCompRemote := completion.RemoteImages(cmd, args, toComplete)
|
||||
if shellCompRemote != cobra.ShellCompDirectiveError {
|
||||
if len(all) == 0 {
|
||||
all = make([]string, 0, len(remoteImages))
|
||||
if image, tag, found := strings.Cut(toComplete, ":"); found {
|
||||
remoteTags, err := dockerCli.Client().ImageHubTags(cmd.Context(), image, hub.ImageOptions{
|
||||
Name: tag,
|
||||
Ordering: "last_updated",
|
||||
Page: 0,
|
||||
PageSize: 25,
|
||||
})
|
||||
if err == nil {
|
||||
if len(all) == 0 {
|
||||
all = make([]string, 0, len(remoteTags.Results))
|
||||
}
|
||||
for _, tag := range remoteTags.Results {
|
||||
fullName := image + ":" + tag.Name
|
||||
if _, ok := unique[fullName]; !ok {
|
||||
all = append(all, fullName+"\tremote")
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, img := range remoteImages {
|
||||
if _, ok := unique[img]; !ok {
|
||||
all = append(all, img+"\tremote")
|
||||
return all, cobra.ShellCompDirectiveKeepOrder | cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
|
||||
remoteImages, err := dockerCli.Client().ImageHubSearch(cmd.Context(), toComplete, hub.SearchOptions{
|
||||
From: 0,
|
||||
Size: 25,
|
||||
Type: hub.SearchTypeImage,
|
||||
Order: hub.SearchOrderDesc,
|
||||
Official: true,
|
||||
Source: hub.SearchSourceStore,
|
||||
OpenSource: true,
|
||||
ExtensionReviewed: true,
|
||||
})
|
||||
if err == nil {
|
||||
if len(all) == 0 {
|
||||
all = make([]string, 0, len(remoteImages.Results))
|
||||
}
|
||||
for _, img := range remoteImages.Results {
|
||||
if _, ok := unique[img.Name]; !ok {
|
||||
all = append(all, img.Name+"\tremote")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/completion"
|
||||
"github.com/docker/cli/cli/trust"
|
||||
"github.com/docker/docker/api/types/hub"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
@ -43,7 +44,50 @@ func NewPullCommand(dockerCli command.Cli) *cobra.Command {
|
|||
if len(args) > 0 {
|
||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
return completion.RemoteImages(cmd, args, toComplete)
|
||||
|
||||
if image, tag, found := strings.Cut(toComplete, ":"); found {
|
||||
remoteTags, err := dockerCli.Client().ImageHubTags(cmd.Context(), image, hub.ImageOptions{
|
||||
Name: tag,
|
||||
Ordering: "last_updated",
|
||||
Page: 0,
|
||||
PageSize: 25,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
|
||||
images := make([]string, 0, len(remoteTags.Results))
|
||||
for _, tag := range remoteTags.Results {
|
||||
fullName := image + ":" + tag.Name
|
||||
images = append(images, fullName+"\t"+tag.LastUpdated.String())
|
||||
}
|
||||
return images, cobra.ShellCompDirectiveKeepOrder | cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
|
||||
remoteImages, err := dockerCli.Client().ImageHubSearch(cmd.Context(), toComplete, hub.SearchOptions{
|
||||
From: 0,
|
||||
Size: 25,
|
||||
Type: hub.SearchTypeImage,
|
||||
Order: hub.SearchOrderDesc,
|
||||
Official: true,
|
||||
Source: hub.SearchSourceStore,
|
||||
OpenSource: true,
|
||||
ExtensionReviewed: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
|
||||
images := make([]string, 0, len(remoteImages.Results))
|
||||
for _, img := range remoteImages.Results {
|
||||
categories := make([]string, 0, len(img.Categories))
|
||||
for _, cat := range img.Categories {
|
||||
categories = append(categories, cat.Name)
|
||||
}
|
||||
images = append(images, img.Name+"\t"+strings.Join(categories, ", "))
|
||||
}
|
||||
|
||||
return images, cobra.ShellCompDirectiveKeepOrder | cobra.ShellCompDirectiveNoFileComp
|
||||
},
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue