12 Commits

Author SHA1 Message Date
Manuel Romero
e4f070826d Divvy toggle on scenario props 2020-07-14 15:02:58 +02:00
Manuel Romero
bf84db1254 Finished 24x7 UI 2020-07-14 13:37:37 +02:00
Manuel Romero
36ea9bbba1 Autoshutdown 2020-07-13 17:57:50 +02:00
Manuel Romero
bd63ef3837 costexports download file 2020-07-09 12:57:38 +02:00
Manuel Romero
0283850cce Assign user to provision 2020-07-06 14:33:17 +02:00
Manuel Romero
dd1380f13b discurage external access 2020-06-25 16:53:23 +02:00
Manuel Romero
811c1560c4 docker-compose back to version 3.7 2020-06-10 16:46:00 +02:00
Manuel Romero
257cc64d8d Added docker image versions for workers 2020-06-10 16:40:15 +02:00
Manuel Romero
7abf246fd5 some examples in readme.md 2020-06-08 10:33:51 +02:00
Manuel Romero
3aea0e6acc new version 2020-06-08 09:16:46 +02:00
Manuel Romero
d3bf735edc build order changed 2020-06-05 15:53:09 +02:00
Manuel Romero
de09fe22a7 build order changed 2020-06-05 15:43:25 +02:00
45 changed files with 636 additions and 145 deletions

Binary file not shown.

View File

@@ -6,8 +6,8 @@
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="assets/favicon.ico">
<link rel="stylesheet" href="styles.529f751cbb5308365172.css"></head>
<link rel="stylesheet" href="styles.096cda9efd9a8b224b3d.css"></head>
<body>
<app-root></app-root>
<script src="runtime.689ba4fd6cadb82c1ac2.js" defer></script><script src="polyfills-es5.f752a17531a45fe93c1f.js" nomodule defer></script><script src="polyfills.06ba8d1a3d9dd3a8e8b9.js" defer></script><script src="scripts.6866cf66954a0b739d41.js" defer></script><script src="main.a8feb6a790452d58d3ff.js" defer></script></body>
<script src="runtime.e227d1a0e31cbccbf8ec.js" defer></script><script src="polyfills-es5.f1f388528ea207060cbf.js" nomodule defer></script><script src="polyfills.335424f161535f57733f.js" defer></script><script src="scripts.5520a99f673924c17e00.js" defer></script><script src="main.39aa2c5b2de4993d0e07.js" defer></script></body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,4 @@
version: '3.8'
version: '3.7'
volumes:
redisdb:
@@ -55,11 +55,11 @@ services:
- source: qmicloud_config
target: config.json
environment:
- HOSTNAME_URL=https://localhost:3000
- HOSTNAME_URL=http://localhost:3000
- REDIS_URL=redis://redis
- MONGO_URI=mongodb://root:example@mongo/qmicloud?authSource=admin
#- CERT_PFX_FILENAME=wildcard_qliktech_com.pfx
#- CERT_PFX_PASSWORD=xxxxxxxxxxx
- CERT_PFX_FILENAME=
- CERT_PFX_PASSWORD=
command:
- ./server/wait-for.sh
- --timeout=20
@@ -92,8 +92,6 @@ services:
image: qlikgear/qmi-cloud-worker:latest
container_name: qmi-cloud-worker
restart: on-failure
deploy:
replicas: 2
environment:
- REDIS_URL=redis://redis
- MONGO_URI=mongodb://root:example@mongo/qmicloud?authSource=admin
@@ -101,6 +99,8 @@ services:
- GIT_SCENARIOS=git::git@gitlab.com:qmi/qmi-cloud-scenarios.git
- GIT_TAG=dev
- SSHPATH=/Users/aor/.ssh
- DOCKERIMAGE_AZURE_POWERSHELL=mcr.microsoft.com/azure-powershell:4.2.0-ubuntu-18.04
- DOCKERIMAGE_TERRAFORM=qlikgear/terraform:1.0.1
command: "sh -c 'npm run start:dev'"
volumes:
# -- Dev only volumes

View File

@@ -18,27 +18,24 @@ fi
echo "$DOCKER_REGISTRY_PASSWORD" | docker login --username "$DOCKER_REGISTRY_USER" --password-stdin
echo "--- Building image: qlikgear/qmi-cloud-app:$TAG_APP"
docker build -f ./Dockerfile -t qlikgear/qmi-cloud-app:$TAG_APP ./
echo "--- Pushing image: qlikgear/qmi-cloud-app:$TAG_APP"
docker push qlikgear/qmi-cloud-app:$TAG_APP
echo "--- Building image: qlikgear/qmi-cloud-cli:$TAG_CLI"
docker build -f ./qmi-cloud-cli/Dockerfile -t qlikgear/qmi-cloud-cli:$TAG_CLI ./
echo "--- Pushing image: qlikgear/qmi-cloud-cli:$TAG_CLI"
docker push qlikgear/qmi-cloud-cli:$TAG_CLI
docker build -f ./qmi-cloud-cli/Dockerfile -t qlikgear/qmi-cloud-cli:$STABLE_TAG ./
docker push qlikgear/qmi-cloud-cli:$STABLE_TAG
echo "--- Building image: qlikgear/qmi-cloud-worker:$TAG_WORKER"
docker build -f ./qmi-cloud-worker/Dockerfile -t qlikgear/qmi-cloud-worker:$TAG_WORKER ./
echo "--- Pushing image: qlikgear/qmi-cloud-worker:$TAG_WORKER"
docker push qlikgear/qmi-cloud-worker:$TAG_WORKER
docker build -f ./qmi-cloud-worker/Dockerfile -t qlikgear/qmi-cloud-worker:$STABLE_TAG ./
docker push qlikgear/qmi-cloud-worker:$STABLE_TAG
echo "--- Building image: qlikgear/qmi-cloud-cli:$TAG_CLI"
docker build -f ./qmi-cloud-cli/Dockerfile -t qlikgear/qmi-cloud-cli:$TAG_CLI ./
echo "--- Pushing image: qlikgear/qmi-cloud-cli:$TAG_CLI"
docker push qlikgear/qmi-cloud-cli:$TAG_CLI
if [ "$CI_COMMIT_REF_NAME" = "master" ] || [ "$CI_COMMIT_REF_NAME" = "dev" ]; then
docker build -f ./Dockerfile -t qlikgear/qmi-cloud-app:$STABLE_TAG ./
docker build -f ./qmi-cloud-worker/Dockerfile -t qlikgear/qmi-cloud-worker:$STABLE_TAG ./
docker build -f ./qmi-cloud-cli/Dockerfile -t qlikgear/qmi-cloud-cli:$STABLE_TAG ./
docker push qlikgear/qmi-cloud-app:$STABLE_TAG
docker push qlikgear/qmi-cloud-worker:$STABLE_TAG
docker push qlikgear/qmi-cloud-cli:$STABLE_TAG
fi
echo "--- Building image: qlikgear/qmi-cloud-app:$TAG_APP"
docker build -f ./Dockerfile -t qlikgear/qmi-cloud-app:$TAG_APP ./
echo "--- Pushing image: qlikgear/qmi-cloud-app:$TAG_APP"
docker push qlikgear/qmi-cloud-app:$TAG_APP
docker build -f ./Dockerfile -t qlikgear/qmi-cloud-app:$STABLE_TAG ./
docker push qlikgear/qmi-cloud-app:$STABLE_TAG

View File

@@ -1,6 +1,6 @@
{
"name": "qmi-cloud-app",
"version": "1.1.2",
"version": "1.1.5",
"scripts": {
"start": "node -r esm server/server.js",
"start:dev": "nodemon -r esm server/server.js",
@@ -8,7 +8,6 @@
},
"private": true,
"dependencies": {
"qmi-cloud-common": "./qmi-cloud-common",
"@angular-devkit/build-angular": "^0.900.7",
"@angular/animations": "~9.0.7",
"@angular/common": "~9.0.7",
@@ -16,11 +15,13 @@
"@angular/core": "~9.0.7",
"@angular/forms": "~9.0.7",
"@angular/http": "~7.0.0",
"@angular/localize": "~9.0.7",
"@angular/platform-browser": "~9.0.7",
"@angular/platform-browser-dynamic": "~9.0.7",
"@angular/router": "~9.0.7",
"@fortawesome/fontawesome-free": "^5.12.1",
"@hapi/boom": "^9.1.0",
"@ng-bootstrap/ng-bootstrap": "6.2.0",
"@types/chart.js": "^2.9.16",
"adal-angular4": "^4.0.12",
"angular-bootstrap-md": "^9.0.0",
@@ -46,6 +47,7 @@
"nodemon": "^1.19.1",
"passport": "^0.4.0",
"passport-azure-ad": "^4.1.0",
"qmi-cloud-common": "./qmi-cloud-common",
"rxjs": "~6.5.4",
"swagger-jsdoc": "3.5.0",
"swagger-ui-express": "4.1.3",
@@ -71,4 +73,4 @@
"tslint": "~5.11.0",
"typescript": "~3.7.5"
}
}
}

View File

@@ -4,7 +4,7 @@
docker run --net=host \
-e MONGO_URI="mongodb://root:example@localhost:27017/qmicloud?authSource=admin" \
-e API_KEY="c229219ccdd72d11e8ea253fd3876d247e5f489c9c84922cabdfb0cc194d8ff398a8d8d6528d8241efc99add2207e0ec75122a1b2c5598cc340cbe6b7c3c0dbf" \
qlikgear/qmi-cloud-cli:latest -s destroy -t warning -p 4 -r test
qlikgear/qmi-cloud-cli:latest -s checkdestroy -t warning -p 4 -r test
```
```
@@ -12,3 +12,11 @@ docker run --net=host \
-e MONGO_URI="mongodb://root:example@localhost:27017/qmicloud?authSource=admin" \
qlikgear/qmi-cloud-cli:latest -s initdb
```
```
docker run --net=host -e MONGO_URI=$MONGO_URI -e API_KEY=$API_KEY qlikgear/qmi-cloud-cli:latest -s checkdestroy -t warning -p 20 -r test
```
```
docker run --net=host -e MONGO_URI=$MONGO_URI -e API_KEY=$API_KEY qlikgear/qmi-cloud-cli:latest -s checkstop -t warning -p 4 -r test
```

View File

@@ -1,6 +1,6 @@
{
"name": "qmi-cloud-cli",
"version": "1.1.2",
"version": "1.1.3",
"scripts": {
},
"private": true,

View File

@@ -0,0 +1,24 @@
# LOGIN
az login --identity
BASEDIR=$(dirname "$0")
SUBS="62ebff8f-c40b-41be-9239-252d6c0c8ad9"
CONTAINER="exports"
STORAGEACCOUNT="qmiexports"
STORAGEACCOUNTKEY="6PI/qNoJ7UnX83lVcffN7p7X1TwYXv+jHKLIEcMKZWpWA01Vj75AAyjq4dXJdmUgCeSEIRefHnJzQeuPZRHInQ=="
# GET FILES
az storage blob download-batch --destination . --source $CONTAINER --account-name $STORAGEACCOUNT --account-key $STORAGEACCOUNTKEY --pattern *.csv --subscription $SUBS
# MOVE LATEST FILE PER MONTH TO FOLDER latest
echo "BASEDIR=$BASEDIR"
for d in "$BASEDIR/qmicloud/qmicloud/"*
do
folderBase=$(basename "$d")
ymn=$(echo $folderBase | cut -c1-6)
lastFile=$(find $d -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" ")
echo $lastFile
cp $lastFile $BASEDIR/$ymn.csv
done

View File

@@ -69,7 +69,10 @@ const provisionSchema = new mongoose.Schema({
},
pendingNextAction: {
type: String
}
},
autoShutdown: {
type: mongoose.Types.ObjectId, ref: 'ProvisionAutoShutdown'
},
});

View File

@@ -0,0 +1,34 @@
const mongoose = require('mongoose');
mongoose.set('useFindAndModify', false);
//mongoose.set('debug', true)
const sc = new mongoose.Schema({
is24x7: {
type: Boolean,
required: true,
default: true
},
localeShutdownTime: {
type: String
},
localeStartupTime: {
type: String
},
utcTagShutdownTime: {
type: String
},
utcTagStartupTime: {
type: String
},
timezoneOffset: {
type: Number
},
weekStartDay: {
type: Number,
default: 1
}
});
module.exports = mongoose.model('ProvisionAutoShutdown', sc)

View File

@@ -35,6 +35,10 @@ const scenarioSchema = new mongoose.Schema({
type: Boolean,
default: false
},
isDivvyEnabled: {
type: Boolean,
default: false
},
isDisabled: {
type: Boolean,
default: false

View File

@@ -31,6 +31,7 @@ mongoose.connection.on('error', (err) => {
// Get Data Models
const ProvisionAutoShutdown = require('./models/ProvisionAutoShutdown');
const Provision = require('./models/Provision');
const Destroy = require('./models/Destroy');
const User = require('./models/User');
@@ -87,7 +88,7 @@ const get = async (model, filter, select, skip, limit, populates, reply) => {
});
} else {
if ( model === Provision ) {
exec = exec.populate({ path: 'user', select: 'displayName upn'}).populate({path:'destroy', select: "-user -jobId"});
exec = exec.populate({ path: 'user', select: 'displayName upn'}).populate({path:'destroy', select: "-user -jobId"}).populate({path: "autoShutdown"});
}
if ( model === ApiKey ) {
@@ -120,7 +121,7 @@ const getById = async (model, id, reply) => {
try {
var exec = model.findById(id);
if ( model === Provision ) {
exec = exec.populate('user').populate('destroy');
exec = exec.populate('user').populate('destroy').populate("autoShutdown");
}
if ( model === ApiKey ) {
exec = exec.populate('user');
@@ -139,7 +140,7 @@ const getOne = async (model, filter, reply) => {
try {
var exec = model.findOne(filter);
if ( model === Provision ) {
exec = exec.populate('user').populate('destroy');
exec = exec.populate('user').populate('destroy').populate("autoShutdown");
}
if ( model === ApiKey ) {
exec = exec.populate('user');
@@ -170,7 +171,7 @@ const update = async (model, id, body, reply) => {
console.log("UPDATE", id, updateData);
var exec = model.findByIdAndUpdate(id, updateData, { new: true });
if ( model === Provision ) {
exec = exec.populate('user').populate('destroy');
exec = exec.populate('user').populate('destroy').populate("autoShutdown");
}
if ( model === ApiKey ) {
exec = exec.populate('user');
@@ -219,6 +220,7 @@ function _m(model) {
module.exports = {
provisionAutoShutdown: _m(ProvisionAutoShutdown),
provision: _m(Provision),
destroy: _m(Destroy),
scenario: _m(Scenario),

View File

@@ -1,6 +1,6 @@
{
"name": "qmi-cloud-common",
"version": "1.1.2",
"version": "1.1.3",
"dependencies": {
"@hapi/boom": "^9.1.0",
"mongoose": "^5.7.4",

View File

@@ -4,7 +4,7 @@ const docker = new Docker({
//'socketPath': '/var/run/docker.sock'
});
const fs = require("fs");
const DOCKERIMAGE = "mcr.microsoft.com/azure-powershell";
const DOCKERIMAGE = process.env.DOCKERIMAGE_AZURE_POWERSHELL || "mcr.microsoft.com/azure-powershell";
//const cmd = `docker run --net=host -w /myapp -v ${FOLDER}:/myapp mcr.microsoft.com/azure-powershell pwsh appgw.ps1 -ApplicationGatewayName ${appGwName}`;
const appgateway = function( provision, scenario ) {

View File

@@ -5,7 +5,7 @@ const docker = new Docker({
const fs = require('fs');
const GIT_SCENARIOS = process.env.GIT_SCENARIOS;
const GIT_TAG = process.env.GIT_TAG || "master";
const DOCKERIMAGE = "qlikgear/terraform:1.0.1";
const DOCKERIMAGE = process.env.DOCKERIMAGE_TERRAFORM || "qlikgear/terraform:1.0.1";
const SSHPATH = process.env.SSHPATH;
function hook_stdout(callback) {
@@ -92,6 +92,24 @@ function _buildVarsExec( exec, provision, scenario ) {
exec.push(`is_external_access=${provision.isExternalAccess}`);
}
if ( provision.autoShutdown ) {
if ( provision.autoShutdown.is24x7 === true ) {
exec.push('-var');
exec.push(`is_24x7=true`);
} else if ( provision.autoShutdown.is24x7 === false ) {
exec.push('-var');
exec.push(`is_24x7=false`);
if ( provision.autoShutdown.utcTagStartupTime ) {
exec.push('-var');
exec.push(`startupTime=${provision.autoShutdown.utcTagStartupTime}`);
}
if ( provision.autoShutdown.utcTagShutdownTime ) {
exec.push('-var');
exec.push(`shutdownTime=${provision.autoShutdown.utcTagShutdownTime}`);
}
}
}
return exec;
}

View File

@@ -1,6 +1,6 @@
{
"name": "qmi-cloud-worker",
"version": "1.1.2",
"version": "1.1.3",
"scripts": {
"start": "node -r esm index.js",
"start:dev": "nodemon -r esm index.js",

View File

@@ -229,6 +229,39 @@ router.delete('/:id', passport.ensureAuthenticatedAndAdmin, async (req, res, nex
}
});
/**
* @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:

View File

@@ -172,6 +172,12 @@ router.post('/:userId/provisions', passport.ensureAuthenticatedAndIsMe, async (r
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 mongoJob = await db.provision.add(req.body);

View File

@@ -41,6 +41,8 @@ import { SubscriptionsService } from './services/deployopts.service';
import { TableApiKeysComponent } from './tables/table-apikeys.component';
import { ApikeyModalComponent } from './modals/edit-apikey.component';
import { VmTypeModalComponent } from './modals/edit-vmtype.component';
import { ProvisionModalComponent } from './modals/edit-provision.component';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
@@ -81,7 +83,8 @@ export function markedOptions(): MarkedOptions {
TableApiKeysComponent,
ApikeyModalComponent,
TableVmTypesComponent,
VmTypeModalComponent
VmTypeModalComponent,
ProvisionModalComponent
],
imports: [
BrowserModule,
@@ -93,6 +96,7 @@ export function markedOptions(): MarkedOptions {
MarkdownModule.forRoot({
loader: HttpClient
}),
NgbModule,
],
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: MyHttpInterceptor, multi: true },

View File

@@ -2,7 +2,7 @@
<div class="modal-content text-center">
<!--Header-->
<div class="modal-header d-flex justify-content-center">
<p class="heading">{{info.title}}</p>
<p class="heading" [innerHTML]="info.title"></p>
</div>
<!--Body-->

View File

@@ -24,13 +24,13 @@ export class ApikeyModalComponent implements OnInit, OnDestroy {
ngOnInit() {
this._usersService.getUsers().subscribe(res=> {
this.users = res.results;
console.log("apiKey",this.apiKey);
if (this.apiKey) {
this.sendData = JSON.parse(JSON.stringify(this.apiKey))
}
if (this.apiKey.user ) {
this.selectedUser = this.apiKey.user._id;
}
this.users = this.users.sort(function(a, b){return a.displayName.localeCompare(b.displayName);});
if (this.apiKey) {
this.sendData = JSON.parse(JSON.stringify(this.apiKey))
}
if (this.apiKey.user ) {
this.selectedUser = this.apiKey.user._id;
}
})
}

View File

@@ -0,0 +1,26 @@
<!--Content-->
<div class="modal-content">
<div class="modal-header text-center">
<button type="button" class="close pull-right" aria-label="Close" (click)="modalRef.hide()">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title w-100 font-weight-bold">Edit Provision</h4>
</div>
<div class="modal-body" style="max-height: 650px; overflow: auto;">
<div>
<section style="padding: 20px 0px;">
<label>Onwer (*):</label>
<select class="browser-default custom-select custom-select-sm" [(ngModel)]="selectedUser">
<option *ngFor="let item of users" [value]="item._id">{{item.displayName}}</option>
</select>
</section>
</div>
</div>
<div class="modal-footer d-flex justify-content-center">
<button style="margin-right: 100px;" *ngIf="sendData._id" mdbBtn color="danger" outline="true" class="waves-light" size="sm" mdbWavesEffect (click)="delete();">Delete</button>
<button mdbBtn color="dark-green" size="sm" outline="true" class="waves-effect" mdbWavesEffect (click)="modalRef.hide()">Cancel</button>
<button mdbBtn color="dark-green" class="waves-light" size="sm" mdbWavesEffect (click)="confirm();">Save</button>
</div>
</div>
<!--/.Content-->

View File

@@ -0,0 +1,45 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { MDBModalRef } from 'angular-bootstrap-md';
import { Subject } from 'rxjs';
import { UsersService } from '../services/users.service';
import { ProvisionsService } from '../services/provisions.service';
@Component({
selector: 'qmi-edit-provision',
templateUrl: './edit-provision.component.html',
styleUrls: ['./edit-provision.component.scss']
})
export class ProvisionModalComponent implements OnInit, OnDestroy {
provision;
action: Subject<any> = new Subject();
users;
selectedUser;
sendData : any = {};
constructor( public modalRef: MDBModalRef, private _usersService: UsersService, private _provisionsService: ProvisionsService ) {}
ngOnInit() {
var sub = this._usersService.getUsers().subscribe(res=> {
this.users = res.results;
this.users = this.users.sort(function(a, b){return a.displayName.localeCompare(b.displayName);});
sub.unsubscribe();
if (this.provision.user ) {
this.selectedUser = this.provision.user._id;
}
});
}
ngOnDestroy() {
}
confirm() : void {
this._provisionsService.updateProvisionAdmin(this.provision._id, { user: this.selectedUser } ).subscribe( res=>{
this.action.next(res);
this.modalRef.hide();
});
}
}

View File

@@ -40,6 +40,9 @@
<section style="padding: 20px 0px; margin: 0px 20px">
<mdb-checkbox (change)="checkOnchange($event, 'isExternal')" [checked]="sendData.isExternal" [default]="false"><mdb-icon fas icon="globe-americas" class="grey-text" aria-hidden="true"></mdb-icon> With External Access?</mdb-checkbox>
</section>
<section style="padding: 20px 0px; margin: 0px 20px">
<mdb-checkbox (change)="checkOnchange($event, 'isDivvyEnabled')" [checked]="sendData.isDivvyEnabled" [default]="false"><mdb-icon fas icon="clock" class="grey-text" aria-hidden="true"></mdb-icon> Enable DivvyCloud Tags?</mdb-checkbox>
</section>
<section style="padding: 20px 0px; margin: 0px 20px">
<mdb-checkbox (change)="checkOnchange($event, 'isWafPolicyAppGw')" [checked]="sendData.isWafPolicyAppGw" [default]="false"><mdb-icon fas icon="fire-extinguisher" class="grey-text" aria-hidden="true"></mdb-icon> Apply WAF policy after provision?</mdb-checkbox>
</section>

View File

@@ -16,11 +16,11 @@
</div>
<section *ngIf="scenario.isExternal" style="padding: 20px 0px; margin: 0px 20px">
<mdb-checkbox [default]="false" (change)="checkOnchange($event)">Enable External Access</mdb-checkbox>
<mdb-checkbox [default]="false" (change)="checkOnchange($event)">Enable External Access <i>(<mdb-icon fas icon="exclamation-triangle"></mdb-icon> only if it's strictly necessary)</i></mdb-checkbox>
</section>
<section *ngIf="!scenario.isExternal" style="padding: 20px 0px; margin: 0px 20px">
<mdb-checkbox [default]="false" (change)="checkOnchange($event)" [disabled]="true"><span style="color:#ccc">Enable External Access</span><br><i><mdb-icon fas icon="exclamation-triangle"></mdb-icon> This scenario only allows access from VPN</i></mdb-checkbox>
<mdb-checkbox [default]="false" (change)="checkOnchange($event)" [disabled]="true"><span style="color:#ccc">Enable External Access <i>(only if it's strictly necessary)</i></span><br><i><mdb-icon fas icon="exclamation-triangle"></mdb-icon> This scenario only allows access from VPN</i></mdb-checkbox>
</section>
<div style="padding-top: 10px" class="md-form" >
@@ -55,6 +55,30 @@
</select>
</div>
</div>
<div *ngIf="scenario.isDivvyEnabled">
<div>
<label>Running window</label>
</div>
<div class="md-form row" *ngIf="!autoShutdown.is24x7">
<div class="col-sm-6">
<div>Startup time:</div>
<ngb-timepicker style="font-size: 10px;" [(ngModel)]="autoShutdown.startupTime" [meridian]="true" [minuteStep]="15"></ngb-timepicker>
<div>
<i>UTC - {{getUTCTimes().startupTime}}</i>
</div>
</div>
<div class="col-sm-6">
<div>Shutdown time:</div>
<ngb-timepicker [(ngModel)]="autoShutdown.shutdownTime" [meridian]="true" [minuteStep]="15"></ngb-timepicker>
<div>
<i>UTC - {{getUTCTimes().shutdownTime}}</i>
</div>
</div>
</div>
<section style="padding: 20px 0px; margin: 0px 20px">
<mdb-checkbox [default]="false" [checked]="autoShutdown.is24x7" (change)="checkOnchangeAutoshutdown($event)">Enable 24x7 access <i>(Requires permission from regional manager)</i></mdb-checkbox>
</section>
</div>
</div>
<div class="modal-footer d-flex justify-content-center">

View File

@@ -1,5 +1,6 @@
label {
position: relative;
font-weight: bold;
}
.md-form {
@@ -9,4 +10,8 @@ label {
::placeholder {
color: #ccc;
}
}
.ngb-tp-meridian .btn {
padding: 5px 10px;
}

View File

@@ -1,8 +1,9 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Component, Injectable, OnInit, OnDestroy } from '@angular/core';
import { MDBModalRef } from 'angular-bootstrap-md';
import { Subject, Subscription } from 'rxjs';
import { ScenariosService } from '../services/scenarios.service';
@Component({
selector: 'qmi-new-provision',
templateUrl: './new-provision.component.html',
@@ -13,10 +14,10 @@ export class NewProvisionConfirmComponent implements OnInit, OnDestroy {
scenario;
action: Subject<any> = new Subject();
shortDesc: string;
sendData = {
sendData : any = {
description: "",
servers: null,
isExternalAccess: false,
isExternalAccess: false
};
selectedProductVersion: any = {};
selectedVmType: any = {};
@@ -25,6 +26,19 @@ export class NewProvisionConfirmComponent implements OnInit, OnDestroy {
vmTypesSub: Subscription;
vmTypes: any;
servers: any = {};
today = new Date();
autoShutdown: any = {
is24x7: false,
startupTime: {
"hour": this.today.getHours(),
"minute": 0
},
shutdownTime: {
"hour": this.today.getHours()+8,
"minute": 0
}
};
constructor( public modalRef: MDBModalRef, private _scenariosService: ScenariosService ) {}
ngOnInit() {
@@ -55,6 +69,35 @@ export class NewProvisionConfirmComponent implements OnInit, OnDestroy {
})
}
private _addZero(i) {
if (i < 10) {
i = "0" + i;
}
return i;
}
getUTCTimes() : any {
var dateStartup = new Date();
var dateShutdown = new Date();
dateStartup.setHours(this.autoShutdown.startupTime.hour);
dateStartup.setMinutes(this.autoShutdown.startupTime.minute);
dateStartup.setSeconds(0);
dateShutdown.setHours(this.autoShutdown.shutdownTime.hour);
dateShutdown.setMinutes(this.autoShutdown.shutdownTime.minute);
dateShutdown.setSeconds(0);
//var hourStart = this._addZero(dateStartup.getUTCHours());
//var hourShut = this._addZero(dateShutdown.getUTCHours());
var minShut = this._addZero(dateShutdown.getUTCMinutes());
var minStart = this._addZero(dateStartup.getUTCMinutes());
return {
startupTime: dateStartup.getUTCHours() +":"+minStart,
shutdownTime: dateShutdown.getUTCHours() +":"+minShut,
tagStartup: this._addZero(dateStartup.getUTCHours())+""+minStart,
tagShutdown: this._addZero(dateShutdown.getUTCHours())+""+minShut,
timezoneOffset: dateStartup.getTimezoneOffset()
}
}
ngOnDestroy() {
}
@@ -87,14 +130,34 @@ export class NewProvisionConfirmComponent implements OnInit, OnDestroy {
})
});
}
if ( this.scenario.isDivvyEnabled ) {
if ( !this.autoShutdown.is24x7 ) {
this.sendData.autoShutdownData = {
is24x7: false,
utcTagStartupTime: this.getUTCTimes().tagStartup,
utcTagShutdownTime: this.getUTCTimes().tagShutdown,
localeStartupTime: this.autoShutdown.startupTime.hour+":"+this._addZero(this.autoShutdown.startupTime.minute),
localeShutdownTime: this.autoShutdown.shutdownTime.hour+":"+this._addZero(this.autoShutdown.shutdownTime.minute),
timezoneOffset: this.getUTCTimes().timezoneOffset
}
} else {
this.sendData.autoShutdownData = {
is24x7: true
}
}
}
console.log("sendData", this.sendData);
this.action.next(this.sendData);
this.modalRef.hide();
}
checkOnchange($event) {
console.log("Checked?", $event.checked);
this.sendData.isExternalAccess = $event.checked;
}
checkOnchangeAutoshutdown($event) {
this.autoShutdown.is24x7 = $event.checked;
}
}

View File

@@ -41,7 +41,7 @@ export class ScenariosComponent implements OnInit, OnDestroy {
openNewProvisionConfirmModal(scenario) {
var modalRef = this.modalService.show(NewProvisionConfirmComponent, {
class: 'modal-md modal-notify',
class: 'modal-lg modal-notify',
containerClass: '',
data: {
scenario: scenario
@@ -60,6 +60,9 @@ export class ScenariosComponent implements OnInit, OnDestroy {
if ( data.servers ) {
postData["vmImage"] = data.servers;
}
if (data.autoShutdownData) {
postData["autoShutdownData"] = data.autoShutdownData;
}
this._provisionsService.newProvision(postData, this.user._id).subscribe( res => {
console.log("Done!", res);

View File

@@ -43,6 +43,10 @@ export class ProvisionsService {
return this.httpClient.delete(`${environment.apiVersionPath}/users/${userId}/provisions/${id}`);
}
updateProvisionAdmin(id, patch): Observable<any> {
return this.httpClient.put(`${environment.apiVersionPath}/provisions/${id}`, patch);
}
newDestroy(id, userId) : Observable<any> {
return this.httpClient.post(`${environment.apiVersionPath}/users/${userId}/provisions/${id}/destroy`, null);
}

View File

@@ -23,7 +23,7 @@
<tr>
<th>ProvisionID</th>
<th [mdbTableSort]="elements" sortBy="created" >Prov. Date <mdb-icon fas icon="sort"></mdb-icon></th>
<th [mdbTableSort]="elements" sortBy="user.displayName">User <mdb-icon fas icon="sort"></mdb-icon></th>
<th [mdbTableSort]="elements" sortBy="user.displayName">Owner <mdb-icon fas icon="sort"></mdb-icon></th>
<th [mdbTableSort]="elements" sortBy="scenario">Scenario (v)<mdb-icon fas icon="sort"></mdb-icon></th>
<th [mdbTableSort]="elements" sortBy="isExternalAccess">Ext. Access? <mdb-icon fas icon="sort"></mdb-icon></th>
<th [mdbTableSort]="elements" sortBy="statusVms">VMs (Running time)<mdb-icon fas icon="sort"></mdb-icon></th>
@@ -40,7 +40,9 @@
<a href (click)="showLogs($event, provision, 'provision')" class="lui-text-info">{{ provision._id }}</a>
</td>
<td (click)="openInfoModal(provision)" *ngIf="pagingIsDisabled || (i+1 >= mdbTablePagination.firstItemIndex && i < mdbTablePagination.lastItemIndex)">{{provision.created | date: 'MMM dd, yyyy - H:mm'}}</td>
<td (click)="openInfoModal(provision)" *ngIf="pagingIsDisabled || (i+1 >= mdbTablePagination.firstItemIndex && i < mdbTablePagination.lastItemIndex)" class="ell" title="{{provision.path}}" >{{provision.user.displayName}}</td>
<td *ngIf="pagingIsDisabled || (i+1 >= mdbTablePagination.firstItemIndex && i < mdbTablePagination.lastItemIndex)" class="ell" title="{{provision.path}}" >
<a href (click)="openOwnerChange($event, provision)" class="lui-text-info">{{provision.user.displayName}}</a>
</td>
<td (click)="openInfoModal(provision)"*ngIf="pagingIsDisabled || (i+1 >= mdbTablePagination.firstItemIndex && i < mdbTablePagination.lastItemIndex)">{{provision.scenario}} (v{{provision.scenarioVersion}})</td>
<td style="text-align: center;" (click)="openInfoModal(provision)"*ngIf="pagingIsDisabled || (i+1 >= mdbTablePagination.firstItemIndex && i < mdbTablePagination.lastItemIndex)"><mdb-icon *ngIf="provision.isExternalAccess" fas icon="check"></mdb-icon></td>
<td (click)="openInfoModal(provision)" *ngIf="pagingIsDisabled || (i+1 >= mdbTablePagination.firstItemIndex && i < mdbTablePagination.lastItemIndex)">

View File

@@ -1,12 +1,12 @@
import { Component, OnInit, ElementRef, HostListener, AfterViewInit, ViewChild, ChangeDetectorRef, Input, OnDestroy } from '@angular/core';
import { Component, OnInit, HostListener, AfterViewInit, ViewChild, ChangeDetectorRef, OnDestroy } from '@angular/core';
import { MdbTableDirective, MdbTablePaginationComponent, MDBModalService } from 'angular-bootstrap-md';
import { ProvisionsService } from '../services/provisions.service';
import { AlertService } from '../services/alert.service';
import { ModalInfoComponent } from '../modals/modalinfo.component';
import { ModalConfirmComponent } from '../modals/confirm.component';
import { Subscription, timer } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { ScenariosService } from '../services/scenarios.service';
import { ProvisionModalComponent } from '../modals/edit-provision.component';
@Component({
selector: 'table-provisions',
templateUrl: './table-provisions.component.html',
@@ -39,7 +39,6 @@ export class TableProvisionsAdminComponent implements OnInit, OnDestroy, AfterVi
this.mdbTablePagination.searchText = this.searchText;
}
selectedprov: any = null;
showInfo: boolean = false;
logShow: boolean = false;
@@ -59,10 +58,11 @@ export class TableProvisionsAdminComponent implements OnInit, OnDestroy, AfterVi
}
private _process(provisions) : void {
provisions.forEach(p=>{
provisions.forEach( p=> {
p.user.currentUserId = p.user._id;
p._scenario = this.scenarios.filter(s => s.name === p.scenario);
this._provisionsService.timeRunning(p);
});
} );
if ( this.elements.length === 0 ) {
this.elements = provisions;
} else {
@@ -93,7 +93,6 @@ export class TableProvisionsAdminComponent implements OnInit, OnDestroy, AfterVi
}
ngOnInit() {
var scenariosSub = this._scenariosService.getScenariosAll().subscribe( res => {
scenariosSub.unsubscribe();
this.scenarios = res.results;
@@ -126,6 +125,26 @@ export class TableProvisionsAdminComponent implements OnInit, OnDestroy, AfterVi
}
}
openOwnerChange($event, provision){
$event.preventDefault();
var modalRef = this.modalService.show(ProvisionModalComponent, {
class: 'modal-md modal-notify',
containerClass: '',
data: {
provision: provision
}
} );
var sub = modalRef.content.action.subscribe( (result: any) => {
sub.unsubscribe();
provision.user = result.user;
this._alertService.showAlert({
type: 'alert-primary',
text: `New owner ${provision.user.displayName} assigned to this provision`
});
});
}
searchItems() {
const prev = this.mdbTable.getDataSource();

View File

@@ -17,6 +17,7 @@
<th style="width: 400px;">AvailableProductVersions</th>
<th mdbTooltip="isAdminOnly?" style="width: 34px; text-align: center;"><mdb-icon fas icon="user-secret" class="grey-text" aria-hidden="true"></mdb-icon></th>
<th mdbTooltip="isExternal?" style="width: 34px; text-align: center;"><mdb-icon fas icon="globe-americas" class="grey-text" aria-hidden="true"></mdb-icon></th>
<th mdbTooltip="isDivvyEnabled?" style="width: 34px; text-align: center;"><mdb-icon fas icon="clock" class="grey-text" aria-hidden="true"></mdb-icon></th>
<th mdbTooltip="isWafPolicyAppGw?" style="width: 34px; text-align: center;"><mdb-icon fas icon="fire-extinguisher" class="grey-text" aria-hidden="true"></mdb-icon></th>
<!--<th mdbTooltip="isVnetIsolated?" style="width: 34px; text-align: center;"><mdb-icon fas icon="network-wired" class="grey-text" aria-hidden="true"></mdb-icon></th>-->
<th mdbTooltip="isDisabled?" style="width: 34px; text-align: center;"><mdb-icon fas icon="ban" class="grey-text" aria-hidden="true"></mdb-icon></th>
@@ -35,6 +36,7 @@
<td *ngIf="i+1 >= mdbTablePagination.firstItemIndex && i < mdbTablePagination.lastItemIndex"><pre>{{item.availableProductVersions | json}}</pre></td>
<td mdbTooltip="isAdminOnly?" style="width: 34px; text-align: center;" *ngIf="i+1 >= mdbTablePagination.firstItemIndex && i < mdbTablePagination.lastItemIndex"><mdb-icon *ngIf="item.isAdminOnly" fas icon="check"></mdb-icon></td>
<td mdbTooltip="isExternal?" style="width: 34px; text-align: center;" *ngIf="i+1 >= mdbTablePagination.firstItemIndex && i < mdbTablePagination.lastItemIndex"><mdb-icon *ngIf="item.isExternal" fas icon="check"></mdb-icon></td>
<td mdbTooltip="isDivvyEnabled?" style="width: 34px; text-align: center;" *ngIf="i+1 >= mdbTablePagination.firstItemIndex && i < mdbTablePagination.lastItemIndex"><mdb-icon *ngIf="item.isDivvyEnabled" fas icon="check"></mdb-icon></td>
<td mdbTooltip="isWafPolicyAppGw?" style="width: 34px; text-align: center;" *ngIf="i+1 >= mdbTablePagination.firstItemIndex && i < mdbTablePagination.lastItemIndex"><mdb-icon *ngIf="item.isWafPolicyAppGw" fas icon="check"></mdb-icon></td>
<!--<td mdbTooltip="isVnetIsolated?" style="width: 34px; text-align: center;" *ngIf="i+1 >= mdbTablePagination.firstItemIndex && i < mdbTablePagination.lastItemIndex"><mdb-icon *ngIf="item.isVnetIsolated" fas icon="check"></mdb-icon></td>-->
<td mdbTooltip="isDisabled?" style="width: 34px; text-align: center;" *ngIf="i+1 >= mdbTablePagination.firstItemIndex && i < mdbTablePagination.lastItemIndex"><mdb-icon *ngIf="item.isDisabled" fas icon="check"></mdb-icon></td>

View File

@@ -1,3 +1,7 @@
/***************************************************************************************************
* Load `$localize` onto the global scope - used if i18n tags appear in Angular templates.
*/
import '@angular/localize/init';
/**
* This file includes polyfills needed by Angular and is loaded before the app.
* You can add your own extra polyfills to this file.

View File

@@ -31,4 +31,6 @@ body {
color: #616161 !important;
}
}
//@import "assets/album.css";
//@import "assets/album.css";
/* Importing Bootstrap SCSS file. */
@import '~bootstrap/scss/bootstrap';

150
yarn.lock
View File

@@ -198,6 +198,15 @@
resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-9.0.7.tgz#c204467383ee5f194a73a365ea7c543c6900bb54"
integrity sha512-IZG1kvw48JyFRy7bfMHqBixWrEHZmXmkP5DWsi5Tw6KusaczkMghI20BevCkodPcajXWHAUHNKyp1tlE3OnH0w==
"@angular/localize@~9.0.7":
version "9.0.7"
resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-9.0.7.tgz#c40846e679917ee1575b009f78de822ac100add0"
integrity sha512-nlmcxEVZmz4ty1MXE1OFnHMYndedQUunZY4MB3lm7c8MJrRnI5x7zAOvkwI+sUF0Hy3rfjkO7ddOzGBfDtjPPA==
dependencies:
"@babel/core" "7.8.3"
glob "7.1.2"
yargs "13.1.0"
"@angular/platform-browser-dynamic@~9.0.7":
version "9.0.7"
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.0.7.tgz#7ca7e728fea0ba81b1009de1aa59a003b73c89af"
@@ -220,6 +229,13 @@
dependencies:
"@babel/highlight" "^7.10.1"
"@babel/code-frame@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a"
integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==
dependencies:
"@babel/highlight" "^7.10.4"
"@babel/code-frame@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e"
@@ -247,6 +263,27 @@
semver "^5.4.1"
source-map "^0.5.0"
"@babel/core@7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.3.tgz#30b0ebb4dd1585de6923a0b4d179e0b9f5d82941"
integrity sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA==
dependencies:
"@babel/code-frame" "^7.8.3"
"@babel/generator" "^7.8.3"
"@babel/helpers" "^7.8.3"
"@babel/parser" "^7.8.3"
"@babel/template" "^7.8.3"
"@babel/traverse" "^7.8.3"
"@babel/types" "^7.8.3"
convert-source-map "^1.7.0"
debug "^4.1.0"
gensync "^1.0.0-beta.1"
json5 "^2.1.0"
lodash "^4.17.13"
resolve "^1.3.2"
semver "^5.4.1"
source-map "^0.5.0"
"@babel/core@^7.7.5":
version "7.10.2"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.2.tgz#bd6786046668a925ac2bd2fd95b579b92a23b36a"
@@ -289,6 +326,16 @@
lodash "^4.17.13"
source-map "^0.5.0"
"@babel/generator@^7.10.4", "@babel/generator@^7.8.3":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.4.tgz#e49eeed9fe114b62fa5b181856a43a5e32f5f243"
integrity sha512-toLIHUIAgcQygFZRAQcsLQV3CBuX6yOIru1kJk/qqqvcRmZrYe6WavZTSG+bB8MxhnL9YPf+pKQfuiP161q7ng==
dependencies:
"@babel/types" "^7.10.4"
jsesc "^2.5.1"
lodash "^4.17.13"
source-map "^0.5.0"
"@babel/generator@^7.4.0", "@babel/generator@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.4.tgz#35bbc74486956fe4251829f9f6c48330e8d0985e"
@@ -349,6 +396,15 @@
"@babel/template" "^7.10.1"
"@babel/types" "^7.10.1"
"@babel/helper-function-name@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a"
integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==
dependencies:
"@babel/helper-get-function-arity" "^7.10.4"
"@babel/template" "^7.10.4"
"@babel/types" "^7.10.4"
"@babel/helper-function-name@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca"
@@ -365,6 +421,13 @@
dependencies:
"@babel/types" "^7.10.1"
"@babel/helper-get-function-arity@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2"
integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==
dependencies:
"@babel/types" "^7.10.4"
"@babel/helper-get-function-arity@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5"
@@ -461,6 +524,13 @@
dependencies:
"@babel/types" "^7.10.1"
"@babel/helper-split-export-declaration@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz#2c70576eaa3b5609b24cb99db2888cc3fc4251d1"
integrity sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg==
dependencies:
"@babel/types" "^7.10.4"
"@babel/helper-split-export-declaration@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9"
@@ -473,6 +543,11 @@
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz#5770b0c1a826c4f53f5ede5e153163e0318e94b5"
integrity sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==
"@babel/helper-validator-identifier@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2"
integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==
"@babel/helper-wrap-function@^7.10.1":
version "7.10.1"
resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.1.tgz#956d1310d6696257a7afd47e4c42dfda5dfcedc9"
@@ -492,6 +567,15 @@
"@babel/traverse" "^7.10.1"
"@babel/types" "^7.10.1"
"@babel/helpers@^7.8.3":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044"
integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==
dependencies:
"@babel/template" "^7.10.4"
"@babel/traverse" "^7.10.4"
"@babel/types" "^7.10.4"
"@babel/highlight@^7.10.1":
version "7.10.1"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.1.tgz#841d098ba613ba1a427a2b383d79e35552c38ae0"
@@ -501,6 +585,15 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
"@babel/highlight@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143"
integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==
dependencies:
"@babel/helper-validator-identifier" "^7.10.4"
chalk "^2.0.0"
js-tokens "^4.0.0"
"@babel/highlight@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797"
@@ -515,6 +608,11 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.2.tgz#871807f10442b92ff97e4783b9b54f6a0ca812d0"
integrity sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ==
"@babel/parser@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.4.tgz#9eedf27e1998d87739fb5028a5120557c06a1a64"
integrity sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA==
"@babel/parser@^7.4.3", "@babel/parser@^7.8.3", "@babel/parser@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8"
@@ -929,6 +1027,15 @@
"@babel/parser" "^7.10.1"
"@babel/types" "^7.10.1"
"@babel/template@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278"
integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==
dependencies:
"@babel/code-frame" "^7.10.4"
"@babel/parser" "^7.10.4"
"@babel/types" "^7.10.4"
"@babel/template@^7.4.0", "@babel/template@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.3.tgz#e02ad04fe262a657809327f578056ca15fd4d1b8"
@@ -953,6 +1060,21 @@
globals "^11.1.0"
lodash "^4.17.13"
"@babel/traverse@^7.10.4", "@babel/traverse@^7.8.3":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.4.tgz#e642e5395a3b09cc95c8e74a27432b484b697818"
integrity sha512-aSy7p5THgSYm4YyxNGz6jZpXf+Ok40QF3aA2LyIONkDHpAcJzDUqlCKXv6peqYUs2gmic849C/t2HKw2a2K20Q==
dependencies:
"@babel/code-frame" "^7.10.4"
"@babel/generator" "^7.10.4"
"@babel/helper-function-name" "^7.10.4"
"@babel/helper-split-export-declaration" "^7.10.4"
"@babel/parser" "^7.10.4"
"@babel/types" "^7.10.4"
debug "^4.1.0"
globals "^11.1.0"
lodash "^4.17.13"
"@babel/traverse@^7.4.3":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.4.tgz#f0845822365f9d5b0e312ed3959d3f827f869e3c"
@@ -977,6 +1099,15 @@
lodash "^4.17.13"
to-fast-properties "^2.0.0"
"@babel/types@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.4.tgz#369517188352e18219981efd156bfdb199fff1ee"
integrity sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==
dependencies:
"@babel/helper-validator-identifier" "^7.10.4"
lodash "^4.17.13"
to-fast-properties "^2.0.0"
"@babel/types@^7.4.0", "@babel/types@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c"
@@ -1008,6 +1139,11 @@
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd"
integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==
"@ng-bootstrap/ng-bootstrap@6.2.0":
version "6.2.0"
resolved "https://registry.yarnpkg.com/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-6.2.0.tgz#0506d612ca6002bd8fa398d006fa2641013e11d4"
integrity sha512-wqwhnJFyEwvzWQJjXrEt+7oBTSvu2qPbdYvUFYhDVzOJLWB5M7YEhDAkMrfHQJ0pZNBMGr580FqYue+XiURY0Q==
"@ngtools/webpack@9.0.7":
version "9.0.7"
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-9.0.7.tgz#2d9397544afcf503530eafc764c64d40a99fa070"
@@ -4593,6 +4729,18 @@ glob-parent@~5.1.0:
dependencies:
is-glob "^4.0.1"
glob@7.1.2:
version "7.1.2"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.0.4"
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@7.1.5:
version "7.1.5"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.5.tgz#6714c69bee20f3c3e64c4dd905553e532b40cdc0"
@@ -8390,7 +8538,7 @@ qjobs@^1.1.4:
integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==
qmi-cloud-common@./qmi-cloud-common:
version "1.1.2"
version "1.1.3"
dependencies:
"@hapi/boom" "^9.1.0"
azure-arm-compute "^10.0.0"