@itentialopensource/adapter-meraki 1.0.3 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. package/AUTH.md +14 -18
  2. package/CALLS.md +4264 -0
  3. package/CHANGELOG.md +16 -0
  4. package/CONTRIBUTING.md +1 -160
  5. package/ENHANCE.md +2 -2
  6. package/README.md +23 -18
  7. package/SYSTEMINFO.md +15 -2
  8. package/adapter.js +164 -335
  9. package/adapterBase.js +411 -920
  10. package/changelogs/changelog.md +198 -0
  11. package/metadata.json +61 -0
  12. package/package.json +24 -24
  13. package/pronghorn.json +470 -138
  14. package/propertiesSchema.json +358 -31
  15. package/refs?service=git-upload-pack +0 -0
  16. package/report/adapterInfo.json +8 -8
  17. package/report/updateReport1690417926405.json +119 -0
  18. package/sampleProperties.json +74 -27
  19. package/test/integration/adapterTestBasicGet.js +2 -4
  20. package/test/integration/adapterTestConnectivity.js +91 -42
  21. package/test/integration/adapterTestIntegration.js +130 -2
  22. package/test/unit/adapterBaseTestUnit.js +388 -313
  23. package/test/unit/adapterTestUnit.js +332 -112
  24. package/utils/adapterInfo.js +1 -1
  25. package/utils/addAuth.js +1 -1
  26. package/utils/artifactize.js +1 -1
  27. package/utils/checkMigrate.js +1 -1
  28. package/utils/entitiesToDB.js +2 -2
  29. package/utils/findPath.js +1 -1
  30. package/utils/methodDocumentor.js +225 -0
  31. package/utils/modify.js +13 -15
  32. package/utils/packModificationScript.js +1 -1
  33. package/utils/pre-commit.sh +2 -0
  34. package/utils/taskMover.js +309 -0
  35. package/utils/tbScript.js +89 -34
  36. package/utils/tbUtils.js +41 -21
  37. package/utils/testRunner.js +1 -1
  38. package/utils/troubleshootingAdapter.js +9 -6
  39. package/versions.json +0 -542
  40. package/workflows/README.md +0 -3
@@ -0,0 +1,119 @@
1
+ {
2
+ "errors": [
3
+ {
4
+ "propertiesSchemaJson": "propertiesSchema.json owner reporting - Create propertiesSchema caught: SyntaxError: Unexpected token } in JSON at position 2262"
5
+ }
6
+ ],
7
+ "statistics": [
8
+ {
9
+ "owner": "errorJson",
10
+ "description": "New adapter errors available for use",
11
+ "value": 0
12
+ },
13
+ {
14
+ "owner": "errorJson",
15
+ "description": "Adapter errors no longer available for use",
16
+ "value": 0
17
+ },
18
+ {
19
+ "owner": "errorJson",
20
+ "description": "Adapter errors that have been updated (e.g. recommendation changes)",
21
+ "value": 31
22
+ },
23
+ {
24
+ "owner": "packageJson",
25
+ "description": "Number of production dependencies",
26
+ "value": 17
27
+ },
28
+ {
29
+ "owner": "packageJson",
30
+ "description": "Number of development dependencies",
31
+ "value": 7
32
+ },
33
+ {
34
+ "owner": "packageJson",
35
+ "description": "Number of npm scripts",
36
+ "value": 22
37
+ },
38
+ {
39
+ "owner": "packageJson",
40
+ "description": "Runtime Library dependency",
41
+ "value": "^5.0.5"
42
+ },
43
+ {
44
+ "owner": "markdown",
45
+ "description": "Number of lines in the README.md",
46
+ "value": 343
47
+ },
48
+ {
49
+ "owner": "markdown",
50
+ "description": "Number of lines in the SUMMARY.md",
51
+ "value": 9
52
+ },
53
+ {
54
+ "owner": "markdown",
55
+ "description": "Number of lines in the PROPERTIES.md",
56
+ "value": 642
57
+ },
58
+ {
59
+ "owner": "markdown",
60
+ "description": "Number of lines in the TROUBLESHOOT.md",
61
+ "value": 48
62
+ },
63
+ {
64
+ "owner": "markdown",
65
+ "description": "Number of lines in the ENHANCE.md",
66
+ "value": 70
67
+ },
68
+ {
69
+ "owner": "markdown",
70
+ "description": "Number of lines in the BROKER.md",
71
+ "value": 70
72
+ },
73
+ {
74
+ "owner": "unitTestJS",
75
+ "description": "Number of lines of code in unit tests",
76
+ "value": 24024
77
+ },
78
+ {
79
+ "owner": "unitTestJS",
80
+ "description": "Number of unit tests",
81
+ "value": 1565
82
+ },
83
+ {
84
+ "owner": "integrationTestJS",
85
+ "description": "Number of lines of code in integration tests",
86
+ "value": 18150
87
+ },
88
+ {
89
+ "owner": "integrationTestJS",
90
+ "description": "Number of integration tests",
91
+ "value": 595
92
+ },
93
+ {
94
+ "owner": "staticFile",
95
+ "description": "Number of lines of code in adapterBase.js",
96
+ "value": 1357
97
+ },
98
+ {
99
+ "owner": "staticFile",
100
+ "description": "Number of static files added",
101
+ "value": 38
102
+ },
103
+ {
104
+ "owner": "Overall",
105
+ "description": "Total lines of Code",
106
+ "value": 43531
107
+ },
108
+ {
109
+ "owner": "Overall",
110
+ "description": "Total Tests",
111
+ "value": 2160
112
+ },
113
+ {
114
+ "owner": "Overall",
115
+ "description": "Total Files",
116
+ "value": 6
117
+ }
118
+ ]
119
+ }
@@ -4,6 +4,7 @@
4
4
  "properties": {
5
5
  "host": "api.meraki.com",
6
6
  "port": 443,
7
+ "choosepath": "",
7
8
  "base_path": "/api",
8
9
  "version": "v1",
9
10
  "cache_location": "none",
@@ -13,24 +14,39 @@
13
14
  "stub": true,
14
15
  "protocol": "https",
15
16
  "authentication": {
16
- "auth_method": "basic user_password",
17
+ "auth_method": "static_token",
17
18
  "username": "username",
18
19
  "password": "password",
19
- "token": "",
20
+ "token": "<token>",
20
21
  "token_timeout": 1800000,
21
22
  "token_cache": "local",
22
23
  "invalid_token_error": 401,
23
- "auth_field": "header.headers.Authorization",
24
- "auth_field_format": "Basic {b64}{username}:{password}{/b64}",
24
+ "auth_field": "header.headers.X-Cisco-Meraki-API-Key",
25
+ "auth_field_format": "{token}",
25
26
  "auth_logging": false,
26
27
  "client_id": "",
27
28
  "client_secret": "",
28
- "grant_type": ""
29
+ "grant_type": "",
30
+ "sensitive": [],
31
+ "sso": {
32
+ "protocol": "",
33
+ "host": "",
34
+ "port": 0
35
+ },
36
+ "multiStepAuthCalls": [
37
+ {
38
+ "name": "",
39
+ "requestFields": {},
40
+ "responseFields": {},
41
+ "successfullResponseCode": 200
42
+ }
43
+ ]
29
44
  },
30
45
  "healthcheck": {
31
46
  "type": "none",
32
47
  "frequency": 300000,
33
- "query_object": {}
48
+ "query_object": {},
49
+ "addlHeaders": {}
34
50
  },
35
51
  "throttle": {
36
52
  "throttle_enabled": false,
@@ -102,14 +118,17 @@
102
118
  {
103
119
  "path": "/organizations/{orgID}/devices",
104
120
  "method": "GET",
105
- "query": {},
121
+ "query": {
122
+ "networkID": "networkID",
123
+ "serial": "serial"
124
+ },
106
125
  "body": {},
107
126
  "headers": {},
108
127
  "handleFailure": "ignore",
109
128
  "requestFields": {
110
- "networkID": "627126248111459727",
111
- "serial": "Q4AB-J4J8-6BJR",
112
- "orgID": "1076949"
129
+ "networkID": "port",
130
+ "serial": "name",
131
+ "orgID": "orgID"
113
132
  },
114
133
  "responseDatakey": "",
115
134
  "responseFields": {
@@ -139,7 +158,7 @@
139
158
  "ostypePrefix": "meraki-",
140
159
  "port": "networkId",
141
160
  "ipaddress": "mac",
142
- "orgID": "1076949"
161
+ "orgID": "orgID"
143
162
  }
144
163
  }
145
164
  ],
@@ -153,8 +172,8 @@
153
172
  "handleFailure": "ignore",
154
173
  "requestFields": {
155
174
  "networkID": "port",
156
- "serial": "Q4AB-J4J8-6BJR",
157
- "orgID": "1076949"
175
+ "serial": "name",
176
+ "orgID": "orgID"
158
177
  },
159
178
  "responseDatakey": "",
160
179
  "responseFields": {
@@ -173,8 +192,8 @@
173
192
  "handleFailure": "ignore",
174
193
  "requestFields": {
175
194
  "networkID": "port",
176
- "serial": "Q4AB-J4J8-6BJR",
177
- "orgID": "1076949"
195
+ "serial": "name",
196
+ "orgID": "orgID"
178
197
  },
179
198
  "responseDatakey": "",
180
199
  "responseFields": {}
@@ -193,19 +212,47 @@
193
212
  },
194
213
  "responseDatakey": "",
195
214
  "responseFields": {}
196
- },
215
+ }
216
+ ]
217
+ },
218
+ "cache": {
219
+ "enabled": false,
220
+ "entities": [
197
221
  {
198
- "path": "/organizations/{orgID}/devices",
199
- "method": "GET",
200
- "query": {},
201
- "body": {},
202
- "headers": {},
203
- "handleFailure": "ignore",
204
- "requestFields": {
205
- "orgID": "1076949"
206
- },
207
- "responseDatakey": "",
208
- "responseFields": {}
222
+ "entityType": "device",
223
+ "frequency": 3600,
224
+ "flushOnFail": false,
225
+ "limit": 10000,
226
+ "retryAttempts": 5,
227
+ "sort": true,
228
+ "populate": [
229
+ {
230
+ "path": "/organizations/{orgID}/devices",
231
+ "method": "GET",
232
+ "query": {},
233
+ "body": {},
234
+ "headers": {},
235
+ "handleFailure": "ignore",
236
+ "requestFields": {
237
+ "orgID": "1076949"
238
+ },
239
+ "responseDatakey": "",
240
+ "responseFields": {
241
+ "serial": "serial",
242
+ "model": "model",
243
+ "networkId": "networkId",
244
+ "mac": "mac",
245
+ "orgID": "orgID"
246
+ }
247
+ }
248
+ ],
249
+ "cachedTasks": [
250
+ {
251
+ "name": "",
252
+ "filterField": "",
253
+ "filterLoc": ""
254
+ }
255
+ ]
209
256
  }
210
257
  ]
211
258
  }
@@ -7,9 +7,9 @@
7
7
  /* eslint import/no-dynamic-require: warn */
8
8
  /* eslint import/no-unresolved: warn */
9
9
 
10
- const mocha = require('mocha');
11
10
  const path = require('path');
12
11
  const assert = require('assert');
12
+ const mocha = require('mocha');
13
13
  const itParam = require('mocha-param');
14
14
 
15
15
  const utils = require('../../utils/tbUtils');
@@ -18,12 +18,10 @@ const { name } = require('../../package.json');
18
18
  const { methods } = require('../../pronghorn.json');
19
19
 
20
20
  const getPronghornProps = (iapDir) => {
21
- const { Discovery } = require('@itential/itential-utils');
22
21
  console.log('Retrieving properties.json file...');
23
22
  const rawProps = require(path.join(iapDir, 'properties.json'));
24
23
  console.log('Decrypting properties...');
25
- const discovery = new Discovery();
26
- const pronghornProps = utils.decryptProperties(rawProps, path.join(__dirname, '..'), discovery);
24
+ const pronghornProps = utils.decryptProperties(rawProps, iapDir);
27
25
  console.log('Found properties.\n');
28
26
  return pronghornProps;
29
27
  };
@@ -3,9 +3,12 @@
3
3
  /* global describe it context before after */
4
4
  /* eslint no-unused-vars: warn */
5
5
 
6
- const mocha = require('mocha');
7
6
  const assert = require('assert');
8
- const diagnostics = require('network-diagnostics');
7
+ const http = require('http');
8
+ const https = require('https');
9
+ const mocha = require('mocha');
10
+ const ping = require('ping');
11
+ const dnsLookup = require('dns-lookup-promise');
9
12
 
10
13
  let host;
11
14
  process.argv.forEach((val) => {
@@ -16,78 +19,124 @@ process.argv.forEach((val) => {
16
19
 
17
20
  describe('[integration] Adapter Test', () => {
18
21
  context(`Testing network connection on ${host}`, () => {
19
- before(() => {
20
- diagnostics.setTestURL(host);
21
- });
22
-
23
22
  after((done) => {
24
23
  done();
25
24
  });
26
25
 
27
26
  it('DNS resolve', (done) => {
28
- diagnostics.haveDNS((result) => {
29
- try {
30
- assert.equal(result, true);
31
- done();
32
- } catch (error) {
33
- done(error);
34
- }
35
- });
27
+ dnsLookup(host)
28
+ .then((addresses) => {
29
+ try {
30
+ assert.ok(addresses.length > 0);
31
+ done();
32
+ } catch (error) {
33
+ done(error);
34
+ }
35
+ })
36
+ .catch((err) => {
37
+ done(err);
38
+ });
36
39
  });
37
40
 
38
41
  it('Responds to ping', (done) => {
39
- diagnostics.havePing((result) => {
40
- try {
41
- assert.equal(result, true);
42
- done();
43
- } catch (error) {
44
- done(error);
45
- }
46
- });
42
+ ping.promise.probe(host)
43
+ .then((result) => {
44
+ try {
45
+ assert.ok(result.alive);
46
+ done();
47
+ } catch (error) {
48
+ done(error);
49
+ }
50
+ })
51
+ .catch((err) => {
52
+ done(err);
53
+ });
47
54
  });
48
55
 
49
56
  it('Support HTTP on port 80', (done) => {
50
- diagnostics.haveHTTP((result) => {
57
+ const requestOptions = {
58
+ host,
59
+ port: 80,
60
+ method: 'HEAD'
61
+ };
62
+
63
+ const req = http.request(requestOptions, (res) => {
51
64
  try {
52
- assert.equal(result, true);
65
+ assert.ok(res.statusCode >= 200 && res.statusCode < 400);
53
66
  done();
54
67
  } catch (error) {
55
68
  done(error);
56
69
  }
57
70
  });
71
+
72
+ req.on('error', (err) => {
73
+ done(err);
74
+ });
75
+
76
+ req.end();
58
77
  });
59
78
 
60
79
  it('Support HTTPS on port 443', (done) => {
61
- diagnostics.haveHTTPS((result) => {
80
+ const requestOptions = {
81
+ host,
82
+ port: 443,
83
+ method: 'HEAD'
84
+ };
85
+
86
+ const req = https.request(requestOptions, (res) => {
62
87
  try {
63
- assert.equal(result, true);
88
+ assert.ok(res.statusCode >= 200 && res.statusCode < 400);
64
89
  done();
65
90
  } catch (error) {
66
91
  done(error);
67
92
  }
68
93
  });
94
+
95
+ req.on('error', (err) => {
96
+ done(err);
97
+ });
98
+
99
+ req.end();
69
100
  });
70
101
 
71
102
  it('Support IPv4', (done) => {
72
- diagnostics.haveIPv4Async((result) => {
73
- try {
74
- assert.equal(result, true);
75
- done();
76
- } catch (error) {
77
- done(error);
78
- }
79
- });
103
+ const options = {
104
+ family: 4,
105
+ hints: dnsLookup.ADDRCONFIG
106
+ };
107
+
108
+ dnsLookup.lookup(host, options)
109
+ .then((address, family) => {
110
+ try {
111
+ assert.ok(address !== null && family === 4);
112
+ done();
113
+ } catch (error) {
114
+ done(error);
115
+ }
116
+ })
117
+ .catch((err) => {
118
+ done(err);
119
+ });
80
120
  });
81
121
 
82
122
  it('Support IPv6', (done) => {
83
- diagnostics.haveIPv6Async((result) => {
84
- try {
85
- assert.equal(result, true);
86
- done();
87
- } catch (error) {
88
- done(error);
89
- }
90
- });
123
+ const options = {
124
+ family: 6,
125
+ hints: dnsLookup.ADDRCONFIG
126
+ };
127
+
128
+ dnsLookup.lookup(host, options)
129
+ .then((address, family) => {
130
+ try {
131
+ assert.ok(address !== null && family === 6);
132
+ done();
133
+ } catch (error) {
134
+ done(error);
135
+ }
136
+ })
137
+ .catch((err) => {
138
+ done(err);
139
+ });
91
140
  });
92
141
  });
93
142
  });
@@ -9,13 +9,13 @@
9
9
  // include required items for testing & logging
10
10
  const assert = require('assert');
11
11
  const fs = require('fs');
12
- const mocha = require('mocha');
13
12
  const path = require('path');
13
+ const util = require('util');
14
+ const mocha = require('mocha');
14
15
  const winston = require('winston');
15
16
  const { expect } = require('chai');
16
17
  const { use } = require('chai');
17
18
  const td = require('testdouble');
18
- const util = require('util');
19
19
 
20
20
  const anything = td.matchers.anything();
21
21
 
@@ -335,6 +335,134 @@ describe('[integration] Meraki Adapter Test', () => {
335
335
  }).timeout(attemptTimeout);
336
336
  });
337
337
 
338
+ // broker tests
339
+ describe('#getDevicesFiltered - errors', () => {
340
+ it('should work if integrated but since no mockdata should error when run standalone', (done) => {
341
+ try {
342
+ const opts = {
343
+ filter: {
344
+ name: 'deviceName'
345
+ }
346
+ };
347
+ a.getDevicesFiltered(opts, (data, error) => {
348
+ try {
349
+ if (stub) {
350
+ if (samProps.devicebroker.getDevicesFiltered[0].handleFailure === 'ignore') {
351
+ assert.equal(null, error);
352
+ assert.notEqual(undefined, data);
353
+ assert.notEqual(null, data);
354
+ assert.equal(0, data.total);
355
+ assert.equal(0, data.list.length);
356
+ } else {
357
+ const displayE = 'Error 400 received on request';
358
+ runErrorAsserts(data, error, 'AD.500', 'Test-meraki-connectorRest-handleEndResponse', displayE);
359
+ }
360
+ } else {
361
+ runCommonAsserts(data, error);
362
+ }
363
+ done();
364
+ } catch (err) {
365
+ log.error(`Test Failure: ${err}`);
366
+ done(err);
367
+ }
368
+ });
369
+ } catch (error) {
370
+ log.error(`Adapter Exception: ${error}`);
371
+ done(error);
372
+ }
373
+ }).timeout(attemptTimeout);
374
+ });
375
+
376
+ describe('#iapGetDeviceCount - errors', () => {
377
+ it('should work if integrated but since no mockdata should error when run standalone', (done) => {
378
+ try {
379
+ const opts = {
380
+ filter: {
381
+ name: 'deviceName'
382
+ }
383
+ };
384
+ a.iapGetDeviceCount((data, error) => {
385
+ try {
386
+ if (stub) {
387
+ if (samProps.devicebroker.getDevicesFiltered[0].handleFailure === 'ignore') {
388
+ assert.equal(null, error);
389
+ assert.notEqual(undefined, data);
390
+ assert.notEqual(null, data);
391
+ assert.equal(0, data.count);
392
+ } else {
393
+ const displayE = 'Error 400 received on request';
394
+ runErrorAsserts(data, error, 'AD.500', 'Test-meraki-connectorRest-handleEndResponse', displayE);
395
+ }
396
+ } else {
397
+ runCommonAsserts(data, error);
398
+ }
399
+ done();
400
+ } catch (err) {
401
+ log.error(`Test Failure: ${err}`);
402
+ done(err);
403
+ }
404
+ });
405
+ } catch (error) {
406
+ log.error(`Adapter Exception: ${error}`);
407
+ done(error);
408
+ }
409
+ }).timeout(attemptTimeout);
410
+ });
411
+
412
+ // exposed cache tests
413
+ describe('#iapPopulateEntityCache - errors', () => {
414
+ it('should work if integrated but since no mockdata should error when run standalone', (done) => {
415
+ try {
416
+ a.iapPopulateEntityCache('Device', (data, error) => {
417
+ try {
418
+ if (stub) {
419
+ assert.equal(null, data);
420
+ assert.notEqual(undefined, error);
421
+ assert.notEqual(null, error);
422
+ done();
423
+ } else {
424
+ assert.equal(undefined, error);
425
+ assert.equal('success', data[0]);
426
+ done();
427
+ }
428
+ } catch (err) {
429
+ log.error(`Test Failure: ${err}`);
430
+ done(err);
431
+ }
432
+ });
433
+ } catch (error) {
434
+ log.error(`Adapter Exception: ${error}`);
435
+ done(error);
436
+ }
437
+ }).timeout(attemptTimeout);
438
+ });
439
+
440
+ describe('#iapRetrieveEntitiesCache - errors', () => {
441
+ it('should work if integrated but since no mockdata should error when run standalone', (done) => {
442
+ try {
443
+ a.iapRetrieveEntitiesCache('Device', {}, (data, error) => {
444
+ try {
445
+ if (stub) {
446
+ assert.equal(null, data);
447
+ assert.notEqual(null, error);
448
+ assert.notEqual(undefined, error);
449
+ } else {
450
+ assert.equal(undefined, error);
451
+ assert.notEqual(null, data);
452
+ assert.notEqual(undefined, data);
453
+ }
454
+ done();
455
+ } catch (err) {
456
+ log.error(`Test Failure: ${err}`);
457
+ done(err);
458
+ }
459
+ });
460
+ } catch (error) {
461
+ log.error(`Adapter Exception: ${error}`);
462
+ done(error);
463
+ }
464
+ }).timeout(attemptTimeout);
465
+ });
338
466
  /*
339
467
  -----------------------------------------------------------------------
340
468
  -----------------------------------------------------------------------