From d5df8bbda077cdfa5f82fd74f524f2815656fdea Mon Sep 17 00:00:00 2001 From: Kevin Postlethwait Date: Thu, 13 Jan 2022 16:56:28 -0500 Subject: [PATCH] move adviser requests from keb admin to investigator --- .pre-commit-config.yaml | 3 + Pipfile | 9 +- Pipfile.lock | 1079 +++++++++++++---- consumer.py | 12 +- .../get_installation_token_success.json | 134 ++ .../get_repo_installation_success.json | 50 + tests/github_service_test.py | 63 + tests/investigate_unresolved_package_test.py | 2 +- tests/keys/jwt-key | 52 + tests/keys/jwt-key.pub | 14 + thoth/investigator/common.py | 72 +- .../cve_provided/investigate_cve_provided.py | 59 +- .../cve_provided/metrics_cve_provided.py | 3 +- thoth/investigator/github_service.py | 267 ++++ .../investigate_hash_mismatch.py | 56 +- .../hash_mismatch/metrics_hash_mismatch.py | 3 +- thoth/investigator/metrics.py | 7 + .../investigate_missing_package.py | 48 +- .../metrics_missing_package.py | 3 +- .../investigate_missing_version.py | 58 +- .../metrics_missing_version.py | 3 +- .../investigate_solved_package.py | 57 +- .../solved_package/metrics_solved_package.py | 3 +- 23 files changed, 1658 insertions(+), 399 deletions(-) create mode 100644 tests/github_api_responses/get_installation_token_success.json create mode 100644 tests/github_api_responses/get_repo_installation_success.json create mode 100644 tests/github_service_test.py create mode 100644 tests/keys/jwt-key create mode 100644 tests/keys/jwt-key.pub create mode 100644 thoth/investigator/github_service.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2121ecc5..ce88b5b4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,6 +20,7 @@ repos: - id: check-yaml - id: debug-statements - id: detect-private-key + exclude: tests/keys/ - id: end-of-file-fixer - id: name-tests-test - id: trailing-whitespace @@ -28,6 +29,8 @@ repos: rev: 6.1.1 hooks: - id: pydocstyle + exclude: ^tests/ + additional_dependencies: ["toml"] - repo: https://github.com/psf/black rev: 22.3.0 diff --git a/Pipfile b/Pipfile index 8ec31e2e..b065fc1f 100644 --- a/Pipfile +++ b/Pipfile @@ -11,16 +11,23 @@ prometheus-async = "*" confluent-kafka = "*" thoth-common = "*" thoth-messaging = "*" +aiohttp = "*" +pyjwt = "*" +thamos = "*" +semver = "*" +types-pyyaml = "*" +cryptography = "*" [dev-packages] pytest = "*" pytest-timeout = "*" pytest-cov = "*" hypothesis-auto = "*" -hypothesis = "*" +hypothesis = "<6.47" pytest-mypy = "*" mypy = "*" pre-commit = "==2.0.1" +pytest-aiohttp = "*" [requires] python_version = "3.8" diff --git a/Pipfile.lock b/Pipfile.lock index f34fab68..065c62b1 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "6fbe567aefa3fd94b058b8f1c407e2a54b9b71f3fbdf625c591cb021528a8770" + "sha256": "4135ff13e655cafe7ca9ebb4fb849d6e7fbe356d6721cdcd1e0e7e1a75c6f5bb" }, "pipfile-spec": 6, "requires": { @@ -91,7 +91,7 @@ "sha256:fa0ffcace9b3aa34d205d8130f7873fcfefcb6a4dd3dd705b0dab69af6712642", "sha256:fc5471e1a54de15ef71c1bc6ebe80d4dc681ea600e68bfd1cbce40427f0b7578" ], - "markers": "python_version >= '3.6'", + "index": "pypi", "version": "==3.8.1" }, "aiosignal": { @@ -104,11 +104,11 @@ }, "alembic": { "hashes": [ - "sha256:29be0856ec7591c39f4e1cb10f198045d890e6e2274cf8da80cb5e721a09642b", - "sha256:4961248173ead7ce8a21efb3de378f13b8398e6630fab0eb258dc74a8af24c58" + "sha256:a2d4d90da70b30e70352cd9455e35873a255a31402a438fe24815758d7a0e5e1", + "sha256:b5ae4bbfc7d1302ed413989d39474d102e7cfa158f6d5969d2497955ffe85a30" ], - "markers": "python_version >= '3.6'", - "version": "==1.7.7" + "markers": "python_version >= '3.7'", + "version": "==1.8.0" }, "amun": { "hashes": [ @@ -179,98 +179,112 @@ }, "boto3": { "hashes": [ - "sha256:5b05d219db06cca7d372cef2cdbbee5acfec23cb1f8dcbbfa95c5fa098269c7f", - "sha256:9e44d22a9cfb72e84add3ce1580e6dfef6a67321da0b958f7f33411de468a7ea" + "sha256:551e902b70ccf9f6a58e28bb409718a0403b021b17ff6d63ab0b9af5a122386e", + "sha256:abe5b44010e3f50c5e0243aa4fc2338f10e5a868413faa0d6ae79131d6b507b8" ], - "markers": "python_version >= '3.6'", - "version": "==1.23.9" + "markers": "python_version >= '3.7'", + "version": "==1.24.21" }, "botocore": { "hashes": [ - "sha256:5df2cf7ebe34377470172bd0bbc582cf98c5cbd02da0909a14e9e2885ab3ae9c", - "sha256:8a4a984bf901ccefe40037da11ba2abd1ddbcb3b490a492b7f218509c99fc12f" + "sha256:3bafa8e773d207c0ce02c63790a8820562e22d2e892abaf1eb90c343e995218a", + "sha256:b685ffc0ac170bf7de5fde931504eccd939f8545a9c9d10259245ca4c91101e5" ], - "markers": "python_version >= '3.6'", - "version": "==1.26.10" + "markers": "python_version >= '3.7'", + "version": "==1.27.21" }, "cachetools": { "hashes": [ - "sha256:4ebbd38701cdfd3603d1f751d851ed248ab4570929f2d8a7ce69e30c420b141c", - "sha256:8b3b8fa53f564762e5b221e9896798951e7f915513abf2ba072ce0f07f3f5a98" + "sha256:6a94c6402995a99c3970cc7e4884bb60b4a8639938157eeed436098bf9831757", + "sha256:f9f17d2aec496a9aa6b76f53e3b614c965223c061982d434d160f930c698a9db" ], "markers": "python_version ~= '3.7'", - "version": "==5.1.0" + "version": "==5.2.0" }, "certifi": { "hashes": [ - "sha256:9c5705e395cd70084351dd8ad5c41e65655e08ce46f2ec9cf6c2c08390f71eb7", - "sha256:f1d53542ee8cbedbe2118b5686372fb33c297fcd6379b050cca0ef13a597382a" + "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d", + "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412" ], "markers": "python_version >= '3.6'", - "version": "==2022.5.18.1" + "version": "==2022.6.15" }, "cffi": { "hashes": [ - "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3", - "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2", - "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636", - "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20", - "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728", - "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27", - "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66", - "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443", - "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0", - "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7", - "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39", - "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605", - "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a", - "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37", - "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029", - "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139", - "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc", - "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df", - "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14", - "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880", - "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2", - "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a", - "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e", - "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474", - "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024", - "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8", - "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0", - "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e", - "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a", - "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e", - "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032", - "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6", - "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e", - "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b", - "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e", - "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954", - "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962", - "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c", - "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4", - "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55", - "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962", - "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023", - "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c", - "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6", - "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8", - "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382", - "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7", - "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc", - "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997", - "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796" - ], - "version": "==1.15.0" + "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5", + "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef", + "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104", + "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426", + "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405", + "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375", + "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a", + "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e", + "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc", + "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf", + "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185", + "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497", + "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3", + "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35", + "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c", + "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83", + "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21", + "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca", + "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984", + "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac", + "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd", + "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee", + "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a", + "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2", + "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192", + "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7", + "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585", + "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f", + "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e", + "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27", + "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b", + "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e", + "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e", + "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d", + "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c", + "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415", + "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82", + "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02", + "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314", + "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325", + "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c", + "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3", + "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914", + "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045", + "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d", + "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9", + "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5", + "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2", + "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c", + "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3", + "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2", + "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8", + "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d", + "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d", + "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9", + "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162", + "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76", + "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4", + "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e", + "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9", + "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6", + "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b", + "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01", + "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0" + ], + "version": "==1.15.1" }, "charset-normalizer": { "hashes": [ - "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597", - "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df" + "sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5", + "sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413" ], - "markers": "python_version >= '3'", - "version": "==2.0.12" + "markers": "python_version >= '3.6'", + "version": "==2.1.0" }, "click": { "hashes": [ @@ -280,35 +294,74 @@ "markers": "python_version >= '3.7'", "version": "==8.1.3" }, + "commonmark": { + "hashes": [ + "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60", + "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9" + ], + "version": "==0.9.1" + }, "confluent-kafka": { "hashes": [ - "sha256:02b78bb6d1199ea350240eae1f4415f22014896199a46edf85f779a69751f984", - "sha256:039c68379f9a5ece6e45a683ec7abebb95a9dac904ec4e2f9d93738e1cf6fab2", - "sha256:1df83fa20e4fe032651ad73ce0ba85dd14a7fabff6066c9cb20e944d2748e72b", - "sha256:3d66e8c1a6a15144ca5b176170adbf30207c27813c76202c56abf52ef2b475e1", - "sha256:4f26052ef53212752039cd1d9e932b2feb6a0975d717ab070af323629a72a0b9", - "sha256:585bc8e8aa7d6fbd46dc0b2da3d4b1fd8457555288fee1ecba6af2c97ab738cc", - "sha256:748813f47641dd65dd8d3bae8dcb3ce96a3e455c12b467d4b35e1fc880362d01", - "sha256:ac7155e1b9a94445ed8eecf691c80c61407148813808a2aa1cba0babbe197e77", - "sha256:add05db627435697d4ed8f81b3ce1081931770813a989fd775910865f07d694d", - "sha256:ae75d3f4bc3d2109663912d77911c45aaa2939bde3694fc05e75842c806fa760", - "sha256:b679c3f9f555e87a9cbb043c676473c30d12182609e075be85afd98f84bcc863", - "sha256:b79e836c3554bc51c6837a8a0152f7521c9bf31342f5b8e21eba6b28044fa585", - "sha256:b7cb6fa3d44972e3670e0b3b054186a6006e6fd664600cfe70e008fad2443d16", - "sha256:d50b091770d277714766943d885ad6b2c5c427e67328706cfd33dc86eef540c9", - "sha256:e49382a943fb47813f421e913cc6c87cd1d4bfdecad1785efa0dacada7003d84", - "sha256:ead7f18c516f7bcb886b643fa78ff2a2142270adaf931ba0311b62e9a047e6ca", - "sha256:f843680e183479f6e0732b593ea3235c836a5bb2de6be3819a11b891b6af1dde" + "sha256:066856f43b248c6634f43a01bb5798c1acf8553fcad0ee04f353643a2473b788", + "sha256:0eca04a9321de8172a5563d79ee3d09b93ec5811616502361af96b22070465ef", + "sha256:1446e5d8502694f4a9140ace087567b85300bd9766a532e006f2f6e9c6e99284", + "sha256:2008aeca66112722d3bcbff0baa40e129bdc6747755d5e71409493f2b56ffa36", + "sha256:2f87004473718d1976f57c9e23307c216daf8cbd47ffa7115ef0ce48963c9c69", + "sha256:41590186d9528b4a9e3a6116551918471f41e82f54438742f1c8ecbe2441d1c3", + "sha256:45fa3b9d4d015c099dcb5fd77cbc0d40f6683afe9a9b279c82fb0ed814e11724", + "sha256:49312cd1dce9963578669412831c55a83dc42ced0af975fe8a885860d4439505", + "sha256:4a93eccaab455ab4ad70cdd22f2e15b9fd5607a019dd08cd95b04308193f84cb", + "sha256:5559cb175cb668f53e4a053d921a06393aaf2a16b14cd807439e93d7100b1594", + "sha256:7cec61388faf7d122ae0bfb7948bdb1333ad8bd95a6cdc50eac97342e0faff75", + "sha256:80b87db486566067f7a24955f33db0fe74af977938c917216fe709b0332f668e", + "sha256:9ea5916b7537e5679011387336c101433567587d3862351e75c8bb8d0dc3d838", + "sha256:c3bfe2a13efb0bb810146466175038c0202b8e5f14a9a37ca494bbd777f26870", + "sha256:dee2f5d3a193dd0b5500e4e129b7da9f662b49f5a9b8a13cb6b8af72c69c534b", + "sha256:e1e0aeaff2afba8138d5c103589bde1c3d8f870606d00115df03adffbffd368f", + "sha256:f46a445556831a23b356bcc6211aab8a09b5e709ec956bce01237b3152eeb166", + "sha256:f85c80a6b37bf60caa8118d2be205380e037e389769ee92b15cc733e3044e17a", + "sha256:fa1cbc113809a0aa1f8b33c4ec2cf246fcbc329c3b9e40054514d4c95ffd44e4", + "sha256:fb23fd087695cf1753a43bf77173e9c87f535b9293b94b7f29f17461c1ba9eb5", + "sha256:fdca4a62ed61ae8d77758f3df163c7959a1757a2cd37f0f54a15f7f347841b59" + ], + "index": "pypi", + "version": "==1.9.0" + }, + "cryptography": { + "hashes": [ + "sha256:093cb351031656d3ee2f4fa1be579a8c69c754cf874206be1d4cf3b542042804", + "sha256:0cc20f655157d4cfc7bada909dc5cc228211b075ba8407c46467f63597c78178", + "sha256:1b9362d34363f2c71b7853f6251219298124aa4cc2075ae2932e64c91a3e2717", + "sha256:1f3bfbd611db5cb58ca82f3deb35e83af34bb8cf06043fa61500157d50a70982", + "sha256:2bd1096476aaac820426239ab534b636c77d71af66c547b9ddcd76eb9c79e004", + "sha256:31fe38d14d2e5f787e0aecef831457da6cec68e0bb09a35835b0b44ae8b988fe", + "sha256:3b8398b3d0efc420e777c40c16764d6870bcef2eb383df9c6dbb9ffe12c64452", + "sha256:3c81599befb4d4f3d7648ed3217e00d21a9341a9a688ecdd615ff72ffbed7336", + "sha256:419c57d7b63f5ec38b1199a9521d77d7d1754eb97827bbb773162073ccd8c8d4", + "sha256:46f4c544f6557a2fefa7ac8ac7d1b17bf9b647bd20b16decc8fbcab7117fbc15", + "sha256:471e0d70201c069f74c837983189949aa0d24bb2d751b57e26e3761f2f782b8d", + "sha256:59b281eab51e1b6b6afa525af2bd93c16d49358404f814fe2c2410058623928c", + "sha256:731c8abd27693323b348518ed0e0705713a36d79fdbd969ad968fbef0979a7e0", + "sha256:95e590dd70642eb2079d280420a888190aa040ad20f19ec8c6e097e38aa29e06", + "sha256:a68254dd88021f24a68b613d8c51d5c5e74d735878b9e32cc0adf19d1f10aaf9", + "sha256:a7d5137e556cc0ea418dca6186deabe9129cee318618eb1ffecbd35bee55ddc1", + "sha256:aeaba7b5e756ea52c8861c133c596afe93dd716cbcacae23b80bc238202dc023", + "sha256:dc26bb134452081859aa21d4990474ddb7e863aa39e60d1592800a8865a702de", + "sha256:e53258e69874a306fcecb88b7534d61820db8a98655662a3dd2ec7f1afd9132f", + "sha256:ef15c2df7656763b4ff20a9bc4381d8352e6640cfeb95c2972c38ef508e75181", + "sha256:f224ad253cc9cea7568f49077007d2263efa57396a2f2f78114066fd54b5c68e", + "sha256:f8ec91983e638a9bcd75b39f1396e5c0dc2330cbd9ce4accefe68717e6779e0a" ], "index": "pypi", - "version": "==1.8.2" + "version": "==37.0.2" }, "daiquiri": { "hashes": [ - "sha256:0ab561a11f4dbd2e73de9d7890eef45b46be2cfdaef0b5fbf01b8b9f093d5242", - "sha256:70995a0f7a2d5a62ec5498ffeef733dca47e10cc96ee6331fba5f6ec0387e6fb" + "sha256:37eecf852657d2ae8a2a4700215bd4498e5afabd32d2d622c1a8b4f255de9881", + "sha256:6252f83db9d29f1826208369c047e90e51ccbd4ee5150b5c12c16e9d8412d175" ], - "version": "==3.0.1" + "version": "==3.2.0" }, "delegator.py": { "hashes": [ @@ -324,6 +377,13 @@ ], "version": "==0.9.0" }, + "distlib": { + "hashes": [ + "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b", + "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579" + ], + "version": "==0.3.4" + }, "distro": { "hashes": [ "sha256:151aeccf60c216402932b52e40ee477a939f8d58898927378a02abbe852c1c39", @@ -332,6 +392,14 @@ "markers": "python_version >= '3.6'", "version": "==1.7.0" }, + "filelock": { + "hashes": [ + "sha256:37def7b658813cda163b56fc564cdc75e86d338246458c4c28ae84cabefa2404", + "sha256:3a0fd85166ad9dbab54c9aec96737b744106dc5f15c0b09a6744a445299fcf04" + ], + "markers": "python_version >= '3.7'", + "version": "==3.7.1" + }, "frozenlist": { "hashes": [ "sha256:006d3595e7d4108a12025ddf415ae0f6c9e736e726a5db0183326fd191b14c5e", @@ -399,35 +467,42 @@ }, "google-auth": { "hashes": [ - "sha256:1ba4938e032b73deb51e59c4656a00e0939cf0b1112575099f136babb4563312", - "sha256:349ac49b18b01019453cc99c11c92ed772739778c92f184002b7ab3a5b7ac77d" + "sha256:3b2f9d2f436cc7c3b363d0ac66470f42fede249c3bafcc504e9f0bcbe983cff0", + "sha256:75b3977e7e22784607e074800048f44d6a56df589fb2abe58a11d4d20c97c314" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==2.6.6" + "version": "==2.9.0" }, "idna": { "hashes": [ "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" ], - "markers": "python_version >= '3'", + "markers": "python_version >= '3.5'", "version": "==3.3" }, "importlib-metadata": { "hashes": [ - "sha256:5d26852efe48c0a32b0509ffbc583fda1a2266545a78d104a6f4aff3db17d700", - "sha256:c58c8eb8a762858f49e18436ff552e83914778e50e9d2f1660535ffb364552ec" + "sha256:637245b8bab2b6502fcbc752cc4b7a6f6243bb02b31c5c26156ad103d3d45670", + "sha256:7401a975809ea1fdc658c3aa4f78cc2195a0e019c5cbc4c06122884e9ae80c23" ], "markers": "python_version < '3.9'", - "version": "==4.11.4" + "version": "==4.12.0" }, "importlib-resources": { "hashes": [ - "sha256:b6062987dfc51f0fcb809187cffbd60f35df7acb4589091f154214af6d0d49d3", - "sha256:e447dc01619b1e951286f3929be820029d48c75eb25d265c28b92a16548212b8" + "sha256:568c9f16cb204f9decc8d6d24a572eeea27dacbb4cee9e6b03a8025736769751", + "sha256:7952325ffd516c05a8ad0858c74dff2c3343f136fe66a6002b2623dd1d43f223" ], "markers": "python_version < '3.9'", - "version": "==5.7.1" + "version": "==5.8.0" + }, + "invectio": { + "hashes": [ + "sha256:888653e92fb4901bf9825ccc3e76fc0749f05f716e9007f1e6bdda066580b756", + "sha256:ea1da827514c3976d9bf85c1365ee96f51623e6407aedc77fa8ceba14335687e" + ], + "version": "==0.2.1" }, "jinja2": { "hashes": [ @@ -439,11 +514,11 @@ }, "jmespath": { "hashes": [ - "sha256:a490e280edd1f57d6de88636992d05b71e97d69a26a19f058ecf7d304474bf5e", - "sha256:e8dcd576ed616f14ec02eed0005c85973b5890083313860136657e24784e4c04" + "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", + "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe" ], "markers": "python_version >= '3.7'", - "version": "==1.0.0" + "version": "==1.0.1" }, "jsonformatter": { "hashes": [ @@ -452,6 +527,14 @@ "markers": "python_version >= '2.7'", "version": "==0.3.1" }, + "jsonschema": { + "hashes": [ + "sha256:5eb781753403847fb320f05e9ab2191725b58c5e7f97f1bed63285ca423159bc", + "sha256:ec2802e6a37517f09d47d9ba107947589ae1d25ff557b925d83a321fc2aa5d3b" + ], + "markers": "python_version >= '3.7'", + "version": "==4.6.1" + }, "kubernetes": { "hashes": [ "sha256:1a2472f8b01bc6aa87e3a34781f859bded5a5c8ff791a53d889a8bd6cc550430", @@ -461,78 +544,80 @@ }, "lxml": { "hashes": [ - "sha256:078306d19a33920004addeb5f4630781aaeabb6a8d01398045fcde085091a169", - "sha256:0c1978ff1fd81ed9dcbba4f91cf09faf1f8082c9d72eb122e92294716c605428", - "sha256:1010042bfcac2b2dc6098260a2ed022968dbdfaf285fc65a3acf8e4eb1ffd1bc", - "sha256:1d650812b52d98679ed6c6b3b55cbb8fe5a5460a0aef29aeb08dc0b44577df85", - "sha256:20b8a746a026017acf07da39fdb10aa80ad9877046c9182442bf80c84a1c4696", - "sha256:2403a6d6fb61c285969b71f4a3527873fe93fd0abe0832d858a17fe68c8fa507", - "sha256:24f5c5ae618395ed871b3d8ebfcbb36e3f1091fd847bf54c4de623f9107942f3", - "sha256:28d1af847786f68bec57961f31221125c29d6f52d9187c01cd34dc14e2b29430", - "sha256:31499847fc5f73ee17dbe1b8e24c6dafc4e8d5b48803d17d22988976b0171f03", - "sha256:31ba2cbc64516dcdd6c24418daa7abff989ddf3ba6d3ea6f6ce6f2ed6e754ec9", - "sha256:330bff92c26d4aee79c5bc4d9967858bdbe73fdbdbacb5daf623a03a914fe05b", - "sha256:5045ee1ccd45a89c4daec1160217d363fcd23811e26734688007c26f28c9e9e7", - "sha256:52cbf2ff155b19dc4d4100f7442f6a697938bf4493f8d3b0c51d45568d5666b5", - "sha256:530f278849031b0eb12f46cca0e5db01cfe5177ab13bd6878c6e739319bae654", - "sha256:545bd39c9481f2e3f2727c78c169425efbfb3fbba6e7db4f46a80ebb249819ca", - "sha256:5804e04feb4e61babf3911c2a974a5b86f66ee227cc5006230b00ac6d285b3a9", - "sha256:5a58d0b12f5053e270510bf12f753a76aaf3d74c453c00942ed7d2c804ca845c", - "sha256:5f148b0c6133fb928503cfcdfdba395010f997aa44bcf6474fcdd0c5398d9b63", - "sha256:5f7d7d9afc7b293147e2d506a4596641d60181a35279ef3aa5778d0d9d9123fe", - "sha256:60d2f60bd5a2a979df28ab309352cdcf8181bda0cca4529769a945f09aba06f9", - "sha256:6259b511b0f2527e6d55ad87acc1c07b3cbffc3d5e050d7e7bcfa151b8202df9", - "sha256:6268e27873a3d191849204d00d03f65c0e343b3bcb518a6eaae05677c95621d1", - "sha256:627e79894770783c129cc5e89b947e52aa26e8e0557c7e205368a809da4b7939", - "sha256:62f93eac69ec0f4be98d1b96f4d6b964855b8255c345c17ff12c20b93f247b68", - "sha256:6d6483b1229470e1d8835e52e0ff3c6973b9b97b24cd1c116dca90b57a2cc613", - "sha256:6f7b82934c08e28a2d537d870293236b1000d94d0b4583825ab9649aef7ddf63", - "sha256:6fe4ef4402df0250b75ba876c3795510d782def5c1e63890bde02d622570d39e", - "sha256:719544565c2937c21a6f76d520e6e52b726d132815adb3447ccffbe9f44203c4", - "sha256:730766072fd5dcb219dd2b95c4c49752a54f00157f322bc6d71f7d2a31fecd79", - "sha256:74eb65ec61e3c7c019d7169387d1b6ffcfea1b9ec5894d116a9a903636e4a0b1", - "sha256:7993232bd4044392c47779a3c7e8889fea6883be46281d45a81451acfd704d7e", - "sha256:80bbaddf2baab7e6de4bc47405e34948e694a9efe0861c61cdc23aa774fcb141", - "sha256:86545e351e879d0b72b620db6a3b96346921fa87b3d366d6c074e5a9a0b8dadb", - "sha256:891dc8f522d7059ff0024cd3ae79fd224752676447f9c678f2a5c14b84d9a939", - "sha256:8a31f24e2a0b6317f33aafbb2f0895c0bce772980ae60c2c640d82caac49628a", - "sha256:8b99ec73073b37f9ebe8caf399001848fced9c08064effdbfc4da2b5a8d07b93", - "sha256:986b7a96228c9b4942ec420eff37556c5777bfba6758edcb95421e4a614b57f9", - "sha256:a1547ff4b8a833511eeaceacbcd17b043214fcdb385148f9c1bc5556ca9623e2", - "sha256:a2bfc7e2a0601b475477c954bf167dee6d0f55cb167e3f3e7cefad906e7759f6", - "sha256:a3c5f1a719aa11866ffc530d54ad965063a8cbbecae6515acbd5f0fae8f48eaa", - "sha256:a9f1c3489736ff8e1c7652e9dc39f80cff820f23624f23d9eab6e122ac99b150", - "sha256:aa0cf4922da7a3c905d000b35065df6184c0dc1d866dd3b86fd961905bbad2ea", - "sha256:ad4332a532e2d5acb231a2e5d33f943750091ee435daffca3fec0a53224e7e33", - "sha256:b2582b238e1658c4061ebe1b4df53c435190d22457642377fd0cb30685cdfb76", - "sha256:b6fc2e2fb6f532cf48b5fed57567ef286addcef38c28874458a41b7837a57807", - "sha256:b92d40121dcbd74831b690a75533da703750f7041b4bf951befc657c37e5695a", - "sha256:bbab6faf6568484707acc052f4dfc3802bdb0cafe079383fbaa23f1cdae9ecd4", - "sha256:c0b88ed1ae66777a798dc54f627e32d3b81c8009967c63993c450ee4cbcbec15", - "sha256:ce13d6291a5f47c1c8dbd375baa78551053bc6b5e5c0e9bb8e39c0a8359fd52f", - "sha256:db3535733f59e5605a88a706824dfcb9bd06725e709ecb017e165fc1d6e7d429", - "sha256:dd10383f1d6b7edf247d0960a3db274c07e96cf3a3fc7c41c8448f93eac3fb1c", - "sha256:e01f9531ba5420838c801c21c1b0f45dbc9607cb22ea2cf132844453bec863a5", - "sha256:e11527dc23d5ef44d76fef11213215c34f36af1608074561fcc561d983aeb870", - "sha256:e1ab2fac607842ac36864e358c42feb0960ae62c34aa4caaf12ada0a1fb5d99b", - "sha256:e1fd7d2fe11f1cb63d3336d147c852f6d07de0d0020d704c6031b46a30b02ca8", - "sha256:e9f84ed9f4d50b74fbc77298ee5c870f67cb7e91dcdc1a6915cb1ff6a317476c", - "sha256:ec4b4e75fc68da9dc0ed73dcdb431c25c57775383fec325d23a770a64e7ebc87", - "sha256:f10ce66fcdeb3543df51d423ede7e238be98412232fca5daec3e54bcd16b8da0", - "sha256:f63f62fc60e6228a4ca9abae28228f35e1bd3ce675013d1dfb828688d50c6e23", - "sha256:fa56bb08b3dd8eac3a8c5b7d075c94e74f755fd9d8a04543ae8d37b1612dd170", - "sha256:fa9b7c450be85bfc6cd39f6df8c5b8cbd76b5d6fc1f69efec80203f9894b885f" + "sha256:00f3a6f88fd5f4357844dd91a1abac5f466c6799f1b7f1da2df6665253845b11", + "sha256:024684e0c5cfa121c22140d3a0898a3a9b2ea0f0fd2c229b6658af4bdf1155e5", + "sha256:03370ec37fe562238d385e2c53089076dee53aabf8325cab964fdb04a9130fa0", + "sha256:0aa4cce579512c33373ca4c5e23c21e40c1aa1a33533a75e51b654834fd0e4f2", + "sha256:1057356b808d149bc14eb8f37bb89129f237df488661c1e0fc0376ca90e1d2c3", + "sha256:11d62c97ceff9bab94b6b29c010ea5fb6831743459bb759c917f49ba75601cd0", + "sha256:1254a79f8a67a3908de725caf59eae62d86738f6387b0a34b32e02abd6ae73db", + "sha256:1bfb791a8fcdbf55d1d41b8be940393687bec0e9b12733f0796668086d1a23ff", + "sha256:28cf04a1a38e961d4a764d2940af9b941b66263ed5584392ef875ee9c1e360a3", + "sha256:2b9c2341d96926b0d0e132e5c49ef85eb53fa92ae1c3a70f9072f3db0d32bc07", + "sha256:2d10659e6e5c53298e6d718fd126e793285bff904bb71d7239a17218f6a197b7", + "sha256:3af00ee88376022589ceeb8170eb67dacf5f7cd625ea59fa0977d719777d4ae8", + "sha256:3cf816aed8125cfc9e6e5c6c31ff94278320d591bd7970c4a0233bee0d1c8790", + "sha256:4becd16750ca5c2a1b1588269322b2cebd10c07738f336c922b658dbab96a61c", + "sha256:4cd69bca464e892ea4ed544ba6a7850aaff6f8d792f8055a10638db60acbac18", + "sha256:4e97c8fc761ad63909198acc892f34c20f37f3baa2c50a62d5ec5d7f1efc68a1", + "sha256:520461c36727268a989790aef08884347cd41f2d8ae855489ccf40b50321d8d7", + "sha256:53b0410b220766321759f7f9066da67b1d0d4a7f6636a477984cbb1d98483955", + "sha256:56e19fb6e4b8bd07fb20028d03d3bc67bcc0621347fbde64f248e44839771756", + "sha256:5a49ad78543925e1a4196e20c9c54492afa4f1502c2a563f73097e2044c75190", + "sha256:5d52e1173f52020392f593f87a6af2d4055dd800574a5cb0af4ea3878801d307", + "sha256:607224ffae9a0cf0a2f6e14f5f6bce43e83a6fbdaa647891729c103bdd6a5593", + "sha256:612ef8f2795a89ba3a1d4c8c1af84d8453fd53ee611aa5ad460fdd2cab426fc2", + "sha256:615886ee84b6f42f1bdf1852a9669b5fe3b96b6ff27f1a7a330b67ad9911200a", + "sha256:63419db39df8dc5564f6f103102c4665f7e4d9cb64030e98cf7a74eae5d5760d", + "sha256:6467626fa74f96f4d80fc6ec2555799e97fff8f36e0bfc7f67769f83e59cff40", + "sha256:65b3b5f12c6fb5611e79157214f3cd533083f9b058bf2fc8a1c5cc5ee40fdc5a", + "sha256:686565ac77ff94a8965c11829af253d9e2ce3bf0d9225b1d2eb5c4d4666d0dca", + "sha256:6af7f51a6010748fc1bb71917318d953c9673e4ae3f6d285aaf93ef5b2eb11c1", + "sha256:70a198030d26f5e569367f0f04509b63256faa76a22886280eea69a4f535dd40", + "sha256:754a1dd04bff8a509a31146bd8f3a5dc8191a8694d582dd5fb71ff09f0722c22", + "sha256:75da29a0752c8f2395df0115ac1681cefbdd4418676015be8178b733704cbff2", + "sha256:81c29c8741fa07ecec8ec7417c3d8d1e2f18cf5a10a280f4e1c3f8c3590228b2", + "sha256:9093a359a86650a3dbd6532c3e4d21a6f58ba2cb60d0e72db0848115d24c10ba", + "sha256:915ecf7d486df17cc65aeefdb680d5ad4390cc8c857cf8db3fe241ed234f856a", + "sha256:94b181dd2777890139e49a5336bf3a9a3378ce66132c665fe8db4e8b7683cde2", + "sha256:94f2e45b054dd759bed137b6e14ae8625495f7d90ddd23cf62c7a68f72b62656", + "sha256:9af19eb789d674b59a9bee5005779757aab857c40bf9cc313cb01eafac55ce55", + "sha256:9cae837b988f44925d14d048fa6a8c54f197c8b1223fd9ee9c27084f84606143", + "sha256:aa7447bf7c1a15ef24e2b86a277b585dd3f055e8890ac7f97374d170187daa97", + "sha256:b1e22f3ee4d75ca261b6bffbf64f6f178cb194b1be3191065a09f8d98828daa9", + "sha256:b5031d151d6147eac53366d6ec87da84cd4d8c5e80b1d9948a667a7164116e39", + "sha256:b62d1431b4c40cda43cc986f19b8c86b1d2ae8918cfc00f4776fdf070b65c0c4", + "sha256:b71c52d69b91af7d18c13aef1b0cc3baee36b78607c711eb14a52bf3aa7c815e", + "sha256:b7679344f2270840dc5babc9ccbedbc04f7473c1f66d4676bb01680c0db85bcc", + "sha256:bb7c1b029e54e26e01b1d1d912fc21abb65650d16ea9a191d026def4ed0859ed", + "sha256:c2a57755e366e0ac7ebdb3e9207f159c3bf1afed02392ab18453ce81f5ee92ee", + "sha256:cf9ec915857d260511399ab87e1e70fa13d6b2972258f8e620a3959468edfc32", + "sha256:d0d03b9636f1326772e6854459728676354d4c7731dae9902b180e2065ba3da6", + "sha256:d1690c4d37674a5f0cdafbc5ed7e360800afcf06928c2a024c779c046891bf09", + "sha256:d76da27f5e3e9bc40eba6ed7a9e985f57547e98cf20521d91215707f2fb57e0f", + "sha256:d882c2f3345261e898b9f604be76b61c901fbfa4ac32e3f51d5dc1edc89da3cb", + "sha256:d8e5021e770b0a3084c30dda5901d5fce6d4474feaf0ced8f8e5a82702502fbb", + "sha256:dd00d28d1ab5fa7627f5abc957f29a6338a7395b724571a8cbff8fbed83aaa82", + "sha256:e35a298691b9e10e5a5631f8f0ba605b30ebe19208dc8f58b670462f53753641", + "sha256:e4d020ecf3740b7312bacab2cb966bb720fd4d3490562d373b4ad91dd1857c0d", + "sha256:e564d5a771b4015f34166a05ea2165b7e283635c41b1347696117f780084b46d", + "sha256:ea3f2e9eb41f973f73619e88bf7bd950b16b4c2ce73d15f24a11800ce1eaf276", + "sha256:eabdbe04ee0a7e760fa6cd9e799d2b020d098c580ba99107d52e1e5e538b1ecb", + "sha256:f17b9df97c5ecdfb56c5e85b3c9df9831246df698f8581c6e111ac664c7c656e", + "sha256:f386def57742aacc3d864169dfce644a8c396f95aa35b41b69df53f558d56dd0", + "sha256:f6d23a01921b741774f35e924d418a43cf03eca1444f3fdfd7978d35a5aaab8b", + "sha256:fcdf70191f0d1761d190a436db06a46f05af60e1410e1507935f0332280c9268" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==4.8.0" + "version": "==4.9.0" }, "mako": { "hashes": [ - "sha256:23aab11fdbbb0f1051b93793a58323ff937e98e34aece1c4219675122e57e4ba", - "sha256:9a7c7e922b87db3686210cf49d5d767033a41d4010b284e747682c92bddd8b39" + "sha256:df3921c3081b013c8a2d5ff03c18375651684921ae83fd12e64800b7da923257", + "sha256:f054a5ff4743492f1aa9ecc47172cb33b42b9d993cffcc146c9de17e717b0307" ], "markers": "python_version >= '3.7'", - "version": "==1.2.0" + "version": "==1.2.1" }, "markupsafe": { "hashes": [ @@ -580,6 +665,13 @@ "markers": "python_version >= '3.7'", "version": "==2.1.1" }, + "micropipenv": { + "hashes": [ + "sha256:d576b1e5830ffe5ad9a67450ed975175a586bd8e91ea0c38acaef744ceae8630", + "sha256:f441b7876f95be77611dc948bf0c54b0c1e369fc98665b764ef61ae1bb064b1c" + ], + "version": "==1.3.0" + }, "mock": { "hashes": [ "sha256:122fcb64ee37cfad5b3f48d7a7d51875d7031aaf3d8be7c42e2bee25044eee62", @@ -682,6 +774,14 @@ ], "version": "==4.8.0" }, + "platformdirs": { + "hashes": [ + "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788", + "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19" + ], + "markers": "python_version >= '3.7'", + "version": "==2.5.2" + }, "prometheus-async": { "hashes": [ "sha256:5cbfa535561342b834c087c4f3f3be0a3cb8785a0b8748111c916f3d68bbc370", @@ -808,7 +908,6 @@ "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.21" }, "pydantic": { @@ -859,6 +958,22 @@ ], "version": "==0.28" }, + "pygments": { + "hashes": [ + "sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb", + "sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519" + ], + "markers": "python_version >= '3.6'", + "version": "==2.12.0" + }, + "pyjwt": { + "hashes": [ + "sha256:72d1d253f32dbd4f5c88eaf1fdc62f3a19f676ccbadb9dbc5d07e951b2b26daf", + "sha256:d42908208c699b3b973cbeb01a969ba6a96c821eefb1c5bfe4c390c01d67abba" + ], + "index": "pypi", + "version": "==2.4.0" + }, "pyparsing": { "hashes": [ "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb", @@ -867,6 +982,33 @@ "markers": "python_full_version >= '3.6.8'", "version": "==3.0.9" }, + "pyrsistent": { + "hashes": [ + "sha256:0e3e1fcc45199df76053026a51cc59ab2ea3fc7c094c6627e93b7b44cdae2c8c", + "sha256:1b34eedd6812bf4d33814fca1b66005805d3640ce53140ab8bbb1e2651b0d9bc", + "sha256:4ed6784ceac462a7d6fcb7e9b663e93b9a6fb373b7f43594f9ff68875788e01e", + "sha256:5d45866ececf4a5fff8742c25722da6d4c9e180daa7b405dc0a2a2790d668c26", + "sha256:636ce2dc235046ccd3d8c56a7ad54e99d5c1cd0ef07d9ae847306c91d11b5fec", + "sha256:6455fc599df93d1f60e1c5c4fe471499f08d190d57eca040c0ea182301321286", + "sha256:6bc66318fb7ee012071b2792024564973ecc80e9522842eb4e17743604b5e045", + "sha256:7bfe2388663fd18bd8ce7db2c91c7400bf3e1a9e8bd7d63bf7e77d39051b85ec", + "sha256:7ec335fc998faa4febe75cc5268a9eac0478b3f681602c1f27befaf2a1abe1d8", + "sha256:914474c9f1d93080338ace89cb2acee74f4f666fb0424896fcfb8d86058bf17c", + "sha256:b568f35ad53a7b07ed9b1b2bae09eb15cdd671a5ba5d2c66caee40dbf91c68ca", + "sha256:cdfd2c361b8a8e5d9499b9082b501c452ade8bbf42aef97ea04854f4a3f43b22", + "sha256:d1b96547410f76078eaf66d282ddca2e4baae8964364abb4f4dcdde855cd123a", + "sha256:d4d61f8b993a7255ba714df3aca52700f8125289f84f704cf80916517c46eb96", + "sha256:d7a096646eab884bf8bed965bad63ea327e0d0c38989fc83c5ea7b8a87037bfc", + "sha256:df46c854f490f81210870e509818b729db4488e1f30f2a1ce1698b2295a878d1", + "sha256:e24a828f57e0c337c8d8bb9f6b12f09dfdf0273da25fda9e314f0b684b415a07", + "sha256:e4f3149fd5eb9b285d6bfb54d2e5173f6a116fe19172686797c056672689daf6", + "sha256:e92a52c166426efbe0d1ec1332ee9119b6d32fc1f0bbfd55d5c1088070e7fc1b", + "sha256:f87cc2863ef33c709e237d4b5f4502a62a00fab450c9e020892e8e2ede5847f5", + "sha256:fd8da6d0124efa2f67d86fa70c851022f87c98e205f0594e1fae044e7119a5a6" + ], + "markers": "python_version >= '3.7'", + "version": "==0.18.1" + }, "python-dateutil": { "hashes": [ "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", @@ -947,11 +1089,11 @@ }, "requests": { "hashes": [ - "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61", - "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d" + "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983", + "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==2.27.1" + "markers": "python_version >= '3.7' and python_full_version < '4.0.0'", + "version": "==2.28.1" }, "requests-oauthlib": { "hashes": [ @@ -968,6 +1110,22 @@ ], "version": "==1.4.3" }, + "rich": { + "hashes": [ + "sha256:4c586de507202505346f3e32d1363eb9ed6932f0c2f63184dea88983ff4971e2", + "sha256:d2bbd99c320a2532ac71ff6a3164867884357da3e3301f0240090c5d2fdac7ec" + ], + "markers": "python_full_version >= '3.6.3' and python_full_version < '4.0.0'", + "version": "==12.4.4" + }, + "rich-click": { + "hashes": [ + "sha256:2ca72637d618c8033891ecb73e6e0c01af15afdac80d134ca93a58f1cbcd5ded", + "sha256:cf16bf9e390d5c9aa3b379c3884c52b47f54c8e6e2e7ddb7b2a002f4420c35c0" + ], + "markers": "python_version >= '3.7'", + "version": "==1.5.1" + }, "rsa": { "hashes": [ "sha256:5c6bd9dc7a543b7fe4304a631f8a8a3b674e2bbfc49c2ae96200cdbe55df6b17", @@ -1017,11 +1175,11 @@ }, "s3transfer": { "hashes": [ - "sha256:7a6f4c4d1fdb9a2b640244008e142cbc2cd3ae34b386584ef044dd0f27101971", - "sha256:95c58c194ce657a5f4fb0b9e60a84968c808888aed628cd98ab8771fe1db98ed" + "sha256:06176b74f3a15f61f1b4f25a1fc29a4429040b7647133a463da8fa5bd28d5ecd", + "sha256:2ed07d3866f523cc561bf4a00fc5535827981b117dd7876f036b0c1aca42c947" ], - "markers": "python_version >= '3.6'", - "version": "==0.5.2" + "markers": "python_version >= '3.7'", + "version": "==0.6.0" }, "semantic-version": { "hashes": [ @@ -1031,12 +1189,20 @@ "markers": "python_version >= '2.7'", "version": "==2.10.0" }, + "semver": { + "hashes": [ + "sha256:ced8b23dceb22134307c1b8abfa523da14198793d9787ac838e70e29e77458d4", + "sha256:fa0fe2722ee1c3f57eac478820c3a5ae2f624af8264cbdf9000c980ff7f75e3f" + ], + "index": "pypi", + "version": "==2.13.0" + }, "sentry-sdk": { "hashes": [ - "sha256:259535ba66933eacf85ab46524188c84dcb4c39f40348455ce15e2c0aca68863", - "sha256:778b53f0a6c83b1ee43d3b7886318ba86d975e686cb2c7906ccc35b334360be1" + "sha256:b82ad57306d5546713f15d5d70daea0408cf7f998c7566db16e0e6257e51e561", + "sha256:ddbd191b6f4e696b7845b4d87389898ae1207981faf114f968a57363aa6be03c" ], - "version": "==1.5.12" + "version": "==1.6.0" }, "six": { "hashes": [ @@ -1094,6 +1260,20 @@ "markers": "python_version ~= '3.4'", "version": "==0.38.2" }, + "termcolor": { + "hashes": [ + "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b" + ], + "version": "==1.1.0" + }, + "thamos": { + "hashes": [ + "sha256:db084f618d67f9c9cd9d151b3dd903f698272f32cf0c823312b7ef1422171cba", + "sha256:fe64f5b9b476c9f6b6393fd556ed9833434cfee1652ba9696c7b3d2dbfcf4697" + ], + "index": "pypi", + "version": "==1.27.7" + }, "thoth-analyzer": { "hashes": [ "sha256:3f830334a3ba725cacf64ccc756e42f0c7946fd8038da6565cb2de569ea5c9c1", @@ -1151,6 +1331,14 @@ "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.10.2" }, + "types-pyyaml": { + "hashes": [ + "sha256:33ae75c84b8f61fddf0c63e9c7e557db9db1694ad3c2ee8628ec5efebb5a5e9b", + "sha256:b738e9ef120da0af8c235ba49d3b72510f56ef9bcc308fc8e7357100ff122284" + ], + "index": "pypi", + "version": "==6.0.9" + }, "typing-extensions": { "hashes": [ "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708", @@ -1180,9 +1368,17 @@ "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14", "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_full_version < '4.0.0'", "version": "==1.26.9" }, + "virtualenv": { + "hashes": [ + "sha256:288171134a2ff3bfb1a2f54f119e77cd1b81c29fc1265a2356f3e8d14c7d58c4", + "sha256:b30aefac647e86af6d82bfc944c556f8f1a9c90427b2fb4e3bfbf338cb82becf" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==20.15.1" + }, "voluptuous": { "hashes": [ "sha256:4b838b185f5951f2d6e8752b68fcf18bd7a9c26ded8f143f92d6d28f3921a3e6", @@ -1192,11 +1388,11 @@ }, "websocket-client": { "hashes": [ - "sha256:50b21db0058f7a953d67cc0445be4b948d7fc196ecbeb8083d68d94628e4abf6", - "sha256:722b171be00f2b90e1d4fb2f2b53146a536ca38db1da8ff49c972a4e1365d0ef" + "sha256:5d55652dc1d0b3c734f044337d929aaf83f4f9138816ec680c1aefefb4dc4877", + "sha256:d58c5f284d6a9bf8379dab423259fe8f85b70d5fa5d2916d5791a84594b122b1" ], "markers": "python_version >= '3.7'", - "version": "==1.3.2" + "version": "==1.3.3" }, "wrapt": { "hashes": [ @@ -1346,6 +1542,14 @@ "markers": "python_version >= '3.6'", "version": "==1.7.2" }, + "yaspin": { + "hashes": [ + "sha256:c8d34eca9fda3f4dfbe59f57f3cf0f3641af3eefbf1544fbeb9b3bacf82c580a", + "sha256:d574cbfaf0a349df466c91f7f81b22460ae5ebb15ecb8bf9411d6049923aee8d" + ], + "markers": "python_full_version >= '3.6.2' and python_full_version < '4.0.0'", + "version": "==2.1.0" + }, "zipp": { "hashes": [ "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad", @@ -1356,6 +1560,92 @@ } }, "develop": { + "aiohttp": { + "hashes": [ + "sha256:01d7bdb774a9acc838e6b8f1d114f45303841b89b95984cbb7d80ea41172a9e3", + "sha256:03a6d5349c9ee8f79ab3ff3694d6ce1cfc3ced1c9d36200cb8f08ba06bd3b782", + "sha256:04d48b8ce6ab3cf2097b1855e1505181bdd05586ca275f2505514a6e274e8e75", + "sha256:0770e2806a30e744b4e21c9d73b7bee18a1cfa3c47991ee2e5a65b887c49d5cf", + "sha256:07b05cd3305e8a73112103c834e91cd27ce5b4bd07850c4b4dbd1877d3f45be7", + "sha256:086f92daf51a032d062ec5f58af5ca6a44d082c35299c96376a41cbb33034675", + "sha256:099ebd2c37ac74cce10a3527d2b49af80243e2a4fa39e7bce41617fbc35fa3c1", + "sha256:0c7ebbbde809ff4e970824b2b6cb7e4222be6b95a296e46c03cf050878fc1785", + "sha256:102e487eeb82afac440581e5d7f8f44560b36cf0bdd11abc51a46c1cd88914d4", + "sha256:11691cf4dc5b94236ccc609b70fec991234e7ef8d4c02dd0c9668d1e486f5abf", + "sha256:11a67c0d562e07067c4e86bffc1553f2cf5b664d6111c894671b2b8712f3aba5", + "sha256:12de6add4038df8f72fac606dff775791a60f113a725c960f2bab01d8b8e6b15", + "sha256:13487abd2f761d4be7c8ff9080de2671e53fff69711d46de703c310c4c9317ca", + "sha256:15b09b06dae900777833fe7fc4b4aa426556ce95847a3e8d7548e2d19e34edb8", + "sha256:1c182cb873bc91b411e184dab7a2b664d4fea2743df0e4d57402f7f3fa644bac", + "sha256:1ed0b6477896559f17b9eaeb6d38e07f7f9ffe40b9f0f9627ae8b9926ae260a8", + "sha256:28d490af82bc6b7ce53ff31337a18a10498303fe66f701ab65ef27e143c3b0ef", + "sha256:2e5d962cf7e1d426aa0e528a7e198658cdc8aa4fe87f781d039ad75dcd52c516", + "sha256:2ed076098b171573161eb146afcb9129b5ff63308960aeca4b676d9d3c35e700", + "sha256:2f2f69dca064926e79997f45b2f34e202b320fd3782f17a91941f7eb85502ee2", + "sha256:31560d268ff62143e92423ef183680b9829b1b482c011713ae941997921eebc8", + "sha256:31d1e1c0dbf19ebccbfd62eff461518dcb1e307b195e93bba60c965a4dcf1ba0", + "sha256:37951ad2f4a6df6506750a23f7cbabad24c73c65f23f72e95897bb2cecbae676", + "sha256:3af642b43ce56c24d063325dd2cf20ee012d2b9ba4c3c008755a301aaea720ad", + "sha256:44db35a9e15d6fe5c40d74952e803b1d96e964f683b5a78c3cc64eb177878155", + "sha256:473d93d4450880fe278696549f2e7aed8cd23708c3c1997981464475f32137db", + "sha256:477c3ea0ba410b2b56b7efb072c36fa91b1e6fc331761798fa3f28bb224830dd", + "sha256:4a4a4e30bf1edcad13fb0804300557aedd07a92cabc74382fdd0ba6ca2661091", + "sha256:4aed991a28ea3ce320dc8ce655875e1e00a11bdd29fe9444dd4f88c30d558602", + "sha256:51467000f3647d519272392f484126aa716f747859794ac9924a7aafa86cd411", + "sha256:55c3d1072704d27401c92339144d199d9de7b52627f724a949fc7d5fc56d8b93", + "sha256:589c72667a5febd36f1315aa6e5f56dd4aa4862df295cb51c769d16142ddd7cd", + "sha256:5bfde62d1d2641a1f5173b8c8c2d96ceb4854f54a44c23102e2ccc7e02f003ec", + "sha256:5c23b1ad869653bc818e972b7a3a79852d0e494e9ab7e1a701a3decc49c20d51", + "sha256:61bfc23df345d8c9716d03717c2ed5e27374e0fe6f659ea64edcd27b4b044cf7", + "sha256:6ae828d3a003f03ae31915c31fa684b9890ea44c9c989056fea96e3d12a9fa17", + "sha256:6c7cefb4b0640703eb1069835c02486669312bf2f12b48a748e0a7756d0de33d", + "sha256:6d69f36d445c45cda7b3b26afef2fc34ef5ac0cdc75584a87ef307ee3c8c6d00", + "sha256:6f0d5f33feb5f69ddd57a4a4bd3d56c719a141080b445cbf18f238973c5c9923", + "sha256:6f8b01295e26c68b3a1b90efb7a89029110d3a4139270b24fda961893216c440", + "sha256:713ac174a629d39b7c6a3aa757b337599798da4c1157114a314e4e391cd28e32", + "sha256:718626a174e7e467f0558954f94af117b7d4695d48eb980146016afa4b580b2e", + "sha256:7187a76598bdb895af0adbd2fb7474d7f6025d170bc0a1130242da817ce9e7d1", + "sha256:71927042ed6365a09a98a6377501af5c9f0a4d38083652bcd2281a06a5976724", + "sha256:7d08744e9bae2ca9c382581f7dce1273fe3c9bae94ff572c3626e8da5b193c6a", + "sha256:7dadf3c307b31e0e61689cbf9e06be7a867c563d5a63ce9dca578f956609abf8", + "sha256:81e3d8c34c623ca4e36c46524a3530e99c0bc95ed068fd6e9b55cb721d408fb2", + "sha256:844a9b460871ee0a0b0b68a64890dae9c415e513db0f4a7e3cab41a0f2fedf33", + "sha256:8b7ef7cbd4fec9a1e811a5de813311ed4f7ac7d93e0fda233c9b3e1428f7dd7b", + "sha256:97ef77eb6b044134c0b3a96e16abcb05ecce892965a2124c566af0fd60f717e2", + "sha256:99b5eeae8e019e7aad8af8bb314fb908dd2e028b3cdaad87ec05095394cce632", + "sha256:a25fa703a527158aaf10dafd956f7d42ac6d30ec80e9a70846253dd13e2f067b", + "sha256:a2f635ce61a89c5732537a7896b6319a8fcfa23ba09bec36e1b1ac0ab31270d2", + "sha256:a79004bb58748f31ae1cbe9fa891054baaa46fb106c2dc7af9f8e3304dc30316", + "sha256:a996d01ca39b8dfe77440f3cd600825d05841088fd6bc0144cc6c2ec14cc5f74", + "sha256:b0e20cddbd676ab8a64c774fefa0ad787cc506afd844de95da56060348021e96", + "sha256:b6613280ccedf24354406caf785db748bebbddcf31408b20c0b48cb86af76866", + "sha256:b9d00268fcb9f66fbcc7cd9fe423741d90c75ee029a1d15c09b22d23253c0a44", + "sha256:bb01ba6b0d3f6c68b89fce7305080145d4877ad3acaed424bae4d4ee75faa950", + "sha256:c2aef4703f1f2ddc6df17519885dbfa3514929149d3ff900b73f45998f2532fa", + "sha256:c34dc4958b232ef6188c4318cb7b2c2d80521c9a56c52449f8f93ab7bc2a8a1c", + "sha256:c3630c3ef435c0a7c549ba170a0633a56e92629aeed0e707fec832dee313fb7a", + "sha256:c3d6a4d0619e09dcd61021debf7059955c2004fa29f48788a3dfaf9c9901a7cd", + "sha256:d15367ce87c8e9e09b0f989bfd72dc641bcd04ba091c68cd305312d00962addd", + "sha256:d2f9b69293c33aaa53d923032fe227feac867f81682f002ce33ffae978f0a9a9", + "sha256:e999f2d0e12eea01caeecb17b653f3713d758f6dcc770417cf29ef08d3931421", + "sha256:ea302f34477fda3f85560a06d9ebdc7fa41e82420e892fc50b577e35fc6a50b2", + "sha256:eaba923151d9deea315be1f3e2b31cc39a6d1d2f682f942905951f4e40200922", + "sha256:ef9612483cb35171d51d9173647eed5d0069eaa2ee812793a75373447d487aa4", + "sha256:f5315a2eb0239185af1bddb1abf472d877fede3cc8d143c6cddad37678293237", + "sha256:fa0ffcace9b3aa34d205d8130f7873fcfefcb6a4dd3dd705b0dab69af6712642", + "sha256:fc5471e1a54de15ef71c1bc6ebe80d4dc681ea600e68bfd1cbce40427f0b7578" + ], + "index": "pypi", + "version": "==3.8.1" + }, + "aiosignal": { + "hashes": [ + "sha256:26e62109036cd181df6e6ad646f91f0dcfd05fe16d0cb924138ff2ab75d64e3a", + "sha256:78ed67db6c7b7ced4f98e495e572106d5c432a93e1ddd1bf475e1dc05f5b7df2" + ], + "markers": "python_version >= '3.6'", + "version": "==1.2.0" + }, "aspy.yaml": { "hashes": [ "sha256:463372c043f70160a9ec950c3f1e4c3a82db5fca01d334b6bc89c7164d744bdc", @@ -1364,6 +1654,14 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.3.0" }, + "async-timeout": { + "hashes": [ + "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15", + "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c" + ], + "markers": "python_version >= '3.6'", + "version": "==4.0.2" + }, "attrs": { "hashes": [ "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4", @@ -1380,55 +1678,63 @@ "markers": "python_full_version >= '3.6.1'", "version": "==3.3.1" }, + "charset-normalizer": { + "hashes": [ + "sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5", + "sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413" + ], + "markers": "python_version >= '3.6'", + "version": "==2.1.0" + }, "coverage": { "extras": [ "toml" ], "hashes": [ - "sha256:00c8544510f3c98476bbd58201ac2b150ffbcce46a8c3e4fb89ebf01998f806a", - "sha256:016d7f5cf1c8c84f533a3c1f8f36126fbe00b2ec0ccca47cc5731c3723d327c6", - "sha256:03014a74023abaf5a591eeeaf1ac66a73d54eba178ff4cb1fa0c0a44aae70383", - "sha256:033ebec282793bd9eb988d0271c211e58442c31077976c19c442e24d827d356f", - "sha256:21e6686a95025927775ac501e74f5940cdf6fe052292f3a3f7349b0abae6d00f", - "sha256:26f8f92699756cb7af2b30720de0c5bb8d028e923a95b6d0c891088025a1ac8f", - "sha256:2e76bd16f0e31bc2b07e0fb1379551fcd40daf8cdf7e24f31a29e442878a827c", - "sha256:341e9c2008c481c5c72d0e0dbf64980a4b2238631a7f9780b0fe2e95755fb018", - "sha256:3cfd07c5889ddb96a401449109a8b97a165be9d67077df6802f59708bfb07720", - "sha256:4002f9e8c1f286e986fe96ec58742b93484195defc01d5cc7809b8f7acb5ece3", - "sha256:50ed480b798febce113709846b11f5d5ed1e529c88d8ae92f707806c50297abf", - "sha256:543e172ce4c0de533fa892034cce260467b213c0ea8e39da2f65f9a477425211", - "sha256:5a78cf2c43b13aa6b56003707c5203f28585944c277c1f3f109c7b041b16bd39", - "sha256:5cd698341626f3c77784858427bad0cdd54a713115b423d22ac83a28303d1d95", - "sha256:60c2147921da7f4d2d04f570e1838db32b95c5509d248f3fe6417e91437eaf41", - "sha256:62d382f7d77eeeaff14b30516b17bcbe80f645f5cf02bb755baac376591c653c", - "sha256:69432946f154c6add0e9ede03cc43b96e2ef2733110a77444823c053b1ff5166", - "sha256:727dafd7f67a6e1cad808dc884bd9c5a2f6ef1f8f6d2f22b37b96cb0080d4f49", - "sha256:742fb8b43835078dd7496c3c25a1ec8d15351df49fb0037bffb4754291ef30ce", - "sha256:750e13834b597eeb8ae6e72aa58d1d831b96beec5ad1d04479ae3772373a8088", - "sha256:7b546cf2b1974ddc2cb222a109b37c6ed1778b9be7e6b0c0bc0cf0438d9e45a6", - "sha256:83bd142cdec5e4a5c4ca1d4ff6fa807d28460f9db919f9f6a31babaaa8b88426", - "sha256:8d2e80dd3438e93b19e1223a9850fa65425e77f2607a364b6fd134fcd52dc9df", - "sha256:9229d074e097f21dfe0643d9d0140ee7433814b3f0fc3706b4abffd1e3038632", - "sha256:968ed5407f9460bd5a591cefd1388cc00a8f5099de9e76234655ae48cfdbe2c3", - "sha256:9c82f2cd69c71698152e943f4a5a6b83a3ab1db73b88f6e769fabc86074c3b08", - "sha256:a00441f5ea4504f5abbc047589d09e0dc33eb447dc45a1a527c8b74bfdd32c65", - "sha256:a022394996419142b33a0cf7274cb444c01d2bb123727c4bb0b9acabcb515dea", - "sha256:af5b9ee0fc146e907aa0f5fb858c3b3da9199d78b7bb2c9973d95550bd40f701", - "sha256:b5578efe4038be02d76c344007b13119b2b20acd009a88dde8adec2de4f630b5", - "sha256:b84ab65444dcc68d761e95d4d70f3cfd347ceca5a029f2ffec37d4f124f61311", - "sha256:c53ad261dfc8695062fc8811ac7c162bd6096a05a19f26097f411bdf5747aee7", - "sha256:cc173f1ce9ffb16b299f51c9ce53f66a62f4d975abe5640e976904066f3c835d", - "sha256:d548edacbf16a8276af13063a2b0669d58bbcfca7c55a255f84aac2870786a61", - "sha256:d55fae115ef9f67934e9f1103c9ba826b4c690e4c5bcf94482b8b2398311bf9c", - "sha256:d8099ea680201c2221f8468c372198ceba9338a5fec0e940111962b03b3f716a", - "sha256:e35217031e4b534b09f9b9a5841b9344a30a6357627761d4218818b865d45055", - "sha256:e4f52c272fdc82e7c65ff3f17a7179bc5f710ebc8ce8a5cadac81215e8326740", - "sha256:e637ae0b7b481905358624ef2e81d7fb0b1af55f5ff99f9ba05442a444b11e45", - "sha256:eef5292b60b6de753d6e7f2d128d5841c7915fb1e3321c3a1fe6acfe76c38052", - "sha256:fb45fe08e1abc64eb836d187b20a59172053999823f7f6ef4f18a819c44ba16f" + "sha256:01c5615d13f3dd3aa8543afc069e5319cfa0c7d712f6e04b920431e5c564a749", + "sha256:106c16dfe494de3193ec55cac9640dd039b66e196e4641fa8ac396181578b982", + "sha256:129cd05ba6f0d08a766d942a9ed4b29283aff7b2cccf5b7ce279d50796860bb3", + "sha256:145f296d00441ca703a659e8f3eb48ae39fb083baba2d7ce4482fb2723e050d9", + "sha256:1480ff858b4113db2718848d7b2d1b75bc79895a9c22e76a221b9d8d62496428", + "sha256:269eaa2c20a13a5bf17558d4dc91a8d078c4fa1872f25303dddcbba3a813085e", + "sha256:26dff09fb0d82693ba9e6231248641d60ba606150d02ed45110f9ec26404ed1c", + "sha256:2bd9a6fc18aab8d2e18f89b7ff91c0f34ff4d5e0ba0b33e989b3cd4194c81fd9", + "sha256:309ce4a522ed5fca432af4ebe0f32b21d6d7ccbb0f5fcc99290e71feba67c264", + "sha256:3384f2a3652cef289e38100f2d037956194a837221edd520a7ee5b42d00cc605", + "sha256:342d4aefd1c3e7f620a13f4fe563154d808b69cccef415415aece4c786665397", + "sha256:39ee53946bf009788108b4dd2894bf1349b4e0ca18c2016ffa7d26ce46b8f10d", + "sha256:4321f075095a096e70aff1d002030ee612b65a205a0a0f5b815280d5dc58100c", + "sha256:4803e7ccf93230accb928f3a68f00ffa80a88213af98ed338a57ad021ef06815", + "sha256:4ce1b258493cbf8aec43e9b50d89982346b98e9ffdfaae8ae5793bc112fb0068", + "sha256:664a47ce62fe4bef9e2d2c430306e1428ecea207ffd68649e3b942fa8ea83b0b", + "sha256:75ab269400706fab15981fd4bd5080c56bd5cc07c3bccb86aab5e1d5a88dc8f4", + "sha256:83c4e737f60c6936460c5be330d296dd5b48b3963f48634c53b3f7deb0f34ec4", + "sha256:84631e81dd053e8a0d4967cedab6db94345f1c36107c71698f746cb2636c63e3", + "sha256:84e65ef149028516c6d64461b95a8dbcfce95cfd5b9eb634320596173332ea84", + "sha256:865d69ae811a392f4d06bde506d531f6a28a00af36f5c8649684a9e5e4a85c83", + "sha256:87f4f3df85aa39da00fd3ec4b5abeb7407e82b68c7c5ad181308b0e2526da5d4", + "sha256:8c08da0bd238f2970230c2a0d28ff0e99961598cb2e810245d7fc5afcf1254e8", + "sha256:961e2fb0680b4f5ad63234e0bf55dfb90d302740ae9c7ed0120677a94a1590cb", + "sha256:9b3e07152b4563722be523e8cd0b209e0d1a373022cfbde395ebb6575bf6790d", + "sha256:a7f3049243783df2e6cc6deafc49ea123522b59f464831476d3d1448e30d72df", + "sha256:bf5601c33213d3cb19d17a796f8a14a9eaa5e87629a53979a5981e3e3ae166f6", + "sha256:cec3a0f75c8f1031825e19cd86ee787e87cf03e4fd2865c79c057092e69e3a3b", + "sha256:d42c549a8f41dc103a8004b9f0c433e2086add8a719da00e246e17cbe4056f72", + "sha256:d67d44996140af8b84284e5e7d398e589574b376fb4de8ccd28d82ad8e3bea13", + "sha256:d9c80df769f5ec05ad21ea34be7458d1dc51ff1fb4b2219e77fe24edf462d6df", + "sha256:e57816f8ffe46b1df8f12e1b348f06d164fd5219beba7d9433ba79608ef011cc", + "sha256:ee2ddcac99b2d2aec413e36d7a429ae9ebcadf912946b13ffa88e7d4c9b712d6", + "sha256:f02cbbf8119db68455b9d763f2f8737bb7db7e43720afa07d8eb1604e5c5ae28", + "sha256:f1d5aa2703e1dab4ae6cf416eb0095304f49d004c39e9db1d86f57924f43006b", + "sha256:f5b66caa62922531059bc5ac04f836860412f7f88d38a476eda0a6f11d4724f4", + "sha256:f69718750eaae75efe506406c490d6fc5a6161d047206cc63ce25527e8a3adad", + "sha256:fb73e0011b8793c053bfa85e53129ba5f0250fdc0392c1591fd35d915ec75c46", + "sha256:fd180ed867e289964404051a958f7cccabdeed423f91a899829264bb7974d3d3", + "sha256:fdb6f7bd51c2d1714cea40718f6149ad9be6a2ee7d93b19e9f00934c0f2a74d9", + "sha256:ffa9297c3a453fba4717d06df579af42ab9a28022444cae7fa605af4df612d54" ], "markers": "python_version >= '3.7'", - "version": "==6.4" + "version": "==6.4.1" }, "distlib": { "hashes": [ @@ -1439,19 +1745,84 @@ }, "filelock": { "hashes": [ - "sha256:b795f1b42a61bbf8ec7113c341dad679d772567b936fbd1bf43c9a238e673e20", - "sha256:c7b5fdb219b398a5b28c8e4c1893ef5f98ece6a38c6ab2c22e26ec161556fed6" + "sha256:37def7b658813cda163b56fc564cdc75e86d338246458c4c28ae84cabefa2404", + "sha256:3a0fd85166ad9dbab54c9aec96737b744106dc5f15c0b09a6744a445299fcf04" + ], + "markers": "python_version >= '3.7'", + "version": "==3.7.1" + }, + "frozenlist": { + "hashes": [ + "sha256:006d3595e7d4108a12025ddf415ae0f6c9e736e726a5db0183326fd191b14c5e", + "sha256:01a73627448b1f2145bddb6e6c2259988bb8aee0fb361776ff8604b99616cd08", + "sha256:03a7dd1bfce30216a3f51a84e6dd0e4a573d23ca50f0346634916ff105ba6e6b", + "sha256:0437fe763fb5d4adad1756050cbf855bbb2bf0d9385c7bb13d7a10b0dd550486", + "sha256:04cb491c4b1c051734d41ea2552fde292f5f3a9c911363f74f39c23659c4af78", + "sha256:0c36e78b9509e97042ef869c0e1e6ef6429e55817c12d78245eb915e1cca7468", + "sha256:25af28b560e0c76fa41f550eacb389905633e7ac02d6eb3c09017fa1c8cdfde1", + "sha256:2fdc3cd845e5a1f71a0c3518528bfdbfe2efaf9886d6f49eacc5ee4fd9a10953", + "sha256:30530930410855c451bea83f7b272fb1c495ed9d5cc72895ac29e91279401db3", + "sha256:31977f84828b5bb856ca1eb07bf7e3a34f33a5cddce981d880240ba06639b94d", + "sha256:3c62964192a1c0c30b49f403495911298810bada64e4f03249ca35a33ca0417a", + "sha256:3f7c935c7b58b0d78c0beea0c7358e165f95f1fd8a7e98baa40d22a05b4a8141", + "sha256:40dff8962b8eba91fd3848d857203f0bd704b5f1fa2b3fc9af64901a190bba08", + "sha256:40ec383bc194accba825fbb7d0ef3dda5736ceab2375462f1d8672d9f6b68d07", + "sha256:436496321dad302b8b27ca955364a439ed1f0999311c393dccb243e451ff66aa", + "sha256:4406cfabef8f07b3b3af0f50f70938ec06d9f0fc26cbdeaab431cbc3ca3caeaa", + "sha256:45334234ec30fc4ea677f43171b18a27505bfb2dba9aca4398a62692c0ea8868", + "sha256:47be22dc27ed933d55ee55845d34a3e4e9f6fee93039e7f8ebadb0c2f60d403f", + "sha256:4a44ebbf601d7bac77976d429e9bdb5a4614f9f4027777f9e54fd765196e9d3b", + "sha256:4eda49bea3602812518765810af732229b4291d2695ed24a0a20e098c45a707b", + "sha256:57f4d3f03a18facacb2a6bcd21bccd011e3b75d463dc49f838fd699d074fabd1", + "sha256:603b9091bd70fae7be28bdb8aa5c9990f4241aa33abb673390a7f7329296695f", + "sha256:65bc6e2fece04e2145ab6e3c47428d1bbc05aede61ae365b2c1bddd94906e478", + "sha256:691ddf6dc50480ce49f68441f1d16a4c3325887453837036e0fb94736eae1e58", + "sha256:6983a31698490825171be44ffbafeaa930ddf590d3f051e397143a5045513b01", + "sha256:6a202458d1298ced3768f5a7d44301e7c86defac162ace0ab7434c2e961166e8", + "sha256:6eb275c6385dd72594758cbe96c07cdb9bd6becf84235f4a594bdf21e3596c9d", + "sha256:754728d65f1acc61e0f4df784456106e35afb7bf39cfe37227ab00436fb38676", + "sha256:768efd082074bb203c934e83a61654ed4931ef02412c2fbdecea0cff7ecd0274", + "sha256:772965f773757a6026dea111a15e6e2678fbd6216180f82a48a40b27de1ee2ab", + "sha256:871d42623ae15eb0b0e9df65baeee6976b2e161d0ba93155411d58ff27483ad8", + "sha256:88aafd445a233dbbf8a65a62bc3249a0acd0d81ab18f6feb461cc5a938610d24", + "sha256:8c905a5186d77111f02144fab5b849ab524f1e876a1e75205cd1386a9be4b00a", + "sha256:8cf829bd2e2956066dd4de43fd8ec881d87842a06708c035b37ef632930505a2", + "sha256:92e650bd09b5dda929523b9f8e7f99b24deac61240ecc1a32aeba487afcd970f", + "sha256:93641a51f89473837333b2f8100f3f89795295b858cd4c7d4a1f18e299dc0a4f", + "sha256:94c7a8a9fc9383b52c410a2ec952521906d355d18fccc927fca52ab575ee8b93", + "sha256:9f892d6a94ec5c7b785e548e42722e6f3a52f5f32a8461e82ac3e67a3bd073f1", + "sha256:acb267b09a509c1df5a4ca04140da96016f40d2ed183cdc356d237286c971b51", + "sha256:adac9700675cf99e3615eb6a0eb5e9f5a4143c7d42c05cea2e7f71c27a3d0846", + "sha256:aff388be97ef2677ae185e72dc500d19ecaf31b698986800d3fc4f399a5e30a5", + "sha256:b5009062d78a8c6890d50b4e53b0ddda31841b3935c1937e2ed8c1bda1c7fb9d", + "sha256:b684c68077b84522b5c7eafc1dc735bfa5b341fb011d5552ebe0968e22ed641c", + "sha256:b9e3e9e365991f8cc5f5edc1fd65b58b41d0514a6a7ad95ef5c7f34eb49b3d3e", + "sha256:bd89acd1b8bb4f31b47072615d72e7f53a948d302b7c1d1455e42622de180eae", + "sha256:bde99812f237f79eaf3f04ebffd74f6718bbd216101b35ac7955c2d47c17da02", + "sha256:c6c321dd013e8fc20735b92cb4892c115f5cdb82c817b1e5b07f6b95d952b2f0", + "sha256:ce6f2ba0edb7b0c1d8976565298ad2deba6f8064d2bebb6ffce2ca896eb35b0b", + "sha256:d2257aaba9660f78c7b1d8fea963b68f3feffb1a9d5d05a18401ca9eb3e8d0a3", + "sha256:d26b650b71fdc88065b7a21f8ace70175bcf3b5bdba5ea22df4bfd893e795a3b", + "sha256:d6d32ff213aef0fd0bcf803bffe15cfa2d4fde237d1d4838e62aec242a8362fa", + "sha256:e1e26ac0a253a2907d654a37e390904426d5ae5483150ce3adedb35c8c06614a", + "sha256:e30b2f9683812eb30cf3f0a8e9f79f8d590a7999f731cf39f9105a7c4a39489d", + "sha256:e84cb61b0ac40a0c3e0e8b79c575161c5300d1d89e13c0e02f76193982f066ed", + "sha256:e982878792c971cbd60ee510c4ee5bf089a8246226dea1f2138aa0bb67aff148", + "sha256:f20baa05eaa2bcd5404c445ec51aed1c268d62600362dc6cfe04fae34a424bd9", + "sha256:f7353ba3367473d1d616ee727945f439e027f0bb16ac1a750219a8344d1d5d3c", + "sha256:f96293d6f982c58ebebb428c50163d010c2f05de0cde99fd681bfdc18d4b2dc2", + "sha256:ff9310f05b9d9c5c4dd472983dc956901ee6cb2c3ec1ab116ecdde25f3ce4951" ], "markers": "python_version >= '3.7'", - "version": "==3.7.0" + "version": "==1.3.0" }, "hypothesis": { "hashes": [ - "sha256:5a9629e10700e5c93f761fa310baf127f36f8a9e179e7dae087aeb22b3d1f535", - "sha256:8b1349dab58cf9bc85687e2721c008e99f23a32fb70e688779c81b0298904160" + "sha256:4c912677c2c5d7cf0c25f623d940c32a7003345bd476b8820d03ed1228a422ee", + "sha256:f5c1cf61b24b094355577a6b8fbbb8eb54c1b0216fbc0519af97c46bddf43c42" ], "index": "pypi", - "version": "==6.46.9" + "version": "==6.46.11" }, "hypothesis-auto": { "hashes": [ @@ -1469,6 +1840,14 @@ "markers": "python_version >= '3.7'", "version": "==2.5.1" }, + "idna": { + "hashes": [ + "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", + "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" + ], + "markers": "python_version >= '3.5'", + "version": "==3.3" + }, "iniconfig": { "hashes": [ "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3", @@ -1476,34 +1855,99 @@ ], "version": "==1.1.1" }, + "multidict": { + "hashes": [ + "sha256:0327292e745a880459ef71be14e709aaea2f783f3537588fb4ed09b6c01bca60", + "sha256:041b81a5f6b38244b34dc18c7b6aba91f9cdaf854d9a39e5ff0b58e2b5773b9c", + "sha256:0556a1d4ea2d949efe5fd76a09b4a82e3a4a30700553a6725535098d8d9fb672", + "sha256:05f6949d6169878a03e607a21e3b862eaf8e356590e8bdae4227eedadacf6e51", + "sha256:07a017cfa00c9890011628eab2503bee5872f27144936a52eaab449be5eaf032", + "sha256:0b9e95a740109c6047602f4db4da9949e6c5945cefbad34a1299775ddc9a62e2", + "sha256:19adcfc2a7197cdc3987044e3f415168fc5dc1f720c932eb1ef4f71a2067e08b", + "sha256:19d9bad105dfb34eb539c97b132057a4e709919ec4dd883ece5838bcbf262b80", + "sha256:225383a6603c086e6cef0f2f05564acb4f4d5f019a4e3e983f572b8530f70c88", + "sha256:23b616fdc3c74c9fe01d76ce0d1ce872d2d396d8fa8e4899398ad64fb5aa214a", + "sha256:2957489cba47c2539a8eb7ab32ff49101439ccf78eab724c828c1a54ff3ff98d", + "sha256:2d36e929d7f6a16d4eb11b250719c39560dd70545356365b494249e2186bc389", + "sha256:2e4a0785b84fb59e43c18a015ffc575ba93f7d1dbd272b4cdad9f5134b8a006c", + "sha256:3368bf2398b0e0fcbf46d85795adc4c259299fec50c1416d0f77c0a843a3eed9", + "sha256:373ba9d1d061c76462d74e7de1c0c8e267e9791ee8cfefcf6b0b2495762c370c", + "sha256:4070613ea2227da2bfb2c35a6041e4371b0af6b0be57f424fe2318b42a748516", + "sha256:45183c96ddf61bf96d2684d9fbaf6f3564d86b34cb125761f9a0ef9e36c1d55b", + "sha256:4571f1beddff25f3e925eea34268422622963cd8dc395bb8778eb28418248e43", + "sha256:47e6a7e923e9cada7c139531feac59448f1f47727a79076c0b1ee80274cd8eee", + "sha256:47fbeedbf94bed6547d3aa632075d804867a352d86688c04e606971595460227", + "sha256:497988d6b6ec6ed6f87030ec03280b696ca47dbf0648045e4e1d28b80346560d", + "sha256:4bae31803d708f6f15fd98be6a6ac0b6958fcf68fda3c77a048a4f9073704aae", + "sha256:50bd442726e288e884f7be9071016c15a8742eb689a593a0cac49ea093eef0a7", + "sha256:514fe2b8d750d6cdb4712346a2c5084a80220821a3e91f3f71eec11cf8d28fd4", + "sha256:5774d9218d77befa7b70d836004a768fb9aa4fdb53c97498f4d8d3f67bb9cfa9", + "sha256:5fdda29a3c7e76a064f2477c9aab1ba96fd94e02e386f1e665bca1807fc5386f", + "sha256:5ff3bd75f38e4c43f1f470f2df7a4d430b821c4ce22be384e1459cb57d6bb013", + "sha256:626fe10ac87851f4cffecee161fc6f8f9853f0f6f1035b59337a51d29ff3b4f9", + "sha256:6701bf8a5d03a43375909ac91b6980aea74b0f5402fbe9428fc3f6edf5d9677e", + "sha256:684133b1e1fe91eda8fa7447f137c9490a064c6b7f392aa857bba83a28cfb693", + "sha256:6f3cdef8a247d1eafa649085812f8a310e728bdf3900ff6c434eafb2d443b23a", + "sha256:75bdf08716edde767b09e76829db8c1e5ca9d8bb0a8d4bd94ae1eafe3dac5e15", + "sha256:7c40b7bbece294ae3a87c1bc2abff0ff9beef41d14188cda94ada7bcea99b0fb", + "sha256:8004dca28e15b86d1b1372515f32eb6f814bdf6f00952699bdeb541691091f96", + "sha256:8064b7c6f0af936a741ea1efd18690bacfbae4078c0c385d7c3f611d11f0cf87", + "sha256:89171b2c769e03a953d5969b2f272efa931426355b6c0cb508022976a17fd376", + "sha256:8cbf0132f3de7cc6c6ce00147cc78e6439ea736cee6bca4f068bcf892b0fd658", + "sha256:9cc57c68cb9139c7cd6fc39f211b02198e69fb90ce4bc4a094cf5fe0d20fd8b0", + "sha256:a007b1638e148c3cfb6bf0bdc4f82776cef0ac487191d093cdc316905e504071", + "sha256:a2c34a93e1d2aa35fbf1485e5010337c72c6791407d03aa5f4eed920343dd360", + "sha256:a45e1135cb07086833ce969555df39149680e5471c04dfd6a915abd2fc3f6dbc", + "sha256:ac0e27844758d7177989ce406acc6a83c16ed4524ebc363c1f748cba184d89d3", + "sha256:aef9cc3d9c7d63d924adac329c33835e0243b5052a6dfcbf7732a921c6e918ba", + "sha256:b9d153e7f1f9ba0b23ad1568b3b9e17301e23b042c23870f9ee0522dc5cc79e8", + "sha256:bfba7c6d5d7c9099ba21f84662b037a0ffd4a5e6b26ac07d19e423e6fdf965a9", + "sha256:c207fff63adcdf5a485969131dc70e4b194327666b7e8a87a97fbc4fd80a53b2", + "sha256:d0509e469d48940147e1235d994cd849a8f8195e0bca65f8f5439c56e17872a3", + "sha256:d16cce709ebfadc91278a1c005e3c17dd5f71f5098bfae1035149785ea6e9c68", + "sha256:d48b8ee1d4068561ce8033d2c344cf5232cb29ee1a0206a7b828c79cbc5982b8", + "sha256:de989b195c3d636ba000ee4281cd03bb1234635b124bf4cd89eeee9ca8fcb09d", + "sha256:e07c8e79d6e6fd37b42f3250dba122053fddb319e84b55dd3a8d6446e1a7ee49", + "sha256:e2c2e459f7050aeb7c1b1276763364884595d47000c1cddb51764c0d8976e608", + "sha256:e5b20e9599ba74391ca0cfbd7b328fcc20976823ba19bc573983a25b32e92b57", + "sha256:e875b6086e325bab7e680e4316d667fc0e5e174bb5611eb16b3ea121c8951b86", + "sha256:f4f052ee022928d34fe1f4d2bc743f32609fb79ed9c49a1710a5ad6b2198db20", + "sha256:fcb91630817aa8b9bc4a74023e4198480587269c272c58b3279875ed7235c293", + "sha256:fd9fc9c4849a07f3635ccffa895d57abce554b467d611a5009ba4f39b78a8849", + "sha256:feba80698173761cddd814fa22e88b0661e98cb810f9f986c54aa34d281e4937", + "sha256:feea820722e69451743a3d56ad74948b68bf456984d63c1a92e8347b7b88452d" + ], + "markers": "python_version >= '3.7'", + "version": "==6.0.2" + }, "mypy": { "hashes": [ - "sha256:0ebfb3f414204b98c06791af37a3a96772203da60636e2897408517fcfeee7a8", - "sha256:239d6b2242d6c7f5822163ee082ef7a28ee02e7ac86c35593ef923796826a385", - "sha256:29dc94d9215c3eb80ac3c2ad29d0c22628accfb060348fd23d73abe3ace6c10d", - "sha256:2c7f8bb9619290836a4e167e2ef1f2cf14d70e0bc36c04441e41487456561409", - "sha256:33d53a232bb79057f33332dbbb6393e68acbcb776d2f571ba4b1d50a2c8ba873", - "sha256:3a3e525cd76c2c4f90f1449fd034ba21fcca68050ff7c8397bb7dd25dd8b8248", - "sha256:3eabcbd2525f295da322dff8175258f3fc4c3eb53f6d1929644ef4d99b92e72d", - "sha256:481f98c6b24383188c928f33dd2f0776690807e12e9989dd0419edd5c74aa53b", - "sha256:7a76dc4f91e92db119b1be293892df8379b08fd31795bb44e0ff84256d34c251", - "sha256:7d390248ec07fa344b9f365e6ed9d205bd0205e485c555bed37c4235c868e9d5", - "sha256:826a2917c275e2ee05b7c7b736c1e6549a35b7ea5a198ca457f8c2ebea2cbecf", - "sha256:85cf2b14d32b61db24ade8ac9ae7691bdfc572a403e3cb8537da936e74713275", - "sha256:8d645e9e7f7a5da3ec3bbcc314ebb9bb22c7ce39e70367830eb3c08d0140b9ce", - "sha256:925aa84369a07846b7f3b8556ccade1f371aa554f2bd4fb31cb97a24b73b036e", - "sha256:a85a20b43fa69efc0b955eba1db435e2ffecb1ca695fe359768e0503b91ea89f", - "sha256:bfd4f6536bd384c27c392a8b8f790fd0ed5c0cf2f63fc2fed7bce56751d53026", - "sha256:cb7752b24528c118a7403ee955b6a578bfcf5879d5ee91790667c8ea511d2085", - "sha256:cc537885891382e08129d9862553b3d00d4be3eb15b8cae9e2466452f52b0117", - "sha256:d4fccf04c1acf750babd74252e0f2db6bd2ac3aa8fe960797d9f3ef41cf2bfd4", - "sha256:f1ba54d440d4feee49d8768ea952137316d454b15301c44403db3f2cb51af024", - "sha256:f47322796c412271f5aea48381a528a613f33e0a115452d03ae35d673e6064f8", - "sha256:fbfb873cf2b8d8c3c513367febde932e061a5f73f762896826ba06391d932b2a", - "sha256:ffdad80a92c100d1b0fe3d3cf1a4724136029a29afe8566404c0146747114382" + "sha256:006be38474216b833eca29ff6b73e143386f352e10e9c2fbe76aa8549e5554f5", + "sha256:03c6cc893e7563e7b2949b969e63f02c000b32502a1b4d1314cabe391aa87d66", + "sha256:0e9f70df36405c25cc530a86eeda1e0867863d9471fe76d1273c783df3d35c2e", + "sha256:1ece702f29270ec6af25db8cf6185c04c02311c6bb21a69f423d40e527b75c56", + "sha256:3e09f1f983a71d0672bbc97ae33ee3709d10c779beb613febc36805a6e28bb4e", + "sha256:439c726a3b3da7ca84a0199a8ab444cd8896d95012c4a6c4a0d808e3147abf5d", + "sha256:5a0b53747f713f490affdceef835d8f0cb7285187a6a44c33821b6d1f46ed813", + "sha256:5f1332964963d4832a94bebc10f13d3279be3ce8f6c64da563d6ee6e2eeda932", + "sha256:63e85a03770ebf403291ec50097954cc5caf2a9205c888ce3a61bd3f82e17569", + "sha256:64759a273d590040a592e0f4186539858c948302c653c2eac840c7a3cd29e51b", + "sha256:697540876638ce349b01b6786bc6094ccdaba88af446a9abb967293ce6eaa2b0", + "sha256:9940e6916ed9371809b35b2154baf1f684acba935cd09928952310fbddaba648", + "sha256:9f5f5a74085d9a81a1f9c78081d60a0040c3efb3f28e5c9912b900adf59a16e6", + "sha256:a5ea0875a049de1b63b972456542f04643daf320d27dc592d7c3d9cd5d9bf950", + "sha256:b117650592e1782819829605a193360a08aa99f1fc23d1d71e1a75a142dc7e15", + "sha256:b24be97351084b11582fef18d79004b3e4db572219deee0212078f7cf6352723", + "sha256:b88f784e9e35dcaa075519096dc947a388319cb86811b6af621e3523980f1c8a", + "sha256:bdd5ca340beffb8c44cb9dc26697628d1b88c6bddf5c2f6eb308c46f269bb6f3", + "sha256:d5aaf1edaa7692490f72bdb9fbd941fbf2e201713523bdb3f4038be0af8846c6", + "sha256:e999229b9f3198c0c880d5e269f9f8129c8862451ce53a011326cad38b9ccd24", + "sha256:f4a21d01fc0ba4e31d82f0fff195682e29f9401a8bdb7173891070eb260aeb3b", + "sha256:f4b794db44168a4fc886e3450201365c9526a522c46ba089b55e1f11c163750d", + "sha256:f730d56cb924d371c26b8eaddeea3cc07d78ff51c521c6d04899ac6904b75492" ], "index": "pypi", - "version": "==0.960" + "version": "==0.961" }, "mypy-extensions": { "hashes": [ @@ -1514,10 +1958,11 @@ }, "nodeenv": { "hashes": [ - "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b", - "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7" + "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e", + "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b" ], - "version": "==1.6.0" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", + "version": "==1.7.0" }, "packaging": { "hashes": [ @@ -1616,6 +2061,23 @@ "index": "pypi", "version": "==7.1.2" }, + "pytest-aiohttp": { + "hashes": [ + "sha256:1d2dc3a304c2be1fd496c0c2fb6b31ab60cd9fc33984f761f951f8ea1eb4ca95", + "sha256:39ff3a0d15484c01d1436cbedad575c6eafbf0f57cdf76fb94994c97b5b8c5a4" + ], + "index": "pypi", + "version": "==1.0.4" + }, + "pytest-asyncio": { + "hashes": [ + "sha256:16cf40bdf2b4fb7fc8e4b82bd05ce3fbcd454cbf7b92afc445fe299dabb88213", + "sha256:7659bdb0a9eb9c6e3ef992eef11a2b3e69697800ad02fb06374a210d85b29f91", + "sha256:8fafa6c52161addfd41ee7ab35f11836c5a16ec208f93ee388f752bea3493a84" + ], + "markers": "python_version >= '3.7'", + "version": "==0.18.3" + }, "pytest-cov": { "hashes": [ "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6", @@ -1707,6 +2169,7 @@ "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" ], + "markers": "python_version >= '3.7'", "version": "==2.0.1" }, "typing-extensions": { @@ -1719,11 +2182,89 @@ }, "virtualenv": { "hashes": [ - "sha256:e617f16e25b42eb4f6e74096b9c9e37713cf10bf30168fb4a739f3fa8f898a3a", - "sha256:ef589a79795589aada0c1c5b319486797c03b67ac3984c48c669c0e4f50df3a5" + "sha256:288171134a2ff3bfb1a2f54f119e77cd1b81c29fc1265a2356f3e8d14c7d58c4", + "sha256:b30aefac647e86af6d82bfc944c556f8f1a9c90427b2fb4e3bfbf338cb82becf" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==20.14.1" + "version": "==20.15.1" + }, + "yarl": { + "hashes": [ + "sha256:044daf3012e43d4b3538562da94a88fb12a6490652dbc29fb19adfa02cf72eac", + "sha256:0cba38120db72123db7c58322fa69e3c0efa933040ffb586c3a87c063ec7cae8", + "sha256:167ab7f64e409e9bdd99333fe8c67b5574a1f0495dcfd905bc7454e766729b9e", + "sha256:1be4bbb3d27a4e9aa5f3df2ab61e3701ce8fcbd3e9846dbce7c033a7e8136746", + "sha256:1ca56f002eaf7998b5fcf73b2421790da9d2586331805f38acd9997743114e98", + "sha256:1d3d5ad8ea96bd6d643d80c7b8d5977b4e2fb1bab6c9da7322616fd26203d125", + "sha256:1eb6480ef366d75b54c68164094a6a560c247370a68c02dddb11f20c4c6d3c9d", + "sha256:1edc172dcca3f11b38a9d5c7505c83c1913c0addc99cd28e993efeaafdfaa18d", + "sha256:211fcd65c58bf250fb994b53bc45a442ddc9f441f6fec53e65de8cba48ded986", + "sha256:29e0656d5497733dcddc21797da5a2ab990c0cb9719f1f969e58a4abac66234d", + "sha256:368bcf400247318382cc150aaa632582d0780b28ee6053cd80268c7e72796dec", + "sha256:39d5493c5ecd75c8093fa7700a2fb5c94fe28c839c8e40144b7ab7ccba6938c8", + "sha256:3abddf0b8e41445426d29f955b24aeecc83fa1072be1be4e0d194134a7d9baee", + "sha256:3bf8cfe8856708ede6a73907bf0501f2dc4e104085e070a41f5d88e7faf237f3", + "sha256:3ec1d9a0d7780416e657f1e405ba35ec1ba453a4f1511eb8b9fbab81cb8b3ce1", + "sha256:45399b46d60c253327a460e99856752009fcee5f5d3c80b2f7c0cae1c38d56dd", + "sha256:52690eb521d690ab041c3919666bea13ab9fbff80d615ec16fa81a297131276b", + "sha256:534b047277a9a19d858cde163aba93f3e1677d5acd92f7d10ace419d478540de", + "sha256:580c1f15500e137a8c37053e4cbf6058944d4c114701fa59944607505c2fe3a0", + "sha256:59218fef177296451b23214c91ea3aba7858b4ae3306dde120224cfe0f7a6ee8", + "sha256:5ba63585a89c9885f18331a55d25fe81dc2d82b71311ff8bd378fc8004202ff6", + "sha256:5bb7d54b8f61ba6eee541fba4b83d22b8a046b4ef4d8eb7f15a7e35db2e1e245", + "sha256:6152224d0a1eb254f97df3997d79dadd8bb2c1a02ef283dbb34b97d4f8492d23", + "sha256:67e94028817defe5e705079b10a8438b8cb56e7115fa01640e9c0bb3edf67332", + "sha256:695ba021a9e04418507fa930d5f0704edbce47076bdcfeeaba1c83683e5649d1", + "sha256:6a1a9fe17621af43e9b9fcea8bd088ba682c8192d744b386ee3c47b56eaabb2c", + "sha256:6ab0c3274d0a846840bf6c27d2c60ba771a12e4d7586bf550eefc2df0b56b3b4", + "sha256:6feca8b6bfb9eef6ee057628e71e1734caf520a907b6ec0d62839e8293e945c0", + "sha256:737e401cd0c493f7e3dd4db72aca11cfe069531c9761b8ea474926936b3c57c8", + "sha256:788713c2896f426a4e166b11f4ec538b5736294ebf7d5f654ae445fd44270832", + "sha256:797c2c412b04403d2da075fb93c123df35239cd7b4cc4e0cd9e5839b73f52c58", + "sha256:8300401dc88cad23f5b4e4c1226f44a5aa696436a4026e456fe0e5d2f7f486e6", + "sha256:87f6e082bce21464857ba58b569370e7b547d239ca22248be68ea5d6b51464a1", + "sha256:89ccbf58e6a0ab89d487c92a490cb5660d06c3a47ca08872859672f9c511fc52", + "sha256:8b0915ee85150963a9504c10de4e4729ae700af11df0dc5550e6587ed7891e92", + "sha256:8cce6f9fa3df25f55521fbb5c7e4a736683148bcc0c75b21863789e5185f9185", + "sha256:95a1873b6c0dd1c437fb3bb4a4aaa699a48c218ac7ca1e74b0bee0ab16c7d60d", + "sha256:9b4c77d92d56a4c5027572752aa35082e40c561eec776048330d2907aead891d", + "sha256:9bfcd43c65fbb339dc7086b5315750efa42a34eefad0256ba114cd8ad3896f4b", + "sha256:9c1f083e7e71b2dd01f7cd7434a5f88c15213194df38bc29b388ccdf1492b739", + "sha256:a1d0894f238763717bdcfea74558c94e3bc34aeacd3351d769460c1a586a8b05", + "sha256:a467a431a0817a292121c13cbe637348b546e6ef47ca14a790aa2fa8cc93df63", + "sha256:aa32aaa97d8b2ed4e54dc65d241a0da1c627454950f7d7b1f95b13985afd6c5d", + "sha256:ac10bbac36cd89eac19f4e51c032ba6b412b3892b685076f4acd2de18ca990aa", + "sha256:ac35ccde589ab6a1870a484ed136d49a26bcd06b6a1c6397b1967ca13ceb3913", + "sha256:bab827163113177aee910adb1f48ff7af31ee0289f434f7e22d10baf624a6dfe", + "sha256:baf81561f2972fb895e7844882898bda1eef4b07b5b385bcd308d2098f1a767b", + "sha256:bf19725fec28452474d9887a128e98dd67eee7b7d52e932e6949c532d820dc3b", + "sha256:c01a89a44bb672c38f42b49cdb0ad667b116d731b3f4c896f72302ff77d71656", + "sha256:c0910c6b6c31359d2f6184828888c983d54d09d581a4a23547a35f1d0b9484b1", + "sha256:c10ea1e80a697cf7d80d1ed414b5cb8f1eec07d618f54637067ae3c0334133c4", + "sha256:c1164a2eac148d85bbdd23e07dfcc930f2e633220f3eb3c3e2a25f6148c2819e", + "sha256:c145ab54702334c42237a6c6c4cc08703b6aa9b94e2f227ceb3d477d20c36c63", + "sha256:c17965ff3706beedafd458c452bf15bac693ecd146a60a06a214614dc097a271", + "sha256:c19324a1c5399b602f3b6e7db9478e5b1adf5cf58901996fc973fe4fccd73eed", + "sha256:c2a1ac41a6aa980db03d098a5531f13985edcb451bcd9d00670b03129922cd0d", + "sha256:c6ddcd80d79c96eb19c354d9dca95291589c5954099836b7c8d29278a7ec0bda", + "sha256:c9c6d927e098c2d360695f2e9d38870b2e92e0919be07dbe339aefa32a090265", + "sha256:cc8b7a7254c0fc3187d43d6cb54b5032d2365efd1df0cd1749c0c4df5f0ad45f", + "sha256:cff3ba513db55cc6a35076f32c4cdc27032bd075c9faef31fec749e64b45d26c", + "sha256:d260d4dc495c05d6600264a197d9d6f7fc9347f21d2594926202fd08cf89a8ba", + "sha256:d6f3d62e16c10e88d2168ba2d065aa374e3c538998ed04996cd373ff2036d64c", + "sha256:da6df107b9ccfe52d3a48165e48d72db0eca3e3029b5b8cb4fe6ee3cb870ba8b", + "sha256:dfe4b95b7e00c6635a72e2d00b478e8a28bfb122dc76349a06e20792eb53a523", + "sha256:e39378894ee6ae9f555ae2de332d513a5763276a9265f8e7cbaeb1b1ee74623a", + "sha256:ede3b46cdb719c794427dcce9d8beb4abe8b9aa1e97526cc20de9bd6583ad1ef", + "sha256:f2a8508f7350512434e41065684076f640ecce176d262a7d54f0da41d99c5a95", + "sha256:f44477ae29025d8ea87ec308539f95963ffdc31a82f42ca9deecf2d505242e72", + "sha256:f64394bd7ceef1237cc604b5a89bf748c95982a84bcd3c4bbeb40f685c810794", + "sha256:fc4dd8b01a8112809e6b636b00f487846956402834a7fd59d46d4f4267181c41", + "sha256:fce78593346c014d0d986b7ebc80d782b7f5e19843ca798ed62f8e3ba8728576", + "sha256:fd547ec596d90c8676e369dd8a581a21227fe9b4ad37d0dc7feb4ccf544c2d59" + ], + "markers": "python_version >= '3.6'", + "version": "==1.7.2" } } } diff --git a/consumer.py b/consumer.py index 77001e3a..358a2aa9 100644 --- a/consumer.py +++ b/consumer.py @@ -52,6 +52,7 @@ missing_handler, current_consumer_offset, ) +from thoth.investigator.github_service import GithubService from thoth.common import OpenShift, init_logging from thoth.storages.graph import GraphDatabase @@ -117,6 +118,9 @@ halted_partitions = [] # type: List[TopicPartition] c = None # type: Optional[Consumer] +gh_service = GithubService( + app_id=os.getenv("KEBECHET_APP_ID"), app_private_key_path=os.getenv("KEBECHET_APP_PRIVATE_KEY_PATH") +) def _handler_lookup(topic_name, version, table=investigator_handler_table, default=None): @@ -209,7 +213,13 @@ async def _worker(q: asyncio.Queue): contents = json.loads(msg.value().decode("utf-8")) for i in range(0, Configuration.MAX_RETRIES): try: - await func(contents, openshift=openshift, graph=graph, msg=msg) + await func( + contents, + openshift=openshift, + graph=graph, + gh_service=gh_service, + msg=msg, + ) c.commit(message=msg) current_consumer_offset.labels(topic_name=msg.topic(), partition=msg.partition()).set(msg.offset()) break diff --git a/tests/github_api_responses/get_installation_token_success.json b/tests/github_api_responses/get_installation_token_success.json new file mode 100644 index 00000000..84a9196c --- /dev/null +++ b/tests/github_api_responses/get_installation_token_success.json @@ -0,0 +1,134 @@ +{ + "token": "ghs_16C7e42F292c6912E7710c838347Ae178B4a", + "expires_at": "2016-07-11T22:14:10Z", + "permissions": { + "issues": "write", + "contents": "read" + }, + "repository_selection": "selected", + "repositories": [ + { + "id": 1296269, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/octocat/Hello-World", + "description": "This your first repo!", + "fork": false, + "url": "https://api.github.com/repos/octocat/Hello-World", + "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "https://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", + "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", + "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "clone_url": "https://github.com/octocat/Hello-World.git", + "mirror_url": "git:git.example.com/octocat/Hello-World", + "hooks_url": "https://api.github.com/repos/octocat/Hello-World/hooks", + "svn_url": "https://svn.github.com/octocat/Hello-World", + "homepage": "https://github.com", + "language": null, + "forks_count": 9, + "stargazers_count": 80, + "watchers_count": 80, + "size": 108, + "default_branch": "master", + "open_issues_count": 0, + "is_template": true, + "topics": [ + "octocat", + "atom", + "electron", + "api" + ], + "has_issues": true, + "has_projects": true, + "has_wiki": true, + "has_pages": false, + "has_downloads": true, + "archived": false, + "disabled": false, + "visibility": "public", + "pushed_at": "2011-01-26T19:06:43Z", + "created_at": "2011-01-26T19:01:12Z", + "updated_at": "2011-01-26T19:14:43Z", + "permissions": { + "admin": false, + "push": false, + "pull": true + }, + "allow_rebase_merge": true, + "template_repository": null, + "temp_clone_token": "ABTLWHOULUVAXGTRYU7OC2876QJ2O", + "allow_squash_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": true, + "allow_merge_commit": true, + "subscribers_count": 42, + "network_count": 0, + "license": { + "key": "mit", + "name": "MIT License", + "url": "https://api.github.com/licenses/mit", + "spdx_id": "MIT", + "node_id": "MDc6TGljZW5zZW1pdA==", + "html_url": "https://github.com/licenses/mit" + }, + "forks": 1, + "open_issues": 1, + "watchers": 1 + } + ] +} diff --git a/tests/github_api_responses/get_repo_installation_success.json b/tests/github_api_responses/get_repo_installation_success.json new file mode 100644 index 00000000..805813a2 --- /dev/null +++ b/tests/github_api_responses/get_repo_installation_success.json @@ -0,0 +1,50 @@ +{ + "id": 1, + "account": { + "login": "github", + "id": 1, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjE=", + "avatar_url": "https://github.com/images/error/hubot_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/orgs/github", + "html_url": "https://github.com/github", + "followers_url": "https://api.github.com/users/github/followers", + "following_url": "https://api.github.com/users/github/following{/other_user}", + "gists_url": "https://api.github.com/users/github/gists{/gist_id}", + "starred_url": "https://api.github.com/users/github/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/github/subscriptions", + "organizations_url": "https://api.github.com/users/github/orgs", + "repos_url": "https://api.github.com/orgs/github/repos", + "events_url": "https://api.github.com/orgs/github/events", + "received_events_url": "https://api.github.com/users/github/received_events", + "type": "Organization", + "site_admin": false + }, + "repository_selection": "all", + "access_tokens_url": "https://api.github.com/installations/1/access_tokens", + "repositories_url": "https://api.github.com/installation/repositories", + "html_url": "https://github.com/organizations/github/settings/installations/1", + "app_id": 1, + "target_id": 1, + "target_type": "Organization", + "permissions": { + "checks": "write", + "metadata": "read", + "contents": "read" + }, + "events": [ + "push", + "pull_request" + ], + "created_at": "2018-02-09T20:51:14Z", + "updated_at": "2018-02-09T20:51:14Z", + "single_file_name": "config.yml", + "has_multiple_single_files": true, + "single_file_paths": [ + "config.yml", + ".github/issue_TEMPLATE.md" + ], + "app_slug": "github-actions", + "suspended_at": null, + "suspended_by": null +} diff --git a/tests/github_service_test.py b/tests/github_service_test.py new file mode 100644 index 00000000..85271a9e --- /dev/null +++ b/tests/github_service_test.py @@ -0,0 +1,63 @@ +"""Testing for async github service classes.""" + +import json +import os +from unittest.mock import MagicMock +import jwt +import pytest +from thoth.investigator.github_service import GithubApp + +PUBLICKEY_FILENAME = os.path.join(os.path.dirname(__file__), "keys/jwt-key.pub") +PRIVATEKEY_FILENAME = os.path.join(os.path.dirname(__file__), "keys/jwt-key") + +GITHUBAPI_RESPONSES_DIR = os.path.join(os.path.dirname(__file__), "github_api_responses") + + +def _decrypt_jwt(jw_token: str, publickey): + return jwt.decode(jwt=jw_token.encode(), key=publickey, algorithms=["RS256"]) + + +async def get_json_file_content(file_name) -> dict: + with open(file_name, "r") as f: + return json.load(f) + + +class TestGithubApp: + def setup(self): + with open(PUBLICKEY_FILENAME, "r") as f: + self.public_key = f.read() + self.github_app = GithubApp("kebechet", PRIVATEKEY_FILENAME) + + def test_generate_jwt(self): + jw_token = self.github_app._generate_jwt() + content: dict = _decrypt_jwt(jw_token, self.public_key) + assert content["iss"] == "kebechet" + assert "iat" in content + assert "exp" in content + + @pytest.mark.asyncio + async def test_get_repo_installation_info(self): + self.setup() + mock = self.github_app._session + mock.get = MagicMock() + mock.get.return_value.__aenter__.return_value.json = lambda: get_json_file_content( + os.path.join(GITHUBAPI_RESPONSES_DIR, "get_repo_installation_success.json") + ) + mock.get.return_value.__aenter__.return_value.status = 200 + id = await self.github_app._get_installation_id_for_repo("github", "octocat") + assert mock.get.call_count == 1 + assert id == 1 + + @pytest.mark.asyncio + async def test_get_repo_installation_token(self): + self.setup() + self.github_app._get_installation_id_for_repo = MagicMock() + self.github_app._get_installation_id_for_repo.return_value = 1 + mock = self.github_app._session + mock.post = MagicMock() + mock.post.return_value.__aenter__.return_value.json = lambda: get_json_file_content( + os.path.join(GITHUBAPI_RESPONSES_DIR, "get_installation_token_success.json") + ) + mock.post.return_value.__aenter__.return_value.status = 201 + token = await self.github_app.get_repository_token("foo", "bar") + assert token.token == "ghs_16C7e42F292c6912E7710c838347Ae178B4a" diff --git a/tests/investigate_unresolved_package_test.py b/tests/investigate_unresolved_package_test.py index 4e5a54b8..c783fe80 100644 --- a/tests/investigate_unresolved_package_test.py +++ b/tests/investigate_unresolved_package_test.py @@ -18,7 +18,7 @@ """Test investigator.""" from tests.base_test import InvestigatorTestCase -from thoth.investigator.investigate_unresolved_package import investigate_unresolved_package +from thoth.investigator.unresolved_package import investigate_unresolved_package class TestProducer(InvestigatorTestCase): diff --git a/tests/keys/jwt-key b/tests/keys/jwt-key new file mode 100644 index 00000000..18512214 --- /dev/null +++ b/tests/keys/jwt-key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJQQIBADANBgkqhkiG9w0BAQEFAASCCSswggknAgEAAoICAQCqKu7vdySxrNV0 +CxiUEPwQlp8Y5rhL1iNndQhU8KgQsXv601t7nfEBV0OIr9Brqli0QjEXWSZACBOx +dbM+tU5fdHKMx8eICuxNBKDE7OojOdCMmF4IfMeGGnpO7IuSn3pv0FaKGb232prd +VqW5XJ7eO5BMido0kn3KhqmWunkosw78390phPXxzHpyOpngTlP4olAj7EoJqo6K +lFfeYm7hB0ob+pxoLWYsKMafS1lexWFoSOT6dtT37As2sof/RjeWtZYd05M8ImhX +LntCeBY9aEGkfXn/3y6U6NrMAvXgtHBNb6zjSJ+zXaytHdycmHiKlINX8tvrETYU +BUfQ4LO8EwYe57a+bsAbX0XFslw8GGQROpPUwe1JV+yGZkhVnLWcEtptzWk3iqqE +pzsAKyP1mtMLdlF5rTP6sFRRInz4rth3o458oz9Ttj2LXURTUTy26PDGu6axfMMh +Q9hBII6pQUnlArWRXHjsawH+hJJ8255mBTA60DoF4mK49/oeecFRyB+fEGM3bBFO +7rU0+Rb3eU1WioaKTpOWPRClaqp/bMKMuEaXcKrXwJMbvoo848YgLJNO8UeAcecy +SZrI1V9a/R+GqO/0IToVkw009o9ZINtL/VLnVohJvhWRGfIOCzGm68abgj+4Nkm9 +yftqx/PoVNEHutzRL35ZI1YSdX7bYQIDAQABAoICAAHGSYp5TUC8S8CG4WYlKgwD +BtPNyZmmUFmwWQI+e1LtPe5Gf2gNDSIZZquyQU73GBBavtdvDTAzXKKLzv6VKMAt +ggx8bUlN+wIM2TL1/ALoTaLtWEUWilYvob5gr5P9czDjKktiDqP9wIoU4Tl13Ebv +GuaBrPhsrxXldXVheBxhjxp4BamEcGaE3lQGO6odBoNNhO5W2dO3OKHlHnfTi/WG +pQKscS6KFyWSaUlsX3J5m2h8QcGWuPVCrF8z+JnbKJYf5XjaL3yY8njaCGfpD5AC +d2XekoHmkxdvcz5dnXoqKAjeNftrw3JYNPbUajW+8R8bobVgvP6WF2ChAr26+PD3 +fBIB04TNwP+D7LZK6AmXgoe7ohaiQtcHVz56TqikrPkIHnX2RJR8fv/+WjCAM5G7 +zsNXBjtghl+80Adw8YUUkXxTcTTsAX8irnl6tkF8c4ZgkFy2yYuPG/dYoh2o4zgq +jXJVLKhkWG64cGwnpYdl3cxZAynW0k7jtmoAqRFQHa2G0hmL65ftXOjwEAlB+Bdf +D99vQjrDuFxBlnJBosdZEZpbjLrO7zzazc0AOQOyUn2RI7aHJEOurUxjihH61MZq +2oADJGl+h6t8rQe5IbvP5kN+Fuw0B6Dcu5BIj5I6eSWAumgcyc3EKlzjCnOO5FVB +wPe7SYxwFtApWwdKhb3/AoIBAQDW9DDt17uJ7s3zSAia2msRB0yvlkh/osfhhf2h +drHyj/rAPu/xfgInMt1rjj/caE26SY9L/vq53Z9e9PqOgikbQWDTycqgLD6pZCwD +otO5c90k094yzGJLwrKjFUSLTAak6PuKoJJnLexc51vvmh958YFbH9qX0m2LkA6W +Hu004cCfuyc5+YU1GKUplHvi/O413nFuLL07njjlLP2GBesnBndcksM7K3R+aAO2 +EAMDmivjlaPzoxVQNz4SqEOnVCfXl12vxgf+1l7d95PBZPGDoDn5+oQ3y094wDc1 +OOj1GSelfCAXHU0EZ4f5nrDrYZ+UWzpmME58uQqSZOoNq6IrAoIBAQDKqWokLs9L +DIVTNOg/oK+GtODKZQ1cyEE0wkhUBTgDas27eXXD8nxUsZ0/qJKH7RWbGY/hvyvV +rKwFKl8ELJYkf32euH+utM5wNO4aAEV6kEHnl0jwBnEoVlcZqt1D0u3Q2FTKc9uj +lPuQFz7m3BWqsIqwgFmqS1xDVVoKtm56PhO4hGKao2SAOOR5qRiiorg/GisULd1k +gzIme58wuyl3sN44qII0w+gAbzcI3+n56c8uiQEXAnaYXIG3tAy3giu4bj7SQ7p2 +WLhDcIwwEu9wXeO+2L10wsL1nEyD7VRhN3ckrlxS4X0ii7bxSIeqKG2B1sEvtoF1 +6QfJnn3qKM6jAoIBAHAfdfpKYpejSihRdbOYpOp//T9Fy9FQDqUTqGX1rQKSmcB3 +098K1IKv5JF65NLKUWkPf8CrYwtakAwPCzcUq+58ns46XwhHq/PdvZuz7m65Aix4 +m1myBL/x8g5hRJzIblrM8JCyC0vox3b6c5k6spqAH/JxXit9Zwi6fvFNdnv0Ge73 +x5FVF2fH0DctLaYMOxE8U7ydd6PGd3ULj76+DZgQpmhSYaXWl/BrvyvTlE7nt2cC +IkAu3Co4dpdyz79ThWjOmt7aFEeYeGmd/6OMTPJUvIkpZJhZ471fvixz4AghM+39 +HhwQe6EFhAbwAOb2yC+xmne9UON7/gi4vOGemnsCggEACPL+OubORJQi9w+pCdZA +qgQmwQlBU82MA5Zotz0bwhrfRt4QMzzr/JlzRjJddh8kCxtP3Toh52eemQPL+lU1 +tBrlIzMmgEJ/szjDIubMKqNgJafqkp7WNF/LrNh8uNgBpG1JIT+IfWrAyRYdsvgZ +BNaS6URhsUFuq5KDTWHM8xz2pflCmW2JrJfWjwDGk7f3xuGS8WstEZkxh72BxBcf +t6dZyMq4JThZcFt45K1umZiXi4iFQczcC9JZ8BDFVv0qjRRhNcvD2iIE0QWRSzYq +2J1sxyqvAw7uqQXj4xeB2GEoo7gHX6mRawscYv8+7mamn0sqcL7wbJKDw4V6LfLr +XQKCAQB7Hp61RNPN2WmXH1ctVIrLnj/QmDHPZygASpdjBnRcbxG319bgpMNWDJLd +rrSHJOX66AlobzisF6liCYhdLMorAXffzX19cS2iB8Ft3T7QJQ5lpV4eHb5rM5vt +Fz6MWj7chzUrCXEw8NjiMS0aL5ADf9qAH4i6gfc/rAvvJl5vSCXJwu4Nm6Jgw0hW +LP/viRt1jW3J/nE86iMamlvCxGX+A8HzqvlXixdGeVHFYQqt61kfSqnSojezRSPV +uayF3/shCRbRfg6rk1FJFChvCecV8NaiIuTKugXoViKXmUAvPQp2mcyVr2ar6mH2 +Nqp0u3nM2LBCb1WPY31MGdcSX/qp +-----END PRIVATE KEY----- diff --git a/tests/keys/jwt-key.pub b/tests/keys/jwt-key.pub new file mode 100644 index 00000000..21c25a57 --- /dev/null +++ b/tests/keys/jwt-key.pub @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqiru73cksazVdAsYlBD8 +EJafGOa4S9YjZ3UIVPCoELF7+tNbe53xAVdDiK/Qa6pYtEIxF1kmQAgTsXWzPrVO +X3RyjMfHiArsTQSgxOzqIznQjJheCHzHhhp6TuyLkp96b9BWihm9t9qa3ValuVye +3juQTInaNJJ9yoaplrp5KLMO/N/dKYT18cx6cjqZ4E5T+KJQI+xKCaqOipRX3mJu +4QdKG/qcaC1mLCjGn0tZXsVhaEjk+nbU9+wLNrKH/0Y3lrWWHdOTPCJoVy57QngW +PWhBpH15/98ulOjazAL14LRwTW+s40ifs12srR3cnJh4ipSDV/Lb6xE2FAVH0OCz +vBMGHue2vm7AG19FxbJcPBhkETqT1MHtSVfshmZIVZy1nBLabc1pN4qqhKc7ACsj +9ZrTC3ZRea0z+rBUUSJ8+K7Yd6OOfKM/U7Y9i11EU1E8tujwxrumsXzDIUPYQSCO +qUFJ5QK1kVx47GsB/oSSfNueZgUwOtA6BeJiuPf6HnnBUcgfnxBjN2wRTu61NPkW +93lNVoqGik6Tlj0QpWqqf2zCjLhGl3Cq18CTG76KPOPGICyTTvFHgHHnMkmayNVf +Wv0fhqjv9CE6FZMNNPaPWSDbS/1S51aISb4VkRnyDgsxpuvGm4I/uDZJvcn7asfz +6FTRB7rc0S9+WSNWEnV+22ECAwEAAQ== +-----END PUBLIC KEY----- diff --git a/thoth/investigator/common.py b/thoth/investigator/common.py index a092c10e..2954afd2 100644 --- a/thoth/investigator/common.py +++ b/thoth/investigator/common.py @@ -22,12 +22,17 @@ from math import inf from asyncio import sleep import json - +import os from typing import List, Tuple, Optional, Callable +import yaml + +from .github_service import GithubService from thoth.common import OpenShift +from thoth.common.enums import ThothAdviserIntegrationEnum from thoth.storages import GraphDatabase from thoth.messaging import ALL_MESSAGES +from thamos import lib as thamos_lib from .configuration import Configuration from .metrics import message_version_metric @@ -103,21 +108,6 @@ async def wait_for_limit(openshift: OpenShift, workflow_namespace: str): _LOGGER.debug("Current number pending = %d", total_pending) -async def schedule_kebechet_administrator(openshift: OpenShift, message_info: dict, message_name: str) -> Optional[str]: - """Schedule Kebechet Administrator from a particular message.""" - try: - await wait_for_limit(openshift, workflow_namespace=Configuration.THOTH_BACKEND_NAMESPACE) - workflow_id = openshift.schedule_kebechet_administrator(message_info=message_info, message_type=message_name) - _LOGGER.info( - "Scheduled Kebechet Administrator workflow" - f" for message type {message_name} with workflow id - {workflow_id}" - ) - except Exception as e: - _LOGGER.exception(f"Failed to schedule Kebechet Administrator workflow for message type {message_name}: {e}") - raise e - return workflow_id - - async def learn_about_security( openshift: OpenShift, graph: GraphDatabase, @@ -320,3 +310,53 @@ async def _schedule_all_solvers( raise e return are_scheduled + + +async def send_advise_request_for_installation( + slug: str, environment_name: str, keb_meta: dict, gh_service: GithubService +): + """Send a request to Thoth user-api for a given runtime environment. + + args: + slug (str): '/' + environment_name (str): runtime environment name as it appears in .thoth.yaml + keb_meta (dict): meta data which indicates which internal trigger caused the request + gh_service (GithubService): GithubService instance for interacting with Github api + returns: + bool: returns true if the request was sent and false if it was not sent + """ + namespace, repo = slug.split("/") + project = gh_service.get_project(namespace=namespace, repo=repo) + thoth_config = await project.get_file(".thoth.yaml") + thoth_config = yaml.safe_load(thoth_config) + overlay_dir = thoth_config.get("overlays_dir", "") + if not overlay_dir and thoth_config["runtime_environments"][0]["name"] != environment_name: + return False # if no overlay present, only the first entry of environments should be acted on + for r_e in thoth_config["runtime_environments"]: + if r_e["name"] == environment_name: + runtime_environment = r_e + break + else: + return False # runtime environment is no longer present in config file, do not run adviser + + directory = os.path.join(overlay_dir, environment_name) if overlay_dir else "" + # TODO: use thoth_config["requirements_format"] to hand other types of requirements files + pipfile_path = os.path.join(directory, "Pipfile") + pipfile_lock_path = os.path.join(directory, "Pipfile.lock") + pipfile = await project.get_file(pipfile_path) + pipfile_lock = await project.get_file(pipfile_lock_path) + + # THAMOS_TOKEN env variable must be set because kebechet_metadata is protected + thamos_lib.advise( + pipfile=pipfile, + pipfile_lock=pipfile_lock, + recommendation_type=thoth_config.get("recommendation_type"), + runtime_environment=runtime_environment, + no_static_analysis=True, + nowait=True, + origin=f"https://github.com/{slug}", + source_type=ThothAdviserIntegrationEnum.KEBECHET, + kebechet_metadata=keb_meta, + ) + print("SUCCESS") + return True diff --git a/thoth/investigator/cve_provided/investigate_cve_provided.py b/thoth/investigator/cve_provided/investigate_cve_provided.py index bfb6e7d7..d57cf2b1 100644 --- a/thoth/investigator/cve_provided/investigate_cve_provided.py +++ b/thoth/investigator/cve_provided/investigate_cve_provided.py @@ -17,19 +17,25 @@ """Logic for handling cve provided message.""" +import asyncio import logging from typing import Dict, Any -from ..common import schedule_kebechet_administrator, register_handler +from ..common import register_handler, send_advise_request_for_installation from ..configuration import Configuration -from ..metrics import scheduled_workflows +from ..github_service import GithubService -from .metrics_cve_provided import cve_provided_exceptions -from .metrics_cve_provided import cve_provided_success -from .metrics_cve_provided import cve_provided_in_progress +from .metrics_cve_provided import ( + cve_provided_exceptions, + cve_provided_success, + cve_provided_in_progress, + cve_provided_sent_advise_requests, +) from prometheus_async.aio import track_inprogress, count_exceptions from thoth.messaging import cve_provided_message from thoth.common import OpenShift +from thoth.storages import GraphDatabase +from thoth.common.enums import InternalTriggerEnum _LOGGER = logging.getLogger(__name__) @@ -37,28 +43,35 @@ @register_handler(cve_provided_message.topic_name, ["v1"]) @count_exceptions(cve_provided_exceptions) @track_inprogress(cve_provided_in_progress) -async def parse_cve_provided(cve_provided: Dict[str, Any], openshift: OpenShift, **kwargs): +async def parse_cve_provided( + cve_provided: Dict[str, Any], openshift: OpenShift, graph: GraphDatabase, gh_service: GithubService, **kwargs +): """Process a cve provided message.""" # Add more logic if neccessary. - # Schedule Kebechet administrator. if Configuration.THOTH_INVESTIGATOR_SCHEDULE_KEBECHET_ADMIN: - message_info = { - "PACKAGE_NAME": cve_provided["package_name"], - "PACKAGE_VERSION": cve_provided["package_version"], - "PACKAGE_INDEX": cve_provided["index_url"], - } - - # We schedule Kebechet Administrator workflow here - - workflow_id = await schedule_kebechet_administrator( - openshift=openshift, - message_info=message_info, - message_name=cve_provided_message.base_name, + installations = graph.get_kebechet_github_installations_info_for_python_package_version( + package_name=cve_provided["package_name"], + package_version=cve_provided["package_version"], + index_url=cve_provided["index_url"], ) - - scheduled_workflows.labels( - message_type=cve_provided_message.base_name, workflow_type="kebechet-administrator" - ).inc() - _LOGGER.info(f"Scheduled kebechet administrator workflow {workflow_id}") + keb_meta = { + "message_justification": InternalTriggerEnum.CVE.value, + "package_name": cve_provided["package_name"], + "package_version": cve_provided["package_version"], + "package_index": cve_provided["index_url"], + } + tasks = [] + for key in installations: + tasks.append( + send_advise_request_for_installation( + slug=key, + environment_name=installations[key]["environment_name"], + keb_meta=keb_meta, + gh_service=gh_service, + ) + ) + num_requests_sent = sum(await asyncio.gather(*tasks)) + cve_provided_sent_advise_requests.inc(num_requests_sent) cve_provided_success.inc() diff --git a/thoth/investigator/cve_provided/metrics_cve_provided.py b/thoth/investigator/cve_provided/metrics_cve_provided.py index 4ba0ad64..bdff521b 100644 --- a/thoth/investigator/cve_provided/metrics_cve_provided.py +++ b/thoth/investigator/cve_provided/metrics_cve_provided.py @@ -17,8 +17,9 @@ """Set labels for cve provided metrics.""" -from ..metrics import in_progress, success, exceptions +from ..metrics import in_progress, success, exceptions, sent_advise_requests cve_provided_in_progress = in_progress.labels(message_type="cve_provided") cve_provided_success = success.labels(message_type="cve_provided") cve_provided_exceptions = exceptions.labels(message_type="cve_provided") +cve_provided_sent_advise_requests = sent_advise_requests.labels(message_type="cve_provided") diff --git a/thoth/investigator/github_service.py b/thoth/investigator/github_service.py new file mode 100644 index 00000000..620c6606 --- /dev/null +++ b/thoth/investigator/github_service.py @@ -0,0 +1,267 @@ +#!/usr/bin/env python3 +# thoth-investigator +# Copyright(C) 2022 Kevin Postlethwait +# +# This program is free software: you can redistribute it and / or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +"""This is an async library for interacting with the Github API using aiohttp.""" + +from typing import Optional, Union, NamedTuple +import asyncio +import time +from datetime import datetime + +import aiohttp +import jwt + +# this is an async wrapper for the GitHub API a more feature rich library is +# available here, but it is unclear whether this project is stable. +# https://github.com/brettcannon/gidgethub/issues + + +BASE_API_URL = "https://api.github.com" + + +class InstallationNotFoundError(Exception): + """Raised on http auth errors when the service is not installed on the requested repo.""" + + pass + + +class UnknownResponseCodeError(Exception): + """Raised when aiohttp request returns with status that is not handled.""" + + pass + + +class AccessToken(NamedTuple): + """Generic access token representation.""" + + token: str + expiration: Optional[Union[int, float]] = None # epoch time + + +class GithubAuth: + """Authorization interface.""" + + def __init__(self): + """Create generic github auth object.""" + self._event_loop = asyncio.get_event_loop() + self._session = aiohttp.ClientSession( + loop=self._event_loop, headers={"Accept": "application/vnd.github.v3"} # current API version + ) + + def __del__(self): + """Close aiohttp session associated with the object.""" + self._event_loop.run_until_complete(self._session.close()) + + async def get_auth_token(self): + """Get auth token for interacting with github api.""" + raise NotImplementedError() + + async def get_repository_token(self, namespace, repo) -> AccessToken: + """Get auth token for interacting with a specific repository.""" + raise NotImplementedError() + + +class GithubOAuth(GithubAuth): + """Implementation of GithubAuth using an OAuth token.""" + + def __init__(self, token: str): + """Github auth which uses simple OAuth token authentication.""" + self._token = AccessToken(token=token, expiration=None) + super().__init__() + + async def get_auth_token(self): + """Return OAuth token for authorization.""" + return self._token + + async def get_repository_token(self, namespace, repo) -> AccessToken: + """Return OAuthToken for authorization.""" + del namespace, repo # unused for this implementation + return self._token + + +class GithubApp(GithubAuth): + """Implementation of GithubAuth using github app.""" + + def __init__(self, app_id, app_private_key_path: str): + """Return GitHubAuth instance for a GitHub application.""" + self.app_private_key = self._get_app_private_key(app_private_key_path) + self.app_id = app_id + super().__init__() + + def _generate_jwt(self): + payload = { + # issued at time, 60 seconds in the past to allow for clock drift + "iat": int(time.time()) - 60, + # JWT expiration time (1 minute) + "exp": int(time.time()) + 60, + # GitHub App's identifier + "iss": self.app_id, + } + encrypted = jwt.encode(payload, self.app_private_key, algorithm="RS256") + if isinstance(encrypted, bytes): + encrypted = encrypted.decode("utf-8") + return encrypted + + @staticmethod + def _get_app_private_key(private_key_path: str) -> str: + """ + Get private key string from file. + + Returns + str: PEM256 key found in private_key_path file + Raises + FileNotFoundError + """ + with open(private_key_path, "r") as f: + return f.read() + + async def get_auth_token(self): + """ + Get App auth token. + + Note + expires in 60s it is best to generate a new token for each request + """ + return AccessToken(token=self._generate_jwt(), expiration=int(time.time()) + 60) + + async def _get_repository_installation(self, namespace, repo): + """https://docs.github.com/en/rest/reference/apps#get-a-repository-installation-for-the-authenticated-app.""" + async with self._session.get( + f"{BASE_API_URL}/repos/{namespace}/{repo}/installation", + headers={"Authorization": f"Bearer {(await self.get_auth_token()).token}"}, + ) as r: + if r.status == 404: + raise InstallationNotFoundError(f"App not installed for {namespace}/{repo}.") + elif r.status == 200: + return await r.json() + else: # only other response type is 301-'Moved Permanently' which should automatically redirect + raise UnknownResponseCodeError(f"GitHub API responded with status: {r.status}") + + async def _get_installation_id_for_repo(self, namespace, repo): + """Return the installation id for a given repository. + + Returns: + int: id of installation + Raises: + InstallationNotFoundError + """ + installation_info = await self._get_repository_installation(namespace, repo) + return installation_info["id"] + + async def get_repository_token(self, namespace, repo, installation_id: Optional[int] = None) -> AccessToken: + """ + Get auth token for a specific repository. Resultant token can be used for the github API Authorization header. + + args: namespace (str): user or organization which owns the repository repo (str): the name of the repository + without the attached namespace + raises: UnknownResponseCodeError, aiohttp.ClientResponseError + """ + installation_id = self._get_installation_id_for_repo(namespace, repo) + async with self._session.post( + f"{BASE_API_URL}/app/installations/{installation_id}/access_tokens", + headers={"Authorization": f"Bearer {(await self.get_auth_token()).token}"}, + raise_for_status=True, + ) as r: + if r.status == 201: # Successfully created + r_dict = await r.json() + return AccessToken( + r_dict["token"], datetime.strptime(r_dict["expires_at"], "%Y-%m-%dT%H:%M:%SZ").timestamp() + ) + else: + raise UnknownResponseCodeError(f"Unknown response code {r.status} while retrieving repository token") + + +class GithubService: + """Async class for interacting with generic GithubApi.""" + + def __init__( + self, token: Optional[str] = None, app_id: Optional[str] = None, app_private_key_path: Optional[str] = None + ): + """Return instance of GithubService.""" + if app_private_key_path and app_id: + self._auth: GithubAuth = GithubApp(app_id=app_id, app_private_key_path=app_private_key_path) + elif token: + self._auth = GithubOAuth(token=token) + + def get_project(self, namespace, repo): + """Return instance of a GitHubProject.""" + return GithubProject(self, namespace, repo) + + +class GithubProject: + """Async class for interacting with GitHub repository API.""" + + def __init__( + self, + github_service: GithubService, + namespace: str, + repo: str, + repository_id: Optional[int] = None, + ): + """Return an instance of a GithubProject.""" + self._repository_id = repository_id # for cases where we already have the repo_id to minimize api calls + self._github_service = github_service + self.namespace = namespace + self.repo = repo + self._token: Optional[AccessToken] = None + + async def _get_token(self) -> str: + if self._token is None: + self._token = await self._github_service._auth.get_repository_token(self.namespace, self.repo) + elif self._token.expiration is not None and self._token.expiration - time.time() < 0: # refresh token + self._token = await self._github_service._auth.get_repository_token(self.namespace, self.repo) + return self._token.token + + async def get_file(self, file_path: str) -> str: + """ + Download GitHub file to given path. + + args: + file_path (str): path to file relative to the root of the git repository + returns: + str + raises: + FileNotFoundError, TypeError, aiohttp.ClientResponseError + GitHubAPI docs: + https://docs.github.com/en/rest/reference/repos#get-repository-content + """ + async with self._github_service._auth._session.get( + f"{BASE_API_URL}/repos/{self.namespace}/{self.repo}/contents/{file_path}", + headers={"Authorization": f"token {await self._get_token()}"}, + ) as r: + if r.status == 404: + raise FileNotFoundError(f"{self.namespace}/{self.repo} does not have {file_path}") + elif r.status == 200: + r_dict = await r.json() + if type(r_dict) == list: + raise TypeError(f"{self.namespace}/{self.repo} has {file_path} but it is a directory") + if r_dict["type"] != "file": + raise TypeError(f"{self.namespace}/{self.repo} has {file_path} but it is a {r_dict['type']}") + download_url = r_dict["download_url"] + async with self._github_service._auth._session.get( + download_url, headers={"Authorization": f"token {await self._get_token()}"} + ) as r2: + if r2.status == 200: + return (await r2.read()).decode("utf8") + else: + raise UnknownResponseCodeError( + f"Unknown response code, {r.status}, when downloading file from git" + ) + else: + r.raise_for_status() + raise UnknownResponseCodeError(f"github api responded with status code {r.status} which is not handled") diff --git a/thoth/investigator/hash_mismatch/investigate_hash_mismatch.py b/thoth/investigator/hash_mismatch/investigate_hash_mismatch.py index e20ae217..d63b47df 100644 --- a/thoth/investigator/hash_mismatch/investigate_hash_mismatch.py +++ b/thoth/investigator/hash_mismatch/investigate_hash_mismatch.py @@ -17,19 +17,25 @@ """Logic for handling hash_mismatch message.""" +import asyncio import logging from typing import Dict, Any -from ..common import schedule_kebechet_administrator, learn_using_solver, register_handler +from ..common import send_advise_request_for_installation, learn_using_solver, register_handler from ..configuration import Configuration from ..metrics import scheduled_workflows +from ..github_service import GithubService -from .metrics_hash_mismatch import hash_mismatch_exceptions -from .metrics_hash_mismatch import hash_mismatch_success -from .metrics_hash_mismatch import hash_mismatch_in_progress +from .metrics_hash_mismatch import ( + hash_mismatch_exceptions, + hash_mismatch_success, + hash_mismatch_in_progress, + hash_mismatch_sent_advise_requests, +) from prometheus_async.aio import track_inprogress, count_exceptions from thoth.messaging import hash_mismatch_message from thoth.common import OpenShift +from thoth.common.enums import InternalTriggerEnum from thoth.storages import GraphDatabase _LOGGER = logging.getLogger(__name__) @@ -38,7 +44,9 @@ @register_handler(hash_mismatch_message.topic_name, ["v1"]) @count_exceptions(hash_mismatch_exceptions) @track_inprogress(hash_mismatch_in_progress) -async def parse_hash_mismatch(mismatch: Dict[str, Any], openshift: OpenShift, graph: GraphDatabase, **kwargs): +async def parse_hash_mismatch( + mismatch: Dict[str, Any], openshift: OpenShift, graph: GraphDatabase, gh_service: GithubService, **kwargs +): """Process a hash mismatch message from package-update producer.""" if Configuration.THOTH_INVESTIGATOR_SCHEDULE_SOLVER: # Solver logic @@ -65,22 +73,28 @@ async def parse_hash_mismatch(mismatch: Dict[str, Any], openshift: OpenShift, gr ) if Configuration.THOTH_INVESTIGATOR_SCHEDULE_KEBECHET_ADMIN: - message_info = { - "PACKAGE_NAME": mismatch["package_name"], - "PACKAGE_VERSION": mismatch["package_version"], - "PACKAGE_INDEX": mismatch["index_url"], - } - - # We schedule Kebechet Administrator workflow here - - workflow_id = await schedule_kebechet_administrator( - openshift=openshift, - message_info=message_info, - message_name=hash_mismatch_message.base_name, + installations = graph.get_kebechet_github_installations_info_for_python_package_version( + package_name=mismatch["package_name"], + package_version=mismatch["package_version"], + index_url=mismatch["index_url"], ) - scheduled_workflows.labels( - message_type=hash_mismatch_message.base_name, workflow_type="kebechet-administrator" - ).inc() - - _LOGGER.info(f"Scheduled kebechet administrator workflow {workflow_id}") + keb_meta = { + "message_justification": InternalTriggerEnum.HASH_MISMATCH.value, + "package_name": mismatch["package_name"], + "package_version": mismatch["package_version"], + "package_index": mismatch["index_url"], + } + tasks = [] + for key in installations: + tasks.append( + send_advise_request_for_installation( + slug=key, + environment_name=installations[key]["environment_name"], + keb_meta=keb_meta, + gh_service=gh_service, + ) + ) + num_requests_sent = sum(await asyncio.gather(*tasks)) + hash_mismatch_sent_advise_requests.inc(num_requests_sent) hash_mismatch_success.inc() diff --git a/thoth/investigator/hash_mismatch/metrics_hash_mismatch.py b/thoth/investigator/hash_mismatch/metrics_hash_mismatch.py index f28099ca..77d99047 100644 --- a/thoth/investigator/hash_mismatch/metrics_hash_mismatch.py +++ b/thoth/investigator/hash_mismatch/metrics_hash_mismatch.py @@ -17,8 +17,9 @@ """Set labels for hash_mismatch metrics.""" -from ..metrics import in_progress, success, exceptions +from ..metrics import in_progress, success, exceptions, sent_advise_requests hash_mismatch_in_progress = in_progress.labels(message_type="hash_mismatch") hash_mismatch_success = success.labels(message_type="hash_mismatch") hash_mismatch_exceptions = exceptions.labels(message_type="hash_mismatch") +hash_mismatch_sent_advise_requests = sent_advise_requests.labels(message_type="hash_mismatch") diff --git a/thoth/investigator/metrics.py b/thoth/investigator/metrics.py index e220b5b3..cfa0623b 100644 --- a/thoth/investigator/metrics.py +++ b/thoth/investigator/metrics.py @@ -69,6 +69,13 @@ registry=registry, ) +sent_advise_requests = Counter( + "thoth_investigator_sent_advise_requests", + "Requests sent to adviser from investigator.", + ["message_type"], + registry=registry, +) + halted_topics = Gauge( "thoth_investigator_halted_topics", "Boolean gauge indicating whether consumption of the topic has been halted.", diff --git a/thoth/investigator/missing_package/investigate_missing_package.py b/thoth/investigator/missing_package/investigate_missing_package.py index d633ac50..1802b2d2 100644 --- a/thoth/investigator/missing_package/investigate_missing_package.py +++ b/thoth/investigator/missing_package/investigate_missing_package.py @@ -17,20 +17,22 @@ """Logic for handling missing_package message.""" +import asyncio from typing import Dict, Any import logging from .metrics_missing_package import missing_package_exceptions from .metrics_missing_package import missing_package_success from .metrics_missing_package import missing_package_in_progress -from ..common import register_handler, Configuration, schedule_kebechet_administrator - -from ..metrics import scheduled_workflows +from .metrics_missing_package import missing_package_sent_advise_requests +from ..common import register_handler, Configuration, send_advise_request_for_installation +from ..github_service import GithubService from prometheus_async.aio import track_inprogress, count_exceptions from thoth.messaging import missing_package_message from thoth.storages import GraphDatabase from thoth.common import OpenShift +from thoth.common.enums import InternalTriggerEnum _LOGGER = logging.getLogger(__name__) @@ -38,7 +40,9 @@ @register_handler(missing_package_message.topic_name, ["v1"]) @count_exceptions(missing_package_exceptions) @track_inprogress(missing_package_in_progress) -async def parse_missing_package(package: Dict[str, Any], openshift: OpenShift, graph: GraphDatabase, **kwargs): +async def parse_missing_package( + package: Dict[str, Any], openshift: OpenShift, graph: GraphDatabase, gh_service: GithubService, **kwargs +): """Process a missing package message from package-update producer.""" python_package_versions = graph.get_python_package_versions_all( package_name=package["package_name"], @@ -55,22 +59,26 @@ async def parse_missing_package(package: Dict[str, Any], openshift: OpenShift, g ) if Configuration.THOTH_INVESTIGATOR_SCHEDULE_KEBECHET_ADMIN: - message_info = { - "PACKAGE_NAME": package["package_name"], - "PACKAGE_INDEX": package["index_url"], - } - - # We schedule Kebechet Administrator workflow here - - workflow_id = await schedule_kebechet_administrator( - openshift=openshift, - message_info=message_info, - message_name=missing_package_message.base_name, + installations = graph.get_kebechet_github_installations_info_for_python_package_version( + package_name=package["package_name"], + index_url=package["index_url"], ) - - _LOGGER.info(f"Scheduled kebechet administrator workflow {workflow_id}") - - scheduled_workflows.labels( - message_type=missing_package_message.base_name, workflow_type="kebechet-administrator" - ).inc() + keb_meta = { + "message_justification": InternalTriggerEnum.MISSING_PACKAGE.value, + "package_name": package["package_name"], + "package_index": package["index_url"], + } + tasks = [] + for key in installations: + tasks.append( + send_advise_request_for_installation( + slug=key, + environment_name=installations[key]["environment_name"], + keb_meta=keb_meta, + gh_service=gh_service, + ) + ) + num_requests_sent = sum(await asyncio.gather(*tasks)) + missing_package_sent_advise_requests.inc(num_requests_sent) missing_package_success.inc() diff --git a/thoth/investigator/missing_package/metrics_missing_package.py b/thoth/investigator/missing_package/metrics_missing_package.py index ba441fc2..17f31ff9 100644 --- a/thoth/investigator/missing_package/metrics_missing_package.py +++ b/thoth/investigator/missing_package/metrics_missing_package.py @@ -17,8 +17,9 @@ """Set labels for missing_package metrics.""" -from ..metrics import in_progress, success, exceptions +from ..metrics import in_progress, success, exceptions, sent_advise_requests missing_package_in_progress = in_progress.labels(message_type="missing_package") missing_package_success = success.labels(message_type="missing_package") missing_package_exceptions = exceptions.labels(message_type="missing_package") +missing_package_sent_advise_requests = sent_advise_requests.labels(message_type="missing_package") diff --git a/thoth/investigator/missing_version/investigate_missing_version.py b/thoth/investigator/missing_version/investigate_missing_version.py index 84508b04..1eb149ba 100644 --- a/thoth/investigator/missing_version/investigate_missing_version.py +++ b/thoth/investigator/missing_version/investigate_missing_version.py @@ -17,19 +17,24 @@ """Logic for handling hash_version message.""" +import asyncio import logging from typing import Dict, Any -from ..common import schedule_kebechet_administrator, register_handler -from ..metrics import scheduled_workflows +from ..common import send_advise_request_for_installation, register_handler +from ..github_service import GithubService -from .metrics_missing_version import missing_version_exceptions -from .metrics_missing_version import missing_version_in_progress -from .metrics_missing_version import missing_version_success +from .metrics_missing_version import ( + missing_version_exceptions, + missing_version_in_progress, + missing_version_success, + missing_version_sent_advise_requests, +) from prometheus_async.aio import track_inprogress, count_exceptions from thoth.messaging import missing_version_message from thoth.common import OpenShift +from thoth.common.enums import InternalTriggerEnum from thoth.storages import GraphDatabase from ..configuration import Configuration @@ -39,7 +44,9 @@ @register_handler(missing_version_message.topic_name, ["v1"]) @count_exceptions(missing_version_exceptions) @track_inprogress(missing_version_in_progress) -async def parse_missing_version(version: Dict[str, Any], openshift: OpenShift, graph: GraphDatabase, **kwargs): +async def parse_missing_version( + version: Dict[str, Any], openshift: OpenShift, graph: GraphDatabase, gh_service: GithubService, **kwargs +): """Process a missing version message from package-update producer.""" graph.update_missing_flag_package_version( index_url=version["index_url"], @@ -47,24 +54,29 @@ async def parse_missing_version(version: Dict[str, Any], openshift: OpenShift, g package_version=version["package_version"], value=True, ) - if Configuration.THOTH_INVESTIGATOR_SCHEDULE_KEBECHET_ADMIN: - message_info = { - "PACKAGE_NAME": version["package_name"], - "PACKAGE_VERSION": version["package_version"], - "PACKAGE_INDEX": version["index_url"], - } - - # We schedule Kebechet Administrator workflow here - - workflow_id = await schedule_kebechet_administrator( - openshift=openshift, - message_info=message_info, - message_name=missing_version_message.base_name, + installations = graph.get_kebechet_github_installations_info_for_python_package_version( + package_name=version["package_name"], + package_version=version["package_version"], + index_url=version["index_url"], ) + keb_meta = { + "message_justification": InternalTriggerEnum.MISSING_VERSION.value, + "package_name": version["package_name"], + "package_version": version["package_version"], + "package_index": version["index_url"], + } + tasks = [] + for key in installations: + tasks.append( + send_advise_request_for_installation( + slug=key, + environment_name=installations[key]["environment_name"], + keb_meta=keb_meta, + gh_service=gh_service, + ) + ) + num_requests_sent = sum(await asyncio.gather(*tasks)) + missing_version_sent_advise_requests.inc(num_requests_sent) - _LOGGER.info(f"Scheduled kebechet administrator workflow {workflow_id}") - - scheduled_workflows.labels( - message_type=missing_version_message.base_name, workflow_type="kebechet-administrator" - ).inc() missing_version_success.inc() diff --git a/thoth/investigator/missing_version/metrics_missing_version.py b/thoth/investigator/missing_version/metrics_missing_version.py index 708fe1c7..8041ead7 100644 --- a/thoth/investigator/missing_version/metrics_missing_version.py +++ b/thoth/investigator/missing_version/metrics_missing_version.py @@ -17,8 +17,9 @@ """Set labels for missing_version metrics.""" -from ..metrics import in_progress, success, exceptions +from ..metrics import in_progress, success, exceptions, sent_advise_requests missing_version_in_progress = in_progress.labels(message_type="missing_version") missing_version_success = success.labels(message_type="missing_version") missing_version_exceptions = exceptions.labels(message_type="missing_version") +missing_version_sent_advise_requests = sent_advise_requests.labels(message_type="missing_version") diff --git a/thoth/investigator/solved_package/investigate_solved_package.py b/thoth/investigator/solved_package/investigate_solved_package.py index f385609c..ed60af76 100644 --- a/thoth/investigator/solved_package/investigate_solved_package.py +++ b/thoth/investigator/solved_package/investigate_solved_package.py @@ -17,21 +17,26 @@ """This file contains methods used by Thoth investigator to investigate on solved packages.""" +import asyncio import logging +import semver from typing import Dict, Any from thoth.storages.graph import GraphDatabase from thoth.messaging import solved_package_message from thoth.common import OpenShift +from thoth.common.enums import InternalTriggerEnum from ..metrics import scheduled_workflows from .. import common from ..configuration import Configuration -from ..common import register_handler +from ..common import register_handler, send_advise_request_for_installation +from ..github_service import GithubService from .metrics_solved_package import solved_package_exceptions from .metrics_solved_package import solved_package_success from .metrics_solved_package import solved_package_in_progress +from .metrics_solved_package import solved_package_sent_advise_requests from prometheus_async.aio import count_exceptions, track_inprogress _LOGGER = logging.getLogger(__name__) @@ -41,7 +46,7 @@ @count_exceptions(solved_package_exceptions) @track_inprogress(solved_package_in_progress) async def parse_solved_package_message( - solved_package: Dict[str, Any], openshift: OpenShift, graph: GraphDatabase, **kwargs + solved_package: Dict[str, Any], openshift: OpenShift, graph: GraphDatabase, gh_service: GithubService, **kwargs ) -> None: """Parse solved package message.""" package_name = solved_package["package_name"] @@ -64,23 +69,37 @@ async def parse_solved_package_message( ).inc(si_wfs_scheduled) if Configuration.THOTH_INVESTIGATOR_SCHEDULE_KEBECHET_ADMIN: - # Schedule Kebechet Administrator - message_info = { - "PACKAGE_NAME": package_name, - "PACKAGE_VERSION": package_version, - "PACKAGE_INDEX": index_url, - "SOLVER_NAME": solved_package.get("solver"), # We pass the solver name also. - } - - # We schedule Kebechet Administrator workflow here - - workflow_id = await common.schedule_kebechet_administrator( - openshift=openshift, - message_info=message_info, - message_name=solved_package_message.base_name, + solver_dict = OpenShift.parse_python_solver_name(solved_package.get("solver")) + os_name, os_version, python_version = ( + solver_dict["os_name"], + solver_dict["os_version"], + solver_dict["python_version"], ) - _LOGGER.info(f"Schedule Kebechet Administrator with id = {workflow_id}") - scheduled_workflows.labels( - message_type=solved_package_message.base_name, workflow_type="kebechet-administrator" - ).inc() + installations = graph.get_kebechet_github_installations_info_for_python_package_version( + package_name=package_name, + index_url=index_url, + os_name=os_name, + os_version=os_version, + python_version=python_version, + ) + keb_meta = { + "message_justification": InternalTriggerEnum.NEW_RELEASE.value, + "package_name": package_name, + "package_version": package_version, + "package_index": index_url, + } + tasks = [] + for key in installations: + if semver.compare(package_version, installations[key]["package_version"]) < 0: # only request if newer + tasks.append( + send_advise_request_for_installation( + slug=key, + environment_name=installations[key]["environment_name"], + keb_meta=keb_meta, + gh_service=gh_service, + ) + ) + num_requests_sent = sum(await asyncio.gather(*tasks)) + solved_package_sent_advise_requests.inc(num_requests_sent) solved_package_success.inc() diff --git a/thoth/investigator/solved_package/metrics_solved_package.py b/thoth/investigator/solved_package/metrics_solved_package.py index c8e3d858..083843a1 100644 --- a/thoth/investigator/solved_package/metrics_solved_package.py +++ b/thoth/investigator/solved_package/metrics_solved_package.py @@ -17,8 +17,9 @@ """Set labels for solved_package metrics.""" -from ..metrics import in_progress, success, exceptions +from ..metrics import in_progress, success, exceptions, sent_advise_requests solved_package_in_progress = in_progress.labels(message_type="solved_package") solved_package_success = success.labels(message_type="solved_package") solved_package_exceptions = exceptions.labels(message_type="solved_package") +solved_package_sent_advise_requests = sent_advise_requests.labels(message_type="solved_package")