Giuseppe Lavagetto has submitted this change and it was merged.

Change subject: confctl: allow regex expression and a global "all"
......................................................................


confctl: allow regex expression and a global "all"

Change-Id: I377d5476d16c8df416bfca58f750f99c643f8a8e
---
M conftool/__init__.py
M conftool/cli/tool.py
M conftool/tests/unit/__init__.py
A conftool/tests/unit/test_cli_tool.py
M conftool/tests/unit/test_node.py
M debian/changelog
M setup.py
7 files changed, 122 insertions(+), 38 deletions(-)

Approvals:
  Giuseppe Lavagetto: Verified; Looks good to me, approved



diff --git a/conftool/__init__.py b/conftool/__init__.py
index 93456f7..9a28331 100644
--- a/conftool/__init__.py
+++ b/conftool/__init__.py
@@ -88,7 +88,7 @@
         try:
             setattr(self, key, validator(values[key]))
         except Exception as e:
-            _log.error("Value for key %s is invalid: %s",
+            _log.info("Value for key %s is invalid: %s",
                        key, e)
             if set_defaults:
                 val = self.get_default(key)
diff --git a/conftool/cli/tool.py b/conftool/cli/tool.py
index 31e9fad..1ae4eaf 100644
--- a/conftool/cli/tool.py
+++ b/conftool/cli/tool.py
@@ -8,9 +8,51 @@
 from conftool.drivers import BackendError
 # TODO: auto import these somehow
 from conftool import service, node
+import re
 
 object_types = {"node": node.Node, "service": service.Service}
 
+
+def host_list(name, cur_dir, act):
+    warn = False
+    if name == "all":
+        leaves = KVObject.backend.driver.ls(cur_dir)
+        if act == "get":
+            print json.dumps(dict(leaves))
+            return []
+        else:
+            retval = leaves.keys()
+            warn = True
+    elif not name.startswith('re:'):
+        return [name]
+    else:
+        regex = name.replace('re:', '', 1)
+        try:
+            r = re.compile(regex)
+        except:
+            _log.critical("Invalid regexp: %s", regex)
+            sys.exit(1)
+        all = KVObject.backend.driver.ls(cur_dir).keys()
+        retval = [objname for objname in all if r.match(objname)]
+        warn = (len(all) <= 2 * len(retval))
+    if warn and act in ['set', 'del']:
+        raise_warning()
+    return retval
+
+def raise_warning():
+    if not sys.stdin.isatty() or not sys.stdout.isatty():
+        print "Destructive operations are not scriptable"
+        " and should be run from the command line"
+        sys.exit(1)
+
+    print "You are operating on more than half of the objects, this is "
+    "potentially VERY DANGEROUS: do you want to continue?"
+    print "If so, please type: 'Yes, I am sure of what I am doing.'"
+    a = raw_input("confctl>")
+    if a == "Yes, I am sure of what I am doing.":
+        return True
+    print "Aborting"
+    sys.exit(1)
 
 def main(cmdline=None):
     if cmdline is None:
@@ -32,7 +74,8 @@
                         choices=object_types.keys(), default='node')
     parser.add_argument('--action', action="append", metavar="ACTIONS",
                         help="the action to take: "
-                        " [set/k1=v1:k2=v2...|get|delete] node", nargs=2,
+                        " [set/k1=v1:k2=v2...|get|delete]"
+                        " node|all|re:<regex>", nargs=2,
                         required=True)
     parser.add_argument('--debug', action="store_true",
                         default=False, help="print debug info")
@@ -59,26 +102,24 @@
         sys.exit(1)
 
     for unit in args.action:
-        try:
-            act, name = unit
-            if act == 'get' and name == "all":
-                cur_dir = cls.dir(*tags)
-                print json.dumps(dict(KVObject.backend.driver.ls(cur_dir)))
-                return
-            # Oh python I <3 you...
-            arguments = list(tags)
-            arguments.append(name)
-            obj = cls(*arguments)
-            a = action.Action(obj, act)
-            msg = a.run()
-        except action.ActionError as e:
-            _log.error("Invalid action, reason: %s", str(e))
-        except BackendError as e:
-            _log.error("Failure writing to the kvstore: %s", str(e))
-        except Exception as e:
-            _log.error("Generic action failure: %s", str(e))
-        else:
-            print(msg)
+        act, n = unit
+        cur_dir = cls.dir(*tags)
+        for name in host_list(n, cur_dir, act):
+            try:
+                # Oh python I <3 you...
+                arguments = list(tags)
+                arguments.append(name)
+                obj = cls(*arguments)
+                a = action.Action(obj, act)
+                msg = a.run()
+            except action.ActionError as e:
+                _log.error("Invalid action, reason: %s", str(e))
+            except BackendError as e:
+                _log.error("Failure writing to the kvstore: %s", str(e))
+            except Exception as e:
+                _log.error("Generic action failure: %s", str(e))
+            else:
+                print(msg)
 
 
 if __name__ == '__main__':
diff --git a/conftool/tests/unit/__init__.py b/conftool/tests/unit/__init__.py
index e69de29..aeb1efd 100644
--- a/conftool/tests/unit/__init__.py
+++ b/conftool/tests/unit/__init__.py
@@ -0,0 +1,14 @@
+from conftool import drivers
+
+
+class MockDriver(drivers.BaseDriver):
+
+    def __init__(self, config):
+        self.base_path = '/base_path/v2'
+
+
+class MockBackend(object):
+
+    def __init__(self, config):
+        self.config = config
+        self.driver = MockDriver(config)
diff --git a/conftool/tests/unit/test_cli_tool.py 
b/conftool/tests/unit/test_cli_tool.py
new file mode 100644
index 0000000..4fefc74
--- /dev/null
+++ b/conftool/tests/unit/test_cli_tool.py
@@ -0,0 +1,36 @@
+import unittest
+import mock
+from conftool import KVObject, configuration
+from conftool.tests.unit import MockBackend
+from conftool.cli import tool
+
+class TestCliTool(unittest.TestCase):
+
+    def setUp(self):
+        KVObject.backend = MockBackend({})
+        KVObject.config = configuration.Config(driver="")
+
+    def _mock_list(self, values):
+        KVObject.backend.driver.ls = mock.MagicMock(return_value=values)
+
+
+    def test_get_hosts(self):
+        """Tests getting the host list"""
+        host_dir = {
+            'cp1011.example.com': {'pooled': 'yes'},
+            'cp1020.example.com': {'pooled': 'no'},
+            'cp1014.local': {'pooled': 'no'}
+        }
+        self._mock_list(host_dir)
+        l = tool.host_list('simple', '/whatever', 'get')
+        self.assertEquals(l, ['simple'])
+        l = tool.host_list('all', '/whatever', 'dummy')
+        self.assertItemsEqual(l, host_dir.keys())
+        l = tool.host_list('all', '/whatever', 'get')
+        self.assertEquals(l, [])
+        l = tool.host_list('re:.*\.local', '/whatever', 'get')
+        self.assertEquals(l, ['cp1014.local'])
+        l = tool.host_list('re:cp10[1-2][0-3]', '/whatever', 'get')
+        self.assertItemsEqual(l, ['cp1011.example.com', 'cp1020.example.com'])
+        with self.assertRaises(SystemExit):
+            tool.host_list('all', '/something', 'set')
diff --git a/conftool/tests/unit/test_node.py b/conftool/tests/unit/test_node.py
index 974ec0d..28493c1 100644
--- a/conftool/tests/unit/test_node.py
+++ b/conftool/tests/unit/test_node.py
@@ -1,20 +1,8 @@
 import unittest
 import mock
 from conftool import KVObject, node, service
-from conftool import configuration, drivers
-
-
-class MockDriver(drivers.BaseDriver):
-
-    def __init__(self, config):
-        self.base_path = '/base_path/v2'
-
-
-class MockBackend(object):
-
-    def __init__(self, config):
-        self.config = config
-        self.driver = MockDriver(config)
+from conftool import configuration
+from conftool.tests.unit import MockBackend
 
 
 class TestNode(unittest.TestCase):
@@ -30,7 +18,6 @@
     def setUp(self):
         KVObject.backend = MockBackend({})
         KVObject.config = configuration.Config(driver="")
-        pass
 
     @mock.patch('conftool.node.Node.get_default')
     def test_new_node(self, mocker):
diff --git a/debian/changelog b/debian/changelog
index a6f27cc..9776fbd 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+python-conftool (0.1.2) UNRELEASED; urgency=medium
+
+  * Added regexp matching of targets
+
+ -- Giuseppe Lavagetto <oblivian@flint>  Fri, 26 Jun 2015 07:51:14 +0200
+
 python-conftool (0.1.1) precise-wikimedia; urgency=medium
 
   * Fix a bug introduced with performance improvements
diff --git a/setup.py b/setup.py
index 182e822..033ba41 100755
--- a/setup.py
+++ b/setup.py
@@ -4,7 +4,7 @@
 
 setup(
     name='conftool',
-    version='0.1.1',
+    version='0.1.2',
     description='Collection of tools to interoperate with distributed k/v 
stores',
     author='Joe',
     author_email='[email protected]',

-- 
To view, visit https://gerrit.wikimedia.org/r/220536
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I377d5476d16c8df416bfca58f750f99c643f8a8e
Gerrit-PatchSet: 4
Gerrit-Project: operations/software/conftool
Gerrit-Branch: master
Gerrit-Owner: Giuseppe Lavagetto <[email protected]>
Gerrit-Reviewer: BBlack <[email protected]>
Gerrit-Reviewer: Giuseppe Lavagetto <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to