Cannot Connect EC2 MongoDB Instance During CodeDeploy LifeCycleEvent

0

I have an EC2 (RHEL) instance running a NodeJS server. I have setup the start of this server as a systemd service (included below) and run this service via a shell script executed during the ApplicationStart part of CodeDeploy LifeCycleEvent. In the server itself, I am using mongoose to connect to MongoDB running on another EC2 instance. My problem is that my server does not connect to MongoDB and instead returns the following error:

{
  message: 'Could not connect to MongoDB!!! getaddrinfo ENOTFOUND undefined',
  reason: TopologyDescription {
    type: 'Single',
    setName: null,
    maxSetVersion: null,
    maxElectionId: null,
    servers: Map {
      'undefined:27017' => ServerDescription {
        address: 'undefined:27017',
        error: Error: getaddrinfo ENOTFOUND undefined
            at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:66:26) {
          name: 'MongoNetworkError'
        },
        roundTripTime: -1,
        lastUpdateTime: 23933862843,
        lastWriteDate: null,
        opTime: null,
        type: 'Unknown',
        topologyVersion: undefined,
        minWireVersion: 0,
        maxWireVersion: 0,
        hosts: [],
        passives: [],
        arbiters: [],
        tags: []
      }
    },
    stale: false,
    compatible: true,
    compatibilityError: null,
    logicalSessionTimeoutMinutes: null,
    heartbeatFrequencyMS: 10000,
    localThresholdMS: 15,
    commonWireVersion: null
  },
  level: 'error',
  stack: 'MongooseServerSelectionError: getaddrinfo ENOTFOUND undefined\n' +
    '    at NativeConnection.Connection.openUri (/home/centos/my-server/node_modules/mongoose/lib/connection.js:847:32)\n' +
    '    at /home/centos/my-server/node_modules/mongoose/lib/index.js:351:10\n' +
    '    at /home/centos/my-server/node_modules/mongoose/lib/helpers/promiseOrCallback.js:32:5\n' +
    '    at new Promise (<anonymous>)\n' +
    '    at promiseOrCallback (/home/centos/my-server/node_modules/mongoose/lib/helpers/promiseOrCallback.js:31:10)\n' +
    '    at Mongoose._promiseOrCallback (/home/centos/my-server/node_modules/mongoose/lib/index.js:1149:10)\n' +
    '    at Mongoose.connect (/home/centos/my-server/node_modules/mongoose/lib/index.js:350:20)\n' +
    '    at module.exports (/home/centos/my-server/startup/db.js:20:6)\n' +
    '    at startServer (/home/centos/my-server/index.js:22:9)\n' +
    '    at processTicksAndRejections (internal/process/task_queues.js:97:5)',
  label: 'qa-server',
  timestamp: '1/21/2022, 11:41:15 AM'
}

I tried the following solutions and these did not work: 1. https://aws.amazon.com/premiumsupport/knowledge-center/dns-resolution-failures-ec2-linux/ 2. Adding the following lines to my .service file:

After=network-online.target
Wants=network-online.target

If anyone could provide some insight as to how I can solve this, it'd be greatly appreciated.

appspec.yaml

version: 0.0
os: linux
files:
  - source: /
    destination: /home/centos/my-server
hooks:
  BeforeInstall:
    - location: scripts/cleanup.sh
      timeout: 300
      runas: root
  AfterInstall:
    - location: scripts/install_dependencies.sh
      timeout: 300
      runas: root
    - location: scripts/update_service.sh
      timeout: 300
      runas: root
  ApplicationStart:
    - location: scripts/start_server.sh
      timeout: 300
      runas: root
  ApplicationStop:
    - location: scripts/stop_server.sh
      timeout: 300
      runas: root

start_server.sh

#!/bin/bash

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 9080
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 9443

sudo systemctl daemon-reload
sudo systemctl restart myserver.service

myserver.service

[Unit]
Description=Node.js My server
[Service]
ExecStart=/usr/bin/node /home/centos/my-server/index.js
WorkingDirectory=/home/centos/my-server/
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=my-server-log
Environment=PATH=/usr/bin:/usr/local/bin
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target

index.js

const winston = require('winston');
const express = require('express');
const logging = require('./startup/logging');
const config = require('./startup/config');
const routes = require('./startup/routes');
const db = require('./startup/db');
const validation = require('./startup/validation');
const redirect = require('./startup/redirect');

const app = express();

const successMessage = async () => {
  const message = 'my-server is up and running and ready for requests..';
  winston.info(message);
  console.log(message);
};

const startServer = async () => {
  await logging();
  await config();
  await routes(app);
  await db();
  await validation();
  await redirect(app);

  await successMessage();
};

startServer();

db.js

const mongoose = require('mongoose');
const winston = require('winston');
const nconf = require('nconf');
const fs = require('fs');

module.exports = async function () {
  // Get the mongodb credentials from config memory
  const ipAddress = fs.existsSync('/.dockerenv')
    ? nconf.get('mongodb:dockerIPAddress')
    : nconf.get('mongodb:ipAddress');
  const port = nconf.get('mongodb:port');
  const username = encodeURIComponent(nconf.get('mongodb:username'));
  const password = encodeURIComponent(nconf.get('mongodb:password'));
  const database = nconf.get('mongodb:database');

  const mongoUrl = `mongodb://${username}:${password}@${ipAddress}:${port}/${database}?authSource=admin`;

  mongoose
    .connect(mongoUrl, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
      useCreateIndex: true,
      useFindAndModify: false,
    })
    .then(() => winston.info('Connected to mongodb successfully..'))
    .catch((err) => winston.error('Could not connect to MongoDB!!!', err));
};
asked 2 years ago903 views
1 Answer
0
Accepted Answer

Looking at the information surrounding the ENOTFOUND error, it looks like your application's configuration is missing the connection details:

      'undefined:27017' => ServerDescription {
        address: 'undefined:27017',
        error: Error: getaddrinfo ENOTFOUND undefined
            at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:66:26) {
          name: 'MongoNetworkError'
        },

From this, it appears that mongoose is attempting to connect to undefined. While trying to connect, a DNS query for undefined is being made, which leads to the ENOTFOUND.

It seems like nconf is not finding the configuration values, and it's not clear to me where it expects them by default. There may be value in configuring this explicitly with nconf.file() (1)

(1) https://github.com/indexzero/nconf

AWS
SUPPORT ENGINEER
Wayne_G
answered 2 years ago
  • Hi Wayne,

    Thank you for responding. That's it. That was the problem. Though I do have your solution implemented in my config.js file which is executed in the index.js file where it says await config(). This config function is downloading a file from an S3 bucket where the ipAddress and other MongoDB info is stored. The problem is, I think, that nconf is trying to access those variables in db.js before the file is fully downloaded. Any suggestions for that?

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions