This commit is contained in:
Manuel Romero
2024-06-12 16:12:26 +02:00
parent dc2ff34955
commit 0f26e92eea
7 changed files with 2932 additions and 0 deletions

View File

@@ -3,10 +3,12 @@ echo "--- Building QMI Cloud docker images for branch $CI_COMMIT_REF_NAME"
export VERSION_APP=$(cat package.json | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[",]//g' | tr -d '[[:space:]]')
export VERSION_WORKER=$(cat qmi-cloud-worker/package.json | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[",]//g' | tr -d '[[:space:]]')
export VERSION_CLI=$(cat qmi-cloud-cli/package.json | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[",]//g' | tr -d '[[:space:]]')
export VERSION_WEBHOOK=$(cat qmi-cloud-webhook/package.json | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[",]//g' | tr -d '[[:space:]]')
export TAG_APP=$VERSION_APP
export TAG_WORKER=$VERSION_WORKER
export TAG_CLI=$VERSION_CLI
export TAG_WEBHOOK=$VERSION_WEBHOOK
export STABLE_TAG="latest"
export BUILD_ENV=""
@@ -14,6 +16,7 @@ if [ "$CI_COMMIT_REF_NAME" != "master" ]; then
TAG_APP="$VERSION_APP-$CI_COMMIT_REF_NAME"
TAG_WORKER="$VERSION_WORKER-$CI_COMMIT_REF_NAME"
TAG_CLI="$VERSION_CLI-$CI_COMMIT_REF_NAME"
TAG_WEBHOOK="$VERSION_WEBHOOK-$CI_COMMIT_REF_NAME"
STABLE_TAG="latestdev"
BUILD_ENV="staging"
fi
@@ -44,3 +47,12 @@ docker push qlikgear/qmi-cloud-app:$TAG_APP
docker image tag qlikgear/qmi-cloud-app:$TAG_APP qlikgear/qmi-cloud-app:$STABLE_TAG
#docker build -f ./Dockerfile -t qlikgear/qmi-cloud-app:$STABLE_TAG ./
docker push qlikgear/qmi-cloud-app:$STABLE_TAG
echo "--- Building image: qlikgear/qmi-cloud-webhook:$TAG_WEBHOOK"
docker build -f ./qmi-cloud-webhook/Dockerfile -t qlikgear/qmi-cloud-webhook:$TAG_WEBHOOK ./
echo "--- Pushing image: qlikgear/qmi-cloud-webhook:$TAG_WEBHOOK"
docker push qlikgear/qmi-cloud-webhook:$TAG_WEBHOOK
docker image tag qlikgear/qmi-cloud-webhook:$TAG_WEBHOOK qlikgear/qmi-cloud-webhook:$STABLE_TAG
#docker build -f ./qmi-cloud-webhook/Dockerfile -t qlikgear/qmi-cloud-webhook:$STABLE_TAG ./
docker push qlikgear/qmi-cloud-webhook:$STABLE_TAG

View File

@@ -0,0 +1,20 @@
# Stage 1:
FROM node:20.14-alpine AS sources
RUN apk --no-cache add yarn git
WORKDIR /app
ADD ./qmi-cloud-webhook ./
ADD ./qmi-cloud-common ../qmi-cloud-common
RUN yarn install --production
# Stage 2:
FROM node:20.14-alpine AS production
WORKDIR /app
COPY --from=sources /app ./
EXPOSE 5050
CMD ["node", "index.js"]

84
qmi-cloud-webhook/app.js Normal file
View File

@@ -0,0 +1,84 @@
'use strict'
/* dependencies */
const express = require('express');
const NodeCache = require( "node-cache" );
const TRIGGER_STATUS = process.env.TRIGGER_STATUS || "Stopped";
const LOGEVENT_NAME = process.env.LOGEVENT_NAME || "AzureWebhook";
const SERVICE_NAME = process.env.SERVICE_NAME || "QMI Automation";
const processEvent = require('./process-event');
// Create an Express application.
const app = express();
const myCache = new NodeCache( { stdTTL: 300 } ); //5 minutes cache
// Add body parser.
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Add routers
app.post('/', (req, res) => {
var now = new Date();
now = now.toISOString();
const event = req.body;
if ( event.data && event.data.context && event.data.context.activityLog ) {
var rgName = event.data.context.activityLog.resourceGroupName;
var provId = rgName.split("-")[rgName.split("-").length-1];
var sendData = {
"provID": provId,
"rgName": rgName,
"cloudName": SERVICE_NAME,
"instanceState": TRIGGER_STATUS,
"logEvent": LOGEVENT_NAME
};
if ( !myCache.get( provId ) ) {
myCache.set(provId, sendData);
console.log(`${now}# ProvId (${provId}). Sending '${sendData.instanceState}' to QMICLOUD (${process.env.QMICLOUD_API_URL})...`, sendData);
processEvent.onEvent(sendData);
/*axios({
method: 'post',
url: process.env.QMICLOUD_API_URL,
headers: { 'QMI-ApiKey' : process.env.QMICLOUD_KEY },
data: sendData
}).then(function (response) {
myCache.set(provId, sendData);
}).catch(function(err){
myCache.del(provId);
console.log('Error# ', err);
});*/
} else {
console.log(`${now}# ProvId (${provId}) recently sent. Won't be sent again.`);
}
}
res.json(event);
})
app.post('/test', (req, res) => {
console.log("Calling /test POST endpoint");
res.send("OK");
});
app.use((req, res, next) => res.send("404"))
app.use((err, req, res, next) => {
console.error(err)
if (res.headerSent) return next(err)
return res.send("500")
})
module.exports = app;

View File

@@ -0,0 +1,11 @@
let port = process.env.PORT || 5050;
const app = require('./app');
// Start listening for requests.
app.listen(port, ()=>{
console.log("Server is running on port ", port);
});
process.on('uncaughtException', err => console.error('uncaught exception:', err.toString()));
process.on('unhandledRejection', error => console.error('unhandled rejection:', error.toString()));

View File

@@ -0,0 +1,14 @@
{
"name": "qmi-cloud-webhook",
"version": "1.0.0",
"description": "qmi-cloud-webhook",
"main": "index.js",
"scripts": {
"start": "node ./index.js"
},
"dependencies": {
"express": "^4.19.2",
"node-cache": "^5.1.2",
"qmi-cloud-common": "../qmi-cloud-common"
}
}

View File

@@ -0,0 +1,132 @@
const db = require('qmi-cloud-common/mongo');
const MYQUEUES = require('qmi-cloud-common/queues');
const queues = MYQUEUES.queues;
const SYNAPSE_QUEUE = MYQUEUES.SYNAPSE_QUEUE;
const onEvent = async function (event) {
const dateNow = new Date();
const now = dateNow.toISOString();
const logEvent = event && event.logEvent || 'DivvyCloud';
try {
if (event.cloudName === 'QMI Automation') {
console.log(`${logEvent} (${now})# event received for subscription (${event.cloudName}) - provision (${event.provID}) -> new status (${event.instanceState})`);
if (event.provID && event.provID !== 'None') {
let provision = await db.provision.getById(event.provID);
if (provision) {
var type = "vms";
if (logEvent.indexOf("RDS") !== -1) {
type = "db";
}
let id = provision._id.toString();
console.log(`${logEvent} (${now})# provision (${id}) - scenario is (${provision.scenario} - v${provision.scenarioVersion})`);
if (provision.status === 'provisioned' || provision.status === 'error') {
if (event.instanceState === 'Stopped') {
//Check active children provisions
let children = await db.provision.get({ "parent": provision._id, "isDestroyed": false, "isDeleted": false });
if (children.results.length > 0) {
let result = await db.apiKey.getOne({ "apiKey": process.env.QMICLOUD_KEY });
var user;
if (result) {
user = result.user;
}
children.results.forEach(function (child) {
if (child.scenario === 'azqmi-synapse') {
queues[SYNAPSE_QUEUE].add("synapse_job", {
provId: child._id,
user: user,
tasktype: 'pause'
});
}
});
}
if (provision.statusVms === 'Stopped') {
console.log(`${logEvent} (${now})# provision (${id}) - were already Stopped!`);
} else {
let timeRunning = db.utils.getNewTimeRunning(provision);
let patch = {
"statusVms": "Stopped",
"timeRunning": timeRunning,
"stoppedFrom": dateNow,
"pendingNextAction": null
};
if (provision.schedule && !provision.schedule.is24x7) {
patch["endDateOnSchedule"] = dateNow;
//This is temporary, only to make sure there is value
if (!provision["startDateOnSchedule"]) {
patch["startDateOnSchedule"] = dateNow;
}
}
await db.provision.update(id, patch);
console.log(`${logEvent} (${now})# provision (${id}) - changed to Stopped!`);
db.event.add({ provision: provision._id, type: `${type}.stop`, message: `[Divvy] TotalTimeRunning: ${timeRunning} mins` });
}
} else if (event.instanceState === 'Running') {
if (provision.statusVms === 'Running') {
console.log(`${logEvent} (${now})# provision (${id}) - were already Running!`);
} else {
let patch = {
"statusVms": "Running",
"runningFrom": dateNow,
"pendingNextAction": null
};
// This is temporary, only to make sure there are values soon
if (provision.schedule && !provision.schedule.is24x7) {
if (!provision["startDateOnSchedule"]) {
patch["startDateOnSchedule"] = dateNow;
patch["endDateOnSchedule"] = dateNow;
}
}
await db.provision.update(id, patch);
console.log(`${logEvent} (${now})# provision (${id}) - changed to Running!`);
db.event.add({ provision: provision._id, type: `${type}.start`, message: `[Divvy] TotalTimeRunning: ${provision.timeRunning} mins` });
}
}
} else {
console.log(`${logEvent} (${now})# provision (${event.provID}) - Scenario not yet 'provisioned'`);
}
} else {
console.log(`${logEvent} (${now})# provision (${event.provID}) - Provision not found.`);
}
} else {
console.log(`${logEvent} (${now})# 'provID' attribute is missing.`);
}
} else {
//console.log(`${logEvent} (${now}): event received for subscription (${event.cloudName}) --> won't be processed`);
}
return res.json(event);
} catch (error) {
console.log(`${logEvent} (${now})# error!!!!`, error);
}
}
module.exports.onEvent = onEvent;

2659
qmi-cloud-webhook/yarn.lock Normal file

File diff suppressed because it is too large Load Diff