diff --git a/.config/dictionaries/project.dic b/.config/dictionaries/project.dic index a9d7135f4b..c5f7235baf 100644 --- a/.config/dictionaries/project.dic +++ b/.config/dictionaries/project.dic @@ -5,6 +5,7 @@ adminer androidx appspot asyncio +asyncpg auditability bluefireteam BROTLI @@ -31,6 +32,7 @@ dotglob drep dreps encryptor +fetchval fontawesome formz Formz @@ -46,11 +48,13 @@ iphoneos jetbrains jorm jormungandr +Joaquín Jörmungandr kroki lcov Leshiy localizable +loguru mdlint mitigations moderations @@ -76,6 +80,7 @@ psql Ptarget pubkey pubspec +pytest rapidoc redoc reqwest @@ -120,4 +125,4 @@ nextest testcov testdocs fmtchk -fmtfix \ No newline at end of file +fmtfix diff --git a/catalyst-gateway/Earthfile b/catalyst-gateway/Earthfile index fe98ec05c2..09033797aa 100644 --- a/catalyst-gateway/Earthfile +++ b/catalyst-gateway/Earthfile @@ -4,7 +4,7 @@ VERSION --try --global-cache 0.7 # Set up our target toolchains, and copy our files. builder: - DO github.com/input-output-hk/catalyst-ci/earthly/rust:v2.6.0+SETUP + DO github.com/input-output-hk/catalyst-ci/earthly/rust:v2.7.0+SETUP COPY --dir .cargo .config Cargo.* clippy.toml deny.toml rustfmt.toml bin crates tests . diff --git a/catalyst-gateway/deny.toml b/catalyst-gateway/deny.toml index 926f2ef437..886341af4f 100644 --- a/catalyst-gateway/deny.toml +++ b/catalyst-gateway/deny.toml @@ -108,6 +108,7 @@ allow = [ "Apache-2.0", "Unicode-DFS-2016", "BSD-3-Clause", + "BSD-2-Clause", "BlueOak-1.0.0", "Apache-2.0 WITH LLVM-exception" ] @@ -279,4 +280,4 @@ allow-git = [ # 1 or more gitlab.com organizations to allow git sources for #gitlab = [""] # 1 or more bitbucket.org organizations to allow git sources for -#bitbucket = [""] \ No newline at end of file +#bitbucket = [""] diff --git a/catalyst-gateway/event-db/Earthfile b/catalyst-gateway/event-db/Earthfile index 4c32943a40..df0643c25d 100644 --- a/catalyst-gateway/event-db/Earthfile +++ b/catalyst-gateway/event-db/Earthfile @@ -9,7 +9,7 @@ VERSION 0.7 # Internal: builder is our Event db builder target. Prepares all necessary artifacts. # CI target : dependency builder: - DO github.com/input-output-hk/catalyst-ci/earthly/postgresql:v2.0.15+BUILDER \ + DO github.com/input-output-hk/catalyst-ci/earthly/postgresql:v2.7.0+BUILDER \ --sqlfluff_cfg=./../../+repo-config/repo/.sqlfluff COPY ./../../+repo-config-2/repo/.sqlfluff . @@ -21,7 +21,7 @@ builder: check: FROM +builder - DO github.com/input-output-hk/catalyst-ci/earthly/postgresql:v2.0.15+CHECK + DO github.com/input-output-hk/catalyst-ci/earthly/postgresql:v2.7.0+CHECK # format all SQL files in the current project. Local developers tool. @@ -29,22 +29,22 @@ check: format: LOCALLY - DO github.com/input-output-hk/catalyst-ci/earthly/postgresql:v2.0.15+FORMAT --src=$(echo ${PWD}/../../) + DO github.com/input-output-hk/catalyst-ci/earthly/postgresql:v2.7.0+FORMAT --src=$(echo ${PWD}/../../) # build - an event db docker image. # CI target : true build: FROM +builder - DO github.com/input-output-hk/catalyst-ci/earthly/postgresql:v2.0.15+BUILD --image_name=event-db - DO github.com/input-output-hk/catalyst-ci/earthly/postgresql:v2.0.15+DOCS --image_name=event-db + DO github.com/input-output-hk/catalyst-ci/earthly/postgresql:v2.7.0+BUILD --image_name=event-db + DO github.com/input-output-hk/catalyst-ci/earthly/postgresql:v2.7.0+DOCS --image_name=event-db # test the event db database schema # CI target : true #test: -# FROM github.com/input-output-hk/catalyst-ci/earthly/postgresql:v2.0.15+postgres-base +# FROM github.com/input-output-hk/catalyst-ci/earthly/postgresql:v2.7.0+postgres-base -# COPY github.com/input-output-hk/catalyst-ci/earthly/utils:v2.0.15+shell-assert/assert.sh . +# COPY github.com/input-output-hk/catalyst-ci/earthly/utils:v2.7.0+shell-assert/assert.sh . # COPY ./docker-compose.yml . # WITH DOCKER \ diff --git a/catalyst-gateway/tests/Earthfile b/catalyst-gateway/tests/Earthfile index e0f574d834..4a421379dc 100644 --- a/catalyst-gateway/tests/Earthfile +++ b/catalyst-gateway/tests/Earthfile @@ -5,7 +5,7 @@ build: RUN cargo build -p cat-gateway --release SAVE ARTIFACT target/release/cat-gateway cat-gateway -cat-gateway-publish: +package-cat-gateway: FROM alpine:3.19 ARG tag="latest" ARG address @@ -16,7 +16,7 @@ cat-gateway-publish: ENTRYPOINT ./cat-gateway run --address $address --database-url $db_url --log-level $log_level SAVE IMAGE cat-gateway:$tag -schemathesis-publish: +package-schemathesis: FROM python:3.12-alpine3.19 ARG tag="latest" ARG max_examples=1000 @@ -40,9 +40,9 @@ fuzzer-api-test: COPY integration/docker-compose.yml . WITH DOCKER \ --compose docker-compose.yml \ - --load schemathesis:latest=(+schemathesis-publish --openapi_spec="http://127.0.0.1:3030/docs/cat-gateway.json") \ + --load schemathesis:latest=(+package-schemathesis --openapi_spec="http://127.0.0.1:3030/docs/cat-gateway.json") \ --load event-db:latest=(../event-db+build --with_historic_data=false) \ - --load cat-gateway:latest=(+cat-gateway-publish --address="127.0.0.1:3030" \ + --load cat-gateway:latest=(+package-cat-gateway --address="127.0.0.1:3030" \ --db_url="postgres://catalyst-event-dev:CHANGE_ME@localhost/CatalystEventDev") \ --service event-db \ --service cat-gateway \ @@ -86,4 +86,4 @@ integration-test: IF [ -f fail ] RUN echo "Integration tests failed" && \ exit 1 - END \ No newline at end of file + END diff --git a/catalyst-gateway/tests/schema-mismatch/Earthfile b/catalyst-gateway/tests/schema-mismatch/Earthfile new file mode 100644 index 0000000000..751baebaeb --- /dev/null +++ b/catalyst-gateway/tests/schema-mismatch/Earthfile @@ -0,0 +1,34 @@ +VERSION --global-cache 0.7 + +builder: + FROM github.com/input-output-hk/catalyst-ci/earthly/python:v2.7.0+python-base + + COPY --dir ./schema_mismatch README.md . + DO github.com/input-output-hk/catalyst-ci/earthly/python:v2.7.0+BUILDER + +package-tester: + FROM +builder + + CMD poetry run pytest + # The following is useful for debugging the tests + # CMD poetry run pytest -vvvv --capture tee-sys --show-capture=stderr + +test: + FROM earthly/dind:alpine + + ARG DB_URL="postgres://catalyst-event-dev:CHANGE_ME@event-db/CatalystEventDev" + ARG CAT_ADDRESS="0.0.0.0:3030" + + WORKDIR /default + COPY ./docker-compose.yml . + + WITH DOCKER \ + --compose docker-compose.yml \ + --load event-db:latest=(../../event-db+build --with_historic_data=false) \ + --load cat-gateway:latest=(../+package-cat-gateway --address=$CAT_ADDRESS --db_url=$DB_URL) \ + --load test:latest=(+package-tester) \ + --service event-db \ + --service cat-gateway \ + --allow-privileged + RUN docker run --network=default_default test + END diff --git a/catalyst-gateway/tests/schema-mismatch/README.md b/catalyst-gateway/tests/schema-mismatch/README.md new file mode 100644 index 0000000000..d315f2242f --- /dev/null +++ b/catalyst-gateway/tests/schema-mismatch/README.md @@ -0,0 +1,14 @@ +# Integration testing for DB Schema Version Mismatch behavior + +Sets up a containerized environment with the `EventDB` and `catalyst-gateway` services running. + +Integration tests are run in this environment that probe the behavior of the `catalyst-gateway` service in situations +where the DB schema version changes during execution, and creates a mismatch with the version that gateway service expects. + +## Running + +To run: + +```bash +earthly -P +test +``` diff --git a/catalyst-gateway/tests/schema-mismatch/docker-compose.yml b/catalyst-gateway/tests/schema-mismatch/docker-compose.yml new file mode 100644 index 0000000000..d06aa36dd3 --- /dev/null +++ b/catalyst-gateway/tests/schema-mismatch/docker-compose.yml @@ -0,0 +1,35 @@ +version: "3" + +services: + event-db: + image: event-db:latest + environment: + # Required environment variables for migrations + - DB_HOST=localhost + - DB_PORT=5432 + - DB_NAME=CatalystEventDev + - DB_DESCRIPTION="Catalyst Event DB" + - DB_SUPERUSER=postgres + - DB_SUPERUSER_PASSWORD=postgres + - DB_USER=catalyst-event-dev + - DB_USER_PASSWORD=CHANGE_ME + + - INIT_AND_DROP_DB=true + - WITH_MIGRATIONS=true + - WITH_SEED_DATA=true + ports: + - 5432:5432 + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $${DB_SUPERUSER} -d $${DB_SUPERUSER_PASSWORD}"] + interval: 10s + timeout: 5s + retries: 10 + + cat-gateway: + image: cat-gateway:latest + hostname: gateway + ports: + - 3030:3030 + depends_on: + event-db: + condition: service_healthy diff --git a/catalyst-gateway/tests/schema-mismatch/poetry.lock b/catalyst-gateway/tests/schema-mismatch/poetry.lock new file mode 100644 index 0000000000..602b20b5ed --- /dev/null +++ b/catalyst-gateway/tests/schema-mismatch/poetry.lock @@ -0,0 +1,187 @@ +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. + +[[package]] +name = "async-timeout" +version = "4.0.3" +description = "Timeout context manager for asyncio programs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, + {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, +] + +[[package]] +name = "asyncio" +version = "3.4.3" +description = "reference implementation of PEP 3156" +optional = false +python-versions = "*" +files = [ + {file = "asyncio-3.4.3-cp33-none-win32.whl", hash = "sha256:b62c9157d36187eca799c378e572c969f0da87cd5fc42ca372d92cdb06e7e1de"}, + {file = "asyncio-3.4.3-cp33-none-win_amd64.whl", hash = "sha256:c46a87b48213d7464f22d9a497b9eef8c1928b68320a2fa94240f969f6fec08c"}, + {file = "asyncio-3.4.3-py3-none-any.whl", hash = "sha256:c4d18b22701821de07bd6aea8b53d21449ec0ec5680645e5317062ea21817d2d"}, + {file = "asyncio-3.4.3.tar.gz", hash = "sha256:83360ff8bc97980e4ff25c964c7bd3923d333d177aa4f7fb736b019f26c7cb41"}, +] + +[[package]] +name = "asyncpg" +version = "0.29.0" +description = "An asyncio PostgreSQL driver" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "asyncpg-0.29.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72fd0ef9f00aeed37179c62282a3d14262dbbafb74ec0ba16e1b1864d8a12169"}, + {file = "asyncpg-0.29.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52e8f8f9ff6e21f9b39ca9f8e3e33a5fcdceaf5667a8c5c32bee158e313be385"}, + {file = "asyncpg-0.29.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e6823a7012be8b68301342ba33b4740e5a166f6bbda0aee32bc01638491a22"}, + {file = "asyncpg-0.29.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:746e80d83ad5d5464cfbf94315eb6744222ab00aa4e522b704322fb182b83610"}, + {file = "asyncpg-0.29.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ff8e8109cd6a46ff852a5e6bab8b0a047d7ea42fcb7ca5ae6eaae97d8eacf397"}, + {file = "asyncpg-0.29.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:97eb024685b1d7e72b1972863de527c11ff87960837919dac6e34754768098eb"}, + {file = "asyncpg-0.29.0-cp310-cp310-win32.whl", hash = "sha256:5bbb7f2cafd8d1fa3e65431833de2642f4b2124be61a449fa064e1a08d27e449"}, + {file = "asyncpg-0.29.0-cp310-cp310-win_amd64.whl", hash = "sha256:76c3ac6530904838a4b650b2880f8e7af938ee049e769ec2fba7cd66469d7772"}, + {file = "asyncpg-0.29.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4900ee08e85af01adb207519bb4e14b1cae8fd21e0ccf80fac6aa60b6da37b4"}, + {file = "asyncpg-0.29.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a65c1dcd820d5aea7c7d82a3fdcb70e096f8f70d1a8bf93eb458e49bfad036ac"}, + {file = "asyncpg-0.29.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b52e46f165585fd6af4863f268566668407c76b2c72d366bb8b522fa66f1870"}, + {file = "asyncpg-0.29.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc600ee8ef3dd38b8d67421359779f8ccec30b463e7aec7ed481c8346decf99f"}, + {file = "asyncpg-0.29.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:039a261af4f38f949095e1e780bae84a25ffe3e370175193174eb08d3cecab23"}, + {file = "asyncpg-0.29.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6feaf2d8f9138d190e5ec4390c1715c3e87b37715cd69b2c3dfca616134efd2b"}, + {file = "asyncpg-0.29.0-cp311-cp311-win32.whl", hash = "sha256:1e186427c88225ef730555f5fdda6c1812daa884064bfe6bc462fd3a71c4b675"}, + {file = "asyncpg-0.29.0-cp311-cp311-win_amd64.whl", hash = "sha256:cfe73ffae35f518cfd6e4e5f5abb2618ceb5ef02a2365ce64f132601000587d3"}, + {file = "asyncpg-0.29.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6011b0dc29886ab424dc042bf9eeb507670a3b40aece3439944006aafe023178"}, + {file = "asyncpg-0.29.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b544ffc66b039d5ec5a7454667f855f7fec08e0dfaf5a5490dfafbb7abbd2cfb"}, + {file = "asyncpg-0.29.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d84156d5fb530b06c493f9e7635aa18f518fa1d1395ef240d211cb563c4e2364"}, + {file = "asyncpg-0.29.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54858bc25b49d1114178d65a88e48ad50cb2b6f3e475caa0f0c092d5f527c106"}, + {file = "asyncpg-0.29.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bde17a1861cf10d5afce80a36fca736a86769ab3579532c03e45f83ba8a09c59"}, + {file = "asyncpg-0.29.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:37a2ec1b9ff88d8773d3eb6d3784dc7e3fee7756a5317b67f923172a4748a175"}, + {file = "asyncpg-0.29.0-cp312-cp312-win32.whl", hash = "sha256:bb1292d9fad43112a85e98ecdc2e051602bce97c199920586be83254d9dafc02"}, + {file = "asyncpg-0.29.0-cp312-cp312-win_amd64.whl", hash = "sha256:2245be8ec5047a605e0b454c894e54bf2ec787ac04b1cb7e0d3c67aa1e32f0fe"}, + {file = "asyncpg-0.29.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0009a300cae37b8c525e5b449233d59cd9868fd35431abc470a3e364d2b85cb9"}, + {file = "asyncpg-0.29.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cad1324dbb33f3ca0cd2074d5114354ed3be2b94d48ddfd88af75ebda7c43cc"}, + {file = "asyncpg-0.29.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:012d01df61e009015944ac7543d6ee30c2dc1eb2f6b10b62a3f598beb6531548"}, + {file = "asyncpg-0.29.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000c996c53c04770798053e1730d34e30cb645ad95a63265aec82da9093d88e7"}, + {file = "asyncpg-0.29.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e0bfe9c4d3429706cf70d3249089de14d6a01192d617e9093a8e941fea8ee775"}, + {file = "asyncpg-0.29.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:642a36eb41b6313ffa328e8a5c5c2b5bea6ee138546c9c3cf1bffaad8ee36dd9"}, + {file = "asyncpg-0.29.0-cp38-cp38-win32.whl", hash = "sha256:a921372bbd0aa3a5822dd0409da61b4cd50df89ae85150149f8c119f23e8c408"}, + {file = "asyncpg-0.29.0-cp38-cp38-win_amd64.whl", hash = "sha256:103aad2b92d1506700cbf51cd8bb5441e7e72e87a7b3a2ca4e32c840f051a6a3"}, + {file = "asyncpg-0.29.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5340dd515d7e52f4c11ada32171d87c05570479dc01dc66d03ee3e150fb695da"}, + {file = "asyncpg-0.29.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e17b52c6cf83e170d3d865571ba574577ab8e533e7361a2b8ce6157d02c665d3"}, + {file = "asyncpg-0.29.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f100d23f273555f4b19b74a96840aa27b85e99ba4b1f18d4ebff0734e78dc090"}, + {file = "asyncpg-0.29.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48e7c58b516057126b363cec8ca02b804644fd012ef8e6c7e23386b7d5e6ce83"}, + {file = "asyncpg-0.29.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f9ea3f24eb4c49a615573724d88a48bd1b7821c890c2effe04f05382ed9e8810"}, + {file = "asyncpg-0.29.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8d36c7f14a22ec9e928f15f92a48207546ffe68bc412f3be718eedccdf10dc5c"}, + {file = "asyncpg-0.29.0-cp39-cp39-win32.whl", hash = "sha256:797ab8123ebaed304a1fad4d7576d5376c3a006a4100380fb9d517f0b59c1ab2"}, + {file = "asyncpg-0.29.0-cp39-cp39-win_amd64.whl", hash = "sha256:cce08a178858b426ae1aa8409b5cc171def45d4293626e7aa6510696d46decd8"}, + {file = "asyncpg-0.29.0.tar.gz", hash = "sha256:d1c49e1f44fffafd9a55e1a9b101590859d881d639ea2922516f5d9c512d354e"}, +] + +[package.dependencies] +async-timeout = {version = ">=4.0.3", markers = "python_version < \"3.12.0\""} + +[package.extras] +docs = ["Sphinx (>=5.3.0,<5.4.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] +test = ["flake8 (>=6.1,<7.0)", "uvloop (>=0.15.3)"] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "loguru" +version = "0.7.2" +description = "Python logging made (stupidly) simple" +optional = false +python-versions = ">=3.5" +files = [ + {file = "loguru-0.7.2-py3-none-any.whl", hash = "sha256:003d71e3d3ed35f0f8984898359d65b79e5b21943f78af86aa5491210429b8eb"}, + {file = "loguru-0.7.2.tar.gz", hash = "sha256:e671a53522515f34fd406340ee968cb9ecafbc4b36c679da03c18fd8d0bd51ac"}, +] + +[package.dependencies] +colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} +win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} + +[package.extras] +dev = ["Sphinx (==7.2.5)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.2.2)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.4.1)", "mypy (==v1.5.1)", "pre-commit (==3.4.0)", "pytest (==6.1.2)", "pytest (==7.4.0)", "pytest-cov (==2.12.1)", "pytest-cov (==4.1.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.0.0)", "sphinx-autobuild (==2021.3.14)", "sphinx-rtd-theme (==1.3.0)", "tox (==3.27.1)", "tox (==4.11.0)"] + +[[package]] +name = "packaging" +version = "23.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + +[[package]] +name = "pluggy" +version = "1.4.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pytest" +version = "8.0.0" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-8.0.0-py3-none-any.whl", hash = "sha256:50fb9cbe836c3f20f0dfa99c565201fb75dc54c8d76373cd1bde06b06657bdb6"}, + {file = "pytest-8.0.0.tar.gz", hash = "sha256:249b1b0864530ba251b7438274c4d251c58d868edaaec8762893ad4a0d71c36c"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=1.3.0,<2.0" + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "win32-setctime" +version = "1.1.0" +description = "A small Python utility to set file creation time on Windows" +optional = false +python-versions = ">=3.5" +files = [ + {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"}, + {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"}, +] + +[package.extras] +dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.11" +content-hash = "0d40ff719d469e1d1a46d68029593cc014ddec56d9ffd018f732f14711867815" diff --git a/catalyst-gateway/tests/schema-mismatch/pyproject.toml b/catalyst-gateway/tests/schema-mismatch/pyproject.toml new file mode 100644 index 0000000000..8b7c2f8199 --- /dev/null +++ b/catalyst-gateway/tests/schema-mismatch/pyproject.toml @@ -0,0 +1,18 @@ +[tool.poetry] +name = "schema-mismatch" +version = "0.1.0" +description = "" +authors = ["Joaquín Rosales "] +readme = "README.md" +license = "MIT or Apache-2.0" + +[tool.poetry.dependencies] +python = "^3.11" +loguru = "^0.7.2" +asyncio = "^3.4.3" +asyncpg = "^0.29.0" +pytest = "^8.0.0" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/catalyst-gateway/tests/schema-mismatch/schema_mismatch/__init__.py b/catalyst-gateway/tests/schema-mismatch/schema_mismatch/__init__.py new file mode 100644 index 0000000000..0924f6b63c --- /dev/null +++ b/catalyst-gateway/tests/schema-mismatch/schema_mismatch/__init__.py @@ -0,0 +1,45 @@ +"""Utilities for testing schema mismatch behavior.""" + +import asyncio +import asyncpg +import http.client + +GET_VERSION_QUERY = "SELECT MAX(version) FROM refinery_schema_history" +UPDATE_QUERY = "UPDATE refinery_schema_history SET version=$1 WHERE version=$2" + +DB_URL="postgres://catalyst-event-dev:CHANGE_ME@event-db/CatalystEventDev" +DEFAULT_TIMEOUT: int = 10 +HOST = "gateway" +PORT = 3030 + +def call_api_url(method, endpoint, *args, **kwargs): + client = http.client.HTTPConnection(HOST, PORT, timeout=DEFAULT_TIMEOUT) + client.request(method, endpoint) + resp = client.getresponse() + client.close() + return resp + +def fetch_schema_version(): + async def get_current_version(): + conn = await asyncpg.connect(DB_URL) + if conn is None: + raise Exception("no db connection found") + + version = await conn.fetchval(GET_VERSION_QUERY) + if version is None: + raise Exception("failed to fetch version from db") + return version + + return asyncio.run(get_current_version()) + +def change_version(from_value: int, change_to: int): + async def change_schema_version(): + conn = await asyncpg.connect(DB_URL) + if conn is None: + raise Exception("no db connection found for") + + update = await conn.execute(UPDATE_QUERY, change_to, from_value) + if update is None: + raise Exception("failed to fetch version from db") + + return asyncio.run(change_schema_version()) diff --git a/catalyst-gateway/tests/schema-mismatch/schema_mismatch/test_schema_mismatch_behavior.py b/catalyst-gateway/tests/schema-mismatch/schema_mismatch/test_schema_mismatch_behavior.py new file mode 100644 index 0000000000..00815b4d4d --- /dev/null +++ b/catalyst-gateway/tests/schema-mismatch/schema_mismatch/test_schema_mismatch_behavior.py @@ -0,0 +1,58 @@ +"""Test the `catalyst-gateway` service when a DB schema mismatch occurs.""" +from loguru import logger + +from schema_mismatch import call_api_url, fetch_schema_version, change_version + +def check_is_live(): + resp = call_api_url("GET", "/api/health/live") + assert resp.status == 204 + logger.info("cat-gateway service is LIVE.") + +def check_is_ready(): + resp = call_api_url("GET", "/api/health/ready") + assert resp.status == 204 + logger.info("cat-gateway service is READY.") + +def check_is_not_ready(): + resp = call_api_url("GET", "/api/health/ready") + assert resp.status == 503 + logger.info("cat-gateway service is NOT READY.") + +def test_schema_version_mismatch_changes_cat_gateway_behavior(): + # Check that the `live` endpoint is OK + check_is_live() + + # Check that the `ready` endpoint is OK + check_is_ready() + + # Fetch current schema version from DB + initial_version = fetch_schema_version() + logger.info(f"cat-gateway schema version is: {initial_version}.") + changed_version = initial_version + 1 + + # Change version to a new value + change_version(initial_version, changed_version) + logger.info("Changed schema version in DB") + + # Fetch current schema version from DB + current_version = fetch_schema_version() + assert current_version == changed_version + logger.info(f"cat-gateway schema version is: {changed_version}.") + + # Check that the `live` endpoint is OK + check_is_live() + + # Check that the `ready` endpoint is NOT OK + check_is_not_ready() + + # Change version back + change_version(changed_version, initial_version) + logger.info("Changed schema version back to original in DB") + + # Fetch current schema version from DB + current_version = fetch_schema_version() + assert current_version == initial_version + logger.info(f"cat-gateway schema version is: {changed_version}.") + + # Check that the `ready` endpoint is OK + check_is_ready()