@itentialopensource/adapter-sevone 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CALLS.md +1661 -22
  2. package/CHANGELOG.md +8 -0
  3. package/CONTRIBUTING.md +1 -160
  4. package/ENHANCE.md +2 -2
  5. package/README.md +32 -23
  6. package/adapter.js +158 -668
  7. package/adapterBase.js +549 -879
  8. package/changelogs/CHANGELOG.md +118 -0
  9. package/metadata.json +49 -0
  10. package/package.json +24 -24
  11. package/pronghorn.json +980 -641
  12. package/propertiesSchema.json +431 -31
  13. package/refs?service=git-upload-pack +0 -0
  14. package/report/adapter-openapi.json +26172 -0
  15. package/report/adapter-openapi.yaml +11817 -0
  16. package/report/adapterInfo.json +8 -8
  17. package/report/updateReport1691508994383.json +120 -0
  18. package/report/updateReport1692202309339.json +120 -0
  19. package/report/updateReport1692203396464.json +120 -0
  20. package/report/updateReport1694470055393.json +120 -0
  21. package/report/updateReport1698423190930.json +120 -0
  22. package/sampleProperties.json +63 -2
  23. package/test/integration/adapterTestBasicGet.js +2 -4
  24. package/test/integration/adapterTestConnectivity.js +91 -42
  25. package/test/integration/adapterTestIntegration.js +130 -2
  26. package/test/unit/adapterBaseTestUnit.js +388 -313
  27. package/test/unit/adapterTestUnit.js +384 -158
  28. package/utils/adapterInfo.js +1 -1
  29. package/utils/addAuth.js +1 -1
  30. package/utils/artifactize.js +1 -1
  31. package/utils/checkMigrate.js +1 -1
  32. package/utils/entitiesToDB.js +2 -2
  33. package/utils/findPath.js +1 -1
  34. package/utils/methodDocumentor.js +273 -0
  35. package/utils/modify.js +13 -15
  36. package/utils/packModificationScript.js +1 -1
  37. package/utils/pre-commit.sh +2 -0
  38. package/utils/taskMover.js +309 -0
  39. package/utils/tbScript.js +89 -34
  40. package/utils/tbUtils.js +41 -21
  41. package/utils/testRunner.js +1 -1
  42. package/utils/troubleshootingAdapter.js +9 -6
  43. package/workflows/README.md +0 -3
@@ -0,0 +1,309 @@
1
+ /* eslint-disable */
2
+ const fs = require('fs');
3
+
4
+ const blacklistTasks = [
5
+ 'genericAdapterRequest',
6
+ 'genericAdapterRequestNoBasePath',
7
+ 'hasEntities',
8
+ 'healthcheck'
9
+ ];
10
+
11
+ const adapterBaseTasks = [
12
+ 'getDevicesFiltered',
13
+ 'isAlive',
14
+ 'getConfig',
15
+ 'getDevice',
16
+ 'iapUpdateAdapterConfiguration',
17
+ 'iapFindAdapterPath',
18
+ 'iapSuspendAdapter',
19
+ 'iapUnsuspendAdapter',
20
+ 'iapGetAdapterQueue',
21
+ 'iapTroubleshootAdapter',
22
+ 'iapRunAdapterHealthcheck',
23
+ 'iapRunAdapterConnectivity',
24
+ 'iapRunAdapterBasicGet',
25
+ 'iapMoveAdapterEntitiesToDB',
26
+ 'getDevice',
27
+ 'getDevicesFiltered',
28
+ 'isAlive',
29
+ 'getConfig',
30
+ 'iapGetDeviceCount',
31
+ 'iapRunAdapterLint',
32
+ 'iapRunAdapterTests',
33
+ 'iapGetAdapterInventory'
34
+ ];
35
+
36
+ function updatePronghorn(tasks, original, updated) {
37
+ const originalFile = require(original);
38
+ const unusedMethods = [];
39
+ const usedMethods = originalFile.methods.filter((method) => {
40
+ if (tasks.includes(method.name)) {
41
+ unusedMethods.push(method);
42
+ return false;
43
+ }
44
+ return true;
45
+ });
46
+ //write used and unused to new files
47
+ let updatedFile;
48
+ if (!fs.existsSync(updated)) {
49
+ updatedFile = { ...originalFile, methods: [], src: 'adapter-inactive.js' };
50
+ } else {
51
+ updatedFile = require(updated);
52
+ }
53
+ updatedFile.methods = updatedFile.methods.concat(unusedMethods);
54
+ originalFile.methods = usedMethods;
55
+ fs.writeFileSync(updated, JSON.stringify(updatedFile, null, 2));
56
+ fs.writeFileSync(original, JSON.stringify(originalFile, null, 2));
57
+ return 'Done';
58
+ }
59
+
60
+ function flipTaskFlag(task, pronghornPath, value)
61
+ {
62
+ const pronghorn = require(pronghornPath);
63
+ const index = pronghorn.methods.findIndex((method) => method.name === task);
64
+ pronghorn.methods[index] = { ...pronghorn.methods[index], task: value };
65
+ fs.writeFileSync(pronghornPath, JSON.stringify(pronghorn, null, 2));
66
+ }
67
+
68
+ //Return array of relevant paths given adapter directory
69
+ function createPaths(currentAdapter) {
70
+ const paths = [];
71
+ const filePaths = [
72
+ 'adapter.js',
73
+ 'pronghorn.json',
74
+ 'test/integration/adapterTestIntegration.js',
75
+ 'test/unit/adapterTestUnit.js',
76
+ 'adapter-inactive.js',
77
+ 'pronghorn-inactive.json',
78
+ ];
79
+ filePaths.forEach((file) => {
80
+ paths.push(`${currentAdapter}/${file}`);
81
+ });
82
+ return paths;
83
+ }
84
+
85
+ function insert(str, index, value) {
86
+ return str.substr(0, index) + value + str.substr(index);
87
+ }
88
+
89
+ //modify adapter js
90
+ //original - path to file containing tasks we want to remove
91
+ // updated - path to file we want to move the tasks to
92
+ function updateAdapterJs(tasks, original, updated, adapterDir) {
93
+ if (!fs.existsSync(original)) {
94
+ //could do this or just let the error ocurr lower down and catch in warpper
95
+ throw new Error(`Original file ${original} does not exist.`);
96
+ }
97
+ let originalFile = fs.readFileSync(original, 'utf8');
98
+ let updatedFile;
99
+ if (!fs.existsSync(updated)) {
100
+ const adapterExport = require(`${adapterDir}/pronghorn.json`).export;
101
+ updatedFile = `/* @copyright Itential, LLC 2019 */\n\n/* eslint import/no-dynamic-require: warn */\n/* eslint no-unused-vars: warn */\n/* global log */\n\nconst path = require('path');\n\nconst AdapterBaseCl = require(path.join(__dirname, 'adapterBase.js'));\n\nclass ${adapterExport}Inactive extends AdapterBaseCl {}\n`;
102
+ //To do handles backup files where og doesn't exist
103
+ } else {
104
+ updatedFile = fs.readFileSync(updated, 'utf8');
105
+ }
106
+
107
+ tasks.forEach((method) => {
108
+ //accounting for different js docs format
109
+ const comment = originalFile.indexOf(`* @function ${method}`);
110
+ const start = originalFile.slice(0, comment).lastIndexOf('/**');
111
+ if (start !== -1) {
112
+ //next comment block
113
+ const end = originalFile.indexOf('/**\n', start + 1);
114
+ let func = end === -1
115
+ ? originalFile.substring(start - 3, originalFile.lastIndexOf('}'))
116
+ : originalFile.substring(start, end);
117
+ originalFile = originalFile.replace(func, '');
118
+ func = '\n ' + func.trim() + '\n';
119
+ updatedFile = insert(updatedFile, updatedFile.lastIndexOf('}'), func);
120
+ } else {
121
+ console.log(`Task ${method} wasn't found in original file. Skipping.`);
122
+ }
123
+ });
124
+ fs.writeFileSync(original, originalFile, 'utf8');
125
+ fs.writeFileSync(updated, updatedFile, 'utf8');
126
+ return 'done';
127
+ }
128
+
129
+ //Update test file for when we deactivate a task
130
+ function deactivateTest(adapterPath, testPath, tasks) {
131
+ let unitTest = fs.readFileSync(`${adapterPath}/${testPath}`, 'utf8');
132
+ tasks.forEach((task) => {
133
+ const searchStr = `describe('#${task}`;
134
+ unitTest = unitTest.replace(searchStr, `describe.skip('#${task}`);
135
+ });
136
+ fs.writeFileSync(`${adapterPath}/${testPath}`, unitTest, 'utf8');
137
+ }
138
+
139
+ //Update test file when we activate tasks
140
+ function activateTest(adapterPath, testPath, tasks) {
141
+ let unitTest = fs.readFileSync(`${adapterPath}/${testPath}`, 'utf8');
142
+ //tasks ==> toMove
143
+ tasks.forEach((task) => {
144
+ const searchStr = `describe.skip('#${task}`;
145
+ unitTest = unitTest.replace(searchStr, `describe('#${task}`);
146
+ });
147
+ fs.writeFileSync(`${adapterPath}/${testPath}`, unitTest, 'utf8');
148
+ }
149
+
150
+ //backups are not actually being written back
151
+ function rollbackChanges(adapterPath) {
152
+ const backups = fs.readdirSync(`${adapterPath}/temp`); //this is an array of file names not the full path
153
+ const filePaths = createPaths(adapterPath);
154
+ for (let i = 0; i < backups.length; i++) {
155
+ const file = fs.readFileSync(`${adapterPath}/temp/${backups[i]}`, 'utf8'); //make sure this is getting the file
156
+ const currentFile = filePaths.find((path) => {
157
+ const index = path.split('/').length - 1;
158
+ const fileName = path.split('/')[index];
159
+ return fileName === backups[i].replace('temp-', '');
160
+ }); //returns undefined if no match
161
+
162
+ if (currentFile) {
163
+ fs.writeFileSync(currentFile, file, 'utf8');
164
+ }
165
+ }
166
+ //inactive didn't exist before script
167
+ if (!backups.includes('temp-adapter-inactive.js')) {
168
+ fs.unlinkSync(`${adapterPath}/pronghorn-inactive.json`);
169
+ fs.unlinkSync(`${adapterPath}/adapter-inactive.js`);
170
+ }
171
+ deleteBackups(adapterPath);
172
+ }
173
+
174
+ function deleteBackups(adapterPath) {
175
+ fs.rmSync(`${adapterPath}/temp`, { recursive: true });
176
+ }
177
+
178
+ function activateTasks(adapterDir, tasks) {
179
+ const toDelete = [];
180
+ const backupFiles = [];
181
+ const filePaths = createPaths(adapterDir);
182
+ try {
183
+ //take backup of each file here
184
+ if (!fs.existsSync(`${adapterDir}/temp`)) {
185
+ fs.mkdirSync(`${adapterDir}/temp`);
186
+ }
187
+ filePaths.forEach((filePath) => {
188
+ if (fs.existsSync(filePath)) {
189
+ const index = filePath.split('/').length - 1;
190
+ const backupName = `temp-${filePath.split('/')[index]}`;
191
+ backupFiles.push(`${adapterDir}/temp/${backupName}`);
192
+ fs.copyFileSync(filePath, `${adapterDir}/temp/${backupName}`);
193
+ } else {
194
+ //File doesn't exist before script
195
+ toDelete.push(filePath);
196
+ }
197
+ });
198
+ tasks = tasks.filter((task) => {
199
+ if (adapterBaseTasks.includes(task)) {
200
+ flipTaskFlag(task, `${adapterDir}/pronghorn.json`, true);
201
+ return false;
202
+ } else {
203
+ return true;
204
+ }
205
+ });
206
+ updateAdapterJs(
207
+ tasks,
208
+ `${adapterDir}/adapter-inactive.js`,
209
+ `${adapterDir}/adapter.js`,
210
+ adapterDir
211
+ );
212
+ updatePronghorn(
213
+ tasks,
214
+ `${adapterDir}/pronghorn-inactive.json`,
215
+ `${adapterDir}/pronghorn.json`
216
+ );
217
+ activateTest(
218
+ adapterDir,
219
+ '/test/integration/adapterTestIntegration.js',
220
+ tasks
221
+ );
222
+ activateTest(adapterDir, '/test/unit/adapterTestUnit.js', tasks);
223
+ return 'success';
224
+ } catch (e) {
225
+ console.log(`Error: ${e} ocurred during execution. Rolling back changes.`);
226
+ for (let i = 0; i < backupFiles.length; i++) {
227
+ const file = fs.readFileSync(backupFiles[i], 'utf8');
228
+ fs.writeFileSync(filePaths[i], file, 'utf8');
229
+ }
230
+ toDelete.forEach((filePath) => {
231
+ if (fs.existsSync(filePath)) {
232
+ fs.unlinkSync(filePath);
233
+ }
234
+ });
235
+ deleteBackups(adapterDir);
236
+ process.exit(1);
237
+ }
238
+ }
239
+
240
+ //moving from adapter.js to adapter-inactive.js
241
+ function deactivateTasks(adapterDir, tasks) {
242
+ const toDelete = [];
243
+ const backupFiles = [];
244
+ const filePaths = createPaths(adapterDir);
245
+ try {
246
+ //take backup of each file here
247
+ if (!fs.existsSync(`${adapterDir}/temp`)) {
248
+ fs.mkdirSync(`${adapterDir}/temp`);
249
+ }
250
+ filePaths.forEach((filePath) => {
251
+ if (fs.existsSync(filePath)) {
252
+ const index = filePath.split('/').length - 1;
253
+ const backupName = `temp-${filePath.split('/')[index]}`;
254
+ backupFiles.push(`${adapterDir}/temp/${backupName}`);
255
+ fs.copyFileSync(filePath, `${adapterDir}/temp/${backupName}`);
256
+ } else {
257
+ //File doesn't exist before script
258
+ toDelete.push(filePath);
259
+ }
260
+ });
261
+ //filter tasks for blacklisted tasks or IAP tasks
262
+ tasks = tasks.filter((task) => {
263
+ if (blacklistTasks.includes(task)) {
264
+ console.log(`${task} cannot be deactivated.`);
265
+ return false;
266
+ } else if (adapterBaseTasks.includes(task)) {
267
+ flipTaskFlag(task, `${adapterDir}/pronghorn.json`, false);
268
+ return false;
269
+ } else {
270
+ return true;
271
+ }
272
+ });
273
+ updateAdapterJs(
274
+ tasks,
275
+ `${adapterDir}/adapter.js`,
276
+ `${adapterDir}/adapter-inactive.js`,
277
+ adapterDir
278
+ );
279
+ updatePronghorn(
280
+ tasks,
281
+ `${adapterDir}/pronghorn.json`,
282
+ `${adapterDir}/pronghorn-inactive.json`
283
+ );
284
+ deactivateTest(
285
+ adapterDir,
286
+ '/test/integration/adapterTestIntegration.js',
287
+ tasks
288
+ );
289
+ deactivateTest(adapterDir, '/test/unit/adapterTestUnit.js', tasks);
290
+ return 'success';
291
+ } catch (e) {
292
+ console.log(`Error: ${e} ocurred during execution. Rolling back changes.`);
293
+ for (let i = 0; i < backupFiles.length; i++) {
294
+ const file = fs.readFileSync(backupFiles[i], 'utf8');
295
+ fs.writeFileSync(filePaths[i], file, 'utf8');
296
+ }
297
+ toDelete.forEach((filePath) => {
298
+ if (fs.existsSync(filePath)) {
299
+ fs.unlinkSync(filePath);
300
+ }
301
+ });
302
+ deleteBackups(adapterDir);
303
+ process.exit(1);
304
+ }
305
+ }
306
+
307
+ module.exports = {
308
+ activateTasks, deactivateTasks, rollbackChanges, deleteBackups
309
+ };
package/utils/tbScript.js CHANGED
@@ -9,6 +9,7 @@
9
9
 
10
10
  const program = require('commander');
11
11
  const rls = require('readline-sync');
12
+ const prompts = require('prompts');
12
13
  const utils = require('./tbUtils');
13
14
  const basicGet = require('./basicGet');
14
15
  const { name } = require('../package.json');
@@ -50,10 +51,81 @@ const executeInStandaloneMode = async (command) => {
50
51
  process.exit(0);
51
52
  };
52
53
 
54
+ const getAdapterInstanceConfig = async (command) => {
55
+ const instances = await utils.getAllAdapterInstances();
56
+ if (!instances || instances.length === 0) {
57
+ return console.log('None adapter instances found!');
58
+ }
59
+
60
+ let instance;
61
+ if (instances.length === 1) {
62
+ [instance] = instances;
63
+ } else {
64
+ const choices = instances.map((item) => ({ title: item.name }));
65
+ const menu = {
66
+ type: 'select',
67
+ name: 'index',
68
+ message: `Pick an adapter for ${command} check`,
69
+ choices
70
+ };
71
+
72
+ console.log('\n');
73
+ const selected = await prompts(menu);
74
+ console.log('\n');
75
+ instance = instances[selected.index];
76
+ }
77
+
78
+ if (!instance) {
79
+ console.error('No adapter instance selected');
80
+ return null;
81
+ }
82
+
83
+ const { serviceItem: adapterConfig } = await utils.getAdapterConfig(instance._id); /* eslint-disable-line no-underscore-dangle */
84
+
85
+ console.log('\nAdapter instance configuration =>');
86
+ console.log('======================================');
87
+ console.log(adapterConfig);
88
+ console.log('======================================');
89
+
90
+ return adapterConfig;
91
+ };
92
+
93
+ const executeCommandOnInstance = async (command) => {
94
+ const adapterConfig = await getAdapterInstanceConfig(command);
95
+ if (!adapterConfig) {
96
+ process.exit(0);
97
+ }
98
+
99
+ switch (command) {
100
+ case 'connectivity': {
101
+ const { host } = adapterConfig.properties.properties;
102
+ console.log(`perform networking diagnositics to ${host}`);
103
+ utils.runConnectivity(host, true);
104
+ break;
105
+ }
106
+ case 'healthcheck': {
107
+ const adapterInstance = basicGet.getAdapterInstance(adapterConfig);
108
+ await utils.healthCheck(adapterInstance);
109
+ break;
110
+ }
111
+ case 'basicget': {
112
+ utils.runBasicGet(true);
113
+ break;
114
+ }
115
+ case 'troubleshoot': {
116
+ const adapter = { properties: adapterConfig };
117
+ await troubleshoot({}, true, true, adapter);
118
+ break;
119
+ }
120
+ default: {
121
+ console.error(`Unknown command: ${command}`);
122
+ }
123
+ }
124
+ return process.exit(0);
125
+ };
126
+
53
127
  const executeUnderIAPInstallationDirectory = async (command) => {
54
- if (command === undefined) {
55
- await troubleshoot({}, true, true);
56
- } else if (command === 'install') {
128
+ if (command === 'install') {
57
129
  const { database, serviceItem, pronghornProps } = await utils.getAdapterConfig();
58
130
  const filter = { id: pronghornProps.id };
59
131
  const profileItem = await database.collection(utils.IAP_PROFILES_COLLECTION).findOne(filter);
@@ -71,9 +143,7 @@ const executeUnderIAPInstallationDirectory = async (command) => {
71
143
  const serviceIndex = profileItem.services.indexOf(serviceItem.name);
72
144
  profileItem.services.splice(serviceIndex, 1);
73
145
  const update = { $set: { services: profileItem.services } };
74
- await database.collection(utils.IAP_PROFILES_COLLECTION).updateOne(
75
- { id: pronghornProps.id }, update
76
- );
146
+ await database.collection(utils.IAP_PROFILES_COLLECTION).updateOne({ id: pronghornProps.id }, update);
77
147
  console.log(`${serviceItem.name} removed from profileItem.services.`);
78
148
  console.log(`Rerun the script to reinstall ${serviceItem.name}.`);
79
149
  process.exit(0);
@@ -90,43 +160,20 @@ const executeUnderIAPInstallationDirectory = async (command) => {
90
160
  utils.runTest();
91
161
  if (rls.keyInYN(`Do you want to install ${name} to IAP?`)) {
92
162
  console.log('Creating database entries...');
93
- const adapter = utils.createAdapter(
94
- pronghornProps, profileItem, sampleProperties, adapterPronghorn
95
- );
96
-
163
+ const adapter = utils.createAdapter(pronghornProps, profileItem, sampleProperties, adapterPronghorn);
97
164
  adapter.properties.properties = await addAuthInfo(adapter.properties.properties);
98
165
 
99
166
  await database.collection(utils.SERVICE_CONFIGS_COLLECTION).insertOne(adapter);
100
167
  profileItem.services.push(adapter.name);
101
168
  const update = { $set: { services: profileItem.services } };
102
- await database.collection(utils.IAP_PROFILES_COLLECTION).updateOne(
103
- { id: pronghornProps.id }, update
104
- );
169
+ await database.collection(utils.IAP_PROFILES_COLLECTION).updateOne({ id: pronghornProps.id }, update);
105
170
  console.log('Database entry creation complete.');
106
171
  }
107
172
  console.log('Exiting...');
108
173
  process.exit(0);
109
174
  }
110
- } else if (['healthcheck', 'basicget', 'connectivity'].includes(command)) {
111
- const { serviceItem } = await utils.getAdapterConfig();
112
- if (serviceItem) {
113
- const adapter = serviceItem;
114
- const a = basicGet.getAdapterInstance(adapter);
115
- if (command === 'healthcheck') {
116
- await utils.healthCheck(a);
117
- process.exit(0);
118
- } else if (command === 'basicget') {
119
- await utils.runBasicGet(true);
120
- } else if (command === 'connectivity') {
121
- const { host } = adapter.properties.properties;
122
- console.log(`perform networking diagnositics to ${host}`);
123
- await utils.runConnectivity(host, true);
124
- process.exit(0);
125
- }
126
- } else {
127
- console.log(`${name} not installed. Run npm \`run install:adapter\` to install.`);
128
- process.exit(0);
129
- }
175
+ } else if (['healthcheck', 'basicget', 'connectivity', 'troubleshoot'].includes(command)) {
176
+ await executeCommandOnInstance(command);
130
177
  }
131
178
  };
132
179
 
@@ -170,13 +217,21 @@ program
170
217
  main('basicget');
171
218
  });
172
219
 
220
+ program
221
+ .command('troubleshoot')
222
+ .alias('tb')
223
+ .description('perfom troubleshooting')
224
+ .action(() => {
225
+ main('troubleshoot');
226
+ });
227
+
173
228
  // Allow commander to parse `process.argv`
174
229
  program.parse(process.argv);
175
230
 
176
231
  if (process.argv.length < 3) {
177
232
  main();
178
233
  }
179
- const allowedParams = ['install', 'healthcheck', 'basicget', 'connectivity'];
234
+ const allowedParams = ['install', 'healthcheck', 'basicget', 'connectivity', 'troubleshoot'];
180
235
  if (process.argv.length === 3 && !allowedParams.includes(process.argv[2])) {
181
236
  console.log(`unknown parameter ${process.argv[2]}`);
182
237
  console.log('try `node troubleshootingAdapter.js -h` to see allowed parameters. Exiting...');
package/utils/tbUtils.js CHANGED
@@ -6,8 +6,8 @@
6
6
  /* eslint-disable no-console */
7
7
 
8
8
  const path = require('path');
9
- const fs = require('fs-extra');
10
9
  const cp = require('child_process');
10
+ const fs = require('fs-extra');
11
11
 
12
12
  module.exports = {
13
13
  SERVICE_CONFIGS_COLLECTION: 'service_configs',
@@ -101,10 +101,8 @@ module.exports = {
101
101
  *
102
102
  * @function decryptProperties
103
103
  */
104
- decryptProperties: (props, iapDir, discovery) => {
105
- const propertyEncryptionClassPath = path.join(iapDir, 'node_modules/@itential/pronghorn-core/core/PropertyEncryption.js');
106
- const isEncrypted = props.pathProps.encrypted;
107
- const PropertyEncryption = discovery.require(propertyEncryptionClassPath, isEncrypted);
104
+ decryptProperties: (props, iapDir) => {
105
+ const { PropertyEncryption } = require(path.join(iapDir, 'node_modules/@itential/itential-utils'));
108
106
  const propertyEncryption = new PropertyEncryption({
109
107
  algorithm: 'aes-256-ctr',
110
108
  key: 'TG9uZ0Rpc3RhbmNlUnVubmVyUHJvbmdob3JuCg==',
@@ -160,8 +158,7 @@ module.exports = {
160
158
  * @param {Object} healthcheck - {Object} healthcheck - ./entities/.system/action.json object
161
159
  */
162
160
  getHealthCheckEndpoint: (healthcheck) => {
163
- const endpoint = healthcheck.actions[1].entitypath.slice(21,
164
- healthcheck.actions[1].entitypath.length - 8);
161
+ const endpoint = healthcheck.actions[1].entitypath.slice(21, healthcheck.actions[1].entitypath.length - 8);
165
162
  return { healthCheckEndpoint: endpoint };
166
163
  },
167
164
 
@@ -203,6 +200,7 @@ module.exports = {
203
200
  try {
204
201
  stdout = cp.execSync(cmd).toString();
205
202
  } catch (error) {
203
+ console.log('execute command error', error.stdout.toString(), error.stderr.toString());
206
204
  stdout = error.stdout.toString();
207
205
  }
208
206
  const output = this.getTestCount(stdout);
@@ -290,10 +288,12 @@ module.exports = {
290
288
  */
291
289
  runConnectivity: function runConnectivity(host, scriptFlag) {
292
290
  let testPath = 'test/integration/adapterTestConnectivity.js';
291
+ let executable = 'mocha';
293
292
  if (!scriptFlag) {
294
293
  testPath = path.resolve(__dirname, '..', testPath);
294
+ executable = path.join(__dirname, '..', 'node_modules/mocha/bin/mocha');
295
295
  }
296
- return this.systemSync(`mocha ${testPath} --HOST=${host} --timeout 10000 --exit`, !scriptFlag);
296
+ return this.systemSync(`${executable} ${testPath} --HOST=${host} --timeout 10000 --exit`, !scriptFlag);
297
297
  },
298
298
 
299
299
  /**
@@ -340,28 +340,42 @@ module.exports = {
340
340
  return adapter;
341
341
  },
342
342
 
343
- getPronghornProps: function getPronghornProps(iapDir) {
343
+ getPronghornProps: function getPronghornProps() {
344
+ const iapDir = this.getIAPHome();
344
345
  console.log('Retrieving properties.json file...');
345
346
  const rawProps = require(path.join(iapDir, 'properties.json'));
346
347
  console.log('Decrypting properties...');
347
- const { Discovery } = require(path.join(iapDir, 'node_modules/@itential/itential-utils'));
348
- const discovery = new Discovery();
349
- const pronghornProps = this.decryptProperties(rawProps, iapDir, discovery);
348
+ const pronghornProps = this.decryptProperties(rawProps, iapDir);
350
349
  console.log('Found properties.\n');
351
350
  return pronghornProps;
352
351
  },
353
352
 
353
+ getAllAdapterInstances: async function getAllAdapterInstances() {
354
+ const database = await this.getIAPDatabaseConnection();
355
+ const { name } = require(path.join(__dirname, '..', 'package.json'));
356
+ const query = { model: name };
357
+ const options = { projection: { name: 1 } };
358
+ const adapterInstancesNames = await database.collection(this.SERVICE_CONFIGS_COLLECTION).find(
359
+ query,
360
+ options
361
+ ).toArray();
362
+ return adapterInstancesNames;
363
+ },
364
+
354
365
  // get database connection and existing adapter config
355
- getAdapterConfig: async function getAdapterConfig() {
356
- const iapDir = this.getIAPHome();
357
- const pronghornProps = this.getPronghornProps(iapDir);
358
- console.log('Connecting to Database...');
359
- const database = await this.connect(iapDir, pronghornProps);
360
- console.log('Connection established.');
366
+ getAdapterConfig: async function getAdapterConfig(adapterId) {
367
+ const database = await this.getIAPDatabaseConnection();
361
368
  const { name } = require(path.join(__dirname, '..', 'package.json'));
369
+ let query = {};
370
+ if (!adapterId) {
371
+ query = { model: name };
372
+ } else {
373
+ query = { _id: adapterId };
374
+ }
362
375
  const serviceItem = await database.collection(this.SERVICE_CONFIGS_COLLECTION).findOne(
363
- { model: name }
376
+ query
364
377
  );
378
+ const pronghornProps = await this.getPronghornProps();
365
379
  return { database, serviceItem, pronghornProps };
366
380
  },
367
381
 
@@ -438,13 +452,19 @@ module.exports = {
438
452
  return path.join(this.getCurrentExecutionPath(), '../../..') === this.getIAPHome();
439
453
  },
440
454
 
455
+ getIAPDatabaseConnection: async function getIAPDatabaseConnection() {
456
+ const pronghornProps = await this.getPronghornProps();
457
+ const database = await this.connect(pronghornProps);
458
+ return database;
459
+ },
460
+
441
461
  /**
442
462
  * @summary connect to mongodb
443
463
  *
444
464
  * @function connect
445
465
  * @param {Object} properties - pronghornProps
446
466
  */
447
- connect: async function connect(iapDir, properties) {
467
+ connect: async function connect(properties) {
448
468
  let dbConnectionProperties = {};
449
469
  if (properties.mongoProps) {
450
470
  dbConnectionProperties = properties.mongoProps;
@@ -459,7 +479,7 @@ module.exports = {
459
479
  if (!dbConnectionProperties.url || !dbConnectionProperties.db) {
460
480
  throw new Error('Mongo properties are not specified in IAP configuration!');
461
481
  }
462
-
482
+ const iapDir = this.getIAPHome();
463
483
  const { MongoDBConnection } = require(path.join(iapDir, 'node_modules/@itential/database'));
464
484
  const connection = new MongoDBConnection(dbConnectionProperties);
465
485
  const database = await connection.connect(true);
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  /* @copyright Itential, LLC 2019 */
3
3
 
4
+ const execute = require('child_process').exec;
4
5
  const fs = require('fs-extra');
5
6
  const rl = require('readline-sync');
6
- const execute = require('child_process').exec;
7
7
 
8
8
  /**
9
9
  * This script will determine the type of integration test to run
@@ -134,9 +134,13 @@ const offline = async () => {
134
134
  };
135
135
 
136
136
  const troubleshoot = async (props, scriptFlag, persistFlag, adapter) => {
137
- // get database connection and existing adapter config
138
- const { database, serviceItem } = await utils.getAdapterConfig();
139
- // where troubleshoot should start
137
+ let serviceItem;
138
+ if (adapter && adapter.allProps) {
139
+ serviceItem = { properties: { properties: adapter.allProps } };
140
+ }
141
+ if (adapter && adapter.properties && adapter.properties.properties) {
142
+ serviceItem = adapter.properties;
143
+ }
140
144
  if (serviceItem) {
141
145
  if (!scriptFlag || rls.keyInYN(`Start verifying the connection and authentication properties for ${name}?`)) {
142
146
  const { result, updatedAdapter } = VerifyHealthCheckEndpoint(serviceItem, props, scriptFlag);
@@ -154,10 +158,9 @@ const troubleshoot = async (props, scriptFlag, persistFlag, adapter) => {
154
158
  }
155
159
 
156
160
  if (persistFlag && healthRes) {
161
+ const { database } = await utils.getIAPDatabaseConnection();
157
162
  const update = { $set: { properties: updatedAdapter.properties } };
158
- await database.collection(utils.SERVICE_CONFIGS_COLLECTION).updateOne(
159
- { model: name }, update
160
- );
163
+ await database.collection(utils.SERVICE_CONFIGS_COLLECTION).updateOne({ model: name }, update);
161
164
  if (scriptFlag) {
162
165
  console.log(`${name} updated.`);
163
166
  }
@@ -1,3 +0,0 @@
1
- # Adapter Workflows
2
-
3
- This directory contains workflows that support the adapter use cases. These workflows can be imported into IAP. If the adapter is installed using App-Artifact the workflows should be automatically imported.