const express = require('express') const router = express.Router() const db = require('@QMI/qmi-cloud-common/mongo'); const passport = require('../passport-okta'); const fs = require('fs-extra'); const cli = require('@QMI/qmi-cloud-common/cli'); /** * @swagger * /provisions: * get: * description: Get all Provisions * summary: Get all Provisions * tags: * - admin * produces: * - application/json * parameters: * - name: filter * in: query * required: false * type: object * content: * application/json: * schema: * type: object * - name: populates * in: query * required: false * type: array * - name: select * in: query * required: false * type: string * - name: page * in: query * required: false * type: integer * - name: size * in: query * required: false * type: integer * responses: * 200: * description: JSON Array */ router.get('/', passport.ensureAuthenticatedAndAdmin, async (req, res, next) => { try { let filter = req.query.filter? JSON.parse(req.query.filter) : {}; if ( filter.isDeleted === undefined ) { filter.isDeleted = false; } var page; if ( req.query.page && req.query.size ) { page = { page: parseInt(req.query.page), size: parseInt(req.query.size) } } const result = await db.provision.getPage(filter, page, req.query.populates, req.query.select); if (result.next){ result.nextUrl = new URL('https://' + req.hostname + req.baseUrl); if ( req.query.filter ) { result.nextUrl.searchParams.append("filter", req.query.filter); } if ( req.query.populates ) { result.nextUrl.searchParams.append("populates", req.query.populates); } if ( req.query.select ) { result.nextUrl.searchParams.append("select", req.query.select); } result.nextUrl.searchParams.append("page", result.next.page); result.nextUrl.searchParams.append("size", result.next.size); } return res.json(result); } catch (error) { next(error); } }); /** * @swagger * /provisions/azure-app-reg: * post: * description: Update existing APP Reg Outputs for active provisions * summary: Update existing APP Reg Outputs for active provisions * tags: * - admin * produces: * - application/json * parameters: * - name: client_id * in: query * required: true * type: string * - name: client_secret * in: query * required: true * type: string * responses: * 200: * description: JSON Array */ router.post('/azure-app-reg', passport.ensureAuthenticated, async (req, res, next) => { try { const result = await db.provision.get({"status": "provisioned", "isDestroyed": false, "isDeleted": false}, "outputs", null, null, "[]"); result.results.forEach( (p) =>{ if (p.outputs && p.outputs['Azure_Application_Registration_Client_ID'] && p.outputs['Azure_Application_Registration_Client_ID'] === req.query.client_id ) { p.outputs['Azure_Application_Registration_Secret'] = req.query.client_secret; db.provision.update(p._id, {"outputs": p.outputs}); } }); return res.json(); } catch (error) { next(error); } }); /** * @swagger * /provisions/optionssLogs: * get: * description: Get all optionss * summary: Get all optionss * produces: * - application/json * parameters: * - name: filter * in: query * required: false * type: object * content: * application/json: * schema: * type: object * - name: skip * in: query * required: false * type: integer * - name: limit * in: query * required: false * type: integer * responses: * 200: * description: JSON Array */ router.get('/optionssLogs', passport.ensureAuthenticated, async (req, res, next) => { try { let filter = req.query.filter? JSON.parse(req.query.filter) : {}; filter.isDeleted = {"$exists": true}; let select = "_id options" let populates = "[]"; const result = await db.provision.get(filter, select, req.query.skip, req.query.limit, populates); var final = []; result.results.forEach(p=>{ for( let key in p.options ) { var o = { "_id": p._id.toString(), "vmIndex": key, "vmType": p.options[key].vmType? p.options[key].vmType : null, "diskSizeGb": p.options[key].diskSizeGb? p.options[key].diskSizeGb : null, "versionProduct": p.options[key].selected? p.options[key].selected.name : null, "versionImage": p.options[key].selected? p.options[key].selected.value : null } final.push(o); } }) var out = { total: result.total, count: result.count }; if ( result.nextSkip && result.nextLimit ) { out.nextUrl = new URL('https://' + req.hostname + req.baseUrl); if ( req.query.filter ) { out.nextUrl.searchParams.append("filter", req.query.filter); } if ( req.query.populates ) { out.nextUrl.searchParams.append("populates", req.query.populates); } out.nextUrl.searchParams.append("skip", result.nextSkip); out.nextUrl.searchParams.append("limit", result.nextLimit); } out.results = final; return res.json(out); } catch (error) { next(error); } }); /** * @swagger * /provisions/{id}: * get: * description: Get Provision by ID * summary: Get a Terraform Provision details by ID * tags: * - admin * produces: * - application/json * parameters: * - name: id * in: path * type: string * required: true * responses: * 200: * description: Provision * 404: * description: Not found * */ router.get('/:id', passport.ensureAuthenticatedAndAdmin, async (req, res, next) => { try { const mongoJob = await db.provision.getById(req.params.id); if (!mongoJob){ return res.status(404).json({"msg": "Not found"}); } return res.json(mongoJob); } catch (error) { next(error); } }); /** * @swagger * /provisions/{id}: * delete: * description: Delete Provision by ID * summary: Delete a Terraform Provision by ID * tags: * - admin * produces: * - application/json * parameters: * - name: id * in: path * type: string * required: true * responses: * 200: * description: Provision * 404: * description: Not found * */ router.delete('/:id', passport.ensureAuthenticatedAndAdmin, async (req, res, next) => { try { const mongoJob = await db.provision.getById(req.params.id); if (!mongoJob){ return res.status(404).json({"msg": "Not found"}); } const toDestroy = await db.destroy.get({"provId": req.params.id}); const delDest = await db.destroy.del(toDestroy[0]._id.toString()); const delProv = await db.provision.del(req.params.id); //Move folder fs.moveSync(`/provisions/${mongoJob.scenario}_${req.params.id}`, `/provisions/deleted/${mongoJob.scenario}_${req.params.id}`, { overwrite: true }) return res.json({"provision": delProv, "destroy": delDest}); } catch (error) { next(error); } }); /** * @swagger * /provisions/{id}: * put: * description: Update Provision by ID * summary: Update Provision by ID * tags: * - admin * parameters: * - 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('/:id', passport.ensureAuthenticatedAndAdmin, async (req, res, next) => { try { const result = await db.provision.update(req.params.id, req.body); return res.json(result); } catch (error) { next(error); } }); /** * @swagger * /provisions/{id}/logs: * get: * description: Get Logs for Provision by ID * summary: Get Logs for a Provision by ID * produces: * - text/plain * parameters: * - name: id * in: path * type: string * required: true * responses: * 200: * description: Log file * 404: * description: Not found */ router.get('/:id/logs', passport.ensureAuthenticated, async (req, res, next) => { try { const mongoJob = await db.provision.getById(req.params.id); if (!mongoJob){ return res.status(404).json({"msg": "Not found"}); } return res.sendFile(mongoJob.logFile); } catch (error) { next(error); } }); /** * @swagger * /provisions/{id}/snapshots: * get: * description: Get Snapshots for a provision * summary: Get Snapshots for a provision * tags: * - admin * produces: * - application/json * parameters: * - name: id * in: path * type: string * required: true * responses: * 200: * description: OK * 404: * description: Not found * */ router.get('/:id/snapshots', passport.ensureAuthenticated, async (req, res, next) => { try { const snaps = await db.snapshot.get({"provision": req.params.id}, null, null, null, '["provision","owner"]'); return res.json(snaps); } catch (error) { next(error); } }); /** * @swagger * /provisions/{id}/snapshots: * post: * description: Create Snapshots from all disks of this provision * summary: Create Snapshots from all disks of this provision * tags: * - admin * produces: * - application/json * parameters: * - name: id * in: path * type: string * required: true * responses: * 200: * description: OK * 404: * description: Not found * */ router.post('/:id/snapshots', passport.ensureAuthenticatedAndAdmin, async (req, res, next) => { try { const snaps = await cli.createSnapshots(req.params.id, "QMI-Machines", req.user._id); return res.json(snaps); } catch (error) { next(error); } }); /** * @swagger * /provisions/{id}/updatetagsvms: * post: * description: Update Tags in VMs for this provision * summary: Update Tags in VMs for this provision * tags: * - admin * produces: * - application/json * parameters: * - name: id * in: path * type: string * required: true * requestBody: * required: true * content: * application/json: * schema: * type: object * responses: * 200: * description: Provision * 404: * description: Not found * */ router.post('/:id/updatetagsvms', passport.ensureAuthenticatedAndAdmin, async (req, res, next) => { try { let tagsEdit = req.body; if ( !tagsEdit ) { return res.json({"msg": "No tags to be updated", "success": false}); } 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, "success": false}); } var result = await cli.updateVmsTags(provision._id, tagsEdit); return res.json({"msg": "Tags are being updated", "result": result, "success": true}); } catch (error) { next(error); } }); module.exports = router;