diff --git a/solution-base/images/Makefile b/solution-base/images/Makefile index f7ed011d16..9d067ad8e9 100644 --- a/solution-base/images/Makefile +++ b/solution-base/images/Makefile @@ -1,21 +1,20 @@ BITNAMI_REMOTE := bitnami-containers BITNAMI_REPO := https://github.com/bitnami/containers.git -BITNAMI_UPSTREAM_MAIN_REF := $(BITNAMI_REMOTE)/main IMAGES := mongodb-sharded mongodb-exporter os-shell BITNAMI_mongodb_sharded_PATH := 8.0/debian-12 # Latest commit on upstream main known to still contain # bitnami/mongodb-sharded/8.0/debian-12. -BITNAMI_mongodb_sharded_REF := 48a109547d39cd8cf8a5d4058d832ecb5844829e +BITNAMI_mongodb_sharded_REF := 657585595c550d4dc107a4e6cd3a598a9d284eec BITNAMI_mongodb_exporter_PATH := 0/debian-12 -BITNAMI_mongodb_exporter_REF := $(BITNAMI_UPSTREAM_MAIN_REF) +BITNAMI_mongodb_exporter_REF := main BITNAMI_os_shell_PATH := 12/debian-12 -BITNAMI_os_shell_REF := $(BITNAMI_UPSTREAM_MAIN_REF) +BITNAMI_os_shell_REF := main -.PHONY: create-remote fetch-remote vendor-sync $(addprefix vendor-sync-,$(IMAGES)) $(addprefix update-vendor-branch-,$(IMAGES)) +.PHONY: create-remote vendor-sync normalize = $(subst -,_,$1) bitnami_path = $(BITNAMI_$(call normalize,$1)_PATH) @@ -25,15 +24,20 @@ vendor_branch = vendor/$1/$(call bitnami_path,$1) create-remote: @git remote get-url $(BITNAMI_REMOTE) >/dev/null 2>&1 || git remote add $(BITNAMI_REMOTE) $(BITNAMI_REPO) -fetch-remote: create-remote - # Fetch full history from Bitnami main so subtree split can see full subtree history. - git fetch $(BITNAMI_REMOTE) main - -update-vendor-branch-%: fetch-remote +update-vendor-branch-%: create-remote + # Shallow-fetch only the pinned ref; full upstream history is unnecessary for a --squash merge. + git fetch --depth 1 --filter=blob:none $(BITNAMI_REMOTE) $(call bitnami_ref,$*) -git branch -D $(call vendor_branch,$*) - git subtree split --prefix=bitnami/$*/$(call bitnami_path,$*) $(call bitnami_ref,$*) -b $(call vendor_branch,$*) + sha=$$(git rev-parse FETCH_HEAD) && \ + wt=$$(mktemp -d) && \ + trap 'git worktree remove --force "$$wt" 2>/dev/null' EXIT && \ + git worktree add --no-checkout --detach "$$wt" "$$sha" && \ + git -C "$$wt" sparse-checkout set --no-cone bitnami/$*/$(call bitnami_path,$*) && \ + git -C "$$wt" checkout && \ + git -C "$$wt" subtree split --prefix=bitnami/$*/$(call bitnami_path,$*) "$$sha" -b $(call vendor_branch,$*) vendor-sync-%: update-vendor-branch-% + cd "$$(git rev-parse --show-toplevel)" && \ git subtree merge --prefix=solution-base/images/$*/debian-12 $(call vendor_branch,$*) --squash vendor-sync: $(addprefix vendor-sync-,$(IMAGES)) diff --git a/solution-base/images/mongodb-sharded/debian-12/rootfs/opt/bitnami/scripts/libmongodb.sh b/solution-base/images/mongodb-sharded/debian-12/rootfs/opt/bitnami/scripts/libmongodb.sh index ea90282a47..274905c35c 100644 --- a/solution-base/images/mongodb-sharded/debian-12/rootfs/opt/bitnami/scripts/libmongodb.sh +++ b/solution-base/images/mongodb-sharded/debian-12/rootfs/opt/bitnami/scripts/libmongodb.sh @@ -951,6 +951,32 @@ EOF grep -q "ok: 1" <<<"$result" } +######################## +# Get if secondary node already has voting rights +# Globals: +# MONGODB_* +# Arguments: +# $1 - node +# $2 - port +# Returns: +# Boolean +######################### +mongodb_secondary_node_has_voting_rights() { + local -r node="${1:?node is required}" + local -r port="${2:?port is required}" + local result + + debug "Checking voting rights of the node" + result=$( + mongodb_execute_print_output "$MONGODB_INITIAL_PRIMARY_ROOT_USER" "$MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD" "admin" "$MONGODB_INITIAL_PRIMARY_HOST" "$MONGODB_INITIAL_PRIMARY_PORT_NUMBER" < m.host === '$node:$port' && m.votes > 0 && m.priority > 0).length === 1 +EOF + ) + debug "$result" + + grep -q "true" <<<"$result" +} + ######################## # Get if hidden node is pending # Globals: @@ -1187,7 +1213,15 @@ mongodb_configure_secondary() { exit 1 fi mongodb_wait_confirmation "$node" "$port" + fi + # Grant voting rights to the node if it does not have them yet. This must be + # done even when the node is already in the cluster: a previous attempt may + # have added it with votes/priority 0 and failed (or been restarted) before + # granting voting rights, leaving the node stuck without them. + if mongodb_secondary_node_has_voting_rights "$node" "$port"; then + info "Node already has voting rights" + else # Ensure that secondary nodes do not count as voting members until they are fully initialized # https://docs.mongodb.com/manual/reference/method/rs.add/#behavior if ! retry_while "mongodb_is_secondary_node_ready $node $port" "$MONGODB_INIT_RETRY_ATTEMPTS" "$MONGODB_INIT_RETRY_DELAY"; then @@ -1198,17 +1232,16 @@ mongodb_configure_secondary() { # Grant voting rights to node # https://docs.mongodb.com/manual/tutorial/modify-psa-replica-set-safely/ if ! retry_while "mongodb_configure_secondary_node_voting $node $port" "$MONGODB_INIT_RETRY_ATTEMPTS" "$MONGODB_INIT_RETRY_DELAY"; then - error "Secondary node did not get marked as secondary" + error "Secondary node did not get granted voting rights" exit 1 fi + fi - # Mark node as readable. This is necessary in cases where the PVC is lost - if is_boolean_yes "$MONGODB_SET_SECONDARY_OK"; then - mongodb_execute_print_output "$MONGODB_INITIAL_PRIMARY_ROOT_USER" "$MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD" "admin" <