Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/kubevela.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
const slugify = require("slugify");
const mathutils = require("./math");
const _ = require("lodash");
const transliterate = require('transliteration').transliterate;

module.exports = {
json: (doc) =>{
let object = _.clone(doc)
object['title'] = transliterate(object['title'])
object['variables'] = _.map(doc['variables'], (v)=>{

return {
'key': slugify(v['name'].replaceAll('/','_'),'_'),
'key': slugify(transliterate(v['name']).replaceAll("\s+"," ").replaceAll('/','_'),'_'),
'path': '/'+v['name'],
'type': 'float',
'meaning': v['name'].split('/').pop(),
Expand Down
2 changes: 2 additions & 0 deletions lib/metric_model.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
const slugify = require("slugify");
const _ = require("lodash");
const yaml = require('yaml');
const {transliterate} = require("transliteration");

module.exports = {
yaml: (doc) => {
let object = _.cloneDeep(doc);
object['title'] = transliterate(object['title'])
let componentsForAppSpecComp = [];
let componentsForAppWideScope = [];

Expand Down
134 changes: 119 additions & 15 deletions modules/application/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const OpenAI = require("openai");
const projection = {
title: 1,
uuid: 1,
token: 1,
status: 1,
organization: 1,
content: 1,
Expand Down Expand Up @@ -40,6 +41,10 @@ module.exports = {
type: 'string',
label: 'UUID'
},
token:{
type: 'string',
label: 'Token'
},
status: {
type: 'string',
label: 'Status',
Expand Down Expand Up @@ -516,6 +521,9 @@ module.exports = {
};
},
methods(self) {
validateMetaConstraints = (uuid,doc) => {
return self.apos.modules.exn.bqa_application_validate(uuid,doc)
};
const contentSchema = Joi.string().custom((value, helpers) => {
try {
yaml.parse(value);
Expand Down Expand Up @@ -850,7 +858,9 @@ module.exports = {
async updateWithRegions(req, doc) {

return new Promise(async (resolve) => {

if(!doc.resources){
doc.resources = []
}
const resource_uuids = doc.resources.map(r => {
return r.uuid
})
Expand Down Expand Up @@ -945,24 +955,22 @@ module.exports = {

const doc = req.body;
let errorResponses = self.validateDocument(doc) || [];

if(doc.uuid){
const metaConstraintValidation = await validateMetaConstraints(doc.uuid, doc)
if(!metaConstraintValidation.valid){
errorResponses.push({
path: `slMetaConstraint`,
index: 90,
key: `slMetaConstraint`,
message: metaConstraintValidation.message || 'Please check the SL Meta Constraints'
})
}
}
if (errorResponses.length > 0) {
throw self.apos.error('required', 'Validation failed', {error: errorResponses});
}
},
async validateConstraints(req) {
if (!self.apos.permission.can(req, 'edit')) {
throw self.apos.error('forbidden', 'Insufficient permissions');
}
const slMetaContraints = req.body;
const valid = await new Promise((resolve) => {
setTimeout(() => {
const randomBoolean = Math.random() < 0.5;
resolve(randomBoolean);
}, 5000);
});
console.log("Returning valid for ", slMetaContraints, valid);
return valid;
},
async 'generate'(req) {
if (!self.apos.permission.can(req, 'edit')) {
throw self.apos.error('forbidden', 'Insufficient permissions');
Expand Down Expand Up @@ -1041,6 +1049,28 @@ module.exports = {
throw self.apos.error(error.name, error.message);
}
},
async ':uuid/uuid/debug'(req) {

const uuid = req.params.uuid;

// let errorResponses = self.validateDocument(updateData, true) || [];
// if (errorResponses.length > 0) {
// throw self.apos.error('required', 'Validation failed', { error: errorResponses });
// }
const currentUser = req.user;
const adminOrganization = currentUser.organization;

const existingApp = await self.apos.doc.db.findOne({uuid: uuid, organization: adminOrganization});
if (!existingApp) {
throw self.apos.error('notfound', 'Application not found');
}

try {
await self.apos.modules.exn.send_application_dsl(uuid)
} catch (error) {
throw self.apos.error(error.name, error.message);
}
},
async ':uuid/uuid/undeploy'(req) {
const uuid = req.params.uuid;
const currentUser = req.user;
Expand Down Expand Up @@ -1128,6 +1158,38 @@ module.exports = {
} catch (error) {
throw self.apos.error('error', error.message);
}
},
async ':uuid/vr/token'(req) {

const uuid = req.params.uuid;

if (!self.apos.permission.can(req, 'view')) {
throw self.apos.error('forbidden', 'Insufficient permissions');
}

try {
const currentUser = req.user;
const adminOrganization = currentUser.organization;

const doc = await self.find(req, {
uuid: uuid,
organization: adminOrganization
}).toObject();
if (!doc) {
throw self.apos.error('notfound', 'Application not found');
}

if (doc.organization !== adminOrganization) {
throw self.apos.error('forbidden', 'Access denied');
}

const token = uuidv4();
doc.token = token;
await self.update(req,doc)
return token;
} catch (error) {
throw self.apos.error(error.name, error.message);
}
}

},
Expand Down Expand Up @@ -1303,8 +1365,50 @@ module.exports = {
} catch (error) {
throw self.apos.error('error', error.message);
}
},
async 'vr/data/:token'(req) {

const token = req.params.token;

const doc = await self.find(req, {
token: token,
}).project(projection).toObject();

if (!doc) {
throw self.apos.error('notfound', 'Application not found');
}

try {
const measurements = req.query.measurement || []
const interval = req.query.interval || '-30d'
const range = req.query.range || 10
const slice = req.query.slice || 5

const res = await self.apos.modules.influxdb.getTimeSeriesForMeasurements(doc.uuid, measurements, interval)
return {
application: doc.title,
uuid: doc.uuid,
charts: res.map(chart => {
const slicedValues = chart.config.datasets[0].data.slice(0, slice);
const maxValue = Math.max(...slicedValues);

return {
title: chart.title,
points: chart.config.labels.slice(0, slice).map((label, index) => ({
title: label,
value: maxValue > 0 ? (chart.config.datasets[0].data[index] / maxValue) * range : 0,
raw: chart.config.datasets[0].data[index]
}))

}
})
};
} catch (error) {
throw self.apos.error('error', error.message);
}
}


},
delete: {
async ':uuid/uuid'(req) {
Expand Down
37 changes: 37 additions & 0 deletions modules/exn/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ let sender_ui_application_dsl_metric;
let sender_ui_policies_rule_upsert;
let sender_ui_policies_model_upsert;

let sender_bqa_validate_slos;


let sender_ui_application_user_info;
let sender_ui_application_info;
Expand Down Expand Up @@ -108,6 +110,11 @@ module.exports = {
await aposSelf.update_application_state(context.message.application_properties.application, context.message.body);
}

if (context.message.to === "topic://eu.nebulouscloud.ontology.bqa.reply") {
correlations[context.message.correlation_id]['resolve'](context.message.body)
return
}

if (context.message.correlation_id in correlations) {
if (context.message.body.metaData['status'] >= 400) {
correlations[context.message.correlation_id]['reject'](context.message.body['message'])
Expand All @@ -127,6 +134,7 @@ module.exports = {
context.connection.open_receiver('topic://eu.nebulouscloud.optimiser.controller.app_state')
context.connection.open_receiver('topic://eu.nebulouscloud.ui.user.get')
context.connection.open_receiver('topic://eu.nebulouscloud.ui.app.get')
context.connection.open_receiver('topic://eu.nebulouscloud.ontology.bqa.reply')

sender_sal_nodecandidate_get = context.connection.open_sender('topic://eu.nebulouscloud.exn.sal.nodecandidate.get');
sender_sal_cloud_get = context.connection.open_sender('topic://eu.nebulouscloud.exn.sal.cloud.get');
Expand All @@ -147,6 +155,8 @@ module.exports = {
sender_ui_application_user_info = context.connection.open_sender('topic://eu.nebulouscloud.ui.user.get.reply');
sender_ui_application_info = context.connection.open_sender('topic://eu.nebulouscloud.ui.app.get.reply');

sender_bqa_validate_slos = context.connection.open_sender('topic://eu.nebulouscloud.ontology.bqa');

});

if (process.env.EXN_DISABLE == "True") {
Expand Down Expand Up @@ -350,6 +360,33 @@ module.exports = {
})
}
,
async bqa_application_validate(uuid) {
return new Promise(async (resolve, reject) => {

const correlation_id = uuidv4()
correlations[correlation_id] = {
'resolve': resolve, 'reject': reject,
};
const req = aposSelf.apos.task.getReq()
const dsl = await aposSelf.apos.modules.application.getDSL(req, uuid)
const message = {
to: sender_bqa_validate_slos.options.target.address,
correlation_id: correlation_id,
message_annotations: {application: uuid},
application_properties: {application: uuid},
body: dsl.json
}
const timer = setTimeout(() => {
console.warn("SLO Validator timeout")
resolve({
'valid':true
})
}, 7000);

console.log("[bqa_application_validate] Send ", JSON.stringify( message))
sender_bqa_validate_slos.send(message)
})
},
get_cloud_candidates() {
return new Promise((resolve, reject) => {

Expand Down
Loading