Example #1
0
    def remove_github_token(self):
        '''
        If for some reason an ansible-galaxy token was left from a prior login, remove it. We cannot
        retrieve the token after creation, so we are forced to create a new one.
        '''
        try:
            tokens = json.load(
                open_url(
                    self.GITHUB_AUTH,
                    url_username=self.github_username,
                    url_password=self.github_password,
                    force_basic_auth=True,
                ))
        except HTTPError as e:
            res = json.load(e)
            raise exceptions.GalaxyClientError(res['message'])

        for token in tokens:
            if token['note'] == 'ansible-galaxy login':
                self.log.debug('removing token: %s', token['token_last_eight'])
                try:
                    open_url('https://api.github.com/authorizations/%d' %
                             token['id'],
                             url_username=self.github_username,
                             url_password=self.github_password,
                             method='DELETE',
                             force_basic_auth=True)
                except HTTPError as e:
                    self.log.exception(e)
                    res = json.load(e)
                    raise exceptions.GalaxyClientError(res['message'])
Example #2
0
    def _get_server_api_version(self):
        """
        Fetches the Galaxy API current version to ensure
        the API server is up and reachable.
        """
        url = '%s/api/' % self._api_server

        try:
            return_data = open_url(url, validate_certs=self._validate_certs)
        except Exception as e:
            raise exceptions.GalaxyClientError(
                "Failed to get data from the API server (%s): %s " %
                (url, to_native(e)))

        try:
            data = json.loads(
                to_text(return_data.read(), errors='surrogate_or_strict'))
        except Exception as e:
            raise exceptions.GalaxyClientError(
                "Could not process data from the API server (%s): %s " %
                (url, to_native(e)))

        if 'current_version' not in data:
            raise exceptions.GalaxyClientError(
                "missing required 'current_version' from server response (%s)"
                % url)

        self.log.debug('Server API version of URL %s is "%s"', url,
                       data['current_version'])
        return data['current_version']
Example #3
0
 def __call_galaxy(self, url, args=None, headers=None, method=None):
     if args and not headers:
         headers = self.__auth_header()
     try:
         # self.log.info('%s %s', method, url)
         # self.log.debug('%s %s args=%s', method, url, args)
         # self.log.debug('%s %s headers=%s', method, url, headers)
         resp = open_url(url,
                         data=args,
                         validate_certs=self._validate_certs,
                         headers=headers,
                         method=method,
                         timeout=20)
         self.log.debug('%s %s http_status=%s', method, url, resp.getcode())
         final_url = resp.geturl()
         if final_url != url:
             self.log.debug('%s %s Redirected to: %s', method, url,
                            resp.geturl())
         # self.log.debug('%s %s info:\n%s', method, url, resp.info())
         data = json.loads(
             to_text(resp.read(), errors='surrogate_or_strict'))
         # self.log.debug('%s %s data: \n%s', method, url, json.dumps(data, indent=2))
     except HTTPError as e:
         self.log.debug('Exception on %s %s', method, url)
         self.log.exception(e)
         res = json.loads(to_text(e.fp.read(),
                                  errors='surrogate_or_strict'))
         raise exceptions.GalaxyClientError(res['detail'])
     return data
Example #4
0
def fetch_url(archive_url, validate_certs=True):
    """
    Downloads the archived content from github to a temp location
    """

    # TODO: should probably be based on/shared with rest API client code, so that
    #       content downloads could support any thing the rest code does
    #       (ie, any TLS cert setup, proxy config, auth options, etc)
    # WHEN: if we change the underlying http client impl at least
    try:
        url_file = open_url(archive_url, validate_certs=validate_certs)

        temp_file = tempfile.NamedTemporaryFile(
            delete=False,
            prefix='tmp-ansible-galaxy-content-archive-',
            suffix='.tar.gz')

        data = url_file.read()
        while data:
            temp_file.write(data)
            data = url_file.read()
        temp_file.close()
        return temp_file.name
    except Exception as e:
        # FIXME: there is a ton of reasons a download and save could fail so could likely provided better errors here
        log.exception(e)
        raise exceptions.GalaxyDownloadError(
            "failed to download the file: %s" % str(e))

    return False
Example #5
0
    def __call_galaxy(self, url, args=None, headers=None, method=None):
        if args and not headers:
            headers = self.__auth_header()
        try:
            http_log.info('%s %s', method, url)
            request_log.debug('%s %s args=%s', method, url, args)
            request_log.debug('%s %s headers=%s', method, url, headers)

            resp = open_url(url,
                            data=args,
                            validate_certs=self._validate_certs,
                            headers=headers,
                            method=method,
                            timeout=20)

            http_log.info('%s %s http_status=%s', method, url, resp.getcode())

            final_url = resp.geturl()
            if final_url != url:
                http_log.debug('%s %s Redirected to: %s', method, url,
                               resp.geturl())

            resp_info = resp.info()
            response_log.debug('%s %s info:\n%s', method, url, resp_info)

            # FIXME: making the request and loading the response should be sep try/except blocks
            response_body = to_text(resp.read(), errors='surrogate_or_strict')

            # debug log the raw response body
            response_log.debug('%s %s response body:\n%s', method, url,
                               response_body)

            data = json.loads(response_body)

            # debug log a json version of the data that was created from the response
            response_log.debug('%s %s data:\n%s', method, url,
                               json.dumps(data, indent=2))
        except HTTPError as e:
            self.log.debug('Exception on %s %s', method, url)
            self.log.exception(e)

            # FIXME: probably need a try/except here if the response body isnt json which
            #        can happen if a proxy mangles the response
            res = json.loads(to_text(e.fp.read(),
                                     errors='surrogate_or_strict'))

            http_log.error('%s %s data from server error response:\n%s',
                           method, url, res)

            raise exceptions.GalaxyClientError(res['detail'])
        except (ssl.SSLError, socket.error) as e:
            self.log.debug(
                'Connection error to Galaxy API for request "%s %s": %s',
                method, url, e)
            self.log.exception(e)
            raise exceptions.GalaxyClientAPIConnectionError(
                'Connection error to Galaxy API for request "%s %s": %s' %
                (method, url, e))

        return data
Example #6
0
 def authenticate(self, github_token):
     """
     Retrieve an authentication token
     """
     url = '%s/tokens/' % self.baseurl
     args = urlencode({"github_token": github_token})
     resp = open_url(url,
                     data=args,
                     validate_certs=self._validate_certs,
                     method="POST")
     data = json.loads(to_text(resp.read(), errors='surrogate_or_strict'))
     return data
Example #7
0
 def create_github_token(self):
     '''
     Create a personal authorization token with a note of 'ansible-galaxy login'
     '''
     self.remove_github_token()
     args = json.dumps({
         "scopes": ["public_repo"],
         "note": "ansible-galaxy login"
     })
     try:
         data = json.load(
             open_url(self.GITHUB_AUTH,
                      url_username=self.github_username,
                      url_password=self.github_password,
                      force_basic_auth=True,
                      data=args))
     except HTTPError as e:
         self.log.exception(e)
         res = json.load(e)
         raise exceptions.GalaxyClientError(res['message'])
     return data['token']
Example #8
0
    def __call_galaxy(self, url, args=None, headers=None, http_method=None):
        http_method = http_method or 'GET'
        headers = headers or {}
        request_id = uuid.uuid4().hex
        headers['X-Request-ID'] = request_id

        # The slug we use to identify a request by method, url and request id
        # For ex, '"GET https://galaxy.ansible.com/api/v1/repositories" c48937f4e8e849828772c4a0ce0fd5ed'
        request_slug = '"%s %s" %s' % (http_method, url, request_id)

        try:
            # log the http request_slug with request_id to the main log and
            # to the http log, both at INFO level for now.
            http_log.info('%s', request_slug)
            self.log.info('%s', request_slug)

            request_log.debug('%s args=%s', request_slug, args)
            request_log.debug('%s headers=%s', request_slug, headers)

            resp = open_url(url,
                            data=args,
                            validate_certs=self._validate_certs,
                            headers=headers,
                            method=http_method,
                            http_agent=self.user_agent,
                            timeout=20)

            response_log.info('%s http_status=%s', request_slug,
                              resp.getcode())

            final_url = resp.geturl()
            if final_url != url:
                request_log.debug('%s Redirected to: %s', request_slug,
                                  resp.geturl())

            resp_info = resp.info()
            response_log.debug('%s info:\n%s', request_slug, resp_info)

            # FIXME: making the request and loading the response should be sep try/except blocks
            response_body = to_text(resp.read(), errors='surrogate_or_strict')

            # debug log the raw response body
            response_log.debug('%s response body:\n%s', request_slug,
                               response_body)

            data = json.loads(response_body)

            # debug log a json version of the data that was created from the response
            response_log.debug('%s data:\n%s', request_slug,
                               json.dumps(data, indent=2))
        except HTTPError as http_exc:
            self.log.debug('Exception on %s', request_slug)
            self.log.exception("%s: %s", request_slug, http_exc)

            # FIXME: probably need a try/except here if the response body isnt json which
            #        can happen if a proxy mangles the response
            res = json.loads(
                to_text(http_exc.fp.read(), errors='surrogate_or_strict'))

            http_log.error('%s data from server error response:\n%s',
                           request_slug, res)

            try:
                error_msg = 'HTTP error on request %s: %s' % (request_slug,
                                                              res['detail'])
                raise exceptions.GalaxyClientError(error_msg)
            except (KeyError, TypeError) as detail_parse_exc:
                self.log.exception("%s: %s", request_slug, detail_parse_exc)
                self.log.warning(
                    'Unable to parse error detail from response for request: %s response:  %s',
                    request_slug, detail_parse_exc)

            # TODO: great place to be able to use 'raise from'
            # FIXME: this needs to be tweaked so the
            raise exceptions.GalaxyClientError(http_exc)
        except (ssl.SSLError, socket.error) as e:
            self.log.debug('Connection error to Galaxy API for request %s: %s',
                           request_slug, e)
            self.log.exception("%s: %s", request_slug, e)
            raise exceptions.GalaxyClientAPIConnectionError(
                'Connection error to Galaxy API for request %s: %s' %
                (request_slug, e))

        return data