This closes #112
diff --git a/ui-modules/blueprint-composer/app/components/dsl-editor/dsl-editor.js b/ui-modules/blueprint-composer/app/components/dsl-editor/dsl-editor.js
index 6fb1d26..cf1e695 100644
--- a/ui-modules/blueprint-composer/app/components/dsl-editor/dsl-editor.js
+++ b/ui-modules/blueprint-composer/app/components/dsl-editor/dsl-editor.js
@@ -291,6 +291,18 @@
};
});
+ let params = entity.miscData.get('parameters').filter(param => param !== definition).map(param => {
+ return {
+ id: param.name,
+ type: DSL_KINDS.CONFIG,
+ entity: entity,
+ name: param.name,
+ description: param.description
+ };
+ });
+
+ config = config.concat(params);
+
config = Object.values(entity.getClusterMemberspecEntities()).reduce((acc, spec) => {
return acc.concat(getConfigItems(spec, definition));
}, config);
diff --git a/ui-modules/blueprint-composer/app/components/providers/blueprint-service.provider.js b/ui-modules/blueprint-composer/app/components/providers/blueprint-service.provider.js
index a896aac..7cc63b0 100644
--- a/ui-modules/blueprint-composer/app/components/providers/blueprint-service.provider.js
+++ b/ui-modules/blueprint-composer/app/components/providers/blueprint-service.provider.js
@@ -253,11 +253,13 @@
entity.miscData.set('traits', []);
deferred.resolve(entity);
addUnlistedConfigKeysDefinitions(entity);
+ addUnlistedParameterDefinitions(entity);
} else {
entity.miscData.set('sensors', []);
entity.miscData.set('traits', []);
deferred.resolve(entity);
addUnlistedConfigKeysDefinitions(entity);
+ addUnlistedParameterDefinitions(entity);
}
return deferred.promise;
@@ -534,6 +536,16 @@
entity.miscData.set('config', allConfig);
}
+ function addUnlistedParameterDefinitions(entity) {
+ let allParams = entity.miscData.get('parameters') || [];
+ entity.parameters.forEach((param) => {
+ if (!allParams.some((e) => e.name === param.name)) {
+ allParams.push(param);
+ }
+ });
+ entity.miscData.set('parameters', allParams);
+ }
+
function populateEntityFromApiSuccess(entity, data) {
entity.clearIssues({group: 'type'});
entity.type = data.symbolicName;
@@ -545,6 +557,7 @@
});
entity.miscData.set('typeName', data.displayName || data.symbolicName);
entity.miscData.set('config', data.config || []);
+ entity.miscData.set('parameters', data.parameters || []);
entity.miscData.set('sensors', data.sensors || []);
entity.miscData.set('traits', data.supertypes || []);
entity.miscData.set('tags', data.tags || []);
@@ -555,6 +568,7 @@
entity.miscData.set('ui-composer-hints', uiHints);
entity.miscData.set('virtual', data.virtual || null);
addUnlistedConfigKeysDefinitions(entity);
+ addUnlistedParameterDefinitions(entity);
return entity;
}
function mergeAppendingLists(dst, src) {
@@ -574,11 +588,13 @@
entity.addIssue(Issue.builder().group('type').message($sce.trustAsHtml(`Type <samp>${entity.type + (entity.hasVersion ? ':' + entity.version : '')}</samp> does not exist`)).build());
entity.miscData.set('typeName', entity.type || '');
entity.miscData.set('config', []);
+ entity.miscData.set('parameters', []);
entity.miscData.set('sensors', []);
entity.miscData.set('traits', []);
entity.miscData.set('virtual', null);
entity.icon = typeNotFoundIcon;
addUnlistedConfigKeysDefinitions(entity);
+ addUnlistedParameterDefinitions(entity);
return entity;
}
diff --git a/ui-modules/blueprint-composer/app/components/util/model/entity.model.js b/ui-modules/blueprint-composer/app/components/util/model/entity.model.js
index 9643c66..7d04410 100644
--- a/ui-modules/blueprint-composer/app/components/util/model/entity.model.js
+++ b/ui-modules/blueprint-composer/app/components/util/model/entity.model.js
@@ -23,9 +23,9 @@
const FIRST_MEMBERSPEC_REGEX = /^(\w+\.)*first[mM]ember[sS]pec$/;
// TODO ideally we'd just look at type EntitySpec, not key name, but for now look at keyname, anything ending memberSpec
const ANY_MEMBERSPEC_REGEX = /^(\w+\.)*(\w*)[mM]ember[sS]pec$/;
-const RESERVED_KEY_REGEX = /(^children$|^services$|^locations?$|^brooklyn\.config$|^brooklyn\.enrichers$|^brooklyn\.policies$)/;
+const RESERVED_KEY_REGEX = /(^children$|^services$|^locations?$|^brooklyn\.config$|^brooklyn\.parameters$|^brooklyn\.enrichers$|^brooklyn\.policies$)/;
const FIELD = {
- SERVICES: 'services', CHILDREN: 'brooklyn.children', CONFIG: 'brooklyn.config', LOCATION: 'location',
+ SERVICES: 'services', CHILDREN: 'brooklyn.children', CONFIG: 'brooklyn.config', PARAMETERS: 'brooklyn.parameters', LOCATION: 'location',
POLICIES: 'brooklyn.policies', ENRICHERS: 'brooklyn.enrichers', TYPE: 'type', NAME: 'name', ID: 'id',
// This field is not part of the Brooklyn blueprint spec but used to store information about the composer, e.g. X,Y coordinates, virtual items, etc
COMPOSER_META: 'brooklyn.composer.metadata'
@@ -50,6 +50,7 @@
const PARENT = new WeakMap();
const METADATA = new WeakMap();
const CONFIG = new WeakMap();
+const PARAMETERS = new WeakMap();
const CHILDREN = new WeakMap();
const LOCATIONS = new WeakMap();
const POLICIES = new WeakMap();
@@ -69,6 +70,7 @@
constructor() {
ID.set(this, Math.random().toString(36).slice(2));
CONFIG.set(this, new Map());
+ PARAMETERS.set(this, new Map());
METADATA.set(this, new Map());
ENRICHERS.set(this, new Map());
POLICIES.set(this, new Map());
@@ -321,6 +323,10 @@
return CONFIG.get(this);
}
+ get parameters() {
+ return PARAMETERS.get(this);
+ }
+
get metadata() {
return METADATA.get(this);
}
@@ -474,6 +480,14 @@
}
/**
+ * Has {Entity} got parameters
+ * @returns {boolean}
+ */
+ hasParameters() {
+ return PARAMETERS.get(this).size > 0;
+ }
+
+ /**
* Has {Entity} got a location
* @returns {boolean}
*/
@@ -544,6 +558,9 @@
Entity.prototype.getConfigAsJson = getConfigAsJson;
Entity.prototype.setConfigFromJson = setConfigFromJson;
+Entity.prototype.getParametersAsArray = getParametersAsArray;
+Entity.prototype.setParametersFromJson = setParametersFromJson;
+
Entity.prototype.getMetadataAsJson = getMetadataAsJson;
Entity.prototype.setMetadataFromJson = setMetadataFromJson;
@@ -552,8 +569,10 @@
Entity.prototype.getData = getData;
Entity.prototype.addConfig = addConfig;
+Entity.prototype.addParameter = addParameter;
Entity.prototype.addMetadata = addMetadata;
Entity.prototype.removeConfig = removeConfig;
+Entity.prototype.removeParameter = removeParameter;
Entity.prototype.removeMetadata = removeMetadata;
Entity.prototype.isCluster = isCluster;
Entity.prototype.isMemberSpec = isMemberSpec;
@@ -596,6 +615,13 @@
}
}
+function addParameter(param) {
+ let key = param.name;
+ PARAMETERS.get(this).set(key, param);
+ this.touch();
+ return this;
+}
+
function addMetadata(key, value) {
if (!RESERVED_KEY_REGEX.test(key)) {
METADATA.get(this).set(key, value);
@@ -619,6 +645,17 @@
}
/**
+ * Remove an entry from brooklyn.parameters
+ * @param {string} key
+ * @returns {Entity}
+ */
+function removeParameter(key) {
+ PARAMETERS.get(this).delete(key);
+ this.touch();
+ return this;
+}
+
+/**
* Remove an entry from the entity metadata
* @param {string} key
* @returns {Entity}
@@ -734,6 +771,9 @@
if (this.hasConfig()) {
result[FIELD.CONFIG] = this.getConfigAsJson();
}
+ if (this.hasParameters()) {
+ result[FIELD.PARAMETERS] = this.getParametersAsArray();
+ }
if (this.hasLocation()) {
result.location = LOCATIONS.get(this);
}
@@ -845,6 +885,7 @@
ID.set(this, Math.random().toString(36).slice(2));
this.removeLocation();
CONFIG.set(this, new Map());
+ PARAMETERS.set(this, new Map());
METADATA.set(this, new Map());
ENRICHERS.set(this, new Map());
POLICIES.set(this, new Map());
@@ -896,6 +937,9 @@
case FIELD.CONFIG:
self.setConfigFromJson(incomingModel[key]);
break;
+ case FIELD.PARAMETERS:
+ self.setParametersFromJson(incomingModel[key]);
+ break;
case FIELD.ENRICHERS:
self.setEnrichersFromJson(incomingModel[key]);
break;
@@ -964,6 +1008,22 @@
this.touch();
}
+/**
+ * Set brooklyn.parameters from JSON {Array}
+ * @param {Array} incomingModel
+ */
+function setParametersFromJson(incomingModel) {
+ if (!Array.isArray(incomingModel)) {
+ throw new Error('Model parse error ... cannot add parameters as it must be an array')
+ }
+ PARAMETERS.get(this).clear();
+ var self = this;
+ incomingModel.map((param)=> {
+ self.addParameter(param);
+ });
+ this.touch();
+}
+
function setMetadataFromJson(incomingModel) {
METADATA.get(this).clear();
@@ -1022,6 +1082,10 @@
return cleanForJson(CONFIG.get(this), -1);
}
+function getParametersAsArray() {
+ return Array.from(PARAMETERS.get(this).values());
+}
+
/* "cleaning" here means: Dsl objects are toStringed, to the given depth (or infinite if depth<0);
* and entries in Map that are memberspec are unwrapped.
* previously we also stringified maps/lists but that seemed pointless, and it was lossy and buggy.