Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ export SC_USERNAME=admin
export SC_PASSWORD=admin_pass
```

## Debugging

Requests sent to and responses received from HyperCore can be written to a file for debugging.
Environ variable `SC_DEBUG_LOG_TRAFFIC=1` should be set, and `q` python library needs to be installed.
The output is written to file `/tmp/q` on Ansible controller.

Note that `/tmp/q` will contain login passwords, HTTP session cookies and other sensitive data.
It should not be shared around.

# Integration tests configuration

For integration tests we need to configure access to test cluster.
Expand Down
56 changes: 56 additions & 0 deletions plugins/module_utils/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
__metaclass__ = type

import json
import os
import ssl
from typing import Any, Optional, Union
from io import BufferedReader
Expand All @@ -30,6 +31,20 @@
DEFAULT_HEADERS = dict(Accept="application/json")


def _str_to_bool(s: str) -> bool:
return s.lower() not in ["", "0", "false", "f", "no", "n"]


SC_DEBUG_LOG_TRAFFIC = _str_to_bool(os.environ.get("SC_DEBUG_LOG_TRAFFIC", "0"))
if SC_DEBUG_LOG_TRAFFIC:
try:
import q as q_log # type: ignore
except ImportError:
# a do-nothing replacement
def q_log(*args, **kwargs): # type: ignore
pass


class AuthMethod(str, enum.Enum):
local = "local"
oidc = "oidc"
Expand Down Expand Up @@ -134,6 +149,47 @@ def _request(
data: Optional[Union[dict[Any, Any], bytes, str, BufferedReader]] = None,
headers: Optional[dict[Any, Any]] = None,
timeout: Optional[float] = None,
) -> Response:
# _request() with debug logging
try:
if SC_DEBUG_LOG_TRAFFIC:
effective_timeout = timeout
if timeout is None:
# If timeout from request is not specifically provided, take it from the Client.
effective_timeout = self.timeout
request_in = dict(
method=method,
path=path,
data=data,
headers=headers,
timeout=effective_timeout,
)
resp = self._request_no_log(method, path, data, headers, timeout)
if SC_DEBUG_LOG_TRAFFIC:
request_out = dict(
status=resp.status,
data=resp.data,
headers=resp.headers,
)
q_log(request_in, request_out)
return resp
except Exception as ex:
if SC_DEBUG_LOG_TRAFFIC:
request_out = dict(
status=resp.status,
data=resp.data,
headers=resp.headers,
)
q_log(request_in, exception=ex)
raise

def _request_no_log(
self,
method: str,
path: str,
data: Optional[Union[dict[Any, Any], bytes, str, BufferedReader]] = None,
headers: Optional[dict[Any, Any]] = None,
timeout: Optional[float] = None,
) -> Response:
if timeout is None:
# If timeout from request is not specifically provided, take it from the Client.
Expand Down