Skip to content

Commit 651aa79

Browse files
Implement auto complete for --image(-i) flag (#2449)
1 parent 9f12361 commit 651aa79

File tree

4 files changed

+97
-0
lines changed

4 files changed

+97
-0
lines changed

internal/cmdcomplete/complete.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package cmdcomplete
1818
import (
1919
"strings"
2020

21+
"github.com/GoogleContainerTools/kpt/internal/util/cmdutil"
2122
kptfilev1 "github.com/GoogleContainerTools/kpt/pkg/api/kptfile/v1"
2223
"github.com/posener/complete/v2"
2324
"github.com/posener/complete/v2/predict"
@@ -67,6 +68,12 @@ func Complete(cmd *cobra.Command, skipHelp bool, visitFlags VisitFlags) *complet
6768
cc.Flags[flag.Name] = predict.Options(predict.OptValues("%k_%n.yaml"))
6869
return
6970
}
71+
if flag.Name == "image" || flag.Shorthand == "i" {
72+
fnImages := cmdutil.FetchFunctionImages()
73+
cc.Flags[flag.Name] = predict.Options(predict.OptValues(fnImages...))
74+
cc.Flags[flag.Shorthand] = predict.Options(predict.OptValues(fnImages...))
75+
return
76+
}
7077
cc.Flags[flag.Name] = predict.Nothing
7178
})
7279

internal/util/cmdutil/cmdutil.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package cmdutil
1717
import (
1818
"bytes"
1919
"context"
20+
"encoding/json"
2021
"fmt"
2122
"io"
2223
"os"
@@ -26,6 +27,7 @@ import (
2627
"time"
2728

2829
"github.com/GoogleContainerTools/kpt/internal/fnruntime"
30+
"github.com/GoogleContainerTools/kpt/internal/util/httputil"
2931
"github.com/spf13/cobra"
3032
"sigs.k8s.io/kustomize/kyaml/kio"
3133
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
@@ -37,6 +39,7 @@ const (
3739
Stdout = "stdout"
3840
Unwrap = "unwrap"
3941
dockerVersionTimeout time.Duration = 5 * time.Second
42+
FunctionsCatalogURL = "https://catalog.kpt.dev/catalog.json"
4043
)
4144

4245
// FixDocs replaces instances of old with new in the docs for c
@@ -178,3 +181,33 @@ func CheckDirectoryNotPresent(outDir string) error {
178181
}
179182
return nil
180183
}
184+
185+
// FetchFunctionImages returns the list of latest function images from catalog.kpt.dev
186+
func FetchFunctionImages() []string {
187+
content, err := httputil.FetchContent(FunctionsCatalogURL)
188+
if err != nil {
189+
return nil
190+
}
191+
192+
return listImages(content)
193+
}
194+
195+
// listImages returns the list of latest images from the input catalog content
196+
func listImages(content string) []string {
197+
var result []string
198+
jsonData := map[string]map[string]interface{}{}
199+
err := json.Unmarshal([]byte(content), &jsonData)
200+
if err != nil {
201+
return result
202+
}
203+
for fnName, fnInfo := range jsonData {
204+
var latestVersion string
205+
for version := range fnInfo {
206+
if latestVersion < version {
207+
latestVersion = version
208+
}
209+
}
210+
result = append(result, fmt.Sprintf("%s:%s", fnName, latestVersion))
211+
}
212+
return result
213+
}

internal/util/cmdutil/cmdutil_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"io/ioutil"
2020
"os"
2121
"path/filepath"
22+
"sort"
2223
"testing"
2324

2425
"github.com/stretchr/testify/assert"
@@ -305,3 +306,35 @@ metadata:
305306
})
306307
}
307308
}
309+
310+
func TestListImages(t *testing.T) {
311+
result := listImages(`{
312+
"apply-setters": {
313+
"v0.1": {
314+
"apply-setters-simple": {
315+
"LocalExamplePath": "/apply-setters/v0.1/apply-setters-simple",
316+
"RemoteExamplePath": "https://github.com/GoogleContainerTools/kpt-functions-catalog/tree/apply-setters/v0.1/examples/apply-setters-simple",
317+
"RemoteSourcePath": "https://github.com/GoogleContainerTools/kpt-functions-catalog/tree/apply-setters/v0.1/functions/go/apply-setters"
318+
}
319+
}
320+
},
321+
"gatekeeper": {
322+
"v0.1": {
323+
"gatekeeper-warning-only": {
324+
"LocalExamplePath": "/gatekeeper/v0.1/gatekeeper-warning-only",
325+
"RemoteExamplePath": "https://github.com/GoogleContainerTools/kpt-functions-catalog/tree/gatekeeper/v0.1/examples/gatekeeper-warning-only",
326+
"RemoteSourcePath": "https://github.com/GoogleContainerTools/kpt-functions-catalog/tree/gatekeeper/v0.1/functions/go/gatekeeper"
327+
}
328+
},
329+
"v0.2": {
330+
"gatekeeper-warning-only": {
331+
"LocalExamplePath": "/gatekeeper/v0.2/gatekeeper-warning-only",
332+
"RemoteExamplePath": "https://github.com/GoogleContainerTools/kpt-functions-catalog/tree/gatekeeper/v0.2/examples/gatekeeper-warning-only",
333+
"RemoteSourcePath": "https://github.com/GoogleContainerTools/kpt-functions-catalog/tree/gatekeeper/v0.2/functions/go/gatekeeper"
334+
}
335+
}
336+
}
337+
}`)
338+
sort.Strings(result)
339+
assert.Equal(t, []string{"apply-setters:v0.1", "gatekeeper:v0.2"}, result)
340+
}

internal/util/httputil/httputil.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package httputil
2+
3+
import (
4+
"io/ioutil"
5+
"net/http"
6+
)
7+
8+
// FetchContent fetches the content from the input url
9+
func FetchContent(url string) (string, error) {
10+
req, err := http.NewRequest("GET", url, nil)
11+
if err != nil {
12+
return "", err
13+
}
14+
res, err := http.DefaultClient.Do(req)
15+
if err != nil {
16+
return "", err
17+
}
18+
defer res.Body.Close()
19+
body, err := ioutil.ReadAll(res.Body)
20+
if err != nil {
21+
return "", err
22+
}
23+
return string(body), nil
24+
}

0 commit comments

Comments
 (0)