Setting up disaster recovery for Metric Anomaly Detection

Learn how to set up disaster recovery for Metric Anomaly Detection.

About this task

This script must be run on a Linux® host with the following tools installed (the tools are preinstalled or available on RHEL 8 hosts):
  • bash
  • curl
  • jq

Procedure

  1. Run the steps mentioned in Kubernetes secret synchronization.
  2. Run the steps mentioned in Exposing Apache CouchDB.
  3. Save the script as couchdbReplication.sh on the local disk and set the executable part as chmod u+x couchdbReplication.sh.
    #!/bin/bash
    #/************************************************* {COPYRIGHT-TOP} ****
    #* Licensed Materials - Property of IBM
    #*
    #* "Restricted Materials of IBM"
    #*
    #* © Copyright IBM Corp. 2022  All Rights Reserved.
    #*
    #* 5725-Q09
    #*
    #* US Government Users Restricted Rights - Use, duplication, or
    #* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
    #************************************************** {COPYRIGHT-END} ****/
    # This script can be used to configure a bidirectional replication between two sides of RBA.
    # If variables are exported and valid, the script will not prompt for values, otherwise an
    # interactive wizard will prompt for missing values.
    # Credentials can be defined individually per side, if they change, the setup needs to be repeated.
    
    # Headless mode:
    # export RBA_DB_URL_SIDE_A="https://rba-geo-1.company.com:6984"
    # export RBA_DB_USER_SIDE_A="xxx"
    # export RBA_DB_PW_SIDE_A="xxx"
    # export RBA_DB_URL_SIDE_B="https://rba-geo-2.company.com:6984"
    # export RBA_DB_USER_SIDE_B="xxx"
    # export RBA_DB_PW_SIDE_B="xxx"
    # ./couchdbReplication.sh setup|delete
    
    ACTION="${1}"
    
    # ensure only allowed actions are defined
    if [[ "${ACTION}" != "setup" ]] && [[ "${ACTION}" != "delete" ]]; then
        echo "Usage: ./couchdbReplication.sh setup|delete"
        exit 1
    fi
    
    set -e
    echo "================ RBA Replication Setup ================"
    echo "Running in ${ACTION} mode"
    
    # validate that prerequisites are available
    if ! command -v jq &> /dev/null; then
        echo "jq could not be found"
        exit
    fi
    
    if ! command -v curl &> /dev/null; then
        echo "curl could not be found"
        exit
    fi
    
    ######################################################################
    # side A config setup
    while true; do
        if [[ -z "${RBA_DB_URL_SIDE_A}" ]]; then
            echo -n "CouchDB URL side A: "
            read -r RBA_DB_URL_SIDE_A
            if [[ -z "${RBA_DB_URL_SIDE_A}" ]]; then
                echo "CouchDB URL cannot be empty"
                continue
            fi
        fi
    
        if [[ -z "${RBA_DB_USER_SIDE_A}" ]]; then
            echo -n "CouchDB username side A: "
            read -r RBA_DB_USER_SIDE_A
            if [[ -z "${RBA_DB_USER_SIDE_A}" ]]; then
                echo "CouchDB username cannot be empty"
                continue
            fi
        fi
    
        if [[ -z "${RBA_DB_PW_SIDE_A}" ]]; then
            echo -n "CouchDB password side A: "
            read -rs RBA_DB_PW_SIDE_A
            echo ""
            if [[ -z "${RBA_DB_PW_SIDE_A}" ]]; then
                echo "CouchDB password cannot be emtpy"
                continue
            fi
        fi
    
        # side A config validation
        set +e
        RBA_COUCHDB_STATUS=$(curl -k -sL -w "%{http_code}\\n" -u "${RBA_DB_USER_SIDE_A}:${RBA_DB_PW_SIDE_A}" "${RBA_DB_URL_SIDE_A}" -o /dev/null)
        set -e
        if [[ "200" == "${RBA_COUCHDB_STATUS}" ]]; then
            echo "CouchDB on side A is accessible"
    
            # the check if databases are initialized is only important to setup a replication, not to delete it
            if [[ "${ACTION}" == "setup" ]] ; then
                echo "Detecting runbook automation databases"
                RBA_COUCHDB_ALL_DBS=$(curl -k -s -u "${RBA_DB_USER_SIDE_A}:${RBA_DB_PW_SIDE_A}" "${RBA_DB_URL_SIDE_A}/_all_dbs" | jq -r '.[]')
                # only include dbs with the string rba (excludes _global_changes, _replicator and _users or other potential non-rba dbs)
                # RBA_DB_NAMES=$(echo "${RBA_COUCHDB_ALL_DBS}" | jq -r '.[] | select( . | test("(rba)"))')
                RBA_DB_NAMES=""
                for CURRENT_DB_NAME in ${RBA_COUCHDB_ALL_DBS}; do
                    if [[ ("${CURRENT_DB_NAME}" == *"rba"*  && "${CURRENT_DB_NAME}" != "rba-pdoc") || "${CURRENT_DB_NAME}" == "collabopsuser" ]]; then 
                        echo "replicate: ${CURRENT_DB_NAME}"
                        RBA_DB_NAMES="${RBA_DB_NAMES} ${CURRENT_DB_NAME}"
                    else
                        echo "skip: ${CURRENT_DB_NAME}"
                    fi
                done
    
                for CURRENT_DB_NAME in ${RBA_DB_NAMES}; do
                    echo "RBA db detected: ${CURRENT_DB_NAME}"
                    if [[ "${CURRENT_DB_NAME}" == "collabopsuser" ]]; then
                        break
                    fi
                    set +e
                    RBA_DESIGN_DOC_STATUS=$(curl -k -sL -w "%{http_code}\\n" -u "${RBA_DB_USER_SIDE_A}:${RBA_DB_PW_SIDE_A}" "${RBA_DB_URL_SIDE_A}/${CURRENT_DB_NAME}/_design/georedundancy" -o /dev/null)
                    set -e
                    if [[ "200" == "${RBA_DESIGN_DOC_STATUS}" ]]; then
                        echo "CouchDB design doc ${RBA_DB_URL_SIDE_A}/${CURRENT_DB_NAME}/_design/georedundancy is accessible"
                    else
                        echo "CouchDB design doc ${RBA_DB_URL_SIDE_A}/${CURRENT_DB_NAME}/_design/georedundancy is not accessible"
                        echo "Please ensure that the IBM Runbook Automation database is initialized on side A and rerun this script"
                        exit 1
                    fi
                done
            fi
            break;
        else
            echo "CouchDB could not be accessed: ${RBA_COUCHDB_STATUS}"
            # at least one of the following variables are incorrect,
            # resetting them to trigger new prompt on next loop execution
            unset RBA_DB_URL_SIDE_A RBA_DB_USER_SIDE_A RBA_DB_PW_SIDE_A
        fi
    done
    
    ######################################################################
    # side B config setup
    while true; do
        if [[ -z "${RBA_DB_URL_SIDE_B}" ]]; then
            echo -n "CouchDB URL side B: "
            read -r RBA_DB_URL_SIDE_B
            if [[ -z "${RBA_DB_URL_SIDE_B}" ]]; then
                echo "CouchDB URL cannot be emtpy"
                continue
            fi
        fi
    
        if [[ -z "${RBA_DB_USER_SIDE_B}" ]]; then
            echo -n "CouchDB username side B: "
            read -r RBA_DB_USER_SIDE_B
            if [[ -z "${RBA_DB_USER_SIDE_B}" ]]; then
                echo "CouchDB username cannot be emtpy"
                continue
            fi
        fi
    
        if [[ -z "${RBA_DB_PW_SIDE_B}" ]]; then
            echo -n "CouchDB password side B: "
            read -rs RBA_DB_PW_SIDE_B
            echo ""
            if [[ -z "${RBA_DB_PW_SIDE_B}" ]]; then
                echo "CouchDB password cannot be emtpy"
                continue
            fi
        fi
    
        # side B config validation
        set +e
        RBA_COUCHDB_STATUS=$(curl -k -sL -w "%{http_code}\\n" -u "${RBA_DB_USER_SIDE_B}:${RBA_DB_PW_SIDE_B}" "${RBA_DB_URL_SIDE_B}" -o /dev/null)
        set -e
        if [[ "200" == "${RBA_COUCHDB_STATUS}" ]]; then
            echo "CouchDB on side B is accessible"
            # Do not check if side B is initialized as the replication can create targets if necessary.
            # This will simplify the setup after a disaster.
            break;
        else
            echo "CouchDB could not be accessed: ${RBA_COUCHDB_STATUS}"
            # at least one of the following variables are incorrect,
            # resetting them to trigger new prompt on next loop execution
            unset RBA_DB_URL_SIDE_B RBA_DB_USER_SIDE_B RBA_DB_PW_SIDE_B
        fi
    done
    
    
    if [[ "${ACTION}" == "setup" ]] ; then
        ######################################################################
        # computing basic auth headers required for replication documents
        AUTH_HEADER_SIDE_A="Basic $(echo -ne "${RBA_DB_USER_SIDE_A}:${RBA_DB_PW_SIDE_A}" | base64)"
        AUTH_HEADER_SIDE_B="Basic $(echo -ne "${RBA_DB_USER_SIDE_B}:${RBA_DB_PW_SIDE_B}" | base64)"
    
        ######################################################################
        echo "Creating replication for Runbook Service Database"
    
        for CURRENT_DB_NAME in ${RBA_DB_NAMES}; do
            echo "Setting up replication: ${RBA_DB_URL_SIDE_A}/${CURRENT_DB_NAME} -> ${RBA_DB_URL_SIDE_B}/${CURRENT_DB_NAME}"
            echo "Deleting old replication if present, continuing if missing"
            # get old rev to delete document
            OLD_REV=$(curl \
                -k \
                -s \
                -X GET \
                -u "${RBA_DB_USER_SIDE_A}:${RBA_DB_PW_SIDE_A}" \
                "${RBA_DB_URL_SIDE_A}/_replicator/${CURRENT_DB_NAME}-georedundancy-replication" | jq -r "._rev")
    
            # delete document
            curl \
                -k \
                -s \
                -X DELETE \
                -u "${RBA_DB_USER_SIDE_A}:${RBA_DB_PW_SIDE_A}" \
                "${RBA_DB_URL_SIDE_A}/_replicator/${CURRENT_DB_NAME}-georedundancy-replication?rev=${OLD_REV}"
    
            # create document on side A pushing docs to side B
            if [[ "${CURRENT_DB_NAME}" == "collabopsuser" ]]; then
              echo "Creating replication"
              CREATE_REPLICATION_RBA_A_TO_B=$(curl \
                -k \
                -s \
                -X POST \
                -u "${RBA_DB_USER_SIDE_A}:${RBA_DB_PW_SIDE_A}" \
                -H "Content-Type: application/json" \
                "${RBA_DB_URL_SIDE_A}/_replicator" -d '
              {
                "_id": "'"${CURRENT_DB_NAME}"'-georedundancy-replication",
                "source": {
                    "url": "'"${RBA_DB_URL_SIDE_A}"'/'"${CURRENT_DB_NAME}"'",
                    "headers": {
                        "Authorization": "'"${AUTH_HEADER_SIDE_A}"'"
                    }
                },
                "target": {
                    "url": "'"${RBA_DB_URL_SIDE_B}"'/'"${CURRENT_DB_NAME}"'",
                    "headers": {
                        "Authorization": "'"${AUTH_HEADER_SIDE_B}"'"
                    }
                },
                "create_target": true,
                "continuous": true
              }')
            else
              echo "Creating replication"
              CREATE_REPLICATION_RBA_A_TO_B=$(curl \
                -k \
                -s \
                -X POST \
                -u "${RBA_DB_USER_SIDE_A}:${RBA_DB_PW_SIDE_A}" \
                -H "Content-Type: application/json" \
                "${RBA_DB_URL_SIDE_A}/_replicator" -d '
              {
                "_id": "'"${CURRENT_DB_NAME}"'-georedundancy-replication",
                "source": {
                    "url": "'"${RBA_DB_URL_SIDE_A}"'/'"${CURRENT_DB_NAME}"'",
                    "headers": {
                        "Authorization": "'"${AUTH_HEADER_SIDE_A}"'"
                    }
                },
                "target": {
                    "url": "'"${RBA_DB_URL_SIDE_B}"'/'"${CURRENT_DB_NAME}"'",
                    "headers": {
                        "Authorization": "'"${AUTH_HEADER_SIDE_B}"'"
                    }
                },
                "filter": "georedundancy/standard",
                "create_target": true,
                "continuous": true
              }')
            fi 
    
            # expected result: {"ok":true,"id":"rba-georedundancy-replication","rev":"1-9c73161d3485230f84ec12f0c922f5a3"}
            echo "${CREATE_REPLICATION_RBA_A_TO_B}"
            if [[ "$(echo "${CREATE_REPLICATION_RBA_A_TO_B}" | jq ".ok")" ]] ; then
                echo "Replication for ${CURRENT_DB_NAME} from side A to B was configured successfully"
            else
                echo "Failed to setup replication for ${CURRENT_DB_NAME} from side A to B"
                exit 1
            fi
    
            ######################################################################
            echo "${RBA_DB_URL_SIDE_B}/${CURRENT_DB_NAME} -> ${RBA_DB_URL_SIDE_A}/${CURRENT_DB_NAME}"
            echo "Deleting old replication if present, continuing if missing"
            # get old rev to delete document
            OLD_REV=$(curl \
                -k \
                -s \
                -X GET \
                -u "${RBA_DB_USER_SIDE_B}:${RBA_DB_PW_SIDE_B}" \
                "${RBA_DB_URL_SIDE_B}/_replicator/${CURRENT_DB_NAME}-georedundancy-replication" | jq -r "._rev")
    
            # delete document
            curl \
                -k \
                -s \
                -X DELETE \
                -u "${RBA_DB_USER_SIDE_B}:${RBA_DB_PW_SIDE_B}" \
                "${RBA_DB_URL_SIDE_B}/_replicator/${CURRENT_DB_NAME}-georedundancy-replication?rev=${OLD_REV}"
    
            # create document on side B pushing docs to side A
            echo "Creating replication document"
            CREATE_REPLICATION_RBA_B_TO_A=$(curl \
                -k \
                -s \
                -X POST \
                -u "${RBA_DB_USER_SIDE_B}:${RBA_DB_PW_SIDE_B}" \
                -H "Content-Type: application/json" \
                "${RBA_DB_URL_SIDE_B}/_replicator" -d '
            {
                "_id": "'"${CURRENT_DB_NAME}"'-georedundancy-replication",
                "source": {
                    "url": "'"${RBA_DB_URL_SIDE_B}"'/'"${CURRENT_DB_NAME}"'",
                    "headers": {
                        "Authorization": "'"${AUTH_HEADER_SIDE_B}"'"
                    }
                },
                "target": {
                    "url": "'"${RBA_DB_URL_SIDE_A}"'/'"${CURRENT_DB_NAME}"'",
                    "headers": {
                        "Authorization": "'"${AUTH_HEADER_SIDE_A}"'"
                    }
                },
                "filter": "georedundancy/standard",
                "create_target": true,
                "continuous": true
            }')
            echo "${CREATE_REPLICATION_RBA_B_TO_A}"
    
            # expected result: {"ok":true,"id":"rba-georedundancy-replication","rev":"1-9c73161d3485230f84ec12f0c922f5a3"}
            echo "${CREATE_REPLICATION_RBA_B_TO_A}"
            if [[ "$(echo "${CREATE_REPLICATION_RBA_B_TO_A}" | jq ".ok")" ]] ; then
                echo "Replication for ${CURRENT_DB_NAME} from side B to A was configured successfully"
            else
                echo "Failed to setup replication for ${CURRENT_DB_NAME} from side B to A"
                exit 1
            fi
        done
    
        echo "Replication setup completed, displaying replication status"
    else
        function deleteRbaReplications {
            CURRENT_DB_SERVER=${1}
            CURRENT_DB_USER=${2}
            CURRENT_DB_PW=${3}
            echo "Detecting runbook automation replications on ${CURRENT_DB_SERVER}"
            COUCHDB_REPLICATIONS=$(curl -k -s -u "${CURRENT_DB_USER}:${CURRENT_DB_PW}" "${CURRENT_DB_SERVER}/_replicator/_all_docs")
            # check for rba and georedundancy-replication in the doc id to delete
            # potential doc names would be 
            # bmstage-30363937666435352d393238372d343836382d383365362d353832393337313031313137-rba-as-georedundancy-replication
            # bmstage-30363937666435352d393238372d343836382d383365362d353832393337313031313137-rba-rbs-georedundancy-replication
            # rba-as-georedundancy-replication
            # rba-georedundancy-replication
            RBA_COUCHDB_REPLICATION_DOCS=$(echo "${COUCHDB_REPLICATIONS}" | jq -r '.rows[].id | select( . | test("(.*georedundancy-replication)"))')
            if [[ "${RBA_COUCHDB_REPLICATION_DOCS}" == "" ]]; then
                echo "No RBA replications were detected on ${CURRENT_DB_SERVER}, skipping deletion"
                return
            fi
    
            for CURRENT_DOC_TO_DELETE in ${RBA_COUCHDB_REPLICATION_DOCS}; do
                echo "Deleting replication doc ${CURRENT_DOC_TO_DELETE} on ${CURRENT_DB_SERVER}"
    
                # fetch rev required to delete replication doc
                CURRENT_DOC_REV=$(curl \
                    -k \
                    -s \
                    -X GET \
                    -u "${CURRENT_DB_USER}:${CURRENT_DB_PW}" \
                    "${CURRENT_DB_SERVER}/_replicator/${CURRENT_DOC_TO_DELETE}" | jq -r "._rev")
                
                # delete replication document
                DELETE_REPLICATION_DOC=$(curl \
                    -k \
                    -s \
                    -X DELETE \
                    -u "${CURRENT_DB_USER}:${CURRENT_DB_PW}" \
                    "${CURRENT_DB_SERVER}/_replicator/${CURRENT_DOC_TO_DELETE}?rev=${CURRENT_DOC_REV}")
    
                echo "${DELETE_REPLICATION_DOC}"
                if [[ "$(echo "${DELETE_REPLICATION_DOC}" | jq ".ok")" ]] ; then
                    echo "Replication ${CURRENT_DOC_TO_DELETE} on ${CURRENT_DB_SERVER} was delete successfully"
                else
                    echo "Failed to delete replication doc ${CURRENT_DOC_TO_DELETE} on ${CURRENT_DB_SERVER}"
                    exit 1
                fi
            done
        }
    
        deleteRbaReplications "${RBA_DB_URL_SIDE_A}" "${RBA_DB_USER_SIDE_A}" "${RBA_DB_PW_SIDE_A}"
        deleteRbaReplications "${RBA_DB_URL_SIDE_B}" "${RBA_DB_USER_SIDE_B}" "${RBA_DB_PW_SIDE_B}"
    fi
    
    echo "Showing current CouchDB scheduler jobs"
    echo "Side A:"
    curl \
        -k \
        -s \
        -X GET \
        -u "${RBA_DB_USER_SIDE_A}:${RBA_DB_PW_SIDE_A}" \
        "${RBA_DB_URL_SIDE_A}/_scheduler/jobs" | jq "."
    
    echo "Side B:"
    curl \
        -k \
        -s \
        -X GET \
        -u "${RBA_DB_USER_SIDE_B}:${RBA_DB_PW_SIDE_B}" \
        "${RBA_DB_URL_SIDE_B}/_scheduler/jobs" | jq "."
  4. To set up the replication, run the following command and enter the prompted values:
    $ ./couchdbReplication.sh
    Usage: ./couchdbReplication.sh setup|delete
    Example:
    ./couchdbReplication.sh setup
    ================ RBA Replication Setup ================
    Running in setup mode
    CouchDB on side A is accessible
    Detecting runbook automation databases
    skip: _global_changes
    skip: _replicator
    skip: _users
    replicate: collabopsuser
    skip: emailrecipients
    skip: genericproperties
    replicate: icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as
    replicate: icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs
    skip: integration
    skip: noi-aggconfigdb
    skip: noi-osregdb
    skip: osb-map
    skip: otc_omaas_broker
    skip: rba-pdoc
    skip: schedule
    skip: tenant
    skip: trainingjob
    RBA db detected: collabopsuser
    CouchDB on side B is accessible
    Creating replication for Runbook Service Database
    Setting up replication: https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com/collabopsuser -> https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com/collabopsuser
    Deleting old replication if present, continuing if missing
    {"error":"not_found","reason":"missing"}
    Creating replication
    {"ok":true,"id":"collabopsuser-georedundancy-replication","rev":"1-684fa9c5ca9b0b04b9df0fecb8988871"}
    Replication for collabopsuser from side A to B was configured successfully
    https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com/collabopsuser -> https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com/collabopsuser
    Deleting old replication if present, continuing if missing
    {"error":"not_found","reason":"missing"}
    Creating replication document
    {"ok":true,"id":"collabopsuser-georedundancy-replication","rev":"1-e42ef5e23a59391eeb3763aeedb39976"}
    {"ok":true,"id":"collabopsuser-georedundancy-replication","rev":"1-e42ef5e23a59391eeb3763aeedb39976"}
    Replication for collabopsuser from side B to A was configured successfully
    Setting up replication: https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as -> https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as
    Deleting old replication if present, continuing if missing
    {"error":"not_found","reason":"missing"}
    Creating replication
    {"ok":true,"id":"icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as-georedundancy-replication","rev":"1-db0a27c8a7d3b7332b3ebb3f3e046fc0"}
    Replication for icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as from side A to B was configured successfully
    https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as -> https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as
    Deleting old replication if present, continuing if missing
    {"error":"not_found","reason":"missing"}
    Creating replication document
    {"ok":true,"id":"icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as-georedundancy-replication","rev":"1-ee9081a2c823e903a82fac497e78a493"}
    {"ok":true,"id":"icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as-georedundancy-replication","rev":"1-ee9081a2c823e903a82fac497e78a493"}
    Replication for icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as from side B to A was configured successfully
    Setting up replication: https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs -> https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs
    Deleting old replication if present, continuing if missing
    {"error":"not_found","reason":"missing"}
    Creating replication
    {"ok":true,"id":"icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs-georedundancy-replication","rev":"1-f5f63f21fa090323d03eaafa694c03a9"}
    Replication for icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs from side A to B was configured successfully
    https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs -> https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs
    Deleting old replication if present, continuing if missing
    {"error":"not_found","reason":"missing"}
    Creating replication document
    {"ok":true,"id":"icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs-georedundancy-replication","rev":"1-54a4fcf9dc1df30faa0703f4792ed8d4"}
    {"ok":true,"id":"icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs-georedundancy-replication","rev":"1-54a4fcf9dc1df30faa0703f4792ed8d4"}
    Replication for icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs from side B to A was configured successfully
    Replication setup completed, displaying replication status
    Showing current CouchDB scheduler jobs
    Side A:
    {
      "total_rows": 3,
      "offset": 0,
      "jobs": [
        {
          "database": "_replicator",
          "id": "25b7ea12b4314ef19453ca55780a3f58+continuous+create_target",
          "pid": "<0.10373.3>",
          "source": "https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs/",
          "target": "https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs/",
          "user": null,
          "doc_id": "icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs-georedundancy-replication",
          "history": [
            {
              "timestamp": "2022-09-22T08:21:28Z",
              "type": "started"
            },
            {
              "timestamp": "2022-09-22T08:21:28Z",
              "type": "added"
            }
          ],
          "node": "couchdb@primary-couchdb-0.primary-couchdb.primary.svc.cluster.local",
          "start_time": "2022-09-22T08:21:28Z"
        },
        {
          "database": "_replicator",
          "id": "30e190747c0f1b34d64235fb8b28f74c+continuous+create_target",
          "pid": "<0.9905.3>",
          "source": "https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as/",
          "target": "https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as/",
          "user": null,
          "doc_id": "icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as-georedundancy-replication",
          "history": [
            {
              "timestamp": "2022-09-22T08:21:20Z",
              "type": "started"
            },
            {
              "timestamp": "2022-09-22T08:21:20Z",
              "type": "added"
            }
          ],
          "node": "couchdb@primary-couchdb-0.primary-couchdb.primary.svc.cluster.local",
          "start_time": "2022-09-22T08:21:20Z"
        },
        {
          "database": "_replicator",
          "id": "bfc5226c667b0727ab07323b99184e00+continuous+create_target",
          "pid": "<0.9526.3>",
          "source": "https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com/collabopsuser/",
          "target": "https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com/collabopsuser/",
          "user": null,
          "doc_id": "collabopsuser-georedundancy-replication",
          "history": [
            {
              "timestamp": "2022-09-22T08:21:13Z",
              "type": "started"
            },
            {
              "timestamp": "2022-09-22T08:21:13Z",
              "type": "added"
            }
          ],
          "node": "couchdb@primary-couchdb-0.primary-couchdb.primary.svc.cluster.local",
          "start_time": "2022-09-22T08:21:13Z"
        }
      ]
    }
    Side B:
    {
      "total_rows": 1,
      "offset": 0,
      "jobs": [
        {
          "database": "_replicator",
          "id": "afcde8d15fa0f9ee1420e7db24bdcf03+continuous+create_target",
          "pid": "<0.20967.2>",
          "source": "https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs/",
          "target": "https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs/",
          "user": null,
          "doc_id": "icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs-georedundancy-replication",
          "history": [
            {
              "timestamp": "2022-09-22T08:21:32Z",
              "type": "started"
            },
            {
              "timestamp": "2022-09-22T08:21:32Z",
              "type": "added"
            }
          ],
          "node": "couchdb@backup-couchdb-0.backup-couchdb.backup.svc.cluster.local",
          "start_time": "2022-09-22T08:21:32Z"
        }
      ]
    }

    Alternatively, you can export variables to start the script in noninteractive mode. This step is useful when you start the script by automation:

    $ export RBA_DB_URL_SIDE_A="https://couchdb.apps.noi-side-a.company.com"
    $ export RBA_DB_USER_SIDE_A="usera"
    $ export RBA_DB_PW_SIDE_A="xxx"
    $ export RBA_DB_URL_SIDE_B="https://couchdb.apps.noi-side-b.company.com"
    $ export RBA_DB_USER_SIDE_B="userb"
    $ export RBA_DB_PW_SIDE_B="xxx"
    $ ./couchdbReplication.sh setup
  5. To stop the replication between sides, use the same script with the delete command (the example uses the noninteractive mode):
    Example:
    ./couchdbReplication.sh delete
    ================ RBA Replication Setup ================
    Running in delete mode
    CouchDB on side A is accessible
    CouchDB on side B is accessible
    Detecting runbook automation replications on https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com
    Deleting replication doc collabopsuser-georedundancy-replication on https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com
    {"ok":true,"id":"collabopsuser-georedundancy-replication","rev":"2-6fcb9facc438ce8e968a869df56420cc"}
    Replication collabopsuser-georedundancy-replication on https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com was delete successfully
    Deleting replication doc icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as-georedundancy-replication on https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com
    {"ok":true,"id":"icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as-georedundancy-replication","rev":"2-54a248efe3564d62d683ef812d700d1b"}
    Replication icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as-georedundancy-replication on https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com was delete successfully
    Deleting replication doc icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs-georedundancy-replication on https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com
    {"ok":true,"id":"icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs-georedundancy-replication","rev":"2-966b8d8b123e67b3cd5baaa579de9716"}
    Replication icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs-georedundancy-replication on https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com was delete successfully
    Detecting runbook automation replications on https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com
    Deleting replication doc collabopsuser-georedundancy-replication on https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com
    {"ok":true,"id":"collabopsuser-georedundancy-replication","rev":"2-9aa83ba8ba017f635c52729bb21f8038"}
    Replication collabopsuser-georedundancy-replication on https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com was delete successfully
    Deleting replication doc icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as-georedundancy-replication on https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com
    {"ok":true,"id":"icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as-georedundancy-replication","rev":"2-cea95dfea595e4c738ead2a62ee53eb3"}
    Replication icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as-georedundancy-replication on https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com was delete successfully
    Deleting replication doc icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs-georedundancy-replication on https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com
    {"ok":true,"id":"icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs-georedundancy-replication","rev":"2-60828d548a5a3df447d107767fc01d5f"}
    Replication icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs-georedundancy-replication on https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com was delete successfully
    Showing current CouchDB scheduler jobs
    Side A:
    {
      "total_rows": 0,
      "offset": 0,
      "jobs": []
    }
    Side B:
    {
      "total_rows": 0,
      "offset": 0,
      "jobs": []
    }
    Note: If one side becomes unavailable for a short time, for example due to Kubernetes rescheduling actions or a router restart, the replication resumes automatically. If there is a longer outage, resume replication manually by running the replication setup again. The step deletes existing replication records and creates them again, which triggers a new replication on CouchDB instantaneously.
  6. To verify whether the replication completed, run the following command against both sides:
    $ curl -sku xxx:xxx https://couchdb.apps.noi-side-a.company.com/_active_tasks | jq "."
    Example output from Curl:
    [
      {
        "node": "couchdb@primary-couchdb-0.primary-couchdb.primary.svc.cluster.local",
        "pid": "<0.10373.3>",
        "changes_pending": 0,
        "checkpoint_interval": 30000,
        "checkpointed_source_seq": "25-g1AAAAVJeJzN00sKwjAQBuCgBRUPoRewpNWmuFLwIDrJJFSJVVoruNKb6E30JnqTmtqKj6VU6GbCzCL_x5BoQkgzqCOZiFUiAuTjdTRfQrTrFX3Ptb8mz96Ot8IWOok3MrL1SoDW5rIaEN5J03QR1KG9NIOGdAcwdNxyIkql8q6pfFRoyUOrkDNF-0haSYhSzUOJ5WaOs8xpkVl7ZKKUEvmwihuaZdr9h9YZAKV9VUFtaJlKDuYw4ONL7HngIYXKik-5-JyJrfzP-B5FVt0dX3Lx9bVjxqWvzDP-v9j5SXzLxW_vmIIvFGPlJC3uoCjdEw",
        "continuous": true,
        "database": "shards/e0000000-ffffffff/_replicator.1663550895",
        "doc_id": "icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs-georedundancy-replication",
        "doc_write_failures": 0,
        "docs_read": 0,
        "docs_written": 0,
        "missing_revisions_found": 0,
        "replication_id": "25b7ea12b4314ef19453ca55780a3f58+continuous+create_target",
        "revisions_checked": 1,
        "source": "https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs/",
        "source_seq": "25-g1AAAAVJeJzN00sKwjAQBuCgBRUPoRewpNWmuFLwIDrJJFSJVVoruNKb6E30JnqTmtqKj6VU6GbCzCL_x5BoQkgzqCOZiFUiAuTjdTRfQrTrFX3Ptb8mz96Ot8IWOok3MrL1SoDW5rIaEN5J03QR1KG9NIOGdAcwdNxyIkql8q6pfFRoyUOrkDNF-0haSYhSzUOJ5WaOs8xpkVl7ZKKUEvmwihuaZdr9h9YZAKV9VUFtaJlKDuYw4ONL7HngIYXKik-5-JyJrfzP-B5FVt0dX3Lx9bVjxqWvzDP-v9j5SXzLxW_vmIIvFGPlJC3uoCjdEw",
        "started_on": 1663834891,
        "target": "https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-rbs/",
        "through_seq": "25-g1AAAAVJeJzN00sKwjAQBuCgBRUPoRewpNWmuFLwIDrJJFSJVVoruNKb6E30JnqTmtqKj6VU6GbCzCL_x5BoQkgzqCOZiFUiAuTjdTRfQrTrFX3Ptb8mz96Ot8IWOok3MrL1SoDW5rIaEN5J03QR1KG9NIOGdAcwdNxyIkql8q6pfFRoyUOrkDNF-0haSYhSzUOJ5WaOs8xpkVl7ZKKUEvmwihuaZdr9h9YZAKV9VUFtaJlKDuYw4ONL7HngIYXKik-5-JyJrfzP-B5FVt0dX3Lx9bVjxqWvzDP-v9j5SXzLxW_vmIIvFGPlJC3uoCjdEw",
        "type": "replication",
        "updated_on": 1663834981,
        "user": null
      },
      {
        "node": "couchdb@primary-couchdb-0.primary-couchdb.primary.svc.cluster.local",
        "pid": "<0.9526.3>",
        "changes_pending": 0,
        "checkpoint_interval": 30000,
        "checkpointed_source_seq": "30-g1AAAAWDeJzN0ksKwjAQBuBgBV14B72AJU2jNisLHkQzaUqV-KBawZXeRG-iN9Gb1PQhPhaFQpFuJswsMh8_oxBC7cDw0ESsIxF44G7C-ZKHh37e94n5M3n15nYvTKGi7U6GploLrpT-rMERdOM4XgQGbyz1oIUdnwIl1awopOKSVOjpCuNca6RaJhwLpKxmS7VaN9FOv7IlYGGG2R-0Zc8AZon2-JWtBURK4tTwElZNXdFJPxp8fufrS0YHAmqYbya-ZOLrO2PsSJsyr7YZ3zLxPRF3UvHIt5k1pLXN-JGJP-7Y5twGUnQVJTYtnhJH8hM",
        "continuous": true,
        "database": "shards/e0000000-ffffffff/_replicator.1663550895",
        "doc_id": "collabopsuser-georedundancy-replication",
        "doc_write_failures": 0,
        "docs_read": 1,
        "docs_written": 1,
        "missing_revisions_found": 1,
        "replication_id": "bfc5226c667b0727ab07323b99184e00+continuous+create_target",
        "revisions_checked": 23,
        "source": "https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com/collabopsuser/",
        "source_seq": "30-g1AAAAWDeJzN0ksKwjAQBuBgBV14B72AJU2jNisLHkQzaUqV-KBawZXeRG-iN9Gb1PQhPhaFQpFuJswsMh8_oxBC7cDw0ESsIxF44G7C-ZKHh37e94n5M3n15nYvTKGi7U6GploLrpT-rMERdOM4XgQGbyz1oIUdnwIl1awopOKSVOjpCuNca6RaJhwLpKxmS7VaN9FOv7IlYGGG2R-0Zc8AZon2-JWtBURK4tTwElZNXdFJPxp8fufrS0YHAmqYbya-ZOLrO2PsSJsyr7YZ3zLxPRF3UvHIt5k1pLXN-JGJP-7Y5twGUnQVJTYtnhJH8hM",
        "started_on": 1663834877,
        "target": "https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com/collabopsuser/",
        "through_seq": "30-g1AAAAWDeJzN0ksKwjAQBuBgBV14B72AJU2jNisLHkQzaUqV-KBawZXeRG-iN9Gb1PQhPhaFQpFuJswsMh8_oxBC7cDw0ESsIxF44G7C-ZKHh37e94n5M3n15nYvTKGi7U6GploLrpT-rMERdOM4XgQGbyz1oIUdnwIl1awopOKSVOjpCuNca6RaJhwLpKxmS7VaN9FOv7IlYGGG2R-0Zc8AZon2-JWtBURK4tTwElZNXdFJPxp8fufrS0YHAmqYbya-ZOLrO2PsSJsyr7YZ3zLxPRF3UvHIt5k1pLXN-JGJP-7Y5twGUnQVJTYtnhJH8hM",
        "type": "replication",
        "updated_on": 1663834967,
        "user": null
      },
      {
        "node": "couchdb@primary-couchdb-0.primary-couchdb.primary.svc.cluster.local",
        "pid": "<0.9905.3>",
        "changes_pending": 0,
        "checkpoint_interval": 30000,
        "checkpointed_source_seq": "13-g1AAAAUPeJzN01FqwjAYB_BghW2n0AtYkqw29mmCB5nJl4QqaSvVDva03URv4m7ibtKli2PVByFQii8J-R7y_5F8n0EIPaaBRAsoKkilmG_KVcbL98n5PKHhVeXvHG7fIARTbXeqDE0B3Bh72YAjMarrep0GfJDZwgORCWMEdxNxk4o9qWJsV_Fy1qJfbYIhilgs0VOVS6VXuZI3M4lv5rzJfL14oQhEokncTUqnnymWjfbjQou1ZAnVPfynrzYf2hV92s2C9_9iNWUg2PPdig9OfGzEgZuZWTylmvQg9u1fJ_5y4lOrh2NCqOA99LDvlDvxtxO3Jp1rhWkE7Ulf_wCeasTU",
        "continuous": true,
        "database": "shards/00000000-1fffffff/_replicator.1663550895",
        "doc_id": "icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as-georedundancy-replication",
        "doc_write_failures": 0,
        "docs_read": 1,
        "docs_written": 1,
        "missing_revisions_found": 1,
        "replication_id": "30e190747c0f1b34d64235fb8b28f74c+continuous+create_target",
        "revisions_checked": 1,
        "source": "https://couchdb-georedundancy-primary.apps.geor-1-166-180911.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as/",
        "source_seq": "13-g1AAAAUPeJzN01FqwjAYB_BghW2n0AtYkqw29mmCB5nJl4QqaSvVDva03URv4m7ibtKli2PVByFQii8J-R7y_5F8n0EIPaaBRAsoKkilmG_KVcbL98n5PKHhVeXvHG7fIARTbXeqDE0B3Bh72YAjMarrep0GfJDZwgORCWMEdxNxk4o9qWJsV_Fy1qJfbYIhilgs0VOVS6VXuZI3M4lv5rzJfL14oQhEokncTUqnnymWjfbjQou1ZAnVPfynrzYf2hV92s2C9_9iNWUg2PPdig9OfGzEgZuZWTylmvQg9u1fJ_5y4lOrh2NCqOA99LDvlDvxtxO3Jp1rhWkE7Ulf_wCeasTU",
        "started_on": 1663834883,
        "target": "https://couchdb-georedundancy-backup.apps.geor-2-166-180914.cp.xyz.com/icp-63666439356237652d336263372d343030362d613461382d613733613739633731323535-rba-as/",
        "through_seq": "13-g1AAAAUPeJzN01FqwjAYB_BghW2n0AtYkqw29mmCB5nJl4QqaSvVDva03URv4m7ibtKli2PVByFQii8J-R7y_5F8n0EIPaaBRAsoKkilmG_KVcbL98n5PKHhVeXvHG7fIARTbXeqDE0B3Bh72YAjMarrep0GfJDZwgORCWMEdxNxk4o9qWJsV_Fy1qJfbYIhilgs0VOVS6VXuZI3M4lv5rzJfL14oQhEokncTUqnnymWjfbjQou1ZAnVPfynrzYf2hV92s2C9_9iNWUg2PPdig9OfGzEgZuZWTylmvQg9u1fJ_5y4lOrh2NCqOA99LDvlDvxtxO3Jp1rhWkE7Ulf_wCeasTU",
        "type": "replication",
        "updated_on": 1663834973,
        "user": null
      }
    ]
  7. For database migrations, disable replication, upgrade both sides, and then reactivate replication again. For more information, see Upgrading Runbook Automation in replicated environments.