From 69baf26b8d77f4b07b6ac0c153706b1a9a0e374f Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Sun, 27 Apr 2025 17:37:17 +0200 Subject: [PATCH 01/19] Add v3.2 smoke test updates --- smoke-release-testing/mgconsole/indices.bash | 3 +++ 1 file changed, 3 insertions(+) diff --git a/smoke-release-testing/mgconsole/indices.bash b/smoke-release-testing/mgconsole/indices.bash index 801e1ddbc..5941a22e7 100755 --- a/smoke-release-testing/mgconsole/indices.bash +++ b/smoke-release-testing/mgconsole/indices.bash @@ -11,3 +11,6 @@ test_composite_indices() { echo "CREATE (:Label {prop1:0, prop2: 1});" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port echo "EXPLAIN MATCH (n:Label {prop1:0, prop2: 1}) RETURN n;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port | grep -E "ScanAllByLabelProperties \(n :Label \{prop1, prop2\}\)" } + +test_nested_indices() { +} From d3666dacb78dd5b91057cb38925de7bee6d1b33f Mon Sep 17 00:00:00 2001 From: antejavor Date: Fri, 6 Jun 2025 11:20:32 +0200 Subject: [PATCH 02/19] add nested indices --- smoke-release-testing/experiment.bash | 2 +- smoke-release-testing/mgconsole/indices.bash | 10 ++++++++++ smoke-release-testing/test.bash | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/smoke-release-testing/experiment.bash b/smoke-release-testing/experiment.bash index 634fe1a42..0ef96253d 100755 --- a/smoke-release-testing/experiment.bash +++ b/smoke-release-testing/experiment.bash @@ -11,7 +11,7 @@ wait_for_memgraph $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT echo "Memgraph is up and running!" source ./mgconsole/multi_tenancy.bash -test_multi_tenancy $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT +test_nested_indices $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT # NOTE: Test what's the exit status of the script by using `echo $?`: # * if it's == 0 -> all good diff --git a/smoke-release-testing/mgconsole/indices.bash b/smoke-release-testing/mgconsole/indices.bash index 5941a22e7..6fdee0372 100755 --- a/smoke-release-testing/mgconsole/indices.bash +++ b/smoke-release-testing/mgconsole/indices.bash @@ -13,4 +13,14 @@ test_composite_indices() { } test_nested_indices() { + __host="$1" + __port="$2" + echo "FEATURE: Nested Indices" + + echo "CREATE INDEX ON :Project(delivery.status.due_date);" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port + echo "CREATE (:Project {delivery: {status: {due_date: date('2025-06-04'), milestone: 'v3.14'}}});" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port + + # Assuming the + echo "EXPLAIN MATCH (proj:Project) WHERE proj.delivery.status.due_date = date('2025-06-04') RETURN *;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port | grep -E "ScanAllByLabelProperties" + } diff --git a/smoke-release-testing/test.bash b/smoke-release-testing/test.bash index c779d1256..7205d8bcf 100755 --- a/smoke-release-testing/test.bash +++ b/smoke-release-testing/test.bash @@ -49,6 +49,7 @@ test_edge_type_operations $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT test_composite_indices $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT test_monitoring $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT test_multi_tenancy $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT +#test_nested_indices $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT # NOTE: If the testing container is NOT restarted, all the auth test have to # come after all tests that assume there are no users. test_impersonate_user $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT From d14fa8f3fb18411555a4e53433d91981ce93b6f6 Mon Sep 17 00:00:00 2001 From: antejavor Date: Mon, 9 Jun 2025 10:38:30 +0200 Subject: [PATCH 03/19] Update nested indices --- smoke-release-testing/experiment.bash | 2 +- smoke-release-testing/mgconsole/indices.bash | 2 -- smoke-release-testing/test.bash | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/smoke-release-testing/experiment.bash b/smoke-release-testing/experiment.bash index 0ef96253d..bd7301ed1 100755 --- a/smoke-release-testing/experiment.bash +++ b/smoke-release-testing/experiment.bash @@ -10,7 +10,7 @@ echo "Waiting for memgraph to initialize..." wait_for_memgraph $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT echo "Memgraph is up and running!" -source ./mgconsole/multi_tenancy.bash +source ./mgconsole/indices.bash test_nested_indices $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT # NOTE: Test what's the exit status of the script by using `echo $?`: diff --git a/smoke-release-testing/mgconsole/indices.bash b/smoke-release-testing/mgconsole/indices.bash index 6fdee0372..fd8c1bb10 100755 --- a/smoke-release-testing/mgconsole/indices.bash +++ b/smoke-release-testing/mgconsole/indices.bash @@ -19,8 +19,6 @@ test_nested_indices() { echo "CREATE INDEX ON :Project(delivery.status.due_date);" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port echo "CREATE (:Project {delivery: {status: {due_date: date('2025-06-04'), milestone: 'v3.14'}}});" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port - - # Assuming the echo "EXPLAIN MATCH (proj:Project) WHERE proj.delivery.status.due_date = date('2025-06-04') RETURN *;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port | grep -E "ScanAllByLabelProperties" } diff --git a/smoke-release-testing/test.bash b/smoke-release-testing/test.bash index 7205d8bcf..96e4fcbc2 100755 --- a/smoke-release-testing/test.bash +++ b/smoke-release-testing/test.bash @@ -49,7 +49,7 @@ test_edge_type_operations $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT test_composite_indices $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT test_monitoring $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT test_multi_tenancy $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT -#test_nested_indices $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT +test_nested_indices $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT # NOTE: If the testing container is NOT restarted, all the auth test have to # come after all tests that assume there are no users. test_impersonate_user $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT From 2381df6ef3222d4d20dbb43d92a0403241943875 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Mon, 7 Jul 2025 19:22:56 +0200 Subject: [PATCH 04/19] Delete redundant file --- .../text2cypher/queries_crashing_memgraph_file.cypher | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 smoke-release-testing/text2cypher/queries_crashing_memgraph_file.cypher diff --git a/smoke-release-testing/text2cypher/queries_crashing_memgraph_file.cypher b/smoke-release-testing/text2cypher/queries_crashing_memgraph_file.cypher deleted file mode 100644 index e69de29bb..000000000 From 07532383d0ba4a9c580d915acaed6bbb7e192757 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Mon, 7 Jul 2025 20:54:47 +0200 Subject: [PATCH 05/19] Add edge vector search check --- smoke-release-testing/experiment.bash | 5 ++++- smoke-release-testing/mgconsole/vector_search.bash | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/smoke-release-testing/experiment.bash b/smoke-release-testing/experiment.bash index 5458eaaa5..6daf292a8 100755 --- a/smoke-release-testing/experiment.bash +++ b/smoke-release-testing/experiment.bash @@ -5,7 +5,8 @@ source "$SCRIPT_DIR/utils.bash" # NOTE: Use the below line if you just want to spin up the containers and leave them running. # run_memgraph_docker_containers RC RC # NOTE: Use the below line if you want to cleanup the containers after run of this script. -spinup_and_cleanup_memgraph_dockers none none +# TODO(gitbuda): The below picking of what to download is super error prone -> improve. +spinup_and_cleanup_memgraph_dockers Dockerhub RC echo "Waiting for memgraph to initialize..." wait_for_memgraph $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT echo "Memgraph is up and running!" @@ -14,6 +15,8 @@ source ./mgconsole/indices.bash test_nested_indices $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT source ./mgconsole/regex.bash test_regex $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT +source ./mgconsole/vector_search.bash +test_vector_search $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT # NOTE: Test what's the exit status of the script by using `echo $?`: # * if it's == 0 -> all good diff --git a/smoke-release-testing/mgconsole/vector_search.bash b/smoke-release-testing/mgconsole/vector_search.bash index dd388b8fc..8cf8ec7ec 100755 --- a/smoke-release-testing/mgconsole/vector_search.bash +++ b/smoke-release-testing/mgconsole/vector_search.bash @@ -8,6 +8,8 @@ test_vector_search() { echo "FEATURE: Vector Search" echo "CREATE VECTOR INDEX vsi ON :Label(embedding) WITH CONFIG {\"dimension\":2, \"capacity\": 10};" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port + echo "CREATE VECTOR EDGE INDEX etvsi ON :EdgeType(embedding) WITH CONFIG {\"dimension\": 256, \"capacity\": 1000};" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port + echo "CALL vector_search.show_index_info() YIELD * RETURN *;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port echo "SHOW VECTOR INDEX INFO;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port } From d31e2cf7b951dea5c7cd1ae4e4f1980ec3d06206 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Tue, 8 Jul 2025 13:45:52 +0200 Subject: [PATCH 06/19] Improve the utils script, vector search test is passing --- smoke-release-testing/utils.bash | 34 ++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/smoke-release-testing/utils.bash b/smoke-release-testing/utils.bash index 9c3020196..ef94ba725 100755 --- a/smoke-release-testing/utils.bash +++ b/smoke-release-testing/utils.bash @@ -1,8 +1,6 @@ #!/bin/bash SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -# TODO(gitbuda): Write the helper to fail with a nice error message in the case required env variables are not set. - MEMGRAPH_BUILD_PATH="${MEMGRAPH_BUILD_PATH:-/tmp/memgraph/build}" MEMGRAPH_CONSOLE_BINARY="${MEMGRAPH_CONSOLE_BINARY:-$SCRIPT_DIR/mgconsole.build/build/src/mgconsole}" # Required env vars to define. @@ -15,6 +13,38 @@ MEMGRAPH_NEXT_RC_DIRECT_DOCKER_IMAGE_X86="${MEMGRAPH_NEXT_RC_DIRECT_DOCKER_IMAGE MEMGRAPH_LAST_DOCKERHUB_IMAGE="${MEMGRAPH_LAST_DOCKERHUB_IMAGE:-provide_dockerhub_image_name}" MEMGRAPH_NEXT_DOCKERHUB_IMAGE="${MEMGRAPH_NEXT_DOCKERHUB_IMAGE:-provide_dockerhub_image_name}" +print_help_and_exit_unsuccessfully() { + echo "It's required to define the following environment variables:" + echo " MEMGRAPH_ENTERPRISE_LICENSE" + echo " MEMGRAPH_ORGANIZATION_NAME" + echo " MEMGRAPH_LAST_DOCKERHUB_IMAGE" + echo " MEMGRAPH_NEXT_DOCKERHUB_IMAGE" + echo "Optionally if you want to test daily or RC builds you can define the following environment variables:" + echo " MEMGRAPH_LAST_RC_DIRECT_DOCKER_IMAGE_ARM" + echo " MEMGRAPH_NEXT_RC_DIRECT_DOCKER_IMAGE_ARM" + echo " MEMGRAPH_LAST_RC_DIRECT_DOCKER_IMAGE_X86" + echo " MEMGRAPH_NEXT_RC_DIRECT_DOCKER_IMAGE_X86" + exit 1 +} +check_dockerhub_images() { + if [ "$MEMGRAPH_ENTERPRISE_LICENSE" = "provide_licanse_string" ]; then + print_help_and_exit_unsuccessfully + fi + if [ "$MEMGRAPH_ORGANIZATION_NAME" = "provide_organization_name_string" ]; then + print_help_and_exit_unsuccessfully + fi + if [ "$MEMGRAPH_LAST_DOCKERHUB_IMAGE" = "provide_dockerhub_image_name" ]; then + print_help_and_exit_unsuccessfully + fi + if [ "$MEMGRAPH_NEXT_DOCKERHUB_IMAGE" = "provide_dockerhub_image_name" ]; then + print_help_and_exit_unsuccessfully + fi + echo "License and Docker images validation passed:" + echo " LAST: $MEMGRAPH_LAST_DOCKERHUB_IMAGE" + echo " NEXT: $MEMGRAPH_NEXT_DOCKERHUB_IMAGE" +} +check_dockerhub_images + MEMGRAPH_GENERAL_FLAGS="--telemetry-enabled=false --log-level=TRACE --also-log-to-stderr" MEMGRAPH_ENTERPRISE_DOCKER_ENVS="-e MEMGRAPH_ENTERPRISE_LICENSE=$MEMGRAPH_ENTERPRISE_LICENSE -e MEMGRAPH_ORGANIZATION_NAME=$MEMGRAPH_ORGANIZATION_NAME" MEMGRAPH_DOCKER_MOUNT_VOLUME_FLAGS="-v mg_lib:/var/lib/memgraph" From 15601fe47b277ce5548f6b689965cf3d5421c469 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Tue, 8 Jul 2025 13:54:12 +0200 Subject: [PATCH 07/19] Update the number of query modules --- smoke-release-testing/mgconsole/query_modules.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smoke-release-testing/mgconsole/query_modules.bash b/smoke-release-testing/mgconsole/query_modules.bash index bfd4cea46..ed7160ac2 100755 --- a/smoke-release-testing/mgconsole/query_modules.bash +++ b/smoke-release-testing/mgconsole/query_modules.bash @@ -8,7 +8,7 @@ test_query_modules() { echo "FEATURE: All MAGE query modules" # TODO(gitbuda): What are the 3 added modules? -> Probably the migration modules. - echo "CALL mg.procedures() YIELD * RETURN count(*) AS cnt;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port --output-format=csv | python3 $SCRIPT_DIR/validator.py first_as_int -f cnt -e 309 + echo "CALL mg.procedures() YIELD * RETURN count(*) AS cnt;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port --output-format=csv | python3 $SCRIPT_DIR/validator.py first_as_int -f cnt -e 312 echo "CREATE (a), (b), (c), (d), (a)-[:ET]->(b), (c)-[:ET]->(d);" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port echo "CALL leiden_community_detection.get() YIELD * RETURN communities, community_id, node;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port From 1dcfa95c10bb4794d81e93a5675cf23b2c53c4ab Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Tue, 8 Jul 2025 15:38:15 +0200 Subject: [PATCH 08/19] Add HA smoke tests, just added code to actually run custom memgraph image under HA cluster (WIP) --- smoke-release-testing/experiment.bash | 7 +++---- smoke-release-testing/k8s/run.bash | 23 ++++++++++++++++++----- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/smoke-release-testing/experiment.bash b/smoke-release-testing/experiment.bash index 6daf292a8..463ebf15b 100755 --- a/smoke-release-testing/experiment.bash +++ b/smoke-release-testing/experiment.bash @@ -11,13 +11,12 @@ echo "Waiting for memgraph to initialize..." wait_for_memgraph $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT echo "Memgraph is up and running!" -source ./mgconsole/indices.bash -test_nested_indices $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT -source ./mgconsole/regex.bash -test_regex $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT source ./mgconsole/vector_search.bash test_vector_search $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT +source ./k8s/run.bash +test_k8s_single + # NOTE: Test what's the exit status of the script by using `echo $?`: # * if it's == 0 -> all good # * if it's != 0 -> something went wrong. diff --git a/smoke-release-testing/k8s/run.bash b/smoke-release-testing/k8s/run.bash index 8ef6a55f0..bfa3be049 100755 --- a/smoke-release-testing/k8s/run.bash +++ b/smoke-release-testing/k8s/run.bash @@ -17,12 +17,20 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # * If you want more details or helm dry run just append `--debug` of # `--dry-run`. -test_k8s_single() { - echo "Test k8s single memgraph instance using image: $MEMGRAPH_NEXT_DOCKERHUB_IMAGE" +# TODO(gitbuda): Move under utils. +load_next_image_into_kind() { kind load docker-image $MEMGRAPH_NEXT_DOCKERHUB_IMAGE -n smoke-release-testing MEMGRAPH_NEXT_DOCKERHUB_TAG="${MEMGRAPH_NEXT_DOCKERHUB_IMAGE##*:}" +} + +# TODO(gitbuda): Setup memgraph HA cluster. + +test_k8s_single() { + echo "Test k8s single memgraph instance using image: $MEMGRAPH_NEXT_DOCKERHUB_IMAGE" + load_next_image_into_kind helm install memgraph-single-smoke memgraph/memgraph \ - -f "$SCRIPT_DIR/values-single.yaml" --set "image.tag=$MEMGRAPH_NEXT_DOCKERHUB_TAG" + -f "$SCRIPT_DIR/values-single.yaml" \ + --set "image.tag=$MEMGRAPH_NEXT_DOCKERHUB_TAG" kubectl wait --for=condition=Ready pod/memgraph-single-smoke-0 --timeout=120s kubectl port-forward memgraph-single-smoke-0 17687:7687 & PF_PID=$! @@ -35,12 +43,17 @@ test_k8s_single() { } test_k8s_ha() { + echo "Test k8s HA memgraph cluster using image: $MEMGRAPH_NEXT_DOCKERHUB_IMAGE" + kind load docker-image $MEMGRAPH_NEXT_DOCKERHUB_IMAGE -n smoke-release-testing + MEMGRAPH_NEXT_DOCKERHUB_TAG="${MEMGRAPH_NEXT_DOCKERHUB_IMAGE##*:}" helm install myhadb memgraph/memgraph-high-availability \ --set env.MEMGRAPH_ENTERPRISE_LICENSE=$MEMGRAPH_ENTERPRISE_LICENSE,env.MEMGRAPH_ORGANIZATION_NAME=$MEMGRAPH_ORGANIZATION_NAME \ - -f $SCRIPT_DIR/values-ha.yaml + -f "$SCRIPT_DIR/values-ha.yaml" \ + --set "image.tag=$MEMGRAPH_NEXT_DOCKERHUB_TAG" # TODO(gitbuda): Setup cluster commands + routing + test query. } if [ "${BASH_SOURCE[0]}" -ef "$0" ]; then - test_k8s_single + # NOTE: Developing workflow: download+load required images and define MEMGRAPH_NEXT_DOCKERHUB_IMAGE. + test_k8s_ha fi From 1f2a45e858fbe86e165ee64856d475fe07ef0cb2 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Sat, 12 Jul 2025 21:51:17 +0200 Subject: [PATCH 09/19] Add LAST + NEXT HA helm chart test (cluster was not fully setup yet) --- smoke-release-testing/experiment.bash | 16 +++++++++------- smoke-release-testing/k8s/run.bash | 14 ++++++++++---- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/smoke-release-testing/experiment.bash b/smoke-release-testing/experiment.bash index 463ebf15b..4710e0889 100755 --- a/smoke-release-testing/experiment.bash +++ b/smoke-release-testing/experiment.bash @@ -6,16 +6,18 @@ source "$SCRIPT_DIR/utils.bash" # run_memgraph_docker_containers RC RC # NOTE: Use the below line if you want to cleanup the containers after run of this script. # TODO(gitbuda): The below picking of what to download is super error prone -> improve. -spinup_and_cleanup_memgraph_dockers Dockerhub RC -echo "Waiting for memgraph to initialize..." -wait_for_memgraph $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT -echo "Memgraph is up and running!" +# spinup_and_cleanup_memgraph_dockers Dockerhub Dockerhub +# echo "Waiting for memgraph to initialize..." +# wait_for_memgraph $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT +# echo "Memgraph is up and running!" -source ./mgconsole/vector_search.bash -test_vector_search $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT +# source ./mgconsole/vector_search.bash +# test_vector_search $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT source ./k8s/run.bash -test_k8s_single +# test_k8s_single +test_k8s_ha LAST +test_k8s_ha NEXT # NOTE: Test what's the exit status of the script by using `echo $?`: # * if it's == 0 -> all good diff --git a/smoke-release-testing/k8s/run.bash b/smoke-release-testing/k8s/run.bash index 8c7b1d87d..027d88853 100755 --- a/smoke-release-testing/k8s/run.bash +++ b/smoke-release-testing/k8s/run.bash @@ -42,15 +42,21 @@ test_k8s_single() { helm uninstall memgraph-single-smoke } +# TODO(gitbuda): Here we need memgraph/memgraph because that's what's used under the helm chart... test_k8s_ha() { - echo "Test k8s HA memgraph cluster using image: $MEMGRAPH_NEXT_DOCKERHUB_IMAGE" - kind load docker-image $MEMGRAPH_NEXT_DOCKERHUB_IMAGE -n smoke-release-testing - MEMGRAPH_NEXT_DOCKERHUB_TAG="${MEMGRAPH_NEXT_DOCKERHUB_IMAGE##*:}" + WHICH="$1" + WHICH_TMP="MEMGRAPH_${WHICH}_DOCKERHUB_IMAGE" + WHICH_IMAGE="${!WHICH_TMP}" + echo "Test k8s HA memgraph cluster using image: $WHICH_IMAGE" + kind load docker-image $WHICH_IMAGE -n smoke-release-testing + MEMGRAPH_DOCKERHUB_TAG="${WHICH_IMAGE##*:}" + echo $MEMGRAPH_DOCKERHUB_TAG helm install myhadb memgraph/memgraph-high-availability \ --set env.MEMGRAPH_ENTERPRISE_LICENSE=$MEMGRAPH_ENTERPRISE_LICENSE,env.MEMGRAPH_ORGANIZATION_NAME=$MEMGRAPH_ORGANIZATION_NAME \ -f "$SCRIPT_DIR/values-ha.yaml" \ - --set "image.tag=$MEMGRAPH_NEXT_DOCKERHUB_TAG" + --set "image.tag=$MEMGRAPH_DOCKERHUB_TAG" # TODO(gitbuda): Setup cluster commands + routing + test query. + helm uninstall myhadb } if [ "${BASH_SOURCE[0]}" -ef "$0" ]; then From bf12a29e602d6f9816a2ab3479e7d3d7c95fd535 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Sun, 13 Jul 2025 21:10:39 +0200 Subject: [PATCH 10/19] Add the cluster setup + some init queries, stuck at the same as under https://github.com/memgraph/memgraph/issues/3023 --- smoke-release-testing/experiment.bash | 2 +- smoke-release-testing/k8s/run.bash | 68 +++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/smoke-release-testing/experiment.bash b/smoke-release-testing/experiment.bash index 4710e0889..90cb0ffde 100755 --- a/smoke-release-testing/experiment.bash +++ b/smoke-release-testing/experiment.bash @@ -16,7 +16,7 @@ source "$SCRIPT_DIR/utils.bash" source ./k8s/run.bash # test_k8s_single -test_k8s_ha LAST +# test_k8s_ha LAST test_k8s_ha NEXT # NOTE: Test what's the exit status of the script by using `echo $?`: diff --git a/smoke-release-testing/k8s/run.bash b/smoke-release-testing/k8s/run.bash index 027d88853..750c7cb72 100755 --- a/smoke-release-testing/k8s/run.bash +++ b/smoke-release-testing/k8s/run.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -x SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source "$SCRIPT_DIR/../utils.bash" SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" @@ -16,6 +16,8 @@ export PATH="$(go env GOPATH)/bin:$PATH" # * It takes some time to delete all PVs, check with `kubectl get pv`. # * If you want more details or helm dry run just append `--debug` of # `--dry-run`. +BOLT_SERVER="localhost:10000" # Just tmp value -> each coordinator should have a different value. +# E.g. if kubectl port-foward is used, the configured host values should be passed as `bolt_server`. # TODO(gitbuda): Move under utils. load_next_image_into_kind() { @@ -23,6 +25,52 @@ load_next_image_into_kind() { MEMGRAPH_NEXT_DOCKERHUB_TAG="${MEMGRAPH_NEXT_DOCKERHUB_IMAGE##*:}" } +setup_coordinator_1_query() { + echo "ADD COORDINATOR 1 WITH CONFIG {\"bolt_server\": \"$BOLT_SERVER\", \"management_server\": \"memgraph-coordinator-1.default.svc.cluster.local:10000\", \"coordinator_server\": \"memgraph-coordinator-1.default.svc.cluster.local:12000\"};" | $MEMGRAPH_CONSOLE_BINARY --port 17687 +} +setup_coordinator_2_query() { + echo "ADD COORDINATOR 2 WITH CONFIG {\"bolt_server\": \"$BOLT_SERVER\", \"management_server\": \"memgraph-coordinator-2.default.svc.cluster.local:10000\", \"coordinator_server\": \"memgraph-coordinator-2.default.svc.cluster.local:12000\"};" | $MEMGRAPH_CONSOLE_BINARY --port 17687 +} +setup_coordinator_3_query() { + echo "ADD COORDINATOR 3 WITH CONFIG {\"bolt_server\": \"$BOLT_SERVER\", \"management_server\": \"memgraph-coordinator-3.default.svc.cluster.local:10000\", \"coordinator_server\": \"memgraph-coordinator-3.default.svc.cluster.local:12000\"};" | $MEMGRAPH_CONSOLE_BINARY --port 17687 +} +setup_replica_0() { + echo "REGISTER INSTANCE instance_0 WITH CONFIG {\"bolt_server\": \"$BOLT_SERVER\", \"management_server\": \"memgraph-data-0.default.svc.cluster.local:10000\", \"replication_server\": \"memgraph-data-0.default.svc.cluster.local:20000\"};" | $MEMGRAPH_CONSOLE_BINARY --port 17687 +} +setup_replica_1() { + echo "REGISTER INSTANCE instance_1 WITH CONFIG {\"bolt_server\": \"$BOLT_SERVER\", \"management_server\": \"memgraph-data-1.default.svc.cluster.local:10000\", \"replication_server\": \"memgraph-data-1.default.svc.cluster.local:20000\"};" | $MEMGRAPH_CONSOLE_BINARY --port 17687 +} +setup_main() { + echo "SET INSTANCE instance_0 TO MAIN;" | $MEMGRAPH_CONSOLE_BINARY --port 17687 +} + +setup_cluster() { + kubectl wait --for=condition=Ready pod/memgraph-coordinator-1-0 --timeout=120s + kubectl port-forward memgraph-coordinator-1-0 17687:7687 & + PF_PID=$! + # TODO(gitbuda): wait + memgraph check. + sleep 3 + setup_coordinator_1_query + setup_coordinator_2_query + setup_coordinator_3_query + setup_replica_0 + setup_replica_1 + setup_main + # TODO(gitbuda): make sure this is always executed because the above lines have high chance of failing. + kill $PF_PID + wait $PF_PID 2>/dev/null +} + +execute_query_against_main() { + query="$1" + kubectl port-forward memgraph-data-0-0 17687:7687 & + PF_PID=$! + wait_for_memgraph localhost 17687 + echo "$query" | $MEMGRAPH_CONSOLE_BINARY --port 17687 + kill $PF_PID + wait $PF_PID 2>/dev/null || true +} + # TODO(gitbuda): Setup memgraph HA cluster. test_k8s_single() { @@ -55,11 +103,25 @@ test_k8s_ha() { --set env.MEMGRAPH_ENTERPRISE_LICENSE=$MEMGRAPH_ENTERPRISE_LICENSE,env.MEMGRAPH_ORGANIZATION_NAME=$MEMGRAPH_ORGANIZATION_NAME \ -f "$SCRIPT_DIR/values-ha.yaml" \ --set "image.tag=$MEMGRAPH_DOCKERHUB_TAG" - # TODO(gitbuda): Setup cluster commands + routing + test query. + setup_cluster + execute_query_against_main "CREATE ();" + execute_query_against_main "MATCH (n) RETURN n;" helm uninstall myhadb } if [ "${BASH_SOURCE[0]}" -ef "$0" ]; then + echo "running $0 directly" # NOTE: Developing workflow: download+load required images and define MEMGRAPH_NEXT_DOCKERHUB_IMAGE. - test_k8s_ha + # test_k8s_ha + + # kubectl wait --for=condition=Ready pod/memgraph-coordinator-1-0 --timeout=120s + # kubectl port-forward memgraph-coordinator-1-0 17687:7687 & + # PF_PID=$! + # sleep 2 + # setup_main + # kill $PF_PID + # wait $PF_PID 2>/dev/null + + # execute_query_against_main "CREATE ();" + # execute_query_against_main "MATCH (n) RETURN n;" fi From 3a8e31dd5b8ced9e4bcefa67c7a4b6238f3924c1 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Wed, 16 Jul 2025 15:25:54 +0200 Subject: [PATCH 11/19] Add more/less working version of the upgrade scenario --- smoke-release-testing/k8s/run.bash | 36 ++++++++++++++++++------ smoke-release-testing/k8s/values-ha.yaml | 2 +- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/smoke-release-testing/k8s/run.bash b/smoke-release-testing/k8s/run.bash index 750c7cb72..9bbbe88fa 100755 --- a/smoke-release-testing/k8s/run.bash +++ b/smoke-release-testing/k8s/run.bash @@ -46,10 +46,12 @@ setup_main() { setup_cluster() { kubectl wait --for=condition=Ready pod/memgraph-coordinator-1-0 --timeout=120s + kubectl wait --for=condition=Ready pod/memgraph-coordinator-2-0 --timeout=120s + kubectl wait --for=condition=Ready pod/memgraph-coordinator-3-0 --timeout=120s kubectl port-forward memgraph-coordinator-1-0 17687:7687 & PF_PID=$! # TODO(gitbuda): wait + memgraph check. - sleep 3 + sleep 5 setup_coordinator_1_query setup_coordinator_2_query setup_coordinator_3_query @@ -63,16 +65,16 @@ setup_cluster() { execute_query_against_main() { query="$1" + kubectl wait --for=condition=Ready pod/memgraph-data-0-0 --timeout=120s kubectl port-forward memgraph-data-0-0 17687:7687 & PF_PID=$! wait_for_memgraph localhost 17687 + # TODO: Wait for coordinator OR execute query with timeout (while success loop). echo "$query" | $MEMGRAPH_CONSOLE_BINARY --port 17687 kill $PF_PID wait $PF_PID 2>/dev/null || true } -# TODO(gitbuda): Setup memgraph HA cluster. - test_k8s_single() { echo "Test k8s single memgraph instance using image: $MEMGRAPH_NEXT_DOCKERHUB_IMAGE" load_next_image_into_kind @@ -95,26 +97,42 @@ test_k8s_ha() { WHICH="$1" WHICH_TMP="MEMGRAPH_${WHICH}_DOCKERHUB_IMAGE" WHICH_IMAGE="${!WHICH_TMP}" - echo "Test k8s HA memgraph cluster using image: $WHICH_IMAGE" - kind load docker-image $WHICH_IMAGE -n smoke-release-testing MEMGRAPH_DOCKERHUB_TAG="${WHICH_IMAGE##*:}" - echo $MEMGRAPH_DOCKERHUB_TAG - helm install myhadb memgraph/memgraph-high-availability \ + CHART_PATH="${2:-memgraph/memgraph-high-availability}" + echo "Test k8s HA memgraph cluster using image:" + echo " * image: $WHICH_IMAGE" + echo " * tag: $MEMGRAPH_DOCKERHUB_TAG" + echo " * chart: $CHART_PATH" + + kind load docker-image $WHICH_IMAGE -n smoke-release-testing + helm install myhadb $CHART_PATH \ --set env.MEMGRAPH_ENTERPRISE_LICENSE=$MEMGRAPH_ENTERPRISE_LICENSE,env.MEMGRAPH_ORGANIZATION_NAME=$MEMGRAPH_ORGANIZATION_NAME \ -f "$SCRIPT_DIR/values-ha.yaml" \ --set "image.tag=$MEMGRAPH_DOCKERHUB_TAG" + # TODO(gitbuda): On recovery, this is not required -> skip. setup_cluster + # TODO: The sleep here was because it takes some time to init main -> figure that out. + sleep 5 + # TODO(gitbuda): After recovery, it's uncretain what instance will be MAIN -> figure that out using the query. + # execute_query_against_main "SHOW REPLICATION ROLE;" OR pull from coordinator "SHOW INSTANCES;" + execute_query_against_main "SHOW VERSION;" execute_query_against_main "CREATE ();" execute_query_against_main "MATCH (n) RETURN n;" + # TODO(gitbuda): flag also for this because we want to debug cluster after something fails. helm uninstall myhadb } if [ "${BASH_SOURCE[0]}" -ef "$0" ]; then - echo "running $0 directly" + echo "Running $0 directly..." # NOTE: Developing workflow: download+load required images and define MEMGRAPH_NEXT_DOCKERHUB_IMAGE. - # test_k8s_ha + + # Inject local version of the helm chart because we want to test any local fixes upfront. + # test_k8s_ha LAST + # test_k8s_ha NEXT ~/Workspace/code/memgraph/helm-charts/charts/memgraph-high-availability + test_k8s_ha NEXT # kubectl wait --for=condition=Ready pod/memgraph-coordinator-1-0 --timeout=120s + # kubectl wait --for=condition=Ready pod/memgraph-data-0-0 --timeout=120s # kubectl port-forward memgraph-coordinator-1-0 17687:7687 & # PF_PID=$! # sleep 2 diff --git a/smoke-release-testing/k8s/values-ha.yaml b/smoke-release-testing/k8s/values-ha.yaml index 3478fec81..5de7a9d92 100644 --- a/smoke-release-testing/k8s/values-ha.yaml +++ b/smoke-release-testing/k8s/values-ha.yaml @@ -2,7 +2,7 @@ image: repository: memgraph/memgraph # It is a bad practice to set the image tag name to latest as it can trigger automatic upgrade of the charts # With some of the pullPolicy values. Please consider fixing the tag to a specific Memgraph version - tag: 3.2.1 + tag: 3.4.0 pullPolicy: IfNotPresent env: From f4d7df45e69703c0fd808fb628685fda2a408132 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Wed, 16 Jul 2025 21:28:23 +0200 Subject: [PATCH 12/19] Structure is good -> TODO polish --- smoke-release-testing/k8s/run.bash | 45 +++++++++--------------------- smoke-release-testing/test.bash | 2 ++ smoke-release-testing/utils.bash | 10 ++++++- 3 files changed, 24 insertions(+), 33 deletions(-) diff --git a/smoke-release-testing/k8s/run.bash b/smoke-release-testing/k8s/run.bash index 9bbbe88fa..bd19a6363 100755 --- a/smoke-release-testing/k8s/run.bash +++ b/smoke-release-testing/k8s/run.bash @@ -1,4 +1,4 @@ -#!/bin/bash -x +#!/bin/bash SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source "$SCRIPT_DIR/../utils.bash" SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" @@ -19,12 +19,6 @@ export PATH="$(go env GOPATH)/bin:$PATH" BOLT_SERVER="localhost:10000" # Just tmp value -> each coordinator should have a different value. # E.g. if kubectl port-foward is used, the configured host values should be passed as `bolt_server`. -# TODO(gitbuda): Move under utils. -load_next_image_into_kind() { - kind load docker-image $MEMGRAPH_NEXT_DOCKERHUB_IMAGE -n smoke-release-testing - MEMGRAPH_NEXT_DOCKERHUB_TAG="${MEMGRAPH_NEXT_DOCKERHUB_IMAGE##*:}" -} - setup_coordinator_1_query() { echo "ADD COORDINATOR 1 WITH CONFIG {\"bolt_server\": \"$BOLT_SERVER\", \"management_server\": \"memgraph-coordinator-1.default.svc.cluster.local:10000\", \"coordinator_server\": \"memgraph-coordinator-1.default.svc.cluster.local:12000\"};" | $MEMGRAPH_CONSOLE_BINARY --port 17687 } @@ -45,31 +39,32 @@ setup_main() { } setup_cluster() { - kubectl wait --for=condition=Ready pod/memgraph-coordinator-1-0 --timeout=120s - kubectl wait --for=condition=Ready pod/memgraph-coordinator-2-0 --timeout=120s - kubectl wait --for=condition=Ready pod/memgraph-coordinator-3-0 --timeout=120s + kubectl wait --for=condition=Ready pod -l role=data --timeout=120s + kubectl wait --for=condition=Ready pod -l role=coordinator --timeout=120s + # TODO(gitbuda): The port forward seems flaky -> rerun a few times and make sure it's robust... -> make sure that it's not because of Memgraph failing... kubectl port-forward memgraph-coordinator-1-0 17687:7687 & PF_PID=$! - # TODO(gitbuda): wait + memgraph check. - sleep 5 + wait_for_memgraph_coordinator localhost 17687 setup_coordinator_1_query setup_coordinator_2_query setup_coordinator_3_query setup_replica_0 setup_replica_1 setup_main - # TODO(gitbuda): make sure this is always executed because the above lines have high chance of failing. kill $PF_PID wait $PF_PID 2>/dev/null } execute_query_against_main() { query="$1" + # TODO(gitbuda): Derive what's the main instance. + # TODO: Wait for coordinator OR execute query with timeout (while success loop). + # TODO(gitbuda): After recovery, it's uncretain what instance will be MAIN -> figure that out using the query. + # execute_query_against_main "SHOW REPLICATION ROLE;" OR pull from coordinator "SHOW INSTANCES;" kubectl wait --for=condition=Ready pod/memgraph-data-0-0 --timeout=120s kubectl port-forward memgraph-data-0-0 17687:7687 & PF_PID=$! wait_for_memgraph localhost 17687 - # TODO: Wait for coordinator OR execute query with timeout (while success loop). echo "$query" | $MEMGRAPH_CONSOLE_BINARY --port 17687 kill $PF_PID wait $PF_PID 2>/dev/null || true @@ -77,6 +72,8 @@ execute_query_against_main() { test_k8s_single() { echo "Test k8s single memgraph instance using image: $MEMGRAPH_NEXT_DOCKERHUB_IMAGE" + kind load docker-image $MEMGRAPH_NEXT_DOCKERHUB_IMAGE -n smoke-release-testing + MEMGRAPH_NEXT_DOCKERHUB_TAG="${MEMGRAPH_NEXT_DOCKERHUB_IMAGE##*:}" load_next_image_into_kind helm install memgraph-single-smoke memgraph/memgraph \ -f "$SCRIPT_DIR/values-single.yaml" \ @@ -92,7 +89,6 @@ test_k8s_single() { helm uninstall memgraph-single-smoke } -# TODO(gitbuda): Here we need memgraph/memgraph because that's what's used under the helm chart... test_k8s_ha() { WHICH="$1" WHICH_TMP="MEMGRAPH_${WHICH}_DOCKERHUB_IMAGE" @@ -111,15 +107,12 @@ test_k8s_ha() { --set "image.tag=$MEMGRAPH_DOCKERHUB_TAG" # TODO(gitbuda): On recovery, this is not required -> skip. setup_cluster - # TODO: The sleep here was because it takes some time to init main -> figure that out. - sleep 5 - # TODO(gitbuda): After recovery, it's uncretain what instance will be MAIN -> figure that out using the query. - # execute_query_against_main "SHOW REPLICATION ROLE;" OR pull from coordinator "SHOW INSTANCES;" execute_query_against_main "SHOW VERSION;" execute_query_against_main "CREATE ();" execute_query_against_main "MATCH (n) RETURN n;" - # TODO(gitbuda): flag also for this because we want to debug cluster after something fails. + # TODO(gitbuda): flag also for this because we want to debug cluster after something fails. -> abstract into 2 operations (app & data) and make it optional. helm uninstall myhadb + kubectl delete pvc --all } if [ "${BASH_SOURCE[0]}" -ef "$0" ]; then @@ -130,16 +123,4 @@ if [ "${BASH_SOURCE[0]}" -ef "$0" ]; then # test_k8s_ha LAST # test_k8s_ha NEXT ~/Workspace/code/memgraph/helm-charts/charts/memgraph-high-availability test_k8s_ha NEXT - - # kubectl wait --for=condition=Ready pod/memgraph-coordinator-1-0 --timeout=120s - # kubectl wait --for=condition=Ready pod/memgraph-data-0-0 --timeout=120s - # kubectl port-forward memgraph-coordinator-1-0 17687:7687 & - # PF_PID=$! - # sleep 2 - # setup_main - # kill $PF_PID - # wait $PF_PID 2>/dev/null - - # execute_query_against_main "CREATE ();" - # execute_query_against_main "MATCH (n) RETURN n;" fi diff --git a/smoke-release-testing/test.bash b/smoke-release-testing/test.bash index 17156e7eb..b167475f4 100755 --- a/smoke-release-testing/test.bash +++ b/smoke-release-testing/test.bash @@ -53,3 +53,5 @@ test_impersonate_user $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT # k8s is a special case, because it requires extra setup. source $SCRIPT_DIR/k8s/run.bash test_k8s_single +test_k8s_ha LAST +test_k8s_ha NEXT diff --git a/smoke-release-testing/utils.bash b/smoke-release-testing/utils.bash index ef94ba725..e84ba34b6 100755 --- a/smoke-release-testing/utils.bash +++ b/smoke-release-testing/utils.bash @@ -72,7 +72,15 @@ wait_port() { wait_for_memgraph() { __host=$1 __port=$2 - while ! echo "return 1;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port > /dev/null 2>&1; do + while ! echo "RETURN 1;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port > /dev/null 2>&1; do + sleep 0.1 + done +} + +wait_for_memgraph_coordinator() { + __host=$1 + __port=$2 + while ! echo "SHOW INSTANCE;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port > /dev/null 2>&1; do sleep 0.1 done } From 70f6c48df297cf0242eb84d86dd34a5d4812f2b0 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Thu, 17 Jul 2025 21:34:58 +0200 Subject: [PATCH 13/19] Almost there with the HA upgrade test in terms of polishments --- smoke-release-testing/k8s/run.bash | 116 +++++++++++++++++++---------- smoke-release-testing/reader.py | 35 +++++++++ smoke-release-testing/utils.bash | 38 ++++++++++ 3 files changed, 151 insertions(+), 38 deletions(-) create mode 100644 smoke-release-testing/reader.py diff --git a/smoke-release-testing/k8s/run.bash b/smoke-release-testing/k8s/run.bash index bd19a6363..0fe6b9d20 100755 --- a/smoke-release-testing/k8s/run.bash +++ b/smoke-release-testing/k8s/run.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -x SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source "$SCRIPT_DIR/../utils.bash" SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" @@ -19,50 +19,64 @@ export PATH="$(go env GOPATH)/bin:$PATH" BOLT_SERVER="localhost:10000" # Just tmp value -> each coordinator should have a different value. # E.g. if kubectl port-foward is used, the configured host values should be passed as `bolt_server`. -setup_coordinator_1_query() { - echo "ADD COORDINATOR 1 WITH CONFIG {\"bolt_server\": \"$BOLT_SERVER\", \"management_server\": \"memgraph-coordinator-1.default.svc.cluster.local:10000\", \"coordinator_server\": \"memgraph-coordinator-1.default.svc.cluster.local:12000\"};" | $MEMGRAPH_CONSOLE_BINARY --port 17687 +setup_coordinator() { + local i=$1 + echo "ADD COORDINATOR $i WITH CONFIG {\"bolt_server\": \"$BOLT_SERVER\", \"management_server\": \"memgraph-coordinator-$i.default.svc.cluster.local:10000\", \"coordinator_server\": \"memgraph-coordinator-$i.default.svc.cluster.local:12000\"};" | $MEMGRAPH_CONSOLE_BINARY --port 17687 + echo "coordinator $i DONE" } -setup_coordinator_2_query() { - echo "ADD COORDINATOR 2 WITH CONFIG {\"bolt_server\": \"$BOLT_SERVER\", \"management_server\": \"memgraph-coordinator-2.default.svc.cluster.local:10000\", \"coordinator_server\": \"memgraph-coordinator-2.default.svc.cluster.local:12000\"};" | $MEMGRAPH_CONSOLE_BINARY --port 17687 -} -setup_coordinator_3_query() { - echo "ADD COORDINATOR 3 WITH CONFIG {\"bolt_server\": \"$BOLT_SERVER\", \"management_server\": \"memgraph-coordinator-3.default.svc.cluster.local:10000\", \"coordinator_server\": \"memgraph-coordinator-3.default.svc.cluster.local:12000\"};" | $MEMGRAPH_CONSOLE_BINARY --port 17687 -} -setup_replica_0() { - echo "REGISTER INSTANCE instance_0 WITH CONFIG {\"bolt_server\": \"$BOLT_SERVER\", \"management_server\": \"memgraph-data-0.default.svc.cluster.local:10000\", \"replication_server\": \"memgraph-data-0.default.svc.cluster.local:20000\"};" | $MEMGRAPH_CONSOLE_BINARY --port 17687 -} -setup_replica_1() { - echo "REGISTER INSTANCE instance_1 WITH CONFIG {\"bolt_server\": \"$BOLT_SERVER\", \"management_server\": \"memgraph-data-1.default.svc.cluster.local:10000\", \"replication_server\": \"memgraph-data-1.default.svc.cluster.local:20000\"};" | $MEMGRAPH_CONSOLE_BINARY --port 17687 +setup_replica() { + local i=$1 + echo "REGISTER INSTANCE instance_$i WITH CONFIG {\"bolt_server\": \"$BOLT_SERVER\", \"management_server\": \"memgraph-data-$i.default.svc.cluster.local:10000\", \"replication_server\": \"memgraph-data-$i.default.svc.cluster.local:20000\"};" | $MEMGRAPH_CONSOLE_BINARY --port 17687 + echo "replica $i DONE" } setup_main() { - echo "SET INSTANCE instance_0 TO MAIN;" | $MEMGRAPH_CONSOLE_BINARY --port 17687 + local i=$1 + echo "SET INSTANCE instance_$i TO MAIN;" | $MEMGRAPH_CONSOLE_BINARY --port 17687 + echo "main DONE" } setup_cluster() { - kubectl wait --for=condition=Ready pod -l role=data --timeout=120s kubectl wait --for=condition=Ready pod -l role=coordinator --timeout=120s - # TODO(gitbuda): The port forward seems flaky -> rerun a few times and make sure it's robust... -> make sure that it's not because of Memgraph failing... + kubectl wait --for=condition=Ready pod -l role=data --timeout=120s + kubectl port-forward memgraph-coordinator-1-0 17687:7687 & PF_PID=$! wait_for_memgraph_coordinator localhost 17687 - setup_coordinator_1_query - setup_coordinator_2_query - setup_coordinator_3_query - setup_replica_0 - setup_replica_1 - setup_main + setup_coordinator 1 + setup_coordinator 2 + setup_coordinator 3 + setup_replica 0 + setup_replica 1 + setup_main 0 kill $PF_PID - wait $PF_PID 2>/dev/null + wait $PF_PID 2>/dev/null || true + + # # TODO(gitbuda): The reason for the abstracted code is also that sometimes port-foward fails (again some sync issue). + # # TODO(gitbuda): An attempt to make the code nicer but it still doesn't work -> not all gets executed + there is an infinitely loop. + # with_kubectl_portforward memgraph-coordinator-1-0 17687:7687 -- \ + # wait_for_memgraph_coordinator localhost 17687 && \ + # setup_coordinator 1 && \ + # setup_coordinator 2 && \ + # setup_coordinator 3 && \ + # setup_replica 0 && \ + # setup_main 0 } execute_query_against_main() { query="$1" - # TODO(gitbuda): Derive what's the main instance. - # TODO: Wait for coordinator OR execute query with timeout (while success loop). - # TODO(gitbuda): After recovery, it's uncretain what instance will be MAIN -> figure that out using the query. - # execute_query_against_main "SHOW REPLICATION ROLE;" OR pull from coordinator "SHOW INSTANCES;" - kubectl wait --for=condition=Ready pod/memgraph-data-0-0 --timeout=120s - kubectl port-forward memgraph-data-0-0 17687:7687 & + + # Derive what's the main instance (it's not deterministic where is MAIN after recovery). + kubectl wait --for=condition=Ready pod/memgraph-coordinator-1-0 --timeout=120s + kubectl port-forward memgraph-coordinator-1-0 17687:7687 & + PF_PID=$! + wait_for_memgraph_coordinator localhost 17687 + main_instance=$(echo "SHOW INSTANCES;" | $MEMGRAPH_CONSOLE_BINARY --port 17687 --output-format=csv | python3 $SCRIPT_DIR/../reader.py get_main_parser) + echo "NOTE: MAIN instance is $main_instance" + kill $PF_PID + wait $PF_PID 2>/dev/null || true + + kubectl wait --for=condition=Ready pod/${main_instance}-0 --timeout=120s + kubectl port-forward ${main_instance}-0 17687:7687 & PF_PID=$! wait_for_memgraph localhost 17687 echo "$query" | $MEMGRAPH_CONSOLE_BINARY --port 17687 @@ -89,38 +103,64 @@ test_k8s_single() { helm uninstall memgraph-single-smoke } +test_k8s_help() { + echo "usage: test_k8s_ha LAST|NEXT [-p|--chart-path PATH] [-s|--skip-cluster-setup] [-c|--skip-cleanup] [-h|--help]" + exit 1 +} + test_k8s_ha() { + if [ "$#" -lt 1 ]; then + test_k8s_help + fi WHICH="$1" WHICH_TMP="MEMGRAPH_${WHICH}_DOCKERHUB_IMAGE" WHICH_IMAGE="${!WHICH_TMP}" MEMGRAPH_DOCKERHUB_TAG="${WHICH_IMAGE##*:}" - CHART_PATH="${2:-memgraph/memgraph-high-availability}" + shift + CHART_PATH="memgraph/memgraph-high-availability" + SKIP_CLUSTER_SETUP=false + SKIP_CLEANUP=false + while true; do + case $1 in + -p|--chart-path) CHART_PATH="$2"; shift 2 ;; + -s|--skip-cluster-setup) SKIP_CLUSTER_SETUP=true; shift ;; + -c|--skip-cleanup) SKIP_CLEANUP=true; shift ;; + -h|--help) test_k8s_help; ;; + *) shift; break ;; + esac + done echo "Test k8s HA memgraph cluster using image:" echo " * image: $WHICH_IMAGE" echo " * tag: $MEMGRAPH_DOCKERHUB_TAG" echo " * chart: $CHART_PATH" + echo " * skip cluster setup: $SKIP_CLUSTER_SETUP" + echo " * skip cleanup: $SKIP_CLEANUP" kind load docker-image $WHICH_IMAGE -n smoke-release-testing helm install myhadb $CHART_PATH \ --set env.MEMGRAPH_ENTERPRISE_LICENSE=$MEMGRAPH_ENTERPRISE_LICENSE,env.MEMGRAPH_ORGANIZATION_NAME=$MEMGRAPH_ORGANIZATION_NAME \ -f "$SCRIPT_DIR/values-ha.yaml" \ --set "image.tag=$MEMGRAPH_DOCKERHUB_TAG" - # TODO(gitbuda): On recovery, this is not required -> skip. - setup_cluster + if [ "$SKIP_CLUSTER_SETUP" = false ]; then + setup_cluster + fi execute_query_against_main "SHOW VERSION;" execute_query_against_main "CREATE ();" execute_query_against_main "MATCH (n) RETURN n;" - # TODO(gitbuda): flag also for this because we want to debug cluster after something fails. -> abstract into 2 operations (app & data) and make it optional. + # TODO(gitbuda): Add additional flag for this. helm uninstall myhadb - kubectl delete pvc --all + if [ "$SKIP_CLEANUP" = false ]; then + kubectl delete pvc --all + fi } if [ "${BASH_SOURCE[0]}" -ef "$0" ]; then echo "Running $0 directly..." # NOTE: Developing workflow: download+load required images and define MEMGRAPH_NEXT_DOCKERHUB_IMAGE. - # Inject local version of the helm chart because we want to test any local fixes upfront. - # test_k8s_ha LAST + test_k8s_ha LAST -c # Skip cleanup because we want to recover from existing PVCs. + test_k8s_ha NEXT -s # Skip cluster setup because that should be recovered from PVCs. + + # How to inject local version of the helm chart because we want to test any local fixes upfront. # test_k8s_ha NEXT ~/Workspace/code/memgraph/helm-charts/charts/memgraph-high-availability - test_k8s_ha NEXT fi diff --git a/smoke-release-testing/reader.py b/smoke-release-testing/reader.py new file mode 100644 index 000000000..d4136d64d --- /dev/null +++ b/smoke-release-testing/reader.py @@ -0,0 +1,35 @@ +import sys +import csv +import argparse + + +def read_all_csv_from_stdin(): + return list(csv.DictReader(sys.stdin)) + + +def get_main_parser(data): + main_addr=None + for instance in data: + if instance["role"] == '"main"': + main_addr=instance["management_server"][1:-1].split(".")[0] + print(main_addr) + + +def get_arguments(): + parser = argparse.ArgumentParser( + description="Smoke Tests Validator", + ) + subparsers = parser.add_subparsers( + help="sub-command help", dest="action", required=True + ) + subparsers.add_parser( + "get_main_parser", help="Get main parser" + ) + return parser.parse_args() + + +if __name__ == "__main__": + args = get_arguments() + data = read_all_csv_from_stdin() + if args.action == "get_main_parser": + get_main_parser(data) diff --git a/smoke-release-testing/utils.bash b/smoke-release-testing/utils.bash index e84ba34b6..157412fe0 100755 --- a/smoke-release-testing/utils.bash +++ b/smoke-release-testing/utils.bash @@ -231,3 +231,41 @@ spinup_and_cleanup_memgraph_dockers() { run_memgraph_docker_containers "$__how_to_pull_last" "$__how_to_pull_next" trap cleanup_docker_exit EXIT } + +with_kubectl_portforward() ( + # --- 1. peel off first two required arguments -------------------------- + local target=$1 # svc/foo, pod/bar, deployment/baz, … + local map=$2 # 8080:80 or 8443 or 0.0.0.0:8080:80 + shift 3 # “--” + user commands remain + + # --- 2. launch port-forward in background ------------------------------ + # Send its output to a temp file so we can inspect errors if it dies early + local log + log=$(mktemp) + kubectl port-forward "$target" "$map" >/dev/null 2>>"$log" & + local pf_pid=$! + + # Clean up on normal exit or on signals + cleanup() { + echo "calling port forward cleanup" + kill "$pf_pid" 2>/dev/null || true + wait "$pf_pid" 2>/dev/null || true # reap the child + rm -f "$log" + } + trap cleanup EXIT INT TERM + + # --- 3. wait until the local port is actually open --------------------- + local lport=${map%%:*} # leftmost number before the first ':' + for _ in {1..50}; do # ~10 s max (50×0.2 s) + if nc -z 127.0.0.1 "$lport" 2>/dev/null; then break; fi + if ! kill -0 "$pf_pid" 2>/dev/null; then + echo "port-forward crashed — see $log" >&2 + exit 1 + fi + sleep 0.2 + done + + # --- 4. hand control to the caller’s command list ---------------------- + "$@" + # cleanup() runs automatically thanks to the trap +) From c97b28fa7100f51e39299c49176240afc80cb928 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Fri, 18 Jul 2025 18:53:46 +0200 Subject: [PATCH 14/19] Add WIP, still broken --- smoke-release-testing/k8s/run.bash | 98 ++++++++++++++++-------------- smoke-release-testing/utils.bash | 37 ++++++++--- 2 files changed, 83 insertions(+), 52 deletions(-) diff --git a/smoke-release-testing/k8s/run.bash b/smoke-release-testing/k8s/run.bash index 0fe6b9d20..9a57fff20 100755 --- a/smoke-release-testing/k8s/run.bash +++ b/smoke-release-testing/k8s/run.bash @@ -39,52 +39,45 @@ setup_cluster() { kubectl wait --for=condition=Ready pod -l role=coordinator --timeout=120s kubectl wait --for=condition=Ready pod -l role=data --timeout=120s - kubectl port-forward memgraph-coordinator-1-0 17687:7687 & - PF_PID=$! - wait_for_memgraph_coordinator localhost 17687 - setup_coordinator 1 - setup_coordinator 2 - setup_coordinator 3 - setup_replica 0 - setup_replica 1 - setup_main 0 - kill $PF_PID - wait $PF_PID 2>/dev/null || true - - # # TODO(gitbuda): The reason for the abstracted code is also that sometimes port-foward fails (again some sync issue). - # # TODO(gitbuda): An attempt to make the code nicer but it still doesn't work -> not all gets executed + there is an infinitely loop. - # with_kubectl_portforward memgraph-coordinator-1-0 17687:7687 -- \ - # wait_for_memgraph_coordinator localhost 17687 && \ - # setup_coordinator 1 && \ - # setup_coordinator 2 && \ - # setup_coordinator 3 && \ - # setup_replica 0 && \ - # setup_main 0 + # TODO(gitbuda): The reason for the abstracted code is also that sometimes port-foward fails (again some sync issue). + # TODO(gitbuda): An attempt to make the code nicer but it still doesn't work -> not all gets executed + there is an infinitely loop. + with_kubectl_portforward memgraph-coordinator-1-0 17687:7687 -- \ + 'wait_for_memgraph_coordinator localhost 17687' \ + 'setup_coordinator 1' \ + 'setup_coordinator 2' \ + 'setup_coordinator 3' \ + 'setup_replica 0' \ + 'setup_main 0' } execute_query_against_main() { query="$1" # Derive what's the main instance (it's not deterministic where is MAIN after recovery). - kubectl wait --for=condition=Ready pod/memgraph-coordinator-1-0 --timeout=120s - kubectl port-forward memgraph-coordinator-1-0 17687:7687 & - PF_PID=$! - wait_for_memgraph_coordinator localhost 17687 - main_instance=$(echo "SHOW INSTANCES;" | $MEMGRAPH_CONSOLE_BINARY --port 17687 --output-format=csv | python3 $SCRIPT_DIR/../reader.py get_main_parser) - echo "NOTE: MAIN instance is $main_instance" - kill $PF_PID - wait $PF_PID 2>/dev/null || true + # kubectl wait --for=condition=Ready pod/memgraph-coordinator-1-0 --timeout=120s + # kubectl port-forward memgraph-coordinator-1-0 17687:7687 & + # PF_PID=$! + # kill $PF_PID + # wait $PF_PID 2>/dev/null || true - kubectl wait --for=condition=Ready pod/${main_instance}-0 --timeout=120s - kubectl port-forward ${main_instance}-0 17687:7687 & - PF_PID=$! - wait_for_memgraph localhost 17687 - echo "$query" | $MEMGRAPH_CONSOLE_BINARY --port 17687 - kill $PF_PID - wait $PF_PID 2>/dev/null || true + # kubectl wait --for=condition=Ready pod/${main_instance}-0 --timeout=120s + # kubectl port-forward ${main_instance}-0 17687:7687 & + # PF_PID=$! + # kill $PF_PID + # wait $PF_PID 2>/dev/null || true + + with_kubectl_portforward memgraph-coordinator-1-0 17687:7687 -- \ + "wait_for_memgraph_coordinator localhost 17687" \ + "export MAIN_INSTANCE=\$(echo \"SHOW INSTANCES;\" | $MEMGRAPH_CONSOLE_BINARY --port 17687 --output-format=csv | python3 $SCRIPT_DIR/../reader.py get_main_parser)" \ + "echo \"NOTE: MAIN instance is \$MAIN_INSTANCE\"" + # TODO(gitbuda): MAIN_INSTANCE variable here is lost -> FIX + with_kubectl_portforward $MAIN_INSTANCE 17687:7687 -- \ + "wait_for_memgraph localhost 17687" \ + "echo \"$query\" | $MEMGRAPH_CONSOLE_BINARY --port 17687" } test_k8s_single() { + # TODO(gitbuda): Refactor test_k8s_single to also use with_kubectl_portforward echo "Test k8s single memgraph instance using image: $MEMGRAPH_NEXT_DOCKERHUB_IMAGE" kind load docker-image $MEMGRAPH_NEXT_DOCKERHUB_IMAGE -n smoke-release-testing MEMGRAPH_NEXT_DOCKERHUB_TAG="${MEMGRAPH_NEXT_DOCKERHUB_IMAGE##*:}" @@ -120,13 +113,15 @@ test_k8s_ha() { CHART_PATH="memgraph/memgraph-high-availability" SKIP_CLUSTER_SETUP=false SKIP_CLEANUP=false + SKIP_HELM_UNINSTALL=false while true; do case $1 in - -p|--chart-path) CHART_PATH="$2"; shift 2 ;; - -s|--skip-cluster-setup) SKIP_CLUSTER_SETUP=true; shift ;; - -c|--skip-cleanup) SKIP_CLEANUP=true; shift ;; - -h|--help) test_k8s_help; ;; - *) shift; break ;; + -p|--chart-path) CHART_PATH="$2"; shift 2 ;; + -s|--skip-cluster-setup) SKIP_CLUSTER_SETUP=true; shift ;; + -u|--skip-helm-uninstall) SKIP_HELM_UNINSTALL=true; shift ;; + -c|--skip-cleanup) SKIP_CLEANUP=true; shift ;; + -h|--help) test_k8s_help; ;; + *) shift; break ;; esac done echo "Test k8s HA memgraph cluster using image:" @@ -147,20 +142,33 @@ test_k8s_ha() { execute_query_against_main "SHOW VERSION;" execute_query_against_main "CREATE ();" execute_query_against_main "MATCH (n) RETURN n;" - # TODO(gitbuda): Add additional flag for this. - helm uninstall myhadb + if [ "$SKIP_HELM_UNINSTALL" = false ]; then + helm uninstall myhadb + fi if [ "$SKIP_CLEANUP" = false ]; then kubectl delete pvc --all fi } +call_me() { + echo "x" +} if [ "${BASH_SOURCE[0]}" -ef "$0" ]; then echo "Running $0 directly..." # NOTE: Developing workflow: download+load required images and define MEMGRAPH_NEXT_DOCKERHUB_IMAGE. - test_k8s_ha LAST -c # Skip cleanup because we want to recover from existing PVCs. - test_k8s_ha NEXT -s # Skip cluster setup because that should be recovered from PVCs. + # test_k8s_ha LAST -c # Skip cleanup because we want to recover from existing PVCs. + # test_k8s_ha NEXT -s # Skip cluster setup because that should be recovered from PVCs. # How to inject local version of the helm chart because we want to test any local fixes upfront. # test_k8s_ha NEXT ~/Workspace/code/memgraph/helm-charts/charts/memgraph-high-availability + + # TODO(gitbuda): At the moment, it can happen that exit code is 0 while there is a failure -> FIX. + # test_k8s_ha NEXT -u -c + + with_kubectl_portforward memgraph-coordinator-1-0 17687:7687 -- \ + 'export EXP_VAR="foo"' + "echo \"MG_MAIN=\"data0\" > $SCRIPT_DIR/mg_main.out" + source $SCRIPT_DIR/mg_main.out + echo "$MG_MAIN" fi diff --git a/smoke-release-testing/utils.bash b/smoke-release-testing/utils.bash index 157412fe0..1be7155dd 100755 --- a/smoke-release-testing/utils.bash +++ b/smoke-release-testing/utils.bash @@ -72,16 +72,30 @@ wait_port() { wait_for_memgraph() { __host=$1 __port=$2 + __max_retries=${3:-50} + __retries=0 while ! echo "RETURN 1;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port > /dev/null 2>&1; do sleep 0.1 + __retries=$((__retries+1)) + if [ "$__retries" -ge "$__max_retries" ]; then + echo "wait_for_memgraph: Reached max retries ($__max_retries) for $__host:$__port" + return 1 + fi done } wait_for_memgraph_coordinator() { __host=$1 __port=$2 + __max_retries=${3:-50} + __retries=0 while ! echo "SHOW INSTANCE;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port > /dev/null 2>&1; do sleep 0.1 + __retries=$((__retries+1)) + if [ "$__retries" -ge "$__max_retries" ]; then + echo "wait_for_memgraph_coordinator: Reached max retries ($__max_retries) for $__host:$__port" + return 1 + fi done } @@ -233,19 +247,26 @@ spinup_and_cleanup_memgraph_dockers() { } with_kubectl_portforward() ( - # --- 1. peel off first two required arguments -------------------------- - local target=$1 # svc/foo, pod/bar, deployment/baz, … - local map=$2 # 8080:80 or 8443 or 0.0.0.0:8080:80 - shift 3 # “--” + user commands remain + # --- 1. peel off first two required arguments --------------------------- + local target=$1 # svc/foo, pod/bar, deployment/baz, … + local map=$2 # 8080:80 or 8443 or 0.0.0.0:8080:80 + shift 3 # “--” + user commands; NOTE: Use an array of commands + # inside a string: + # -- 'cmd1' 'cmd2' ... + # because if you use ; or && to separate + # commands, bash will treat that as one + # command + cleanup + the rest. - # --- 2. launch port-forward in background ------------------------------ + # --- 2. launch port-forward in background ------------------------------- # Send its output to a temp file so we can inspect errors if it dies early local log log=$(mktemp) + # TODO(gitbuda): port-forward sometimes failes (something is flaky) -> FIX kubectl port-forward "$target" "$map" >/dev/null 2>>"$log" & + pf_status=$? + echo "$pf_status" local pf_pid=$! - # Clean up on normal exit or on signals cleanup() { echo "calling port forward cleanup" kill "$pf_pid" 2>/dev/null || true @@ -266,6 +287,8 @@ with_kubectl_portforward() ( done # --- 4. hand control to the caller’s command list ---------------------- - "$@" + for cmd in "$@"; do + eval "$cmd" + done # cleanup() runs automatically thanks to the trap ) From fa10c9629b3c147aaaa9888a7efbcd7bc00d4881 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Sat, 19 Jul 2025 20:54:11 +0200 Subject: [PATCH 15/19] Most of the refactoring is done -> TODO: improve stability and polish --- smoke-release-testing/k8s/run.bash | 70 ++++++-------------- smoke-release-testing/k8s/values-single.yaml | 2 +- smoke-release-testing/test.bash | 5 +- 3 files changed, 26 insertions(+), 51 deletions(-) diff --git a/smoke-release-testing/k8s/run.bash b/smoke-release-testing/k8s/run.bash index 9a57fff20..bc9817dde 100755 --- a/smoke-release-testing/k8s/run.bash +++ b/smoke-release-testing/k8s/run.bash @@ -34,13 +34,7 @@ setup_main() { echo "SET INSTANCE instance_$i TO MAIN;" | $MEMGRAPH_CONSOLE_BINARY --port 17687 echo "main DONE" } - setup_cluster() { - kubectl wait --for=condition=Ready pod -l role=coordinator --timeout=120s - kubectl wait --for=condition=Ready pod -l role=data --timeout=120s - - # TODO(gitbuda): The reason for the abstracted code is also that sometimes port-foward fails (again some sync issue). - # TODO(gitbuda): An attempt to make the code nicer but it still doesn't work -> not all gets executed + there is an infinitely loop. with_kubectl_portforward memgraph-coordinator-1-0 17687:7687 -- \ 'wait_for_memgraph_coordinator localhost 17687' \ 'setup_coordinator 1' \ @@ -52,48 +46,33 @@ setup_cluster() { execute_query_against_main() { query="$1" - - # Derive what's the main instance (it's not deterministic where is MAIN after recovery). - # kubectl wait --for=condition=Ready pod/memgraph-coordinator-1-0 --timeout=120s - # kubectl port-forward memgraph-coordinator-1-0 17687:7687 & - # PF_PID=$! - # kill $PF_PID - # wait $PF_PID 2>/dev/null || true - - # kubectl wait --for=condition=Ready pod/${main_instance}-0 --timeout=120s - # kubectl port-forward ${main_instance}-0 17687:7687 & - # PF_PID=$! - # kill $PF_PID - # wait $PF_PID 2>/dev/null || true - with_kubectl_portforward memgraph-coordinator-1-0 17687:7687 -- \ "wait_for_memgraph_coordinator localhost 17687" \ - "export MAIN_INSTANCE=\$(echo \"SHOW INSTANCES;\" | $MEMGRAPH_CONSOLE_BINARY --port 17687 --output-format=csv | python3 $SCRIPT_DIR/../reader.py get_main_parser)" \ - "echo \"NOTE: MAIN instance is \$MAIN_INSTANCE\"" - # TODO(gitbuda): MAIN_INSTANCE variable here is lost -> FIX - with_kubectl_portforward $MAIN_INSTANCE 17687:7687 -- \ + "MAIN_INSTANCE=\$(echo \"SHOW INSTANCES;\" | $MEMGRAPH_CONSOLE_BINARY --port 17687 --output-format=csv | python3 $SCRIPT_DIR/../reader.py get_main_parser)" \ + "echo \"NOTE: MAIN instance is \$MAIN_INSTANCE\"" \ + "echo \"MG_MAIN=\$MAIN_INSTANCE\" > $SCRIPT_DIR/mg_main.out" # Couldn't get export to move the info -> used file instead. + source $SCRIPT_DIR/mg_main.out + with_kubectl_portforward "$MG_MAIN-0" 17687:7687 -- \ "wait_for_memgraph localhost 17687" \ "echo \"$query\" | $MEMGRAPH_CONSOLE_BINARY --port 17687" } test_k8s_single() { - # TODO(gitbuda): Refactor test_k8s_single to also use with_kubectl_portforward echo "Test k8s single memgraph instance using image: $MEMGRAPH_NEXT_DOCKERHUB_IMAGE" kind load docker-image $MEMGRAPH_NEXT_DOCKERHUB_IMAGE -n smoke-release-testing MEMGRAPH_NEXT_DOCKERHUB_TAG="${MEMGRAPH_NEXT_DOCKERHUB_IMAGE##*:}" - load_next_image_into_kind helm install memgraph-single-smoke memgraph/memgraph \ -f "$SCRIPT_DIR/values-single.yaml" \ --set "image.tag=$MEMGRAPH_NEXT_DOCKERHUB_TAG" kubectl wait --for=condition=Ready pod/memgraph-single-smoke-0 --timeout=120s - kubectl port-forward memgraph-single-smoke-0 17687:7687 & - PF_PID=$! - wait_for_memgraph localhost 17687 - echo "CREATE ();" | $MEMGRAPH_CONSOLE_BINARY --port 17687 - echo "MATCH (n) RETURN n;" | $MEMGRAPH_CONSOLE_BINARY --port 17687 - kill $PF_PID - wait $PF_PID 2>/dev/null || true + + with_kubectl_portforward memgraph-single-smoke-0 17687:7687 -- \ + "wait_for_memgraph localhost 17687" \ + "echo \"CREATE ();\" | $MEMGRAPH_CONSOLE_BINARY --port 17687" \ + "echo \"MATCH (n) RETURN n;\" | $MEMGRAPH_CONSOLE_BINARY --port 17687" + helm uninstall memgraph-single-smoke + kubectl delete pvc --all } test_k8s_help() { @@ -136,6 +115,9 @@ test_k8s_ha() { --set env.MEMGRAPH_ENTERPRISE_LICENSE=$MEMGRAPH_ENTERPRISE_LICENSE,env.MEMGRAPH_ORGANIZATION_NAME=$MEMGRAPH_ORGANIZATION_NAME \ -f "$SCRIPT_DIR/values-ha.yaml" \ --set "image.tag=$MEMGRAPH_DOCKERHUB_TAG" + kubectl wait --for=condition=Ready pod -l role=coordinator --timeout=120s + kubectl wait --for=condition=Ready pod -l role=data --timeout=120s + if [ "$SKIP_CLUSTER_SETUP" = false ]; then setup_cluster fi @@ -150,25 +132,17 @@ test_k8s_ha() { fi } -call_me() { - echo "x" -} if [ "${BASH_SOURCE[0]}" -ef "$0" ]; then + # NOTE: Developing workflow: download+load required images and defined MEMGRAPH_NEXT_DOCKERHUB_IMAGE. echo "Running $0 directly..." - # NOTE: Developing workflow: download+load required images and define MEMGRAPH_NEXT_DOCKERHUB_IMAGE. - # test_k8s_ha LAST -c # Skip cleanup because we want to recover from existing PVCs. - # test_k8s_ha NEXT -s # Skip cluster setup because that should be recovered from PVCs. + # TODO(gitbuda): Exit on failures. + # TODO(gitbuda): Check the results. + + test_k8s_single + test_k8s_ha LAST -c # Skip cleanup because we want to recover from existing PVCs. + test_k8s_ha NEXT -s # Skip cluster setup because that should be recovered from PVCs. # How to inject local version of the helm chart because we want to test any local fixes upfront. # test_k8s_ha NEXT ~/Workspace/code/memgraph/helm-charts/charts/memgraph-high-availability - - # TODO(gitbuda): At the moment, it can happen that exit code is 0 while there is a failure -> FIX. - # test_k8s_ha NEXT -u -c - - with_kubectl_portforward memgraph-coordinator-1-0 17687:7687 -- \ - 'export EXP_VAR="foo"' - "echo \"MG_MAIN=\"data0\" > $SCRIPT_DIR/mg_main.out" - source $SCRIPT_DIR/mg_main.out - echo "$MG_MAIN" fi diff --git a/smoke-release-testing/k8s/values-single.yaml b/smoke-release-testing/k8s/values-single.yaml index 9035b33b4..723df7a64 100644 --- a/smoke-release-testing/k8s/values-single.yaml +++ b/smoke-release-testing/k8s/values-single.yaml @@ -1,5 +1,5 @@ image: - repository: memgraph/memgraph-mage + repository: memgraph/memgraph # Overrides the image tag whose default is v{{ .Chart.AppVersion }} # It is a bad practice to set the image tag name to latest as it can trigger automatic upgrade of the charts # With some of the pullPolicy values. Please consider fixing the tag to a specific Memgraph version diff --git a/smoke-release-testing/test.bash b/smoke-release-testing/test.bash index b167475f4..cdcb24177 100755 --- a/smoke-release-testing/test.bash +++ b/smoke-release-testing/test.bash @@ -4,6 +4,7 @@ source "$SCRIPT_DIR/utils.bash" # TODO(gitbuda): Measure the total execution time, it should be under ~10s. # TODO(gitbuda): Test docker compose. +# TODO(gitbuda): memgraph vs mage -> docker tests assume mage while helm is memgraph -> RESOLVE. # NOTE: 1st arg is how to pull LAST image, 2nd arg is how to pull NEXT image. spinup_and_cleanup_memgraph_dockers DockerHub RC @@ -53,5 +54,5 @@ test_impersonate_user $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT # k8s is a special case, because it requires extra setup. source $SCRIPT_DIR/k8s/run.bash test_k8s_single -test_k8s_ha LAST -test_k8s_ha NEXT +test_k8s_ha LAST -c # Skip cleanup because we want to recover from existing PVCs. +test_k8s_ha NEXT -s # Skip cluster setup because that should be recovered from PVCs. From 0262b8f20df5218c29ad63a762a5496643a9966a Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Sun, 20 Jul 2025 15:57:14 +0200 Subject: [PATCH 16/19] Add much more robust version, still not perfect --- .github/workflows/reusable_smoke_tests.yml | 2 +- smoke-release-testing/k8s/run.bash | 69 ++++++++++++------- smoke-release-testing/reader.py | 35 ---------- smoke-release-testing/test_ha_memgraph.bash | 12 ++++ .../{test.bash => test_single_mage.bash} | 10 +-- smoke-release-testing/utils.bash | 68 ++++++++++-------- smoke-release-testing/validator.py | 28 +++++++- 7 files changed, 126 insertions(+), 98 deletions(-) delete mode 100644 smoke-release-testing/reader.py create mode 100755 smoke-release-testing/test_ha_memgraph.bash rename smoke-release-testing/{test.bash => test_single_mage.bash} (85%) diff --git a/.github/workflows/reusable_smoke_tests.yml b/.github/workflows/reusable_smoke_tests.yml index d371ee624..79005bbc2 100644 --- a/.github/workflows/reusable_smoke_tests.yml +++ b/.github/workflows/reusable_smoke_tests.yml @@ -160,7 +160,7 @@ jobs: -e MEMGRAPH_LAST_DOCKERHUB_IMAGE="$MEMGRAPH_LAST_DOCKERHUB_IMAGE" \ -e MEMGRAPH_NEXT_DOCKERHUB_IMAGE="$MEMGRAPH_NEXT_DOCKERHUB_IMAGE" \ "$CONTAINER_NAME" \ - bash -c "cd /mage/smoke-release-testing && ./test.bash" + bash -c "cd /mage/smoke-release-testing && ./test_single_mage.bash" - name: Clean up inner Docker state if: always() diff --git a/smoke-release-testing/k8s/run.bash b/smoke-release-testing/k8s/run.bash index bc9817dde..8a5836071 100755 --- a/smoke-release-testing/k8s/run.bash +++ b/smoke-release-testing/k8s/run.bash @@ -35,8 +35,7 @@ setup_main() { echo "main DONE" } setup_cluster() { - with_kubectl_portforward memgraph-coordinator-1-0 17687:7687 -- \ - 'wait_for_memgraph_coordinator localhost 17687' \ + with_kubectl_portforward memgraph-coordinator-1-0 17687:7687 'wait_for_memgraph_coordinator localhost 17687 5' -- \ 'setup_coordinator 1' \ 'setup_coordinator 2' \ 'setup_coordinator 3' \ @@ -46,17 +45,27 @@ setup_cluster() { execute_query_against_main() { query="$1" - with_kubectl_portforward memgraph-coordinator-1-0 17687:7687 -- \ - "wait_for_memgraph_coordinator localhost 17687" \ - "MAIN_INSTANCE=\$(echo \"SHOW INSTANCES;\" | $MEMGRAPH_CONSOLE_BINARY --port 17687 --output-format=csv | python3 $SCRIPT_DIR/../reader.py get_main_parser)" \ + with_kubectl_portforward memgraph-coordinator-1-0 17687:7687 'wait_for_memgraph_coordinator localhost 17687 5' -- \ + "MAIN_INSTANCE=\$(echo \"SHOW INSTANCES;\" | $MEMGRAPH_CONSOLE_BINARY --port 17687 --output-format=csv | python3 $SCRIPT_DIR/../validator.py get_main_parser)" \ "echo \"NOTE: MAIN instance is \$MAIN_INSTANCE\"" \ "echo \"MG_MAIN=\$MAIN_INSTANCE\" > $SCRIPT_DIR/mg_main.out" # Couldn't get export to move the info -> used file instead. source $SCRIPT_DIR/mg_main.out - with_kubectl_portforward "$MG_MAIN-0" 17687:7687 -- \ - "wait_for_memgraph localhost 17687" \ + with_kubectl_portforward "$MG_MAIN-0" 17687:7687 'wait_for_memgraph localhost 17687 5' -- \ "echo \"$query\" | $MEMGRAPH_CONSOLE_BINARY --port 17687" } +validate_nodes_against_main() { + expected=$1 + with_kubectl_portforward memgraph-coordinator-1-0 17687:7687 'wait_for_memgraph_coordinator localhost 17687 5' -- \ + "MAIN_INSTANCE=\$(echo \"SHOW INSTANCES;\" | $MEMGRAPH_CONSOLE_BINARY --port 17687 --output-format=csv | python3 $SCRIPT_DIR/../validator.py get_main_parser)" \ + "echo \"NOTE: MAIN instance is \$MAIN_INSTANCE\"" \ + "echo \"MG_MAIN=\$MAIN_INSTANCE\" > $SCRIPT_DIR/mg_main.out" # Couldn't get export to move the info -> used file instead. + source $SCRIPT_DIR/mg_main.out + with_kubectl_portforward "$MG_MAIN-0" 17687:7687 'wait_for_memgraph localhost 17687 5' -- \ + "echo \"MATCH (n) RETURN n;\" | $MEMGRAPH_CONSOLE_BINARY --port 17687 --output-format=csv | python3 $SCRIPT_DIR/../validator.py validate_number_of_results -e $expected" + +} + test_k8s_single() { echo "Test k8s single memgraph instance using image: $MEMGRAPH_NEXT_DOCKERHUB_IMAGE" kind load docker-image $MEMGRAPH_NEXT_DOCKERHUB_IMAGE -n smoke-release-testing @@ -66,13 +75,11 @@ test_k8s_single() { --set "image.tag=$MEMGRAPH_NEXT_DOCKERHUB_TAG" kubectl wait --for=condition=Ready pod/memgraph-single-smoke-0 --timeout=120s - with_kubectl_portforward memgraph-single-smoke-0 17687:7687 -- \ - "wait_for_memgraph localhost 17687" \ + with_kubectl_portforward memgraph-single-smoke-0 17687:7687 "wait_for_memgraph localhost 17687 5" -- \ "echo \"CREATE ();\" | $MEMGRAPH_CONSOLE_BINARY --port 17687" \ "echo \"MATCH (n) RETURN n;\" | $MEMGRAPH_CONSOLE_BINARY --port 17687" helm uninstall memgraph-single-smoke - kubectl delete pvc --all } test_k8s_help() { @@ -80,6 +87,18 @@ test_k8s_help() { exit 1 } +cleanup_k8s_all() { + # NOTE: An attempt to cleanup any leftovers from kubectl port-forward... + kill -9 $(pgrep kubectl) || true + if helm status myhadb > /dev/null 2>&1; then + helm uninstall myhadb + fi + if helm status myhadb > /dev/null 2>&1; then + helm uninstall memgraph-single-smoke + fi + kubectl delete pvc --all +} + test_k8s_ha() { if [ "$#" -lt 1 ]; then test_k8s_help @@ -93,21 +112,25 @@ test_k8s_ha() { SKIP_CLUSTER_SETUP=false SKIP_CLEANUP=false SKIP_HELM_UNINSTALL=false - while true; do + EXPECTED_NODES_COUNT=1 + while [ "$#" -gt 0 ]; do case $1 in - -p|--chart-path) CHART_PATH="$2"; shift 2 ;; - -s|--skip-cluster-setup) SKIP_CLUSTER_SETUP=true; shift ;; - -u|--skip-helm-uninstall) SKIP_HELM_UNINSTALL=true; shift ;; - -c|--skip-cleanup) SKIP_CLEANUP=true; shift ;; - -h|--help) test_k8s_help; ;; - *) shift; break ;; + -p|--chart-path) CHART_PATH="$2"; shift 2 ;; + -s|--skip-cluster-setup) SKIP_CLUSTER_SETUP=true; shift ;; + -u|--skip-helm-uninstall) SKIP_HELM_UNINSTALL=true; shift ;; + -c|--skip-cleanup) SKIP_CLEANUP=true; shift ;; + -n|--expected-nodes-no) EXPECTED_NODES_COUNT="$2"; shift 2 ;; + -h|--help) test_k8s_help; ;; + *) shift; break ;; esac done echo "Test k8s HA memgraph cluster using image:" echo " * image: $WHICH_IMAGE" echo " * tag: $MEMGRAPH_DOCKERHUB_TAG" echo " * chart: $CHART_PATH" + echo " * expected nodes number: $EXPECTED_NODES_COUNT" echo " * skip cluster setup: $SKIP_CLUSTER_SETUP" + echo " * skip helm uninstall: $SKIP_HELM_UNINSTALL" echo " * skip cleanup: $SKIP_CLEANUP" kind load docker-image $WHICH_IMAGE -n smoke-release-testing @@ -115,6 +138,7 @@ test_k8s_ha() { --set env.MEMGRAPH_ENTERPRISE_LICENSE=$MEMGRAPH_ENTERPRISE_LICENSE,env.MEMGRAPH_ORGANIZATION_NAME=$MEMGRAPH_ORGANIZATION_NAME \ -f "$SCRIPT_DIR/values-ha.yaml" \ --set "image.tag=$MEMGRAPH_DOCKERHUB_TAG" + sleep 1 # NOTE: Sometimes there is an Error from Server -> pod XYZ not found... kubectl wait --for=condition=Ready pod -l role=coordinator --timeout=120s kubectl wait --for=condition=Ready pod -l role=data --timeout=120s @@ -123,7 +147,7 @@ test_k8s_ha() { fi execute_query_against_main "SHOW VERSION;" execute_query_against_main "CREATE ();" - execute_query_against_main "MATCH (n) RETURN n;" + validate_nodes_against_main $EXPECTED_NODES_COUNT if [ "$SKIP_HELM_UNINSTALL" = false ]; then helm uninstall myhadb fi @@ -136,12 +160,9 @@ if [ "${BASH_SOURCE[0]}" -ef "$0" ]; then # NOTE: Developing workflow: download+load required images and defined MEMGRAPH_NEXT_DOCKERHUB_IMAGE. echo "Running $0 directly..." - # TODO(gitbuda): Exit on failures. - # TODO(gitbuda): Check the results. - - test_k8s_single - test_k8s_ha LAST -c # Skip cleanup because we want to recover from existing PVCs. - test_k8s_ha NEXT -s # Skip cluster setup because that should be recovered from PVCs. + # test_k8s_single + # test_k8s_ha LAST -c # Skip cleanup because we want to recover from existing PVCs. + # test_k8s_ha NEXT -s # Skip cluster setup because that should be recovered from PVCs. # How to inject local version of the helm chart because we want to test any local fixes upfront. # test_k8s_ha NEXT ~/Workspace/code/memgraph/helm-charts/charts/memgraph-high-availability diff --git a/smoke-release-testing/reader.py b/smoke-release-testing/reader.py deleted file mode 100644 index d4136d64d..000000000 --- a/smoke-release-testing/reader.py +++ /dev/null @@ -1,35 +0,0 @@ -import sys -import csv -import argparse - - -def read_all_csv_from_stdin(): - return list(csv.DictReader(sys.stdin)) - - -def get_main_parser(data): - main_addr=None - for instance in data: - if instance["role"] == '"main"': - main_addr=instance["management_server"][1:-1].split(".")[0] - print(main_addr) - - -def get_arguments(): - parser = argparse.ArgumentParser( - description="Smoke Tests Validator", - ) - subparsers = parser.add_subparsers( - help="sub-command help", dest="action", required=True - ) - subparsers.add_parser( - "get_main_parser", help="Get main parser" - ) - return parser.parse_args() - - -if __name__ == "__main__": - args = get_arguments() - data = read_all_csv_from_stdin() - if args.action == "get_main_parser": - get_main_parser(data) diff --git a/smoke-release-testing/test_ha_memgraph.bash b/smoke-release-testing/test_ha_memgraph.bash new file mode 100755 index 000000000..56e03e295 --- /dev/null +++ b/smoke-release-testing/test_ha_memgraph.bash @@ -0,0 +1,12 @@ +#!/bin/bash -ex +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +source "$SCRIPT_DIR/utils.bash" + +# TODO(gitbuda): Measure the total execution time, it should be under ~10s. +source $SCRIPT_DIR/k8s/run.bash +cleanup_k8s_all + +# test_k8s_single + +test_k8s_ha LAST -n 1 -c # Skip cleanup because we want to recover from existing PVCs. +test_k8s_ha NEXT -n 2 -s # Skip cluster setup because that should be recovered from PVCs. diff --git a/smoke-release-testing/test.bash b/smoke-release-testing/test_single_mage.bash similarity index 85% rename from smoke-release-testing/test.bash rename to smoke-release-testing/test_single_mage.bash index cdcb24177..90f7ca4a8 100755 --- a/smoke-release-testing/test.bash +++ b/smoke-release-testing/test_single_mage.bash @@ -3,11 +3,9 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source "$SCRIPT_DIR/utils.bash" # TODO(gitbuda): Measure the total execution time, it should be under ~10s. -# TODO(gitbuda): Test docker compose. -# TODO(gitbuda): memgraph vs mage -> docker tests assume mage while helm is memgraph -> RESOLVE. # NOTE: 1st arg is how to pull LAST image, 2nd arg is how to pull NEXT image. -spinup_and_cleanup_memgraph_dockers DockerHub RC +spinup_and_cleanup_memgraph_dockers DockerHub DockerHub echo "Waiting for memgraph to initialize..." wait_for_memgraph $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_LAST_DATA_BOLT_PORT wait_for_memgraph $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT @@ -50,9 +48,3 @@ test_or_expression_for_labels $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PO # NOTE: If the testing container is NOT restarted, all the auth test have to # come after all tests that assume there are no users. test_impersonate_user $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT - -# k8s is a special case, because it requires extra setup. -source $SCRIPT_DIR/k8s/run.bash -test_k8s_single -test_k8s_ha LAST -c # Skip cleanup because we want to recover from existing PVCs. -test_k8s_ha NEXT -s # Skip cluster setup because that should be recovered from PVCs. diff --git a/smoke-release-testing/utils.bash b/smoke-release-testing/utils.bash index 1be7155dd..61b47a2ce 100755 --- a/smoke-release-testing/utils.bash +++ b/smoke-release-testing/utils.bash @@ -72,31 +72,33 @@ wait_port() { wait_for_memgraph() { __host=$1 __port=$2 - __max_retries=${3:-50} + __max_retries=${3:-100} __retries=0 while ! echo "RETURN 1;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port > /dev/null 2>&1; do - sleep 0.1 + sleep 0.2 __retries=$((__retries+1)) if [ "$__retries" -ge "$__max_retries" ]; then echo "wait_for_memgraph: Reached max retries ($__max_retries) for $__host:$__port" return 1 fi done + return 0 } wait_for_memgraph_coordinator() { __host=$1 __port=$2 - __max_retries=${3:-50} + __max_retries=${3:-100} __retries=0 while ! echo "SHOW INSTANCE;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port > /dev/null 2>&1; do - sleep 0.1 + sleep 0.2 __retries=$((__retries+1)) if [ "$__retries" -ge "$__max_retries" ]; then echo "wait_for_memgraph_coordinator: Reached max retries ($__max_retries) for $__host:$__port" return 1 fi done + return 0 } run_memgraph_binary() { @@ -247,35 +249,49 @@ spinup_and_cleanup_memgraph_dockers() { } with_kubectl_portforward() ( - # --- 1. peel off first two required arguments --------------------------- - local target=$1 # svc/foo, pod/bar, deployment/baz, … - local map=$2 # 8080:80 or 8443 or 0.0.0.0:8080:80 - shift 3 # “--” + user commands; NOTE: Use an array of commands - # inside a string: - # -- 'cmd1' 'cmd2' ... - # because if you use ; or && to separate - # commands, bash will treat that as one - # command + cleanup + the rest. + local target=$1 # svc/foo, pod/bar, deployment/baz, … + local map=$2 # 8080:80 or 8443 or 0.0.0.0:8080:80 + local probe="$3" # probe to test the target process, e.g. wait_for_xyz + shift 4 # “--” + user commands; NOTE: Use an array of commands + # inside a string: -- 'cmd1' 'cmd2' ... + # because if you use ; or && to separate commands, + # bash will treat that as one command + cleanup + the + # rest. - # --- 2. launch port-forward in background ------------------------------- - # Send its output to a temp file so we can inspect errors if it dies early local log - log=$(mktemp) - # TODO(gitbuda): port-forward sometimes failes (something is flaky) -> FIX - kubectl port-forward "$target" "$map" >/dev/null 2>>"$log" & - pf_status=$? - echo "$pf_status" - local pf_pid=$! + local pf_pid + local retries=0 + local max_retries=5 + while true; do + log=$(mktemp) + kubectl port-forward "$target" "$map" >/dev/null 2>>"$log" & + pf_pid=$! + # NOTE: port-forward doesn't have built-in timeout. The target process + # might take arbitrary time to initialize. -> The only way to know if + # everything is right in the shortest amount of time is to inject the + # probe as one of the required params. + # TODO(gitbuda): If this is lower (depending how much), wait_for_coordinator fails or MAIN is not elected in the cluster yet... -> FIX + sleep 1 + if ! eval "$probe"; then + kill -9 "$pf_pid" 2>/dev/null || true + wait "$pf_pid" 2>/dev/null || true + retries=$((retries+1)) + if [ $retries -ge $max_retries ]; then + echo "kubectl port-forward failed after $max_retries attempts — see $log and inspect the target process" >&2 + exit 1 + fi + else + break + fi + done cleanup() { echo "calling port forward cleanup" - kill "$pf_pid" 2>/dev/null || true - wait "$pf_pid" 2>/dev/null || true # reap the child - rm -f "$log" + kill -9 "$pf_pid" 2>/dev/null || true + wait "$pf_pid" 2>/dev/null || true } trap cleanup EXIT INT TERM - # --- 3. wait until the local port is actually open --------------------- local lport=${map%%:*} # leftmost number before the first ':' for _ in {1..50}; do # ~10 s max (50×0.2 s) if nc -z 127.0.0.1 "$lport" 2>/dev/null; then break; fi @@ -286,9 +302,7 @@ with_kubectl_portforward() ( sleep 0.2 done - # --- 4. hand control to the caller’s command list ---------------------- for cmd in "$@"; do eval "$cmd" done - # cleanup() runs automatically thanks to the trap ) diff --git a/smoke-release-testing/validator.py b/smoke-release-testing/validator.py index bc450632c..f9ba458db 100644 --- a/smoke-release-testing/validator.py +++ b/smoke-release-testing/validator.py @@ -15,6 +15,17 @@ def validate_first_as_int(data, field, expected_value): print(f"Validation of the first {field} is OK.") +def get_main_parser(data): + main_addr=None + for instance in data: + if instance["role"] == '"main"': + main_addr=instance["management_server"][1:-1].split(".")[0] + print(main_addr) + +def validate_number_of_results(data, expected): + assert len(data) == int(expected) + + def get_arguments(): parser = argparse.ArgumentParser( description="Smoke Tests Validator", @@ -33,14 +44,27 @@ def get_arguments(): "-e", "--expected", help="Expected value", required=True ) + subparsers.add_parser( + "get_main_parser", help="Get main parser" + ) + + validate_number_of_results_parser = subparsers.add_parser( + "validate_number_of_results", help="Get the number of results" + ) + validate_number_of_results_parser.add_argument( + "-e", "--expected", help="Expected value", required=True + ) + return parser.parse_args() if __name__ == "__main__": - args = get_arguments() - data = read_all_csv_from_stdin() if args.action == "first_as_int": validate_first_as_int(data, args.field, args.expected) + if args.action == "get_main_parser": + get_main_parser(data) + if args.action == "validate_number_of_results": + validate_number_of_results(data, args.expected) From 34bde879dad2ea2ff9d3a15628748afa085bf1c7 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Sun, 20 Jul 2025 19:00:42 +0200 Subject: [PATCH 17/19] Revert some changes back --- smoke-release-testing/experiment.bash | 18 ++++++------------ smoke-release-testing/k8s/run.bash | 2 +- smoke-release-testing/test_ha_memgraph.bash | 3 +-- smoke-release-testing/test_single_mage.bash | 4 +--- 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/smoke-release-testing/experiment.bash b/smoke-release-testing/experiment.bash index 90cb0ffde..662e19bea 100755 --- a/smoke-release-testing/experiment.bash +++ b/smoke-release-testing/experiment.bash @@ -5,19 +5,13 @@ source "$SCRIPT_DIR/utils.bash" # NOTE: Use the below line if you just want to spin up the containers and leave them running. # run_memgraph_docker_containers RC RC # NOTE: Use the below line if you want to cleanup the containers after run of this script. -# TODO(gitbuda): The below picking of what to download is super error prone -> improve. -# spinup_and_cleanup_memgraph_dockers Dockerhub Dockerhub -# echo "Waiting for memgraph to initialize..." -# wait_for_memgraph $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT -# echo "Memgraph is up and running!" +spinup_and_cleanup_memgraph_dockers Dockerhub Dockerhub +echo "Waiting for memgraph to initialize..." +wait_for_memgraph $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT +echo "Memgraph is up and running!" -# source ./mgconsole/vector_search.bash -# test_vector_search $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT - -source ./k8s/run.bash -# test_k8s_single -# test_k8s_ha LAST -test_k8s_ha NEXT +source ./mgconsole/vector_search.bash +test_vector_search $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT # NOTE: Test what's the exit status of the script by using `echo $?`: # * if it's == 0 -> all good diff --git a/smoke-release-testing/k8s/run.bash b/smoke-release-testing/k8s/run.bash index 8a5836071..b5871c428 100755 --- a/smoke-release-testing/k8s/run.bash +++ b/smoke-release-testing/k8s/run.bash @@ -1,4 +1,4 @@ -#!/bin/bash -x +#!/bin/bash SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source "$SCRIPT_DIR/../utils.bash" SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" diff --git a/smoke-release-testing/test_ha_memgraph.bash b/smoke-release-testing/test_ha_memgraph.bash index 56e03e295..01537e44a 100755 --- a/smoke-release-testing/test_ha_memgraph.bash +++ b/smoke-release-testing/test_ha_memgraph.bash @@ -2,11 +2,10 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source "$SCRIPT_DIR/utils.bash" -# TODO(gitbuda): Measure the total execution time, it should be under ~10s. source $SCRIPT_DIR/k8s/run.bash cleanup_k8s_all -# test_k8s_single +test_k8s_single test_k8s_ha LAST -n 1 -c # Skip cleanup because we want to recover from existing PVCs. test_k8s_ha NEXT -n 2 -s # Skip cluster setup because that should be recovered from PVCs. diff --git a/smoke-release-testing/test_single_mage.bash b/smoke-release-testing/test_single_mage.bash index 90f7ca4a8..457befa61 100755 --- a/smoke-release-testing/test_single_mage.bash +++ b/smoke-release-testing/test_single_mage.bash @@ -2,10 +2,8 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source "$SCRIPT_DIR/utils.bash" -# TODO(gitbuda): Measure the total execution time, it should be under ~10s. - # NOTE: 1st arg is how to pull LAST image, 2nd arg is how to pull NEXT image. -spinup_and_cleanup_memgraph_dockers DockerHub DockerHub +spinup_and_cleanup_memgraph_dockers Dockerhub RC echo "Waiting for memgraph to initialize..." wait_for_memgraph $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_LAST_DATA_BOLT_PORT wait_for_memgraph $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT From 81b846de84a2184afe439f8ebe7adaa73ea3d627 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Sun, 20 Jul 2025 19:50:26 +0200 Subject: [PATCH 18/19] Add improvements --- smoke-release-testing/experiment.bash | 2 +- smoke-release-testing/k8s/run.bash | 26 +++++++++++++---- smoke-release-testing/test_ha_memgraph.bash | 3 +- smoke-release-testing/utils.bash | 32 +++++++++++++++------ smoke-release-testing/validator.py | 17 +++++++---- 5 files changed, 58 insertions(+), 22 deletions(-) diff --git a/smoke-release-testing/experiment.bash b/smoke-release-testing/experiment.bash index 662e19bea..3fe7d4f02 100755 --- a/smoke-release-testing/experiment.bash +++ b/smoke-release-testing/experiment.bash @@ -5,7 +5,7 @@ source "$SCRIPT_DIR/utils.bash" # NOTE: Use the below line if you just want to spin up the containers and leave them running. # run_memgraph_docker_containers RC RC # NOTE: Use the below line if you want to cleanup the containers after run of this script. -spinup_and_cleanup_memgraph_dockers Dockerhub Dockerhub +spinup_and_cleanup_memgraph_dockers none none echo "Waiting for memgraph to initialize..." wait_for_memgraph $MEMGRAPH_DEFAULT_HOST $MEMGRAPH_NEXT_DATA_BOLT_PORT echo "Memgraph is up and running!" diff --git a/smoke-release-testing/k8s/run.bash b/smoke-release-testing/k8s/run.bash index b5871c428..ae2d658d7 100755 --- a/smoke-release-testing/k8s/run.bash +++ b/smoke-release-testing/k8s/run.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -e SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source "$SCRIPT_DIR/../utils.bash" SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" @@ -50,7 +50,9 @@ execute_query_against_main() { "echo \"NOTE: MAIN instance is \$MAIN_INSTANCE\"" \ "echo \"MG_MAIN=\$MAIN_INSTANCE\" > $SCRIPT_DIR/mg_main.out" # Couldn't get export to move the info -> used file instead. source $SCRIPT_DIR/mg_main.out + # NOTE: Waiting for MAIN is required because sometimes all instances are up, but MAIN is not yet fully configured. with_kubectl_portforward "$MG_MAIN-0" 17687:7687 'wait_for_memgraph localhost 17687 5' -- \ + "wait_for_memgraph_main localhost 17687 10" \ "echo \"$query\" | $MEMGRAPH_CONSOLE_BINARY --port 17687" } @@ -82,8 +84,20 @@ test_k8s_single() { helm uninstall memgraph-single-smoke } +helm_install_myhadb() { + chart_path="$1" + image_tag="$2" + helm install myhadb $chart_path \ + --set env.MEMGRAPH_ENTERPRISE_LICENSE=$MEMGRAPH_ENTERPRISE_LICENSE,env.MEMGRAPH_ORGANIZATION_NAME=$MEMGRAPH_ORGANIZATION_NAME \ + -f "$SCRIPT_DIR/values-ha.yaml" \ + --set "image.tag=$image_tag" +} + test_k8s_help() { - echo "usage: test_k8s_ha LAST|NEXT [-p|--chart-path PATH] [-s|--skip-cluster-setup] [-c|--skip-cleanup] [-h|--help]" + echo "usage: test_k8s_ha LAST|NEXT [-p|--chart-path PATH]" + echo " [-s|--skip-cluster-setup] [-u|--skip-helm-uninstall] [-c|--skip-cleanup]" + echo " [-n|--expected-nodes-no]" + echo " [-h|--help]" exit 1 } @@ -134,10 +148,7 @@ test_k8s_ha() { echo " * skip cleanup: $SKIP_CLEANUP" kind load docker-image $WHICH_IMAGE -n smoke-release-testing - helm install myhadb $CHART_PATH \ - --set env.MEMGRAPH_ENTERPRISE_LICENSE=$MEMGRAPH_ENTERPRISE_LICENSE,env.MEMGRAPH_ORGANIZATION_NAME=$MEMGRAPH_ORGANIZATION_NAME \ - -f "$SCRIPT_DIR/values-ha.yaml" \ - --set "image.tag=$MEMGRAPH_DOCKERHUB_TAG" + helm_install_myhadb $CHART_PATH $MEMGRAPH_DOCKERHUB_TAG sleep 1 # NOTE: Sometimes there is an Error from Server -> pod XYZ not found... kubectl wait --for=condition=Ready pod -l role=coordinator --timeout=120s kubectl wait --for=condition=Ready pod -l role=data --timeout=120s @@ -166,4 +177,7 @@ if [ "${BASH_SOURCE[0]}" -ef "$0" ]; then # How to inject local version of the helm chart because we want to test any local fixes upfront. # test_k8s_ha NEXT ~/Workspace/code/memgraph/helm-charts/charts/memgraph-high-availability + + # helm_install_myhadb "memgraph/memgraph-high-availability" "3.4.0" + # wait_for_memgraph_main localhost 17687 5 fi diff --git a/smoke-release-testing/test_ha_memgraph.bash b/smoke-release-testing/test_ha_memgraph.bash index 01537e44a..50df4a3c2 100755 --- a/smoke-release-testing/test_ha_memgraph.bash +++ b/smoke-release-testing/test_ha_memgraph.bash @@ -1,4 +1,4 @@ -#!/bin/bash -ex +#!/bin/bash -e SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source "$SCRIPT_DIR/utils.bash" @@ -7,5 +7,6 @@ cleanup_k8s_all test_k8s_single +# Test the upgrade scenario. PVCs are preserved between the two runs. test_k8s_ha LAST -n 1 -c # Skip cleanup because we want to recover from existing PVCs. test_k8s_ha NEXT -n 2 -s # Skip cluster setup because that should be recovered from PVCs. diff --git a/smoke-release-testing/utils.bash b/smoke-release-testing/utils.bash index 61b47a2ce..ee1bafd20 100755 --- a/smoke-release-testing/utils.bash +++ b/smoke-release-testing/utils.bash @@ -3,15 +3,14 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" MEMGRAPH_BUILD_PATH="${MEMGRAPH_BUILD_PATH:-/tmp/memgraph/build}" MEMGRAPH_CONSOLE_BINARY="${MEMGRAPH_CONSOLE_BINARY:-$SCRIPT_DIR/mgconsole.build/build/src/mgconsole}" -# Required env vars to define. MEMGRAPH_ENTERPRISE_LICENSE="${MEMGRAPH_ENTERPRISE_LICENSE:-provide_licanse_string}" MEMGRAPH_ORGANIZATION_NAME="${MEMGRAPH_ORGANIZATION_NAME:-provide_organization_name_string}" +MEMGRAPH_LAST_DOCKERHUB_IMAGE="${MEMGRAPH_LAST_DOCKERHUB_IMAGE:-provide_dockerhub_image_name}" +MEMGRAPH_NEXT_DOCKERHUB_IMAGE="${MEMGRAPH_NEXT_DOCKERHUB_IMAGE:-provide_dockerhub_image_name}" MEMGRAPH_LAST_RC_DIRECT_DOCKER_IMAGE_ARM="${MEMGRAPH_LAST_RC_DIRECT_DOCKER_IMAGE_ARM:-provide_https_download_link}" MEMGRAPH_NEXT_RC_DIRECT_DOCKER_IMAGE_ARM="${MEMGRAPH_NEXT_RC_DIRECT_DOCKER_IMAGE_ARM:-provide_https_download_link}" MEMGRAPH_LAST_RC_DIRECT_DOCKER_IMAGE_X86="${MEMGRAPH_LAST_RC_DIRECT_DOCKER_IMAGE_X86:-provide_https_download_link}" MEMGRAPH_NEXT_RC_DIRECT_DOCKER_IMAGE_X86="${MEMGRAPH_NEXT_RC_DIRECT_DOCKER_IMAGE_X86:-provide_https_donwload_link}" -MEMGRAPH_LAST_DOCKERHUB_IMAGE="${MEMGRAPH_LAST_DOCKERHUB_IMAGE:-provide_dockerhub_image_name}" -MEMGRAPH_NEXT_DOCKERHUB_IMAGE="${MEMGRAPH_NEXT_DOCKERHUB_IMAGE:-provide_dockerhub_image_name}" print_help_and_exit_unsuccessfully() { echo "It's required to define the following environment variables:" @@ -75,7 +74,7 @@ wait_for_memgraph() { __max_retries=${3:-100} __retries=0 while ! echo "RETURN 1;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port > /dev/null 2>&1; do - sleep 0.2 + sleep 0.3 __retries=$((__retries+1)) if [ "$__retries" -ge "$__max_retries" ]; then echo "wait_for_memgraph: Reached max retries ($__max_retries) for $__host:$__port" @@ -91,7 +90,7 @@ wait_for_memgraph_coordinator() { __max_retries=${3:-100} __retries=0 while ! echo "SHOW INSTANCE;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port > /dev/null 2>&1; do - sleep 0.2 + sleep 0.3 __retries=$((__retries+1)) if [ "$__retries" -ge "$__max_retries" ]; then echo "wait_for_memgraph_coordinator: Reached max retries ($__max_retries) for $__host:$__port" @@ -101,6 +100,22 @@ wait_for_memgraph_coordinator() { return 0 } +wait_for_memgraph_main() { + __host=$1 + __port=$2 + __max_retries=${3:-20} + __retries=0 + while ! echo "SHOW REPLICATION ROLE;" | $MEMGRAPH_CONSOLE_BINARY --host $__host --port $__port --output-format=csv | python3 $SCRIPT_DIR/../validator.py validate_is_main > /dev/null 2>&1; do + sleep 0.3 + __retries=$((__retries+1)) + if [ "$__retries" -ge "$__max_retries" ]; then + echo "wait_for_memgraph_main: Reached max retries ($__max_retries) for $__host:$__port" + return 1 + fi + done + return 0 +} + run_memgraph_binary() { # note: printing anything is tricky if this is called under $(...). __args="$1" @@ -266,12 +281,11 @@ with_kubectl_portforward() ( log=$(mktemp) kubectl port-forward "$target" "$map" >/dev/null 2>>"$log" & pf_pid=$! - # NOTE: port-forward doesn't have built-in timeout. The target process + # NOTE: port-forward doesn't have built-in timeout + the target process # might take arbitrary time to initialize. -> The only way to know if # everything is right in the shortest amount of time is to inject the - # probe as one of the required params. - # TODO(gitbuda): If this is lower (depending how much), wait_for_coordinator fails or MAIN is not elected in the cluster yet... -> FIX - sleep 1 + # target process probe as one of the required params. + sleep 0.3 if ! eval "$probe"; then kill -9 "$pf_pid" 2>/dev/null || true wait "$pf_pid" 2>/dev/null || true diff --git a/smoke-release-testing/validator.py b/smoke-release-testing/validator.py index f9ba458db..aac2f6f60 100644 --- a/smoke-release-testing/validator.py +++ b/smoke-release-testing/validator.py @@ -16,12 +16,18 @@ def validate_first_as_int(data, field, expected_value): def get_main_parser(data): - main_addr=None + main_addr = None for instance in data: if instance["role"] == '"main"': - main_addr=instance["management_server"][1:-1].split(".")[0] + main_addr = instance["management_server"][1:-1].split(".")[0] print(main_addr) + +def validate_is_main(data): + assert len(data) == 1 + assert data[0]["replication role"] == '"main"' + + def validate_number_of_results(data, expected): assert len(data) == int(expected) @@ -44,9 +50,8 @@ def get_arguments(): "-e", "--expected", help="Expected value", required=True ) - subparsers.add_parser( - "get_main_parser", help="Get main parser" - ) + subparsers.add_parser("get_main_parser", help="Get main parser") + subparsers.add_parser("validate_is_main", help="Validate if data instance is main") validate_number_of_results_parser = subparsers.add_parser( "validate_number_of_results", help="Get the number of results" @@ -66,5 +71,7 @@ def get_arguments(): validate_first_as_int(data, args.field, args.expected) if args.action == "get_main_parser": get_main_parser(data) + if args.action == "validate_is_main": + validate_is_main(data) if args.action == "validate_number_of_results": validate_number_of_results(data, args.expected) From c971e357bd23205ebf3c686404b41826bd8f05f2 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Sun, 20 Jul 2025 19:56:38 +0200 Subject: [PATCH 19/19] Final cleanup --- smoke-release-testing/k8s/run.bash | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/smoke-release-testing/k8s/run.bash b/smoke-release-testing/k8s/run.bash index ae2d658d7..86f3e4294 100755 --- a/smoke-release-testing/k8s/run.bash +++ b/smoke-release-testing/k8s/run.bash @@ -65,7 +65,7 @@ validate_nodes_against_main() { source $SCRIPT_DIR/mg_main.out with_kubectl_portforward "$MG_MAIN-0" 17687:7687 'wait_for_memgraph localhost 17687 5' -- \ "echo \"MATCH (n) RETURN n;\" | $MEMGRAPH_CONSOLE_BINARY --port 17687 --output-format=csv | python3 $SCRIPT_DIR/../validator.py validate_number_of_results -e $expected" - + echo "validate_nodes_against_main PASSED" } test_k8s_single() { @@ -177,7 +177,4 @@ if [ "${BASH_SOURCE[0]}" -ef "$0" ]; then # How to inject local version of the helm chart because we want to test any local fixes upfront. # test_k8s_ha NEXT ~/Workspace/code/memgraph/helm-charts/charts/memgraph-high-availability - - # helm_install_myhadb "memgraph/memgraph-high-availability" "3.4.0" - # wait_for_memgraph_main localhost 17687 5 fi