Source: inspector.js

/**
 * @file retrieves information about the ec2 instance and the docker container where the current process is being executed
 * @author Florian Schaper <f.schaper@reply.de>
 * @copyright Florian Schaper 2018, MIT License
 */

'use strict';

const queryEc2Metadata = require('./query/ec2Metadata');
const queryEcsAgentClusterName = require('./query/ecsAgentClusterName');
const queryEcsAgentCurrentTask = require('./query/ecsAgentCurrentTask');
const queryEcsCurrentTaskFromFile = require('./query/ecsCurrentTaskFromFile');

/**
 * @typedef {Object} ECSTaskInformationPortInfo
 * @property {string} protocol - protocol used e.g. tcp
 * @property {number} container - port on the container side
 * @property {number} host - port on the host side
 */

/**
 * @typedef {Object} ECSTaskInformation
 * @property {string} arn - aws arn uniquely identifying the task
 * @property {string} cluster - name of the cluster
 * @property {string} dockerId - docker id
 * @property {string} containerName - name of the container
 * @property {string} [publicHostname] - public dns domain name of the ec2 instance (if available)
 * @property {string} [publicIpv4] - public ipv4 address of the ec2 instance (if available)
 * @property {string} [localHostname] - private dns domain name of the ec2 instance (if available)
 * @property {string} [localIpv4] - private ipv4 address of the ec2 instance (if available)
 * @property {Array.<ECSTaskInformationPortInfo>} ports - docker to host port mapping
 */

/**
 * @callback InspectHandler
 * @param {Error|null} error - error that may have occurred
 * @param {ECSTaskInformation} result - result of the operation
 */

/**
 * provides information about the ec2/ecs instance that a docker image is currently running from
 *
 * @param {Object} [options] - additional options
 * @param {InspectHandler} [options.callback] - optional callback which will be called with the result or an error
 * @returns {Promise<ECSTaskInformation>} information about the current docker process on ecs
 */
function inspect(options) {
  // combine agent cluster and task information
  const queryEcsAgentInformation = () => Promise.all([
    queryEcsAgentClusterName(),
    queryEcsAgentCurrentTask()
  ]).then(result => Object.assign(...result));

  const response = Promise.all([
    // if the ECS_CONTAINER_METADATA_FILE environment variable has been defined,
    // we try to lookup the mounted file from the docker volume otherwise we will fall back to querying the local agent
    queryEcsCurrentTaskFromFile().catch(() => queryEcsAgentInformation()),
    // collect additional information about the ec2 instance
    queryEc2Metadata()
  ]).then(result => Object.assign(...result));

  // if an callback has been passed we execute it for result and failure conditions
  // promise rejections will be caught and passed on to the callback
  if (options && typeof options.callback === 'function') {
    response.then((taskInformation) => {
      options.callback(null, taskInformation);
      return taskInformation;
    }).catch(error => options.callback(error instanceof Error ? error : new Error(error)));
  }
  return response;
}

module.exports = inspect;