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
Shell completion of multiple resource names #105711
Shell completion of multiple resource names #105711
Conversation
@marckhouzam: GitHub didn't allow me to request PR reviews from the following users: phil9909. Note that only kubernetes members and repo collaborators can review this PR, and authors cannot review their own PRs. In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@marckhouzam: This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the The Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
Hi @marckhouzam. Thanks for your PR. I'm waiting for a kubernetes member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
/sig cli |
/ok-to-test |
/retest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. I left a few comments, but this looks like a good improvement to completions.
@@ -733,3 +733,21 @@ func Warning(cmdErr io.Writer, newGeneratorName, oldGeneratorName string) { | |||
oldGeneratorName, | |||
) | |||
} | |||
|
|||
// Unique removes any elements of subArray from fullArray and returns the result | |||
func Unique(fullArray []string, subArray []string) []string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It took me a couple of looks to realize what this function is doing.
It is called Unique
but it does not de-duplicate items in the fullArray
, it only removes them if their exist in subArray
. That's fine, but I think the name could be more accurate for its purpose.
Might I suggest Exclude()
as a name? Or Difference()
(which I think would be the term for this in set theory)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. Unique()
is a very poor name in this case. Let's go with Difference()
since it is used in Set theory.
var result []string | ||
for _, elem := range fullArray { | ||
found := false | ||
for _, subElem := range subArray { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know subArray
is usually going to be pretty small in your particular use case, but I think this could be a little simpler and more efficient by using a map instead of nested loops.
For example, something like this is what I'm thinking:
exclude := make(map[string]bool)
for _, elem := range subArray {
exclude[elem] = true
}
var result []string
for _, elem := range fullArray {
if _, found := exclude[elem]; !found {
result = append(result, elem)
}
}
return result
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good optimization. I will use it. Thanks.
@@ -733,3 +733,21 @@ func Warning(cmdErr io.Writer, newGeneratorName, oldGeneratorName string) { | |||
oldGeneratorName, | |||
) | |||
} | |||
|
|||
// Unique removes any elements of subArray from fullArray and returns the result | |||
func Unique(fullArray []string, subArray []string) []string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we get a unit test for this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
I needed a function to check if two arrays were equal so I created checkArrayEqual()
, but if you know of an existing function that does that, please let me know.
e3d6d2d
to
d982df1
Compare
Thanks for the review @brianpursley, I believe the latest version addresses your comments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Tried it out locally and seems to work well. Nice work.
/assign @eddiezane |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is awesome! Thanks for adding. A few nits to address and then lgtm.
@@ -321,3 +322,43 @@ func TestDumpReaderToFile(t *testing.T) { | |||
t.Fatalf("Wrong file content %s != %s", testString, stringData) | |||
} | |||
} | |||
|
|||
func TestDifferenceFunc(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Let's use table driven tests here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much better. Thanks for pointing it out.
} | ||
} | ||
|
||
func checkArrayEqual(arr1, arr2 []string) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already use go-cmp in kubectl and can use it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
defer tf.Cleanup() | ||
|
||
pods, _, _ := cmdtesting.TestData() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use
tf, cmd := prepareCompletionTest()
addPodsToFactory(tf)
like above for these three tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know what happened there. I created the common functions when moving to Go completions but forgot to use them for the other tests 😮
I fixed all of them. Thanks for catching that!
This commit teaches the completion function to repeat resource names when supported by the command. The logic checks if a resource name has already been specified by the user and does not include it again when repeating the completion. For example, the get command can receive multiple pods names, therefore with this commit we have: kubectl get pod pod1 [tab] will provide completion of pod names again, but not show 'pod1' since it is already part of the command-line. The improvement affects the following commands: - annotate - apply edit-last-applied - apply view-last-applied - autoscale - delete - describe - edit - expose - get - label - patch - rollout history - rollout pause - rollout restart - rollout resume - rollout undo - scale - taint Note that "rollout status" only accepts a single resource name, unlike the other "rollout ..." commands; this required the creation of a special completion function that did not repeat just for that case. Signed-off-by: Marc Khouzam <marc.khouzam@montreal.ca>
d982df1
to
7aa5cb4
Compare
Ready again @eddiezane |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/lgtm
/approve
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: brianpursley, eddiezane, marckhouzam 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 |
/retest |
What type of PR is this?
/kind feature
What this PR does / why we need it:
This PR teaches the completion functions to repeat resource names when applicable and supported. The logic checks if a resource name has already been specified by the user and does not include it again when repeating the completion.
For example, the
get
command can receive multiple pods names, therefore with this commit:kubectl get pod pod1 [tab]
will provide completion of pod names again, but not show
pod1
a second time since it is already part of the command-line.The improvement affects the following commands:
Note that "rollout status" only accepts a single resource name, unlike the other "rollout ..." commands; this required the creation of a special completion function that did not repeat just for that case.
Which issue(s) this PR fixes:
Replaces #101427
Special notes for your reviewer:
The PR adds a utility function to remove a list of values from an array. It is used to prevent the completion from suggesting choices that are already on the command-line (as explained above). I don't know if such a utility already existed in the code base or if I put it in the right place (
cmd/util/helpers.go#Unique(..)
)Does this PR introduce a user-facing change?
/cc @phil9909