@itentialopensource/adapter-checkpoint_management 0.2.5 → 0.2.6

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 (90) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +84 -11
  3. package/adapter.js +469 -1
  4. package/adapterBase.js +25 -3
  5. package/entities/.generic/action.json +5 -5
  6. package/entities/.system/action.json +5 -5
  7. package/entities/APISettings/action.json +3 -3
  8. package/entities/AccessLayer/action.json +6 -6
  9. package/entities/AccessRole/action.json +6 -6
  10. package/entities/AccessRule/action.json +6 -6
  11. package/entities/AccessSection/action.json +5 -5
  12. package/entities/AddressRange/action.json +6 -6
  13. package/entities/Administrator/action.json +7 -7
  14. package/entities/Application/action.json +6 -6
  15. package/entities/ApplicationCategory/action.json +6 -6
  16. package/entities/ApplicationGroup/action.json +6 -6
  17. package/entities/DNSDomain/action.json +6 -6
  18. package/entities/DataCenter/action.json +4 -4
  19. package/entities/DataCenterObject/action.json +5 -5
  20. package/entities/Domain/action.json +6 -6
  21. package/entities/DynamicObject/action.json +6 -6
  22. package/entities/GlobalAssignment/action.json +7 -7
  23. package/entities/GlobalDomain/action.json +3 -3
  24. package/entities/Group/action.json +6 -6
  25. package/entities/GroupWithExclusion/action.json +6 -6
  26. package/entities/Host/action.json +6 -6
  27. package/entities/IPS/action.json +5 -5
  28. package/entities/IPSExtendedAttributes/action.json +3 -3
  29. package/entities/LoginMessage/action.json +3 -3
  30. package/entities/Misc/action.json +15 -15
  31. package/entities/MultiDomainServerMDS/action.json +3 -3
  32. package/entities/MulticastAddressRange/action.json +6 -6
  33. package/entities/NATRule/action.json +6 -6
  34. package/entities/NATSection/action.json +5 -5
  35. package/entities/Network/action.json +6 -6
  36. package/entities/OPSECApplication/action.json +6 -6
  37. package/entities/Placeholder/action.json +2 -2
  38. package/entities/Policy/action.json +3 -3
  39. package/entities/PolicyPackage/action.json +6 -6
  40. package/entities/SecurityZone/action.json +6 -6
  41. package/entities/ServiceDCERPC/action.json +6 -6
  42. package/entities/ServiceGroup/action.json +6 -6
  43. package/entities/ServiceICMP/action.json +6 -6
  44. package/entities/ServiceICMP6/action.json +6 -6
  45. package/entities/ServiceOther/action.json +6 -6
  46. package/entities/ServiceRPC/action.json +6 -6
  47. package/entities/ServiceSCTP/action.json +6 -6
  48. package/entities/ServiceTCP/action.json +6 -6
  49. package/entities/ServiceUDP/action.json +6 -6
  50. package/entities/Session/action.json +10 -10
  51. package/entities/SessionManagement/action.json +7 -7
  52. package/entities/SimpleGateway/action.json +6 -6
  53. package/entities/Tags/action.json +6 -6
  54. package/entities/ThreatEmulation/action.json +2 -2
  55. package/entities/ThreatException/action.json +6 -6
  56. package/entities/ThreatExceptionGroup/action.json +6 -6
  57. package/entities/ThreatIndicator/action.json +6 -6
  58. package/entities/ThreatLayer/action.json +6 -6
  59. package/entities/ThreatProfile/action.json +6 -6
  60. package/entities/ThreatProtection/action.json +6 -6
  61. package/entities/ThreatRule/action.json +6 -6
  62. package/entities/Time/action.json +6 -6
  63. package/entities/TimeGroup/action.json +6 -6
  64. package/entities/TrustedClient/action.json +6 -6
  65. package/entities/UpdatableObject/action.json +5 -5
  66. package/entities/UpdatableObjectsRepository/action.json +3 -3
  67. package/entities/VPNCommunityMeshed/action.json +6 -6
  68. package/entities/VPNCommunityStar/action.json +6 -6
  69. package/entities/Wildcard/action.json +6 -6
  70. package/error.json +6 -0
  71. package/package.json +19 -14
  72. package/pronghorn.json +192 -0
  73. package/propertiesSchema.json +15 -0
  74. package/refs?service=git-upload-pack +0 -0
  75. package/report/updateReport1646177180887.json +95 -0
  76. package/sampleProperties.json +15 -8
  77. package/test/integration/adapterTestBasicGet.js +1 -1
  78. package/test/integration/adapterTestIntegration.js +10 -2
  79. package/test/unit/adapterBaseTestUnit.js +6 -3
  80. package/test/unit/adapterTestUnit.js +619 -4
  81. package/utils/addAuth.js +94 -0
  82. package/utils/basicGet.js +1 -14
  83. package/utils/entitiesToDB.js +224 -0
  84. package/utils/modify.js +1 -1
  85. package/utils/packModificationScript.js +1 -1
  86. package/utils/patches2bundledDeps.js +90 -0
  87. package/utils/removeHooks.js +20 -0
  88. package/utils/tbScript.js +14 -8
  89. package/utils/tbUtils.js +98 -19
  90. package/utils/troubleshootingAdapter.js +2 -26
package/CHANGELOG.md CHANGED
@@ -1,4 +1,12 @@
1
1
 
2
+ ## 0.2.6 [03-02-2022]
3
+
4
+ * Improve sample properties with tested config
5
+
6
+ See merge request itentialopensource/adapters/security/adapter-checkpoint_management!6
7
+
8
+ ---
9
+
2
10
  ## 0.2.5 [03-02-2021]
3
11
 
4
12
  * migration to the latest adapter foundation
package/README.md CHANGED
@@ -125,7 +125,8 @@ This section defines **all** the properties that are available for the adapter,
125
125
  },
126
126
  "healthcheck": {
127
127
  "type": "startup",
128
- "frequency": 300000
128
+ "frequency": 300000,
129
+ "query_object": {}
129
130
  },
130
131
  "request": {
131
132
  "number_redirects": 0,
@@ -250,6 +251,7 @@ The healthcheck properties defines the API that runs the healthcheck to tell the
250
251
  | ------- | ------- |
251
252
  | type | Required. The type of health check to run. |
252
253
  | frequency | Required if intermittent. Defines how often the health check should run. Measured in milliseconds. Default is 300000.|
254
+ | query_object | Query parameters to be added to the adapter healthcheck call.|
253
255
 
254
256
  ### Request Properties
255
257
 
@@ -398,7 +400,7 @@ There are several node scripts that now accompany the adapter. These scripts are
398
400
  | npm run troubleshoot | Provides a way to troubleshoot the adapter - runs connectivity, healthcheck and basic get.|
399
401
  | npm run connectivity | Provides a connectivity check to the Checkpoint_Management system.|
400
402
  | npm run healthcheck | Checks whether the configured healthcheck call works to Checkpoint_Management.|
401
- | npm run basicget | Checks whether the cbasic get calls works to Checkpoint_Management.|
403
+ | npm run basicget | Checks whether the basic get calls works to Checkpoint_Management.|
402
404
 
403
405
  ## Installing an Itential Product Adapter
404
406
 
@@ -412,21 +414,21 @@ if the @itentialopensource directory does not exist, create it:
412
414
  mkdir @itentialopensource
413
415
  ```
414
416
 
415
- 1. Clone the adapter into your IAP environment.
417
+ 2. Clone the adapter into your IAP environment.
416
418
 
417
419
  ```bash
418
420
  cd \@itentialopensource
419
421
  git clone git@gitlab.com:\@itentialopensource/adapters/adapter-checkpoint_management
420
422
  ```
421
423
 
422
- 1. Run the adapter install script.
424
+ 3. Run the adapter install script.
423
425
 
424
426
  ```bash
425
427
  cd adapter-checkpoint_management
426
428
  npm run adapter:install
427
429
  ```
428
430
 
429
- 1. Restart IAP
431
+ 4. Restart IAP
430
432
 
431
433
  ```bash
432
434
  systemctl restart pronghorn
@@ -446,7 +448,7 @@ Depending on where your code is located, this process is different.
446
448
  Adapter should be placed into: /opt/pronghorn/current/node_modules/\@itentialopensource
447
449
  ```
448
450
 
449
- 1. Follow Steps 3-4 (above) to install an Itential adapter to load your properties, dependencies and restart IAP.
451
+ 2. Follow Steps 3-4 (above) to install an Itential adapter to load your properties, dependencies and restart IAP.
450
452
 
451
453
  ## Using this Adapter
452
454
 
@@ -494,7 +496,7 @@ The `verifyCapability` call verifies the adapter can perform the provided action
494
496
  verifyCapability(entityType, actionType, entityId, callback)
495
497
  ```
496
498
 
497
- The `updateEntityCache` call will update the entity cache.
499
+ The `updateEntityCache` call will update the entity cache.
498
500
  ```js
499
501
  updateEntityCache()
500
502
  ```
@@ -548,6 +550,77 @@ getQueue(callback)
548
550
 
549
551
  Specific adapter calls are built based on the API of the Checkpoint_Management. The Adapter Builder creates the proper method comments for generating JS-DOC for the adapter. This is the best way to get information on the calls.
550
552
 
553
+
554
+ ## Extending/Enhancing the Adapter
555
+
556
+ ### Adding a Second Instance of an Adapter
557
+
558
+ You can add a second instance of this adapter without adding new code on the file system. To do this go into the IAP Admin Essentials and add a new service config for this adapter. The two instances of the adapter should have unique ids. In addition, they should point to different instances of the other system. For example, they should be configured to talk to different hosts.
559
+
560
+ ### Adding Adapter Calls
561
+
562
+ There are multiple ways to add calls to an existing adapter.
563
+
564
+ The easiest way would be to use the Adapter Builder update process. This process takes in a Swagger or OpenAPI document, allows you to select the calls you want to add and then generates a zip file that can be used to update the adapter. Once you have the zip file simple put it in the adapter direcctory and execute `npm run adapter:update`.
565
+
566
+ ```bash
567
+ mv updatePackage.zip adapter-checkpoint_management
568
+ cd adapter-checkpoint_management
569
+ npm run adapter:update
570
+ ```
571
+
572
+ If you do not have a Swagger or OpenAPI document, you can use a Postman Collection and convert that to an OpenAPI document using APIMatic and then follow the first process.
573
+
574
+ If you want to manually update the adapter that can also be done the key thing is to make sure you update all of the right files. Within the entities directory you will find 1 or more entities. You can create a new entity or add to an existing entity. Each entity has an action.json file, any new call will need to be put in the action.json file. It will also need to be added to the enum for the ph_request_type in the appropriate schema files. Once this configuration is complete you will need to add the call to the adapter.js file and in order to make it available as a workflow task in IAP, it should also be added to the pronghorn.json file. You can optionally add it to the unit and integration test files. There is more information on how to work on each of these files in the Adapter Technical Resources on Dev Site [HERE](https://developer.itential.io/adapters-resources/)
575
+
576
+ ```text
577
+ Files to update
578
+ * entities/<entity>/action.json: add an action
579
+ * entities/<entity>/schema.json (or the schema defined on the action): add action to the enum for ph_request_type
580
+ * adapter.js: add the new method and make sure it calls the proper entity and action
581
+ * pronghorn.json: add the new method
582
+ * test/unit/adapterTestUnit.js (optional but best practice): add unit test(s) - function is there, any required parameters error when not passed in
583
+ * test/integration/adapterTestIntegration.js (optional but best practice): add integration test
584
+ ```
585
+
586
+ ### Adding Adapter Properties
587
+
588
+ While changing adapter properties is done in the service instance configuration section of IAP, adding properties has to be done in the adapter. To add a property you should edit the propertiesSchema.json with the proper information for the property. In addition, you should modify the sampleProperties to have the new property in it.
589
+
590
+ ```text
591
+ Files to update
592
+ * propertiesSchema.json: add the new property and how it is defined
593
+ * sampleProperties: add the new property with a default value
594
+ * test/unit/adapterTestUnit.js (optional but best practice): add the property to the global properties
595
+ * test/integration/adapterTestIntegration.js (optional but best practice): add the property to the global properties
596
+ ```
597
+
598
+ ### Changing Adapter Authentication
599
+
600
+ Often an adapter is built before knowing the authentication and authentication process can also change over time. The adapter supports many different kinds of authentication but it does require configuration. Some forms of authentication can be defined entirely with the adapter properties but others require configuration.
601
+
602
+ ```text
603
+ Files to update
604
+ * entities/<entity>/action.json: change the getToken action as needed
605
+ * entities/<entity>/schemaTokenReq.json: add input parameters (external name is name in other system)
606
+ * entities/<entity>/schemaTokenResp.json: add response parameters (external name is name in other system)
607
+ * propertiesSchema.json: add any new property and how it is defined
608
+ * sampleProperties: add any new property with a default value
609
+ * test/unit/adapterTestUnit.js (optional but best practice): add the property to the global properties
610
+ * test/integration/adapterTestIntegration.js (optional but best practice): add the property to the global properties
611
+ ```
612
+
613
+ ### Enhancing Adapter Integration Tests
614
+
615
+ The adapter integration tests are written to be able to test in either stub (standalone) mode or integrated to the other system. However, if integrating to the other system, you may need to provide better data than what the adapter provides by default as that data is likely to fail for create and update. To provide better data, edit the adapter integration test file. Make sure you do not remove the marker and keep custom code below the marker so you do not impact future migrations. Once the edits are complete, run the integration test as it instructs you to above. When you run integrated to the other system, you can also save mockdata for future use by changing the isSaveMockData flag to true.
616
+
617
+ ```text
618
+ Files to update
619
+ * test/integration/adapterTestIntegration.js: add better data for the create and update calls so that they will not fail.
620
+ ```
621
+
622
+ As mentioned previously, for most of these changes as well as other possible changes, there is more information on how to work on an adapter in the Adapter Technical Resources on Dev Site [HERE](https://developer.itential.io/adapters-resources/)
623
+
551
624
  ## Troubleshooting the Adapter
552
625
 
553
626
  Run `npm run troubleshoot` to start the interactive troubleshooting process. The command allows user to verify and update connection, authentication as well as healthcheck configuration. After that it will test these properties by sending HTTP request to the endpoint. If the tests pass, it will persist these changes into IAP.
@@ -566,26 +639,26 @@ User also have the option to run individual command to perform specific test
566
639
  npm run troubleshoot
567
640
  ```
568
641
 
569
- 1. Verify the adapter properties are set up correctly.
642
+ 2. Verify the adapter properties are set up correctly.
570
643
 
571
644
  ```text
572
645
  Go into the Itential Platform GUI and verify/update the properties
573
646
  ```
574
647
 
575
- 1. Verify there is connectivity between the Itential Platform Server and Checkpoint_Management Server.
648
+ 3. Verify there is connectivity between the Itential Platform Server and Checkpoint_Management Server.
576
649
 
577
650
  ```text
578
651
  ping the ip address of Checkpoint_Management server
579
652
  try telnet to the ip address port of Checkpoint_Management
580
653
  ```
581
654
 
582
- 1. Verify the credentials provided for Checkpoint_Management.
655
+ 4. Verify the credentials provided for Checkpoint_Management.
583
656
 
584
657
  ```text
585
658
  login to Checkpoint_Management using the provided credentials
586
659
  ```
587
660
 
588
- 1. Verify the API of the call utilized for Checkpoint_Management Healthcheck.
661
+ 5. Verify the API of the call utilized for Checkpoint_Management Healthcheck.
589
662
 
590
663
  ```text
591
664
  Go into the Itential Platform GUI and verify/update the properties
package/adapter.js CHANGED
@@ -83,7 +83,7 @@ class CheckpointManagement extends AdapterBaseCl {
83
83
  * @getWorkflowFunctions
84
84
  */
85
85
  getWorkflowFunctions(inIgnore) {
86
- let myIgnore = [];
86
+ let myIgnore = ['hasEntities', 'hasDevices'];
87
87
  if (!inIgnore && Array.isArray(inIgnore)) {
88
88
  myIgnore = inIgnore;
89
89
  } else if (!inIgnore && typeof inIgnore === 'string') {
@@ -247,6 +247,24 @@ class CheckpointManagement extends AdapterBaseCl {
247
247
  }
248
248
  }
249
249
 
250
+ /**
251
+ * @summary moves entites into Mongo DB
252
+ *
253
+ * @function moveEntitiesToDB
254
+ * @param {getCallback} callback - a callback function to return the result (Generics)
255
+ * or the error
256
+ */
257
+ moveEntitiesToDB(callback) {
258
+ const origin = `${this.id}-adapter-moveEntitiesToDB`;
259
+ log.trace(origin);
260
+ try {
261
+ return super.moveEntitiesToDB(callback);
262
+ } catch (err) {
263
+ log.error(`${origin}: ${err}`);
264
+ return callback(null, err);
265
+ }
266
+ }
267
+
250
268
  /**
251
269
  * @summary Determines if this adapter supports the specific entity
252
270
  *
@@ -526,6 +544,456 @@ class CheckpointManagement extends AdapterBaseCl {
526
544
  }
527
545
  }
528
546
 
547
+ /* BROKER CALLS */
548
+ /**
549
+ * @summary Determines if this adapter supports any in a list of entities
550
+ *
551
+ * @function hasEntities
552
+ * @param {String} entityType - the entity type to check for
553
+ * @param {Array} entityList - the list of entities we are looking for
554
+ *
555
+ * @param {Callback} callback - A map where the entity is the key and the
556
+ * value is true or false
557
+ */
558
+ hasEntities(entityType, entityList, callback) {
559
+ const origin = `${this.id}-adapter-hasEntities`;
560
+ log.trace(origin);
561
+
562
+ switch (entityType) {
563
+ case 'Device':
564
+ return this.hasDevices(entityList, callback);
565
+ default:
566
+ return callback(null, `${this.id} does not support entity ${entityType}`);
567
+ }
568
+ }
569
+
570
+ /**
571
+ * @summary Helper method for hasEntities for the specific device case
572
+ *
573
+ * @param {Array} deviceList - array of unique device identifiers
574
+ * @param {Callback} callback - A map where the device is the key and the
575
+ * value is true or false
576
+ */
577
+ hasDevices(deviceList, callback) {
578
+ const origin = `${this.id}-adapter-hasDevices`;
579
+ log.trace(origin);
580
+
581
+ const findings = deviceList.reduce((map, device) => {
582
+ // eslint-disable-next-line no-param-reassign
583
+ map[device] = false;
584
+ log.debug(`In reduce: ${JSON.stringify(map)}`);
585
+ return map;
586
+ }, {});
587
+ const apiCalls = deviceList.map((device) => new Promise((resolve) => {
588
+ this.getDevice(device, (result, error) => {
589
+ if (error) {
590
+ log.debug(`In map error: ${JSON.stringify(device)}`);
591
+ return resolve({ name: device, found: false });
592
+ }
593
+ log.debug(`In map: ${JSON.stringify(device)}`);
594
+ return resolve({ name: device, found: true });
595
+ });
596
+ }));
597
+ Promise.all(apiCalls).then((results) => {
598
+ results.forEach((device) => {
599
+ findings[device.name] = device.found;
600
+ });
601
+ log.debug(`FINDINGS: ${JSON.stringify(findings)}`);
602
+ return callback(findings);
603
+ }).catch((errors) => {
604
+ log.error('Unable to do device lookup.');
605
+ return callback(null, { code: 503, message: 'Unable to do device lookup.', error: errors });
606
+ });
607
+ }
608
+
609
+ /**
610
+ * @summary Get Appliance that match the deviceName
611
+ *
612
+ * @function getDevice
613
+ * @param {String} deviceName - the deviceName to find (required)
614
+ *
615
+ * @param {getCallback} callback - a callback function to return the result
616
+ * (appliance) or the error
617
+ */
618
+ getDevice(deviceName, callback) {
619
+ const meth = 'adapter-getDevice';
620
+ const origin = `${this.id}-${meth}`;
621
+ log.trace(origin);
622
+
623
+ if (this.suspended && this.suspendMode === 'error') {
624
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'AD.600', [], null, null, null);
625
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
626
+ return callback(null, errorObj);
627
+ }
628
+
629
+ /* HERE IS WHERE YOU VALIDATE DATA */
630
+ if (deviceName === undefined || deviceName === null || deviceName === '' || deviceName.length === 0) {
631
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['deviceName'], null, null, null);
632
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
633
+ return callback(null, errorObj);
634
+ }
635
+
636
+ try {
637
+ // need to get the device so we can convert the deviceName to an id
638
+ // !! if we can do a lookup by name the getDevicesFiltered may not be necessary
639
+ const opts = {
640
+ filter: {
641
+ name: deviceName
642
+ }
643
+ };
644
+ return this.getDevicesFiltered(opts, (devs, ferr) => {
645
+ // if we received an error or their is no response on the results return an error
646
+ if (ferr) {
647
+ return callback(null, ferr);
648
+ }
649
+ if (devs.list.length < 1) {
650
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Did Not Find Device ${deviceName}`, [], null, null, null);
651
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
652
+ return callback(null, errorObj);
653
+ }
654
+ // get the uuid from the device
655
+ const { uuid } = devs.list[0];
656
+
657
+ // !! using Generic makes it easier on the Adapter Builder (just need to change the path)
658
+ // !! you can also replace with a specific call if that is easier
659
+ const uriPath = `/call/toget/device/${uuid}`;
660
+ return this.genericAdapterRequest(uriPath, 'GET', {}, {}, {}, (result, error) => {
661
+ // if we received an error or their is no response on the results return an error
662
+ if (error) {
663
+ return callback(null, error);
664
+ }
665
+ if (!result.response || !result.response.applianceMo) {
666
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Invalid Response', ['getDevice'], null, null, null);
667
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
668
+ return callback(null, errorObj);
669
+ }
670
+
671
+ // return the response
672
+ // !! format the data we send back
673
+ // !! these fields are config manager fields you need to map to the data we receive
674
+ const thisDevice = result.response;
675
+ thisDevice.name = thisDevice.systemName;
676
+ thisDevice.ostype = `System-${thisDevice.systemType}`;
677
+ thisDevice.port = thisDevice.systemPort;
678
+ thisDevice.ipaddress = thisDevice.systemIP;
679
+ return callback(thisDevice);
680
+ });
681
+ });
682
+ } catch (ex) {
683
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
684
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
685
+ return callback(null, errorObj);
686
+ }
687
+ }
688
+
689
+ /**
690
+ * @summary Get Appliances that match the filter
691
+ *
692
+ * @function getDevicesFiltered
693
+ * @param {Object} options - the data to use to filter the appliances (optional)
694
+ *
695
+ * @param {getCallback} callback - a callback function to return the result
696
+ * (appliances) or the error
697
+ */
698
+ getDevicesFiltered(options, callback) {
699
+ const meth = 'adapter-getDevicesFiltered';
700
+ const origin = `${this.id}-${meth}`;
701
+ log.trace(origin);
702
+
703
+ // verify the required fields have been provided
704
+ if (options === undefined || options === null || options === '' || options.length === 0) {
705
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['options'], null, null, null);
706
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
707
+ return callback(null, errorObj);
708
+ }
709
+ log.debug(`Device Filter Options: ${JSON.stringify(options)}`);
710
+
711
+ // TODO - get pagination working
712
+ // const nextToken = options.start;
713
+ // const maxResults = options.limit;
714
+
715
+ // set up the filter of Device Names
716
+ let filterName = [];
717
+ if (options && options.filter && options.filter.name) {
718
+ // when this hack is removed, remove the lint ignore above
719
+ if (Array.isArray(options.filter.name)) {
720
+ // eslint-disable-next-line prefer-destructuring
721
+ filterName = options.filter.name;
722
+ } else {
723
+ filterName = [options.filter.name];
724
+ }
725
+ }
726
+
727
+ // TODO - get sort and order working
728
+ /*
729
+ if (options && options.sort) {
730
+ reqObj.uriOptions.sort = JSON.stringify(options.sort);
731
+ }
732
+ if (options && options.order) {
733
+ reqObj.uriOptions.order = options.order;
734
+ }
735
+ */
736
+ try {
737
+ // !! using Generic makes it easier on the Adapter Builder (just need to change the path)
738
+ // !! you can also replace with a specific call if that is easier
739
+ const uriPath = '/call/toget/devices';
740
+ return this.genericAdapterRequest(uriPath, 'GET', {}, {}, {}, (result, error) => {
741
+ // if we received an error or their is no response on the results return an error
742
+ if (error) {
743
+ return callback(null, error);
744
+ }
745
+ if (!result.response) {
746
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Invalid Response', ['getDevicesFiltered'], null, null, null);
747
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
748
+ return callback(null, errorObj);
749
+ }
750
+
751
+ // !! go through the response - may have to look for sub object
752
+ // handle an array of devices
753
+ if (Array.isArray(result.response)) {
754
+ const myDevices = [];
755
+
756
+ for (let d = 0; d < result.response.length; d += 1) {
757
+ // !! format the data we send back
758
+ // !! these fields are config manager fields you need to map to the data we receive
759
+ const thisDevice = result.response;
760
+ thisDevice.name = thisDevice.systemName;
761
+ thisDevice.ostype = `System-${thisDevice.systemType}`;
762
+ thisDevice.port = thisDevice.systemPort;
763
+ thisDevice.ipaddress = thisDevice.systemIP;
764
+
765
+ // if there is no filter - return the device
766
+ if (filterName.length === 0) {
767
+ myDevices.push(thisDevice);
768
+ } else {
769
+ // if we have to match a filter
770
+ let found = false;
771
+ for (let f = 0; f < filterName.length; f += 1) {
772
+ if (thisDevice.name.indexOf(filterName[f]) >= 0) {
773
+ found = true;
774
+ break;
775
+ }
776
+ }
777
+ // matching device
778
+ if (found) {
779
+ myDevices.push(thisDevice);
780
+ }
781
+ }
782
+ }
783
+ log.debug(`${origin}: Found #${myDevices.length} devices.`);
784
+ log.debug(`Devices: ${JSON.stringify(myDevices)}`);
785
+ return callback({ total: myDevices.length, list: myDevices });
786
+ }
787
+ // handle a single device response
788
+ // !! format the data we send back
789
+ // !! these fields are config manager fields you need to map to the data we receive
790
+ const thisDevice = result.response;
791
+ thisDevice.name = thisDevice.systemName;
792
+ thisDevice.ostype = `System-${thisDevice.systemType}`;
793
+ thisDevice.port = thisDevice.systemPort;
794
+ thisDevice.ipaddress = thisDevice.systemIP;
795
+
796
+ // if there is no filter - return the device
797
+ if (filterName.length === 0) {
798
+ log.debug(`${origin}: Found #1 device.`);
799
+ log.debug(`Device: ${JSON.stringify(thisDevice)}`);
800
+ return callback({ total: 1, list: [thisDevice] });
801
+ }
802
+
803
+ // if there is a filter need to check for matching device
804
+ let found = false;
805
+ for (let f = 0; f < filterName.length; f += 1) {
806
+ if (thisDevice.name.indexOf(filterName[f]) >= 0) {
807
+ found = true;
808
+ break;
809
+ }
810
+ }
811
+ // matching device
812
+ if (found) {
813
+ log.debug(`${origin}: Found #1 device.`);
814
+ log.debug(`Device Found: ${JSON.stringify(thisDevice)}`);
815
+ return callback({ total: 1, list: [thisDevice] });
816
+ }
817
+ // not a matching device
818
+ log.debug(`${origin}: No matching device found.`);
819
+ return callback({ total: 0, list: [] });
820
+ });
821
+ } catch (ex) {
822
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
823
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
824
+ return callback(null, errorObj);
825
+ }
826
+ }
827
+
828
+ /**
829
+ * @summary Gets the status for the provided appliance
830
+ *
831
+ * @function isAlive
832
+ * @param {String} deviceName - the deviceName of the appliance. (required)
833
+ *
834
+ * @param {configCallback} callback - callback function to return the result
835
+ * (appliance isAlive) or the error
836
+ */
837
+ isAlive(deviceName, callback) {
838
+ const meth = 'adapter-isAlive';
839
+ const origin = `${this.id}-${meth}`;
840
+ log.trace(origin);
841
+
842
+ // verify the required fields have been provided
843
+ if (deviceName === undefined || deviceName === null || deviceName === '' || deviceName.length === 0) {
844
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['deviceName'], null, null, null);
845
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
846
+ return callback(null, errorObj);
847
+ }
848
+
849
+ try {
850
+ // need to get the device so we can convert the deviceName to an id
851
+ // !! if we can do a lookup by name the getDevicesFiltered may not be necessary
852
+ const opts = {
853
+ filter: {
854
+ name: deviceName
855
+ }
856
+ };
857
+ return this.getDevicesFiltered(opts, (devs, ferr) => {
858
+ // if we received an error or their is no response on the results return an error
859
+ if (ferr) {
860
+ return callback(null, ferr);
861
+ }
862
+ if (devs.list.length < 1) {
863
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Did Not Find Device ${deviceName}`, [], null, null, null);
864
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
865
+ return callback(null, errorObj);
866
+ }
867
+ // get the uuid from the device
868
+ const { uuid } = devs.list[0];
869
+
870
+ // !! using Generic makes it easier on the Adapter Builder (just need to change the path)
871
+ // !! you can also replace with a specific call if that is easier
872
+ const uriPath = `/call/toget/status/${uuid}`;
873
+ return this.genericAdapterRequest(uriPath, 'GET', {}, {}, {}, (result, error) => {
874
+ // if we received an error or their is no response on the results return an error
875
+ if (error) {
876
+ return callback(null, error);
877
+ }
878
+ // !! should update this to make sure we are checking for the appropriate object/field
879
+ if (!result.response || !result.response.returnObj || !Object.hasOwnProperty.call(result.response.returnObj, 'statusField')) {
880
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Invalid Response', ['isAlive'], null, null, null);
881
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
882
+ return callback(null, errorObj);
883
+ }
884
+
885
+ // !! return the response - Update to the appropriate object/field
886
+ return callback(!result.response.returnObj.statusField);
887
+ });
888
+ });
889
+ } catch (ex) {
890
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
891
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
892
+ return callback(null, errorObj);
893
+ }
894
+ }
895
+
896
+ /**
897
+ * @summary Gets a config for the provided Appliance
898
+ *
899
+ * @function getConfig
900
+ * @param {String} deviceName - the deviceName of the appliance. (required)
901
+ * @param {String} format - the desired format of the config. (optional)
902
+ *
903
+ * @param {configCallback} callback - callback function to return the result
904
+ * (appliance config) or the error
905
+ */
906
+ getConfig(deviceName, format, callback) {
907
+ const meth = 'adapter-getConfig';
908
+ const origin = `${this.id}-${meth}`;
909
+ log.trace(origin);
910
+
911
+ // verify the required fields have been provided
912
+ if (deviceName === undefined || deviceName === null || deviceName === '' || deviceName.length === 0) {
913
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['deviceName'], null, null, null);
914
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
915
+ return callback(null, errorObj);
916
+ }
917
+
918
+ try {
919
+ // need to get the device so we can convert the deviceName to an id
920
+ // !! if we can do a lookup by name the getDevicesFiltered may not be necessary
921
+ const opts = {
922
+ filter: {
923
+ name: deviceName
924
+ }
925
+ };
926
+ return this.getDevicesFiltered(opts, (devs, ferr) => {
927
+ // if we received an error or their is no response on the results return an error
928
+ if (ferr) {
929
+ return callback(null, ferr);
930
+ }
931
+ if (devs.list.length < 1) {
932
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Did Not Find Device ${deviceName}`, [], null, null, null);
933
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
934
+ return callback(null, errorObj);
935
+ }
936
+ // get the uuid from the device
937
+ const { uuid } = devs.list[0];
938
+
939
+ // !! using Generic makes it easier on the Adapter Builder (just need to change the path)
940
+ // !! you can also replace with a specific call if that is easier
941
+ const uriPath = `/call/toget/config/${uuid}`;
942
+ return this.genericAdapterRequest(uriPath, 'GET', {}, {}, {}, (result, error) => {
943
+ // if we received an error or their is no response on the results return an error
944
+ if (error) {
945
+ return callback(null, error);
946
+ }
947
+
948
+ // return the result
949
+ const newResponse = {
950
+ response: JSON.stringify(result.response, null, 2)
951
+ };
952
+ return callback(newResponse);
953
+ });
954
+ });
955
+ } catch (ex) {
956
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
957
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
958
+ return callback(null, errorObj);
959
+ }
960
+ }
961
+
962
+ /**
963
+ * @summary Gets the device count from the system
964
+ *
965
+ * @function getCount
966
+ *
967
+ * @param {getCallback} callback - callback function to return the result
968
+ * (count) or the error
969
+ */
970
+ getCount(callback) {
971
+ const meth = 'adapter-getCount';
972
+ const origin = `${this.id}-${meth}`;
973
+ log.trace(origin);
974
+
975
+ // verify the required fields have been provided
976
+
977
+ try {
978
+ // !! using Generic makes it easier on the Adapter Builder (just need to change the path)
979
+ // !! you can also replace with a specific call if that is easier
980
+ const uriPath = '/call/toget/count';
981
+ return this.genericAdapterRequest(uriPath, 'GET', {}, {}, {}, (result, error) => {
982
+ // if we received an error or their is no response on the results return an error
983
+ if (error) {
984
+ return callback(null, error);
985
+ }
986
+
987
+ // return the result
988
+ return callback({ count: result.response });
989
+ });
990
+ } catch (ex) {
991
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
992
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
993
+ return callback(null, errorObj);
994
+ }
995
+ }
996
+
529
997
  /**
530
998
  * @callback healthCallback
531
999
  * @param {Object} result - the result of the get request (contains an id and a status)