motig88 motig88 - 3 years ago 116
Node.js Question

Alternative to `replSetGetConfig` in MongoDB 2.4.5 driver?

I'm working with an application running MongoDB 2.4.5, and currently an upgrade is out of the question.

I'm writing some automation scripts in node.js to initiate a replica set, but since I'm starting out with 3 identical, existing mongodb nodes I can't just use the

replSetInitiate
command with all 3 nodes - I need to init with one which I intend to be the primary, and then call
replSetReconfig
with the additional 2 to make them wipe and sync up.

The problem is, I would call the
replSetGetConfig
command to get a config object which I can manipulate and send back, but this command was only added in mongodb 3.0. So what are my alternatives? Is there an alternative command to
replSetGetConfig
? Is there any way I can generate the appropriate config object myself after
replSetInitiate
is done? Or should I just give up and run a mongo shell with
rs.conf()
?

This is what that code looks like right now, which does not work in said version:

return connectToMongoDB(host)
.then((db) => {
// Initial configuration contains only the intended primary
var cfg = {
_id : id,
members : [{ _id: 0, host: host }]
};
return executeMongoCommand(db, { replSetInitiate : cfg })
.then((res) => {
// Passing on the db object so I don't have to reconnect
return {
db: db
};
});
})
.then((data) => {
// This would work in 3.0.0 and up to get the current RS config, but doesn't work at all in 2.4.5
return executeMongoCommand(data.db, { replSetGetConfig: 1 })
.then((res) => {
// storing the config we got and passing it on with the db object to the next step
data.cfg = data;
return data;
})
})
.then((data) => {
otherNodes.forEach((val, idx) => {
data.cfg.members.push({ _id: idx+1, host: val });
});
return executeMongoCommand(data.db, { replSetReconfig : data.cfg });
})
.catch(console.error);


And the returned error is
no such cmd: replSetGetConfig


(As a side note,
rs.conf()
is supposed to be a wrapper for
replSetGetConfig
for somehow the wrapper is supported and the underlying function is not. Don't get it.)

UPDATE / ANSWER:



Based on @Stennie 's answer below I've implemented the following function to get this information for both sides of version 3.0.0:

function getRSconfig(db){
return new Promise((resolve, reject) => {
if(parseInt(mongoVersion, 10) < 3){
db.db("local").collection("system.replset").findOne()
.then((data) => {
resolve(data);
}, (err) => {
reject(err);
});
}
else {
executeMongoCommand(db, { replSetGetConfig: 1 })
.then((data) => {
resolve(data);
}, (err) => {
reject(err);
})
}
});
}


And using this one to get the current version:

function getMongoVersion(db){
var adminDb = db.admin();
adminDb.serverStatus(function(err, info) {
mongoVersion = info.version;
});
}

Answer Source

Prior to the replSetGetConfig command being introduced, drivers read the config directly from the local database: db.getSiblingDB("local").system.replset.findOne().

You could read this config document as a fallback for servers older than MongoDB 3.0, which introduced replSetGetConfig as a proper command abstraction. For newer servers the command is the supported API to use.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download