All files index.js

49.02% Statements 25/51
47.62% Branches 20/42
27.27% Functions 3/11
49.02% Lines 25/51

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141    1x 1x           5x 4x   4x 4x 4x     4x 4x 4x   4x                                     4x                                     4x     4x 8x 5x     3x             5x 1x     4x 4x 1x 1x   3x 3x                                                                                                                
import consul from 'consul';
 
const _ = require('lodash');
const CONSUL_PREFIX = 'consul';
var consulClient;
 
export default class ServerlessConsulVariables {
 
  constructor(serverless, options) {
    const consulSettings = (serverless.service.custom && serverless.service.custom['serverless-consul-variables']['consul_settings']) ? serverless.service.custom['serverless-consul-variables']['consul_settings'] : {};
    consulClient = consul({...consulSettings, promisify: true});
 
    const enableServiceRegistration = (serverless.service.custom && serverless.service.custom['serverless-consul-variables']['service']['enable_registration']) ?  serverless.service.custom['serverless-consul-variables']['service']['enable_registration'] : false;
    const service_endpoint_filter = (serverless.service.custom && serverless.service.custom['serverless-consul-variables']['service']['enpdoint_filters']) ? serverless.service.custom['serverless-consul-variables']['service']['enpdoint_filters'] : 'api';
    const consul_endpoint_key_path = (serverless.service.custom && serverless.service.custom['serverless-consul-variables']['service']['consul_endpoint_key_path']) ? serverless.service.custom['serverless-consul-variables']['service']['consul_endpoint_key_path'] : '/';
    
 
    this.serverless = serverless;
    this.options = options;
    this.resolvedValues = {};
 
    this.commands = {
      consul: {
        usage: 'Gets value for Key Path from consul KV',
        lifecycleEvents: [
          'getValue',
          'getEndpoint',
          'registerEndpoint'
        ],
        options: {
          'get-key': {
            usage:
              'Specify the Key Path you want to get '
              + '(e.g. "--get-key \'my_folder/key\'")',
            required: true,
          },
        },
      },
    };
 
    this.hooks = {
      'consul:getValue': async () => {
        const result = await this._getValueFromConsul.call(this, options['get-key']);
        this.serverless.cli.log(result);
       },
       'after:deploy:deploy': async () => {
          if(enableServiceRegistration){
            this._generateEndpoint(service_endpoint_filter, consul_endpoint_key_path);
          }
          
       },
       'info:info': async () => {
          if(enableServiceRegistration){
            this._generateEndpoint(service_endpoint_filter, consul_endpoint_key_path);
          }
       } 
        
    }
 
    const delegate = serverless.variables
    .getValueFromSource.bind(serverless.variables);
 
    serverless.variables.getValueFromSource = (variableString) => {
      if (variableString.startsWith(`${CONSUL_PREFIX}:`)) {
        return this._getValueFromConsul(variableString.split(`${CONSUL_PREFIX}:`)[1]);
      }
 
      return delegate(variableString);
    }
    
  }
 
  async _getValueFromConsul(variable) {
 
    if (this.resolvedValues[variable]) {
      return this.resolvedValues[variable];
    }
 
    const data = await consulClient.kv.get(variable.startsWith('/') ? variable.substr(1) : variable);
    if (!data) {
      const errorMessage = `Error getting variable from Consul: ${variable}. Variable not found.`;
      throw new this.serverless.classes.Error(errorMessage);
    }
    this.resolvedValues[variable] = data.Value;
    return data.Value;
  }
 
 
 
 
  // Generate AWS Endpoint from API Gateway plus the task name.
  async _generateEndpoint(service_endpoint_filter, consul_endpoint_key_path){
    var info;
    let plugins = this.serverless.pluginManager.plugins;
    plugins.forEach( plugin => {
      if(plugin.constructor.name == 'AwsInfo'){
        info = plugin.gatheredData.info;
      }
    });
 
    var endpoint;
 
    // Only if we have an endpoint makes sense.
    if(info.endpoint) {
      _.forEach(this.serverless.service.functions, functionObject => {
        functionObject.events.forEach( event => {
            if(event.http) {
              let path;
              if (typeof event.http === 'object') {
                path = event.http.path;
              } else {
                path = event.http.split(' ')[1];
              }
              if(path == service_endpoint_filter) {
                endpoint = `${info.endpoint}/${path}`;
                this._registerEndpoint(endpoint, consul_endpoint_key_path);
              }
 
            }
        });
      });
    }
 
    
  };
 
  // Lets register the endpoint api into consul KV
  async _registerEndpoint(endpoint, consul_endpoint_key_path){
    
    const result = await consulClient.kv.set((consul_endpoint_key_path.startsWith('/') ? consul_endpoint_key_path.substr(1) : consul_endpoint_key_path), endpoint);
    if(!result){
      const errorMessage = 'Error trying to set ' + consul_endpoint_key_path + ', ' + err;
      throw new this.serverless.classes.Error(errorMessage);
    }
    console.log(`Endpoint ${endpoint} registered succesfully in Consul ${consul_endpoint_key_path}`);
    return result;
  }
  
}