add support of environtment variable for tab & group

This commit is contained in:
Hiroyasu Nishiyama
2021-08-19 21:15:13 +09:00
parent f1e7ec0c6b
commit 6aecc3915c
15 changed files with 673 additions and 95 deletions

View File

@@ -396,6 +396,17 @@ class Flow {
return undefined;
}
/**
* Get a group node instance
* @param {String} id
* @return {Node} group node
*/
getGroupNode(id) {
const groups = this.global.groups;
return groups[id];
}
/**
* Get all of the nodes instantiated within this flow
* @return {[type]} [description]
@@ -404,6 +415,57 @@ class Flow {
return this.activeNodes;
}
/**
* Get a flow setting value deined in this flow.
* @param {String} key
* @return {Object} result containinig val property or null
*/
getFlowSetting(name) {
const flow = this.flow;
if (flow.env) {
if (!name.startsWith("$parent.")) {
if (!flow._env) {
const envs = flow.env;
const entries = envs.map((env) => [env.name, env]);
flow._env = Object.fromEntries(entries);
}
const env = flow._env[name];
if (env) {
let value = env.value;
const type = env.type;
if ((type !== "env") || (value !== name)) {
if (type === "env") {
value = value.replace(new RegExp("\\${"+name+"}","g"),"${$parent."+name+"}");
}
try {
if (type === "bool") {
const val = ((value === "true") ||
(value === true));
return {
val: val
};
}
if (type === "cred") {
return {
val: value
};
}
var val = redUtil.evaluateNodeProperty(value, type, null, null, null);
return {
val: val
};
}
catch (e) {
this.error(e);
return null;
}
}
}
}
}
return null;
}
/**
* Get a flow setting value. This currently automatically defers to the parent
* flow which, as defined in ./index.js returns `process.env[key]`.
@@ -412,6 +474,10 @@ class Flow {
* @return {[type]} [description]
*/
getSetting(key) {
const result = this.getFlowSetting(key);
if (result) {
return result.val;
}
return this.parent.getSetting(key);
}

View File

@@ -43,6 +43,54 @@ function evaluateInputValue(value, type, node) {
return redUtil.evaluateNodeProperty(value, type, node, null, null);
}
/*!
* Get value of environment variable defined in group node.
* @param {String} group - group node
* @param {String} name - name of variable
* @return {Object} object containing the value in val property or null if not defined
*/
function getGroupSetting(node, group, flow, name) {
if (group) {
if (!name.startsWith("$parent.")) {
if (group.env) {
if (!group._env) {
const envs = group.env;
const entries = envs.map((env) => [env.name, env]);
group._env = Object.fromEntries(entries);
}
const env = group._env[name];
if (env) {
let value = env.value;
const type = env.type;
if ((type !== "env") || (value !== name)) {
if (type === "env") {
value = value.replace(new RegExp("\\${"+name+"}","g"),"${$parent."+name+"}");
}
try {
const val = evaluateInputValue(value, type, node);
return {
val: val
};
}
catch (e) {
this.error(e);
return null;
}
}
}
}
}
else {
name = name.substring(8);
}
if (group.g && flow) {
const parent = flow.getGroupNode(group.g);
return getGroupSetting(node, parent, flow, name);
}
}
return null;
}
/**
* This class represents a subflow - which is handled as a special type of Flow
*/
@@ -370,6 +418,16 @@ class Subflow extends Flow {
// name starts $parent. ... so delegate to parent automatically
name = name.substring(8);
}
const node = this.subflowInstance;
if (node.g) {
const group = this.getGroupNode(node.g);
const result = getGroupSetting(node, group, this, name);
if (result) {
return result.val;
}
}
var parent = this.parent;
if (parent) {
var val = parent.getSetting(name);

View File

@@ -539,6 +539,9 @@ async function addFlow(flow, user) {
if (flow.hasOwnProperty('disabled')) {
tabNode.disabled = flow.disabled;
}
if (flow.hasOwnProperty('env')) {
tabNode.env = flow.env;
}
var nodes = [tabNode];
@@ -599,6 +602,9 @@ function getFlow(id) {
if (flow.hasOwnProperty('info')) {
result.info = flow.info;
}
if (flow.hasOwnProperty('env')) {
result.env = flow.env;
}
if (id !== 'global') {
result.nodes = [];
}
@@ -694,6 +700,9 @@ async function updateFlow(id,newFlow, user) {
if (newFlow.hasOwnProperty('disabled')) {
tabNode.disabled = newFlow.disabled;
}
if (newFlow.hasOwnProperty('env')) {
tabNode.env = newFlow.env;
}
nodes = [tabNode].concat(newFlow.nodes||[]).concat(newFlow.configs||[]);
nodes.forEach(function(n) {

View File

@@ -44,24 +44,25 @@ function diffNodes(oldNode,newNode) {
var EnvVarPropertyRE_old = /^\$\((\S+)\)$/;
var EnvVarPropertyRE = /^\${(\S+)}$/;
function mapEnvVarProperties(obj,prop,flow) {
function mapEnvVarProperties(obj,prop,flow,config) {
var v = obj[prop];
if (Buffer.isBuffer(v)) {
return;
} else if (Array.isArray(v)) {
for (var i=0;i<v.length;i++) {
mapEnvVarProperties(v,i,flow);
mapEnvVarProperties(v,i,flow,config);
}
} else if (typeof obj[prop] === 'string') {
if (obj[prop][0] === "$" && (EnvVarPropertyRE_old.test(v) || EnvVarPropertyRE.test(v)) ) {
var envVar = v.substring(2,v.length-1);
var r = flow.getSetting(envVar);
obj[prop] = r!==undefined?r:obj[prop];
var r = redUtil.getSetting(config, envVar, flow);
obj[prop] = r ? r : obj[prop];
}
} else {
for (var p in v) {
if (v.hasOwnProperty(p)) {
mapEnvVarProperties(v,p,flow);
mapEnvVarProperties(v,p,flow,config);
}
}
}
@@ -78,7 +79,7 @@ function createNode(flow,config) {
delete conf.credentials;
for (var p in conf) {
if (conf.hasOwnProperty(p)) {
mapEnvVarProperties(conf,p,flow);
mapEnvVarProperties(conf,p,flow,conf);
}
}
try {

View File

@@ -38,6 +38,7 @@ function Node(n) {
this.id = n.id;
this.type = n.type;
this.z = n.z;
this.g = n.g;
this._closeCallbacks = [];
this._inputCallback = null;
this._inputCallbacks = null;

View File

@@ -103,7 +103,7 @@ function createNode(node,def) {
// allow $(foo) syntax to substitute env variables for credentials also...
for (var p in creds) {
if (creds.hasOwnProperty(p)) {
flowUtil.mapEnvVarProperties(creds,p,node._flow);
flowUtil.mapEnvVarProperties(creds,p,node._flow,node);
}
}
node.credentials = creds;