2015-02-26 01:23:46 +08:00
#!/usr/bin/env python
2010-11-01 23:49:21 +08:00
# The contents of this file are subject to the Mozilla Public License
# Version 1.1 (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.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is RabbitMQ Management Plugin.
#
2013-07-01 17:49:13 +08:00
# The Initial Developer of the Original Code is GoPivotal, Inc.
2016-01-01 17:59:18 +08:00
# Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved.
2017-08-03 01:26:22 +08:00
from __future__ import print_function
2017-07-19 07:49:06 +08:00
try:
from signal import signal, SIGPIPE, SIG_DFL
signal(SIGPIPE, SIG_DFL)
except ImportError:
pass
2010-11-01 23:49:21 +08:00
2012-06-06 19:14:08 +08:00
import sys
2015-02-26 00:45:47 +08:00
if sys.version_info[0] < 2 or (sys.version_info[0] == 2 and sys.version_info[1] < 6):
2017-08-03 01:26:22 +08:00
eprint("Sorry, rabbitmqadmin requires at least Python 2.6 (2.7.9 when HTTPS is enabled).")
2012-06-06 19:14:08 +08:00
sys.exit(1)
2012-02-13 22:42:35 +08:00
from optparse import OptionParser, TitledHelpFormatter
2010-10-13 00:56:45 +08:00
import urllib
import base64
import json
2010-10-19 18:52:38 +08:00
import os
2010-11-20 01:50:07 +08:00
import socket
2016-03-18 19:49:52 +08:00
import ssl
import traceback
2010-10-13 00:56:45 +08:00
2015-02-26 01:59:25 +08:00
if sys.version_info[0] == 2:
from ConfigParser import ConfigParser, NoSectionError
import httplib
import urlparse
2018-05-25 01:33:03 +08:00
from urllib import quote_plus
2015-02-26 01:59:25 +08:00
def b64(s):
return base64.b64encode(s)
else:
from configparser import ConfigParser, NoSectionError
import http.client as httplib
import urllib.parse as urlparse
2018-05-25 01:33:03 +08:00
from urllib.parse import quote_plus
2015-02-26 01:59:25 +08:00
def b64(s):
return base64.b64encode(s.encode('utf-8')).decode('utf-8')
2013-01-11 22:54:46 +08:00
VERSION = '%%VSN%%'
2014-09-25 21:54:54 +08:00
LISTABLE = {'connections': {'vhost': False, 'cols': ['name','user','channels']},
'channels': {'vhost': False, 'cols': ['name', 'user']},
2014-05-01 19:14:48 +08:00
'consumers': {'vhost': True},
2014-09-25 21:54:54 +08:00
'exchanges': {'vhost': True, 'cols': ['name', 'type']},
'queues': {'vhost': True, 'cols': ['name', 'messages']},
'bindings': {'vhost': True, 'cols': ['source', 'destination',
'routing_key']},
2012-10-17 19:24:17 +08:00
'users': {'vhost': False},
2014-09-25 21:54:54 +08:00
'vhosts': {'vhost': False, 'cols': ['name', 'messages']},
2012-10-17 19:24:17 +08:00
'permissions': {'vhost': False},
2014-09-25 21:54:54 +08:00
'nodes': {'vhost': False, 'cols': ['name','type','mem_used']},
'parameters': {'vhost': False, 'json': ['value']},
2016-09-01 23:13:42 +08:00
'policies': {'vhost': False, 'json': ['definition']},
2016-10-07 01:19:14 +08:00
'operator_policies': {'vhost': False, 'json': ['definition']},
'vhost_limits': {'vhost': False, 'json': ['value']}}
2012-10-17 19:24:17 +08:00
2014-09-25 21:54:54 +08:00
SHOWABLE = {'overview': {'vhost': False, 'cols': ['rabbitmq_version',
'cluster_name',
'queue_totals.messages',
'object_totals.queues']}}
2011-01-03 21:20:13 +08:00
2010-10-19 01:21:10 +08:00
PROMOTE_COLUMNS = ['vhost', 'name', 'type',
'source', 'destination', 'destination_type', 'routing_key']
2010-10-19 18:17:11 +08:00
URIS = {
'exchange': '/exchanges/{vhost}/{name}',
'queue': '/queues/{vhost}/{name}',
'binding': '/bindings/{vhost}/e/{source}/{destination_char}/{destination}',
'binding_del':'/bindings/{vhost}/e/{source}/{destination_char}/{destination}/{properties_key}',
'vhost': '/vhosts/{name}',
'user': '/users/{name}',
2012-04-19 23:03:24 +08:00
'permission': '/permissions/{vhost}/{user}',
2012-11-02 20:58:19 +08:00
'parameter': '/parameters/{component}/{vhost}/{name}',
2016-09-01 23:13:42 +08:00
'policy': '/policies/{vhost}/{name}',
2017-01-03 18:57:21 +08:00
'operator_policy': '/operator-policies/{vhost}/{name}',
'vhost_limit': '/vhost-limits/{vhost}/{name}'
2010-10-19 18:17:11 +08:00
}
2010-10-19 17:39:25 +08:00
DECLARABLE = {
2010-10-19 18:17:11 +08:00
'exchange': {'mandatory': ['name', 'type'],
2013-01-18 18:56:13 +08:00
'json': ['arguments'],
2010-11-17 18:51:23 +08:00
'optional': {'auto_delete': 'false', 'durable': 'true',
2013-01-18 18:56:13 +08:00
'internal': 'false', 'arguments': {}}},
2010-10-19 18:17:11 +08:00
'queue': {'mandatory': ['name'],
2013-01-18 18:56:13 +08:00
'json': ['arguments'],
2012-01-12 21:06:42 +08:00
'optional': {'auto_delete': 'false', 'durable': 'true',
2013-01-18 18:56:13 +08:00
'arguments': {}, 'node': None}},
2013-01-18 19:12:39 +08:00
'binding': {'mandatory': ['source', 'destination'],
2013-01-18 18:56:13 +08:00
'json': ['arguments'],
2013-01-18 19:12:39 +08:00
'optional': {'destination_type': 'queue',
'routing_key': '', 'arguments': {}}},
2010-10-19 18:17:11 +08:00
'vhost': {'mandatory': ['name'],
2013-06-24 18:54:04 +08:00
'optional': {'tracing': None}},
2011-06-09 22:12:02 +08:00
'user': {'mandatory': ['name', 'password', 'tags'],
2010-10-19 18:17:11 +08:00
'optional': {}},
2010-11-27 01:42:13 +08:00
'permission': {'mandatory': ['vhost', 'user', 'configure', 'write', 'read'],
2012-04-19 23:03:24 +08:00
'optional': {}},
2012-11-02 20:58:19 +08:00
'parameter': {'mandatory': ['component', 'name', 'value'],
2012-04-19 23:03:24 +08:00
'json': ['value'],
2012-10-11 00:13:22 +08:00
'optional': {}},
2016-09-01 23:13:42 +08:00
# priority has to be converted to an integer
2012-11-02 20:58:19 +08:00
'policy': {'mandatory': ['name', 'pattern', 'definition'],
2012-10-17 19:27:42 +08:00
'json': ['definition', 'priority'],
2016-09-01 23:13:42 +08:00
'optional': {'priority' : 0, 'apply-to': None}},
'operator_policy': {'mandatory': ['name', 'pattern', 'definition'],
'json': ['definition', 'priority'],
2016-10-07 01:19:14 +08:00
'optional': {'priority' : 0, 'apply-to': None}},
'vhost_limit': {'mandatory': ['name', 'value'],
'json': ['value'],
'optional': {}},
2010-10-19 18:17:11 +08:00
}
DELETABLE = {
'exchange': {'mandatory': ['name']},
'queue': {'mandatory': ['name']},
'binding': {'mandatory': ['source', 'destination_type', 'destination',
'properties_key']},
'vhost': {'mandatory': ['name']},
'user': {'mandatory': ['name']},
2012-04-19 23:03:24 +08:00
'permission': {'mandatory': ['vhost', 'user']},
2012-11-02 20:58:19 +08:00
'parameter': {'mandatory': ['component', 'name']},
2016-09-01 23:13:42 +08:00
'policy': {'mandatory': ['name']},
2016-10-07 01:19:14 +08:00
'operator_policy': {'mandatory': ['name']},
'vhost_limit': {'mandatory': ['name']}
2010-10-19 17:39:25 +08:00
}
2010-10-19 01:51:42 +08:00
2010-10-19 18:29:39 +08:00
CLOSABLE = {
'connection': {'mandatory': ['name'],
'optional': {},
'uri': '/connections/{name}'}
}
PURGABLE = {
'queue': {'mandatory': ['name'],
'optional': {},
'uri': '/queues/{vhost}/{name}/contents'}
}
2011-03-10 21:39:10 +08:00
EXTRA_VERBS = {
2011-03-10 23:09:04 +08:00
'publish': {'mandatory': ['routing_key'],
'optional': {'payload': None,
2014-08-22 19:58:00 +08:00
'properties': {},
2011-03-10 23:09:04 +08:00
'exchange': 'amq.default',
2011-03-10 21:39:10 +08:00
'payload_encoding': 'string'},
2014-08-22 19:58:00 +08:00
'json': ['properties'],
2011-03-10 21:39:10 +08:00
'uri': '/exchanges/{vhost}/{exchange}/publish'},
'get': {'mandatory': ['queue'],
2016-04-28 20:56:21 +08:00
'optional': {'count': '1', 'ackmode': 'ack_requeue_true',
2012-01-04 22:45:01 +08:00
'payload_file': None, 'encoding': 'auto'},
2011-03-10 21:39:10 +08:00
'uri': '/queues/{vhost}/{queue}/get'}
}
2010-10-19 18:17:11 +08:00
for k in DECLARABLE:
DECLARABLE[k]['uri'] = URIS[k]
for k in DELETABLE:
DELETABLE[k]['uri'] = URIS[k]
DELETABLE[k]['optional'] = {}
DELETABLE['binding']['uri'] = URIS['binding_del']
2012-02-13 22:42:35 +08:00
def short_usage():
return "rabbitmqadmin [options] subcommand"
def title(name):
return "\n%s\n%s\n\n" % (name, '=' * len(name))
def subcommands_usage():
usage = """Usage
=====
""" + short_usage() + """
where subcommand is one of:
""" + title("Display")
2010-10-19 18:17:11 +08:00
2010-10-13 00:56:45 +08:00
for l in LISTABLE:
2010-12-22 00:10:38 +08:00
usage += " list {0} [<column>...]\n".format(l)
2011-01-03 21:20:13 +08:00
for s in SHOWABLE:
usage += " show {0} [<column>...]\n".format(s)
2012-02-13 22:42:35 +08:00
usage += title("Object Manipulation")
2011-03-10 21:39:10 +08:00
usage += fmt_usage_stanza(DECLARABLE, 'declare')
usage += fmt_usage_stanza(DELETABLE, 'delete')
usage += fmt_usage_stanza(CLOSABLE, 'close')
usage += fmt_usage_stanza(PURGABLE, 'purge')
2012-02-13 23:41:21 +08:00
usage += title("Broker Definitions")
usage += """ export <file>
import <file>
"""
2012-02-13 22:42:35 +08:00
usage += title("Publishing and Consuming")
2011-03-10 21:39:10 +08:00
usage += fmt_usage_stanza(EXTRA_VERBS, '')
2012-02-13 23:41:21 +08:00
usage += """
* If payload is not specified on publish, standard input is used
2011-03-10 23:12:24 +08:00
* If payload_file is not specified on get, the payload will be shown on
standard output along with the message metadata
2012-02-09 22:35:38 +08:00
* If payload_file is specified on get, count must not be set
2012-02-13 22:42:35 +08:00
"""
return usage
def config_usage():
usage = "Usage\n=====\n" + short_usage()
usage += "\n" + title("Configuration File")
usage += """ It is possible to specify a configuration file from the command line.
2012-02-09 22:35:38 +08:00
Hosts can be configured easily in a configuration file and called
from the command line.
2012-02-13 22:42:35 +08:00
"""
usage += title("Example")
usage += """ # rabbitmqadmin.conf.example START
2012-02-09 22:35:38 +08:00
[host_normal]
hostname = localhost
2012-10-31 02:10:22 +08:00
port = 15672
2012-02-09 22:35:38 +08:00
username = guest
password = guest
2012-02-22 21:12:25 +08:00
declare_vhost = / # Used as default for declare / delete only
2012-02-22 21:11:42 +08:00
vhost = / # Used as default for declare / delete / list
2012-02-13 22:42:35 +08:00
2012-02-09 22:35:38 +08:00
[host_ssl]
hostname = otherhost
2012-10-31 02:10:22 +08:00
port = 15672
2012-02-09 22:35:38 +08:00
username = guest
password = guest
ssl = True
ssl_key_file = /path/to/key.pem
ssl_cert_file = /path/to/cert.pem
2012-02-13 22:42:35 +08:00
2012-02-09 22:35:38 +08:00
# rabbitmqadmin.conf.example END
2012-02-13 22:42:35 +08:00
"""
usage += title("Use")
usage += """ rabbitmqadmin -c rabbitmqadmin.conf.example -N host_normal ..."""
2010-10-13 00:56:45 +08:00
return usage
2012-02-13 22:42:35 +08:00
def more_help():
return """
More Help
=========
For more help use the help subcommand:
rabbitmqadmin help subcommands # For a list of available subcommands
rabbitmqadmin help config # For help with the configuration file
"""
2010-10-19 18:29:39 +08:00
def fmt_usage_stanza(root, verb):
2010-10-19 18:40:10 +08:00
def fmt_args(args):
2011-01-06 19:37:59 +08:00
res = " ".join(["{0}=...".format(a) for a in args['mandatory']])
2010-10-19 18:40:10 +08:00
opts = " ".join("{0}=...".format(o) for o in args['optional'].keys())
if opts != "":
res += " [{0}]".format(opts)
return res
2010-10-19 18:29:39 +08:00
2012-02-13 22:42:35 +08:00
text = ""
2011-03-10 21:39:10 +08:00
if verb != "":
verb = " " + verb
2010-10-19 18:29:39 +08:00
for k in root.keys():
2011-03-10 21:39:10 +08:00
text += " {0} {1} {2}\n".format(verb, k, fmt_args(root[k]))
2012-02-13 23:41:21 +08:00
return text
2010-10-19 01:51:42 +08:00
2012-02-13 21:58:43 +08:00
default_options = { "hostname" : "localhost",
2012-10-31 02:10:22 +08:00
"port" : "15672",
2016-02-16 17:07:33 +08:00
"path_prefix" : "",
2012-02-22 21:12:25 +08:00
"declare_vhost" : "/",
2012-02-13 21:58:43 +08:00
"username" : "guest",
"password" : "guest",
"ssl" : False,
"verbose" : True,
"format" : "table",
2014-10-13 23:40:04 +08:00
"depth" : 1,
2012-02-13 21:58:43 +08:00
"bash_completion" : False }
2012-02-09 22:35:38 +08:00
2012-02-13 22:42:35 +08:00
class MyFormatter(TitledHelpFormatter):
def format_epilog(self, epilog):
return epilog
parser = OptionParser(usage=short_usage(),
formatter=MyFormatter(),
epilog=more_help())
2010-10-13 00:56:45 +08:00
def make_parser():
2012-02-13 21:58:43 +08:00
def add(*args, **kwargs):
key = kwargs['dest']
if key in default_options:
default = " [default: %s]" % default_options[key]
kwargs['help'] = kwargs['help'] + default
parser.add_option(*args, **kwargs)
add("-c", "--config", dest="config",
help="configuration file [default: ~/.rabbitmqadmin.conf]",
metavar="CONFIG")
add("-N", "--node", dest="node",
2012-02-20 19:49:33 +08:00
help="node described in the configuration file [default: 'default'" + \
" only if configuration file is specified]",
2012-02-13 21:58:43 +08:00
metavar="NODE")
add("-H", "--host", dest="hostname",
help="connect to host HOST" ,
metavar="HOST")
add("-P", "--port", dest="port",
help="connect to port PORT",
metavar="PORT")
2016-02-16 17:07:33 +08:00
add("--path-prefix", dest="path_prefix",
2017-07-19 06:01:53 +08:00
help="use specific URI path prefix for the RabbitMQ HTTP API. /api and operation path will be appended to it. (default: blank string)")
2012-02-13 21:58:43 +08:00
add("-V", "--vhost", dest="vhost",
help="connect to vhost VHOST [default: all vhosts for list, '/' for declare]",
metavar="VHOST")
add("-u", "--username", dest="username",
help="connect using username USERNAME",
metavar="USERNAME")
add("-p", "--password", dest="password",
help="connect using password PASSWORD",
metavar="PASSWORD")
2017-07-19 06:01:53 +08:00
add("-U", "--base-uri", dest="base_uri",
help="connect using a base HTTP API URI. /api and operation path will be appended to it. Path will be ignored. --vhost has to be provided separately.",
metavar="URI")
2012-02-13 21:58:43 +08:00
add("-q", "--quiet", action="store_false", dest="verbose",
help="suppress status messages")
add("-s", "--ssl", action="store_true", dest="ssl",
help="connect with ssl")
add("--ssl-key-file", dest="ssl_key_file",
help="PEM format key file for SSL")
add("--ssl-cert-file", dest="ssl_cert_file",
help="PEM format certificate file for SSL")
2016-03-18 19:49:52 +08:00
add("--ssl-ca-cert-file", dest="ssl_ca_cert_file",
help="PEM format CA certificate file for SSL")
2016-03-18 20:08:21 +08:00
add("--ssl-disable-hostname-verification", dest="ssl_disable_hostname_verification",
2017-08-03 01:26:22 +08:00
help="Disables peer hostname verification", default=False, action="store_true")
add("-k", "--ssl-insecure", dest="ssl_insecure",
help="Disables all SSL validations like curl's '-k' argument", default=False, action="store_true")
2012-02-13 21:58:43 +08:00
add("-f", "--format", dest="format",
help="format for listing commands - one of [" + ", ".join(FORMATS.keys()) + "]")
2012-11-06 22:11:46 +08:00
add("-S", "--sort", dest="sort", help="sort key for listing queries")
add("-R", "--sort-reverse", action="store_true", dest="sort_reverse",
help="reverse the sort order")
2012-02-13 21:58:43 +08:00
add("-d", "--depth", dest="depth",
help="maximum depth to recurse for listing tables")
add("--bash-completion", action="store_true",
dest="bash_completion",
help="Print bash completion script")
2013-01-11 22:54:46 +08:00
add("--version", action="store_true",
dest="version",
help="Display version and exit")
2010-10-13 00:56:45 +08:00
2013-10-08 19:40:08 +08:00
def default_config():
home = os.getenv('USERPROFILE') or os.getenv('HOME')
2013-12-10 22:50:18 +08:00
if home is not None:
config_file = home + os.sep + ".rabbitmqadmin.conf"
if os.path.isfile(config_file):
return config_file
return None
2013-10-08 19:40:08 +08:00
2012-02-09 22:35:38 +08:00
def make_configuration():
make_parser()
(options, args) = parser.parse_args()
2012-02-22 21:12:25 +08:00
setattr(options, "declare_vhost", None)
2013-01-11 22:54:46 +08:00
if options.version:
print_version()
2013-10-08 19:40:08 +08:00
if options.config is None:
config_file = default_config()
2013-12-10 22:50:18 +08:00
if config_file is not None:
2013-10-08 19:40:08 +08:00
setattr(options, "config", config_file)
2013-10-09 19:24:03 +08:00
else:
if not os.path.isfile(options.config):
assert_usage(False,
"Could not read config file '%s'" % options.config)
2013-10-08 19:40:08 +08:00
2012-02-20 19:49:33 +08:00
if options.node is None and options.config:
options.node = "default"
2013-10-08 19:40:08 +08:00
else:
options.node = options.node
for (key, val) in default_options.items():
if getattr(options, key) is None:
setattr(options, key, val)
if options.config is not None:
2013-10-09 18:52:40 +08:00
config = ConfigParser()
2012-02-09 22:35:38 +08:00
try:
2012-02-13 21:03:49 +08:00
config.read(options.config)
2012-02-09 22:35:38 +08:00
new_conf = dict(config.items(options.node))
2015-02-26 00:45:47 +08:00
except NoSectionError as error:
2013-10-09 19:24:03 +08:00
if options.node == "default":
2013-10-08 19:40:08 +08:00
pass
else:
assert_usage(False, ("Could not read section '%s' in config file" +
" '%s':\n %s") %
(options.node, options.config, error))
2013-10-09 18:52:40 +08:00
else:
for key, val in new_conf.items():
2015-10-12 17:43:53 +08:00
if key == 'ssl':
setattr(options, key, val == "True")
else:
setattr(options, key, val)
2013-10-08 19:40:08 +08:00
2017-07-19 06:01:53 +08:00
# if --base-uri is passed, set connection parameters from it
if options.base_uri is not None:
u = urlparse.urlparse(options.base_uri)
for key in ["hostname", "port", "username", "password"]:
if getattr(u, key) is not None:
setattr(options, key, getattr(u, key))
if u.path is not None and (u.path != "") and (u.path != "/"):
2017-08-03 01:26:22 +08:00
eprint("WARNING: path in --base-uri is ignored. Please specify --vhost and/or --path-prefix separately.\n")
2017-07-19 06:01:53 +08:00
2012-02-09 22:35:38 +08:00
return (options, args)
2010-10-19 18:52:38 +08:00
def assert_usage(expr, error):
if not expr:
2017-08-03 01:26:22 +08:00
eprint("\nERROR: {0}\n".format(error))
eprint("{0} --help for help\n".format(os.path.basename(sys.argv[0])))
2010-10-13 00:56:45 +08:00
sys.exit(1)
2013-01-11 22:54:46 +08:00
def print_version():
2017-08-03 01:26:22 +08:00
print("rabbitmqadmin {0}".format(VERSION))
2013-01-11 22:54:46 +08:00
sys.exit(0)
2010-10-19 01:21:10 +08:00
def column_sort_key(col):
if col in PROMOTE_COLUMNS:
return (1, PROMOTE_COLUMNS.index(col))
else:
return (2, col)
2010-10-13 00:56:45 +08:00
def main():
2012-02-09 22:35:38 +08:00
(options, args) = make_configuration()
2010-11-17 18:17:39 +08:00
if options.bash_completion:
print_bash_completion()
2017-08-03 01:26:22 +08:00
sys.exit(0)
2010-10-19 18:52:38 +08:00
assert_usage(len(args) > 0, 'Action not specified')
2010-10-13 00:56:45 +08:00
mgmt = Management(options, args[1:])
mode = "invoke_" + args[0]
2010-10-19 18:52:38 +08:00
assert_usage(hasattr(mgmt, mode),
'Action {0} not understood'.format(args[0]))
2010-10-13 00:56:45 +08:00
method = getattr(mgmt, "invoke_%s" % args[0])
method()
2017-08-03 01:26:22 +08:00
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
2011-03-15 18:39:21 +08:00
def die(s):
2017-08-03 01:26:22 +08:00
eprint("*** {0}\n".format(s))
sys.exit(1)
2010-11-20 01:50:07 +08:00
2017-02-07 17:22:54 +08:00
def maybe_utf8(s):
if isinstance(s, int):
# s can be also an int for ex messages count
return str(s)
2017-07-27 22:06:45 +08:00
if isinstance(s, float):
# s can be also a float for message rate
return str(s)
2017-02-07 17:22:54 +08:00
if sys.version_info[0] == 3:
2011-03-15 18:39:21 +08:00
# It will have an encoding, which Python will respect
return s
else:
# It won't have an encoding, and Python will pick ASCII by default
return s.encode('utf-8')
2017-02-07 17:22:54 +08:00
2010-10-13 00:56:45 +08:00
class Management:
def __init__(self, options, args):
self.options = options
self.args = args
def get(self, path):
2016-02-16 17:07:33 +08:00
return self.http("GET", "%s/api%s" % (self.options.path_prefix, path), "")
2010-10-13 00:56:45 +08:00
def put(self, path, body):
2016-02-16 17:07:33 +08:00
return self.http("PUT", "%s/api%s" % (self.options.path_prefix, path), body)
2010-10-13 00:56:45 +08:00
def post(self, path, body):
2016-02-16 17:07:33 +08:00
return self.http("POST", "%s/api%s" % (self.options.path_prefix, path), body)
2010-10-13 00:56:45 +08:00
2010-10-19 18:17:11 +08:00
def delete(self, path):
2016-02-16 17:07:33 +08:00
return self.http("DELETE", "%s/api%s" % (self.options.path_prefix, path), "")
2010-10-19 18:17:11 +08:00
2016-06-13 19:40:34 +08:00
def __initialize_https_connection(self, hostname, port):
# Python 2.7.9+
if hasattr(ssl, 'create_default_context'):
return httplib.HTTPSConnection(hostname, port,
context = self.__initialize_tls_context())
# Python < 2.7.8, note: those versions still have SSLv3 enabled
# and other limitations. See rabbitmq/rabbitmq-management#225
else:
2017-08-03 01:26:22 +08:00
eprint("WARNING: rabbitmqadmin requires Python 2.7.9+ when HTTPS is used.")
2016-06-13 19:40:34 +08:00
return httplib.HTTPSConnection(hostname, port,
cert_file = self.options.ssl_cert_file,
key_file = self.options.ssl_key_file)
def __initialize_tls_context(self):
# Python 2.7.9+ only
2017-02-15 06:37:15 +08:00
ssl_ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
2016-06-13 19:40:34 +08:00
ssl_ctx.options &= ~ssl.OP_NO_SSLv3
2017-08-03 01:26:22 +08:00
ssl_insecure = self.options.ssl_insecure
ssl_disable_hostname_verification = ssl_insecure or \
self.options.ssl_disable_hostname_verification
# Note: you must set check_hostname prior to verify_mode
if ssl_disable_hostname_verification:
ssl_ctx.check_hostname = False
if ssl_insecure:
ssl_ctx.verify_mode = ssl.CERT_NONE
2017-02-15 06:44:04 +08:00
if self.options.ssl_key_file:
ssl_ctx.load_cert_chain(self.options.ssl_cert_file,
self.options.ssl_key_file)
2016-06-13 19:40:34 +08:00
if self.options.ssl_ca_cert_file:
ssl_ctx.load_verify_locations(self.options.ssl_ca_cert_file)
return ssl_ctx
2010-10-13 00:56:45 +08:00
def http(self, method, path, body):
2011-03-14 21:29:56 +08:00
if self.options.ssl:
2016-06-13 19:40:34 +08:00
conn = self.__initialize_https_connection(self.options.hostname,
self.options.port)
2011-03-14 21:29:56 +08:00
else:
conn = httplib.HTTPConnection(self.options.hostname,
self.options.port)
2015-02-26 00:45:47 +08:00
auth = (self.options.username + ":" + self.options.password)
2015-02-26 01:59:25 +08:00
headers = {"Authorization": "Basic " + b64(auth)}
2010-10-13 00:56:45 +08:00
if body != "":
headers["Content-Type"] = "application/json"
2010-11-20 01:50:07 +08:00
try:
2012-10-31 22:15:57 +08:00
conn.request(method, path, body, headers)
2015-02-26 00:45:47 +08:00
except socket.error as e:
2016-03-18 19:49:52 +08:00
traceback.print_exc(e)
2010-11-20 01:50:07 +08:00
die("Could not connect: {0}".format(e))
2010-10-13 00:56:45 +08:00
resp = conn.getresponse()
2010-11-20 01:50:07 +08:00
if resp.status == 400:
die(json.loads(resp.read())['reason'])
if resp.status == 401:
die("Access refused: {0}".format(path))
if resp.status == 404:
die("Not found: {0}".format(path))
2012-10-31 22:15:57 +08:00
if resp.status == 301:
url = urlparse.urlparse(resp.getheader('location'))
[host, port] = url.netloc.split(':')
self.options.hostname = host
self.options.port = int(port)
return self.http(method, url.path + '?' + url.query, body)
2010-11-20 01:50:07 +08:00
if resp.status < 200 or resp.status > 400:
2010-10-13 00:56:45 +08:00
raise Exception("Received %d %s for path %s\n%s"
% (resp.status, resp.reason, path, resp.read()))
2015-02-26 00:45:47 +08:00
return resp.read().decode('utf-8')
2010-10-13 00:56:45 +08:00
def verbose(self, string):
if self.options.verbose:
2017-08-03 01:26:22 +08:00
print(string)
2010-10-13 00:56:45 +08:00
def get_arg(self):
2010-10-19 18:52:38 +08:00
assert_usage(len(self.args) == 1, 'Exactly one argument required')
return self.args[0]
2010-10-13 00:56:45 +08:00
2014-10-13 23:40:04 +08:00
def use_cols(self):
# Deliberately do not cast to int here; we only care about the
# default, not explicit setting.
return self.options.depth == 1 and not 'json' in self.options.format
2012-02-13 22:42:35 +08:00
def invoke_help(self):
2012-11-06 22:44:45 +08:00
if len(self.args) == 0:
parser.print_help()
2012-02-13 22:42:35 +08:00
else:
2012-11-06 22:44:45 +08:00
help_cmd = self.get_arg()
if help_cmd == 'subcommands':
usage = subcommands_usage()
elif help_cmd == 'config':
usage = config_usage()
else:
assert_usage(False, """help topic must be one of:
2012-02-13 22:44:09 +08:00
subcommands
config""")
2015-02-26 00:45:47 +08:00
print(usage)
2017-08-03 01:26:22 +08:00
sys.exit(0)
2012-02-13 22:42:35 +08:00
2011-02-26 01:00:13 +08:00
def invoke_publish(self):
2011-03-10 23:00:45 +08:00
(uri, upload) = self.parse_args(self.args, EXTRA_VERBS['publish'])
2012-01-16 19:43:34 +08:00
if not 'payload' in upload:
2011-03-10 23:09:04 +08:00
data = sys.stdin.read()
2015-02-26 01:59:25 +08:00
upload['payload'] = b64(data)
2011-03-10 23:09:04 +08:00
upload['payload_encoding'] = 'base64'
2011-03-10 23:00:45 +08:00
resp = json.loads(self.post(uri, json.dumps(upload)))
2011-02-26 01:00:13 +08:00
if resp['routed']:
self.verbose("Message published")
else:
self.verbose("Message published but NOT routed")
def invoke_get(self):
2011-03-10 23:00:45 +08:00
(uri, upload) = self.parse_args(self.args, EXTRA_VERBS['get'])
2012-01-16 19:43:34 +08:00
payload_file = 'payload_file' in upload and upload['payload_file'] or None
2011-03-10 23:00:45 +08:00
assert_usage(not payload_file or upload['count'] == '1',
2011-03-10 22:58:02 +08:00
'Cannot get multiple messages using payload_file')
2011-03-10 23:00:45 +08:00
result = self.post(uri, json.dumps(upload))
2011-03-10 22:58:02 +08:00
if payload_file:
write_payload_file(payload_file, result)
columns = ['routing_key', 'exchange', 'message_count',
'payload_bytes', 'redelivered']
2012-10-17 19:24:17 +08:00
format_list(result, columns, {}, self.options)
2011-03-10 22:58:02 +08:00
else:
2012-10-17 19:24:17 +08:00
format_list(result, [], {}, self.options)
2011-02-26 01:00:13 +08:00
2010-10-13 00:56:45 +08:00
def invoke_export(self):
path = self.get_arg()
2016-02-15 19:47:06 +08:00
uri = "/definitions"
if self.options.vhost:
2018-05-25 01:33:03 +08:00
uri += "/%s" % quote_plus(self.options.vhost)
2016-02-15 19:47:06 +08:00
definitions = self.get(uri)
2012-06-06 19:14:08 +08:00
f = open(path, 'w')
f.write(definitions)
f.close()
2011-10-13 23:32:55 +08:00
self.verbose("Exported definitions for %s to \"%s\""
2010-10-13 00:56:45 +08:00
% (self.options.hostname, path))
def invoke_import(self):
path = self.get_arg()
2012-06-06 19:14:08 +08:00
f = open(path, 'r')
definitions = f.read()
f.close()
2016-02-15 19:47:06 +08:00
uri = "/definitions"
if self.options.vhost:
2018-05-25 01:33:03 +08:00
uri += "/%s" % quote_plus(self.options.vhost)
2016-02-15 19:47:06 +08:00
self.post(uri, definitions)
2011-10-13 23:32:55 +08:00
self.verbose("Imported definitions for %s from \"%s\""
2010-10-13 00:56:45 +08:00
% (self.options.hostname, path))
def invoke_list(self):
2014-09-25 21:54:54 +08:00
(uri, obj_info, cols) = self.list_show_uri(LISTABLE, 'list')
2012-10-17 19:24:17 +08:00
format_list(self.get(uri), cols, obj_info, self.options)
2011-01-03 21:20:13 +08:00
def invoke_show(self):
2014-09-25 21:54:54 +08:00
(uri, obj_info, cols) = self.list_show_uri(SHOWABLE, 'show')
2012-10-17 19:24:17 +08:00
format_list('[{0}]'.format(self.get(uri)), cols, obj_info, self.options)
2011-01-03 21:20:13 +08:00
2017-01-03 18:57:21 +08:00
def _list_path_for_obj_type(self, obj_type):
# This returns a URL path for given object type, e.g.
# replaces underscores in command names with
# dashes that HTTP API endpoints use
return obj_type.replace("_", "-")
2014-09-25 21:54:54 +08:00
def list_show_uri(self, obj_types, verb):
2010-12-22 00:10:38 +08:00
obj_type = self.args[0]
2011-01-03 21:20:13 +08:00
assert_usage(obj_type in obj_types,
"Don't know how to {0} {1}".format(verb, obj_type))
2012-10-17 19:24:17 +08:00
obj_info = obj_types[obj_type]
2017-01-03 18:57:21 +08:00
uri = "/%s" % self._list_path_for_obj_type(obj_type)
2012-11-06 22:11:46 +08:00
query = []
2012-10-17 19:24:17 +08:00
if obj_info['vhost'] and self.options.vhost:
2018-05-25 01:33:03 +08:00
uri += "/%s" % quote_plus(self.options.vhost)
2014-09-25 21:54:54 +08:00
cols = self.args[1:]
2014-10-13 23:40:04 +08:00
if cols == [] and 'cols' in obj_info and self.use_cols():
2014-09-25 21:54:54 +08:00
cols = obj_info['cols']
2011-05-09 23:08:24 +08:00
if cols != []:
2012-11-06 22:11:46 +08:00
query.append("columns=" + ",".join(cols))
sort = self.options.sort
if sort:
query.append("sort=" + sort)
if self.options.sort_reverse:
query.append("sort_reverse=true")
query = "&".join(query)
if query != "":
uri += "?" + query
2014-09-25 21:54:54 +08:00
return (uri, obj_info, cols)
2010-10-19 01:21:10 +08:00
2010-10-19 01:51:42 +08:00
def invoke_declare(self):
2011-03-10 23:00:45 +08:00
(obj_type, uri, upload) = self.declare_delete_parse(DECLARABLE)
2010-10-19 18:17:11 +08:00
if obj_type == 'binding':
2011-03-10 23:00:45 +08:00
self.post(uri, json.dumps(upload))
2010-10-19 18:17:11 +08:00
else:
2011-03-10 23:00:45 +08:00
self.put(uri, json.dumps(upload))
2010-10-19 18:17:11 +08:00
self.verbose("{0} declared".format(obj_type))
def invoke_delete(self):
2011-03-10 23:00:45 +08:00
(obj_type, uri, upload) = self.declare_delete_parse(DELETABLE)
2010-10-19 18:17:11 +08:00
self.delete(uri)
self.verbose("{0} deleted".format(obj_type))
2010-10-19 18:29:39 +08:00
def invoke_close(self):
2011-03-10 23:00:45 +08:00
(obj_type, uri, upload) = self.declare_delete_parse(CLOSABLE)
2010-10-19 18:29:39 +08:00
self.delete(uri)
self.verbose("{0} closed".format(obj_type))
def invoke_purge(self):
2011-03-10 23:00:45 +08:00
(obj_type, uri, upload) = self.declare_delete_parse(PURGABLE)
2010-10-19 18:29:39 +08:00
self.delete(uri)
self.verbose("{0} purged".format(obj_type))
2010-10-19 18:17:11 +08:00
def declare_delete_parse(self, root):
2010-10-19 18:52:38 +08:00
assert_usage(len(self.args) > 0, 'Type not specified')
2010-10-19 01:51:42 +08:00
obj_type = self.args[0]
2010-10-19 18:52:38 +08:00
assert_usage(obj_type in root,
'Type {0} not recognised'.format(obj_type))
2011-02-26 01:00:13 +08:00
obj = root[obj_type]
2011-03-10 23:00:45 +08:00
(uri, upload) = self.parse_args(self.args[1:], obj)
return (obj_type, uri, upload)
2011-02-26 01:00:13 +08:00
2011-03-10 21:39:10 +08:00
def parse_args(self, args, obj):
mandatory = obj['mandatory']
optional = obj['optional']
uri_template = obj['uri']
2011-03-10 23:00:45 +08:00
upload = {}
2010-10-19 01:51:42 +08:00
for k in optional.keys():
2014-08-22 20:24:46 +08:00
if optional[k] is not None:
2012-01-12 21:06:42 +08:00
upload[k] = optional[k]
2010-11-20 01:37:26 +08:00
for arg in args:
assert_usage("=" in arg,
'Argument "{0}" not in format name=value'.format(arg))
2011-03-10 21:22:46 +08:00
(name, value) = arg.split("=", 1)
2010-11-20 01:37:26 +08:00
assert_usage(name in mandatory or name in optional.keys(),
'Argument "{0}" not recognised'.format(name))
2012-04-19 23:16:25 +08:00
if 'json' in obj and name in obj['json']:
2013-01-17 01:45:37 +08:00
upload[name] = self.parse_json(value)
2012-04-19 23:03:24 +08:00
else:
upload[name] = value
2010-11-20 01:37:26 +08:00
for m in mandatory:
2011-03-10 23:00:45 +08:00
assert_usage(m in upload.keys(),
2010-11-20 01:37:26 +08:00
'mandatory argument "{0}" required'.format(m))
2012-02-21 23:37:28 +08:00
if 'vhost' not in mandatory:
2012-02-22 21:12:25 +08:00
upload['vhost'] = self.options.vhost or self.options.declare_vhost
2010-10-19 17:39:25 +08:00
uri_args = {}
2011-03-10 23:00:45 +08:00
for k in upload:
v = upload[k]
2015-02-26 00:45:47 +08:00
if v and isinstance(v, (str, bytes)):
2018-05-25 01:53:01 +08:00
uri_args[k] = quote_plus(v).replace("+", "%20")
2011-03-10 22:58:02 +08:00
if k == 'destination_type':
uri_args['destination_char'] = v[0]
2011-02-26 01:00:13 +08:00
uri = uri_template.format(**uri_args)
2011-03-10 23:00:45 +08:00
return (uri, upload)
2010-10-19 01:51:42 +08:00
2013-01-17 01:45:37 +08:00
def parse_json(self, text):
try:
return json.loads(text)
except ValueError:
2017-08-03 01:26:22 +08:00
eprint("ERROR: Could not parse JSON:\n {0}".format(text))
2013-01-17 01:45:37 +08:00
sys.exit(1)
2012-10-17 19:24:17 +08:00
def format_list(json_list, columns, args, options):
2010-10-19 01:21:10 +08:00
format = options.format
formatter = None
if format == "raw_json":
2017-08-03 01:26:22 +08:00
print(json_list)
2010-10-19 01:21:10 +08:00
return
elif format == "pretty_json":
2010-10-13 00:56:45 +08:00
enc = json.JSONEncoder(False, False, True, True, True, 2)
2017-08-03 01:26:22 +08:00
print(enc.encode(json.loads(json_list)))
2010-10-19 01:21:10 +08:00
return
2010-11-17 18:17:39 +08:00
else:
formatter = FORMATS[format]
2010-10-19 18:52:38 +08:00
assert_usage(formatter != None,
"Format {0} not recognised".format(format))
2012-10-17 19:24:17 +08:00
formatter_instance = formatter(columns, args, options)
2010-10-19 01:21:10 +08:00
formatter_instance.display(json_list)
2010-10-13 00:56:45 +08:00
2010-10-19 01:21:10 +08:00
class Lister:
def verbose(self, string):
if self.options.verbose:
2017-08-03 01:26:22 +08:00
print(string)
2010-10-13 00:56:45 +08:00
2010-10-19 01:21:10 +08:00
def display(self, json_list):
2015-02-26 00:45:47 +08:00
depth = sys.maxsize
2010-12-22 00:10:38 +08:00
if len(self.columns) == 0:
depth = int(self.options.depth)
(columns, table) = self.list_to_table(json.loads(json_list), depth)
2010-10-19 01:21:10 +08:00
if len(table) > 0:
self.display_list(columns, table)
2010-10-13 00:56:45 +08:00
else:
self.verbose("No items")
2010-10-19 01:21:10 +08:00
def list_to_table(self, items, max_depth):
columns = {}
column_ix = {}
row = None
table = []
2010-10-13 00:56:45 +08:00
2010-10-19 01:21:10 +08:00
def add(prefix, depth, item, fun):
2010-10-13 00:56:45 +08:00
for key in item:
2011-05-09 23:08:55 +08:00
column = prefix == '' and key or (prefix + '.' + key)
2012-01-04 23:15:54 +08:00
subitem = item[key]
if type(subitem) == dict:
2015-02-26 00:45:47 +08:00
if 'json' in self.obj_info and key in self.obj_info['json']:
2012-10-17 19:24:17 +08:00
fun(column, json.dumps(subitem))
else:
if depth < max_depth:
add(column, depth + 1, subitem, fun)
2012-01-04 23:15:54 +08:00
elif type(subitem) == list:
# The first branch has slave nodes in queues in
# mind (which come out looking decent); the second
# one has applications in nodes (which look less
# so, but what would look good?).
2015-02-26 00:45:47 +08:00
if [x for x in subitem if type(x) != str] == []:
2012-01-04 23:15:54 +08:00
serialised = " ".join(subitem)
else:
serialised = json.dumps(subitem)
fun(column, serialised)
2010-10-19 01:21:10 +08:00
else:
2012-01-04 23:15:54 +08:00
fun(column, subitem)
2010-10-19 01:21:10 +08:00
def add_to_columns(col, val):
columns[col] = True
def add_to_row(col, val):
2010-12-22 00:10:38 +08:00
if col in column_ix:
2018-05-04 17:52:24 +08:00
if val is not None:
row[column_ix[col]] = maybe_utf8(val)
else:
row[column_ix[col]] = None
2010-12-22 00:10:38 +08:00
if len(self.columns) == 0:
for item in items:
add('', 1, item, add_to_columns)
2015-02-26 00:45:47 +08:00
columns = list(columns.keys())
2010-12-22 00:10:38 +08:00
columns.sort(key=column_sort_key)
else:
columns = self.columns
2010-10-19 01:21:10 +08:00
2015-02-26 00:45:47 +08:00
for i in range(0, len(columns)):
2010-10-19 01:21:10 +08:00
column_ix[columns[i]] = i
for item in items:
row = len(columns) * ['']
add('', 1, item, add_to_row)
table.append(row)
return (columns, table)
class TSVList(Lister):
2012-10-17 19:24:17 +08:00
def __init__(self, columns, obj_info, options):
2010-12-22 00:10:38 +08:00
self.columns = columns
2012-10-17 19:24:17 +08:00
self.obj_info = obj_info
2010-10-19 01:21:10 +08:00
self.options = options
def display_list(self, columns, table):
2012-02-21 23:37:52 +08:00
head = "\t".join(columns)
2010-10-19 01:21:10 +08:00
self.verbose(head)
for row in table:
2012-02-21 23:37:52 +08:00
line = "\t".join(row)
2017-08-03 01:26:22 +08:00
print(line)
2010-10-19 01:21:10 +08:00
class LongList(Lister):
2012-10-17 19:24:17 +08:00
def __init__(self, columns, obj_info, options):
2010-12-22 00:10:38 +08:00
self.columns = columns
2012-10-17 19:24:17 +08:00
self.obj_info = obj_info
2010-10-19 01:21:10 +08:00
self.options = options
def display_list(self, columns, table):
sep = "\n" + "-" * 80 + "\n"
max_width = 0
for col in columns:
max_width = max(max_width, len(col))
2015-02-26 00:45:47 +08:00
fmt = "{0:>" + str(max_width) + "}: {1}"
2017-08-03 01:26:22 +08:00
print(sep)
2015-02-26 00:45:47 +08:00
for i in range(0, len(table)):
for j in range(0, len(columns)):
2017-08-03 01:26:22 +08:00
print(fmt.format(columns[j], table[i][j]))
print(sep)
2010-10-19 01:21:10 +08:00
class TableList(Lister):
2012-10-17 19:24:17 +08:00
def __init__(self, columns, obj_info, options):
2010-12-22 00:10:38 +08:00
self.columns = columns
2012-10-17 19:24:17 +08:00
self.obj_info = obj_info
2010-10-19 01:21:10 +08:00
self.options = options
def display_list(self, columns, table):
total = [columns]
total.extend(table)
self.ascii_table(total)
2010-10-13 00:56:45 +08:00
def ascii_table(self, rows):
table = ""
col_widths = [0] * len(rows[0])
2015-02-26 00:45:47 +08:00
for i in range(0, len(rows[0])):
for j in range(0, len(rows)):
2010-10-13 00:56:45 +08:00
col_widths[i] = max(col_widths[i], len(rows[j][i]))
self.ascii_bar(col_widths)
self.ascii_row(col_widths, rows[0], "^")
self.ascii_bar(col_widths)
for row in rows[1:]:
self.ascii_row(col_widths, row, "<")
self.ascii_bar(col_widths)
def ascii_row(self, col_widths, row, align):
txt = "|"
2015-02-26 00:45:47 +08:00
for i in range(0, len(col_widths)):
fmt = " {0:" + align + str(col_widths[i]) + "} "
2010-10-13 00:56:45 +08:00
txt += fmt.format(row[i]) + "|"
2017-08-03 01:26:22 +08:00
print(txt)
2010-10-13 00:56:45 +08:00
def ascii_bar(self, col_widths):
txt = "+"
for w in col_widths:
txt += ("-" * (w + 2)) + "+"
2017-08-03 01:26:22 +08:00
print(txt)
2010-10-13 00:56:45 +08:00
2010-11-09 18:55:04 +08:00
class KeyValueList(Lister):
2012-10-17 19:24:17 +08:00
def __init__(self, columns, obj_info, options):
2010-12-22 00:10:38 +08:00
self.columns = columns
2012-10-17 19:24:17 +08:00
self.obj_info = obj_info
2010-11-09 18:55:04 +08:00
self.options = options
def display_list(self, columns, table):
2015-02-26 00:45:47 +08:00
for i in range(0, len(table)):
2010-11-09 18:55:04 +08:00
row = []
2015-02-26 00:45:47 +08:00
for j in range(0, len(columns)):
2010-11-09 18:55:04 +08:00
row.append("{0}=\"{1}\"".format(columns[j], table[i][j]))
2017-08-03 01:26:22 +08:00
print(" ".join(row))
2010-11-09 18:55:04 +08:00
2010-11-17 18:17:39 +08:00
# TODO handle spaces etc in completable names
class BashList(Lister):
2012-10-17 19:24:17 +08:00
def __init__(self, columns, obj_info, options):
2010-12-22 00:10:38 +08:00
self.columns = columns
2012-10-17 19:24:17 +08:00
self.obj_info = obj_info
2010-11-17 18:17:39 +08:00
self.options = options
def display_list(self, columns, table):
ix = None
2015-02-26 00:45:47 +08:00
for i in range(0, len(columns)):
2010-11-17 18:17:39 +08:00
if columns[i] == 'name':
ix = i
if ix is not None:
res = []
for row in table:
res.append(row[ix])
2017-08-03 01:26:22 +08:00
print(" ".join(res))
2010-11-17 18:17:39 +08:00
FORMATS = {
'raw_json' : None, # Special cased
'pretty_json' : None, # Ditto
'tsv' : TSVList,
'long' : LongList,
'table' : TableList,
'kvp' : KeyValueList,
'bash' : BashList
}
2011-03-10 22:58:02 +08:00
def write_payload_file(payload_file, json_list):
result = json.loads(json_list)[0]
payload = result['payload']
payload_encoding = result['payload_encoding']
2012-06-06 19:14:08 +08:00
f = open(payload_file, 'w')
if payload_encoding == 'base64':
data = base64.b64decode(payload)
else:
data = payload
f.write(data)
f.close()
2011-03-10 22:58:02 +08:00
2010-11-17 18:17:39 +08:00
def print_bash_completion():
script = """# This is a bash completion script for rabbitmqadmin.
# Redirect it to a file, then source it or copy it to /etc/bash_completion.d
# to get tab completion. rabbitmqadmin must be on your PATH for this to work.
_rabbitmqadmin()
{
local cur prev opts base
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
2012-02-13 22:42:35 +08:00
opts="list show declare delete close purge import export get publish help"
2012-11-06 22:12:52 +08:00
fargs="--help --host --port --vhost --username --password --format --depth --sort --sort-reverse"
2010-11-17 18:17:39 +08:00
case "${prev}" in
2016-02-16 17:07:33 +08:00
list)
COMPREPLY=( $(compgen -W '""" + " ".join(LISTABLE) + """' -- ${cur}) )
2010-11-17 18:17:39 +08:00
return 0
;;
2016-02-16 17:07:33 +08:00
show)
COMPREPLY=( $(compgen -W '""" + " ".join(SHOWABLE) + """' -- ${cur}) )
2011-01-03 21:20:13 +08:00
return 0
;;
2016-02-16 17:07:33 +08:00
declare)
COMPREPLY=( $(compgen -W '""" + " ".join(DECLARABLE.keys()) + """' -- ${cur}) )
2010-11-17 18:17:39 +08:00
return 0
;;
2016-02-16 17:07:33 +08:00
delete)
COMPREPLY=( $(compgen -W '""" + " ".join(DELETABLE.keys()) + """' -- ${cur}) )
2010-11-17 18:17:39 +08:00
return 0
;;
2016-02-16 17:07:33 +08:00
close)
COMPREPLY=( $(compgen -W '""" + " ".join(CLOSABLE.keys()) + """' -- ${cur}) )
2010-11-17 18:17:39 +08:00
return 0
;;
2016-02-16 17:07:33 +08:00
purge)
COMPREPLY=( $(compgen -W '""" + " ".join(PURGABLE.keys()) + """' -- ${cur}) )
2010-11-17 18:17:39 +08:00
return 0
;;
2016-02-16 17:07:33 +08:00
export)
COMPREPLY=( $(compgen -f ${cur}) )
2010-11-17 18:17:39 +08:00
return 0
;;
2016-02-16 17:07:33 +08:00
import)
COMPREPLY=( $(compgen -f ${cur}) )
2010-11-17 18:17:39 +08:00
return 0
;;
2016-02-16 17:07:33 +08:00
help)
2012-02-13 22:42:35 +08:00
opts="subcommands config"
2016-02-16 17:07:33 +08:00
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
2012-02-13 22:42:35 +08:00
return 0
;;
2016-02-16 17:07:33 +08:00
-H)
COMPREPLY=( $(compgen -A hostname ${cur}) )
2010-11-17 18:17:39 +08:00
return 0
;;
2016-02-16 17:07:33 +08:00
--host)
COMPREPLY=( $(compgen -A hostname ${cur}) )
2013-01-18 01:39:46 +08:00
return 0
;;
2016-02-16 17:07:33 +08:00
-V)
2013-01-18 01:39:46 +08:00
opts="$(rabbitmqadmin -q -f bash list vhosts)"
2016-02-16 17:07:33 +08:00
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
2013-01-18 01:39:46 +08:00
return 0
;;
2016-02-16 17:07:33 +08:00
--vhost)
2010-11-17 18:17:39 +08:00
opts="$(rabbitmqadmin -q -f bash list vhosts)"
2016-02-16 17:07:33 +08:00
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
2010-11-17 18:17:39 +08:00
return 0
;;
2016-02-16 17:07:33 +08:00
-u)
2010-11-17 18:17:39 +08:00
opts="$(rabbitmqadmin -q -f bash list users)"
2016-02-16 17:07:33 +08:00
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
2010-11-17 18:17:39 +08:00
return 0
;;
2016-02-16 17:07:33 +08:00
--username)
2013-01-18 01:39:46 +08:00
opts="$(rabbitmqadmin -q -f bash list users)"
2016-02-16 17:07:33 +08:00
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
2013-01-18 01:39:46 +08:00
return 0
;;
2016-02-16 17:07:33 +08:00
-f)
COMPREPLY=( $(compgen -W \"""" + " ".join(FORMATS.keys()) + """\" -- ${cur}) )
2013-01-18 01:39:46 +08:00
return 0
;;
2016-02-16 17:07:33 +08:00
--format)
COMPREPLY=( $(compgen -W \"""" + " ".join(FORMATS.keys()) + """\" -- ${cur}) )
2010-11-17 18:17:39 +08:00
return 0
;;
"""
for l in LISTABLE:
key = l[0:len(l) - 1]
script += " " + key + """)
opts="$(rabbitmqadmin -q -f bash list """ + l + """)"
2016-02-16 17:07:33 +08:00
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
2010-11-17 18:17:39 +08:00
return 0
;;
"""
script += """ *)
;;
esac
COMPREPLY=($(compgen -W "${opts} ${fargs}" -- ${cur}))
return 0
}
complete -F _rabbitmqadmin rabbitmqadmin
"""
2017-08-03 01:26:22 +08:00
print(script)
2010-11-09 18:55:04 +08:00
2010-10-13 00:56:45 +08:00
if __name__ == "__main__":
main()