diff --git a/poetry.lock b/poetry.lock index b5eb6d2..bd4743c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,12 +1,12 @@ -# This file is automatically @generated by Poetry 2.3.4 and should not be changed by hand. +# This file is automatically @generated by Poetry and should not be changed by hand. [[package]] name = "annotated-doc" version = "0.0.4" description = "Document parameters, class attributes, return types, and variables inline, with Annotated." +category = "main" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320"}, {file = "annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4"}, @@ -16,9 +16,9 @@ files = [ name = "annotated-types" version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" +category = "main" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, @@ -28,9 +28,9 @@ files = [ name = "anyio" version = "4.13.0" description = "High-level concurrency and networking framework on top of asyncio or Trio" +category = "main" optional = false python-versions = ">=3.10" -groups = ["main"] files = [ {file = "anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708"}, {file = "anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc"}, @@ -46,24 +46,23 @@ trio = ["trio (>=0.32.0)"] [[package]] name = "certifi" -version = "2026.4.22" +version = "2026.2.25" description = "Python package for providing Mozilla's CA Bundle." +category = "main" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ - {file = "certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a"}, - {file = "certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580"}, + {file = "certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa"}, + {file = "certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7"}, ] [[package]] name = "cffi" version = "2.0.0" description = "Foreign Function Interface for Python calling C code." +category = "main" optional = false python-versions = ">=3.9" -groups = ["main"] -markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, @@ -158,9 +157,9 @@ pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} name = "cfgv" version = "3.5.0" description = "Validate configuration and produce human readable error messages." +category = "dev" optional = false python-versions = ">=3.10" -groups = ["dev"] files = [ {file = "cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0"}, {file = "cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132"}, @@ -170,9 +169,9 @@ files = [ name = "charset-normalizer" version = "3.4.7" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d"}, {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8"}, @@ -309,9 +308,9 @@ files = [ name = "click" version = "8.3.2" description = "Composable command line interface toolkit" +category = "main" optional = false python-versions = ">=3.10" -groups = ["main"] files = [ {file = "click-8.3.2-py3-none-any.whl", hash = "sha256:1924d2c27c5653561cd2cae4548d1406039cb79b858b747cfea24924bbc1616d"}, {file = "click-8.3.2.tar.gz", hash = "sha256:14162b8b3b3550a7d479eafa77dfd3c38d9dc8951f6f69c78913a8f9a7540fd5"}, @@ -324,22 +323,21 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main", "dev"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -markers = {main = "platform_system == \"Windows\"", dev = "sys_platform == \"win32\""} [[package]] name = "coverage" version = "7.13.5" description = "Code coverage measurement for Python" +category = "dev" optional = false python-versions = ">=3.10" -groups = ["dev"] files = [ {file = "coverage-7.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0723d2c96324561b9aa76fb982406e11d93cdb388a7a7da2b16e04719cf7ca5"}, {file = "coverage-7.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52f444e86475992506b32d4e5ca55c24fc88d73bcbda0e9745095b28ef4dc0cf"}, @@ -450,15 +448,15 @@ files = [ ] [package.extras] -toml = ["tomli ; python_full_version <= \"3.11.0a6\""] +toml = ["tomli"] [[package]] name = "cryptography" version = "46.0.7" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +category = "main" optional = false python-versions = "!=3.9.0,!=3.9.1,>=3.8" -groups = ["main"] files = [ {file = "cryptography-46.0.7-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:ea42cbe97209df307fdc3b155f1b6fa2577c0defa8f1f7d3be7d31d189108ad4"}, {file = "cryptography-46.0.7-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b36a4695e29fe69215d75960b22577197aca3f7a25b9cf9d165dcfe9d80bc325"}, @@ -512,8 +510,8 @@ files = [ ] [package.dependencies] -cffi = {version = ">=2.0.0", markers = "python_full_version >= \"3.9.0\" and platform_python_implementation != \"PyPy\""} -typing-extensions = {version = ">=4.13.2", markers = "python_full_version < \"3.11.0\""} +cffi = {version = ">=2.0.0", markers = "python_full_version >= \"3.9\" and platform_python_implementation != \"PyPy\""} +typing-extensions = {version = ">=4.13.2", markers = "python_full_version < \"3.11\""} [package.extras] docs = ["sphinx (>=5.3.0)", "sphinx-inline-tabs", "sphinx-rtd-theme (>=3.0.0)"] @@ -529,9 +527,9 @@ test-randomorder = ["pytest-randomly"] name = "distlib" version = "0.4.0" description = "Distribution utilities" +category = "dev" optional = false python-versions = "*" -groups = ["dev"] files = [ {file = "distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16"}, {file = "distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d"}, @@ -541,9 +539,9 @@ files = [ name = "dnspython" version = "2.8.0" description = "DNS toolkit" +category = "main" optional = false python-versions = ">=3.10" -groups = ["main"] files = [ {file = "dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af"}, {file = "dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f"}, @@ -556,15 +554,15 @@ doh = ["h2 (>=4.2.0)", "httpcore (>=1.0.0)", "httpx (>=0.28.0)"] doq = ["aioquic (>=1.2.0)"] idna = ["idna (>=3.10)"] trio = ["trio (>=0.30)"] -wmi = ["wmi (>=1.5.1) ; platform_system == \"Windows\""] +wmi = ["wmi (>=1.5.1)"] [[package]] name = "docker" version = "7.1.0" description = "A Python library for the Docker Engine API." +category = "main" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0"}, {file = "docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c"}, @@ -585,9 +583,9 @@ websockets = ["websocket-client (>=1.3.0)"] name = "durationpy" version = "0.10" description = "Module for converting between datetime.timedelta and Go's Duration strings." +category = "main" optional = false python-versions = "*" -groups = ["main"] files = [ {file = "durationpy-0.10-py3-none-any.whl", hash = "sha256:3b41e1b601234296b4fb368338fdcd3e13e0b4fb5b67345948f4f2bf9868b286"}, {file = "durationpy-0.10.tar.gz", hash = "sha256:1fa6893409a6e739c9c72334fc65cca1f355dbdd93405d30f726deb5bde42fba"}, @@ -597,9 +595,9 @@ files = [ name = "email-validator" version = "2.3.0" description = "A robust email address syntax and deliverability validation library." +category = "main" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4"}, {file = "email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426"}, @@ -613,10 +611,9 @@ idna = ">=2.0.0" name = "exceptiongroup" version = "1.3.1" description = "Backport of PEP 654 (exception groups)" +category = "main" optional = false python-versions = ">=3.7" -groups = ["main", "dev"] -markers = "python_version == \"3.10\"" files = [ {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, @@ -632,9 +629,9 @@ test = ["pytest (>=6)"] name = "fastapi" version = "0.135.4" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" +category = "main" optional = false python-versions = ">=3.10" -groups = ["main"] files = [ {file = "fastapi-0.135.4-py3-none-any.whl", hash = "sha256:539d3531f8aba9b286ab44658344553f4a4adc218529137501e5d97be071a78b"}, {file = "fastapi-0.135.4.tar.gz", hash = "sha256:d87c41b0a7bcaa6f14629d73fe48e360821605c7b6d518caacbc00dcf8fa5e0e"}, @@ -656,9 +653,9 @@ standard-no-fastapi-cloud-cli = ["email-validator (>=2.0.0)", "fastapi-cli[stand name = "filelock" version = "3.29.0" description = "A platform independent file lock." +category = "dev" optional = false python-versions = ">=3.10" -groups = ["dev"] files = [ {file = "filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258"}, {file = "filelock-3.29.0.tar.gz", hash = "sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90"}, @@ -668,9 +665,9 @@ files = [ name = "flame-hub-client" version = "0.2.15" description = "HTTP client for interacting with FLAME Hub services." +category = "main" optional = false python-versions = "<4,>=3.10" -groups = ["main"] files = [ {file = "flame_hub_client-0.2.15-py3-none-any.whl", hash = "sha256:a31f04dd0e55cbdf0f12984613b3834da0cf294fa0e6ae5988a1335133e88734"}, {file = "flame_hub_client-0.2.15.tar.gz", hash = "sha256:dd296472c05a92bf546e6ec2b9c68a68bc00848607539e77ba12dc756a912a7c"}, @@ -685,10 +682,9 @@ pydantic = {version = ">=2.12.5,<3.0.0", extras = ["email"]} name = "greenlet" version = "3.4.0" description = "Lightweight in-process concurrent programming" +category = "main" optional = false python-versions = ">=3.10" -groups = ["main"] -markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\"" files = [ {file = "greenlet-3.4.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:d18eae9a7fb0f499efcd146b8c9750a2e1f6e0e93b5a382b3481875354a430e6"}, {file = "greenlet-3.4.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:636d2f95c309e35f650e421c23297d5011716be15d966e6328b367c9fc513a82"}, @@ -759,9 +755,9 @@ test = ["objgraph", "psutil", "setuptools"] name = "h11" version = "0.16.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +category = "main" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, @@ -771,9 +767,9 @@ files = [ name = "httpcore" version = "1.0.9" description = "A minimal low-level HTTP client." +category = "main" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, @@ -786,16 +782,16 @@ h11 = ">=0.16" [package.extras] asyncio = ["anyio (>=4.0,<5.0)"] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] +socks = ["socksio (>=1.0.0,<2.0.0)"] trio = ["trio (>=0.22.0,<1.0)"] [[package]] name = "httpx" version = "0.28.1" description = "The next generation HTTP client." +category = "main" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, @@ -804,23 +800,23 @@ files = [ [package.dependencies] anyio = "*" certifi = "*" -httpcore = "==1.*" +httpcore = ">=1.0.0,<2.0.0" idna = "*" [package.extras] -brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] -cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +brotli = ["brotli", "brotlicffi"] +cli = ["click (>=8.0.0,<9.0.0)", "pygments (>=2.0.0,<3.0.0)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] +socks = ["socksio (>=1.0.0,<2.0.0)"] zstd = ["zstandard (>=0.18.0)"] [[package]] name = "identify" version = "2.6.19" description = "File identification library for Python" +category = "dev" optional = false python-versions = ">=3.10" -groups = ["dev"] files = [ {file = "identify-2.6.19-py2.py3-none-any.whl", hash = "sha256:20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a"}, {file = "identify-2.6.19.tar.gz", hash = "sha256:6be5020c38fcb07da56c53733538a3081ea5aa70d36a156f83044bfbf9173842"}, @@ -833,9 +829,9 @@ license = ["ukkonen"] name = "idna" version = "3.12" description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "idna-3.12-py3-none-any.whl", hash = "sha256:60ffaa1858fac94c9c124728c24fcde8160f3fb4a7f79aa8cdd33a9d1af60a67"}, {file = "idna-3.12.tar.gz", hash = "sha256:724e9952cc9e2bd7550ea784adb098d837ab5267ef67a1ab9cf7846bdbdd8254"}, @@ -848,9 +844,9 @@ all = ["mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] name = "iniconfig" version = "2.3.0" description = "brain-dead simple config-ini parsing" +category = "dev" optional = false python-versions = ">=3.10" -groups = ["dev"] files = [ {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}, {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}, @@ -860,9 +856,9 @@ files = [ name = "kong-admin-client" version = "3.5.0" description = "Kong Admin API" +category = "main" optional = false python-versions = "^3.7" -groups = ["main"] files = [] develop = false @@ -882,16 +878,16 @@ resolved_reference = "0524678992903864694c706ed50c0d8cad80f45a" name = "kubernetes" version = "35.0.0" description = "Kubernetes python client" +category = "main" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "kubernetes-35.0.0-py2.py3-none-any.whl", hash = "sha256:39e2b33b46e5834ef6c3985ebfe2047ab39135d41de51ce7641a7ca5b372a13d"}, {file = "kubernetes-35.0.0.tar.gz", hash = "sha256:3d00d344944239821458b9efd484d6df9f011da367ecb155dadf9513f05f09ee"}, ] [package.dependencies] -certifi = ">=14.5.14" +certifi = ">=14.05.14" durationpy = ">=0.7" python-dateutil = ">=2.5.3" pyyaml = ">=5.4.1" @@ -899,7 +895,7 @@ requests = "*" requests-oauthlib = "*" six = ">=1.9.0" urllib3 = ">=1.24.2,<2.6.0 || >2.6.0" -websocket-client = ">=0.32.0,<0.40.0 || >0.40.0,<0.41.dev0 || >=0.43.dev0" +websocket-client = ">=0.32.0,<0.40.0 || >0.40.0,<0.41.0 || >=0.43.0" [package.extras] adal = ["adal (>=1.0.2)"] @@ -909,9 +905,9 @@ google-auth = ["google-auth (>=1.0.1)"] name = "nodeenv" version = "1.10.0" description = "Node.js virtual environment builder" +category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["dev"] files = [ {file = "nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827"}, {file = "nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb"}, @@ -921,9 +917,9 @@ files = [ name = "oauthlib" version = "3.3.1" description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" +category = "main" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "oauthlib-3.3.1-py3-none-any.whl", hash = "sha256:88119c938d2b8fb88561af5f6ee0eec8cc8d552b7bb1f712743136eb7523b7a1"}, {file = "oauthlib-3.3.1.tar.gz", hash = "sha256:0f0f8aa759826a193cf66c12ea1af1637f87b9b4622d46e866952bb022e538c9"}, @@ -938,9 +934,9 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] name = "packaging" version = "26.1" description = "Core utilities for Python packages" +category = "dev" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "packaging-26.1-py3-none-any.whl", hash = "sha256:5d9c0669c6285e491e0ced2eee587eaf67b670d94a19e94e3984a481aba6802f"}, {file = "packaging-26.1.tar.gz", hash = "sha256:f042152b681c4bfac5cae2742a55e103d27ab2ec0f3d88037136b6bfe7c9c5de"}, @@ -950,9 +946,9 @@ files = [ name = "platformdirs" version = "4.9.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +category = "dev" optional = false python-versions = ">=3.10" -groups = ["dev"] files = [ {file = "platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917"}, {file = "platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a"}, @@ -962,9 +958,9 @@ files = [ name = "pluggy" version = "1.6.0" description = "plugin and hook calling mechanisms for python" +category = "dev" optional = false python-versions = ">=3.9" -groups = ["dev"] files = [ {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, @@ -976,14 +972,14 @@ testing = ["coverage", "pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "4.6.0" +version = "4.5.1" description = "A framework for managing and maintaining multi-language pre-commit hooks." +category = "dev" optional = false python-versions = ">=3.10" -groups = ["dev"] files = [ - {file = "pre_commit-4.6.0-py2.py3-none-any.whl", hash = "sha256:e2cf246f7299edcabcf15f9b0571fdce06058527f0a06535068a86d38089f29b"}, - {file = "pre_commit-4.6.0.tar.gz", hash = "sha256:718d2208cef53fdc38206e40524a6d4d9576d103eb16f0fec11c875e7716e9d9"}, + {file = "pre_commit-4.5.1-py2.py3-none-any.whl", hash = "sha256:3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77"}, + {file = "pre_commit-4.5.1.tar.gz", hash = "sha256:eb545fcff725875197837263e977ea257a402056661f09dae08e4b149b030a61"}, ] [package.dependencies] @@ -997,9 +993,9 @@ virtualenv = ">=20.10.0" name = "psycopg2-binary" version = "2.9.12" description = "psycopg2 - Python-PostgreSQL Database Adapter" +category = "main" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "psycopg2_binary-2.9.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9b818ceff717f98851a64bffd4c5eb5b3059ae280276dcecc52ac658dcf006a4"}, {file = "psycopg2_binary-2.9.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d2fa0d7caca8635c56e373055094eeda3208d901d55dd0ff5abc1d4e47f82b56"}, @@ -1074,10 +1070,9 @@ files = [ name = "pycparser" version = "3.0" description = "C parser in Python" +category = "main" optional = false python-versions = ">=3.10" -groups = ["main"] -markers = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\"" files = [ {file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"}, {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"}, @@ -1087,9 +1082,9 @@ files = [ name = "pydantic" version = "2.13.3" description = "Data validation using Python type hints" +category = "main" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "pydantic-2.13.3-py3-none-any.whl", hash = "sha256:6db14ac8dfc9a1e57f87ea2c0de670c251240f43cb0c30a5130e9720dc612927"}, {file = "pydantic-2.13.3.tar.gz", hash = "sha256:af09e9d1d09f4e7fe37145c1f577e1d61ceb9a41924bf0094a36506285d0a84d"}, @@ -1104,15 +1099,15 @@ typing-inspection = ">=0.4.2" [package.extras] email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] +timezone = ["tzdata"] [[package]] name = "pydantic-core" version = "2.46.3" description = "Core functionality for Pydantic validation and serialization" +category = "main" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "pydantic_core-2.46.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:1da3786b8018e60349680720158cc19161cc3b4bdd815beb0a321cd5ce1ad5b1"}, {file = "pydantic_core-2.46.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cc0988cb29d21bf4a9d5cf2ef970b5c0e38d8d8e107a493278c05dc6c1dda69f"}, @@ -1243,9 +1238,9 @@ typing-extensions = ">=4.14.1" name = "pygments" version = "2.20.0" description = "Pygments is a syntax highlighting package written in Python." +category = "dev" optional = false python-versions = ">=3.9" -groups = ["dev"] files = [ {file = "pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176"}, {file = "pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f"}, @@ -1258,9 +1253,9 @@ windows-terminal = ["colorama (>=0.4.6)"] name = "pyjwt" version = "2.12.1" description = "JSON Web Token implementation in Python" +category = "main" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "pyjwt-2.12.1-py3-none-any.whl", hash = "sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c"}, {file = "pyjwt-2.12.1.tar.gz", hash = "sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b"}, @@ -1279,9 +1274,9 @@ tests = ["coverage[toml] (==7.10.7)", "pytest (>=8.4.2,<9.0.0)"] name = "pytest" version = "9.0.3" description = "pytest: simple powerful testing with Python" +category = "dev" optional = false python-versions = ">=3.10" -groups = ["dev"] files = [ {file = "pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9"}, {file = "pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c"}, @@ -1303,9 +1298,9 @@ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests name = "python-dateutil" version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -1318,9 +1313,9 @@ six = ">=1.5" name = "python-discovery" version = "1.2.2" description = "Python interpreter discovery" +category = "dev" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "python_discovery-1.2.2-py3-none-any.whl", hash = "sha256:e1ae95d9af875e78f15e19aed0c6137ab1bb49c200f21f5061786490c9585c7a"}, {file = "python_discovery-1.2.2.tar.gz", hash = "sha256:876e9c57139eb757cb5878cbdd9ae5379e5d96266c99ef731119e04fffe533bb"}, @@ -1338,9 +1333,9 @@ testing = ["covdefaults (>=2.3)", "coverage (>=7.5.4)", "pytest (>=8.3.5)", "pyt name = "python-dotenv" version = "1.2.2" description = "Read key-value pairs from a .env file and set them as environment variables" +category = "main" optional = false python-versions = ">=3.10" -groups = ["main"] files = [ {file = "python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a"}, {file = "python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3"}, @@ -1353,10 +1348,9 @@ cli = ["click (>=5.0)"] name = "pywin32" version = "311" description = "Python for Window Extensions" +category = "main" optional = false python-versions = "*" -groups = ["main"] -markers = "sys_platform == \"win32\"" files = [ {file = "pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3"}, {file = "pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b"}, @@ -1384,9 +1378,9 @@ files = [ name = "pyyaml" version = "6.0.3" description = "YAML parser and emitter for Python" +category = "main" optional = false python-versions = ">=3.8" -groups = ["main", "dev"] files = [ {file = "PyYAML-6.0.3-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f"}, {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4"}, @@ -1467,9 +1461,9 @@ files = [ name = "requests" version = "2.33.1" description = "Python HTTP for Humans." +category = "main" optional = false python-versions = ">=3.10" -groups = ["main"] files = [ {file = "requests-2.33.1-py3-none-any.whl", hash = "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a"}, {file = "requests-2.33.1.tar.gz", hash = "sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517"}, @@ -1489,9 +1483,9 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<8)"] name = "requests-oauthlib" version = "2.0.0" description = "OAuthlib authentication support for Requests." +category = "main" optional = false python-versions = ">=3.4" -groups = ["main"] files = [ {file = "requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9"}, {file = "requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36"}, @@ -1508,9 +1502,9 @@ rsa = ["oauthlib[signedtoken] (>=3.0.0)"] name = "ruff" version = "0.15.11" description = "An extremely fast Python linter and code formatter, written in Rust." +category = "dev" optional = false python-versions = ">=3.7" -groups = ["dev"] files = [ {file = "ruff-0.15.11-py3-none-linux_armv6l.whl", hash = "sha256:e927cfff503135c558eb581a0c9792264aae9507904eb27809cdcff2f2c847b7"}, {file = "ruff-0.15.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7a1b5b2938d8f890b76084d4fa843604d787a912541eae85fd7e233398bbb73e"}, @@ -1536,9 +1530,9 @@ files = [ name = "six" version = "1.17.0" description = "Python 2 and 3 compatibility utilities" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, @@ -1548,9 +1542,9 @@ files = [ name = "sqlalchemy" version = "2.0.49" description = "Database Abstraction Library" +category = "main" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "sqlalchemy-2.0.49-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:42e8804962f9e6f4be2cbaedc0c3718f08f60a16910fa3d86da5a1e3b1bfe60f"}, {file = "sqlalchemy-2.0.49-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc992c6ed024c8c3c592c5fc9846a03dd68a425674900c70122c77ea16c5fb0b"}, @@ -1650,9 +1644,9 @@ sqlcipher = ["sqlcipher3_binary"] name = "starlette" version = "1.0.0" description = "The little ASGI library that shines." +category = "main" optional = false python-versions = ">=3.10" -groups = ["main"] files = [ {file = "starlette-1.0.0-py3-none-any.whl", hash = "sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b"}, {file = "starlette-1.0.0.tar.gz", hash = "sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149"}, @@ -1669,10 +1663,9 @@ full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart name = "tomli" version = "2.4.1" description = "A lil' TOML parser" +category = "dev" optional = false python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version == \"3.10\"" files = [ {file = "tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30"}, {file = "tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a"}, @@ -1727,9 +1720,9 @@ files = [ name = "truststore" version = "0.10.4" description = "Verify certificates using native system trust stores" +category = "main" optional = false python-versions = ">=3.10" -groups = ["main"] files = [ {file = "truststore-0.10.4-py3-none-any.whl", hash = "sha256:adaeaecf1cbb5f4de3b1959b42d41f6fab57b2b1666adb59e89cb0b53361d981"}, {file = "truststore-0.10.4.tar.gz", hash = "sha256:9d91bd436463ad5e4ee4aba766628dd6cd7010cf3e2461756b3303710eebc301"}, @@ -1739,22 +1732,21 @@ files = [ name = "typing-extensions" version = "4.15.0" description = "Backported and Experimental Type Hints for Python 3.9+" +category = "main" optional = false python-versions = ">=3.9" -groups = ["main", "dev"] files = [ {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, ] -markers = {dev = "python_version == \"3.10\""} [[package]] name = "typing-inspection" version = "0.4.2" description = "Runtime typing introspection tools" +category = "main" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"}, {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"}, @@ -1767,27 +1759,27 @@ typing-extensions = ">=4.12.0" name = "urllib3" version = "2.6.3" description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4"}, {file = "urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed"}, ] [package.extras] -brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.0) ; platform_python_implementation != \"CPython\""] +brotli = ["brotli (>=1.2.0)", "brotlicffi (>=1.2.0.0)"] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] +zstd = ["backports-zstd (>=1.0.0)"] [[package]] name = "uvicorn" version = "0.44.0" description = "The lightning-fast ASGI server." +category = "main" optional = false python-versions = ">=3.10" -groups = ["main"] files = [ {file = "uvicorn-0.44.0-py3-none-any.whl", hash = "sha256:ce937c99a2cc70279556967274414c087888e8cec9f9c94644dfca11bd3ced89"}, {file = "uvicorn-0.44.0.tar.gz", hash = "sha256:6c942071b68f07e178264b9152f1f16dfac5da85880c4ce06366a96d70d4f31e"}, @@ -1799,15 +1791,15 @@ h11 = ">=0.8" typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} [package.extras] -standard = ["colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.15.1) ; sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"", "watchfiles (>=0.20)", "websockets (>=10.4)"] +standard = ["colorama (>=0.4)", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.15.1)", "watchfiles (>=0.20)", "websockets (>=10.4)"] [[package]] name = "virtualenv" version = "21.2.4" description = "Virtual Python Environment builder" +category = "dev" optional = false python-versions = ">=3.8" -groups = ["dev"] files = [ {file = "virtualenv-21.2.4-py3-none-any.whl", hash = "sha256:29d21e941795206138d0f22f4e45ff7050e5da6c6472299fb7103318763861ac"}, {file = "virtualenv-21.2.4.tar.gz", hash = "sha256:b294ef68192638004d72524ce7ef303e9d0cf5a44c95ce2e54a7500a6381cada"}, @@ -1824,9 +1816,9 @@ typing-extensions = {version = ">=4.13.2", markers = "python_version < \"3.11\"" name = "websocket-client" version = "1.9.0" description = "WebSocket client for Python with low level API options" +category = "main" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef"}, {file = "websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98"}, @@ -1838,6 +1830,6 @@ optional = ["python-socks", "wsaccel"] test = ["pytest", "websockets"] [metadata] -lock-version = "2.1" +lock-version = "2.0" python-versions = ">=3.10,<4.0" content-hash = "89ba097b2444a09843cabd2693b3ee180bc527e3cfe81430f493978ffa495792" diff --git a/src/k8s/kubernetes.py b/src/k8s/kubernetes.py index 5aec805..259185a 100644 --- a/src/k8s/kubernetes.py +++ b/src/k8s/kubernetes.py @@ -101,6 +101,10 @@ def create_analysis_deployment(name: str, if env is not None else []) containers.append(container) + net_stats_container = _build_net_stats_container(name) + if net_stats_container is not None: + containers.append(net_stats_container) + labels = {'app': name, 'component': "flame-analysis"} depl_metadata = client.V1ObjectMeta(name=name, namespace=namespace, labels=labels) depl_pod_metadata = client.V1ObjectMeta(labels=labels) @@ -241,6 +245,42 @@ def get_pod_status(deployment_name: str, namespace: str = 'default') -> Optional return None +def _build_net_stats_container(analysis_name: str) -> Optional[client.V1Container]: + """Build the net-stats sidecar container spec, or return None if disabled. + + Controlled by the ``NET_STATS_ENABLED`` env var. Image is read from + ``NET_STATS_IMAGE``. Emits a single cumulative log on SIGTERM. + """ + if os.getenv('NET_STATS_ENABLED', '').lower() not in ('1', 'true'): + return None + + _NET_STATS_SCRIPT = """\ + iface=$(grep -v -e lo -e 'Inter' -e 'face' /proc/net/dev | awk -F: '{print $1}' | tr -d ' ' | head -1) + line=$(grep "${iface}:" /proc/net/dev | tr -s ' ') + start_rx=$(echo $line | cut -d' ' -f2) + start_tx=$(echo $line | cut -d' ' -f10) + + handle_term() { + line=$(grep "${iface}:" /proc/net/dev | tr -s ' ') + rx=$(echo $line | cut -d' ' -f2) + tx=$(echo $line | cut -d' ' -f10) + printf '{"level":"info","message":"network_stats","bytes_in":%d,"bytes_out":%d,"interface":"%s","event_name":"netstats.analysis.traffic"}\\n' $((rx - start_rx)) $((tx - start_tx)) "$iface" + sleep 5 + exit 0 + } + trap handle_term TERM INT + + while true; do sleep 3600 & wait $!; done + """ + + return client.V1Container( + name=f'net-stats-{analysis_name}', + image=os.getenv('NET_STATS_IMAGE', 'busybox:1.37'), + image_pull_policy='IfNotPresent', + command=['/bin/sh', '-c', _NET_STATS_SCRIPT], + ) + + def _create_analysis_nginx_deployment(analysis_name: str, analysis_service_name: str, analysis_env: Optional[dict[str, str]] = None, diff --git a/src/resources/utils.py b/src/resources/utils.py index 77f49c1..c5c2c4a 100644 --- a/src/resources/utils.py +++ b/src/resources/utils.py @@ -24,9 +24,6 @@ logger = get_logger() -_MAX_UNSTUCK_REATTEMPTS = 10 - - def create_analysis(body: Union[CreateAnalysis, str], database: Database) -> dict[str, str]: """Create and start a new analysis deployment. @@ -272,8 +269,7 @@ def unstuck_analysis_deployments(analysis_id: str, database: Database) -> None: Waits 10 seconds between stop and recreate to let Kubernetes settle, then prunes historical deployment rows so only the latest one remains. """ - deployment = database.get_latest_deployment(analysis_id) - if deployment is not None: + if database.get_latest_deployment(analysis_id) is not None: stop_analysis(analysis_id, database) success = False for i in range(_MAX_UNSTUCK_REATTEMPTS):