Пример #1
0
    def _request(self, url, json_payload='{}', http_verb='GET', params=None):
        json_payload = json.dumps(json_payload)

        try:
            if http_verb == "PUT":
                req = self._session.put(
                    self._construct_url(url),
                    verify=self.verify_ssl,
                    headers=self._fetch_headers(),
                    timeout=self.request_timeout,
                    data=json_payload)
            elif http_verb == 'POST':
                req = self._session.post(
                    self._construct_url(url),
                    verify=self.verify_ssl,
                    headers=self._fetch_headers(),
                    timeout=self.request_timeout,
                    data=json_payload)
            elif http_verb == 'DELETE':
                # Need to follow up - if 'accept' is in the headers
                # delete calls are not working because ECS 2.0 is returning
                # XML even if JSON is specified
                headers = self._fetch_headers()
                del headers['Accept']

                req = self._session.delete(
                    self._construct_url(url),
                    verify=self.verify_ssl,
                    headers=headers,
                    timeout=self.request_timeout,
                    params=params)
            else:  # Default to GET
                req = self._session.get(
                    self._construct_url(url),
                    verify=self.verify_ssl,
                    headers=self._fetch_headers(),
                    timeout=self.request_timeout,
                    params=params)

            # Because some delete actions in the API return HTTP/1.1 204 No Content
            if not (200 <= req.status_code < 300):
                log.error("Status code NOT OK")
                raise ECSClientException.from_response(req)
            try:
                return req.json()
            except ValueError:
                return req.text

        except requests.ConnectionError as conn_err:
            msg = 'Connection error: {0}'.format(conn_err.args)
            log.error(msg)
            raise ECSClientException(message=msg)
        except requests.HTTPError as http_err:
            msg = 'HTTP error: {0}'.format(http_err.args)
            log.error(msg)
            raise ECSClientException(message=msg)
        except requests.RequestException as req_err:
            msg = 'Request error: {0}'.format(req_err.args)
            log.error(msg)
            raise ECSClientException(message=msg)
    def get_token(self):
        """
        Attempt to get an existing token, if successful then ensure it
        hasn't expired yet. If its expired, fetch a new token

        :return: A token
        """
        token = self._get_existing_token()

        if not token:
            log.debug("No Token found getting new one")
            return self.get_new_token()

        # FIXME: Avoid validation at every call
        log.debug("Validating token")
        req = self._request(token, self.token_verification_endpoint)

        if req.status_code == 200:
            log.debug("Token validated successfully")
            return token
        elif req.status_code in (401, 403, 415):
            msg = "Invalid token. Trying to get a new one (Code: {})".format(
                req.status_code)
            log.warning(msg)
            return self.get_new_token()
        else:  # i.e. 500 or unknown raise an exception
            msg = "Token validation error (Code: {})".format(req.status_code)
            log.error(msg)
            raise ECSClientException.from_response(req, message=msg)
    def get_new_token(self):
        """
        Request a new authentication token from ECS and persist it
        to a file for future usage if cache_token is true

        :return: Returns a valid token, or None if failed
        """
        log.info("Getting new token")
        self.session.auth = (self.username, self.password)

        req = self.session.get(self.token_endpoint,
                               verify=self.verify_ssl,
                               headers={'Accept': 'application/json'},
                               timeout=self.request_timeout)

        if req.status_code == 401:
            msg = 'Invalid username or password'
            log.fatal(msg)
            raise ECSClientException.from_response(req, message=msg)
        if req.status_code != 200:
            msg = 'Non-200 status returned ({0})'.format(req.status_code)
            log.fatal(msg)
            raise ECSClientException.from_response(req, message=msg)

        self.token = req.headers['x-sds-auth-token']

        if self.cache_token:
            log.debug("Caching token to '{0}'".format(self.token_path))

            token_dir = os.path.dirname(os.path.abspath(self.token_path))
            if not os.path.isdir(token_dir):
                raise ECSClientException('Token directory not found')

            with open(self.token_path, 'w') as token_file:
                token_file.write(self.token)

        return self.token
    def test_from_response(self):
        response_content = '{"code": "1000", "retryable": false, ' \
                           '"description": "Error description", ' \
                           '"details": "Error details"}'
        self.requests_mock.register_uri('POST', self.TEST_URL,
                                        status_code=500,
                                        text=response_content)
        resp = requests.post(self.TEST_URL, data='body')
        exc = ECSClientException.from_response(resp)

        self.assertEqual(exc.ecs_code, '1000')
        self.assertEqual(exc.ecs_retryable, False)
        self.assertEqual(exc.ecs_description, 'Error description')
        self.assertEqual(exc.ecs_details, 'Error details')
        self.assertEqual(exc.http_scheme, 'https')
        self.assertEqual(exc.http_host, '127.0.0.1')
        self.assertEqual(exc.http_port, 4443)
        self.assertEqual(exc.http_path, '/foor/bar')
        self.assertEqual(exc.http_query, 'param1=value1&param2=value2')
        self.assertEqual(exc.http_status, 500)
        self.assertEqual(exc.http_reason, None)
        self.assertEqual(exc.http_response_content, response_content)