@itentialopensource/adapter-meraki 1.0.4 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
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);