def test_get_issuetracker_info(self, api_value, tmpl_value, audit_value,
                                   expected, mock_tmpl, mock_audit):
        """Test _get_issuetracker_info(api_val={0}, tmpl_val={1}, audit_val={2})"""
        # pylint: disable=protected-access,too-many-arguments

        asmt = mock.Mock()
        asmt.title = 'T'
        api_dict = dict()

        if api_value is not None:
            api_dict['issue_tracker'] = api_value

        if tmpl_value is not None:
            api_dict['template'] = {'type': 'A', 'id': 'B'}
            mock_tmpl.return_value = tmpl_value
        else:
            mock_tmpl.return_value = {}

        if audit_value is not None:
            api_dict['audit'] = {'type': 'A', 'id': 'B'}
            mock_audit.return_value = audit_value
        else:
            mock_audit.return_value = {}

        # test result
        tracker_handler = assessment_integration.AssessmentTrackerHandler()
        ret = tracker_handler._get_issuetracker_info(asmt, api_dict)

        self.assertEqual(ret, expected)
예제 #2
0
    def handle_assessment_post(sender,
                               objects=None,
                               sources=None,
                               service=None):
        """Applies custom attribute definitions and maps people roles.

    Applicable when generating Assessment with template.

    Args:
      sender: A class of Resource handling the POST request.
      objects: A list of model instances created from the POSTed JSON.
      sources: A list of original POSTed JSON dictionaries.
    """
        del sender, service  # Unused

        db.session.flush()

        for assessment, src in itertools.izip(objects, sources):
            _handle_assessment(assessment, src)

        # Flush roles objects for generated assessments.
        db.session.flush()

        tracker_handler = assessment_integration.AssessmentTrackerHandler()
        for assessment, src in itertools.izip(objects, sources):
            # Handling IssueTracker info here rather than in hooks/issue_tracker
            # would avoid querying same data (such as snapshots, audits and
            # templates) twice.
            tracker_handler.handle_assessment_create(assessment, src)
    def test_is_issue_on_create_enabled(self, is_tracker_enabled,
                                        api_issue_dict, tmpl_issue_dict,
                                        expected, mock_tracker_enabled,
                                        mock_template):
        """Test _is_issue_on_create_enabled(in_audit={0}, api={1}, tmpl={2})"""
        # pylint: disable=protected-access,too-many-arguments

        # prepare Assessment instance
        asmt = mock.Mock()
        asmt.audit = mock.Mock()
        mock_tracker_enabled.return_value = is_tracker_enabled

        # prepare API dictionary
        api_dict = {}

        if api_issue_dict is not None:
            api_dict['issue_tracker'] = api_issue_dict

        if tmpl_issue_dict is not None:
            api_dict['template'] = {}
            mock_template.return_value = tmpl_issue_dict
        else:
            mock_template.return_value = {}

        # test result
        tracker_handler = assessment_integration.AssessmentTrackerHandler()
        ret = tracker_handler._is_issue_on_create_enabled(asmt, api_dict)

        self.assertEqual(ret, expected)
예제 #4
0
    def handle_assessment_post(sender,
                               objects=None,
                               sources=None,
                               service=None):
        """Applies custom attribute definitions and maps people roles.

    Applicable when generating Assessment with template.

    Args:
      sender: A class of Resource handling the POST request.
      objects: A list of model instances created from the POSTed JSON.
      sources: A list of original POSTed JSON dictionaries.
    """
        del sender, service  # Unused

        db.session.flush()

        audit, template = None, None
        for assessment, src in itertools.izip(objects, sources):
            audit = _get_object_from_src(src,
                                         _get_audit_id,
                                         all_models.Audit,
                                         current=audit)

            template = _get_object_from_src(src,
                                            _get_template_id,
                                            all_models.AssessmentTemplate,
                                            current=template)

            snapshot_rev_content = None
            snapshot = _get_object_from_src(src, _get_snapshot_id,
                                            all_models.Snapshot)
            if snapshot is not None:
                # Since every content call on revision leads to it calculation (and
                # one is quite expensive) it is better for performance to compute it
                # one time and pass it everywhere though it may seem redundant.
                snapshot_rev_content = snapshot.revision.content

            _handle_assessment(
                assessment,
                audit,
                tmpl=template,
                snapshot=snapshot,
                snapshot_rev_content=snapshot_rev_content,
                is_autogenerated=_is_autogenerated(src),
            )

        _batch_insert_cads(attributables=objects)
        _batch_insert_acps(assessments=objects)

        # Flush roles objects for generated assessments.
        db.session.flush()

        tracker_handler = assessment_integration.AssessmentTrackerHandler()
        for assessment, src in itertools.izip(objects, sources):
            # Handling IssueTracker info here rather than in hooks/issue_tracker
            # would avoid querying same data (such as snapshots, audits and
            # templates) twice.
            integration_utils.update_issue_tracker_for_import(assessment)
            tracker_handler.handle_assessment_create(assessment, src)
예제 #5
0
 def test_merge_ccs_method(self, object_ccs, additional_ccs, expected_ccs):
     """Test merge_ccs method"""
     # pylint: disable=protected-access
     tracker_handler = assessment_integration.AssessmentTrackerHandler()
     grouped_ccs = tracker_handler._merge_ccs(
         object_ccs,
         additional_ccs,
     )
     self.assertEqual(set(grouped_ccs), set(expected_ccs))
예제 #6
0
    def test_validate_info(self, info, expected_error):
        """Test _validate_issue_tracker_info function."""
        initial_info = dict(info)
        tracker_handler = assessment_integration.AssessmentTrackerHandler()
        # pylint: disable=protected-access
        if expected_error:
            with self.assertRaises(expected_error):
                tracker_handler._validate_generic_fields(info)
        else:
            tracker_handler._validate_generic_fields(info)

        self.assertEqual(info, initial_info)
예제 #7
0
 def test_assignee_sync_not_exists(self):
     """Test for get assignee on sync if not assignee exists."""
     # pylint: disable=protected-access
     assmt_object = mock.MagicMock(id=1)
     with mock.patch.object(assessment_integration.AssessmentTrackerHandler,
                            '_is_assignee_exists',
                            return_value=False):
         tracker_handler = assessment_integration.AssessmentTrackerHandler()
         reporter = "*****@*****.**"
         reporter_tracker = tracker_handler._get_assignee_on_sync(
             assmt_object, reporter)
         self.assertEqual("*****@*****.**", reporter_tracker)
예제 #8
0
 def test_reporter_sync_exists(self):
     """Test for get reporter on sync if reporter exists."""
     # pylint: disable=protected-access
     mock_object = mock.MagicMock(id=1)
     with mock.patch.object(assessment_integration.AssessmentTrackerHandler,
                            '_is_reporter_exists',
                            return_value=True):
         tracker_handler = assessment_integration.AssessmentTrackerHandler()
         reporter = "*****@*****.**"
         reporter_tracker = tracker_handler._get_reporter_on_sync(
             mock_object, reporter)
         self.assertEqual(reporter, reporter_tracker)
예제 #9
0
def sync_assessment_attributes():  # noqa
  """Synchronizes issue tracker ticket statuses with the Assessment statuses.

  Checks for Assessments which are in sync with Issue Tracker issues and
  updates their statuses in accordance to the corresponding Assessments
  if differ.
  """
  logger.info(
      "Assessment synchronization start: %s",
      datetime.datetime.utcnow()
  )
  assessment_issues = sync_utils.collect_issue_tracker_info(
      "Assessment"
  )
  if not assessment_issues:
    return
  logger.info("Syncing state of %d issues.", len(assessment_issues))

  processed_ids = set()
  tracker_handler = assessment_integration.AssessmentTrackerHandler()
  for batch in sync_utils.iter_issue_batches(assessment_issues.keys()):
    for issue_id, issuetracker_state in batch.iteritems():
      issue_id, issue_info = _get_issue_info_by_issue_id(
          issue_id,
          assessment_issues
      )
      if not issue_info:
        logger.warning(
            "Got an unexpected issue from Issue Tracker: %s", issue_id
        )
        continue

      processed_ids.add(issue_id)

      try:
        tracker_handler.handle_assessment_sync(
            issue_info,
            issue_id,
            issuetracker_state
        )
      except Exception as ex:  # pylint: disable=broad-except
        logger.error(
            "Unhandled synchronization error: %s %s %s",
            issue_id,
            issue_info,
            ex
        )
        continue

  logger.info("Sync is done, %d issue(s) were processed.", len(processed_ids))
  _check_missing_ids(assessment_issues, processed_ids)
    def test_is_issue_create_disabled(self):
        """Test 'is issue tracker disabled' on create."""
        # pylint: disable=protected-access
        assessment_src = {
            "issue_tracker": {
                "enabled": False,
            },
        }

        tracker_handler = assessment_integration.AssessmentTrackerHandler()
        is_issue_enabled = tracker_handler._is_issue_on_create_enabled(
            assessment_src)

        self.assertFalse(is_issue_enabled)
    def test_is_issue_disabled_template(self, return_value, get_issue_mock):
        """Test 'is issue tracker disabled' from assessment template."""
        # pylint: disable=protected-access
        get_issue_mock.return_value = return_value
        assessment_src = {
            "template": {
                "type": 1,
                "id": 1,
            },
        }

        tracker_handler = assessment_integration.AssessmentTrackerHandler()
        is_issue_enabled = tracker_handler._is_issue_on_create_enabled(
            assessment_src)

        self.assertFalse(is_issue_enabled)
  def test_change_assessment_status(self, status,
                                    additional_kwargs,
                                    mocked_update_issue):
    """Issue status should be changed for assessment with {status} status."""
    iti_issue_id = []
    iti = factories.IssueTrackerIssueFactory(
        enabled=True,
        component_id="123123",
        issue_type="PROCESS",
        issue_priority="P2",
        issue_severity="S2"
    )
    iti_issue_id.append(iti.issue_id)
    asmt = iti.issue_tracked_obj
    tracker_handler = assessment_integration.AssessmentTrackerHandler()
    with mock.patch.object(
        assessment_integration.AssessmentTrackerHandler,
        '_is_tracker_enabled',
        return_value=True
    ):
      self.api.put(
          asmt,
          {
              "status": status,
          },
      )
      kwargs = {'component_id': 123123,
                'severity': "S2",
                'title': iti.title,
                'hotlist_ids': [],
                'priority': "P2"}
      asmt_link = tracker_handler._get_assessment_page_url(asmt)
      if 'comment' in additional_kwargs:
        try:
          additional_kwargs['comment'] = \
              additional_kwargs['comment'] % (status, asmt_link)
        except TypeError:
          pass
      kwargs.update(additional_kwargs)
      mocked_update_issue.assert_called_once_with(iti_issue_id[0], kwargs)

      issue = db.session.query(models.IssuetrackerIssue).get(iti.id)
      self.assertEqual(issue.cc_list, "")
    def test_is_need_sync(self, custom_same, common_same, ccs_same,
                          custom_mock, common_mock, ccs_mock):
        """Test _is_need_sync works correctly.

    Test that assessment needs to be synced with Issue Tracker when either ccs,
    common or custom fields differ.
    """
        asmt_handler = assessment_integration.AssessmentTrackerHandler()
        custom_mock.return_value = (custom_same, True)
        common_mock.return_value = common_same
        ccs_mock.return_value = ccs_same
        assessment_id = 0

        self.assertEqual(
            not all([custom_same, common_same, ccs_same]),
            asmt_handler._is_need_sync(
                assessment_id=assessment_id,
                issue_payload={"status": "Not Started"},
                issue_tracker_info={"status": "ASSIGNED"}),
        )
  def test_adding_comment_to_assessment(self, desc, mocked_update_issue):
    """Test adding comment with blank lines in the end."""
    with mock.patch.object(
        assessment_integration.AssessmentTrackerHandler,
        '_is_tracker_enabled',
        return_value=True
    ):
      iti = factories.IssueTrackerIssueFactory(
          enabled=True,
          component_id="11111",
          hotlist_id="222222",
          issue_type="PROCESS",
          issue_priority="P2",
          issue_severity="S2"
      )
      iti_title = iti.title
      iti_issue_id = iti.issue_id
      asmt = iti.issue_tracked_obj
      comment = factories.CommentFactory(description=desc)
      self.api.put(asmt, {
          "actions": {"add_related": [{"id": comment.id,
                                       "type": "Comment"}]},
      })

    tracker_handler = assessment_integration.AssessmentTrackerHandler()
    asmt = db.session.query(models.Assessment).get(asmt.id)
    builder_class = params_builder.BaseIssueTrackerParamsBuilder
    expected_comment = builder_class.COMMENT_TMPL.format(
        author=None,
        comment="test comment",
        model="Assessment",
        link=tracker_handler._get_assessment_page_url(asmt),
    )
    kwargs = {'status': 'ACCEPTED',
              'component_id': 11111,
              'severity': "S2",
              'title': iti_title,
              'hotlist_ids': [222222],
              'priority': "P2",
              'comment': expected_comment}
    mocked_update_issue.assert_called_once_with(iti_issue_id, kwargs)
 def test_prepare_update_json(self):
   """Test prepare_update_json method for Assessment."""
   with factories.single_commit():
     audit = factories.AuditFactory()
     factories.IssueTrackerIssueFactory(
         enabled=True,
         issue_tracked_obj=audit,
         component_id=213,
         hotlist_id=333,
         issue_type=constants.DEFAULT_ISSUETRACKER_VALUES['issue_type'],
         issue_priority="P0",
         issue_severity="S0",
     )
     assmt = factories.AssessmentFactory(
         audit=audit,
         title="title",
     )
     factories.IssueTrackerIssueFactory(
         enabled=True,
         issue_tracked_obj=assmt,
         title='',
     )
   tracker_handler = assessment_integration.AssessmentTrackerHandler()
   without_info = tracker_handler.prepare_issue_update_json(assmt)
   issue_info = assmt.issue_tracker
   with_info = tracker_handler.prepare_issue_update_json(
       assmt,
       issue_info
   )
   expected_info = {
       'component_id': 213,
       'severity': u'S0',
       'title': assmt.title,
       'hotlist_ids': [333, ],
       'priority': u'P0',
       'type': constants.DEFAULT_ISSUETRACKER_VALUES['issue_type'],
   }
   self.assertEqual(expected_info, with_info)
   self.assertEqual(without_info, with_info)