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 &