@itentialopensource/adapter-bluecat_ipam 0.1.1

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 (108) hide show
  1. package/.eslintignore +5 -0
  2. package/.eslintrc.js +19 -0
  3. package/.jshintrc +3 -0
  4. package/AUTH.md +39 -0
  5. package/BROKER.md +211 -0
  6. package/CALLS.md +3069 -0
  7. package/CHANGELOG.md +9 -0
  8. package/CODE_OF_CONDUCT.md +43 -0
  9. package/CONTRIBUTING.md +13 -0
  10. package/ENHANCE.md +69 -0
  11. package/LICENSE +201 -0
  12. package/PROPERTIES.md +681 -0
  13. package/README.md +344 -0
  14. package/SUMMARY.md +9 -0
  15. package/SYSTEMINFO.md +25 -0
  16. package/TAB1.md +15 -0
  17. package/TAB2.md +318 -0
  18. package/TROUBLESHOOT.md +56 -0
  19. package/UTILITIES.md +473 -0
  20. package/adapter.js +47832 -0
  21. package/adapterBase.js +1526 -0
  22. package/entities/.generic/action.json +214 -0
  23. package/entities/.generic/schema.json +28 -0
  24. package/entities/.system/action.json +50 -0
  25. package/entities/.system/mockdatafiles/getToken-default.json +3 -0
  26. package/entities/.system/mockdatafiles/healthcheck-default.json +3 -0
  27. package/entities/.system/schema.json +19 -0
  28. package/entities/.system/schemaTokenReq.json +53 -0
  29. package/entities/.system/schemaTokenResp.json +53 -0
  30. package/entities/ACLResources/action.json +127 -0
  31. package/entities/ACLResources/schema.json +24 -0
  32. package/entities/AdminResources/action.json +1954 -0
  33. package/entities/AdminResources/schema.json +113 -0
  34. package/entities/ConfigurationResources/action.json +106 -0
  35. package/entities/ConfigurationResources/schema.json +23 -0
  36. package/entities/DHCPClientClassResources/action.json +250 -0
  37. package/entities/DHCPClientClassResources/schema.json +30 -0
  38. package/entities/DHCPZoneResources/action.json +250 -0
  39. package/entities/DHCPZoneResources/schema.json +30 -0
  40. package/entities/DNSSECResources/action.json +147 -0
  41. package/entities/DNSSECResources/schema.json +25 -0
  42. package/entities/DeploymentOptionResources/action.json +250 -0
  43. package/entities/DeploymentOptionResources/schema.json +30 -0
  44. package/entities/DeploymentRoleResources/action.json +169 -0
  45. package/entities/DeploymentRoleResources/schema.json +26 -0
  46. package/entities/DeviceResources/action.json +352 -0
  47. package/entities/DeviceResources/schema.json +35 -0
  48. package/entities/FavoriteResources/action.json +65 -0
  49. package/entities/FavoriteResources/schema.json +21 -0
  50. package/entities/IPv4AndIPv6Resources/action.json +1964 -0
  51. package/entities/IPv4AndIPv6Resources/schema.json +113 -0
  52. package/entities/KerberosResources/action.json +393 -0
  53. package/entities/KerberosResources/schema.json +37 -0
  54. package/entities/LocationResources/action.json +209 -0
  55. package/entities/LocationResources/schema.json +28 -0
  56. package/entities/MACAddressAndClientIdentifierResources/action.json +395 -0
  57. package/entities/MACAddressAndClientIdentifierResources/schema.json +37 -0
  58. package/entities/NamingPolicyResources/action.json +476 -0
  59. package/entities/NamingPolicyResources/schema.json +41 -0
  60. package/entities/ResourceRecordResources/action.json +377 -0
  61. package/entities/ResourceRecordResources/schema.json +36 -0
  62. package/entities/ServerResources/action.json +784 -0
  63. package/entities/ServerResources/schema.json +56 -0
  64. package/entities/TFTPResources/action.json +250 -0
  65. package/entities/TFTPResources/schema.json +30 -0
  66. package/entities/TagResources/action.json +495 -0
  67. package/entities/TagResources/schema.json +42 -0
  68. package/entities/TaskResources/action.json +106 -0
  69. package/entities/TaskResources/schema.json +23 -0
  70. package/entities/VendorProfileResources/action.json +106 -0
  71. package/entities/VendorProfileResources/schema.json +23 -0
  72. package/entities/ViewAndZoneResources/action.json +660 -0
  73. package/entities/ViewAndZoneResources/schema.json +50 -0
  74. package/error.json +190 -0
  75. package/metadata.json +84 -0
  76. package/package.json +75 -0
  77. package/pronghorn.json +34480 -0
  78. package/propertiesDecorators.json +18 -0
  79. package/propertiesSchema.json +1777 -0
  80. package/report/Bluecat IPAM 9.5 v2 API.yml-OpenApi3Json.json +114720 -0
  81. package/report/adapterInfo.json +10 -0
  82. package/report/auto-adapter-openapi.json +28663 -0
  83. package/report/creationReport.json +2910 -0
  84. package/sampleProperties.json +264 -0
  85. package/test/integration/adapterTestBasicGet.js +117 -0
  86. package/test/integration/adapterTestConnectivity.js +117 -0
  87. package/test/integration/adapterTestIntegration.js +12568 -0
  88. package/test/unit/adapterBaseTestUnit.js +1628 -0
  89. package/test/unit/adapterTestUnit.js +16058 -0
  90. package/utils/adapterInfo.js +156 -0
  91. package/utils/argParser.js +44 -0
  92. package/utils/checkMigrate.js +102 -0
  93. package/utils/entitiesToDB.js +190 -0
  94. package/utils/findPath.js +74 -0
  95. package/utils/logger.js +26 -0
  96. package/utils/methodDocumentor.js +298 -0
  97. package/utils/modify.js +153 -0
  98. package/utils/mongoDbConnection.js +79 -0
  99. package/utils/mongoUtils.js +162 -0
  100. package/utils/pre-commit.sh +32 -0
  101. package/utils/removeHooks.js +20 -0
  102. package/utils/setup.js +33 -0
  103. package/utils/taskMover.js +308 -0
  104. package/utils/tbScript.js +103 -0
  105. package/utils/tbUtils.js +347 -0
  106. package/utils/testRunner.js +298 -0
  107. package/utils/troubleshootingAdapter.js +177 -0
  108. package/utils/updateAdapterConfig.js +158 -0
@@ -0,0 +1,177 @@
1
+ /* @copyright Itential, LLC 2020 */
2
+ /* eslint global-require: warn */
3
+ /* eslint no-console: warn */
4
+ /* eslint import/no-unresolved: warn */
5
+ /* eslint import/no-dynamic-require: warn */
6
+
7
+ const path = require('path');
8
+ const rls = require('readline-sync');
9
+
10
+ const tbUtils = require(path.join(__dirname, 'tbUtils'));
11
+ const { name } = require(path.join(__dirname, '..', 'package.json'));
12
+ const sampleProperties = require(path.join(__dirname, '..', 'sampleProperties.json'));
13
+
14
+ // send interactive questions and collection answers
15
+ // return updated connection object
16
+ const collectAnswersSync = (questions, props) => {
17
+ const answers = [];
18
+ questions.forEach((q) => {
19
+ const answer = rls.question(q);
20
+ answers.push(answer);
21
+ });
22
+ return tbUtils.getNewProps(answers, props);
23
+ };
24
+
25
+ // change object into array of questions
26
+ const confirm = (props) => {
27
+ const questions = Object.keys(props).map((key) => `${key}: (${props[key]}) `);
28
+ return collectAnswersSync(questions, props);
29
+ };
30
+
31
+ // allow user to change auth_method
32
+ const confirmAuthOptions = (authentication) => {
33
+ const authOptions = ['basic user_password', 'request_token', 'static_token', 'no_authentication'];
34
+ const displayAuthOptions = tbUtils.getDisplayAuthOptions(authentication.auth_method, authOptions);
35
+ const index = rls.keyInSelect(displayAuthOptions, 'Which authentication?');
36
+ if (index === -1) {
37
+ return authentication.auth_method;
38
+ }
39
+ console.log(`${authOptions[index]} is selected.`);
40
+ return authOptions[index];
41
+ };
42
+
43
+ // helper function to update auth properties
44
+ const confirmAndUpdate = (auth, config) => {
45
+ const newAuth = confirm(auth);
46
+ return tbUtils.updateAuth(newAuth, auth, config);
47
+ };
48
+
49
+ // extract basic auth properties
50
+ const updateBasicAuth = (config, authentication) => {
51
+ const auth = {
52
+ username: authentication.username,
53
+ password: authentication.password
54
+ };
55
+ return confirmAndUpdate(auth, config);
56
+ };
57
+
58
+ // extract static auth properties
59
+ const updateStaticAuth = (config, authentication) => {
60
+ const auth = {
61
+ token: authentication.token,
62
+ auth_field: authentication.auth_field,
63
+ auth_field_format: authentication.auth_field_format
64
+ };
65
+ return confirmAndUpdate(auth, config);
66
+ };
67
+
68
+ // troubleshooting connection and healthcheck endpoint setting of adapter
69
+ const VerifyHealthCheckEndpoint = (serviceItem, props, scriptFlag) => {
70
+ let connConfig;
71
+ const result = {};
72
+
73
+ if (scriptFlag) {
74
+ const connection = tbUtils.getConnection(serviceItem.properties);
75
+ const newConnection = confirm(connection);
76
+ tbUtils.runConnectivity(newConnection.host, scriptFlag);
77
+ connConfig = tbUtils.updateNewConnection(serviceItem, newConnection);
78
+ } else {
79
+ let { properties: { properties: { host } } } = serviceItem;
80
+
81
+ connConfig = props.connProps
82
+ ? tbUtils.updateNewConnection(serviceItem, props.connProps)
83
+ : serviceItem;
84
+
85
+ if (props.connProps) {
86
+ host = connConfig.properties.properties.host;
87
+ }
88
+
89
+ result.connectivity = tbUtils.runConnectivity(host, scriptFlag);
90
+ }
91
+
92
+ // Updates the healthcheck endpoint
93
+ const healthcheck = require(path.resolve(__dirname, '../entities/.system/action.json'));
94
+ const healthCheckEndpoint = tbUtils.getHealthCheckEndpoint(healthcheck);
95
+ let newHealthCheckEndpoint = healthCheckEndpoint;
96
+
97
+ if (scriptFlag) {
98
+ newHealthCheckEndpoint = confirm(healthCheckEndpoint);
99
+ tbUtils.getHealthCheckEndpointURL(newHealthCheckEndpoint, connConfig);
100
+ } else if (props.healthCheckEndpoint) {
101
+ newHealthCheckEndpoint = props.healthCheckEndpoint;
102
+ }
103
+
104
+ // Updates the authorization params
105
+ const { authentication } = connConfig.properties.properties;
106
+ let updatedAdapter = connConfig;
107
+ if (scriptFlag) {
108
+ authentication.auth_method = confirmAuthOptions(authentication);
109
+ if (authentication.auth_method === 'basic user_password') {
110
+ updatedAdapter = updateBasicAuth(connConfig, authentication);
111
+ } else if (authentication.auth_method === 'static_token') {
112
+ updatedAdapter = updateStaticAuth(connConfig, authentication);
113
+ } else if (authentication.auth_method === 'request_token') {
114
+ console.log('current troubleshooting script does not support updating request_token authentication');
115
+ }
116
+ } else if (props.auth) {
117
+ updatedAdapter = tbUtils.updateAuth(props.auth, authentication, connConfig);
118
+ }
119
+ return { result, updatedAdapter };
120
+ };
121
+
122
+ const troubleshoot = async (props, scriptFlag, adapter) => {
123
+ let serviceItem;
124
+
125
+ if (adapter && adapter.allProps) {
126
+ serviceItem = { properties: { properties: adapter.allProps } };
127
+ } else if (adapter && adapter.properties && adapter.properties.properties) {
128
+ serviceItem = adapter.properties;
129
+ } else {
130
+ serviceItem = { properties: sampleProperties };
131
+ }
132
+
133
+ if (!serviceItem) {
134
+ console.log(`${name} not installed`);
135
+ console.log('run `npm run install:adapter` to install current adapter to IAP first. Exiting...');
136
+ if (scriptFlag) {
137
+ process.exit(1);
138
+ }
139
+ return null;
140
+ }
141
+
142
+ const shouldRun = !scriptFlag || rls.keyInYN(`Start verifying the connection and authentication properties for ${name}?`);
143
+ if (!shouldRun) {
144
+ console.log('You can update healthCheckEndpoint in ./entities/.system/action.json');
145
+ console.log('You can update authentication credientials under Settings/Services');
146
+ if (scriptFlag) {
147
+ process.exit(0);
148
+ }
149
+ return null;
150
+ }
151
+
152
+ const { result, updatedAdapter } = VerifyHealthCheckEndpoint(serviceItem, props, scriptFlag);
153
+ const a = scriptFlag ? tbUtils.getAdapterInstance(updatedAdapter) : adapter;
154
+
155
+ const healthRes = await tbUtils.healthCheck(a);
156
+ result.healthCheck = healthRes;
157
+
158
+ if (scriptFlag && !healthRes) {
159
+ console.log('run `npm run troubleshoot` again to update settings');
160
+ process.exit(1);
161
+ }
162
+
163
+ if (scriptFlag) {
164
+ if (rls.keyInYN('Test with more GET request')) {
165
+ await tbUtils.runBasicGet(serviceItem.properties.properties, true);
166
+ } else {
167
+ console.log('Exiting');
168
+ }
169
+ process.exit(0);
170
+ }
171
+
172
+ result.basicGet = await tbUtils.runBasicGet(serviceItem.properties.properties, false);
173
+
174
+ return result;
175
+ };
176
+
177
+ module.exports = { troubleshoot };
@@ -0,0 +1,158 @@
1
+ /* @copyright Itential, LLC 2025 */
2
+
3
+ // Set globals
4
+ /* global log */
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+ const PropUtilCl = require('@itentialopensource/adapter-utils').PropertyUtility;
9
+ const MongoDBConnection = require('./mongoDbConnection');
10
+
11
+ const propUtil = new PropUtilCl();
12
+
13
+ /**
14
+ * Updates action configuration in the document
15
+ * @param {Object} doc - Document to update
16
+ * @param {string} action - Action name
17
+ * @param {Object} changes - Changes to apply
18
+ * @returns {Object} Updated document
19
+ */
20
+ function updateActionConfig(doc, action, changes) {
21
+ const updateDoc = { ...doc };
22
+ if (!updateDoc.actions) updateDoc.actions = [];
23
+ const actionIndex = updateDoc.actions.findIndex((a) => a.name === action);
24
+ if (actionIndex >= 0) {
25
+ updateDoc.actions[actionIndex] = propUtil.mergeProperties(changes, updateDoc.actions[actionIndex]);
26
+ } else {
27
+ updateDoc.actions.push({ name: action, ...changes });
28
+ }
29
+ return updateDoc;
30
+ }
31
+
32
+ /**
33
+ * Updates schema configuration in the document
34
+ * @param {Object} doc - Document to update
35
+ * @param {string} configFile - Configuration file name
36
+ * @param {Object} changes - Changes to apply
37
+ * @returns {Object} Updated document
38
+ */
39
+ function updateSchemaConfig(doc, configFile, changes) {
40
+ const updateDoc = { ...doc };
41
+ if (!updateDoc.schema) updateDoc.schema = [];
42
+ const schemaIndex = updateDoc.schema.findIndex((s) => s.name === configFile);
43
+ if (schemaIndex >= 0) {
44
+ updateDoc.schema[schemaIndex].schema = propUtil.mergeProperties(changes, updateDoc.schema[schemaIndex].schema);
45
+ } else {
46
+ updateDoc.schema.push({ name: configFile, schema: changes });
47
+ }
48
+ return updateDoc;
49
+ }
50
+
51
+ /**
52
+ * Updates mock data configuration in the document
53
+ * @param {Object} doc - Document to update
54
+ * @param {string} configFile - Configuration file name
55
+ * @param {Object} changes - Changes to apply
56
+ * @param {boolean} replace - Whether to replace or merge
57
+ * @returns {Object} Updated document
58
+ */
59
+ function updateMockConfig(doc, configFile, changes, replace) {
60
+ const updateDoc = { ...doc };
61
+ if (!updateDoc.mockdatafiles) updateDoc.mockdatafiles = {};
62
+ updateDoc.mockdatafiles[configFile] = replace ? changes : propUtil.mergeProperties(changes, updateDoc.mockdatafiles[configFile] || {});
63
+ return updateDoc;
64
+ }
65
+
66
+ /**
67
+ * Configuration update strategies for different types
68
+ */
69
+ const updateStrategies = {
70
+ action: (doc, configFile, changes, action) => (!action ? doc : updateActionConfig(doc, action, changes)),
71
+ schema: (doc, configFile, changes) => updateSchemaConfig(doc, configFile, changes),
72
+ mock: (doc, configFile, changes, replace) => updateMockConfig(doc, configFile, changes, replace)
73
+ };
74
+
75
+ /**
76
+ * Updates MongoDB configuration for an adapter entity
77
+ * @param {Object} options - Configuration options
78
+ * @param {string} options.id - Adapter ID
79
+ * @param {Object} options.mongoProps - MongoDB connection properties
80
+ * @param {string} options.entity - Entity name
81
+ * @param {string} options.type - Update type (action/schema/mock)
82
+ * @param {string} options.configFile - Configuration file name
83
+ * @param {Object} options.changes - Changes to apply
84
+ * @param {string} options.action - Action name (for action type updates)
85
+ * @param {boolean} options.replace - Whether to replace or merge (for mock type updates)
86
+ * @returns {Promise<void>}
87
+ */
88
+ async function updateMongoDBConfig(options) {
89
+ const {
90
+ id,
91
+ mongoProps,
92
+ entity,
93
+ type,
94
+ configFile,
95
+ changes,
96
+ action,
97
+ replace
98
+ } = options;
99
+
100
+ if (!mongoProps) {
101
+ log.error('MongoDB properties not found');
102
+ return;
103
+ }
104
+
105
+ let mongoConnection = null;
106
+ try {
107
+ // Get adapter type from pronghorn.json
108
+ const pronghornPath = path.join(__dirname, '../pronghorn.json');
109
+ const pronghornData = JSON.parse(fs.readFileSync(pronghornPath, 'utf8'));
110
+ const adapterType = pronghornData.id;
111
+
112
+ mongoConnection = new MongoDBConnection(mongoProps);
113
+ await mongoConnection.connect();
114
+
115
+ const collection = mongoConnection.db.collection('adapter_configs');
116
+ const query = {
117
+ id,
118
+ type: adapterType,
119
+ entity
120
+ };
121
+
122
+ const existingConfig = await collection.findOne(query);
123
+ if (!existingConfig) {
124
+ log.debug(`No existing configuration found for entity ${entity}`);
125
+ return;
126
+ }
127
+
128
+ // Update the configuration based on type
129
+ const updateStrategy = updateStrategies[type];
130
+ if (!updateStrategy) {
131
+ log.error(`Unsupported update type: ${type}`);
132
+ return;
133
+ }
134
+
135
+ const updatedDoc = updateStrategy(existingConfig, configFile, changes, action || replace);
136
+
137
+ // Remove _id from updateDoc as it can't be modified
138
+ const { _id, ...updateDocWithoutId } = updatedDoc;
139
+ const updateResult = await collection.updateOne(
140
+ { id, type: adapterType, entity },
141
+ { $set: updateDocWithoutId }
142
+ );
143
+
144
+ if (updateResult.modifiedCount === 0) {
145
+ log.warn(`No documents were modified for entity ${entity}`);
146
+ }
147
+ log.info(`Successfully updated MongoDB configuration for entity ${entity}`);
148
+ } catch (error) {
149
+ log.error(`Error updating MongoDB configuration: ${error.message}`);
150
+ throw error;
151
+ } finally {
152
+ if (mongoConnection) {
153
+ await mongoConnection.closeConnection();
154
+ }
155
+ }
156
+ }
157
+
158
+ module.exports = { updateMongoDBConfig };