From a596ad068a30c55f032982b1f7073814d33afcbc Mon Sep 17 00:00:00 2001 From: Julien Georges Date: Wed, 6 Dec 2023 15:49:48 +0100 Subject: [PATCH] Bug #12074: Fix mongo isWritablePrimary check. Compute list of mongo nodes to properly execute bootstrap commands on the primary. --- deployment/roles/mongo/tasks/check_auth.yml | 4 +-- deployment/roles/mongo/tasks/main.yml | 13 +++++--- .../roles/mongo/templates/init-replica.js.j2 | 28 +---------------- .../roles/mongo/templates/local-user.js.j2 | 31 +++++++++++++++++-- .../roles/mongo_init/tasks/check_auth.yml | 5 ++- deployment/roles/mongo_init/tasks/main.yml | 3 +- 6 files changed, 44 insertions(+), 40 deletions(-) diff --git a/deployment/roles/mongo/tasks/check_auth.yml b/deployment/roles/mongo/tasks/check_auth.yml index d99806af0c5..ff84410e3c1 100644 --- a/deployment/roles/mongo/tasks/check_auth.yml +++ b/deployment/roles/mongo/tasks/check_auth.yml @@ -11,7 +11,7 @@ set_fact: mongo_credentials: "" mongo_no_auth: true - when: "mongo_authent_enabled.rc != 0" + when: mongo_authent_enabled.rc != 0 tags: update_mongodb_configuration # When authentication is required, we set mongodb admin credentials @@ -19,7 +19,7 @@ set_fact: mongo_credentials: "-u {{ mongodb.admin.user }} -p {{ mongodb.admin.password }}" mongo_no_auth: false - when: "mongo_authent_enabled.rc == 0" + when: mongo_authent_enabled.rc == 0 no_log: "{{ hide_passwords_during_deploy }}" tags: update_mongodb_configuration diff --git a/deployment/roles/mongo/tasks/main.yml b/deployment/roles/mongo/tasks/main.yml index 53b69009298..8ea2bf7c053 100644 --- a/deployment/roles/mongo/tasks/main.yml +++ b/deployment/roles/mongo/tasks/main.yml @@ -150,8 +150,7 @@ host: "{{ hostvars[item]['ip_service'] }}" port: "{{ mongodb.mongod_port }}" timeout: "{{ vitamui_defaults.services.start_timeout }}" - with_items: - - "{{ groups['hosts_vitamui_mongod'] }}" + with_items: "{{ groups['hosts_vitamui_mongod'] }}" tags: update_mongodb_configuration - name: Copy the script which initiate the replica set @@ -164,12 +163,18 @@ tags: update_mongodb_configuration - name: Initiate the replica set - command: "mongo --host {{ ip_service }} --port {{ mongodb.mongod_port }} {{ vitamui_defaults.folder.root_path | default('/vitamui') }}/app/mongod/init-replica.js" + command: "mongosh --host {{ ip_service }} --port {{ mongodb.mongod_port }} --quiet --file {{ vitamui_defaults.folder.root_path | default('/vitamui') }}/app/mongod/init-replica.js" tags: update_mongodb_configuration - import_tasks: check_auth.yml # Create the local shard admin user + - name: Compute list of mongo_nodes + set_fact: + mongo_nodes: "{{ mongo_nodes | default([]) + [ hostvars[item]['ip_service'] + ':' + mongodb.mongod_port | string ] }}" + loop: "{{ groups['hosts_vitamui_mongod'] }}" + when: hostvars[item]['mongo_arbiter'] | default(false) | bool == false + - name: Copy the script which create the local users template: src: local-user.js.j2 @@ -180,7 +185,7 @@ tags: update_mongodb_configuration - name: Create the local shard user - command: "mongo --host {{ ip_service }}:{{ mongodb.mongod_port }} {{ mongo_credentials }} {{ vitamui_defaults.folder.root_path | default('/vitamui') }}/app/mongod/local-user.js" + command: "mongosh --host {{ mongo_nodes | join(',') }} {{ mongo_credentials }} --quiet --file {{ vitamui_defaults.folder.root_path | default('/vitamui') }}/app/mongod/local-user.js" tags: update_mongodb_configuration when: mongo_rs_bootstrap | default(false) | bool == true diff --git a/deployment/roles/mongo/templates/init-replica.js.j2 b/deployment/roles/mongo/templates/init-replica.js.j2 index fa4a6757311..6d85d93f626 100644 --- a/deployment/roles/mongo/templates/init-replica.js.j2 +++ b/deployment/roles/mongo/templates/init-replica.js.j2 @@ -107,38 +107,12 @@ function waitForReplicaSetPrimaryElection() { throw "ERROR : Timeout - NO PRIMARY NODE FOUND"; } -function waitForWritablePrimary() { - print("INFO: waitForWritablePrimary"); - var instanceStatus; - for (let i = 0; i < 60; i++) { - - instanceStatus = db.hello(); - - if(!instanceStatus.ok) { - printjson(instanceStatus); - throw "ERROR : Cannot get db instance status"; - } - - if(instanceStatus.isWritablePrimary) { - print("OK : Primary node " + instanceStatus.primary + " is writable"); - return; - } - - // Retry later - sleep(1000); - } - - printjson(instanceStatus); - throw "ERROR : Timeout - NO PRIMARY NODE FOUND"; -} - -if(checkExistingReplicaSet()) { +if (checkExistingReplicaSet()) { checkExistingReplicaSetMembers(); print("INFO : mongod replica set already configured."); } else { print("INFO : Initializing mongod replica set"); initReplicaSetPrimary(); waitForReplicaSetPrimaryElection(); - waitForWritablePrimary(); print("INFO : mongod replica set intitialization OK"); } diff --git a/deployment/roles/mongo/templates/local-user.js.j2 b/deployment/roles/mongo/templates/local-user.js.j2 index 0e9d2e8145f..0680a2c0cdc 100644 --- a/deployment/roles/mongo/templates/local-user.js.j2 +++ b/deployment/roles/mongo/templates/local-user.js.j2 @@ -1,7 +1,33 @@ +function waitForWritablePrimary() { + print("INFO: waitForWritablePrimary"); + var instanceStatus; + for (let i = 0; i < 60; i++) { + + instanceStatus = db.hello(); + + if (!instanceStatus.ok) { + printjson(instanceStatus); + throw "ERROR : Cannot get db instance status"; + } + + if (instanceStatus.isWritablePrimary) { + print("OK : Primary node " + instanceStatus.primary + " is writable"); + return; + } + + // Retry later + sleep(1000); + } + + printjson(instanceStatus); + throw "ERROR : Timeout - NO PRIMARY NODE FOUND"; +} + +waitForWritablePrimary(); admin = db.getSiblingDB("admin") -if (! admin.getUser("{{ mongodb.localadmin.user }}")) { +if (!admin.getUser("{{ mongodb.localadmin.user }}")) { admin.createUser( { user: "{{ mongodb.localadmin.user }}", @@ -17,8 +43,7 @@ if (! admin.getUser("{{ mongodb.localadmin.user }}")) { ] } ) -} -else { +} else { admin.updateUser( "{{ mongodb.localadmin.user }}", { diff --git a/deployment/roles/mongo_init/tasks/check_auth.yml b/deployment/roles/mongo_init/tasks/check_auth.yml index 28ace7b8ad0..77e016289e9 100644 --- a/deployment/roles/mongo_init/tasks/check_auth.yml +++ b/deployment/roles/mongo_init/tasks/check_auth.yml @@ -15,20 +15,19 @@ - name: Set mongo_no_auth fact to true set_fact: mongo_no_auth: true - when: "mongo_authent_enabled.rc != 0" + when: mongo_authent_enabled.rc != 0 when: mongodb.docker is not defined or not mongodb.docker.enable - block: - name: Load script in database (docker) shell: "docker exec --tty {{ mongodb.docker.image_name }} /bin/bash -c \"mongo --host mongodb://{{ mongod_uri }}/admin?replicaSet={{ mongod_replicaset_name }} -u {{ mongodb.admin.user }} -p {{ mongodb.admin.password }} --quiet --eval 'db.help()'\"" - failed_when: false register: mongo_authent_enabled - name: Set mongo_no_auth fact to true set_fact: mongo_no_auth: true - when: "mongo_authent_enabled.rc != 0" + when: mongo_authent_enabled.rc != 0 when: mongodb.docker is defined and mongodb.docker.enable # When authentication is required, we set mongodb admin credentials diff --git a/deployment/roles/mongo_init/tasks/main.yml b/deployment/roles/mongo_init/tasks/main.yml index 79434d844b2..72692743b5b 100644 --- a/deployment/roles/mongo_init/tasks/main.yml +++ b/deployment/roles/mongo_init/tasks/main.yml @@ -9,10 +9,11 @@ set_fact: mongo_nodes: "{{ mongo_nodes | default([]) + [ hostvars[item]['ip_service'] + ':'+ mongodb.mongod_port | string ] }}" loop: "{{ groups['hosts_vitamui_mongod'] }}" + when: hostvars[item]['mongo_arbiter'] | default(false) | bool == false - name: Set Mongo URI set_fact: - mongod_uri: "{{ mongo_nodes| join(',') }}" + mongod_uri: "{{ mongo_nodes | join(',') }}" - name: Set mongod_output_dir_entry_point set_fact: