deep-package-manager
Version:
DEEP Package Manager
522 lines (428 loc) • 13.6 kB
JavaScript
/**
* Created by AlexanderC on 5/27/15.
*/
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.AbstractService = undefined;
var _deepCore = require('deep-core');
var _deepCore2 = _interopRequireDefault(_deepCore);
var _WaitFor = require('../../Helpers/WaitFor');
var _Hash = require('../../Helpers/Hash');
var _Exception = require('../../Exception/Exception');
var _Inflector = require('../../Helpers/Inflector');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Abstract service
*/
class AbstractService extends _deepCore2.default.OOP.Interface {
/**
* @param {Instance} provisioning
*/
constructor(provisioning) {
super(['name', '_setup', '_postProvision', '_postDeployProvision']);
this._config = {};
this._provisioning = provisioning;
this._ready = false;
this._readyTeardown = false;
this._isUpdate = false;
}
/**
* @param {Boolean} state
*/
set isUpdate(state) {
this._isUpdate = state;
}
/**
* @returns {Boolean}
*/
get isUpdate() {
return this._isUpdate;
}
/**
* @returns {string}
*/
static get DELIMITER_UPPER_CASE() {
return 'upperCase';
}
/**
* @returns {string}
*/
static get DELIMITER_DOT() {
return '.';
}
/**
* @returns {string}
*/
static get DELIMITER_HYPHEN_LOWER_CASE() {
return 'hyphenLowerCase';
}
/**
* @returns {string}
*/
static get DELIMITER_HYPHEN() {
return '-';
}
/**
* @returns {string}
*/
static get DELIMITER_UNDERSCORE() {
return '_';
}
/**
* @returns {string}
*/
static get AWS_RESOURCES_PREFIX() {
return 'deep';
}
/**
* @returns {RegExp}
*/
static get AWS_RESOURCE_GENERALIZED_REGEXP() {
let regexp = '';
let capitalizedResourcePrefix = AbstractService.capitalizeFirst(AbstractService.AWS_RESOURCES_PREFIX);
regexp += '(.*\/)?'; // case CloudFrontLogs or similar...
regexp += `(${AbstractService.AWS_RESOURCES_PREFIX}|${capitalizedResourcePrefix})`;
regexp += '(-|_|\.|[A-Z])';
regexp += '.+';
regexp += `[a-zA-Z0-9]{${AbstractService.MAIN_HASH_SIZE}}`;
return new RegExp(`^${regexp}$`);
}
/**
* @returns {RegExp}
*/
static get AWS_RESOURCE_LISTING_REGEXP() {
let regExp = '';
let prefix = AbstractService.AWS_RESOURCES_PREFIX;
let capPrefix = AbstractService.capitalizeFirst(prefix);
let hashSize = AbstractService.MAIN_HASH_SIZE;
regExp += `${capPrefix}[A-Z].+[A-Z].+(\\w{${hashSize}})$|`; // upperCase delimiter
regExp += `${prefix}\\.\\w+\\.\\w+\\.(\\w{${hashSize}})$|`; // dot delimiter
regExp += `${prefix}\\_\\w+\\_\\w+\\_(\\w{${hashSize}})$|`; // underscore delimiter
regExp += `(${capPrefix}|${prefix})\\-\\w+\\-\\w+\\-(\\w{${hashSize}})`; // hyphen delimiter
return new RegExp(`^${regExp}$`);
}
/**
* @param {Core.Generic.ObjectStorage} services
* @returns {WaitFor}
*/
setup(services) {
let wait = new _WaitFor.WaitFor();
this._setup(services);
wait.push(() => {
if (this._ready) {
this._ready = false;
return true;
}
return false;
});
return wait;
}
/**
* @param {Core.Generic.ObjectStorage} services
* @returns {WaitFor}
*/
postProvision(services) {
let wait = new _WaitFor.WaitFor();
this._postProvision(services);
wait.push(() => {
if (this._readyTeardown) {
this._readyTeardown = false;
return true;
}
return false;
});
return wait;
}
/**
* @param {Core.Generic.ObjectStorage} services
* @returns {WaitFor}
*/
postDeployProvision(services) {
let wait = new _WaitFor.WaitFor();
this._postDeployProvision(services);
wait.push(() => {
if (this._ready) {
this._ready = false;
return true;
}
return false;
});
return wait;
}
/**
* @returns {Boolean}
*/
get readyTeardown() {
return this._readyTeardown;
}
/**
* @returns {Boolean}
*/
get ready() {
return this._ready;
}
/**
* @param {Object} config
*/
injectConfig(config) {
this._config = config;
this._onConfigInject();
}
/**
* @todo: override this
*
* @private
*/
_onConfigInject() {}
/**
* @returns {Object}
*/
config() {
return this._config;
}
/**
* @returns {Property}
*/
get property() {
return this.provisioning.property;
}
/**
* @returns {Provisioning}
*/
get provisioning() {
return this._provisioning;
}
/**
* @returns {String}
*/
get appIdentifier() {
return this.property.identifier;
}
/**
* @returns {String}
*/
get awsAccountId() {
return this.property.config.awsAccountId;
}
/**
* @returns {String}
*/
get env() {
return this.property.config.env;
}
/**
* @param {String} service
* @returns {Array}
*/
getApiVersions(service) {
try {
return this.property.AWS[service].apiVersions.slice(); // return an array clone
} catch (e) {
throw new _Exception.Exception(`Failed to retrieve apiVersions for "${service}" AWS service. ${e.message}`);
}
}
/**
* @param {String} microserviceIdentifier
* @returns {String}
*/
getUniqueHash(microserviceIdentifier = '') {
return AbstractService.generateUniqueResourceHash(this.awsAccountId, this.appIdentifier, microserviceIdentifier);
}
/**
* @param {String} awsAccountId
* @param {String} appIdentifier
* @param {String} microserviceIdentifier
* @returns {String}
*/
static generateUniqueResourceHash(awsAccountId, appIdentifier, microserviceIdentifier = '') {
let globId = _Hash.Hash.crc32(`${awsAccountId}${appIdentifier}`);
return microserviceIdentifier ? `${_Hash.Hash.loseLoseMod(microserviceIdentifier)}${globId}` : globId;
}
/**
* @param {String} msIdentifier
* @param {String} delimiter
* @returns {String}
*/
_getGlobalResourceMask(msIdentifier = '', delimiter = AbstractService.DELIMITER_UPPER_CASE) {
let mask = null;
let uniqueHash = this.getUniqueHash(msIdentifier);
let appendMatcher = msIdentifier ? '' : '*';
switch (delimiter) {
case AbstractService.DELIMITER_UPPER_CASE:
mask = AbstractService.capitalizeFirst(AbstractService.AWS_RESOURCES_PREFIX) + AbstractService.capitalizeFirst(this.env) + '*' + uniqueHash + appendMatcher;
break;
case AbstractService.DELIMITER_DOT:
mask = `${AbstractService.AWS_RESOURCES_PREFIX}.${this.env}.*.${uniqueHash}${appendMatcher}`;
break;
case AbstractService.DELIMITER_UNDERSCORE:
mask = `${AbstractService.AWS_RESOURCES_PREFIX}_${this.env}_*_${uniqueHash}${appendMatcher}`;
break;
case AbstractService.DELIMITER_HYPHEN_LOWER_CASE:
let lowerAwsResourcesPrefix = AbstractService.AWS_RESOURCES_PREFIX.toLowerCase();
let lowerEnv = this.env.toLowerCase();
let lowerUniqueHash = uniqueHash.toLowerCase();
mask = `${lowerAwsResourcesPrefix}-${lowerEnv}-*-${lowerUniqueHash}${appendMatcher}`;
break;
case AbstractService.DELIMITER_HYPHEN:
mask = `${AbstractService.AWS_RESOURCES_PREFIX}-${this.env}-*-${uniqueHash}${appendMatcher}`;
break;
default:
throw new _Exception.Exception(`Undefined aws resource name delimiter ${delimiter}.`);
}
return mask;
}
/**
* @note: Leave this method as it is for back compatibility
*
* @param {String} resourceName
* @param {String} awsService
* @param {String} msIdentifier
* @param {String} delimiter
* @returns {String}
*/
generateAwsResourceName(resourceName, awsService, msIdentifier = '', delimiter = AbstractService.DELIMITER_UPPER_CASE) {
return AbstractService.generateAwsResourceName(resourceName, awsService, this.awsAccountId, this.appIdentifier, this.env, msIdentifier, delimiter);
}
/**
* @param {String} resourceName
* @param {String} awsService
* @param {String} awsAccountId
* @param {String} appIdentifier
* @param {String} env
* @param {String} msIdentifier
* @param {String} delimiter
* @returns {String}
*/
static generateAwsResourceName(resourceName, awsService, awsAccountId, appIdentifier, env, msIdentifier = '', delimiter = AbstractService.DELIMITER_UPPER_CASE) {
let name = null;
let uniqueHash = AbstractService.generateUniqueResourceHash(awsAccountId, appIdentifier, msIdentifier);
let nameTplLength = (AbstractService.AWS_RESOURCES_PREFIX + env + uniqueHash).length;
switch (delimiter) {
case AbstractService.DELIMITER_UPPER_CASE:
resourceName = AbstractService.sliceNameToAwsLimits(resourceName, awsService, nameTplLength);
name = AbstractService.capitalizeFirst(AbstractService.AWS_RESOURCES_PREFIX) + AbstractService.capitalizeFirst(env) + AbstractService.capitalizeFirst(resourceName) + uniqueHash;
break;
case AbstractService.DELIMITER_DOT:
nameTplLength += 3; // adding 3 dot delimiters
resourceName = AbstractService.sliceNameToAwsLimits(resourceName, awsService, nameTplLength);
name = `${AbstractService.AWS_RESOURCES_PREFIX}.${env}.${resourceName}.${uniqueHash}`;
break;
case AbstractService.DELIMITER_UNDERSCORE:
nameTplLength += 3; // adding 3 underscore delimiters
resourceName = AbstractService.sliceNameToAwsLimits(resourceName, awsService, nameTplLength);
name = `${AbstractService.AWS_RESOURCES_PREFIX}_${env}_${resourceName}_${uniqueHash}`;
break;
case AbstractService.DELIMITER_HYPHEN_LOWER_CASE:
nameTplLength += 3; // adding 3 hyphen delimiters
resourceName = AbstractService.sliceNameToAwsLimits(resourceName, awsService, nameTplLength);
let lowerAwsResourcesPrefix = AbstractService.AWS_RESOURCES_PREFIX.toLowerCase();
let lowerEnv = env.toLowerCase();
let lowerResourceName = resourceName.toLowerCase();
let lowerUniqueHash = uniqueHash.toLowerCase();
name = `${lowerAwsResourcesPrefix}-${lowerEnv}-${lowerResourceName}-${lowerUniqueHash}`;
break;
case AbstractService.DELIMITER_HYPHEN:
nameTplLength += 3; // adding 3 hyphen delimiters
resourceName = AbstractService.sliceNameToAwsLimits(resourceName, awsService, nameTplLength);
name = `${AbstractService.AWS_RESOURCES_PREFIX}-${env}-${resourceName}-${uniqueHash}`;
break;
default:
throw new _Exception.Exception(`Undefined aws resource name delimiter ${delimiter}.`);
}
return name;
}
/**
* @param {String} resourceName
* @returns {String}
*/
static extractBaseHashFromResourceName(resourceName) {
let rawRegexp = `^(?:.*\/)?${AbstractService.AWS_RESOURCES_PREFIX}.+([a-z0-9]{${AbstractService.MAIN_HASH_SIZE}})$`;
let matches = resourceName.match(new RegExp(rawRegexp, 'i'));
if (!matches) {
return null;
}
return matches[1];
}
/**
* @param {String} resourceName
* @returns {String}
*/
static extractEnvFromResourceName(resourceName) {
let rawRegexp = `^(?:.*\/)?${AbstractService.AWS_RESOURCES_PREFIX}`;
rawRegexp += `(?:\.|_|-)?(dev|stage|test|prod).+[a-z0-9]{${AbstractService.MAIN_HASH_SIZE}}$`;
let matches = resourceName.match(new RegExp(rawRegexp, 'i'));
if (!matches) {
return null;
}
return matches[1].toLowerCase();
}
/**
* @returns {Number}
*/
static get MAIN_HASH_SIZE() {
return 8;
}
/**
* @param {String} resourceName
* @param {String} awsService
* @param {Number} nameTplLength
* @returns {*}
*/
static sliceNameToAwsLimits(resourceName, awsService, nameTplLength) {
let slicedName = resourceName;
let totalLength = nameTplLength + resourceName.length;
let awsServiceLimit = null;
switch (awsService) {
case _deepCore2.default.AWS.Service.ELASTIC_CACHE:
awsServiceLimit = 20;
break;
case _deepCore2.default.AWS.Service.CLOUD_SEARCH:
case _deepCore2.default.AWS.Service.ELASTIC_SEARCH:
awsServiceLimit = 28;
break;
case _deepCore2.default.AWS.Service.SIMPLE_STORAGE_SERVICE:
awsServiceLimit = 63;
break;
case _deepCore2.default.AWS.Service.LAMBDA:
case _deepCore2.default.AWS.Service.IDENTITY_AND_ACCESS_MANAGEMENT:
awsServiceLimit = 64;
break;
case _deepCore2.default.AWS.Service.COGNITO_IDENTITY_PROVIDER:
case _deepCore2.default.AWS.Service.COGNITO_IDENTITY:
case _deepCore2.default.AWS.Service.API_GATEWAY:
awsServiceLimit = 128;
break;
case _deepCore2.default.AWS.Service.DYNAMO_DB:
awsServiceLimit = 255;
break;
case _deepCore2.default.AWS.Service.SIMPLE_QUEUE_SERVICE:
awsServiceLimit = 80;
break;
default:
throw new _Exception.Exception(`Naming limits for aws service ${awsService} are not defined.`);
}
if (totalLength > awsServiceLimit) {
slicedName = resourceName.slice(0, -(totalLength - awsServiceLimit));
}
return slicedName;
}
/**
* @todo: remove
* @param {String} str
* @returns {String}
*/
static capitalizeFirst(str) {
return _Inflector.Inflector.capitalizeFirst(str);
}
/**
* @todo: remove
* @param {String} str
* @returns {String}
*/
static lowerCaseFirst(str) {
return _Inflector.Inflector.lowerCaseFirst(str);
}
}
exports.AbstractService = AbstractService;