go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/projects/nodes/_temporal/auto-setup.sh (about) 1 #!/bin/bash 2 3 set -eu -o pipefail 4 5 echo "--------------------------" 6 echo "| Customized Auto-Setup |" 7 echo "--------------------------" 8 9 # === Auto setup defaults === 10 11 DB="${DB:-cassandra}" 12 SKIP_SCHEMA_SETUP="${SKIP_SCHEMA_SETUP:-false}" 13 14 # Cassandra 15 KEYSPACE="${KEYSPACE:-temporal}" 16 VISIBILITY_KEYSPACE="${VISIBILITY_KEYSPACE:-temporal_visibility}" 17 18 CASSANDRA_SEEDS="${CASSANDRA_SEEDS:-}" 19 CASSANDRA_PORT="${CASSANDRA_PORT:-9042}" 20 CASSANDRA_USER="${CASSANDRA_USER:-}" 21 CASSANDRA_PASSWORD="${CASSANDRA_PASSWORD:-}" 22 CASSANDRA_TLS_ENABLED="${CASSANDRA_TLS_ENABLED:-}" 23 CASSANDRA_CERT="${CASSANDRA_CERT:-}" 24 CASSANDRA_CERT_KEY="${CASSANDRA_CERT_KEY:-}" 25 CASSANDRA_CA="${CASSANDRA_CA:-}" 26 CASSANDRA_REPLICATION_FACTOR="${CASSANDRA_REPLICATION_FACTOR:-1}" 27 28 # MySQL/PostgreSQL 29 DBNAME="${DBNAME:-temporal}" 30 VISIBILITY_DBNAME="${VISIBILITY_DBNAME:-temporal_visibility}" 31 DB_PORT="${DB_PORT:-3306}" 32 33 MYSQL_SEEDS="${MYSQL_SEEDS:-}" 34 MYSQL_USER="${MYSQL_USER:-}" 35 MYSQL_PWD="${MYSQL_PWD:-}" 36 MYSQL_TX_ISOLATION_COMPAT="${MYSQL_TX_ISOLATION_COMPAT:-false}" 37 38 POSTGRES_SEEDS="${POSTGRES_SEEDS:-}" 39 POSTGRES_USER="${POSTGRES_USER:-}" 40 POSTGRES_PWD="${POSTGRES_PWD:-}" 41 # Don't create the DB instance 42 SKIP_POSTGRES_DB_CREATION="${SKIP_POSTGRES_DB_CREATION:-false}" 43 44 # Elasticsearch 45 ENABLE_ES="${ENABLE_ES:-false}" 46 ES_SCHEME="${ES_SCHEME:-http}" 47 ES_SEEDS="${ES_SEEDS:-}" 48 ES_PORT="${ES_PORT:-9200}" 49 ES_USER="${ES_USER:-}" 50 ES_PWD="${ES_PWD:-}" 51 ES_VERSION="${ES_VERSION:-v7}" 52 ES_VIS_INDEX="${ES_VIS_INDEX:-temporal_visibility_v1_dev}" 53 ES_SCHEMA_SETUP_TIMEOUT_IN_SECONDS="${ES_SCHEMA_SETUP_TIMEOUT_IN_SECONDS:-0}" 54 55 # Server setup 56 TEMPORAL_CLI_ADDRESS="${TEMPORAL_CLI_ADDRESS:-}" 57 58 SKIP_DEFAULT_NAMESPACE_CREATION="${SKIP_DEFAULT_NAMESPACE_CREATION:-false}" 59 DEFAULT_NAMESPACE="${DEFAULT_NAMESPACE:-default}" 60 DEFAULT_NAMESPACE_RETENTION=${DEFAULT_NAMESPACE_RETENTION:-1} 61 62 SKIP_ADD_CUSTOM_SEARCH_ATTRIBUTES="${SKIP_ADD_CUSTOM_SEARCH_ATTRIBUTES:-false}" 63 64 # === Main database functions === 65 66 validate_db_env() { 67 if [ "${DB}" == "mysql" ]; then 68 if [ -z "${MYSQL_SEEDS}" ]; then 69 echo "MYSQL_SEEDS env must be set if DB is ${DB}." 70 exit 1 71 fi 72 elif [ "${DB}" == "postgresql" ]; then 73 if [ -z "${POSTGRES_SEEDS}" ]; then 74 echo "POSTGRES_SEEDS env must be set if DB is ${DB}." 75 exit 1 76 fi 77 elif [ "${DB}" == "cassandra" ]; then 78 if [ -z "${CASSANDRA_SEEDS}" ]; then 79 echo "CASSANDRA_SEEDS env must be set if DB is ${DB}." 80 exit 1 81 fi 82 else 83 echo "Unsupported DB type: ${DB}." 84 exit 1 85 fi 86 } 87 88 wait_for_cassandra() { 89 # TODO (alex): Remove exports 90 export CASSANDRA_USER=${CASSANDRA_USER} 91 export CASSANDRA_PORT=${CASSANDRA_PORT} 92 export CASSANDRA_ENABLE_TLS=${CASSANDRA_TLS_ENABLED} 93 export CASSANDRA_TLS_CERT=${CASSANDRA_CERT} 94 export CASSANDRA_TLS_KEY=${CASSANDRA_CERT_KEY} 95 export CASSANDRA_TLS_CA=${CASSANDRA_CA} 96 97 { export CASSANDRA_PASSWORD=${CASSANDRA_PASSWORD}; } 2> /dev/null 98 99 until temporal-cassandra-tool --ep "${CASSANDRA_SEEDS}" validate-health; do 100 echo 'Waiting for Cassandra to start up.' 101 sleep 1 102 done 103 echo 'Cassandra started.' 104 } 105 106 wait_for_mysql() { 107 until nc -z "${MYSQL_SEEDS%%,*}" "${DB_PORT}"; do 108 echo 'Waiting for MySQL to start up.' 109 sleep 1 110 done 111 112 echo 'MySQL started.' 113 } 114 115 wait_for_postgres() { 116 until nc -z "${POSTGRES_SEEDS%%,*}" "${DB_PORT}"; do 117 echo 'Waiting for PostgreSQL to startup.' 118 sleep 1 119 done 120 121 echo 'PostgreSQL started.' 122 } 123 124 wait_for_db() { 125 if [ "${DB}" == "mysql" ]; then 126 wait_for_mysql 127 elif [ "${DB}" == "postgresql" ]; then 128 wait_for_postgres 129 elif [ "${DB}" == "cassandra" ]; then 130 wait_for_cassandra 131 else 132 echo "Unsupported DB type: ${DB}." 133 exit 1 134 fi 135 } 136 137 setup_cassandra_schema() { 138 # TODO (alex): Remove exports 139 export CASSANDRA_USER=${CASSANDRA_USER} 140 export CASSANDRA_PORT=${CASSANDRA_PORT} 141 export CASSANDRA_ENABLE_TLS=${CASSANDRA_TLS_ENABLED} 142 export CASSANDRA_TLS_CERT=${CASSANDRA_CERT} 143 export CASSANDRA_TLS_KEY=${CASSANDRA_CERT_KEY} 144 export CASSANDRA_TLS_CA=${CASSANDRA_CA} 145 146 { export CASSANDRA_PASSWORD=${CASSANDRA_PASSWORD}; } 2> /dev/null 147 148 SCHEMA_DIR=${TEMPORAL_HOME}/schema/cassandra/temporal/versioned 149 temporal-cassandra-tool --ep "${CASSANDRA_SEEDS}" create -k "${KEYSPACE}" --rf "${CASSANDRA_REPLICATION_FACTOR}" 150 temporal-cassandra-tool --ep "${CASSANDRA_SEEDS}" -k "${KEYSPACE}" setup-schema -v 0.0 151 temporal-cassandra-tool --ep "${CASSANDRA_SEEDS}" -k "${KEYSPACE}" update-schema -d "${SCHEMA_DIR}" 152 153 VISIBILITY_SCHEMA_DIR=${TEMPORAL_HOME}/schema/cassandra/visibility/versioned 154 temporal-cassandra-tool --ep "${CASSANDRA_SEEDS}" create -k "${VISIBILITY_KEYSPACE}" --rf "${CASSANDRA_REPLICATION_FACTOR}" 155 temporal-cassandra-tool --ep "${CASSANDRA_SEEDS}" -k "${VISIBILITY_KEYSPACE}" setup-schema -v 0.0 156 temporal-cassandra-tool --ep "${CASSANDRA_SEEDS}" -k "${VISIBILITY_KEYSPACE}" update-schema -d "${VISIBILITY_SCHEMA_DIR}" 157 } 158 159 setup_mysql_schema() { 160 # TODO (alex): Remove exports 161 { export SQL_PASSWORD=${MYSQL_PWD}; } 2> /dev/null 162 163 if [ "${MYSQL_TX_ISOLATION_COMPAT}" == "true" ]; then 164 MYSQL_CONNECT_ATTR=(--connect-attributes "tx_isolation=READ-COMMITTED") 165 else 166 MYSQL_CONNECT_ATTR=() 167 fi 168 169 SCHEMA_DIR=${TEMPORAL_HOME}/schema/mysql/v57/temporal/versioned 170 temporal-sql-tool --ep "${MYSQL_SEEDS}" -u "${MYSQL_USER}" "${MYSQL_CONNECT_ATTR[@]}" create --db "${DBNAME}" 171 temporal-sql-tool --ep "${MYSQL_SEEDS}" -u "${MYSQL_USER}" "${MYSQL_CONNECT_ATTR[@]}" --db "${DBNAME}" setup-schema -v 0.0 172 temporal-sql-tool --ep "${MYSQL_SEEDS}" -u "${MYSQL_USER}" "${MYSQL_CONNECT_ATTR[@]}" --db "${DBNAME}" update-schema -d "${SCHEMA_DIR}" 173 VISIBILITY_SCHEMA_DIR=${TEMPORAL_HOME}/schema/mysql/v57/visibility/versioned 174 temporal-sql-tool --ep "${MYSQL_SEEDS}" -u "${MYSQL_USER}" "${MYSQL_CONNECT_ATTR[@]}" create --db "${VISIBILITY_DBNAME}" 175 temporal-sql-tool --ep "${MYSQL_SEEDS}" -u "${MYSQL_USER}" "${MYSQL_CONNECT_ATTR[@]}" --db "${VISIBILITY_DBNAME}" setup-schema -v 0.0 176 temporal-sql-tool --ep "${MYSQL_SEEDS}" -u "${MYSQL_USER}" "${MYSQL_CONNECT_ATTR[@]}" --db "${VISIBILITY_DBNAME}" update-schema -d "${VISIBILITY_SCHEMA_DIR}" 177 } 178 179 setup_postgres_schema() { 180 # TODO (alex): Remove exports 181 { export SQL_PASSWORD=${POSTGRES_PWD}; } 2> /dev/null 182 183 SCHEMA_DIR=${TEMPORAL_HOME}/schema/postgresql/v96/temporal/versioned 184 # Create database only if its name is different from the user name. Otherwise PostgreSQL container itself will create database. 185 if [[ "${DBNAME}" != "${POSTGRES_USER}" && "${SKIP_POSTGRES_DB_CREATION}" != true ]]; then 186 temporal-sql-tool --plugin postgres --ep "${POSTGRES_SEEDS}" -u "${POSTGRES_USER}" -p "${DB_PORT}" create --db "${DBNAME}" 187 fi 188 temporal-sql-tool --plugin postgres --ep "${POSTGRES_SEEDS}" -u "${POSTGRES_USER}" -p "${DB_PORT}" --db "${DBNAME}" setup-schema -v 0.0 189 temporal-sql-tool --plugin postgres --ep "${POSTGRES_SEEDS}" -u "${POSTGRES_USER}" -p "${DB_PORT}" --db "${DBNAME}" update-schema -d "${SCHEMA_DIR}" 190 191 { export SQL_PASSWORD=${VISIBILITY_POSTGRES_PWD}; } 2> /dev/null 192 VISIBILITY_SCHEMA_DIR=${TEMPORAL_HOME}/schema/postgresql/v96/visibility/versioned 193 if [[ "${VISIBILITY_DBNAME}" != "${POSTGRES_USER}" && "${SKIP_POSTGRES_DB_CREATION}" != true ]]; then 194 temporal-sql-tool --plugin postgres --ep "${VISIBILITY_POSTGRES_SEEDS}" -u "${VISIBILITY_POSTGRES_USER}" -p "${VISIBILITY_DB_PORT}" create --db "${VISIBILITY_DBNAME}" 195 fi 196 temporal-sql-tool --plugin postgres --ep "${VISIBILITY_POSTGRES_SEEDS}" -u "${VISIBILITY_POSTGRES_USER}" -p "${VISIBILITY_DB_PORT}" --db "${VISIBILITY_DBNAME}" setup-schema -v 0.0 197 temporal-sql-tool --plugin postgres --ep "${VISIBILITY_POSTGRES_SEEDS}" -u "${VISIBILITY_POSTGRES_USER}" -p "${VISIBILITY_DB_PORT}" --db "${VISIBILITY_DBNAME}" update-schema -d "${VISIBILITY_SCHEMA_DIR}" 198 } 199 200 setup_schema() { 201 if [ "${DB}" == "mysql" ]; then 202 echo 'Setup MySQL schema.' 203 setup_mysql_schema 204 elif [ "${DB}" == "postgresql" ]; then 205 echo 'Setup PostgreSQL schema.' 206 setup_postgres_schema 207 else 208 echo 'Setup Cassandra schema.' 209 setup_cassandra_schema 210 fi 211 } 212 213 # === Elasticsearch functions === 214 215 validate_es_env() { 216 if [ "${ENABLE_ES}" == true ]; then 217 if [ -z "${ES_SEEDS}" ]; then 218 echo "ES_SEEDS env must be set if ENABLE_ES is ${ENABLE_ES}" 219 exit 1 220 fi 221 fi 222 } 223 224 wait_for_es() { 225 SECONDS=0 226 227 ES_SERVER="${ES_SCHEME}://${ES_SEEDS%%,*}:${ES_PORT}" 228 229 until curl --silent --fail --user "${ES_USER}":"${ES_PWD}" "${ES_SERVER}" > /dev/null 2>&1; do 230 DURATION=${SECONDS} 231 232 if [ "${ES_SCHEMA_SETUP_TIMEOUT_IN_SECONDS}" -gt 0 ] && [ ${DURATION} -ge "${ES_SCHEMA_SETUP_TIMEOUT_IN_SECONDS}" ]; then 233 echo 'WARNING: timed out waiting for Elasticsearch to start up. Skipping index creation.' 234 return; 235 fi 236 237 echo 'Waiting for Elasticsearch to start up.' 238 sleep 1 239 done 240 241 echo 'Elasticsearch started.' 242 } 243 244 setup_es_index() { 245 ES_SERVER="${ES_SCHEME}://${ES_SEEDS%%,*}:${ES_PORT}" 246 # @@@SNIPSTART setup-es-template-commands 247 # ES_SERVER is the URL of Elasticsearch server i.e. "http://localhost:9200". 248 SETTINGS_URL="${ES_SERVER}/_cluster/settings" 249 SETTINGS_FILE=${TEMPORAL_HOME}/schema/elasticsearch/visibility/cluster_settings_${ES_VERSION}.json 250 TEMPLATE_URL="${ES_SERVER}/_template/temporal_visibility_v1_template" 251 SCHEMA_FILE=${TEMPORAL_HOME}/schema/elasticsearch/visibility/index_template_${ES_VERSION}.json 252 INDEX_URL="${ES_SERVER}/${ES_VIS_INDEX}" 253 curl --fail --user "${ES_USER}":"${ES_PWD}" -X PUT "${SETTINGS_URL}" -H "Content-Type: application/json" --data-binary "@${SETTINGS_FILE}" --write-out "\n" 254 curl --fail --user "${ES_USER}":"${ES_PWD}" -X PUT "${TEMPLATE_URL}" -H 'Content-Type: application/json' --data-binary "@${SCHEMA_FILE}" --write-out "\n" 255 curl --user "${ES_USER}":"${ES_PWD}" -X PUT "${INDEX_URL}" --write-out "\n" 256 # @@@SNIPEND 257 } 258 259 # === Server setup === 260 261 register_default_namespace() { 262 echo "Registering default namespace: ${DEFAULT_NAMESPACE}." 263 if ! tctl --ns "${DEFAULT_NAMESPACE}" namespace describe; then 264 echo "Default namespace ${DEFAULT_NAMESPACE} not found. Creating..." 265 tctl --ns "${DEFAULT_NAMESPACE}" namespace register --rd "${DEFAULT_NAMESPACE_RETENTION}" --desc "Default namespace for Temporal Server." 266 echo "Default namespace ${DEFAULT_NAMESPACE} registration complete." 267 else 268 echo "Default namespace ${DEFAULT_NAMESPACE} already registered." 269 fi 270 } 271 272 add_custom_search_attributes() { 273 echo "Adding Custom*Field search attributes." 274 # TODO: Remove CustomStringField 275 # @@@SNIPSTART add-custom-search-attributes-for-testing-command 276 tctl --auto_confirm admin cluster add-search-attributes \ 277 --name CustomKeywordField --type Keyword \ 278 --name CustomStringField --type Text \ 279 --name CustomTextField --type Text \ 280 --name CustomIntField --type Int \ 281 --name CustomDatetimeField --type Datetime \ 282 --name CustomDoubleField --type Double \ 283 --name CustomBoolField --type Bool 284 # @@@SNIPEND 285 } 286 287 setup_server(){ 288 echo "Temporal CLI address: ${TEMPORAL_CLI_ADDRESS}." 289 290 until tctl cluster health | grep SERVING; do 291 echo "Waiting for Temporal server to start..." 292 sleep 1 293 done 294 295 echo "Temporal server started." 296 297 if [ "${SKIP_DEFAULT_NAMESPACE_CREATION}" != true ]; then 298 register_default_namespace 299 fi 300 301 if [ "${SKIP_ADD_CUSTOM_SEARCH_ATTRIBUTES}" != true ]; then 302 add_custom_search_attributes 303 fi 304 } 305 306 # === Main === 307 308 if [ "${SKIP_SCHEMA_SETUP}" != true ]; then 309 validate_db_env 310 wait_for_db 311 setup_schema 312 fi 313 314 if [ "${ENABLE_ES}" == true ]; then 315 validate_es_env 316 wait_for_es 317 setup_es_index 318 fi 319 320 # Run this func in parallel process. It will wait for server to start and then run required steps. 321 setup_server &