388 lines
16 KiB
JavaScript
388 lines
16 KiB
JavaScript
'use strict';
|
|
const axios = require('axios');
|
|
const https = require("https");
|
|
const SMTP_EMAIL_SENDER = process.env.SMTP_EMAIL_SENDER;
|
|
|
|
const HOSTNAME_URL = process.env.HOSTNAME_URL || "https://qmicloud.qliktech.com";
|
|
const FOOTER = `<div style="color:#404040;font-size:16px;padding:30px 0px 50px 0px">
|
|
<p style="margin:0px">Check it out at <a href="${HOSTNAME_URL}">${HOSTNAME_URL}</a></p>
|
|
</div>`;
|
|
|
|
|
|
const getFooter = function(provision) {
|
|
return `<div style="color:#404040;font-size:16px;padding:30px 0px 50px 0px">
|
|
<p style="margin:0px">Check it out at <a href="${HOSTNAME_URL}/provision/${provision._id}">${HOSTNAME_URL}/provision/${provision._id}</a></p>
|
|
</div>`;
|
|
}
|
|
|
|
|
|
async function _doSend(to, subject, htmlText) {
|
|
try {
|
|
var body = {
|
|
"to": to,
|
|
"subject": subject,
|
|
"html": htmlText
|
|
};
|
|
await axios({
|
|
url: SMTP_EMAIL_SENDER,
|
|
method: "post",
|
|
data: body,
|
|
httpsAgent: new https.Agent({
|
|
rejectUnauthorized: false
|
|
})
|
|
});
|
|
console.log('SendEmail (Qlik SMTP)# message sent to: ' + to);
|
|
|
|
} catch (err) {
|
|
// Handle Error Here
|
|
console.log("SendEmail (Qlik SMTP) _doSend error: could not send the email to: " +to);
|
|
}
|
|
}
|
|
|
|
function _getCommonDetails(provision, scenario){
|
|
var description = decodeURI(scenario.description);
|
|
var externalAccess = provision.isExternalAccess? 'Yes' : 'No';
|
|
var schedule = "";
|
|
if ( !provision.schedule || provision.schedule.is24x7 ) {
|
|
schedule = "24x7";
|
|
} else if ( provision.schedule && !provision.schedule.is24x7 ) {
|
|
schedule = `from ${provision.schedule.localeStartupTime}h until ${provision.schedule.localeShutdownTime}h (${provision.schedule.localTimezone})`;
|
|
}
|
|
return `<div style="color:#404040;font-size:18px;margin:20px 0px">
|
|
<p style="margin:0px">Provision information:</p>
|
|
</div>
|
|
<div>
|
|
<span style="color:#404040">ID: </span> ${provision._id}
|
|
</div>
|
|
<div>
|
|
<span style="color:#404040">VMs Running schedule: </span> ${schedule}
|
|
</div>
|
|
<div>
|
|
<span style="color:#404040">Purpose: </span> ${provision.description}
|
|
</div>
|
|
<div>
|
|
<span style="color:#404040">Scenario: </span> ${scenario.title}
|
|
</div>
|
|
<div>
|
|
<span style="color:#404040">With external access: </span> ${externalAccess}
|
|
</div>
|
|
<div>
|
|
<span style="color:#404040">Description: </span> ${description}
|
|
</div>`;
|
|
}
|
|
|
|
function getHtmlScenarioDestroyIn24( provision, scenario, period, warningDays) {
|
|
var common = _getCommonDetails(provision,scenario);
|
|
return`<div style="width:600px;color:black!important;font-family:'Source Sans Pro',sans-serif;padding:50px">
|
|
<div style="background-color:white;height:100%;padding:20px 10px">
|
|
<div style="color:#404040;font-size:34px;text-align:center;margin:20px">
|
|
<p style="margin:0px">QMI Cloud</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:22px;margin:20px 0px 40px 0px">
|
|
<p style="margin:0px">Provision '${scenario.title}' inactive more than ${period} days</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:18px;margin:10px 0px">
|
|
<p style="margin:0px;color: #FF2020">This scenario will be automatically DESTROYED in ${(warningDays*24)} hours.</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:16px;margin:30px 0px">
|
|
<p style="margin:0px">If you don't want this to happen, you've got ${(warningDays*24)} hours (from when this email was sent) as a grace period to get back at 'Running' status this provision.</p>
|
|
</div>
|
|
${common}
|
|
${FOOTER}
|
|
</div>
|
|
</div>`;
|
|
}
|
|
|
|
function getHtmlScenarioIndays( provision, scenario, period, warningDays) {
|
|
var common = _getCommonDetails(provision,scenario);
|
|
return`<div style="width:600px;color:black!important;font-family:'Source Sans Pro',sans-serif;padding:50px">
|
|
<div style="background-color:white;height:100%;padding:20px 10px">
|
|
<div style="color:#404040;font-size:34px;text-align:center;margin:20px">
|
|
<p style="margin:0px">QMI Cloud</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:22px;margin:20px 0px 40px 0px">
|
|
<p style="margin:0px">Provision '${scenario.title}' running more than ${period} days</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:18px;margin:10px 0px">
|
|
<p style="margin:0px;color: #FF2020">This scenario was meant to live active no more than 90 days. It's been 80 days since creation and it will be automatically DESTROYED in ${warningDays} days. Please, consider to backup it up manually if you don't want to lose data.</p>
|
|
</div>
|
|
${common}
|
|
${FOOTER}
|
|
</div>
|
|
</div>`;
|
|
}
|
|
|
|
|
|
function getHtmlScenarioVMsStopped( provision, scenario) {
|
|
var common = _getCommonDetails(provision,scenario);
|
|
return `<div style="width:600px;color:black!important;font-family:'Source Sans Pro',sans-serif;padding:50px">
|
|
<div style="background-color:white;height:100%;padding:20px 10px">
|
|
<div style="color:#404040;font-size:34px;text-align:center;margin:20px">
|
|
<p style="margin:0px">QMI Cloud</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:22px;margin:20px 0px 40px 0px">
|
|
<p style="margin:0px">Provision '${scenario.title}'</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:18px;margin:10px 0px">
|
|
<p style="margin:0px;color: #FF2020">All VMs for this provision <b>stopped</b> automatically.</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:16px;margin:30px 0px">
|
|
<p style="margin:0px">You can start them up again from <a href="${HOSTNAME_URL}">${HOSTNAME_URL}</a></p>
|
|
</div>
|
|
${common}
|
|
${FOOTER}
|
|
</div>
|
|
</div>`;
|
|
}
|
|
|
|
function getHtmlSharedProvision( provision, scenario) {
|
|
var common = _getCommonDetails(provision,scenario);
|
|
return `<div style="width:600px;color:black!important;font-family:'Source Sans Pro',sans-serif;padding:50px">
|
|
<div style="background-color:white;height:100%;padding:20px 10px">
|
|
<div style="color:#404040;font-size:34px;text-align:center;margin:20px">
|
|
<p style="margin:0px">QMI Cloud</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:22px;margin:20px 0px 40px 0px">
|
|
<p style="margin:0px">Provision '${scenario.title}'</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:18px;margin:30px 0px">
|
|
<p style="margin:0px;color: #FF2020">'${provision.user.displayName}' is sharing with you!</p>
|
|
</div>
|
|
|
|
${common}
|
|
${FOOTER}
|
|
</div>
|
|
</div>`;
|
|
}
|
|
|
|
function getHtmlRotateKeyProvision(provision, scenario) {
|
|
var htmlint;
|
|
if ( provision && provision.outputs ) {
|
|
htmlint = `<div style="color:#404040;font-size:20px;padding: 10px 0px;">New Storage Account Details:</div>`;
|
|
htmlint += `<table style="width:100%" border="0">`;
|
|
} else {
|
|
htmlint = "";
|
|
}
|
|
for (let key in provision.outputs) {
|
|
if (key.includes("StorageAccount-")){
|
|
htmlint += `<tr>
|
|
<td style="padding-right: 15px"><b style="color:#404040">${key}</b></td>
|
|
<td><pre style="color:#404040;">${provision.outputs[key]}</pre></td>
|
|
</tr>`;
|
|
}
|
|
}
|
|
|
|
if ( provision && provision.outputs ) {
|
|
htmlint += `</table>`;
|
|
}
|
|
|
|
var myFooter = getFooter(provision);
|
|
var common = `<div style="color:#404040;font-size:18px;margin:20px 0px">
|
|
<p style="margin:0px">Provision information:</p>
|
|
</div>
|
|
<div>
|
|
<span style="color:#404040">Provision ID: </span> ${provision._id}
|
|
</div>
|
|
<div>
|
|
<span style="color:#404040">Purpose: </span> ${provision.description}
|
|
</div>
|
|
<div>
|
|
<span style="color:#404040">Scenario: </span> ${scenario.title}
|
|
</div>`;
|
|
|
|
return `<div style="width:600px;color:black!important;font-family:'Source Sans Pro',sans-serif;padding:50px">
|
|
<div style="background-color:white;height:100%;padding:20px 10px">
|
|
<div style="color:#404040;font-size:34px;text-align:center;margin:20px">
|
|
<p style="margin:0px">QMI Cloud</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:22px;margin:20px 0px">
|
|
<p style="margin:0px">Scenario '${scenario.title}' - Storage Account Access Key!</p>
|
|
</div>
|
|
<div style="color:#404040;margin:20px 0px">
|
|
<p style="margin:0px">In order to improve security, your Storage Account Access Key in this QMI scenario provision has been rotated. You may need to update your Storage Account connections with bellow new details.</p>
|
|
</div>
|
|
|
|
${common}
|
|
|
|
<div style="margin: 30px 0px;">
|
|
${htmlint}
|
|
</div>
|
|
${myFooter}
|
|
|
|
</div>
|
|
</div>`;
|
|
}
|
|
|
|
function getHtmlScenarioWillStopIn24( provision, scenario, period, warningDays ) {
|
|
var common = _getCommonDetails(provision,scenario);
|
|
return`<div style="width:600px;color:black!important;font-family:'Source Sans Pro',sans-serif;padding:50px">
|
|
<div style="background-color:white;height:100%;padding:20px 10px">
|
|
<div style="color:#404040;font-size:34px;text-align:center;margin:20px">
|
|
<p style="margin:0px">QMI Cloud</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:22px;margin:20px 0px 40px 0px">
|
|
<p style="margin:0px">Provision '${scenario.title}' - VMs running for ${period} days</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:18px;margin:10px 0px">
|
|
<p style="margin:0px;color: #FF2020">This scenario will automatically stop its VMs in ${warningDays*24} hours.</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:18px;margin:20px 0px 10px 0px">
|
|
<p style="margin:0px;color: #FF2020">Take action and extend the period ${(period+warningDays)} extra days.</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:16px;margin:30px 0px">
|
|
<p style="margin:0px">If you don't want the VMs to automatically stop, you've got ${warningDays*24} hours (from when this email was sent) as a grace period to extend this scenario's <b style="color: #009845">Running</b> VMs for ${(period+warningDays)} extra days.</p>
|
|
</div>
|
|
${common}
|
|
${FOOTER}
|
|
</div>
|
|
</div>`;
|
|
}
|
|
function getHtmlNewProvision(provision, scenario) {
|
|
var htmlint;
|
|
if ( provision && provision.outputs ) {
|
|
htmlint = `<div style="color:#404040;font-size:20px;padding: 10px 0px;">Connection resources</div>`;
|
|
htmlint += `<table style="width:100%" border="0">`;
|
|
} else {
|
|
htmlint = "";
|
|
}
|
|
for (let key in provision.outputs) {
|
|
htmlint += `<tr>
|
|
<td style="padding-right: 15px"><b style="color:#404040">${key}</b></td>
|
|
<td><pre style="color:#404040;">${provision.outputs[key]}</pre></td>
|
|
</tr>`;
|
|
}
|
|
|
|
if ( provision && provision.outputs ) {
|
|
htmlint += `</table>`;
|
|
}
|
|
|
|
var common = _getCommonDetails(provision, scenario);
|
|
|
|
return `<div style="width:600px;color:black!important;font-family:'Source Sans Pro',sans-serif;padding:50px">
|
|
<div style="background-color:white;height:100%;padding:20px 10px">
|
|
<div style="color:#404040;font-size:34px;text-align:center;margin:20px">
|
|
<p style="margin:0px">QMI Cloud</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:22px;margin:20px 0px">
|
|
<p style="margin:0px">Scenario '${scenario.title}' successfully provisioned!</p>
|
|
</div>
|
|
|
|
${common}
|
|
|
|
<div style="margin: 30px 0px;">
|
|
${htmlint}
|
|
</div>
|
|
${FOOTER}
|
|
|
|
</div>
|
|
</div>`;
|
|
}
|
|
|
|
function getHtmlErrorProvision(provision, scenario) {
|
|
var common = _getCommonDetails(provision, scenario);
|
|
return`<div style="width:600px;color:black!important;font-family:'Source Sans Pro',sans-serif;padding:50px">
|
|
<div style="background-color:white;height:100%;padding:20px 10px">
|
|
<div style="color:#404040;font-size:34px;text-align:center;margin:20px">
|
|
<p style="margin:0px">QMI Cloud</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:20px;margin:20px 0px">
|
|
<p style="margin:0px;color: #FF2020">Oops! Something didn't work.</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:20px;margin:20px 0px 50px 0px">
|
|
<p style="margin:0px">Scenario '${scenario.title}' failed during provision.</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:16px;margin:30px 0px">
|
|
<p style="margin:0px">Please, follow these steps:</p>
|
|
<ul>
|
|
<li>Reach out the person responsible for this scenario for support.</li>
|
|
<li>As soon as it's possible, consider destroy this provision since it's taking valuable cloud resources which might imply relevant cost.</li>
|
|
</ul>
|
|
</div>
|
|
${common}
|
|
${FOOTER}
|
|
</div>
|
|
</div>`;
|
|
}
|
|
|
|
function getHtmlDestroyProvision(provision, scenario) {
|
|
var common = _getCommonDetails(provision, scenario);
|
|
return`<div style="width:600px;color:black!important;font-family:'Source Sans Pro',sans-serif;padding:50px">
|
|
<div style="background-color:white;height:100%;padding:20px 10px">
|
|
<div style="color:#404040;font-size:34px;text-align:center;margin:20px">
|
|
<p style="margin:0px">QMI Cloud</p>
|
|
</div>
|
|
<div style="color:#404040;font-size:20px;margin:40px 0px">
|
|
<p style="margin:0px">Scenario '${scenario.title}' successfully destroyed!</p>
|
|
</div>
|
|
${common}
|
|
${FOOTER}
|
|
</div>
|
|
</div>`;
|
|
}
|
|
|
|
|
|
// async..await is not allowed in global scope, must use a wrapper
|
|
async function sendProvisionSuccess( provision, scenario ) {
|
|
const htmlText = getHtmlNewProvision(provision, scenario);
|
|
await _doSend(provision.user.upn, 'QMI Cloud - Provision finished successfully', htmlText);
|
|
}
|
|
|
|
async function sendProvisionError(provision, scenario ) {
|
|
const htmlText = getHtmlErrorProvision(provision, scenario);
|
|
await _doSend(provision.user.upn, 'QMI Cloud - Provision with errors', htmlText);
|
|
}
|
|
|
|
async function sendDestroyedSuccess(provision, scenario ) {
|
|
|
|
const htmlText = getHtmlDestroyProvision(provision, scenario);
|
|
await _doSend(provision.user.upn, 'QMI Cloud - Provision destroyed successfully', htmlText);
|
|
|
|
}
|
|
|
|
async function sendWillStopIn24( provision, scenario, period, warningDays ) {
|
|
|
|
const htmlText = getHtmlScenarioWillStopIn24( provision, scenario, period, warningDays);
|
|
await _doSend(provision.user.upn, `QMI Cloud - VMs will stop in ${warningDays*24} hours`, htmlText);
|
|
|
|
}
|
|
|
|
async function sendWillDestroyIn24( provision, scenario, period, warningDays ) {
|
|
|
|
const htmlText = getHtmlScenarioDestroyIn24( provision, scenario, period, warningDays);
|
|
await _doSend(provision.user.upn, `QMI Cloud - Provision will destroy in ${(warningDays*24)} hours`, htmlText);
|
|
}
|
|
|
|
async function sendWillDestroyInDays( provision, scenario, period, warningDays ) {
|
|
|
|
const htmlText = getHtmlScenarioIndays( provision, scenario, period, warningDays);
|
|
await _doSend(provision.user.upn, `QMI Cloud - Provision will destroy in ${warningDays} days`, htmlText);
|
|
}
|
|
|
|
async function sendVMsStopped( provision, scenario ) {
|
|
const htmlText = getHtmlScenarioVMsStopped( provision, scenario);
|
|
await _doSend(provision.user.upn, 'QMI Cloud - VMs stopped automatically', htmlText);
|
|
}
|
|
|
|
async function sendSharedProvision(provision, shareWithUser) {
|
|
const htmlText = getHtmlSharedProvision( provision, provision._scenarioDoc);
|
|
await _doSend(shareWithUser.upn, `${provision.user.displayName} shared a QMI Cloud provision with you.`, htmlText);
|
|
}
|
|
|
|
async function sendRotateKey(provision, user) {
|
|
const htmlText = getHtmlRotateKeyProvision( provision, provision._scenarioDoc);
|
|
await _doSend(user.upn, `QMI Cloud - NEW Storage Account Access Key`, htmlText);
|
|
}
|
|
|
|
module.exports.sendProvisionSuccess = sendProvisionSuccess;
|
|
module.exports.sendProvisionError = sendProvisionError;
|
|
module.exports.sendDestroyedSuccess = sendDestroyedSuccess;
|
|
module.exports.sendWillStopIn24 = sendWillStopIn24;
|
|
module.exports.sendWillDestroyInDays = sendWillDestroyInDays;
|
|
module.exports.sendVMsStopped = sendVMsStopped;
|
|
module.exports.sendWillDestroyIn24 = sendWillDestroyIn24;
|
|
module.exports.sendSharedProvision= sendSharedProvision;
|
|
module.exports.sendRotateKey = sendRotateKey;
|
|
module.exports._doSend = _doSend;
|
|
|
|
|