diff --git a/Makefile b/Makefile index 3c1f01f..1f69f0f 100644 --- a/Makefile +++ b/Makefile @@ -78,3 +78,10 @@ generate: tools ${OPENAPI_SPEC} ## Generate the Horreum client set -e ;\ ${PROJECT_BIN}/kiota generate -l python -c HorreumRawClient -n raw_client -d ${OPENAPI_PATH}/openapi.yaml -o ${GENERATED_CLIENT_PATH} ;\ } + + +##@ Example + +.PHONY: run-example +run-example: ## Run basic example + cd examples && python basic_example.py diff --git a/examples/basic_example.py b/examples/basic_example.py new file mode 100644 index 0000000..1102a56 --- /dev/null +++ b/examples/basic_example.py @@ -0,0 +1,134 @@ +import asyncio +import json + +from kiota_abstractions.base_request_configuration import RequestConfiguration + +from horreum import new_horreum_client +from horreum.horreum_client import HorreumClient +from horreum.raw_client.models.extractor import Extractor +from horreum.raw_client.models.run import Run +from horreum.raw_client.models.schema import Schema +from horreum.raw_client.models.test import Test +from horreum.raw_client.models.transformer import Transformer +from horreum.raw_client.api.run.test.test_request_builder import TestRequestBuilder + +base_url = "http://localhost:8080" +username = "user" +password = "secret" + +cleanup_data = True + + +async def create_schema(client: HorreumClient, data_path: str) -> int: + print(f"creating schema from {data_path}") + schema_data = json.load(open(data_path), object_hook=lambda d: Schema(**d)) + print(schema_data) + + schema_id = await client.raw_client.api.schema.post(schema_data) + assert schema_id > 0 + return schema_id + + +async def create_schema_transformers(client: HorreumClient, schema_id: int, data_path: str, + extractors_data_path: str) -> int: + print(f"creating transformer from {data_path}") + transformer_data = json.load(open(data_path), object_hook=lambda d: Transformer(**d)) + print(transformer_data) + + print(f"creating extractors from {extractors_data_path}") + extractors_data = json.load(open(extractors_data_path), + object_hook=lambda d: Extractor(**d)) + print(extractors_data) + + transformer_data.extractors = extractors_data + + transformer_id = await client.raw_client.api.schema.by_id_id(schema_id).transformers.post(transformer_data) + assert transformer_id > 0 + return transformer_id + + +async def create_test(client: HorreumClient, data_path: str) -> Test: + print(f"creating test from {data_path}") + + test_data = json.load(open(data_path), object_hook=lambda d: Test(**d)) + print(test_data) + + test = await client.raw_client.api.test.post(test_data) + assert test.id > 0 + return test + + +async def set_test_transformers(client: HorreumClient, test_id: int, transformers: list[int]): + await client.raw_client.api.test.by_id(test_id).transformers.post(transformers) + + +async def upload_run(client: HorreumClient, test_id: int, run_path: str, run_data_path: str): + print(f"uploading run from {run_path}") + + run = json.load(open(run_path), object_hook=lambda d: Run(**d)) + run_data = json.load(open(run_data_path)) + run.data = json.dumps(run_data) + print(run) + + query_params = TestRequestBuilder.TestRequestBuilderPostQueryParameters(test=str(test_id)) + config = RequestConfiguration(query_parameters=query_params) + await client.raw_client.api.run.test.post(run, config) + + +async def setup_roadrunner_test(client: HorreumClient): + print("creating roadrunner test") + + acme_benchmark_schema_id = await create_schema(client, "./data/acme_benchmark_schema.json") + acme_horreum_schema_id = await create_schema(client, "./data/acme_horreum_schema.json") + + acme_transformers_id = await create_schema_transformers(client, acme_benchmark_schema_id, + "./data/acme_transformer.json", + "./data/acme_transformer_extractors.json") + + roadrunner_test = await create_test(client, "./data/roadrunner_test.json") + await set_test_transformers(client, roadrunner_test.id, [acme_transformers_id]) + + await upload_run(client, roadrunner_test.id, "./data/roadrunner_run.json", "./data/roadrunner_run_data.json") + + +async def delete_all(client: HorreumClient): + """ cleanup all Horreum data """ + + print("cleaning up tests") + get_tests = await client.raw_client.api.test.get() + for t in get_tests.tests: + await client.raw_client.api.test.by_id(t.id).delete() + + get_tests = await client.raw_client.api.test.get() + assert get_tests.count == 0 + + print("cleaning up schemas") + get_schemas = await client.raw_client.api.schema.get() + for s in get_schemas.schemas: + await client.raw_client.api.schema.by_id_id(s.id).delete() + + get_schemas = await client.raw_client.api.schema.get() + assert get_schemas.count == 0 + + +async def example(): + client = await new_horreum_client(base_url, username, password) + + if cleanup_data: + await delete_all(client) + + await setup_roadrunner_test(client) + + # check data is properly injected in the server + get_schemas = await client.raw_client.api.schema.get() + assert get_schemas.count == 2 + + get_tests = await client.raw_client.api.test.get() + assert get_tests.count == 1 + + get_runs = await client.raw_client.api.run.list_.get() + assert get_runs.total == 1 + + +if __name__ == '__main__': + asyncio.run(example()) diff --git a/examples/data/acme_benchmark_schema.json b/examples/data/acme_benchmark_schema.json new file mode 100644 index 0000000..d7e4751 --- /dev/null +++ b/examples/data/acme_benchmark_schema.json @@ -0,0 +1,7 @@ +{ + "name": "ACME Benchmark Schema", + "description": "Data produced by benchmarking tool", + "owner": "dev-team", + "access": "PUBLIC", + "uri": "urn:acme:benchmark:0.1" +} \ No newline at end of file diff --git a/examples/data/acme_horreum_schema.json b/examples/data/acme_horreum_schema.json new file mode 100644 index 0000000..b7b9aca --- /dev/null +++ b/examples/data/acme_horreum_schema.json @@ -0,0 +1,7 @@ +{ + "name": "ACME Horreum Schema", + "description": "Used in Datasets", + "owner": "dev-team", + "access": "PUBLIC", + "uri": "urn:acme:horreum:0.1" +} \ No newline at end of file diff --git a/examples/data/acme_transformer.json b/examples/data/acme_transformer.json new file mode 100644 index 0000000..6091761 --- /dev/null +++ b/examples/data/acme_transformer.json @@ -0,0 +1,8 @@ +{ + "name": "Acme Transformer", + "description": "Transformer for converting complex runs into individual datasets", + "owner": "dev-team", + "access": "PUBLIC", + "target_schema_uri": "urn:acme:horreum:0.1", + "function": "({results, hash}) => results.map(r => ({ ...r, hash }))" +} \ No newline at end of file diff --git a/examples/data/acme_transformer_extractors.json b/examples/data/acme_transformer_extractors.json new file mode 100644 index 0000000..e7acf2b --- /dev/null +++ b/examples/data/acme_transformer_extractors.json @@ -0,0 +1,12 @@ +[ + { + "name": "hash", + "jsonpath": "$.buildHash", + "isarray": false + }, + { + "name": "results", + "jsonpath": "$.results", + "isarray": false + } +] \ No newline at end of file diff --git a/examples/data/hyperfoil_schema.json b/examples/data/hyperfoil_schema.json new file mode 100644 index 0000000..0c008a4 --- /dev/null +++ b/examples/data/hyperfoil_schema.json @@ -0,0 +1,7 @@ +{ + "name": "Hyperfoil", + "description": "Results from Hyperfoil benchmark", + "owner": "dev-team", + "access": "PUBLIC", + "uri": "http://hyperfoil.io/run-schema/v3.0" +} \ No newline at end of file diff --git a/examples/data/protected_test.json b/examples/data/protected_test.json new file mode 100644 index 0000000..ad35fd4 --- /dev/null +++ b/examples/data/protected_test.json @@ -0,0 +1,7 @@ +{ + "name": "Protected test", + "description": "You should see this only when logged in", + "owner": "dev-team", + "access": "PROTECTED", + "datastore_id": 11 +} \ No newline at end of file diff --git a/examples/data/roadrunner_run.json b/examples/data/roadrunner_run.json new file mode 100644 index 0000000..97eb531 --- /dev/null +++ b/examples/data/roadrunner_run.json @@ -0,0 +1,7 @@ +{ + "description": "Example run of Roadrunner", + "owner": "dev-team", + "access": "PUBLIC", + "start": 1669388931000, + "stop": 1669388932000 +} \ No newline at end of file diff --git a/examples/data/roadrunner_run_data.json b/examples/data/roadrunner_run_data.json new file mode 100644 index 0000000..a109d68 --- /dev/null +++ b/examples/data/roadrunner_run_data.json @@ -0,0 +1,17 @@ +{ + "$schema": "urn:acme:benchmark:0.1", + "something": "This gets lost by the transformer", + "buildHash": "defec8eddeadbeafcafebabeb16b00b5", + "results": [ + { + "test": "Foo", + "requests": 123, + "duration": 10 + }, + { + "test": "Bar", + "requests": 456, + "duration": 20 + } + ] +} \ No newline at end of file diff --git a/examples/data/roadrunner_test.json b/examples/data/roadrunner_test.json new file mode 100644 index 0000000..af3d8b7 --- /dev/null +++ b/examples/data/roadrunner_test.json @@ -0,0 +1,7 @@ +{ + "name": "Roadrunner Test", + "description": "acme.com benchmark", + "owner": "dev-team", + "access": "PUBLIC", + "fingerprint_labels": [ "benchmark_test" ] +} \ No newline at end of file diff --git a/examples/data/roadrunner_variables.json b/examples/data/roadrunner_variables.json new file mode 100644 index 0000000..1f60cb0 --- /dev/null +++ b/examples/data/roadrunner_variables.json @@ -0,0 +1,11 @@ +[ + { + "name": "throughput", + "labels": [ "throughput" ], + "changeDetection": [ + { + "model": "relativeDifference" + } + ] + } +] \ No newline at end of file diff --git a/examples/data/roadrunner_view.json b/examples/data/roadrunner_view.json new file mode 100644 index 0000000..a9c03d2 --- /dev/null +++ b/examples/data/roadrunner_view.json @@ -0,0 +1,16 @@ +{ + "name": "Default", + "components": [ + { + "headerOrder": 1, + "headerName": "Test", + "labels": [ "benchmark_test" ] + }, + { + "headerOrder": 1, + "headerName": "Throughput", + "labels": [ "throughput" ], + "render": "value => value + \"req/s\"" + } + ] +} \ No newline at end of file