Merge "New cron type for audit interval"
This commit is contained in:
@@ -481,6 +481,7 @@ class TestPost(api_base.FunctionalTest):
|
||||
del audit_dict['state']
|
||||
del audit_dict['interval']
|
||||
del audit_dict['scope']
|
||||
del audit_dict['next_run_time']
|
||||
|
||||
response = self.post_json('/audits', audit_dict)
|
||||
self.assertEqual('application/json', response.content_type)
|
||||
@@ -523,6 +524,7 @@ class TestPost(api_base.FunctionalTest):
|
||||
del audit_dict['state']
|
||||
del audit_dict['interval']
|
||||
del audit_dict['scope']
|
||||
del audit_dict['next_run_time']
|
||||
# Make the audit template UUID some garbage value
|
||||
audit_dict['audit_template_uuid'] = (
|
||||
'01234567-8910-1112-1314-151617181920')
|
||||
@@ -545,6 +547,7 @@ class TestPost(api_base.FunctionalTest):
|
||||
del audit_dict['state']
|
||||
del audit_dict['interval']
|
||||
del audit_dict['scope']
|
||||
del audit_dict['next_run_time']
|
||||
with mock.patch.object(self.dbapi, 'create_audit',
|
||||
wraps=self.dbapi.create_audit) as cn_mock:
|
||||
response = self.post_json('/audits', audit_dict)
|
||||
@@ -562,6 +565,7 @@ class TestPost(api_base.FunctionalTest):
|
||||
del audit_dict['state']
|
||||
del audit_dict['interval']
|
||||
del audit_dict['scope']
|
||||
del audit_dict['next_run_time']
|
||||
|
||||
response = self.post_json('/audits', audit_dict)
|
||||
self.assertEqual('application/json', response.content_type)
|
||||
@@ -571,15 +575,16 @@ class TestPost(api_base.FunctionalTest):
|
||||
self.assertTrue(utils.is_uuid_like(response.json['uuid']))
|
||||
|
||||
@mock.patch.object(deapi.DecisionEngineAPI, 'trigger_audit')
|
||||
def test_create_continuous_audit_with_period(self, mock_trigger_audit):
|
||||
def test_create_continuous_audit_with_interval(self, mock_trigger_audit):
|
||||
mock_trigger_audit.return_value = mock.ANY
|
||||
|
||||
audit_dict = post_get_test_audit()
|
||||
del audit_dict['uuid']
|
||||
del audit_dict['state']
|
||||
del audit_dict['scope']
|
||||
del audit_dict['next_run_time']
|
||||
audit_dict['audit_type'] = objects.audit.AuditType.CONTINUOUS.value
|
||||
audit_dict['interval'] = 1200
|
||||
audit_dict['interval'] = '1200'
|
||||
|
||||
response = self.post_json('/audits', audit_dict)
|
||||
self.assertEqual('application/json', response.content_type)
|
||||
@@ -589,6 +594,48 @@ class TestPost(api_base.FunctionalTest):
|
||||
self.assertEqual(audit_dict['interval'], response.json['interval'])
|
||||
self.assertTrue(utils.is_uuid_like(response.json['uuid']))
|
||||
|
||||
@mock.patch.object(deapi.DecisionEngineAPI, 'trigger_audit')
|
||||
def test_create_continuous_audit_with_cron_interval(self,
|
||||
mock_trigger_audit):
|
||||
mock_trigger_audit.return_value = mock.ANY
|
||||
|
||||
audit_dict = post_get_test_audit()
|
||||
del audit_dict['uuid']
|
||||
del audit_dict['state']
|
||||
del audit_dict['scope']
|
||||
del audit_dict['next_run_time']
|
||||
audit_dict['audit_type'] = objects.audit.AuditType.CONTINUOUS.value
|
||||
audit_dict['interval'] = '* * * * *'
|
||||
|
||||
response = self.post_json('/audits', audit_dict)
|
||||
self.assertEqual('application/json', response.content_type)
|
||||
self.assertEqual(201, response.status_int)
|
||||
self.assertEqual(objects.audit.State.PENDING,
|
||||
response.json['state'])
|
||||
self.assertEqual(audit_dict['interval'], response.json['interval'])
|
||||
self.assertTrue(utils.is_uuid_like(response.json['uuid']))
|
||||
|
||||
@mock.patch.object(deapi.DecisionEngineAPI, 'trigger_audit')
|
||||
def test_create_continuous_audit_with_wrong_interval(self,
|
||||
mock_trigger_audit):
|
||||
mock_trigger_audit.return_value = mock.ANY
|
||||
|
||||
audit_dict = post_get_test_audit()
|
||||
del audit_dict['uuid']
|
||||
del audit_dict['state']
|
||||
del audit_dict['scope']
|
||||
del audit_dict['next_run_time']
|
||||
audit_dict['audit_type'] = objects.audit.AuditType.CONTINUOUS.value
|
||||
audit_dict['interval'] = 'zxc'
|
||||
|
||||
response = self.post_json('/audits', audit_dict, expect_errors=True)
|
||||
self.assertEqual('application/json', response.content_type)
|
||||
self.assertEqual(500, response.status_int)
|
||||
expected_error_msg = ('Exactly 5 or 6 columns has to be '
|
||||
'specified for iteratorexpression.')
|
||||
self.assertTrue(response.json['error_message'])
|
||||
self.assertIn(expected_error_msg, response.json['error_message'])
|
||||
|
||||
@mock.patch.object(deapi.DecisionEngineAPI, 'trigger_audit')
|
||||
def test_create_continuous_audit_without_period(self, mock_trigger_audit):
|
||||
mock_trigger_audit.return_value = mock.ANY
|
||||
@@ -599,6 +646,7 @@ class TestPost(api_base.FunctionalTest):
|
||||
audit_dict['audit_type'] = objects.audit.AuditType.CONTINUOUS.value
|
||||
del audit_dict['interval']
|
||||
del audit_dict['scope']
|
||||
del audit_dict['next_run_time']
|
||||
|
||||
response = self.post_json('/audits', audit_dict, expect_errors=True)
|
||||
self.assertEqual(400, response.status_int)
|
||||
@@ -616,8 +664,8 @@ class TestPost(api_base.FunctionalTest):
|
||||
del audit_dict['uuid']
|
||||
del audit_dict['state']
|
||||
audit_dict['audit_type'] = objects.audit.AuditType.ONESHOT.value
|
||||
audit_dict['interval'] = 1200
|
||||
del audit_dict['scope']
|
||||
del audit_dict['next_run_time']
|
||||
|
||||
response = self.post_json('/audits', audit_dict, expect_errors=True)
|
||||
self.assertEqual(400, response.status_int)
|
||||
@@ -634,6 +682,7 @@ class TestPost(api_base.FunctionalTest):
|
||||
del audit_dict['state']
|
||||
del audit_dict['interval']
|
||||
del audit_dict['scope']
|
||||
del audit_dict['next_run_time']
|
||||
response = self.post_json('/audits', audit_dict)
|
||||
de_mock.assert_called_once_with(mock.ANY, response.json['uuid'])
|
||||
|
||||
@@ -657,6 +706,7 @@ class TestPost(api_base.FunctionalTest):
|
||||
del audit_dict['state']
|
||||
del audit_dict['interval']
|
||||
del audit_dict['scope']
|
||||
del audit_dict['next_run_time']
|
||||
|
||||
response = self.post_json('/audits', audit_dict, expect_errors=True)
|
||||
self.assertEqual('application/json', response.content_type)
|
||||
@@ -678,6 +728,7 @@ class TestPost(api_base.FunctionalTest):
|
||||
del audit_dict['state']
|
||||
del audit_dict['interval']
|
||||
del audit_dict['scope']
|
||||
del audit_dict['next_run_time']
|
||||
|
||||
response = self.post_json('/audits', audit_dict, expect_errors=True)
|
||||
self.assertEqual('application/json', response.content_type)
|
||||
@@ -700,7 +751,7 @@ class TestPost(api_base.FunctionalTest):
|
||||
|
||||
audit_dict['audit_template_uuid'] = audit_template['uuid']
|
||||
del_keys = ['uuid', 'goal_id', 'strategy_id', 'state', 'interval',
|
||||
'scope']
|
||||
'scope', 'next_run_time']
|
||||
for k in del_keys:
|
||||
del audit_dict[k]
|
||||
|
||||
@@ -839,6 +890,7 @@ class TestAuditPolicyEnforcement(api_base.FunctionalTest):
|
||||
del audit_dict['uuid']
|
||||
del audit_dict['state']
|
||||
del audit_dict['scope']
|
||||
del audit_dict['next_run_time']
|
||||
self._common_policy_check(
|
||||
"audit:create", self.post_json, '/audits', audit_dict,
|
||||
expect_errors=True)
|
||||
|
||||
@@ -89,11 +89,12 @@ def get_test_audit(**kwargs):
|
||||
'updated_at': kwargs.get('updated_at'),
|
||||
'deleted_at': kwargs.get('deleted_at'),
|
||||
'parameters': kwargs.get('parameters', {}),
|
||||
'interval': kwargs.get('interval', 3600),
|
||||
'interval': kwargs.get('interval', '3600'),
|
||||
'goal_id': kwargs.get('goal_id', 1),
|
||||
'strategy_id': kwargs.get('strategy_id', None),
|
||||
'scope': kwargs.get('scope', []),
|
||||
'auto_trigger': kwargs.get('auto_trigger', False)
|
||||
'auto_trigger': kwargs.get('auto_trigger', False),
|
||||
'next_run_time': kwargs.get('next_run_time')
|
||||
}
|
||||
# ObjectField doesn't allow None nor dict, so if we want to simulate a
|
||||
# non-eager object loading, the field should not be referenced at all.
|
||||
|
||||
@@ -14,12 +14,15 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import datetime
|
||||
|
||||
import mock
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from apscheduler import job
|
||||
|
||||
from watcher.applier import rpcapi
|
||||
from watcher.common import exception
|
||||
from watcher.common import scheduling
|
||||
from watcher.db.sqlalchemy import api as sq_api
|
||||
from watcher.decision_engine.audit import continuous
|
||||
@@ -241,20 +244,65 @@ class TestContinuousAuditHandler(base.DbTestCase):
|
||||
@mock.patch.object(scheduling.BackgroundSchedulerService, 'add_job')
|
||||
@mock.patch.object(scheduling.BackgroundSchedulerService, 'get_jobs')
|
||||
@mock.patch.object(objects.audit.Audit, 'list')
|
||||
def test_launch_audits_periodically(self, mock_list, mock_jobs,
|
||||
m_add_job, m_engine, m_service):
|
||||
def test_launch_audits_periodically_with_interval(
|
||||
self, mock_list, mock_jobs, m_add_job, m_engine, m_service):
|
||||
audit_handler = continuous.ContinuousAuditHandler()
|
||||
mock_list.return_value = self.audits
|
||||
self.audits[0].next_run_time = (datetime.datetime.now() -
|
||||
datetime.timedelta(seconds=1800))
|
||||
mock_jobs.return_value = mock.MagicMock()
|
||||
m_engine.return_value = mock.MagicMock()
|
||||
m_add_job.return_value = audit_handler.execute_audit(
|
||||
self.audits[0], self.context)
|
||||
m_add_job.return_value = mock.MagicMock()
|
||||
|
||||
audit_handler.launch_audits_periodically()
|
||||
m_service.assert_called()
|
||||
m_engine.assert_called()
|
||||
m_add_job.assert_called()
|
||||
mock_jobs.assert_called()
|
||||
self.assertIsNotNone(self.audits[0].next_run_time)
|
||||
self.assertIsNone(self.audits[1].next_run_time)
|
||||
|
||||
@mock.patch.object(objects.service.Service, 'list')
|
||||
@mock.patch.object(sq_api, 'get_engine')
|
||||
@mock.patch.object(scheduling.BackgroundSchedulerService, 'add_job')
|
||||
@mock.patch.object(scheduling.BackgroundSchedulerService, 'get_jobs')
|
||||
@mock.patch.object(objects.audit.Audit, 'list')
|
||||
def test_launch_audits_periodically_with_cron(
|
||||
self, mock_list, mock_jobs, m_add_job, m_engine, m_service):
|
||||
audit_handler = continuous.ContinuousAuditHandler()
|
||||
mock_list.return_value = self.audits
|
||||
self.audits[0].interval = "*/5 * * * *"
|
||||
mock_jobs.return_value = mock.MagicMock()
|
||||
m_engine.return_value = mock.MagicMock()
|
||||
m_add_job.return_value = mock.MagicMock()
|
||||
|
||||
audit_handler.launch_audits_periodically()
|
||||
m_service.assert_called()
|
||||
m_engine.assert_called()
|
||||
m_add_job.assert_called()
|
||||
mock_jobs.assert_called()
|
||||
self.assertIsNotNone(self.audits[0].next_run_time)
|
||||
self.assertIsNone(self.audits[1].next_run_time)
|
||||
|
||||
@mock.patch.object(continuous.ContinuousAuditHandler, '_next_cron_time')
|
||||
@mock.patch.object(objects.service.Service, 'list')
|
||||
@mock.patch.object(sq_api, 'get_engine')
|
||||
@mock.patch.object(scheduling.BackgroundSchedulerService, 'add_job')
|
||||
@mock.patch.object(scheduling.BackgroundSchedulerService, 'get_jobs')
|
||||
@mock.patch.object(objects.audit.Audit, 'list')
|
||||
def test_launch_audits_periodically_with_invalid_cron(
|
||||
self, mock_list, mock_jobs, m_add_job, m_engine, m_service,
|
||||
mock_cron):
|
||||
audit_handler = continuous.ContinuousAuditHandler()
|
||||
mock_list.return_value = self.audits
|
||||
self.audits[0].interval = "*/5* * * *"
|
||||
mock_cron.side_effect = exception.CronFormatIsInvalid
|
||||
mock_jobs.return_value = mock.MagicMock()
|
||||
m_engine.return_value = mock.MagicMock()
|
||||
m_add_job.return_value = mock.MagicMock()
|
||||
|
||||
self.assertRaises(exception.CronFormatIsInvalid,
|
||||
audit_handler.launch_audits_periodically)
|
||||
|
||||
@mock.patch.object(objects.service.Service, 'list')
|
||||
@mock.patch.object(sq_api, 'get_engine')
|
||||
@@ -273,7 +321,7 @@ class TestContinuousAuditHandler(base.DbTestCase):
|
||||
args=[mock.ANY, mock.ANY],
|
||||
seconds=3600,
|
||||
name='execute_audit',
|
||||
next_run_time=mock.ANY) for audit in self.audits]
|
||||
next_run_time=mock.ANY) for _ in self.audits]
|
||||
audit_handler.launch_audits_periodically()
|
||||
m_add_job.assert_has_calls(calls)
|
||||
|
||||
|
||||
@@ -94,6 +94,8 @@ class TestActionPlanNotification(base.DbTestCase):
|
||||
"audit": {
|
||||
"watcher_object.data": {
|
||||
"interval": None,
|
||||
"next_run_time": None,
|
||||
"auto_trigger": False,
|
||||
"parameters": {},
|
||||
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||
"strategy_uuid": None,
|
||||
@@ -108,7 +110,7 @@ class TestActionPlanNotification(base.DbTestCase):
|
||||
},
|
||||
"watcher_object.name": "TerseAuditPayload",
|
||||
"watcher_object.namespace": "watcher",
|
||||
"watcher_object.version": "1.0"
|
||||
"watcher_object.version": "1.1"
|
||||
},
|
||||
"deleted_at": None,
|
||||
"state": "ONGOING",
|
||||
@@ -168,6 +170,8 @@ class TestActionPlanNotification(base.DbTestCase):
|
||||
"audit": {
|
||||
"watcher_object.data": {
|
||||
"interval": None,
|
||||
"next_run_time": None,
|
||||
"auto_trigger": False,
|
||||
"parameters": {},
|
||||
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||
"strategy_uuid": None,
|
||||
@@ -182,7 +186,7 @@ class TestActionPlanNotification(base.DbTestCase):
|
||||
},
|
||||
"watcher_object.name": "TerseAuditPayload",
|
||||
"watcher_object.namespace": "watcher",
|
||||
"watcher_object.version": "1.0"
|
||||
"watcher_object.version": "1.1"
|
||||
},
|
||||
"deleted_at": None,
|
||||
"state": "PENDING",
|
||||
@@ -234,6 +238,8 @@ class TestActionPlanNotification(base.DbTestCase):
|
||||
"audit": {
|
||||
"watcher_object.data": {
|
||||
"interval": None,
|
||||
"next_run_time": None,
|
||||
"auto_trigger": False,
|
||||
"parameters": {},
|
||||
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||
"strategy_uuid": None,
|
||||
@@ -248,7 +254,7 @@ class TestActionPlanNotification(base.DbTestCase):
|
||||
},
|
||||
"watcher_object.name": "TerseAuditPayload",
|
||||
"watcher_object.namespace": "watcher",
|
||||
"watcher_object.version": "1.0"
|
||||
"watcher_object.version": "1.1"
|
||||
},
|
||||
"deleted_at": None,
|
||||
"state": "DELETED",
|
||||
@@ -287,9 +293,11 @@ class TestActionPlanNotification(base.DbTestCase):
|
||||
"audit": {
|
||||
"watcher_object.namespace": "watcher",
|
||||
"watcher_object.name": "TerseAuditPayload",
|
||||
"watcher_object.version": "1.0",
|
||||
"watcher_object.version": "1.1",
|
||||
"watcher_object.data": {
|
||||
"interval": None,
|
||||
"next_run_time": None,
|
||||
"auto_trigger": False,
|
||||
"parameters": {},
|
||||
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||
"strategy_uuid": None,
|
||||
@@ -373,6 +381,8 @@ class TestActionPlanNotification(base.DbTestCase):
|
||||
"audit": {
|
||||
"watcher_object.data": {
|
||||
"interval": None,
|
||||
"next_run_time": None,
|
||||
"auto_trigger": False,
|
||||
"parameters": {},
|
||||
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||
"strategy_uuid": None,
|
||||
@@ -387,7 +397,7 @@ class TestActionPlanNotification(base.DbTestCase):
|
||||
},
|
||||
"watcher_object.name": "TerseAuditPayload",
|
||||
"watcher_object.namespace": "watcher",
|
||||
"watcher_object.version": "1.0"
|
||||
"watcher_object.version": "1.1"
|
||||
},
|
||||
"global_efficacy": {},
|
||||
"state": "ONGOING",
|
||||
|
||||
@@ -69,9 +69,11 @@ class TestAuditNotification(base.DbTestCase):
|
||||
self.assertDictEqual(
|
||||
{
|
||||
"watcher_object.namespace": "watcher",
|
||||
"watcher_object.version": "1.0",
|
||||
"watcher_object.version": "1.1",
|
||||
"watcher_object.data": {
|
||||
"interval": None,
|
||||
"next_run_time": None,
|
||||
"auto_trigger": False,
|
||||
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||
"strategy": {
|
||||
"watcher_object.namespace": "watcher",
|
||||
@@ -141,9 +143,11 @@ class TestAuditNotification(base.DbTestCase):
|
||||
self.assertDictEqual(
|
||||
{
|
||||
"watcher_object.namespace": "watcher",
|
||||
"watcher_object.version": "1.0",
|
||||
"watcher_object.version": "1.1",
|
||||
"watcher_object.data": {
|
||||
"interval": None,
|
||||
"next_run_time": None,
|
||||
"auto_trigger": False,
|
||||
"parameters": {},
|
||||
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||
"goal_uuid": "f7ad87ae-4298-91cf-93a0-f35a852e3652",
|
||||
@@ -200,9 +204,11 @@ class TestAuditNotification(base.DbTestCase):
|
||||
self.assertDictEqual(
|
||||
{
|
||||
"watcher_object.namespace": "watcher",
|
||||
"watcher_object.version": "1.0",
|
||||
"watcher_object.version": "1.1",
|
||||
"watcher_object.data": {
|
||||
"interval": None,
|
||||
"next_run_time": None,
|
||||
"auto_trigger": False,
|
||||
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||
"strategy": {
|
||||
"watcher_object.namespace": "watcher",
|
||||
@@ -263,9 +269,11 @@ class TestAuditNotification(base.DbTestCase):
|
||||
self.assertDictEqual(
|
||||
{
|
||||
"watcher_object.namespace": "watcher",
|
||||
"watcher_object.version": "1.0",
|
||||
"watcher_object.version": "1.1",
|
||||
"watcher_object.data": {
|
||||
"interval": None,
|
||||
"next_run_time": None,
|
||||
"auto_trigger": False,
|
||||
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||
"strategy": {
|
||||
"watcher_object.namespace": "watcher",
|
||||
@@ -350,6 +358,8 @@ class TestAuditNotification(base.DbTestCase):
|
||||
"watcher_object.version": "1.0"
|
||||
},
|
||||
"interval": None,
|
||||
"next_run_time": None,
|
||||
"auto_trigger": False,
|
||||
"parameters": {},
|
||||
"scope": [],
|
||||
"state": "ONGOING",
|
||||
@@ -374,7 +384,7 @@ class TestAuditNotification(base.DbTestCase):
|
||||
},
|
||||
"watcher_object.name": "AuditActionPayload",
|
||||
"watcher_object.namespace": "watcher",
|
||||
"watcher_object.version": "1.0"
|
||||
"watcher_object.version": "1.1"
|
||||
}
|
||||
},
|
||||
notification
|
||||
@@ -434,6 +444,8 @@ class TestAuditNotification(base.DbTestCase):
|
||||
"watcher_object.version": "1.0"
|
||||
},
|
||||
"interval": None,
|
||||
"next_run_time": None,
|
||||
"auto_trigger": False,
|
||||
"parameters": {},
|
||||
"scope": [],
|
||||
"state": "ONGOING",
|
||||
@@ -458,7 +470,7 @@ class TestAuditNotification(base.DbTestCase):
|
||||
},
|
||||
"watcher_object.name": "AuditActionPayload",
|
||||
"watcher_object.namespace": "watcher",
|
||||
"watcher_object.version": "1.0"
|
||||
"watcher_object.version": "1.1"
|
||||
}
|
||||
},
|
||||
notification
|
||||
|
||||
@@ -254,17 +254,17 @@ expected_notification_fingerprints = {
|
||||
'ExceptionNotification': '1.0-9b69de0724fda8310d05e18418178866',
|
||||
'ExceptionPayload': '1.0-4516ae282a55fe2fd5c754967ee6248b',
|
||||
'NotificationPublisher': '1.0-bbbc1402fb0e443a3eb227cc52b61545',
|
||||
'TerseAuditPayload': '1.0-aaf31166b8698f08d12cae98c380b8e0',
|
||||
'AuditPayload': '1.0-30c85c834648c8ca11f54fc5e084d86b',
|
||||
'TerseAuditPayload': '1.1-19b0e9224c0953366418a30ed785f267',
|
||||
'AuditPayload': '1.1-4c59e0cc5d30c42d3b842ce0332709d5',
|
||||
'AuditStateUpdatePayload': '1.0-1a1b606bf14a2c468800c2b010801ce5',
|
||||
'AuditUpdateNotification': '1.0-9b69de0724fda8310d05e18418178866',
|
||||
'AuditUpdatePayload': '1.0-d3aace28d9eb978c1ecf833e108f61f7',
|
||||
'AuditUpdatePayload': '1.1-9b1f725e736051b976571701e5cc1e55',
|
||||
'AuditCreateNotification': '1.0-9b69de0724fda8310d05e18418178866',
|
||||
'AuditCreatePayload': '1.0-30c85c834648c8ca11f54fc5e084d86b',
|
||||
'AuditCreatePayload': '1.1-4c59e0cc5d30c42d3b842ce0332709d5',
|
||||
'AuditDeleteNotification': '1.0-9b69de0724fda8310d05e18418178866',
|
||||
'AuditDeletePayload': '1.0-30c85c834648c8ca11f54fc5e084d86b',
|
||||
'AuditDeletePayload': '1.1-4c59e0cc5d30c42d3b842ce0332709d5',
|
||||
'AuditActionNotification': '1.0-9b69de0724fda8310d05e18418178866',
|
||||
'AuditActionPayload': '1.0-09f5d005f94ba9e5f6b9200170332c52',
|
||||
'AuditActionPayload': '1.1-5a43e7321495c19f98ef5663efa0a821',
|
||||
'GoalPayload': '1.0-fa1fecb8b01dd047eef808ded4d50d1a',
|
||||
'StrategyPayload': '1.0-94f01c137b083ac236ae82573c1fcfc1',
|
||||
'ActionPlanActionPayload': '1.0-d9f134708e06cf2ff2d3b8d522ac2aa8',
|
||||
|
||||
@@ -412,7 +412,7 @@ expected_object_fingerprints = {
|
||||
'Goal': '1.0-93881622db05e7b67a65ca885b4a022e',
|
||||
'Strategy': '1.1-73f164491bdd4c034f48083a51bdeb7b',
|
||||
'AuditTemplate': '1.1-b291973ffc5efa2c61b24fe34fdccc0b',
|
||||
'Audit': '1.2-910522db78b7b1cb59df614754656db4',
|
||||
'Audit': '1.3-f47ffb1ee79d8248eb991674bda565ce',
|
||||
'ActionPlan': '2.0-394f1abbf5d73d7b6675a118fe1a0284',
|
||||
'Action': '2.0-1dd4959a7e7ac30c62ef170fe08dd935',
|
||||
'EfficacyIndicator': '1.0-655b71234a82bc7478aff964639c4bb0',
|
||||
|
||||
Reference in New Issue
Block a user