예제 #1
0
    def run(self):
        """
        Synchronize the repository with the remote repository.

        This walks through the standard workflow that most sync operations want to follow. This
        pattern is a recommended starting point for other plugins.

        - Determine what is available remotely.
        - Determine what is already in the local repository.
        - Compare those two, and based on any importer settings or content-type-specific logic,
          figure out what you want to add and remove from the local repository.
        - Use a ChangeSet to make those changes happen.
        """
        # Determine what is available remotely
        self._fetch_manifest()
        # Determine what is already in the repo
        self._fetch_inventory()

        # Based on the above two, figure out what we want to add and remove
        self._find_delta()
        additions = SizedIterable(self._build_additions(),
                                  len(self._keys_to_add))
        removals = SizedIterable(self._build_removals(),
                                 len(self._keys_to_remove))

        # Hand that to a ChangeSet, and we're done!
        changeset = ChangeSet(self._importer,
                              additions=additions,
                              removals=removals)
        changeset.apply_and_drain()
예제 #2
0
def build_removals(base_version, delta):
    """
    Build the content to be removed.

    Args:
        base_version (RepositoryVersion):  The base repository version.
        delta (Delta): The set of Key to be added and removed.

    Returns:
        SizedIterable: The AnsibleRoleVersion to be removed from the repository.
    """
    def generate():
        for removals in BatchIterator(delta.removals):
            q = Q()
            for key in removals:
                role = AnsibleRoleVersion.objects.get(name=key.name,
                                                      namespace=key.namespace)
                q |= Q(ansibleroleversion__role_id=role.pk,
                       ansibleroleversion__version=key.version)
            q_set = base_version.content.filter(q)
            q_set = q_set.only('id')
            for file in q_set:
                yield file

    return SizedIterable(generate(), len(delta.removals))
예제 #3
0
def build_additions(remote, manifest, delta):
    """
    Build the content to be added.

    Args:
        remote (FileRemote): An remote.
        manifest (Manifest): The downloaded manifest.
        delta (Delta): The set of Key to be added and removed.

    Returns:
        SizedIterable: The PendingContent to be added to the repository.
    """
    def generate():
        for entry in manifest.read():
            key = Key(relative_path=entry.relative_path, digest=entry.digest)
            if key not in delta.additions:
                continue
            path = os.path.join(root_dir, entry.relative_path)
            url = urlunparse(parsed_url._replace(path=path))
            file = FileContent(relative_path=entry.relative_path,
                               digest=entry.digest)
            artifact = Artifact(size=entry.size, sha256=entry.digest)
            content = PendingContent(file,
                                     artifacts={
                                         PendingArtifact(
                                             artifact, url,
                                             entry.relative_path)
                                     })
            yield content

    parsed_url = urlparse(remote.url)
    root_dir = os.path.dirname(parsed_url.path)
    return SizedIterable(generate(), len(delta.additions))
예제 #4
0
def _build_additions(delta, remote_metadata):
    """
    Generate the content to be added.

    Args:
        delta (namedtuple): Tuple of content to add, and content to remove from the repository
        remote_metadata (list): List of contentunit metadata

    Returns:
        The PythonPackageContent to be added to the repository.

    """
    def generate():
        for entry in remote_metadata:
            if entry['filename'] not in delta.additions:
                continue

            url = entry.pop('url')
            artifact = models.Artifact(sha256=entry.pop('sha256_digest'))

            package = python_models.PythonPackageContent(**entry)
            content = PendingContent(package,
                                     artifacts={
                                         PendingArtifact(
                                             model=artifact,
                                             url=url,
                                             relative_path=entry['filename'])
                                     })
            yield content

    return SizedIterable(generate(), len(delta.additions))
예제 #5
0
def build_additions(remote, roles, delta):
    """
    Build the content to be added.

    Args:
        remote (AnsibleRemote): A remote.
        roles (list): The list of role dict from Galaxy
        delta (Delta): The set of Key to be added and removed.

    Returns:
        SizedIterable: The PendingContent to be added to the repository.

    """
    def generate():
        for metadata in roles:
            role, _ = AnsibleRole.objects.get_or_create(
                name=metadata['name'], namespace=metadata['namespace'])

            for version in metadata['summary_fields']['versions']:
                key = Key(name=metadata['name'],
                          namespace=metadata['namespace'],
                          version=version['name'])

                if key not in delta.additions:
                    continue

                url = GITHUB_URL % (metadata['github_user'],
                                    metadata['github_repo'], version['name'])
                role_version = AnsibleRoleVersion(version=version['name'],
                                                  role=role)
                path = "%s/%s/%s.tar.gz" % (metadata['namespace'],
                                            metadata['name'], version['name'])
                artifact = Artifact()
                content = PendingContent(
                    role_version,
                    artifacts={PendingArtifact(artifact, url, path)})
                yield content

    return SizedIterable(generate(), len(delta.additions))
예제 #6
0
def build_removals(base_version, delta):
    """
    Build the content to be removed.

    Args:
        base_version (RepositoryVersion):  The base repository version.
        delta (Delta): The set of Key to be added and removed.

    Returns:
        SizedIterable: The FileContent to be removed from the repository.
    """
    def generate():
        for removals in BatchIterator(delta.removals):
            q = Q()
            for key in removals:
                q |= Q(gemcontent__name=key.name,
                       gemcontent__version=key.version)
            q_set = base_version.content.filter(q)
            q_set = q_set.only('id')
            for gem in q_set:
                yield gem

    return SizedIterable(generate(), len(delta.removals))
예제 #7
0
def build_removals(base_version, delta):
    """
    Build the content to be removed.

    Args:
        base_version (RepositoryVersion):  The base repository version.
        delta (Delta): The set of Key to be added and removed.

    Returns:
        SizedIterable: The FileContent to be removed from the repository.
    """
    def generate():
        for removals in BatchIterator(delta.removals):
            q = Q()
            for key in removals:
                q |= Q(filecontent__relative_path=key.relative_path,
                       filecontent__digest=key.digest)
            q_set = base_version.content.filter(q)
            q_set = q_set.only('id')
            for file in q_set:
                yield file

    return SizedIterable(generate(), len(delta.removals))
예제 #8
0
def build_additions(remote, specs, delta):
    """
    Build the content to be added.

    Args:
        remote (FileRemote): A remote.
        specs (Specs): The downloaded specs.
        delta (Delta): The set of Key to be added and removed.

    Returns:
        SizedIterable: The PendingContent to be added to the repository.
    """
    def generate():
        for key in delta.additions:
            relative_path = os.path.join('gems',
                                         key.name + '-' + key.version + '.gem')
            path = os.path.join(root_dir, relative_path)
            url = urlunparse(parsed_url._replace(path=path))

            spec_relative_path = os.path.join(
                'quick/Marshal.4.8',
                key.name + '-' + key.version + '.gemspec.rz')
            spec_path = os.path.join(root_dir, spec_relative_path)
            spec_url = urlunparse(parsed_url._replace(path=spec_path))

            gem = GemContent(name=key.name, version=key.version)
            content = PendingContent(
                gem,
                artifacts={
                    PendingArtifact(Artifact(), url, relative_path),
                    PendingArtifact(Artifact(), spec_url, spec_relative_path),
                })
            yield content

    parsed_url = urlparse(remote.url)
    root_dir = os.path.dirname(parsed_url.path)
    return SizedIterable(generate(), len(delta.additions))
예제 #9
0
def _build_removals(delta, version):
    """
    Generate the content to be removed.

    Args:
        delta (namedtuple): Tuple of content to add, and content to remove from the repository
        version (pulpcore.plugin.models.RepositoryVersion): Version of repository to remove
            contents from

    Returns:
        The PythonPackageContent to be removed from the repository.

    """
    def generate():
        for removals in BatchIterator(delta.removals):
            q = Q()
            for content_key in removals:
                q |= Q(pythonpackagecontent__filename=content_key)
            q_set = version.content.filter(q)
            q_set = q_set.only('id')
            for content in q_set:
                yield content

    return SizedIterable(generate(), len(delta.removals))