mirror of
https://github.com/vvsviridov/enm-cli.git
synced 2025-10-23 00:12:23 +00:00
FEA: config with multiple objects
This commit is contained in:
226
README.md
226
README.md
@@ -86,117 +86,6 @@ Options:
|
||||
-h, --help display help for command
|
||||
```
|
||||
|
||||
## 🗂 AutoProvisioning Application
|
||||
|
||||

|
||||
|
||||
### Connection
|
||||
|
||||
```shell
|
||||
>enm-cli -l USERNAME -p PASSWORD -u https://enm.your.company.domain.com -a prvn
|
||||
✔ Login in...
|
||||
✔ Getting projects...
|
||||
323 projects> (Use arrow keys or type to search)
|
||||
──────────────
|
||||
> [new]
|
||||
[exit]
|
||||
──────────────
|
||||
Project1 (1) 1✅
|
||||
Project2 (2) 1✅ 1⌛
|
||||
Project3 (2) 1❌ 1⌚
|
||||
Project4 (1) 1❌
|
||||
```
|
||||
|
||||
### Working with Projects
|
||||
|
||||
- `[new]` - Import an Auto Provisioning project to start Auto Provisioning workflows based on the content of the AutoProvisioning project. The Auto Provisioning project file contains project related data in the projectInfo.xml file and node folders which contain configurations required to execute AutoProvisioning use-cases.
|
||||
- `[exit]` - Exit this app.
|
||||
|
||||
Start typing and you see only commands and projects matches input.
|
||||
|
||||
```shell
|
||||
323 projects> pro
|
||||
──────────────
|
||||
──────────────
|
||||
> Project1 (1) 1✅
|
||||
Project2 (2) 1✅ 1⌛
|
||||
Project3 (2) 1❌ 1⌚
|
||||
Project4 (1) 1❌
|
||||
SubNetwork=ONRM_ROOT_MO> ex
|
||||
──────────────
|
||||
>[exit]
|
||||
──────────────
|
||||
```
|
||||
|
||||
### Working with Single Project
|
||||
|
||||
Select project you want to work with.
|
||||
|
||||
Available commands are:
|
||||
|
||||
- `[delete]` - Delete of an Auto Provisioning project removes an Auto Provisioning project and all the Auto Provisioning data for nodes within that project. This includes removal or rollback of any ongoing Auto Provisioning workflows within that project.
|
||||
- `[back]` - Return to projects.
|
||||
- `[exit]` - Exit this app.
|
||||
|
||||
```shell
|
||||
323 projects> Project1 (1) 1✅
|
||||
✔ Getting Project1s status...
|
||||
✔ Getting Project1s properties...
|
||||
|
||||
Project id : Project1
|
||||
Author : Ericsson
|
||||
Creation Date : 2019-01-06 11:23:39
|
||||
Description : Project1 description
|
||||
Nodes :
|
||||
|
||||
RadioNode1
|
||||
RadioNode
|
||||
3432-762-238
|
||||
192.168.192.168
|
||||
Successful
|
||||
Integration Completed
|
||||
|
||||
Project1> (Use arrow keys or type to search)
|
||||
──────────────
|
||||
> [delete]
|
||||
[back]
|
||||
[exit]
|
||||
──────────────
|
||||
RadioNode1
|
||||
```
|
||||
|
||||
### Wotking with Node
|
||||
|
||||
Select node ...
|
||||
|
||||
```shell
|
||||
Project1 (RadioNode1) > (Use arrow keys or type to search)
|
||||
──────────────
|
||||
> [status]
|
||||
[properties]
|
||||
[delete]
|
||||
[bind]
|
||||
[cancel]
|
||||
[resume]
|
||||
[configurations]
|
||||
[siteinstall]
|
||||
[back]
|
||||
(Move up and down to reveal more choices)
|
||||
```
|
||||
|
||||
Available commands are:
|
||||
|
||||
- `[status]` - Retrieving Auto Provisioning node status returns the node status information for each task that has been executed for the specified node.
|
||||
- `[properties]` - Retrieving Auto Provisioning node properties returns the node properties for each task that has been executed for the specified node.
|
||||
- `[delete]` - Delete an Auto Provisioning node removes the Auto Provisioning data for a Network Element. If a node is the last node in a project and there are no profiles associated with the project the project will automatically be deleted.
|
||||
- `[bind]` - Binding a hardware serial number to a node configuration associates the specified node configurations with a hardware serial number for Zero Touch Integration or Hardware Replace.
|
||||
- `[cancel]` - Cancelling the auto provisioning activity rolls back an AutoProvisoning workflow for Node Integration. For expansion a node is rolled back to it\s original configuration if additional configurations have been applied to the node.
|
||||
- `[resume]` - Resuming the auto provisioning activity recommences an Auto Provisioning workflow that is suspended.
|
||||
- `[configurations]` - Uploading an auto provisioning configuration replaces a configuration file that was part of the initial Auto Provisioning node configuration.
|
||||
- `[siteinstall]` - Download Site Installation File (SIF) that is required to be taken on site for LMT Integration or LMT Hardware Replace.
|
||||
- `[back]` - Return to project's nodes.
|
||||
- `[exit]` - Exit this app.
|
||||
|
||||
## 🔭 TopologyBrowser Application
|
||||
|
||||

|
||||
@@ -355,6 +244,8 @@ Available commands are:
|
||||
- `[check]` - view configuration changes
|
||||
- `[get]` - get attribute value
|
||||
- `[set]` - set attribute value
|
||||
- `[abort]` - clear configuration and exit config mode
|
||||
- `[xml]` - export configuration to XML
|
||||
- `[end]` - end config mode without commiting
|
||||
- `[exit]` - logout and exit application
|
||||
|
||||
@@ -517,6 +408,117 @@ CONSTRAINTS
|
||||
Value Resolution: null
|
||||
```
|
||||
|
||||
## 🗂 AutoProvisioning Application
|
||||
|
||||

|
||||
|
||||
### Connection
|
||||
|
||||
```shell
|
||||
>enm-cli -l USERNAME -p PASSWORD -u https://enm.your.company.domain.com -a prvn
|
||||
✔ Login in...
|
||||
✔ Getting projects...
|
||||
323 projects> (Use arrow keys or type to search)
|
||||
──────────────
|
||||
> [new]
|
||||
[exit]
|
||||
──────────────
|
||||
Project1 (1) 1✅
|
||||
Project2 (2) 1✅ 1⌛
|
||||
Project3 (2) 1❌ 1⌚
|
||||
Project4 (1) 1❌
|
||||
```
|
||||
|
||||
### Working with Projects
|
||||
|
||||
- `[new]` - Import an Auto Provisioning project to start Auto Provisioning workflows based on the content of the AutoProvisioning project. The Auto Provisioning project file contains project related data in the projectInfo.xml file and node folders which contain configurations required to execute AutoProvisioning use-cases.
|
||||
- `[exit]` - Exit this app.
|
||||
|
||||
Start typing and you see only commands and projects matches input.
|
||||
|
||||
```shell
|
||||
323 projects> pro
|
||||
──────────────
|
||||
──────────────
|
||||
> Project1 (1) 1✅
|
||||
Project2 (2) 1✅ 1⌛
|
||||
Project3 (2) 1❌ 1⌚
|
||||
Project4 (1) 1❌
|
||||
SubNetwork=ONRM_ROOT_MO> ex
|
||||
──────────────
|
||||
>[exit]
|
||||
──────────────
|
||||
```
|
||||
|
||||
### Working with Single Project
|
||||
|
||||
Select project you want to work with.
|
||||
|
||||
Available commands are:
|
||||
|
||||
- `[delete]` - Delete of an Auto Provisioning project removes an Auto Provisioning project and all the Auto Provisioning data for nodes within that project. This includes removal or rollback of any ongoing Auto Provisioning workflows within that project.
|
||||
- `[back]` - Return to projects.
|
||||
- `[exit]` - Exit this app.
|
||||
|
||||
```shell
|
||||
323 projects> Project1 (1) 1✅
|
||||
✔ Getting Project1s status...
|
||||
✔ Getting Project1s properties...
|
||||
|
||||
Project id : Project1
|
||||
Author : Ericsson
|
||||
Creation Date : 2019-01-06 11:23:39
|
||||
Description : Project1 description
|
||||
Nodes :
|
||||
|
||||
RadioNode1
|
||||
RadioNode
|
||||
3432-762-238
|
||||
192.168.192.168
|
||||
Successful
|
||||
Integration Completed
|
||||
|
||||
Project1> (Use arrow keys or type to search)
|
||||
──────────────
|
||||
> [delete]
|
||||
[back]
|
||||
[exit]
|
||||
──────────────
|
||||
RadioNode1
|
||||
```
|
||||
|
||||
### Wotking with Node
|
||||
|
||||
Select node ...
|
||||
|
||||
```shell
|
||||
Project1 (RadioNode1) > (Use arrow keys or type to search)
|
||||
──────────────
|
||||
> [status]
|
||||
[properties]
|
||||
[delete]
|
||||
[bind]
|
||||
[cancel]
|
||||
[resume]
|
||||
[configurations]
|
||||
[siteinstall]
|
||||
[back]
|
||||
(Move up and down to reveal more choices)
|
||||
```
|
||||
|
||||
Available commands are:
|
||||
|
||||
- `[status]` - Retrieving Auto Provisioning node status returns the node status information for each task that has been executed for the specified node.
|
||||
- `[properties]` - Retrieving Auto Provisioning node properties returns the node properties for each task that has been executed for the specified node.
|
||||
- `[delete]` - Delete an Auto Provisioning node removes the Auto Provisioning data for a Network Element. If a node is the last node in a project and there are no profiles associated with the project the project will automatically be deleted.
|
||||
- `[bind]` - Binding a hardware serial number to a node configuration associates the specified node configurations with a hardware serial number for Zero Touch Integration or Hardware Replace.
|
||||
- `[cancel]` - Cancelling the auto provisioning activity rolls back an AutoProvisoning workflow for Node Integration. For expansion a node is rolled back to it\s original configuration if additional configurations have been applied to the node.
|
||||
- `[resume]` - Resuming the auto provisioning activity recommences an Auto Provisioning workflow that is suspended.
|
||||
- `[configurations]` - Uploading an auto provisioning configuration replaces a configuration file that was part of the initial Auto Provisioning node configuration.
|
||||
- `[siteinstall]` - Download Site Installation File (SIF) that is required to be taken on site for LMT Integration or LMT Hardware Replace.
|
||||
- `[back]` - Return to project's nodes.
|
||||
- `[exit]` - Exit this app.
|
||||
|
||||
## 🗃 Bulk Import
|
||||
|
||||

|
||||
@@ -562,3 +564,5 @@ this.stream.clearLine(1);
|
||||
1.0.7 - Check for updates
|
||||
|
||||
1.0.8 - added `enmdata` command
|
||||
|
||||
1.0.9 - added ability to change multiple objects simultaneously and export configuration to XML
|
||||
|
18
lib/applications/TopologyBrowser/TopologyBrowser.js
Executable file → Normal file
18
lib/applications/TopologyBrowser/TopologyBrowser.js
Executable file → Normal file
@@ -11,6 +11,7 @@ const show = require('./commands/show')
|
||||
const up = require('./commands/up')
|
||||
const config = require('./commands/config')
|
||||
const end = require('./commands/end')
|
||||
const xml = require('./commands/xml')
|
||||
const setAttribute = require('./commands/setAttribute')
|
||||
const description = require('./commands/description')
|
||||
const get = require('./commands/get')
|
||||
@@ -48,7 +49,7 @@ class TopologyBrowser extends ENM {
|
||||
this.networkDetails = null
|
||||
this.configSet = []
|
||||
this.includeNonPersistent = false
|
||||
this.configCommands = ['commit', 'check', 'end', 'exit']
|
||||
this.configCommands = ['commit', 'check', 'abort', 'xml', 'end', 'exit']
|
||||
this.help = mainHelp
|
||||
}
|
||||
|
||||
@@ -91,6 +92,16 @@ class TopologyBrowser extends ENM {
|
||||
end.call(this)
|
||||
}
|
||||
|
||||
abort() {
|
||||
this.help = mainHelp
|
||||
end.call(this)
|
||||
this.configSet.length = 0
|
||||
}
|
||||
|
||||
async xml() {
|
||||
await xml.call(this)
|
||||
}
|
||||
|
||||
setAttribute(attribute) {
|
||||
return setAttribute.call(this, attribute)
|
||||
}
|
||||
@@ -112,7 +123,10 @@ class TopologyBrowser extends ENM {
|
||||
}
|
||||
|
||||
check() {
|
||||
logAttributes(this.fdn, this.configSet)
|
||||
this.configSet.forEach(item => {
|
||||
const fdn = item.fdn
|
||||
logAttributes(fdn, item.attributes)
|
||||
})
|
||||
}
|
||||
|
||||
async home() {
|
||||
|
40
lib/applications/TopologyBrowser/commands/commit.js
Executable file → Normal file
40
lib/applications/TopologyBrowser/commands/commit.js
Executable file → Normal file
@@ -6,29 +6,27 @@ async function commit() {
|
||||
if (!this.configSet.length) {
|
||||
throw new Error('Configuration is empty❗')
|
||||
}
|
||||
this.fdn = this.fdn.replace(/\((\w+)\)/g, '')
|
||||
logAttributes(this.fdn, this.configSet)
|
||||
const axiosConfig = {
|
||||
text: 'Commiting Config...',
|
||||
method: 'put',
|
||||
url: `${this.objectUrl}${this.currentPoId}`,
|
||||
data: {
|
||||
poId: this.currentPoId,
|
||||
fdn: this.fdn,
|
||||
attributes: [...this.configSet],
|
||||
},
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
for (const { fdn, poId, attributes } of this.configSet) {
|
||||
logAttributes(fdn, attributes)
|
||||
const axiosConfig = {
|
||||
text: 'Commiting Config...',
|
||||
method: 'put',
|
||||
url: `${this.objectUrl}${poId}`,
|
||||
data: {
|
||||
poId,
|
||||
fdn,
|
||||
attributes,
|
||||
},
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
const response = await this.httpClient.request(axiosConfig)
|
||||
if (response.data) {
|
||||
logCommit(response.data)
|
||||
}
|
||||
}
|
||||
this.configSet.length = 0
|
||||
this.end()
|
||||
const response = await this.httpClient.request(axiosConfig)
|
||||
if (response.data) {
|
||||
logCommit(response.data)
|
||||
} else {
|
||||
throw new Error('No data or response❗')
|
||||
}
|
||||
this.abort()
|
||||
}
|
||||
|
||||
|
||||
|
5
lib/applications/TopologyBrowser/commands/config.js
Executable file → Normal file
5
lib/applications/TopologyBrowser/commands/config.js
Executable file → Normal file
@@ -1,7 +1,12 @@
|
||||
const logDetails = require('../../../../util/logDetails')
|
||||
const chalk = require('chalk')
|
||||
|
||||
|
||||
async function config() {
|
||||
if (this.configSet.length !== 0){
|
||||
this.check()
|
||||
console.log(`⚠ ${chalk.yellow.bold('Config is non empty')} ⚠`)
|
||||
}
|
||||
this.isConfig = true
|
||||
const axiosConfig = {
|
||||
text: 'Reading Attributes...',
|
||||
|
2
lib/applications/TopologyBrowser/commands/end.js
Executable file → Normal file
2
lib/applications/TopologyBrowser/commands/end.js
Executable file → Normal file
@@ -2,7 +2,7 @@ function end() {
|
||||
this.fdn = this.fdn.replace(/\((\w+)\)/g, '')
|
||||
this.isConfig = false
|
||||
this.attribute = null
|
||||
this.configSet.length = 0
|
||||
// this.configSet.length = 0
|
||||
this.configCommands = this.configCommands.filter(cmd => !['get', 'set', 'description'].includes(cmd) )
|
||||
this.nextVariants = async (input) => await this.nextObjects(input)
|
||||
}
|
||||
|
46
lib/applications/TopologyBrowser/commands/set.js
Executable file → Normal file
46
lib/applications/TopologyBrowser/commands/set.js
Executable file → Normal file
@@ -2,25 +2,41 @@ const inputByType = require('../inputValue')
|
||||
|
||||
|
||||
async function set() {
|
||||
if (!this.isConfig) return
|
||||
const attributeData = this.attributesData.find(item => item.key === this.attribute)
|
||||
if (!attributeData) return
|
||||
if (!attributeData) {
|
||||
throw new Error('No attribute data found❗')
|
||||
}
|
||||
if (attributeData.writeBehavior === 'NOT_ALLOWED' || attributeData.immutable) {
|
||||
throw new Error('Attribute Is ReadOnly')
|
||||
}
|
||||
if (this.isConfig) {
|
||||
const found = this.configSet.find(item => item.key === this.attribute)
|
||||
const { value } = await inputByType(attributeData)
|
||||
if (found) {
|
||||
found.value = value
|
||||
} else {
|
||||
this.configSet.push(
|
||||
{
|
||||
key: this.attribute,
|
||||
value,
|
||||
datatype: attributeData.type,
|
||||
}
|
||||
)
|
||||
}
|
||||
const clearFdn = this.fdn.replace(/\((\w+)\)/g, '')
|
||||
const itemFound = this.configSet.find(item => item.fdn === clearFdn)
|
||||
const { value } = await inputByType(attributeData)
|
||||
const currentAttribute = {
|
||||
key: this.attribute,
|
||||
value,
|
||||
datatype: attributeData.type,
|
||||
}
|
||||
if (!itemFound) {
|
||||
this.configSet.push(
|
||||
{
|
||||
fdn: clearFdn,
|
||||
poId: this.currentPoId,
|
||||
attributes: [
|
||||
currentAttribute
|
||||
]
|
||||
}
|
||||
)
|
||||
return
|
||||
}
|
||||
const attributeFound = itemFound.attributes.find(item => item.key === this.attribute)
|
||||
if (attributeFound) {
|
||||
attributeFound.value = value
|
||||
} else {
|
||||
itemFound.attributes.push(
|
||||
currentAttribute
|
||||
)
|
||||
}
|
||||
}
|
||||
module.exports = set
|
||||
|
49
lib/applications/TopologyBrowser/commands/xml.js
Normal file
49
lib/applications/TopologyBrowser/commands/xml.js
Normal file
@@ -0,0 +1,49 @@
|
||||
const fsPromises = require('fs').promises
|
||||
const path = require('path')
|
||||
const chalk = require('chalk')
|
||||
|
||||
|
||||
function reduceArrayToObject(value) {
|
||||
if (Array.isArray(value)) {
|
||||
return value.reduce((prev, curr) => {
|
||||
if (Array.isArray(curr.value)) {
|
||||
prev[curr.key] = curr.value.every(item => item.key) ?
|
||||
reduceArrayToObject(curr.value) :
|
||||
curr.value.map(item => {
|
||||
return reduceArrayToObject(item)
|
||||
})
|
||||
} else {
|
||||
prev[curr.key] = curr.value
|
||||
}
|
||||
return prev
|
||||
}, {})
|
||||
} else {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function xml() {
|
||||
const operations = this.configSet.map(({ fdn, attributes }) => ({
|
||||
fdn,
|
||||
changeType: 'UPDATE',
|
||||
attributes: reduceArrayToObject(attributes),
|
||||
}))
|
||||
const axiosConfig = {
|
||||
text: 'Generating XML...',
|
||||
method: 'post',
|
||||
url: '/parametermanagement/v1/importFile',
|
||||
data: {
|
||||
fileType: 'THREE_GPP',
|
||||
importFileName: 'bulk_import',
|
||||
operations
|
||||
}
|
||||
}
|
||||
const { data } = await this.httpClient.request(axiosConfig)
|
||||
const saveFileName = path.join(process.cwd(), `bulk_import_${this.currentPoId}.xml`)
|
||||
await fsPromises.writeFile(saveFileName, data)
|
||||
console.log(chalk.bgGreen(`Saved bulk import file to ${saveFileName}`))
|
||||
}
|
||||
|
||||
|
||||
module.exports = xml
|
2
lib/applications/TopologyBrowser/help.js
Executable file → Normal file
2
lib/applications/TopologyBrowser/help.js
Executable file → Normal file
@@ -24,6 +24,8 @@ const configHelp = [
|
||||
'commit - commiting changes to the network',
|
||||
'description - show attribute\'s description',
|
||||
'check - view configuration changes',
|
||||
'abort - clear configuration and exit config mode',
|
||||
'xml - generate XML file for current configuration changes',
|
||||
'end - exit config mode without commiting',
|
||||
'exit - logout and exit application',
|
||||
].join('\n')
|
||||
|
6
lib/applications/TopologyBrowser/inputHandler.js
Executable file → Normal file
6
lib/applications/TopologyBrowser/inputHandler.js
Executable file → Normal file
@@ -50,6 +50,12 @@ async function handleCommand(tplg, command) {
|
||||
case '_end':
|
||||
tplg.end()
|
||||
break
|
||||
case '_abort':
|
||||
tplg.abort()
|
||||
break
|
||||
case '_xml':
|
||||
await tplg.xml()
|
||||
break
|
||||
case '_home':
|
||||
await tplg.home()
|
||||
break
|
||||
|
Reference in New Issue
Block a user