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