UNPKG

deep-package-manager

Version:
317 lines (264 loc) 9.21 kB
/** * Created by CCristi on 3/6/17. */ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.CloudFrontService = undefined; var _AbstractService = require('./AbstractService'); var _CloudFrontEvent = require('./Helpers/CloudFrontEvent'); var _MissingCloudFrontEventTypeException = require('../Exception/MissingCloudFrontEventTypeException'); var _deepCore = require('deep-core'); var _deepCore2 = _interopRequireDefault(_deepCore); var _CloudFrontEventAlreadyExistsException = require('../Exception/CloudFrontEventAlreadyExistsException'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class CloudFrontService extends _AbstractService.AbstractService { /** * @param {Object[]} args */ constructor(...args) { super(...args); this._cloudFrontClient = null; } /** * @returns {*} */ name() { return _deepCore2.default.AWS.Service.CLOUD_FRONT; } /** * @param {AWS.CloudFront|Object} cloudFrontClient */ set cloudFrontClient(cloudFrontClient) { this._cloudFrontClient = cloudFrontClient; } /** * @param {String} lambdaArn * @param {String} distributionId * @param {String} eventType * @returns {Promise} */ attachLambdaToDistributionEvent(lambdaArn, distributionId, eventType) { if (!_CloudFrontEvent.CloudFrontEvent.exists(eventType)) { return Promise.reject(new _MissingCloudFrontEventTypeException.MissingCloudFrontEventTypeException(eventType)); } return this._getDistributionConfig({ Id: distributionId }).then(response => { let distributionConfig = response.DistributionConfig; let functionAssociations = distributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations; let payload = { Id: distributionId, IfMatch: response.ETag, DistributionConfig: distributionConfig }; functionAssociations.Items = functionAssociations.Items || []; for (let item of functionAssociations.Items) { if (item.EventType === eventType) { if (item.LambdaFunctionARN === lambdaArn) { // looks like it's already attached // do not return Promise.resolve() // functionAssociations are not reliable return this._cloudFrontClient.updateDistribution(payload).promise(); } throw new _CloudFrontEventAlreadyExistsException.CloudFrontEventAlreadyExistsException(eventType, distributionId, item.LambdaFunctionARN); } } functionAssociations.Quantity += 1; functionAssociations.Items.push({ EventType: eventType, LambdaFunctionARN: lambdaArn }); return this._updateDistribution(payload); }); } /** * @param {String[]} events * @param {String} distributionId * @returns {Promise} */ detachEventsFromDistribution(events, distributionId) { return this._getDistributionConfig({ Id: distributionId }).then(response => { let distributionConfig = response.DistributionConfig; let functionAssociations = distributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations; let payload = { Id: distributionId, IfMatch: response.ETag, DistributionConfig: distributionConfig }; let newFunctionAssociations = { Quantity: 0, Items: [] }; functionAssociations.Items.forEach(item => { if (events.indexOf(item.EventType) === -1) { newFunctionAssociations.Items.push(item); newFunctionAssociations.Quantity += 1; } }); distributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations = newFunctionAssociations; return this._updateDistribution(payload); }); } /** * @param {String} distributionId * @param {Object} changeSet * @returns {Promise} */ cloneDistribution(distributionId, changeSet = {}) { return this._getDistributionConfig({ Id: distributionId }).then(response => { let newDistributionConfig = Object.assign(response.DistributionConfig, changeSet); return this._createDistribution({ DistributionConfig: newDistributionConfig }); }); } /** * @Note: this method returns a Promise which resolves old cnames * * @param {String} distributionId * @param {String[]} newCNames * @returns {Promise.<String[]>} */ changeCloudFrontCNAMEs(distributionId, newCNames) { return this._getDistributionConfig({ Id: distributionId }).then(response => { let distributionConfig = response.DistributionConfig; let oldCNames = JSON.parse(JSON.stringify(distributionConfig.Aliases)); distributionConfig.Aliases.Quantity = newCNames.length; distributionConfig.Aliases.Items = newCNames; return this._updateDistribution({ IfMatch: response.ETag, Id: distributionId, DistributionConfig: distributionConfig }).then(() => oldCNames); }); } /** * @param {String} distributionId * @param {Number} _interval * @param {Number} _estTime * * @returns {Promise} */ waitForDistributionDeployed(distributionId, _interval = 1000 * 30, _estTime = 1200) { return this._getDistribution({ Id: distributionId }).then(response => { let status = response.Distribution.Status; if (status === 'Deployed') { return Promise.resolve(); } let estTimeMinutes = _estTime / 60; console.info(`Waiting for CloudFront distribution ${distributionId} to be deployed`, `(currently ${status}, ETC ${estTimeMinutes <= 0 ? '...' : `${estTimeMinutes} min`})`); return this.wait(_interval).then(() => { return this.waitForDistributionDeployed(distributionId, _interval, _estTime - 30); }); }); } /** * @param {String} bDistributionId * @param {String} gDistributionId * @returns {Promise} */ hotSwapCloudFrontCNames(bDistributionId = null, gDistributionId = null) { bDistributionId = bDistributionId || this.blueConfig().id; gDistributionId = gDistributionId || this.greenConfig().id; return Promise.all([this._getDistributionConfig({ Id: bDistributionId }), this._getDistributionConfig({ Id: gDistributionId })]).then(responses => { let bDistributionConfig = responses[0].DistributionConfig; let gDistributionConfig = responses[1].DistributionConfig; let tmpAliases = bDistributionConfig.Aliases; bDistributionConfig.Aliases = gDistributionConfig.Aliases; gDistributionConfig.Aliases = tmpAliases; let bPayload = { Id: bDistributionId, IfMatch: responses[0].ETag, DistributionConfig: bDistributionConfig }; let gPayload = { Id: gDistributionId, IfMatch: responses[1].ETag, DistributionConfig: gDistributionConfig }; return Promise.all([this._updateDistribution(this._resetCfAliases(bPayload)), this._updateDistribution(this._resetCfAliases(gPayload))]).then(() => Promise.all([this._refreshDistributionObjETag(bPayload), this._refreshDistributionObjETag(gPayload)])).then(() => Promise.all([this._updateDistribution(bPayload), this._updateDistribution(gPayload)])); }); } /** * @param {Object} distributionObj * @returns {Promise} * @private */ _refreshDistributionObjETag(distributionObj) { return this._getDistributionConfig({ Id: distributionObj.Id }).then(response => { distributionObj.IfMatch = response.ETag; return distributionObj; }); } /** * @param {Object} distributionObj * * @returns {Object} * @private */ _resetCfAliases(distributionObj) { let clone = JSON.parse(JSON.stringify(distributionObj)); clone.DistributionConfig.Aliases = { Items: [], Quantity: 0 }; return clone; } /** * @param {String} distributionId * @returns {Promise} */ getDistributionCNAMES(distributionId) { return this._getDistributionConfig({ Id: distributionId }).then(response => { let cnamesObj = response.DistributionConfig.Aliases; return cnamesObj.Items || []; }); } /** * @param {Object} payload * @returns {Promise} * @private */ _getDistributionConfig(payload) { return this._retryableRequest(this._cloudFrontClient.getDistributionConfig(payload)).promise(); } /** * @param {Object} updatePayload * @returns {Promise} * @private */ _updateDistribution(updatePayload) { return this._retryableRequest(this._cloudFrontClient.updateDistribution(updatePayload)).promise(); } /** * @param {Object} payload * @returns {Promise} * @private */ _createDistribution(payload) { return this._retryableRequest(this._cloudFrontClient.createDistribution(payload)).promise(); } /** * @param {Object} payload * @returns {Promise} * @private */ _getDistribution(payload) { return this._retryableRequest(this._cloudFrontClient.getDistribution(payload)).promise(); } /** * @returns {String} */ static get CF_HOSTED_ZONE_ID() { return 'Z2FDTNDATAQYW2'; } } exports.CloudFrontService = CloudFrontService;