diff --git a/test/cql-pytest/rest_api.py b/test/cql-pytest/rest_api.py index d768dc46c6..d2d3d571b4 100644 --- a/test/cql-pytest/rest_api.py +++ b/test/cql-pytest/rest_api.py @@ -9,8 +9,9 @@ import requests import nodetool import pytest +from contextlib import contextmanager -# Sends GET request to REST API. Response is restured as JSON. +# Sends GET request to REST API. Response is returned as JSON. # If API isn't available, `pytest.skip()` is called. def get_request(cql, *path): if nodetool.has_rest_api(cql): @@ -19,6 +20,31 @@ def get_request(cql, *path): else: pytest.skip("REST API not available") +# Sends POST request to REST API. Response is returned as JSON or None +# if the response body was empty (this is typical). +# If API isn't available, `pytest.skip()` is called. +def post_request(cql, *path): + if nodetool.has_rest_api(cql): + response = requests.post(f"{nodetool.rest_api_url(cql)}/{'/'.join(path)}") + if not response.text: + return None + return response.json() + else: + pytest.skip("REST API not available") + +# Sends DELETE request to REST API. Response is returned as JSON or None +# if the response body was empty (this is typical). +# If API isn't available, `pytest.skip()` is called. +def delete_request(cql, *path): + if nodetool.has_rest_api(cql): + response = requests.delete(f"{nodetool.rest_api_url(cql)}/{'/'.join(path)}") + if not response.text: + return None + return response.json() + else: + pytest.skip("REST API not available") + + # Get column family's metric. # metric - name of matric # table - (optional) column family name to add to request's path @@ -29,4 +55,24 @@ def get_column_family_metric(cql, metric, table=None): ks, cf = table.split('.') args.append(f"{ks}:{cf}") - return get_request(cql, *args) \ No newline at end of file + return get_request(cql, *args) + +# scylla_inject_error() is a context manager, running a block of code with +# the given error injection enabled - and automatically disabling the +# injection when the block exits. +# This error-injection feature uses Scylla's REST API, so it only works on +# Scylla. Also, only works in specific build modes (dev, debug, sanitize). +# When Cassandra or non-supporting build of Scylla is being tested, using +# this function will cause the calling test to be skipped. +@contextmanager +def scylla_inject_error(cql, err, one_shot=False): + post_request(cql, f'v2/error_injection/injection/{err}?one_shot={one_shot}') + response = get_request(cql, f'v2/error_injection/injection') + print("Enabled error injections:", response) + if not err in response: + pytest.skip("Error injection not enabled in Scylla - try compiling in dev/debug/sanitize mode") + try: + yield + finally: + print("Disabling error injection", err) + delete_request(cql, f'v2/error_injection/injection/{err}')