@@ -934,21 +934,40 @@ mongodb_configure_secondary_node_voting() {
934934 local -r node=" ${1:? node is required} "
935935 local -r port=" ${2:? port is required} "
936936
937- debug " Granting voting rights to the node "
937+ debug " Ensuring the node has full voting rights (votes: 1, priority: 1) "
938938 local reconfig_cmd=" rs.reconfigForPSASet(member, cfg)"
939939 [[ " $( mongodb_get_version) " =~ ^4\. (0| 2)\. ]] && reconfig_cmd=" rs.reconfig(cfg)"
940- result=$(
941- mongodb_execute_print_output " $MONGODB_INITIAL_PRIMARY_ROOT_USER " " $MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD " " admin" " $MONGODB_INITIAL_PRIMARY_HOST " " $MONGODB_INITIAL_PRIMARY_PORT_NUMBER " << EOF
940+ # Idempotent: skip the reconfig when the node already has full voting rights.
941+ # rs.reconfigForPSASet applies the change in two internal steps (first
942+ # votes: 1 / priority: 0, then priority: 1); if a previous run was
943+ # interrupted between the two steps the member can be left at
944+ # votes: 1 / priority: 0, so we must be able to re-run and finish the job.
945+ mongodb_execute_print_output " $MONGODB_INITIAL_PRIMARY_ROOT_USER " " $MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD " " admin" " $MONGODB_INITIAL_PRIMARY_HOST " " $MONGODB_INITIAL_PRIMARY_PORT_NUMBER " << EOF
942946cfg = rs.conf()
943947member = cfg.members.findIndex(m => m.host === '$node :$port ')
944- cfg.members[member].priority = 1
945- cfg.members[member].votes = 1
946- $reconfig_cmd
948+ if (member === -1) {
949+ print('node-not-in-replicaset')
950+ } else if (cfg.members[member].votes === 1 && cfg.members[member].priority === 1) {
951+ print('voting-already-configured')
952+ } else {
953+ cfg.members[member].priority = 1
954+ cfg.members[member].votes = 1
955+ $reconfig_cmd
956+ }
957+ EOF
958+
959+ # Verify the node actually ended up as a full voting member. The retry_while
960+ # wrapper around this function re-runs it until this check passes, so a
961+ # partially applied reconfig converges to votes: 1 / priority: 1.
962+ result=$(
963+ mongodb_execute_print_output " $MONGODB_INITIAL_PRIMARY_ROOT_USER " " $MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD " " admin" " $MONGODB_INITIAL_PRIMARY_HOST " " $MONGODB_INITIAL_PRIMARY_PORT_NUMBER " << EOF
964+ m = rs.conf().members.find(m => m.host === '$node :$port ')
965+ print(m && m.votes === 1 && m.priority === 1 ? 'voting-ok' : 'voting-pending')
947966EOF
948967 )
949968 debug " $result "
950969
951- grep -q " ok: 1 " <<< " $result"
970+ grep -q " voting-ok " <<< " $result"
952971}
953972
954973# #######################
@@ -1194,21 +1213,22 @@ mongodb_configure_secondary() {
11941213 error " Secondary node did not get marked as secondary"
11951214 exit 1
11961215 fi
1216+ fi
11971217
1198- # Grant voting rights to node
1199- # https://docs.mongodb.com/manual/tutorial/modify-psa-replica-set-safely/
1200- if ! retry_while " mongodb_configure_secondary_node_voting $node $port " " $MONGODB_INIT_RETRY_ATTEMPTS " " $MONGODB_INIT_RETRY_DELAY " ; then
1201- error " Secondary node did not get marked as secondary"
1202- exit 1
1203- fi
1218+ # Always grant voting rights, whether the node was just added or was already
1219+ # a member. This guarantees the replica set converges to votes: 1 / priority: 1
1220+ # for every secondary, even if a previous run was interrupted before this step.
1221+ # https://docs.mongodb.com/manual/tutorial/modify-psa-replica-set-safely/
1222+ if ! retry_while " mongodb_configure_secondary_node_voting $node $port " " $MONGODB_INIT_RETRY_ATTEMPTS " " $MONGODB_INIT_RETRY_DELAY " ; then
1223+ error " Secondary node did not get full voting rights (votes: 1, priority: 1)"
1224+ exit 1
1225+ fi
12041226
1205- # Mark node as readable. This is necessary in cases where the PVC is lost
1206- if is_boolean_yes " $MONGODB_SET_SECONDARY_OK " ; then
1207- mongodb_execute_print_output " $MONGODB_INITIAL_PRIMARY_ROOT_USER " " $MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD " " admin" << EOF
1227+ # Mark node as readable. This is necessary in cases where the PVC is lost
1228+ if is_boolean_yes " $MONGODB_SET_SECONDARY_OK " ; then
1229+ mongodb_execute_print_output " $MONGODB_INITIAL_PRIMARY_ROOT_USER " " $MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD " " admin" << EOF
12081230rs.secondaryOk()
12091231EOF
1210- fi
1211-
12121232 fi
12131233}
12141234
@@ -1324,8 +1344,12 @@ mongodb_node_currently_in_cluster() {
13241344 local -r port=" ${2:? port is required} "
13251345 local result
13261346
1347+ # Use mongodb_execute_print_output (not mongodb_execute): mongodb_execute
1348+ # wraps the call in debug_execute, which discards stdout unless BITNAMI_DEBUG
1349+ # is enabled. We need to capture rs.status() output to inspect the members,
1350+ # otherwise this check always sees an empty string and returns false.
13271351 result=$(
1328- mongodb_execute " $MONGODB_INITIAL_PRIMARY_ROOT_USER " " $MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD " " admin" " $MONGODB_INITIAL_PRIMARY_HOST " " $MONGODB_INITIAL_PRIMARY_PORT_NUMBER " << EOF
1352+ mongodb_execute_print_output " $MONGODB_INITIAL_PRIMARY_ROOT_USER " " $MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD " " admin" " $MONGODB_INITIAL_PRIMARY_HOST " " $MONGODB_INITIAL_PRIMARY_PORT_NUMBER " << EOF
13291353rs.status().members
13301354EOF
13311355 )
0 commit comments