Beispiel #1
0
def check_kibana_adminrouter_integration(path: str) -> bool:
    curl_cmd = 'curl -L -I -k -H "Authorization: token={}" -s -X GET {}/{}'.format(
        sdk_utils.dcos_token(),
        sdk_utils.dcos_url().rstrip("/"), path.lstrip("/"))
    rc, stdout, _ = sdk_cmd.master_ssh(curl_cmd)
    return bool(rc == 0 and stdout and "HTTP/1.1 200" in stdout)
Beispiel #2
0
def cluster_request(
    method: str,
    cluster_path: str,
    retry: bool = True,
    raise_on_error: bool = True,
    log_args: bool = True,
    log_response: bool = False,
    timeout_seconds: int = 60,
    **kwargs: Any,
) -> requests.Response:
    """Queries the provided cluster HTTP path using the provided method, with the following handy features:
    - The DCOS cluster's URL is automatically applied to the provided path.
    - Auth headers are automatically added.
    - If the response code is >= 400, optionally retries and / or raises a `requests.exceptions.HTTPError`.

    : param method: Method to use for the query, such as `GET`, `POST`, `DELETE`, or `PUT`.
    : param cluster_path: HTTP path to be queried on the cluster, e.g. `/ marathon / v2 / apps`. Leading slash is optional.
    : param retry: Whether to retry the request automatically if an HTTP error (>= 400) is returned.
    : param raise_on_error: Whether to raise a `requests.exceptions.HTTPError` if the response code is >= 400.
                           Disabling this effectively implies `retry = False` where HTTP status is concerned.
    : param log_args: Whether to log the contents of `kwargs`. Can be disabled to reduce noise.
    : param log_response: Whether to always log the response content.
                          Otherwise responses are only logged if the response code is >= 400.
    : param kwargs: Additional arguments to requests.request(), such as `json = {"example": "content"}`
                   or `params = {"example": "param"}`.
    : rtype: requests.Response
    """

    url = urllib.parse.urljoin(sdk_utils.dcos_url(), cluster_path)
    # consistently include slash prefix for clearer logging below
    cluster_path = "/" + cluster_path.lstrip("/")

    # Wrap token in callback for requests library to invoke:
    class AuthHeader(requests.auth.AuthBase):
        def __init__(self, token: str) -> None:
            self._token = token

        def __call__(self, r: requests.Request) -> requests.Request:
            r.headers["Authorization"] = "token={}".format(self._token)
            return r

    auth = AuthHeader(sdk_utils.dcos_token())

    def _cluster_request() -> requests.Response:
        start = time.time()

        # check if we have verify key already exists.
        if kwargs is not None and kwargs.get("verify") is not None:
            kwargs["verify"] = False
            response = requests.request(method, url, auth=auth, timeout=timeout_seconds, **kwargs)
        else:
            response = requests.request(
                method, url, auth=auth, verify=False, timeout=timeout_seconds, **kwargs
            )

        end = time.time()

        log_msg = "(HTTP {}) {}".format(method.upper(), cluster_path)
        if kwargs:
            # log arg content (or just arg names, with hack to avoid 'dict_keys([...])') if present
            log_msg += " (args: {})".format(kwargs if log_args else [e for e in kwargs.keys()])
        log_msg += " => {} ({})".format(
            response.status_code, sdk_utils.pretty_duration(end - start)
        )
        log.info(log_msg)

        if log_response or not response.ok:
            # Response logging enabled, or query failed (>= 400). Before (potentially) throwing,
            # print response payload which may include additional error details.
            response_text = response.text
            if response_text:
                log.info(
                    "Response content ({} bytes):\n{}".format(len(response_text), response_text)
                )
            else:
                log.info("No response content")
        if raise_on_error:
            response.raise_for_status()
        return response

    if retry:
        # Use wrapper to implement retry:
        @retrying.retry(wait_fixed=1000, stop_max_delay=timeout_seconds * 1000)
        def retry_fn() -> requests.Response:
            return _cluster_request()

        response = retry_fn()
        assert isinstance(response, requests.Response)
        return response
    else:
        # No retry, invoke directly:
        return _cluster_request()
Beispiel #3
0
def check_kibana_adminrouter_integration(path: str) -> bool:
    curl_cmd = 'curl -L -I -k -H "Authorization: token={}" -s {}/{}'.format(
        sdk_utils.dcos_token(), sdk_utils.dcos_url().rstrip("/"), path.lstrip("/")
    )
    rc, stdout, _ = sdk_cmd.master_ssh(curl_cmd)
    return bool(rc == 0 and stdout and "HTTP/1.1 200" in stdout)
Beispiel #4
0
def cluster_request(
    method: str,
    cluster_path: str,
    retry: bool = True,
    raise_on_error: bool = True,
    log_args: bool = True,
    log_response: bool = False,
    timeout_seconds: int = 60,
    **kwargs: Any,
) -> requests.Response:
    """Queries the provided cluster HTTP path using the provided method, with the following handy features:
    - The DCOS cluster's URL is automatically applied to the provided path.
    - Auth headers are automatically added.
    - If the response code is >= 400, optionally retries and / or raises a `requests.exceptions.HTTPError`.

    : param method: Method to use for the query, such as `GET`, `POST`, `DELETE`, or `PUT`.
    : param cluster_path: HTTP path to be queried on the cluster, e.g. `/ marathon / v2 / apps`. Leading slash is optional.
    : param retry: Whether to retry the request automatically if an HTTP error (>= 400) is returned.
    : param raise_on_error: Whether to raise a `requests.exceptions.HTTPError` if the response code is >= 400.
                           Disabling this effectively implies `retry = False` where HTTP status is concerned.
    : param log_args: Whether to log the contents of `kwargs`. Can be disabled to reduce noise.
    : param log_response: Whether to always log the response content.
                          Otherwise responses are only logged if the response code is >= 400.
    : param kwargs: Additional arguments to requests.request(), such as `json = {"example": "content"}`
                   or `params = {"example": "param"}`.
    : rtype: requests.Response
    """

    url = urllib.parse.urljoin(sdk_utils.dcos_url(), cluster_path)
    # consistently include slash prefix for clearer logging below
    cluster_path = "/" + cluster_path.lstrip("/")

    # Wrap token in callback for requests library to invoke:
    class AuthHeader(requests.auth.AuthBase):
        def __init__(self, token: str) -> None:
            self._token = token

        def __call__(self, r: requests.Request) -> requests.Request:
            r.headers["Authorization"] = "token={}".format(self._token)
            return r

    auth = AuthHeader(sdk_utils.dcos_token())

    def _cluster_request() -> requests.Response:
        start = time.time()

        # check if we have verify key already exists.
        if kwargs is not None and kwargs.get("verify") is not None:
            kwargs["verify"] = False
            response = requests.request(method,
                                        url,
                                        auth=auth,
                                        timeout=timeout_seconds,
                                        **kwargs)
        else:
            response = requests.request(method,
                                        url,
                                        auth=auth,
                                        verify=False,
                                        timeout=timeout_seconds,
                                        **kwargs)

        end = time.time()

        log_msg = "(HTTP {}) {}".format(method.upper(), cluster_path)
        if kwargs:
            # log arg content (or just arg names, with hack to avoid 'dict_keys([...])') if present
            log_msg += " (args: {})".format(
                kwargs if log_args else [e for e in kwargs.keys()])
        log_msg += " => {} ({})".format(response.status_code,
                                        sdk_utils.pretty_duration(end - start))
        log.info(log_msg)

        if log_response or not response.ok:
            # Response logging enabled, or query failed (>= 400). Before (potentially) throwing,
            # print response payload which may include additional error details.
            response_text = response.text
            if response_text:
                log.info("Response content ({} bytes):\n{}".format(
                    len(response_text), response_text))
            else:
                log.info("No response content")
        if raise_on_error:
            response.raise_for_status()
        return response

    if retry:
        # Use wrapper to implement retry:
        @retrying.retry(wait_fixed=1000, stop_max_delay=timeout_seconds * 1000)
        def retry_fn() -> requests.Response:
            return _cluster_request()

        response = retry_fn()
        assert isinstance(response, requests.Response)
        return response
    else:
        # No retry, invoke directly:
        return _cluster_request()