mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Installing a module returns module info
Removing a module checks module exists and checks type is not in use
This commit is contained in:
parent
4c9d53388c
commit
dd5821ee1b
@ -34,6 +34,7 @@ module.exports = {
|
|||||||
res.send(redNodes.getNodeConfigs());
|
res.send(redNodes.getNodeConfigs());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
post: function(req,res) {
|
post: function(req,res) {
|
||||||
if (!settings.available()) {
|
if (!settings.available()) {
|
||||||
res.send(400,new Error("Settings unavailable").toString());
|
res.send(400,new Error("Settings unavailable").toString());
|
||||||
@ -55,7 +56,7 @@ module.exports = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
promise.then(function(info) {
|
promise.then(function(info) {
|
||||||
res.json(info);
|
res.json(redNodes.getModuleInfo(node.module));
|
||||||
}).otherwise(function(err) {
|
}).otherwise(function(err) {
|
||||||
if (err.code === 404) {
|
if (err.code === 404) {
|
||||||
res.send(404);
|
res.send(404);
|
||||||
|
@ -55,20 +55,21 @@ function checkTypeInUse(id) {
|
|||||||
var nodeInfo = registry.getNodeInfo(id);
|
var nodeInfo = registry.getNodeInfo(id);
|
||||||
if (!nodeInfo) {
|
if (!nodeInfo) {
|
||||||
throw new Error("Unrecognised id: "+id);
|
throw new Error("Unrecognised id: "+id);
|
||||||
}
|
} else {
|
||||||
var inUse = {};
|
var inUse = {};
|
||||||
flows.each(function(n) {
|
flows.each(function(n) {
|
||||||
inUse[n.type] = (inUse[n.type]||0)+1;
|
inUse[n.type] = (inUse[n.type]||0)+1;
|
||||||
});
|
});
|
||||||
var nodesInUse = [];
|
var nodesInUse = [];
|
||||||
nodeInfo.types.forEach(function(t) {
|
nodeInfo.types.forEach(function(t) {
|
||||||
if (inUse[t]) {
|
if (inUse[t]) {
|
||||||
nodesInUse.push(t);
|
nodesInUse.push(t);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (nodesInUse.length > 0) {
|
||||||
|
var msg = nodesInUse.join(", ");
|
||||||
|
throw new Error("Type in use: "+msg);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
if (nodesInUse.length > 0) {
|
|
||||||
var msg = nodesInUse.join(", ");
|
|
||||||
throw new Error("Type in use: "+msg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,13 +80,16 @@ function removeNode(id) {
|
|||||||
|
|
||||||
function removeModule(module) {
|
function removeModule(module) {
|
||||||
var info = registry.getNodeModuleInfo(module);
|
var info = registry.getNodeModuleInfo(module);
|
||||||
for (var i=0;i<info.nodes.length;i++) {
|
if (!info) {
|
||||||
checkTypeInUse(info.nodes[i]);
|
throw new Error("Unrecognised module: "+module);
|
||||||
|
} else {
|
||||||
|
for (var i=0;i<info.nodes.length;i++) {
|
||||||
|
checkTypeInUse(module+"/"+info.nodes[i]);
|
||||||
|
}
|
||||||
|
return registry.removeModule(module);
|
||||||
}
|
}
|
||||||
return registry.removeModule(module);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function disableNode(id) {
|
function disableNode(id) {
|
||||||
checkTypeInUse(id);
|
checkTypeInUse(id);
|
||||||
return registry.disableNode(id);
|
return registry.disableNode(id);
|
||||||
|
@ -203,13 +203,21 @@ describe("nodes api", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('by module', function() {
|
describe('by module', function() {
|
||||||
it('installs the module and returns node info', function(done) {
|
it('installs the module and returns module info', function(done) {
|
||||||
var settingsAvailable = sinon.stub(settings,'available', function() {
|
var settingsAvailable = sinon.stub(settings,'available', function() {
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
var getNodeModuleInfo = sinon.stub(redNodes,'getNodeModuleInfo',function(id) {
|
var getNodeModuleInfo = sinon.stub(redNodes,'getNodeModuleInfo',function(id) {
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
var getModuleInfo = sinon.stub(redNodes,'getModuleInfo',function(module) {
|
||||||
|
if (module === "foo") {
|
||||||
|
return {
|
||||||
|
name:"foo",
|
||||||
|
nodes:[{id:123}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
var installModule = sinon.stub(server,'installModule', function() {
|
var installModule = sinon.stub(server,'installModule', function() {
|
||||||
return when.resolve({id:"123"});
|
return when.resolve({id:"123"});
|
||||||
});
|
});
|
||||||
@ -221,11 +229,14 @@ describe("nodes api", function() {
|
|||||||
.end(function(err,res) {
|
.end(function(err,res) {
|
||||||
settingsAvailable.restore();
|
settingsAvailable.restore();
|
||||||
getNodeModuleInfo.restore();
|
getNodeModuleInfo.restore();
|
||||||
|
getModuleInfo.restore();
|
||||||
installModule.restore();
|
installModule.restore();
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
res.body.should.have.property("id","123");
|
res.body.should.have.property("name","foo");
|
||||||
|
res.body.should.have.property("nodes");
|
||||||
|
res.body.nodes[0].should.have.property("id","123");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -23,7 +23,7 @@ var sinon = require('sinon');
|
|||||||
var index = require("../../../red/nodes/index");
|
var index = require("../../../red/nodes/index");
|
||||||
|
|
||||||
describe("red/nodes/index", function() {
|
describe("red/nodes/index", function() {
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
index.clearRegistry();
|
index.clearRegistry();
|
||||||
});
|
});
|
||||||
@ -44,7 +44,7 @@ describe("red/nodes/index", function() {
|
|||||||
return when(true);
|
return when(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var settings = {
|
var settings = {
|
||||||
available: function() { return false }
|
available: function() { return false }
|
||||||
};
|
};
|
||||||
@ -56,13 +56,13 @@ describe("red/nodes/index", function() {
|
|||||||
// do nothing
|
// do nothing
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
it('nodes are initialised with credentials',function(done) {
|
it('nodes are initialised with credentials',function(done) {
|
||||||
|
|
||||||
index.init(settings, storage);
|
index.init(settings, storage);
|
||||||
index.registerType('test', TestNode);
|
index.registerType('test', TestNode);
|
||||||
index.loadFlows().then(function() {
|
index.loadFlows().then(function() {
|
||||||
var testnode = new TestNode({id:'tab1',type:'test',name:'barney'});
|
var testnode = new TestNode({id:'tab1',type:'test',name:'barney'});
|
||||||
testnode.credentials.should.have.property('b',1);
|
testnode.credentials.should.have.property('b',1);
|
||||||
testnode.credentials.should.have.property('c',2);
|
testnode.credentials.should.have.property('c',2);
|
||||||
done();
|
done();
|
||||||
@ -71,8 +71,8 @@ describe("red/nodes/index", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('flows should be initialised',function(done) {
|
it('flows should be initialised',function(done) {
|
||||||
index.init(settings, storage);
|
index.init(settings, storage);
|
||||||
index.loadFlows().then(function() {
|
index.loadFlows().then(function() {
|
||||||
should.deepEqual(testFlows, index.getFlows());
|
should.deepEqual(testFlows, index.getFlows());
|
||||||
@ -82,7 +82,7 @@ describe("red/nodes/index", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("registerType should register credentials definition", function() {
|
describe("registerType should register credentials definition", function() {
|
||||||
var http = require('http');
|
var http = require('http');
|
||||||
var express = require('express');
|
var express = require('express');
|
||||||
@ -91,7 +91,7 @@ describe("red/nodes/index", function() {
|
|||||||
var credentials = require("../../../red/nodes/credentials");
|
var credentials = require("../../../red/nodes/credentials");
|
||||||
var localfilesystem = require("../../../red/storage/localfilesystem");
|
var localfilesystem = require("../../../red/storage/localfilesystem");
|
||||||
var RED = require("../../../red/red.js");
|
var RED = require("../../../red/red.js");
|
||||||
|
|
||||||
var userDir = path.join(__dirname,".testUserHome");
|
var userDir = path.join(__dirname,".testUserHome");
|
||||||
before(function(done) {
|
before(function(done) {
|
||||||
fs.remove(userDir,function(err) {
|
fs.remove(userDir,function(err) {
|
||||||
@ -109,7 +109,7 @@ describe("red/nodes/index", function() {
|
|||||||
RED.init(http.createServer(function(req,res){app(req,res)}),
|
RED.init(http.createServer(function(req,res){app(req,res)}),
|
||||||
{userDir: userDir});
|
{userDir: userDir});
|
||||||
server.start().then(function () {
|
server.start().then(function () {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -121,24 +121,24 @@ describe("red/nodes/index", function() {
|
|||||||
index.load.restore();
|
index.load.restore();
|
||||||
localfilesystem.getCredentials.restore();
|
localfilesystem.getCredentials.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it(': definition defined',function(done) {
|
it(': definition defined',function(done) {
|
||||||
index.registerType('test', TestNode, {
|
index.registerType('test', TestNode, {
|
||||||
credentials: {
|
credentials: {
|
||||||
foo: {type:"test"}
|
foo: {type:"test"}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var testnode = new TestNode({id:'tab1',type:'test',name:'barney'});
|
var testnode = new TestNode({id:'tab1',type:'test',name:'barney'});
|
||||||
credentials.getDefinition("test").should.have.property('foo');
|
credentials.getDefinition("test").should.have.property('foo');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('allows nodes to be added/remove/enabled/disabled from the registry', function() {
|
describe('allows nodes to be added/removed/enabled/disabled from the registry', function() {
|
||||||
var registry = require("../../../red/nodes/registry");
|
var registry = require("../../../red/nodes/registry");
|
||||||
var randomNodeInfo = {id:"5678",types:["random"]};
|
var randomNodeInfo = {id:"5678",types:["random"]};
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
sinon.stub(registry,"getNodeInfo",function(id) {
|
sinon.stub(registry,"getNodeInfo",function(id) {
|
||||||
if (id == "test") {
|
if (id == "test") {
|
||||||
@ -162,9 +162,9 @@ describe("red/nodes/index", function() {
|
|||||||
registry.disableNode.restore();
|
registry.disableNode.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it(': allows an unused node type to be removed',function(done) {
|
it(': allows an unused node type to be removed',function(done) {
|
||||||
index.init(settings, storage);
|
index.init(settings, storage);
|
||||||
index.registerType('test', TestNode);
|
index.registerType('test', TestNode);
|
||||||
index.loadFlows().then(function() {
|
index.loadFlows().then(function() {
|
||||||
var info = index.removeNode("5678");
|
var info = index.removeNode("5678");
|
||||||
registry.removeNode.calledOnce.should.be.true;
|
registry.removeNode.calledOnce.should.be.true;
|
||||||
@ -175,10 +175,10 @@ describe("red/nodes/index", function() {
|
|||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it(': allows an unused node type to be disabled',function(done) {
|
it(': allows an unused node type to be disabled',function(done) {
|
||||||
index.init(settings, storage);
|
index.init(settings, storage);
|
||||||
index.registerType('test', TestNode);
|
index.registerType('test', TestNode);
|
||||||
index.loadFlows().then(function() {
|
index.loadFlows().then(function() {
|
||||||
var info = index.disableNode("5678");
|
var info = index.disableNode("5678");
|
||||||
registry.disableNode.calledOnce.should.be.true;
|
registry.disableNode.calledOnce.should.be.true;
|
||||||
@ -190,66 +190,131 @@ describe("red/nodes/index", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it(': prevents removing a node type that is in use',function(done) {
|
it(': prevents removing a node type that is in use',function(done) {
|
||||||
index.init(settings, storage);
|
index.init(settings, storage);
|
||||||
index.registerType('test', TestNode);
|
index.registerType('test', TestNode);
|
||||||
index.loadFlows().then(function() {
|
index.loadFlows().then(function() {
|
||||||
/*jshint immed: false */
|
/*jshint immed: false */
|
||||||
(function() {
|
(function() {
|
||||||
index.removeNode("test");
|
index.removeNode("test");
|
||||||
}).should.throw();
|
}).should.throw();
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).otherwise(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it(': prevents disabling a node type that is in use',function(done) {
|
it(': prevents disabling a node type that is in use',function(done) {
|
||||||
index.init(settings, storage);
|
index.init(settings, storage);
|
||||||
index.registerType('test', TestNode);
|
index.registerType('test', TestNode);
|
||||||
index.loadFlows().then(function() {
|
index.loadFlows().then(function() {
|
||||||
/*jshint immed: false */
|
/*jshint immed: false */
|
||||||
(function() {
|
(function() {
|
||||||
index.disabledNode("test");
|
index.disabledNode("test");
|
||||||
}).should.throw();
|
}).should.throw();
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).otherwise(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it(': prevents removing a node type that is unknown',function(done) {
|
it(': prevents removing a node type that is unknown',function(done) {
|
||||||
index.init(settings, storage);
|
index.init(settings, storage);
|
||||||
index.registerType('test', TestNode);
|
index.registerType('test', TestNode);
|
||||||
index.loadFlows().then(function() {
|
index.loadFlows().then(function() {
|
||||||
/*jshint immed: false */
|
/*jshint immed: false */
|
||||||
(function() {
|
(function() {
|
||||||
index.removeNode("doesnotexist");
|
index.removeNode("doesnotexist");
|
||||||
}).should.throw();
|
}).should.throw();
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).otherwise(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it(': prevents disabling a node type that is unknown',function(done) {
|
it(': prevents disabling a node type that is unknown',function(done) {
|
||||||
index.init(settings, storage);
|
index.init(settings, storage);
|
||||||
index.registerType('test', TestNode);
|
index.registerType('test', TestNode);
|
||||||
index.loadFlows().then(function() {
|
index.loadFlows().then(function() {
|
||||||
/*jshint immed: false */
|
/*jshint immed: false */
|
||||||
(function() {
|
(function() {
|
||||||
index.disableNode("doesnotexist");
|
index.disableNode("doesnotexist");
|
||||||
}).should.throw();
|
}).should.throw();
|
||||||
|
|
||||||
|
done();
|
||||||
|
}).otherwise(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('allows modules to be removed from the registry', function() {
|
||||||
|
var registry = require("../../../red/nodes/registry");
|
||||||
|
var randomNodeInfo = {id:"5678",types:["random"]};
|
||||||
|
var randomModuleInfo = {
|
||||||
|
name:"random",
|
||||||
|
nodes: [randomNodeInfo]
|
||||||
|
};
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
sinon.stub(registry,"getNodeInfo",function(id) {
|
||||||
|
if (id == "node-red/foo") {
|
||||||
|
return {id:"1234",types:["test"]};
|
||||||
|
} else if (id == "doesnotexist") {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return randomNodeInfo;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sinon.stub(registry,"getNodeModuleInfo",function(module) {
|
||||||
|
if (module == "node-red") {
|
||||||
|
return {name:"node-red",nodes:["foo"]};
|
||||||
|
} else if (module == "doesnotexist") {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return randomModuleInfo.nodes;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sinon.stub(registry,"removeModule",function(id) {
|
||||||
|
return randomModuleInfo;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
after(function() {
|
||||||
|
registry.getNodeInfo.restore();
|
||||||
|
registry.getNodeModuleInfo.restore();
|
||||||
|
registry.removeModule.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(': prevents removing a module that is in use',function(done) {
|
||||||
|
index.init(settings, storage);
|
||||||
|
index.registerType('test', TestNode);
|
||||||
|
index.loadFlows().then(function() {
|
||||||
|
/*jshint immed: false */
|
||||||
|
(function() {
|
||||||
|
index.removeModule("node-red");
|
||||||
|
}).should.throw();
|
||||||
|
|
||||||
|
done();
|
||||||
|
}).otherwise(function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it(': prevents removing a module that is unknown',function(done) {
|
||||||
|
index.init(settings, storage);
|
||||||
|
index.registerType('test', TestNode);
|
||||||
|
index.loadFlows().then(function() {
|
||||||
|
/*jshint immed: false */
|
||||||
|
(function() {
|
||||||
|
index.removeModule("doesnotexist");
|
||||||
|
}).should.throw();
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).otherwise(function(err) {
|
}).otherwise(function(err) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user