Skip to content

Connectivity debug script

Felicia Hsieh edited this page Dec 11, 2020 · 8 revisions

What follows is a script that can be uses to debug connectivity and isolate the root cause of issues directly inside Compass.

Usage

  1. Open DevTools in compass.
  2. Copy/paste the script below in the console.
  3. Run one of the available test, ie. connectivityTests.testNativeDriverUri('mongodb://localhost:27017').
  4. Wait for the test to print "Done. Test succeeded.". If that message is not printed the connection was not established correctly.

Available tests

testConnectionModelUri(connectionString)

Tests the connection simulating the process happening in Compass when connecting with a connection string.

Usage & Examples
connectivityTests.testConnectionModelUri('mongodb://localhost:27017');

testConnectionModelAttributes(attributes)

Tests the connection simulating the process happening in Compass when connecting with form parameters.

Usage & Examples

Basic standalone server:

connectivityTests.testConnectionModelAttributes({
  "isSrvRecord": false,
  "hostname": "localhost",
  "port": 27017,
  "hosts": [
    {
      "host": "localhost",
      "port": 27017
    }
  ],
  "authStrategy": "NONE"
});

Kerberos:

connectivityTests.testConnectionModelAttributes({
  "isSrvRecord": false,
  "hostname": "<server hostname>",
  "port": <server port>,
  "hosts": [
    {
      "host": "<server hostname>",
      "port": <server port>
    }
  ],
  "authStrategy": "KERBEROS",
  "kerberosServiceName": "<kerberos service name>",
  "kerberosPrincipal": "<kerberos principal>",
  "kerberosCanonicalizeHostname": false
});

LDAP:

connectivityTests.testConnectionModelAttributes({
  "isSrvRecord": false,
  "hostname": "<server hostname>",
  "port": <server port>,
  "hosts": [
    {
      "host": "<server hostname>",
      "port": <server port>
    }
  ],
  "authStrategy": "LDAP",
  "ldapUsername": "<ldap username>",
  "ldapPassword": "<ldap password>"
});

testNativeDriverUri(connectionString, driverOptions)

Tests the connection using the same node.js driver and default options as the Compass does. Default driver options are:

{
  connectWithNoPrimary: true,
  readPreference: "primary",
  useNewUrlParser: true,
  useUnifiedTopology: true
}
Usage & Examples
connectivityTests.testNativeDriverUri('mongodb://localhost:27017');

Overriding driver options:

connectivityTests.testNativeDriverUri('mongodb://localhost:27017', { useUnifiedTopology: false });

buildConnectionString(connectionString, { username, password?, searchParams })

Utility to build a connection string with proper characters escaping.

Usage & Examples
uri = connectivityTests.buildConnectionString(
  'mongodb://localhost:27017/database', 
  {
    username: '[email protected]',
    searchParams: {
      authMechanism: 'GSSAPI',
      gssapiServiceName: 'mongodb'
    }
  }
)

connectivityTests.testNativeDriverUri(uri);

This would connect to mongodb://principal%40MY.ORG@localhost:27017/database?authMechanism=GSSAPI&gssapiServiceName=mongodb;

Script

connectivityTests = (() => {
  console.log('using driver version:', require('mongodb/package.json').version);
  console.log('using mongodb-connection-model version:', require('mongodb-connection-model/package.json').version);
  console.log('using kerberos extension version:', require('kerberos/package.json').version);

  const util = require('util');
  const { MongoClient } = require('mongodb');
  const Connection = require('mongodb-connection-model');

  const connectionModelFromUri = util.promisify(Connection.from.bind(Connection));
  const connectWithConnectionModel = util.promisify(Connection.connect.bind(Connection));

  async function testAndCloseClient(client) {
    console.log('connected')
    console.log('testing commands ...');
    try {
      await client.db().command({ connectionStatus: 1 });
      console.log('Done. Test succeeded.');
    } catch (e) {
      console.log('Error', e);
    } finally {
      if (!client) {
        return;
      }
      await client.close();
    }
  }

  async function testConnectionModelAttributes(attributes) {
    const connectionModel = new Connection(attributes);
    console.log('Connecting ...');
    const client = await connectWithConnectionModel(connectionModel, () => { });
    await testAndCloseClient(client);
  }

  async function testConnectionModelUri(uri) {
    const connectionModel = await connectionModelFromUri(uri);
    console.log('Connecting ...');
    const client = await connectWithConnectionModel(connectionModel, () => { });

    await testAndCloseClient(client);
  }

  async function testNativeDriverUri(uri, driverOptions = {}) {
    driverOptions = {
      connectWithNoPrimary: true,
      readPreference: "primary",
      useNewUrlParser: true,
      useUnifiedTopology: true,
      ...driverOptions
    };

    console.log('Connecting ...');
    const client = await MongoClient.connect(uri, driverOptions);

    await testAndCloseClient(client);
  }

  function buildConnectionString(connectionString, options = {}) {
    const {
      username,
      password,
      searchParams
    } = options;

    const connectionStringUrl = new URL(connectionString);

    if (username) {
      connectionStringUrl.username = username;
    }

    if (password) {
      connectionStringUrl.password = password;
    }

    if (searchParams) {
      for (const [name, value] of Object.entries(searchParams)) {
        connectionStringUrl.searchParams.append(name, value);
      }
    }

    return connectionStringUrl.toString();
  }

  return {
    testConnectionModelAttributes,
    testConnectionModelUri,
    testNativeDriverUri,
    buildConnectionString
  };
})();