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
|
package completion
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/docker/cli/cli/command/formatter"
|
"github.com/docker/cli/cli/command/formatter"
|
||||||
"github.com/docker/docker/api/types/container"
|
"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/network"
|
||||||
"github.com/docker/docker/api/types/volume"
|
"github.com/docker/docker/api/types/volume"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -194,122 +189,3 @@ var commonPlatforms = []string{
|
||||||
func Platforms(_ *cobra.Command, _ []string, _ string) (platforms []string, _ cobra.ShellCompDirective) {
|
func Platforms(_ *cobra.Command, _ []string, _ string) (platforms []string, _ cobra.ShellCompDirective) {
|
||||||
return commonPlatforms, cobra.ShellCompDirectiveNoFileComp
|
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/cli/command/completion"
|
||||||
"github.com/docker/cli/opts"
|
"github.com/docker/cli/opts"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
|
"github.com/docker/docker/api/types/hub"
|
||||||
"github.com/moby/sys/signal"
|
"github.com/moby/sys/signal"
|
||||||
"github.com/moby/term"
|
"github.com/moby/term"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -61,14 +62,44 @@ func NewRunCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteImages, shellCompRemote := completion.RemoteImages(cmd, args, toComplete)
|
if image, tag, found := strings.Cut(toComplete, ":"); found {
|
||||||
if shellCompRemote != cobra.ShellCompDirectiveError {
|
remoteTags, err := dockerCli.Client().ImageHubTags(cmd.Context(), image, hub.ImageOptions{
|
||||||
if len(all) == 0 {
|
Name: tag,
|
||||||
all = make([]string, 0, len(remoteImages))
|
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 {
|
return all, cobra.ShellCompDirectiveKeepOrder | cobra.ShellCompDirectiveNoFileComp
|
||||||
if _, ok := unique[img]; !ok {
|
}
|
||||||
all = append(all, img+"\tremote")
|
|
||||||
|
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"
|
||||||
"github.com/docker/cli/cli/command/completion"
|
"github.com/docker/cli/cli/command/completion"
|
||||||
"github.com/docker/cli/cli/trust"
|
"github.com/docker/cli/cli/trust"
|
||||||
|
"github.com/docker/docker/api/types/hub"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -43,7 +44,50 @@ func NewPullCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
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