berlioz
Version:
Berlioz - cloud deployment and migration services
323 lines (276 loc) • 7.66 kB
JavaScript
const CliTable = require('./cli-table');
const _ = require('the-lodash');
const util = require('util');
const {stopwatch} = require('durations');
class Screen
{
constructor(screenWidth)
{
this.setupScreen(screenWidth);
}
get screenWidth() {
return this._screenWidth;
}
setupScreen(width)
{
this._screenWidth = width;
if (!this._screenWidth) {
this._screenWidth = 100;
}
}
stopwatch()
{
const watch = stopwatch();
watch.start();
return {
finish() {
watch.stop()
var ms = watch.duration().millis();
var seconds = ms / 1000;
seconds = seconds.toFixed(2);
return `[${seconds}s]`;
}
}
}
error(str)
{
return this._write('ERROR: ', arguments);
}
warn(str)
{
return this._write('WARNING: ', arguments);
}
info()
{
return this._write('', arguments);
}
header()
{
var msg = this._massageFormat(arguments);
var line = "";
var x = (this._screenWidth - msg.length - 2) / 2;
if (x > 0) {
line += '*'.repeat((this._screenWidth - msg.length - 2) / 2);
}
line += ' ' + msg + ' ';
var x = this._screenWidth - line.length;
if (x > 0) {
line += '*'.repeat(x);
}
this._rawOutput();
this.line();
this._rawOutput(line);
}
line()
{
return this._rawOutput('*'.repeat(this._screenWidth));
}
_write(header, formats)
{
for(var i = 0; i < formats.length; i++)
{
if (_.isObject(formats[i]) && !_.isString(formats[i])) {
formats[i] = JSON.stringify(formats[i], null, 2);
}
}
var line = header + this._massageFormat(formats);
this._rawOutput(line);
}
_rawOutput(line)
{
if (!line) {
console.log();
} else {
console.log(line);
}
}
_massageFormat(formats)
{
formats = Array.from(formats);
var values = formats.map(x => {
if (_.isObject(x)) {
JSON.stringify(x, null, 2);
} else {
return x;
}
});
return util.format.apply(null, values);
}
table(headers)
{
var table = new CliTable(this, headers);
return table;
}
invertedTable(rows, ignoreKeys)
{
var headerMap = {};
var newRows = [];
var columns = [];
for(var row of rows)
{
var newRowMap = {};
for(var entry of row)
{
var key = entry[0];
if (ignoreKeys) {
if (_.includes(ignoreKeys, key)) {
continue;
}
}
var value = entry[1];
if (!(key in headerMap)) {
headerMap[key] = _.keys(headerMap).length;
columns.push(key);
}
newRowMap[key] = value;
}
newRows.push(newRowMap);
}
var finalRows = [];
for(var newRowMap of newRows)
{
var finalRow = [];
for(var column of columns)
{
var value = 'N/A'
if (column in newRowMap) {
value = newRowMap[column];
}
finalRow.push(value);
}
finalRows.push(finalRow);
}
// console.log("NEW TABLE COLUMNS:")
// console.log(columns)
// console.log("FINAL ROWS:")
// console.log(finalRows)
var table = this.table(columns);
return table;
}
outputEntity(entity)
{
this.header('%s %s', _.toUpper(entity.kind), entity.id);
var data = [];
entity.extractData(data);
this.table()
.autofitColumn('Property')
.column('Value')
.addRange(data)
.output();
this.outputLinks(entity);
}
outputService(service)
{
this.outputEntity(service);
if (_.values(service.provides).length > 0) {
this.header('SERVICE %s ENDPOINTS PROVIDED', service.id);
this.invertedTable(_.values(service.provides).map(x => {
var data = [];
x.extractData(data);
return data;
}), ['naming', 'dn', 'kind', 'path']).output();
}
}
outputConsumes(item)
{
if (item.allLinks.length > 0) {
this.header('%s %s CONSUMED', _.toUpper(item.kind), item.id);
this.invertedTable(item.allLinks.map(x => {
var data = [];
x.extractData(data);
return data;
}), ['naming', 'dn', 'kind', 'path']).output();
}
}
outputLinks(item)
{
if (item.allLinks.length > 0) {
this.header('%s %s LINKS', _.toUpper(item.kind), item.id);
this.invertedTable(item.allLinks.map(x => {
var data = [];
x.extractData(data);
return data;
}), ['naming', 'dn', 'kind', 'path', 'dockerfile', 'class', 'subclass', 'extendSymlinks']).output();
}
}
outputDatabase(database)
{
this.outputEntity(database);
this.header('DATABASE %s ATTRIBUTES', database.id);
this.table(['Name', 'Type', 'Key Type'])
.addRange(database.attributes, x => [x.name, x.type, x.keyType])
.output();
}
outputQueue(queue)
{
this.outputEntity(queue);
}
outputTrigger(trigger)
{
this.outputEntity(trigger);
}
outputSecret(secret)
{
this.outputEntity(secret);
}
outputLambda(lambda)
{
this.outputEntity(lambda);
}
outputCluster(cluster)
{
this.outputEntity(cluster);
this.header('CLUSTER %s PROVIDED', cluster.id);
this.invertedTable(_.values(cluster.provides).map(x => {
var data = [];
x.extractData(data);
return data;
}), ['naming', 'dn', 'kind', 'path']).output();
for(var sector of cluster.sectors)
{
this.outputSector(sector);
}
for(var service of cluster.services)
{
this.outputService(service);
}
for(var database of cluster.databases)
{
this.outputDatabase(database);
}
for(var queue of cluster.queues)
{
this.outputQueue(queue);
}
for(var secret of cluster.secrets)
{
this.outputSecret(secret);
}
for(var lambda of cluster.lambdas)
{
this.outputLambda(lambda);
}
for(var trigger of cluster.triggers)
{
this.outputTrigger(trigger);
}
}
outputSector(sector)
{
this.outputEntity(sector);
}
outputEndpoints(endpointMap)
{
var entries = _.keys(endpointMap).sort().map(id => {
var entry = endpointMap[id];
return {
identity: id,
endpoint: entry.protocol + '://' + entry.address + ':' + entry.port
};
});
this.table(['Identity', 'Endpoint'])
.addRange(entries, x => [x.identity, x.endpoint])
.output();
}
}
module.exports = Screen;