UNPKG

rainbow-cli

Version:

Rainbow CLI application based on the Rainbow SDK for Node.js

763 lines (652 loc) 28.9 kB
"use strict"; const NodeSDK = require("../common/SDK"); const Message = require("../common/Message"); const CApplication = require("../commands/CApplication"); const Exit = require("../common/Exit"); const moment = require("moment"); const limiter = require("../common/Limiter"); class CInternal { constructor(prefs) { this._prefs = prefs; this._applications = new CApplication(this._prefs); } _formatCSVDevelopers(json, options) { let csvJSON = { data: [] }; let users = json; users.forEach(user => { let developerSince = "in error"; let payAsYouGoSince = ""; let sandboxSince = "-"; let hasASandboxAccount = user => { return user.developer && user.developer.sandbox; }; let hasADeveloperSandboxAccountSucceed = user => { return user.developer && user.developer.sandbox && user.developer.sandbox.status === "succeeded"; }; let hasAPaymentMethod = user => { return Boolean(user.developer.bsAccountId); }; developerSince = moment(user.developer.account.lastUpdateDate).format("LL"); if (hasASandboxAccount(user)) { if (hasADeveloperSandboxAccountSucceed(user)) { sandboxSince = moment(user.developer.sandbox.lastUpdateDate).format("LL"); } else { sandboxSince = "in error"; } } if (hasAPaymentMethod(user)) { payAsYouGoSince = moment(user.developer.accountCreationDate).format("LL"); } let line = []; line.push(user.lastName); line.push(user.firstName); line.push(user.country); line.push(user.loginEmail); line.push(user.companyName); line.push(user.company.country); line.push( user.company.isBP ? "yes" : user.company.bpId && user.company.bpId.length > 0 ? "affiliate" : "no" ); line.push(developerSince); line.push(sandboxSince); line.push(payAsYouGoSince); csvJSON["data"].push(line); }); return csvJSON; } _formatCSVInDeployment(json, options) { let csvJSON = { data: [] }; let apps = json.data; for (var i = 0; i < apps.length; i++) { let app = apps[i]; let user = app.user; let line = []; line.push(app.name); line.push(app.id); line.push(app.type); line.push(app.env); line.push(app.dateOfCreation); line.push(app.dateOfDeploymentRequest); line.push(app.activity); line.push(app.user.displayName); line.push(app.user.country); line.push(app.user.loginEmail); line.push(app.user.companyName); line.push(user.company.country); line.push( user.company.isBP ? "yes" : user.company.bpId && user.company.bpId.length > 0 ? "affiliate" : "no" ); csvJSON["data"].push(line); } return csvJSON; } _formatCSVMetrics(json, options) { let csvJSON = { data: [] }; let apps = json.data; // TODO : manage internal / external & active options /!\ let internalPatterns = ["al-enterprise.com", "al-mydemo.com", "cpaas.applicationid@provisoire.com"]; apps.forEach(app => { let isInternal = internalPatterns.some(pattern => { return app.user.loginEmail.includes(pattern); }); let data = app.metrics; let res = 0; let admin = 0; let webrtc = 0; let turn = 0; let file = 0; let cost = 0; if (data) { data.forEach(metric => { switch (metric.group) { case "administration": admin = metric.count; if (admin > 2000) { cost += (admin - 2000) * 0.005; } break; case "resources": res = metric.count; if (res > 5000) { cost += (res - 5000) * 0.001; } break; case "webrtc_minutes": webrtc = metric.count; if (webrtc > 500) { cost += (webrtc - 500) * 0.005; } break; case "turn": turn = metric.count; break; case "storage": file = metric.count; if (file > 5) { cost += (file - 5) * 0.1; } break; } }); } var consumption = res + admin + webrtc + turn + file; var result = ((options.intOrExt === "internal" && isInternal) || (options.intOrExt === "external" && !isInternal) || options.intOrExt === "both") && ((options.active && consumption > 0) || !options.active); console.log("isInternal: " + (isInternal?"YES":"NO") + " active: " + (options.active?"YES":"NO") + " consumption: " + consumption + " result: " + result); if ( ((options.intOrExt === "internal" && isInternal) || (options.intOrExt === "external" && !isInternal) || options.intOrExt === "both") && ((options.active && consumption > 0) || !options.active) ) { let line = []; let isBusiness = true; line.push(app.name); line.push(app.id); line.push(app.kpi); line.push(app.type); line.push(app.activity); line.push(app.user.firstName + " " + app.user.lastName); line.push(app.user.country); line.push(app.user.loginEmail); line.push(app.user.companyName); line.push(app.dateOfCreation); line.push(app.dateOfDeployment); if (options.kpi === "business") { line.push(app.deployReason || ""); } line.push(app.state); line.push(res); line.push(admin); line.push(webrtc); line.push(turn); line.push(file); if (isBusiness) { line.push(0); } else { line.push(cost.toFixed(2)); } csvJSON["data"].push(line); } }); return csvJSON; } _getCompanyInfo(token, id) { let random = Math.floor(Math.random() * 500) + 1; return new Promise(resolve => { setTimeout(() => { NodeSDK.get(`/api/rainbow/admin/v1.0/companies/${id}?format=full`, token) .then(json => { resolve(json.data); }) .catch(err => { resolve(null); }); }, random); }); } _getUser(token, id) { return new Promise(function(resolve, reject) { let random = Math.floor(Math.random() * 500) + 1; setTimeout(() => { NodeSDK.get("/api/rainbow/admin/v1.0/users/" + id, token) .then(function(json) { resolve(json); }) .catch(err => { NodeSDK.get("/api/rainbow/enduser/v1.0/users/" + id, token) .then(function(json) { resolve(json); }) .catch(err => { resolve({ data: { loginEmail: "unknown", firstName: "-", lastName: "-" } }); }); }); }, random); }); } _dashboardApplications(token, options) { const BATCH_SIZE=10; var groups = []; var categories = []; let apps = []; let filterToApply = "format=full&env=deployed&limit=1000"; filterToApply += "&kpi=" + options.kpi; if (options.owner) { filterToApply += "&ownerId=" + options.owner; } filterToApply += "&sortField=ownerId"; return new Promise((resolve, reject) => { this._applications ._getGroupMetrics(token) .then(jsonGroups => { if (jsonGroups.data) { for (var group in jsonGroups.data) { jsonGroups.data[group].forEach(function(metric) { groups.push(metric); }); } categories = jsonGroups.data; } return NodeSDK.get("/api/rainbow/applications/v1.0/applications?" + filterToApply, token); }) .then( async jsonApps => { apps = jsonApps.data; let promisesUser = []; let promisesResolved = [] for( let i = 0; i < apps.length; i++ ) { promisesUser.push( this._getUser(token, apps[i].ownerId)) if( i%BATCH_SIZE === BATCH_SIZE-1 || i == apps.length -1 ) { let result = await Promise.all(promisesUser); promisesResolved = promisesResolved.concat( result ) promisesUser = []; } } return Promise.resolve( promisesResolved ); }) .then( async jsonUsers => { jsonUsers.forEach((user, index) => { apps[index].user = user.data; }); let promises = []; let promisesResolved= []; for( let i = 0; i < apps.length; i++ ){ let appOptions = Object.assign({}, options); appOptions.appid = apps[i].id; appOptions.forcePeriod = "month"; promises.push(this._applications._getMetrics(token, appOptions)); if( i % BATCH_SIZE === BATCH_SIZE-1 || i === apps.length - 1 ){ let result = await Promise.all(promises); promisesResolved = promisesResolved.concat( result ) promises = []; } } return Promise.resolve( promisesResolved ); }) .then(jsonMetrics => { let seconds = ["audio", "video", "webrtc_minutes"]; jsonMetrics.forEach((metrics, index) => { var aggregatedApp = []; metrics.data.forEach(metric => { let groups = metric.groupCounters; // Put webrtc trafic in minutes (received in s) if (groups) { groups.forEach(group => { if (seconds.includes(group.group)) { group.count = Math.round(group.count / 60); } }); for (var category in categories) { if (!aggregatedApp.find(function(element) { return element.group === category; })) { aggregatedApp.push({ group: category, count: 0 }); } } groups.forEach(group => { for (var category in categories) { if (categories[category].includes(group.group)) { aggregatedApp.forEach((aggregated, index) => { if (aggregated.group === category) { aggregatedApp[index].count += group.count; } }); } } }); } apps[index].metrics = aggregatedApp; }); }); resolve({ data: apps }); }) .catch(function(err) { reject(err); }); }); } _dashboardInDeployment(token, options) { let apps = []; let filterToApply = "format=full&env=in_deployment&limit=1000"; return new Promise((resolve, reject) => { NodeSDK.get("/api/rainbow/applications/v1.0/applications?" + filterToApply, token) .then(jsonApps => { apps = jsonApps.data; let promisesUser = []; apps.forEach(application => { promisesUser.push(this._getUser(token, application.ownerId)); }); return Promise.all(promisesUser); }) .then(jsonUsers => { let companies = [], promisesCompanies = []; jsonUsers.forEach((userData, index) => { let user = userData.data; apps[index].user = user; if (!companies.includes(user.companyId)) { companies.push(user.companyId); } }); companies.forEach(id => { promisesCompanies.push(this._getCompanyInfo(token, id)); }); Promise.all(promisesCompanies).then(listOfCompanies => { for (let i = 0; i < apps.length; i++) { let company = listOfCompanies.find(c => { return c.id === apps[i].user.companyId; }); apps[i].user.company = company; } resolve({ data: apps }); }); }) .catch(function(err) { reject(err); }); }); } _dashboardDevelopers(token, options) { let getDevelopers = (offset, limit, existing) => { return new Promise(function(resolve, reject) { let filterToApply = "format=full&roles=app_admin&sortField=companyId&limit=" + limit + "&offset=" + offset * limit; NodeSDK.get("/api/rainbow/admin/v1.0/users?" + filterToApply, token).then(json => { existing.push(...json.data); offset += 1; if (json.total > limit * offset) { return getDevelopers(offset, limit, existing).then(json => { resolve(json); }); } resolve({ data: existing, total: existing.length }); }); }); }; let fromDate = null, toDate = null; if (options.month) { fromDate = moment(options.month, "YYYYMM").startOf("month"); toDate = moment(options.month, "YYYYMM").endOf("month"); } else { fromDate = moment().startOf("month"); toDate = moment().endOf("month"); } return new Promise((resolve, reject) => { getDevelopers(0, 1000, []) .then(users => { let companies = []; let listOfCompanies = []; let isADeveloper = user => { return user.developer && user.developer.account; }; let hasASandboxAccount = user => { return user.developer && user.developer.sandbox; }; let hasAPaymentMethod = user => { return Boolean(user.developer.bsAccountId); }; let shouldDisplayRegisteredSandbox = options => { return options.sandbox; }; let shouldDisplayRegisteredPaymentMethod = options => { return options.pay; }; let filteredUsers = users.data.filter(user => { if (!isADeveloper(user)) { return false; } if (shouldDisplayRegisteredPaymentMethod(options)) { if (!hasAPaymentMethod(user)) { return false; } return moment(user.developer.accountCreationDate).isBetween(fromDate, toDate); } else if (shouldDisplayRegisteredSandbox(options)) { if (!hasASandboxAccount(user)) { return false; } return moment(user.developer.sandbox.lastUpdateDate).isBetween(fromDate, toDate); } else { return moment(user.developer.account.lastUpdateDate).isBetween(fromDate, toDate); } }); filteredUsers.forEach(user => { if (!companies.includes(user.companyId)) { companies.push(user.companyId); } }); companies.forEach(id => { limiter.limiter1param(this._getCompanyInfo, token, id, company => { listOfCompanies.push(company); }); }); limiter.stop().then(() => { for (let i = 0; i < filteredUsers.length; i++) { let company = listOfCompanies.find(c => { return c.id === filteredUsers[i].companyId; }); filteredUsers[i].company = company; } resolve({ data: filteredUsers, total: users.total }); }); }) .catch(err => { reject(err); }); }); } dashboardApplications(options) { var that = this; Message.welcome(options); if (this._prefs.token && this._prefs.user) { Message.loggedin(this._prefs, options); if (!options.csv) { Message.action("Dashboard applications metrics", options.kpi, options); } let spin = Message.spin(options); NodeSDK.start( this._prefs.email, this._prefs.password, this._prefs.host, this._prefs.proxy, this._prefs.appid, this._prefs.appsecret ) .then(function() { Message.log("execute action..."); return that._dashboardApplications(that._prefs.token, options); }) .then(function(json) { Message.unspin(spin); Message.log("action done...", json); if (options.csv) { let columns = [ "Name", "Id", "Offer", "Type", "Activity", "Owner name", "Owner country", "Owner email", "Company name", "Creation date", "Deployed date" ]; if (options.kpi === "business") { columns.push("Deployed reason"); } columns.push( "Current state", "API resources", "API administration", "WebRTC minutes", "TURN bytes", "File storage", "Fees" ); let jsonCSV = that._formatCSVMetrics(json, options); Message.csv(options.csv, jsonCSV.data, false, columns) .then(() => {}) .catch(err => { Exit.error(); }); } else if (options.noOutput) { Message.out(json.data); } else { Message.tableDashboardMetrics(json.data, options); } Message.log("finished! will exit!"); Exit.ok(); }) .catch(function(err) { Message.unspin(spin); Message.error(err, options); Exit.error(); }); } else { Message.notLoggedIn(options); Exit.error(); } } dashboardInDeployment(options) { var that = this; Message.welcome(options); if (this._prefs.token && this._prefs.user) { Message.loggedin(this._prefs, options); if (!options.csv) { Message.action("Dashboard applications in deployment", null, options); } let spin = Message.spin(options); NodeSDK.start( this._prefs.email, this._prefs.password, this._prefs.host, this._prefs.proxy, this._prefs.appid, this._prefs.appsecret ) .then(function() { Message.log("execute action..."); return that._dashboardInDeployment(that._prefs.token, options); }) .then(function(json) { Message.unspin(spin); Message.log("action done...", json); if (options.csv) { let columns = [ "Name", "Id", "Type", "Environment", "Creation date", "Request date", "Activity", "Owner name", "Owner country", "Owner email", "Company name", "Company country", "Is BP/Affiliate" ]; let jsonCSV = that._formatCSVInDeployment(json, options); Message.csv(options.csv, jsonCSV.data, false, columns) .then(() => {}) .catch(err => { Exit.error(); }); } else if (options.noOutput) { Message.out(json.data); } else { Message.tableDashboardInDeployment(json, options); } Message.log("finished! will exit!"); Exit.ok(); }) .catch(function(err) { Message.unspin(spin); Message.error(err, options); Exit.error(); }); } else { Message.notLoggedIn(options); Exit.error(); } } dashboardDevelopers(options) { var that = this; Message.welcome(options); if (this._prefs.token && this._prefs.user) { Message.loggedin(this._prefs, options); if (!options.csv) { Message.action("Dashboard developers metrics", null, options); } let spin = Message.spin(options); NodeSDK.start( this._prefs.email, this._prefs.password, this._prefs.host, this._prefs.proxy, this._prefs.appid, this._prefs.appsecret ) .then(function() { Message.log("execute action..."); return that._dashboardDevelopers(that._prefs.token, options); }) .then(function(json) { Message.unspin(spin); Message.log("action done...", json); if (options.csv) { let columns = [ "Name", "Firstname", "Country", "Email", "Company name", "Company country", "is BP", "Registration date", "Sandbox registration date", "Payment Method" ]; let jsonCSV = that._formatCSVDevelopers(json.data, options); Message.csv(options.csv, jsonCSV.data, false, columns) .then(() => {}) .catch(err => { Exit.error(); }); } else if (options.noOutput) { Message.out(json.data); } else { Message.tableDashboardDevelopers(json, options); } Message.log("finished! will exit!"); Exit.ok(); }) .catch(function(err) { Message.unspin(spin); Message.error(err, options); Exit.error(); }); } else { Message.notLoggedIn(options); Exit.error(); } } } module.exports = CInternal;