@itentialopensource/adapter-openstack_neutron 3.0.3 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/AUTH.md +9 -9
  2. package/CALLS.md +364 -328
  3. package/CHANGELOG.md +8 -0
  4. package/CONTRIBUTING.md +1 -160
  5. package/ENHANCE.md +2 -2
  6. package/README.md +32 -23
  7. package/adapter.js +174 -373
  8. package/adapterBase.js +517 -875
  9. package/changelogs/CHANGELOG.md +58 -0
  10. package/metadata.json +56 -0
  11. package/package.json +24 -26
  12. package/pronghorn.json +474 -142
  13. package/propertiesSchema.json +431 -34
  14. package/refs?service=git-upload-pack +0 -0
  15. package/report/adapter-openapi.json +14594 -0
  16. package/report/adapter-openapi.yaml +12289 -0
  17. package/report/adapterInfo.json +8 -8
  18. package/report/updateReport1691507382282.json +120 -0
  19. package/report/updateReport1692202417483.json +120 -0
  20. package/report/updateReport1694460523394.json +120 -0
  21. package/report/updateReport1698420447048.json +120 -0
  22. package/sampleProperties.json +58 -3
  23. package/test/integration/adapterTestBasicGet.js +2 -4
  24. package/test/integration/adapterTestConnectivity.js +91 -42
  25. package/test/integration/adapterTestIntegration.js +130 -2
  26. package/test/unit/adapterBaseTestUnit.js +389 -317
  27. package/test/unit/adapterTestUnit.js +303 -114
  28. package/utils/adapterInfo.js +1 -1
  29. package/utils/addAuth.js +1 -1
  30. package/utils/artifactize.js +1 -1
  31. package/utils/checkMigrate.js +1 -1
  32. package/utils/entitiesToDB.js +2 -2
  33. package/utils/findPath.js +1 -1
  34. package/utils/methodDocumentor.js +71 -23
  35. package/utils/modify.js +13 -15
  36. package/utils/packModificationScript.js +1 -1
  37. package/utils/taskMover.js +309 -0
  38. package/utils/tbScript.js +89 -34
  39. package/utils/tbUtils.js +41 -21
  40. package/utils/testRunner.js +1 -1
  41. package/utils/troubleshootingAdapter.js +9 -6
  42. package/workflows/README.md +0 -3
package/adapterBase.js CHANGED
@@ -11,14 +11,18 @@
11
11
  /* eslint prefer-destructuring: warn */
12
12
 
13
13
  /* Required libraries. */
14
- const fs = require('fs-extra');
15
14
  const path = require('path');
16
- const jsonQuery = require('json-query');
17
- const EventEmitterCl = require('events').EventEmitter;
18
15
  const { execSync } = require('child_process');
16
+ const { spawnSync } = require('child_process');
17
+ const EventEmitterCl = require('events').EventEmitter;
18
+ const fs = require('fs-extra');
19
+ const jsonQuery = require('json-query');
20
+
21
+ const sampleProperties = require(`${__dirname}/sampleProperties.json`).properties;
19
22
 
20
23
  /* The schema validator */
21
24
  const AjvCl = require('ajv');
25
+ const { Test } = require('mocha');
22
26
 
23
27
  /* Fetch in the other needed components for the this Adaptor */
24
28
  const PropUtilCl = require('@itentialopensource/adapter-utils').PropertyUtility;
@@ -27,6 +31,7 @@ const RequestHandlerCl = require('@itentialopensource/adapter-utils').RequestHan
27
31
  const entitiesToDB = require(path.join(__dirname, 'utils/entitiesToDB'));
28
32
  const troubleshootingAdapter = require(path.join(__dirname, 'utils/troubleshootingAdapter'));
29
33
  const tbUtils = require(path.join(__dirname, 'utils/tbUtils'));
34
+ const taskMover = require(path.join(__dirname, 'utils/taskMover'));
30
35
 
31
36
  let propUtil = null;
32
37
  let choosepath = null;
@@ -102,7 +107,7 @@ function updateSchema(entityPath, configFile, changes) {
102
107
  /*
103
108
  * INTERNAL FUNCTION: update the mock data file
104
109
  */
105
- function updateMock(mockPath, configFile, changes) {
110
+ function updateMock(mockPath, configFile, changes, replace) {
106
111
  // if the mock file does not exist - create it
107
112
  const mockFile = path.join(mockPath, `/${configFile}`);
108
113
  if (!fs.existsSync(mockFile)) {
@@ -114,7 +119,11 @@ function updateMock(mockPath, configFile, changes) {
114
119
  let mock = require(path.resolve(mockPath, configFile));
115
120
 
116
121
  // merge the changes into the mock file
117
- mock = propUtil.mergeProperties(changes, mock);
122
+ if (replace === true) {
123
+ mock = changes;
124
+ } else {
125
+ mock = propUtil.mergeProperties(changes, mock);
126
+ }
118
127
 
119
128
  fs.writeFileSync(mockFile, JSON.stringify(mock, null, 2));
120
129
  return null;
@@ -146,27 +155,6 @@ function updatePackage(changes) {
146
155
  return null;
147
156
  }
148
157
 
149
- /*
150
- * INTERNAL FUNCTION: get data from source(s) - nested
151
- */
152
- function getDataFromSources(loopField, sources) {
153
- let fieldValue = loopField;
154
-
155
- // go through the sources to find the field
156
- for (let s = 0; s < sources.length; s += 1) {
157
- // find the field value using jsonquery
158
- const nestedValue = jsonQuery(loopField, { data: sources[s] }).value;
159
-
160
- // if we found in source - set and no need to check other sources
161
- if (nestedValue) {
162
- fieldValue = nestedValue;
163
- break;
164
- }
165
- }
166
-
167
- return fieldValue;
168
- }
169
-
170
158
  /* GENERAL ADAPTER FUNCTIONS THESE SHOULD NOT BE DIRECTLY MODIFIED */
171
159
  /* IF YOU NEED MODIFICATIONS, REDEFINE THEM IN adapter.js!!! */
172
160
  class AdapterBase extends EventEmitterCl {
@@ -256,7 +244,7 @@ class AdapterBase extends EventEmitterCl {
256
244
  this.allProps = this.propUtilInst.mergeProperties(properties, defProps);
257
245
 
258
246
  // validate the entity against the schema
259
- const ajvInst = new AjvCl();
247
+ const ajvInst = new AjvCl({ strictSchema: false, allowUnionTypes: true });
260
248
  const validate = ajvInst.compile(propertiesSchema);
261
249
  const result = validate(this.allProps);
262
250
 
@@ -434,6 +422,40 @@ class AdapterBase extends EventEmitterCl {
434
422
  return myfunctions;
435
423
  }
436
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
+
437
459
  /**
438
460
  * checkActionFiles is used to update the validation of the action files.
439
461
  *
@@ -489,40 +511,6 @@ class AdapterBase extends EventEmitterCl {
489
511
  return this.requestHandlerInst.encryptProperty(property, technique, callback);
490
512
  }
491
513
 
492
- /**
493
- * iapGetAdapterWorkflowFunctions is used to get all of the workflow function in the adapter
494
- * @param {array} ignoreThese - additional methods to ignore (optional)
495
- *
496
- * @function iapGetAdapterWorkflowFunctions
497
- */
498
- iapGetAdapterWorkflowFunctions(ignoreThese) {
499
- const myfunctions = this.getAllFunctions();
500
- const wffunctions = [];
501
-
502
- // remove the functions that should not be in a Workflow
503
- for (let m = 0; m < myfunctions.length; m += 1) {
504
- if (myfunctions[m] === 'addEntityCache') {
505
- // got to the second tier (adapterBase)
506
- break;
507
- }
508
- if (!(myfunctions[m].endsWith('Emit') || myfunctions[m].match(/Emit__v[0-9]+/))) {
509
- let found = false;
510
- if (ignoreThese && Array.isArray(ignoreThese)) {
511
- for (let i = 0; i < ignoreThese.length; i += 1) {
512
- if (myfunctions[m].toUpperCase() === ignoreThese[i].toUpperCase()) {
513
- found = true;
514
- }
515
- }
516
- }
517
- if (!found) {
518
- wffunctions.push(myfunctions[m]);
519
- }
520
- }
521
- }
522
-
523
- return wffunctions;
524
- }
525
-
526
514
  /**
527
515
  * iapUpdateAdapterConfiguration is used to update any of the adapter configuration files. This
528
516
  * allows customers to make changes to adapter configuration without having to be on the
@@ -534,16 +522,17 @@ class AdapterBase extends EventEmitterCl {
534
522
  * @param {string} entity - the entity to be changed, if an action, schema or mock data file (optional)
535
523
  * @param {string} type - the type of entity file to change, (action, schema, mock) (optional)
536
524
  * @param {string} action - the action to be changed, if an action, schema or mock data file (optional)
525
+ * @param {boolean} replace - true to replace entire mock data, false to merge/append (optional)
537
526
  * @param {Callback} callback - The results of the call
538
527
  */
539
- iapUpdateAdapterConfiguration(configFile, changes, entity, type, action, callback) {
528
+ iapUpdateAdapterConfiguration(configFile, changes, entity, type, action, replace, callback) {
540
529
  const meth = 'adapterBase-iapUpdateAdapterConfiguration';
541
530
  const origin = `${this.id}-${meth}`;
542
531
  log.trace(origin);
543
532
 
544
533
  // verify the parameters are valid
545
534
  if (changes === undefined || changes === null || typeof changes !== 'object'
546
- || Object.keys(changes).length === 0) {
535
+ || Object.keys(changes).length === 0) {
547
536
  const result = {
548
537
  response: 'No configuration updates to make'
549
538
  };
@@ -628,8 +617,14 @@ class AdapterBase extends EventEmitterCl {
628
617
  if (!fs.existsSync(mpath)) {
629
618
  fs.mkdirSync(mpath);
630
619
  }
620
+ // this means we are changing a mock data file so replace is required
621
+ if (replace === undefined || replace === null || replace === '') {
622
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['replace'], null, null, null);
623
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
624
+ return callback(null, errorObj);
625
+ }
626
+ const mres = updateMock(mpath, configFile, changes, replace);
631
627
 
632
- const mres = updateMock(mpath, configFile, changes);
633
628
  if (mres) {
634
629
  const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Incomplete Configuration Change: ${mres}`, [], null, null, null);
635
630
  log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
@@ -646,6 +641,86 @@ class AdapterBase extends EventEmitterCl {
646
641
  return callback(null, errorObj);
647
642
  }
648
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
+ /* ********************************************** */
649
724
  /**
650
725
  * See if the API path provided is found in this adapter
651
726
  *
@@ -665,6 +740,7 @@ class AdapterBase extends EventEmitterCl {
665
740
  result.message = 'NO PATH PROVIDED!';
666
741
  return callback(null, result);
667
742
  }
743
+
668
744
  if (typeof this.allProps.choosepath === 'string') {
669
745
  choosepath = this.allProps.choosepath;
670
746
  }
@@ -750,81 +826,6 @@ class AdapterBase extends EventEmitterCl {
750
826
  return callback(result, null);
751
827
  }
752
828
 
753
- /**
754
- * @summary Suspends the adapter
755
- * @param {Callback} callback - The adapater suspension status
756
- * @function iapSuspendAdapter
757
- */
758
- iapSuspendAdapter(mode, callback) {
759
- const origin = `${this.id}-adapterBase-iapSuspendAdapter`;
760
- if (this.suspended) {
761
- throw new Error(`${origin}: Adapter is already suspended`);
762
- }
763
- try {
764
- this.suspended = true;
765
- this.suspendMode = mode;
766
- if (this.suspendMode === 'pause') {
767
- const props = JSON.parse(JSON.stringify(this.initProps));
768
- // To suspend adapter, enable throttling and set concurrent max to 0
769
- props.throttle.throttle_enabled = true;
770
- props.throttle.concurrent_max = 0;
771
- this.refreshProperties(props);
772
- }
773
- return callback({ suspended: true });
774
- } catch (error) {
775
- return callback(null, error);
776
- }
777
- }
778
-
779
- /**
780
- * @summary Unsuspends the adapter
781
- * @param {Callback} callback - The adapater suspension status
782
- *
783
- * @function iapUnsuspendAdapter
784
- */
785
- iapUnsuspendAdapter(callback) {
786
- const origin = `${this.id}-adapterBase-iapUnsuspendAdapter`;
787
- if (!this.suspended) {
788
- throw new Error(`${origin}: Adapter is not suspended`);
789
- }
790
- if (this.suspendMode === 'pause') {
791
- const props = JSON.parse(JSON.stringify(this.initProps));
792
- // To unsuspend adapter, keep throttling enabled and begin processing queued requests in order
793
- props.throttle.throttle_enabled = true;
794
- props.throttle.concurrent_max = 1;
795
- this.refreshProperties(props);
796
- setTimeout(() => {
797
- this.getQueue((q, error) => {
798
- // console.log("Items in queue: " + String(q.length))
799
- if (q.length === 0) {
800
- // if queue is empty, return to initial properties state
801
- this.refreshProperties(this.initProps);
802
- this.suspended = false;
803
- return callback({ suspended: false });
804
- }
805
- // recursive call to check queue again every second
806
- return this.iapUnsuspendAdapter(callback);
807
- });
808
- }, 1000);
809
- } else {
810
- this.suspended = false;
811
- callback({ suspend: false });
812
- }
813
- }
814
-
815
- /**
816
- * iapGetAdapterQueue is used to get information for all of the requests currently in the queue.
817
- *
818
- * @function iapGetAdapterQueue
819
- * @param {Callback} callback - a callback function to return the result (Queue) or the error
820
- */
821
- iapGetAdapterQueue(callback) {
822
- const origin = `${this.id}-adapterBase-iapGetAdapterQueue`;
823
- log.trace(origin);
824
-
825
- return this.requestHandlerInst.getQueue(callback);
826
- }
827
-
828
829
  /**
829
830
  * @summary runs troubleshoot scripts for adapter
830
831
  *
@@ -859,7 +860,7 @@ class AdapterBase extends EventEmitterCl {
859
860
  if (result) {
860
861
  return callback(result);
861
862
  }
862
- return callback(null, result);
863
+ return callback(null, 'Healthcheck failed');
863
864
  } catch (error) {
864
865
  return callback(null, error);
865
866
  }
@@ -874,8 +875,7 @@ class AdapterBase extends EventEmitterCl {
874
875
  */
875
876
  async iapRunAdapterConnectivity(callback) {
876
877
  try {
877
- const { serviceItem } = await tbUtils.getAdapterConfig();
878
- const { host } = serviceItem.properties.properties;
878
+ const { host } = this.allProps;
879
879
  const result = tbUtils.runConnectivity(host, false);
880
880
  if (result.failCount > 0) {
881
881
  return callback(null, result);
@@ -927,156 +927,89 @@ class AdapterBase extends EventEmitterCl {
927
927
  }
928
928
 
929
929
  /**
930
- * @summary take the entities and add them to the cache
931
- *
932
- * @function addEntityCache
933
- * @param {String} entityType - the type of the entities
934
- * @param {Array} data - the list of entities
935
- * @param {String} key - unique key for the entities
930
+ * @function iapDeactivateTasks
936
931
  *
937
- * @param {Callback} callback - An array of whether the adapter can has the
938
- * desired capability or an error
932
+ * @param {Array} tasks - List of tasks to deactivate
933
+ * @param {Callback} callback
939
934
  */
940
- addEntityCache(entityType, entities, key, callback) {
941
- const meth = 'adapterBase-addEntityCache';
935
+ iapDeactivateTasks(tasks, callback) {
936
+ const meth = 'adapterBase-iapDeactivateTasks';
942
937
  const origin = `${this.id}-${meth}`;
943
938
  log.trace(origin);
944
-
945
- // list containing the items to add to the cache
946
- const entityIds = [];
947
-
948
- if (entities && Object.hasOwnProperty.call(entities, 'response')
949
- && Array.isArray(entities.response)) {
950
- for (let e = 0; e < entities.response.length; e += 1) {
951
- entityIds.push(entities.response[e][key]);
952
- }
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);
953
946
  }
954
-
955
- // add the entities to the cache
956
- return this.requestHandlerInst.addEntityCache(entityType, entityIds, (loaded, error) => {
957
- if (error) {
958
- return callback(null, error);
959
- }
960
- if (!loaded) {
961
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Entity Cache Not Loading', [entityType], null, null, null);
962
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
963
- return callback(null, errorObj);
964
- }
965
-
966
- return callback(loaded);
967
- });
947
+ taskMover.deleteBackups(__dirname);
948
+ return callback(data, null);
968
949
  }
969
950
 
970
951
  /**
971
- * @summary sees if the entity is in the entity list or not
972
- *
973
- * @function entityInList
974
- * @param {String/Array} entityId - the specific entity we are looking for
975
- * @param {Array} data - the list of entities
952
+ * @function iapActivateTasks
976
953
  *
977
- * @param {Callback} callback - An array of whether the adapter can has the
978
- * desired capability or an error
954
+ * @param {Array} tasks - List of tasks to deactivate
955
+ * @param {Callback} callback
979
956
  */
980
- entityInList(entityId, data) {
981
- const origin = `${this.id}-adapterBase-entityInList`;
957
+ iapActivateTasks(tasks, callback) {
958
+ const meth = 'adapterBase-iapActivateTasks';
959
+ const origin = `${this.id}-${meth}`;
982
960
  log.trace(origin);
983
-
984
- // need to check on the entities that were passed in
985
- if (Array.isArray(entityId)) {
986
- const resEntity = [];
987
-
988
- for (let e = 0; e < entityId.length; e += 1) {
989
- if (data.includes(entityId[e])) {
990
- resEntity.push(true);
991
- } else {
992
- resEntity.push(false);
993
- }
994
- }
995
-
996
- 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);
997
968
  }
998
-
999
- // does the entity list include the specific entity
1000
- return [data.includes(entityId)];
969
+ taskMover.deleteBackups(__dirname);
970
+ return callback(data, null);
1001
971
  }
1002
972
 
973
+ /* ********************************************** */
974
+ /* */
975
+ /* EXPOSES CACHE CALLS */
976
+ /* */
977
+ /* ********************************************** */
1003
978
  /**
1004
- * @summary prepare results for verify capability so they are true/false
1005
- *
1006
- * @function capabilityResults
1007
- * @param {Array} results - the results from the capability check
979
+ * @summary Populate the cache for the given entities
1008
980
  *
1009
- * @param {Callback} callback - An array of whether the adapter can has the
1010
- * 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
1011
985
  */
1012
- capabilityResults(results, callback) {
1013
- const meth = 'adapterBase-capabilityResults';
1014
- const origin = `${this.id}-${meth}`;
986
+ iapPopulateEntityCache(entityTypes, callback) {
987
+ const origin = `${this.myid}-adapterBase-iapPopulateEntityCache`;
1015
988
  log.trace(origin);
1016
- let locResults = results;
1017
-
1018
- if (locResults && locResults[0] === 'needupdate') {
1019
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Entity Cache Not Loading', ['unknown'], null, null, null);
1020
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1021
- this.repeatCacheCount += 1;
1022
- return callback(null, errorObj);
1023
- }
1024
-
1025
- // if an error occured, return the error
1026
- if (locResults && locResults[0] === 'error') {
1027
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Error Verifying Entity Cache', null, null, null, null);
1028
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1029
- return callback(null, errorObj);
1030
- }
1031
-
1032
- // go through the response and change to true/false
1033
- if (locResults) {
1034
- // if not an array, just convert the return
1035
- if (!Array.isArray(locResults)) {
1036
- if (locResults === 'found') {
1037
- locResults = [true];
1038
- } else {
1039
- locResults = [false];
1040
- }
1041
- } else {
1042
- const temp = [];
1043
989
 
1044
- // go through each element in the array to convert
1045
- for (let r = 0; r < locResults.length; r += 1) {
1046
- if (locResults[r] === 'found') {
1047
- temp.push(true);
1048
- } else {
1049
- temp.push(false);
1050
- }
1051
- }
1052
- locResults = temp;
1053
- }
1054
- }
1055
-
1056
- // return the results
1057
- return callback(locResults);
990
+ return this.requestHandlerInst.populateEntityCache(entityTypes, callback);
1058
991
  }
1059
992
 
1060
993
  /**
1061
- * @summary Provides a way for the adapter to tell north bound integrations
1062
- * all of the capabilities for the current adapter
994
+ * @summary Retrieves data from cache for specified entity type
1063
995
  *
1064
- * @function getAllCapabilities
1065
- *
1066
- * @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
1067
1000
  */
1068
- getAllCapabilities() {
1069
- const origin = `${this.id}-adapterBase-getAllCapabilities`;
1001
+ iapRetrieveEntitiesCache(entityType, options, callback) {
1002
+ const origin = `${this.myid}-adapterBase-iapRetrieveEntitiesCache`;
1070
1003
  log.trace(origin);
1071
1004
 
1072
- // validate the capabilities for the adapter
1073
- try {
1074
- return this.requestHandlerInst.getAllCapabilities();
1075
- } catch (e) {
1076
- return [];
1077
- }
1005
+ return this.requestHandlerInst.retrieveEntitiesCache(entityType, options, callback);
1078
1006
  }
1079
1007
 
1008
+ /* ********************************************** */
1009
+ /* */
1010
+ /* EXPOSES BROKER CALLS */
1011
+ /* */
1012
+ /* ********************************************** */
1080
1013
  /**
1081
1014
  * @summary Determines if this adapter supports any in a list of entities
1082
1015
  *
@@ -1088,396 +1021,61 @@ class AdapterBase extends EventEmitterCl {
1088
1021
  * value is true or false
1089
1022
  */
1090
1023
  hasEntities(entityType, entityList, callback) {
1091
- const origin = `${this.id}-adapter-hasEntities`;
1024
+ const origin = `${this.id}-adapterBase-hasEntities`;
1092
1025
  log.trace(origin);
1093
1026
 
1094
- switch (entityType) {
1095
- case 'Device':
1096
- return this.hasDevices(entityList, callback);
1097
- default:
1098
- return callback(null, `${this.id} does not support entity ${entityType}`);
1099
- }
1027
+ return this.requestHandlerInst.hasEntities(entityType, entityList, callback);
1100
1028
  }
1101
1029
 
1102
1030
  /**
1103
- * @summary Helper method for hasEntities for the specific device case
1031
+ * @summary Determines if this adapter supports any in a list of entities
1104
1032
  *
1105
- * @param {Array} deviceList - array of unique device identifiers
1106
- * @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
1107
1039
  * value is true or false
1108
1040
  */
1109
- hasDevices(deviceList, callback) {
1110
- const origin = `${this.id}-adapter-hasDevices`;
1041
+ hasEntitiesAuth(entityType, entityList, callOptions, callback) {
1042
+ const origin = `${this.id}-adapterBase-hasEntitiesAuth`;
1111
1043
  log.trace(origin);
1112
1044
 
1113
- const findings = deviceList.reduce((map, device) => {
1114
- // eslint-disable-next-line no-param-reassign
1115
- map[device] = false;
1116
- log.debug(`In reduce: ${JSON.stringify(map)}`);
1117
- return map;
1118
- }, {});
1119
- const apiCalls = deviceList.map((device) => new Promise((resolve) => {
1120
- this.getDevice(device, (result, error) => {
1121
- if (error) {
1122
- log.debug(`In map error: ${JSON.stringify(device)}`);
1123
- return resolve({ name: device, found: false });
1124
- }
1125
- log.debug(`In map: ${JSON.stringify(device)}`);
1126
- return resolve({ name: device, found: true });
1127
- });
1128
- }));
1129
- Promise.all(apiCalls).then((results) => {
1130
- results.forEach((device) => {
1131
- findings[device.name] = device.found;
1132
- });
1133
- log.debug(`FINDINGS: ${JSON.stringify(findings)}`);
1134
- return callback(findings);
1135
- }).catch((errors) => {
1136
- log.error('Unable to do device lookup.');
1137
- return callback(null, { code: 503, message: 'Unable to do device lookup.', error: errors });
1138
- });
1045
+ return this.requestHandlerInst.hasEntitiesAuth(entityType, entityList, callOptions, callback);
1139
1046
  }
1140
1047
 
1141
1048
  /**
1142
- * @summary Make one of the needed Broker calls - could be one of many
1049
+ * @summary Get Appliance that match the deviceName
1143
1050
  *
1144
- * @function iapMakeBrokerCall
1145
- * @param {string} brokCall - the name of the broker call (required)
1146
- * @param {object} callProps - the proeprties for the broker call (required)
1147
- * @param {object} devResp - the device details to extract needed inputs (required)
1148
- * @param {string} filterName - any filter to search on (required)
1051
+ * @function getDevice
1052
+ * @param {String} deviceName - the deviceName to find (required)
1149
1053
  *
1150
- * @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
1151
1056
  */
1152
- iapMakeBrokerCall(brokCall, callProps, devResp, filterName, callback) {
1153
- const meth = 'adapterBase-iapMakeBrokerCall';
1154
- const origin = `${this.id}-${meth}`;
1057
+ getDevice(deviceName, callback) {
1058
+ const origin = `${this.id}-adapterBase-getDevice`;
1155
1059
  log.trace(origin);
1156
1060
 
1157
- try {
1158
- let uriPath = '';
1159
- let uriMethod = 'GET';
1160
- let callQuery = {};
1161
- let callBody = {};
1162
- let callHeaders = {};
1163
- let handleFail = 'fail';
1164
- let ostypePrefix = '';
1165
- let statusValue = 'true';
1166
- if (callProps.path) {
1167
- uriPath = `${callProps.path}`;
1168
-
1169
- // make any necessary changes to the path
1170
- if (devResp !== null && callProps.requestFields && Object.keys(callProps.requestFields).length > 0) {
1171
- const rqKeys = Object.keys(callProps.requestFields);
1172
-
1173
- // get the field from the provided device
1174
- for (let rq = 0; rq < rqKeys.length; rq += 1) {
1175
- const fieldValue = getDataFromSources(callProps.requestFields[rqKeys[rq]], devResp);
1176
-
1177
- // put the value into the path - if it has been specified in the path
1178
- uriPath = uriPath.replace(`{${rqKeys[rq]}}`, fieldValue);
1179
- }
1180
- }
1181
- }
1182
- if (callProps.method) {
1183
- uriMethod = callProps.method;
1184
- }
1185
- if (callProps.query) {
1186
- callQuery = callProps.query;
1187
-
1188
- // go through the query params to check for variable values
1189
- const cpKeys = Object.keys(callQuery);
1190
- for (let cp = 0; cp < cpKeys.length; cp += 1) {
1191
- if (callQuery[cpKeys[cp]].startsWith('{') && callQuery[cpKeys[cp]].endsWith('}')) {
1192
- // make any necessary changes to the query params
1193
- if (devResp !== null && callProps.requestFields && Object.keys(callProps.requestFields).length > 0) {
1194
- const rqKeys = Object.keys(callProps.requestFields);
1195
-
1196
- // get the field from the provided device
1197
- for (let rq = 0; rq < rqKeys.length; rq += 1) {
1198
- if (cpKeys[cp] === rqKeys[rq]) {
1199
- const fieldValue = getDataFromSources(callProps.requestFields[rqKeys[rq]], devResp);
1200
-
1201
- // put the value into the query - if it has been specified in the query
1202
- callQuery[cpKeys[cp]] = fieldValue;
1203
- }
1204
- }
1205
- }
1206
- }
1207
- }
1208
- }
1209
- if (callProps.body) {
1210
- callBody = callProps.body;
1211
-
1212
- // go through the body fields to check for variable values
1213
- const cbKeys = Object.keys(callBody);
1214
- for (let cb = 0; cb < cbKeys.length; cb += 1) {
1215
- if (callBody[cbKeys[cb]].startsWith('{') && callBody[cbKeys[cb]].endsWith('}')) {
1216
- // make any necessary changes to the query params
1217
- if (devResp !== null && callProps.requestFields && Object.keys(callProps.requestFields).length > 0) {
1218
- const rqKeys = Object.keys(callProps.requestFields);
1219
-
1220
- // get the field from the provided device
1221
- for (let rq = 0; rq < rqKeys.length; rq += 1) {
1222
- if (cbKeys[cb] === rqKeys[rq]) {
1223
- const fieldValue = getDataFromSources(callProps.requestFields[rqKeys[rq]], devResp);
1224
-
1225
- // put the value into the query - if it has been specified in the query
1226
- callBody[cbKeys[cb]] = fieldValue;
1227
- }
1228
- }
1229
- }
1230
- }
1231
- }
1232
- }
1233
- if (callProps.headers) {
1234
- callHeaders = callProps.headers;
1235
-
1236
- // go through the body fields to check for variable values
1237
- const chKeys = Object.keys(callHeaders);
1238
- for (let ch = 0; ch < chKeys.length; ch += 1) {
1239
- if (callHeaders[chKeys[ch]].startsWith('{') && callHeaders[chKeys[ch]].endsWith('}')) {
1240
- // make any necessary changes to the query params
1241
- if (devResp !== null && callProps.requestFields && Object.keys(callProps.requestFields).length > 0) {
1242
- const rqKeys = Object.keys(callProps.requestFields);
1243
-
1244
- // get the field from the provided device
1245
- for (let rq = 0; rq < rqKeys.length; rq += 1) {
1246
- if (chKeys[ch] === rqKeys[rq]) {
1247
- const fieldValue = getDataFromSources(callProps.requestFields[rqKeys[rq]], devResp);
1248
-
1249
- // put the value into the query - if it has been specified in the query
1250
- callHeaders[chKeys[ch]] = fieldValue;
1251
- }
1252
- }
1253
- }
1254
- }
1255
- }
1256
- }
1257
- if (callProps.handleFailure) {
1258
- handleFail = callProps.handleFailure;
1259
- }
1260
- if (callProps.responseFields && callProps.responseFields.ostypePrefix) {
1261
- ostypePrefix = callProps.responseFields.ostypePrefix;
1262
- }
1263
- if (callProps.responseFields && callProps.responseFields.statusValue) {
1264
- statusValue = callProps.responseFields.statusValue;
1265
- }
1266
-
1267
- // !! using Generic makes it easier on the Adapter Builder (just need to change the path)
1268
- // !! you can also replace with a specific call if that is easier
1269
- return this.genericAdapterRequest(uriPath, uriMethod, callQuery, callBody, callHeaders, (result, error) => {
1270
- // if we received an error or their is no response on the results return an error
1271
- if (error) {
1272
- if (handleFail === 'fail') {
1273
- return callback(null, error);
1274
- }
1275
- return callback({}, null);
1276
- }
1277
- if (!result.response) {
1278
- if (handleFail === 'fail') {
1279
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Invalid Response', [brokCall], null, null, null);
1280
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1281
- return callback(null, errorObj);
1282
- }
1283
- return callback({}, null);
1284
- }
1285
-
1286
- // get the response piece we care about from the response
1287
- const myResult = result;
1288
- if (callProps.responseDatakey) {
1289
- myResult.response = jsonQuery(callProps.responseDatakey, { data: myResult.response }).value;
1290
- }
1291
-
1292
- // get the keys for the response fields
1293
- let rfKeys = [];
1294
- if (callProps.responseFields && Object.keys(callProps.responseFields).length > 0) {
1295
- rfKeys = Object.keys(callProps.responseFields);
1296
- }
1297
-
1298
- // if we got an array returned (e.g. getDevicesFitered)
1299
- if (Array.isArray(myResult.response)) {
1300
- const listDevices = [];
1301
- for (let a = 0; a < myResult.response.length; a += 1) {
1302
- const thisDevice = myResult.response[a];
1303
- for (let rf = 0; rf < rfKeys.length; rf += 1) {
1304
- if (rfKeys[rf] !== 'ostypePrefix') {
1305
- let fieldValue = getDataFromSources(callProps.responseFields[rfKeys[rf]], [thisDevice, devResp, callProps.requestFields]);
1306
-
1307
- // if the field is ostype - need to add prefix
1308
- if (rfKeys[rf] === 'ostype' && typeof fieldValue === 'string') {
1309
- fieldValue = ostypePrefix + fieldValue;
1310
- }
1311
- // if there is a status to set, set it
1312
- if (rfKeys[rf] === 'status') {
1313
- // if really looking for just a good response
1314
- if (callProps.responseFields[rfKeys[rf]] === 'return2xx' && myResult.icode === statusValue.toString()) {
1315
- thisDevice.isAlive = true;
1316
- } else if (fieldValue.toString() === statusValue.toString()) {
1317
- thisDevice.isAlive = true;
1318
- } else {
1319
- thisDevice.isAlive = false;
1320
- }
1321
- }
1322
- // if we found a good value
1323
- thisDevice[rfKeys[rf]] = fieldValue;
1324
- }
1325
- }
1326
-
1327
- // if there is no filter - add the device to the list
1328
- if (!filterName || filterName.length === 0) {
1329
- listDevices.push(thisDevice);
1330
- } else {
1331
- // if we have to match a filter
1332
- let found = false;
1333
- for (let f = 0; f < filterName.length; f += 1) {
1334
- if (thisDevice.name.indexOf(filterName[f]) >= 0) {
1335
- found = true;
1336
- break;
1337
- }
1338
- }
1339
- // matching device
1340
- if (found) {
1341
- listDevices.push(thisDevice);
1342
- }
1343
- }
1344
- }
1345
-
1346
- // return the array of devices
1347
- return callback(listDevices, null);
1348
- }
1349
-
1350
- // if this is not an array - just about everything else, just handle as a single object
1351
- let thisDevice = myResult.response;
1352
- for (let rf = 0; rf < rfKeys.length; rf += 1) {
1353
- // skip ostypePrefix since it is not a field
1354
- if (rfKeys[rf] !== 'ostypePrefix') {
1355
- let fieldValue = getDataFromSources(callProps.responseFields[rfKeys[rf]], [thisDevice, devResp, callProps.requestFields]);
1356
-
1357
- // if the field is ostype - need to add prefix
1358
- if (rfKeys[rf] === 'ostype' && typeof fieldValue === 'string') {
1359
- fieldValue = ostypePrefix + fieldValue;
1360
- }
1361
- // if there is a status to set, set it
1362
- if (rfKeys[rf] === 'status') {
1363
- // if really looking for just a good response
1364
- if (callProps.responseFields[rfKeys[rf]] === 'return2xx' && myResult.icode === statusValue.toString()) {
1365
- thisDevice.isAlive = true;
1366
- } else if (fieldValue.toString() === statusValue.toString()) {
1367
- thisDevice.isAlive = true;
1368
- } else {
1369
- thisDevice.isAlive = false;
1370
- }
1371
- }
1372
- // if we found a good value
1373
- thisDevice[rfKeys[rf]] = fieldValue;
1374
- }
1375
- }
1376
-
1377
- // if there is a filter - check the device is in the list
1378
- if (filterName && filterName.length > 0) {
1379
- let found = false;
1380
- for (let f = 0; f < filterName.length; f += 1) {
1381
- if (thisDevice.name.indexOf(filterName[f]) >= 0) {
1382
- found = true;
1383
- break;
1384
- }
1385
- }
1386
- // no matching device - clear the device
1387
- if (!found) {
1388
- thisDevice = {};
1389
- }
1390
- }
1391
-
1392
- return callback(thisDevice, null);
1393
- });
1394
- } catch (e) {
1395
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, e);
1396
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1397
- return callback(null, errorObj);
1398
- }
1061
+ return this.requestHandlerInst.getDevice(deviceName, callback);
1399
1062
  }
1400
1063
 
1401
1064
  /**
1402
1065
  * @summary Get Appliance that match the deviceName
1403
1066
  *
1404
- * @function getDevice
1067
+ * @function getDeviceAuth
1405
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
1406
1070
  *
1407
1071
  * @param {getCallback} callback - a callback function to return the result
1408
1072
  * (appliance) or the error
1409
1073
  */
1410
- getDevice(deviceName, callback) {
1411
- const meth = 'adapterBase-getDevice';
1412
- const origin = `${this.id}-${meth}`;
1074
+ getDeviceAuth(deviceName, callOptions, callback) {
1075
+ const origin = `${this.id}-adapterBase-getDeviceAuth`;
1413
1076
  log.trace(origin);
1414
1077
 
1415
- // make sure we are set up for device broker getDevice
1416
- if (!this.allProps.devicebroker || !this.allProps.devicebroker.getDevice || this.allProps.devicebroker.getDevice.length === 0 || !this.allProps.devicebroker.getDevice[0].path) {
1417
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Properties', ['devicebroker.getDevice.path'], null, null, null);
1418
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1419
- return callback(null, errorObj);
1420
- }
1421
-
1422
- /* HERE IS WHERE YOU VALIDATE DATA */
1423
- if (deviceName === undefined || deviceName === null || deviceName === '' || deviceName.length === 0) {
1424
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['deviceName'], null, null, null);
1425
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1426
- return callback(null, errorObj);
1427
- }
1428
-
1429
- try {
1430
- // need to get the device so we can convert the deviceName to an id
1431
- // !! if we can do a lookup by name the getDevicesFiltered may not be necessary
1432
- const opts = {
1433
- filter: {
1434
- name: deviceName
1435
- }
1436
- };
1437
- return this.getDevicesFiltered(opts, (devs, ferr) => {
1438
- // if we received an error or their is no response on the results return an error
1439
- if (ferr) {
1440
- return callback(null, ferr);
1441
- }
1442
- if (devs.list.length < 1) {
1443
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Did Not Find Device ${deviceName}`, [], null, null, null);
1444
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1445
- return callback(null, errorObj);
1446
- }
1447
-
1448
- const callPromises = [];
1449
- for (let i = 0; i < this.allProps.devicebroker.getDevice.length; i += 1) {
1450
- // Perform component calls here.
1451
- callPromises.push(
1452
- new Promise((resolve, reject) => {
1453
- this.iapMakeBrokerCall('getDevice', this.allProps.devicebroker.getDevice[i], [devs.list[0]], null, (callRet, callErr) => {
1454
- // return an error
1455
- if (callErr) {
1456
- reject(callErr);
1457
- } else {
1458
- // return the data
1459
- resolve(callRet);
1460
- }
1461
- });
1462
- })
1463
- );
1464
- }
1465
-
1466
- // return an array of repsonses
1467
- return Promise.all(callPromises).then((results) => {
1468
- let myResult = {};
1469
- results.forEach((result) => {
1470
- myResult = { ...myResult, ...result };
1471
- });
1472
-
1473
- return callback(myResult, null);
1474
- });
1475
- });
1476
- } catch (ex) {
1477
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
1478
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1479
- return callback(null, errorObj);
1480
- }
1078
+ return this.requestHandlerInst.getDeviceAuth(deviceName, callOptions, callback);
1481
1079
  }
1482
1080
 
1483
1081
  /**
@@ -1490,89 +1088,27 @@ class AdapterBase extends EventEmitterCl {
1490
1088
  * (appliances) or the error
1491
1089
  */
1492
1090
  getDevicesFiltered(options, callback) {
1493
- const meth = 'adapterBase-getDevicesFiltered';
1494
- const origin = `${this.id}-${meth}`;
1091
+ const origin = `${this.id}-adapterBase-getDevicesFiltered`;
1495
1092
  log.trace(origin);
1496
1093
 
1497
- // make sure we are set up for device broker getDevicesFiltered
1498
- if (!this.allProps.devicebroker || !this.allProps.devicebroker.getDevicesFiltered || this.allProps.devicebroker.getDevicesFiltered.length === 0 || !this.allProps.devicebroker.getDevicesFiltered[0].path) {
1499
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Properties', ['devicebroker.getDevicesFiltered.path'], null, null, null);
1500
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1501
- return callback(null, errorObj);
1502
- }
1503
-
1504
- // verify the required fields have been provided
1505
- if (options === undefined || options === null || options === '' || options.length === 0) {
1506
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['options'], null, null, null);
1507
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1508
- return callback(null, errorObj);
1509
- }
1510
- log.debug(`Device Filter Options: ${JSON.stringify(options)}`);
1511
-
1512
- try {
1513
- // TODO - get pagination working
1514
- // const nextToken = options.start;
1515
- // const maxResults = options.limit;
1516
-
1517
- // set up the filter of Device Names
1518
- let filterName = [];
1519
- if (options && options.filter && options.filter.name) {
1520
- // when this hack is removed, remove the lint ignore above
1521
- if (Array.isArray(options.filter.name)) {
1522
- // eslint-disable-next-line prefer-destructuring
1523
- filterName = options.filter.name;
1524
- } else {
1525
- filterName = [options.filter.name];
1526
- }
1527
- }
1528
-
1529
- // TODO - get sort and order working
1530
- /*
1531
- if (options && options.sort) {
1532
- reqObj.uriOptions.sort = JSON.stringify(options.sort);
1533
- }
1534
- if (options && options.order) {
1535
- reqObj.uriOptions.order = options.order;
1536
- }
1537
- */
1538
- const callPromises = [];
1539
- for (let i = 0; i < this.allProps.devicebroker.getDevicesFiltered.length; i += 1) {
1540
- // Perform component calls here.
1541
- callPromises.push(
1542
- new Promise((resolve, reject) => {
1543
- this.iapMakeBrokerCall('getDevicesFiltered', this.allProps.devicebroker.getDevicesFiltered[i], [{ fake: 'fakedata' }], filterName, (callRet, callErr) => {
1544
- // return an error
1545
- if (callErr) {
1546
- reject(callErr);
1547
- } else {
1548
- // return the data
1549
- resolve(callRet);
1550
- }
1551
- });
1552
- })
1553
- );
1554
- }
1094
+ return this.requestHandlerInst.getDevicesFiltered(options, callback);
1095
+ }
1555
1096
 
1556
- // return an array of repsonses
1557
- return Promise.all(callPromises).then((results) => {
1558
- let myResult = [];
1559
- results.forEach((result) => {
1560
- if (Array.isArray(result)) {
1561
- myResult = [...myResult, ...result];
1562
- } else if (Object.keys(result).length > 0) {
1563
- myResult.push(result);
1564
- }
1565
- });
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);
1566
1110
 
1567
- log.debug(`${origin}: Found #${myResult.length} devices.`);
1568
- log.debug(`Devices: ${JSON.stringify(myResult)}`);
1569
- return callback({ total: myResult.length, list: myResult });
1570
- });
1571
- } catch (ex) {
1572
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
1573
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1574
- return callback(null, errorObj);
1575
- }
1111
+ return this.requestHandlerInst.getDevicesFilteredAuth(options, callOptions, callback);
1576
1112
  }
1577
1113
 
1578
1114
  /**
@@ -1585,80 +1121,27 @@ class AdapterBase extends EventEmitterCl {
1585
1121
  * (appliance isAlive) or the error
1586
1122
  */
1587
1123
  isAlive(deviceName, callback) {
1588
- const meth = 'adapterBase-isAlive';
1589
- const origin = `${this.id}-${meth}`;
1124
+ const origin = `${this.id}-adapterBase-isAlive`;
1590
1125
  log.trace(origin);
1591
1126
 
1592
- // make sure we are set up for device broker isAlive
1593
- if (!this.allProps.devicebroker || !this.allProps.devicebroker.isAlive || this.allProps.devicebroker.isAlive.length === 0 || !this.allProps.devicebroker.isAlive[0].path) {
1594
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Properties', ['devicebroker.isAlive.path'], null, null, null);
1595
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1596
- return callback(null, errorObj);
1597
- }
1598
-
1599
- // verify the required fields have been provided
1600
- if (deviceName === undefined || deviceName === null || deviceName === '' || deviceName.length === 0) {
1601
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['deviceName'], null, null, null);
1602
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1603
- return callback(null, errorObj);
1604
- }
1605
-
1606
- try {
1607
- // need to get the device so we can convert the deviceName to an id
1608
- // !! if we can do a lookup by name the getDevicesFiltered may not be necessary
1609
- const opts = {
1610
- filter: {
1611
- name: deviceName
1612
- }
1613
- };
1614
- return this.getDevicesFiltered(opts, (devs, ferr) => {
1615
- // if we received an error or their is no response on the results return an error
1616
- if (ferr) {
1617
- return callback(null, ferr);
1618
- }
1619
- if (devs.list.length < 1) {
1620
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Did Not Find Device ${deviceName}`, [], null, null, null);
1621
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1622
- return callback(null, errorObj);
1623
- }
1624
-
1625
- const callPromises = [];
1626
- for (let i = 0; i < this.allProps.devicebroker.isAlive.length; i += 1) {
1627
- // Perform component calls here.
1628
- callPromises.push(
1629
- new Promise((resolve, reject) => {
1630
- this.iapMakeBrokerCall('isAlive', this.allProps.devicebroker.isAlive[i], [devs.list[0]], null, (callRet, callErr) => {
1631
- // return an error
1632
- if (callErr) {
1633
- reject(callErr);
1634
- } else {
1635
- // return the data
1636
- resolve(callRet);
1637
- }
1638
- });
1639
- })
1640
- );
1641
- }
1127
+ return this.requestHandlerInst.isAlive(deviceName, callback);
1128
+ }
1642
1129
 
1643
- // return an array of repsonses
1644
- return Promise.all(callPromises).then((results) => {
1645
- let myResult = {};
1646
- results.forEach((result) => {
1647
- myResult = { ...myResult, ...result };
1648
- });
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);
1649
1143
 
1650
- let response = true;
1651
- if (myResult.isAlive !== null && myResult.isAlive !== undefined && myResult.isAlive === false) {
1652
- response = false;
1653
- }
1654
- return callback(response);
1655
- });
1656
- });
1657
- } catch (ex) {
1658
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
1659
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1660
- return callback(null, errorObj);
1661
- }
1144
+ return this.requestHandlerInst.isAliveAuth(deviceName, callOptions, callback);
1662
1145
  }
1663
1146
 
1664
1147
  /**
@@ -1672,80 +1155,28 @@ class AdapterBase extends EventEmitterCl {
1672
1155
  * (appliance config) or the error
1673
1156
  */
1674
1157
  getConfig(deviceName, format, callback) {
1675
- const meth = 'adapterBase-getConfig';
1676
- const origin = `${this.id}-${meth}`;
1158
+ const origin = `${this.id}-adapterBase-getConfig`;
1677
1159
  log.trace(origin);
1678
1160
 
1679
- // make sure we are set up for device broker getConfig
1680
- if (!this.allProps.devicebroker || !this.allProps.devicebroker.getConfig || this.allProps.devicebroker.getConfig.length === 0 || !this.allProps.devicebroker.getConfig[0].path) {
1681
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Properties', ['devicebroker.getConfig.path'], null, null, null);
1682
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1683
- return callback(null, errorObj);
1684
- }
1685
-
1686
- // verify the required fields have been provided
1687
- if (deviceName === undefined || deviceName === null || deviceName === '' || deviceName.length === 0) {
1688
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['deviceName'], null, null, null);
1689
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1690
- return callback(null, errorObj);
1691
- }
1692
-
1693
- try {
1694
- // need to get the device so we can convert the deviceName to an id
1695
- // !! if we can do a lookup by name the getDevicesFiltered may not be necessary
1696
- const opts = {
1697
- filter: {
1698
- name: deviceName
1699
- }
1700
- };
1701
- return this.getDevicesFiltered(opts, (devs, ferr) => {
1702
- // if we received an error or their is no response on the results return an error
1703
- if (ferr) {
1704
- return callback(null, ferr);
1705
- }
1706
- if (devs.list.length < 1) {
1707
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Did Not Find Device ${deviceName}`, [], null, null, null);
1708
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1709
- return callback(null, errorObj);
1710
- }
1161
+ return this.requestHandlerInst.getConfig(deviceName, format, callback);
1162
+ }
1711
1163
 
1712
- const callPromises = [];
1713
- for (let i = 0; i < this.allProps.devicebroker.getConfig.length; i += 1) {
1714
- // Perform component calls here.
1715
- callPromises.push(
1716
- new Promise((resolve, reject) => {
1717
- this.iapMakeBrokerCall('getConfig', this.allProps.devicebroker.getConfig[i], [devs.list[0]], null, (callRet, callErr) => {
1718
- // return an error
1719
- if (callErr) {
1720
- reject(callErr);
1721
- } else {
1722
- // return the data
1723
- resolve(callRet);
1724
- }
1725
- });
1726
- })
1727
- );
1728
- }
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);
1729
1178
 
1730
- // return an array of repsonses
1731
- return Promise.all(callPromises).then((results) => {
1732
- let myResult = {};
1733
- results.forEach((result) => {
1734
- myResult = { ...myResult, ...result };
1735
- });
1736
-
1737
- // return the result
1738
- const newResponse = {
1739
- response: JSON.stringify(myResult, null, 2)
1740
- };
1741
- return callback(newResponse, null);
1742
- });
1743
- });
1744
- } catch (ex) {
1745
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
1746
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1747
- return callback(null, errorObj);
1748
- }
1179
+ return this.requestHandlerInst.getConfigAuth(deviceName, format, callOptions, callback);
1749
1180
  }
1750
1181
 
1751
1182
  /**
@@ -1757,47 +1188,258 @@ class AdapterBase extends EventEmitterCl {
1757
1188
  * (count) or the error
1758
1189
  */
1759
1190
  iapGetDeviceCount(callback) {
1760
- 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';
1761
1302
  const origin = `${this.id}-${meth}`;
1762
1303
  log.trace(origin);
1304
+ let command = null;
1763
1305
 
1764
- // make sure we are set up for device broker getCount
1765
- if (!this.allProps.devicebroker || !this.allProps.devicebroker.getCount || this.allProps.devicebroker.getCount.length === 0 || !this.allProps.devicebroker.getCount[0].path) {
1766
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Properties', ['devicebroker.getCount.path'], null, null, null);
1767
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1768
- 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);
1769
1327
  }
1770
1328
 
1771
- // verify the required fields have been provided
1329
+ log.error('Package Not Found');
1330
+ return callback(null, 'Package Not Found');
1331
+ }
1772
1332
 
1773
- try {
1774
- const callPromises = [];
1775
- for (let i = 0; i < this.allProps.devicebroker.getCount.length; i += 1) {
1776
- // Perform component calls here.
1777
- callPromises.push(
1778
- new Promise((resolve, reject) => {
1779
- this.iapMakeBrokerCall('getCount', this.allProps.devicebroker.getCount[i], null, null, (callRet, callErr) => {
1780
- // return an error
1781
- if (callErr) {
1782
- reject(callErr);
1783
- } else {
1784
- // return the data
1785
- resolve(callRet);
1786
- }
1787
- });
1788
- })
1789
- );
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');
1790
1355
  }
1791
1356
 
1792
- // return an array of repsonses
1793
- return Promise.all(callPromises).then((results) => {
1794
- let myResult = {};
1795
- results.forEach((result) => {
1796
- myResult = { ...myResult, ...result };
1797
- });
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
+ }
1798
1388
 
1799
- // return the result
1800
- return callback({ count: 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
+ });
1801
1443
  });
1802
1444
  } catch (ex) {
1803
1445
  const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);