@itentialopensource/adapter-meraki 0.8.0 → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/adapterBase.js CHANGED
@@ -8,6 +8,7 @@
8
8
  /* eslint no-cond-assign: warn */
9
9
  /* eslint global-require: warn */
10
10
  /* eslint no-unused-vars: warn */
11
+ /* eslint prefer-destructuring: warn */
11
12
 
12
13
  /* Required libraries. */
13
14
  const fs = require('fs-extra');
@@ -143,6 +144,44 @@ function updatePackage(changes) {
143
144
  return null;
144
145
  }
145
146
 
147
+ /*
148
+ * INTERNAL FUNCTION: get data from source(s) - nested
149
+ */
150
+ function getDataFromSources(loopField, sources) {
151
+ const loopArray = loopField.split('.');
152
+ let fieldValue = loopField;
153
+
154
+ // go through the sources to find the field
155
+ for (let s = 0; s < sources.length; s += 1) {
156
+ let nestedValue = sources[s];
157
+ let found = false;
158
+
159
+ // loops through incase the field is nested
160
+ for (let i = 0; i < loopArray.length; i += 1) {
161
+ // if not nested finds it first pass - otherwise set to new level and loop
162
+ if (Object.hasOwnProperty.call(nestedValue, loopArray[i])) {
163
+ nestedValue = nestedValue[loopArray[i]];
164
+
165
+ // set found if we are at the leaf (going to stop looping)
166
+ if (i + 1 === loopArray.length) {
167
+ found = true;
168
+ }
169
+ } else {
170
+ // not found in source - check next one
171
+ break;
172
+ }
173
+ }
174
+
175
+ // if we found in source - set and no need to check other sources
176
+ if (found) {
177
+ fieldValue = nestedValue;
178
+ break;
179
+ }
180
+ }
181
+
182
+ return fieldValue;
183
+ }
184
+
146
185
  /* GENERAL ADAPTER FUNCTIONS THESE SHOULD NOT BE DIRECTLY MODIFIED */
147
186
  /* IF YOU NEED MODIFICATIONS, REDEFINE THEM IN adapter.js!!! */
148
187
  class AdapterBase extends EventEmitterCl {
@@ -154,6 +193,9 @@ class AdapterBase extends EventEmitterCl {
154
193
  // Instantiate the EventEmitter super class
155
194
  super();
156
195
 
196
+ // IAP home directory injected by core when running the adapter within IAP
197
+ process.env.iap_home = process.argv[3];
198
+
157
199
  try {
158
200
  // Capture the adapter id
159
201
  this.id = prongid;
@@ -277,129 +319,6 @@ class AdapterBase extends EventEmitterCl {
277
319
  }
278
320
  }
279
321
 
280
- /**
281
- * updateAdapterConfiguration is used to update any of the adapter configuration files. This
282
- * allows customers to make changes to adapter configuration without having to be on the
283
- * file system.
284
- *
285
- * @function updateAdapterConfiguration
286
- * @param {string} configFile - the name of the file being updated (required)
287
- * @param {Object} changes - an object containing all of the changes = formatted like the configuration file (required)
288
- * @param {string} entity - the entity to be changed, if an action, schema or mock data file (optional)
289
- * @param {string} type - the type of entity file to change, (action, schema, mock) (optional)
290
- * @param {string} action - the action to be changed, if an action, schema or mock data file (optional)
291
- * @param {Callback} callback - The results of the call
292
- */
293
- updateAdapterConfiguration(configFile, changes, entity, type, action, callback) {
294
- const meth = 'adapterBase-updateAdapterConfiguration';
295
- const origin = `${this.id}-${meth}`;
296
- log.trace(origin);
297
-
298
- // verify the parameters are valid
299
- if (changes === undefined || changes === null || typeof changes !== 'object'
300
- || Object.keys(changes).length === 0) {
301
- const result = {
302
- response: 'No configuration updates to make'
303
- };
304
- log.info(result.response);
305
- return callback(result, null);
306
- }
307
- if (configFile === undefined || configFile === null || configFile === '') {
308
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['configFile'], null, null, null);
309
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
310
- return callback(null, errorObj);
311
- }
312
-
313
- // take action based on configFile being changed
314
- if (configFile === 'package.json') {
315
- const pres = updatePackage(changes);
316
- if (pres) {
317
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Incomplete Configuration Change: ${pres}`, [], null, null, null);
318
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
319
- return callback(null, errorObj);
320
- }
321
- const result = {
322
- response: 'Package updates completed - restarting adapter'
323
- };
324
- log.info(result.response);
325
- forceFail(true);
326
- return callback(result, null);
327
- }
328
- if (entity === undefined || entity === null || entity === '') {
329
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Unsupported Configuration Change or Missing Entity', [], null, null, null);
330
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
331
- return callback(null, errorObj);
332
- }
333
-
334
- // this means we are changing an entity file so type is required
335
- if (type === undefined || type === null || type === '') {
336
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['type'], null, null, null);
337
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
338
- return callback(null, errorObj);
339
- }
340
-
341
- // if the entity does not exist - error
342
- const epath = `${__dirname}/entities/${entity}`;
343
- if (!fs.existsSync(epath)) {
344
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Incomplete Configuration Change: Invalid Entity - ${entity}`, [], null, null, null);
345
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
346
- return callback(null, errorObj);
347
- }
348
-
349
- // take action based on type of file being changed
350
- if (type === 'action') {
351
- // BACKUP???
352
- const ares = updateAction(epath, action, changes);
353
- if (ares) {
354
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Incomplete Configuration Change: ${ares}`, [], null, null, null);
355
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
356
- return callback(null, errorObj);
357
- }
358
- // AJV CHECK???
359
- // RESTORE IF NEEDED???
360
- const result = {
361
- response: `Action updates completed to entity: ${entity} - ${action}`
362
- };
363
- log.info(result.response);
364
- return callback(result, null);
365
- }
366
- if (type === 'schema') {
367
- const sres = updateSchema(epath, configFile, changes);
368
- if (sres) {
369
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Incomplete Configuration Change: ${sres}`, [], null, null, null);
370
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
371
- return callback(null, errorObj);
372
- }
373
- const result = {
374
- response: `Schema updates completed to entity: ${entity} - ${configFile}`
375
- };
376
- log.info(result.response);
377
- return callback(result, null);
378
- }
379
- if (type === 'mock') {
380
- // if the mock directory does not exist - error
381
- const mpath = `${__dirname}/entities/${entity}/mockdatafiles`;
382
- if (!fs.existsSync(mpath)) {
383
- fs.mkdirSync(mpath);
384
- }
385
-
386
- const mres = updateMock(mpath, configFile, changes);
387
- if (mres) {
388
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Incomplete Configuration Change: ${mres}`, [], null, null, null);
389
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
390
- return callback(null, errorObj);
391
- }
392
- const result = {
393
- response: `Mock data updates completed to entity: ${entity} - ${configFile}`
394
- };
395
- log.info(result.response);
396
- return callback(result, null);
397
- }
398
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Incomplete Configuration Change: Unsupported Type - ${type}`, [], null, null, null);
399
- log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
400
- return callback(null, errorObj);
401
- }
402
-
403
322
  /**
404
323
  * @summary Connect function is used during Pronghorn startup to provide instantiation feedback.
405
324
  *
@@ -468,7 +387,7 @@ class AdapterBase extends EventEmitterCl {
468
387
  }
469
388
 
470
389
  // call to the healthcheck in connector
471
- return this.requestHandlerInst.identifyHealthcheck(reqObj, (res, error) => {
390
+ return this.requestHandlerInst.identifyHealthcheck(myRequest, (res, error) => {
472
391
  // unhealthy
473
392
  if (error) {
474
393
  // if we were healthy, toggle health
@@ -500,68 +419,6 @@ class AdapterBase extends EventEmitterCl {
500
419
  });
501
420
  }
502
421
 
503
- /**
504
- * @summary Suspends the adapter
505
- * @param {Callback} callback - The adapater suspension status
506
- * @function suspend
507
- */
508
- suspend(mode, callback) {
509
- const origin = `${this.id}-adapterBase-suspend`;
510
- if (this.suspended) {
511
- throw new Error(`${origin}: Adapter is already suspended`);
512
- }
513
- try {
514
- this.suspended = true;
515
- this.suspendMode = mode;
516
- if (this.suspendMode === 'pause') {
517
- const props = JSON.parse(JSON.stringify(this.initProps));
518
- // To suspend adapter, enable throttling and set concurrent max to 0
519
- props.throttle.throttle_enabled = true;
520
- props.throttle.concurrent_max = 0;
521
- this.refreshProperties(props);
522
- }
523
- return callback({ suspended: true });
524
- } catch (error) {
525
- return callback(null, error);
526
- }
527
- }
528
-
529
- /**
530
- * @summary Unsuspends the adapter
531
- * @param {Callback} callback - The adapater suspension status
532
- *
533
- * @function unsuspend
534
- */
535
- unsuspend(callback) {
536
- const origin = `${this.id}-adapterBase-unsuspend`;
537
- if (!this.suspended) {
538
- throw new Error(`${origin}: Adapter is not suspended`);
539
- }
540
- if (this.suspendMode === 'pause') {
541
- const props = JSON.parse(JSON.stringify(this.initProps));
542
- // To unsuspend adapter, keep throttling enabled and begin processing queued requests in order
543
- props.throttle.throttle_enabled = true;
544
- props.throttle.concurrent_max = 1;
545
- this.refreshProperties(props);
546
- setTimeout(() => {
547
- this.getQueue((q, error) => {
548
- // console.log("Items in queue: " + String(q.length))
549
- if (q.length === 0) {
550
- // if queue is empty, return to initial properties state
551
- this.refreshProperties(this.initProps);
552
- this.suspended = false;
553
- return callback({ suspended: false });
554
- }
555
- // recursive call to check queue again every second
556
- return this.unsuspend(callback);
557
- });
558
- }, 1000);
559
- } else {
560
- this.suspended = false;
561
- callback({ suspend: false });
562
- }
563
- }
564
-
565
422
  /**
566
423
  * getAllFunctions is used to get all of the exposed function in the adapter
567
424
  *
@@ -587,12 +444,67 @@ class AdapterBase extends EventEmitterCl {
587
444
  }
588
445
 
589
446
  /**
590
- * getWorkflowFunctions is used to get all of the workflow function in the adapter
447
+ * checkActionFiles is used to update the validation of the action files.
448
+ *
449
+ * @function checkActionFiles
450
+ */
451
+ checkActionFiles() {
452
+ const origin = `${this.id}-adapterBase-checkActionFiles`;
453
+ log.trace(origin);
454
+
455
+ // validate the action files for the adapter
456
+ try {
457
+ return this.requestHandlerInst.checkActionFiles();
458
+ } catch (e) {
459
+ return ['Exception increase log level'];
460
+ }
461
+ }
462
+
463
+ /**
464
+ * checkProperties is used to validate the adapter properties.
465
+ *
466
+ * @function checkProperties
467
+ * @param {Object} properties - an object containing all of the properties
468
+ */
469
+ checkProperties(properties) {
470
+ const origin = `${this.myid}-adapterBase-checkProperties`;
471
+ log.trace(origin);
472
+
473
+ // validate the properties for the adapter
474
+ try {
475
+ return this.requestHandlerInst.checkProperties(properties);
476
+ } catch (e) {
477
+ return { exception: 'Exception increase log level' };
478
+ }
479
+ }
480
+
481
+ /**
482
+ * @summary Takes in property text and an encoding/encryption and returns the resulting
483
+ * encoded/encrypted string
484
+ *
485
+ * @function encryptProperty
486
+ * @param {String} property - the property to encrypt
487
+ * @param {String} technique - the technique to use to encrypt
488
+ *
489
+ * @param {Callback} callback - a callback function to return the result
490
+ * Encrypted String or the Error
491
+ */
492
+ encryptProperty(property, technique, callback) {
493
+ const origin = `${this.id}-adapterBase-encryptProperty`;
494
+ log.trace(origin);
495
+
496
+ // Make the call -
497
+ // encryptProperty(property, technique, callback)
498
+ return this.requestHandlerInst.encryptProperty(property, technique, callback);
499
+ }
500
+
501
+ /**
502
+ * iapGetAdapterWorkflowFunctions is used to get all of the workflow function in the adapter
591
503
  * @param {array} ignoreThese - additional methods to ignore (optional)
592
504
  *
593
- * @function getWorkflowFunctions
505
+ * @function iapGetAdapterWorkflowFunctions
594
506
  */
595
- getWorkflowFunctions(ignoreThese) {
507
+ iapGetAdapterWorkflowFunctions(ignoreThese) {
596
508
  const myfunctions = this.getAllFunctions();
597
509
  const wffunctions = [];
598
510
 
@@ -602,9 +514,7 @@ class AdapterBase extends EventEmitterCl {
602
514
  // got to the second tier (adapterBase)
603
515
  break;
604
516
  }
605
- if (myfunctions[m] !== 'hasEntity' && myfunctions[m] !== 'verifyCapability' && myfunctions[m] !== 'updateEntityCache'
606
- && myfunctions[m] !== 'healthCheck' && myfunctions[m] !== 'getWorkflowFunctions'
607
- && !(myfunctions[m].endsWith('Emit') || myfunctions[m].match(/Emit__v[0-9]+/))) {
517
+ if (!(myfunctions[m].endsWith('Emit') || myfunctions[m].match(/Emit__v[0-9]+/))) {
608
518
  let found = false;
609
519
  if (ignoreThese && Array.isArray(ignoreThese)) {
610
520
  for (let i = 0; i < ignoreThese.length; i += 1) {
@@ -623,30 +533,136 @@ class AdapterBase extends EventEmitterCl {
623
533
  }
624
534
 
625
535
  /**
626
- * checkActionFiles is used to update the validation of the action files.
536
+ * iapUpdateAdapterConfiguration is used to update any of the adapter configuration files. This
537
+ * allows customers to make changes to adapter configuration without having to be on the
538
+ * file system.
627
539
  *
628
- * @function checkActionFiles
540
+ * @function iapUpdateAdapterConfiguration
541
+ * @param {string} configFile - the name of the file being updated (required)
542
+ * @param {Object} changes - an object containing all of the changes = formatted like the configuration file (required)
543
+ * @param {string} entity - the entity to be changed, if an action, schema or mock data file (optional)
544
+ * @param {string} type - the type of entity file to change, (action, schema, mock) (optional)
545
+ * @param {string} action - the action to be changed, if an action, schema or mock data file (optional)
546
+ * @param {Callback} callback - The results of the call
629
547
  */
630
- checkActionFiles() {
631
- const origin = `${this.id}-adapterBase-checkActionFiles`;
548
+ iapUpdateAdapterConfiguration(configFile, changes, entity, type, action, callback) {
549
+ const meth = 'adapterBase-iapUpdateAdapterConfiguration';
550
+ const origin = `${this.id}-${meth}`;
632
551
  log.trace(origin);
633
552
 
634
- // validate the action files for the adapter
635
- try {
636
- return this.requestHandlerInst.checkActionFiles();
637
- } catch (e) {
638
- return ['Exception increase log level'];
553
+ // verify the parameters are valid
554
+ if (changes === undefined || changes === null || typeof changes !== 'object'
555
+ || Object.keys(changes).length === 0) {
556
+ const result = {
557
+ response: 'No configuration updates to make'
558
+ };
559
+ log.info(result.response);
560
+ return callback(result, null);
561
+ }
562
+ if (configFile === undefined || configFile === null || configFile === '') {
563
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['configFile'], null, null, null);
564
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
565
+ return callback(null, errorObj);
566
+ }
567
+
568
+ // take action based on configFile being changed
569
+ if (configFile === 'package.json') {
570
+ const pres = updatePackage(changes);
571
+ if (pres) {
572
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Incomplete Configuration Change: ${pres}`, [], null, null, null);
573
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
574
+ return callback(null, errorObj);
575
+ }
576
+ const result = {
577
+ response: 'Package updates completed - restarting adapter'
578
+ };
579
+ log.info(result.response);
580
+ forceFail(true);
581
+ return callback(result, null);
582
+ }
583
+ if (entity === undefined || entity === null || entity === '') {
584
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Unsupported Configuration Change or Missing Entity', [], null, null, null);
585
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
586
+ return callback(null, errorObj);
587
+ }
588
+
589
+ // this means we are changing an entity file so type is required
590
+ if (type === undefined || type === null || type === '') {
591
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['type'], null, null, null);
592
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
593
+ return callback(null, errorObj);
594
+ }
595
+
596
+ // if the entity does not exist - error
597
+ const epath = `${__dirname}/entities/${entity}`;
598
+ if (!fs.existsSync(epath)) {
599
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Incomplete Configuration Change: Invalid Entity - ${entity}`, [], null, null, null);
600
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
601
+ return callback(null, errorObj);
602
+ }
603
+
604
+ // take action based on type of file being changed
605
+ if (type === 'action') {
606
+ // BACKUP???
607
+ const ares = updateAction(epath, action, changes);
608
+ if (ares) {
609
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Incomplete Configuration Change: ${ares}`, [], null, null, null);
610
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
611
+ return callback(null, errorObj);
612
+ }
613
+ // AJV CHECK???
614
+ // RESTORE IF NEEDED???
615
+ const result = {
616
+ response: `Action updates completed to entity: ${entity} - ${action}`
617
+ };
618
+ log.info(result.response);
619
+ return callback(result, null);
620
+ }
621
+ if (type === 'schema') {
622
+ const sres = updateSchema(epath, configFile, changes);
623
+ if (sres) {
624
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Incomplete Configuration Change: ${sres}`, [], null, null, null);
625
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
626
+ return callback(null, errorObj);
627
+ }
628
+ const result = {
629
+ response: `Schema updates completed to entity: ${entity} - ${configFile}`
630
+ };
631
+ log.info(result.response);
632
+ return callback(result, null);
633
+ }
634
+ if (type === 'mock') {
635
+ // if the mock directory does not exist - error
636
+ const mpath = `${__dirname}/entities/${entity}/mockdatafiles`;
637
+ if (!fs.existsSync(mpath)) {
638
+ fs.mkdirSync(mpath);
639
+ }
640
+
641
+ const mres = updateMock(mpath, configFile, changes);
642
+ if (mres) {
643
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Incomplete Configuration Change: ${mres}`, [], null, null, null);
644
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
645
+ return callback(null, errorObj);
646
+ }
647
+ const result = {
648
+ response: `Mock data updates completed to entity: ${entity} - ${configFile}`
649
+ };
650
+ log.info(result.response);
651
+ return callback(result, null);
639
652
  }
653
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Incomplete Configuration Change: Unsupported Type - ${type}`, [], null, null, null);
654
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
655
+ return callback(null, errorObj);
640
656
  }
641
657
 
642
658
  /**
643
659
  * See if the API path provided is found in this adapter
644
660
  *
645
- * @function findPath
661
+ * @function iapFindAdapterPath
646
662
  * @param {string} apiPath - the api path to check on
647
663
  * @param {Callback} callback - The results of the call
648
664
  */
649
- findPath(apiPath, callback) {
665
+ iapFindAdapterPath(apiPath, callback) {
650
666
  const result = {
651
667
  apiPath
652
668
  };
@@ -723,66 +739,90 @@ class AdapterBase extends EventEmitterCl {
723
739
  }
724
740
 
725
741
  /**
726
- * checkProperties is used to validate the adapter properties.
727
- *
728
- * @function checkProperties
729
- * @param {Object} properties - an object containing all of the properties
742
+ * @summary Suspends the adapter
743
+ * @param {Callback} callback - The adapater suspension status
744
+ * @function iapSuspendAdapter
730
745
  */
731
- checkProperties(properties) {
732
- const origin = `${this.myid}-adapterBase-checkProperties`;
733
- log.trace(origin);
734
-
735
- // validate the properties for the adapter
746
+ iapSuspendAdapter(mode, callback) {
747
+ const origin = `${this.id}-adapterBase-iapSuspendAdapter`;
748
+ if (this.suspended) {
749
+ throw new Error(`${origin}: Adapter is already suspended`);
750
+ }
736
751
  try {
737
- return this.requestHandlerInst.checkProperties(properties);
738
- } catch (e) {
739
- return { exception: 'Exception increase log level' };
752
+ this.suspended = true;
753
+ this.suspendMode = mode;
754
+ if (this.suspendMode === 'pause') {
755
+ const props = JSON.parse(JSON.stringify(this.initProps));
756
+ // To suspend adapter, enable throttling and set concurrent max to 0
757
+ props.throttle.throttle_enabled = true;
758
+ props.throttle.concurrent_max = 0;
759
+ this.refreshProperties(props);
760
+ }
761
+ return callback({ suspended: true });
762
+ } catch (error) {
763
+ return callback(null, error);
740
764
  }
741
765
  }
742
766
 
743
767
  /**
744
- * getQueue is used to get information for all of the requests currently in the queue.
768
+ * @summary Unsuspends the adapter
769
+ * @param {Callback} callback - The adapater suspension status
745
770
  *
746
- * @function getQueue
747
- * @param {Callback} callback - a callback function to return the result (Queue) or the error
771
+ * @function iapUnsuspendAdapter
748
772
  */
749
- getQueue(callback) {
750
- const origin = `${this.id}-adapterBase-getQueue`;
751
- log.trace(origin);
752
-
753
- return this.requestHandlerInst.getQueue(callback);
773
+ iapUnsuspendAdapter(callback) {
774
+ const origin = `${this.id}-adapterBase-iapUnsuspendAdapter`;
775
+ if (!this.suspended) {
776
+ throw new Error(`${origin}: Adapter is not suspended`);
777
+ }
778
+ if (this.suspendMode === 'pause') {
779
+ const props = JSON.parse(JSON.stringify(this.initProps));
780
+ // To unsuspend adapter, keep throttling enabled and begin processing queued requests in order
781
+ props.throttle.throttle_enabled = true;
782
+ props.throttle.concurrent_max = 1;
783
+ this.refreshProperties(props);
784
+ setTimeout(() => {
785
+ this.getQueue((q, error) => {
786
+ // console.log("Items in queue: " + String(q.length))
787
+ if (q.length === 0) {
788
+ // if queue is empty, return to initial properties state
789
+ this.refreshProperties(this.initProps);
790
+ this.suspended = false;
791
+ return callback({ suspended: false });
792
+ }
793
+ // recursive call to check queue again every second
794
+ return this.iapUnsuspendAdapter(callback);
795
+ });
796
+ }, 1000);
797
+ } else {
798
+ this.suspended = false;
799
+ callback({ suspend: false });
800
+ }
754
801
  }
755
802
 
756
803
  /**
757
- * @summary Takes in property text and an encoding/encryption and returns the resulting
758
- * encoded/encrypted string
804
+ * iapGetAdapterQueue is used to get information for all of the requests currently in the queue.
759
805
  *
760
- * @function encryptProperty
761
- * @param {String} property - the property to encrypt
762
- * @param {String} technique - the technique to use to encrypt
763
- *
764
- * @param {Callback} callback - a callback function to return the result
765
- * Encrypted String or the Error
806
+ * @function iapGetAdapterQueue
807
+ * @param {Callback} callback - a callback function to return the result (Queue) or the error
766
808
  */
767
- encryptProperty(property, technique, callback) {
768
- const origin = `${this.id}-adapterBase-encryptProperty`;
809
+ iapGetAdapterQueue(callback) {
810
+ const origin = `${this.id}-adapterBase-iapGetAdapterQueue`;
769
811
  log.trace(origin);
770
812
 
771
- // Make the call -
772
- // encryptProperty(property, technique, callback)
773
- return this.requestHandlerInst.encryptProperty(property, technique, callback);
813
+ return this.requestHandlerInst.getQueue(callback);
774
814
  }
775
815
 
776
816
  /**
777
817
  * @summary runs troubleshoot scripts for adapter
778
818
  *
779
- * @function troubleshoot
819
+ * @function iapTroubleshootAdapter
780
820
  * @param {Object} props - the connection, healthcheck and authentication properties
781
821
  * @param {boolean} persistFlag - whether the adapter properties should be updated
782
822
  * @param {Adapter} adapter - adapter instance to troubleshoot
783
823
  * @param {Callback} callback - callback function to return troubleshoot results
784
824
  */
785
- async troubleshoot(props, persistFlag, adapter, callback) {
825
+ async iapTroubleshootAdapter(props, persistFlag, adapter, callback) {
786
826
  try {
787
827
  const result = await troubleshootingAdapter.troubleshoot(props, false, persistFlag, adapter);
788
828
  if (result.healthCheck && result.connectivity.failCount === 0 && result.basicGet.failCount === 0) {
@@ -797,11 +837,11 @@ class AdapterBase extends EventEmitterCl {
797
837
  /**
798
838
  * @summary runs healthcheck script for adapter
799
839
  *
800
- * @function runHealthcheck
840
+ * @function iapRunAdapterHealthcheck
801
841
  * @param {Adapter} adapter - adapter instance to troubleshoot
802
842
  * @param {Callback} callback - callback function to return healthcheck status
803
843
  */
804
- async runHealthcheck(adapter, callback) {
844
+ async iapRunAdapterHealthcheck(adapter, callback) {
805
845
  try {
806
846
  const result = await tbUtils.healthCheck(adapter);
807
847
  if (result) {
@@ -816,11 +856,11 @@ class AdapterBase extends EventEmitterCl {
816
856
  /**
817
857
  * @summary runs connectivity check script for adapter
818
858
  *
819
- * @function runConnectivity
859
+ * @function iapRunAdapterConnectivity
820
860
  * @param {Adapter} adapter - adapter instance to troubleshoot
821
861
  * @param {Callback} callback - callback function to return connectivity status
822
862
  */
823
- async runConnectivity(callback) {
863
+ async iapRunAdapterConnectivity(callback) {
824
864
  try {
825
865
  const { serviceItem } = await tbUtils.getAdapterConfig();
826
866
  const { host } = serviceItem.properties.properties;
@@ -837,10 +877,10 @@ class AdapterBase extends EventEmitterCl {
837
877
  /**
838
878
  * @summary runs basicGet script for adapter
839
879
  *
840
- * @function runBasicGet
880
+ * @function iapRunAdapterBasicGet
841
881
  * @param {Callback} callback - callback function to return basicGet result
842
882
  */
843
- runBasicGet(callback) {
883
+ iapRunAdapterBasicGet(callback) {
844
884
  try {
845
885
  const result = tbUtils.runBasicGet(false);
846
886
  if (result.failCount > 0) {
@@ -852,6 +892,27 @@ class AdapterBase extends EventEmitterCl {
852
892
  }
853
893
  }
854
894
 
895
+ /**
896
+ * @summary moves entities to mongo database
897
+ *
898
+ * @function iapMoveAdapterEntitiesToDB
899
+ *
900
+ * @return {Callback} - containing the response from the mongo transaction
901
+ */
902
+ iapMoveAdapterEntitiesToDB(callback) {
903
+ const meth = 'adapterBase-iapMoveAdapterEntitiesToDB';
904
+ const origin = `${this.id}-${meth}`;
905
+ log.trace(origin);
906
+
907
+ try {
908
+ return callback(entitiesToDB.iapMoveAdapterEntitiesToDB(__dirname, { pronghornProps: this.allProps, id: this.id }), null);
909
+ } catch (err) {
910
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, err);
911
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
912
+ return callback(null, errorObj);
913
+ }
914
+ }
915
+
855
916
  /**
856
917
  * @summary take the entities and add them to the cache
857
918
  *
@@ -1004,21 +1065,681 @@ class AdapterBase extends EventEmitterCl {
1004
1065
  }
1005
1066
 
1006
1067
  /**
1007
- * @summary moves entities to mongo database
1068
+ * @summary Determines if this adapter supports any in a list of entities
1008
1069
  *
1009
- * @function moveEntitiesToDB
1070
+ * @function hasEntities
1071
+ * @param {String} entityType - the entity type to check for
1072
+ * @param {Array} entityList - the list of entities we are looking for
1010
1073
  *
1011
- * @return {Callback} - containing the response from the mongo transaction
1074
+ * @param {Callback} callback - A map where the entity is the key and the
1075
+ * value is true or false
1076
+ */
1077
+ hasEntities(entityType, entityList, callback) {
1078
+ const origin = `${this.id}-adapter-hasEntities`;
1079
+ log.trace(origin);
1080
+
1081
+ switch (entityType) {
1082
+ case 'Device':
1083
+ return this.hasDevices(entityList, callback);
1084
+ default:
1085
+ return callback(null, `${this.id} does not support entity ${entityType}`);
1086
+ }
1087
+ }
1088
+
1089
+ /**
1090
+ * @summary Helper method for hasEntities for the specific device case
1091
+ *
1092
+ * @param {Array} deviceList - array of unique device identifiers
1093
+ * @param {Callback} callback - A map where the device is the key and the
1094
+ * value is true or false
1095
+ */
1096
+ hasDevices(deviceList, callback) {
1097
+ const origin = `${this.id}-adapter-hasDevices`;
1098
+ log.trace(origin);
1099
+
1100
+ const findings = deviceList.reduce((map, device) => {
1101
+ // eslint-disable-next-line no-param-reassign
1102
+ map[device] = false;
1103
+ log.debug(`In reduce: ${JSON.stringify(map)}`);
1104
+ return map;
1105
+ }, {});
1106
+ const apiCalls = deviceList.map((device) => new Promise((resolve) => {
1107
+ this.getDevice(device, (result, error) => {
1108
+ if (error) {
1109
+ log.debug(`In map error: ${JSON.stringify(device)}`);
1110
+ return resolve({ name: device, found: false });
1111
+ }
1112
+ log.debug(`In map: ${JSON.stringify(device)}`);
1113
+ return resolve({ name: device, found: true });
1114
+ });
1115
+ }));
1116
+ Promise.all(apiCalls).then((results) => {
1117
+ results.forEach((device) => {
1118
+ findings[device.name] = device.found;
1119
+ });
1120
+ log.debug(`FINDINGS: ${JSON.stringify(findings)}`);
1121
+ return callback(findings);
1122
+ }).catch((errors) => {
1123
+ log.error('Unable to do device lookup.');
1124
+ return callback(null, { code: 503, message: 'Unable to do device lookup.', error: errors });
1125
+ });
1126
+ }
1127
+
1128
+ /**
1129
+ * @summary Make one of the needed Broker calls - could be one of many
1130
+ *
1131
+ * @function iapMakeBrokerCall
1132
+ * @param {string} brokCall - the name of the broker call (required)
1133
+ * @param {object} callProps - the proeprties for the broker call (required)
1134
+ * @param {object} devResp - the device details to extract needed inputs (required)
1135
+ * @param {string} filterName - any filter to search on (required)
1136
+ *
1137
+ * @param {getCallback} callback - a callback function to return the result of the call
1012
1138
  */
1013
- moveEntitiesToDB(callback) {
1014
- const meth = 'adapterBase-moveEntitiesToDB';
1139
+ iapMakeBrokerCall(brokCall, callProps, devResp, filterName, callback) {
1140
+ const meth = 'adapterBase-iapMakeBrokerCall';
1015
1141
  const origin = `${this.id}-${meth}`;
1016
1142
  log.trace(origin);
1017
1143
 
1018
1144
  try {
1019
- return callback(entitiesToDB.moveEntitiesToDB(__dirname, { pronghornProps: this.allProps, id: this.id }), null);
1020
- } catch (err) {
1021
- const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, err);
1145
+ let uriPath = '';
1146
+ let uriMethod = 'GET';
1147
+ let callQuery = {};
1148
+ let callBody = {};
1149
+ let callHeaders = {};
1150
+ let handleFail = 'fail';
1151
+ let ostypePrefix = '';
1152
+ let statusValue = 'true';
1153
+ if (callProps.path) {
1154
+ uriPath = `${callProps.path}`;
1155
+
1156
+ // make any necessary changes to the path
1157
+ if (devResp !== null && callProps.requestFields && Object.keys(callProps.requestFields).length > 0) {
1158
+ const rqKeys = Object.keys(callProps.requestFields);
1159
+
1160
+ // get the field from the provided device
1161
+ for (let rq = 0; rq < rqKeys.length; rq += 1) {
1162
+ const fieldValue = getDataFromSources(callProps.requestFields[rqKeys[rq]], devResp);
1163
+
1164
+ // put the value into the path - if it has been specified in the path
1165
+ uriPath = uriPath.replace(`{${rqKeys[rq]}}`, fieldValue);
1166
+ }
1167
+ }
1168
+ }
1169
+ if (callProps.method) {
1170
+ uriMethod = callProps.method;
1171
+ }
1172
+ if (callProps.query) {
1173
+ callQuery = callProps.query;
1174
+
1175
+ // go through the query params to check for variable values
1176
+ const cpKeys = Object.keys(callQuery);
1177
+ for (let cp = 0; cp < cpKeys.length; cp += 1) {
1178
+ if (callQuery[cpKeys[cp]].startsWith('{') && callQuery[cpKeys[cp]].endsWith('}')) {
1179
+ // make any necessary changes to the query params
1180
+ if (devResp !== null && callProps.requestFields && Object.keys(callProps.requestFields).length > 0) {
1181
+ const rqKeys = Object.keys(callProps.requestFields);
1182
+
1183
+ // get the field from the provided device
1184
+ for (let rq = 0; rq < rqKeys.length; rq += 1) {
1185
+ if (cpKeys[cp] === rqKeys[rq]) {
1186
+ const fieldValue = getDataFromSources(callProps.requestFields[rqKeys[rq]], devResp);
1187
+
1188
+ // put the value into the query - if it has been specified in the query
1189
+ callQuery[cpKeys[cp]] = fieldValue;
1190
+ }
1191
+ }
1192
+ }
1193
+ }
1194
+ }
1195
+ }
1196
+ if (callProps.body) {
1197
+ callBody = callProps.body;
1198
+ }
1199
+ if (callProps.headers) {
1200
+ callHeaders = callProps.headers;
1201
+ }
1202
+ if (callProps.handleFailure) {
1203
+ handleFail = callProps.handleFailure;
1204
+ }
1205
+ if (callProps.responseFields && callProps.responseFields.ostypePrefix) {
1206
+ ostypePrefix = callProps.responseFields.ostypePrefix;
1207
+ }
1208
+ if (callProps.responseFields && callProps.responseFields.statusValue) {
1209
+ statusValue = callProps.responseFields.statusValue;
1210
+ }
1211
+
1212
+ // !! using Generic makes it easier on the Adapter Builder (just need to change the path)
1213
+ // !! you can also replace with a specific call if that is easier
1214
+ return this.genericAdapterRequest(uriPath, uriMethod, callQuery, callBody, callHeaders, (result, error) => {
1215
+ // if we received an error or their is no response on the results return an error
1216
+ if (error) {
1217
+ if (handleFail === 'fail') {
1218
+ return callback(null, error);
1219
+ }
1220
+ return callback({}, null);
1221
+ }
1222
+ if (!result.response) {
1223
+ if (handleFail === 'fail') {
1224
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Invalid Response', [brokCall], null, null, null);
1225
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1226
+ return callback(null, errorObj);
1227
+ }
1228
+ return callback({}, null);
1229
+ }
1230
+
1231
+ // get the keys for the response fields
1232
+ let rfKeys = [];
1233
+ if (callProps.responseFields && Object.keys(callProps.responseFields).length > 0) {
1234
+ rfKeys = Object.keys(callProps.responseFields);
1235
+ }
1236
+
1237
+ // if we got an array returned (e.g. getDevicesFitered)
1238
+ if (Array.isArray(result.response)) {
1239
+ const listDevices = [];
1240
+ for (let a = 0; a < result.response.length; a += 1) {
1241
+ const thisDevice = result.response[a];
1242
+ for (let rf = 0; rf < rfKeys.length; rf += 1) {
1243
+ if (rfKeys[rf] !== 'ostypePrefix') {
1244
+ let fieldValue = getDataFromSources(callProps.responseFields[rfKeys[rf]], [thisDevice, devResp, callProps.requestFields]);
1245
+
1246
+ // if the field is ostype - need to add prefix
1247
+ if (rfKeys[rf] === 'ostype' && typeof fieldValue === 'string') {
1248
+ fieldValue = ostypePrefix + fieldValue;
1249
+ }
1250
+ // if there is a status to set, set it
1251
+ if (rfKeys[rf] === 'status') {
1252
+ // if really looking for just a good response
1253
+ if (callProps.responseFields[rfKeys[rf]] === 'return2xx' && result.icode === statusValue.toString()) {
1254
+ thisDevice.isAlive = true;
1255
+ } else if (fieldValue.toString() === statusValue.toString()) {
1256
+ thisDevice.isAlive = true;
1257
+ } else {
1258
+ thisDevice.isAlive = false;
1259
+ }
1260
+ }
1261
+ // if we found a good value
1262
+ thisDevice[rfKeys[rf]] = fieldValue;
1263
+ }
1264
+ }
1265
+
1266
+ // if there is no filter - add the device to the list
1267
+ if (!filterName || filterName.length === 0) {
1268
+ listDevices.push(thisDevice);
1269
+ } else {
1270
+ // if we have to match a filter
1271
+ let found = false;
1272
+ for (let f = 0; f < filterName.length; f += 1) {
1273
+ if (thisDevice.name.indexOf(filterName[f]) >= 0) {
1274
+ found = true;
1275
+ break;
1276
+ }
1277
+ }
1278
+ // matching device
1279
+ if (found) {
1280
+ listDevices.push(thisDevice);
1281
+ }
1282
+ }
1283
+ }
1284
+
1285
+ // return the array of devices
1286
+ return callback(listDevices, null);
1287
+ }
1288
+
1289
+ // if this is not an array - just about everything else, just handle as a single object
1290
+ let thisDevice = result.response;
1291
+ for (let rf = 0; rf < rfKeys.length; rf += 1) {
1292
+ // skip ostypePrefix since it is not a field
1293
+ if (rfKeys[rf] !== 'ostypePrefix') {
1294
+ let fieldValue = getDataFromSources(callProps.responseFields[rfKeys[rf]], [thisDevice, devResp, callProps.requestFields]);
1295
+
1296
+ // if the field is ostype - need to add prefix
1297
+ if (rfKeys[rf] === 'ostype' && typeof fieldValue === 'string') {
1298
+ fieldValue = ostypePrefix + fieldValue;
1299
+ }
1300
+ // if there is a status to set, set it
1301
+ if (rfKeys[rf] === 'status') {
1302
+ // if really looking for just a good response
1303
+ if (callProps.responseFields[rfKeys[rf]] === 'return2xx' && result.icode === statusValue.toString()) {
1304
+ thisDevice.isAlive = true;
1305
+ } else if (fieldValue.toString() === statusValue.toString()) {
1306
+ thisDevice.isAlive = true;
1307
+ } else {
1308
+ thisDevice.isAlive = false;
1309
+ }
1310
+ }
1311
+ // if we found a good value
1312
+ thisDevice[rfKeys[rf]] = fieldValue;
1313
+ }
1314
+ }
1315
+
1316
+ // if there is a filter - check the device is in the list
1317
+ if (filterName && filterName.length > 0) {
1318
+ let found = false;
1319
+ for (let f = 0; f < filterName.length; f += 1) {
1320
+ if (thisDevice.name.indexOf(filterName[f]) >= 0) {
1321
+ found = true;
1322
+ break;
1323
+ }
1324
+ }
1325
+ // no matching device - clear the device
1326
+ if (!found) {
1327
+ thisDevice = {};
1328
+ }
1329
+ }
1330
+
1331
+ return callback(thisDevice, null);
1332
+ });
1333
+ } catch (e) {
1334
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, e);
1335
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1336
+ return callback(null, errorObj);
1337
+ }
1338
+ }
1339
+
1340
+ /**
1341
+ * @summary Get Appliance that match the deviceName
1342
+ *
1343
+ * @function getDevice
1344
+ * @param {String} deviceName - the deviceName to find (required)
1345
+ *
1346
+ * @param {getCallback} callback - a callback function to return the result
1347
+ * (appliance) or the error
1348
+ */
1349
+ getDevice(deviceName, callback) {
1350
+ const meth = 'adapterBase-getDevice';
1351
+ const origin = `${this.id}-${meth}`;
1352
+ log.trace(origin);
1353
+
1354
+ // make sure we are set up for device broker getDevice
1355
+ if (!this.allProps.devicebroker || !this.allProps.devicebroker.getDevice || this.allProps.devicebroker.getDevice.length === 0 || !this.allProps.devicebroker.getDevice[0].path) {
1356
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Properties', ['devicebroker.getDevice.path'], null, null, null);
1357
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1358
+ return callback(null, errorObj);
1359
+ }
1360
+
1361
+ /* HERE IS WHERE YOU VALIDATE DATA */
1362
+ if (deviceName === undefined || deviceName === null || deviceName === '' || deviceName.length === 0) {
1363
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['deviceName'], null, null, null);
1364
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1365
+ return callback(null, errorObj);
1366
+ }
1367
+
1368
+ try {
1369
+ // need to get the device so we can convert the deviceName to an id
1370
+ // !! if we can do a lookup by name the getDevicesFiltered may not be necessary
1371
+ const opts = {
1372
+ filter: {
1373
+ name: deviceName
1374
+ }
1375
+ };
1376
+ return this.getDevicesFiltered(opts, (devs, ferr) => {
1377
+ // if we received an error or their is no response on the results return an error
1378
+ if (ferr) {
1379
+ return callback(null, ferr);
1380
+ }
1381
+ if (devs.list.length < 1) {
1382
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Did Not Find Device ${deviceName}`, [], null, null, null);
1383
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1384
+ return callback(null, errorObj);
1385
+ }
1386
+
1387
+ const callPromises = [];
1388
+ for (let i = 0; i < this.allProps.devicebroker.getDevice.length; i += 1) {
1389
+ // Perform component calls here.
1390
+ callPromises.push(
1391
+ new Promise((resolve, reject) => {
1392
+ this.iapMakeBrokerCall('getDevice', this.allProps.devicebroker.getDevice[i], [devs.list[0]], null, (callRet, callErr) => {
1393
+ // return an error
1394
+ if (callErr) {
1395
+ reject(callErr);
1396
+ } else {
1397
+ // return the data
1398
+ resolve(callRet);
1399
+ }
1400
+ });
1401
+ })
1402
+ );
1403
+ }
1404
+
1405
+ // return an array of repsonses
1406
+ return Promise.all(callPromises).then((results) => {
1407
+ let myResult = {};
1408
+ results.forEach((result) => {
1409
+ myResult = { ...myResult, ...result };
1410
+ });
1411
+
1412
+ return callback(myResult, null);
1413
+ });
1414
+ });
1415
+ } catch (ex) {
1416
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
1417
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1418
+ return callback(null, errorObj);
1419
+ }
1420
+ }
1421
+
1422
+ /**
1423
+ * @summary Get Appliances that match the filter
1424
+ *
1425
+ * @function getDevicesFiltered
1426
+ * @param {Object} options - the data to use to filter the appliances (optional)
1427
+ *
1428
+ * @param {getCallback} callback - a callback function to return the result
1429
+ * (appliances) or the error
1430
+ */
1431
+ getDevicesFiltered(options, callback) {
1432
+ const meth = 'adapterBase-getDevicesFiltered';
1433
+ const origin = `${this.id}-${meth}`;
1434
+ log.trace(origin);
1435
+
1436
+ // make sure we are set up for device broker getDevicesFiltered
1437
+ if (!this.allProps.devicebroker || !this.allProps.devicebroker.getDevicesFiltered || this.allProps.devicebroker.getDevicesFiltered.length === 0 || !this.allProps.devicebroker.getDevicesFiltered[0].path) {
1438
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Properties', ['devicebroker.getDevicesFiltered.path'], null, null, null);
1439
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1440
+ return callback(null, errorObj);
1441
+ }
1442
+
1443
+ // verify the required fields have been provided
1444
+ if (options === undefined || options === null || options === '' || options.length === 0) {
1445
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['options'], null, null, null);
1446
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1447
+ return callback(null, errorObj);
1448
+ }
1449
+ log.debug(`Device Filter Options: ${JSON.stringify(options)}`);
1450
+
1451
+ try {
1452
+ // TODO - get pagination working
1453
+ // const nextToken = options.start;
1454
+ // const maxResults = options.limit;
1455
+
1456
+ // set up the filter of Device Names
1457
+ let filterName = [];
1458
+ if (options && options.filter && options.filter.name) {
1459
+ // when this hack is removed, remove the lint ignore above
1460
+ if (Array.isArray(options.filter.name)) {
1461
+ // eslint-disable-next-line prefer-destructuring
1462
+ filterName = options.filter.name;
1463
+ } else {
1464
+ filterName = [options.filter.name];
1465
+ }
1466
+ }
1467
+
1468
+ // TODO - get sort and order working
1469
+ /*
1470
+ if (options && options.sort) {
1471
+ reqObj.uriOptions.sort = JSON.stringify(options.sort);
1472
+ }
1473
+ if (options && options.order) {
1474
+ reqObj.uriOptions.order = options.order;
1475
+ }
1476
+ */
1477
+ const callPromises = [];
1478
+ for (let i = 0; i < this.allProps.devicebroker.getDevicesFiltered.length; i += 1) {
1479
+ // Perform component calls here.
1480
+ callPromises.push(
1481
+ new Promise((resolve, reject) => {
1482
+ this.iapMakeBrokerCall('getDevicesFiltered', this.allProps.devicebroker.getDevicesFiltered[i], [{ fake: 'fakedata' }], filterName, (callRet, callErr) => {
1483
+ // return an error
1484
+ if (callErr) {
1485
+ reject(callErr);
1486
+ } else {
1487
+ // return the data
1488
+ resolve(callRet);
1489
+ }
1490
+ });
1491
+ })
1492
+ );
1493
+ }
1494
+
1495
+ // return an array of repsonses
1496
+ return Promise.all(callPromises).then((results) => {
1497
+ let myResult = [];
1498
+ results.forEach((result) => {
1499
+ if (Array.isArray(result)) {
1500
+ myResult = [...myResult, ...result];
1501
+ } else if (Object.keys(result).length > 0) {
1502
+ myResult.push(result);
1503
+ }
1504
+ });
1505
+
1506
+ log.debug(`${origin}: Found #${myResult.length} devices.`);
1507
+ log.debug(`Devices: ${JSON.stringify(myResult)}`);
1508
+ return callback({ total: myResult.length, list: myResult });
1509
+ });
1510
+ } catch (ex) {
1511
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
1512
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1513
+ return callback(null, errorObj);
1514
+ }
1515
+ }
1516
+
1517
+ /**
1518
+ * @summary Gets the status for the provided appliance
1519
+ *
1520
+ * @function isAlive
1521
+ * @param {String} deviceName - the deviceName of the appliance. (required)
1522
+ *
1523
+ * @param {configCallback} callback - callback function to return the result
1524
+ * (appliance isAlive) or the error
1525
+ */
1526
+ isAlive(deviceName, callback) {
1527
+ const meth = 'adapterBase-isAlive';
1528
+ const origin = `${this.id}-${meth}`;
1529
+ log.trace(origin);
1530
+
1531
+ // make sure we are set up for device broker isAlive
1532
+ if (!this.allProps.devicebroker || !this.allProps.devicebroker.isAlive || this.allProps.devicebroker.isAlive.length === 0 || !this.allProps.devicebroker.isAlive[0].path) {
1533
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Properties', ['devicebroker.isAlive.path'], null, null, null);
1534
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1535
+ return callback(null, errorObj);
1536
+ }
1537
+
1538
+ // verify the required fields have been provided
1539
+ if (deviceName === undefined || deviceName === null || deviceName === '' || deviceName.length === 0) {
1540
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['deviceName'], null, null, null);
1541
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1542
+ return callback(null, errorObj);
1543
+ }
1544
+
1545
+ try {
1546
+ // need to get the device so we can convert the deviceName to an id
1547
+ // !! if we can do a lookup by name the getDevicesFiltered may not be necessary
1548
+ const opts = {
1549
+ filter: {
1550
+ name: deviceName
1551
+ }
1552
+ };
1553
+ return this.getDevicesFiltered(opts, (devs, ferr) => {
1554
+ // if we received an error or their is no response on the results return an error
1555
+ if (ferr) {
1556
+ return callback(null, ferr);
1557
+ }
1558
+ if (devs.list.length < 1) {
1559
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Did Not Find Device ${deviceName}`, [], null, null, null);
1560
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1561
+ return callback(null, errorObj);
1562
+ }
1563
+
1564
+ const callPromises = [];
1565
+ for (let i = 0; i < this.allProps.devicebroker.isAlive.length; i += 1) {
1566
+ // Perform component calls here.
1567
+ callPromises.push(
1568
+ new Promise((resolve, reject) => {
1569
+ this.iapMakeBrokerCall('isAlive', this.allProps.devicebroker.isAlive[i], [devs.list[0]], null, (callRet, callErr) => {
1570
+ // return an error
1571
+ if (callErr) {
1572
+ reject(callErr);
1573
+ } else {
1574
+ // return the data
1575
+ resolve(callRet);
1576
+ }
1577
+ });
1578
+ })
1579
+ );
1580
+ }
1581
+
1582
+ // return an array of repsonses
1583
+ return Promise.all(callPromises).then((results) => {
1584
+ let myResult = {};
1585
+ results.forEach((result) => {
1586
+ myResult = { ...myResult, ...result };
1587
+ });
1588
+
1589
+ let response = true;
1590
+ if (myResult.isAlive !== null && myResult.isAlive !== undefined && myResult.isAlive === false) {
1591
+ response = false;
1592
+ }
1593
+ return callback(response);
1594
+ });
1595
+ });
1596
+ } catch (ex) {
1597
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
1598
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1599
+ return callback(null, errorObj);
1600
+ }
1601
+ }
1602
+
1603
+ /**
1604
+ * @summary Gets a config for the provided Appliance
1605
+ *
1606
+ * @function getConfig
1607
+ * @param {String} deviceName - the deviceName of the appliance. (required)
1608
+ * @param {String} format - the desired format of the config. (optional)
1609
+ *
1610
+ * @param {configCallback} callback - callback function to return the result
1611
+ * (appliance config) or the error
1612
+ */
1613
+ getConfig(deviceName, format, callback) {
1614
+ const meth = 'adapterBase-getConfig';
1615
+ const origin = `${this.id}-${meth}`;
1616
+ log.trace(origin);
1617
+
1618
+ // make sure we are set up for device broker getConfig
1619
+ if (!this.allProps.devicebroker || !this.allProps.devicebroker.getConfig || this.allProps.devicebroker.getConfig.length === 0 || !this.allProps.devicebroker.getConfig[0].path) {
1620
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Properties', ['devicebroker.getConfig.path'], null, null, null);
1621
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1622
+ return callback(null, errorObj);
1623
+ }
1624
+
1625
+ // verify the required fields have been provided
1626
+ if (deviceName === undefined || deviceName === null || deviceName === '' || deviceName.length === 0) {
1627
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Data', ['deviceName'], null, null, null);
1628
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1629
+ return callback(null, errorObj);
1630
+ }
1631
+
1632
+ try {
1633
+ // need to get the device so we can convert the deviceName to an id
1634
+ // !! if we can do a lookup by name the getDevicesFiltered may not be necessary
1635
+ const opts = {
1636
+ filter: {
1637
+ name: deviceName
1638
+ }
1639
+ };
1640
+ return this.getDevicesFiltered(opts, (devs, ferr) => {
1641
+ // if we received an error or their is no response on the results return an error
1642
+ if (ferr) {
1643
+ return callback(null, ferr);
1644
+ }
1645
+ if (devs.list.length < 1) {
1646
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, `Did Not Find Device ${deviceName}`, [], null, null, null);
1647
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1648
+ return callback(null, errorObj);
1649
+ }
1650
+
1651
+ const callPromises = [];
1652
+ for (let i = 0; i < this.allProps.devicebroker.getConfig.length; i += 1) {
1653
+ // Perform component calls here.
1654
+ callPromises.push(
1655
+ new Promise((resolve, reject) => {
1656
+ this.iapMakeBrokerCall('getConfig', this.allProps.devicebroker.getConfig[i], [devs.list[0]], null, (callRet, callErr) => {
1657
+ // return an error
1658
+ if (callErr) {
1659
+ reject(callErr);
1660
+ } else {
1661
+ // return the data
1662
+ resolve(callRet);
1663
+ }
1664
+ });
1665
+ })
1666
+ );
1667
+ }
1668
+
1669
+ // return an array of repsonses
1670
+ return Promise.all(callPromises).then((results) => {
1671
+ let myResult = {};
1672
+ results.forEach((result) => {
1673
+ myResult = { ...myResult, ...result };
1674
+ });
1675
+
1676
+ // return the result
1677
+ const newResponse = {
1678
+ response: JSON.stringify(myResult, null, 2)
1679
+ };
1680
+ return callback(newResponse, null);
1681
+ });
1682
+ });
1683
+ } catch (ex) {
1684
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
1685
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1686
+ return callback(null, errorObj);
1687
+ }
1688
+ }
1689
+
1690
+ /**
1691
+ * @summary Gets the device count from the system
1692
+ *
1693
+ * @function iapGetDeviceCount
1694
+ *
1695
+ * @param {getCallback} callback - callback function to return the result
1696
+ * (count) or the error
1697
+ */
1698
+ iapGetDeviceCount(callback) {
1699
+ const meth = 'adapterBase-iapGetDeviceCount';
1700
+ const origin = `${this.id}-${meth}`;
1701
+ log.trace(origin);
1702
+
1703
+ // make sure we are set up for device broker getCount
1704
+ if (!this.allProps.devicebroker || !this.allProps.devicebroker.getCount || this.allProps.devicebroker.getCount.length === 0 || !this.allProps.devicebroker.getCount[0].path) {
1705
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Missing Properties', ['devicebroker.getCount.path'], null, null, null);
1706
+ log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1707
+ return callback(null, errorObj);
1708
+ }
1709
+
1710
+ // verify the required fields have been provided
1711
+
1712
+ try {
1713
+ const callPromises = [];
1714
+ for (let i = 0; i < this.allProps.devicebroker.getCount.length; i += 1) {
1715
+ // Perform component calls here.
1716
+ callPromises.push(
1717
+ new Promise((resolve, reject) => {
1718
+ this.iapMakeBrokerCall('getCount', this.allProps.devicebroker.getCount[i], null, null, (callRet, callErr) => {
1719
+ // return an error
1720
+ if (callErr) {
1721
+ reject(callErr);
1722
+ } else {
1723
+ // return the data
1724
+ resolve(callRet);
1725
+ }
1726
+ });
1727
+ })
1728
+ );
1729
+ }
1730
+
1731
+ // return an array of repsonses
1732
+ return Promise.all(callPromises).then((results) => {
1733
+ let myResult = {};
1734
+ results.forEach((result) => {
1735
+ myResult = { ...myResult, ...result };
1736
+ });
1737
+
1738
+ // return the result
1739
+ return callback({ count: myResult.length });
1740
+ });
1741
+ } catch (ex) {
1742
+ const errorObj = this.requestHandlerInst.formatErrorObject(this.id, meth, 'Caught Exception', null, null, null, ex);
1022
1743
  log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
1023
1744
  return callback(null, errorObj);
1024
1745
  }