Skip to content

Commit c99749f

Browse files
authored
cmd: Update each index instead of just default (#588)
* Update each index instead of just default * Fix linting issue * Split into two tests * Code review changes * Wrap error in search * Add integration tests Switch back to sequential updates. The test where gitutil.EnsureUpdated fails seems to hang when it happens in a goroutine for some reason. * Code review changes * Code review changes
1 parent b2b8a40 commit c99749f

File tree

10 files changed

+106
-42
lines changed

10 files changed

+106
-42
lines changed

cmd/krew/cmd/install.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ Remarks:
189189
klog.V(4).Infof("--no-update-index specified, skipping updating local copy of plugin index")
190190
return nil
191191
}
192-
return ensureIndexUpdated(cmd, args)
192+
return ensureIndexesUpdated(cmd, args)
193193
},
194194
}
195195

cmd/krew/cmd/search.go

+3-13
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import (
2727
"sigs.k8s.io/krew/internal/index/indexoperations"
2828
"sigs.k8s.io/krew/internal/index/indexscanner"
2929
"sigs.k8s.io/krew/internal/installation"
30-
"sigs.k8s.io/krew/pkg/constants"
3130
)
3231

3332
// searchCmd represents the search command
@@ -44,18 +43,9 @@ Examples:
4443
To fuzzy search plugins with a keyword:
4544
kubectl krew search KEYWORD`,
4645
RunE: func(cmd *cobra.Command, args []string) error {
47-
indexes := []indexoperations.Index{
48-
{
49-
Name: constants.DefaultIndexName,
50-
URL: constants.DefaultIndexURI, // unused here but providing for completeness
51-
},
52-
}
53-
if os.Getenv(constants.EnableMultiIndexSwitch) != "" {
54-
out, err := indexoperations.ListIndexes(paths)
55-
if err != nil {
56-
return errors.Wrapf(err, "failed to list plugin indexes available")
57-
}
58-
indexes = out
46+
indexes, err := indexoperations.ListIndexes(paths)
47+
if err != nil {
48+
return errors.Wrap(err, "failed to list indexes")
5949
}
6050

6151
klog.V(3).Infof("found %d indexes", len(indexes))

cmd/krew/cmd/system.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ This command will be removed without further notice from future versions of krew
5151
RunE: func(cmd *cobra.Command, args []string) error {
5252
return receiptsmigration.Migrate(paths)
5353
},
54-
PreRunE: ensureIndexUpdated,
54+
PreRunE: ensureIndexesUpdated,
5555
}
5656

5757
var indexUpgradeCmd = &cobra.Command{

cmd/krew/cmd/update.go

+23-6
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ import (
1919
"fmt"
2020
"io"
2121
"os"
22+
"strings"
2223

2324
"github.com/pkg/errors"
2425
"github.com/spf13/cobra"
2526
"k8s.io/klog"
2627

2728
"sigs.k8s.io/krew/internal/gitutil"
29+
"sigs.k8s.io/krew/internal/index/indexoperations"
2830
"sigs.k8s.io/krew/internal/index/indexscanner"
2931
"sigs.k8s.io/krew/internal/installation"
3032
"sigs.k8s.io/krew/pkg/constants"
@@ -43,7 +45,7 @@ plugin index from the internet.
4345
Remarks:
4446
You don't need to run this command: Running "krew update" or "krew upgrade"
4547
will silently run this command.`,
46-
RunE: ensureIndexUpdated,
48+
RunE: ensureIndexesUpdated,
4749
}
4850

4951
func showFormattedPluginsInfo(out io.Writer, header string, plugins []string) {
@@ -102,13 +104,28 @@ func showUpdatedPlugins(out io.Writer, preUpdate, posUpdate []index.Plugin, inst
102104
}
103105
}
104106

105-
func ensureIndexUpdated(_ *cobra.Command, _ []string) error {
107+
func ensureIndexesUpdated(_ *cobra.Command, _ []string) error {
106108
preUpdateIndex, _ := indexscanner.LoadPluginListFromFS(paths.IndexPluginsPath(constants.DefaultIndexName))
107109

108-
klog.V(1).Infof("Updating the local copy of plugin index (%s)", paths.IndexPath(constants.DefaultIndexName))
109-
if err := gitutil.EnsureUpdated(constants.DefaultIndexURI, paths.IndexPath(constants.DefaultIndexName)); err != nil {
110-
return errors.Wrap(err, "failed to update the local index")
110+
indexes, err := indexoperations.ListIndexes(paths)
111+
if err != nil {
112+
return errors.Wrap(err, "failed to list indexes")
111113
}
114+
115+
var failed []string
116+
var returnErr error
117+
for _, idx := range indexes {
118+
indexPath := paths.IndexPath(idx.Name)
119+
klog.V(1).Infof("Updating the local copy of plugin index (%s)", indexPath)
120+
if err := gitutil.EnsureUpdated(idx.URL, indexPath); err != nil {
121+
klog.Warningf("failed to update index %q: %v", idx.Name, err)
122+
failed = append(failed, idx.Name)
123+
if returnErr == nil {
124+
returnErr = err
125+
}
126+
}
127+
}
128+
112129
fmt.Fprintln(os.Stderr, "Updated the local copy of plugin index.")
113130

114131
if len(preUpdateIndex) == 0 {
@@ -132,7 +149,7 @@ func ensureIndexUpdated(_ *cobra.Command, _ []string) error {
132149
// TODO(chriskim06) consider commenting this out when refactoring for custom indexes
133150
showUpdatedPlugins(os.Stderr, preUpdateIndex, posUpdateIndex, installedPlugins)
134151

135-
return nil
152+
return errors.Wrapf(returnErr, "failed to update the following indexes: %s\n", strings.Join(failed, ", "))
136153
}
137154

138155
func init() {

cmd/krew/cmd/upgrade.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ kubectl krew upgrade foo bar"`,
106106
klog.V(4).Infof("--no-update-index specified, skipping updating local copy of plugin index")
107107
return nil
108108
}
109-
return ensureIndexUpdated(cmd, args)
109+
return ensureIndexesUpdated(cmd, args)
110110
},
111111
}
112112

integration_test/index_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ func TestKrewIndexRemove_unsafe(t *testing.T) {
150150
func TestKrewIndexRemoveFailsWhenPluginsInstalled(t *testing.T) {
151151
skipShort(t)
152152
test, cleanup := NewTest(t)
153-
test = test.WithEnv(constants.EnableMultiIndexSwitch, 1)
153+
test = test.WithEnv(constants.EnableMultiIndexSwitch, 1).WithIndex()
154154
defer cleanup()
155155

156156
test.Krew("install", validPlugin).RunOrFailOutput()

integration_test/update_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,52 @@ func TestKrewUpdate(t *testing.T) {
4949
}
5050
}
5151

52+
func TestKrewUpdateMultipleIndexes(t *testing.T) {
53+
skipShort(t)
54+
test, cleanup := NewTest(t)
55+
defer cleanup()
56+
57+
test = test.WithEnv(constants.EnableMultiIndexSwitch, 1).WithIndex()
58+
// to enable new paths in environment.NewPaths()
59+
os.Setenv(constants.EnableMultiIndexSwitch, "1")
60+
defer os.Unsetenv(constants.EnableMultiIndexSwitch)
61+
62+
paths := environment.NewPaths(test.Root())
63+
test.Krew("index", "add", "foo", paths.IndexPath(constants.DefaultIndexName)).RunOrFail()
64+
if err := os.RemoveAll(paths.IndexPluginsPath("foo")); err != nil {
65+
t.Errorf("error removing plugins directory from index: %s", err)
66+
}
67+
test.Krew("update").RunOrFailOutput()
68+
out := string(test.Krew("search").RunOrFailOutput())
69+
if !strings.Contains(out, "\nctx") {
70+
t.Error("expected plugin ctx in list of plugins")
71+
}
72+
if !strings.Contains(out, "foo/ctx") {
73+
t.Error("expected plugin foo/ctx in list of plugins")
74+
}
75+
}
76+
77+
func TestKrewUpdateFailedIndex(t *testing.T) {
78+
skipShort(t)
79+
test, cleanup := NewTest(t)
80+
defer cleanup()
81+
82+
test = test.WithEnv(constants.EnableMultiIndexSwitch, 1).WithIndex()
83+
os.Setenv(constants.EnableMultiIndexSwitch, "1")
84+
defer os.Unsetenv(constants.EnableMultiIndexSwitch)
85+
86+
paths := environment.NewPaths(test.Root())
87+
test.TempDir().InitEmptyGitRepo(paths.IndexPath("foo"), "invalid-git")
88+
out, err := test.Krew("update").Run()
89+
if err == nil {
90+
t.Error("expected update to fail")
91+
}
92+
msg := "failed to update the following indexes: foo"
93+
if !strings.Contains(string(out), msg) {
94+
t.Errorf("%q doesn't contain msg=%q", string(out), msg)
95+
}
96+
}
97+
5298
func TestKrewUpdateListsNewPlugins(t *testing.T) {
5399
skipShort(t)
54100
test, cleanup := NewTest(t)

internal/index/indexoperations/index.go

+10
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323

2424
"sigs.k8s.io/krew/internal/environment"
2525
"sigs.k8s.io/krew/internal/gitutil"
26+
"sigs.k8s.io/krew/pkg/constants"
2627
)
2728

2829
var validNamePattern = regexp.MustCompile(`^[A-Za-z0-9_-]+$`)
@@ -36,6 +37,15 @@ type Index struct {
3637
// ListIndexes returns a slice of Index objects. The path argument is used as
3738
// the base path of the index.
3839
func ListIndexes(paths environment.Paths) ([]Index, error) {
40+
if _, ok := os.LookupEnv(constants.EnableMultiIndexSwitch); !ok {
41+
return []Index{
42+
{
43+
Name: constants.DefaultIndexName,
44+
URL: constants.DefaultIndexURI,
45+
},
46+
}, nil
47+
}
48+
3949
dirs, err := ioutil.ReadDir(paths.IndexBase())
4050
if err != nil {
4151
return nil, errors.Wrap(err, "failed to list directory")

internal/index/indexoperations/index_test.go

+4-19
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"github.com/google/go-cmp/cmp"
2323

2424
"sigs.k8s.io/krew/internal/environment"
25-
"sigs.k8s.io/krew/internal/gitutil"
2625
"sigs.k8s.io/krew/internal/testutil"
2726
"sigs.k8s.io/krew/pkg/constants"
2827
)
@@ -49,7 +48,7 @@ func TestListIndexes(t *testing.T) {
4948
paths := environment.NewPaths(tmpDir.Root())
5049
for _, index := range wantIndexes {
5150
path := paths.IndexPath(index.Name)
52-
initEmptyGitRepo(t, path, index.URL)
51+
tmpDir.InitEmptyGitRepo(path, index.URL)
5352
}
5453

5554
gotIndexes, err := ListIndexes(paths)
@@ -71,7 +70,7 @@ func TestAddIndexSuccess(t *testing.T) {
7170

7271
indexName := "foo"
7372
localRepo := tmpDir.Path("local/" + indexName)
74-
initEmptyGitRepo(t, localRepo, "")
73+
tmpDir.InitEmptyGitRepo(localRepo, "")
7574

7675
paths := environment.NewPaths(tmpDir.Root())
7776
if err := AddIndex(paths, indexName, localRepo); err != nil {
@@ -107,8 +106,8 @@ func TestAddIndexFailure(t *testing.T) {
107106
}
108107

109108
localRepo := tmpDir.Path("local/" + indexName)
110-
initEmptyGitRepo(t, tmpDir.Path("index/"+indexName), "")
111-
initEmptyGitRepo(t, localRepo, "")
109+
tmpDir.InitEmptyGitRepo(tmpDir.Path("index/"+indexName), "")
110+
tmpDir.InitEmptyGitRepo(localRepo, "")
112111

113112
if err := AddIndex(paths, indexName, localRepo); err == nil {
114113
t.Error("expected error when adding an index that already exists")
@@ -151,20 +150,6 @@ func TestDeleteIndex(t *testing.T) {
151150
}
152151
}
153152

154-
func initEmptyGitRepo(t *testing.T, path, url string) {
155-
t.Helper()
156-
157-
if err := os.MkdirAll(path, os.ModePerm); err != nil {
158-
t.Fatalf("cannot create directory %q: %s", filepath.Dir(path), err)
159-
}
160-
if _, err := gitutil.Exec(path, "init"); err != nil {
161-
t.Fatalf("error initializing git repo: %s", err)
162-
}
163-
if _, err := gitutil.Exec(path, "remote", "add", "origin", url); err != nil {
164-
t.Fatalf("error setting remote origin: %s", err)
165-
}
166-
}
167-
168153
func TestIsValidIndexName(t *testing.T) {
169154
tests := []struct {
170155
name string

internal/testutil/tempdir.go

+16
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323
"testing"
2424

2525
"sigs.k8s.io/yaml"
26+
27+
"sigs.k8s.io/krew/internal/gitutil"
2628
)
2729

2830
type TempDir struct {
@@ -83,3 +85,17 @@ func (td *TempDir) WriteYAML(file string, obj interface{}) *TempDir {
8385
}
8486
return td.Write(file, content)
8587
}
88+
89+
func (td *TempDir) InitEmptyGitRepo(path, url string) {
90+
td.t.Helper()
91+
92+
if err := os.MkdirAll(path, os.ModePerm); err != nil {
93+
td.t.Fatalf("cannot create directory %q: %s", filepath.Dir(path), err)
94+
}
95+
if _, err := gitutil.Exec(path, "init"); err != nil {
96+
td.t.Fatalf("error initializing git repo: %s", err)
97+
}
98+
if _, err := gitutil.Exec(path, "remote", "add", "origin", url); err != nil {
99+
td.t.Fatalf("error setting remote origin: %s", err)
100+
}
101+
}

0 commit comments

Comments
 (0)