feat: run with hub completion

Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
This commit is contained in:
Alano Terblanche 2024-10-09 16:19:09 +02:00
parent f4c164d9b8
commit 5760a3d201
No known key found for this signature in database
GPG Key ID: 0E8FACD1BA98DE27
5 changed files with 19 additions and 14 deletions

View File

@ -223,6 +223,7 @@ type Image struct {
Creator int `json:"creator"` Creator int `json:"creator"`
Repository int `json:"repository"` Repository int `json:"repository"`
} }
type ImageTags struct { type ImageTags struct {
Count int `json:"count"` Count int `json:"count"`
Next string `json:"next"` Next string `json:"next"`
@ -230,7 +231,7 @@ type ImageTags struct {
Results []Image `json:"results"` Results []Image `json:"results"`
} }
func Images(cmd *cobra.Command, arg []string, toComplete string) ([]string, cobra.ShellCompDirective) { func RemoteImages(cmd *cobra.Command, arg []string, toComplete string) ([]string, cobra.ShellCompDirective) {
ctx := cmd.Context() ctx := cmd.Context()
c := &http.Client{ c := &http.Client{
Timeout: 2 * time.Second, Timeout: 2 * time.Second,
@ -259,7 +260,6 @@ func Images(cmd *cobra.Command, arg []string, toComplete string) ([]string, cobr
logrus.Errorf("Error sending hub image tags request: %v", err) logrus.Errorf("Error sending hub image tags request: %v", err)
return nil, cobra.ShellCompDirectiveError return nil, cobra.ShellCompDirectiveError
} }
defer resp.Body.Close() defer resp.Body.Close()
var tags *ImageTags var tags *ImageTags
@ -278,7 +278,7 @@ func Images(cmd *cobra.Command, arg []string, toComplete string) ([]string, cobr
u, err := url.Parse("https://hub.docker.com/api/search/v3/catalog/search") u, err := url.Parse("https://hub.docker.com/api/search/v3/catalog/search")
if err != nil { if err != nil {
logrus.Errorf("Error parsing hub image search URL: %v", err) logrus.Errorf("Error parsing hub image search URL: %v", err)
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveError
} }
q := u.Query() q := u.Query()
q.Set("query", toComplete) q.Set("query", toComplete)
@ -290,20 +290,20 @@ func Images(cmd *cobra.Command, arg []string, toComplete string) ([]string, cobr
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
if err != nil { if err != nil {
logrus.Errorf("Error creating hub image search request: %v", err) logrus.Errorf("Error creating hub image search request: %v", err)
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveError
} }
resp, err := c.Do(req) resp, err := c.Do(req)
if err != nil { if err != nil {
logrus.Errorf("Error sending hub image search request: %v", err) logrus.Errorf("Error sending hub image search request: %v", err)
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveError
} }
defer resp.Body.Close() defer resp.Body.Close()
var images *ImageSearch var images *ImageSearch
if err := json.NewDecoder(resp.Body).Decode(&images); err != nil { if err := json.NewDecoder(resp.Body).Decode(&images); err != nil {
logrus.Errorf("Error decoding hub image search response: %v", err) logrus.Errorf("Error decoding hub image search response: %v", err)
return nil, cobra.ShellCompDirectiveNoFileComp return nil, cobra.ShellCompDirectiveError
} }
names := make([]string, 0, len(images.Results)) names := make([]string, 0, len(images.Results))

View File

@ -37,13 +37,18 @@ func NewRunCommand(dockerCli command.Cli) *cobra.Command {
Short: "Create and run a new container from an image", Short: "Create and run a new container from an image",
Args: cli.RequiresMinArgs(1), Args: cli.RequiresMinArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
copts.Image = args[0] replacer := strings.NewReplacer("(local)", "", "(remote)", "")
copts.Image = replacer.Replace(args[0])
if len(args) > 1 { if len(args) > 1 {
copts.Args = args[1:] copts.Args = args[1:]
} }
return runRun(cmd.Context(), dockerCli, cmd.Flags(), &options, copts) return runRun(cmd.Context(), dockerCli, cmd.Flags(), &options, copts)
}, },
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) > 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
unique := map[string]struct{}{} unique := map[string]struct{}{}
localImages, shellComp := completion.ImageNames(dockerCli)(cmd, args, toComplete) localImages, shellComp := completion.ImageNames(dockerCli)(cmd, args, toComplete)
@ -52,23 +57,23 @@ func NewRunCommand(dockerCli command.Cli) *cobra.Command {
all = make([]string, 0, len(localImages)) all = make([]string, 0, len(localImages))
for _, img := range localImages { for _, img := range localImages {
unique[img] = struct{}{} unique[img] = struct{}{}
all = append(all, fmt.Sprintf("%s\tlocal", img)) all = append(all, img+"\tlocal")
} }
} }
remoteImages, shellCompRemote := completion.Images(cmd, args, toComplete) remoteImages, shellCompRemote := completion.RemoteImages(cmd, args, toComplete)
if shellCompRemote != cobra.ShellCompDirectiveError { if shellCompRemote != cobra.ShellCompDirectiveError {
if len(all) == 0 { if len(all) == 0 {
all = make([]string, 0, len(remoteImages)) all = make([]string, 0, len(remoteImages))
} }
for _, img := range remoteImages { for _, img := range remoteImages {
if _, ok := unique[img]; !ok { if _, ok := unique[img]; !ok {
all = append(all, fmt.Sprintf("%s\tremote", img)) all = append(all, img+"\tremote")
} }
} }
} }
return all, cobra.ShellCompDirectiveKeepOrder | cobra.ShellCompDirectiveNoFileComp | cobra.ShellCompDirectiveDefault return all, cobra.ShellCompDirectiveKeepOrder | cobra.ShellCompDirectiveNoFileComp
}, },
Annotations: map[string]string{ Annotations: map[string]string{
"category-top": "1", "category-top": "1",

View File

@ -43,7 +43,7 @@ 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.Images(cmd, args, toComplete) return completion.RemoteImages(cmd, args, toComplete)
}, },
} }

View File

@ -92,7 +92,7 @@ func newDockerCommand(dockerCli *command.DockerCli) *cli.TopLevelCommand {
CompletionOptions: cobra.CompletionOptions{ CompletionOptions: cobra.CompletionOptions{
DisableDefaultCmd: false, DisableDefaultCmd: false,
HiddenDefaultCmd: true, HiddenDefaultCmd: true,
DisableDescriptions: true, DisableDescriptions: false,
}, },
} }
cmd.SetIn(dockerCli.In()) cmd.SetIn(dockerCli.In())

View File

@ -24,6 +24,6 @@ if [ "$(go env GOOS)" = "windows" ]; then
fi fi
fi fi
(set -x ; go build -o "${TARGET}" -tags "${GO_BUILDTAGS}" -ldflags "${GO_LDFLAGS}" ${GO_BUILDMODE} -buildvcs=false "${SOURCE}") (set -x ; go build -o "${TARGET}" -tags "${GO_BUILDTAGS}" -ldflags "${GO_LDFLAGS}" ${GO_BUILDMODE} "${SOURCE}")
ln -sf "$(basename "${TARGET}")" "$(dirname "${TARGET}")/docker" ln -sf "$(basename "${TARGET}")" "$(dirname "${TARGET}")/docker"