简体   繁体   中英

Check MongoDB database instance is a replica set

I'm writing tests for functions that use transactions.

Transactions only work on replica sets or mongos :

pymongo.errors.OperationFailure: Transaction numbers are only allowed on a replica set member or mongos, full error: {'ok': 0.0, 'errmsg': 'Transaction numbers are only allowed on a replica set member or mongos', 'code': 20, 'codeName': 'IllegalOperation'}

I would like those tests to be skipped if the database is a standalone mongod instance.

How can I check from Python code (eg with a pymongo function) that I'm using an adequate environment?

I can configure the CI Pipeline to use a replica set. I can, and did, configure that on my machine. But I don't want those few tests to be a hassle for potential contributors, so I'd rather skip them.

Alternatively, I could catch the OperationFailure and try to ensure it is exactly the error above, not another OperationFailure , by matching the string, but this would be a sorry workaround.


Perhaps I could use something like

MongoClient('localhost', 27017).admin.command("replSetGetStatus")

Before going through a tough trial and error session, I'd be happy to get an informed advice.

Here is a way to check if the MongoDB instance is a replica-set:

Every mongod instance has its own local database ( local is the database name), which stores data used in the replication process, and other instance-specific data. The system.replset collection in the local database holds the replica set's configuration object as its single document.

To view this configuration, issue rs.conf() from the mongo shell. You can also query this collection directly (see below code used in a method).

client = pymongo.MongoClient(url)
collection = client.local.system.replset
try:
    doc = collection.find()[0]
    print(doc['_id'])
    return True
except Exception as e:
    print("local.system.replset doesn't exist: " + str(e))
    return False

Note the code raises an exception if cursor is empty, ie, when the system.replset collection doesn't exist in the local database and the query fails (and the query fails for a standalone instance).

In the code, the doc['_id'] is the replica-set name.

Here's what I came up with:

def is_replica_set():
    try:
        pymongo.MongoClient().admin.command("replSetGetStatus")
        return True
    except pymongo.errors.OperationFailure:
        return False


@pytest.mark.skipif(not is_replica_set(), reason="Replica set required")
def test_transaction():
    ...

Send {ismaster: 1} command and follow the rules here for parsing the response.

Replica set node will have setName field set in the response.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM