Continue to add/remove the valid hosts or users to the label or ACL in
case of failures.
Modified the corresponding unittests:
. Adding check_playback() everywhere.
. Changing to the new Exception messages.
. New test for partial failure.
Risk: medium
Visibility: medium
Signed-off-by: Jean-Marc Eurin <[email protected]>
git-svn-id: http://test.kernel.org/svn/autotest/trunk@2525 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/cli/acl_unittest.py b/cli/acl_unittest.py
index 89ec59e..9f5c9ff 100755
--- a/cli/acl_unittest.py
+++ b/cli/acl_unittest.py
@@ -292,9 +292,40 @@
{'id': 'acl0',
'users': ['user0', 'user1']},
False,
- 'DoesNotExist: User matching query '
- 'does not exist.')],
- err_words_ok=['acl0', 'user0', 'user1'])
+ 'DoesNotExist: The following Users do not exist: '
+ 'user0, user1')],
+ err_words_ok=['user0', 'user1'])
+
+
+ def test_acl_add_bad_users_hosts(self):
+ self.run_cmd(argv=['atest', 'acl', 'add', 'acl0',
+ '-u', 'user0,user1', '-m', 'host0'],
+ rpcs=[('acl_group_add_users',
+ {'id': 'acl0',
+ 'users': ['user0', 'user1']},
+ False,
+ 'DoesNotExist: The following Users do not exist: '
+ 'user0'),
+ ('acl_group_add_users',
+ {'id': 'acl0',
+ 'users': ['user1']},
+ True,
+ None),
+ ('acl_group_add_hosts',
+ {'id': 'acl0',
+ 'hosts': ['host0', 'host1']},
+ False,
+ 'DoesNotExist: The following Hosts do not exist: '
+ 'host1'),
+ ('acl_group_add_hosts',
+ {'id': 'acl0',
+ 'hosts': ['host0']},
+ True,
+ None)],
+ out_words_ok=['acl0', 'user1', 'host0'],
+ out_words_no=['user0', 'host1'],
+ err_words_ok=['user0', 'host1'],
+ err_words_no=['user1', 'host0'])
class acl_remove_unittest(cli_mock.cli_unittest):
diff --git a/cli/action_common.py b/cli/action_common.py
index 13e1ac5..edcd8aa 100755
--- a/cli/action_common.py
+++ b/cli/action_common.py
@@ -217,9 +217,19 @@
# To skip the try/else
raise AttributeError
op = '%s_%s_%s' % (self.topic, self.op_action, what)
- self.execute_rpc(op=op, # The opcode
- item='%s (%s)' %(item, ','.join(uhs)), # The error
- **{'id': item, what: uhs}) # The data
+ try:
+ self.execute_rpc(op=op, # The opcode
+ **{'id': item, what: uhs}) # The data
+ setattr(self, 'good_%s' % what, uhs)
+ except topic_common.CliError, full_error:
+ bad_uhs = self.parse_json_exception(full_error)
+ good_uhs = list(set(uhs) - set(bad_uhs))
+ if bad_uhs and good_uhs:
+ self.execute_rpc(op=op,
+ **{'id': item, what: good_uhs})
+ setattr(self, 'good_%s' % what, good_uhs)
+ else:
+ raise
def execute(self):
@@ -227,7 +237,7 @@
add hosts to labels:
self.topic = 'label'
self.op_action = 'add'
- self.get_items() = the labels that the hosts
+ self.get_items() = the labels/ACLs that the hosts
should be added to"""
oks = {}
for item in self.get_items():
@@ -256,14 +266,14 @@
(self.msg_done,
self.msg_topic,
', '.join(users_ok)),
- self.users)
+ self.good_users)
if hosts_ok:
self.print_wrapped("%s %s %s host" %
(self.msg_done,
self.msg_topic,
', '.join(hosts_ok)),
- self.hosts)
+ self.good_hosts)
class atest_add(atest_add_or_remove):
diff --git a/cli/action_common_unittest.py b/cli/action_common_unittest.py
index 84c340f..95ef576 100755
--- a/cli/action_common_unittest.py
+++ b/cli/action_common_unittest.py
@@ -198,6 +198,7 @@
{'name': 'label0', 'platform': False},
True, 42)])
ret = acr.execute()
+ self.god.check_playback()
self.assert_(['label0'], ret)
@@ -210,6 +211,7 @@
{'name': 'label1', 'platform': False},
True, 43)])
ret = acr.execute()
+ self.god.check_playback()
self.assertEqualNoOrder(['label0', 'label1'], ret)
@@ -221,23 +223,10 @@
'''ValidationError:
{'name': 'This value must be unique (label0)'}''')])
ret = acr.execute()
+ self.god.check_playback()
self.assertEqualNoOrder([], ret)
- def test_execute_create_error_dup(self):
- acr = self._create_cr_del(['label0'])
- self.mock_rpcs([('add_label',
- {'name': 'label0', 'platform': False},
- True, 42),
- ('add_label',
- {'name': 'label0', 'platform': False},
- False,
- '''ValidationError:
- {'name': 'This value must be unique (label0)'}''')])
- ret = acr.execute()
- self.assertEqualNoOrder(['label0'], ret)
-
-
#
# Adding or Removing users or hosts from a topic(ACL or label)
@@ -254,8 +243,9 @@
addrm.hosts = hosts
addrm.topic = 'acl_group'
- addrm.usage_topic = 'ACL'
+ addrm.msg_topic = 'ACL'
addrm.op_action = 'add'
+ addrm.msg_done = 'Added to'
addrm.get_items = _items
return addrm
@@ -269,6 +259,7 @@
True,
None)])
acl_addrm._add_remove_uh_to_topic('acl0', 'users')
+ self.god.check_playback()
def test__add_remove_uh_to_topic_raise(self):
@@ -288,6 +279,7 @@
True,
None)])
(users_ok, hosts_ok) = acl_addrm.execute()
+ self.god.check_playback()
self.assertEqualNoOrder(['acl0'], users_ok)
self.assertEqual([], hosts_ok)
@@ -308,29 +300,79 @@
True,
None)])
(users_ok, hosts_ok) = acl_addrm.execute()
+ self.god.check_playback()
self.assertEqualNoOrder(['acl0'], users_ok)
self.assertEqualNoOrder(['acl0'], hosts_ok)
- self.god.check_playback()
def test_execute_add_or_remove_uh_to_topic_acl_bad_users(self):
acl_addrm = self._create_add_remove('acl0',
- users=['user0', 'user1'])
+ users=['user0', 'user1'])
self.mock_rpcs([('acl_group_add_users',
{'id': 'acl0',
'users': ['user0', 'user1']},
False,
- 'DoesNotExist: User matching query does not exist.')])
+ 'DoesNotExist: The following users do not exist: '
+ 'user0, user1')])
(users_ok, hosts_ok) = acl_addrm.execute()
+ self.god.check_playback()
self.assertEqual([], users_ok)
self.assertEqual([], hosts_ok)
- self.assertOutput(acl_addrm,
- err_words_ok=['DoesNotExist', 'acl0',
+ self.assertOutput(acl_addrm, (users_ok, hosts_ok),
+ err_words_ok=['DoesNotExist',
'acl_group_add_users',
'user0', 'user1'],
err_words_no = ['acl_group_add_hosts'])
+ def test_execute_add_or_remove_uh_to_topic_acl_bad_users_partial(self):
+ acl_addrm = self._create_add_remove('acl0',
+ users=['user0', 'user1'])
+ self.mock_rpcs([('acl_group_add_users',
+ {'id': 'acl0',
+ 'users': ['user0', 'user1']},
+ False,
+ 'DoesNotExist: The following users do not exist: '
+ 'user0'),
+ ('acl_group_add_users',
+ {'id': 'acl0',
+ 'users': ['user1']},
+ True,
+ None)])
+ (users_ok, hosts_ok) = acl_addrm.execute()
+ self.god.check_playback()
+ self.assertEqual(['acl0'], users_ok)
+ self.assertEqual([], hosts_ok)
+ self.assertOutput(acl_addrm, (users_ok, hosts_ok),
+ out_words_ok=['Added to ACL acl0', 'user1'],
+ err_words_ok=['DoesNotExist',
+ 'acl_group_add_users',
+ 'user0'],
+ err_words_no = ['acl_group_add_hosts'])
+
+
+ def test_execute_add_or_remove_uh_to_topic_acl_bad_u_partial_kill(self):
+ acl_addrm = self._create_add_remove('acl0',
+ users=['user0', 'user1'])
+ acl_addrm.kill_on_failure = True
+ self.mock_rpcs([('acl_group_add_users',
+ {'id': 'acl0',
+ 'users': ['user0', 'user1']},
+ False,
+ 'DoesNotExist: The following users do not exist: '
+ 'user0')])
+ sys.exit.expect_call(1).and_raises(cli_mock.ExitException)
+ self.god.mock_io()
+ self.assertRaises(cli_mock.ExitException, acl_addrm.execute)
+ (out, err) = self.god.unmock_io()
+ self.god.check_playback()
+ self._check_output(out=out, err=err,
+ err_words_ok=['DoesNotExist',
+ 'acl_group_add_users',
+ 'user0'],
+ err_words_no = ['acl_group_add_hosts'])
+
+
def test_execute_add_or_remove_uh_to_topic_acl_bad_users_good_hosts(self):
acl_addrm = self._create_add_remove('acl0',
users=['user0', 'user1'],
@@ -339,7 +381,8 @@
{'id': 'acl0',
'users': ['user0', 'user1']},
False,
- 'DoesNotExist: User matching query does not exist.'),
+ 'DoesNotExist: The following users do not exist: '
+ 'user0, user1'),
('acl_group_add_hosts',
{'id': 'acl0',
'hosts': ['host0', 'host1']},
@@ -347,10 +390,13 @@
None)])
(users_ok, hosts_ok) = acl_addrm.execute()
+ self.god.check_playback()
self.assertEqual([], users_ok)
self.assertEqual(['acl0'], hosts_ok)
- self.assertOutput(acl_addrm,
- err_words_ok=['DoesNotExist', 'acl0',
+ self.assertOutput(acl_addrm, (users_ok, hosts_ok),
+ out_words_ok=['Added to ACL acl0 hosts:',
+ 'host0', 'host1'],
+ err_words_ok=['DoesNotExist',
'acl_group_add_users',
'user0', 'user1'],
err_words_no = ['acl_group_add_hosts'])
@@ -369,18 +415,56 @@
{'id': 'acl0',
'hosts': ['host0', 'host1']},
False,
- 'DoesNotExist: Host matching query does not exist.')])
+ 'DoesNotExist: The following hosts do not exist: '
+ 'host0, host1')])
(users_ok, hosts_ok) = acl_addrm.execute()
+ self.god.check_playback()
self.assertEqual(['acl0'], users_ok)
self.assertEqual([], hosts_ok)
- self.assertOutput(acl_addrm,
- err_words_ok=['DoesNotExist', 'acl0',
+ self.assertOutput(acl_addrm, (users_ok, hosts_ok),
+ out_words_ok=['Added to ACL acl0 users:',
+ 'user0', 'user1'],
+ err_words_ok=['DoesNotExist',
'acl_group_add_hosts',
'host0', 'host1'],
err_words_no = ['acl_group_add_users'])
+ def test_exe_add_or_remove_uh_to_topic_acl_good_u_bad_hosts_partial(self):
+ acl_addrm = self._create_add_remove('acl0',
+ users=['user0', 'user1'],
+ hosts=['host0', 'host1'])
+ self.mock_rpcs([('acl_group_add_users',
+ {'id': 'acl0',
+ 'users': ['user0', 'user1']},
+ True,
+ None),
+ ('acl_group_add_hosts',
+ {'id': 'acl0',
+ 'hosts': ['host0', 'host1']},
+ False,
+ 'DoesNotExist: The following hosts do not exist: '
+ 'host1'),
+ ('acl_group_add_hosts',
+ {'id': 'acl0',
+ 'hosts': ['host0']},
+ True,
+ None)])
+
+ (users_ok, hosts_ok) = acl_addrm.execute()
+ self.god.check_playback()
+ self.assertEqual(['acl0'], users_ok)
+ self.assertEqual(['acl0'], hosts_ok)
+ self.assertOutput(acl_addrm, (users_ok, hosts_ok),
+ out_words_ok=['Added to ACL acl0 users:',
+ 'user0', 'user1', 'host0'],
+ err_words_ok=['DoesNotExist',
+ 'acl_group_add_hosts',
+ 'host1'],
+ err_words_no = ['acl_group_add_users'])
+
+
def test_execute_add_or_remove_uh_to_topic_acl_bad_users_bad_hosts(self):
acl_addrm = self._create_add_remove('acl0',
users=['user0', 'user1'],
@@ -389,24 +473,69 @@
{'id': 'acl0',
'users': ['user0', 'user1']},
False,
- 'DoesNotExist: User matching query does not exist.'),
+ 'DoesNotExist: The following users do not exist: '
+ 'user0, user1'),
('acl_group_add_hosts',
{'id': 'acl0',
'hosts': ['host0', 'host1']},
False,
- 'DoesNotExist: Host matching query does not exist.')])
+ 'DoesNotExist: The following hosts do not exist: '
+ 'host0, host1')])
+
(users_ok, hosts_ok) = acl_addrm.execute()
+ self.god.check_playback()
self.assertEqual([], users_ok)
self.assertEqual([], hosts_ok)
- self.assertOutput(acl_addrm,
- err_words_ok=['DoesNotExist', 'acl0',
+ self.assertOutput(acl_addrm, (users_ok, hosts_ok),
+ err_words_ok=['DoesNotExist',
'acl_group_add_hosts',
'host0', 'host1',
'acl_group_add_users',
'user0', 'user1'])
+ def test_execute_add_or_remove_uh_to_topic_acl_bad_u_bad_h_partial(self):
+ acl_addrm = self._create_add_remove('acl0',
+ users=['user0', 'user1'],
+ hosts=['host0', 'host1'])
+ self.mock_rpcs([('acl_group_add_users',
+ {'id': 'acl0',
+ 'users': ['user0', 'user1']},
+ False,
+ 'DoesNotExist: The following users do not exist: '
+ 'user0'),
+ ('acl_group_add_users',
+ {'id': 'acl0',
+ 'users': ['user1']},
+ True,
+ None),
+ ('acl_group_add_hosts',
+ {'id': 'acl0',
+ 'hosts': ['host0', 'host1']},
+ False,
+ 'DoesNotExist: The following hosts do not exist: '
+ 'host1'),
+ ('acl_group_add_hosts',
+ {'id': 'acl0',
+ 'hosts': ['host0']},
+ True,
+ None)])
+ (users_ok, hosts_ok) = acl_addrm.execute()
+ self.god.check_playback()
+ self.assertEqual(['acl0'], users_ok)
+ self.assertEqual(['acl0'], hosts_ok)
+ self.assertOutput(acl_addrm, (users_ok, hosts_ok),
+ out_words_ok=['Added to ACL acl0 user:',
+ 'Added to ACL acl0 host:',
+ 'user1', 'host0'],
+ err_words_ok=['DoesNotExist',
+ 'acl_group_add_hosts',
+ 'host1',
+ 'acl_group_add_users',
+ 'user0'])
+
+
def test_execute_add_or_remove_to_topic_bad_acl_uh(self):
acl_addrm = self._create_add_remove('acl0',
users=['user0', 'user1'],
@@ -424,15 +553,13 @@
'DoesNotExist: acl_group matching '
'query does not exist.')])
(users_ok, hosts_ok) = acl_addrm.execute()
+ self.god.check_playback()
self.assertEqual([], users_ok)
self.assertEqual([], hosts_ok)
- self.assertOutput(acl_addrm,
- err_words_ok=['DoesNotExist', 'acl0',
- 'acl_group_add_hosts', 'host0',
- 'host1', 'acl_group_add_users',
- 'user0', 'user1'])
-
-
+ self.assertOutput(acl_addrm, (users_ok, hosts_ok),
+ err_words_ok=['DoesNotExist',
+ 'acl_group_add_hosts',
+ 'acl_group_add_users'])
if __name__ == '__main__':
diff --git a/cli/cli_mock.py b/cli/cli_mock.py
index 59d15b5..4acf976 100755
--- a/cli/cli_mock.py
+++ b/cli/cli_mock.py
@@ -62,10 +62,11 @@
self.assertEqual('', err)
- def assertOutput(self, obj,
+ def assertOutput(self, obj, results,
out_words_ok=[], out_words_no=[],
err_words_ok=[], err_words_no=[]):
self.god.mock_io()
+ obj.output(results)
obj.show_all_failures()
(out, err) = self.god.unmock_io()
self._check_output(out, out_words_ok, out_words_no,
diff --git a/cli/topic_common.py b/cli/topic_common.py
index 8092bac..ec6a6bc 100755
--- a/cli/topic_common.py
+++ b/cli/topic_common.py
@@ -171,6 +171,21 @@
sys.exit(1)
+ def parse_json_exception(self, full_error):
+ """Parses the JSON exception to extract the bad
+ items and returns them
+ This is very kludgy for the moment, but we would need
+ to refactor the exceptions sent from the front end
+ to make this better"""
+ errmsg = str(full_error).split('Traceback')[0].rstrip('\n')
+ parts = errmsg.split(':')
+ # Kludge: If there are 2 colons the last parts contains
+ # the items that failed.
+ if len(parts) != 3:
+ return []
+ return [item.strip() for item in parts[2].split(',') if item.strip()]
+
+
def failure(self, full_error, item=None, what_failed=''):
"""If kill_on_failure, print this error and die,
otherwise, queue the error and accumulate all the items