CORD-2944 do not mark objects deleted if ansible returns a nonzero rc
Change-Id: I1d1b3968524d3bb613d28b64df1791fc52e72a4c
diff --git a/xos/synchronizers/new_base/syncstep.py b/xos/synchronizers/new_base/syncstep.py
index 8aa2afa..4ca697e 100644
--- a/xos/synchronizers/new_base/syncstep.py
+++ b/xos/synchronizers/new_base/syncstep.py
@@ -141,9 +141,13 @@
tenant_fields['delete'] = True
res = run_template(self.playbook, tenant_fields, path=path)
- try:
+
+ if hasattr(self, "map_delete_outputs"):
self.map_delete_outputs(o, res)
- except AttributeError:
- pass
+ else:
+ # "rc" is often only returned when something bad happens, so assume that no "rc" implies a successful rc
+ # of 0.
+ if res[0].get("rc", 0) != 0:
+ raise Exception("Nonzero rc from Ansible during delete_record")
self.log.debug("Finished default delete record", **o.tologdict())
diff --git a/xos/synchronizers/new_base/tests/test_payload.py b/xos/synchronizers/new_base/tests/test_payload.py
index 524c5ea..a72a5da 100644
--- a/xos/synchronizers/new_base/tests/test_payload.py
+++ b/xos/synchronizers/new_base/tests/test_payload.py
@@ -30,6 +30,12 @@
def run_fake_ansible_template(*args,**kwargs):
opts = args[1]
open(ANSIBLE_FILE,'w').write(json.dumps(opts))
+ return [{"rc": 0}]
+
+def run_fake_ansible_template_fail(*args,**kwargs):
+ opts = args[1]
+ open(ANSIBLE_FILE,'w').write(json.dumps(opts))
+ return [{"rc": 1}]
def get_ansible_output():
ansible_str = open(ANSIBLE_FILE).read()
@@ -92,7 +98,21 @@
a = get_ansible_output()
self.assertDictContainsSubset({'delete':True, 'name':o.name}, a)
o.save.assert_called_with(update_fields=['backend_need_reap'])
-
+
+ @mock.patch("steps.sync_instances.syncstep.run_template",side_effect=run_fake_ansible_template_fail)
+ @mock.patch("event_loop.model_accessor")
+ def test_delete_record_fail(self, mock_run_template, mock_modelaccessor):
+ with mock.patch.object(Instance, "save") as instance_save:
+ o = Instance()
+ o.name = "Sisi Pascal"
+
+ o.synchronizer_step = steps.sync_instances.SyncInstances()
+
+ with self.assertRaises(Exception) as e:
+ self.synchronizer.delete_record(o, log)
+
+ self.assertEqual(e.exception.message, "Nonzero rc from Ansible during delete_record")
+
@mock.patch("steps.sync_instances.syncstep.run_template",side_effect=run_fake_ansible_template)
@mock.patch("event_loop.model_accessor")
def test_sync_record(self, mock_run_template, mock_modelaccessor):