cisco-axl 1.5.0 → 2.0.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.
- package/README.md +219 -308
- package/bin/cisco-axl.js +2 -0
- package/cli/commands/add.js +175 -0
- package/cli/commands/config.js +155 -0
- package/cli/commands/describe.js +84 -0
- package/cli/commands/execute.js +173 -0
- package/cli/commands/get.js +93 -0
- package/cli/commands/list.js +216 -0
- package/cli/commands/operations.js +80 -0
- package/cli/commands/remove.js +61 -0
- package/cli/commands/sql.js +110 -0
- package/cli/commands/update.js +185 -0
- package/cli/formatters/csv.js +16 -0
- package/cli/formatters/json.js +12 -0
- package/cli/formatters/table.js +55 -0
- package/cli/formatters/toon.js +15 -0
- package/cli/index.js +42 -0
- package/cli/utils/audit.js +89 -0
- package/cli/utils/config.js +296 -0
- package/cli/utils/connection.js +142 -0
- package/cli/utils/output.js +53 -0
- package/cli/utils/readonly.js +31 -0
- package/cli/utils/template.js +80 -0
- package/dist/index.js +29 -6
- package/dist/index.js.map +1 -1
- package/package.json +13 -5
- package/skills/cisco-axl-cli/SKILL.md +179 -0
- package/src/index.ts +32 -6
package/README.md
CHANGED
|
@@ -1,298 +1,252 @@
|
|
|
1
|
-
# Cisco AXL
|
|
1
|
+
# Cisco AXL Library & CLI
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A JavaScript library and CLI to interact with Cisco CUCM via AXL SOAP API. Dynamically discovers all AXL operations from the WSDL schema — any operation for your specified version is available without static definitions.
|
|
4
4
|
|
|
5
5
|
Administrative XML (AXL) information can be found at:
|
|
6
6
|
[Administrative XML (AXL) Reference](https://developer.cisco.com/docs/axl/#!axl-developer-guide).
|
|
7
7
|
|
|
8
8
|
## Installation
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
```javascript
|
|
13
|
-
npm i -g npm
|
|
14
|
-
npm i --save cisco-axl
|
|
10
|
+
```bash
|
|
11
|
+
npm install cisco-axl
|
|
15
12
|
```
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
This package uses the built in Fetch API of Node. This feature was first introduced in Node v16.15.0. You may need to enable expermential vm module. Also you can disable warnings with an optional enviromental variable.
|
|
14
|
+
### Global CLI install
|
|
20
15
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
Suggested enviromental variables:
|
|
24
|
-
|
|
25
|
-
```env
|
|
26
|
-
NODE_OPTIONS=--experimental-vm-modules
|
|
27
|
-
NODE_NO_WARNINGS=1
|
|
28
|
-
NODE_TLS_REJECT_UNAUTHORIZED=0
|
|
16
|
+
```bash
|
|
17
|
+
npm install -g cisco-axl
|
|
29
18
|
```
|
|
30
19
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
You can configure logging via the constructor options or the `DEBUG` environment variable.
|
|
20
|
+
Or run without installing:
|
|
34
21
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
```env
|
|
38
|
-
DEBUG=true
|
|
22
|
+
```bash
|
|
23
|
+
npx cisco-axl --help
|
|
39
24
|
```
|
|
40
25
|
|
|
41
|
-
|
|
26
|
+
### AI Agent Skills
|
|
42
27
|
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
logging: {
|
|
46
|
-
level: "info", // "error" | "warn" | "info" | "debug"
|
|
47
|
-
handler: (level, message, data) => {
|
|
48
|
-
// Custom log handler — send to your logging framework, file, etc.
|
|
49
|
-
myLogger[level](message, data);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// Change level at runtime
|
|
55
|
-
service.setLogLevel("debug");
|
|
28
|
+
```bash
|
|
29
|
+
npx skillsadd sieteunoseis/cisco-axl
|
|
56
30
|
```
|
|
57
31
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
## Features
|
|
61
|
-
|
|
62
|
-
- Uses strong-soap to parse the AXL WSDL file — any AXL function for your specified version is available
|
|
63
|
-
- Promise-based API with async/await support
|
|
64
|
-
- Returns JSON, with optional cleaning of empty/null fields and attribute removal
|
|
65
|
-
- [json-variables](https://codsen.com/os/json-variables) support for template-based operations
|
|
66
|
-
- TypeScript support with full type definitions
|
|
67
|
-
- ESM and CommonJS dual-package support
|
|
68
|
-
- Custom error classes (`AXLAuthError`, `AXLOperationError`, `AXLNotFoundError`, `AXLValidationError`)
|
|
69
|
-
- Retry mechanism with exponential backoff for transient network errors
|
|
70
|
-
- Batch operations with concurrency control (`executeBatch`)
|
|
71
|
-
- Convenience methods for common CRUD operations (`getItem`, `listItems`, `addItem`, `updateItem`, `removeItem`)
|
|
72
|
-
- SQL query/update helpers (`executeSqlQuery`, `executeSqlUpdate`)
|
|
73
|
-
- Detailed tag metadata including required/nillable/type info (`getOperationTagsDetailed`)
|
|
74
|
-
- Configurable logging with levels and custom handlers
|
|
75
|
-
- SOAP client caching for improved performance
|
|
76
|
-
- Input parameter validation with descriptive error messages
|
|
77
|
-
- Authentication testing with the `testAuthentication` method
|
|
78
|
-
|
|
79
|
-
## Usage
|
|
32
|
+
## Requirements
|
|
80
33
|
|
|
81
|
-
|
|
82
|
-
const axlService = require("cisco-axl");
|
|
34
|
+
If you are using self-signed certificates on Cisco VOS products you may need to disable TLS verification, or use the `--insecure` CLI flag.
|
|
83
35
|
|
|
84
|
-
|
|
36
|
+
Supported CUCM versions: `11.0`, `11.5`, `12.0`, `12.5`, `14.0`, `15.0`
|
|
85
37
|
|
|
86
|
-
|
|
87
|
-
var tags = {
|
|
88
|
-
routePartition: {
|
|
89
|
-
name: "INTERNAL-PT",
|
|
90
|
-
description: "Internal directory numbers",
|
|
91
|
-
},
|
|
92
|
-
};
|
|
38
|
+
## CLI
|
|
93
39
|
|
|
94
|
-
|
|
95
|
-
.executeOperation("addRoutePartition", tags)
|
|
96
|
-
.then((results) => {
|
|
97
|
-
console.log("addRoutePartition UUID", results);
|
|
98
|
-
})
|
|
99
|
-
.catch((error) => {
|
|
100
|
-
console.log(error);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
// Convenience methods (v1.5.0+)
|
|
104
|
-
await service.addItem("RoutePartition", { name: "INTERNAL-PT", description: "Internal" });
|
|
105
|
-
await service.listItems("RoutePartition");
|
|
106
|
-
await service.getItem("RoutePartition", "INTERNAL-PT");
|
|
107
|
-
await service.updateItem("RoutePartition", "INTERNAL-PT", { description: "Updated" });
|
|
108
|
-
await service.removeItem("RoutePartition", "INTERNAL-PT");
|
|
109
|
-
|
|
110
|
-
// SQL queries
|
|
111
|
-
await service.executeSqlQuery("SELECT name FROM routepartition");
|
|
112
|
-
|
|
113
|
-
// Batch operations
|
|
114
|
-
const results = await service.executeBatch([
|
|
115
|
-
{ operation: "getRoutePartition", tags: { name: "INTERNAL-PT" } },
|
|
116
|
-
{ operation: "getRoutePartition", tags: { name: "EXTERNAL-PT" } },
|
|
117
|
-
], 5); // concurrency limit
|
|
118
|
-
```
|
|
40
|
+
The CLI provides full AXL access from the command line — CRUD operations, SQL queries, operation discovery, bulk provisioning from CSV, and a raw execute escape hatch for any AXL operation.
|
|
119
41
|
|
|
120
|
-
|
|
42
|
+
### Quick Start
|
|
121
43
|
|
|
122
|
-
|
|
44
|
+
```bash
|
|
45
|
+
# Configure a cluster
|
|
46
|
+
cisco-axl config add lab --host 10.0.0.1 --username admin --password secret --cucm-version 14.0 --insecure
|
|
123
47
|
|
|
124
|
-
|
|
125
|
-
-
|
|
126
|
-
- `service.returnOperations(filter?)`
|
|
127
|
-
- `service.getOperationTags(operation)`
|
|
128
|
-
- `service.getOperationTagsDetailed(operation)`
|
|
129
|
-
- `service.executeOperation(operation, tags, opts?)`
|
|
130
|
-
- `service.executeBatch(operations, concurrency?)`
|
|
131
|
-
- `service.setLogLevel(level)`
|
|
48
|
+
# Test the connection
|
|
49
|
+
cisco-axl config test
|
|
132
50
|
|
|
133
|
-
|
|
51
|
+
# List phones
|
|
52
|
+
cisco-axl list Phone --search "name=SEP%"
|
|
134
53
|
|
|
135
|
-
|
|
136
|
-
-
|
|
137
|
-
- `service.addItem(itemType, data, opts?)`
|
|
138
|
-
- `service.updateItem(itemType, identifier, updates, opts?)`
|
|
139
|
-
- `service.removeItem(itemType, identifier, opts?)`
|
|
140
|
-
- `service.executeSqlQuery(sql)`
|
|
141
|
-
- `service.executeSqlUpdate(sql)`
|
|
54
|
+
# Get a specific phone
|
|
55
|
+
cisco-axl get Phone SEP001122334455 --returned-tags "name,model,description"
|
|
142
56
|
|
|
143
|
-
|
|
57
|
+
# SQL query
|
|
58
|
+
cisco-axl sql query "SELECT name, description FROM device WHERE name LIKE 'SEP%'"
|
|
144
59
|
|
|
145
|
-
|
|
60
|
+
# Discover available operations
|
|
61
|
+
cisco-axl operations --filter phone
|
|
62
|
+
cisco-axl operations --type action --filter phone
|
|
146
63
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
let service = new axlService("10.10.20.1", "administrator", "ciscopsdt", "14.0");
|
|
64
|
+
# Describe what tags an operation needs
|
|
65
|
+
cisco-axl describe getPhone --detailed
|
|
150
66
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
logging: { level: "info" },
|
|
154
|
-
retry: { retries: 3, retryDelay: 1000 } // exponential backoff for transient errors
|
|
155
|
-
});
|
|
67
|
+
# Execute any AXL operation
|
|
68
|
+
cisco-axl execute doLdapSync --tags '{"name":"LDAP_Main"}'
|
|
156
69
|
```
|
|
157
70
|
|
|
158
|
-
|
|
71
|
+
### Commands
|
|
72
|
+
|
|
73
|
+
| Command | Description |
|
|
74
|
+
|---------|-------------|
|
|
75
|
+
| `config add/use/list/show/remove/test` | Manage multi-cluster configurations |
|
|
76
|
+
| `get <type> <identifier>` | Get a single item |
|
|
77
|
+
| `list <type>` | List items with search, pagination, returned tags |
|
|
78
|
+
| `add <type>` | Add an item (inline JSON, template, or bulk CSV) |
|
|
79
|
+
| `update <type> <identifier>` | Update an item |
|
|
80
|
+
| `remove <type> <identifier>` | Remove an item |
|
|
81
|
+
| `sql query/update` | Execute SQL against CUCM |
|
|
82
|
+
| `execute <operation>` | Run any raw AXL operation |
|
|
83
|
+
| `operations` | List available operations with `--filter` and `--type crud\|action` |
|
|
84
|
+
| `describe <operation>` | Show tag schema with `--detailed` for required/optional/type info |
|
|
85
|
+
|
|
86
|
+
### Configuration
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# Multiple clusters
|
|
90
|
+
cisco-axl config add lab --host 10.0.0.1 --username admin --password secret --cucm-version 14.0 --insecure
|
|
91
|
+
cisco-axl config add prod --host 10.0.0.2 --username axladmin --password secret --cucm-version 15.0 --insecure
|
|
92
|
+
cisco-axl config use prod
|
|
93
|
+
cisco-axl config list
|
|
94
|
+
|
|
95
|
+
# Per-command cluster override
|
|
96
|
+
cisco-axl list Phone --search "name=SEP%" --cluster lab
|
|
97
|
+
|
|
98
|
+
# Environment variables (CI/CD, AI agents)
|
|
99
|
+
export CUCM_HOST=10.0.0.1 CUCM_USERNAME=admin CUCM_PASSWORD=secret CUCM_VERSION=14.0
|
|
100
|
+
```
|
|
159
101
|
|
|
160
|
-
|
|
102
|
+
Config stored at `~/.cisco-axl/config.json`. Supports optional [Secret Server](https://github.com/sieteunoseis/ss-cli) integration via `<ss:ID:field>` placeholders.
|
|
161
103
|
|
|
162
|
-
|
|
104
|
+
### Output Formats
|
|
163
105
|
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
.catch((error) => {
|
|
170
|
-
console.error('Authentication failed:', error.message);
|
|
171
|
-
});
|
|
106
|
+
```bash
|
|
107
|
+
cisco-axl list Phone --search "name=SEP%" --format table # default, human-readable
|
|
108
|
+
cisco-axl list Phone --search "name=SEP%" --format json # structured JSON
|
|
109
|
+
cisco-axl list Phone --search "name=SEP%" --format toon # token-efficient for AI agents
|
|
110
|
+
cisco-axl list Phone --search "name=SEP%" --format csv # spreadsheet export
|
|
172
111
|
```
|
|
173
112
|
|
|
174
|
-
###
|
|
113
|
+
### Bulk Operations from CSV
|
|
175
114
|
|
|
176
|
-
|
|
115
|
+
Requires optional packages: `npm install json-variables csv-parse`
|
|
177
116
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
117
|
+
```bash
|
|
118
|
+
# Bulk add phones from template + CSV
|
|
119
|
+
cisco-axl add Phone --template phone-template.json --csv phones.csv
|
|
120
|
+
cisco-axl add Phone --template phone-template.json --csv phones.csv --dry-run # preview first
|
|
181
121
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
122
|
+
# Single template with inline vars
|
|
123
|
+
cisco-axl add Phone --template phone-template.json --vars '{"mac":"001122334455","dp":"DP_HQ"}'
|
|
124
|
+
```
|
|
185
125
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
126
|
+
Template file (`phone-template.json`):
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"name": "SEP%%mac%%",
|
|
130
|
+
"devicePoolName": "%%devicePool%%",
|
|
131
|
+
"description": "%%description%%",
|
|
132
|
+
"protocol": "SIP"
|
|
133
|
+
}
|
|
134
|
+
```
|
|
189
135
|
|
|
190
|
-
###
|
|
136
|
+
### Global Flags
|
|
191
137
|
|
|
192
|
-
|
|
138
|
+
```
|
|
139
|
+
--format table|json|toon|csv Output format (default: table)
|
|
140
|
+
--insecure Skip TLS certificate verification
|
|
141
|
+
--clean Remove empty/null values from results
|
|
142
|
+
--no-attributes Remove XML attributes from results
|
|
143
|
+
--read-only Restrict to read-only operations
|
|
144
|
+
--no-audit Disable audit logging for this command
|
|
145
|
+
--debug Enable debug logging
|
|
146
|
+
```
|
|
193
147
|
|
|
194
|
-
|
|
195
|
-
| :----------------------- | :-------- | :----- | :--------- | :----------------------------------------------------------------------- |
|
|
196
|
-
| getOperationTagsDetailed | operation | string | Yes | Provide the name of the AXL operation you wish to retrieve the tags for. |
|
|
148
|
+
### Audit Trail
|
|
197
149
|
|
|
198
|
-
|
|
150
|
+
All operations are logged to `~/.cisco-axl/audit.jsonl` (JSONL format). Credentials are never logged. Use `--no-audit` to skip.
|
|
199
151
|
|
|
200
|
-
|
|
201
|
-
| :------- | :--------------- | :------------------------------------------------ |
|
|
202
|
-
| name | string | Tag name |
|
|
203
|
-
| required | boolean | Whether the tag is required (based on minOccurs) |
|
|
204
|
-
| nillable | boolean | Whether the tag accepts null values |
|
|
205
|
-
| isMany | boolean | Whether the tag can appear multiple times (array) |
|
|
206
|
-
| type | string \| null | XSD type name (e.g. "string", "XRoutePartition") |
|
|
207
|
-
| children | object \| null | Nested tag metadata, or null for leaf elements |
|
|
152
|
+
## Library API
|
|
208
153
|
|
|
209
|
-
|
|
154
|
+
### Setup
|
|
210
155
|
|
|
211
156
|
```javascript
|
|
212
|
-
|
|
213
|
-
console.log(tags.routePartition.required); // true
|
|
214
|
-
console.log(tags.routePartition.children.name.nillable); // true
|
|
215
|
-
console.log(tags.routePartition.children.name.type); // "string"
|
|
216
|
-
});
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### service.executeOperation(operation,tags,opts?) ⇒ Returns promise
|
|
220
|
-
|
|
221
|
-
Method requires passing an AXL operation and JSON object of tags. Returns results via Promise.
|
|
222
|
-
|
|
223
|
-
Current options include:
|
|
224
|
-
| option | type | description |
|
|
225
|
-
| :--------------------------- | :------ | :---------------------------------------------------------------------------------- |
|
|
226
|
-
| clean | boolean | Default: **false**. Allows method to remove all tags that have no values from return data. |
|
|
227
|
-
| removeAttributes | boolean | Default: **false**. Allows method to remove all attributes tags return data. |
|
|
228
|
-
| dataContainerIdentifierTails | string | Default: **'\_data'**. executeOperation will automatically remove any tag with the defined string. This is used with json-variables library. |
|
|
157
|
+
const axlService = require("cisco-axl");
|
|
229
158
|
|
|
230
|
-
|
|
159
|
+
let service = new axlService("10.10.20.1", "administrator", "ciscopsdt", "14.0");
|
|
231
160
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
};
|
|
161
|
+
// With options
|
|
162
|
+
let service = new axlService("10.10.20.1", "administrator", "ciscopsdt", "14.0", {
|
|
163
|
+
logging: { level: "info" },
|
|
164
|
+
retry: { retries: 3, retryDelay: 1000 }
|
|
165
|
+
});
|
|
238
166
|
```
|
|
239
167
|
|
|
240
|
-
|
|
241
|
-
| :--------------- | :-------- | :----- | :--------- | :--------------------------------------------------------- |
|
|
242
|
-
| executeOperation | operation | string | Yes | Provide the name of the AXL operation you wish to execute. |
|
|
243
|
-
| executeOperation | tags | object | Yes | Provide a JSON object of the tags for your operation. |
|
|
244
|
-
| executeOperation | opts | object | No | Provide a JSON object of options for your operation. |
|
|
245
|
-
|
|
246
|
-
### service.executeBatch(operations, concurrency?) ⇒ Returns promise
|
|
247
|
-
|
|
248
|
-
Executes multiple AXL operations in parallel with concurrency control. Returns an array of `BatchResult` objects in the same order as the input.
|
|
168
|
+
### Logging
|
|
249
169
|
|
|
250
170
|
```javascript
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
{ operation: "getPhone", tags: { name: "SEP556677889900" } },
|
|
254
|
-
{ operation: "getLine", tags: { pattern: "1001", routePartitionName: "INTERNAL-PT" } },
|
|
255
|
-
], 3); // max 3 concurrent requests
|
|
171
|
+
// Via environment variable
|
|
172
|
+
// DEBUG=true
|
|
256
173
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
174
|
+
// Via constructor
|
|
175
|
+
let service = new axlService("10.10.20.1", "administrator", "ciscopsdt", "14.0", {
|
|
176
|
+
logging: {
|
|
177
|
+
level: "info", // "error" | "warn" | "info" | "debug"
|
|
178
|
+
handler: (level, message, data) => {
|
|
179
|
+
myLogger[level](message, data);
|
|
180
|
+
}
|
|
262
181
|
}
|
|
263
182
|
});
|
|
183
|
+
|
|
184
|
+
// Change at runtime
|
|
185
|
+
service.setLogLevel("debug");
|
|
264
186
|
```
|
|
265
187
|
|
|
266
188
|
### Convenience Methods
|
|
267
189
|
|
|
268
|
-
These methods simplify common CRUD operations. The `itemType` parameter is the PascalCase AXL type (e.g. `"Phone"`, `"Line"`, `"RoutePartition"`).
|
|
269
|
-
|
|
270
190
|
```javascript
|
|
271
191
|
// Get a single item by name or UUID
|
|
272
192
|
await service.getItem("Phone", "SEP001122334455");
|
|
273
193
|
await service.getItem("Phone", { uuid: "abc-123" });
|
|
274
194
|
|
|
275
|
-
// List items with search criteria
|
|
195
|
+
// List items with search criteria and returned tags
|
|
276
196
|
await service.listItems("RoutePartition"); // all partitions
|
|
277
|
-
await service.listItems("Phone", { name: "SEP%" });
|
|
197
|
+
await service.listItems("Phone", { name: "SEP%" }, { name: "", model: "" });
|
|
278
198
|
|
|
279
|
-
// Add
|
|
280
|
-
await service.addItem("RoutePartition", { name: "NEW-PT", description: "New
|
|
281
|
-
|
|
282
|
-
// Update an existing item
|
|
199
|
+
// Add, update, remove
|
|
200
|
+
await service.addItem("RoutePartition", { name: "NEW-PT", description: "New" });
|
|
283
201
|
await service.updateItem("Phone", "SEP001122334455", { description: "Updated" });
|
|
284
|
-
|
|
285
|
-
// Remove an item
|
|
286
202
|
await service.removeItem("RoutePartition", "NEW-PT");
|
|
287
203
|
|
|
288
|
-
// SQL
|
|
289
|
-
const rows = await service.executeSqlQuery("SELECT name
|
|
204
|
+
// SQL
|
|
205
|
+
const rows = await service.executeSqlQuery("SELECT name FROM routepartition");
|
|
290
206
|
await service.executeSqlUpdate("UPDATE routepartition SET description='test' WHERE name='NEW-PT'");
|
|
291
207
|
```
|
|
292
208
|
|
|
293
|
-
|
|
209
|
+
### Operation Discovery
|
|
294
210
|
|
|
295
|
-
|
|
211
|
+
```javascript
|
|
212
|
+
// List all operations
|
|
213
|
+
const ops = await service.returnOperations();
|
|
214
|
+
const phoneOps = await service.returnOperations("phone");
|
|
215
|
+
|
|
216
|
+
// Get tag schema
|
|
217
|
+
const tags = await service.getOperationTags("addRoutePartition");
|
|
218
|
+
|
|
219
|
+
// Get detailed metadata (required, nillable, type)
|
|
220
|
+
const detailed = await service.getOperationTagsDetailed("addRoutePartition");
|
|
221
|
+
console.log(detailed.routePartition.required); // true
|
|
222
|
+
console.log(detailed.routePartition.children.name.type); // "string"
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Execute Any Operation
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
const tags = await service.getOperationTags("addRoutePartition");
|
|
229
|
+
tags.routePartition.name = "INTERNAL-PT";
|
|
230
|
+
tags.routePartition.description = "Internal directory numbers";
|
|
231
|
+
|
|
232
|
+
const result = await service.executeOperation("addRoutePartition", tags);
|
|
233
|
+
console.log("UUID:", result);
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Batch Operations
|
|
237
|
+
|
|
238
|
+
```javascript
|
|
239
|
+
const results = await service.executeBatch([
|
|
240
|
+
{ operation: "getPhone", tags: { name: "SEP001122334455" } },
|
|
241
|
+
{ operation: "getPhone", tags: { name: "SEP556677889900" } },
|
|
242
|
+
], 5); // concurrency limit
|
|
243
|
+
|
|
244
|
+
results.forEach((r) => {
|
|
245
|
+
console.log(r.success ? `${r.operation}: OK` : `${r.operation}: ${r.error.message}`);
|
|
246
|
+
});
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Error Handling
|
|
296
250
|
|
|
297
251
|
```javascript
|
|
298
252
|
const { AXLAuthError, AXLNotFoundError, AXLOperationError, AXLValidationError } = require("cisco-axl");
|
|
@@ -300,38 +254,26 @@ const { AXLAuthError, AXLNotFoundError, AXLOperationError, AXLValidationError }
|
|
|
300
254
|
try {
|
|
301
255
|
await service.executeOperation("getPhone", { name: "INVALID" });
|
|
302
256
|
} catch (error) {
|
|
303
|
-
if (error instanceof AXLAuthError)
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
} else if (error instanceof AXLOperationError) {
|
|
308
|
-
console.log("SOAP fault:", error.message, error.faultCode);
|
|
309
|
-
} else if (error instanceof AXLValidationError) {
|
|
310
|
-
console.log("Invalid input:", error.message);
|
|
311
|
-
}
|
|
257
|
+
if (error instanceof AXLAuthError) console.log("Bad credentials");
|
|
258
|
+
else if (error instanceof AXLNotFoundError) console.log("Operation not found:", error.operation);
|
|
259
|
+
else if (error instanceof AXLOperationError) console.log("SOAP fault:", error.message);
|
|
260
|
+
else if (error instanceof AXLValidationError) console.log("Invalid input:", error.message);
|
|
312
261
|
}
|
|
313
262
|
```
|
|
314
263
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
Transient network errors (ECONNRESET, ETIMEDOUT, etc.) can be automatically retried with exponential backoff:
|
|
264
|
+
### Retry Configuration
|
|
318
265
|
|
|
319
266
|
```javascript
|
|
320
267
|
let service = new axlService("10.10.20.1", "admin", "pass", "14.0", {
|
|
321
268
|
retry: {
|
|
322
|
-
retries: 3,
|
|
323
|
-
retryDelay: 1000,
|
|
324
|
-
retryOn: (error) =>
|
|
325
|
-
// Custom function to determine if error is retryable (optional)
|
|
326
|
-
return error.message.includes("ECONNRESET");
|
|
327
|
-
}
|
|
269
|
+
retries: 3,
|
|
270
|
+
retryDelay: 1000,
|
|
271
|
+
retryOn: (error) => error.message.includes("ECONNRESET")
|
|
328
272
|
}
|
|
329
273
|
});
|
|
330
274
|
```
|
|
331
275
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
This library supports both CommonJS and ES modules:
|
|
276
|
+
### ESM Support
|
|
335
277
|
|
|
336
278
|
```javascript
|
|
337
279
|
// CommonJS
|
|
@@ -342,32 +284,12 @@ import axlService from "cisco-axl";
|
|
|
342
284
|
import { AXLAuthError, AXLOperationError } from "cisco-axl";
|
|
343
285
|
```
|
|
344
286
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
Check **examples** folder for different ways to use this library. Each folder should have a **README** to explain about each example.
|
|
348
|
-
|
|
349
|
-
You can also run the **tests.js** against Cisco's DevNet sandbox so see how each various method works.
|
|
287
|
+
### json-variables Support
|
|
350
288
|
|
|
351
289
|
```javascript
|
|
352
|
-
npm run test
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
Note: Test are using Cisco's DevNet sandbox information. Find more information here: [Cisco DevNet](https://devnetsandbox.cisco.com/).
|
|
356
|
-
|
|
357
|
-
## json-variables support
|
|
358
|
-
|
|
359
|
-
At a tactical level, json-variables program lets you take a plain object (JSON files contents) and add special markers in any value which you can then reference in a different path.
|
|
360
|
-
|
|
361
|
-
This library will recoginize json-variables **\*\_data** keys in the tags and delete before executing the operation.
|
|
362
|
-
|
|
363
|
-
Example:
|
|
364
|
-
|
|
365
|
-
```node
|
|
366
290
|
var lineTemplate = {
|
|
367
291
|
pattern: "%%_extension_%%",
|
|
368
|
-
routePartitionName: "",
|
|
369
292
|
alertingName: "%%_firstName_%% %%_lastName_%%",
|
|
370
|
-
asciiAlertingName: "%%_firstName_%% %%_lastName_%%",
|
|
371
293
|
description: "%%_firstName_%% %%_lastName_%%",
|
|
372
294
|
_data: {
|
|
373
295
|
extension: "1001",
|
|
@@ -377,70 +299,59 @@ var lineTemplate = {
|
|
|
377
299
|
};
|
|
378
300
|
|
|
379
301
|
const lineTags = jVar(lineTemplate);
|
|
380
|
-
|
|
381
|
-
service
|
|
382
|
-
.executeOperation("updateLine", lineTags)
|
|
383
|
-
.then((results) => {
|
|
384
|
-
console.log(results);
|
|
385
|
-
})
|
|
386
|
-
.catch((error) => {
|
|
387
|
-
console.log(error);
|
|
388
|
-
});
|
|
302
|
+
await service.executeOperation("updateLine", lineTags);
|
|
389
303
|
```
|
|
390
304
|
|
|
391
|
-
|
|
305
|
+
## Methods Reference
|
|
392
306
|
|
|
393
|
-
|
|
307
|
+
### Core
|
|
394
308
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
309
|
+
| Method | Description |
|
|
310
|
+
|--------|-------------|
|
|
311
|
+
| `new axlService(host, user, pass, version, opts?)` | Constructor |
|
|
312
|
+
| `testAuthentication()` | Test credentials against AXL endpoint |
|
|
313
|
+
| `returnOperations(filter?)` | List available operations |
|
|
314
|
+
| `getOperationTags(operation)` | Get tag schema for an operation |
|
|
315
|
+
| `getOperationTagsDetailed(operation)` | Get detailed tag metadata (required/nillable/type) |
|
|
316
|
+
| `executeOperation(operation, tags, opts?)` | Execute any AXL operation |
|
|
317
|
+
| `executeBatch(operations[], concurrency?)` | Parallel batch execution |
|
|
318
|
+
| `setLogLevel(level)` | Change log level at runtime |
|
|
398
319
|
|
|
399
|
-
|
|
400
|
-
...
|
|
401
|
-
```
|
|
320
|
+
### Convenience
|
|
402
321
|
|
|
403
|
-
|
|
322
|
+
| Method | Description |
|
|
323
|
+
|--------|-------------|
|
|
324
|
+
| `getItem(type, identifier, opts?)` | Get single item by name or UUID |
|
|
325
|
+
| `listItems(type, search?, returnedTags?, opts?)` | List items with filtering |
|
|
326
|
+
| `addItem(type, data, opts?)` | Add a new item |
|
|
327
|
+
| `updateItem(type, identifier, updates, opts?)` | Update an existing item |
|
|
328
|
+
| `removeItem(type, identifier, opts?)` | Remove an item |
|
|
329
|
+
| `executeSqlQuery(sql)` | Run a SQL SELECT query |
|
|
330
|
+
| `executeSqlUpdate(sql)` | Run a SQL INSERT/UPDATE/DELETE |
|
|
404
331
|
|
|
405
|
-
|
|
332
|
+
## Examples
|
|
406
333
|
|
|
407
|
-
|
|
334
|
+
Check the **examples** folder for different ways to use this library.
|
|
408
335
|
|
|
409
|
-
|
|
336
|
+
Run the integration tests against a CUCM cluster:
|
|
410
337
|
|
|
411
|
-
|
|
338
|
+
```bash
|
|
339
|
+
npm run staging
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
## TypeScript Support
|
|
412
343
|
|
|
413
344
|
```typescript
|
|
414
345
|
import axlService from 'cisco-axl';
|
|
415
346
|
|
|
416
|
-
const service = new axlService(
|
|
417
|
-
"10.10.20.1",
|
|
418
|
-
"administrator",
|
|
419
|
-
"ciscopsdt",
|
|
420
|
-
"14.0"
|
|
421
|
-
);
|
|
422
|
-
|
|
423
|
-
async function getPartitions() {
|
|
424
|
-
try {
|
|
425
|
-
const operation = "listRoutePartition";
|
|
426
|
-
const tags = await service.getOperationTags(operation);
|
|
427
|
-
tags.searchCriteria.name = "%%";
|
|
428
|
-
|
|
429
|
-
const result = await service.executeOperation(operation, tags);
|
|
430
|
-
return result.routePartition;
|
|
431
|
-
} catch (error) {
|
|
432
|
-
console.error("Error fetching partitions:", error);
|
|
433
|
-
throw error;
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
```
|
|
437
|
-
|
|
438
|
-
See the `examples/typescript` directory for more TypeScript examples.
|
|
347
|
+
const service = new axlService("10.10.20.1", "administrator", "ciscopsdt", "14.0");
|
|
439
348
|
|
|
440
|
-
|
|
349
|
+
const tags = await service.getOperationTags("listRoutePartition");
|
|
350
|
+
tags.searchCriteria.name = "%%";
|
|
351
|
+
const result = await service.executeOperation("listRoutePartition", tags);
|
|
352
|
+
```
|
|
441
353
|
|
|
442
|
-
|
|
443
|
-
- Add example for saving SQL output to CSV.
|
|
354
|
+
See the `examples/typescript` directory for more examples.
|
|
444
355
|
|
|
445
356
|
## Giving Back
|
|
446
357
|
|
package/bin/cisco-axl.js
ADDED