示例#1
0
    def test_sync_with_graceful_fail(self):
        # Setup
        sync_config = {'bruce': 'hulk', 'tony': 'ironman'}
        self.repo_manager.create_repo('repo-1')
        self.importer_manager.set_importer('repo-1', 'mock-importer',
                                           sync_config)

        mock_plugins.MOCK_IMPORTER.sync_repo.return_value = SyncReport(
            False, 10, 5, 1, 'Summary of the sync', 'Details of the sync')

        # Test
        self.assertRaises(PulpExecutionException, self.sync_manager.sync,
                          'repo-1')

        # Verify
        history = list(RepoSyncResult.get_collection().find(
            {'repo_id': 'repo-1'}))
        self.assertEqual(1, len(history))
        self.assertEqual('repo-1', history[0]['repo_id'])
        self.assertEqual(RepoSyncResult.RESULT_FAILED, history[0]['result'])
        self.assertEqual('mock-importer', history[0]['importer_id'])
        self.assertEqual('mock-importer', history[0]['importer_type_id'])
        self.assertTrue(history[0]['started'] is not None)
        self.assertTrue(history[0]['completed'] is not None)

        # Cleanup
        mock_plugins.reset()
示例#2
0
    def build_cancel_report(self, summary, details):
        """
        Creates the SyncReport instance that needs to be returned to the Pulp
        server at the end of a sync_repo call. The report built in this fashion
        will indicate the sync has been cancelled.

        The added, updated, and removed unit count fields will be populated with
        the tracking counters maintained by the conduit based on calls into it.
        If these are inaccurate for a given plugin's implementation, the counts
        can be changed in the returned report before returning it to Pulp. This
        data will capture how far it got before building the report and should
        be overridden if the plugin attempts to do some form of rollback due to
        the cancellation.

        @param summary: short log of the sync; may be None but probably shouldn't be
        @type  summary: any serializable

        @param details: potentially longer log of the sync; may be None
        @type  details: any serializable
        """
        r = SyncReport(False, self._added_count, self._updated_count, self._removed_count, summary, details)
        r.canceled_flag = True
        return r
示例#3
0
    def build_cancel_report(self, summary, details):
        """
        Creates the SyncReport instance that needs to be returned to the Pulp
        server at the end of a sync_repo call. The report built in this fashion
        will indicate the sync has been cancelled.

        The added, updated, and removed unit count fields will be populated with
        the tracking counters maintained by the conduit based on calls into it.
        If these are inaccurate for a given plugin's implementation, the counts
        can be changed in the returned report before returning it to Pulp. This
        data will capture how far it got before building the report and should
        be overridden if the plugin attempts to do some form of rollback due to
        the cancellation.

        @param summary: short log of the sync; may be None but probably shouldn't be
        @type  summary: any serializable

        @param details: potentially longer log of the sync; may be None
        @type  details: any serializable
        """
        r = SyncReport(False, self._added_count, self._updated_count,
                       self._removed_count, summary, details)
        r.canceled_flag = True
        return r
示例#4
0
    def build_success_report(self, summary, details):
        """
        Creates the SyncReport instance that needs to be returned to the Pulp
        server at the end of a successful sync_repo call.

        The added, updated, and removed unit count fields will be populated with
        the tracking counters maintained by the conduit based on calls into it.
        If these are inaccurate for a given plugin's implementation, the counts
        can be changed in the returned report before returning it to Pulp.

        @param summary: short log of the sync; may be None but probably shouldn't be
        @type  summary: any serializable

        @param details: potentially longer log of the sync; may be None
        @type  details: any serializable
        """
        r = SyncReport(True, self._added_count, self._updated_count,
                       self._removed_count, summary, details)
        return r
示例#5
0
 def build_success_report(summary, details):
     return SyncReport(True, sync_conduit._added_count, sync_conduit._updated_count,
                       sync_conduit._removed_count, summary, details)
示例#6
0
 def build_failure_report(summary, details):
     return SyncReport(False, sync_conduit._added_count, sync_conduit._updated_count,
                       sync_conduit._removed_count, summary, details)
示例#7
0
 def build_failure_report(self, summary, details):
     return SyncReport(False, -1, -1, -1, summary, details)
示例#8
0
 def build_success_report(self, summary, details):
     return SyncReport(True, -1, -1, -1, summary, details)
示例#9
0
def install():
    """
    Called during test setup to monkey patch the plugin loader for testing.
    """

    # -- update plugin loader inventory ---------------------------------------

    plugin_api._create_manager()

    plugin_api._MANAGER.importers.add_plugin('mock-importer', MockImporter, {})
    plugin_api._MANAGER.group_importers.add_plugin('mock-group-importer', MockGroupImporter, {})
    plugin_api._MANAGER.distributors.add_plugin('mock-distributor', MockDistributor, {})
    plugin_api._MANAGER.distributors.add_plugin('mock-distributor-2', MockDistributor, {})
    plugin_api._MANAGER.group_distributors.add_plugin('mock-group-distributor', MockGroupDistributor, {})
    plugin_api._MANAGER.group_distributors.add_plugin('mock-group-distributor-2', MockGroupDistributor, {})
    plugin_api._MANAGER.profilers.add_plugin('mock-profiler', MockProfiler, {})
    plugin_api._MANAGER.profilers.add_plugin('mock-rpm-profiler', MockRpmProfiler, {})

    # -- return mock instances instead of ephemeral ones ----------------------

    # Save the state of the original plugin loader so it can be reverted
    global _ORIG_GET_DISTRIBUTOR_BY_ID
    global _ORIG_GET_GROUP_DISTRIBUTOR_BY_ID
    global _ORIG_GET_IMPORTER_BY_ID
    global _ORIG_GET_GROUP_IMPORTER_BY_ID
    global _ORIG_GET_PROFILER_BY_TYPE

    _ORIG_GET_DISTRIBUTOR_BY_ID = plugin_api.get_distributor_by_id
    _ORIG_GET_GROUP_DISTRIBUTOR_BY_ID = plugin_api.get_group_distributor_by_id
    _ORIG_GET_IMPORTER_BY_ID = plugin_api.get_importer_by_id
    _ORIG_GET_GROUP_IMPORTER_BY_ID = plugin_api.get_group_importer_by_id
    _ORIG_GET_PROFILER_BY_TYPE = plugin_api.get_profiler_by_type

    # Setup the importer/distributor mappings that return the mock instances
    global DISTRIBUTOR_MAPPINGS
    DISTRIBUTOR_MAPPINGS = {
            'mock-distributor' : MOCK_DISTRIBUTOR,
            'mock-distributor-2' : MOCK_DISTRIBUTOR_2,
    }

    global GROUP_DISTRIBUTOR_MAPPINGS
    GROUP_DISTRIBUTOR_MAPPINGS = {
        'mock-group-distributor' : MOCK_GROUP_DISTRIBUTOR,
        'mock-group-distributor-2' : MOCK_GROUP_DISTRIBUTOR_2,
    }

    global IMPORTER_MAPPINGS
    IMPORTER_MAPPINGS = {
        'mock-importer' : MOCK_IMPORTER
    }

    global GROUP_IMPORTER_MAPPINGS
    GROUP_IMPORTER_MAPPINGS = {
        'mock-group-importer' : MOCK_GROUP_IMPORTER
    }

    global PROFILER_MAPPINGS
    PROFILER_MAPPINGS = {}
    for profiler in MOCK_PROFILERS:
        for t in profiler.metadata()['types']:
            PROFILER_MAPPINGS[t] = profiler

    # Return the mock instance; eventually can enhance this to support
    # multiple IDs and instances
    def mock_get_distributor_by_id(id):
        if id not in DISTRIBUTOR_MAPPINGS:
            raise plugin_exceptions.PluginNotFound()

        return DISTRIBUTOR_MAPPINGS[id], {}

    def mock_get_group_distributor_by_id(id):
        if id not in GROUP_DISTRIBUTOR_MAPPINGS:
            raise plugin_exceptions.PluginNotFound()

        return GROUP_DISTRIBUTOR_MAPPINGS[id], {}

    def mock_get_importer_by_id(id):
        if id not in IMPORTER_MAPPINGS:
            raise plugin_exceptions.PluginNotFound()

        return IMPORTER_MAPPINGS[id], {}

    def mock_get_group_importer_by_id(id):
        if id not in GROUP_IMPORTER_MAPPINGS:
            raise plugin_exceptions.PluginNotFound()

        return GROUP_IMPORTER_MAPPINGS[id], {}

    def mock_get_profiler_by_type(type):
        if type not in PROFILER_MAPPINGS:
            raise plugin_exceptions.PluginNotFound()

        return PROFILER_MAPPINGS[type], {}

    # Monkey patch in the mock methods
    plugin_api.get_distributor_by_id = mock_get_distributor_by_id
    plugin_api.get_group_distributor_by_id = mock_get_group_distributor_by_id
    plugin_api.get_importer_by_id = mock_get_importer_by_id
    plugin_api.get_group_importer_by_id = mock_get_group_importer_by_id
    plugin_api.get_profiler_by_type = mock_get_profiler_by_type

    # -- configure the mock instances -----------------------------------------

    # By default, have the plugins indicate configurations are valid
    MOCK_IMPORTER.validate_config.return_value = True, None
    MOCK_IMPORTER.sync_repo.return_value = SyncReport(True, 10, 5, 1, 'Summary of the sync', 'Details of the sync')

    MOCK_GROUP_IMPORTER.validate_config.return_value = True, None

    MOCK_DISTRIBUTOR.validate_config.return_value = True, None
    MOCK_DISTRIBUTOR.publish_repo.return_value = PublishReport(True, 'Summary of the publish', 'Details of the publish')

    MOCK_DISTRIBUTOR_2.validate_config.return_value = True, None
    MOCK_DISTRIBUTOR_2.publish_repo.return_value = PublishReport(True, 'Summary of the publish', 'Details of the publish')

    MOCK_GROUP_DISTRIBUTOR.validate_config.return_value = True, None
    MOCK_GROUP_DISTRIBUTOR_2.validate_config.return_value = True, None

    for profiler in MOCK_PROFILERS:
        profiler.update_profile = \
            mock.Mock(side_effect=lambda consumer,content_type,profile,config: profile)
        profiler.install_units = \
            mock.Mock(side_effect=lambda i,u,o,c,x: sorted(u))
        profiler.update_units = \
            mock.Mock(side_effect=lambda i,u,o,c,x: sorted(u))
        profiler.uninstall_units = \
            mock.Mock(side_effect=lambda i,u,o,c,x: sorted(u))
        profiler.calculate_applicable_units = \
            mock.Mock(side_effect=lambda t,p,r,c,x: ['mocked-unit1', 'mocked-unit2'])
示例#10
0
 def sync_repo(self, *args, **kwargs):
     return SyncReport(True, 10, 5, 1, 'Summary of the sync',
                       'Details of the sync')