Example #1
0
    def test_sync_with_modified_strategy(
            self, m_g_list, m_g_create, m_g_save, m_g_soft_delete,
            m_g_get_by_name, m_s_list, m_s_create, m_s_save, m_s_soft_delete):
        m_g_get_by_name.side_effect = [
            objects.Goal(self.ctx, id=i) for i in range(1, 10)]
        m_g_list.return_value = [
            objects.Goal(self.ctx, id=1, uuid=utils.generate_uuid(),
                         name="dummy_1", display_name="Dummy 1",
                         efficacy_specification=(
                             self.goal1_spec.serialize_indicators_specs()))
        ]
        m_s_list.return_value = [
            objects.Strategy(self.ctx, id=1, name="strategy_1",
                             goal_id=1, display_name="original",
                             parameters_spec='{}')
        ]
        self.syncer.sync()

        self.assertEqual(1, m_g_create.call_count)
        self.assertEqual(0, m_g_save.call_count)
        self.assertEqual(0, m_g_soft_delete.call_count)

        self.assertEqual(4, m_s_create.call_count)
        self.assertEqual(0, m_s_save.call_count)
        self.assertEqual(1, m_s_soft_delete.call_count)
Example #2
0
    def test_sync_strategies_with_removed_goal(self):
        # ### Setup ### #

        goal1 = objects.Goal(
            self.ctx, id=1, uuid=utils.generate_uuid(),
            name="dummy_1", display_name="Dummy 1",
            efficacy_specification=self.goal1_spec.serialize_indicators_specs()
        )
        goal2 = objects.Goal(
            self.ctx, id=2, uuid=utils.generate_uuid(),
            name="dummy_2", display_name="Dummy 2",
            efficacy_specification=self.goal2_spec.serialize_indicators_specs()
        )
        goal1.create()
        goal2.create()

        strategy1 = objects.Strategy(
            self.ctx, id=1, name="strategy_1", uuid=utils.generate_uuid(),
            display_name="Strategy 1", goal_id=goal1.id)
        strategy2 = objects.Strategy(
            self.ctx, id=2, name="strategy_2", uuid=utils.generate_uuid(),
            display_name="Strategy 2", goal_id=goal2.id)
        strategy1.create()
        strategy2.create()
        # to be removed by some reasons
        goal2.soft_delete()

        before_goals = objects.Goal.list(self.ctx)
        before_strategies = objects.Strategy.list(self.ctx)

        # ### Action under test ### #

        try:
            self.syncer.sync()
        except Exception as exc:
            self.fail(exc)

        # ### Assertions ### #

        after_goals = objects.Goal.list(self.ctx)
        after_strategies = objects.Strategy.list(self.ctx)

        self.assertEqual(1, len(before_goals))
        self.assertEqual(2, len(before_strategies))
        self.assertEqual(2, len(after_goals))
        self.assertEqual(4, len(after_strategies))
        self.assertEqual(
            {"dummy_1", "dummy_2"},
            set([g.name for g in after_goals]))
        self.assertEqual(
            {"strategy_1", "strategy_2", "strategy_3", "strategy_4"},
            set([s.name for s in after_strategies]))
Example #3
0
    def _sync_goal(self, goal_map):
        goal_name = goal_map.name
        goal_mapping = dict()
        # Goals that are matching by name with the given discovered goal name
        matching_goals = [g for g in self.available_goals
                          if g.name == goal_name]
        stale_goals = self._soft_delete_stale_goals(goal_map, matching_goals)

        if stale_goals or not matching_goals:
            goal = objects.Goal(self.ctx)
            goal.name = goal_name
            goal.display_name = goal_map.display_name
            goal.efficacy_specification = [
                indicator._asdict()
                for indicator in goal_map.efficacy_specification]
            goal.create()
            LOG.info("Goal %s created", goal_name)

            # Updating the internal states
            self.available_goals_map[goal] = goal_map
            # Map the old goal IDs to the new (equivalent) goal
            for matching_goal in matching_goals:
                goal_mapping[matching_goal.id] = goal

        return goal_mapping
Example #4
0
 def test_create(self):
     with mock.patch.object(self.dbapi, 'create_goal',
                            autospec=True) as mock_create_goal:
         mock_create_goal.return_value = self.fake_goal
         goal = objects.Goal(self.context, **self.fake_goal)
         goal.create()
         mock_create_goal.assert_called_once_with(self.fake_goal)
         self.assertEqual(self.context, goal._context)
Example #5
0
 def test_create(self, mock_create_goal):
     mock_create_goal.return_value = self.fake_goal
     goal = objects.Goal(self.context, **self.fake_goal)
     goal.create()
     expected_goal = self.fake_goal.copy()
     expected_goal['created_at'] = expected_goal['created_at'].replace(
         tzinfo=iso8601.UTC)
     mock_create_goal.assert_called_once_with(expected_goal)
     self.assertEqual(self.context, goal._context)
Example #6
0
def get_test_goal(context, **kw):
    """Return a Goal object with appropriate attributes.

    NOTE: The object leaves the attributes marked as changed, such
    that a create() could be used to commit it to the DB.
    """
    db_goal = db_utils.get_test_goal(**kw)
    # Let DB generate ID if it isn't specified explicitly
    if 'id' not in kw:
        del db_goal['id']
    goal = objects.Goal(context)
    for key in db_goal:
        setattr(goal, key, db_goal[key])
    return goal
Example #7
0
    def test_sync_empty_db(
            self, m_g_list, m_g_create, m_g_save, m_g_soft_delete,
            m_g_get_by_name, m_s_list, m_s_create, m_s_save, m_s_soft_delete):
        m_g_get_by_name.side_effect = [
            objects.Goal(self.ctx, id=i) for i in range(1, 10)]
        m_g_list.return_value = []
        m_s_list.return_value = []

        self.syncer.sync()

        self.assertEqual(2, m_g_create.call_count)
        self.assertEqual(0, m_g_save.call_count)
        self.assertEqual(0, m_g_soft_delete.call_count)

        self.assertEqual(4, m_s_create.call_count)
        self.assertEqual(0, m_s_save.call_count)
        self.assertEqual(0, m_s_soft_delete.call_count)
Example #8
0
    def test_end2end_sync_goals_with_removed_goal_and_strategy(self):
        # ### Setup ### #

        # We simulate the fact that we removed 2 strategies
        self.m_available_strategies.return_value = {
            fake_strategies.FakeDummy1Strategy1.get_name():
                fake_strategies.FakeDummy1Strategy1
        }
        # We simulate the fact that we removed the dummy_2 goal
        self.m_available_goals.return_value = {
            fake_goals.FakeDummy1.get_name(): fake_goals.FakeDummy1,
        }
        # Should stay unmodified after sync()
        goal1 = objects.Goal(
            self.ctx, id=1, uuid=utils.generate_uuid(),
            name="dummy_1", display_name="Dummy 1",
            efficacy_specification=self.goal1_spec.serialize_indicators_specs()
        )
        # To be removed by the sync()
        goal2 = objects.Goal(
            self.ctx, id=2, uuid=utils.generate_uuid(),
            name="dummy_2", display_name="Dummy 2",
            efficacy_specification=self.goal2_spec.serialize_indicators_specs()
        )
        goal1.create()
        goal2.create()

        # Should stay unmodified after sync()
        strategy1 = objects.Strategy(
            self.ctx, id=1, name="strategy_1", uuid=utils.generate_uuid(),
            display_name="Strategy 1", goal_id=goal1.id)
        # To be removed by the sync() because strategy entry point does not
        # exist anymore
        strategy2 = objects.Strategy(
            self.ctx, id=2, name="strategy_2", uuid=utils.generate_uuid(),
            display_name="Strategy 2", goal_id=goal1.id)
        # To be removed by the sync() because the goal has been soft deleted
        # and because the strategy entry point does not exist anymore
        strategy3 = objects.Strategy(
            self.ctx, id=3, name="strategy_3", uuid=utils.generate_uuid(),
            display_name="Original", goal_id=goal2.id)
        strategy1.create()
        strategy2.create()
        strategy3.create()

        # Here we simulate audit_templates that were already created in the
        # past and hence saved within the Watcher DB

        # The strategy of this audit template will be dereferenced
        # as it does not exist anymore
        audit_template1 = objects.AuditTemplate(
            self.ctx, id=1, name="Synced AT1", uuid=utils.generate_uuid(),
            goal_id=goal1.id, strategy_id=strategy1.id)
        # Stale after syncing because the goal has been soft deleted
        audit_template2 = objects.AuditTemplate(
            self.ctx, id=2, name="Synced AT2", uuid=utils.generate_uuid(),
            goal_id=goal2.id, strategy_id=strategy2.id)

        audit_template1.create()
        audit_template2.create()

        # Should stay unmodified after sync()
        audit1 = objects.Audit(
            self.ctx, id=1, uuid=utils.generate_uuid(), name='audit_1',
            audit_type=objects.audit.AuditType.ONESHOT.value,
            state=objects.audit.State.PENDING,
            goal_id=goal1.id, strategy_id=strategy1.id, auto_trigger=False)
        # Stale after syncing because the goal has been soft deleted
        audit2 = objects.Audit(
            self.ctx, id=2, uuid=utils.generate_uuid(), name='audit_2',
            audit_type=objects.audit.AuditType.ONESHOT.value,
            state=objects.audit.State.PENDING,
            goal_id=goal2.id, strategy_id=strategy2.id, auto_trigger=False)
        audit1.create()
        audit2.create()

        # Stale after syncing because its related strategy has been be
        # soft deleted
        action_plan1 = objects.ActionPlan(
            self.ctx, id=1, uuid=utils.generate_uuid(),
            audit_id=audit1.id, strategy_id=strategy1.id,
            state='DOESNOTMATTER', global_efficacy={})
        # Stale after syncing because its related goal has been soft deleted
        action_plan2 = objects.ActionPlan(
            self.ctx, id=2, uuid=utils.generate_uuid(),
            audit_id=audit2.id, strategy_id=strategy2.id,
            state='DOESNOTMATTER', global_efficacy={})

        action_plan1.create()
        action_plan2.create()

        before_goals = objects.Goal.list(self.ctx)
        before_strategies = objects.Strategy.list(self.ctx)
        before_audit_templates = objects.AuditTemplate.list(self.ctx)
        before_audits = objects.Audit.list(self.ctx)
        before_action_plans = objects.ActionPlan.list(self.ctx)

        # ### Action under test ### #

        try:
            self.syncer.sync()
        except Exception as exc:
            self.fail(exc)

        # ### Assertions ### #

        after_goals = objects.Goal.list(self.ctx)
        after_strategies = objects.Strategy.list(self.ctx)
        after_audit_templates = objects.AuditTemplate.list(self.ctx)
        after_audits = objects.Audit.list(self.ctx)
        after_action_plans = objects.ActionPlan.list(self.ctx)

        self.assertEqual(2, len(before_goals))
        self.assertEqual(3, len(before_strategies))
        self.assertEqual(2, len(before_audit_templates))
        self.assertEqual(2, len(before_audits))
        self.assertEqual(2, len(before_action_plans))
        self.assertEqual(1, len(after_goals))
        self.assertEqual(1, len(after_strategies))
        self.assertEqual(2, len(after_audit_templates))
        self.assertEqual(2, len(after_audits))
        self.assertEqual(2, len(after_action_plans))
        self.assertEqual(
            {"dummy_1"},
            set([g.name for g in after_goals]))
        self.assertEqual(
            {"strategy_1"},
            set([s.name for s in after_strategies]))

        created_goals, modified_goals, unmodified_goals = (
            self._find_created_modified_unmodified_ids(
                before_goals, after_goals))

        created_strategies, modified_strategies, unmodified_strategies = (
            self._find_created_modified_unmodified_ids(
                before_strategies, after_strategies))

        (created_audit_templates, modified_audit_templates,
         unmodified_audit_templates) = (
             self._find_created_modified_unmodified_ids(
                 before_audit_templates, after_audit_templates))

        created_audits, modified_audits, unmodified_audits = (
            self._find_created_modified_unmodified_ids(
                before_audits, after_audits))

        (created_action_plans, modified_action_plans,
         unmodified_action_plans) = (
             self._find_created_modified_unmodified_ids(
                 before_action_plans, after_action_plans))

        self.assertEqual(0, len(created_goals))
        self.assertEqual(0, len(created_strategies))
        self.assertEqual(0, len(created_audits))
        self.assertEqual(0, len(created_action_plans))

        self.assertEqual(set([audit_template2.id]),
                         set(modified_audit_templates))
        self.assertEqual(set([audit_template1.id]),
                         set(unmodified_audit_templates))

        self.assertEqual(set([audit2.id]), set(modified_audits))
        self.assertEqual(set([audit1.id]), set(unmodified_audits))

        self.assertEqual(set([action_plan2.id]), set(modified_action_plans))
        self.assertTrue(
            all(ap.state == objects.action_plan.State.CANCELLED
                for ap in modified_action_plans.values()))
        self.assertEqual(set([action_plan1.id]), set(unmodified_action_plans))
Example #9
0
    def test_end2end_sync_goals_with_modified_goal_and_strategy(self):
        # ### Setup ### #

        # Here, we simulate goals and strategies already discovered in the past
        # that were saved in DB

        # Should stay unmodified after sync()
        goal1 = objects.Goal(
            self.ctx, id=1, uuid=utils.generate_uuid(),
            name="dummy_1", display_name="Dummy 1",
            efficacy_specification=(
                self.goal1_spec.serialize_indicators_specs()))
        # Should be modified by the sync()
        goal2 = objects.Goal(
            self.ctx, id=2, uuid=utils.generate_uuid(),
            name="dummy_2", display_name="Original",
            efficacy_specification=self.goal2_spec.serialize_indicators_specs()
        )
        goal1.create()
        goal2.create()

        # Should stay unmodified after sync()
        strategy1 = objects.Strategy(
            self.ctx, id=1, name="strategy_1", uuid=utils.generate_uuid(),
            display_name="Strategy 1", goal_id=goal1.id)
        # Should be modified after sync() because its related goal has been
        # modified
        strategy2 = objects.Strategy(
            self.ctx, id=2, name="strategy_2", uuid=utils.generate_uuid(),
            display_name="Strategy 2", goal_id=goal2.id)
        # Should be modified after sync() because its strategy name has been
        # modified
        strategy3 = objects.Strategy(
            self.ctx, id=3, name="strategy_3", uuid=utils.generate_uuid(),
            display_name="Original", goal_id=goal1.id)
        # Should be modified after sync() because both its related goal
        # and its strategy name have been modified
        strategy4 = objects.Strategy(
            self.ctx, id=4, name="strategy_4", uuid=utils.generate_uuid(),
            display_name="Original", goal_id=goal2.id)
        strategy1.create()
        strategy2.create()
        strategy3.create()
        strategy4.create()

        # Here we simulate audit_templates that were already created in the
        # past and hence saved within the Watcher DB

        # Should stay unmodified after sync()
        audit_template1 = objects.AuditTemplate(
            self.ctx, id=1, name="Synced AT1", uuid=utils.generate_uuid(),
            goal_id=goal1.id, strategy_id=strategy1.id)
        # Should be modified by the sync() because its associated goal
        # has been modified (compared to the defined fake goals)
        audit_template2 = objects.AuditTemplate(
            self.ctx, id=2, name="Synced AT2", uuid=utils.generate_uuid(),
            goal_id=goal2.id, strategy_id=strategy2.id)
        # Should be modified by the sync() because its associated strategy
        # has been modified (compared to the defined fake strategies)
        audit_template3 = objects.AuditTemplate(
            self.ctx, id=3, name="Synced AT3", uuid=utils.generate_uuid(),
            goal_id=goal1.id, strategy_id=strategy3.id)
        # Modified because of both because its associated goal and associated
        # strategy should be modified
        audit_template4 = objects.AuditTemplate(
            self.ctx, id=4, name="Synced AT4", uuid=utils.generate_uuid(),
            goal_id=goal2.id, strategy_id=strategy4.id)
        audit_template1.create()
        audit_template2.create()
        audit_template3.create()
        audit_template4.create()

        # Should stay unmodified after sync()
        audit1 = objects.Audit(
            self.ctx, id=1, uuid=utils.generate_uuid(), name='audit_1',
            audit_type=objects.audit.AuditType.ONESHOT.value,
            state=objects.audit.State.PENDING,
            goal_id=goal1.id, strategy_id=strategy1.id, auto_trigger=False)
        # Should be modified by the sync() because its associated goal
        # has been modified (compared to the defined fake goals)
        audit2 = objects.Audit(
            self.ctx, id=2, uuid=utils.generate_uuid(), name='audit_2',
            audit_type=objects.audit.AuditType.ONESHOT.value,
            state=objects.audit.State.PENDING,
            goal_id=goal2.id, strategy_id=strategy2.id, auto_trigger=False)
        # Should be modified by the sync() because its associated strategy
        # has been modified (compared to the defined fake strategies)
        audit3 = objects.Audit(
            self.ctx, id=3, uuid=utils.generate_uuid(), name='audit_3',
            audit_type=objects.audit.AuditType.ONESHOT.value,
            state=objects.audit.State.PENDING,
            goal_id=goal1.id, strategy_id=strategy3.id, auto_trigger=False)
        # Modified because of both because its associated goal and associated
        # strategy should be modified (compared to the defined fake
        # goals/strategies)
        audit4 = objects.Audit(
            self.ctx, id=4, uuid=utils.generate_uuid(), name='audit_4',
            audit_type=objects.audit.AuditType.ONESHOT.value,
            state=objects.audit.State.PENDING,
            goal_id=goal2.id, strategy_id=strategy4.id, auto_trigger=False)

        audit1.create()
        audit2.create()
        audit3.create()
        audit4.create()

        # Should stay unmodified after sync()
        action_plan1 = objects.ActionPlan(
            self.ctx, id=1, uuid=utils.generate_uuid(),
            audit_id=audit1.id, strategy_id=strategy1.id,
            state='DOESNOTMATTER', global_efficacy={})
        # Stale after syncing because the goal of the audit has been modified
        # (compared to the defined fake goals)
        action_plan2 = objects.ActionPlan(
            self.ctx, id=2, uuid=utils.generate_uuid(),
            audit_id=audit2.id, strategy_id=strategy2.id,
            state='DOESNOTMATTER', global_efficacy={})
        # Stale after syncing because the strategy has been modified
        # (compared to the defined fake strategies)
        action_plan3 = objects.ActionPlan(
            self.ctx, id=3, uuid=utils.generate_uuid(),
            audit_id=audit3.id, strategy_id=strategy3.id,
            state='DOESNOTMATTER', global_efficacy={})
        # Stale after syncing because both the strategy and the related audit
        # have been modified (compared to the defined fake goals/strategies)
        action_plan4 = objects.ActionPlan(
            self.ctx, id=4, uuid=utils.generate_uuid(),
            audit_id=audit4.id, strategy_id=strategy4.id,
            state='DOESNOTMATTER', global_efficacy={})

        action_plan1.create()
        action_plan2.create()
        action_plan3.create()
        action_plan4.create()

        before_goals = objects.Goal.list(self.ctx)
        before_strategies = objects.Strategy.list(self.ctx)
        before_audit_templates = objects.AuditTemplate.list(self.ctx)
        before_audits = objects.Audit.list(self.ctx)
        before_action_plans = objects.ActionPlan.list(self.ctx)

        # ### Action under test ### #

        try:
            self.syncer.sync()
        except Exception as exc:
            self.fail(exc)

        # ### Assertions ### #

        after_goals = objects.Goal.list(self.ctx)
        after_strategies = objects.Strategy.list(self.ctx)
        after_audit_templates = objects.AuditTemplate.list(self.ctx)
        after_audits = objects.Audit.list(self.ctx)
        after_action_plans = objects.ActionPlan.list(self.ctx)

        self.assertEqual(2, len(before_goals))
        self.assertEqual(4, len(before_strategies))
        self.assertEqual(4, len(before_audit_templates))
        self.assertEqual(4, len(before_audits))
        self.assertEqual(4, len(before_action_plans))
        self.assertEqual(2, len(after_goals))
        self.assertEqual(4, len(after_strategies))
        self.assertEqual(4, len(after_audit_templates))
        self.assertEqual(4, len(after_audits))
        self.assertEqual(4, len(after_action_plans))

        self.assertEqual(
            {"dummy_1", "dummy_2"},
            set([g.name for g in after_goals]))
        self.assertEqual(
            {"strategy_1", "strategy_2", "strategy_3", "strategy_4"},
            set([s.name for s in after_strategies]))

        created_goals, modified_goals, unmodified_goals = (
            self._find_created_modified_unmodified_ids(
                before_goals, after_goals))

        created_strategies, modified_strategies, unmodified_strategies = (
            self._find_created_modified_unmodified_ids(
                before_strategies, after_strategies))

        (created_audit_templates, modified_audit_templates,
         unmodified_audit_templates) = (
             self._find_created_modified_unmodified_ids(
                 before_audit_templates, after_audit_templates))

        created_audits, modified_audits, unmodified_audits = (
            self._find_created_modified_unmodified_ids(
                before_audits, after_audits))

        (created_action_plans, modified_action_plans,
         unmodified_action_plans) = (
             self._find_created_modified_unmodified_ids(
                 before_action_plans, after_action_plans))

        dummy_1_spec = [
            {'description': 'Dummy indicator', 'name': 'dummy',
             'schema': 'Range(min=0, max=100, min_included=True, '
                       'max_included=True, msg=None)',
             'unit': '%'}]
        dummy_2_spec = []
        self.assertEqual(
            [dummy_1_spec, dummy_2_spec],
            [g.efficacy_specification for g in after_goals])

        self.assertEqual(1, len(created_goals))
        self.assertEqual(3, len(created_strategies))
        self.assertEqual(0, len(created_audits))
        self.assertEqual(0, len(created_action_plans))

        self.assertEqual(2, strategy2.goal_id)

        self.assertNotEqual(
            set([strategy2.id, strategy3.id, strategy4.id]),
            set(modified_strategies))
        self.assertEqual(set([strategy1.id]), set(unmodified_strategies))

        self.assertEqual(
            set([audit_template2.id, audit_template3.id, audit_template4.id]),
            set(modified_audit_templates))
        self.assertEqual(set([audit_template1.id]),
                         set(unmodified_audit_templates))

        self.assertEqual(
            set([audit2.id, audit3.id, audit4.id]),
            set(modified_audits))
        self.assertEqual(set([audit1.id]), set(unmodified_audits))

        self.assertEqual(
            set([action_plan2.id, action_plan3.id, action_plan4.id]),
            set(modified_action_plans))
        self.assertTrue(
            all(ap.state == objects.action_plan.State.CANCELLED
                for ap in modified_action_plans.values()))
        self.assertEqual(set([action_plan1.id]), set(unmodified_action_plans))