Remove old test dependencies, updated ones still being used. Introduce Black formatter

This commit is contained in:
Daniel 2022-09-17 04:28:01 +00:00
parent 2164220c69
commit 4da66313f4
No known key found for this signature in database
GPG Key ID: 4940B41048AF73EA
9 changed files with 442 additions and 840 deletions

View File

@ -1,4 +1,4 @@
FROM python:3.8-slim-bullseye FROM python:3.10-slim-bullseye
# Only works for docker CLIENT (bind mounted socket) # Only works for docker CLIENT (bind mounted socket)
COPY --from=docker:20.10.17 /usr/local/bin/docker /usr/local/bin/ COPY --from=docker:20.10.17 /usr/local/bin/docker /usr/local/bin/
@ -10,7 +10,7 @@ RUN apt-get update && \
&& rm -rf /var/lib/apt/lists/* \ && rm -rf /var/lib/apt/lists/* \
&& pip3 install --no-cache-dir -U pip pipenv && pip3 install --no-cache-dir -U pip pipenv
RUN curl -L https://github.com/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose && \ RUN curl -L https://github.com/docker/compose/releases/download/2.10.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose && \
chmod +x /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
COPY ./cmd.sh /usr/local/bin/ COPY ./cmd.sh /usr/local/bin/
@ -18,7 +18,7 @@ COPY Pipfile* /root/
WORKDIR /root WORKDIR /root
RUN pipenv install --system \ RUN pipenv install --system \
&& sed -i 's|/bin/sh|/bin/bash|g' /usr/local/lib/python3.8/site-packages/testinfra/backend/docker.py && sed -i 's|/bin/sh|/bin/bash|g' /usr/local/lib/python3.10/site-packages/testinfra/backend/docker.py
RUN echo "set -ex && cmd.sh && \$@" > /usr/local/bin/entrypoint.sh RUN echo "set -ex && cmd.sh && \$@" > /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh

View File

@ -6,59 +6,10 @@ verify_ssl = true
[dev-packages] [dev-packages]
[packages] [packages]
apipkg = "==1.5" pytest = "==7.1.3"
atomicwrites = "==1.4.1" pytest-xdist = "==2.5.0"
attrs = "==19.3.0" pytest-testinfra = "==6.8.0"
bcrypt = "==3.1.7" black = "==22.8.0"
cached-property = "==1.5.1"
certifi = "==2019.11.28"
cffi = "==1.13.2"
chardet = "==3.0.4"
configparser = "==4.0.2"
contextlib2 = "==0.6.0.post1"
coverage = "==5.0.1"
cryptography = "==3.3.2"
docker = "==4.1.0"
dockerpty = "==0.4.1"
docopt = "==0.6.2"
enum34 = "==1.1.6"
execnet = "==1.7.1"
filelock = "==3.0.12"
funcsigs = "==1.0.2"
idna = "==2.8"
importlib-metadata = "==1.3.0"
ipaddress = "==1.0.23"
jsonschema = "==3.2.0"
more-itertools = "==5.0.0"
pathlib2 = "==2.3.5"
pluggy = "==0.13.1"
py = "==1.10.0"
pycparser = "==2.19"
pyparsing = "==2.4.6"
pyrsistent = "==0.15.6"
pytest = "==4.6.8"
pytest-cov = "==2.8.1"
pytest-forked = "==1.1.3"
pytest-xdist = "==1.31.0"
requests = "==2.28.1"
scandir = "==1.10.0"
six = "==1.13.0"
subprocess32 = "==3.5.4"
testinfra = "==3.3.0"
texttable = "==1.6.2"
toml = "==0.10.0"
tox = "==3.14.3"
urllib3 = "==1.26.5"
virtualenv = "==16.7.9"
wcwidth = "==0.1.7"
zipp = "==0.6.0"
"backports.shutil_get_terminal_size" = "==1.0.0"
"backports.ssl_match_hostname" = "==3.7.0.1"
Jinja2 = "==2.11.3"
MarkupSafe = "==1.1.1"
PyYAML = "==5.4"
websocket_client = "==0.57.0"
python-dotenv = "==0.17.1"
[requires] [requires]
python_version = "3.8" python_version = "3"

655
test/Pipfile.lock generated
View File

@ -1,11 +1,11 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "c679c3eaa7a38959fa47159a01b66d7f7dd1e1667c188c9437a52302ee5a9290" "sha256": "7cd0c8140d8505e7613e9bf2a9853aaf7cb08a1f100f49db0bec1b94b93be3e1"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
"python_version": "3.8" "python_version": "3"
}, },
"sources": [ "sources": [
{ {
@ -16,619 +16,160 @@
] ]
}, },
"default": { "default": {
"apipkg": {
"hashes": [
"sha256:37228cda29411948b422fae072f57e31d3396d2ee1c9783775980ee9c9990af6",
"sha256:58587dd4dc3daefad0487f6d9ae32b4542b185e1c36db6993290e7c41ca2b47c"
],
"index": "pypi",
"version": "==1.5"
},
"atomicwrites": {
"hashes": [
"sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"
],
"index": "pypi",
"version": "==1.4.1"
},
"attrs": { "attrs": {
"hashes": [ "hashes": [
"sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6",
"sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72" "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"
],
"markers": "python_version >= '3.5'",
"version": "==22.1.0"
},
"black": {
"hashes": [
"sha256:0a12e4e1353819af41df998b02c6742643cfef58282915f781d0e4dd7a200411",
"sha256:0ad827325a3a634bae88ae7747db1a395d5ee02cf05d9aa7a9bd77dfb10e940c",
"sha256:32a4b17f644fc288c6ee2bafdf5e3b045f4eff84693ac069d87b1a347d861497",
"sha256:3b2c25f8dea5e8444bdc6788a2f543e1fb01494e144480bc17f806178378005e",
"sha256:4a098a69a02596e1f2a58a2a1c8d5a05d5a74461af552b371e82f9fa4ada8342",
"sha256:5107ea36b2b61917956d018bd25129baf9ad1125e39324a9b18248d362156a27",
"sha256:53198e28a1fb865e9fe97f88220da2e44df6da82b18833b588b1883b16bb5d41",
"sha256:5594efbdc35426e35a7defa1ea1a1cb97c7dbd34c0e49af7fb593a36bd45edab",
"sha256:5b879eb439094751185d1cfdca43023bc6786bd3c60372462b6f051efa6281a5",
"sha256:78dd85caaab7c3153054756b9fe8c611efa63d9e7aecfa33e533060cb14b6d16",
"sha256:792f7eb540ba9a17e8656538701d3eb1afcb134e3b45b71f20b25c77a8db7e6e",
"sha256:8ce13ffed7e66dda0da3e0b2eb1bdfc83f5812f66e09aca2b0978593ed636b6c",
"sha256:a05da0430bd5ced89176db098567973be52ce175a55677436a271102d7eaa3fe",
"sha256:a983526af1bea1e4cf6768e649990f28ee4f4137266921c2c3cee8116ae42ec3",
"sha256:bc4d4123830a2d190e9cc42a2e43570f82ace35c3aeb26a512a2102bce5af7ec",
"sha256:c3a73f66b6d5ba7288cd5d6dad9b4c9b43f4e8a4b789a94bf5abfb878c663eb3",
"sha256:ce957f1d6b78a8a231b18e0dd2d94a33d2ba738cd88a7fe64f53f659eea49fdd",
"sha256:cea1b2542d4e2c02c332e83150e41e3ca80dc0fb8de20df3c5e98e242156222c",
"sha256:d2c21d439b2baf7aa80d6dd4e3659259be64c6f49dfd0f32091063db0e006db4",
"sha256:d839150f61d09e7217f52917259831fe2b689f5c8e5e32611736351b89bb2a90",
"sha256:dd82842bb272297503cbec1a2600b6bfb338dae017186f8f215c8958f8acf869",
"sha256:e8166b7bfe5dcb56d325385bd1d1e0f635f24aae14b3ae437102dedc0c186747",
"sha256:e981e20ec152dfb3e77418fb616077937378b322d7b26aa1ff87717fb18b4875"
], ],
"index": "pypi", "index": "pypi",
"version": "==19.3.0" "version": "==22.8.0"
}, },
"backports.shutil-get-terminal-size": { "click": {
"hashes": [ "hashes": [
"sha256:0975ba55054c15e346944b38956a4c9cbee9009391e41b86c68990effb8c1f64", "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e",
"sha256:713e7a8228ae80341c70586d1cc0a8caa5207346927e23d09dcbcaf18eadec80" "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"
], ],
"index": "pypi", "markers": "python_version >= '3.7'",
"version": "==1.0.0" "version": "==8.1.3"
},
"backports.ssl-match-hostname": {
"hashes": [
"sha256:bb82e60f9fbf4c080eabd957c39f0641f0fc247d9a16e31e26d594d8f42b9fd2"
],
"index": "pypi",
"version": "==3.7.0.1"
},
"bcrypt": {
"hashes": [
"sha256:0258f143f3de96b7c14f762c770f5fc56ccd72f8a1857a451c1cd9a655d9ac89",
"sha256:0b0069c752ec14172c5f78208f1863d7ad6755a6fae6fe76ec2c80d13be41e42",
"sha256:19a4b72a6ae5bb467fea018b825f0a7d917789bcfe893e53f15c92805d187294",
"sha256:436a487dec749bca7e6e72498a75a5fa2433bda13bac91d023e18df9089ae0b8",
"sha256:5432dd7b34107ae8ed6c10a71b4397f1c853bd39a4d6ffa7e35f40584cffd161",
"sha256:6305557019906466fc42dbc53b46da004e72fd7a551c044a827e572c82191752",
"sha256:69361315039878c0680be456640f8705d76cb4a3a3fe1e057e0f261b74be4b31",
"sha256:6fe49a60b25b584e2f4ef175b29d3a83ba63b3a4df1b4c0605b826668d1b6be5",
"sha256:74a015102e877d0ccd02cdeaa18b32aa7273746914a6c5d0456dd442cb65b99c",
"sha256:763669a367869786bb4c8fcf731f4175775a5b43f070f50f46f0b59da45375d0",
"sha256:8b10acde4e1919d6015e1df86d4c217d3b5b01bb7744c36113ea43d529e1c3de",
"sha256:9fe92406c857409b70a38729dbdf6578caf9228de0aef5bc44f859ffe971a39e",
"sha256:a190f2a5dbbdbff4b74e3103cef44344bc30e61255beb27310e2aec407766052",
"sha256:a595c12c618119255c90deb4b046e1ca3bcfad64667c43d1166f2b04bc72db09",
"sha256:c9457fa5c121e94a58d6505cadca8bed1c64444b83b3204928a866ca2e599105",
"sha256:cb93f6b2ab0f6853550b74e051d297c27a638719753eb9ff66d1e4072be67133",
"sha256:ce4e4f0deb51d38b1611a27f330426154f2980e66582dc5f438aad38b5f24fc1",
"sha256:d7bdc26475679dd073ba0ed2766445bb5b20ca4793ca0db32b399dccc6bc84b7",
"sha256:ff032765bb8716d9387fd5376d987a937254b0619eff0972779515b5c98820bc"
],
"index": "pypi",
"version": "==3.1.7"
},
"cached-property": {
"hashes": [
"sha256:3a026f1a54135677e7da5ce819b0c690f156f37976f3e30c5430740725203d7f",
"sha256:9217a59f14a5682da7c4b8829deadbfc194ac22e9908ccf7c8820234e80a1504"
],
"index": "pypi",
"version": "==1.5.1"
},
"certifi": {
"hashes": [
"sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3",
"sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"
],
"index": "pypi",
"version": "==2019.11.28"
},
"cffi": {
"hashes": [
"sha256:0b49274afc941c626b605fb59b59c3485c17dc776dc3cc7cc14aca74cc19cc42",
"sha256:0e3ea92942cb1168e38c05c1d56b0527ce31f1a370f6117f1d490b8dcd6b3a04",
"sha256:135f69aecbf4517d5b3d6429207b2dff49c876be724ac0c8bf8e1ea99df3d7e5",
"sha256:19db0cdd6e516f13329cba4903368bff9bb5a9331d3410b1b448daaadc495e54",
"sha256:2781e9ad0e9d47173c0093321bb5435a9dfae0ed6a762aabafa13108f5f7b2ba",
"sha256:291f7c42e21d72144bb1c1b2e825ec60f46d0a7468f5346841860454c7aa8f57",
"sha256:2c5e309ec482556397cb21ede0350c5e82f0eb2621de04b2633588d118da4396",
"sha256:2e9c80a8c3344a92cb04661115898a9129c074f7ab82011ef4b612f645939f12",
"sha256:32a262e2b90ffcfdd97c7a5e24a6012a43c61f1f5a57789ad80af1d26c6acd97",
"sha256:3c9fff570f13480b201e9ab69453108f6d98244a7f495e91b6c654a47486ba43",
"sha256:415bdc7ca8c1c634a6d7163d43fb0ea885a07e9618a64bda407e04b04333b7db",
"sha256:42194f54c11abc8583417a7cf4eaff544ce0de8187abaf5d29029c91b1725ad3",
"sha256:4424e42199e86b21fc4db83bd76909a6fc2a2aefb352cb5414833c030f6ed71b",
"sha256:4a43c91840bda5f55249413037b7a9b79c90b1184ed504883b72c4df70778579",
"sha256:599a1e8ff057ac530c9ad1778293c665cb81a791421f46922d80a86473c13346",
"sha256:5c4fae4e9cdd18c82ba3a134be256e98dc0596af1e7285a3d2602c97dcfa5159",
"sha256:5ecfa867dea6fabe2a58f03ac9186ea64da1386af2159196da51c4904e11d652",
"sha256:62f2578358d3a92e4ab2d830cd1c2049c9c0d0e6d3c58322993cc341bdeac22e",
"sha256:6471a82d5abea994e38d2c2abc77164b4f7fbaaf80261cb98394d5793f11b12a",
"sha256:6d4f18483d040e18546108eb13b1dfa1000a089bcf8529e30346116ea6240506",
"sha256:71a608532ab3bd26223c8d841dde43f3516aa5d2bf37b50ac410bb5e99053e8f",
"sha256:74a1d8c85fb6ff0b30fbfa8ad0ac23cd601a138f7509dc617ebc65ef305bb98d",
"sha256:7b93a885bb13073afb0aa73ad82059a4c41f4b7d8eb8368980448b52d4c7dc2c",
"sha256:7d4751da932caaec419d514eaa4215eaf14b612cff66398dd51129ac22680b20",
"sha256:7f627141a26b551bdebbc4855c1157feeef18241b4b8366ed22a5c7d672ef858",
"sha256:8169cf44dd8f9071b2b9248c35fc35e8677451c52f795daa2bb4643f32a540bc",
"sha256:aa00d66c0fab27373ae44ae26a66a9e43ff2a678bf63a9c7c1a9a4d61172827a",
"sha256:ccb032fda0873254380aa2bfad2582aedc2959186cce61e3a17abc1a55ff89c3",
"sha256:d754f39e0d1603b5b24a7f8484b22d2904fa551fe865fd0d4c3332f078d20d4e",
"sha256:d75c461e20e29afc0aee7172a0950157c704ff0dd51613506bd7d82b718e7410",
"sha256:dcd65317dd15bc0451f3e01c80da2216a31916bdcffd6221ca1202d96584aa25",
"sha256:e570d3ab32e2c2861c4ebe6ffcad6a8abf9347432a37608fe1fbd157b3f0036b",
"sha256:fd43a88e045cf992ed09fa724b5315b790525f2676883a6ea64e3263bae6549d"
],
"index": "pypi",
"version": "==1.13.2"
},
"chardet": {
"hashes": [
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
],
"index": "pypi",
"version": "==3.0.4"
},
"charset-normalizer": {
"hashes": [
"sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5",
"sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413"
],
"markers": "python_full_version >= '3.6.0'",
"version": "==2.1.0"
},
"configparser": {
"hashes": [
"sha256:254c1d9c79f60c45dfde850850883d5aaa7f19a23f13561243a050d5a7c3fe4c",
"sha256:c7d282687a5308319bf3d2e7706e575c635b0a470342641c93bea0ea3b5331df"
],
"index": "pypi",
"version": "==4.0.2"
},
"contextlib2": {
"hashes": [
"sha256:01f490098c18b19d2bd5bb5dc445b2054d2fa97f09a4280ba2c5f3c394c8162e",
"sha256:3355078a159fbb44ee60ea80abd0d87b80b78c248643b49aa6d94673b413609b"
],
"index": "pypi",
"version": "==0.6.0.post1"
},
"coverage": {
"hashes": [
"sha256:0101888bd1592a20ccadae081ba10e8b204d20235d18d05c6f7d5e904a38fc10",
"sha256:04b961862334687549eb91cd5178a6fbe977ad365bddc7c60f2227f2f9880cf4",
"sha256:1ca43dbd739c0fc30b0a3637a003a0d2c7edc1dd618359d58cc1e211742f8bd1",
"sha256:1cbb88b34187bdb841f2599770b7e6ff8e259dc3bb64fc7893acf44998acf5f8",
"sha256:232f0b52a5b978288f0bbc282a6c03fe48cd19a04202df44309919c142b3bb9c",
"sha256:24bcfa86fd9ce86b73a8368383c39d919c497a06eebb888b6f0c12f13e920b1a",
"sha256:25b8f60b5c7da71e64c18888f3067d5b6f1334b9681876b2fb41eea26de881ae",
"sha256:2714160a63da18aed9340c70ed514973971ee7e665e6b336917ff4cca81a25b1",
"sha256:2ca2cd5264e84b2cafc73f0045437f70c6378c0d7dbcddc9ee3fe192c1e29e5d",
"sha256:2cc707fc9aad2592fc686d63ef72dc0031fc98b6fb921d2f5395d9ab84fbc3ef",
"sha256:348630edea485f4228233c2f310a598abf8afa5f8c716c02a9698089687b6085",
"sha256:40fbfd6b044c9db13aeec1daf5887d322c710d811f944011757526ef6e323fd9",
"sha256:46c9c6a1d1190c0b75ec7c0f339088309952b82ae8d67a79ff1319eb4e749b96",
"sha256:591506e088901bdc25620c37aec885e82cc896528f28c57e113751e3471fc314",
"sha256:5ac71bba1e07eab403b082c4428f868c1c9e26a21041436b4905c4c3d4e49b08",
"sha256:5f622f19abda4e934938e24f1d67599249abc201844933a6f01aaa8663094489",
"sha256:65bead1ac8c8930cf92a1ccaedcce19a57298547d5d1db5c9d4d068a0675c38b",
"sha256:7362a7f829feda10c7265b553455de596b83d1623b3d436b6d3c51c688c57bf6",
"sha256:7f2675750c50151f806070ec11258edf4c328340916c53bac0adbc465abd6b1e",
"sha256:960d7f42277391e8b1c0b0ae427a214e1b31a1278de6b73f8807b20c2e913bba",
"sha256:a50b0888d8a021a3342d36a6086501e30de7d840ab68fca44913e97d14487dc1",
"sha256:b7dbc5e8c39ea3ad3db22715f1b5401cd698a621218680c6daf42c2f9d36e205",
"sha256:bb3d29df5d07d5399d58a394d0ef50adf303ab4fbf66dfd25b9ef258effcb692",
"sha256:c0fff2733f7c2950f58a4fd09b5db257b00c6fec57bf3f68c5bae004d804b407",
"sha256:c792d3707a86c01c02607ae74364854220fb3e82735f631cd0a345dea6b4cee5",
"sha256:c90bda74e16bcd03861b09b1d37c0a4158feda5d5a036bb2d6e58de6ff65793e",
"sha256:cfce79ce41cc1a1dc7fc85bb41eeeb32d34a4cf39a645c717c0550287e30ff06",
"sha256:eeafb646f374988c22c8e6da5ab9fb81367ecfe81c70c292623373d2a021b1a1",
"sha256:f425f50a6dd807cb9043d15a4fcfba3b5874a54d9587ccbb748899f70dc18c47",
"sha256:fcd4459fe35a400b8f416bc57906862693c9f88b66dc925e7f2a933e77f6b18b",
"sha256:ff3936dd5feaefb4f91c8c1f50a06c588b5dc69fba4f7d9c79a6617ad80bb7df"
],
"index": "pypi",
"version": "==5.0.1"
},
"cryptography": {
"hashes": [
"sha256:0d7b69674b738068fa6ffade5c962ecd14969690585aaca0a1b1fc9058938a72",
"sha256:1bd0ccb0a1ed775cd7e2144fe46df9dc03eefd722bbcf587b3e0616ea4a81eff",
"sha256:3c284fc1e504e88e51c428db9c9274f2da9f73fdf5d7e13a36b8ecb039af6e6c",
"sha256:49570438e60f19243e7e0d504527dd5fe9b4b967b5a1ff21cc12b57602dd85d3",
"sha256:541dd758ad49b45920dda3b5b48c968f8b2533d8981bcdb43002798d8f7a89ed",
"sha256:5a60d3780149e13b7a6ff7ad6526b38846354d11a15e21068e57073e29e19bed",
"sha256:7951a966613c4211b6612b0352f5bf29989955ee592c4a885d8c7d0f830d0433",
"sha256:922f9602d67c15ade470c11d616f2b2364950602e370c76f0c94c94ae672742e",
"sha256:a0f0b96c572fc9f25c3f4ddbf4688b9b38c69836713fb255f4a2715d93cbaf44",
"sha256:a777c096a49d80f9d2979695b835b0f9c9edab73b59e4ceb51f19724dda887ed",
"sha256:a9a4ac9648d39ce71c2f63fe7dc6db144b9fa567ddfc48b9fde1b54483d26042",
"sha256:aa4969f24d536ae2268c902b2c3d62ab464b5a66bcb247630d208a79a8098e9b",
"sha256:c7390f9b2119b2b43160abb34f63277a638504ef8df99f11cb52c1fda66a2e6f",
"sha256:e18e6ab84dfb0ab997faf8cca25a86ff15dfea4027b986322026cc99e0a892da"
],
"index": "pypi",
"version": "==3.3.2"
},
"docker": {
"hashes": [
"sha256:6e06c5e70ba4fad73e35f00c55a895a448398f3ada7faae072e2bb01348bafc1",
"sha256:8f93775b8bdae3a2df6bc9a5312cce564cade58d6555f2c2570165a1270cd8a7"
],
"index": "pypi",
"version": "==4.1.0"
},
"dockerpty": {
"hashes": [
"sha256:69a9d69d573a0daa31bcd1c0774eeed5c15c295fe719c61aca550ed1393156ce"
],
"index": "pypi",
"version": "==0.4.1"
},
"docopt": {
"hashes": [
"sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"
],
"index": "pypi",
"version": "==0.6.2"
},
"enum34": {
"hashes": [
"sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850",
"sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a",
"sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79",
"sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1"
],
"index": "pypi",
"version": "==1.1.6"
}, },
"execnet": { "execnet": {
"hashes": [ "hashes": [
"sha256:cacb9df31c9680ec5f95553976c4da484d407e85e41c83cb812aa014f0eddc50", "sha256:8f694f3ba9cc92cab508b152dcfe322153975c29bda272e2fd7f3f00f36e47c5",
"sha256:d4efd397930c46415f62f8a31388d6be4f27a91d7550eb79bc64a756e0056547" "sha256:a295f7cc774947aac58dde7fdc85f4aa00c42adf5d8f5468fc630c1acf30a142"
], ],
"index": "pypi", "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==1.7.1" "version": "==1.9.0"
}, },
"filelock": { "iniconfig": {
"hashes": [ "hashes": [
"sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59", "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3",
"sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836" "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"
], ],
"index": "pypi",
"version": "==3.0.12"
},
"funcsigs": {
"hashes": [
"sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca",
"sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"
],
"index": "pypi",
"version": "==1.0.2"
},
"idna": {
"hashes": [
"sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
"sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
],
"index": "pypi",
"version": "==2.8"
},
"importlib-metadata": {
"hashes": [
"sha256:073a852570f92da5f744a3472af1b61e28e9f78ccf0c9117658dc32b15de7b45",
"sha256:d95141fbfa7ef2ec65cfd945e2af7e5a6ddbd7c8d9a25e66ff3be8e3daf9f60f"
],
"index": "pypi",
"version": "==1.3.0"
},
"ipaddress": {
"hashes": [
"sha256:6e0f4a39e66cb5bb9a137b00276a2eff74f93b71dcbdad6f10ff7df9d3557fcc",
"sha256:b7f8e0369580bb4a24d5ba1d7cc29660a4a6987763faf1d8a8046830e020e7e2"
],
"index": "pypi",
"version": "==1.0.23"
},
"jinja2": {
"hashes": [
"sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419",
"sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6"
],
"index": "pypi",
"version": "==2.11.3"
},
"jsonschema": {
"hashes": [
"sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163",
"sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"
],
"index": "pypi",
"version": "==3.2.0"
},
"markupsafe": {
"hashes": [
"sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
"sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
"sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
"sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
"sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42",
"sha256:195d7d2c4fbb0ee8139a6cf67194f3973a6b3042d742ebe0a9ed36d8b6f0c07f",
"sha256:22c178a091fc6630d0d045bdb5992d2dfe14e3259760e713c490da5323866c39",
"sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
"sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
"sha256:2beec1e0de6924ea551859edb9e7679da6e4870d32cb766240ce17e0a0ba2014",
"sha256:3b8a6499709d29c2e2399569d96719a1b21dcd94410a586a18526b143ec8470f",
"sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
"sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
"sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
"sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
"sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b",
"sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
"sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15",
"sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
"sha256:6f1e273a344928347c1290119b493a1f0303c52f5a5eae5f16d74f48c15d4a85",
"sha256:6fffc775d90dcc9aed1b89219549b329a9250d918fd0b8fa8d93d154918422e1",
"sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
"sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
"sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
"sha256:7fed13866cf14bba33e7176717346713881f56d9d2bcebab207f7a036f41b850",
"sha256:84dee80c15f1b560d55bcfe6d47b27d070b4681c699c572af2e3c7cc90a3b8e0",
"sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
"sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
"sha256:98bae9582248d6cf62321dcb52aaf5d9adf0bad3b40582925ef7c7f0ed85fceb",
"sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
"sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
"sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
"sha256:a6a744282b7718a2a62d2ed9d993cad6f5f585605ad352c11de459f4108df0a1",
"sha256:acf08ac40292838b3cbbb06cfe9b2cb9ec78fce8baca31ddb87aaac2e2dc3bc2",
"sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
"sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
"sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
"sha256:b1dba4527182c95a0db8b6060cc98ac49b9e2f5e64320e2b56e47cb2831978c7",
"sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
"sha256:b7d644ddb4dbd407d31ffb699f1d140bc35478da613b441c582aeb7c43838dd8",
"sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
"sha256:bf5aa3cbcfdf57fa2ee9cd1822c862ef23037f5c832ad09cfea57fa846dec193",
"sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
"sha256:caabedc8323f1e93231b52fc32bdcde6db817623d33e100708d9a68e1f53b26b",
"sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
"sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2",
"sha256:d53bc011414228441014aa71dbec320c66468c1030aae3a6e29778a3382d96e5",
"sha256:d73a845f227b0bfe8a7455ee623525ee656a9e2e749e4742706d80a6065d5e2c",
"sha256:d9be0ba6c527163cbed5e0857c451fcd092ce83947944d6c14bc95441203f032",
"sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7",
"sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be",
"sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621"
],
"index": "pypi",
"version": "==1.1.1" "version": "==1.1.1"
}, },
"more-itertools": { "mypy-extensions": {
"hashes": [ "hashes": [
"sha256:38a936c0a6d98a38bcc2d03fdaaedaba9f412879461dd2ceff8d37564d6522e4", "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d",
"sha256:c0a5785b1109a6bd7fac76d6837fd1feca158e54e521ccd2ae8bfe393cc9d4fc", "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"
"sha256:fe7a7cae1ccb57d33952113ff4fa1bc5f879963600ed74918f1236e212ee50b9"
], ],
"index": "pypi", "version": "==0.4.3"
"version": "==5.0.0"
}, },
"packaging": { "packaging": {
"hashes": [ "hashes": [
"sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb",
"sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522" "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"
], ],
"markers": "python_full_version >= '3.6.0'", "markers": "python_version >= '3.6'",
"version": "==21.3" "version": "==21.3"
}, },
"pathlib2": { "pathspec": {
"hashes": [ "hashes": [
"sha256:0ec8205a157c80d7acc301c0b18fbd5d44fe655968f5d947b6ecef5290fc35db", "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93",
"sha256:6cd9a47b597b37cc57de1c05e56fb1a1c9cc9fab04fe78c29acd090418529868" "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"
], ],
"index": "pypi", "markers": "python_version >= '3.7'",
"version": "==2.3.5" "version": "==0.10.1"
},
"platformdirs": {
"hashes": [
"sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788",
"sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"
],
"markers": "python_version >= '3.7'",
"version": "==2.5.2"
}, },
"pluggy": { "pluggy": {
"hashes": [ "hashes": [
"sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159",
"sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"
], ],
"index": "pypi", "markers": "python_version >= '3.6'",
"version": "==0.13.1" "version": "==1.0.0"
}, },
"py": { "py": {
"hashes": [ "hashes": [
"sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3", "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719",
"sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a" "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"
], ],
"index": "pypi", "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==1.10.0" "version": "==1.11.0"
},
"pycparser": {
"hashes": [
"sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3"
],
"index": "pypi",
"version": "==2.19"
}, },
"pyparsing": { "pyparsing": {
"hashes": [ "hashes": [
"sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f", "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb",
"sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec" "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"
], ],
"index": "pypi", "markers": "python_full_version >= '3.6.8'",
"version": "==2.4.6" "version": "==3.0.9"
},
"pyrsistent": {
"hashes": [
"sha256:f3b280d030afb652f79d67c5586157c5c1355c9a58dfc7940566e28d28f3df1b"
],
"index": "pypi",
"version": "==0.15.6"
}, },
"pytest": { "pytest": {
"hashes": [ "hashes": [
"sha256:6192875be8af57b694b7c4904e909680102befcb99e610ef3d9f786952f795aa", "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7",
"sha256:f8447ebf8fd3d362868a5d3f43a9df786dfdfe9608843bd9002a2d47a104808f" "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"
], ],
"index": "pypi", "index": "pypi",
"version": "==4.6.8" "version": "==7.1.3"
},
"pytest-cov": {
"hashes": [
"sha256:cc6742d8bac45070217169f5f72ceee1e0e55b0221f54bcf24845972d3a47f2b",
"sha256:cdbdef4f870408ebdbfeb44e63e07eb18bb4619fae852f6e760645fa36172626"
],
"index": "pypi",
"version": "==2.8.1"
}, },
"pytest-forked": { "pytest-forked": {
"hashes": [ "hashes": [
"sha256:1805699ed9c9e60cb7a8179b8d4fa2b8898098e82d229b0825d8095f0f261100", "sha256:8b67587c8f98cbbadfdd804539ed5455b6ed03802203485dd2f53c1422d7440e",
"sha256:1ae25dba8ee2e56fb47311c9638f9e58552691da87e82d25b0ce0e4bf52b7d87" "sha256:bbbb6717efc886b9d64537b41fb1497cfaf3c9601276be8da2cccfea5a3c8ad8"
],
"markers": "python_version >= '3.6'",
"version": "==1.4.0"
},
"pytest-testinfra": {
"hashes": [
"sha256:07c8c2c472aca7d83099ebc5f850d383721cd654b66c60ffbb145e45e584ff99",
"sha256:56ac1dfc61342632a1189091473e253db1a3cdcecce0d49d6a769f33cd264814"
], ],
"index": "pypi", "index": "pypi",
"version": "==1.1.3" "version": "==6.8.0"
}, },
"pytest-xdist": { "pytest-xdist": {
"hashes": [ "hashes": [
"sha256:0f46020d3d9619e6d17a65b5b989c1ebbb58fc7b1da8fb126d70f4bac4dfeed1", "sha256:4580deca3ff04ddb2ac53eba39d76cb5dd5edeac050cb6fbc768b0dd712b4edf",
"sha256:7dc0d027d258cd0defc618fb97055fbd1002735ca7a6d17037018cf870e24011" "sha256:6fe5c74fec98906deb8f2d2b616b5c782022744978e7bd4695d39c8f42d0ce65"
], ],
"index": "pypi", "index": "pypi",
"version": "==1.31.0" "version": "==2.5.0"
}, },
"python-dotenv": { "tomli": {
"hashes": [ "hashes": [
"sha256:00aa34e92d992e9f8383730816359647f358f4a3be1ba45e5a5cefd27ee91544", "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
"sha256:b1ae5e9643d5ed987fc57cc2583021e38db531946518130777734f9589b3141f" "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"
], ],
"index": "pypi", "markers": "python_full_version < '3.11.0a7'",
"version": "==0.17.1" "version": "==2.0.1"
},
"pyyaml": {
"hashes": [
"sha256:02c78d77281d8f8d07a255e57abdbf43b02257f59f50cc6b636937d68efa5dd0",
"sha256:0dc9f2eb2e3c97640928dec63fd8dc1dd91e6b6ed236bd5ac00332b99b5c2ff9",
"sha256:124fd7c7bc1e95b1eafc60825f2daf67c73ce7b33f1194731240d24b0d1bf628",
"sha256:26fcb33776857f4072601502d93e1a619f166c9c00befb52826e7b774efaa9db",
"sha256:31ba07c54ef4a897758563e3a0fcc60077698df10180abe4b8165d9895c00ebf",
"sha256:3c49e39ac034fd64fd576d63bb4db53cda89b362768a67f07749d55f128ac18a",
"sha256:52bf0930903818e600ae6c2901f748bc4869c0c406056f679ab9614e5d21a166",
"sha256:5a3f345acff76cad4aa9cb171ee76c590f37394186325d53d1aa25318b0d4a09",
"sha256:5e7ac4e0e79a53451dc2814f6876c2fa6f71452de1498bbe29c0b54b69a986f4",
"sha256:7242790ab6c20316b8e7bb545be48d7ed36e26bbe279fd56f2c4a12510e60b4b",
"sha256:737bd70e454a284d456aa1fa71a0b429dd527bcbf52c5c33f7c8eee81ac16b89",
"sha256:8635d53223b1f561b081ff4adecb828fd484b8efffe542edcfdff471997f7c39",
"sha256:8b818b6c5a920cbe4203b5a6b14256f0e5244338244560da89b7b0f1313ea4b6",
"sha256:8bf38641b4713d77da19e91f8b5296b832e4db87338d6aeffe422d42f1ca896d",
"sha256:a36a48a51e5471513a5aea920cdad84cbd56d70a5057cca3499a637496ea379c",
"sha256:b2243dd033fd02c01212ad5c601dafb44fbb293065f430b0d3dbf03f3254d615",
"sha256:cc547d3ead3754712223abb7b403f0a184e4c3eae18c9bb7fd15adef1597cc4b",
"sha256:cc552b6434b90d9dbed6a4f13339625dc466fd82597119897e9489c953acbc22",
"sha256:f3790156c606299ff499ec44db422f66f05a7363b39eb9d5b064f17bd7d7c47b",
"sha256:f7a21e3d99aa3095ef0553e7ceba36fb693998fbb1226f1392ce33681047465f",
"sha256:fdc6b2cb4b19e431994f25a9160695cc59a4e861710cc6fc97161c5e845fc579"
],
"index": "pypi",
"version": "==5.4"
},
"requests": {
"hashes": [
"sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983",
"sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"
],
"index": "pypi",
"version": "==2.28.1"
},
"scandir": {
"hashes": [
"sha256:2586c94e907d99617887daed6c1d102b5ca28f1085f90446554abf1faf73123e",
"sha256:2ae41f43797ca0c11591c0c35f2f5875fa99f8797cb1a1fd440497ec0ae4b022",
"sha256:2b8e3888b11abb2217a32af0766bc06b65cc4a928d8727828ee68af5a967fa6f",
"sha256:2c712840c2e2ee8dfaf36034080108d30060d759c7b73a01a52251cc8989f11f",
"sha256:4d4631f6062e658e9007ab3149a9b914f3548cb38bfb021c64f39a025ce578ae",
"sha256:67f15b6f83e6507fdc6fca22fedf6ef8b334b399ca27c6b568cbfaa82a364173",
"sha256:7d2d7a06a252764061a020407b997dd036f7bd6a175a5ba2b345f0a357f0b3f4",
"sha256:8c5922863e44ffc00c5c693190648daa6d15e7c1207ed02d6f46a8dcc2869d32",
"sha256:92c85ac42f41ffdc35b6da57ed991575bdbe69db895507af88b9f499b701c188",
"sha256:b24086f2375c4a094a6b51e78b4cf7ca16c721dcee2eddd7aa6494b42d6d519d",
"sha256:cb925555f43060a1745d0a321cca94bcea927c50114b623d73179189a4e100ac"
],
"index": "pypi",
"version": "==1.10.0"
},
"setuptools": {
"hashes": [
"sha256:16923d366ced322712c71ccb97164d07472abeecd13f3a6c283f6d5d26722793",
"sha256:db3b8e2f922b2a910a29804776c643ea609badb6a32c4bcc226fd4fd902cce65"
],
"markers": "python_version >= '3.7'",
"version": "==63.1.0"
},
"six": {
"hashes": [
"sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd",
"sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"
],
"index": "pypi",
"version": "==1.13.0"
},
"subprocess32": {
"hashes": [
"sha256:88e37c1aac5388df41cc8a8456bb49ebffd321a3ad4d70358e3518176de3a56b",
"sha256:e45d985aef903c5b7444d34350b05da91a9e0ea015415ab45a21212786c649d0",
"sha256:eb2937c80497978d181efa1b839ec2d9622cf9600a039a79d0e108d1f9aec79d"
],
"index": "pypi",
"version": "==3.5.4"
},
"testinfra": {
"hashes": [
"sha256:780e6c2ab392ea93c26cee1777c968a144c2189a56b3e239a3a66e6d256925b5",
"sha256:c3492b39c8d2c98d8419ce1a91d7fe348213f9b98b91198d2e7e88b3954b050b"
],
"index": "pypi",
"version": "==3.3.0"
},
"texttable": {
"hashes": [
"sha256:7dc282a5b22564fe0fdc1c771382d5dd9a54742047c61558e071c8cd595add86",
"sha256:eff3703781fbc7750125f50e10f001195174f13825a92a45e9403037d539b4f4"
],
"index": "pypi",
"version": "==1.6.2"
},
"toml": {
"hashes": [
"sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
"sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e",
"sha256:f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"
],
"index": "pypi",
"version": "==0.10.0"
},
"tox": {
"hashes": [
"sha256:06ba73b149bf838d5cd25dc30c2dd2671ae5b2757cf98e5c41a35fe449f131b3",
"sha256:806d0a9217584558cc93747a945a9d9bff10b141a5287f0c8429a08828a22192"
],
"index": "pypi",
"version": "==3.14.3"
},
"urllib3": {
"hashes": [
"sha256:753a0374df26658f99d826cfe40394a686d05985786d946fbe4165b5148f5a7c",
"sha256:a7acd0977125325f516bda9735fa7142b909a8d01e8b2e4c8108d0984e6e0098"
],
"index": "pypi",
"version": "==1.26.5"
},
"virtualenv": {
"hashes": [
"sha256:0d62c70883c0342d59c11d0ddac0d954d0431321a41ab20851facf2b222598f3",
"sha256:55059a7a676e4e19498f1aad09b8313a38fcc0cdbe4fdddc0e9b06946d21b4bb"
],
"index": "pypi",
"version": "==16.7.9"
},
"wcwidth": {
"hashes": [
"sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e",
"sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"
],
"index": "pypi",
"version": "==0.1.7"
},
"websocket-client": {
"hashes": [
"sha256:0fc45c961324d79c781bab301359d5a1b00b13ad1b10415a4780229ef71a5549",
"sha256:d735b91d6d1692a6a181f2a8c9e0238e5f6373356f561bb9dc4c7af36f452010"
],
"index": "pypi",
"version": "==0.57.0"
},
"zipp": {
"hashes": [
"sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e",
"sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335"
],
"index": "pypi",
"version": "==0.6.0"
} }
}, },
"develop": {} "develop": {}

View File

@ -12,3 +12,8 @@ Should result in:
- An image named `pihole:[branch-name]` being built - An image named `pihole:[branch-name]` being built
- Tests being ran to confirm the image doesn't have any regressions - Tests being ran to confirm the image doesn't have any regressions
# Modify Pipfile
You can enter into the test docker image using `./build-and-test.sh enter`.
From there, you can `cd test` and execute any needed pipenv commands.

View File

@ -4,6 +4,9 @@ set -eux
docker build ./src --tag pihole:${GIT_TAG} --no-cache docker build ./src --tag pihole:${GIT_TAG} --no-cache
docker images docker images
# auto-format the pytest code
python -m black ./test/tests/
# TODO: Add junitxml output and have something consume it # TODO: Add junitxml output and have something consume it
# 2 parallel max b/c race condition with docker fixture (I think?) # 2 parallel max b/c race condition with docker fixture (I think?)
py.test -vv -n 2 ./test/tests/ py.test -vv -n 2 ./test/tests/

View File

@ -1,55 +0,0 @@
-i https://pypi.org/simple/
apipkg==1.5
atomicwrites==1.3.0
attrs==19.3.0
backports.shutil-get-terminal-size==1.0.0
backports.ssl-match-hostname==3.7.0.1
bcrypt==3.1.7
cached-property==1.5.1
certifi==2019.11.28
cffi==1.13.2
chardet==3.0.4
configparser==4.0.2
contextlib2==0.6.0.post1
coverage==5.0.1
cryptography==3.3.2
docker==4.1.0
dockerpty==0.4.1
docopt==0.6.2
enum34==1.1.6
execnet==1.7.1
filelock==3.0.12
funcsigs==1.0.2
idna==2.8
importlib-metadata==1.3.0
ipaddress==1.0.23
jinja2==2.11.3
jsonschema==3.2.0
markupsafe==1.1.1
more-itertools==5.0.0
packaging==20.9
pathlib2==2.3.5
pluggy==0.13.1
py==1.10.0
pycparser==2.19
pyparsing==2.4.6
pyrsistent==0.15.6
pytest-cov==2.8.1
pytest-forked==1.1.3
pytest-xdist==1.31.0
pytest==4.6.8
pyyaml==5.4
requests==2.22.0
scandir==1.10.0
six==1.13.0
subprocess32==3.5.4
testinfra==3.3.0
texttable==1.6.2
toml==0.10.0
tox==3.14.3
urllib3==1.26.5
virtualenv==16.7.9
wcwidth==0.1.7
websocket-client==0.57.0
zipp==0.6.0
python-dotenv==0.17.1

View File

@ -3,63 +3,79 @@ import pytest
import subprocess import subprocess
import testinfra import testinfra
local_host = testinfra.get_host('local://') local_host = testinfra.get_host("local://")
check_output = local_host.check_output check_output = local_host.check_output
TAIL_DEV_NULL='tail -f /dev/null' TAIL_DEV_NULL = "tail -f /dev/null"
@pytest.fixture() @pytest.fixture()
def run_and_stream_command_output(): def run_and_stream_command_output():
def run_and_stream_command_output_inner(command, verbose=False): def run_and_stream_command_output_inner(command, verbose=False):
print("Running", command) print("Running", command)
build_env = os.environ.copy() build_env = os.environ.copy()
build_env['PIHOLE_DOCKER_TAG'] = version build_env["PIHOLE_DOCKER_TAG"] = version
build_result = subprocess.Popen(command.split(), env=build_env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, build_result = subprocess.Popen(
bufsize=1, universal_newlines=True) command.split(),
env=build_env,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
bufsize=1,
universal_newlines=True,
)
if verbose: if verbose:
while build_result.poll() is None: while build_result.poll() is None:
for line in build_result.stdout: for line in build_result.stdout:
print(line, end='') print(line, end="")
build_result.wait() build_result.wait()
if build_result.returncode != 0: if build_result.returncode != 0:
print(f' [i] Error running: {command}') print(f" [i] Error running: {command}")
print(build_result.stderr) print(build_result.stderr)
return run_and_stream_command_output_inner return run_and_stream_command_output_inner
@pytest.fixture() @pytest.fixture()
def args_volumes(): def args_volumes():
return '-v /dev/null:/etc/pihole/adlists.list' return "-v /dev/null:/etc/pihole/adlists.list"
@pytest.fixture() @pytest.fixture()
def args_env(): def args_env():
return '-e FTLCONF_LOCAL_IPV4="127.0.0.1"' return '-e FTLCONF_LOCAL_IPV4="127.0.0.1"'
@pytest.fixture() @pytest.fixture()
def args(args_volumes, args_env): def args(args_volumes, args_env):
return "{} {}".format(args_volumes, args_env) return "{} {}".format(args_volumes, args_env)
@pytest.fixture() @pytest.fixture()
def test_args(): def test_args():
''' test override fixture to provide arguments separate from our core args ''' """test override fixture to provide arguments separate from our core args"""
return '' return ""
def docker_generic(request, _test_args, _args, _image, _cmd, _entrypoint): def docker_generic(request, _test_args, _args, _image, _cmd, _entrypoint):
#assert 'docker' in check_output('id'), "Are you in the docker group?" # assert 'docker' in check_output('id'), "Are you in the docker group?"
# Always appended PYTEST arg to tell pihole we're testing # Always appended PYTEST arg to tell pihole we're testing
if 'pihole' in _image and 'PYTEST=1' not in _args: if "pihole" in _image and "PYTEST=1" not in _args:
_args = '{} -e PYTEST=1'.format(_args) _args = "{} -e PYTEST=1".format(_args)
docker_run = 'docker run -d -t {args} {test_args} {entry} {image} {cmd}'\ docker_run = "docker run -d -t {args} {test_args} {entry} {image} {cmd}".format(
.format(args=_args, test_args=_test_args, entry=_entrypoint, image=_image, cmd=_cmd) args=_args, test_args=_test_args, entry=_entrypoint, image=_image, cmd=_cmd
)
# Print a human runable version of the container run command for faster debugging # Print a human runable version of the container run command for faster debugging
print(docker_run.replace('-d -t', '--rm -it').replace(TAIL_DEV_NULL, 'bash')) print(docker_run.replace("-d -t", "--rm -it").replace(TAIL_DEV_NULL, "bash"))
docker_id = check_output(docker_run) docker_id = check_output(docker_run)
def teardown(): def teardown():
check_output("docker logs {}".format(docker_id)) check_output("docker logs {}".format(docker_id))
check_output("docker rm -f {}".format(docker_id)) check_output("docker rm -f {}".format(docker_id))
request.addfinalizer(teardown)
docker_container = testinfra.backend.get_backend("docker://" + docker_id, sudo=False) request.addfinalizer(teardown)
docker_container = testinfra.backend.get_backend(
"docker://" + docker_id, sudo=False
)
docker_container.id = docker_id docker_container.id = docker_id
return docker_container return docker_container
@ -67,90 +83,126 @@ def docker_generic(request, _test_args, _args, _image, _cmd, _entrypoint):
@pytest.fixture @pytest.fixture
def docker(request, test_args, args, image, cmd, entrypoint): def docker(request, test_args, args, image, cmd, entrypoint):
''' One-off Docker container run ''' """One-off Docker container run"""
return docker_generic(request, test_args, args, image, cmd, entrypoint) return docker_generic(request, test_args, args, image, cmd, entrypoint)
@pytest.fixture(scope='module')
def docker_persist(request, persist_test_args, persist_args, persist_image, persist_cmd, persist_entrypoint, dig): @pytest.fixture(scope="module")
''' Persistent Docker container for multiple tests, instead of stopping container after one test ''' def docker_persist(
''' Uses DUP'd module scoped fixtures because smaller scoped fixtures won't mix with module scope ''' request,
persistent_container = docker_generic(request, persist_test_args, persist_args, persist_image, persist_cmd, persist_entrypoint) persist_test_args,
''' attach a dig container for lookups ''' persist_args,
persist_image,
persist_cmd,
persist_entrypoint,
dig,
):
"""
Persistent Docker container for multiple tests, instead of stopping container after one test
Uses DUP'd module scoped fixtures because smaller scoped fixtures won't mix with module scope
"""
persistent_container = docker_generic(
request,
persist_test_args,
persist_args,
persist_image,
persist_cmd,
persist_entrypoint,
)
""" attach a dig container for lookups """
persistent_container.dig = dig(persistent_container.id) persistent_container.dig = dig(persistent_container.id)
return persistent_container return persistent_container
@pytest.fixture @pytest.fixture
def entrypoint(): def entrypoint():
return '' return ""
@pytest.fixture() @pytest.fixture()
def version(): def version():
return os.environ.get('GIT_TAG', None) return os.environ.get("GIT_TAG", None)
@pytest.fixture() @pytest.fixture()
def tag(version): def tag(version):
return '{}'.format(version) return "{}".format(version)
@pytest.fixture @pytest.fixture
def webserver(tag): def webserver(tag):
''' TODO: this is obvious without alpine+nginx as the alternative, remove fixture, hard code lighttpd in tests? ''' """TODO: this is obvious without alpine+nginx as the alternative, remove fixture, hard code lighttpd in tests?"""
return 'lighttpd' return "lighttpd"
@pytest.fixture() @pytest.fixture()
def image(tag): def image(tag):
image = 'pihole' image = "pihole"
return '{}:{}'.format(image, tag) return "{}:{}".format(image, tag)
@pytest.fixture() @pytest.fixture()
def cmd(): def cmd():
return TAIL_DEV_NULL return TAIL_DEV_NULL
@pytest.fixture(scope='module')
@pytest.fixture(scope="module")
def persist_version(): def persist_version():
return version return version
@pytest.fixture(scope='module')
@pytest.fixture(scope="module")
def persist_args_dns(): def persist_args_dns():
return '--dns 127.0.0.1 --dns 1.1.1.1' return "--dns 127.0.0.1 --dns 1.1.1.1"
@pytest.fixture(scope='module')
@pytest.fixture(scope="module")
def persist_args_volumes(): def persist_args_volumes():
return '-v /dev/null:/etc/pihole/adlists.list' return "-v /dev/null:/etc/pihole/adlists.list"
@pytest.fixture(scope='module')
@pytest.fixture(scope="module")
def persist_args_env(): def persist_args_env():
return '-e ServerIP="127.0.0.1"' return '-e ServerIP="127.0.0.1"'
@pytest.fixture(scope='module')
@pytest.fixture(scope="module")
def persist_args(persist_args_volumes, persist_args_env): def persist_args(persist_args_volumes, persist_args_env):
return "{} {}".format(persist_args_volumes, persist_args_env) return "{} {}".format(persist_args_volumes, persist_args_env)
@pytest.fixture(scope='module')
@pytest.fixture(scope="module")
def persist_test_args(): def persist_test_args():
''' test override fixture to provide arguments separate from our core args ''' """test override fixture to provide arguments separate from our core args"""
return '' return ""
@pytest.fixture(scope='module')
@pytest.fixture(scope="module")
def persist_tag(persist_version): def persist_tag(persist_version):
return '{}'.format(persist_version) return "{}".format(persist_version)
@pytest.fixture(scope='module')
@pytest.fixture(scope="module")
def persist_webserver(persist_tag): def persist_webserver(persist_tag):
''' TODO: this is obvious without alpine+nginx as the alternative, remove fixture, hard code lighttpd in tests? ''' """TODO: this is obvious without alpine+nginx as the alternative, remove fixture, hard code lighttpd in tests?"""
return 'lighttpd' return "lighttpd"
@pytest.fixture(scope='module')
@pytest.fixture(scope="module")
def persist_image(persist_tag): def persist_image(persist_tag):
image = 'pihole' image = "pihole"
return '{}:{}'.format(image, persist_tag) return "{}:{}".format(image, persist_tag)
@pytest.fixture(scope='module')
@pytest.fixture(scope="module")
def persist_cmd(): def persist_cmd():
return TAIL_DEV_NULL return TAIL_DEV_NULL
@pytest.fixture(scope='module')
@pytest.fixture(scope="module")
def persist_entrypoint(): def persist_entrypoint():
return '' return ""
@pytest.fixture @pytest.fixture
def slow(): def slow():
@ -158,6 +210,7 @@ def slow():
Run a slow check, check if the state is correct for `timeout` seconds. Run a slow check, check if the state is correct for `timeout` seconds.
""" """
import time import time
def _slow(check, timeout=20): def _slow(check, timeout=20):
timeout_at = time.time() + timeout timeout_at = time.time() + timeout
while True: while True:
@ -170,26 +223,28 @@ def slow():
raise e raise e
else: else:
return return
return _slow return _slow
@pytest.fixture(scope='module')
@pytest.fixture(scope="module")
def dig(): def dig():
''' separate container to link to pi-hole and perform lookups ''' """separate container to link to pi-hole and perform lookups"""
''' a docker pull is faster than running an install of dnsutils ''' """ a docker pull is faster than running an install of dnsutils """
def _dig(docker_id): def _dig(docker_id):
args = '--link {}:test_pihole'.format(docker_id) args = "--link {}:test_pihole".format(docker_id)
image = 'azukiapp/dig' image = "azukiapp/dig"
cmd = TAIL_DEV_NULL cmd = TAIL_DEV_NULL
dig_container = docker_generic(request, '', args, image, cmd, '') dig_container = docker_generic(request, "", args, image, cmd, "")
return dig_container return dig_container
return _dig return _dig
'''
Persistent Docker container for testing service post _startup.sh
'''
@pytest.fixture @pytest.fixture
def running_pihole(docker_persist, slow, persist_webserver): def running_pihole(docker_persist, slow, persist_webserver):
''' Persist a fully started docker-pi-hole to help speed up subsequent tests ''' """Persist a fully started docker-pi-hole to help speed up subsequent tests"""
slow(lambda: docker_persist.run('pgrep pihole-FTL').rc == 0) slow(lambda: docker_persist.run("pgrep pihole-FTL").rc == 0)
slow(lambda: docker_persist.run('pgrep lighttpd').rc == 0) slow(lambda: docker_persist.run("pgrep lighttpd").rc == 0)
return docker_persist return docker_persist

View File

@ -1,165 +1,249 @@
import os import os
import pytest import pytest
import re import re
SETUPVARS_LOC='/etc/pihole/setupVars.conf' SETUPVARS_LOC = "/etc/pihole/setupVars.conf"
DNSMASQ_CONFIG_LOC = '/etc/dnsmasq.d/01-pihole.conf' DNSMASQ_CONFIG_LOC = "/etc/dnsmasq.d/01-pihole.conf"
CMD_SETUP_FTL_CACHESIZE='. bash_functions.sh ; setup_FTL_CacheSize' CMD_SETUP_FTL_CACHESIZE = ". bash_functions.sh ; setup_FTL_CacheSize"
CMD_SETUP_FTL_INTERFACE='. bash_functions.sh ; setup_FTL_Interface' CMD_SETUP_FTL_INTERFACE = ". bash_functions.sh ; setup_FTL_Interface"
CMD_SETUP_WEB_PASSWORD='. bash_functions.sh ; setup_web_password' CMD_SETUP_WEB_PASSWORD = ". bash_functions.sh ; setup_web_password"
def _cat(file): def _cat(file):
return 'cat {}'.format(file) return "cat {}".format(file)
def _grep(string, file): def _grep(string, file):
return 'grep -q \'{}\' {}'.format(string,file) return "grep -q '{}' {}".format(string, file)
@pytest.mark.parametrize('test_args,expected_ipv6,expected_stdout', [
('', True, 'IPv4 and IPv6'),
('-e "IPv6=True"', True, 'IPv4 and IPv6'),
('-e "IPv6=False"', False, 'IPv4'),
('-e "IPv6=foobar"', False, 'IPv4'),
])
def test_ipv6_not_true_removes_ipv6(docker, slow, test_args, expected_ipv6, expected_stdout):
''' When a user overrides IPv6=True they only get IPv4 listening webservers '''
IPV6_LINE = 'use-ipv6.pl'
WEB_CONFIG = '/etc/lighttpd/lighttpd.conf'
function = docker.run('. /usr/local/bin/bash_functions.sh ; setup_ipv4_ipv6') @pytest.mark.parametrize(
"test_args,expected_ipv6,expected_stdout",
[
("", True, "IPv4 and IPv6"),
('-e "IPv6=True"', True, "IPv4 and IPv6"),
('-e "IPv6=False"', False, "IPv4"),
('-e "IPv6=foobar"', False, "IPv4"),
],
)
def test_ipv6_not_true_removes_ipv6(
docker, slow, test_args, expected_ipv6, expected_stdout
):
"""When a user overrides IPv6=True they only get IPv4 listening webservers"""
IPV6_LINE = "use-ipv6.pl"
WEB_CONFIG = "/etc/lighttpd/lighttpd.conf"
function = docker.run(". /usr/local/bin/bash_functions.sh ; setup_ipv4_ipv6")
assert "Using {}".format(expected_stdout) in function.stdout assert "Using {}".format(expected_stdout) in function.stdout
if expected_stdout == 'IPv4': if expected_stdout == "IPv4":
assert 'IPv6' not in function.stdout assert "IPv6" not in function.stdout
# On overlay2(?) docker sometimes writes to disk are slow enough to break some tests... # On overlay2(?) docker sometimes writes to disk are slow enough to break some tests...
expected_ipv6_check = lambda: (\ expected_ipv6_check = (
IPV6_LINE in docker.run('grep \'use-ipv6.pl\' {}'.format(WEB_CONFIG)).stdout lambda: (
) == expected_ipv6 IPV6_LINE in docker.run("grep 'use-ipv6.pl' {}".format(WEB_CONFIG)).stdout
)
== expected_ipv6
)
slow(expected_ipv6_check) slow(expected_ipv6_check)
@pytest.mark.parametrize('test_args', ['-e "WEB_PORT=999"']) @pytest.mark.parametrize("test_args", ['-e "WEB_PORT=999"'])
def test_overrides_default_web_port(docker, slow, test_args): def test_overrides_default_web_port(docker, slow, test_args):
''' When a --net=host user sets WEB_PORT to avoid synology's 80 default IPv4 and or IPv6 ports are updated''' """When a --net=host user sets WEB_PORT to avoid synology's 80 default IPv4 and or IPv6 ports are updated"""
CONFIG_LINE = r'server.port\s*=\s*999' CONFIG_LINE = r"server.port\s*=\s*999"
WEB_CONFIG = '/etc/lighttpd/lighttpd.conf' WEB_CONFIG = "/etc/lighttpd/lighttpd.conf"
function = docker.run('. /usr/local/bin/bash_functions.sh ; eval `grep setup_web_port /usr/local/bin/_startup.sh`') function = docker.run(
". /usr/local/bin/bash_functions.sh ; eval `grep setup_web_port /usr/local/bin/_startup.sh`"
)
assert " [i] Custom WEB_PORT set to 999" in function.stdout assert " [i] Custom WEB_PORT set to 999" in function.stdout
assert " [i] Without proper router DNAT forwarding to 127.0.0.1:999, you may not get any blocked websites on ads" in function.stdout assert (
slow(lambda: re.search(CONFIG_LINE, docker.run(_cat(WEB_CONFIG)).stdout) != None) " [i] Without proper router DNAT forwarding to 127.0.0.1:999, you may not get any blocked websites on ads"
in function.stdout
)
slow(
lambda: re.search(CONFIG_LINE, docker.run(_cat(WEB_CONFIG)).stdout) is not None
)
@pytest.mark.parametrize('test_args,expected_error', [ @pytest.mark.parametrize(
('-e WEB_PORT="LXXX"', 'WARNING: Custom WEB_PORT not used - LXXX is not an integer'), "test_args,expected_error",
('-e WEB_PORT="1,000"', 'WARNING: Custom WEB_PORT not used - 1,000 is not an integer'), [
('-e WEB_PORT="99999"', 'WARNING: Custom WEB_PORT not used - 99999 is not within valid port range of 1-65535'), (
]) '-e WEB_PORT="LXXX"',
"WARNING: Custom WEB_PORT not used - LXXX is not an integer",
),
(
'-e WEB_PORT="1,000"',
"WARNING: Custom WEB_PORT not used - 1,000 is not an integer",
),
(
'-e WEB_PORT="99999"',
"WARNING: Custom WEB_PORT not used - 99999 is not within valid port range of 1-65535",
),
],
)
def test_bad_input_to_web_port(docker, test_args, expected_error): def test_bad_input_to_web_port(docker, test_args, expected_error):
function = docker.run('. /usr/local/bin/bash_functions.sh ; eval `grep setup_web_port /usr/local/bin/_startup.sh`') function = docker.run(
". /usr/local/bin/bash_functions.sh ; eval `grep setup_web_port /usr/local/bin/_startup.sh`"
)
assert expected_error in function.stdout assert expected_error in function.stdout
@pytest.mark.parametrize('test_args,cache_size', [('-e CUSTOM_CACHE_SIZE="0"', '0'), ('-e CUSTOM_CACHE_SIZE="20000"', '20000')]) @pytest.mark.parametrize(
"test_args,cache_size",
[('-e CUSTOM_CACHE_SIZE="0"', "0"), ('-e CUSTOM_CACHE_SIZE="20000"', "20000")],
)
def test_overrides_default_custom_cache_size(docker, slow, test_args, cache_size): def test_overrides_default_custom_cache_size(docker, slow, test_args, cache_size):
''' Changes the cache_size setting to increase or decrease the cache size for dnsmasq''' """Changes the cache_size setting to increase or decrease the cache size for dnsmasq"""
CONFIG_LINE = r'cache-size\s*=\s*{}'.format(cache_size) CONFIG_LINE = r"cache-size\s*=\s*{}".format(cache_size)
function = docker.run('echo ${CUSTOM_CACHE_SIZE};. ./usr/local/bin/bash_functions.sh; echo ${CUSTOM_CACHE_SIZE}; eval `grep setup_FTL_CacheSize /usr/local/bin/_startup.sh`') function = docker.run(
"echo ${CUSTOM_CACHE_SIZE};. ./usr/local/bin/bash_functions.sh; echo ${CUSTOM_CACHE_SIZE}; eval `grep setup_FTL_CacheSize /usr/local/bin/_startup.sh`"
)
assert "Custom CUSTOM_CACHE_SIZE set to {}".format(cache_size) in function.stdout assert "Custom CUSTOM_CACHE_SIZE set to {}".format(cache_size) in function.stdout
slow(lambda: re.search(CONFIG_LINE, docker.run(_cat(DNSMASQ_CONFIG_LOC)).stdout) != None) slow(
lambda: re.search(CONFIG_LINE, docker.run(_cat(DNSMASQ_CONFIG_LOC)).stdout)
is not None
)
@pytest.mark.parametrize('test_args', [ @pytest.mark.parametrize(
'-e CUSTOM_CACHE_SIZE="-1"', "test_args",
'-e CUSTOM_CACHE_SIZE="1,000"', [
]) '-e CUSTOM_CACHE_SIZE="-1"',
'-e CUSTOM_CACHE_SIZE="1,000"',
],
)
def test_bad_input_to_custom_cache_size(docker, slow, test_args): def test_bad_input_to_custom_cache_size(docker, slow, test_args):
CONFIG_LINE = r'cache-size\s*=\s*10000' CONFIG_LINE = r"cache-size\s*=\s*10000"
docker.run(CMD_SETUP_FTL_CACHESIZE) docker.run(CMD_SETUP_FTL_CACHESIZE)
slow(lambda: re.search(CONFIG_LINE, docker.run(_cat(DNSMASQ_CONFIG_LOC)).stdout) != None) slow(
lambda: re.search(CONFIG_LINE, docker.run(_cat(DNSMASQ_CONFIG_LOC)).stdout)
is not None
)
@pytest.mark.parametrize('test_args', [
'-e DNSSEC="true" -e CUSTOM_CACHE_SIZE="0"', @pytest.mark.parametrize(
]) "test_args",
[
'-e DNSSEC="true" -e CUSTOM_CACHE_SIZE="0"',
],
)
def test_dnssec_enabled_with_custom_cache_size(docker, slow, test_args): def test_dnssec_enabled_with_custom_cache_size(docker, slow, test_args):
CONFIG_LINE = r'cache-size\s*=\s*10000' CONFIG_LINE = r"cache-size\s*=\s*10000"
docker.run(CMD_SETUP_FTL_CACHESIZE) docker.run(CMD_SETUP_FTL_CACHESIZE)
slow(lambda: re.search(CONFIG_LINE, docker.run(_cat(DNSMASQ_CONFIG_LOC)).stdout) != None) slow(
lambda: re.search(CONFIG_LINE, docker.run(_cat(DNSMASQ_CONFIG_LOC)).stdout)
is not None
)
@pytest.mark.parametrize('args_env, expected_stdout, expected_config_line', [ @pytest.mark.parametrize(
('', 'binding to default interface: eth0', 'PIHOLE_INTERFACE=eth0'), "args_env, expected_stdout, expected_config_line",
('-e INTERFACE="br0"', 'binding to custom interface: br0', 'PIHOLE_INTERFACE=br0'), [
]) ("", "binding to default interface: eth0", "PIHOLE_INTERFACE=eth0"),
def test_dns_interface_override_defaults(docker, slow, args_env, expected_stdout, expected_config_line): (
''' When INTERFACE environment var is passed in, overwrite dnsmasq interface ''' '-e INTERFACE="br0"',
"binding to custom interface: br0",
"PIHOLE_INTERFACE=br0",
),
],
)
def test_dns_interface_override_defaults(
docker, slow, args_env, expected_stdout, expected_config_line
):
"""When INTERFACE environment var is passed in, overwrite dnsmasq interface"""
function = docker.run(CMD_SETUP_FTL_INTERFACE) function = docker.run(CMD_SETUP_FTL_INTERFACE)
assert expected_stdout in function.stdout assert expected_stdout in function.stdout
slow(lambda: expected_config_line + '\n' == docker.run('grep "^PIHOLE_INTERFACE" {}'.format(SETUPVARS_LOC)).stdout) slow(
lambda: expected_config_line + "\n"
== docker.run('grep "^PIHOLE_INTERFACE" {}'.format(SETUPVARS_LOC)).stdout
)
expected_debian_lines = [ expected_debian_lines = [
'"VIRTUAL_HOST" => "127.0.0.1"', '"VIRTUAL_HOST" => "127.0.0.1"',
'"PHP_ERROR_LOG" => "/var/log/lighttpd/error-pihole.log"' '"PHP_ERROR_LOG" => "/var/log/lighttpd/error-pihole.log"',
] ]
@pytest.mark.parametrize('expected_lines,repeat_function', [ @pytest.mark.parametrize(
(expected_debian_lines, 1), "expected_lines,repeat_function",
(expected_debian_lines, 2) [(expected_debian_lines, 1), (expected_debian_lines, 2)],
]) )
def test_debian_setup_php_env(docker, expected_lines, repeat_function): def test_debian_setup_php_env(docker, expected_lines, repeat_function):
''' confirm all expected output is there and nothing else ''' """confirm all expected output is there and nothing else"""
for _ in range(repeat_function): for _ in range(repeat_function):
docker.run('. /usr/local/bin/bash_functions.sh ; eval `grep setup_php_env /usr/local/bin/_startup.sh`').stdout docker.run(
". /usr/local/bin/bash_functions.sh ; eval `grep setup_php_env /usr/local/bin/_startup.sh`"
)
for expected_line in expected_lines: for expected_line in expected_lines:
search_config_cmd = "grep -c '{}' /etc/lighttpd/conf-enabled/15-fastcgi-php.conf".format(expected_line) search_config_cmd = (
"grep -c '{}' /etc/lighttpd/conf-enabled/15-fastcgi-php.conf".format(
expected_line
)
)
search_config_count = docker.run(search_config_cmd) search_config_count = docker.run(search_config_cmd)
found_lines = int(search_config_count.stdout.rstrip('\n')) found_lines = int(search_config_count.stdout.rstrip("\n"))
if found_lines > 1: if found_lines > 1:
assert False, f'Found line {expected_line} times (more than once): {found_lines}' assert (
False
), f"Found line {expected_line} times (more than once): {found_lines}"
def test_webpassword_random_generation(docker): def test_webpassword_random_generation(docker):
''' When a user sets webPassword env the admin password gets set to that ''' """When a user sets webPassword env the admin password gets set to that"""
function = docker.run(CMD_SETUP_WEB_PASSWORD) function = docker.run(CMD_SETUP_WEB_PASSWORD)
assert 'assigning random password' in function.stdout.lower() assert "assigning random password" in function.stdout.lower()
@pytest.mark.parametrize('entrypoint,cmd', [('--entrypoint=tail','-f /dev/null')]) @pytest.mark.parametrize("entrypoint,cmd", [("--entrypoint=tail", "-f /dev/null")])
@pytest.mark.parametrize('args_env,secure,setupvars_hash', [ @pytest.mark.parametrize(
('-e WEBPASSWORD=login', True, 'WEBPASSWORD=6060d59351e8c2f48140f01b2c3f3b61652f396c53a5300ae239ebfbe7d5ff08'), "args_env,secure,setupvars_hash",
('-e WEBPASSWORD=""', False, ''), [
]) (
def test_webpassword_env_assigns_password_to_file_or_removes_if_empty(docker, args_env, secure, setupvars_hash): "-e WEBPASSWORD=login",
''' When a user sets webPassword env the admin password gets set or removed if empty ''' True,
"WEBPASSWORD=6060d59351e8c2f48140f01b2c3f3b61652f396c53a5300ae239ebfbe7d5ff08",
),
('-e WEBPASSWORD=""', False, ""),
],
)
def test_webpassword_env_assigns_password_to_file_or_removes_if_empty(
docker, args_env, secure, setupvars_hash
):
"""When a user sets webPassword env the admin password gets set or removed if empty"""
function = docker.run(CMD_SETUP_WEB_PASSWORD) function = docker.run(CMD_SETUP_WEB_PASSWORD)
if secure: if secure:
assert 'new password set' in function.stdout.lower() assert "new password set" in function.stdout.lower()
assert docker.run(_grep(setupvars_hash, SETUPVARS_LOC)).rc == 0 assert docker.run(_grep(setupvars_hash, SETUPVARS_LOC)).rc == 0
else: else:
assert 'password removed' in function.stdout.lower() assert "password removed" in function.stdout.lower()
assert docker.run(_grep('^WEBPASSWORD=$', SETUPVARS_LOC)).rc == 0 assert docker.run(_grep("^WEBPASSWORD=$", SETUPVARS_LOC)).rc == 0
@pytest.mark.parametrize('entrypoint,cmd', [('--entrypoint=tail','-f /dev/null')]) @pytest.mark.parametrize("entrypoint,cmd", [("--entrypoint=tail", "-f /dev/null")])
@pytest.mark.parametrize('test_args', ['-e WEBPASSWORD=login', '-e WEBPASSWORD=""']) @pytest.mark.parametrize("test_args", ["-e WEBPASSWORD=login", '-e WEBPASSWORD=""'])
def test_env_always_updates_password(docker, args_env, test_args): def test_env_always_updates_password(docker, args_env, test_args):
'''When a user sets the WEBPASSWORD environment variable, ensure it always sets the password''' """When a user sets the WEBPASSWORD environment variable, ensure it always sets the password"""
function = docker.run(CMD_SETUP_WEB_PASSWORD) function = docker.run(CMD_SETUP_WEB_PASSWORD)
assert ' [i] Assigning password defined by Environment Variable' in function.stdout assert " [i] Assigning password defined by Environment Variable" in function.stdout
@pytest.mark.parametrize('entrypoint,cmd', [('--entrypoint=tail','-f /dev/null')]) @pytest.mark.parametrize("entrypoint,cmd", [("--entrypoint=tail", "-f /dev/null")])
def test_setupvars_trumps_random_password_if_set(docker, args_env, test_args): def test_setupvars_trumps_random_password_if_set(docker, args_env, test_args):
'''If a password is already set in setupvars, and no password is set in the environment variable, do not generate a random password''' """If a password is already set in setupvars, and no password is set in the environment variable, do not generate a random password"""
docker.run('. /opt/pihole/utils.sh ; addOrEditKeyValPair {} WEBPASSWORD volumepass'.format(SETUPVARS_LOC)) docker.run(
". /opt/pihole/utils.sh ; addOrEditKeyValPair {} WEBPASSWORD volumepass".format(
SETUPVARS_LOC
)
)
function = docker.run(CMD_SETUP_WEB_PASSWORD) function = docker.run(CMD_SETUP_WEB_PASSWORD)
assert 'Pre existing WEBPASSWORD found' in function.stdout assert "Pre existing WEBPASSWORD found" in function.stdout
assert docker.run(_grep('WEBPASSWORD=volumepass', SETUPVARS_LOC)).rc == 0 assert docker.run(_grep("WEBPASSWORD=volumepass", SETUPVARS_LOC)).rc == 0

View File

@ -1,19 +1,37 @@
import pytest import pytest
import time import time
''' conftest.py provides the defaults through fixtures '''
''' Note, testinfra builtins don't seem fully compatible with """ conftest.py provides the defaults through fixtures """
docker containers (esp. musl based OSs) stripped down nature ''' """ Note, testinfra builtins don't seem fully compatible with
docker containers (esp. musl based OSs) stripped down nature """
# If the test runs /usr/local/bin/_startup.sh, do not let s6 run it too! Kill entrypoint to avoid race condition/duplicated execution # If the test runs /usr/local/bin/_startup.sh, do not let s6 run it too! Kill entrypoint to avoid race condition/duplicated execution
@pytest.mark.parametrize('entrypoint,cmd', [('--entrypoint=tail','-f /dev/null')]) @pytest.mark.parametrize("entrypoint,cmd", [("--entrypoint=tail", "-f /dev/null")])
@pytest.mark.parametrize('args,error_msg,expect_rc', [ @pytest.mark.parametrize(
('-e FTLCONF_LOCAL_IPV4="1.2.3.z"', "FTLCONF_LOCAL_IPV4 Environment variable (1.2.3.z) doesn't appear to be a valid IPv4 address",1), "args,error_msg,expect_rc",
('-e FTLCONF_LOCAL_IPV4="1.2.3.4" -e FTLCONF_LOCAL_IPV6="1234:1234:1234:ZZZZ"', "Environment variable (1234:1234:1234:ZZZZ) doesn't appear to be a valid IPv6 address",1), [
('-e FTLCONF_LOCAL_IPV4="1.2.3.4" -e FTLCONF_LOCAL_IPV6="kernel"', "ERROR: You passed in IPv6 with a value of 'kernel'",1), (
]) '-e FTLCONF_LOCAL_IPV4="1.2.3.z"',
def test_ftlconf_local_addr_invalid_ips_triggers_exit_error(docker, error_msg, expect_rc): "FTLCONF_LOCAL_IPV4 Environment variable (1.2.3.z) doesn't appear to be a valid IPv4 address",
start = docker.run('/usr/local/bin/_startup.sh') 1,
),
(
'-e FTLCONF_LOCAL_IPV4="1.2.3.4" -e FTLCONF_LOCAL_IPV6="1234:1234:1234:ZZZZ"',
"Environment variable (1234:1234:1234:ZZZZ) doesn't appear to be a valid IPv6 address",
1,
),
(
'-e FTLCONF_LOCAL_IPV4="1.2.3.4" -e FTLCONF_LOCAL_IPV6="kernel"',
"ERROR: You passed in IPv6 with a value of 'kernel'",
1,
),
],
)
def test_ftlconf_local_addr_invalid_ips_triggers_exit_error(
docker, error_msg, expect_rc
):
start = docker.run("/usr/local/bin/_startup.sh")
assert start.rc == expect_rc assert start.rc == expect_rc
assert 'ERROR' in start.stdout assert "ERROR" in start.stdout
assert error_msg in start.stdout assert error_msg in start.stdout