Add bash_completion to swiftclient
This patch basically follows the bash completion model that other OpenStack clients use. It creates a new command to swiftclient called `bash_completion`. The `bash_completion` command by default will print all base flags and exsiting commands. If you pass it a command, it'll print out all base flags and any flags that command accepts. So as you type out your swift command and auto-complete, only the current available flags are offered to you. This is used by the swift.bash_completion script to allow swift commands to be bash completed. To make it work, place the swift.bash_completion file into /etc/bash_completion.d and source it: cp tools/swift.bash_completion /etc/bash_completion.d/swift source /etc/bash_completion.d/swift Because swiftclient itself is creating this flag/command output it should automatically add anything we add to the swiftclient CLI. Change-Id: I5609a19018269762b4640403daae5827bb9ad724
This commit is contained in:
parent
25e23988b3
commit
45ed21c6c4
@ -51,7 +51,7 @@ except ImportError:
|
||||
|
||||
BASENAME = 'swift'
|
||||
commands = ('delete', 'download', 'list', 'post', 'copy', 'stat', 'upload',
|
||||
'capabilities', 'info', 'tempurl', 'auth')
|
||||
'capabilities', 'info', 'tempurl', 'auth', 'bash_completion')
|
||||
|
||||
|
||||
def immediate_exit(signum, frame):
|
||||
@ -90,7 +90,7 @@ Optional arguments:
|
||||
'''.strip("\n")
|
||||
|
||||
|
||||
def st_delete(parser, args, output_manager):
|
||||
def st_delete(parser, args, output_manager, return_parser=False):
|
||||
parser.add_argument(
|
||||
'-a', '--all', action='store_true', dest='yes_all',
|
||||
default=False, help='Delete all containers and objects.')
|
||||
@ -114,6 +114,11 @@ def st_delete(parser, args, output_manager):
|
||||
'--container-threads', type=int,
|
||||
default=10, help='Number of threads to use for deleting containers. '
|
||||
'Its value must be a positive integer. Default is 10.')
|
||||
|
||||
# We return the parser to build up the bash_completion
|
||||
if return_parser:
|
||||
return parser
|
||||
|
||||
(options, args) = parse_args(parser, args)
|
||||
args = args[1:]
|
||||
if (not args and not options['yes_all']) or (args and options['yes_all']):
|
||||
@ -281,7 +286,7 @@ Optional arguments:
|
||||
'''.strip("\n")
|
||||
|
||||
|
||||
def st_download(parser, args, output_manager):
|
||||
def st_download(parser, args, output_manager, return_parser=False):
|
||||
parser.add_argument(
|
||||
'-a', '--all', action='store_true', dest='yes_all',
|
||||
default=False, help='Indicates that you really want to download '
|
||||
@ -344,6 +349,11 @@ def st_download(parser, args, output_manager):
|
||||
'to store the access and modified timestamp for the downloaded file. '
|
||||
'With this option, the header is ignored and the timestamps are '
|
||||
'created freshly.')
|
||||
|
||||
# We return the parser to build up the bash_completion
|
||||
if return_parser:
|
||||
return parser
|
||||
|
||||
(options, args) = parse_args(parser, args)
|
||||
args = args[1:]
|
||||
if options['out_file'] == '-':
|
||||
@ -494,7 +504,7 @@ Optional arguments:
|
||||
'''.strip('\n')
|
||||
|
||||
|
||||
def st_list(parser, args, output_manager):
|
||||
def st_list(parser, args, output_manager, return_parser=False):
|
||||
|
||||
def _print_stats(options, stats, human):
|
||||
total_count = total_bytes = 0
|
||||
@ -571,6 +581,11 @@ def st_list(parser, args, output_manager):
|
||||
'-H', '--header', action='append', dest='header',
|
||||
default=[],
|
||||
help='Adds a custom request header to use for listing.')
|
||||
|
||||
# We return the parser to build up the bash_completion
|
||||
if return_parser:
|
||||
return parser
|
||||
|
||||
options, args = parse_args(parser, args)
|
||||
args = args[1:]
|
||||
if options['delimiter'] and not args:
|
||||
@ -629,7 +644,7 @@ Optional arguments:
|
||||
'''.strip('\n')
|
||||
|
||||
|
||||
def st_stat(parser, args, output_manager):
|
||||
def st_stat(parser, args, output_manager, return_parser=False):
|
||||
parser.add_argument(
|
||||
'--lh', dest='human', action='store_true', default=False,
|
||||
help='Report sizes in human readable format similar to ls -lh.')
|
||||
@ -638,6 +653,10 @@ def st_stat(parser, args, output_manager):
|
||||
default=[],
|
||||
help='Adds a custom request header to use for stat.')
|
||||
|
||||
# We return the parser to build up the bash_completion
|
||||
if return_parser:
|
||||
return parser
|
||||
|
||||
options, args = parse_args(parser, args)
|
||||
args = args[1:]
|
||||
|
||||
@ -725,7 +744,7 @@ Optional arguments:
|
||||
'''.strip('\n')
|
||||
|
||||
|
||||
def st_post(parser, args, output_manager):
|
||||
def st_post(parser, args, output_manager, return_parser=False):
|
||||
parser.add_argument(
|
||||
'-r', '--read-acl', dest='read_acl', help='Read ACL for containers. '
|
||||
'Quick summary of ACL syntax: .r:*, .r:-.example.com, '
|
||||
@ -750,6 +769,11 @@ def st_post(parser, args, output_manager):
|
||||
'This option may be repeated. '
|
||||
'Example: -H "content-type:text/plain" '
|
||||
'-H "Content-Length: 4000"')
|
||||
|
||||
# We return the parser to build up the bash_completion
|
||||
if return_parser:
|
||||
return parser
|
||||
|
||||
(options, args) = parse_args(parser, args)
|
||||
args = args[1:]
|
||||
if (options['read_acl'] or options['write_acl'] or options['sync_to'] or
|
||||
@ -822,7 +846,7 @@ Optional arguments:
|
||||
'''.strip('\n')
|
||||
|
||||
|
||||
def st_copy(parser, args, output_manager):
|
||||
def st_copy(parser, args, output_manager, return_parser=False):
|
||||
parser.add_argument(
|
||||
'-d', '--destination', help='The container and name of the '
|
||||
'destination object')
|
||||
@ -839,6 +863,11 @@ def st_copy(parser, args, output_manager):
|
||||
'This option may be repeated. '
|
||||
'Example: -H "content-type:text/plain" '
|
||||
'-H "Content-Length: 4000"')
|
||||
|
||||
# We return the parser to build up the bash_completion
|
||||
if return_parser:
|
||||
return parser
|
||||
|
||||
(options, args) = parse_args(parser, args)
|
||||
args = args[1:]
|
||||
|
||||
@ -948,7 +977,7 @@ Optional arguments:
|
||||
'''.strip('\n')
|
||||
|
||||
|
||||
def st_upload(parser, args, output_manager):
|
||||
def st_upload(parser, args, output_manager, return_parser=False):
|
||||
DEFAULT_STDIN_SEGMENT = 10 * 1024 * 1024
|
||||
|
||||
parser.add_argument(
|
||||
@ -1006,6 +1035,11 @@ def st_upload(parser, args, output_manager):
|
||||
parser.add_argument(
|
||||
'--ignore-checksum', dest='checksum', default=True,
|
||||
action='store_false', help='Turn off checksum validation for uploads.')
|
||||
|
||||
# We return the parser to build up the bash_completion
|
||||
if return_parser:
|
||||
return parser
|
||||
|
||||
options, args = parse_args(parser, args)
|
||||
args = args[1:]
|
||||
if len(args) < 2:
|
||||
@ -1185,7 +1219,7 @@ Optional arguments:
|
||||
st_info_help = st_capabilities_help
|
||||
|
||||
|
||||
def st_capabilities(parser, args, output_manager):
|
||||
def st_capabilities(parser, args, output_manager, return_parser=False):
|
||||
def _print_compo_cap(name, capabilities):
|
||||
for feature, options in sorted(capabilities.items(),
|
||||
key=lambda x: x[0]):
|
||||
@ -1198,6 +1232,11 @@ def st_capabilities(parser, args, output_manager):
|
||||
|
||||
parser.add_argument('--json', action='store_true',
|
||||
help='print capability information in json')
|
||||
|
||||
# We return the parser to build up the bash_completion
|
||||
if return_parser:
|
||||
return parser
|
||||
|
||||
(options, args) = parse_args(parser, args)
|
||||
if args and len(args) > 2:
|
||||
output_manager.error('Usage: %s capabilities %s\n%s',
|
||||
@ -1246,7 +1285,12 @@ Display auth related authentication variables in shell friendly format.
|
||||
'''.strip('\n')
|
||||
|
||||
|
||||
def st_auth(parser, args, thread_manager):
|
||||
def st_auth(parser, args, thread_manager, return_parser=False):
|
||||
|
||||
# We return the parser to build up the bash_completion
|
||||
if return_parser:
|
||||
return parser
|
||||
|
||||
(options, args) = parse_args(parser, args)
|
||||
if options['verbose'] > 1:
|
||||
if options['auth_version'] in ('1', '1.0'):
|
||||
@ -1330,7 +1374,7 @@ Optional arguments:
|
||||
'''.strip('\n')
|
||||
|
||||
|
||||
def st_tempurl(parser, args, thread_manager):
|
||||
def st_tempurl(parser, args, thread_manager, return_parser=False):
|
||||
parser.add_argument(
|
||||
'--absolute', action='store_true',
|
||||
dest='absolute_expiry', default=False,
|
||||
@ -1357,6 +1401,10 @@ def st_tempurl(parser, args, thread_manager):
|
||||
"given ip or ip range."),
|
||||
)
|
||||
|
||||
# We return the parser to build up the bash_completion
|
||||
if return_parser:
|
||||
return parser
|
||||
|
||||
(options, args) = parse_args(parser, args)
|
||||
args = args[1:]
|
||||
if len(args) < 4:
|
||||
@ -1388,6 +1436,65 @@ def st_tempurl(parser, args, thread_manager):
|
||||
thread_manager.print_msg(url)
|
||||
|
||||
|
||||
st_bash_completion_help = '''Retrieve command specific flags used by bash_completion.
|
||||
|
||||
Optional positional arguments:
|
||||
<command> Swift client command to filter the flags by.
|
||||
'''.strip('\n')
|
||||
|
||||
|
||||
st_bash_completion_options = '''[command]
|
||||
'''
|
||||
|
||||
|
||||
def st_bash_completion(parser, args, thread_manager, return_parser=False):
|
||||
if return_parser:
|
||||
return parser
|
||||
|
||||
global commands
|
||||
com = args[1] if len(args) > 1 else None
|
||||
|
||||
if com:
|
||||
if com in commands:
|
||||
fn_commands = ["st_%s" % com]
|
||||
else:
|
||||
print("")
|
||||
return
|
||||
else:
|
||||
fn_commands = [fn for fn in globals().keys()
|
||||
if fn.startswith('st_') and not fn.endswith('_options')
|
||||
and not fn.endswith('_help')]
|
||||
|
||||
subparsers = parser.add_subparsers()
|
||||
subcommands = {}
|
||||
if not com:
|
||||
subcommands['base'] = parser
|
||||
for command in fn_commands:
|
||||
cmd = command[3:]
|
||||
if com:
|
||||
subparser = subparsers.add_parser(
|
||||
cmd, help=globals()['%s_help' % command])
|
||||
add_default_args(subparser)
|
||||
subparser = globals()[command](
|
||||
subparser, args, thread_manager, True)
|
||||
subcommands[cmd] = subparser
|
||||
else:
|
||||
subcommands[cmd] = None
|
||||
|
||||
cmds = set()
|
||||
opts = set()
|
||||
for sc_str, sc in list(subcommands.items()):
|
||||
cmds.add(sc_str)
|
||||
if sc:
|
||||
for option in sc._optionals._option_string_actions:
|
||||
opts.add(option)
|
||||
|
||||
for cmd_to_remove in (com, 'bash_completion', 'base'):
|
||||
if cmd_to_remove in cmds:
|
||||
cmds.remove(cmd_to_remove)
|
||||
print(' '.join(cmds | opts))
|
||||
|
||||
|
||||
class HelpFormatter(argparse.HelpFormatter):
|
||||
def _format_action_invocation(self, action):
|
||||
if not action.option_strings:
|
||||
@ -1508,94 +1615,7 @@ adding "-V 2" is necessary for this.'''.strip('\n'))
|
||||
return options, args
|
||||
|
||||
|
||||
def main(arguments=None):
|
||||
argv = sys_argv if arguments is None else arguments
|
||||
|
||||
argv = [a if isinstance(a, text_type) else a.decode('utf-8') for a in argv]
|
||||
|
||||
version = client_version
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False, formatter_class=HelpFormatter, usage='''
|
||||
%(prog)s [--version] [--help] [--os-help] [--snet] [--verbose]
|
||||
[--debug] [--info] [--quiet] [--auth <auth_url>]
|
||||
[--auth-version <auth_version> |
|
||||
--os-identity-api-version <auth_version> ]
|
||||
[--user <username>]
|
||||
[--key <api_key>] [--retries <num_retries>]
|
||||
[--os-username <auth-user-name>]
|
||||
[--os-password <auth-password>]
|
||||
[--os-user-id <auth-user-id>]
|
||||
[--os-user-domain-id <auth-user-domain-id>]
|
||||
[--os-user-domain-name <auth-user-domain-name>]
|
||||
[--os-tenant-id <auth-tenant-id>]
|
||||
[--os-tenant-name <auth-tenant-name>]
|
||||
[--os-project-id <auth-project-id>]
|
||||
[--os-project-name <auth-project-name>]
|
||||
[--os-project-domain-id <auth-project-domain-id>]
|
||||
[--os-project-domain-name <auth-project-domain-name>]
|
||||
[--os-auth-url <auth-url>]
|
||||
[--os-auth-token <auth-token>]
|
||||
[--os-storage-url <storage-url>]
|
||||
[--os-region-name <region-name>]
|
||||
[--os-service-type <service-type>]
|
||||
[--os-endpoint-type <endpoint-type>]
|
||||
[--os-cacert <ca-certificate>]
|
||||
[--insecure]
|
||||
[--os-cert <client-certificate-file>]
|
||||
[--os-key <client-certificate-key-file>]
|
||||
[--no-ssl-compression]
|
||||
[--force-auth-retry]
|
||||
[--prompt]
|
||||
<subcommand> [--help] [<subcommand options>]
|
||||
|
||||
Command-line interface to the OpenStack Swift API.
|
||||
|
||||
Positional arguments:
|
||||
<subcommand>
|
||||
delete Delete a container or objects within a container.
|
||||
download Download objects from containers.
|
||||
list Lists the containers for the account or the objects
|
||||
for a container.
|
||||
post Updates meta information for the account, container,
|
||||
or object; creates containers if not present.
|
||||
copy Copies object, optionally adds meta
|
||||
stat Displays information for the account, container,
|
||||
or object.
|
||||
upload Uploads files or directories to the given container.
|
||||
capabilities List cluster capabilities.
|
||||
tempurl Create a temporary URL.
|
||||
auth Display auth related environment variables.
|
||||
|
||||
Examples:
|
||||
%(prog)s download --help
|
||||
|
||||
%(prog)s -A https://api.example.com/v1.0 \\
|
||||
-U user -K api_key stat -v
|
||||
|
||||
%(prog)s --os-auth-url https://api.example.com/v2.0 \\
|
||||
--os-tenant-name tenant \\
|
||||
--os-username user --os-password password list
|
||||
|
||||
%(prog)s --os-auth-url https://api.example.com/v3 --auth-version 3\\
|
||||
--os-project-name project1 --os-project-domain-name domain1 \\
|
||||
--os-username user --os-user-domain-name domain1 \\
|
||||
--os-password password list
|
||||
|
||||
%(prog)s --os-auth-url https://api.example.com/v3 --auth-version 3\\
|
||||
--os-project-id 0123456789abcdef0123456789abcdef \\
|
||||
--os-user-id abcdef0123456789abcdef0123456789 \\
|
||||
--os-password password list
|
||||
|
||||
%(prog)s --os-auth-token 6ee5eb33efad4e45ab46806eac010566 \\
|
||||
--os-storage-url https://10.1.5.2:8080/v1/AUTH_ced809b6a4baea7aeab61a \\
|
||||
list
|
||||
|
||||
%(prog)s list --lh
|
||||
'''.strip('\n'))
|
||||
parser.add_argument('--version', action='version',
|
||||
version='python-swiftclient %s' % version)
|
||||
parser.add_argument('-h', '--help', action='store_true')
|
||||
|
||||
def add_default_args(parser):
|
||||
default_auth_version = '1.0'
|
||||
for k in ('ST_AUTH_VERSION', 'OS_AUTH_VERSION', 'OS_IDENTITY_API_VERSION'):
|
||||
try:
|
||||
@ -1808,6 +1828,100 @@ Examples:
|
||||
default=environ.get('OS_KEY'),
|
||||
help='Specify a client certificate key file (for '
|
||||
'client auth). Defaults to env[OS_KEY].')
|
||||
|
||||
|
||||
def main(arguments=None):
|
||||
argv = sys_argv if arguments is None else arguments
|
||||
|
||||
argv = [a if isinstance(a, text_type) else a.decode('utf-8') for a in argv]
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False, formatter_class=HelpFormatter, usage='''
|
||||
%(prog)s [--version] [--help] [--os-help] [--snet] [--verbose]
|
||||
[--debug] [--info] [--quiet] [--auth <auth_url>]
|
||||
[--auth-version <auth_version> |
|
||||
--os-identity-api-version <auth_version> ]
|
||||
[--user <username>]
|
||||
[--key <api_key>] [--retries <num_retries>]
|
||||
[--os-username <auth-user-name>]
|
||||
[--os-password <auth-password>]
|
||||
[--os-user-id <auth-user-id>]
|
||||
[--os-user-domain-id <auth-user-domain-id>]
|
||||
[--os-user-domain-name <auth-user-domain-name>]
|
||||
[--os-tenant-id <auth-tenant-id>]
|
||||
[--os-tenant-name <auth-tenant-name>]
|
||||
[--os-project-id <auth-project-id>]
|
||||
[--os-project-name <auth-project-name>]
|
||||
[--os-project-domain-id <auth-project-domain-id>]
|
||||
[--os-project-domain-name <auth-project-domain-name>]
|
||||
[--os-auth-url <auth-url>]
|
||||
[--os-auth-token <auth-token>]
|
||||
[--os-storage-url <storage-url>]
|
||||
[--os-region-name <region-name>]
|
||||
[--os-service-type <service-type>]
|
||||
[--os-endpoint-type <endpoint-type>]
|
||||
[--os-cacert <ca-certificate>]
|
||||
[--insecure]
|
||||
[--os-cert <client-certificate-file>]
|
||||
[--os-key <client-certificate-key-file>]
|
||||
[--no-ssl-compression]
|
||||
[--force-auth-retry]
|
||||
<subcommand> [--help] [<subcommand options>]
|
||||
|
||||
Command-line interface to the OpenStack Swift API.
|
||||
|
||||
Positional arguments:
|
||||
<subcommand>
|
||||
delete Delete a container or objects within a container.
|
||||
download Download objects from containers.
|
||||
list Lists the containers for the account or the objects
|
||||
for a container.
|
||||
post Updates meta information for the account, container,
|
||||
or object; creates containers if not present.
|
||||
copy Copies object, optionally adds meta
|
||||
stat Displays information for the account, container,
|
||||
or object.
|
||||
upload Uploads files or directories to the given container.
|
||||
capabilities List cluster capabilities.
|
||||
tempurl Create a temporary URL.
|
||||
auth Display auth related environment variables.
|
||||
bash_completion Outputs option and flag cli data ready for
|
||||
bash_completion.
|
||||
|
||||
Examples:
|
||||
%(prog)s download --help
|
||||
|
||||
%(prog)s -A https://api.example.com/v1.0 \\
|
||||
-U user -K api_key stat -v
|
||||
|
||||
%(prog)s --os-auth-url https://api.example.com/v2.0 \\
|
||||
--os-tenant-name tenant \\
|
||||
--os-username user --os-password password list
|
||||
|
||||
%(prog)s --os-auth-url https://api.example.com/v3 --auth-version 3\\
|
||||
--os-project-name project1 --os-project-domain-name domain1 \\
|
||||
--os-username user --os-user-domain-name domain1 \\
|
||||
--os-password password list
|
||||
|
||||
%(prog)s --os-auth-url https://api.example.com/v3 --auth-version 3\\
|
||||
--os-project-id 0123456789abcdef0123456789abcdef \\
|
||||
--os-user-id abcdef0123456789abcdef0123456789 \\
|
||||
--os-password password list
|
||||
|
||||
%(prog)s --os-auth-token 6ee5eb33efad4e45ab46806eac010566 \\
|
||||
--os-storage-url https://10.1.5.2:8080/v1/AUTH_ced809b6a4baea7aeab61a \\
|
||||
list
|
||||
|
||||
%(prog)s list --lh
|
||||
'''.strip('\n'))
|
||||
|
||||
version = client_version
|
||||
parser.add_argument('--version', action='version',
|
||||
version='python-swiftclient %s' % version)
|
||||
parser.add_argument('-h', '--help', action='store_true')
|
||||
|
||||
add_default_args(parser)
|
||||
|
||||
options, args = parse_args(parser, argv[1:], enforce_requires=False)
|
||||
|
||||
if options['help'] or options['os_help']:
|
||||
|
32
tools/swift.bash_completion
Normal file
32
tools/swift.bash_completion
Normal file
@ -0,0 +1,32 @@
|
||||
declare -a _swift_opts # lazy init
|
||||
|
||||
_swift_get_current_opt()
|
||||
{
|
||||
local opt
|
||||
for opt in ${_swift_opts[@]} ; do
|
||||
if [[ $(echo ${COMP_WORDS[*]} |grep -c " $opt\$") > 0 ]] || [[ $(echo ${COMP_WORDS[*]} |grep -c " $opt ") > 0 ]] ; then
|
||||
echo $opt
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
return 0
|
||||
}
|
||||
|
||||
_swift()
|
||||
{
|
||||
local opt cur prev sflags
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
|
||||
if [ "x$_swift_opts" == "x" ] ; then
|
||||
_swift_opts=(`swift bash_completion "$sbc" | sed -e "s/-[-A-Za-z0-9_]*//g" -e "s/ */ /g"`)
|
||||
fi
|
||||
|
||||
opt="$(_swift_get_current_opt)"
|
||||
COMPREPLY=($(compgen -W "$(swift bash_completion $opt)" -- ${cur}))
|
||||
|
||||
return 0
|
||||
}
|
||||
complete -F _swift swift
|
Loading…
Reference in New Issue
Block a user