@gregoriusrippenstein/node-red-contrib-introspection 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/nodes/45-get-flows.html +88 -0
- package/nodes/45-get-flows.js +87 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -71,11 +71,13 @@ A node for inserting an SVG image into the workspace. The image is layered above
|
|
|
71
71
|
|
|
72
72
|
### GetFlows -- Experimental
|
|
73
73
|
|
|
74
|
-
Node retrieves the current `flows.json` from the server but using the [Node-RED API](https://nodered.org/docs/api/admin/methods/get/flows/) so that it is storage independent. It returns the flows as a `payload`
|
|
74
|
+
Node retrieves the current `flows.json` from the server but using the [Node-RED API](https://nodered.org/docs/api/admin/methods/get/flows/) so that it is storage independent. It returns the flows as a `payload` of the message.
|
|
75
75
|
|
|
76
|
-
The intention that this is triggered on a regular basis to backup the flows to a third party storage system.
|
|
76
|
+
The intention that this is triggered on a regular basis to backup the flows to a third party storage system. Recommended is usage in combination with the [zip](https://flows.nodered.org/node/node-red-contrib-zip) module to make the backups smaller.
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
GetFlows supports version selection of the flows and it has limited authentication using password `grant_type`.
|
|
79
|
+
|
|
80
|
+
Inspired by the [dsm](https://flows.nodered.org/node/node-red-contrib-dsm) package that has a [backup](https://github.com/cflurin/node-red-contrib-dsm/wiki/Backup) state machine.
|
|
79
81
|
|
|
80
82
|
## Examples
|
|
81
83
|
|
package/nodes/45-get-flows.html
CHANGED
|
@@ -7,6 +7,24 @@
|
|
|
7
7
|
name: {
|
|
8
8
|
value:"",
|
|
9
9
|
},
|
|
10
|
+
flowVersion: {
|
|
11
|
+
value: "v1"
|
|
12
|
+
},
|
|
13
|
+
useAuthentication: {
|
|
14
|
+
value:false
|
|
15
|
+
},
|
|
16
|
+
apiUsername: {
|
|
17
|
+
value: "",
|
|
18
|
+
},
|
|
19
|
+
apiUsernameType: {
|
|
20
|
+
value: "env",
|
|
21
|
+
},
|
|
22
|
+
apiPassword: {
|
|
23
|
+
value: "",
|
|
24
|
+
},
|
|
25
|
+
apiPasswordType: {
|
|
26
|
+
value: "env",
|
|
27
|
+
},
|
|
10
28
|
},
|
|
11
29
|
inputs:1,
|
|
12
30
|
outputs:1,
|
|
@@ -18,6 +36,31 @@
|
|
|
18
36
|
labelStyle: function() {
|
|
19
37
|
return this.name?"node_label_italic":"";
|
|
20
38
|
},
|
|
39
|
+
oneditprepare: function() {
|
|
40
|
+
$("#node-input-apiUsername").typedInput({
|
|
41
|
+
types:["env", "msg", "flow","global", "cred"],
|
|
42
|
+
typeField: "#node-input-apiUsernameType"
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
$("#node-input-apiPassword").typedInput({
|
|
46
|
+
types:["env", "msg", "flow","global", "env", "cred"],
|
|
47
|
+
typeField: "#node-input-apiPasswordType"
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
if ( $('#node-input-useAuthentication').is(":checked") ) {
|
|
51
|
+
$('#useAuthentication-input-fields').show();
|
|
52
|
+
} else {
|
|
53
|
+
$('#useAuthentication-input-fields').hide()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
$('#node-input-useAuthentication').on( 'change', function() {
|
|
57
|
+
if ( $('#node-input-useAuthentication').is(":checked") ) {
|
|
58
|
+
$('#useAuthentication-input-fields').show();
|
|
59
|
+
} else {
|
|
60
|
+
$('#useAuthentication-input-fields').hide()
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
},
|
|
21
64
|
});
|
|
22
65
|
</script>
|
|
23
66
|
|
|
@@ -26,6 +69,51 @@
|
|
|
26
69
|
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
27
70
|
<input type="text" id="node-input-name" placeholder="Name">
|
|
28
71
|
</div>
|
|
72
|
+
|
|
73
|
+
<div class="form-row">
|
|
74
|
+
<label for="node-input-flowVersion">
|
|
75
|
+
<i class="fa fa-tag"></i>
|
|
76
|
+
<span>Flow Version</span>
|
|
77
|
+
</label>
|
|
78
|
+
|
|
79
|
+
<select id="node-input-flowVersion">
|
|
80
|
+
<option value="v1" selected=selected>Version 1</option>
|
|
81
|
+
<option value="v2">Version 2</option>
|
|
82
|
+
</select>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<div class="form-row">
|
|
86
|
+
<label for="node-input-useAuthentication">
|
|
87
|
+
<i class="fa "></i>
|
|
88
|
+
<span>Use Authentication?</span>
|
|
89
|
+
</label>
|
|
90
|
+
|
|
91
|
+
<input type="checkbox" id="node-input-useAuthentication"
|
|
92
|
+
style="display:inline-block; width:15px; vertical-align:baseline;">
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
<div id="useAuthentication-input-fields" class="hidden">
|
|
96
|
+
<div class="form-row">
|
|
97
|
+
<label for="node-input-apiUsername">
|
|
98
|
+
<i class="fa fa-tag"></i>
|
|
99
|
+
Username
|
|
100
|
+
</label>
|
|
101
|
+
<input type="text" id="node-input-apiUsername">
|
|
102
|
+
<input type="hidden" id="node-input-apiUsernameType">
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
<div class="form-row">
|
|
106
|
+
<label for="node-input-apiPassword">
|
|
107
|
+
<i class="fa fa-tag"></i>
|
|
108
|
+
Password
|
|
109
|
+
</label>
|
|
110
|
+
<input type="text" id="node-input-apiPassword">
|
|
111
|
+
<input type="hidden" id="node-input-apiPasswordType">
|
|
112
|
+
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
|
|
29
117
|
</script>
|
|
30
118
|
|
|
31
119
|
<script type="text/html" data-help-name="GetFlows">
|
package/nodes/45-get-flows.js
CHANGED
|
@@ -13,27 +13,96 @@ module.exports = function(RED) {
|
|
|
13
13
|
var os = require('os');
|
|
14
14
|
var got = require('got');
|
|
15
15
|
|
|
16
|
-
var
|
|
16
|
+
var baseUrl = "http://" + os.hostname() + ":" + RED.settings.get("uiPort");
|
|
17
17
|
if ( RED.settings.get("httpAdminRoot") != "/" ) {
|
|
18
|
-
|
|
18
|
+
baseUrl += RED.settings.get("httpAdminRoot");
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
20
|
+
|
|
21
|
+
if ( cfg.useAuthentication ) {
|
|
22
|
+
var username = undefined;
|
|
23
|
+
var password = undefined;
|
|
24
|
+
|
|
25
|
+
node.status({fill:"blue",shape:"dot",text:"Requesting token"});
|
|
26
|
+
|
|
27
|
+
RED.util.evaluateNodeProperty(cfg.apiUsername, cfg.apiUsernameType,
|
|
28
|
+
node, msg, (err, result) => {
|
|
29
|
+
if (err) {
|
|
30
|
+
node.status({fill:"red",shape:"dot",text:"Failed"});
|
|
31
|
+
node.error(err)
|
|
32
|
+
} else {
|
|
33
|
+
username = result;
|
|
34
|
+
|
|
35
|
+
RED.util.evaluateNodeProperty(cfg.apiPassword, cfg.apiPasswordType,
|
|
36
|
+
node, msg, (err, result) => {
|
|
37
|
+
if (err) {
|
|
38
|
+
node.status({fill:"red",shape:"dot",text:"Failed"});
|
|
39
|
+
node.error(err)
|
|
40
|
+
} else {
|
|
41
|
+
password = result;
|
|
42
|
+
|
|
43
|
+
var data = {
|
|
44
|
+
"client_id": "node-red-admin",
|
|
45
|
+
"grant_type": "password",
|
|
46
|
+
"scope": "*",
|
|
47
|
+
"username": username,
|
|
48
|
+
"password": password
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
got.post( baseUrl + "/auth/token", {
|
|
52
|
+
json: data
|
|
53
|
+
}).then( res => {
|
|
54
|
+
node.status({fill:"blue",shape:"dot",text:"Requesting flows"});
|
|
55
|
+
|
|
56
|
+
var access_token = JSON.parse(res.body).access_token;
|
|
57
|
+
got.get( baseUrl + "/flows", {
|
|
58
|
+
headers: {
|
|
59
|
+
"Node-RED-API-Version": cfg.flowVersion,
|
|
60
|
+
"Authorization": "Bearer " + access_token
|
|
61
|
+
}
|
|
62
|
+
}).then( res => {
|
|
63
|
+
node.status({fill:"green",shape:"dot",text:"Good"});
|
|
64
|
+
setTimeout( function() { node.status({}) }, 450);
|
|
65
|
+
send( {
|
|
66
|
+
...msg,
|
|
67
|
+
payload: res.body
|
|
68
|
+
});
|
|
69
|
+
}).catch( err => {
|
|
70
|
+
node.status({fill:"red",shape:"dot",text:"Failed"});
|
|
71
|
+
node.error(err)
|
|
72
|
+
});
|
|
73
|
+
}).catch((err) => {
|
|
74
|
+
node.status({fill:"red",shape:"dot",text:"Failed"});
|
|
75
|
+
node.error( err );
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
} else {
|
|
82
|
+
/*
|
|
83
|
+
* Authentication free zone...
|
|
84
|
+
*/
|
|
85
|
+
node.status({fill:"blue",shape:"dot",text:"Requesting flows"});
|
|
86
|
+
|
|
87
|
+
got.get( baseUrl + "/flows",
|
|
88
|
+
{headers: {"Node-RED-API-Version": cfg.flowVersion}}
|
|
89
|
+
).then( res => {
|
|
90
|
+
if ( res.statusCode == 200 ) {
|
|
91
|
+
send( {
|
|
92
|
+
...msg,
|
|
93
|
+
payload: res.body
|
|
94
|
+
});
|
|
95
|
+
node.status({fill:"green",shape:"dot",text:"Good"});
|
|
96
|
+
setTimeout( function() { node.status({}) }, 450);
|
|
97
|
+
} else {
|
|
98
|
+
node.error( res );
|
|
99
|
+
node.status({fill:"red",shape:"dot",text:"Failed"});
|
|
100
|
+
}
|
|
101
|
+
}).catch( err => {
|
|
34
102
|
node.status({fill:"red",shape:"dot",text:"Failed"});
|
|
35
|
-
|
|
36
|
-
|
|
103
|
+
node.error(err)
|
|
104
|
+
});
|
|
105
|
+
}
|
|
37
106
|
});
|
|
38
107
|
}
|
|
39
108
|
RED.nodes.registerType("GetFlows", GetFlowsFunctionality);
|