Esempio n. 1
0
    def _get_metadata(self):
        if self._metadata:
            return

        n_collection_url = _urljoin(self.api.api_server, 'api', 'v2',
                                    'collections', self.namespace, self.name,
                                    'versions', self.latest_version)
        details = json.load(
            open_url(n_collection_url,
                     validate_certs=self.api.validate_certs,
                     headers=self.api._auth_header(required=False)))
        self._galaxy_info = details
        self._metadata = details['metadata']
Esempio n. 2
0
def publish_collection(collection_path, api, wait, timeout):
    """
    Publish an Ansible collection tarball into an Ansible Galaxy server.

    :param collection_path: The path to the collection tarball to publish.
    :param api: A GalaxyAPI to publish the collection to.
    :param wait: Whether to wait until the import process is complete.
    :param timeout: The time in seconds to wait for the import process to finish, 0 is indefinite.
    """
    b_collection_path = to_bytes(collection_path, errors='surrogate_or_strict')
    if not os.path.exists(b_collection_path):
        raise AnsibleError(
            "The collection path specified '%s' does not exist." %
            to_native(collection_path))
    elif not tarfile.is_tarfile(b_collection_path):
        raise AnsibleError(
            "The collection path specified '%s' is not a tarball, use 'ansible-galaxy collection "
            "build' to create a proper release artifact." %
            to_native(collection_path))

    display.display("Publishing collection artifact '%s' to %s %s" %
                    (collection_path, api.name, api.api_server))

    n_url = _urljoin(api.api_server, 'api', 'v2', 'collections')

    data, content_type = _get_mime_data(b_collection_path)
    headers = {
        'Content-type': content_type,
        'Content-length': len(data),
    }
    headers.update(api._auth_header())

    try:
        resp = json.load(
            open_url(n_url,
                     data=data,
                     headers=headers,
                     method='POST',
                     validate_certs=api.validate_certs))
    except urllib_error.HTTPError as err:
        try:
            err_info = json.load(err)
        except (AttributeError, ValueError):
            err_info = {}

        code = to_native(err_info.get('code', 'Unknown'))
        message = to_native(
            err_info.get('message',
                         'Unknown error returned by Galaxy server.'))

        raise AnsibleError(
            "Error when publishing collection (HTTP Code: %d, Message: %s Code: %s)"
            % (err.code, message, code))

    import_uri = resp['task']
    if wait:
        display.display(
            "Collection has been published to the Galaxy server %s %s" %
            (api.name, api.api_server))
        _wait_import(import_uri, api, timeout)
        display.display(
            "Collection has been successfully published and imported to the Galaxy server %s %s"
            % (api.name, api.api_server))
    else:
        display.display(
            "Collection has been pushed to the Galaxy server %s %s, not waiting until import has "
            "completed due to --no-wait being set. Import task results can be found at %s"
            % (api.name, api.api_server, import_uri))
Esempio n. 3
0
    def from_name(collection, apis, requirement, force, parent=None):
        namespace, name = collection.split('.', 1)
        galaxy_info = None
        galaxy_meta = None

        for api in apis:
            collection_url_paths = [
                api.api_server, 'api', 'v2', 'collections', namespace, name,
                'versions'
            ]
            headers = api._auth_header(required=False)

            is_single = False
            if not (requirement == '*' or requirement.startswith('<')
                    or requirement.startswith('>')
                    or requirement.startswith('!=')):
                if requirement.startswith('='):
                    requirement = requirement.lstrip('=')

                collection_url_paths.append(requirement)
                is_single = True

            n_collection_url = _urljoin(*collection_url_paths)
            try:
                resp = json.load(
                    open_url(n_collection_url,
                             validate_certs=api.validate_certs,
                             headers=headers))
            except urllib_error.HTTPError as err:
                if err.code == 404:
                    display.vvv(
                        "Collection '%s' is not available from server %s %s" %
                        (collection, api.name, api.api_server))
                    continue
                raise

            if is_single:
                galaxy_info = resp
                galaxy_meta = resp['metadata']
                versions = [resp['version']]
            else:
                versions = []
                while True:
                    # Galaxy supports semver but ansible-galaxy does not. We ignore any versions that don't match
                    # StrictVersion (x.y.z) and only support pre-releases if an explicit version was set (done above).
                    versions += [
                        v['version'] for v in resp['results']
                        if StrictVersion.version_re.match(v['version'])
                    ]
                    if resp['next'] is None:
                        break
                    resp = json.load(
                        open_url(to_native(resp['next'],
                                           errors='surrogate_or_strict'),
                                 validate_certs=api.validate_certs,
                                 headers=headers))

            display.vvv("Collection '%s' obtained from server %s %s" %
                        (collection, api.name, api.api_server))
            break
        else:
            raise AnsibleError("Failed to find collection %s:%s" %
                               (collection, requirement))

        req = CollectionRequirement(namespace,
                                    name,
                                    None,
                                    api,
                                    versions,
                                    requirement,
                                    force,
                                    parent=parent,
                                    metadata=galaxy_meta)
        req._galaxy_info = galaxy_info
        return req