562 lines
15 KiB
JavaScript
562 lines
15 KiB
JavaScript
const express = require('express')
|
|
const router = express.Router()
|
|
const db = require('qmi-cloud-common/mongo');
|
|
const passport = require('../passport');
|
|
const fs = require('fs-extra');
|
|
const azurecli = require('qmi-cloud-common/azurecli');
|
|
|
|
import { queues, TF_APPLY_QUEUE, TF_APPLY_QSEOK_QUEUE, TF_DESTROY_QUEUE } from 'qmi-cloud-common/queues';
|
|
|
|
/**
|
|
* @swagger
|
|
* /users:
|
|
* get:
|
|
* description: Get all users
|
|
* summary: Get all users
|
|
* tags:
|
|
* - admin
|
|
* produces:
|
|
* - application/json
|
|
* responses:
|
|
* 200:
|
|
* description: User
|
|
*/
|
|
router.get('/', passport.ensureAuthenticatedAndAdmin, async (req, res, next) => {
|
|
try {
|
|
const result = await db.user.get();
|
|
return res.json(result);
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /users/me:
|
|
* get:
|
|
* description: Get profile logged-in user
|
|
* summary: Get logged-in user
|
|
* produces:
|
|
* - application/json
|
|
* responses:
|
|
* 200:
|
|
* description: User
|
|
*/
|
|
router.get('/me', passport.ensureAuthenticated, async (req, res, next) => {
|
|
try {
|
|
const result = await db.user.getById(req.user._id);
|
|
return res.json(result);
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /users/{userId}:
|
|
* get:
|
|
* description: Get profile for an user
|
|
* summary: Get profile for an user
|
|
* parameters:
|
|
* - name: userId
|
|
* in: path
|
|
* type: string
|
|
* required: true
|
|
* produces:
|
|
* - application/json
|
|
* responses:
|
|
* 200:
|
|
* description: User
|
|
*/
|
|
router.get('/:userId', passport.ensureAuthenticatedAndIsMe, async (req, res, next) => {
|
|
try {
|
|
const result = await db.user.getById(req.params.userId);
|
|
return res.json(result);
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /users/{userId}:
|
|
* put:
|
|
* description: Update profile for an user
|
|
* summary: Update profile for an user
|
|
* tags:
|
|
* - admin
|
|
* parameters:
|
|
* - name: userId
|
|
* in: path
|
|
* type: string
|
|
* required: true
|
|
* - in: body
|
|
* name: body
|
|
* description: User object
|
|
* required: true
|
|
* produces:
|
|
* - application/json
|
|
* responses:
|
|
* 200:
|
|
* description: User
|
|
*/
|
|
router.put('/:userId', passport.ensureAuthenticatedAndAdmin, async (req, res, next) => {
|
|
|
|
try {
|
|
const result = await db.user.update(req.params.userId, req.body);
|
|
return res.json(result);
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
|
|
/**
|
|
* @swagger
|
|
* /users/{userId}/provisions:
|
|
* post:
|
|
* description: Start a new Terraform provision
|
|
* summary: Start a new Terraform provision
|
|
* produces:
|
|
* - application/json
|
|
* parameters:
|
|
* - name: userId
|
|
* in: path
|
|
* type: string
|
|
* required: true
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* scenario:
|
|
* type: string
|
|
* description:
|
|
* type: string
|
|
* vmImage:
|
|
* type: object
|
|
* properties:
|
|
* vm1:
|
|
* type: object
|
|
* properties:
|
|
* vmType:
|
|
* type: string
|
|
* version:
|
|
* type: object
|
|
* properties:
|
|
* name:
|
|
* type: string
|
|
* image:
|
|
* type: string
|
|
* responses:
|
|
* 200:
|
|
* description: Provision
|
|
* 404:
|
|
* description: Scenario not found
|
|
* 400:
|
|
* description: Invalid vmImage
|
|
*/
|
|
router.post('/:userId/provisions', passport.ensureAuthenticatedAndIsMe, async (req, res, next) => {
|
|
try {
|
|
|
|
req.body.user = req.params.userId;
|
|
const scenarioSource = await db.scenario.getOne({name: req.body.scenario});
|
|
|
|
if (!scenarioSource) {
|
|
return res.status(404).json({"msg": "Scenario not found "});
|
|
}
|
|
|
|
if (!req.body.vmImage || !req.body.vmImage.vm1 || !req.body.vmImage.vm1.vmType ) {
|
|
return res.status(400).json({"msg": "Invalid vmImage"});
|
|
}
|
|
req.body.scenarioVersion = scenarioSource.version;
|
|
|
|
if ( req.body.autoShutdownData && req.body.autoShutdownData.is24x7 !== undefined ) {
|
|
const autoShutdown = await db.provisionAutoShutdown.add(req.body.autoShutdownData);
|
|
req.body.autoShutdown = autoShutdown._id;
|
|
}
|
|
|
|
const provision = await db.provision.add(req.body);
|
|
|
|
|
|
if ( provision.scenario === "azqmi-qseok" ){
|
|
queues[TF_APPLY_QSEOK_QUEUE].add("tf_apply_qseok_job", {
|
|
scenario: req.body.scenario,
|
|
vmType: req.body.vmType,
|
|
nodeCount: req.body.nodeCount,
|
|
id: provision._id,
|
|
user: req.user,
|
|
_scenario: scenarioSource
|
|
});
|
|
} else {
|
|
queues[TF_APPLY_QUEUE].add("tf_apply_job", {
|
|
scenario: req.body.scenario,
|
|
vmType: req.body.vmType,
|
|
nodeCount: req.body.nodeCount,
|
|
id: provision._id,
|
|
user: req.user,
|
|
_scenario: scenarioSource
|
|
});
|
|
}
|
|
|
|
return res.status(200).json(provision);
|
|
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /users/{userId}/provisions/{id}:
|
|
* put:
|
|
* description: Update Provision by ID
|
|
* summary: Update Provision by ID
|
|
* parameters:
|
|
* - name: userId
|
|
* in: path
|
|
* type: string
|
|
* required: true
|
|
* - name: id
|
|
* in: path
|
|
* type: string
|
|
* required: true
|
|
* - in: body
|
|
* name: body
|
|
* description: Provision object
|
|
* required: true
|
|
* produces:
|
|
* - application/json
|
|
* responses:
|
|
* 200:
|
|
* description: Provision
|
|
*/
|
|
router.put('/:userId/provisions/:id', passport.ensureAuthenticatedAndIsMe, async (req, res, next) => {
|
|
const provision = await db.provision.getById(req.params.id);
|
|
if (!provision){
|
|
return res.status(404).json({"msg": "Not found privision with id "+req.params.id});
|
|
}
|
|
|
|
try {
|
|
|
|
var resSchedule;
|
|
if ( req.body.autoShutdownData ) {
|
|
if ( req.body.autoShutdownData._id ) {
|
|
resSchedule = await db.provisionAutoShutdown.update(req.body.autoShutdownData._id, req.body.autoShutdownData);
|
|
} else {
|
|
resSchedule = await db.provisionAutoShutdown.add(req.body.autoShutdownData);
|
|
}
|
|
var tagsEdit = {
|
|
"24x7": resSchedule.is24x7? " " : false,
|
|
"StartupTime": resSchedule.utcTagStartupTime || false,
|
|
"ShutdownTime": resSchedule.utcTagShutdownTime || false
|
|
}
|
|
azurecli.updateVmsTags(provision, tagsEdit);
|
|
}
|
|
|
|
var patch = {};
|
|
if ( req.body.user ) {
|
|
patch.user = req.body.user;
|
|
}
|
|
if ( resSchedule ) {
|
|
patch.autoShutdown = resSchedule._id;
|
|
}
|
|
var result = {
|
|
provision: await db.provision.update(provision._id, patch)
|
|
}
|
|
return res.json(result);
|
|
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /users/{userId}/provisions/{id}:
|
|
* delete:
|
|
* description: Delete Provision by ID
|
|
* summary: Delete a Terraform Provision by ID
|
|
* produces:
|
|
* - application/json
|
|
* parameters:
|
|
* - name: userId
|
|
* in: path
|
|
* type: string
|
|
* required: true
|
|
* - name: id
|
|
* in: path
|
|
* type: string
|
|
* required: true
|
|
* responses:
|
|
* 200:
|
|
* description: Provision
|
|
* 404:
|
|
* description: Not found
|
|
*
|
|
*/
|
|
router.delete('/:userId/provisions/:id', passport.ensureAuthenticatedAndIsMe, async (req, res, next) => {
|
|
try {
|
|
|
|
const provision = await db.provision.getById(req.params.id);
|
|
if (!provision){
|
|
return res.status(404).json({"msg": "Not found privision with id "+req.params.id});
|
|
}
|
|
//var delDest = provision.destroy._id;
|
|
//if ( provision.destroy ) {
|
|
// delDest = await db.destroy.del(provision.destroy._id);
|
|
//}
|
|
const delProv = await db.provision.update(req.params.id, {"isDeleted": true});
|
|
|
|
//Move folder
|
|
if (fs.existsSync(`/provisions/${provision.scenario}_${req.params.id}`)) {
|
|
fs.moveSync(`/provisions/${provision.scenario}_${req.params.id}`, `/provisions/deleted/${provision.scenario}_${req.params.id}`, { overwrite: true })
|
|
}
|
|
return res.json({"provision": delProv, "destroy": delProv.destroy});
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /users/{userId}/provisions/{id}/deallocatevms:
|
|
* post:
|
|
* description: Stop all VMs for this provision
|
|
* summary: Stop all VMs for this provision
|
|
* produces:
|
|
* - application/json
|
|
* parameters:
|
|
* - name: userId
|
|
* in: path
|
|
* type: string
|
|
* required: true
|
|
* - name: id
|
|
* in: path
|
|
* type: string
|
|
* required: true
|
|
* responses:
|
|
* 200:
|
|
* description: Provision
|
|
* 404:
|
|
* description: Not found
|
|
*
|
|
*/
|
|
router.post('/:userId/provisions/:id/deallocatevms', passport.ensureAuthenticatedAndIsMe, async (req, res, next) => {
|
|
try {
|
|
|
|
let provision = await db.provision.getById(req.params.id);
|
|
if (!provision){
|
|
return res.status(404).json({"msg": "Not found provision with id "+req.params.id});
|
|
}
|
|
azurecli.deallocate(provision);
|
|
return res.json({"statusVms": "Stopping"});
|
|
|
|
} catch (error) {
|
|
db.provision.update(req.params.id, {"statusVms": "Error_Stopping"});
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /users/{userId}/provisions/{id}/startvms:
|
|
* post:
|
|
* description: Start all VMs for this provision
|
|
* summary: Start all VMs for this provision
|
|
* produces:
|
|
* - application/json
|
|
* parameters:
|
|
* - name: userId
|
|
* in: path
|
|
* type: string
|
|
* required: true
|
|
* - name: id
|
|
* in: path
|
|
* type: string
|
|
* required: true
|
|
* responses:
|
|
* 200:
|
|
* description: Provision
|
|
* 404:
|
|
* description: Not found
|
|
*
|
|
*/
|
|
router.post('/:userId/provisions/:id/startvms', passport.ensureAuthenticatedAndIsMe, async (req, res, next) => {
|
|
try {
|
|
|
|
let provision = await db.provision.getById(req.params.id);
|
|
if (!provision){
|
|
return res.status(404).json({"msg": "Not found privision with id "+req.params.id});
|
|
}
|
|
|
|
azurecli.start(provision);
|
|
return res.json({"statusVms": "Starting"});
|
|
|
|
} catch (error) {
|
|
db.provision.update(req.params.id, {"statusVms": "Error_Starting"});
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /users/{userId}/provisions/{id}/extend:
|
|
* post:
|
|
* description: Extend this provision Running more time
|
|
* summary: Extend this provision Running more time
|
|
* produces:
|
|
* - application/json
|
|
* parameters:
|
|
* - name: userId
|
|
* in: path
|
|
* type: string
|
|
* required: true
|
|
* - name: id
|
|
* in: path
|
|
* type: string
|
|
* required: true
|
|
* responses:
|
|
* 200:
|
|
* description: Provision
|
|
* 404:
|
|
* description: Not found
|
|
*
|
|
*/
|
|
router.post('/:userId/provisions/:id/extend', passport.ensureAuthenticatedAndIsMe, async (req, res, next) => {
|
|
try {
|
|
|
|
let provision = await db.provision.getById(req.params.id);
|
|
if (!provision){
|
|
return res.status(404).json({"msg": "Not found privision with id "+req.params.id});
|
|
}
|
|
|
|
/*if ( provision.countExtend === 5 ) {
|
|
return res.status(200).json({"msg": "You have reached the limit for the number of times to extend the Running VMs period."});
|
|
}*/
|
|
|
|
let timeRunning = db.utils.getNewTimeRunning(provision);
|
|
let countExtend = db.utils.getNewCountExtend(provision);
|
|
provision = await db.provision.update(req.params.id, {"runningFrom":new Date(), "timeRunning": timeRunning, "countExtend": countExtend, "pendingNextAction": undefined});
|
|
|
|
console.log(`Extending running period fo provision (${provision._id}), new total extends: ${countExtend}`);
|
|
|
|
return res.json(provision);
|
|
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /users/{userId}/provisions/{id}/destroy:
|
|
* post:
|
|
* description: Destroy a Terraform Provision
|
|
* summary: Destroy a Terraform Provision
|
|
* produces:
|
|
* - application/json
|
|
* parameters:
|
|
* - name: userId
|
|
* in: path
|
|
* type: string
|
|
* required: true
|
|
* - name: id
|
|
* in: path
|
|
* type: string
|
|
* required: true
|
|
* responses:
|
|
* 200:
|
|
* description: Provision
|
|
* 404:
|
|
* description: Not found
|
|
*
|
|
*/
|
|
router.post('/:userId/provisions/:id/destroy', passport.ensureAuthenticatedAndIsMe, async (req, res, next) => {
|
|
|
|
try {
|
|
|
|
let provision = await db.provision.getById(req.params.id);
|
|
if (!provision){
|
|
return res.status(404).json({"msg": "Not found privision with id "+req.params.id});
|
|
}
|
|
|
|
const destroyJob = await db.destroy.add({ "user": req.params.userId });
|
|
provision = await db.provision.update(req.params.id, {"destroy": destroyJob._id});
|
|
const scenarioSource = await db.scenario.getOne({name: provision.scenario});
|
|
|
|
queues[TF_DESTROY_QUEUE].add("tf_destroy_job", {
|
|
scenario: provision.scenario,
|
|
provId: provision._id,
|
|
user: req.user,
|
|
id: destroyJob._id,
|
|
_scenario: scenarioSource
|
|
});
|
|
|
|
return res.status(200).json(provision);
|
|
|
|
} catch (error) {
|
|
return res.status(error.output.statusCode).json({"err":error});
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /users/{userId}/provisions:
|
|
* get:
|
|
* description: Get all Provisions for an User
|
|
* summary: Get all Provisions for an User
|
|
* produces:
|
|
* - application/json
|
|
* parameters:
|
|
* - name: userId
|
|
* in: path
|
|
* type: string
|
|
* required: true
|
|
* responses:
|
|
* 200:
|
|
* description: JSON Array
|
|
*/
|
|
router.get('/:userId/provisions', passport.ensureAuthenticatedAndIsMe, async (req, res, next) => {
|
|
|
|
try {
|
|
const filter = {"user": req.params.userId, "isDeleted": false};
|
|
const result = await db.provision.get(filter);
|
|
return res.json(result);
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
|
|
/**
|
|
* @swagger
|
|
* /users/{userId}/destroyprovisions:
|
|
* get:
|
|
* description: Get all Destroy Provisions for an User
|
|
* summary: Get all Destroy Provisions for an User
|
|
* produces:
|
|
* - application/json
|
|
* parameters:
|
|
* - name: userId
|
|
* in: path
|
|
* type: string
|
|
* required: true
|
|
* responses:
|
|
* 200:
|
|
* description: JSON Array
|
|
*/
|
|
router.get('/:userId/destroyprovisions', passport.ensureAuthenticatedAndIsMe, async (req, res, next) => {
|
|
|
|
try {
|
|
const result = await db.destroy.get({"user": req.params.userId});
|
|
return res.json(result);
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
|
|
|
|
module.exports = router; |