Пример #1
0
    def __init__(self, config):
        """
        Initialize the state of the Recipe manager based on configuration.

        Args:
            config: The pakit configuration.
        """
        self.interval = config.get('pakit.recipe.update_interval')
        self.root = config.path_to('recipes')
        self.uri_db = RecipeURIDB(os.path.join(self.root, 'uris.yml'))
        self.active_kwargs = {}
        self.active_uris = []
        for kwargs in copy.deepcopy(config.get('pakit.recipe.uris')):
            uri = kwargs.pop('uri')
            self.active_uris.append(uri)
            if len(kwargs):
                self.active_kwargs[uri] = kwargs
Пример #2
0
 def setup(self):
     self.filename = os.path.join(tc.STAGING, 'rdb.yml')
     self.rdb = RecipeURIDB(self.filename)
Пример #3
0
class RecipeManager(object):
    """
    Manage the retrieval and updating of recipe sources remote and local.
    This class works in conjunction with RecipeDB to provide recipes to pakit.

    Attributes:
        active_kwargs: Indexed on uri, value is kwargs for the factory.
        active_uris: Actively configured sources.
        root: Where all recipes will be downloaded and stored.
        uri_db: A database to help keep track of recipe sources.
            Indexed based on uri.
    """
    def __init__(self, config):
        """
        Initialize the state of the Recipe manager based on configuration.

        Args:
            config: The pakit configuration.
        """
        self.interval = config.get('pakit.recipe.update_interval')
        self.root = config.path_to('recipes')
        self.uri_db = RecipeURIDB(os.path.join(self.root, 'uris.yml'))
        self.active_kwargs = {}
        self.active_uris = []
        for kwargs in copy.deepcopy(config.get('pakit.recipe.uris')):
            uri = kwargs.pop('uri')
            self.active_uris.append(uri)
            if len(kwargs):
                self.active_kwargs[uri] = kwargs

    @property
    def paths(self):
        """
        Returns the paths to all active recipe locations on the system.
        """
        return [self.uri_db[uri]['path'] for uri in self.active_uris]

    def check_for_deletions(self):
        """
        Check if any entries in the uri_db are stale.

        Purge any uri_db entries that have been deleted from their path.
        """
        to_remove = []
        for uri in self.uri_db:
            if not os.path.exists(self.uri_db[uri]['path']):
                to_remove.append(uri)

        for uri in to_remove:
            del self.uri_db[uri]
        self.uri_db.write()

    def check_for_updates(self):
        """
        Check if any of the active URIs needs updating.

        A recipe remote will be update if it is version controlled and ...
            - it has not been updated since interval
            - the kwargs between uri_db and active_kwargs differ
        """
        need_updates = self.uri_db.need_updates(self.interval)
        vcs_uris = [uri for uri in self.uri_db if self.uri_db[uri]['is_vcs']]
        for uri in set(self.active_uris).intersection(vcs_uris):
            db_kwargs = self.uri_db[uri].get('kwargs', {})
            kwargs = self.active_kwargs.get(uri, {})
            repo = vcs_factory(uri, **kwargs)
            repo.target = self.uri_db[uri]['path']

            if uri in need_updates or db_kwargs != kwargs:
                PLOG('Updating recipes from: %s.', uri)
                with repo:
                    self.uri_db.update_time(uri)
                    self.uri_db[uri]['kwargs'] = kwargs

        self.uri_db.write()

    def init_new_uris(self):
        """
        For new uris not present in the uri_db:
            - Select a unique name inside recipes folder
            - Add an entry to the uri_db
            - If the uri is local, create the folder at the path.
            - If the uri is remote, clone the version repository
              with optional kwargs.

        Raises:
            PakitError: User attempted to use an unsupported URI.
        """
        for uri in set(self.active_uris).difference(self.uri_db.keys()):
            repo = None
            kwargs = self.active_kwargs.get(uri, {})

            try:
                repo = vcs_factory(uri, **kwargs)
            except PakitError:
                if uri.find('/') != -1 or uri.find('.') != -1:
                    raise

            preferred = os.path.join(self.root, os.path.basename(uri))
            path = self.uri_db.select_path(preferred)
            self.uri_db.add(uri, path, repo is not None, kwargs)

            if repo:
                repo.target = path
                PLOG('Downloading new recipes: %s', uri)
                with repo:
                    pass
            else:
                PLOG('Indexing local recipes from: %s', path)
                try:
                    os.makedirs(path)
                except OSError:
                    pass

        self.uri_db.write()
Пример #4
0
class TestRecipeURIDB(object):
    def setup(self):
        self.filename = os.path.join(tc.STAGING, 'rdb.yml')
        self.rdb = RecipeURIDB(self.filename)

    def teardown(self):
        tc.delete_it(self.filename)

    def test_add_local(self):
        self.rdb.add('local', 'local', False)
        assert self.rdb['local']['path'] == 'local'
        assert self.rdb['local']['is_vcs'] is False

    def test_add_remote(self):
        self.rdb.add('remote_uri', 'remote_path', True)
        assert self.rdb['remote_uri']['path'] == 'remote_path'
        assert self.rdb['remote_uri']['is_vcs']

    def test_add_remote_kwargs(self):
        kwargs = {'tag': '0.30.0'}
        self.rdb.add('remote_uri', 'remote_path', True, kwargs)
        assert self.rdb['remote_uri']['path'] == 'remote_path'
        assert self.rdb['remote_uri']['is_vcs']
        assert self.rdb['remote_uri']['kwargs'] == kwargs

    def test_update_time(self):
        self.rdb.add('local', 'local', False)
        old_time = self.rdb['local']['time']
        self.rdb.update_time('local')
        assert self.rdb['local']['time'] > old_time

    def test_need_updates(self):
        key = 'remote_uri'
        self.rdb.add(key, 'remote_path', True)
        self.rdb[key]['time'] = self.rdb[key]['time'] - 10000
        assert self.rdb.need_updates(5000) == ['remote_uri']

    def test_select_path_preferred(self):
        preferred = '/tmp/first'
        assert self.rdb.select_path(preferred) == preferred

    def test_select_path_collision(self):
        preferred = '/tmp/first'
        self.rdb.add('first', preferred, False)
        assert self.rdb.select_path(preferred) == preferred + '_1'