diff options
Diffstat (limited to 'ui/imports/api/environments/environments.js')
-rw-r--r-- | ui/imports/api/environments/environments.js | 457 |
1 files changed, 457 insertions, 0 deletions
diff --git a/ui/imports/api/environments/environments.js b/ui/imports/api/environments/environments.js new file mode 100644 index 0000000..d616960 --- /dev/null +++ b/ui/imports/api/environments/environments.js @@ -0,0 +1,457 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Mongo } from 'meteor/mongo'; +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import * as R from 'ramda'; +import { Constants } from '/imports/api/constants/constants'; +import { MysqlSchema } from './configuration-groups/mysql-configuration'; +import { OpenStackSchema } from './configuration-groups/open-stack-configuration'; +import { MonitoringSchema } from './configuration-groups/monitoring-configuration'; +import { CLISchema } from './configuration-groups/cli-configuration'; +import { AMQPSchema } from './configuration-groups/amqp-configuration'; +//import { NfvProviderSchema } from './configuration-groups/nfv-provider-configuration'; +import { AciSchema } from './configuration-groups/aci-configuration'; +import { + isMonitoringSupported, + isListeningSupported, +} from '/imports/api/supported_environments/supported_environments'; + +export const Environments = new Mongo.Collection( + 'environments_config', { idGeneration: 'MONGO' }); + +export const requiredConfGroups = [ + 'mysql', + 'OpenStack', + 'CLI', +]; + +export const optionalConfGroups = [ + // 'NFV_provider', + 'AMQP', + 'Monitoring', + 'ACI', +]; + +let simpleSchema = new SimpleSchema({ + _id: { type: { _str: { type: String, regEx: SimpleSchema.RegEx.Id } } }, + auth: { + type: Object, + blackbox: true, + defaultValue: { + 'view-env': [ + ], + 'edit-env': [ + ] + } + }, + configuration: { + type: [Object], + blackbox: true, + autoValue: function () { + console.log('start - autovalue - environment - configuration'); + //console.log(this); + let that = this; + + if (that.isSet) { + let confGroups = that.value; + + let { + isMonitoringSupportedRes, + isListeningSupportedRes, + enable_monitoring, + listen + } = extractCalcEnvSupportedRelatedValues(that); + let dbNode = getDbNode(that); + let aci = extractValue('aci', that, dbNode); + + if (enable_monitoring && isMonitoringSupportedRes) { + if (! R.find(R.propEq('name', 'Monitoring'), confGroups)) { + confGroups = R.append(createNewConfGroup('Monitoring'), confGroups); + } + } else { + console.log('env - configurations - autovalue - monitoring not supported'); + confGroups = R.reject(R.propEq('name', 'Monitoring'), confGroups); + } + + if (listen && isListeningSupportedRes) { + if (! R.find(R.propEq('name', 'AMQP'), confGroups)) { + confGroups = R.append(createNewConfGroup('AMQP'), confGroups); + } + } else { + console.log('env - configurations - autovalue - listening not supported'); + confGroups = R.reject(R.propEq('name', 'AMQP'), confGroups); + } + + if (aci) { + if (! R.find(R.propEq('name', 'ACI'), confGroups)) { + confGroups = R.append(createNewConfGroup('ACI'), confGroups); + } + } else { + console.log('env - configurations - autovalue - aci not requested'); + confGroups = R.reject(R.propEq('name', 'ACI'), confGroups); + } + + confGroups = cleanOptionalGroups(confGroups, optionalConfGroups); + console.log('env - configurations - autovalue - after clean optional groups'); + + let newValue = R.map(function(confGroup) { + let schema = getSchemaForGroupName(confGroup.name); + return schema.clean(confGroup); + }, confGroups); + + console.log('end - autovalue - environment - configurations'); + console.log(newValue); + return newValue; + + } else { + console.log('env - configurations - autovalue - is not set'); + let newValue = R.map((confName) => { + let schema = getSchemaForGroupName(confName); + return schema.clean({}); + }, requiredConfGroups); + console.log('end - autovalue - environment - configurations'); + console.log(newValue); + return newValue; + } + }, + custom: function () { + console.log('start - custom - environment - configurations'); + //console.log(this); + let that = this; + let configurationGroups = that.value; + + let subErrors = []; + + let { + isMonitoringSupportedRes, + isListeningSupportedRes, + enable_monitoring, + listen + } = extractCalcEnvSupportedRelatedValues(that); + + let requiredConfGroupsTemp = R.clone(requiredConfGroups); + if (enable_monitoring && isMonitoringSupportedRes) { + requiredConfGroupsTemp = R.append('Monitoring', requiredConfGroupsTemp); + } + if (listen && isListeningSupportedRes) { + requiredConfGroupsTemp = R.append('AMQP', requiredConfGroupsTemp); + } + + console.log('env - configurations - custom - after mon & listen check'); + + let invalidResult = R.find(function(groupName) { + subErrors = checkGroup(groupName, configurationGroups, true); + if (subErrors.length > 0) { return true; } + return false; + }, requiredConfGroupsTemp); + + console.log(`env - configurations - custom - after require groups check`); + + if (R.isNil(invalidResult)) { + invalidResult = R.find(function(groupName) { + subErrors = checkGroup(groupName, configurationGroups, false); + if (subErrors.length > 0) { return true; } + return false; + }, optionalConfGroups); + } + + console.log(`env - configurations - custom - after optional groups check`); + + if (! R.isNil(invalidResult)) { + console.log(`env - configrations - custom - invalid result end: ${R.toString(subErrors)}`); + throw { + isError: true, + type: 'subGroupError', + data: subErrors, + message: constructSubGroupErrorMessage(subErrors) + }; + } + }, + + }, + user: { + type: String, + }, + distribution: { + type: String, + defaultValue: 'Mirantis-8.0', + custom: function () { + let that = this; + let constsDist = Constants.findOne({ name: 'distributions' }); + + if (R.isNil(constsDist.data)) { return 'notAllowed'; } + let distributions = constsDist.data; + + if (R.isNil(R.find(R.propEq('value', that.value), distributions))) { + return 'notAllowed'; + } + }, + }, + last_scanned: { + type: String, defaultValue: '' + }, + name: { + type: String, + defaultValue: 'MyEnvironmentName', + min: 6, + }, + type_drivers: { + type: String, + defaultValue: 'gre', + custom: function () { + let that = this; + let TypeDriversRec = Constants.findOne({ name: 'type_drivers' }); + + if (R.isNil(TypeDriversRec.data)) { return 'notAllowed'; } + let TypeDrivers = TypeDriversRec.data; + + if (R.isNil(R.find(R.propEq('value', that.value), TypeDrivers))) { + return 'notAllowed'; + } + }, + }, + + mechanism_drivers: { + type: [String], + defaultValue: ['ovs'], + minCount: 1, + custom: function () { + let that = this; + let consts = Constants.findOne({ name: 'mechanism_drivers' }); + + if (R.isNil(consts.data)) { return 'notAllowed'; } + let mechanismDrivers = consts.data; + + let result = R.find((driver) => { + if (R.find(R.propEq('value', driver), mechanismDrivers)) { + return false; + } + return true; + }, that.value); + + if (result) { return 'notAllowed'; } + + }, + }, + + operational: { + type: String, + allowedValues: ['stopped', 'running', 'error'], + defaultValue: 'stopped' + }, + + scanned: { type: Boolean, defaultValue: false }, + + type: { + type: String, + autoValue: function () { + return 'environment'; + }, + }, + + app_path: { + type: String, + autoValue: function () { + return '/home/scan/calipso_prod/app'; + } + }, + + listen: { + type: Boolean, + autoValue: function () { + console.log('env - listen - autoValue - start'); + let that = this; + let newValue = that.value; + console.log(`- current value: ${R.toString(newValue)}`); + + let { isListeningSupportedRes } = extractCalcEnvSupportedRelatedValues(that); + + if (!isListeningSupportedRes) { + console.log('* listening not supported'); + console.log(`* ${R.toString(isListeningSupportedRes)}`); + newValue = false; + } + + return newValue; + }, + }, + + enable_monitoring: { + type: Boolean, + autoValue: function () { + console.log('env - enable_monitoring - autoValue - start'); + let that = this; + let newValue = that.value; + console.log(`- current value: ${R.toString(newValue)}`); + + let { isMonitoringSupportedRes } = extractCalcEnvSupportedRelatedValues(that); + + if (!isMonitoringSupportedRes) { + console.log('* monitoring not supported'); + console.log(`* ${R.toString(isMonitoringSupportedRes)}`); + newValue = false; + } + + return newValue; + }, + }, + aci: { + type: Boolean, + defaultValue: false, + }, +}); + +/* +simpleSchema.addValidator(function () { + //let that = this; +}); +*/ + +// Bug in simple schema. cant add custom message to instance specific +// schema. +// https://github.com/aldeed/meteor-simple-schema/issues/559 +// Version 2 fixes it but it is rc. +//Environments.schema.messages({ +SimpleSchema.messages({ + confGroupInvalid: 'Configuration group is invalid.' +}); + +Environments.schema = simpleSchema; +Environments.attachSchema(Environments.schema); + +function getSchemaForGroupName(groupName) { + switch (groupName) { + case 'mysql': + return MysqlSchema; + case 'OpenStack': + return OpenStackSchema; + case 'CLI': + return CLISchema; + case 'AMQP': + return AMQPSchema; +// case 'NFV_provider': +// return NfvProviderSchema; + case 'ACI': + return AciSchema; + case 'Monitoring': + return MonitoringSchema; + default: + throw 'group name is not recognized. group: ' + groupName; + } +} + +function constructSubGroupErrorMessage(errors) { + let message = 'Validation errors on sub groups:'; + message = message + R.reduce((acc, item) => { + return acc + '\n- ' + item.group + ': ' + item.message; + }, '', errors); + + return message; +} + +function checkGroup(groupName, configurationGroups, groupRequired) { + let subErrors = []; + let confGroup = R.find(R.propEq('name', groupName), configurationGroups); + + if (R.isNil(confGroup)) { + if (groupRequired) { + subErrors = R.append({ + field: 'configuration', + group: groupName, + message: 'group ' + groupName + ' is required' + }, subErrors); + } + return subErrors; + } + + let validationContext = getSchemaForGroupName(groupName).newContext(); + + if (! validationContext.validate(confGroup)) { + subErrors = R.reduce(function (acc, invalidField) { + return R.append({ + field: invalidField, + group: groupName, + message: validationContext.keyErrorMessage(invalidField.name), + }, acc); + }, [], validationContext.invalidKeys()); + + return subErrors; + } + + return subErrors; +} + +export function createNewConfGroup(groupName) { + let schema = getSchemaForGroupName(groupName); + return schema.clean({}); +} + +function cleanOptionalGroups(confGroups, optionalConfGroups) { + return R.filter((conf) => { + if (R.contains(conf.name, optionalConfGroups)) { + return !isConfEmpty(conf); + } + + return true; + }, confGroups); +} + +function isConfEmpty(conf) { + return ! R.any((key) => { + if (key === 'name') { return false; } // We ignore the key 'name'. It is a 'type' key. + let val = conf[key]; + return ! ( R.isNil(val) || R.isEmpty(val)); + })(R.keys(conf)); +} + +function extractValue(name, schemaValidator, dbNode) { + console.log('env - extract value'); + console.log(`-name: ${R.toString(name)}`); + //console.log(`-schemaValidator: ${R.toString(schemaValidator)}`); + console.log(`-dbNode: ${R.toString(dbNode)}`); + + let field = schemaValidator.field(name); + let value = field.value; + + console.log(`extract value - schema value: ${R.toString(value)}`); + + if (R.isNil(field.value) && !field.isSet && dbNode) { + console.log(`extract value - db value: ${R.toString(dbNode[name])}`); + value = dbNode[name]; + } + + console.log(`extract value - result: ${R.toString(value)}`); + return value; +} + +function getDbNode(schemaHelper) { + let _id = R.defaultTo(schemaHelper.docId, R.path(['value'], schemaHelper.field('_id'))); + let dbNode = R.defaultTo(null, Environments.findOne({ _id: _id })); + return dbNode; +} + +function extractCalcEnvSupportedRelatedValues(schemaHelper) { + let dbNode = getDbNode(schemaHelper); + + let dist = extractValue('distribution', schemaHelper, dbNode); + let typeDrivers = extractValue('type_drivers', schemaHelper, dbNode); + let mechDrivers = extractValue('mechanism_drivers', schemaHelper, dbNode); + let enable_monitoring = extractValue('enable_monitoring', schemaHelper, dbNode); + let listen = extractValue('listen', schemaHelper, dbNode); + + let isMonitoringSupportedRes = isMonitoringSupported(dist, typeDrivers, mechDrivers); + let isListeningSupportedRes = isListeningSupported(dist, typeDrivers, mechDrivers); + + return { + enable_monitoring, + listen, + isMonitoringSupportedRes, + isListeningSupportedRes, + }; +} |