Loading .travis/travis.sh +40 −43 File changed.Preview size limit exceeded, changes collapsed. Show changes Documents/bin/rabbitmqadmin +108 −74 Original line number Diff line number Diff line #!/usr/bin/env python #!/usr/bin/env python3 # 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 # https://www.mozilla.org/MPL/ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. # # 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. # # The Initial Developer of the Original Code is GoPivotal, Inc. # Copyright (c) 2007-2018 Pivotal Software, Inc. All rights reserved. # Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. from __future__ import print_function from optparse import OptionParser, TitledHelpFormatter import base64 import copy import json import os import socket Loading Loading @@ -109,6 +101,24 @@ URIS = { 'vhost_limit': '/vhost-limits/{vhost}/{name}' } def queue_upload_fixup(upload): # rabbitmq/rabbitmq-management#761 # # In general, the fixup_upload argument can be used to fixup/change the # upload dict after all argument parsing is complete. # # This simplifies setting the queue type for a new queue by allowing the # user to use a queue_type=quorum argument rather than the somewhat confusing # arguments='{"x-queue-type":"quorum"}' parameter # if 'queue_type' in upload: queue_type = upload.get('queue_type') arguments = upload.get('arguments', {}) arguments['x-queue-type'] = queue_type upload['arguments'] = arguments DECLARABLE = { 'exchange': {'mandatory': ['name', 'type'], 'json': ['arguments'], Loading @@ -117,7 +127,8 @@ DECLARABLE = { 'queue': {'mandatory': ['name'], 'json': ['arguments'], 'optional': {'auto_delete': 'false', 'durable': 'true', 'arguments': {}, 'node': None}}, 'arguments': {}, 'node': None, 'queue_type': None}, 'fixup_upload': queue_upload_fixup}, 'binding': {'mandatory': ['source', 'destination'], 'json': ['arguments'], 'optional': {'destination_type': 'queue', Loading Loading @@ -146,8 +157,8 @@ DECLARABLE = { DELETABLE = { 'exchange': {'mandatory': ['name']}, 'queue': {'mandatory': ['name']}, 'binding': {'mandatory': ['source', 'destination_type', 'destination', 'properties_key']}, 'binding': {'mandatory': ['source', 'destination_type', 'destination'], 'optional': {'properties_key': '~'}}, 'vhost': {'mandatory': ['name']}, 'user': {'mandatory': ['name']}, 'permission': {'mandatory': ['vhost', 'user']}, Loading Loading @@ -188,7 +199,7 @@ for k in DECLARABLE: for k in DELETABLE: DELETABLE[k]['uri'] = URIS[k] DELETABLE[k]['optional'] = {} DELETABLE[k]['optional'] = DELETABLE[k].get('optional', {}) DELETABLE['binding']['uri'] = URIS['binding_del'] Loading Loading @@ -312,6 +323,8 @@ def fmt_usage_stanza(root, verb): default_options = {"hostname": "localhost", "port": "15672", # default config file section name "node": "default", "path_prefix": "", "declare_vhost": "/", "username": "guest", Loading Loading @@ -410,56 +423,72 @@ def default_config(): def make_configuration(): make_parser() (options, args) = parser.parse_args() setattr(options, "declare_vhost", None) if options.version: (cli_options, args) = parser.parse_args() if cli_options.version: print_version() if options.config is None: setattr(cli_options, "declare_vhost", None) final_options = copy.copy(cli_options) # Resolve config file path if cli_options.config is None: config_file = default_config() if config_file is not None: setattr(options, "config", config_file) setattr(final_options, "config", config_file) else: if not os.path.isfile(options.config): assert_usage(False, "Could not read config file '%s'" % options.config) if options.node is None and options.config: options.node = "default" 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: config = ConfigParser() if not os.path.isfile(cli_options.config): assert_usage(False, "Could not read config file '%s'" % cli_options.config) final_options = merge_default_options(cli_options, final_options) final_options = merge_config_file_options(cli_options, final_options) final_options = expand_base_uri_options(cli_options, final_options) return (final_options, args) def merge_default_options(cli_options, final_options): for (key, default_val) in default_options.items(): if getattr(cli_options, key) is None: setattr(final_options, key, default_val) return final_options def merge_config_file_options(cli_options, final_options): # Parse config file and load it, making sure that CLI flags # take precedence if final_options.config is not None: config_parser = ConfigParser() try: config.read(options.config) new_conf = dict(config.items(options.node)) config_parser.read(final_options.config) section_settings = dict(config_parser.items(final_options.node)) except NoSectionError as error: if options.node == "default": # Report if an explicitly provided section (node) does not exist in the file if final_options.node == "default": pass else: msg = "Could not read section '%s' in config file '%s':\n %s" % (options.node, options.config, error) msg = "Could not read section '%s' in config file '%s':\n %s" % (final_options.node, final_options.config, error) assert_usage(False, msg) else: for key, val in new_conf.items(): for key, section_val in section_settings.items(): # special case --ssl if key == 'ssl': setattr(options, key, val == "True") setattr(final_options, key, section_val == "True") else: setattr(options, key, val) # if CLI options do not contain this key, set it from the config file if getattr(cli_options, key) is None: setattr(final_options, key, section_val) return final_options def expand_base_uri_options(cli_options, final_options): # if --base-uri is passed, set connection parameters from it if options.base_uri is not None: u = urlparse.urlparse(options.base_uri) if final_options.base_uri is not None: u = urlparse.urlparse(final_options.base_uri) for key in ["hostname", "port", "username", "password"]: if getattr(u, key) is not None: setattr(options, key, getattr(u, key)) setattr(final_options, key, getattr(u, key)) if u.path is not None and (u.path != "") and (u.path != "/"): eprint("WARNING: path in --base-uri is ignored. Please specify --vhost and/or --path-prefix separately.\n") return (options, args) return final_options def assert_usage(expr, error): if not expr: Loading Loading @@ -671,17 +700,15 @@ class Management: if self.options.vhost: uri += "/%s" % quote_plus(self.options.vhost) definitions = self.get(uri) f = open(path, 'w') f.write(definitions) f.close() with open(path, 'wb') as f: f.write(definitions.encode()) self.verbose("Exported definitions for %s to \"%s\"" % (self.options.hostname, path)) def invoke_import(self): path = self.get_arg() f = open(path, 'r') with open(path, 'rb') as f: definitions = f.read() f.close() uri = "/definitions" if self.options.vhost: uri += "/%s" % quote_plus(self.options.vhost) Loading Loading @@ -759,6 +786,17 @@ class Management: (uri, upload) = self.parse_args(self.args[1:], obj) return (obj_type, uri, upload) def assert_mandatory_keys(self, mandatory, upload): for m in mandatory: if type(m) is list: a_set = set(m) b_set = set(upload.keys()) assert_usage((a_set & b_set), 'one of mandatory arguments "{0}" is required'.format(m)) else: assert_usage(m in upload.keys(), 'mandatory argument "{0}" is required'.format(m)) def parse_args(self, args, obj): mandatory = obj['mandatory'] optional = obj['optional'] Loading Loading @@ -787,15 +825,7 @@ class Management: upload[name] = self.parse_json(value) else: upload[name] = value for m in mandatory: if type(m) is list: a_set = set(m) b_set = set(upload.keys()) assert_usage((a_set & b_set), 'one of mandatory arguments "{0}" is required'.format(m)) else: assert_usage(m in upload.keys(), 'mandatory argument "{0}" is required'.format(m)) self.assert_mandatory_keys(mandatory, upload) if 'vhost' not in mandatory: upload['vhost'] = self.options.vhost or self.options.declare_vhost uri_args = {} Loading @@ -806,6 +836,9 @@ class Management: if k == 'destination_type': uri_args['destination_char'] = v[0] uri = uri_template.format(**uri_args) if 'fixup_upload' in obj: fixup = obj['fixup_upload'] fixup(upload) return (uri, upload) def parse_json(self, text): Loading @@ -823,8 +856,10 @@ def format_list(json_list, columns, args, options): print(json_list) return elif format == "pretty_json": enc = json.JSONEncoder(False, False, True, True, True, 2) print(enc.encode(json.loads(json_list))) json_list_parsed = json.loads(json_list) print(json.dumps(json_list_parsed, skipkeys=False, ensure_ascii=False, check_circular=True, allow_nan=True, sort_keys=True, indent=2)) return else: formatter = FORMATS[format] Loading Loading @@ -866,7 +901,7 @@ class Lister: if depth < max_depth: add(column, depth + 1, subitem, fun) elif type(subitem) == list: # The first branch has slave nodes in queues in # The first branch has mirrors 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?). Loading Loading @@ -1027,13 +1062,12 @@ def write_payload_file(payload_file, json_list): result = json.loads(json_list)[0] payload = result['payload'] payload_encoding = result['payload_encoding'] f = open(payload_file, 'w') with open(payload_file, 'wb') as f: if payload_encoding == 'base64': data = base64.b64decode(payload) else: data = payload f.write(data) f.close() f.write(data.encode("utf-8")) def print_bash_completion(): Loading Loading
Documents/bin/rabbitmqadmin +108 −74 Original line number Diff line number Diff line #!/usr/bin/env python #!/usr/bin/env python3 # 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 # https://www.mozilla.org/MPL/ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. # # 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. # # The Initial Developer of the Original Code is GoPivotal, Inc. # Copyright (c) 2007-2018 Pivotal Software, Inc. All rights reserved. # Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. from __future__ import print_function from optparse import OptionParser, TitledHelpFormatter import base64 import copy import json import os import socket Loading Loading @@ -109,6 +101,24 @@ URIS = { 'vhost_limit': '/vhost-limits/{vhost}/{name}' } def queue_upload_fixup(upload): # rabbitmq/rabbitmq-management#761 # # In general, the fixup_upload argument can be used to fixup/change the # upload dict after all argument parsing is complete. # # This simplifies setting the queue type for a new queue by allowing the # user to use a queue_type=quorum argument rather than the somewhat confusing # arguments='{"x-queue-type":"quorum"}' parameter # if 'queue_type' in upload: queue_type = upload.get('queue_type') arguments = upload.get('arguments', {}) arguments['x-queue-type'] = queue_type upload['arguments'] = arguments DECLARABLE = { 'exchange': {'mandatory': ['name', 'type'], 'json': ['arguments'], Loading @@ -117,7 +127,8 @@ DECLARABLE = { 'queue': {'mandatory': ['name'], 'json': ['arguments'], 'optional': {'auto_delete': 'false', 'durable': 'true', 'arguments': {}, 'node': None}}, 'arguments': {}, 'node': None, 'queue_type': None}, 'fixup_upload': queue_upload_fixup}, 'binding': {'mandatory': ['source', 'destination'], 'json': ['arguments'], 'optional': {'destination_type': 'queue', Loading Loading @@ -146,8 +157,8 @@ DECLARABLE = { DELETABLE = { 'exchange': {'mandatory': ['name']}, 'queue': {'mandatory': ['name']}, 'binding': {'mandatory': ['source', 'destination_type', 'destination', 'properties_key']}, 'binding': {'mandatory': ['source', 'destination_type', 'destination'], 'optional': {'properties_key': '~'}}, 'vhost': {'mandatory': ['name']}, 'user': {'mandatory': ['name']}, 'permission': {'mandatory': ['vhost', 'user']}, Loading Loading @@ -188,7 +199,7 @@ for k in DECLARABLE: for k in DELETABLE: DELETABLE[k]['uri'] = URIS[k] DELETABLE[k]['optional'] = {} DELETABLE[k]['optional'] = DELETABLE[k].get('optional', {}) DELETABLE['binding']['uri'] = URIS['binding_del'] Loading Loading @@ -312,6 +323,8 @@ def fmt_usage_stanza(root, verb): default_options = {"hostname": "localhost", "port": "15672", # default config file section name "node": "default", "path_prefix": "", "declare_vhost": "/", "username": "guest", Loading Loading @@ -410,56 +423,72 @@ def default_config(): def make_configuration(): make_parser() (options, args) = parser.parse_args() setattr(options, "declare_vhost", None) if options.version: (cli_options, args) = parser.parse_args() if cli_options.version: print_version() if options.config is None: setattr(cli_options, "declare_vhost", None) final_options = copy.copy(cli_options) # Resolve config file path if cli_options.config is None: config_file = default_config() if config_file is not None: setattr(options, "config", config_file) setattr(final_options, "config", config_file) else: if not os.path.isfile(options.config): assert_usage(False, "Could not read config file '%s'" % options.config) if options.node is None and options.config: options.node = "default" 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: config = ConfigParser() if not os.path.isfile(cli_options.config): assert_usage(False, "Could not read config file '%s'" % cli_options.config) final_options = merge_default_options(cli_options, final_options) final_options = merge_config_file_options(cli_options, final_options) final_options = expand_base_uri_options(cli_options, final_options) return (final_options, args) def merge_default_options(cli_options, final_options): for (key, default_val) in default_options.items(): if getattr(cli_options, key) is None: setattr(final_options, key, default_val) return final_options def merge_config_file_options(cli_options, final_options): # Parse config file and load it, making sure that CLI flags # take precedence if final_options.config is not None: config_parser = ConfigParser() try: config.read(options.config) new_conf = dict(config.items(options.node)) config_parser.read(final_options.config) section_settings = dict(config_parser.items(final_options.node)) except NoSectionError as error: if options.node == "default": # Report if an explicitly provided section (node) does not exist in the file if final_options.node == "default": pass else: msg = "Could not read section '%s' in config file '%s':\n %s" % (options.node, options.config, error) msg = "Could not read section '%s' in config file '%s':\n %s" % (final_options.node, final_options.config, error) assert_usage(False, msg) else: for key, val in new_conf.items(): for key, section_val in section_settings.items(): # special case --ssl if key == 'ssl': setattr(options, key, val == "True") setattr(final_options, key, section_val == "True") else: setattr(options, key, val) # if CLI options do not contain this key, set it from the config file if getattr(cli_options, key) is None: setattr(final_options, key, section_val) return final_options def expand_base_uri_options(cli_options, final_options): # if --base-uri is passed, set connection parameters from it if options.base_uri is not None: u = urlparse.urlparse(options.base_uri) if final_options.base_uri is not None: u = urlparse.urlparse(final_options.base_uri) for key in ["hostname", "port", "username", "password"]: if getattr(u, key) is not None: setattr(options, key, getattr(u, key)) setattr(final_options, key, getattr(u, key)) if u.path is not None and (u.path != "") and (u.path != "/"): eprint("WARNING: path in --base-uri is ignored. Please specify --vhost and/or --path-prefix separately.\n") return (options, args) return final_options def assert_usage(expr, error): if not expr: Loading Loading @@ -671,17 +700,15 @@ class Management: if self.options.vhost: uri += "/%s" % quote_plus(self.options.vhost) definitions = self.get(uri) f = open(path, 'w') f.write(definitions) f.close() with open(path, 'wb') as f: f.write(definitions.encode()) self.verbose("Exported definitions for %s to \"%s\"" % (self.options.hostname, path)) def invoke_import(self): path = self.get_arg() f = open(path, 'r') with open(path, 'rb') as f: definitions = f.read() f.close() uri = "/definitions" if self.options.vhost: uri += "/%s" % quote_plus(self.options.vhost) Loading Loading @@ -759,6 +786,17 @@ class Management: (uri, upload) = self.parse_args(self.args[1:], obj) return (obj_type, uri, upload) def assert_mandatory_keys(self, mandatory, upload): for m in mandatory: if type(m) is list: a_set = set(m) b_set = set(upload.keys()) assert_usage((a_set & b_set), 'one of mandatory arguments "{0}" is required'.format(m)) else: assert_usage(m in upload.keys(), 'mandatory argument "{0}" is required'.format(m)) def parse_args(self, args, obj): mandatory = obj['mandatory'] optional = obj['optional'] Loading Loading @@ -787,15 +825,7 @@ class Management: upload[name] = self.parse_json(value) else: upload[name] = value for m in mandatory: if type(m) is list: a_set = set(m) b_set = set(upload.keys()) assert_usage((a_set & b_set), 'one of mandatory arguments "{0}" is required'.format(m)) else: assert_usage(m in upload.keys(), 'mandatory argument "{0}" is required'.format(m)) self.assert_mandatory_keys(mandatory, upload) if 'vhost' not in mandatory: upload['vhost'] = self.options.vhost or self.options.declare_vhost uri_args = {} Loading @@ -806,6 +836,9 @@ class Management: if k == 'destination_type': uri_args['destination_char'] = v[0] uri = uri_template.format(**uri_args) if 'fixup_upload' in obj: fixup = obj['fixup_upload'] fixup(upload) return (uri, upload) def parse_json(self, text): Loading @@ -823,8 +856,10 @@ def format_list(json_list, columns, args, options): print(json_list) return elif format == "pretty_json": enc = json.JSONEncoder(False, False, True, True, True, 2) print(enc.encode(json.loads(json_list))) json_list_parsed = json.loads(json_list) print(json.dumps(json_list_parsed, skipkeys=False, ensure_ascii=False, check_circular=True, allow_nan=True, sort_keys=True, indent=2)) return else: formatter = FORMATS[format] Loading Loading @@ -866,7 +901,7 @@ class Lister: if depth < max_depth: add(column, depth + 1, subitem, fun) elif type(subitem) == list: # The first branch has slave nodes in queues in # The first branch has mirrors 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?). Loading Loading @@ -1027,13 +1062,12 @@ def write_payload_file(payload_file, json_list): result = json.loads(json_list)[0] payload = result['payload'] payload_encoding = result['payload_encoding'] f = open(payload_file, 'w') with open(payload_file, 'wb') as f: if payload_encoding == 'base64': data = base64.b64decode(payload) else: data = payload f.write(data) f.close() f.write(data.encode("utf-8")) def print_bash_completion(): Loading