terraform-plus
Version:
Terraform Plus
151 lines (134 loc) • 4.24 kB
JavaScript
;
const fs = require('fs');
const yaml = require('js-yaml');
const treeify = require('treeify');
const ProgressBar = require('progress');
const Aws = require('../helpers/aws');
const TerraformCommand = require('../terraform-command');
class DeployCommand extends TerraformCommand {
/**
* @desc Validates options passed via cli
*
* @returns {Boolean} - Returns true if options given from cli are valid.
*
* @private
*/
_validateOptions() {
this._logger.debug(`this._cli : ${this._cli}`);
return super._validateOptions();
}
/**
* @desc Deploys software from predefined deploy.yml config files
*/
run() {
this._layers = [[]];
this._logger.debug(`templates : ${this.templates}`);
this._folders = {};
this._graph = {};
this.getFilesPath([this._directory]).forEach(element => {
if (fs.existsSync(element)) {
let tfsConf = yaml.safeLoad(fs.readFileSync(`${element}/${this._paramFile}`, 'utf8'));
this._folders[tfsConf.id] = element;
if (tfsConf && tfsConf.parent && !this._cli.include) {
this._graph[tfsConf.id] = tfsConf.parent;
} else if (!this._graph[tfsConf.id]) {
this._graph[tfsConf.id] = null;
this._layers[0].push(tfsConf.id);
}
}
});
console.log('Building tree:');
let graph = this._graph;
if (this._cli.branch) {
graph = this.findBranch(this._graph);
console.log(treeify.asTree(this.listToTree(graph), true));
} else {
console.log(treeify.asTree(this.listToTree(graph), true));
}
console.log('Start terraform deploy\n');
if (!this._verbose) {
this.bar = new ProgressBar('Run deploy [:bar] :percent :elapseds',
{ total: Object.keys(graph).length * 2, width: 30 });
this.bar.tick(0);
}
this.deploy();
return Promise.resolve();
}
/**
*
* @return {Promise<void>}
*/
async deploy() {
let bar = this.bar;
let tf = this.terraform();
let verbose = this._verbose;
for (let id in this._layers) {
let folders = this._folders;
let deploy = this;
let promises = this._layers[id].map(async function(element) {
let elementPath = folders[element];
if (!verbose) {
bar.tick();
}
await deploy.execPromise(tf, elementPath, element);
if (!verbose) {
bar.tick();
}
});
await Promise.all(promises);
}
}
/**
*
* @param tf
* @param elementPath
* @return {Promise<any>}
*/
execPromise(tf, elementPath, element) {
let paramFolder = DeployCommand.TFS_PATH;
let deployFile = DeployCommand.TFS_DEPLOY_CONFIG;
return new Promise(function(resolve, reject) {
tf.then((terraform) => {
terraform.apply(elementPath).then(() => {
if (fs.existsSync(`${elementPath}/${paramFolder}/${deployFile}`)) {
let tfsConf = yaml.safeLoad(fs.readFileSync(`${elementPath}/${paramFolder}/${deployFile}`, 'utf8'));
let s3Paths = tfsConf.aws.s3;
s3Paths.forEach((s3Path) => {
Aws.s3upload(element, `${elementPath}/${s3Path.path}`, s3Path.key);
});
}
}).then(() => {
resolve();
});
});
});
}
/**
* @returns {String}
*/
static get DESCRIPTION() {
return 'deploy software from predefined deploy.yml config files'
}
/**
* @returns {String}
*/
static get OPTIONS() {
return [{
opt: '-p, --provider [provider]',
desc: 'terraform provider name (e.g. aws, azurerm, google)'
}, {
opt: '-i, --include [comma_separated_values]',
desc: 'comma separated values of terraform scripts or folders to be included'
}, {
opt: '-e, --exclude [comma_separated_values]',
desc: 'comma separated values of terraform scripts or folders to be excluded'
}, {
opt: '-d, --directory [directory]',
desc: 'path where terraform will be executed (default value - current working directory)'
}, {
opt: '-b, --branch [branch]',
desc: 'path where terraform will be executed (default value - current working directory)'
}];
}
}
module.exports = DeployCommand;