terraform-plus
Version:
Terraform Plus
255 lines (221 loc) • 6.31 kB
JavaScript
'use strict';
const fs = require('fs-extra');
const path = require('path');
const yaml = require('js-yaml');
const AbstractCommand = require('./abstract-command');
class TerraformCommand extends AbstractCommand {
/**
* @desc Validates options passed via cli
*
* @returns {Boolean} - Returns true if options given from cli are valid.
*
* @private
*/
_validateOptions() {
if (this._directory === path.basename(this._directory)) {
this._logger.warn(`Option --directory='${this._directory}' is invalid. ${this._suffix}`);
return false;
}
if (this._templates[this._directory]) {
this._logger.error(`Directory template '${this._directory}' is missing. ${this._suffix}`);
return false;
}
if (this.getFilesPath([this._directory]).length <= 0) {
this._logger.error(`No terraform files were found in path '${this._directory}'`);
return false;
}
return super._validateOptions();
}
/**
* @desc Gets paths which have .tf files in them.
*
* @param {Array} originPaths - --path value entered from cli
* @param {Array} arr - Empty array which will contain dirs what have .tf files
*
* @returns {Array} - returns arr
*/
getFilesPath(originPaths, arr = []) {
let dirs = [];
let tfFiles = [];
originPaths.forEach(srcPath => {
this._logger.debug(`Initial path : ${srcPath}`);
// reads Sync srcPath and joins their paths
let items = this._fs.readdirSync(srcPath).map(x => this._path.join(srcPath, x));
// folders which have .tf extention
//tfFiles = items.filter(file => file.match(/.*\.tf$/));
// folder which have main.tf file
tfFiles = items.filter(file => file.match(/\/main.tf$/));
// analyses if a file is a directory and pushes it.
dirs.push(...items.filter(file => this._fs.lstatSync(file).isDirectory()));
// Pushes currentDir if they have .tf files
if (tfFiles.length > 0) {
let currentDir = path.dirname(tfFiles.pop());
if (this.hasProvider(currentDir) && this.include(currentDir) && this.exclude(currentDir)) {
arr.push(currentDir);
}
dirs = dirs.filter(item => !item.includes(currentDir));
}
});
if (dirs.length === 0) {
return arr;
}
return this.getFilesPath(dirs, arr);
}
include(directory) {
let confPath = path.join(directory,this._paramFile);
if (fs.existsSync(confPath)) {
let tfsConf = yaml.safeLoad(fs.readFileSync(confPath, 'utf8'));
if (this._cli.include && tfsConf) {
let include = this._cli.include.split(',');
if (include.indexOf(tfsConf.id) < 0) {
return false;
}
}
}
return true;
}
exclude(directory) {
let confPath = path.join(directory,this._paramFile);
if (fs.existsSync(confPath)) {
let tfsConf = yaml.safeLoad(fs.readFileSync(confPath, 'utf8'));
if (this._cli.exclude && tfsConf) {
let exclude = this._cli.exclude.split(',');
if (exclude.indexOf(tfsConf.id) >= 0) {
return false;
}
}
}
return true;
}
hasProvider(directory) {
let confPath = path.join(directory,this._paramFile);
if (fs.existsSync(confPath)) {
let tfsConf = yaml.safeLoad(fs.readFileSync(confPath, 'utf8'));
if (this._provider && tfsConf) {
return (tfsConf.provider === this._provider);
} else {
//if provider not defined, add folders
return true;
}
}
return false;
}
/**
*
* @param {Array} list
* @return {*}
*/
findBranch(list) {
let result = {};
if (this._cli.branch) {
//console.log(list[this._cli.branch]);
let child = this.findElement(list, this._cli.branch, 0);
if (child && Object.keys(child).length > 0) {
for (let i in child) {
result[i] = this._cli.branch;
if (child[i]) {
// TODO: too many nested blocks :(
for (let j in child[i]) {
result[j] = i;
}
}
}
}
let parent = this.findParent(list, this._cli.branch);
if (Object.keys(parent).length > 0) {
for (let i in parent) {
result[parent[i]] = i;
}
for (let i in parent) {
if (!result[i]) {
result[i] = null;
this._layers[0] = [i];
}
}
} else {
result[this._cli.branch] = null;
this._layers[0] = [this._cli.branch];
}
return result;
}
}
/**
*
* @param {Array} list
* @param {String} value
* @param {Array} arr
* @return {*}
*/
findParent(list, value, arr = {}) {
if (list[value] && list[value] !== null) {
arr[list[value]] = value;
let result = this.findParent(list, list[value], arr);
if (result) {
return result;
} else {
return arr;
}
}
return false;
}
/**
*
* @param {Array} list
* @return {Array}
*/
listToTree(list) {
let result = [];
this._layers[0].forEach(id => {
let element = this.findElement(list, id, 0);
result[id] = element;
});
return result;
}
/**
*
* @param {Array} list
* @param {String} element
* @param {Number} layer
* @return {Array|Null}
*/
findElement(list, element, layer) {
let arr = [];
layer++;
//this._layers[++layer] = [];
for (let i in list) {
if (list[i] === element) {
if (!this._layers[layer]) {
this._layers[layer] = [];
}
if (this._layers[layer].indexOf(i) < 0) {
this._layers[layer].push(i);
}
let result = this.findElement(list, i, layer);
if (arr[i]) {
arr[i] = {};
}
if (result) {
arr[i] = this.extend({}, arr[i], result);
} else {
arr[i] = null;
}
}
}
return Object.keys(arr).length > 0 ? arr : null;
}
/**
*
* @param {Object} target
* @return {Object}
*/
extend(target) {
var sources = [].slice.call(arguments, 1);
sources.forEach(function(source) {
for (var prop in source) {
target[prop] = source[prop];
}
});
return target;
}
}
module.exports = TerraformCommand;