Example #1
0
    def _request(  # noqa: C901
        self,
        method,
        endpoint,
        item=None,
        headers=None,
        params=None,
        data=None,
        timeout=None,
        response_required=False,
    ):
        """Run HTTP POST operation."""
        request = self._build_request(
            method=method,
            endpoint=endpoint,
            item=item,
            headers=None,
            params=params,
            data=data,
            timeout=timeout,
            response_required=response_required,
        )

        try:
            response = self._session.request(**request)

            if response.status_code not in range(200, 300):
                status = StatusCode(response.status_code)
                error = self._parse_response(response)
                raise self._exception(
                    f'{status.name.replace("_", " ")}: {error}',
                    level="danger") from None

        except httpx.HTTPError as http_err:
            raise self._exception(parse_exception(http_err),
                                  level="danger") from None

        return self._parse_response(response)
Example #2
0
    async def collect(self) -> Iterable:  # noqa: C901
        """Connect to a device running hyperglass-agent via HTTP."""
        log.debug("Query parameters: {}", self.query)

        client_params = {
            "headers": {
                "Content-Type": "application/json"
            },
            "timeout": params.request_timeout,
        }
        if self.device.ssl is not None and self.device.ssl.enable:
            with self.device.ssl.cert.open("r") as file:
                cert = file.read()
                if not cert:
                    raise RestError(
                        "SSL Certificate for device {d} has not been imported",
                        level="danger",
                        d=self.device.display_name,
                    )
            http_protocol = "https"
            client_params.update({"verify": str(self.device.ssl.cert)})
            log.debug(
                (f"Using {str(self.device.ssl.cert)} to validate connection "
                 f"to {self.device.name}"))
        else:
            http_protocol = "http"
        endpoint = "{protocol}://{address}:{port}/query/".format(
            protocol=http_protocol,
            address=self.device._target,
            port=self.device.port)

        log.debug("URL endpoint: {}", endpoint)

        try:
            async with httpx.AsyncClient(**client_params) as http_client:
                responses = ()

                for query in self.query:
                    encoded_query = await jwt_encode(
                        payload=query,
                        secret=self.device.credential.password.
                        get_secret_value(),
                        duration=params.request_timeout,
                    )
                    log.debug("Encoded JWT: {}", encoded_query)

                    raw_response = await http_client.post(
                        endpoint, json={"encoded": encoded_query})
                    log.debug("HTTP status code: {}", raw_response.status_code)

                    raw = raw_response.text
                    log.debug("Raw Response:\n{}", raw)

                    if raw_response.status_code == 200:
                        decoded = await jwt_decode(
                            payload=raw_response.json()["encoded"],
                            secret=self.device.credential.password.
                            get_secret_value(),
                        )
                        log.debug("Decoded Response:\n{}", decoded)
                        responses += (decoded, )

                    elif raw_response.status_code == 204:
                        raise ResponseEmpty(
                            params.messages.no_output,
                            device_name=self.device.display_name,
                        )

                    else:
                        log.error(raw_response.text)

        except httpx.exceptions.HTTPError as rest_error:
            msg = parse_exception(rest_error)
            log.error("Error connecting to device {}: {}", self.device.name,
                      msg)
            raise RestError(
                params.messages.connection_error,
                device_name=self.device.display_name,
                error=msg,
            )
        except OSError as ose:
            log.critical(str(ose))
            raise RestError(
                params.messages.connection_error,
                device_name=self.device.display_name,
                error="System error",
            )
        except CertificateError as cert_error:
            log.critical(str(cert_error))
            msg = parse_exception(cert_error)
            raise RestError(
                params.messages.connection_error,
                device_name=self.device.display_name,
                error=f"{msg}: {cert_error}",
            )

        if raw_response.status_code != 200:
            log.error("Response code is {}", raw_response.status_code)
            raise RestError(
                params.messages.connection_error,
                device_name=self.device.display_name,
                error=params.messages.general,
            )

        if not responses:
            log.error("No response from device {}", self.device.name)
            raise RestError(
                params.messages.connection_error,
                device_name=self.device.display_name,
                error=params.messages.no_response,
            )

        return responses