From 0ab31694d53dd262c6cf6ce9eb7c420459146cfc Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Thu, 10 Apr 2014 13:48:29 -0400 Subject: [PATCH] Implement create and delete from CLI --- bin/confetty | 54 ++++++++++++++++++++++++++----- confluent/config/configmanager.py | 3 ++ confluent/pluginapi.py | 2 ++ 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/bin/confetty b/bin/confetty index 73cdee63..eb32bc50 100755 --- a/bin/confetty +++ b/bin/confetty @@ -109,6 +109,9 @@ valid_commands = [ 'set', 'unset', 'create', + 'remove', + 'rm', + 'delete', ] candidates = None @@ -255,12 +258,36 @@ def do_command(command, server): return elif argv[0] == 'set': setvalues(argv[1:]) + elif argv[0] == 'create': + createresource(argv[1:]) + elif argv[0] in ('rm', 'delete', 'remove'): + delresource(argv[1]) elif argv[0] in ('unset', 'clear'): clearvalues(argv[1], argv[2:]) else: sys.stderr.write("%s: command not found...\n" % argv[0]) +def createresource(args): + resname = args[0] + attribs = args[1:] + keydata = parameterize_attribs(attribs) + if keydata is None: + return + targpath = fullpath_target(resname) + collection, _, resname = targpath.rpartition('/') + keydata['name'] = resname + makecall(session.create, (collection, keydata)) + + +def makecall(callout, args): + for response in callout(*args): + if 'error' in response: + if 'errorcode' in response: + exitcode = response['errorcode'] + sys.stderr.write('Error: ' + response['error'] + '\n') + + def clearvalues(resource, attribs): targpath = fullpath_target(resource) keydata = {} @@ -273,6 +300,10 @@ def clearvalues(resource, attribs): sys.stderr.write('Error: ' + res['error'] + '\n') +def delresource(resname): + resname = fullpath_target(resname) + makecall(session.delete, (resname,)) + def setvalues(attribs): if '=' in attribs[0]: # going straight to attribute resource = attribs[0][:attribs[0].index("=")] @@ -282,14 +313,9 @@ def setvalues(attribs): else: # an actual resource resource = attribs[0] attribs = attribs[1:] - keydata = {} - for attrib in attribs: - if '=' not in attrib: - sys.stderr.write("Invalid syntax %s" % attrib) - return - key = attrib[:attrib.index("=")] - value = attrib[attrib.index("=") + 1:] - keydata[key] = value + keydata = paramaterize_attribs(attribs) + if not keydata: + return targpath = fullpath_target(resource) for res in session.update(targpath, keydata): if 'error' in res: @@ -297,6 +323,18 @@ def setvalues(attribs): exitcode = res['errorcode'] sys.stderr.write('Error: ' + res['error'] + '\n') +def parameterize_attribs(attribs): + keydata = {} + for attrib in attribs: + if '=' not in attrib: + sys.stderr.write("Invalid syntax %s\n" % attrib) + return None + key = attrib[:attrib.index("=")] + value = attrib[attrib.index("=") + 1:] + if key == 'groups': + value = value.split(',') + keydata[key] = value + return keydata def fullpath_target(path, forcepath=False): diff --git a/confluent/config/configmanager.py b/confluent/config/configmanager.py index 92bcc729..5aa5828f 100644 --- a/confluent/config/configmanager.py +++ b/confluent/config/configmanager.py @@ -246,6 +246,7 @@ def set_global(globalname, value): def _mark_dirtykey(category, key, tenant=None): + key = key.encode('utf-8') with _dirtylock: if 'dirtykeys' not in _cfgstore: _cfgstore['dirtykeys'] = {} @@ -787,6 +788,7 @@ class ConfigManager(object): watcher(added=[], deleting=nodes, configmanager=self) changeset = {} for node in nodes: + node = node.encode('utf-8') if node in self._cfgstore['nodes']: self._sync_groups_to_node(node=node, groups=[], changeset=changeset) @@ -849,6 +851,7 @@ class ConfigManager(object): # first do a sanity check of the input upfront # this mitigates risk of arguments being partially applied for node in attribmap.iterkeys(): + node = node.encode('utf-8') if autocreate is False and node not in self._cfgstore['nodes']: raise ValueError("node {0} does not exist".format(node)) for attrname in attribmap[node].iterkeys(): diff --git a/confluent/pluginapi.py b/confluent/pluginapi.py index bb8e9739..3015ec69 100644 --- a/confluent/pluginapi.py +++ b/confluent/pluginapi.py @@ -255,6 +255,8 @@ def handle_path(path, operation, configmanager, inputdata=None): inputdata = msg.InputAttributes(pathcomponents, inputdata) create_node(inputdata.attribs, configmanager) return iterate_collections(configmanager.get_nodes()) + if len(pathcomponents) == 2: + iscollection = True if iscollection: if operation == "delete": return delete_node_collection(pathcomponents, configmanager)