Make full bash-completion

Also removed some unused code in cliutils
Now `rally bash-completion' prints out bash completion script
Added test for checking completion script is up-to-date

Change-Id: I7e89baf71313da45e264fe344ff69be0e93a96d1
This commit is contained in:
Sergey Skripnick 2014-10-17 18:49:39 +03:00
parent 6e4550747d
commit e8da962c1b
4 changed files with 174 additions and 36 deletions

View File

@ -181,12 +181,8 @@ def _add_command_parsers(categories, subparsers):
# FIXME(markmc): hack to assume dest is the arg name without # FIXME(markmc): hack to assume dest is the arg name without
# the leading hyphens if no dest is supplied # the leading hyphens if no dest is supplied
kwargs.setdefault('dest', args[0][2:]) kwargs.setdefault('dest', args[0][2:])
if kwargs['dest'].startswith('action_kwarg_'): action_kwargs.append(kwargs['dest'])
action_kwargs.append(kwargs['dest'][len('action_kwarg_'):]) kwargs['dest'] = 'action_kwarg_' + kwargs['dest']
else:
action_kwargs.append(kwargs['dest'])
kwargs['dest'] = 'action_kwarg_' + kwargs['dest']
parser.add_argument(*args, **kwargs) parser.add_argument(*args, **kwargs)
parser.set_defaults(action_fn=action_fn) parser.set_defaults(action_fn=action_fn)
@ -236,13 +232,7 @@ def run(argv, categories):
return(0) return(0)
if CONF.category.name == "bash-completion": if CONF.category.name == "bash-completion":
if not CONF.category.query_category: print(_generate_bash_completion_script())
print(" ".join(categories.keys()))
elif CONF.category.query_category in categories:
fn = categories[CONF.category.query_category]
command_object = fn()
actions = _methods_of(command_object)
print(" ".join([k for (k, v) in actions]))
return(0) return(0)
fn = CONF.category.action_fn fn = CONF.category.action_fn
@ -284,3 +274,55 @@ def run(argv, categories):
except Exception: except Exception:
print(_("Command failed, please check log for more info")) print(_("Command failed, please check log for more info"))
raise raise
def _generate_bash_completion_script():
from rally.cmd import main
bash_data = """
#!/bin/bash
_rally()
{
declare -A SUBCOMMANDS
declare -A OPTS
%(data)s
for OPT in ${!OPTS[*]} ; do
CMDSUB=(${OPT//_/ })
SUBCOMMANDS[${CMDSUB[0]}]+="${CMDSUB[1]} "
done
COMMANDS="${!SUBCOMMANDS[*]}"
COMPREPLY=()
local cur="${COMP_WORDS[COMP_CWORD]}"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
if [[ $cur =~ (\.|\~|\/).* ]] ; then
_filedir
elif [ $COMP_CWORD == "1" ] ; then
COMPREPLY=($(compgen -W "$COMMANDS" -- ${cur}))
elif [ $COMP_CWORD == "2" ] ; then
COMPREPLY=($(compgen -W "${SUBCOMMANDS[${prev}]}" -- ${cur}))
else
if [ $prev == "--filename" ] ; then
_filedir '@(json|ya?ml)'
elif [ $prev == "--output-file" ] || [ $prev == "--out" ]; then
_filedir
else
COMMAND="${COMP_WORDS[1]}_${COMP_WORDS[2]}"
COMPREPLY=($(compgen -W "${OPTS[$COMMAND]}" -- ${cur}))
fi
fi
return 0
}
complete -F _rally rally
"""
completion = ""
for category, cmds in main.categories.items():
for name, command in _methods_of(cmds):
args = ' '.join(arg[0][0] for arg in getattr(command, 'args', []))
completion += """ OPTS["{cat}_{cmd}"]="{args}"\n""".format(
cat=category, cmd=name, args=args)
return bash_data % {"data": completion}

View File

@ -28,17 +28,18 @@ from rally.cmd.commands import use
from rally.cmd.commands import verify from rally.cmd.commands import verify
def main(): categories = {
categories = { 'deployment': deployment.DeploymentCommands,
'deployment': deployment.DeploymentCommands, 'info': info.InfoCommands,
'info': info.InfoCommands, 'show': show.ShowCommands,
'show': show.ShowCommands, 'task': task.TaskCommands,
'task': task.TaskCommands, 'use': use.UseCommands,
'use': use.UseCommands, 'verify': verify.VerifyCommands
'verify': verify.VerifyCommands }
}
return cliutils.run(sys.argv, categories)
def main():
return cliutils.run(sys.argv, categories)
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@ -0,0 +1,42 @@
# Copyright 2014: Mirantis Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import difflib
import os
from rally.cmd import cliutils
from tests.unit import test
RES_PATH = os.path.join(os.path.dirname(__file__),
os.pardir, os.pardir, "tools")
class BashCompletionTestCase(test.TestCase):
def test_bash_completion(self):
old = open(os.path.join(RES_PATH,
"rally.bash_completion"), 'rb').read().splitlines()
new = cliutils._generate_bash_completion_script().splitlines()
if old != new:
for line in difflib.unified_diff(old, new):
print (line)
new_filename = "/tmp/rally.bash.new"
new_file = open(new_filename, 'wb')
new_file.write("\n".join(new))
new_file.close()
self.fail("bash completion script is outdated. "
"New script is located at %s "
"You may fix this by executing `"
"mv %s tools/rally.bash_completion'" % (new_filename,
new_filename))

View File

@ -1,18 +1,71 @@
_rally_opts="" # lazy init
_rally_flags="" # lazy init #!/bin/bash
_rally_opts_exp="" # lazy init
_rally() _rally()
{ {
local cur prev rbc cflags declare -A SUBCOMMANDS
COMPREPLY=() declare -A OPTS
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}" OPTS["info_find"]="--query"
base_opts="`rally bash-completion`" OPTS["use_deployment"]="--uuid --name"
if [ $prev == "rally" ] && [ $COMP_CWORD == "1" ] ; then OPTS["use_task"]="--uuid"
COMPREPLY=($(compgen -W "${base_opts}" -- ${cur})) OPTS["task_abort"]="--uuid"
OPTS["task_delete"]="--force --uuid"
OPTS["task_detailed"]="--uuid --iterations-data"
OPTS["task_list"]=""
OPTS["task_plot2html"]="--uuid --out --open"
OPTS["task_report"]="--uuid --out --open"
OPTS["task_results"]="--uuid --pprint --json"
OPTS["task_sla_check"]="--uuid --json"
OPTS["task_start"]="--deploy-id --task --tag --no-use"
OPTS["task_status"]="--uuid"
OPTS["task_validate"]="--deploy-id --task"
OPTS["show_flavors"]="--deploy-id"
OPTS["show_images"]="--deploy-id"
OPTS["show_keypairs"]="--deploy-id"
OPTS["show_networks"]="--deploy-id"
OPTS["show_secgroups"]="--deploy-id"
OPTS["verify_detailed"]="--uuid --sort-by"
OPTS["verify_list"]=""
OPTS["verify_results"]="--uuid --html --json --pprint --output-file"
OPTS["verify_show"]="--uuid --sort-by --detailed"
OPTS["verify_start"]="--deploy-id --set --regex --tempest-config"
OPTS["deployment_check"]="--uuid"
OPTS["deployment_config"]="--uuid --json --pprint"
OPTS["deployment_create"]="--name --fromenv --filename --no-use"
OPTS["deployment_destroy"]="--uuid"
OPTS["deployment_endpoint"]="--uuid"
OPTS["deployment_list"]=""
OPTS["deployment_recreate"]="--uuid"
for OPT in ${!OPTS[*]} ; do
CMDSUB=(${OPT//_/ })
SUBCOMMANDS[${CMDSUB[0]}]+="${CMDSUB[1]} "
done
COMMANDS="${!SUBCOMMANDS[*]}"
COMPREPLY=()
local cur="${COMP_WORDS[COMP_CWORD]}"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
if [[ $cur =~ (\.|\~|\/).* ]] ; then
_filedir
elif [ $COMP_CWORD == "1" ] ; then
COMPREPLY=($(compgen -W "$COMMANDS" -- ${cur}))
elif [ $COMP_CWORD == "2" ] ; then
COMPREPLY=($(compgen -W "${SUBCOMMANDS[${prev}]}" -- ${cur}))
else else
COMPREPLY=($(compgen -W "`rally bash-completion $prev `" -- ${cur})) if [ $prev == "--filename" ] ; then
_filedir '@(json|ya?ml)'
elif [ $prev == "--output-file" ] || [ $prev == "--out" ]; then
_filedir
else
COMMAND="${COMP_WORDS[1]}_${COMP_WORDS[2]}"
COMPREPLY=($(compgen -W "${OPTS[$COMMAND]}" -- ${cur}))
fi
fi fi
return 0 return 0
} }
complete -F _rally rally complete -F _rally rally