diff --git a/README.md b/README.md index cdf7e42..b5cf0eb 100644 --- a/README.md +++ b/README.md @@ -53,19 +53,24 @@ pyninja start > _By default, `PyNinja` will look for a `.env` file in the current working directory._ +- **APIKEY** - API Key for authentication. - **NINJA_HOST** - Hostname for the API server. - **NINJA_PORT** - Port number for the API server. -- **WORKERS** - Number of workers for the uvicorn server. - **REMOTE_EXECUTION** - Boolean flag to enable remote execution. - **API_SECRET** - Secret access key for running commands on server remotely. - **MONITOR_USERNAME** - Username to authenticate the monitoring page. - **MONITOR_PASSWORD** - Password to authenticate the monitoring page. - **MONITOR_SESSION** - Session timeout for the monitoring page. - **MAX_CONNECTIONS** - Maximum number of monitoring sessions allowed in parallel. -- **SERVICE_MANAGER** - Service manager filepath to handle the service status requests. +- **PROCESSES** - List of process names to include in the monitor page. +- **SERVICES** - List of service names to include in the monitor page. +- **GPU_LIB** - GPU library filepath to use for monitoring. +- **DISK_LIB** - Disk library filepath to use for monitoring. +- **SERVICE_LIB** - Memory library filepath to use for monitoring. +- **PROCESSOR_LIB** - Processor library filepath to use for monitoring. - **DATABASE** - FilePath to store the auth database that handles the authentication errors. - **RATE_LIMIT** - List of dictionaries with `max_requests` and `seconds` to apply as rate limit. -- **APIKEY** - API Key for authentication. +- **LOG_CONFIG** - Logging configuration file path. ⚠️ Enabling remote execution can be extremely risky and a major security threat. So use **caution** and set the **API_SECRET** to a strong value. diff --git a/docs/README.html b/docs/README.html index fc0d025..c77ad6e 100644 --- a/docs/README.html +++ b/docs/README.html @@ -90,19 +90,24 @@

Environment Variables

By default, PyNinja will look for a .env file in the current working directory.

⚠️ Enabling remote execution can be extremely risky and a major security threat. So use caution and set the API_SECRET to a strong value.

diff --git a/docs/README.md b/docs/README.md index cdf7e42..b5cf0eb 100644 --- a/docs/README.md +++ b/docs/README.md @@ -53,19 +53,24 @@ pyninja start > _By default, `PyNinja` will look for a `.env` file in the current working directory._ +- **APIKEY** - API Key for authentication. - **NINJA_HOST** - Hostname for the API server. - **NINJA_PORT** - Port number for the API server. -- **WORKERS** - Number of workers for the uvicorn server. - **REMOTE_EXECUTION** - Boolean flag to enable remote execution. - **API_SECRET** - Secret access key for running commands on server remotely. - **MONITOR_USERNAME** - Username to authenticate the monitoring page. - **MONITOR_PASSWORD** - Password to authenticate the monitoring page. - **MONITOR_SESSION** - Session timeout for the monitoring page. - **MAX_CONNECTIONS** - Maximum number of monitoring sessions allowed in parallel. -- **SERVICE_MANAGER** - Service manager filepath to handle the service status requests. +- **PROCESSES** - List of process names to include in the monitor page. +- **SERVICES** - List of service names to include in the monitor page. +- **GPU_LIB** - GPU library filepath to use for monitoring. +- **DISK_LIB** - Disk library filepath to use for monitoring. +- **SERVICE_LIB** - Memory library filepath to use for monitoring. +- **PROCESSOR_LIB** - Processor library filepath to use for monitoring. - **DATABASE** - FilePath to store the auth database that handles the authentication errors. - **RATE_LIMIT** - List of dictionaries with `max_requests` and `seconds` to apply as rate limit. -- **APIKEY** - API Key for authentication. +- **LOG_CONFIG** - Logging configuration file path. ⚠️ Enabling remote execution can be extremely risky and a major security threat. So use **caution** and set the **API_SECRET** to a strong value. diff --git a/docs/_sources/README.md.txt b/docs/_sources/README.md.txt index cdf7e42..b5cf0eb 100644 --- a/docs/_sources/README.md.txt +++ b/docs/_sources/README.md.txt @@ -53,19 +53,24 @@ pyninja start > _By default, `PyNinja` will look for a `.env` file in the current working directory._ +- **APIKEY** - API Key for authentication. - **NINJA_HOST** - Hostname for the API server. - **NINJA_PORT** - Port number for the API server. -- **WORKERS** - Number of workers for the uvicorn server. - **REMOTE_EXECUTION** - Boolean flag to enable remote execution. - **API_SECRET** - Secret access key for running commands on server remotely. - **MONITOR_USERNAME** - Username to authenticate the monitoring page. - **MONITOR_PASSWORD** - Password to authenticate the monitoring page. - **MONITOR_SESSION** - Session timeout for the monitoring page. - **MAX_CONNECTIONS** - Maximum number of monitoring sessions allowed in parallel. -- **SERVICE_MANAGER** - Service manager filepath to handle the service status requests. +- **PROCESSES** - List of process names to include in the monitor page. +- **SERVICES** - List of service names to include in the monitor page. +- **GPU_LIB** - GPU library filepath to use for monitoring. +- **DISK_LIB** - Disk library filepath to use for monitoring. +- **SERVICE_LIB** - Memory library filepath to use for monitoring. +- **PROCESSOR_LIB** - Processor library filepath to use for monitoring. - **DATABASE** - FilePath to store the auth database that handles the authentication errors. - **RATE_LIMIT** - List of dictionaries with `max_requests` and `seconds` to apply as rate limit. -- **APIKEY** - API Key for authentication. +- **LOG_CONFIG** - Logging configuration file path. ⚠️ Enabling remote execution can be extremely risky and a major security threat. So use **caution** and set the **API_SECRET** to a strong value. diff --git a/docs/genindex.html b/docs/genindex.html index 475c246..6b948eb 100644 --- a/docs/genindex.html +++ b/docs/genindex.html @@ -376,6 +376,8 @@

L

M

    +
  • map_docker_stats() (in module pyninja.monitor.resources) +
  • max_connections (pyninja.models.EnvConfig attribute)
  • max_requests (pyninja.models.RateLimit attribute) diff --git a/docs/index.html b/docs/index.html index 887311a..1e6e226 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1884,6 +1884,23 @@

    Authenticator

    Resources

    +
    +
    +pyninja.monitor.resources.map_docker_stats(json_data: Dict[str, str]) Dict[str, str]
    +

    Map the JSON data to a dictionary.

    +
    +
    Parameters:
    +

    json_data – JSON data from the docker stats command.

    +
    +
    Returns:
    +

    Returns a dictionary with container stats.

    +
    +
    Return type:
    +

    Dict[str, str]

    +
    +
    +
    +
    pyninja.monitor.resources.get_cpu_percent(cpu_interval: int) List[float]
    diff --git a/docs/objects.inv b/docs/objects.inv index 0922060..50d67fc 100644 Binary files a/docs/objects.inv and b/docs/objects.inv differ diff --git a/docs/searchindex.js b/docs/searchindex.js index f87004d..152df98 100644 --- a/docs/searchindex.js +++ b/docs/searchindex.js @@ -1 +1 @@ -Search.setIndex({"docnames": ["README", "index"], "filenames": ["README.md", "index.rst"], "titles": ["PyNinja", "Welcome to PyNinja\u2019s documentation!"], "terms": {"lightweight": 0, "o": [0, 1], "agnost": 0, "servic": 0, "monitor": 0, "api": [0, 1], "platform": 0, "support": [0, 1], "deploy": 0, "recommend": 0, "instal": [0, 1], "python": 0, "3": [0, 1], "10": [0, 1], "11": [0, 1], "us": [0, 1], "dedic": [0, 1], "virtual": [0, 1], "m": 0, "pip": 0, "initi": 0, "id": [0, 1], "import": 0, "__name__": 0, "__main__": 0, "start": [0, 1], "cli": 0, "help": 0, "usag": [0, 1], "instruct": 0, "sourc": 0, "from": [0, 1], "an": [0, 1], "env": [0, 1], "file": [0, 1], "By": 0, "default": [0, 1], "look": 0, "current": [0, 1], "work": [0, 1], "directori": 0, "ninja": 0, "_": 0, "host": [0, 1], "hostnam": [0, 1], "server": [0, 1], "port": [0, 1], "number": [0, 1], "worker": 0, "uvicorn": [0, 1], "remot": [0, 1], "execut": [0, 1], "boolean": [0, 1], "flag": [0, 1], "enabl": [0, 1], "secret": [0, 1], "access": [0, 1], "kei": [0, 1], "run": [0, 1], "command": [0, 1], "usernam": [0, 1], "authent": 0, "page": [0, 1], "password": [0, 1], "session": [0, 1], "timeout": [0, 1], "max": [0, 1], "connect": [0, 1], "maximum": [0, 1], "allow": [0, 1], "parallel": 0, "manag": [0, 1], "filepath": [0, 1], "handl": [0, 1], "statu": [0, 1], "request": [0, 1], "databas": 0, "store": [0, 1], "auth": [0, 1], "error": [0, 1], "rate": [0, 1], "limit": [0, 1], "list": [0, 1], "dictionari": [0, 1], "max_request": [0, 1], "second": [0, 1], "appli": [0, 1], "apikei": [0, 1], "can": [0, 1], "extrem": 0, "riski": 0, "major": 0, "secur": 0, "threat": 0, "so": [0, 1], "caution": 0, "set": [0, 1], "strong": [0, 1], "valu": [0, 1], "refer": [0, 1], "sampl": 0, "exampl": [0, 1], "docstr": 0, "format": [0, 1], "googl": 0, "style": 0, "convent": 0, "pep": 0, "8": 0, "isort": 0, "requir": [0, 1], "gitvers": 0, "revers": 0, "f": 0, "release_not": 0, "rst": 0, "t": [0, 1], "pre": 0, "commit": 0, "ensur": 0, "pytest": 0, "gener": [0, 1], "valid": [0, 1], "hyperlink": 0, "all": [0, 1], "markdown": 0, "includ": [0, 1], "wiki": 0, "sphinx": 0, "5": [0, 1], "1": [0, 1], "recommonmark": 0, "http": [0, 1], "org": 0, "project": 0, "thevickypedia": 0, "github": 0, "io": 0, "vignesh": 0, "rao": 0, "under": 0, "mit": 0, "kick": 1, "off": 1, "environ": 1, "variabl": 1, "code": 1, "standard": 1, "releas": 1, "note": 1, "lint": 1, "pypi": 1, "packag": 1, "runbook": 1, "licens": 1, "copyright": 1, "get_desc": 1, "remote_flag": 1, "bool": 1, "monitor_flag": 1, "str": 1, "construct": 1, "detail": 1, "descript": 1, "doc": 1, "paramet": 1, "state": 1, "return": 1, "string": 1, "type": 1, "async": 1, "redirect_exception_handl": 1, "redirectexcept": 1, "jsonrespons": 1, "custom": 1, "handler": 1, "redirect": 1, "take": 1, "object": 1, "argument": 1, "inherit": 1, "cooki": 1, "kwarg": 1, "none": 1, "starter": 1, "function": 1, "which": 1, "trigger": 1, "keyword": 1, "env_fil": 1, "load": 1, "ninja_host": 1, "ninja_port": 1, "remote_execut": 1, "api_secret": 1, "monitor_usernam": 1, "monitor_password": 1, "monitor_sess": 1, "service_manag": 1, "rate_limit": 1, "log_config": 1, "log": 1, "dict": 1, "yaml": 1, "yml": 1, "json": 1, "ini": 1, "epoch": 1, "forbidden": 1, "i": 1, "part": 1, "fastapi": 1, "rais": 1, "apirespons": 1, "403": 1, "If": 1, "address": 1, "level_1": 1, "httpauthorizationcredenti": 1, "httpbearer": 1, "author": 1, "header": 1, "token": 1, "basic": 1, "401": 1, "invalid": 1, "level_2": 1, "addition": 1, "addit": 1, "critic": 1, "increment": 1, "attempt": 1, "int": 1, "block": 1, "time": 1, "base": 1, "fail": 1, "login": 1, "appropri": 1, "minut": 1, "handle_auth_error": 1, "filebrows": 1, "The": 1, "incom": 1, "get_ip_address": 1, "public": 1, "fals": 1, "depend": 1, "get": 1, "local": 1, "ip": 1, "devic": 1, "arg": 1, "httpstatu": 1, "privat": 1, "respons": 1, "get_cpu_util": 1, "interv": 1, "float": 1, "2": 1, "per_cpu": 1, "true": 1, "cpu": 1, "util": 1, "each": 1, "get_memory_util": 1, "memori": 1, "get_cpu_load_avg": 1, "system": 1, "queue": 1, "averag": 1, "over": 1, "last": 1, "15": 1, "respect": 1, "get_disk_util": 1, "disk": 1, "get_all_disk": 1, "attach": 1, "run_command": 1, "payload": 1, "option": 1, "machin": 1, "receiv": 1, "bodi": 1, "get_process_statu": 1, "process_nam": 1, "cpu_interv": 1, "union": 1, "name": 1, "check": 1, "get_service_statu": 1, "service_nam": 1, "get_docker_contain": 1, "container_nam": 1, "get_al": 1, "get_run": 1, "contain": 1, "inform": 1, "get_docker_imag": 1, "imag": 1, "get_docker_volum": 1, "volum": 1, "get_docker_stat": 1, "stat": 1, "get_processor_nam": 1, "redirectrespons": 1, "user": 1, "health": 1, "200": 1, "get_all_rout": 1, "apirout": 1, "ad": 1, "get_container_statu": 1, "get_running_contain": 1, "yield": 1, "correspond": 1, "metric": 1, "get_all_contain": 1, "get_all_imag": 1, "get_all_volum": 1, "_darwin": 1, "lib_path": 1, "vendor": 1, "linux": 1, "librari": 1, "path": 1, "_linux": 1, "_window": 1, "window": 1, "get_nam": 1, "perform": 1, "report": 1, "given": 1, "get_perform": 1, "thread": 1, "open": 1, "pair": 1, "servicestatu": 1, "stop": 1, "501": 1, "unknown": 1, "503": 1, "unavail": 1, "404": 1, "instanc": 1, "get_process_info": 1, "proc": 1, "psutil": 1, "statist": 1, "process_monitor": 1, "executor": 1, "threadpoolexecutor": 1, "case": 1, "sensit": 1, "maco": 1, "top": 1, "grep": 1, "task": 1, "service_monitor": 1, "ar": 1, "follow": 1, "right": 1, "launchctl": 1, "systemctl": 1, "show": 1, "properti": 1, "mainpid": 1, "sc": 1, "queri": 1, "get_service_pid": 1, "retriev": 1, "pid": 1, "get_service_pid_linux": 1, "get_service_pid_maco": 1, "get_service_pid_window": 1, "get_record": 1, "particular": 1, "until": 1, "when": 1, "should": 1, "put_record": 1, "block_until": 1, "insert": 1, "remove_record": 1, "delet": 1, "record": 1, "relat": 1, "class": 1, "rp": 1, "implement": 1, "init": 1, "call": 1, "exce": 1, "identifi": 1, "429": 1, "too": 1, "mani": 1, "status_cod": 1, "ani": 1, "httpexcept": 1, "wrap": 1, "unsupportedo": 1, "unsupport": 1, "locat": 1, "within": 1, "sinc": 1, "doesn": 1, "html": 1, "demand": 1, "where": 1, "solut": 1, "There": 1, "altern": 1, "our": 1, "javascript": 1, "thi": 1, "wai": 1, "come": 1, "handi": 1, "unexpect": 1, "scenario": 1, "tiangolo": 1, "com": 1, "tutori": 1, "sessionerror": 1, "raise_os_error": 1, "operating_system": 1, "noreturn": 1, "validationerror": 1, "overridden": 1, "pydant": 1, "basemodel": 1, "input": 1, "data": 1, "disklib": 1, "darwin": 1, "servicelib": 1, "processorlib": 1, "processor": 1, "auth_count": 1, "forbid": 1, "info": 1, "allowed_origin": 1, "envconfig": 1, "max_connect": 1, "gpu_lib": 1, "disk_lib": 1, "service_lib": 1, "processor_lib": 1, "classmethod": 1, "parse_api_secret": 1, "pars": 1, "complex": 1, "from_env_fil": 1, "creat": 1, "config": 1, "extra": 1, "ignor": 1, "hide_input_in_error": 1, "complexity_check": 1, "verifi": 1, "strength": 1, "A": 1, "consid": 1, "least": 1, "ha": 1, "32": 1, "charact": 1, "digit": 1, "symbol": 1, "uppercas": 1, "letter": 1, "lowercas": 1, "assertionerror": 1, "abov": 1, "condit": 1, "match": 1, "gpulib": 1, "usr": 1, "bin": 1, "lspci": 1, "sbin": 1, "system_profil": 1, "c": 1, "system32": 1, "wbem": 1, "wmic": 1, "ex": 1, "_abc_impl": 1, "_abc": 1, "_abc_data": 1, "model_computed_field": 1, "classvar": 1, "computedfieldinfo": 1, "comput": 1, "field": 1, "model_config": 1, "configdict": 1, "conform": 1, "model_field": 1, "fieldinfo": 1, "annot": 1, "metadata": 1, "pathtyp": 1, "path_typ": 1, "about": 1, "defin": 1, "map": 1, "replac": 1, "__fields__": 1, "v1": 1, "wssession": 1, "client_auth": 1, "websocket": 1, "get_librari": 1, "referenc": 1, "datastor": 1, "sqlite3": 1, "create_t": 1, "table_nam": 1, "column": 1, "tupl": 1, "public_ip_address": 1, "differ": 1, "endpoint": 1, "private_ip_address": 1, "simpl": 1, "network": 1, "see": 1, "format_no": 1, "input_": 1, "remov": 1, "0": 1, "integ": 1, "end": 1, "found": 1, "els": 1, "format_timedelta": 1, "td": 1, "timedelta": 1, "convert": 1, "human": 1, "readabl": 1, "non": 1, "zero": 1, "alwai": 1, "output": 1, "two": 1, "dai": 1, "hour": 1, "23": 1, "size_convert": 1, "byte_s": 1, "consum": 1, "friendli": 1, "byte": 1, "size": 1, "understand": 1, "process_command": 1, "result": 1, "stdout": 1, "stderr": 1, "envfile_load": 1, "filenam": 1, "pathlik": 1, "filetyp": 1, "var": 1, "have": 1, "load_env": 1, "merg": 1, "give": 1, "prioriti": 1, "partial": 1, "through": 1, "keygen": 1, "modul": 1, "forc": 1, "restart": 1, "url": 1, "safe": 1, "64": 1, "bit": 1, "dynamic_numb": 1, "dynam": 1, "failed_auth_count": 1, "keep": 1, "track": 1, "more": 1, "raise_error": 1, "unauthor": 1, "bad": 1, "credenti": 1, "extract_credenti": 1, "extract": 1, "decod": 1, "befor": 1, "verify_login": 1, "generate_cooki": 1, "auth_payload": 1, "timestamp": 1, "session_error": 1, "htmlrespons": 1, "render": 1, "messag": 1, "templat": 1, "jinja2": 1, "validate_sess": 1, "cookie_str": 1, "summari": 1, "clear_sess": 1, "clear": 1, "get_expiri": 1, "lease_start": 1, "lease_dur": 1, "expiri": 1, "datetim": 1, "ag": 1, "wa": 1, "made": 1, "date": 1, "gmt": 1, "get_cpu_perc": 1, "percentag": 1, "asynchron": 1, "get_system_metr": 1, "swap": 1, "nest": 1, "system_resourc": 1, "gather": 1, "error_endpoint": 1, "logout_endpoint": 1, "out": 1, "login_endpoint": 1, "session_token": 1, "redirect_url": 1, "monitor_endpoint": 1, "ui": 1, "after": 1, "websocket_endpoint": 1, "fetch": 1, "live": 1, "calculate_hash": 1, "hash": 1, "base64_encod": 1, "base64": 1, "encod": 1, "base64_decod": 1, "hex_decod": 1, "hex": 1, "hex_encod": 1, "index": 1, "search": 1}, "objects": {"pyninja": [[1, 0, 0, "-", "auth"], [1, 0, 0, "-", "database"], [1, 0, 0, "-", "dockerized"], [1, 0, 0, "-", "exceptions"], [1, 0, 0, "-", "gpu"], [1, 0, 0, "-", "main"], [1, 0, 0, "-", "models"], [1, 0, 0, "-", "operations"], [1, 0, 0, "-", "process"], [1, 0, 0, "-", "rate_limit"], [1, 0, 0, "-", "routes"], [1, 0, 0, "-", "service"], [1, 0, 0, "-", "squire"]], "pyninja.auth": [[1, 1, 1, "", "EPOCH"], [1, 1, 1, "", "forbidden"], [1, 1, 1, "", "handle_auth_error"], [1, 1, 1, "", "incrementer"], [1, 1, 1, "", "level_1"], [1, 1, 1, "", "level_2"]], "pyninja.database": [[1, 1, 1, "", "get_record"], [1, 1, 1, "", "put_record"], [1, 1, 1, "", "remove_record"]], "pyninja.dockerized": [[1, 1, 1, "", "get_all_containers"], [1, 1, 1, "", "get_all_images"], [1, 1, 1, "", "get_all_volumes"], [1, 1, 1, "", "get_container_status"], [1, 1, 1, "", "get_running_containers"]], "pyninja.exceptions": [[1, 2, 1, "", "APIResponse"], [1, 2, 1, "", "RedirectException"], [1, 2, 1, "", "SessionError"], [1, 2, 1, "", "UnSupportedOS"], [1, 1, 1, "", "raise_os_error"]], "pyninja.gpu": [[1, 1, 1, "", "_darwin"], [1, 1, 1, "", "_linux"], [1, 1, 1, "", "_windows"], [1, 1, 1, "", "get_names"]], "pyninja.main": [[1, 1, 1, "", "get_desc"], [1, 1, 1, "", "redirect_exception_handler"], [1, 1, 1, "", "start"]], "pyninja.models": [[1, 3, 1, "", "Database"], [1, 3, 1, "", "DiskLib"], [1, 3, 1, "", "EnvConfig"], [1, 3, 1, "", "GPULib"], [1, 3, 1, "", "Payload"], [1, 3, 1, "", "ProcessorLib"], [1, 3, 1, "", "RateLimit"], [1, 3, 1, "", "ServiceLib"], [1, 3, 1, "", "ServiceStatus"], [1, 3, 1, "", "Session"], [1, 3, 1, "", "WSSession"], [1, 1, 1, "", "complexity_checker"], [1, 1, 1, "", "get_library"]], "pyninja.models.Database": [[1, 4, 1, "", "create_table"]], "pyninja.models.DiskLib": [[1, 5, 1, "", "darwin"], [1, 5, 1, "", "linux"], [1, 5, 1, "", "windows"]], "pyninja.models.EnvConfig": [[1, 3, 1, "", "Config"], [1, 5, 1, "", "api_secret"], [1, 5, 1, "", "apikey"], [1, 5, 1, "", "database"], [1, 5, 1, "", "disk_lib"], [1, 4, 1, "", "from_env_file"], [1, 5, 1, "", "gpu_lib"], [1, 5, 1, "", "log_config"], [1, 5, 1, "", "max_connections"], [1, 5, 1, "", "monitor_password"], [1, 5, 1, "", "monitor_session"], [1, 5, 1, "", "monitor_username"], [1, 5, 1, "", "ninja_host"], [1, 5, 1, "", "ninja_port"], [1, 4, 1, "", "parse_api_secret"], [1, 5, 1, "", "processes"], [1, 5, 1, "", "processor_lib"], [1, 5, 1, "", "rate_limit"], [1, 5, 1, "", "remote_execution"], [1, 5, 1, "", "service_lib"], [1, 5, 1, "", "services"]], "pyninja.models.EnvConfig.Config": [[1, 5, 1, "", "extra"], [1, 5, 1, "", "hide_input_in_errors"]], "pyninja.models.GPULib": [[1, 5, 1, "", "_abc_impl"], [1, 5, 1, "", "darwin"], [1, 5, 1, "", "linux"], [1, 5, 1, "", "model_computed_fields"], [1, 5, 1, "", "model_config"], [1, 5, 1, "", "model_fields"], [1, 5, 1, "", "windows"]], "pyninja.models.Payload": [[1, 5, 1, "", "command"], [1, 5, 1, "", "timeout"]], "pyninja.models.ProcessorLib": [[1, 5, 1, "", "darwin"], [1, 5, 1, "", "linux"], [1, 5, 1, "", "windows"]], "pyninja.models.RateLimit": [[1, 5, 1, "", "max_requests"], [1, 5, 1, "", "seconds"]], "pyninja.models.ServiceLib": [[1, 5, 1, "", "darwin"], [1, 5, 1, "", "linux"], [1, 5, 1, "", "windows"]], "pyninja.models.ServiceStatus": [[1, 5, 1, "", "description"], [1, 5, 1, "", "status_code"]], "pyninja.models.Session": [[1, 5, 1, "", "allowed_origins"], [1, 5, 1, "", "auth_counter"], [1, 5, 1, "", "forbid"], [1, 5, 1, "", "info"], [1, 5, 1, "", "rps"]], "pyninja.models.WSSession": [[1, 5, 1, "", "_abc_impl"], [1, 5, 1, "", "client_auth"], [1, 5, 1, "", "invalid"], [1, 5, 1, "", "model_computed_fields"], [1, 5, 1, "", "model_config"], [1, 5, 1, "", "model_fields"]], "pyninja.monitor": [[1, 0, 0, "-", "authenticator"], [1, 0, 0, "-", "config"], [1, 0, 0, "-", "resources"], [1, 0, 0, "-", "routes"], [1, 0, 0, "-", "secure"]], "pyninja.monitor.authenticator": [[1, 1, 1, "", "extract_credentials"], [1, 1, 1, "", "failed_auth_counter"], [1, 1, 1, "", "generate_cookie"], [1, 1, 1, "", "raise_error"], [1, 1, 1, "", "session_error"], [1, 1, 1, "", "validate_session"], [1, 1, 1, "", "verify_login"]], "pyninja.monitor.config": [[1, 1, 1, "", "clear_session"], [1, 1, 1, "", "get_expiry"]], "pyninja.monitor.resources": [[1, 1, 1, "", "get_cpu_percent"], [1, 1, 1, "", "get_docker_stats"], [1, 1, 1, "", "get_system_metrics"], [1, 1, 1, "", "system_resources"]], "pyninja.monitor.routes": [[1, 1, 1, "", "error_endpoint"], [1, 1, 1, "", "login_endpoint"], [1, 1, 1, "", "logout_endpoint"], [1, 1, 1, "", "monitor_endpoint"], [1, 1, 1, "", "websocket_endpoint"]], "pyninja.monitor.secure": [[1, 1, 1, "", "base64_decode"], [1, 1, 1, "", "base64_encode"], [1, 1, 1, "", "calculate_hash"], [1, 1, 1, "", "hex_decode"], [1, 1, 1, "", "hex_encode"]], "pyninja.operations": [[1, 1, 1, "", "default"], [1, 1, 1, "", "get_process_info"], [1, 1, 1, "", "get_service_pid"], [1, 1, 1, "", "get_service_pid_linux"], [1, 1, 1, "", "get_service_pid_macos"], [1, 1, 1, "", "get_service_pid_windows"], [1, 1, 1, "", "process_monitor"], [1, 1, 1, "", "service_monitor"]], "pyninja.process": [[1, 1, 1, "", "get_performance"], [1, 1, 1, "", "get_process_status"]], "pyninja.rate_limit": [[1, 3, 1, "", "RateLimiter"]], "pyninja.rate_limit.RateLimiter": [[1, 4, 1, "", "init"]], "pyninja.routes": [[1, 1, 1, "", "docs"], [1, 1, 1, "", "get_all_disks"], [1, 1, 1, "", "get_all_routes"], [1, 1, 1, "", "get_cpu_load_avg"], [1, 1, 1, "", "get_cpu_utilization"], [1, 1, 1, "", "get_disk_utilization"], [1, 1, 1, "", "get_docker_containers"], [1, 1, 1, "", "get_docker_images"], [1, 1, 1, "", "get_docker_stats"], [1, 1, 1, "", "get_docker_volumes"], [1, 1, 1, "", "get_ip_address"], [1, 1, 1, "", "get_memory_utilization"], [1, 1, 1, "", "get_process_status"], [1, 1, 1, "", "get_processor_name"], [1, 1, 1, "", "get_service_status"], [1, 1, 1, "", "health"], [1, 1, 1, "", "run_command"]], "pyninja.service": [[1, 1, 1, "", "get_service_status"], [1, 1, 1, "", "running"], [1, 1, 1, "", "stopped"], [1, 1, 1, "", "unavailable"], [1, 1, 1, "", "unknown"]], "pyninja.squire": [[1, 1, 1, "", "dynamic_numbers"], [1, 1, 1, "", "envfile_loader"], [1, 1, 1, "", "format_nos"], [1, 1, 1, "", "format_timedelta"], [1, 1, 1, "", "keygen"], [1, 1, 1, "", "load_env"], [1, 1, 1, "", "private_ip_address"], [1, 1, 1, "", "process_command"], [1, 1, 1, "", "public_ip_address"], [1, 1, 1, "", "size_converter"]]}, "objtypes": {"0": "py:module", "1": "py:function", "2": "py:exception", "3": "py:class", "4": "py:method", "5": "py:attribute"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"], "2": ["py", "exception", "Python exception"], "3": ["py", "class", "Python class"], "4": ["py", "method", "Python method"], "5": ["py", "attribute", "Python attribute"]}, "titleterms": {"pyninja": [0, 1], "kick": 0, "off": 0, "environ": 0, "variabl": 0, "code": 0, "standard": 0, "releas": 0, "note": 0, "lint": 0, "pypi": 0, "packag": 0, "runbook": 0, "licens": 0, "copyright": 0, "welcom": 1, "": 1, "document": 1, "content": 1, "main": 1, "authent": 1, "rout": 1, "monitor": 1, "docker": 1, "gpu": 1, "process": 1, "servic": 1, "oper": 1, "databas": 1, "ratelimit": 1, "except": 1, "model": 1, "squir": 1, "configur": 1, "resourc": 1, "secur": 1, "indic": 1, "tabl": 1}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 6, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 56}}) \ No newline at end of file +Search.setIndex({"docnames": ["README", "index"], "filenames": ["README.md", "index.rst"], "titles": ["PyNinja", "Welcome to PyNinja\u2019s documentation!"], "terms": {"lightweight": 0, "o": [0, 1], "agnost": 0, "servic": 0, "monitor": 0, "api": [0, 1], "platform": 0, "support": [0, 1], "deploy": 0, "recommend": 0, "instal": [0, 1], "python": 0, "3": [0, 1], "10": [0, 1], "11": [0, 1], "us": [0, 1], "dedic": [0, 1], "virtual": [0, 1], "m": 0, "pip": 0, "initi": 0, "id": [0, 1], "import": 0, "__name__": 0, "__main__": 0, "start": [0, 1], "cli": 0, "help": 0, "usag": [0, 1], "instruct": 0, "sourc": 0, "from": [0, 1], "an": [0, 1], "env": [0, 1], "file": [0, 1], "By": 0, "default": [0, 1], "look": 0, "current": [0, 1], "work": [0, 1], "directori": 0, "apikei": [0, 1], "kei": [0, 1], "authent": 0, "ninja": 0, "_": 0, "host": [0, 1], "hostnam": [0, 1], "server": [0, 1], "port": [0, 1], "number": [0, 1], "remot": [0, 1], "execut": [0, 1], "boolean": [0, 1], "flag": [0, 1], "enabl": [0, 1], "secret": [0, 1], "access": [0, 1], "run": [0, 1], "command": [0, 1], "usernam": [0, 1], "page": [0, 1], "password": [0, 1], "session": [0, 1], "timeout": [0, 1], "max": [0, 1], "connect": [0, 1], "maximum": [0, 1], "allow": [0, 1], "parallel": 0, "process": 0, "list": [0, 1], "name": [0, 1], "includ": [0, 1], "gpu": 0, "lib": 0, "librari": [0, 1], "filepath": [0, 1], "disk": [0, 1], "memori": [0, 1], "processor": [0, 1], "databas": 0, "store": [0, 1], "auth": [0, 1], "handl": [0, 1], "error": [0, 1], "rate": [0, 1], "limit": [0, 1], "dictionari": [0, 1], "max_request": [0, 1], "second": [0, 1], "appli": [0, 1], "log": [0, 1], "config": [0, 1], "configur": 0, "path": [0, 1], "can": [0, 1], "extrem": 0, "riski": 0, "major": 0, "secur": 0, "threat": 0, "so": [0, 1], "caution": 0, "set": [0, 1], "strong": [0, 1], "valu": [0, 1], "refer": [0, 1], "sampl": 0, "exampl": [0, 1], "docstr": 0, "format": [0, 1], "googl": 0, "style": 0, "convent": 0, "pep": 0, "8": 0, "isort": 0, "requir": [0, 1], "gitvers": 0, "revers": 0, "f": 0, "release_not": 0, "rst": 0, "t": [0, 1], "pre": 0, "commit": 0, "ensur": 0, "pytest": 0, "gener": [0, 1], "valid": [0, 1], "hyperlink": 0, "all": [0, 1], "markdown": 0, "wiki": 0, "sphinx": 0, "5": [0, 1], "1": [0, 1], "recommonmark": 0, "http": [0, 1], "org": 0, "project": 0, "thevickypedia": 0, "github": 0, "io": 0, "vignesh": 0, "rao": 0, "under": 0, "mit": 0, "kick": 1, "off": 1, "environ": 1, "variabl": 1, "code": 1, "standard": 1, "releas": 1, "note": 1, "lint": 1, "pypi": 1, "packag": 1, "runbook": 1, "licens": 1, "copyright": 1, "get_desc": 1, "remote_flag": 1, "bool": 1, "monitor_flag": 1, "str": 1, "construct": 1, "detail": 1, "descript": 1, "doc": 1, "paramet": 1, "state": 1, "return": 1, "string": 1, "type": 1, "async": 1, "redirect_exception_handl": 1, "request": 1, "redirectexcept": 1, "jsonrespons": 1, "custom": 1, "handler": 1, "redirect": 1, "take": 1, "object": 1, "argument": 1, "inherit": 1, "statu": 1, "cooki": 1, "kwarg": 1, "none": 1, "starter": 1, "function": 1, "which": 1, "uvicorn": 1, "trigger": 1, "keyword": 1, "env_fil": 1, "load": 1, "ninja_host": 1, "ninja_port": 1, "remote_execut": 1, "api_secret": 1, "monitor_usernam": 1, "monitor_password": 1, "monitor_sess": 1, "service_manag": 1, "manag": 1, "rate_limit": 1, "log_config": 1, "dict": 1, "yaml": 1, "yml": 1, "json": 1, "ini": 1, "epoch": 1, "forbidden": 1, "i": 1, "part": 1, "fastapi": 1, "rais": 1, "apirespons": 1, "403": 1, "If": 1, "address": 1, "level_1": 1, "httpauthorizationcredenti": 1, "httpbearer": 1, "author": 1, "header": 1, "token": 1, "basic": 1, "401": 1, "invalid": 1, "level_2": 1, "addition": 1, "addit": 1, "critic": 1, "increment": 1, "attempt": 1, "int": 1, "block": 1, "time": 1, "base": 1, "fail": 1, "login": 1, "appropri": 1, "minut": 1, "handle_auth_error": 1, "filebrows": 1, "The": 1, "incom": 1, "get_ip_address": 1, "public": 1, "fals": 1, "depend": 1, "get": 1, "local": 1, "ip": 1, "devic": 1, "arg": 1, "httpstatu": 1, "privat": 1, "respons": 1, "get_cpu_util": 1, "interv": 1, "float": 1, "2": 1, "per_cpu": 1, "true": 1, "cpu": 1, "util": 1, "each": 1, "get_memory_util": 1, "get_cpu_load_avg": 1, "system": 1, "queue": 1, "averag": 1, "over": 1, "last": 1, "15": 1, "respect": 1, "get_disk_util": 1, "get_all_disk": 1, "attach": 1, "run_command": 1, "payload": 1, "option": 1, "machin": 1, "receiv": 1, "bodi": 1, "get_process_statu": 1, "process_nam": 1, "cpu_interv": 1, "union": 1, "check": 1, "get_service_statu": 1, "service_nam": 1, "get_docker_contain": 1, "container_nam": 1, "get_al": 1, "get_run": 1, "contain": 1, "inform": 1, "get_docker_imag": 1, "imag": 1, "get_docker_volum": 1, "volum": 1, "get_docker_stat": 1, "stat": 1, "get_processor_nam": 1, "redirectrespons": 1, "user": 1, "health": 1, "200": 1, "get_all_rout": 1, "apirout": 1, "ad": 1, "get_container_statu": 1, "get_running_contain": 1, "yield": 1, "correspond": 1, "metric": 1, "get_all_contain": 1, "get_all_imag": 1, "get_all_volum": 1, "_darwin": 1, "lib_path": 1, "vendor": 1, "linux": 1, "_linux": 1, "_window": 1, "window": 1, "get_nam": 1, "perform": 1, "report": 1, "given": 1, "get_perform": 1, "thread": 1, "open": 1, "pair": 1, "servicestatu": 1, "stop": 1, "501": 1, "unknown": 1, "503": 1, "unavail": 1, "404": 1, "instanc": 1, "get_process_info": 1, "proc": 1, "psutil": 1, "statist": 1, "process_monitor": 1, "executor": 1, "threadpoolexecutor": 1, "case": 1, "sensit": 1, "maco": 1, "top": 1, "grep": 1, "task": 1, "service_monitor": 1, "ar": 1, "follow": 1, "right": 1, "launchctl": 1, "systemctl": 1, "show": 1, "properti": 1, "mainpid": 1, "sc": 1, "queri": 1, "get_service_pid": 1, "retriev": 1, "pid": 1, "get_service_pid_linux": 1, "get_service_pid_maco": 1, "get_service_pid_window": 1, "get_record": 1, "particular": 1, "until": 1, "when": 1, "should": 1, "put_record": 1, "block_until": 1, "insert": 1, "remove_record": 1, "delet": 1, "record": 1, "relat": 1, "class": 1, "rp": 1, "implement": 1, "init": 1, "call": 1, "exce": 1, "identifi": 1, "429": 1, "too": 1, "mani": 1, "status_cod": 1, "ani": 1, "httpexcept": 1, "wrap": 1, "unsupportedo": 1, "unsupport": 1, "locat": 1, "within": 1, "sinc": 1, "doesn": 1, "html": 1, "demand": 1, "where": 1, "solut": 1, "There": 1, "altern": 1, "our": 1, "javascript": 1, "thi": 1, "wai": 1, "come": 1, "handi": 1, "unexpect": 1, "scenario": 1, "tiangolo": 1, "com": 1, "tutori": 1, "sessionerror": 1, "raise_os_error": 1, "operating_system": 1, "noreturn": 1, "validationerror": 1, "overridden": 1, "pydant": 1, "basemodel": 1, "input": 1, "data": 1, "disklib": 1, "darwin": 1, "servicelib": 1, "processorlib": 1, "auth_count": 1, "forbid": 1, "info": 1, "allowed_origin": 1, "envconfig": 1, "max_connect": 1, "gpu_lib": 1, "disk_lib": 1, "service_lib": 1, "processor_lib": 1, "classmethod": 1, "parse_api_secret": 1, "pars": 1, "complex": 1, "from_env_fil": 1, "creat": 1, "extra": 1, "ignor": 1, "hide_input_in_error": 1, "complexity_check": 1, "verifi": 1, "strength": 1, "A": 1, "consid": 1, "least": 1, "ha": 1, "32": 1, "charact": 1, "digit": 1, "symbol": 1, "uppercas": 1, "letter": 1, "lowercas": 1, "assertionerror": 1, "abov": 1, "condit": 1, "match": 1, "gpulib": 1, "usr": 1, "bin": 1, "lspci": 1, "sbin": 1, "system_profil": 1, "c": 1, "system32": 1, "wbem": 1, "wmic": 1, "ex": 1, "_abc_impl": 1, "_abc": 1, "_abc_data": 1, "model_computed_field": 1, "classvar": 1, "computedfieldinfo": 1, "comput": 1, "field": 1, "model_config": 1, "configdict": 1, "conform": 1, "model_field": 1, "fieldinfo": 1, "annot": 1, "metadata": 1, "pathtyp": 1, "path_typ": 1, "about": 1, "defin": 1, "map": 1, "replac": 1, "__fields__": 1, "v1": 1, "wssession": 1, "client_auth": 1, "websocket": 1, "get_librari": 1, "referenc": 1, "datastor": 1, "sqlite3": 1, "create_t": 1, "table_nam": 1, "column": 1, "tupl": 1, "public_ip_address": 1, "differ": 1, "endpoint": 1, "private_ip_address": 1, "simpl": 1, "network": 1, "see": 1, "format_no": 1, "input_": 1, "remov": 1, "0": 1, "integ": 1, "end": 1, "found": 1, "els": 1, "format_timedelta": 1, "td": 1, "timedelta": 1, "convert": 1, "human": 1, "readabl": 1, "non": 1, "zero": 1, "alwai": 1, "output": 1, "two": 1, "dai": 1, "hour": 1, "23": 1, "size_convert": 1, "byte_s": 1, "consum": 1, "friendli": 1, "byte": 1, "size": 1, "understand": 1, "process_command": 1, "result": 1, "stdout": 1, "stderr": 1, "envfile_load": 1, "filenam": 1, "pathlik": 1, "filetyp": 1, "var": 1, "have": 1, "load_env": 1, "merg": 1, "give": 1, "prioriti": 1, "partial": 1, "through": 1, "keygen": 1, "modul": 1, "forc": 1, "restart": 1, "url": 1, "safe": 1, "64": 1, "bit": 1, "dynamic_numb": 1, "dynam": 1, "failed_auth_count": 1, "keep": 1, "track": 1, "more": 1, "raise_error": 1, "unauthor": 1, "bad": 1, "credenti": 1, "extract_credenti": 1, "extract": 1, "decod": 1, "befor": 1, "verify_login": 1, "generate_cooki": 1, "auth_payload": 1, "timestamp": 1, "session_error": 1, "htmlrespons": 1, "render": 1, "messag": 1, "templat": 1, "jinja2": 1, "validate_sess": 1, "cookie_str": 1, "summari": 1, "clear_sess": 1, "clear": 1, "get_expiri": 1, "lease_start": 1, "lease_dur": 1, "expiri": 1, "datetim": 1, "ag": 1, "wa": 1, "made": 1, "date": 1, "gmt": 1, "map_docker_stat": 1, "json_data": 1, "get_cpu_perc": 1, "percentag": 1, "asynchron": 1, "get_system_metr": 1, "swap": 1, "nest": 1, "system_resourc": 1, "gather": 1, "error_endpoint": 1, "logout_endpoint": 1, "out": 1, "login_endpoint": 1, "session_token": 1, "redirect_url": 1, "monitor_endpoint": 1, "ui": 1, "after": 1, "websocket_endpoint": 1, "fetch": 1, "live": 1, "calculate_hash": 1, "hash": 1, "base64_encod": 1, "base64": 1, "encod": 1, "base64_decod": 1, "hex_decod": 1, "hex": 1, "hex_encod": 1, "index": 1, "search": 1}, "objects": {"pyninja": [[1, 0, 0, "-", "auth"], [1, 0, 0, "-", "database"], [1, 0, 0, "-", "dockerized"], [1, 0, 0, "-", "exceptions"], [1, 0, 0, "-", "gpu"], [1, 0, 0, "-", "main"], [1, 0, 0, "-", "models"], [1, 0, 0, "-", "operations"], [1, 0, 0, "-", "process"], [1, 0, 0, "-", "rate_limit"], [1, 0, 0, "-", "routes"], [1, 0, 0, "-", "service"], [1, 0, 0, "-", "squire"]], "pyninja.auth": [[1, 1, 1, "", "EPOCH"], [1, 1, 1, "", "forbidden"], [1, 1, 1, "", "handle_auth_error"], [1, 1, 1, "", "incrementer"], [1, 1, 1, "", "level_1"], [1, 1, 1, "", "level_2"]], "pyninja.database": [[1, 1, 1, "", "get_record"], [1, 1, 1, "", "put_record"], [1, 1, 1, "", "remove_record"]], "pyninja.dockerized": [[1, 1, 1, "", "get_all_containers"], [1, 1, 1, "", "get_all_images"], [1, 1, 1, "", "get_all_volumes"], [1, 1, 1, "", "get_container_status"], [1, 1, 1, "", "get_running_containers"]], "pyninja.exceptions": [[1, 2, 1, "", "APIResponse"], [1, 2, 1, "", "RedirectException"], [1, 2, 1, "", "SessionError"], [1, 2, 1, "", "UnSupportedOS"], [1, 1, 1, "", "raise_os_error"]], "pyninja.gpu": [[1, 1, 1, "", "_darwin"], [1, 1, 1, "", "_linux"], [1, 1, 1, "", "_windows"], [1, 1, 1, "", "get_names"]], "pyninja.main": [[1, 1, 1, "", "get_desc"], [1, 1, 1, "", "redirect_exception_handler"], [1, 1, 1, "", "start"]], "pyninja.models": [[1, 3, 1, "", "Database"], [1, 3, 1, "", "DiskLib"], [1, 3, 1, "", "EnvConfig"], [1, 3, 1, "", "GPULib"], [1, 3, 1, "", "Payload"], [1, 3, 1, "", "ProcessorLib"], [1, 3, 1, "", "RateLimit"], [1, 3, 1, "", "ServiceLib"], [1, 3, 1, "", "ServiceStatus"], [1, 3, 1, "", "Session"], [1, 3, 1, "", "WSSession"], [1, 1, 1, "", "complexity_checker"], [1, 1, 1, "", "get_library"]], "pyninja.models.Database": [[1, 4, 1, "", "create_table"]], "pyninja.models.DiskLib": [[1, 5, 1, "", "darwin"], [1, 5, 1, "", "linux"], [1, 5, 1, "", "windows"]], "pyninja.models.EnvConfig": [[1, 3, 1, "", "Config"], [1, 5, 1, "", "api_secret"], [1, 5, 1, "", "apikey"], [1, 5, 1, "", "database"], [1, 5, 1, "", "disk_lib"], [1, 4, 1, "", "from_env_file"], [1, 5, 1, "", "gpu_lib"], [1, 5, 1, "", "log_config"], [1, 5, 1, "", "max_connections"], [1, 5, 1, "", "monitor_password"], [1, 5, 1, "", "monitor_session"], [1, 5, 1, "", "monitor_username"], [1, 5, 1, "", "ninja_host"], [1, 5, 1, "", "ninja_port"], [1, 4, 1, "", "parse_api_secret"], [1, 5, 1, "", "processes"], [1, 5, 1, "", "processor_lib"], [1, 5, 1, "", "rate_limit"], [1, 5, 1, "", "remote_execution"], [1, 5, 1, "", "service_lib"], [1, 5, 1, "", "services"]], "pyninja.models.EnvConfig.Config": [[1, 5, 1, "", "extra"], [1, 5, 1, "", "hide_input_in_errors"]], "pyninja.models.GPULib": [[1, 5, 1, "", "_abc_impl"], [1, 5, 1, "", "darwin"], [1, 5, 1, "", "linux"], [1, 5, 1, "", "model_computed_fields"], [1, 5, 1, "", "model_config"], [1, 5, 1, "", "model_fields"], [1, 5, 1, "", "windows"]], "pyninja.models.Payload": [[1, 5, 1, "", "command"], [1, 5, 1, "", "timeout"]], "pyninja.models.ProcessorLib": [[1, 5, 1, "", "darwin"], [1, 5, 1, "", "linux"], [1, 5, 1, "", "windows"]], "pyninja.models.RateLimit": [[1, 5, 1, "", "max_requests"], [1, 5, 1, "", "seconds"]], "pyninja.models.ServiceLib": [[1, 5, 1, "", "darwin"], [1, 5, 1, "", "linux"], [1, 5, 1, "", "windows"]], "pyninja.models.ServiceStatus": [[1, 5, 1, "", "description"], [1, 5, 1, "", "status_code"]], "pyninja.models.Session": [[1, 5, 1, "", "allowed_origins"], [1, 5, 1, "", "auth_counter"], [1, 5, 1, "", "forbid"], [1, 5, 1, "", "info"], [1, 5, 1, "", "rps"]], "pyninja.models.WSSession": [[1, 5, 1, "", "_abc_impl"], [1, 5, 1, "", "client_auth"], [1, 5, 1, "", "invalid"], [1, 5, 1, "", "model_computed_fields"], [1, 5, 1, "", "model_config"], [1, 5, 1, "", "model_fields"]], "pyninja.monitor": [[1, 0, 0, "-", "authenticator"], [1, 0, 0, "-", "config"], [1, 0, 0, "-", "resources"], [1, 0, 0, "-", "routes"], [1, 0, 0, "-", "secure"]], "pyninja.monitor.authenticator": [[1, 1, 1, "", "extract_credentials"], [1, 1, 1, "", "failed_auth_counter"], [1, 1, 1, "", "generate_cookie"], [1, 1, 1, "", "raise_error"], [1, 1, 1, "", "session_error"], [1, 1, 1, "", "validate_session"], [1, 1, 1, "", "verify_login"]], "pyninja.monitor.config": [[1, 1, 1, "", "clear_session"], [1, 1, 1, "", "get_expiry"]], "pyninja.monitor.resources": [[1, 1, 1, "", "get_cpu_percent"], [1, 1, 1, "", "get_docker_stats"], [1, 1, 1, "", "get_system_metrics"], [1, 1, 1, "", "map_docker_stats"], [1, 1, 1, "", "system_resources"]], "pyninja.monitor.routes": [[1, 1, 1, "", "error_endpoint"], [1, 1, 1, "", "login_endpoint"], [1, 1, 1, "", "logout_endpoint"], [1, 1, 1, "", "monitor_endpoint"], [1, 1, 1, "", "websocket_endpoint"]], "pyninja.monitor.secure": [[1, 1, 1, "", "base64_decode"], [1, 1, 1, "", "base64_encode"], [1, 1, 1, "", "calculate_hash"], [1, 1, 1, "", "hex_decode"], [1, 1, 1, "", "hex_encode"]], "pyninja.operations": [[1, 1, 1, "", "default"], [1, 1, 1, "", "get_process_info"], [1, 1, 1, "", "get_service_pid"], [1, 1, 1, "", "get_service_pid_linux"], [1, 1, 1, "", "get_service_pid_macos"], [1, 1, 1, "", "get_service_pid_windows"], [1, 1, 1, "", "process_monitor"], [1, 1, 1, "", "service_monitor"]], "pyninja.process": [[1, 1, 1, "", "get_performance"], [1, 1, 1, "", "get_process_status"]], "pyninja.rate_limit": [[1, 3, 1, "", "RateLimiter"]], "pyninja.rate_limit.RateLimiter": [[1, 4, 1, "", "init"]], "pyninja.routes": [[1, 1, 1, "", "docs"], [1, 1, 1, "", "get_all_disks"], [1, 1, 1, "", "get_all_routes"], [1, 1, 1, "", "get_cpu_load_avg"], [1, 1, 1, "", "get_cpu_utilization"], [1, 1, 1, "", "get_disk_utilization"], [1, 1, 1, "", "get_docker_containers"], [1, 1, 1, "", "get_docker_images"], [1, 1, 1, "", "get_docker_stats"], [1, 1, 1, "", "get_docker_volumes"], [1, 1, 1, "", "get_ip_address"], [1, 1, 1, "", "get_memory_utilization"], [1, 1, 1, "", "get_process_status"], [1, 1, 1, "", "get_processor_name"], [1, 1, 1, "", "get_service_status"], [1, 1, 1, "", "health"], [1, 1, 1, "", "run_command"]], "pyninja.service": [[1, 1, 1, "", "get_service_status"], [1, 1, 1, "", "running"], [1, 1, 1, "", "stopped"], [1, 1, 1, "", "unavailable"], [1, 1, 1, "", "unknown"]], "pyninja.squire": [[1, 1, 1, "", "dynamic_numbers"], [1, 1, 1, "", "envfile_loader"], [1, 1, 1, "", "format_nos"], [1, 1, 1, "", "format_timedelta"], [1, 1, 1, "", "keygen"], [1, 1, 1, "", "load_env"], [1, 1, 1, "", "private_ip_address"], [1, 1, 1, "", "process_command"], [1, 1, 1, "", "public_ip_address"], [1, 1, 1, "", "size_converter"]]}, "objtypes": {"0": "py:module", "1": "py:function", "2": "py:exception", "3": "py:class", "4": "py:method", "5": "py:attribute"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"], "2": ["py", "exception", "Python exception"], "3": ["py", "class", "Python class"], "4": ["py", "method", "Python method"], "5": ["py", "attribute", "Python attribute"]}, "titleterms": {"pyninja": [0, 1], "kick": 0, "off": 0, "environ": 0, "variabl": 0, "code": 0, "standard": 0, "releas": 0, "note": 0, "lint": 0, "pypi": 0, "packag": 0, "runbook": 0, "licens": 0, "copyright": 0, "welcom": 1, "": 1, "document": 1, "content": 1, "main": 1, "authent": 1, "rout": 1, "monitor": 1, "docker": 1, "gpu": 1, "process": 1, "servic": 1, "oper": 1, "databas": 1, "ratelimit": 1, "except": 1, "model": 1, "squir": 1, "configur": 1, "resourc": 1, "secur": 1, "indic": 1, "tabl": 1}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 6, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 56}}) \ No newline at end of file diff --git a/pyninja/main.py b/pyninja/main.py index 1444af7..f3788c1 100644 --- a/pyninja/main.py +++ b/pyninja/main.py @@ -1,4 +1,5 @@ import logging +import os import pathlib import uvicorn @@ -150,6 +151,7 @@ def start(**kwargs) -> None: BASE_LOGGER.warning("Remote execution disabled") # Conditional endpoint based on monitor_username and monitor_password if all((models.env.monitor_username, models.env.monitor_password)): + models.env.processes.append(str(os.getpid())) PyNinjaAPI.routes.extend(get_all_monitor_routes(dependencies)) PyNinjaAPI.add_exception_handler( exc_class_or_status_code=exceptions.RedirectException, diff --git a/pyninja/monitor/resources.py b/pyninja/monitor/resources.py index b1fc772..c360f92 100644 --- a/pyninja/monitor/resources.py +++ b/pyninja/monitor/resources.py @@ -2,7 +2,6 @@ import json import logging import os -import shutil from concurrent.futures import ThreadPoolExecutor from typing import Dict, List @@ -15,6 +14,27 @@ LOGGER = logging.getLogger("uvicorn.default") +def map_docker_stats(json_data: Dict[str, str]) -> Dict[str, str]: + """Map the JSON data to a dictionary. + + Args: + json_data: JSON data from the docker stats command. + + Returns: + Dict[str, str]: + Returns a dictionary with container stats. + """ + return { + "Container ID": json_data.get("ID"), + "Container Name": json_data.get("Name"), + "CPU": json_data.get("CPUPerc"), + "Memory": json_data.get("MemPerc"), + "Memory Usage": json_data.get("MemUsage"), + "Block I/O": json_data.get("BlockIO"), + "Network I/O": json_data.get("NetIO"), + } + + def get_cpu_percent(cpu_interval: int) -> List[float]: """Get CPU usage percentage. @@ -45,7 +65,7 @@ async def get_docker_stats() -> List[Dict[str, str]]: LOGGER.debug(stderr.decode().strip()) return [] return [ - {key: value for key, value in json.loads(line).items() if key != "PIDs"} + map_docker_stats(json.loads(line)) for line in stdout.decode().strip().splitlines() ] @@ -62,7 +82,6 @@ async def get_system_metrics() -> Dict[str, dict]: return dict( memory_info=psutil.virtual_memory()._asdict(), swap_info=psutil.swap_memory()._asdict(), - disk_info=shutil.disk_usage("/")._asdict(), load_averages=dict(m1=m1, m5=m5, m15=m15), ) diff --git a/pyninja/monitor/routes.py b/pyninja/monitor/routes.py index 60c0279..785409e 100644 --- a/pyninja/monitor/routes.py +++ b/pyninja/monitor/routes.py @@ -195,7 +195,10 @@ async def websocket_endpoint(websocket: WebSocket, session_token: str = Cookie(N session_timestamp = models.ws_session.client_auth.get(websocket.client.host).get( "timestamp" ) + # Base task with a placeholder asyncio sleep to start the task loop task = asyncio.create_task(asyncio.sleep(0.1)) + # Store disk usage information (during startup) to avoid repeated calls + disk_info = shutil.disk_usage("/")._asdict() while True: # Validate session asynchronously (non-blocking) # This way of handling session validation is more efficient than using a blocking call @@ -225,6 +228,7 @@ async def websocket_endpoint(websocket: WebSocket, session_token: str = Cookie(N await websocket.close() break data = await resources.system_resources() + data["disk_info"] = disk_info try: await websocket.send_json(data) except WebSocketDisconnect: diff --git a/pyninja/monitor/templates/main.html b/pyninja/monitor/templates/main.html index 7e53064..bf05769 100644 --- a/pyninja/monitor/templates/main.html +++ b/pyninja/monitor/templates/main.html @@ -342,15 +342,6 @@

    Docker Stats

    - - - - - - - - - @@ -407,7 +398,7 @@

    Process Stats

    } // Function to create the table head - function createHead(tableId, tableCSS) { + function handleTable(dataJSON, tableId, tableCSS) { // Show the service and the table const statsService = document.getElementById(tableCSS); statsService.style.display = "flex"; @@ -416,13 +407,14 @@

    Process Stats

    if (tableHead.children.length === 0) { const col = document.createElement('tr'); // Loop through the JSON data and create the table head - for (const key in serviceStatsJSON[0]) { + for (const key in dataJSON[0]) { const th = document.createElement('th'); th.innerText = key; col.appendChild(th); } tableHead.appendChild(col); } + populateTable(dataJSON, tableId); } // Function to populate data into the table @@ -460,29 +452,7 @@

    Process Stats

    const dockerStatsJSON = data.docker_stats; // Check if dockerStatsJSON is valid if (dockerStatsJSON && dockerStatsJSON.length > 0) { - // Show the container and the table - const statsContainer = document.getElementById("docker-stats"); - statsContainer.style.display = "flex"; - const table = document.getElementById("dockerStatsTable"); - table.style.display = "table"; - // Get reference to the table body - const tableBody = document.querySelector('#dockerStatsTable tbody'); - // Clear the existing table rows - tableBody.innerHTML = ''; - // Loop through the JSON data and populate the table - dockerStatsJSON.forEach(container => { - const row = document.createElement('tr'); - row.innerHTML = ` - - - - - - - - `; - tableBody.appendChild(row); - }); + handleTable(dockerStatsJSON, "dockerStatsTable", "docker-stats"); } else { // Hide the container if no data is available document.getElementById("docker-stats").style.display = "none"; @@ -491,8 +461,7 @@

    Process Stats

    const serviceStatsJSON = data.service_stats; // Check if serviceStatsJSON is valid if (serviceStatsJSON && serviceStatsJSON.length > 0) { - createHead("serviceStatsTable", "service-stats"); - populateTable(serviceStatsJSON, "serviceStatsTable"); + handleTable(serviceStatsJSON, "serviceStatsTable", "service-stats"); } else { // Hide the container if no data is available document.getElementById("service-stats").style.display = "none"; @@ -501,8 +470,7 @@

    Process Stats

    const processStatsJSON = data.process_stats; // Check if processStatsJSON is valid if (processStatsJSON && processStatsJSON.length > 0) { - createHead('processStatsTable', "process-stats"); - populateTable(processStatsJSON, 'processStatsTable'); + handleTable(processStatsJSON, "processStatsTable", "process-stats"); } else { // Hide the container if no data is available document.getElementById("process-stats").style.display = "none"; @@ -601,21 +569,16 @@

    Process Stats

    }); } - // Memory Chart - document.getElementById("memoryTotal").innerText = `Total: ${formatBytes(memoryInfo.total)}`; - if (memoryChartInstance) { - memoryChartInstance.data.datasets[0].data = [memoryInfo.used, memoryInfo.total - memoryInfo.used]; - memoryChartInstance.update(); - } else { - const memoryChart = document.getElementById('memoryChart').getContext('2d'); - memoryChartInstance = new Chart(memoryChart, { + // Function to create a pieChart instances for Memory, Swap and Disk utilization + function createChartInstance(pieChart, chartLabel, colors, chartData) { + return new Chart(pieChart, { type: 'pie', data: { labels: ['Used', 'Free'], datasets: [{ - label: 'Memory Usage', - data: [memoryInfo.used, memoryInfo.total - memoryInfo.used], - backgroundColor: ['#FF6384', '#36A2EB'] + label: chartLabel, + data: chartData, + backgroundColor: colors }] }, options: { @@ -635,6 +598,21 @@

    Process Stats

    }); } + // Memory Chart + document.getElementById("memoryTotal").innerText = `Total: ${formatBytes(memoryInfo.total)}`; + if (memoryChartInstance) { + memoryChartInstance.data.datasets[0].data = [memoryInfo.used, memoryInfo.total - memoryInfo.used]; + memoryChartInstance.update(); + } else { + const memoryChart = document.getElementById('memoryChart').getContext('2d'); + memoryChartInstance = createChartInstance( + memoryChart, + 'Memory Usage', + ['#36A2EB', '#FFCE56'], + [memoryInfo.used, memoryInfo.total - memoryInfo.used] + ); + } + // Swap Chart const swapChart = document.getElementById('swapChart'); if (swapChart) { @@ -643,35 +621,14 @@

    Process Stats

    if (swapChartInstance) { swapChartInstance.data.datasets[0].data = [swapInfo.used, swapInfo.total - swapInfo.used]; swapChartInstance.update(); - } else { - if (swapChart) { - const swapContext = swapChart.getContext('2d') - swapChartInstance = new Chart(swapContext, { - type: 'pie', - data: { - labels: ['Used', 'Free'], - datasets: [{ - label: 'Swap Usage', - data: [swapInfo.used, swapInfo.total - swapInfo.used], - backgroundColor: ['#FFCE56', '#E7E9ED'] - }] - }, - options: { - responsive: true, - plugins: { - tooltip: { - callbacks: { - label: function (tooltipItem) { - const value = tooltipItem.raw; - const formattedValue = formatBytes(value); - return `${tooltipItem.label}: ${formattedValue}`; - } - } - } - } - } - }); - } + } else if (swapChart) { + // swapChart is an optional chart, so create context only when available + swapChartInstance = createChartInstance( + swapChart.getContext('2d'), + 'Swap Usage', + ['#FFCE56', '#E7E9ED'], + [swapInfo.used, swapInfo.total - swapInfo.used] + ); } // Disk Chart @@ -681,31 +638,12 @@

    Process Stats

    diskChartInstance.update(); } else { const diskChart = document.getElementById('diskChart').getContext('2d'); - diskChartInstance = new Chart(diskChart, { - type: 'pie', - data: { - labels: ['Used', 'Free'], - datasets: [{ - label: 'Disk Usage', - data: [diskInfo.used, diskInfo.total - diskInfo.used], - backgroundColor: ['#63950d', '#ca7b00'] - }] - }, - options: { - responsive: true, - plugins: { - tooltip: { - callbacks: { - label: function (tooltipItem) { - const value = tooltipItem.raw; - const formattedValue = formatBytes(value); - return `${tooltipItem.label}: ${formattedValue}`; - } - } - } - } - } - }); + diskChartInstance = createChartInstance( + diskChart, + 'Disk Usage', + ['#63950d', '#ca7b00'], + [diskInfo.used, diskInfo.total - diskInfo.used] + ); } }; diff --git a/pyninja/operations.py b/pyninja/operations.py index b2d5f13..381a5cc 100644 --- a/pyninja/operations.py +++ b/pyninja/operations.py @@ -43,18 +43,23 @@ def get_process_info(proc: psutil.Process) -> Dict[str, str | int]: write_io = squire.size_converter(io_counters.write_bytes) except AttributeError: read_io, write_io = "N/A", "N/A" - return { - "PID": proc.pid, - "Name": proc.name(), - "CPU": f"{proc.cpu_percent(models.MINIMUM_CPU_UPDATE_INTERVAL):.2f}%", - "Memory": squire.size_converter(proc.memory_info().rss), # Resident Set Size, - "Uptime": squire.format_timedelta( - timedelta(seconds=int(time.time() - proc.create_time())) - ), - "Threads": proc.num_threads(), - "Read I/O": read_io, - "Write I/O": write_io, - } + try: + return { + "PID": proc.pid, + "Name": proc.name(), + "CPU": f"{proc.cpu_percent(models.MINIMUM_CPU_UPDATE_INTERVAL):.2f}%", + # Resident Set Size + "Memory": squire.size_converter(proc.memory_info().rss), + "Uptime": squire.format_timedelta( + timedelta(seconds=int(time.time() - proc.create_time())) + ), + "Threads": proc.num_threads(), + "Read I/O": read_io, + "Write I/O": write_io, + } + except psutil.NoSuchProcess as error: + LOGGER.debug(error) + return default(proc.name()) async def process_monitor(executor: ThreadPoolExecutor) -> List[Dict[str, str]]: @@ -75,7 +80,11 @@ async def process_monitor(executor: ThreadPoolExecutor) -> List[Dict[str, str]]: for proc in psutil.process_iter( ["pid", "name", "cpu_percent", "memory_info", "create_time"] ): - if any(name in proc.name() for name in models.env.processes): + # todo: Add a way to include processes (with default values) that don't exist but requested to monitor + if any( + name in proc.name() or name == str(proc.pid) + for name in models.env.processes + ): tasks.append(loop.run_in_executor(executor, get_process_info, proc)) return [await task for task in asyncio.as_completed(tasks)] diff --git a/pyninja/version.py b/pyninja/version.py index 89e9150..3dc1f76 100644 --- a/pyninja/version.py +++ b/pyninja/version.py @@ -1 +1 @@ -__version__ = "0.1.0-alpha" +__version__ = "0.1.0" diff --git a/release_notes.rst b/release_notes.rst index d49131a..b414af3 100644 --- a/release_notes.rst +++ b/release_notes.rst @@ -3,56 +3,79 @@ Release Notes v0.1.0 (09/29/2024) ------------------- -- Release `v0.1.0` +- Include `docker stats` in monitoring page +- **Full Changelog**: https://github.com/thevickypedia/PyNinja/compare/v0.0.9...v0.1.0 v0.1.0-alpha (09/16/2024) ------------------------- -- Release `v0.1.0-alpha` +- Alpha version for docker stats +- **Full Changelog**: https://github.com/thevickypedia/PyNinja/compare/v0.0.9...v0.1.0-alpha v0.0.9 (09/16/2024) ------------------- -- Release `v0.0.9` +- Includes disks information in the monitoring page +- Restructured monitoring page with dedicated div container for each category of system information +- **Full Changelog**: https://github.com/thevickypedia/PyNinja/compare/v0.0.8...v0.0.9 v0.0.8 (09/10/2024) ------------------- -- Release `v0.0.8` +- Includes an option to get CPU load average via API calls and monitoring page UI +- **Full Changelog**: https://github.com/thevickypedia/PyNinja/compare/v0.0.7...v0.0.8 v0.0.7 (09/09/2024) ------------------- -- Release `v0.0.7` +- Includes a new feature to monitor disk utilization and get process name +- Bug fix on uncaught errors during server shutdown +- **Full Changelog**: https://github.com/thevickypedia/PyNinja/compare/v0.0.6...v0.0.7 v0.0.6 (09/09/2024) ------------------- -- Release `v0.0.6` +- Includes an option to limit maximum number of WebSocket sessions +- Includes a logout functionality for the monitoring page +- Uses bearer auth for the monitoring page +- Redefines progress bars with newer color schemes +- **Full Changelog**: https://github.com/thevickypedia/PyNinja/compare/v0.0.5...v0.0.6 v0.0.6a (09/07/2024) -------------------- -- Release `v0.0.6a` +- Includes an option to limit max number of concurrent sessions for monitoring page +- **Full Changelog**: https://github.com/thevickypedia/PyNinja/compare/v0.0.5...v0.0.6a v0.0.5 (09/07/2024) ------------------- -- Release `v0.0.5` +- Packs an entirely new UI and authentication mechanism for monitoring tool +- Includes speed, stability and security improvements for monitoring feature +- Adds night mode option for monitoring UI +- **Full Changelog**: https://github.com/thevickypedia/PyNinja/compare/v0.0.4...v0.0.5 v0.0.4 (09/06/2024) ------------------- -- Include an option to monitor system resources via websockets +- Includes an option to monitor system resources via `WebSockets` +- **Full Changelog**: https://github.com/thevickypedia/PyNinja/compare/v0.0.3...v0.0.4 v0.0.3 (08/16/2024) ------------------- -- Release `v0.0.3` +- Allows env vars to be sourced from both ``env_file`` and ``kwargs`` +- **Full Changelog**: https://github.com/thevickypedia/PyNinja/compare/v0.0.2...v0.0.3 v0.0.2 (08/16/2024) ------------------- -- Release `v0.0.2` +- Includes added support for custom log configuration +- **Full Changelog**: https://github.com/thevickypedia/PyNinja/compare/v0.0.1...v0.0.2 v0.0.1 (08/11/2024) ------------------- -- Release `v0.0.1` +- Includes a process monitor and remote command execution functionality +- Security improvements including brute force protection and rate limiting +- Accepts ``JSON`` and ``YAML`` files for env config +- Supports custom worker count for ``uvicorn`` server +- Allows custom logging using ``logging.ini`` +- Includes an option to set the ``apikey`` via commandline +- **Full Changelog**: https://github.com/thevickypedia/PyNinja/compare/v0.0.0...v0.0.1 v0.0.0 (08/11/2024) ------------------- -- Implement concurrency for validating process health -- Update logger names across the module and README.md +- Release first stable version 0.0.0-a (08/10/2024) --------------------
    Container IDContainer NameCPU %Memory UsageMemory %Net I/OBlock I/O
    ${container.ID}${container.Name}${container.CPUPerc}${container.MemUsage}${container.MemPerc}${container.NetIO}${container.BlockIO}