@itentialopensource/adapter-meraki 1.0.3 → 1.1.0

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.
Files changed (40) hide show
  1. package/AUTH.md +14 -18
  2. package/CALLS.md +4264 -0
  3. package/CHANGELOG.md +16 -0
  4. package/CONTRIBUTING.md +1 -160
  5. package/ENHANCE.md +2 -2
  6. package/README.md +23 -18
  7. package/SYSTEMINFO.md +15 -2
  8. package/adapter.js +164 -335
  9. package/adapterBase.js +411 -920
  10. package/changelogs/changelog.md +198 -0
  11. package/metadata.json +61 -0
  12. package/package.json +24 -24
  13. package/pronghorn.json +470 -138
  14. package/propertiesSchema.json +358 -31
  15. package/refs?service=git-upload-pack +0 -0
  16. package/report/adapterInfo.json +8 -8
  17. package/report/updateReport1690417926405.json +119 -0
  18. package/sampleProperties.json +74 -27
  19. package/test/integration/adapterTestBasicGet.js +2 -4
  20. package/test/integration/adapterTestConnectivity.js +91 -42
  21. package/test/integration/adapterTestIntegration.js +130 -2
  22. package/test/unit/adapterBaseTestUnit.js +388 -313
  23. package/test/unit/adapterTestUnit.js +332 -112
  24. package/utils/adapterInfo.js +1 -1
  25. package/utils/addAuth.js +1 -1
  26. package/utils/artifactize.js +1 -1
  27. package/utils/checkMigrate.js +1 -1
  28. package/utils/entitiesToDB.js +2 -2
  29. package/utils/findPath.js +1 -1
  30. package/utils/methodDocumentor.js +225 -0
  31. package/utils/modify.js +13 -15
  32. package/utils/packModificationScript.js +1 -1
  33. package/utils/pre-commit.sh +2 -0
  34. package/utils/taskMover.js +309 -0
  35. package/utils/tbScript.js +89 -34
  36. package/utils/tbUtils.js +41 -21
  37. package/utils/testRunner.js +1 -1
  38. package/utils/troubleshootingAdapter.js +9 -6
  39. package/versions.json +0 -542
  40. package/workflows/README.md +0 -3
package/adapterBase.js CHANGED
@@ -11,29 +11,29 @@
11
11
  /* eslint prefer-destructuring: warn */
12
12
 
13
13
  /* Required libraries. */
14
- const fs = require('fs-extra');
15
14
  const path = require('path');
16
- const jsonQuery = require('json-query');
17
- const EventEmitterCl = require('events').EventEmitter;
18
15
  const { execSync } = require('child_process');
16
+ const { spawnSync } = require('child_process');
17
+ const EventEmitterCl = require('events').EventEmitter;
18
+ const fs = require('fs-extra');
19
+ const jsonQuery = require('json-query');
19
20
 
20
21
  const sampleProperties = require(`${__dirname}/sampleProperties.json`).properties;
21
22
 
22
23
  /* The schema validator */
23
24
  const AjvCl = require('ajv');
25
+ const { Test } = require('mocha');
24
26
 
25
27
  /* Fetch in the other needed components for the this Adaptor */
26
28
  const PropUtilCl = require('@itentialopensource/adapter-utils').PropertyUtility;
27
29
  const RequestHandlerCl = require('@itentialopensource/adapter-utils').RequestHandler;
28
30
 
29
- const TransUtilCl = require(path.join(__dirname, 'node_modules/@itentialopensource/adapter-utils/lib/translatorUtil.js'));
30
-
31
31
  const entitiesToDB = require(path.join(__dirname, 'utils/entitiesToDB'));
32
32
  const troubleshootingAdapter = require(path.join(__dirname, 'utils/troubleshootingAdapter'));
33
33
  const tbUtils = require(path.join(__dirname, 'utils/tbUtils'));
34
+ const taskMover = require(path.join(__dirname, 'utils/taskMover'));
34
35
 
35
36
  let propUtil = null;
36
- let transUtil = null;
37
37
  let choosepath = null;
38
38
 
39
39
  /*
@@ -155,49 +155,6 @@ function updatePackage(changes) {
155
155
  return null;
156
156
  }
157
157
 
158
- /*
159
- * INTERNAL FUNCTION: get data from source(s) - nested
160
- */
161
- function getDataFromSources(loopField, sources) {
162
- let fieldValue = loopField;
163
-
164
- // go through the sources to find the field
165
- for (let s = 0; s < sources.length; s += 1) {
166
- // find the field value using jsonquery
167
- const nestedValue = jsonQuery(loopField, { data: sources[s] }).value;
168
-
169
- // if we found in source - set and no need to check other sources
170
- if (nestedValue) {
171
- fieldValue = nestedValue;
172
- break;
173
- }
174
- }
175
-
176
- return fieldValue;
177
- }
178
-
179
- /*
180
- * INTERNAL FUNCTION: update allprops device broker array with service config and sample props
181
- */
182
- function getDeviceBrokerArray(sampleProps, allProps) {
183
- const brokerCallsArr = ['getDevice', 'getDevicesFiltered', 'isAlive', 'getConfig', 'getCount'];
184
- const deviceBroker = allProps.devicebroker;
185
- for (let i = 0; i < brokerCallsArr.length; i += 1) {
186
- if (!allProps.devicebroker || !allProps.devicebroker[brokerCallsArr[i]] || allProps.devicebroker[brokerCallsArr[i]].length === 0 || !allProps.devicebroker[brokerCallsArr[i]][0].path) {
187
- // if not in service config check sample props
188
- if (!sampleProps.devicebroker || !sampleProps.devicebroker[brokerCallsArr[i]] || sampleProps.devicebroker[brokerCallsArr[i]].length === 0 || !sampleProps.devicebroker[brokerCallsArr[i]][0].path) {
189
- deviceBroker[brokerCallsArr[i]] = [];
190
- } else {
191
- log.info('Updating device broker with sample props');
192
- deviceBroker[brokerCallsArr[i]] = sampleProps.devicebroker[brokerCallsArr[i]];
193
- }
194
- }
195
- }
196
-
197
- log.info('Device broker array', JSON.stringify(deviceBroker, null, 3));
198
- return deviceBroker;
199
- }
200
-
201
158
  /* GENERAL ADAPTER FUNCTIONS THESE SHOULD NOT BE DIRECTLY MODIFIED */
202
159
  /* IF YOU NEED MODIFICATIONS, REDEFINE THEM IN adapter.js!!! */
203
160
  class AdapterBase extends EventEmitterCl {
@@ -217,10 +174,6 @@ class AdapterBase extends EventEmitterCl {
217
174
  this.id = prongid;
218
175
  this.propUtilInst = new PropUtilCl(prongid, __dirname);
219
176
  propUtil = this.propUtilInst;
220
- this.transUtilInst = new TransUtilCl(prongid, this.propUtilInst);
221
- transUtil = this.transUtilInst;
222
- this.transUtilInst = new TransUtilCl(prongid, this.propUtilInst);
223
- transUtil = this.transUtilInst;
224
177
  this.initProps = properties;
225
178
  this.alive = false;
226
179
  this.healthy = false;
@@ -233,8 +186,6 @@ class AdapterBase extends EventEmitterCl {
233
186
 
234
187
  // set up the properties I care about
235
188
  this.refreshProperties(properties);
236
- // update deviceBroker based on service config and sample props
237
- this.allProps.devicebroker = getDeviceBrokerArray(sampleProperties, this.allProps);
238
189
 
239
190
  // Instantiate the other components for this Adapter
240
191
  this.requestHandlerInst = new RequestHandlerCl(this.id, this.allProps, __dirname);
@@ -293,7 +244,7 @@ class AdapterBase extends EventEmitterCl {
293
244
  this.allProps = this.propUtilInst.mergeProperties(properties, defProps);
294
245
 
295
246
  // validate the entity against the schema
296
- const ajvInst = new AjvCl();
247
+ const ajvInst = new AjvCl({ strictSchema: false, allowUnionTypes: true });
297
248
  const validate = ajvInst.compile(propertiesSchema);
298
249
  const result = validate(this.allProps);
299
250
 
@@ -471,6 +422,40 @@ class AdapterBase extends EventEmitterCl {
471
422
  return myfunctions;
472
423
  }
473
424
 
425
+ /**
426
+ * iapGetAdapterWorkflowFunctions is used to get all of the workflow function in the adapter
427
+ * @param {array} ignoreThese - additional methods to ignore (optional)
428
+ *
429
+ * @function iapGetAdapterWorkflowFunctions
430
+ */
431
+ iapGetAdapterWorkflowFunctions(ignoreThese) {
432
+ const myfunctions = this.getAllFunctions();
433
+ const wffunctions = [];
434
+
435
+ // remove the functions that should not be in a Workflow
436
+ for (let m = 0; m < myfunctions.length; m += 1) {
437
+ if (myfunctions[m] === 'checkActionFiles') {
438
+ // got to the second tier (adapterBase)
439
+ break;
440
+ }
441
+ if (!(myfunctions[m].endsWith('Emit') || myfunctions[m].match(/Emit__v[0-9]+/))) {
442
+ let found = false;
443
+ if (ignoreThese && Array.isArray(ignoreThese)) {
444
+ for (let i = 0; i < ignoreThese.length; i += 1) {
445
+ if (myfunctions[m].toUpperCase() === ignoreThese[i].toUpperCase()) {
446
+ found = true;
447
+ }
448
+ }
449
+ }
450
+ if (!found) {
451
+ wffunctions.push(myfunctions[m]);
452
+ }
453
+ }
454
+ }
455
+
456
+ return wffunctions;
457
+ }
458
+
474
459
  /**
475
460
  * checkActionFiles is used to update the validation of the action files.
476
461
  *
@@ -526,40 +511,6 @@ class AdapterBase extends EventEmitterCl {
526
511
  return this.requestHandlerInst.encryptProperty(property, technique, callback);
527
512
  }
528
513
 
529
- /**
530
- * iapGetAdapterWorkflowFunctions is used to get all of the workflow function in the adapter
531
- * @param {array} ignoreThese - additional methods to ignore (optional)
532
- *
533
- * @function iapGetAdapterWorkflowFunctions
534
- */
535
- iapGetAdapterWorkflowFunctions(ignoreThese) {
536
- const myfunctions = this.getAllFunctions();
537
- const wffunctions = [];
538
-
539
- // remove the functions that should not be in a Workflow
540
- for (let m = 0; m < myfunctions.length; m += 1) {
541
- if (myfunctions[m] === 'addEntityCache') {
542
- // got to the second tier (adapterBase)
543
- break;
544
- }
545
- if (!(myfunctions[m].endsWith('Emit') || myfunctions[m].match(/Emit__v[0-9]+/))) {
546
- let found = false;
547
- if (ignoreThese && Array.isArray(ignoreThese)) {
548
- for (let i = 0; i < ignoreThese.length; i += 1) {
549
- if (myfunctions[m].toUpperCase() === ignoreThese[i].toUpperCase()) {
550
- found = true;
551
- }
552
- }
553
- }
554
- if (!found) {
555
- wffunctions.push(myfunctions[m]);
556
- }
557
- }
558
- }
559
-
560
- return wffunctions;
561
- }
562
-
563
514
  /**
564
515
  * iapUpdateAdapterConfiguration is used to update any of the adapter configuration files. This
565
516
  * allows customers to make changes to adapter configuration without having to be on the
@@ -690,6 +641,86 @@ class AdapterBase extends EventEmitterCl {
690
641
  return callback(null, errorObj);
691
642
  }
692
643
 
644
+ /**
645
+ * @summary Suspends the adapter
646
+ * @param {Callback} callback - The adapater suspension status
647
+ * @function iapSuspendAdapter
648
+ */
649
+ iapSuspendAdapter(mode, callback) {
650
+ const origin = `${this.id}-adapterBase-iapSuspendAdapter`;
651
+ if (this.suspended) {
652
+ throw new Error(`${origin}: Adapter is already suspended`);
653
+ }
654
+ try {
655
+ this.suspended = true;
656
+ this.suspendMode = mode;
657
+ if (this.suspendMode === 'pause') {
658
+ const props = JSON.parse(JSON.stringify(this.initProps));
659
+ // To suspend adapter, enable throttling and set concurrent max to 0
660
+ props.throttle.throttle_enabled = true;
661
+ props.throttle.concurrent_max = 0;
662
+ this.refreshProperties(props);
663
+ }
664
+ return callback({ suspended: true });
665
+ } catch (error) {
666
+ return callback(null, error);
667
+ }
668
+ }
669
+
670
+ /**
671
+ * @summary Unsuspends the adapter
672
+ * @param {Callback} callback - The adapater suspension status
673
+ *
674
+ * @function iapUnsuspendAdapter
675
+ */
676
+ iapUnsuspendAdapter(callback) {
677
+ const origin = `${this.id}-adapterBase-iapUnsuspendAdapter`;
678
+ if (!this.suspended) {
679
+ throw new Error(`${origin}: Adapter is not suspended`);
680
+ }
681
+ if (this.suspendMode === 'pause') {
682
+ const props = JSON.parse(JSON.stringify(this.initProps));
683
+ // To unsuspend adapter, keep throttling enabled and begin processing queued requests in order
684
+ props.throttle.throttle_enabled = true;
685
+ props.throttle.concurrent_max = 1;
686
+ this.refreshProperties(props);
687
+ setTimeout(() => {
688
+ this.getQueue((q, error) => {
689
+ // console.log("Items in queue: " + String(q.length))
690
+ if (q.length === 0) {
691
+ // if queue is empty, return to initial properties state
692
+ this.refreshProperties(this.initProps);
693
+ this.suspended = false;
694
+ return callback({ suspended: false });
695
+ }
696
+ // recursive call to check queue again every second
697
+ return this.iapUnsuspendAdapter(callback);
698
+ });
699
+ }, 1000);
700
+ } else {
701
+ this.suspended = false;
702
+ callback({ suspend: false });
703
+ }
704
+ }
705
+
706
+ /**
707
+ * iapGetAdapterQueue is used to get information for all of the requests currently in the queue.
708
+ *
709
+ * @function iapGetAdapterQueue
710
+ * @param {Callback} callback - a callback function to return the result (Queue) or the error
711
+ */
712
+ iapGetAdapterQueue(callback) {
713
+ const origin = `${this.id}-adapterBase-iapGetAdapterQueue`;
714
+ log.trace(origin);
715
+
716
+ return this.requestHandlerInst.getQueue(callback);
717
+ }
718
+
719
+ /* ********************************************** */
720
+ /* */
721
+ /* EXPOSES ADAPTER SCRIPTS */
722
+ /* */
723
+ /* ********************************************** */
693
724
  /**
694
725
  * See if the API path provided is found in this adapter
695
726
  *
@@ -795,81 +826,6 @@ class AdapterBase extends EventEmitterCl {
795
826
  return callback(result, null);
796
827
  }
797
828
 
798
- /**
799
- * @summary Suspends the adapter
800
- * @param {Callback} callback - The adapater suspension status
801
- * @function iapSuspendAdapter
802
- */
803
- iapSuspendAdapter(mode, callback) {
804
- const origin = `${this.id}-adapterBase-iapSuspendAdapter`;
805
- if (this.suspended) {
806
- throw new Error(`${origin}: Adapter is already suspended`);
807
- }
808
- try {
809
- this.suspended = true;
810
- this.suspendMode = mode;
811
- if (this.suspendMode === 'pause') {
812
- const props = JSON.parse(JSON.stringify(this.initProps));
813
- // To suspend adapter, enable throttling and set concurrent max to 0
814
- props.throttle.throttle_enabled = true;
815
- props.throttle.concurrent_max = 0;
816
- this.refreshProperties(props);
817
- }
818
- return callback({ suspended: true });
819
- } catch (error) {
820
- return callback(null, error);
821
- }
822
- }
823
-
824
- /**
825
- * @summary Unsuspends the adapter
826
- * @param {Callback} callback - The adapater suspension status
827
- *
828
- * @function iapUnsuspendAdapter
829
- */
830
- iapUnsuspendAdapter(callback) {
831
- const origin = `${this.id}-adapterBase-iapUnsuspendAdapter`;
832
- if (!this.suspended) {
833
- throw new Error(`${origin}: Adapter is not suspended`);
834
- }
835
- if (this.suspendMode === 'pause') {
836
- const props = JSON.parse(JSON.stringify(this.initProps));
837
- // To unsuspend adapter, keep throttling enabled and begin processing queued requests in order
838
- props.throttle.throttle_enabled = true;
839
- props.throttle.concurrent_max = 1;
840
- this.refreshProperties(props);
841
- setTimeout(() => {
842
- this.getQueue((q, error) => {
843
- // console.log("Items in queue: " + String(q.length))
844
- if (q.length === 0) {
845
- // if queue is empty, return to initial properties state
846
- this.refreshProperties(this.initProps);
847
- this.suspended = false;
848
- return callback({ suspended: false });
849
- }
850
- // recursive call to check queue again every second
851
- return this.iapUnsuspendAdapter(callback);
852
- });
853
- }, 1000);
854
- } else {
855
- this.suspended = false;
856
- callback({ suspend: false });
857
- }
858
- }
859
-
860
- /**
861
- * iapGetAdapterQueue is used to get information for all of the requests currently in the queue.
862
- *
863
- * @function iapGetAdapterQueue
864
- * @param {Callback} callback - a callback function to return the result (Queue) or the error
865
- */
866
- iapGetAdapterQueue(callback) {
867
- const origin = `${this.id}-adapterBase-iapGetAdapterQueue`;
868
- log.trace(origin);
869
-
870
- return this.requestHandlerInst.getQueue(callback);
871
- }
872
-
873
829
  /**
874
830
  * @summary runs troubleshoot scripts for adapter
875
831
  *
@@ -971,156 +927,89 @@ class AdapterBase extends EventEmitterCl {
971
927
  }
972
928
 
973
929
  /**
974
- * @summary take the entities and add them to the cache
930
+ * @function iapDeactivateTasks
975
931
  *
976
- * @function addEntityCache
977
- * @param {String} entityType - the type of the entities
978
- * @param {Array} data - the list of entities
979
- * @param {String} key - unique key for the entities
980
- *
981
- * @param {Callback} callback - An array of whether the adapter can has the
982
- * desired capability or an error
932
+ * @param {Array} tasks - List of tasks to deactivate
933
+ * @param {Callback} callback
983
934
  */
984
- addEntityCache(entityType, entities, key, callback) {
985
- const meth = 'adapterBase-addEntityCache';
935
+ iapDeactivateTasks(tasks, callback) {
936
+ const meth = 'adapterBase-iapDeactivateTasks';
986
937
  const origin = `${this.id}-${meth}`;
987
938
  log.trace(origin);
988
-
989
- // list containing the items to add to the cache
990
- const entityIds = [];
991
-
992
- if (entities && Object.hasOwnProperty.call(entities, 'response')
993
- && Array.isArray(entities.response)) {
994
- for (let e = 0; e < entities.response.length; e += 1) {
995
- entityIds.push(entities.response[e][key]);
996
- }
939
+ let data;
940
+ try {
941
+ data = taskMover.deactivateTasks(__dirname, tasks);
942
+ } catch (ex) {
943
+ taskMover.rollbackChanges(__dirname);
944
+ taskMover.deleteBackups(__dirname);
945
+ return callback(null, ex);
997
946
  }
998
-
999
- // add the entities to the cache
1000
- return this.requestHandlerInst.addEntityCache(entityType, entityIds, (loaded, error) => {
1001
- if (error) {
1002
- return callback(null, error);
1003
- }
1004
- if (!loaded) {
1005
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Entity Cache Not Loading', [entityType], null, null, null);
1006
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1007
- return callback(null, errorObj);
1008
- }
1009
-
1010
- return callback(loaded);
1011
- });
947
+ taskMover.deleteBackups(__dirname);
948
+ return callback(data, null);
1012
949
  }
1013
950
 
1014
951
  /**
1015
- * @summary sees if the entity is in the entity list or not
952
+ * @function iapActivateTasks
1016
953
  *
1017
- * @function entityInList
1018
- * @param {String/Array} entityId - the specific entity we are looking for
1019
- * @param {Array} data - the list of entities
1020
- *
1021
- * @param {Callback} callback - An array of whether the adapter can has the
1022
- * desired capability or an error
954
+ * @param {Array} tasks - List of tasks to deactivate
955
+ * @param {Callback} callback
1023
956
  */
1024
- entityInList(entityId, data) {
1025
- const origin = `${this.id}-adapterBase-entityInList`;
957
+ iapActivateTasks(tasks, callback) {
958
+ const meth = 'adapterBase-iapActivateTasks';
959
+ const origin = `${this.id}-${meth}`;
1026
960
  log.trace(origin);
1027
-
1028
- // need to check on the entities that were passed in
1029
- if (Array.isArray(entityId)) {
1030
- const resEntity = [];
1031
-
1032
- for (let e = 0; e < entityId.length; e += 1) {
1033
- if (data.includes(entityId[e])) {
1034
- resEntity.push(true);
1035
- } else {
1036
- resEntity.push(false);
1037
- }
1038
- }
1039
-
1040
- return resEntity;
961
+ let data;
962
+ try {
963
+ data = taskMover.activateTasks(__dirname, tasks);
964
+ } catch (ex) {
965
+ taskMover.rollbackChanges(__dirname);
966
+ taskMover.deleteBackups(__dirname);
967
+ return callback(null, ex);
1041
968
  }
1042
-
1043
- // does the entity list include the specific entity
1044
- return [data.includes(entityId)];
969
+ taskMover.deleteBackups(__dirname);
970
+ return callback(data, null);
1045
971
  }
1046
972
 
973
+ /* ********************************************** */
974
+ /* */
975
+ /* EXPOSES CACHE CALLS */
976
+ /* */
977
+ /* ********************************************** */
1047
978
  /**
1048
- * @summary prepare results for verify capability so they are true/false
1049
- *
1050
- * @function capabilityResults
1051
- * @param {Array} results - the results from the capability check
979
+ * @summary Populate the cache for the given entities
1052
980
  *
1053
- * @param {Callback} callback - An array of whether the adapter can has the
1054
- * desired capability or an error
981
+ * @function iapPopulateEntityCache
982
+ * @param {String/Array of Strings} entityType - the entity type(s) to populate
983
+ * @param {Callback} callback - whether the cache was updated or not for each entity type
984
+ * @returns return of the callback
1055
985
  */
1056
- capabilityResults(results, callback) {
1057
- const meth = 'adapterBase-capabilityResults';
1058
- const origin = `${this.id}-${meth}`;
986
+ iapPopulateEntityCache(entityTypes, callback) {
987
+ const origin = `${this.myid}-adapterBase-iapPopulateEntityCache`;
1059
988
  log.trace(origin);
1060
- let locResults = results;
1061
-
1062
- if (locResults && locResults[0] === 'needupdate') {
1063
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Entity Cache Not Loading', ['unknown'], null, null, null);
1064
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1065
- this.repeatCacheCount += 1;
1066
- return callback(null, errorObj);
1067
- }
1068
989
 
1069
- // if an error occured, return the error
1070
- if (locResults && locResults[0] === 'error') {
1071
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Error Verifying Entity Cache', null, null, null, null);
1072
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1073
- return callback(null, errorObj);
1074
- }
1075
-
1076
- // go through the response and change to true/false
1077
- if (locResults) {
1078
- // if not an array, just convert the return
1079
- if (!Array.isArray(locResults)) {
1080
- if (locResults === 'found') {
1081
- locResults = [true];
1082
- } else {
1083
- locResults = [false];
1084
- }
1085
- } else {
1086
- const temp = [];
1087
-
1088
- // go through each element in the array to convert
1089
- for (let r = 0; r < locResults.length; r += 1) {
1090
- if (locResults[r] === 'found') {
1091
- temp.push(true);
1092
- } else {
1093
- temp.push(false);
1094
- }
1095
- }
1096
- locResults = temp;
1097
- }
1098
- }
1099
-
1100
- // return the results
1101
- return callback(locResults);
990
+ return this.requestHandlerInst.populateEntityCache(entityTypes, callback);
1102
991
  }
1103
992
 
1104
993
  /**
1105
- * @summary Provides a way for the adapter to tell north bound integrations
1106
- * all of the capabilities for the current adapter
1107
- *
1108
- * @function getAllCapabilities
994
+ * @summary Retrieves data from cache for specified entity type
1109
995
  *
1110
- * @return {Array} - containing the entities and the actions available on each entity
996
+ * @function iapRetrieveEntitiesCache
997
+ * @param {String} entityType - entity of which to retrieve
998
+ * @param {Object} options - settings of which data to return and how to return it
999
+ * @param {Callback} callback - the data if it was retrieved
1111
1000
  */
1112
- getAllCapabilities() {
1113
- const origin = `${this.id}-adapterBase-getAllCapabilities`;
1001
+ iapRetrieveEntitiesCache(entityType, options, callback) {
1002
+ const origin = `${this.myid}-adapterBase-iapRetrieveEntitiesCache`;
1114
1003
  log.trace(origin);
1115
1004
 
1116
- // validate the capabilities for the adapter
1117
- try {
1118
- return this.requestHandlerInst.getAllCapabilities();
1119
- } catch (e) {
1120
- return [];
1121
- }
1005
+ return this.requestHandlerInst.retrieveEntitiesCache(entityType, options, callback);
1122
1006
  }
1123
1007
 
1008
+ /* ********************************************** */
1009
+ /* */
1010
+ /* EXPOSES BROKER CALLS */
1011
+ /* */
1012
+ /* ********************************************** */
1124
1013
  /**
1125
1014
  * @summary Determines if this adapter supports any in a list of entities
1126
1015
  *
@@ -1132,720 +1021,322 @@ class AdapterBase extends EventEmitterCl {
1132
1021
  * value is true or false
1133
1022
  */
1134
1023
  hasEntities(entityType, entityList, callback) {
1135
- const origin = `${this.id}-adapter-hasEntities`;
1024
+ const origin = `${this.id}-adapterBase-hasEntities`;
1136
1025
  log.trace(origin);
1137
1026
 
1138
- switch (entityType) {
1139
- case 'Device':
1140
- return this.hasDevices(entityList, callback);
1141
- default:
1142
- return callback(null, `${this.id} does not support entity ${entityType}`);
1143
- }
1027
+ return this.requestHandlerInst.hasEntities(entityType, entityList, callback);
1144
1028
  }
1145
1029
 
1146
1030
  /**
1147
- * @summary Helper method for hasEntities for the specific device case
1031
+ * @summary Get Appliance that match the deviceName
1148
1032
  *
1149
- * @param {Array} deviceList - array of unique device identifiers
1150
- * @param {Callback} callback - A map where the device is the key and the
1151
- * value is true or false
1033
+ * @function getDevice
1034
+ * @param {String} deviceName - the deviceName to find (required)
1035
+ *
1036
+ * @param {getCallback} callback - a callback function to return the result
1037
+ * (appliance) or the error
1152
1038
  */
1153
- hasDevices(deviceList, callback) {
1154
- const origin = `${this.id}-adapter-hasDevices`;
1039
+ getDevice(deviceName, callback) {
1040
+ const origin = `${this.id}-adapterBase-getDevice`;
1155
1041
  log.trace(origin);
1156
1042
 
1157
- const findings = deviceList.reduce((map, device) => {
1158
- // eslint-disable-next-line no-param-reassign
1159
- map[device] = false;
1160
- log.debug(`In reduce: ${JSON.stringify(map)}`);
1161
- return map;
1162
- }, {});
1163
- const apiCalls = deviceList.map((device) => new Promise((resolve) => {
1164
- this.getDevice(device, (result, error) => {
1165
- if (error) {
1166
- log.debug(`In map error: ${JSON.stringify(device)}`);
1167
- return resolve({ name: device, found: false });
1168
- }
1169
- log.debug(`In map: ${JSON.stringify(device)}`);
1170
- return resolve({ name: device, found: true });
1171
- });
1172
- }));
1173
- Promise.all(apiCalls).then((results) => {
1174
- results.forEach((device) => {
1175
- findings[device.name] = device.found;
1176
- });
1177
- log.debug(`FINDINGS: ${JSON.stringify(findings)}`);
1178
- return callback(findings);
1179
- }).catch((errors) => {
1180
- log.error('Unable to do device lookup.');
1181
- return callback(null, { code: 503, message: 'Unable to do device lookup.', error: errors });
1182
- });
1043
+ return this.requestHandlerInst.getDevice(deviceName, callback);
1183
1044
  }
1184
1045
 
1185
1046
  /**
1186
- * @summary Make one of the needed Broker calls - could be one of many
1047
+ * @summary Get Appliances that match the filter
1187
1048
  *
1188
- * @function iapMakeBrokerCall
1189
- * @param {string} brokCall - the name of the broker call (required)
1190
- * @param {object} callProps - the proeprties for the broker call (required)
1191
- * @param {object} devResp - the device details to extract needed inputs (required)
1192
- * @param {string} filterName - any filter to search on (required)
1049
+ * @function getDevicesFiltered
1050
+ * @param {Object} options - the data to use to filter the appliances (optional)
1193
1051
  *
1194
- * @param {getCallback} callback - a callback function to return the result of the call
1052
+ * @param {getCallback} callback - a callback function to return the result
1053
+ * (appliances) or the error
1195
1054
  */
1196
- iapMakeBrokerCall(brokCall, callProps, devResp, filterName, callback) {
1197
- const meth = 'adapterBase-iapMakeBrokerCall';
1198
- const origin = `${this.id}-${meth}`;
1055
+ getDevicesFiltered(options, callback) {
1056
+ const origin = `${this.id}-adapterBase-getDevicesFiltered`;
1199
1057
  log.trace(origin);
1200
1058
 
1201
- try {
1202
- let uriPath = '';
1203
- let uriMethod = 'GET';
1204
- let callQuery = {};
1205
- let callBody = {};
1206
- let callHeaders = {};
1207
- let handleFail = 'fail';
1208
- let ostypePrefix = '';
1209
- let statusValue = 'true';
1210
- if (callProps.path) {
1211
- uriPath = `${callProps.path}`;
1212
-
1213
- // make any necessary changes to the path
1214
- if (devResp !== null && callProps.requestFields && Object.keys(callProps.requestFields).length > 0) {
1215
- const rqKeys = Object.keys(callProps.requestFields);
1216
-
1217
- // get the field from the provided device
1218
- for (let rq = 0; rq < rqKeys.length; rq += 1) {
1219
- const fieldValue = getDataFromSources(callProps.requestFields[rqKeys[rq]], devResp);
1220
-
1221
- // put the value into the path - if it has been specified in the path
1222
- uriPath = uriPath.replace(`{${rqKeys[rq]}}`, fieldValue);
1223
- }
1224
- }
1225
- }
1226
- if (callProps.method) {
1227
- uriMethod = callProps.method;
1228
- }
1229
- if (callProps.query) {
1230
- callQuery = { ...callProps.query };
1231
- // go through the query params to check for variable values
1232
- const cpKeys = Object.keys(callQuery);
1233
- for (let cp = 0; cp < cpKeys.length; cp += 1) {
1234
- // if (callQuery[cpKeys[cp]].startsWith('{') && callQuery[cpKeys[cp]].endsWith('}')) {
1235
- // make any necessary changes to the query params
1236
- if (devResp !== null && callProps.requestFields && Object.keys(callProps.requestFields).length > 0) {
1237
- const rqKeys = Object.keys(callProps.requestFields);
1238
-
1239
- // get the field from the provided device
1240
- for (let rq = 0; rq < rqKeys.length; rq += 1) {
1241
- if (callQuery[cpKeys[cp]] === rqKeys[rq]) {
1242
- const fieldValue = getDataFromSources(callProps.requestFields[rqKeys[rq]], devResp);
1243
- // put the value into the query - if it has been specified in the query
1244
- callQuery[cpKeys[cp]] = fieldValue;
1245
- }
1246
- }
1247
- }
1248
- // }
1249
- }
1250
- }
1251
- if (callProps.body) {
1252
- callBody = { ...callProps.body };
1253
-
1254
- // go through the body fields to check for variable values
1255
- const cbKeys = Object.keys(callBody);
1256
- for (let cb = 0; cb < cbKeys.length; cb += 1) {
1257
- // if (callBody[cbKeys[cb]].startsWith('{') && callBody[cbKeys[cb]].endsWith('}')) {
1258
- // make any necessary changes to the query params
1259
- if (devResp !== null && callProps.requestFields && Object.keys(callProps.requestFields).length > 0) {
1260
- const rqKeys = Object.keys(callProps.requestFields);
1261
-
1262
- // get the field from the provided device
1263
- for (let rq = 0; rq < rqKeys.length; rq += 1) {
1264
- if (callBody[cbKeys[cb]] === rqKeys[rq]) {
1265
- const fieldValue = getDataFromSources(callProps.requestFields[rqKeys[rq]], devResp);
1266
-
1267
- // put the value into the query - if it has been specified in the query
1268
- callBody[cbKeys[cb]] = fieldValue;
1269
- }
1270
- }
1271
- }
1272
- // }
1273
- }
1274
- }
1275
- if (callProps.headers) {
1276
- callHeaders = { ...callProps.headers };
1277
-
1278
- // go through the body fields to check for variable values
1279
- const chKeys = Object.keys(callHeaders);
1280
- for (let ch = 0; ch < chKeys.length; ch += 1) {
1281
- // if (callHeaders[chKeys[ch]].startsWith('{') && callHeaders[chKeys[ch]].endsWith('}')) {
1282
- // make any necessary changes to the query params
1283
- if (devResp !== null && callProps.requestFields && Object.keys(callProps.requestFields).length > 0) {
1284
- const rqKeys = Object.keys(callProps.requestFields);
1285
-
1286
- // get the field from the provided device
1287
- for (let rq = 0; rq < rqKeys.length; rq += 1) {
1288
- if (callHeaders[chKeys[ch]] === rqKeys[rq]) {
1289
- const fieldValue = getDataFromSources(callProps.requestFields[rqKeys[rq]], devResp);
1290
-
1291
- // put the value into the query - if it has been specified in the query
1292
- callHeaders[chKeys[ch]] = fieldValue;
1293
- }
1294
- }
1295
- }
1296
- // }
1297
- }
1298
- }
1299
- if (callProps.handleFailure) {
1300
- handleFail = callProps.handleFailure;
1301
- }
1302
- if (callProps.responseFields && callProps.responseFields.ostypePrefix) {
1303
- ostypePrefix = callProps.responseFields.ostypePrefix;
1304
- }
1305
- if (callProps.responseFields && callProps.responseFields.statusValue) {
1306
- statusValue = callProps.responseFields.statusValue;
1307
- }
1308
-
1309
- // !! using Generic makes it easier on the Adapter Builder (just need to change the path)
1310
- // !! you can also replace with a specific call if that is easier
1311
- return this.genericAdapterRequest(uriPath, uriMethod, callQuery, callBody, callHeaders, (result, error) => {
1312
- // if we received an error or their is no response on the results return an error
1313
- if (error) {
1314
- if (handleFail === 'fail') {
1315
- return callback(null, error);
1316
- }
1317
- return callback({}, null);
1318
- }
1319
- if (!result.response) {
1320
- if (handleFail === 'fail') {
1321
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Invalid Response', [brokCall], null, null, null);
1322
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1323
- return callback(null, errorObj);
1324
- }
1325
- return callback({}, null);
1326
- }
1327
-
1328
- // get the response piece we care about from the response
1329
- const myResult = result;
1330
- if (callProps.responseDatakey) {
1331
- myResult.response = jsonQuery(callProps.responseDatakey, { data: myResult.response }).value;
1332
- }
1333
-
1334
- // get the keys for the response fields
1335
- let rfKeys = [];
1336
- if (callProps.responseFields && Object.keys(callProps.responseFields).length > 0) {
1337
- rfKeys = Object.keys(callProps.responseFields);
1338
- }
1339
-
1340
- // if we got an array returned (e.g. getDevicesFitered)
1341
- if (Array.isArray(myResult.response)) {
1342
- const listDevices = [];
1343
- for (let a = 0; a < myResult.response.length; a += 1) {
1344
- const thisDevice = myResult.response[a];
1345
- for (let rf = 0; rf < rfKeys.length; rf += 1) {
1346
- if (rfKeys[rf] !== 'ostypePrefix') {
1347
- let fieldValue = getDataFromSources(callProps.responseFields[rfKeys[rf]], [thisDevice, devResp, callProps.requestFields]);
1348
-
1349
- // if the field is ostype - need to add prefix
1350
- if (rfKeys[rf] === 'ostype' && typeof fieldValue === 'string') {
1351
- fieldValue = ostypePrefix + fieldValue;
1352
- }
1353
- // if there is a status to set, set it
1354
- if (rfKeys[rf] === 'status') {
1355
- // if really looking for just a good response
1356
- if (callProps.responseFields[rfKeys[rf]] === 'return2xx' && myResult.icode === statusValue.toString()) {
1357
- thisDevice.isAlive = true;
1358
- } else if (fieldValue.toString() === statusValue.toString()) {
1359
- thisDevice.isAlive = true;
1360
- } else {
1361
- thisDevice.isAlive = false;
1362
- }
1363
- }
1364
- // if we found a good value
1365
- thisDevice[rfKeys[rf]] = fieldValue;
1366
- }
1367
- }
1368
-
1369
- // if there is no filter - add the device to the list
1370
- if (!filterName || filterName.length === 0) {
1371
- listDevices.push(thisDevice);
1372
- } else {
1373
- // if we have to match a filter
1374
- let found = false;
1375
- for (let f = 0; f < filterName.length; f += 1) {
1376
- if (thisDevice.name.indexOf(filterName[f]) >= 0) {
1377
- found = true;
1378
- break;
1379
- }
1380
- }
1381
- // matching device
1382
- if (found) {
1383
- listDevices.push(thisDevice);
1384
- }
1385
- }
1386
- }
1387
-
1388
- // return the array of devices
1389
- return callback(listDevices, null);
1390
- }
1391
-
1392
- // if this is not an array - just about everything else, just handle as a single object
1393
- let thisDevice = myResult.response;
1394
- for (let rf = 0; rf < rfKeys.length; rf += 1) {
1395
- // skip ostypePrefix since it is not a field
1396
- if (rfKeys[rf] !== 'ostypePrefix') {
1397
- let fieldValue = getDataFromSources(callProps.responseFields[rfKeys[rf]], [thisDevice, devResp, callProps.requestFields]);
1398
-
1399
- // if the field is ostype - need to add prefix
1400
- if (rfKeys[rf] === 'ostype' && typeof fieldValue === 'string') {
1401
- fieldValue = ostypePrefix + fieldValue;
1402
- }
1403
- // if there is a status to set, set it
1404
- if (rfKeys[rf] === 'status') {
1405
- // if really looking for just a good response
1406
- if (callProps.responseFields[rfKeys[rf]] === 'return2xx' && myResult.icode === statusValue.toString()) {
1407
- thisDevice.isAlive = true;
1408
- } else if (fieldValue.toString() === statusValue.toString()) {
1409
- thisDevice.isAlive = true;
1410
- } else {
1411
- thisDevice.isAlive = false;
1412
- }
1413
- }
1414
- // if we found a good value
1415
- thisDevice[rfKeys[rf]] = fieldValue;
1416
- }
1417
- }
1418
-
1419
- // if there is a filter - check the device is in the list
1420
- if (filterName && filterName.length > 0) {
1421
- let found = false;
1422
- for (let f = 0; f < filterName.length; f += 1) {
1423
- if (thisDevice.name.indexOf(filterName[f]) >= 0) {
1424
- found = true;
1425
- break;
1426
- }
1427
- }
1428
- // no matching device - clear the device
1429
- if (!found) {
1430
- thisDevice = {};
1431
- }
1432
- }
1433
-
1434
- return callback(thisDevice, null);
1435
- });
1436
- } catch (e) {
1437
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, e);
1438
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1439
- return callback(null, errorObj);
1440
- }
1059
+ return this.requestHandlerInst.getDevicesFiltered(options, callback);
1441
1060
  }
1442
1061
 
1443
1062
  /**
1444
- * @summary Get Appliance that match the deviceName
1063
+ * @summary Gets the status for the provided appliance
1445
1064
  *
1446
- * @function getDevice
1447
- * @param {String} deviceName - the deviceName to find (required)
1065
+ * @function isAlive
1066
+ * @param {String} deviceName - the deviceName of the appliance. (required)
1448
1067
  *
1449
- * @param {getCallback} callback - a callback function to return the result
1450
- * (appliance) or the error
1068
+ * @param {configCallback} callback - callback function to return the result
1069
+ * (appliance isAlive) or the error
1451
1070
  */
1452
- getDevice(deviceName, callback) {
1453
- const meth = 'adapterBase-getDevice';
1454
- const origin = `${this.id}-${meth}`;
1071
+ isAlive(deviceName, callback) {
1072
+ const origin = `${this.id}-adapterBase-isAlive`;
1455
1073
  log.trace(origin);
1456
1074
 
1457
- // make sure we are set up for device broker getDevice
1458
- if (!this.allProps.devicebroker || !this.allProps.devicebroker.getDevice || this.allProps.devicebroker.getDevice.length === 0 || !this.allProps.devicebroker.getDevice[0].path) {
1459
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Properties', ['devicebroker.getDevice.path'], null, null, null);
1460
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1461
- return callback(null, errorObj);
1462
- }
1463
-
1464
- /* HERE IS WHERE YOU VALIDATE DATA */
1465
- if (deviceName === undefined || deviceName === null || deviceName === '' || deviceName.length === 0) {
1466
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['deviceName'], null, null, null);
1467
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1468
- return callback(null, errorObj);
1469
- }
1470
-
1471
- try {
1472
- // need to get the device so we can convert the deviceName to an id
1473
- // !! if we can do a lookup by name the getDevicesFiltered may not be necessary
1474
- const opts = {
1475
- filter: {
1476
- name: deviceName
1477
- }
1478
- };
1479
- return this.getDevicesFiltered(opts, (devs, ferr) => {
1480
- // if we received an error or their is no response on the results return an error
1481
- if (ferr) {
1482
- return callback(null, ferr);
1483
- }
1484
- if (devs.list.length < 1) {
1485
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Did Not Find Device ${deviceName}`, [], null, null, null);
1486
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1487
- return callback(null, errorObj);
1488
- }
1489
-
1490
- const callPromises = [];
1491
- for (let i = 0; i < this.allProps.devicebroker.getDevice.length; i += 1) {
1492
- // Perform component calls here.
1493
- callPromises.push(
1494
- new Promise((resolve, reject) => {
1495
- this.iapMakeBrokerCall('getDevice', this.allProps.devicebroker.getDevice[i], [devs.list[0]], [deviceName], (callRet, callErr) => {
1496
- // return an error
1497
- if (callErr) {
1498
- reject(callErr);
1499
- } else {
1500
- // return the data
1501
- resolve(callRet);
1502
- }
1503
- });
1504
- })
1505
- );
1506
- }
1075
+ return this.requestHandlerInst.isAlive(deviceName, callback);
1076
+ }
1507
1077
 
1508
- // return an array of repsonses
1509
- return Promise.all(callPromises).then((results) => {
1510
- let myResult = {};
1511
- results.forEach((result) => {
1512
- myResult = { ...myResult, ...result };
1513
- });
1078
+ /**
1079
+ * @summary Gets a config for the provided Appliance
1080
+ *
1081
+ * @function getConfig
1082
+ * @param {String} deviceName - the deviceName of the appliance. (required)
1083
+ * @param {String} format - the desired format of the config. (optional)
1084
+ *
1085
+ * @param {configCallback} callback - callback function to return the result
1086
+ * (appliance config) or the error
1087
+ */
1088
+ getConfig(deviceName, format, callback) {
1089
+ const origin = `${this.id}-adapterBase-getConfig`;
1090
+ log.trace(origin);
1514
1091
 
1515
- return callback(myResult, null);
1516
- });
1517
- });
1518
- } catch (ex) {
1519
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
1520
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1521
- return callback(null, errorObj);
1522
- }
1092
+ return this.requestHandlerInst.getConfig(deviceName, format, callback);
1523
1093
  }
1524
1094
 
1525
1095
  /**
1526
- * @summary Get Appliances that match the filter
1096
+ * @summary Gets the device count from the system
1527
1097
  *
1528
- * @function getDevicesFiltered
1529
- * @param {Object} options - the data to use to filter the appliances (optional)
1098
+ * @function iapGetDeviceCount
1530
1099
  *
1531
- * @param {getCallback} callback - a callback function to return the result
1532
- * (appliances) or the error
1100
+ * @param {getCallback} callback - callback function to return the result
1101
+ * (count) or the error
1533
1102
  */
1534
- getDevicesFiltered(options, callback) {
1535
- const meth = 'adapterBase-getDevicesFiltered';
1536
- const origin = `${this.id}-${meth}`;
1103
+ iapGetDeviceCount(callback) {
1104
+ const origin = `${this.id}-adapterBase-iapGetDeviceCount`;
1537
1105
  log.trace(origin);
1538
1106
 
1539
- // make sure we are set up for device broker getDevicesFiltered
1540
- if (!this.allProps.devicebroker || !this.allProps.devicebroker.getDevicesFiltered || this.allProps.devicebroker.getDevicesFiltered.length === 0 || !this.allProps.devicebroker.getDevicesFiltered[0].path) {
1541
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Properties', ['devicebroker.getDevicesFiltered.path'], null, null, null);
1542
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1543
- return callback(null, errorObj);
1544
- }
1107
+ return this.requestHandlerInst.iapGetDeviceCount(callback);
1108
+ }
1545
1109
 
1546
- // verify the required fields have been provided
1547
- if (options === undefined || options === null || options === '' || options.length === 0) {
1548
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['options'], null, null, null);
1549
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1550
- return callback(null, errorObj);
1551
- }
1552
- log.debug(`Device Filter Options: ${JSON.stringify(options)}`);
1110
+ /* ********************************************** */
1111
+ /* */
1112
+ /* EXPOSES GENERIC HANDLER */
1113
+ /* */
1114
+ /* ********************************************** */
1115
+ /**
1116
+ * Makes the requested generic call
1117
+ *
1118
+ * @function iapExpandedGenericAdapterRequest
1119
+ * @param {Object} metadata - metadata for the call (optional).
1120
+ * Can be a stringified Object.
1121
+ * @param {String} uriPath - the path of the api call - do not include the host, port, base path or version (optional)
1122
+ * @param {String} restMethod - the rest method (GET, POST, PUT, PATCH, DELETE) (optional)
1123
+ * @param {Object} pathVars - the parameters to be put within the url path (optional).
1124
+ * Can be a stringified Object.
1125
+ * @param {Object} queryData - the parameters to be put on the url (optional).
1126
+ * Can be a stringified Object.
1127
+ * @param {Object} requestBody - the body to add to the request (optional).
1128
+ * Can be a stringified Object.
1129
+ * @param {Object} addlHeaders - additional headers to be put on the call (optional).
1130
+ * Can be a stringified Object.
1131
+ * @param {getCallback} callback - a callback function to return the result (Generics)
1132
+ * or the error
1133
+ */
1134
+ iapExpandedGenericAdapterRequest(metadata, uriPath, restMethod, pathVars, queryData, requestBody, addlHeaders, callback) {
1135
+ const origin = `${this.myid}-adapterBase-iapExpandedGenericAdapterRequest`;
1136
+ log.trace(origin);
1553
1137
 
1554
- try {
1555
- // TODO - get pagination working
1556
- // const nextToken = options.start;
1557
- // const maxResults = options.limit;
1558
-
1559
- // set up the filter of Device Names
1560
- let filterName = [];
1561
- if (options && options.filter && options.filter.name) {
1562
- // when this hack is removed, remove the lint ignore above
1563
- if (Array.isArray(options.filter.name)) {
1564
- // eslint-disable-next-line prefer-destructuring
1565
- filterName = options.filter.name;
1566
- } else {
1567
- filterName = [options.filter.name];
1568
- }
1569
- }
1138
+ return this.requestHandlerInst.expandedGenericAdapterRequest(metadata, uriPath, restMethod, pathVars, queryData, requestBody, addlHeaders, callback);
1139
+ }
1570
1140
 
1571
- // TODO - get sort and order working
1572
- /*
1573
- if (options && options.sort) {
1574
- reqObj.uriOptions.sort = JSON.stringify(options.sort);
1575
- }
1576
- if (options && options.order) {
1577
- reqObj.uriOptions.order = options.order;
1578
- }
1579
- */
1580
- const callPromises = [];
1581
- for (let i = 0; i < this.allProps.devicebroker.getDevicesFiltered.length; i += 1) {
1582
- // Perform component calls here.
1583
- callPromises.push(
1584
- new Promise((resolve, reject) => {
1585
- this.iapMakeBrokerCall('getDevicesFiltered', this.allProps.devicebroker.getDevicesFiltered[i], [{ fake: 'fakedata' }], filterName, (callRet, callErr) => {
1586
- // return an error
1587
- if (callErr) {
1588
- reject(callErr);
1589
- } else {
1590
- // return the data
1591
- resolve(callRet);
1592
- }
1593
- });
1594
- })
1595
- );
1596
- }
1141
+ /**
1142
+ * Makes the requested generic call
1143
+ *
1144
+ * @function genericAdapterRequest
1145
+ * @param {String} uriPath - the path of the api call - do not include the host, port, base path or version (required)
1146
+ * @param {String} restMethod - the rest method (GET, POST, PUT, PATCH, DELETE) (required)
1147
+ * @param {Object} queryData - the parameters to be put on the url (optional).
1148
+ * Can be a stringified Object.
1149
+ * @param {Object} requestBody - the body to add to the request (optional).
1150
+ * Can be a stringified Object.
1151
+ * @param {Object} addlHeaders - additional headers to be put on the call (optional).
1152
+ * Can be a stringified Object.
1153
+ * @param {getCallback} callback - a callback function to return the result (Generics)
1154
+ * or the error
1155
+ */
1156
+ genericAdapterRequest(uriPath, restMethod, queryData, requestBody, addlHeaders, callback) {
1157
+ const origin = `${this.myid}-adapterBase-genericAdapterRequest`;
1158
+ log.trace(origin);
1597
1159
 
1598
- // return an array of repsonses
1599
- return Promise.all(callPromises).then((results) => {
1600
- let myResult = [];
1601
- results.forEach((result) => {
1602
- if (Array.isArray(result)) {
1603
- myResult = [...myResult, ...result];
1604
- } else if (Object.keys(result).length > 0) {
1605
- myResult.push(result);
1606
- }
1607
- });
1160
+ return this.requestHandlerInst.genericAdapterRequest(uriPath, restMethod, queryData, requestBody, addlHeaders, callback);
1161
+ }
1608
1162
 
1609
- log.debug(`${origin}: Found #${myResult.length} devices.`);
1610
- log.debug(`Devices: ${JSON.stringify(myResult)}`);
1611
- return callback({ total: myResult.length, list: myResult });
1612
- });
1613
- } catch (ex) {
1614
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
1615
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1616
- return callback(null, errorObj);
1617
- }
1163
+ /**
1164
+ * Makes the requested generic call with no base path or version
1165
+ *
1166
+ * @function genericAdapterRequestNoBasePath
1167
+ * @param {String} uriPath - the path of the api call - do not include the host, port, base path or version (required)
1168
+ * @param {String} restMethod - the rest method (GET, POST, PUT, PATCH, DELETE) (required)
1169
+ * @param {Object} queryData - the parameters to be put on the url (optional).
1170
+ * Can be a stringified Object.
1171
+ * @param {Object} requestBody - the body to add to the request (optional).
1172
+ * Can be a stringified Object.
1173
+ * @param {Object} addlHeaders - additional headers to be put on the call (optional).
1174
+ * Can be a stringified Object.
1175
+ * @param {getCallback} callback - a callback function to return the result (Generics)
1176
+ * or the error
1177
+ */
1178
+ genericAdapterRequestNoBasePath(uriPath, restMethod, queryData, requestBody, addlHeaders, callback) {
1179
+ const origin = `${this.myid}-adapterBase-genericAdapterRequestNoBasePath`;
1180
+ log.trace(origin);
1181
+
1182
+ return this.requestHandlerInst.genericAdapterRequestNoBasePath(uriPath, restMethod, queryData, requestBody, addlHeaders, callback);
1618
1183
  }
1619
1184
 
1185
+ /* ********************************************** */
1186
+ /* */
1187
+ /* EXPOSES INVENTORY CALLS */
1188
+ /* */
1189
+ /* ********************************************** */
1620
1190
  /**
1621
- * @summary Gets the status for the provided appliance
1191
+ * @summary run the adapter lint script to return the results.
1622
1192
  *
1623
- * @function isAlive
1624
- * @param {String} deviceName - the deviceName of the appliance. (required)
1193
+ * @function iapRunAdapterLint
1625
1194
  *
1626
- * @param {configCallback} callback - callback function to return the result
1627
- * (appliance isAlive) or the error
1195
+ * @return {Object} - containing the results of the lint call.
1628
1196
  */
1629
- isAlive(deviceName, callback) {
1630
- const meth = 'adapterBase-isAlive';
1197
+ iapRunAdapterLint(callback) {
1198
+ const meth = 'adapterBase-iapRunAdapterLint';
1631
1199
  const origin = `${this.id}-${meth}`;
1632
1200
  log.trace(origin);
1201
+ let command = null;
1633
1202
 
1634
- // make sure we are set up for device broker isAlive
1635
- if (!this.allProps.devicebroker || !this.allProps.devicebroker.isAlive || this.allProps.devicebroker.isAlive.length === 0 || !this.allProps.devicebroker.isAlive[0].path) {
1636
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Properties', ['devicebroker.isAlive.path'], null, null, null);
1637
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1638
- return callback(null, errorObj);
1639
- }
1203
+ if (fs.existsSync('package.json')) {
1204
+ const packageData = require('./package.json');
1640
1205
 
1641
- // verify the required fields have been provided
1642
- if (deviceName === undefined || deviceName === null || deviceName === '' || deviceName.length === 0) {
1643
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['deviceName'], null, null, null);
1644
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1645
- return callback(null, errorObj);
1646
- }
1647
-
1648
- try {
1649
- // need to get the device so we can convert the deviceName to an id
1650
- // !! if we can do a lookup by name the getDevicesFiltered may not be necessary
1651
- const opts = {
1652
- filter: {
1653
- name: deviceName
1654
- }
1655
- };
1656
- return this.getDevicesFiltered(opts, (devs, ferr) => {
1657
- // if we received an error or their is no response on the results return an error
1658
- if (ferr) {
1659
- return callback(null, ferr);
1660
- }
1661
- if (devs.list.length < 1) {
1662
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Did Not Find Device ${deviceName}`, [], null, null, null);
1663
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1664
- return callback(null, errorObj);
1665
- }
1666
-
1667
- const callPromises = [];
1668
- for (let i = 0; i < this.allProps.devicebroker.isAlive.length; i += 1) {
1669
- // Perform component calls here.
1670
- callPromises.push(
1671
- new Promise((resolve, reject) => {
1672
- this.iapMakeBrokerCall('isAlive', this.allProps.devicebroker.isAlive[i], [devs.list[0]], null, (callRet, callErr) => {
1673
- // return an error
1674
- if (callErr) {
1675
- reject(callErr);
1676
- } else {
1677
- // return the data
1678
- resolve(callRet);
1679
- }
1680
- });
1681
- })
1682
- );
1683
- }
1206
+ // check if 'test', 'test:unit', 'test:integration' exists in package.json file
1207
+ if (!packageData.scripts || !packageData.scripts['lint:errors']) {
1208
+ log.error('The required script does not exist in the package.json file');
1209
+ return callback(null, 'The required script does not exist in the package.json file');
1210
+ }
1684
1211
 
1685
- // return an array of repsonses
1686
- return Promise.all(callPromises).then((results) => {
1687
- let myResult = {};
1688
- results.forEach((result) => {
1689
- myResult = { ...myResult, ...result };
1690
- });
1212
+ // execute 'npm run lint:errors' command
1213
+ command = spawnSync('npm', ['run', 'lint:errors'], { cwd: __dirname, encoding: 'utf-8' });
1691
1214
 
1692
- let response = true;
1693
- if (myResult.isAlive !== null && myResult.isAlive !== undefined && myResult.isAlive === false) {
1694
- response = false;
1695
- }
1696
- return callback(response);
1697
- });
1698
- });
1699
- } catch (ex) {
1700
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
1701
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1702
- return callback(null, errorObj);
1215
+ // analyze and format the response
1216
+ const result = {
1217
+ status: 'SUCCESS'
1218
+ };
1219
+ if (command.status !== 0) {
1220
+ result.status = 'FAILED';
1221
+ result.output = command.stdout;
1222
+ }
1223
+ return callback(result);
1703
1224
  }
1225
+
1226
+ log.error('Package Not Found');
1227
+ return callback(null, 'Package Not Found');
1704
1228
  }
1705
1229
 
1706
1230
  /**
1707
- * @summary Gets a config for the provided Appliance
1231
+ * @summary run the adapter test scripts (baseunit and unit) to return the results.
1232
+ * can not run integration as there can be implications with that.
1708
1233
  *
1709
- * @function getConfig
1710
- * @param {String} deviceName - the deviceName of the appliance. (required)
1711
- * @param {String} format - the desired format of the config. (optional)
1234
+ * @function iapRunAdapterTests
1712
1235
  *
1713
- * @param {configCallback} callback - callback function to return the result
1714
- * (appliance config) or the error
1236
+ * @return {Object} - containing the results of the baseunit and unit tests.
1715
1237
  */
1716
- getConfig(deviceName, format, callback) {
1717
- const meth = 'adapterBase-getConfig';
1238
+ iapRunAdapterTests(callback) {
1239
+ const meth = 'adapterBase-iapRunAdapterTests';
1718
1240
  const origin = `${this.id}-${meth}`;
1719
1241
  log.trace(origin);
1242
+ let basecommand = null;
1243
+ let command = null;
1720
1244
 
1721
- // make sure we are set up for device broker getConfig
1722
- if (!this.allProps.devicebroker || !this.allProps.devicebroker.getConfig || this.allProps.devicebroker.getConfig.length === 0 || !this.allProps.devicebroker.getConfig[0].path) {
1723
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Properties', ['devicebroker.getConfig.path'], null, null, null);
1724
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1725
- return callback(null, errorObj);
1726
- }
1245
+ if (fs.existsSync('package.json')) {
1246
+ const packageData = require('./package.json');
1727
1247
 
1728
- // verify the required fields have been provided
1729
- if (deviceName === undefined || deviceName === null || deviceName === '' || deviceName.length === 0) {
1730
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['deviceName'], null, null, null);
1731
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1732
- return callback(null, errorObj);
1733
- }
1248
+ // check if 'test', 'test:unit', 'test:integration' exists in package.json file
1249
+ if (!packageData.scripts || !packageData.scripts['test:baseunit'] || !packageData.scripts['test:unit']) {
1250
+ log.error('The required scripts do not exist in the package.json file');
1251
+ return callback(null, 'The required scripts do not exist in the package.json file');
1252
+ }
1734
1253
 
1735
- try {
1736
- // need to get the device so we can convert the deviceName to an id
1737
- // !! if we can do a lookup by name the getDevicesFiltered may not be necessary
1738
- const opts = {
1739
- filter: {
1740
- name: deviceName
1741
- }
1254
+ // run baseunit test
1255
+ basecommand = spawnSync('npm', ['run', 'test:baseunit'], { cwd: __dirname, encoding: 'utf-8' });
1256
+
1257
+ // analyze and format the response to baseunit
1258
+ const baseresult = {
1259
+ status: 'SUCCESS'
1742
1260
  };
1743
- return this.getDevicesFiltered(opts, (devs, ferr) => {
1744
- // if we received an error or their is no response on the results return an error
1745
- if (ferr) {
1746
- return callback(null, ferr);
1747
- }
1748
- if (devs.list.length < 1) {
1749
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Did Not Find Device ${deviceName}`, [], null, null, null);
1750
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1751
- return callback(null, errorObj);
1752
- }
1261
+ if (basecommand.status !== 0) {
1262
+ baseresult.status = 'FAILED';
1263
+ baseresult.output = basecommand.stdout;
1264
+ }
1753
1265
 
1754
- const callPromises = [];
1755
- for (let i = 0; i < this.allProps.devicebroker.getConfig.length; i += 1) {
1756
- // Perform component calls here.
1757
- callPromises.push(
1758
- new Promise((resolve, reject) => {
1759
- this.iapMakeBrokerCall('getConfig', this.allProps.devicebroker.getConfig[i], [devs.list[0]], null, (callRet, callErr) => {
1760
- // return an error
1761
- if (callErr) {
1762
- reject(callErr);
1763
- } else {
1764
- // return the data
1765
- resolve(callRet);
1766
- }
1767
- });
1768
- })
1769
- );
1770
- }
1266
+ // run unit test
1267
+ command = spawnSync('npm', ['run', 'test:unit'], { cwd: __dirname, encoding: 'utf-8' });
1771
1268
 
1772
- // return an array of repsonses
1773
- return Promise.all(callPromises).then((results) => {
1774
- let myResult = {};
1775
- results.forEach((result) => {
1776
- if (typeof result === 'string') {
1777
- myResult = { ...myResult, result };
1778
- } else if (Array.isArray(result)) {
1779
- myResult = result[0];
1780
- } else {
1781
- myResult = { ...myResult, ...result };
1782
- }
1783
- });
1269
+ // analyze and format the response to unit
1270
+ const unitresult = {
1271
+ status: 'SUCCESS'
1272
+ };
1273
+ if (command.status !== 0) {
1274
+ unitresult.status = 'FAILED';
1275
+ unitresult.output = command.stdout;
1276
+ }
1784
1277
 
1785
- // return the result
1786
- const newResponse = {
1787
- response: JSON.stringify(myResult, null, 2)
1788
- };
1789
- return callback(newResponse, null);
1790
- });
1791
- });
1792
- } catch (ex) {
1793
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
1794
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1795
- return callback(null, errorObj);
1278
+ // format the response and return it
1279
+ const result = {
1280
+ base: baseresult,
1281
+ unit: unitresult
1282
+ };
1283
+ return callback(result);
1796
1284
  }
1285
+
1286
+ log.error('Package Not Found');
1287
+ return callback(null, 'Package Not Found');
1797
1288
  }
1798
1289
 
1799
1290
  /**
1800
- * @summary Gets the device count from the system
1291
+ * @summary provide inventory information abbout the adapter
1801
1292
  *
1802
- * @function iapGetDeviceCount
1293
+ * @function iapGetAdapterInventory
1803
1294
  *
1804
- * @param {getCallback} callback - callback function to return the result
1805
- * (count) or the error
1295
+ * @return {Object} - containing the adapter inventory information
1806
1296
  */
1807
- iapGetDeviceCount(callback) {
1808
- const meth = 'adapterBase-iapGetDeviceCount';
1297
+ iapGetAdapterInventory(callback) {
1298
+ const meth = 'adapterBase-iapGetAdapterInventory';
1809
1299
  const origin = `${this.id}-${meth}`;
1810
1300
  log.trace(origin);
1811
1301
 
1812
- // make sure we are set up for device broker getCount
1813
- if (!this.allProps.devicebroker || !this.allProps.devicebroker.getCount || this.allProps.devicebroker.getCount.length === 0 || !this.allProps.devicebroker.getCount[0].path) {
1814
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Properties', ['devicebroker.getCount.path'], null, null, null);
1815
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1816
- return callback(null, errorObj);
1817
- }
1818
-
1819
- // verify the required fields have been provided
1820
-
1821
1302
  try {
1822
- const callPromises = [];
1823
- for (let i = 0; i < this.allProps.devicebroker.getCount.length; i += 1) {
1824
- // Perform component calls here.
1825
- callPromises.push(
1826
- new Promise((resolve, reject) => {
1827
- this.iapMakeBrokerCall('getCount', this.allProps.devicebroker.getCount[i], [{ fake: 'fakedata' }], null, (callRet, callErr) => {
1828
- // return an error
1829
- if (callErr) {
1830
- reject(callErr);
1831
- } else {
1832
- // return the data
1833
- resolve(callRet);
1834
- }
1835
- });
1836
- })
1837
- );
1838
- }
1303
+ // call to the adapter utils to get inventory
1304
+ return this.requestHandlerInst.getAdapterInventory((res, error) => {
1305
+ const adapterInv = res;
1306
+
1307
+ // get all of the tasks
1308
+ const allTasks = this.getAllFunctions();
1309
+ adapterInv.totalTasks = allTasks.length;
1310
+
1311
+ // get all of the possible workflow tasks
1312
+ const myIgnore = [
1313
+ 'healthCheck',
1314
+ 'iapGetAdapterWorkflowFunctions',
1315
+ 'hasEntities'
1316
+ ];
1317
+ adapterInv.totalWorkflowTasks = this.iapGetAdapterWorkflowFunctions(myIgnore).length;
1318
+
1319
+ // TODO: CACHE
1320
+ // CONFIRM CACHE
1321
+ // GET CACHE ENTITIES
1322
+
1323
+ // get the Device Count
1324
+ return this.iapGetDeviceCount((devres, deverror) => {
1325
+ // if call failed assume not broker integrated
1326
+ if (deverror) {
1327
+ adapterInv.brokerDefined = false;
1328
+ adapterInv.deviceCount = -1;
1329
+ } else {
1330
+ // broker confirmed
1331
+ adapterInv.brokerDefined = true;
1332
+ adapterInv.deviceCount = 0;
1333
+ if (devres && devres.count) {
1334
+ adapterInv.deviceCount = devres.count;
1335
+ }
1336
+ }
1839
1337
 
1840
- // return an array of repsonses
1841
- return Promise.all(callPromises).then((results) => {
1842
- let myResult = {};
1843
- results.forEach((result) => {
1844
- myResult = { ...myResult, ...result };
1338
+ return callback(adapterInv);
1845
1339
  });
1846
-
1847
- // return the result
1848
- return callback({ count: Object.keys(myResult).length });
1849
1340
  });
1850
1341
  } catch (ex) {
1851
1342
  const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);