Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add index add command #545

Merged
merged 12 commits into from
Mar 16, 2020
Merged

Conversation

chriskim06
Copy link
Member

Relatively small change. The majority of it is the test I added. I wasn't sure how to test the case where an index is added since it relies on git to clone the repo, so the only test cases I have are negative ones where the index with a name has already been configured and an invalid url is provided for the clone operation. I was thinking of using constants.IndexURI in a test case but didn't like that the unit test would need to be able to reach github so I didn't add it.

Related issue: #483

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Mar 10, 2020
Example:
kubectl krew index add index-name index-url`,
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) != 2 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cobra supports this natively. You can set minargs 2


err := indexoperations.AddIndex(paths.IndexBase(), args[0], args[1])
if err != nil {
return errors.Wrapf(err, "failed to add index %s: %s", args[0], args[1])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to print args back again

cmd/krew/cmd/index.go Outdated Show resolved Hide resolved
cmd/krew/cmd/index.go Outdated Show resolved Hide resolved
var indexAddCmd = &cobra.Command{
Use: "add",
Short: "Add a new index",
Long: `Configure a new index to install plugins from.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See if you can name the positional args.
Like NAME GIT_URL.
Cobra probably has facilities to do that.

@ahmetb
Copy link
Member

ahmetb commented Mar 10, 2020

Please add CLI integration tests to ./integration_test.

Copy link
Contributor

@corneliusweig corneliusweig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's really great that you take small steps. This makes reviewing so much easier 👍!

internal/index/indexoperations/index_test.go Outdated Show resolved Hide resolved
internal/index/indexoperations/index.go Show resolved Hide resolved
}

indexName := "foo"
test.Krew("index", "add", indexName, constants.IndexURI).RunOrFail()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add/list should have separate tests ideally.

But for this you can merge them but make sure test name reflects that. Refer to other integration tests for an idea on how to develop. We test cli scenario and behavior here.

For example you don’t test 0 args fails case here :)

@@ -171,6 +173,13 @@ func (it *ITest) WithIndex() *ITest {
return it
}

// WithMigratedIndex initializes the index and performs the index migration.
Copy link
Member

@ahmetb ahmetb Mar 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add TODO for deletion, ditto migrateIndex.

Why don’t we use the env variable for behavior change in initializeIndex instead? Simple if can solve this but you added 2 methods to be removed for it. :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea, I'll change it

@ahmetb
Copy link
Member

ahmetb commented Mar 11, 2020

@chriskim06 does the code handle this case?

krew index add ../../../usr/bin [REPO]

we need sanity checks around names to ensure they don't serve path escapes.

@chriskim06
Copy link
Member Author

I didn't think about that, I'll add those checks.

Comment on lines 65 to 70
err := indexoperations.AddIndex(paths.IndexBase(), args[0], args[1])
if err != nil {
return errors.Wrap(err, "failed to add index")
}
klog.Infoln("Successfully added index")
return nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

honestly this entire func can be 1 line :)
we'd know the success from the command execution anyway, so no need to log that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought that it seemed a little nicer with some explicit validation (similar to index/receipt migration) but am fine either way. I'll remove it.


// AddIndex initializes a new index to install plugins from.
func AddIndex(path, name, url string) error {
if strings.ContainsAny(name, "./") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as you might imagine this won't work on Windows

please use os.PathSeparator

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider extracting this to IsValidIndexName method and check for further things, like spaces, \ /, . ... + add unit tests + reuse everywhere (add, delete, ...)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even easier, we could simply restrict index names to k8s resource names (see https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-subdomain-names). Hopefully, there is a k8s tool that we can just use?

Copy link
Member Author

@chriskim06 chriskim06 Mar 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like IsValidPathSegmentName? Although that doesn't check \

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's start restrictive, we can relax as we need.
Honestly, something like [A-Za-z0-9_-] is good enough and safest for now. Let's make it a method regardless as I'm intending to reuse in other places.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, finally found it: https://github.com/kubernetes/kubernetes/blob/fdb2cb4c8832da1499069bda918c014762d8ac05/staging/src/k8s.io/apimachinery/pkg/util/validation/validation.go#L203

If we can, let's use it. Then we get all the goodness with names starting with alpha characters.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you 100% sure that string supports all repo names on github. If so, let's use it. If not, let's stick to something more relevant.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like GitHub also allows dots in repo names, i.e. [A-Za-z0-9_-.]+. And it does not care whether a repo name starts with an alpha character or _-.. So if we want to support everything that GitHub does, the current pattern is better.

integration_test/index_test.go Show resolved Hide resolved
integration_test/index_test.go Outdated Show resolved Hide resolved
integration_test/index_test.go Outdated Show resolved Hide resolved
integration_test/index_test.go Outdated Show resolved Hide resolved
integration_test/testutil_test.go Show resolved Hide resolved

// AddIndex initializes a new index to install plugins from.
func AddIndex(path, name, url string) error {
if strings.ContainsAny(name, "./") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even easier, we could simply restrict index names to k8s resource names (see https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-subdomain-names). Hopefully, there is a k8s tool that we can just use?

internal/index/indexoperations/index.go Outdated Show resolved Hide resolved

if err := AddIndex(tmpDir.Path("index"), indexName, localRepo); err != nil {
t.Errorf("error adding index: %v", err)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO, you should also test that AddIndex has actually done something.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To do that, you can have a combined Add+List scenario.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That way you can also move away from doing manual mkdir/clone in the test code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chriskim06 What's your opinion about using the ListIndex machinery for the assertion?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure I can change it to use that.

Comment on lines 51 to 54
if len(indexes) == 0 {
klog.Info(indexoperations.NoIndexMessage)
return nil
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's not do this here.

We can do that when user tries to query a plugin (krew install, krew update, krew upgrade etc) but there's no plugins installed.

Furthermore klog isn't good for this. we probably should use fmt.Fprintf or something like that with color pkg.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I think this command should still print an "empty table".

We need to print the output properly to stderr so it doesn't get mixed up with other stuff.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean it should still print:

INDEX  URL

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. That’s expected. Like krew list.

Comment on lines 79 to 85
if !strings.Contains(string(out), indexoperations.NoIndexMessage) {
t.Fatalf("expected index list to be empty:\n%s", string(out))
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

testing with messages isn't good practice, let's not do that.
the previous test was good.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I'll change it back

)

var (
NoIndexMessage = "No index configured, run kubectl krew index add default " + constants.IndexURI + " to get started"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not do this here. We should ideally implement this in cmd/krew pkg as a func PrintDefaultIndexSuggestion().

Index commands are for pro-users, so most users should be realizing they miss an index while using main user cmds (install, search, update etc). "index" cmds are mgmt cmds, so they ideally shouldn't print these.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll just remove this for now then since I'm not covering the main user cmds in this PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah sgtm. We’ll handle the scenario later.

Comment on lines 98 to 146
if IsValidIndexName(" ") {
t.Error("name cannot contain spaces")
}
if IsValidIndexName("foo/bar") {
t.Error("name cannot contain forward slashes")
}
if IsValidIndexName("foo\\bar") {
t.Error("name cannot contain back slashes")
}
if IsValidIndexName("foo.bar") {
t.Error("name cannot contain forward periods")
}
if !IsValidIndexName("foo") {
t.Error("expected valid index name: foo")
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this actually would be the perfect use case for tabular tests :)

Comment on lines 44 to 45
if os.IsNotExist(err) {
return nil, nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: now that we ensure that index/ is present on startup, this error case no longer needs to be treated in a special way.

// AddIndex initializes a new index to install plugins from.
func AddIndex(path, name, url string) error {
if !IsValidIndexName(name) {
return errors.New("index name cannot contain path characters")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That error is no longer accurate.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about something like "index name can only contain alphanumeric characters, -, and _"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just say “invalid index name”.
In a separate PR you can return an error from the validation func and wrap it here :)


if err := AddIndex(tmpDir.Path("index"), indexName, localRepo); err != nil {
t.Errorf("error adding index: %v", err)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chriskim06 What's your opinion about using the ListIndex machinery for the assertion?


// AddIndex initializes a new index to install plugins from.
func AddIndex(path, name, url string) error {
if strings.ContainsAny(name, "./") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like GitHub also allows dots in repo names, i.e. [A-Za-z0-9_-.]+. And it does not care whether a repo name starts with an alpha character or _-.. So if we want to support everything that GitHub does, the current pattern is better.

Copy link
Contributor

@corneliusweig corneliusweig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, I think we are almost there. Just smaller final nits from my side. 👍

chriskim06 and others added 12 commits March 15, 2020 15:50
Add success case to unit test and add initial integration test for index
command
Remove test table to make it easier to read and split into separate
tests for failure and success cases
Print empty index list and convert valid index name to use test tables
Co-Authored-By: Cornelius Weig <22861411+corneliusweig@users.noreply.github.com>
Use ListIndexes in add test and fix error message
@ahmetb
Copy link
Member

ahmetb commented Mar 16, 2020

/lgtm
/approve

Thanks @chriskim06 for pushing it through.
Thanks @corneliusweig for thorough reviews!

I'll be making several followup PRs to clean up a few things!
I also have a patch ready for krew index delete.

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Mar 16, 2020
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: ahmetb, chriskim06

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 16, 2020
@k8s-ci-robot k8s-ci-robot merged commit 1201796 into kubernetes-sigs:master Mar 16, 2020
@chriskim06 chriskim06 deleted the index-add branch June 11, 2020 15:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. area/multi-index cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants