Example #1
0
    def check_for_cosmos_error(*args, **kwargs):
        """Returns response from cosmos or raises exception

        :returns: Response or raises Exception
        :rtype: requests.Response
        """
        error_media_type = 'application/vnd.dcos.package.error+json;' \
                           'charset=utf-8;version=v1'
        response = fn(*args, **kwargs)
        content_type = response.headers.get('Content-Type')
        if content_type is None:
            raise DCOSHTTPException(response)
        elif error_media_type in content_type:
            logger.debug("Error: {}".format(response.json()))
            error_msg = _format_error_message(response.json())
            raise DCOSException(error_msg)
        return response
Example #2
0
def _fetch_metrics_datapoints(url):
    """Retrieve the metrics data from any `dcos-metrics` endpoint.

    :param url: `dcos-metrics` endpoint
    :type url: str
    :returns: List of metrics datapoints
    :rtype: [dict]
    """
    with contextlib.closing(http.get(url)) as r:

        if r.status_code == 204:
            return []

        if r.status_code != 200:
            raise DCOSHTTPException(r)

        return r.json().get('datapoints', [])
Example #3
0
        def check_for_cosmos_error(*args, **kwargs):
            """Returns response from cosmos or raises exception

            :param response: response from cosmos
            :type response: Response
            :returns: Response or raises Exception
            :rtype: valid response
            """

            response = fn(*args, **kwargs)
            content_type = response.headers.get('Content-Type')
            if content_type is None:
                raise DCOSHTTPException(response)
            elif _get_header("error") in content_type:
                error_msg = _format_error_message(response.json())
                raise DCOSException(error_msg)
            return response
Example #4
0
    def test_dcos_error(self):
        mock_response = MagicMock(**{
            'status_code': 500,
            'url': 'dummy',
            'reason': 'test',
        })
        mock_get = MagicMock(side_effect=DCOSHTTPException(mock_response))

        input_args = MagicMock(**self.args)

        with patch('conductr_cli.conduct_request.get', mock_get):
            self.assertRaises(DCOSHTTPException, license.get_license,
                              input_args)

        mock_get.assert_called_once_with(False,
                                         '10.0.0.1',
                                         'https://10.0.0.1:9005/v2/license',
                                         auth=self.auth)
Example #5
0
    def test_dcos_error_endpoint_not_supported(self):
        mock_response = MagicMock(**{
            'status_code': 503,
            'url': 'dummy',
            'reason': 'test',
        })
        mock_get = MagicMock(side_effect=DCOSHTTPException(mock_response))

        input_args = MagicMock(**self.args)

        with patch('conductr_cli.conduct_request.get', mock_get):
            is_license_success, license_result = license.get_license(
                input_args)
            self.assertFalse(is_license_success)
            self.assertIsNone(license_result)

        mock_get.assert_called_once_with(False,
                                         '10.0.0.1',
                                         'https://10.0.0.1:9005/v2/license',
                                         auth=self.auth)
Example #6
0
def _get_resource(resource):
    """
    :param resource: optional filename or http(s) url
    for the application or group resource
    :type resource: str
    :returns: resource
    :rtype: dict
    """
    if resource is not None:
        if os.path.isfile(resource):
            with util.open_file(resource) as resource_file:
                return util.load_json(resource_file)
        else:
            try:
                http.silence_requests_warnings()
                req = http.get(resource)
                if req.status_code == 200:
                    data = b''
                    for chunk in req.iter_content(1024):
                        data += chunk
                    return util.load_jsons(data.decode('utf-8'))
                else:
                    raise DCOSHTTPException("HTTP error code: {}"
                                            .format(req.status_code))
            except Exception:
                logger.exception('Cannot read from resource %s', resource)
                raise DCOSException(
                    "Can't read from resource: {0}.\n"
                    "Please check that it exists.".format(resource))

    # Check that stdin is not tty
    if sys.stdin.isatty():
        # We don't support TTY right now. In the future we will start an
        # editor
        raise DCOSException(
            "We currently don't support reading from the TTY. Please "
            "specify an application JSON.\n"
            "E.g.: dcos job add < app_resource.json")

    return util.load_json(sys.stdin)
Example #7
0
    def test_case(head_fn, status_code):
        request = requests.Request(method='ANY', url='http://arbitrary/url')
        mock_response = mock.create_autospec(requests.Response)
        mock_response.status_code = status_code
        mock_response.reason = 'Arbitrary Reason'
        mock_response.request = request
        mock_response.json.side_effect = ValueError('empty body')
        head_fn.side_effect = DCOSHTTPException(mock_response)

        rpc_client = marathon.RpcClient('http://does/not/matter')
        marathon_client = marathon.Client(rpc_client)

        with pytest.raises(DCOSException) as exception_info:
            marathon_client.pod_feature_supported()

        message = marathon.RpcClient.response_error_message(
            status_code,
            reason='Arbitrary Reason',
            request_method='ANY',
            request_url='http://arbitrary/url',
            json_body=None)
        assert str(exception_info.value).endswith(message)
Example #8
0
def request(method,
            url,
            is_success=_default_is_success,
            timeout=DEFAULT_TIMEOUT,
            verify=None,
            toml_config=None,
            **kwargs):
    """Sends an HTTP request. If the server responds with a 401, ask the
    user for their credentials, and try request again (up to 3 times).

    :param method: method for the new Request object
    :type method: str
    :param url: URL for the new Request object
    :type url: str
    :param is_success: Defines successful status codes for the request
    :type is_success: Function from int to bool
    :param timeout: request timeout
    :type timeout: int
    :param verify: whether to verify SSL certs or path to cert(s)
    :type verify: bool | str
    :param toml_config: cluster config to use
    :type toml_config: Toml
    :param kwargs: Additional arguments to requests.request
        (see http://docs.python-requests.org/en/latest/api/#requests.request)
    :type kwargs: dict
    :rtype: Response
    """

    if toml_config is None:
        toml_config = config.get_config()

    auth_token = config.get_config_val("core.dcos_acs_token", toml_config)
    prompt_login = config.get_config_val("core.prompt_login", toml_config)
    dcos_url = urlparse(config.get_config_val("core.dcos_url", toml_config))

    # only request with DC/OS Auth if request is to DC/OS cluster
    if auth_token and _is_request_to_dcos(url):
        auth = DCOSAcsAuth(auth_token)
    else:
        auth = None

    response = _request(method,
                        url,
                        is_success,
                        timeout,
                        auth=auth,
                        verify=verify,
                        toml_config=toml_config,
                        **kwargs)

    if is_success(response.status_code):
        return response
    elif response.status_code == 401:
        if prompt_login:
            # I don't like having imports that aren't at the top level, but
            # this is to resolve a circular import issue between dcos.http and
            # dcos.auth
            from dcos.auth import header_challenge_auth

            header_challenge_auth(dcos_url.geturl())
            # if header_challenge_auth succeeded, then we auth-ed correctly and
            # thus can safely recursively call ourselves and not have to worry
            # about an infinite loop
            return request(method=method,
                           url=url,
                           is_success=is_success,
                           timeout=timeout,
                           verify=verify,
                           **kwargs)
        else:
            if auth_token is not None:
                msg = ("Your core.dcos_acs_token is invalid. "
                       "Please run: `dcos auth login`")
                raise DCOSAuthenticationException(response, msg)
            else:
                raise DCOSAuthenticationException(response)
    elif response.status_code == 422:
        raise DCOSUnprocessableException(response)
    elif response.status_code == 403:
        raise DCOSAuthorizationException(response)
    elif response.status_code == 400:
        raise DCOSBadRequest(response)
    else:
        raise DCOSHTTPException(response)
Example #9
0
 def method_fn(*args, **kwargs):
     raise DCOSHTTPException(response)
Example #10
0
def request(method,
            url,
            is_success=_default_is_success,
            timeout=None,
            verify=None,
            **kwargs):
    """Sends an HTTP request. We first send a HEAD request for the
    supplied URL so that we can determine the type of authentication
    required (if any). If authentication is required then we again
    use a HEAD request asking the user for their credentials, and
    try request again (up to 3 times). Once authenticated, we issue
    the request passed in. We are careful to execute the request
    passed in just once given that it may be stateful e.g. any files
    object containing a stream may only be evaluated once.

    :param method: method for the new Request object
    :type method: str
    :param url: URL for the new Request object
    :type url: str
    :param is_success: Defines successful status codes for the request
    :type is_success: Function from int to bool
    :param timeout: request timeout
    :type timeout: int
    :param verify: whether to verify SSL certs or path to cert(s)
    :type verify: bool | str
    :param kwargs: Additional arguments to requests.request
        (see http://docs.python-requests.org/en/latest/api/#requests.request)
    :type kwargs: dict
    :rtype: Response
    """

    if 'headers' not in kwargs:
        kwargs['headers'] = {'Accept': 'application/json'}

    verify = _verify_ssl(verify)

    # Silence 'Unverified HTTPS request' and 'SecurityWarning' for bad certs
    if verify is not None:
        silence_requests_warnings()

    response = _request('head', url, is_success, timeout, verify=verify)
    i = 0
    while i < 3 and response.status_code == 401:
        auth_response = _request_with_auth(response,
                                           'head',
                                           url,
                                           is_success,
                                           timeout,
                                           verify=verify)
        response.status_code = auth_response.status_code
        i += 1

    if response.status_code == 401:
        raise DCOSAuthenticationException(response)

    response = _request_with_auth(response, method, url, is_success, timeout,
                                  verify, **kwargs)

    if is_success(response.status_code):
        return response
    elif response.status_code == 403:
        raise DCOSAuthorizationException(response)
    elif response.status_code == 400:
        raise DCOSBadRequest(response)
    else:
        raise DCOSHTTPException(response)