|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +# Sets up a multi-node Citus cluster, creates a distributed table, |
| 4 | +# rebalances shards, and verifies even distribution. |
| 5 | +# |
| 6 | +# Note: need to run this as root |
| 7 | +# |
| 8 | +# Usage: test_basics.sh <expected_pg_major_version> <expected_citus_full_version> <pg_binary_path> |
| 9 | +# Example: test_basics.sh 18 14.0.0 /usr/lib/postgresql/17/bin |
| 10 | + |
| 11 | +set -euo pipefail |
| 12 | + |
| 13 | +if [ "$#" -ne 3 ]; then |
| 14 | + echo "Error: some arguments are missing." >&2 |
| 15 | + echo "Usage: $0 <expected_pg_major_version> <expected_citus_full_version> <pg_binary_path>" >&2 |
| 16 | + exit 1 |
| 17 | +fi |
| 18 | + |
| 19 | +EXPECTED_PG_MAJOR_VERSION="$1" |
| 20 | +EXPECTED_CITUS_FULL_VERSION="$2" |
| 21 | +PG_BIN="$3" |
| 22 | + |
| 23 | +## constants and helpers |
| 24 | + |
| 25 | +NODE_COUNT=3 |
| 26 | +SHARDS_PER_NODE=5 |
| 27 | +FIRST_NODE_PORT=9700 |
| 28 | + |
| 29 | +run_psql_cmd() { |
| 30 | + if [ "$#" -ne 2 ]; then |
| 31 | + echo "Error: some arguments are missing." >&2 |
| 32 | + echo "Usage: run_psql_cmd <port_number> <sql_command>" >&2 |
| 33 | + exit 1 |
| 34 | + fi |
| 35 | + |
| 36 | + PORT_NUMBER="$1" |
| 37 | + SQL_COMMAND="$2" |
| 38 | + |
| 39 | + su - postgres -c "${PG_BIN}/psql -X -qAt -p ${PORT_NUMBER} -c \"${SQL_COMMAND}\"" |
| 40 | +} |
| 41 | + |
| 42 | +## initialize all nodes and create citus extension on them |
| 43 | + |
| 44 | +echo "Initializing nodes and creating citus extension on them ..." |
| 45 | + |
| 46 | +mkdir -p /test_cluster |
| 47 | +chown postgres:postgres /test_cluster |
| 48 | +chmod 755 /test_cluster |
| 49 | + |
| 50 | +for i in $(seq 0 $((NODE_COUNT - 1))); do |
| 51 | + node_name="node${i}" |
| 52 | + echo "Creating node: $node_name" |
| 53 | + |
| 54 | + su - postgres -c "mkdir -p /test_cluster/${node_name}" |
| 55 | + |
| 56 | + port_number=$((FIRST_NODE_PORT + i)) |
| 57 | + |
| 58 | + su - postgres -c "${PG_BIN}/initdb -D /test_cluster/${node_name}" |
| 59 | + su - postgres -c "echo \"shared_preload_libraries = 'citus'\" >> /test_cluster/${node_name}/postgresql.conf" |
| 60 | + su - postgres -c "${PG_BIN}/pg_ctl -D /test_cluster/${node_name} -o \"-p $port_number\" -l /test_cluster/${node_name}/logfile start" |
| 61 | + run_psql_cmd "$port_number" "CREATE EXTENSION citus;" |
| 62 | +done |
| 63 | + |
| 64 | +## verify PG version |
| 65 | + |
| 66 | +pg_version=$(run_psql_cmd "$FIRST_NODE_PORT" "SELECT version();") |
| 67 | +if [[ "$pg_version" != "PostgreSQL ${EXPECTED_PG_MAJOR_VERSION}."* ]]; then |
| 68 | + echo "Error: PostgreSQL version verification failed. Expected version to start with 'PostgreSQL ${EXPECTED_PG_MAJOR_VERSION}.', got: $pg_version" >&2 |
| 69 | + exit 1 |
| 70 | +else |
| 71 | + echo "Verified PostgreSQL version: $pg_version" |
| 72 | +fi |
| 73 | + |
| 74 | +## verify Citus extension version |
| 75 | + |
| 76 | +citus_version=$(run_psql_cmd "$FIRST_NODE_PORT" "SHOW citus.version;") |
| 77 | +if [[ "$citus_version" != "${EXPECTED_CITUS_FULL_VERSION}"* ]]; then |
| 78 | + echo "Error: Citus version verification failed. Expected version to start with '${EXPECTED_CITUS_FULL_VERSION}', got: $citus_version" >&2 |
| 79 | + exit 1 |
| 80 | +else |
| 81 | + echo "Verified Citus version: $citus_version" |
| 82 | +fi |
| 83 | + |
| 84 | +## create a distributed table |
| 85 | + |
| 86 | +echo "Creating a distributed table ..." |
| 87 | + |
| 88 | +shard_count=$((NODE_COUNT * SHARDS_PER_NODE)) |
| 89 | +run_psql_cmd "$FIRST_NODE_PORT" "CREATE TABLE test_table (id INT); SELECT create_distributed_table('test_table', 'id', shard_count => $shard_count);" |
| 90 | + |
| 91 | +## add worker nodes |
| 92 | + |
| 93 | +echo "Adding worker nodes ..." |
| 94 | + |
| 95 | +for i in $(seq 1 $((NODE_COUNT - 1))); do |
| 96 | + port_number=$((FIRST_NODE_PORT + i)) |
| 97 | + run_psql_cmd "$FIRST_NODE_PORT" "SELECT citus_add_node('localhost', $port_number);" |
| 98 | +done |
| 99 | + |
| 100 | +## run rebalancer |
| 101 | + |
| 102 | +echo "Running shard rebalancer ..." |
| 103 | + |
| 104 | +run_psql_cmd "$FIRST_NODE_PORT" "SELECT rebalance_table_shards(shard_transfer_mode =>'block_writes');" |
| 105 | + |
| 106 | +## verify that shards are distributed evenly across nodes |
| 107 | + |
| 108 | +echo "Verifying that shards are distributed evenly across nodes ..." |
| 109 | + |
| 110 | +result=$( |
| 111 | + run_psql_cmd "$FIRST_NODE_PORT" " |
| 112 | + SELECT bool_and(cnt = $SHARDS_PER_NODE) |
| 113 | + FROM ( |
| 114 | + SELECT nodeport, |
| 115 | + COUNT(shardid) AS cnt |
| 116 | + FROM pg_dist_node |
| 117 | + LEFT JOIN pg_dist_shard_placement USING (nodeport) |
| 118 | + GROUP BY nodeport |
| 119 | + ) t; |
| 120 | + " |
| 121 | +) |
| 122 | + |
| 123 | +if [ "$result" = "t" ]; then |
| 124 | + echo "Verified cluster creation, distributed table creation and shard rebalancing. Shards are distributed evenly across nodes." |
| 125 | +else |
| 126 | + echo "Error: Failed. Shards are not distributed evenly across nodes, see below for details:" >&2 |
| 127 | + run_psql_cmd "$FIRST_NODE_PORT" " |
| 128 | + SELECT nodeport, |
| 129 | + COUNT(shardid) AS cnt |
| 130 | + FROM pg_dist_node |
| 131 | + LEFT JOIN pg_dist_shard_placement USING (nodeport) |
| 132 | + GROUP BY nodeport; |
| 133 | + " |
| 134 | + exit 1 |
| 135 | +fi |
0 commit comments