You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2021/04/27 15:12:53 UTC
[brooklyn-ui] 11/15: set from key or parameter working,
with root or anywhere (optionally with type) or ancestors
(optionally with type)
This is an automated email from the ASF dual-hosted git repository.
heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-ui.git
commit 0456306abca63ae1b69962d0f340b7febe23ace6
Author: Alex Heneveld <al...@cloudsoftcorp.com>
AuthorDate: Mon Apr 26 19:29:28 2021 +0100
set from key or parameter working, with root or anywhere (optionally with type) or ancestors (optionally with type)
---
docs/basic-with-constraint.bom | 17 +--
.../app/components/quick-fix/quick-fix.js | 166 ++++++++++++++-------
.../app/components/util/model/entity.model.js | 10 ++
3 files changed, 130 insertions(+), 63 deletions(-)
diff --git a/docs/basic-with-constraint.bom b/docs/basic-with-constraint.bom
index 3ca3e3c..0f1a2db 100644
--- a/docs/basic-with-constraint.bom
+++ b/docs/basic-with-constraint.bom
@@ -37,21 +37,20 @@ brooklyn.catalog:
message-regex: cannot both be set
- key: post_code
- fix: set_from_parameter
+ fix: set_from_key
message-regex: required
- source-mode: suggested
+ source-key: postal_code
source-hierarchy: root
- source-types: [ org.apache.brooklyn.api.entity.Application ]
- source-parameter: postal_code
- source-constraints:
- - required
+ source-key-createable: true
+ source-key-parameter-definition:
+ constraints:
+ - required
- key: post_code
- fix: set_from_config_key
+ fix: set_from_key
message-regex: required
- source-mode: enforced
- source-types: [ basic-with-constraint ]
source-key: post_code
source-hierarchy: anywhere
+ source-types: [ basic-with-constraint ]
diff --git a/ui-modules/blueprint-composer/app/components/quick-fix/quick-fix.js b/ui-modules/blueprint-composer/app/components/quick-fix/quick-fix.js
index 049a713..d703f11 100644
--- a/ui-modules/blueprint-composer/app/components/quick-fix/quick-fix.js
+++ b/ui-modules/blueprint-composer/app/components/quick-fix/quick-fix.js
@@ -90,76 +90,134 @@ const QUICK_FIX_PROPOSERS = {
proposals.clear_config.issues.push(issue);
},
},
- set_from_parameter: {
- propose: proposeSetFrom('parameter')
-
- // - key: post_code
- // fix: set_from_parameter
- // message-regex: required
- // source-mode: suggested
- // source-hierarchy: root
- // source-types: [ org.apache.brooklyn.api.entity.Application ]
- // source-parameter: postal_code
- // source-constraints:
- // - required
-
- },
- set_from_config_key: {
- propose: proposeSetFrom('config')
-
+ set_from_key: {
+ propose: proposeSetFrom()
// - key: post_code
- // fix: set_from_config_key
+ // fix: set_from_key
// message-regex: required
- // source-mode: enforced
- // source-types: [ basic-with-constraint ]
- // source-key: post_code
- // source-hierarchy: anywhere
+ //
+ // source-key: postal_code # required, custom
+ //
+ // source-hierarchy: root # optional, root|anywhere|ancestors -- default is root if no source-types given, anywhere if source-types are given
+ // source-types: [ org.apache.brooklyn.api.entity.Application ] # types to filter by
+ //
+ // source-key-createable: true # whether a parameter can be created or a key/param must already exist there (default the latter, ie false)
+ // source-key-parameter-definition: # if createable and did not exist, extra things to add to definition
+ // constraints:
+ // - required
+
+ // source-mode: suggested | enforced # (enhancement, not supported) could allow user to pick the type and/or key/param name
- }
+ },
};
-function proposeSetFrom(sourceType) {
+function proposeSetFrom() {
return function (qfdef, issue, entity, proposals) {
if (!issue.ref) return;
+
+ let ckey = qfdef['source-key'];
+ if (!ckey) {
+ console.warn("Missing required 'source-key' on hint", qfdef);
+ return;
+ }
+
if (!proposals) proposals = {};
- let sourceNode = {
- id: 'root',
- name: 'the application root node',
- entity: entity.getApplication(),
- };
+ let createable = qfdef['source-key-createable'];
- if (sourceType === 'parameter') {
- let params = sourceNode.entity.getParametersAsArray();
- console.log("params", params);
- }
+ // TODO if root param is required, show error
+ // TODO make default id containts type name
+ // TODO show default id if no id present
+ // TODO if id is changed, update all refs
+ // TODO allow graphically selectable
+
+ let considerNode = (sourceNode) => {
+ if (qfdef['source-types']) {
+ // TODO would be nice to store super-types of entity in miscData and filter based on those
+ if (!qfdef['source-types'].includes(sourceNode.entity.type)) {
+ // wrong type
+ return;
+ }
+ }
+
+ if (sourceNode.entity._id === entity._id && ckey === issue.ref) {
+ // skip proposal for recursive definition
+ return;
+ }
- let key = 'set_from_'+sourceType+'_'+sourceNode.id;
- if (!proposals[key]) {
- proposals[key] = {
- text: "Set from a new "+sourceType+" on "+sourceNode.name,
- tooltip: "This will create a "+sourceType+" on "+sourceNode.name+" and fix this error by setting it equal to that "+sourceType,
- issues: [],
- apply: (issue, entity) => {
- entity = (entity || issue.entity);
- console.log("TODO do this; NB issue invoked wrt", entity, qfdef);
- if (sourceType === 'parameter') {
- if (!sourceNode.entity.getParameterNamed(qfdef['source-parameter'])) {
- sourceNode.entity.addParameter({
- name: qfdef['source-parameter'],
- constraints: qfdef['source-constraints']
- });
+ let hasKey = sourceNode.entity.config[ckey] || (sourceNode.entity.miscData.get("config") || []).find(c => c && c.name === ckey);
+ let hasParam = sourceNode.entity.getParameterNamed(ckey);
+
+ let existing = hasKey || hasParam;
+ let create = !existing && createable;
+
+ if (!existing && !create) {
+ // no proposal available (cannot create)
+ return;
+ }
+
+ sourceNode.id = sourceNode.id || sourceNode.entity.id || sourceNode.entity._id;
+ sourceNode.name = sourceNode.name || sourceNode.entity.name ||
+ ((sourceNode.entity.type || "Unnamed item") + " " + "(" + (sourceNode.entity.id || sourceNode.entity._id) +")");
+
+ let pkey = 'set_from_' + sourceNode.id + '_' + ckey;
+ if (!proposals[pkey]) {
+ if (sourceNode.create_key) {
+ proposals[pkey] = {
+ text: "Set from new parameter '" + ckey + "' on " + sourceNode.name,
+ tooltip: "This will fix the error by setting the value here equal to the value of a new parameter '" + ckey + "' created on " + sourceNode.name
+ + ". The value of that parameter may need to be set in order to deploy this.",
+ };
+ } else {
+ proposals[pkey] = {
+ text: "Set from '" + ckey + "' on " + sourceNode.name,
+ tooltip: "This will fix the error by setting the value here equal to the value of " +
+ sourceNode.target_mode +
+ " '" + ckey + "' on " + sourceNode.name,
+ };
+ }
+
+ Object.assign(proposals[pkey], {
+ issues: [],
+ apply: (issue, entity) => {
+ if (sourceNode.create_key) {
+ // check again so we only create once
+ let hasParam = sourceNode.entity.getParameterNamed(ckey);
+ if (!hasParam) {
+ sourceNode.entity.addParameter(Object.assign(
+ {name: ckey,},
+ qfdef['source-key-parameter-definition'] || {}
+ ));
+ }
}
if (!sourceNode.entity.id) {
- // TODO
- sourceNode.entity.id = 'id_XXX';
+ sourceNode.entity.id = sourceNode.entity._id;
}
- entity.addConfig(issue.ref, '$brooklyn:component("'+sourceNode.entity.id+'").config("'+qfdef['source-parameter']+'")');
+
+ entity = (entity || issue.entity);
+ entity.addConfig(issue.ref, '$brooklyn:component("' + sourceNode.entity.id + '").config("' + ckey + '")');
}
- }
- };
+ });
+ }
+ if (proposals[pkey]) {
+ proposals[pkey].issues.push(issue);
+ }
+ };
+
+ if (qfdef['source-hierarchy']=='root' || (!qfdef['source-hierarchy'] && !qfdef['source-types'])) {
+ considerNode({
+ id: 'root',
+ name: 'the application root node',
+ entity: entity.getApplication(),
+ });
+ } else if (qfdef['source-hierarchy']=='anywhere' || (!qfdef['source-hierarchy'] && qfdef['source-types'])) {
+ entity.getApplication().visitWithDescendants(entity => considerNode({ entity }));
+ } else if (qfdef['source-hierarchy']=='ancestors') {
+ entity.visitWithAncestors(entity => considerNode({ entity }));
+ } else {
+ console.warn("Unsupported source-hierarchy in quick-fix", qfdef);
}
- proposals[key].issues.push(issue);
+
};
}
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 f8afc28..b844450 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
@@ -563,6 +563,16 @@ export class Entity {
toString() {
return 'Entity :: id = [' + this._id + ']' + (this.hasType() ? ' type = [' + this.type + ']' : '');
}
+
+ visitWithDescendants(fn) {
+ fn(this);
+ this.children.forEach(c => c.visitWithDescendants(fn));
+ }
+
+ visitWithAncestors(fn) {
+ fn(this);
+ if (this.parent) this.parent.visitWithAncestors(fn);
+ }
}
Entity.prototype.setEntityFromJson = setEntityFromJson;