@itentialopensource/adapter-meraki 0.8.1 → 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +8 -0
- package/adapter.js +179 -519
- package/adapterBase.js +272 -2
- package/package.json +3 -3
- package/propertiesDecorators.json +14 -0
- package/propertiesSchema.json +339 -195
- package/refs?service=git-upload-pack +0 -0
- package/report/updateReport1651511176919.json +115 -0
- package/test/unit/adapterBaseTestUnit.js +1 -1
- package/test/unit/adapterTestUnit.js +5 -5
- package/utils/tbUtils.js +20 -7
package/adapterBase.js
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
/* eslint no-cond-assign: warn */
|
9
9
|
/* eslint global-require: warn */
|
10
10
|
/* eslint no-unused-vars: warn */
|
11
|
+
/* eslint prefer-destructuring: warn */
|
11
12
|
|
12
13
|
/* Required libraries. */
|
13
14
|
const fs = require('fs-extra');
|
@@ -154,6 +155,9 @@ class AdapterBase extends EventEmitterCl {
|
|
154
155
|
// Instantiate the EventEmitter super class
|
155
156
|
super();
|
156
157
|
|
158
|
+
// IAP home directory injected by core when running the adapter within IAP
|
159
|
+
process.env.iap_home = process.argv[3];
|
160
|
+
|
157
161
|
try {
|
158
162
|
// Capture the adapter id
|
159
163
|
this.id = prongid;
|
@@ -746,7 +750,7 @@ class AdapterBase extends EventEmitterCl {
|
|
746
750
|
try {
|
747
751
|
const { serviceItem } = await tbUtils.getAdapterConfig();
|
748
752
|
const { host } = serviceItem.properties.properties;
|
749
|
-
const result = tbUtils.
|
753
|
+
const result = tbUtils.runConnectivity(host, false);
|
750
754
|
if (result.failCount > 0) {
|
751
755
|
return callback(null, result);
|
752
756
|
}
|
@@ -764,7 +768,7 @@ class AdapterBase extends EventEmitterCl {
|
|
764
768
|
*/
|
765
769
|
iapRunAdapterBasicGet(callback) {
|
766
770
|
try {
|
767
|
-
const result = tbUtils.
|
771
|
+
const result = tbUtils.runBasicGet(false);
|
768
772
|
if (result.failCount > 0) {
|
769
773
|
return callback(null, result);
|
770
774
|
}
|
@@ -1024,6 +1028,272 @@ class AdapterBase extends EventEmitterCl {
|
|
1024
1028
|
return [];
|
1025
1029
|
}
|
1026
1030
|
}
|
1031
|
+
|
1032
|
+
/**
|
1033
|
+
* @summary Make one of the needed Broker calls - could be one of many
|
1034
|
+
*
|
1035
|
+
* @function iapMakeBrokerCall
|
1036
|
+
* @param {string} brokCall - the name of the broker call (required)
|
1037
|
+
* @param {object} callProps - the proeprties for the broker call (required)
|
1038
|
+
* @param {object} devResp - the device details to extract needed inputs (required)
|
1039
|
+
* @param {string} filterName - any filter to search on (required)
|
1040
|
+
*
|
1041
|
+
* @param {getCallback} callback - a callback function to return the result of the call
|
1042
|
+
*/
|
1043
|
+
iapMakeBrokerCall(brokCall, callProps, devResp, filterName, callback) {
|
1044
|
+
const meth = 'adapter-iapMakeBrokerCall';
|
1045
|
+
const origin = `${this.id}-${meth}`;
|
1046
|
+
log.trace(origin);
|
1047
|
+
|
1048
|
+
try {
|
1049
|
+
let uriPath = '';
|
1050
|
+
let uriMethod = 'GET';
|
1051
|
+
let callQuery = {};
|
1052
|
+
let callBody = {};
|
1053
|
+
let callHeaders = {};
|
1054
|
+
let handleFail = 'fail';
|
1055
|
+
let ostypePrefix = '';
|
1056
|
+
let statusValue = 'true';
|
1057
|
+
if (callProps.path) {
|
1058
|
+
uriPath = `${callProps.path}`;
|
1059
|
+
|
1060
|
+
// make any necessary changes to the path
|
1061
|
+
if (devResp !== null && callProps.requestFields && Object.keys(callProps.requestFields).length > 0) {
|
1062
|
+
const rqKeys = Object.keys(callProps.requestFields);
|
1063
|
+
|
1064
|
+
// get the field from the provided device
|
1065
|
+
for (let rq = 0; rq < rqKeys.length; rq += 1) {
|
1066
|
+
// get the request field we are retrieving
|
1067
|
+
const loopField = callProps.requestFields[rqKeys[rq]];
|
1068
|
+
const loopArray = loopField.split('.');
|
1069
|
+
let nestedValue = devResp;
|
1070
|
+
|
1071
|
+
// loops through incase the field is nested
|
1072
|
+
for (let i = 0; i < loopArray.length; i += 1) {
|
1073
|
+
if (Object.hasOwnProperty.call(nestedValue, loopArray[i])) {
|
1074
|
+
nestedValue = nestedValue[loopArray[i]];
|
1075
|
+
} else {
|
1076
|
+
// failed to traverse
|
1077
|
+
nestedValue = loopField;
|
1078
|
+
break;
|
1079
|
+
}
|
1080
|
+
}
|
1081
|
+
|
1082
|
+
// put the value into the path - if it has been specified in the path
|
1083
|
+
uriPath = uriPath.replace(`{${rqKeys[rq]}}`, nestedValue);
|
1084
|
+
}
|
1085
|
+
}
|
1086
|
+
}
|
1087
|
+
if (callProps.method) {
|
1088
|
+
uriMethod = callProps.method;
|
1089
|
+
}
|
1090
|
+
if (callProps.query) {
|
1091
|
+
callQuery = callProps.query;
|
1092
|
+
|
1093
|
+
// go through the query params to check for variable values
|
1094
|
+
const cpKeys = Object.keys(callQuery);
|
1095
|
+
for (let cp = 0; cp < cpKeys.length; cp += 1) {
|
1096
|
+
if (callQuery[cpKeys[cp]].startsWith('{') && callQuery[cpKeys[cp]].endsWith('}')) {
|
1097
|
+
// make any necessary changes to the query params
|
1098
|
+
if (devResp !== null && callProps.requestFields && Object.keys(callProps.requestFields).length > 0) {
|
1099
|
+
const rqKeys = Object.keys(callProps.requestFields);
|
1100
|
+
|
1101
|
+
// get the uuid from the device
|
1102
|
+
for (let rq = 0; rq < rqKeys.length; rq += 1) {
|
1103
|
+
if (cpKeys[cp] === rqKeys[rq]) {
|
1104
|
+
// get the request field we are retrieving
|
1105
|
+
const loopField = callProps.requestFields[rqKeys[rq]];
|
1106
|
+
const loopArray = loopField.split('.');
|
1107
|
+
let nestedValue = devResp;
|
1108
|
+
|
1109
|
+
// loops through incase the field is nested
|
1110
|
+
for (let i = 0; i < loopArray.length; i += 1) {
|
1111
|
+
if (Object.hasOwnProperty.call(nestedValue, loopArray[i])) {
|
1112
|
+
nestedValue = nestedValue[loopArray[i]];
|
1113
|
+
} else {
|
1114
|
+
// failed to traverse
|
1115
|
+
nestedValue = loopField;
|
1116
|
+
break;
|
1117
|
+
}
|
1118
|
+
}
|
1119
|
+
|
1120
|
+
// put the value into the query - if it has been specified in the query
|
1121
|
+
callQuery[cpKeys[cp]] = nestedValue;
|
1122
|
+
}
|
1123
|
+
}
|
1124
|
+
}
|
1125
|
+
}
|
1126
|
+
}
|
1127
|
+
}
|
1128
|
+
if (callProps.body) {
|
1129
|
+
callBody = callProps.body;
|
1130
|
+
}
|
1131
|
+
if (callProps.headers) {
|
1132
|
+
callHeaders = callProps.headers;
|
1133
|
+
}
|
1134
|
+
if (callProps.handleFailure) {
|
1135
|
+
handleFail = callProps.handleFailure;
|
1136
|
+
}
|
1137
|
+
if (callProps.responseFields && callProps.responseFields.ostypePrefix) {
|
1138
|
+
ostypePrefix = callProps.responseFields.ostypePrefix;
|
1139
|
+
}
|
1140
|
+
if (callProps.responseFields && callProps.responseFields.statusValue) {
|
1141
|
+
statusValue = callProps.responseFields.statusValue;
|
1142
|
+
}
|
1143
|
+
|
1144
|
+
// !! using Generic makes it easier on the Adapter Builder (just need to change the path)
|
1145
|
+
// !! you can also replace with a specific call if that is easier
|
1146
|
+
return this.genericAdapterRequest(uriPath, uriMethod, callQuery, callBody, callHeaders, (result, error) => {
|
1147
|
+
// if we received an error or their is no response on the results return an error
|
1148
|
+
if (error) {
|
1149
|
+
if (handleFail === 'fail') {
|
1150
|
+
return callback(null, error);
|
1151
|
+
}
|
1152
|
+
return callback({}, null);
|
1153
|
+
}
|
1154
|
+
if (!result.response) {
|
1155
|
+
if (handleFail === 'fail') {
|
1156
|
+
const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Invalid Response', [brokCall], null, null, null);
|
1157
|
+
log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
|
1158
|
+
return callback(null, errorObj);
|
1159
|
+
}
|
1160
|
+
return callback({}, null);
|
1161
|
+
}
|
1162
|
+
|
1163
|
+
// get the keys for the response fields
|
1164
|
+
let rfKeys = [];
|
1165
|
+
if (callProps.responseFields && Object.keys(callProps.responseFields).length > 0) {
|
1166
|
+
rfKeys = Object.keys(callProps.responseFields);
|
1167
|
+
}
|
1168
|
+
|
1169
|
+
// if we got an array returned (e.g. getDevicesFitered)
|
1170
|
+
if (Array.isArray(result.response)) {
|
1171
|
+
const listDevices = [];
|
1172
|
+
for (let a = 0; a < result.response.length; a += 1) {
|
1173
|
+
const thisDevice = result.response[a];
|
1174
|
+
for (let rf = 0; rf < rfKeys.length; rf += 1) {
|
1175
|
+
if (rfKeys[rf] !== 'ostypePrefix') {
|
1176
|
+
// get the response field we are retrieving
|
1177
|
+
const loopField = callProps.responseFields[rfKeys[rf]];
|
1178
|
+
const loopArray = loopField.split('.');
|
1179
|
+
let nestedValue = thisDevice;
|
1180
|
+
|
1181
|
+
// loops through incase the field is nested
|
1182
|
+
for (let i = 0; i < loopArray.length; i += 1) {
|
1183
|
+
if (Object.hasOwnProperty.call(nestedValue, loopArray[i])) {
|
1184
|
+
nestedValue = nestedValue[loopArray[i]];
|
1185
|
+
} else {
|
1186
|
+
// failed to traverse
|
1187
|
+
nestedValue = '';
|
1188
|
+
break;
|
1189
|
+
}
|
1190
|
+
}
|
1191
|
+
// if the field is ostype - need to add prefix
|
1192
|
+
if (rfKeys[rf] === 'ostype' && typeof nestedValue === 'string') {
|
1193
|
+
nestedValue = ostypePrefix + nestedValue;
|
1194
|
+
}
|
1195
|
+
// if there is a status to set, set it
|
1196
|
+
if (rfKeys[rf] === 'status') {
|
1197
|
+
// if really looking for just a good response
|
1198
|
+
if (loopField === 'return2xx' && result.icode === statusValue.toString()) {
|
1199
|
+
thisDevice.isAlive = true;
|
1200
|
+
} else if (nestedValue.toString() === statusValue.toString()) {
|
1201
|
+
thisDevice.isAlive = true;
|
1202
|
+
} else {
|
1203
|
+
thisDevice.isAlive = false;
|
1204
|
+
}
|
1205
|
+
}
|
1206
|
+
// if we found a good value
|
1207
|
+
thisDevice[rfKeys[rf]] = nestedValue;
|
1208
|
+
}
|
1209
|
+
}
|
1210
|
+
|
1211
|
+
// if there is no filter - add the device to the list
|
1212
|
+
if (!filterName || filterName.length === 0) {
|
1213
|
+
listDevices.push(thisDevice);
|
1214
|
+
} else {
|
1215
|
+
// if we have to match a filter
|
1216
|
+
let found = false;
|
1217
|
+
for (let f = 0; f < filterName.length; f += 1) {
|
1218
|
+
if (thisDevice.name.indexOf(filterName[f]) >= 0) {
|
1219
|
+
found = true;
|
1220
|
+
break;
|
1221
|
+
}
|
1222
|
+
}
|
1223
|
+
// matching device
|
1224
|
+
if (found) {
|
1225
|
+
listDevices.push(thisDevice);
|
1226
|
+
}
|
1227
|
+
}
|
1228
|
+
}
|
1229
|
+
|
1230
|
+
// return the array of devices
|
1231
|
+
return callback(listDevices, null);
|
1232
|
+
}
|
1233
|
+
|
1234
|
+
// if this is not an array - just about everything else, just handle as a single object
|
1235
|
+
let thisDevice = result.response;
|
1236
|
+
for (let rf = 0; rf < rfKeys.length; rf += 1) {
|
1237
|
+
// skip ostypePrefix since it is not a field
|
1238
|
+
if (rfKeys[rf] !== 'ostypePrefix') {
|
1239
|
+
// get the response field we are retrieving
|
1240
|
+
const loopField = callProps.responseFields[rfKeys[rf]];
|
1241
|
+
const loopArray = loopField.split('.');
|
1242
|
+
let nestedValue = thisDevice;
|
1243
|
+
|
1244
|
+
// loops through incase the field is nested
|
1245
|
+
for (let i = 0; i < loopArray.length; i += 1) {
|
1246
|
+
if (Object.hasOwnProperty.call(nestedValue, loopArray[i])) {
|
1247
|
+
nestedValue = nestedValue[loopArray[i]];
|
1248
|
+
} else {
|
1249
|
+
// failed to traverse
|
1250
|
+
nestedValue = '';
|
1251
|
+
break;
|
1252
|
+
}
|
1253
|
+
}
|
1254
|
+
// if the field is ostype - need to add prefix
|
1255
|
+
if (rfKeys[rf] === 'ostype' && typeof nestedValue === 'string') {
|
1256
|
+
nestedValue = ostypePrefix + nestedValue;
|
1257
|
+
}
|
1258
|
+
// if there is a status to set, set it
|
1259
|
+
if (rfKeys[rf] === 'status') {
|
1260
|
+
// if really looking for just a good response
|
1261
|
+
if (loopField === 'return2xx' && result.icode === statusValue.toString()) {
|
1262
|
+
thisDevice.isAlive = true;
|
1263
|
+
} else if (nestedValue.toString() === statusValue.toString()) {
|
1264
|
+
thisDevice.isAlive = true;
|
1265
|
+
} else {
|
1266
|
+
thisDevice.isAlive = false;
|
1267
|
+
}
|
1268
|
+
}
|
1269
|
+
// if we found a good value
|
1270
|
+
thisDevice[rfKeys[rf]] = nestedValue;
|
1271
|
+
}
|
1272
|
+
}
|
1273
|
+
|
1274
|
+
// if there is a filter - check the device is in the list
|
1275
|
+
if (filterName && filterName.length > 0) {
|
1276
|
+
let found = false;
|
1277
|
+
for (let f = 0; f < filterName.length; f += 1) {
|
1278
|
+
if (thisDevice.name.indexOf(filterName[f]) >= 0) {
|
1279
|
+
found = true;
|
1280
|
+
break;
|
1281
|
+
}
|
1282
|
+
}
|
1283
|
+
// no matching device - clear the device
|
1284
|
+
if (!found) {
|
1285
|
+
thisDevice = {};
|
1286
|
+
}
|
1287
|
+
}
|
1288
|
+
|
1289
|
+
return callback(thisDevice, null);
|
1290
|
+
});
|
1291
|
+
} catch (e) {
|
1292
|
+
const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, e);
|
1293
|
+
log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
|
1294
|
+
return callback(null, errorObj);
|
1295
|
+
}
|
1296
|
+
}
|
1027
1297
|
}
|
1028
1298
|
|
1029
1299
|
module.exports = AdapterBase;
|
package/package.json
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
{
|
2
2
|
"name": "@itentialopensource/adapter-meraki",
|
3
|
-
"version": "0.8.
|
3
|
+
"version": "0.8.2",
|
4
4
|
"description": "This adapter integrates with system described as: merakiDashboardApi.",
|
5
5
|
"main": "adapter.js",
|
6
6
|
"wizardVersion": "2.44.7",
|
7
|
-
"engineVersion": "1.
|
7
|
+
"engineVersion": "1.61.2",
|
8
8
|
"adapterType": "http",
|
9
9
|
"scripts": {
|
10
10
|
"artifactize": "npm i && node utils/packModificationScript.js",
|
@@ -52,7 +52,7 @@
|
|
52
52
|
"author": "Itential",
|
53
53
|
"homepage": "https://gitlab.com/itentialopensource/adapters/sd-wan/adapter-meraki#readme",
|
54
54
|
"dependencies": {
|
55
|
-
"@itentialopensource/adapter-utils": "^4.
|
55
|
+
"@itentialopensource/adapter-utils": "^4.45.4",
|
56
56
|
"ajv": "^6.12.0",
|
57
57
|
"axios": "^0.21.0",
|
58
58
|
"commander": "^2.20.0",
|