Delete linked actions when deleting an action plan

When a user deletes an action plan, we now delete all related actions.

Partially Implements: blueprint deletion-of-actions-plan

Change-Id: I5d519c38458741be78591cbec04dbd410a6dc14b
This commit is contained in:
Vincent Françoise
2016-01-29 18:03:59 +01:00
parent b440f5c69a
commit 8bcc1b2097
3 changed files with 55 additions and 14 deletions

View File

@@ -71,6 +71,7 @@ state may be one of the following:
from watcher.common import exception from watcher.common import exception
from watcher.common import utils from watcher.common import utils
from watcher.db import api as dbapi from watcher.db import api as dbapi
from watcher.objects import action as action_objects
from watcher.objects import base from watcher.objects import base
from watcher.objects import utils as obj_utils from watcher.objects import utils as obj_utils
@@ -251,6 +252,14 @@ class ActionPlan(base.WatcherObject):
A context should be set when instantiating the A context should be set when instantiating the
object, e.g.: Audit(context) object, e.g.: Audit(context)
""" """
related_actions = action_objects.Action.list(
context=self._context,
filters={"action_plan_uuid": self.uuid})
# Cascade soft_delete of related actions
for related_action in related_actions:
related_action.soft_delete()
self.dbapi.soft_delete_action_plan(self.uuid) self.dbapi.soft_delete_action_plan(self.uuid)
self.state = "DELETED" self.state = State.DELETED
self.save() self.save()

View File

@@ -285,33 +285,41 @@ class TestListAction(api_base.FunctionalTest):
id=3, id=3,
uuid=utils.generate_uuid(), uuid=utils.generate_uuid(),
audit_id=1) audit_id=1)
action_list = []
ap1_action_list = []
ap2_action_list = []
for id_ in range(0, 2): for id_ in range(0, 2):
action = obj_utils.create_test_action( action = obj_utils.create_test_action(
self.context, id=id_, self.context, id=id_,
action_plan_id=2, action_plan_id=action_plan1.id,
uuid=utils.generate_uuid()) uuid=utils.generate_uuid())
action_list.append(action.uuid) ap1_action_list.append(action)
for id_ in range(2, 4): for id_ in range(2, 4):
action = obj_utils.create_test_action( action = obj_utils.create_test_action(
self.context, id=id_, self.context, id=id_,
action_plan_id=3, action_plan_id=action_plan2.id,
uuid=utils.generate_uuid()) uuid=utils.generate_uuid())
action_list.append(action.uuid) ap2_action_list.append(action)
self.delete('/action_plans/%s' % action_plan1.uuid) self.delete('/action_plans/%s' % action_plan1.uuid)
response = self.get_json('/actions') response = self.get_json('/actions')
self.assertEqual(len(action_list), len(response['actions'])) # We deleted the actions from the 1st action plan so we've got 2 left
for id_ in range(0, 2): self.assertEqual(len(ap2_action_list), len(response['actions']))
action = response['actions'][id_]
self.assertEqual(None, action['action_plan_uuid'])
for id_ in range(2, 4): # We deleted them so that's normal
action = response['actions'][id_] self.assertEqual(
self.assertEqual(action_plan2.uuid, action['action_plan_uuid']) [act for act in response['actions']
if act['action_plan_uuid'] == action_plan1.uuid],
[])
# Here are the 2 actions left
self.assertEqual(
set([act['uuid'] for act in response['actions']
if act['action_plan_uuid'] == action_plan2.uuid]),
set([act.as_dict()['uuid'] for act in ap2_action_list]))
def test_many_with_next_uuid(self): def test_many_with_next_uuid(self):
action_list = [] action_list = []

View File

@@ -307,7 +307,7 @@ class TestDelete(api_base.FunctionalTest):
action_plan = objects.ActionPlan.get_by_uuid(self.context, audit_uuid) action_plan = objects.ActionPlan.get_by_uuid(self.context, audit_uuid)
action_plan.destroy() action_plan.destroy()
def test_delete_action_plan(self): def test_delete_action_plan_without_action(self):
self.delete('/action_plans/%s' % self.action_plan.uuid) self.delete('/action_plans/%s' % self.action_plan.uuid)
response = self.get_json('/action_plans/%s' % self.action_plan.uuid, response = self.get_json('/action_plans/%s' % self.action_plan.uuid,
expect_errors=True) expect_errors=True)
@@ -315,6 +315,30 @@ class TestDelete(api_base.FunctionalTest):
self.assertEqual('application/json', response.content_type) self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message']) self.assertTrue(response.json['error_message'])
def test_delete_action_plan_with_action(self):
action = obj_utils.create_test_action(
self.context, id=self.action_plan.first_action_id)
self.delete('/action_plans/%s' % self.action_plan.uuid)
ap_response = self.get_json('/action_plans/%s' % self.action_plan.uuid,
expect_errors=True)
acts_response = self.get_json(
'/actions/?action_plan_uuid=%s' % self.action_plan.uuid)
act_response = self.get_json(
'/actions/%s' % action.uuid,
expect_errors=True)
# The action plan does not exist anymore
self.assertEqual(404, ap_response.status_int)
self.assertEqual('application/json', ap_response.content_type)
self.assertTrue(ap_response.json['error_message'])
# Nor does the action
self.assertEqual(len(acts_response['actions']), 0)
self.assertEqual(404, act_response.status_int)
self.assertEqual('application/json', act_response.content_type)
self.assertTrue(act_response.json['error_message'])
def test_delete_action_plan_not_found(self): def test_delete_action_plan_not_found(self):
uuid = utils.generate_uuid() uuid = utils.generate_uuid()
response = self.delete('/action_plans/%s' % uuid, expect_errors=True) response = self.delete('/action_plans/%s' % uuid, expect_errors=True)