Skip to content

Support shell completion in vic-machine#7785

Merged
zjs merged 4 commits intovmware:masterfrom
zjs:topic/bash-completion
Apr 26, 2018
Merged

Support shell completion in vic-machine#7785
zjs merged 4 commits intovmware:masterfrom
zjs:topic/bash-completion

Conversation

@zjs
Copy link
Member

@zjs zjs commented Apr 19, 2018

Implement a cli.BashCompleteFunc factory and use it to supply an appropriate instance with each cli.Command in vic-machine.


To try this functionality on Linux, you could run the following command after checking out and building this topic branch. (Replace linux with darwin or windows and/or bash with zsh as necessary.)

PROG=vic-machine-linux source infra/scripts/bash_autocomplete

A customer would just run a command like the following from the root of the extracted vic_*.tar.gz.

source autocomplete/bash/vic-machine-linux

Some example output showing completion suggestions:

~/go/src/github.com/vmware/vic (topic/bash-completion)$ ./bin/vic-machine-linux 
configure  create     debug      delete     h          help       inspect    ls         update     upgrade    version    
~/go/src/github.com/vmware/vic (topic/bash-completion)$ ./bin/vic-machine-linux create -
--affinity-vm-group           --container-name-convention   --ksz                         --public-network-ip
--ai                          --container-network           --kv                          -r
--appliance-iso               --container-network-dns       --management-network          --rc
--ar                          --container-network-firewall  --management-network-gateway  --registry-ca
--asymmetric-routes           --container-network-gateway   --management-network-ip       --syslog-address
-b                            --container-network-ip-range  --mem                         -t
--base-image-size             --cpu                         --memory                      --target
--bi                          --cpur                        --memory-reservation          --thumbprint
--bnr                         --cpu-reservation             --memory-shares               --timeout
--bootstrap-iso               --cpus                        --memr                        --tls-ca
--bridge-network              --cpu-shares                  --mems                        --tls-cert-path
--bridge-network-range        --debug                       --mn                          --tls-cname
--ca                          --dir                         -n                            --tls-server-cert
--certificate-key-size        --dns-server                  --name                        --tls-server-key
--client-network              --endpoint-cpu                --no-tls                      -u
--client-network-gateway      --endpoint-memory             --no-tlsverify                --user
--client-network-ip           --extended-help               --ops-grant-perms             -v
--cln                         -f                            --ops-password                --volume-store
--cn                          --force                       --ops-user                    --vs
--cnc                         --http-proxy                  --organization                --whitelist-registry
--cnd                         --https-proxy                 -p                            --wr
--cnf                         -i                            --password                    -x
--cng                         --image-store                 --pn                          
~/go/src/github.com/vmware/vic (topic/bash-completion)$ ./bin/vic-machine-linux update 
firewall  help      
shephezj@shepherdz-devl:~/go/src/github.com/vmware/vic (topic/bash-completion)$ ./bin/vic-machine-linux update firewall --t
--target      --thumbprint  --timeout     

@zjs zjs self-assigned this Apr 19, 2018
@zjs zjs force-pushed the topic/bash-completion branch from 1d3d54f to 713abdc Compare April 19, 2018 17:43
@codecov-io
Copy link

codecov-io commented Apr 19, 2018

Codecov Report

Merging #7785 into master will increase coverage by 0.83%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #7785      +/-   ##
==========================================
+ Coverage   25.69%   26.52%   +0.83%     
==========================================
  Files          35       36       +1     
  Lines        5125     5183      +58     
==========================================
+ Hits         1317     1375      +58     
  Misses       3701     3701              
  Partials      107      107
Impacted Files Coverage Δ
cmd/vic-machine/common/completion.go 100% <100%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0f3106b...f30e171. Read the comment docs.

@zjs zjs force-pushed the topic/bash-completion branch 3 times, most recently from b76cca6 to 652d50d Compare April 19, 2018 18:52
@zjs
Copy link
Member Author

zjs commented Apr 19, 2018

Testing of changes to .drone.yml: https://ci-vic.vmware.com/vmware/vic/18576/9

@zjs zjs force-pushed the topic/bash-completion branch from 652d50d to 0804d00 Compare April 19, 2018 19:36
@zjs zjs requested a review from mdharamadas1 April 24, 2018 17:31
func getNames(flag cli.Flag) []string {
names := strings.Split(flag.GetName(), ",")

var trimmedNames []string
Copy link
Contributor

Choose a reason for hiding this comment

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

Commenting on this doesn't make much sense, but I will still comment it from the future standpoint.
Since you know the lengths of trimmed names array you could preallocate it all at once, thus resulting in a less memory allocations.

trimmedNames := make([]string, len(names))
for i, name := range names {
   trimmedNames[i] = strings.Trim(name, " ")
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Looking at this blog post, it seems like I might be able to specify the desired capacity without setting a length:

	trimmedNames := make([]string, 0, len(names))
	for _, name := range names {
		trimmedNames = append(trimmedNames, strings.Trim(name, " "))
	}

I find that more intuitive than setting a length up-front, since this way the length is always accurate (after the second iteration through the loop the length would be 2, and so on).

Would there be disadvantages to doing it this way, versus what you suggest?


// findFlag searches a haystack of cli.Flag objects for the first with a name matching the needle.
func findFlag(needle string, haystack []cli.Flag) cli.Flag {
for _, f := range haystack {
Copy link
Contributor

@vburenin vburenin Apr 25, 2018

Choose a reason for hiding this comment

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

O(m*n) :(
sure... it works fine.

Copy link
Member Author

Choose a reason for hiding this comment

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

A couple of factors led me here:

  1. To do better, I need a sorted list. With the sorted list, I could do searches in O(log(n*m)). However initializing that sorted list actually takes O(n*m*log(n*m)). If I needed to find a lot of things (more than log(n*m)), that might be worth it, but in this case I'm only ever searching once so the initialization cost would dominate.
  2. In our code, getNames always returns 1-2 elements (a long flag and maybe a short flag), so that's essential a constant factor.
  3. The current pattern allows us to bail out as soon as we've found what we're looking for.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yah, that's why I said it works fine. Even if there were hundreds of elements in each list, it would not be really noticeable.


// If the argument begins with a hypen, we *guess* that it's probably a flag.
if strings.HasPrefix(lastArg, "-") {
lastFlag := findFlag(strings.Trim(os.Args[len(os.Args)-2], "-"), flags)
Copy link
Contributor

Choose a reason for hiding this comment

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

didn't you get lastArg already? it would simplify this code

@zjs zjs force-pushed the topic/bash-completion branch from 60c682b to 55acd80 Compare April 25, 2018 21:51
@zjs zjs added this to the Sprint 31 Lifecycle milestone Apr 25, 2018
zjs added 2 commits April 25, 2018 16:49
Implement a cli.BashCompleteFunc factory and use it to supply an
appropriate instance with each cli.Command in vic-machine.

Package bash and zsh completion scripts for use by users.
@zjs zjs force-pushed the topic/bash-completion branch 2 times, most recently from 714042c to 2bbb2f0 Compare April 25, 2018 23:50
@zjs zjs force-pushed the topic/bash-completion branch from 2bbb2f0 to 68105bb Compare April 25, 2018 23:58
@zjs zjs requested a review from mhagen-vmware April 25, 2018 23:59
@mdharamadas1
Copy link
Contributor

Don't we need integration tests for this? At least, just to make sure autocomplete can be enabled?

@zjs
Copy link
Member Author

zjs commented Apr 26, 2018

Don't we need integration tests for this? At least, just to make sure autocomplete can be enabled?

I'm not sure how to write an integration test for this. We'd need a way to open a shell, source a script, and enter characters as a user would (including pressing "tab"). That doesn't seem possible from Robot.

Edit: For what it's worth, the autocomplete scripts will not be changing frequently (even across the history of urfave/cli, each only has a handful of revisions). It seems like the easiest thing might be to manually test those any time we do have to make changes to them; the go code is entirely covered by unit tests.

@mdharamadas1
Copy link
Contributor

mdharamadas1 commented Apr 26, 2018

@zjs I agree its complicated to write such tests but I think its possible. We already execute lot of shell commands in existing robot tests but tab press would complicate it a little. I would suggest at least creating an issue to add tests later. Otherwise, LGTM.

Approved with PullApprove Approved with PullApprove Approved with PullApprove

Copy link
Contributor

@mdharamadas1 mdharamadas1 left a comment

Choose a reason for hiding this comment

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

lgtm

@zjs
Copy link
Member Author

zjs commented Apr 26, 2018

Issue to track integration testing: #7850

@zjs zjs merged commit 26ee2f9 into vmware:master Apr 26, 2018
zjs added a commit to zjs/vic that referenced this pull request Jun 21, 2018
Implement a cli.BashCompleteFunc factory and use it to supply an
appropriate instance with each cli.Command in vic-machine.

Package bash and zsh completion scripts for use by users.

(cherry picked from commit 26ee2f9)
zjs added a commit to zjs/vic that referenced this pull request Jun 22, 2018
Implement a cli.BashCompleteFunc factory and use it to supply an
appropriate instance with each cli.Command in vic-machine.

Package bash and zsh completion scripts for use by users.

(cherry picked from commit 26ee2f9)
zjs added a commit to zjs/vic that referenced this pull request Jun 28, 2018
Implement a cli.BashCompleteFunc factory and use it to supply an
appropriate instance with each cli.Command in vic-machine.

Package bash and zsh completion scripts for use by users.

(cherry picked from commit 26ee2f9)
zjs added a commit to zjs/vic that referenced this pull request Jul 2, 2018
Implement a cli.BashCompleteFunc factory and use it to supply an
appropriate instance with each cli.Command in vic-machine.

Package bash and zsh completion scripts for use by users.

(cherry picked from commit 26ee2f9)
zjs added a commit to zjs/vic that referenced this pull request Jul 2, 2018
Implement a cli.BashCompleteFunc factory and use it to supply an
appropriate instance with each cli.Command in vic-machine.

Package bash and zsh completion scripts for use by users.

(cherry picked from commit 26ee2f9)
zjs added a commit to zjs/vic that referenced this pull request Jul 27, 2018
Implement a cli.BashCompleteFunc factory and use it to supply an
appropriate instance with each cli.Command in vic-machine.

Package bash and zsh completion scripts for use by users.

(cherry picked from commit 26ee2f9)
zjs added a commit that referenced this pull request Jul 27, 2018
Implement a cli.BashCompleteFunc factory and use it to supply an
appropriate instance with each cli.Command in vic-machine.

Package bash and zsh completion scripts for use by users.

(cherry picked from commit 26ee2f9)
@stuclem stuclem added the impact/doc/user Requires changes to official user documentation label Aug 17, 2018
@stuclem
Copy link

stuclem commented Sep 17, 2018

@stuclem stuclem removed the impact/doc/user Requires changes to official user documentation label Sep 17, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants