#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you 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 sys, json import qpid_dispatch_site from qpid_dispatch.management import Node, Url from collections import Mapping, Sequence from optparse import OptionGroup from qpid_dispatch_internal.tools.command import OptionParser, Option, UsageError, connection_options, check_args, main def attr_split(attrstr): """Split an attribute string of the form name=value or name to indicate None""" nv = attrstr.split("=", 1) if len(nv) == 1: return [nv[0], None] else: return nv class QdManage(): def __init__(self): self.operations = ['query', 'create', 'read', 'update', 'delete', 'get-types', 'get-operations', 'get-attributes', 'get-annotations', 'get-mgmt-nodes'] usage = "%prog [options...] [arguments...]" description = "Operations: "+", ".join(self.operations) op = OptionParser(usage=usage, option_class=Option, description=description) op.add_option('--type', help='Type of entity to operate on.') op.add_option('--name', help='Name of entity to operate on.') op.add_option('--identity', help='Identity of entity to operate on.', metavar="ID") op.add_option("--indent", type="int", default=2, help="Pretty-printing indent. -1 means don't pretty-print (default %default)") op.add_option('--stdin', action='store_true', help='Read attributes as JSON map or list of maps from stdin.') op.add_option_group(connection_options(op)) self.op = op def run(self, argv): self.opts, self.args = self.op.parse_args(argv[1:]) if len(self.args) == 0: raise UsageError("No operation specified") operation = self.args.pop(0) if operation not in self.operations: raise UsageError("Unknown operation: %s" % operation) self.node = Node(Url(self.opts.bus), self.opts.router) method = getattr(self, operation.replace('-','_')) method() def main(self, argv): return main(self.run, argv, self.op) def print_json(self, data): """Print data as JSON""" print json.dumps(data, indent=self.opts.indent) def call_node(self, method, *argnames, **kwargs): """Call method on node, use opts named in argnames""" names = set(argnames) for k in self.opts.__dict__: if k in names and hasattr(self.opts, k): kwargs[k] = getattr(self.opts, k) return getattr(self.node, method)(**kwargs) def call_bulk(self, func): """Call function for attributes from stdin or --attributes option""" if self.opts.stdin: data = json.load(sys.stdin) if isinstance(data, Mapping): self.print_json(func(data).attributes) elif isinstance(data, Sequence): self.print_json([func(attrs).attributes for attrs in data]) else: raise ValueError("stdin is not a JSON map or list") else: self.print_json(func(self.opts.attributes).attributes) def query(self): """query [ATTR...] Print attributes of entities.""" if self.args: self.opts.attribute_names = self.args result = self.call_node('query', 'type', 'attribute_names') self.print_json(result.get_dicts(clean=True)) def create(self): """create [ATTR=VALUE...] Create a new entity.""" if self.args: self.opts.attributes = dict(attr_split(arg) for arg in self.args) self.call_bulk(lambda attrs: self.call_node('create', 'type', 'name', attributes=attrs)) def read(self): """read Print attributes of selected entity.""" check_args(self.args, 0) self.print_json(self.call_node('read', 'type', 'name', 'identity').attributes) def update(self): """update [ATTR=VALUE...] Update an entity.""" if self.args: self.opts.attributes = dict(attr_split(arg) for arg in self.args) self.call_bulk( lambda attrs: self.call_node('update', 'type', 'name', 'identity', attributes=attrs)) def delete(self): """delete Delete an entity""" check_args(self.args, 0) self.call_node('delete', 'type', 'name', 'identity') def get_types(self): """get-types [TYPE] List entity types with their base types.""" check_args(self.args, 1) if self.args: self.opts.type = self.args[0] self.print_json(self.call_node('get_types', 'type')) def get_annotations(self): """get-annotations [TYPE] List entity types with the annotations they implement.""" check_args(self.args, 1) if self.args: self.opts.type = self.args[0] self.print_json(self.call_node('get_annotations', 'type')) def get_attributes(self): """get-attributes [TYPE] List entity types with their attributes.""" check_args(self.args, 1) if self.args: self.opts.type = self.args[0] self.print_json(self.call_node('get_attributes', 'type')) def get_operations(self): """get-operations [TYPE] List entity types with their operations.""" check_args(self.args, 1) if self.args: self.opts.type = self.args[0] self.print_json(self.call_node('get_operations', 'type')) def get_mgmt_nodes(self): """get-mgmt-nodes List of other known management nodes""" check_args(self.args, 0) self.print_json(self.call_node('get_mgmt_nodes')) if __name__ == "__main__": sys.exit(QdManage().main(sys.argv))