mirror of
https://github.com/vvsviridov/enm-cli.git
synced 2025-11-03 13:43:39 +00:00
first alpha
This commit is contained in:
66
bin/enm-cli.js
Normal file → Executable file
66
bin/enm-cli.js
Normal file → Executable file
@@ -3,43 +3,59 @@
|
|||||||
const { Command, Option } = require('commander')
|
const { Command, Option } = require('commander')
|
||||||
const pkg = require('../package.json')
|
const pkg = require('../package.json')
|
||||||
const inquirer = require('inquirer')
|
const inquirer = require('inquirer')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
const { isEmpty } = require('../util/validation')
|
const { isEmpty } = require('../util/validation')
|
||||||
|
|
||||||
require('dotenv').config()
|
require('dotenv').config({ path: [...__dirname.split(path.sep).slice(0,-1), '.env'].join(path.sep) })
|
||||||
|
|
||||||
const AutoProvisioning = require('../lib/components/AutoProvisioning/AutoProvisioning')
|
const AutoProvisioning = require('../lib/applications/AutoProvisioning/AutoProvisioning')
|
||||||
const TopologyBrowser = require('../lib/components/TopologyBrowser/TopologyBrowser')
|
const TopologyBrowser = require('../lib/applications/TopologyBrowser/TopologyBrowser')
|
||||||
|
|
||||||
const logError = require('../util/logError')
|
const logError = require('../util/logError')
|
||||||
|
|
||||||
const applications = ['tplg', 'prvn']
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
process.on('uncaughtException', function (exception) {
|
||||||
|
console.log(exception);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const applications = [
|
||||||
|
{
|
||||||
|
id: 'tplg',
|
||||||
|
appClass: TopologyBrowser,
|
||||||
|
name: 'Topology Browser',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'prvn',
|
||||||
|
appClass: AutoProvisioning,
|
||||||
|
name: 'Auto Provisioning',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
const appIds = applications.map(item => item.id)
|
||||||
|
|
||||||
const program = new Command()
|
const program = new Command()
|
||||||
program
|
program
|
||||||
.version(pkg.version)
|
.version(pkg.version)
|
||||||
// .option('-l, --login <letters>', 'ENM User Login')
|
|
||||||
// .option('-p, --password <letters>', 'ENM User Password')
|
|
||||||
.addOption(new Option('-l, --login <letters>', 'ENM User Login').env('LOGIN'))
|
.addOption(new Option('-l, --login <letters>', 'ENM User Login').env('LOGIN'))
|
||||||
.addOption(new Option('-p, --password <letters>', 'ENM User Password').env('PASSWORD'))
|
.addOption(new Option('-p, --password <letters>', 'ENM User Password').env('PASSWORD'))
|
||||||
.addOption(new Option('-a, --application <letters>', 'Start specified application')
|
.addOption(new Option('-a, --application <letters>', 'Start specified application')
|
||||||
.choices(applications)
|
.choices(appIds)
|
||||||
.default('tplg')
|
|
||||||
)
|
)
|
||||||
.requiredOption('-u, --url <letters>', 'ENM Url')
|
.requiredOption('-u, --url <valid URL>', 'ENM Url')
|
||||||
.parse(process.argv)
|
.parse(process.argv)
|
||||||
|
|
||||||
|
|
||||||
const options = program.opts()
|
const options = program.opts()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function promptUsername() {
|
async function promptUsername() {
|
||||||
const input = await inquirer.prompt([
|
const input = await inquirer.prompt([
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
name: 'value',
|
name: 'value',
|
||||||
suffix: chalk.bgGreen('?'),
|
prefix: '👤',
|
||||||
message: 'Type ENM login',
|
message: 'Type ENM login:',
|
||||||
validate: isEmpty,
|
validate: isEmpty,
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
@@ -52,7 +68,8 @@ async function promptPassword() {
|
|||||||
{
|
{
|
||||||
type: 'password',
|
type: 'password',
|
||||||
name: 'value',
|
name: 'value',
|
||||||
message: `Type ${options.login}'s ENM password`,
|
prefix: '🔑',
|
||||||
|
message: 'Type ENM password:',
|
||||||
validate: isEmpty,
|
validate: isEmpty,
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
@@ -62,34 +79,31 @@ async function promptPassword() {
|
|||||||
|
|
||||||
async function selectApplication() {
|
async function selectApplication() {
|
||||||
let selectedApp
|
let selectedApp
|
||||||
if (options.application && options.application in applications) {
|
if (options.application && appIds.includes(options.application)) {
|
||||||
selectedApp = options.application
|
selectedApp = options.application
|
||||||
} else {
|
} else {
|
||||||
const input = await inquirer.prompt([
|
const input = await inquirer.prompt([
|
||||||
{
|
{
|
||||||
type: 'list',
|
type: 'list',
|
||||||
name: 'application',
|
name: 'application',
|
||||||
suffix: '💾',
|
prefix: '💾',
|
||||||
message,
|
message: 'Select Application:',
|
||||||
choices: applications
|
choices: applications.map(item => ({name: item.name, value: item.id, short: item.id}))
|
||||||
}])
|
}])
|
||||||
selectedApp = input.application
|
selectedApp = input.application
|
||||||
}
|
}
|
||||||
return {
|
const { appClass } = applications.find(item => item.id === selectedApp)
|
||||||
tplg: TopologyBrowser,
|
const login = options.login || await promptUsername()
|
||||||
prvn: AutoProvisioning
|
const password = options.password || await promptPassword()
|
||||||
}[selectedApp]
|
return new appClass(login, password, options.url)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
try {
|
try {
|
||||||
const app = new selectApplication()(options.login || await promptUsername(), options.password || await promptPassword(), options.url)
|
const app = await selectApplication()
|
||||||
const result = await app.login()
|
await app.login()
|
||||||
const { code } = result
|
|
||||||
if (code === 'SUCCESS') {
|
|
||||||
await app.inputHandler()
|
await app.inputHandler()
|
||||||
await app.logout()
|
await app.logout()
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logError(error)
|
logError(error)
|
||||||
}
|
}
|
||||||
|
|||||||
5
lib/components/AutoProvisioning/AutoProvisioning.js → lib/applications/AutoProvisioning/AutoProvisioning.js
Normal file → Executable file
5
lib/components/AutoProvisioning/AutoProvisioning.js → lib/applications/AutoProvisioning/AutoProvisioning.js
Normal file → Executable file
@@ -1,4 +1,4 @@
|
|||||||
const ENM = require('../ENM/ENM')
|
const ENM = require('../../components/ENM')
|
||||||
|
|
||||||
const { getProjects, getProjectData, deleteProject, newProject } = require('./projects')
|
const { getProjects, getProjectData, deleteProject, newProject } = require('./projects')
|
||||||
const {
|
const {
|
||||||
@@ -23,8 +23,7 @@ class AutoProvisioning extends ENM {
|
|||||||
this.projectIndex = -1
|
this.projectIndex = -1
|
||||||
this.nodes = null
|
this.nodes = null
|
||||||
this.nodeIndex = -1
|
this.nodeIndex = -1
|
||||||
this.commands = null
|
this.prompt = ''
|
||||||
this.choices = null
|
|
||||||
this.help = 'No results...'
|
this.help = 'No results...'
|
||||||
}
|
}
|
||||||
|
|
||||||
43
lib/components/AutoProvisioning/inputHandler.js → lib/applications/AutoProvisioning/inputHandler.js
Normal file → Executable file
43
lib/components/AutoProvisioning/inputHandler.js → lib/applications/AutoProvisioning/inputHandler.js
Normal file → Executable file
@@ -8,32 +8,32 @@ const { isEmpty } = require('../../../util/validation')
|
|||||||
inquirer.registerPrompt('autocomplete', require('inquirer-autocomplete-prompt'))
|
inquirer.registerPrompt('autocomplete', require('inquirer-autocomplete-prompt'))
|
||||||
|
|
||||||
|
|
||||||
async function commandOther(prvn, prompt, command) {
|
async function commandOther(prvn, command) {
|
||||||
const choosedIndex = prvn.choices.indexOf(command)
|
const choosedIndex = prvn.choices.indexOf(command)
|
||||||
if (choosedIndex !== -1) {
|
if (choosedIndex !== -1) {
|
||||||
if (prvn.nodes) {
|
if (prvn.nodes) {
|
||||||
prvn.nodeIndex = choosedIndex
|
prvn.nodeIndex = choosedIndex
|
||||||
prompt = prvn.getNode()
|
prvn.getNode()
|
||||||
} else {
|
} else {
|
||||||
prvn.projectIndex = choosedIndex
|
prvn.projectIndex = choosedIndex
|
||||||
prompt = await prvn.getProjectData()
|
await prvn.getProjectData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return prompt
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function handleCommand(prvn, prompt, command) {
|
async function handleCommand(prvn, command) {
|
||||||
const [, cmd] = command.match(/\[(\w+)\]/) || [, command]
|
const [, cmd] = command.match(/\[(\w+)\]/) || [, command]
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
|
||||||
case 'exit':
|
case 'exit':
|
||||||
return
|
prvn.prompt = ''
|
||||||
|
break
|
||||||
case 'new':
|
case 'new':
|
||||||
await prvn.newProject()
|
await prvn.newProject()
|
||||||
break
|
break
|
||||||
case 'back':
|
case 'back':
|
||||||
prompt = prvn.nodeIndex ? await prvn.getProjects() : await prvn.getProjectData()
|
prvn.nodeIndex ? await prvn.getProjects() : await prvn.getProjectData()
|
||||||
break
|
break
|
||||||
case 'delete':
|
case 'delete':
|
||||||
prvn.nodeIndex ? prvn.deleteNode() : await prvn.deleteProject()
|
prvn.nodeIndex ? prvn.deleteNode() : await prvn.deleteProject()
|
||||||
@@ -62,32 +62,30 @@ async function handleCommand(prvn, prompt, command) {
|
|||||||
break
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
prompt = await commandOther(prvn, prompt, command)
|
await commandOther(prvn, command)
|
||||||
}
|
}
|
||||||
return prompt
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function inputHandlerLoop(prvn) {
|
async function inputHandler() {
|
||||||
let prompt = await prvn.getProjects()
|
await this.getProjects()
|
||||||
let prefix = ''
|
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
const input = await inquirer.prompt([
|
const input = await inquirer.prompt([
|
||||||
{
|
{
|
||||||
type: 'autocomplete',
|
type: 'autocomplete',
|
||||||
name: 'command',
|
name: 'command',
|
||||||
message: chalk.bold.blue(prompt),
|
message: chalk.bold.blue(this.prompt),
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
prefix: chalk.bold.grey(prefix),
|
prefix: '',
|
||||||
suffix: chalk.bold.blue('>'),
|
suffix: chalk.bold.blue('>'),
|
||||||
validate: isEmpty,
|
validate: isEmpty,
|
||||||
source: async (answers, input) => await prvn.next(input),
|
source: async (answers, input) => await this.next(input),
|
||||||
emptyText: prvn.help,
|
emptyText: this.help,
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
prompt = await handleCommand(prvn, prompt, input.command)
|
await handleCommand(this, input.command)
|
||||||
if (!prompt) break
|
if (!this.prompt) break
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logError(error)
|
logError(error)
|
||||||
}
|
}
|
||||||
@@ -95,13 +93,4 @@ async function inputHandlerLoop(prvn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function inputHandler() {
|
|
||||||
try {
|
|
||||||
await inputHandlerLoop(this)
|
|
||||||
} catch (error) {
|
|
||||||
logError(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = inputHandler
|
module.exports = inputHandler
|
||||||
2
lib/components/AutoProvisioning/nodes.js → lib/applications/AutoProvisioning/nodes.js
Normal file → Executable file
2
lib/components/AutoProvisioning/nodes.js → lib/applications/AutoProvisioning/nodes.js
Normal file → Executable file
@@ -35,7 +35,7 @@ async function getNode() {
|
|||||||
this.commands = nodeCommands
|
this.commands = nodeCommands
|
||||||
this.help = nodeCommandsHelp.join('\n ')
|
this.help = nodeCommandsHelp.join('\n ')
|
||||||
this.choices = [] // this.nodes.filter(item => item !== nodeId)
|
this.choices = [] // this.nodes.filter(item => item !== nodeId)
|
||||||
return `${projectId} (${nodeId}) `
|
this.prompt = `${projectId} (${nodeId}) `
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
4
lib/components/AutoProvisioning/projects.js → lib/applications/AutoProvisioning/projects.js
Normal file → Executable file
4
lib/components/AutoProvisioning/projects.js → lib/applications/AutoProvisioning/projects.js
Normal file → Executable file
@@ -34,7 +34,7 @@ async function getProjects() {
|
|||||||
this.commands = projectsCommands
|
this.commands = projectsCommands
|
||||||
this.help = projectsCommandsHelp.join('\n ')
|
this.help = projectsCommandsHelp.join('\n ')
|
||||||
this.nodes = null
|
this.nodes = null
|
||||||
return `${this.projects.length} projects`
|
this.prompt = `${this.projects.length} projects`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ async function getProjectData() {
|
|||||||
this.commands = projectCommands
|
this.commands = projectCommands
|
||||||
this.help = projectCommandsHelp.join('\n ')
|
this.help = projectCommandsHelp.join('\n ')
|
||||||
this.nodeIndex = -1
|
this.nodeIndex = -1
|
||||||
return projectId
|
this.prompt = projectId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
154
lib/applications/TopologyBrowser/TopologyBrowser.js
Executable file
154
lib/applications/TopologyBrowser/TopologyBrowser.js
Executable file
@@ -0,0 +1,154 @@
|
|||||||
|
const logAttributes = require('../../../util/logAttributes')
|
||||||
|
const inputHandler = require('./inputHandler')
|
||||||
|
const alarms = require('./commands/alarms')
|
||||||
|
const sync = require('./commands/sync')
|
||||||
|
const initialPrompt = require('./commands/initialPrompt')
|
||||||
|
const nextObjects = require('./commands/nextObjects')
|
||||||
|
const nextAttributes = require('./commands/nextAttributes')
|
||||||
|
const setIdByCommand = require('./commands/setIdByCommand')
|
||||||
|
const show = require('./commands/show')
|
||||||
|
const up = require('./commands/up')
|
||||||
|
const config = require('./commands/config')
|
||||||
|
const end = require('./commands/end')
|
||||||
|
const setAttribute = require('./commands/setAttribute')
|
||||||
|
const description = require('./commands/description')
|
||||||
|
const get = require('./commands/get')
|
||||||
|
const set = require('./commands/set')
|
||||||
|
const commit = require('./commands/commit')
|
||||||
|
const home = require('./commands/home')
|
||||||
|
const search = require('./commands/search')
|
||||||
|
const goToFdn = require('./commands/goToFdn')
|
||||||
|
const createNext = require('../../../util/createNext')
|
||||||
|
const { mainHelp, configHelp } = require('./help')
|
||||||
|
|
||||||
|
const ENM = require('../../components/ENM')
|
||||||
|
const chalk = require('chalk')
|
||||||
|
|
||||||
|
class TopologyBrowser extends ENM {
|
||||||
|
constructor(username, password, url) {
|
||||||
|
super(username, password, url)
|
||||||
|
this.objectUrl = '/persistentObject/'
|
||||||
|
this.alarmUrl = '/alarmcontroldisplayservice/alarmMonitoring/alarmoperations/'
|
||||||
|
this.nodeTypesUrl = '/modelInfo/model/nodeTypes/'
|
||||||
|
this.nodeSearchUrl = '/managedObjects/search/v2'
|
||||||
|
this.nodePoIdsUrl = '/managedObjects/getPosByPoIds'
|
||||||
|
|
||||||
|
this.currentPoId = 0
|
||||||
|
this.nextPoId = 1
|
||||||
|
this.fdn = ''
|
||||||
|
this.childrens = []
|
||||||
|
this.poIds = []
|
||||||
|
this.isConfig = false
|
||||||
|
this.attributes = []
|
||||||
|
this.nextVariants = null
|
||||||
|
this.attributesData = []
|
||||||
|
this.attribute = null
|
||||||
|
this.networkDetails = null
|
||||||
|
this.configSet = []
|
||||||
|
this.includeNonPersistent = false
|
||||||
|
this.configCommands = ['commit', 'check', 'end', 'exit']
|
||||||
|
this.help = mainHelp
|
||||||
|
}
|
||||||
|
|
||||||
|
async initialPrompt() {
|
||||||
|
await initialPrompt.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
async next(input) {
|
||||||
|
await this.nextVariants(input)
|
||||||
|
return createNext.call(this, input ? input : '')
|
||||||
|
}
|
||||||
|
|
||||||
|
async nextObjects(input) {
|
||||||
|
return await nextObjects.call(this, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
async nextAttributes(input) {
|
||||||
|
return await nextAttributes.call(this, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
setIdByCommand(command) {
|
||||||
|
return setIdByCommand.call(this, command)
|
||||||
|
}
|
||||||
|
|
||||||
|
async show(filter) {
|
||||||
|
await show.call(this, filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
up() {
|
||||||
|
return up.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
async config(fdn) {
|
||||||
|
this.help = configHelp
|
||||||
|
return await config.call(this, fdn)
|
||||||
|
}
|
||||||
|
|
||||||
|
end() {
|
||||||
|
this.help = mainHelp
|
||||||
|
end.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
setAttribute(attribute) {
|
||||||
|
return setAttribute.call(this, attribute)
|
||||||
|
}
|
||||||
|
|
||||||
|
description() {
|
||||||
|
description.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(fdn) {
|
||||||
|
get.call(this, fdn)
|
||||||
|
}
|
||||||
|
|
||||||
|
async set() {
|
||||||
|
await set.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
async commit(fdn) {
|
||||||
|
return await commit.call(this, fdn)
|
||||||
|
}
|
||||||
|
|
||||||
|
check() {
|
||||||
|
logAttributes(this.fdn.replace(/\((\w+)\)/g, ''), this.configSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
home() {
|
||||||
|
home.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
async search() {
|
||||||
|
await search.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
async goToFdn(fromFdn, targetFdn) {
|
||||||
|
return await goToFdn.call(this, fromFdn, targetFdn)
|
||||||
|
}
|
||||||
|
|
||||||
|
persistent() {
|
||||||
|
this.includeNonPersistent = !this.includeNonPersistent
|
||||||
|
console.log(chalk.yellow(`Include Non Persistent Atrributes Set to: ${this.includeNonPersistent}`))
|
||||||
|
}
|
||||||
|
|
||||||
|
async alarms(fdn) {
|
||||||
|
await alarms.call(this, fdn)
|
||||||
|
}
|
||||||
|
|
||||||
|
async sync(fdn) {
|
||||||
|
await sync.call(this, fdn)
|
||||||
|
}
|
||||||
|
|
||||||
|
async inputHandler() {
|
||||||
|
await inputHandler.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
getPrompt() {
|
||||||
|
if (this.fdn.length >= 67) {
|
||||||
|
return `...${this.fdn.slice(-65)}`
|
||||||
|
}
|
||||||
|
return this.fdn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = TopologyBrowser
|
||||||
34
lib/components/TopologyBrowser/commands/alarms.js → lib/applications/TopologyBrowser/commands/alarms.js
Normal file → Executable file
34
lib/components/TopologyBrowser/commands/alarms.js → lib/applications/TopologyBrowser/commands/alarms.js
Normal file → Executable file
@@ -1,19 +1,18 @@
|
|||||||
const colors = require('colors')
|
const chalk = require('chalk')
|
||||||
const inquirer = require('inquirer')
|
const inquirer = require('inquirer')
|
||||||
|
|
||||||
const requestWrapper = require('../../util/requestWrapper')
|
const logAlarm = require('../../../../util/logAlarm')
|
||||||
const logAlarm = require('../../util/logAlarm')
|
const eventTimeToString = require('../../../../util/eventTimeToString')
|
||||||
const eventTimeToString = require('../../util/eventTimeToString')
|
|
||||||
|
|
||||||
const closeAlarms = { name: 'Close Alarms'.yellow, value: -1}
|
const closeAlarms = { name: chalk.yellow('Close Alarms'), value: -1}
|
||||||
|
|
||||||
|
|
||||||
function logTotal(total) {
|
function logTotal(total) {
|
||||||
if (total === 0) {
|
if (total === 0) {
|
||||||
console.log(`Total Alarms: ${total}`.green)
|
console.log(chalk.green(`Total Alarms: ${total}`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
console.log(`Total Alarms: ${total}`.yellow)
|
console.log(chalk.yellow(`Total Alarms: ${total}`))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -36,6 +35,7 @@ function parsePoIdResponse(response) {
|
|||||||
|
|
||||||
async function getPoIds(url, nodes) {
|
async function getPoIds(url, nodes) {
|
||||||
const axiosConfig = {
|
const axiosConfig = {
|
||||||
|
text: 'Getting Alarms...',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url,
|
url,
|
||||||
data: {
|
data: {
|
||||||
@@ -54,7 +54,7 @@ async function getPoIds(url, nodes) {
|
|||||||
advFilters: ''
|
advFilters: ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const response = await requestWrapper(axiosConfig, 'Getting Alarms...')
|
const response = await this.httpClient.request(axiosConfig)
|
||||||
if (!Array.isArray(response.data)) return
|
if (!Array.isArray(response.data)) return
|
||||||
const [total, eventPoIds] = parsePoIdResponse(response)
|
const [total, eventPoIds] = parsePoIdResponse(response)
|
||||||
logTotal(total)
|
logTotal(total)
|
||||||
@@ -64,6 +64,7 @@ async function getPoIds(url, nodes) {
|
|||||||
|
|
||||||
async function getFields(url, eventPoIds) {
|
async function getFields(url, eventPoIds) {
|
||||||
const axiosConfig = {
|
const axiosConfig = {
|
||||||
|
text: 'Getting Alarms Data...',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url,
|
url,
|
||||||
data: {
|
data: {
|
||||||
@@ -74,12 +75,12 @@ async function getFields(url, eventPoIds) {
|
|||||||
category: 'All'
|
category: 'All'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const response = await requestWrapper(axiosConfig, 'Getting Alarms Data...')
|
const response = await this.httpClient.request(axiosConfig)
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function alarmChoices(alarmList, input) {
|
function alarmChoices(alarmList, input) {
|
||||||
const filter = input ? input : ''
|
const filter = input ? input : ''
|
||||||
return alarmList
|
return alarmList
|
||||||
.map(al => {
|
.map(al => {
|
||||||
@@ -102,7 +103,7 @@ async function alarmsLoop(alarmList) {
|
|||||||
name: 'alarm',
|
name: 'alarm',
|
||||||
message: 'Select Alarm:',
|
message: 'Select Alarm:',
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
source: async (answers, input) => await alarmChoices(alarmList, input)
|
source: async (answers, input) => alarmChoices(alarmList, input)
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
if (input.alarm === closeAlarms.value) break
|
if (input.alarm === closeAlarms.value) break
|
||||||
@@ -111,15 +112,14 @@ async function alarmsLoop(alarmList) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function alarms(fdn) {
|
async function alarms() {
|
||||||
const meContextFind = fdn.match(/(NetworkElement|MeContext)=([\w-]+),?/)
|
const meContextFind = this.fdn.match(/(NetworkElement|MeContext)=([\w-]+),?/)
|
||||||
if (!meContextFind) {
|
if (!meContextFind) {
|
||||||
console.log('No alarming object in FDN!'.yellow)
|
throw new Error('No alarming object in FDN!')
|
||||||
return
|
|
||||||
}
|
}
|
||||||
const eventPoIds = await getPoIds(`${this.alarmUrl}eventpoids`, meContextFind[2])
|
const eventPoIds = await getPoIds.call(this, `${this.alarmUrl}eventpoids`, meContextFind[2])
|
||||||
if (!eventPoIds) return
|
if (!eventPoIds) return
|
||||||
const alarmList = await getFields(`${this.alarmUrl}getalarmlist/fields`, eventPoIds)
|
const alarmList = await getFields.call(this, `${this.alarmUrl}getalarmlist/fields`, eventPoIds)
|
||||||
await alarmsLoop(alarmList)
|
await alarmsLoop(alarmList)
|
||||||
}
|
}
|
||||||
|
|
||||||
35
lib/applications/TopologyBrowser/commands/commit.js
Executable file
35
lib/applications/TopologyBrowser/commands/commit.js
Executable file
@@ -0,0 +1,35 @@
|
|||||||
|
const logAttributes = require('../../../../util/logAttributes')
|
||||||
|
const logCommit = require('../../../../util/logCommit')
|
||||||
|
|
||||||
|
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const response = await this.httpClient.request(axiosConfig)
|
||||||
|
if (response.data) {
|
||||||
|
logCommit(response.data)
|
||||||
|
} else {
|
||||||
|
throw new Error('No data or response❗')
|
||||||
|
}
|
||||||
|
this.configSet.length = 0
|
||||||
|
this.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = commit
|
||||||
19
lib/components/TopologyBrowser/commands/config.js → lib/applications/TopologyBrowser/commands/config.js
Normal file → Executable file
19
lib/components/TopologyBrowser/commands/config.js → lib/applications/TopologyBrowser/commands/config.js
Normal file → Executable file
@@ -1,10 +1,10 @@
|
|||||||
const requestWrapper = require('../../util/requestWrapper')
|
const logDetails = require('../../../../util/logDetails')
|
||||||
const logDetails = require('../../util/logDetails')
|
|
||||||
|
|
||||||
|
|
||||||
async function config(fdn) {
|
async function config() {
|
||||||
this.isConfig = true
|
this.isConfig = true
|
||||||
const axiosConfig = {
|
const axiosConfig = {
|
||||||
|
text: 'Reading Attributes...',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: `${this.objectUrl}${this.currentPoId}`,
|
url: `${this.objectUrl}${this.currentPoId}`,
|
||||||
params: {
|
params: {
|
||||||
@@ -12,27 +12,26 @@ async function config(fdn) {
|
|||||||
stringifyLong: true
|
stringifyLong: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const responseA = await requestWrapper(axiosConfig, 'Reading Attributes...')
|
const responseA = await this.httpClient.request(axiosConfig)
|
||||||
if (!responseA.data.attributes) {
|
if (!responseA.data.attributes) {
|
||||||
console.log('Can\'t read attributes'.red)
|
throw new Error('Can\'t read attributes')
|
||||||
return fdn
|
|
||||||
}
|
}
|
||||||
const { attributes, namespace, namespaceVersion, neType, neVersion, networkDetails, type} = responseA.data
|
const { attributes, namespace, namespaceVersion, neType, neVersion, networkDetails, type} = responseA.data
|
||||||
|
axiosConfig.text = 'Reading Attributes Data...'
|
||||||
axiosConfig.url = `${this.objectUrl}model/${neType}/${neVersion}/${namespace}/${type}/${namespaceVersion}/attributes`
|
axiosConfig.url = `${this.objectUrl}model/${neType}/${neVersion}/${namespace}/${type}/${namespaceVersion}/attributes`
|
||||||
axiosConfig.params = {
|
axiosConfig.params = {
|
||||||
includeNonPersistent: this.includeNonPersistent
|
includeNonPersistent: this.includeNonPersistent
|
||||||
}
|
}
|
||||||
const responseD = await requestWrapper(axiosConfig, 'Reading Attributes Data...')
|
const responseD = await this.httpClient.request(axiosConfig)
|
||||||
if (!responseD.data.attributes) {
|
if (!responseD.data.attributes) {
|
||||||
console.log('Can\'t read attributes data'.red)
|
throw new Error('Can\'t read attributes data')
|
||||||
return fdn
|
|
||||||
}
|
}
|
||||||
this.networkDetails = networkDetails
|
this.networkDetails = networkDetails
|
||||||
logDetails(networkDetails)
|
logDetails(networkDetails)
|
||||||
this.attributes = attributes
|
this.attributes = attributes
|
||||||
this.nextVariants = async (input) => await this.nextAttributes(input)
|
this.nextVariants = async (input) => await this.nextAttributes(input)
|
||||||
this.attributesData = responseD.data.attributes
|
this.attributesData = responseD.data.attributes
|
||||||
return `${fdn}(config)`
|
this.fdn = `${this.fdn}(config)`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
21
lib/applications/TopologyBrowser/commands/description.js
Executable file
21
lib/applications/TopologyBrowser/commands/description.js
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
const chalk = require('chalk')
|
||||||
|
const logAttributeData = require('../../../../util/logAttributeData')
|
||||||
|
|
||||||
|
|
||||||
|
function description() {
|
||||||
|
const attributeData = this.attributesData.find(item => item.key === this.attribute)
|
||||||
|
if (attributeData) {
|
||||||
|
logAttributeData(attributeData)
|
||||||
|
if (attributeData.complexRef) {
|
||||||
|
console.log(`${chalk.magenta(attributeData.type)}
|
||||||
|
${chalk.cyan(attributeData.complexRef.key)}: ${chalk.grey(attributeData.complexRef.description)}
|
||||||
|
`)
|
||||||
|
attributeData.complexRef.attributes.forEach(attr => logAttributeData(attr))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error('Attribute Not Found❗')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = description
|
||||||
2
lib/components/TopologyBrowser/commands/end.js → lib/applications/TopologyBrowser/commands/end.js
Normal file → Executable file
2
lib/components/TopologyBrowser/commands/end.js → lib/applications/TopologyBrowser/commands/end.js
Normal file → Executable file
@@ -1,7 +1,9 @@
|
|||||||
function end() {
|
function end() {
|
||||||
|
this.fdn = this.fdn.replace(/\((\w+)\)/g, '')
|
||||||
this.isConfig = false
|
this.isConfig = false
|
||||||
this.attribute = null
|
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)
|
this.nextVariants = async (input) => await this.nextObjects(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
23
lib/applications/TopologyBrowser/commands/get.js
Executable file
23
lib/applications/TopologyBrowser/commands/get.js
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
const logAttributes = require('../../../../util/logAttributes')
|
||||||
|
const banner = require('../../../../util/banner')
|
||||||
|
const chalk = require('chalk')
|
||||||
|
|
||||||
|
|
||||||
|
function get() {
|
||||||
|
const syncStatus = this.networkDetails.find(item => item.key === 'syncStatus')
|
||||||
|
if (syncStatus && syncStatus.value === 'UNSYNCHRONIZED') {
|
||||||
|
console.log(chalk.yellow(`
|
||||||
|
❗ ${syncStatus.key}: ${syncStatus.value} ❗`))
|
||||||
|
}
|
||||||
|
const attribute = this.attributes.find(item => item.key === this.attribute)
|
||||||
|
if (!attribute) {
|
||||||
|
throw new Error(`Attribute not Found: ${this.attribute}`)
|
||||||
|
}
|
||||||
|
const attributeData = this.attributesData.find(item => item.key === this.attribute)
|
||||||
|
logAttributes(this.fdn, [attribute])
|
||||||
|
console.log(` ${chalk.green('Type: ') + attributeData['type']} ${attributeData['defaultValue'] ? chalk.yellow('Default: ') + attributeData['defaultValue'] : ''}
|
||||||
|
`)
|
||||||
|
if (attributeData.constraints && attributeData.constraints.orderingConstraint) banner(attributeData)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = get
|
||||||
21
lib/components/TopologyBrowser/commands/fdn.js → lib/applications/TopologyBrowser/commands/goToFdn.js
Normal file → Executable file
21
lib/components/TopologyBrowser/commands/fdn.js → lib/applications/TopologyBrowser/commands/goToFdn.js
Normal file → Executable file
@@ -1,28 +1,29 @@
|
|||||||
const requestWrapper = require('../../util/requestWrapper')
|
async function goToFdn(targetFdn) {
|
||||||
|
if (!targetFdn) {
|
||||||
|
throw new Error('Valid FDN must be supplied❗')
|
||||||
async function fdn(fromFdn, targetFdn) {
|
}
|
||||||
const axiosConfig = {
|
const axiosConfig = {
|
||||||
|
text: 'Browsing to FDN...',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: `${this.objectUrl}fdn/${targetFdn}`,
|
url: `${this.objectUrl}fdn/${targetFdn}`,
|
||||||
}
|
}
|
||||||
const response1 = await requestWrapper(axiosConfig, 'Browsing to FDN...')
|
const response1 = await this.httpClient.request(axiosConfig)
|
||||||
if (!response1.data.fdn) return fromFdn
|
|
||||||
this.poIds.length = 0
|
this.poIds.length = 0
|
||||||
const { fdn, poId } = response1.data
|
const { fdn, poId } = response1.data
|
||||||
this.currentPoId = poId
|
this.currentPoId = poId
|
||||||
this.nextPoId = poId
|
this.nextPoId = poId
|
||||||
this.nextVariants = async (input) => await this.nextObjects(input)
|
this.nextVariants = async (input) => await this.nextObjects(input)
|
||||||
|
axiosConfig.text = 'Building FDN path...'
|
||||||
axiosConfig.url = `${this.objectUrl}network/${this.currentPoId}/subTrees`
|
axiosConfig.url = `${this.objectUrl}network/${this.currentPoId}/subTrees`
|
||||||
const response2 = await requestWrapper(axiosConfig, 'Building FDN path...')
|
const response2 = await this.httpClient.request(axiosConfig)
|
||||||
if (response2.data) {
|
if (response2.data) {
|
||||||
if (response2.data.treeNodes.length > 1) {
|
if (response2.data.treeNodes.length > 1) {
|
||||||
response2.data.treeNodes.slice(0, -1).forEach((node) => {
|
response2.data.treeNodes.slice(0, -1).forEach((node) => {
|
||||||
this.poIds.push(node.poId)
|
this.poIds.push(node.poId)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.childrens = null
|
this.childrens = []
|
||||||
}
|
}
|
||||||
return fdn
|
this.fdn = fdn
|
||||||
}
|
}
|
||||||
module.exports = fdn
|
module.exports = goToFdn
|
||||||
1
lib/components/TopologyBrowser/commands/home.js → lib/applications/TopologyBrowser/commands/home.js
Normal file → Executable file
1
lib/components/TopologyBrowser/commands/home.js → lib/applications/TopologyBrowser/commands/home.js
Normal file → Executable file
@@ -1,4 +1,5 @@
|
|||||||
function home() {
|
function home() {
|
||||||
|
this.fdn = this.fdn.split(',', 1)[0]
|
||||||
this.nextPoId = this.poIds.shift()
|
this.nextPoId = this.poIds.shift()
|
||||||
this.poIds.length = 0
|
this.poIds.length = 0
|
||||||
this.nextVariants = async (input) => await this.nextObjects(input)
|
this.nextVariants = async (input) => await this.nextObjects(input)
|
||||||
11
lib/components/TopologyBrowser/commands/initialPrompt.js → lib/applications/TopologyBrowser/commands/initialPrompt.js
Normal file → Executable file
11
lib/components/TopologyBrowser/commands/initialPrompt.js → lib/applications/TopologyBrowser/commands/initialPrompt.js
Normal file → Executable file
@@ -1,22 +1,21 @@
|
|||||||
const colors = require('colors')
|
const chalk = require("chalk")
|
||||||
const requestWrapper = require('../../util/requestWrapper')
|
|
||||||
|
|
||||||
|
|
||||||
async function initialPrompt() {
|
async function initialPrompt() {
|
||||||
const axiosConfig = {
|
const axiosConfig = {
|
||||||
|
text: 'Starting Topology Browser...',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: `${this.objectUrl}network/-1?relativeDepth=0:-2&childDepth=1`
|
url: `${this.objectUrl}network/-1?relativeDepth=0:-2&childDepth=1`
|
||||||
}
|
}
|
||||||
const response = await requestWrapper(axiosConfig, 'Starting Topology Browser...')
|
const response = await this.httpClient.request(axiosConfig)
|
||||||
if (!response.data.treeNodes) {
|
if (!response.data.treeNodes) {
|
||||||
console.log('Nothing in initial promt!'.red)
|
throw new Error('Nothing in initial promt‼')
|
||||||
return
|
|
||||||
}
|
}
|
||||||
const { moType, moName, poId } = response.data.treeNodes[0]
|
const { moType, moName, poId } = response.data.treeNodes[0]
|
||||||
this.currentPoId = poId
|
this.currentPoId = poId
|
||||||
this.nextPoId = poId
|
this.nextPoId = poId
|
||||||
this.nextVariants = async (input) => await this.nextObjects(input)
|
this.nextVariants = async (input) => await this.nextObjects(input)
|
||||||
return `${moType}=${moName}`
|
this.fdn = `${moType}=${moName}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
14
lib/applications/TopologyBrowser/commands/nextAttributes.js
Executable file
14
lib/applications/TopologyBrowser/commands/nextAttributes.js
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
|
||||||
|
async function nextAttributes(input) {
|
||||||
|
const filter = input ? input : ''
|
||||||
|
this.commands = this.configCommands
|
||||||
|
.filter(item => item.toLowerCase().includes(filter.toLowerCase()))
|
||||||
|
this.choices = this.attributes
|
||||||
|
.map(item => item.key)
|
||||||
|
.filter(item => item.toLowerCase().includes(filter.toLowerCase()))
|
||||||
|
.sort((a, b) => a > b ? 1 : -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = nextAttributes
|
||||||
57
lib/applications/TopologyBrowser/commands/nextObjects.js
Executable file
57
lib/applications/TopologyBrowser/commands/nextObjects.js
Executable file
@@ -0,0 +1,57 @@
|
|||||||
|
const chalk = require("chalk")
|
||||||
|
const logError = require('../../../../util/logError')
|
||||||
|
|
||||||
|
const otherCommands = ['show', 'config', 'up', 'home', 'fdn', 'search', 'persistent', 'alarms', 'sync', 'exit']
|
||||||
|
|
||||||
|
|
||||||
|
function getSyncStatus(child) {
|
||||||
|
if (child.syncStatus === 'SYNCHRONIZED') return '\t\t✅'
|
||||||
|
if (child.syncStatus === 'UNSYNCHRONIZED') return '\t\t⏳'
|
||||||
|
return child.syncStatus ? '\t\t❓' : ''
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getRadioAccessTechnology(child) {
|
||||||
|
return child.radioAccessTechnology ? ' ' + chalk.bold.cyan(child.radioAccessTechnology.join(' ')) : ''
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function networkRequest() {
|
||||||
|
try {
|
||||||
|
const axiosConfig = {
|
||||||
|
text: 'Loading network data...',
|
||||||
|
method: 'get',
|
||||||
|
url: `${this.objectUrl}network/${this.currentPoId}`
|
||||||
|
}
|
||||||
|
const { data: { treeNodes } } = await this.httpClient.request(axiosConfig)
|
||||||
|
if (treeNodes) {
|
||||||
|
this.childrens = treeNodes[0].childrens
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function nextObjects(input){
|
||||||
|
const filter = input ? input : ''
|
||||||
|
if (this.currentPoId !== this.nextPoId || this.childrens.length === 0) {
|
||||||
|
this.currentPoId = this.nextPoId
|
||||||
|
this.poIds.push(this.currentPoId)
|
||||||
|
await networkRequest.call(this)
|
||||||
|
}
|
||||||
|
this.commands = otherCommands.filter(cmd => cmd.toLowerCase().includes(filter.toLowerCase()))
|
||||||
|
this.choices = this.childrens
|
||||||
|
.map(child => {
|
||||||
|
const st = getSyncStatus(child)
|
||||||
|
const rt = getRadioAccessTechnology(child)
|
||||||
|
const ne = child.neType ? ' ' + chalk.dim.gray(child.neType) : ''
|
||||||
|
return `${child.moType}=${child.moName}${st}${rt}${ne}`
|
||||||
|
})
|
||||||
|
.filter(child => child.toLowerCase().includes(filter.toLowerCase()))
|
||||||
|
.concat(filter.startsWith('show') ? [filter] : [])
|
||||||
|
.concat(filter.startsWith('fdn') ? [filter] : [])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = nextObjects
|
||||||
127
lib/applications/TopologyBrowser/commands/search.js
Executable file
127
lib/applications/TopologyBrowser/commands/search.js
Executable file
@@ -0,0 +1,127 @@
|
|||||||
|
const chalk = require('chalk')
|
||||||
|
const inquirer = require('inquirer')
|
||||||
|
const { isValidNodeName } = require('../../../../util/validation')
|
||||||
|
|
||||||
|
|
||||||
|
async function getNodeTypes() {
|
||||||
|
const axiosConfig = {
|
||||||
|
text: 'Getting Node Types...',
|
||||||
|
method: 'get',
|
||||||
|
url: this.nodeTypesUrl,
|
||||||
|
}
|
||||||
|
const response = await this.httpClient.request(axiosConfig)
|
||||||
|
return response.data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function getPoIds(query) {
|
||||||
|
const axiosConfig = {
|
||||||
|
text: 'Searching Nodes...',
|
||||||
|
method: 'get',
|
||||||
|
url: this.nodeSearchUrl,
|
||||||
|
headers: {
|
||||||
|
'X-Netex-Scoping-Panel': true,
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
query,
|
||||||
|
orderby: 'moName',
|
||||||
|
orderdirection: 'asc',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const { data: { objects } } = await this.httpClient.request(axiosConfig)
|
||||||
|
return objects.map(item => item.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function getNodesData(poList) {
|
||||||
|
const axiosConfig = {
|
||||||
|
text: 'Getting Nodes Data...',
|
||||||
|
method: 'post',
|
||||||
|
url: this.nodePoIdsUrl,
|
||||||
|
data: {
|
||||||
|
poList,
|
||||||
|
defaultMappings: ["syncStatus","managementState","radioAccessTechnology","parentNeType"],
|
||||||
|
attributeMappings:[{"moType":"MeContext","attributeNames":["neType"]}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const response = await this.httpClient.request(axiosConfig)
|
||||||
|
return response.data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function resultOutput(result) {
|
||||||
|
console.log('')
|
||||||
|
result.forEach(item => {
|
||||||
|
const {
|
||||||
|
fdn,
|
||||||
|
attributes,
|
||||||
|
cmSyncStatus,
|
||||||
|
radioAccessTechnology,
|
||||||
|
} = item
|
||||||
|
console.log(`${cmSyncStatus === 'SYNCHRONIZED' ? '✅' : '⏳'} ${fdn} ${chalk.dim.grey(attributes.neType)} ${chalk.bold.cyan(radioAccessTechnology.join(' '))}`)
|
||||||
|
})
|
||||||
|
console.log('')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function filterTypes(input, nodeTypes){
|
||||||
|
const filter = input ? input : ''
|
||||||
|
return nodeTypes.filter(
|
||||||
|
item => item
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(filter.toLowerCase())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function buildQuery(nodeName, nodeType, rat) {
|
||||||
|
const ratFilter = rat.length !== 0
|
||||||
|
? ` filter by radioAccessTechnology ${rat.length === 1 ? 'containing ' : 'contains any of '}${rat.join(',')}`
|
||||||
|
: ''
|
||||||
|
const typeFilter = nodeType === 'ALL'
|
||||||
|
? `with name = ${nodeName}`
|
||||||
|
: `of type ${nodeType} where name = ${nodeName}`
|
||||||
|
return `select all nodes ${nodeName && typeFilter}${ratFilter}`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function search() {
|
||||||
|
const nodeTypes = await getNodeTypes.call(this)
|
||||||
|
nodeTypes.push('ALL')
|
||||||
|
const { nodeName, nodeType, rat } = await inquirer.prompt([
|
||||||
|
{
|
||||||
|
type: 'autocomplete',
|
||||||
|
name: 'nodeType',
|
||||||
|
message: 'Select Node Type (default ALL):',
|
||||||
|
pageSize: 10,
|
||||||
|
default: 'ALL',
|
||||||
|
source: async (answers, input) => filterTypes(input, nodeTypes)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'checkbox',
|
||||||
|
name: 'rat',
|
||||||
|
message: 'Select Radio Access Technologies (default all):',
|
||||||
|
choices: [
|
||||||
|
{name: '2G'},
|
||||||
|
{name: '3G'},
|
||||||
|
{name: '4G'},
|
||||||
|
{name: '5G'},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
name: 'nodeName',
|
||||||
|
message: 'Type a Node Name:',
|
||||||
|
validate: isValidNodeName
|
||||||
|
}
|
||||||
|
])
|
||||||
|
const poList = await getPoIds.call(this, buildQuery(nodeName, nodeType, rat))
|
||||||
|
if (poList.length === 0) {
|
||||||
|
throw new Error('Nodes not found❗')
|
||||||
|
}
|
||||||
|
const result = await getNodesData.call(this, poList)
|
||||||
|
resultOutput(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = search
|
||||||
8
lib/components/TopologyBrowser/commands/set.js → lib/applications/TopologyBrowser/commands/set.js
Normal file → Executable file
8
lib/components/TopologyBrowser/commands/set.js → lib/applications/TopologyBrowser/commands/set.js
Normal file → Executable file
@@ -1,16 +1,14 @@
|
|||||||
const colors = require('colors')
|
|
||||||
const inputByType = require('../inputValue')
|
const inputByType = require('../inputValue')
|
||||||
|
|
||||||
|
|
||||||
async function set() {
|
async function set() {
|
||||||
const attributeData = this.attributesData.filter(item => item.key === this.attribute)[0]
|
const attributeData = this.attributesData.find(item => item.key === this.attribute)
|
||||||
if (!attributeData) return
|
if (!attributeData) return
|
||||||
if (attributeData.writeBehavior === 'NOT_ALLOWED' || attributeData.immutable) {
|
if (attributeData.writeBehavior === 'NOT_ALLOWED' || attributeData.immutable) {
|
||||||
console.log('Attribute Is ReadOnly'.yellow)
|
throw new Error('Attribute Is ReadOnly')
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if (this.isConfig) {
|
if (this.isConfig) {
|
||||||
const found = this.configSet.filter(item => item.key === this.attribute)[0]
|
const found = this.configSet.find(item => item.key === this.attribute)
|
||||||
const { value } = await inputByType(attributeData)
|
const { value } = await inputByType(attributeData)
|
||||||
if (found) {
|
if (found) {
|
||||||
found.value = value
|
found.value = value
|
||||||
12
lib/applications/TopologyBrowser/commands/setAttribute.js
Executable file
12
lib/applications/TopologyBrowser/commands/setAttribute.js
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
function setAttribute(attribute) {
|
||||||
|
if (!this.attributes) return false
|
||||||
|
if (!this.attributes.find(item => item.key === attribute)) return false
|
||||||
|
if (!this.attribute) {
|
||||||
|
['get', 'set', 'description'].forEach(cmd => this.configCommands.push(cmd))
|
||||||
|
}
|
||||||
|
this.attribute = attribute
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = setAttribute
|
||||||
2
lib/components/TopologyBrowser/commands/setIdByCommand.js → lib/applications/TopologyBrowser/commands/setIdByCommand.js
Normal file → Executable file
2
lib/components/TopologyBrowser/commands/setIdByCommand.js → lib/applications/TopologyBrowser/commands/setIdByCommand.js
Normal file → Executable file
@@ -1,5 +1,5 @@
|
|||||||
function setIdByCommand(command) {
|
function setIdByCommand(command) {
|
||||||
const nextChild = this.childrens.filter(child => `${child.moType}=${child.moName}` === command)[0]
|
const nextChild = this.childrens.find(child => `${child.moType}=${child.moName}` === command)
|
||||||
if (nextChild) {
|
if (nextChild) {
|
||||||
this.nextPoId = nextChild.poId
|
this.nextPoId = nextChild.poId
|
||||||
return true
|
return true
|
||||||
6
lib/components/TopologyBrowser/commands/show.js → lib/applications/TopologyBrowser/commands/show.js
Normal file → Executable file
6
lib/components/TopologyBrowser/commands/show.js → lib/applications/TopologyBrowser/commands/show.js
Normal file → Executable file
@@ -1,9 +1,9 @@
|
|||||||
const requestWrapper = require('../../util/requestWrapper')
|
const logAttributes = require('../../../../util/logAttributes')
|
||||||
const logAttributes = require('../../util/logAttributes')
|
|
||||||
|
|
||||||
|
|
||||||
async function show(filter) {
|
async function show(filter) {
|
||||||
const axiosConfig = {
|
const axiosConfig = {
|
||||||
|
text: 'Getting Atrributes...',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: `${this.objectUrl}${this.currentPoId}`,
|
url: `${this.objectUrl}${this.currentPoId}`,
|
||||||
params: {
|
params: {
|
||||||
@@ -11,7 +11,7 @@ async function show(filter) {
|
|||||||
stringifyLong: true
|
stringifyLong: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const response = await requestWrapper(axiosConfig)
|
const response = await this.httpClient.request(axiosConfig)
|
||||||
if (!response.data.fdn || !response.data.attributes) return
|
if (!response.data.fdn || !response.data.attributes) return
|
||||||
logAttributes(response.data.fdn, response.data.attributes.filter(item => item.key.match(filter)))
|
logAttributes(response.data.fdn, response.data.attributes.filter(item => item.key.match(filter)))
|
||||||
}
|
}
|
||||||
26
lib/applications/TopologyBrowser/commands/sync.js
Executable file
26
lib/applications/TopologyBrowser/commands/sync.js
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
const chalk = require("chalk")
|
||||||
|
|
||||||
|
|
||||||
|
async function sync() {
|
||||||
|
const meContextFind = this.fdn.match(/(NetworkElement|MeContext)=([\w-]+),?/)
|
||||||
|
if (!meContextFind) {
|
||||||
|
throw new Error('No sync object in FDN!')
|
||||||
|
}
|
||||||
|
const actionUrl = `${this.objectUrl}v1/perform-mo-action/NetworkElement=${meContextFind[2]},CmFunction=1?actionName=sync`
|
||||||
|
const axiosConfig = {
|
||||||
|
text: 'Initiate Node Sync...',
|
||||||
|
method: 'post',
|
||||||
|
url: actionUrl,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const response = await this.httpClient.request(axiosConfig)
|
||||||
|
console.log(`
|
||||||
|
${chalk.bold(response.data.body)}
|
||||||
|
${chalk.green(response.data.title)}
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = sync
|
||||||
5
lib/components/TopologyBrowser/commands/up.js → lib/applications/TopologyBrowser/commands/up.js
Normal file → Executable file
5
lib/components/TopologyBrowser/commands/up.js → lib/applications/TopologyBrowser/commands/up.js
Normal file → Executable file
@@ -3,9 +3,10 @@ function up() {
|
|||||||
this.poIds.pop()
|
this.poIds.pop()
|
||||||
this.nextPoId = this.poIds.pop()
|
this.nextPoId = this.poIds.pop()
|
||||||
this.currentPoId = this.poIds[this.poIds.length - 1]
|
this.currentPoId = this.poIds[this.poIds.length - 1]
|
||||||
return true
|
this.fdn = this.fdn.split(',').slice(0, -1).join(',')
|
||||||
|
return
|
||||||
}
|
}
|
||||||
return false
|
throw new Error('There\'s no way up!')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
25
lib/applications/TopologyBrowser/help.js
Executable file
25
lib/applications/TopologyBrowser/help.js
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
const mainHelp = [
|
||||||
|
'',
|
||||||
|
'show [<valid regex>] - shows current object\'s attributes filtered with regex',
|
||||||
|
'config - enters config mode',
|
||||||
|
'up - navigate up one level',
|
||||||
|
'fdn [<valid FDN>] - navigate to FDN',
|
||||||
|
'home - navigate to root folder',
|
||||||
|
'alarms - show alarms',
|
||||||
|
'sync - initiate node CM synchronization',
|
||||||
|
'persistent - toggle persistent attributes inclusion',
|
||||||
|
'exit - logout and exit application',
|
||||||
|
].join('\n')
|
||||||
|
|
||||||
|
const configHelp = [
|
||||||
|
'',
|
||||||
|
'set - set attribute\'s value',
|
||||||
|
'get - get attribute\'s value',
|
||||||
|
'commit - commiting changes to the network',
|
||||||
|
'check - view configuration changes',
|
||||||
|
'end - exit config mode without commiting',
|
||||||
|
'exit - logout and exit application',
|
||||||
|
].join('\n')
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = { mainHelp, configHelp }
|
||||||
109
lib/applications/TopologyBrowser/inputHandler.js
Executable file
109
lib/applications/TopologyBrowser/inputHandler.js
Executable file
@@ -0,0 +1,109 @@
|
|||||||
|
const inquirer = require('inquirer')
|
||||||
|
const chalk = require('chalk')
|
||||||
|
|
||||||
|
const logError = require('../../../util/logError')
|
||||||
|
const { isEmpty } = require('../../../util/validation')
|
||||||
|
|
||||||
|
|
||||||
|
inquirer.registerPrompt('autocomplete', require('inquirer-autocomplete-prompt'))
|
||||||
|
|
||||||
|
|
||||||
|
function commandOther(tplg, command) {
|
||||||
|
const spl = command.split(/\s+/).find(item => item)
|
||||||
|
if (tplg.setIdByCommand(spl)) {
|
||||||
|
tplg.fdn = `${tplg.fdn},${spl}`
|
||||||
|
} else if (tplg.setAttribute(command)) {
|
||||||
|
tplg.fdn = tplg.fdn.replace(/\((\w+)\)/g, `(${command})`)
|
||||||
|
} else {
|
||||||
|
throw new Error('Command Unrecognized❗')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function handleCommand(tplg, command) {
|
||||||
|
const [cmd, param] = command.split(/\s+/)
|
||||||
|
const cmdMatch = cmd.match(/\[(\w+)\]/)
|
||||||
|
const cmdName = cmdMatch ? cmdMatch[1] : cmd
|
||||||
|
switch (cmdName) {
|
||||||
|
case 'exit':
|
||||||
|
tplg.fdn = ''
|
||||||
|
break
|
||||||
|
case 'show':
|
||||||
|
await tplg.show(param ? param.trim() : '')
|
||||||
|
break
|
||||||
|
case 'config':
|
||||||
|
await tplg.config()
|
||||||
|
break
|
||||||
|
case 'set':
|
||||||
|
await tplg.set()
|
||||||
|
break
|
||||||
|
case 'commit':
|
||||||
|
await tplg.commit()
|
||||||
|
break
|
||||||
|
case 'up':
|
||||||
|
tplg.up()
|
||||||
|
break
|
||||||
|
case 'get':
|
||||||
|
tplg.get()
|
||||||
|
break
|
||||||
|
case 'check':
|
||||||
|
tplg.check()
|
||||||
|
break
|
||||||
|
case 'end':
|
||||||
|
tplg.end()
|
||||||
|
break
|
||||||
|
case 'home':
|
||||||
|
tplg.home()
|
||||||
|
break
|
||||||
|
case 'search':
|
||||||
|
await tplg.search()
|
||||||
|
break
|
||||||
|
case 'description':
|
||||||
|
tplg.description()
|
||||||
|
break
|
||||||
|
case 'persistent':
|
||||||
|
tplg.persistent()
|
||||||
|
break
|
||||||
|
case 'fdn':
|
||||||
|
await tplg.goToFdn(param ? param.trim() : '')
|
||||||
|
break
|
||||||
|
case 'alarms':
|
||||||
|
await tplg.alarms()
|
||||||
|
break
|
||||||
|
case 'sync':
|
||||||
|
await tplg.sync()
|
||||||
|
break
|
||||||
|
|
||||||
|
default:
|
||||||
|
commandOther(tplg, command)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function inputHandler() {
|
||||||
|
await this.initialPrompt()
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
const input = await inquirer.prompt([
|
||||||
|
{
|
||||||
|
type: 'autocomplete',
|
||||||
|
name: 'command',
|
||||||
|
message: chalk.blue(this.getPrompt()),
|
||||||
|
pageSize: 10,
|
||||||
|
prefix: '',
|
||||||
|
suffix: this.isConfig ? chalk.blue('#') : chalk.blue('>'),
|
||||||
|
validate: isEmpty,
|
||||||
|
source: async (answers, input) => await this.next(input),
|
||||||
|
emptyText: this.help,
|
||||||
|
}
|
||||||
|
])
|
||||||
|
await handleCommand(this, input.command)
|
||||||
|
if (!this.fdn) break
|
||||||
|
} catch (error) {
|
||||||
|
logError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = inputHandler
|
||||||
29
lib/components/TopologyBrowser/inputValue.js → lib/applications/TopologyBrowser/inputValue.js
Normal file → Executable file
29
lib/components/TopologyBrowser/inputValue.js → lib/applications/TopologyBrowser/inputValue.js
Normal file → Executable file
@@ -1,16 +1,16 @@
|
|||||||
const colors = require('colors')
|
const chalk = require('chalk')
|
||||||
const inquirer = require('inquirer')
|
const inquirer = require('inquirer')
|
||||||
const banner = require('../util/banner')
|
const banner = require('../../../util/banner')
|
||||||
const { isValidNumber, isValidString, checkValueRangeConstraints } = require('../util/validation')
|
const { isValidNumber, isValidString, checkValueRangeConstraints } = require('../../../util/validation')
|
||||||
|
|
||||||
|
|
||||||
async function inputInteger(attributeData) {
|
async function inputInteger(attributeData) {
|
||||||
const message = `${attributeData.key.yellow} { ${attributeData.unit ? attributeData.unit : 'parrots'.gray} } (${attributeData.type}): `
|
const message = `${chalk.yellow(attributeData.key)} { ${attributeData.unit ? attributeData.unit : chalk.gray('parrots')} } (${attributeData.type}): `
|
||||||
const input = await inquirer.prompt([
|
const input = await inquirer.prompt([
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
name: 'value',
|
name: 'value',
|
||||||
suffix: '?'.green,
|
suffix: chalk.green('?'),
|
||||||
message,
|
message,
|
||||||
default: attributeData.defaultValue,
|
default: attributeData.defaultValue,
|
||||||
validate: input => isValidNumber(input, attributeData.constraints),
|
validate: input => isValidNumber(input, attributeData.constraints),
|
||||||
@@ -21,12 +21,12 @@ async function inputInteger(attributeData) {
|
|||||||
|
|
||||||
|
|
||||||
async function inputEnumRef(attributeData) {
|
async function inputEnumRef(attributeData) {
|
||||||
const message = `Select Value For ${attributeData.key.yellow}: `
|
const message = `Select Value For ${chalk.yellow(attributeData.key)}: `
|
||||||
const input = await inquirer.prompt([
|
const input = await inquirer.prompt([
|
||||||
{
|
{
|
||||||
type: 'list',
|
type: 'list',
|
||||||
name: 'value',
|
name: 'value',
|
||||||
suffix: '?'.green,
|
suffix: chalk.green('?'),
|
||||||
message,
|
message,
|
||||||
choices: attributeData.enumeration.enumMembers.map(item => ({ name: `${item.key} (${item.description})`, value: item.key, short: item.key })),
|
choices: attributeData.enumeration.enumMembers.map(item => ({ name: `${item.key} (${item.description})`, value: item.key, short: item.key })),
|
||||||
default: attributeData.defaultValue,
|
default: attributeData.defaultValue,
|
||||||
@@ -39,12 +39,12 @@ async function inputEnumRef(attributeData) {
|
|||||||
async function inputBoolean(attributeData) {
|
async function inputBoolean(attributeData) {
|
||||||
const variants = ['true', 'false']
|
const variants = ['true', 'false']
|
||||||
if (attributeData.constraints.nullable) variants.push('null')
|
if (attributeData.constraints.nullable) variants.push('null')
|
||||||
const message = `Select Value For ${attributeData.key.yellow}:`
|
const message = `Select Value For ${chalk.yellow(attributeData.key)}:`
|
||||||
const input = await inquirer.prompt([
|
const input = await inquirer.prompt([
|
||||||
{
|
{
|
||||||
type: 'list',
|
type: 'list',
|
||||||
name: 'value',
|
name: 'value',
|
||||||
suffix: '?'.green,
|
suffix: chalk.green('?'),
|
||||||
message,
|
message,
|
||||||
choices: variants,
|
choices: variants,
|
||||||
default: String(attributeData.defaultValue),
|
default: String(attributeData.defaultValue),
|
||||||
@@ -59,12 +59,12 @@ async function inputBoolean(attributeData) {
|
|||||||
|
|
||||||
|
|
||||||
async function inputString(attributeData) {
|
async function inputString(attributeData) {
|
||||||
const message = `${attributeData.key.yellow} (${attributeData.type}): `
|
const message = `${chalk.yellow(attributeData.key)} (${attributeData.type}): `
|
||||||
const input = await inquirer.prompt([
|
const input = await inquirer.prompt([
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
name: 'value',
|
name: 'value',
|
||||||
suffix: '?'.green,
|
suffix: chalk.green('?'),
|
||||||
message,
|
message,
|
||||||
default: attributeData.defaultValue,
|
default: attributeData.defaultValue,
|
||||||
validate: input => isValidString(input, attributeData.constraints),
|
validate: input => isValidString(input, attributeData.constraints),
|
||||||
@@ -75,13 +75,13 @@ async function inputString(attributeData) {
|
|||||||
|
|
||||||
|
|
||||||
async function inputList(attributeData) {
|
async function inputList(attributeData) {
|
||||||
const message = `${attributeData.key.yellow} List Of (${attributeData.listReference.type}) Size: `
|
const message = `${chalk.yellow(attributeData.key)} List Of (${attributeData.listReference.type}) Size: `
|
||||||
const result = []
|
const result = []
|
||||||
const { value } = await inquirer.prompt([
|
const { value } = await inquirer.prompt([
|
||||||
{
|
{
|
||||||
type: 'number',
|
type: 'number',
|
||||||
name: 'value',
|
name: 'value',
|
||||||
suffix: '?'.green,
|
suffix: chalk.green('?'),
|
||||||
message,
|
message,
|
||||||
default: 'null',
|
default: 'null',
|
||||||
validate: input => +input > 0 || input === 'null',
|
validate: input => +input > 0 || input === 'null',
|
||||||
@@ -108,7 +108,7 @@ async function inputListValues(attributeData, listSize, result) {
|
|||||||
}
|
}
|
||||||
if (attributeData.constraints.uniqueMembers) {
|
if (attributeData.constraints.uniqueMembers) {
|
||||||
if (result.indexOf(input.value) !== -1) {
|
if (result.indexOf(input.value) !== -1) {
|
||||||
console.log('>>Array Values Should Be Unique'.red)
|
console.log(chalk.red('>>Array Values Should Be Unique'))
|
||||||
i--
|
i--
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -138,6 +138,7 @@ async function inputByType(typeReference) {
|
|||||||
const inputs = {
|
const inputs = {
|
||||||
INTEGER: inputInteger,
|
INTEGER: inputInteger,
|
||||||
SHORT: inputInteger,
|
SHORT: inputInteger,
|
||||||
|
LONG: inputInteger,
|
||||||
ENUM_REF: inputEnumRef,
|
ENUM_REF: inputEnumRef,
|
||||||
BOOLEAN: inputBoolean,
|
BOOLEAN: inputBoolean,
|
||||||
STRING: inputString,
|
STRING: inputString,
|
||||||
8
lib/components/AxiosHttpClient/AxiosHttpClient.js → lib/components/AxiosHttpClient.js
Normal file → Executable file
8
lib/components/AxiosHttpClient/AxiosHttpClient.js → lib/components/AxiosHttpClient.js
Normal file → Executable file
@@ -1,9 +1,9 @@
|
|||||||
const axios = require('axios')
|
const axios = require('axios')
|
||||||
const chalk = require('chalk')
|
|
||||||
const https = require('https')
|
const https = require('https')
|
||||||
const axiosCookieJarSupport = require('axios-cookiejar-support').default
|
const axiosCookieJarSupport = require('axios-cookiejar-support').default
|
||||||
const tough = require('tough-cookie')
|
const tough = require('tough-cookie')
|
||||||
const SpinnerWithCounter = require('../../../util/SpinnerWithCounter')
|
const logError = require('../../util/logError')
|
||||||
|
const SpinnerWithCounter = require('./SpinnerWithCounter')
|
||||||
|
|
||||||
|
|
||||||
axiosCookieJarSupport(axios)
|
axiosCookieJarSupport(axios)
|
||||||
@@ -20,6 +20,10 @@ function beforeRequest(config) {
|
|||||||
|
|
||||||
function errorRequest(error) {
|
function errorRequest(error) {
|
||||||
spinner.fail()
|
spinner.fail()
|
||||||
|
if (401 === error.response.status) {
|
||||||
|
logError(error)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
5
lib/components/ENM/ENM.js → lib/components/ENM.js
Normal file → Executable file
5
lib/components/ENM/ENM.js → lib/components/ENM.js
Normal file → Executable file
@@ -1,10 +1,11 @@
|
|||||||
const chalk = require('chalk')
|
const axiosHttpClient = require('./AxiosHttpClient')
|
||||||
const axiosHttpClient = require('../AxiosHttpClient/AxiosHttpClient')
|
|
||||||
|
|
||||||
class ENM {
|
class ENM {
|
||||||
constructor(username, password, url) {
|
constructor(username, password, url) {
|
||||||
this.logoutUrl = '/logout'
|
this.logoutUrl = '/logout'
|
||||||
this.loginUrl = `/login?IDToken1=${username}&IDToken2=${password}`
|
this.loginUrl = `/login?IDToken1=${username}&IDToken2=${password}`
|
||||||
|
this.commands = null
|
||||||
|
this.choices = null
|
||||||
this.httpClient = axiosHttpClient(url)
|
this.httpClient = axiosHttpClient(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
0
util/SpinnerWithCounter.js → lib/components/SpinnerWithCounter.js
Normal file → Executable file
0
util/SpinnerWithCounter.js → lib/components/SpinnerWithCounter.js
Normal file → Executable file
@@ -1,132 +0,0 @@
|
|||||||
const logAttributes = require('../util/logAttributes')
|
|
||||||
const inputHandler = require('./inputHandler')
|
|
||||||
const alarms = require('../commands/alarms')
|
|
||||||
const sync = require('../commands/sync')
|
|
||||||
const initialPrompt = require('../commands/initialPrompt')
|
|
||||||
const nextObjects = require('../commands/nextObjects')
|
|
||||||
const nextAttributes = require('../commands/nextAttributes')
|
|
||||||
const setIdByCommand = require('../commands/setIdByCommand')
|
|
||||||
const show = require('../commands/show')
|
|
||||||
const up = require('../commands/up')
|
|
||||||
const config = require('../commands/config')
|
|
||||||
const end = require('../commands/end')
|
|
||||||
const setAttribute = require('../commands/setAttribute')
|
|
||||||
const description = require('../commands/description')
|
|
||||||
const get = require('../commands/get')
|
|
||||||
const set = require('../commands/set')
|
|
||||||
const commit = require('../commands/commit')
|
|
||||||
const home = require('../commands/home')
|
|
||||||
const fdn = require('../commands/fdn')
|
|
||||||
|
|
||||||
const ENM = require('../ENM/ENM')
|
|
||||||
|
|
||||||
class TopologyBrowser extends ENM {
|
|
||||||
constructor(username, password, url) {
|
|
||||||
super(username, password, url)
|
|
||||||
this.objectUrl = '/persistentObject/'
|
|
||||||
this.alarmUrl = '/alarmcontroldisplayservice/alarmMonitoring/alarmoperations/'
|
|
||||||
|
|
||||||
this.currentPoId = 0
|
|
||||||
this.nextPoId = 1
|
|
||||||
this.childrens = null
|
|
||||||
this.poIds = []
|
|
||||||
this.isConfig = false
|
|
||||||
this.attributes = null
|
|
||||||
this.nextVariants = null
|
|
||||||
this.attributesData = null
|
|
||||||
this.attribute = null
|
|
||||||
this.networkDetails = null
|
|
||||||
this.configSet = []
|
|
||||||
this.includeNonPersistent = false
|
|
||||||
this.configCommands = ['commit', 'check', 'end', 'persistent', 'exit']
|
|
||||||
this.help = 'No results...'
|
|
||||||
}
|
|
||||||
|
|
||||||
async initialPrompt() {
|
|
||||||
return await initialPrompt.call(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
async next(input) {
|
|
||||||
return await this.nextVariants(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
async nextObjects(input) {
|
|
||||||
return await nextObjects.call(this, input)
|
|
||||||
}
|
|
||||||
|
|
||||||
async nextAttributes(input) {
|
|
||||||
return await nextAttributes.call(this, input)
|
|
||||||
}
|
|
||||||
|
|
||||||
setIdByCommand(command) {
|
|
||||||
return setIdByCommand.call(this, command)
|
|
||||||
}
|
|
||||||
|
|
||||||
async show(filter) {
|
|
||||||
await show.call(this, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
up() {
|
|
||||||
return up.call(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
async config(fdn) {
|
|
||||||
return await config.call(this, fdn)
|
|
||||||
}
|
|
||||||
|
|
||||||
end() {
|
|
||||||
end.call(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
setAttribute(attribute) {
|
|
||||||
return setAttribute.call(this, attribute)
|
|
||||||
}
|
|
||||||
|
|
||||||
description() {
|
|
||||||
description.call(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
get(fdn) {
|
|
||||||
get.call(this, fdn)
|
|
||||||
}
|
|
||||||
|
|
||||||
async set() {
|
|
||||||
await set.call(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
async commit(fdn) {
|
|
||||||
return await commit.call(this, fdn)
|
|
||||||
}
|
|
||||||
|
|
||||||
check(fdn) {
|
|
||||||
logAttributes(fdn, this.configSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
home() {
|
|
||||||
home.call(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fdn(fromFdn, targetFdn) {
|
|
||||||
return await fdn.call(this, fromFdn, targetFdn)
|
|
||||||
}
|
|
||||||
|
|
||||||
persistent() {
|
|
||||||
this.includeNonPersistent = !this.includeNonPersistent
|
|
||||||
console.log(`Include Non Persistent Atrributes Set to: ${this.includeNonPersistent}`.yellow)
|
|
||||||
}
|
|
||||||
|
|
||||||
async alarms(fdn) {
|
|
||||||
await alarms.call(this, fdn)
|
|
||||||
}
|
|
||||||
|
|
||||||
async sync(fdn) {
|
|
||||||
await sync.call(this, fdn)
|
|
||||||
}
|
|
||||||
|
|
||||||
async inputHandler() {
|
|
||||||
await inputHandler.call(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = TopologyBrowser
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
const colors = require('colors')
|
|
||||||
const logAttributes = require('../../util/logAttributes')
|
|
||||||
const requestWrapper = require('../../util/requestWrapper')
|
|
||||||
const logCommit = require('../../util/logCommit')
|
|
||||||
|
|
||||||
|
|
||||||
async function commit(fdn) {
|
|
||||||
logAttributes(fdn, this.configSet)
|
|
||||||
this.configSet.forEach(item => delete item.from)
|
|
||||||
const axiosConfig = {
|
|
||||||
method: 'put',
|
|
||||||
url: `${this.objectUrl}${this.currentPoId}`,
|
|
||||||
data: {
|
|
||||||
poId: this.currentPoId,
|
|
||||||
fdn,
|
|
||||||
attributes: this.configSet,
|
|
||||||
},
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const response = await requestWrapper(axiosConfig, 'Commiting Config...')
|
|
||||||
if (response.data) {
|
|
||||||
logCommit(response.data)
|
|
||||||
} else {
|
|
||||||
console.log('No data or response!'.red)
|
|
||||||
}
|
|
||||||
this.configSet.length = 0
|
|
||||||
this.end()
|
|
||||||
return fdn
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = commit
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
const colors = require('colors')
|
|
||||||
const logAttributeData = require('../../util/logAttributeData')
|
|
||||||
|
|
||||||
|
|
||||||
function description() {
|
|
||||||
const attributeData = this.attributesData.filter(item => item.key === this.attribute)[0]
|
|
||||||
if (attributeData) {
|
|
||||||
logAttributeData(attributeData)
|
|
||||||
if (attributeData.complexRef) {
|
|
||||||
console.log(`${attributeData.type.magenta}
|
|
||||||
${attributeData.complexRef.key.cyan}: ${attributeData.complexRef.description.grey}
|
|
||||||
`)
|
|
||||||
attributeData.complexRef.attributes.forEach(attr => logAttributeData(attr))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log('Attribute Not Found!'.yellow)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = description
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
const colors = require('colors')
|
|
||||||
const logAttributes = require('../../util/logAttributes')
|
|
||||||
const banner = require('../../util/banner')
|
|
||||||
|
|
||||||
|
|
||||||
function get(fdn) {
|
|
||||||
const syncStatus = this.networkDetails.filter(item => item.key === 'syncStatus')[0]
|
|
||||||
if (syncStatus && syncStatus.value === 'UNSYNCHRONIZED') {
|
|
||||||
console.log(`
|
|
||||||
❗ ${syncStatus.key}: ${syncStatus.value} ❗`.yellow)
|
|
||||||
}
|
|
||||||
const attribute = this.attributes.filter(item => item.key === this.attribute)[0]
|
|
||||||
const attributeData = this.attributesData.filter(item => item.key === this.attribute)[0]
|
|
||||||
logAttributes(fdn, [attribute])
|
|
||||||
console.log(` ${'Type: '.green + attributeData['type']} ${attributeData['defaultValue'] ? 'Default: '.yellow + attributeData['defaultValue'] : ''}
|
|
||||||
`)
|
|
||||||
if (attributeData.constraints && attributeData.constraints.orderingConstraint) banner(attributeData)
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = get
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
async function nextAttributes(input) {
|
|
||||||
const filter = input ? input : ''
|
|
||||||
let result = this.attributes.map(item => item.key).sort((a, b) => a > b ? 1 : -1)
|
|
||||||
.concat(this.configCommands)
|
|
||||||
.filter(item => item.toLowerCase().includes(filter.toLowerCase()))
|
|
||||||
if (result.includes(filter)) {
|
|
||||||
result = result.filter(item => item !== filter)
|
|
||||||
result.unshift(filter)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = nextAttributes
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
const requestWrapper = require('../../util/requestWrapper')
|
|
||||||
|
|
||||||
const otherCommands = ['show', 'config', 'up', 'home', 'fdn', 'persistent', 'alarms', 'sync', 'exit']
|
|
||||||
|
|
||||||
|
|
||||||
async function nextObjects(input){
|
|
||||||
const filter = input ? input : ''
|
|
||||||
if (this.currentPoId !== this.nextPoId || !this.childrens) {
|
|
||||||
this.currentPoId = this.nextPoId
|
|
||||||
this.poIds.push(this.currentPoId)
|
|
||||||
const axiosConfig = {
|
|
||||||
method: 'get',
|
|
||||||
url: `${this.objectUrl}network/${this.currentPoId}`
|
|
||||||
}
|
|
||||||
const response = await requestWrapper(axiosConfig)
|
|
||||||
if (response.data.treeNodes) {
|
|
||||||
this.childrens = response.data.treeNodes[0].childrens
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let result = this.childrens
|
|
||||||
.map(child => `${child.moType}=${child.moName}`)
|
|
||||||
.concat(otherCommands)
|
|
||||||
.filter(child => child.toLowerCase().includes(filter.toLowerCase()))
|
|
||||||
.concat(filter.startsWith('show') ? [filter] : [])
|
|
||||||
.concat(filter.startsWith('fdn') ? [filter] : [])
|
|
||||||
if (result.includes(filter)) {
|
|
||||||
result = result.filter(item => item !== filter)
|
|
||||||
result.unshift(filter)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = nextObjects
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
function setAttribute(attribute) {
|
|
||||||
if (!this.attributes) return false
|
|
||||||
if (!this.attributes.filter(item => item.key === attribute)[0]) return false
|
|
||||||
if (!this.attribute) {
|
|
||||||
this.configCommands.push('get')
|
|
||||||
this.configCommands.push('set')
|
|
||||||
this.configCommands.push('description')
|
|
||||||
}
|
|
||||||
this.attribute = attribute
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = setAttribute
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
const colors = require('colors')
|
|
||||||
|
|
||||||
const requestWrapper = require('../../util/requestWrapper')
|
|
||||||
|
|
||||||
|
|
||||||
async function sync(fdn) {
|
|
||||||
const meContextFind = fdn.match(/(NetworkElement|MeContext)=([\w-]+),?/)
|
|
||||||
if (!meContextFind) {
|
|
||||||
console.log('No sync object in FDN!'.yellow)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const actionUrl = `${this.objectUrl}v1/perform-mo-action/NetworkElement=${meContextFind[2]},CmFunction=1?actionName=sync`
|
|
||||||
const axiosConfig = {
|
|
||||||
method: 'post',
|
|
||||||
url: actionUrl,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
}
|
|
||||||
const response = await requestWrapper(axiosConfig, 'Initiate Node Sync...')
|
|
||||||
if (response.status === 200) {
|
|
||||||
console.log(`
|
|
||||||
${response.data.body.bold}
|
|
||||||
${response.data.title.green}
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = sync
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
const inquirer = require('inquirer')
|
|
||||||
const colors = require('colors')
|
|
||||||
|
|
||||||
const logError = require('../util/logError')
|
|
||||||
const { isEmpty } = require('../util/validation')
|
|
||||||
|
|
||||||
|
|
||||||
inquirer.registerPrompt('autocomplete', require('inquirer-autocomplete-prompt'))
|
|
||||||
|
|
||||||
|
|
||||||
function buildPrompt(fdn) {
|
|
||||||
if (fdn.length >= 67) {
|
|
||||||
return { prefix: '...', prompt: fdn.slice(-65) }
|
|
||||||
}
|
|
||||||
return { prefix: '', prompt: fdn }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function commndUp(tplg, fdn) {
|
|
||||||
if (tplg.up()) {
|
|
||||||
fdn = fdn.split(',').slice(0, -1).join(',')
|
|
||||||
} else {
|
|
||||||
console.log('There\'s no way up!'.yellow)
|
|
||||||
}
|
|
||||||
return fdn
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function commandOther(tplg, fdn, command) {
|
|
||||||
if (tplg.setIdByCommand(command)) {
|
|
||||||
fdn = `${fdn},${command}`
|
|
||||||
} else if (tplg.setAttribute(command)) {
|
|
||||||
fdn = fdn.replace(/\((\w+)\)/g, `(${command})`)
|
|
||||||
} else {
|
|
||||||
console.log('Command Unrecognized❗'.red)
|
|
||||||
}
|
|
||||||
return fdn
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async function handleCommand(tplg, fdn, command) {
|
|
||||||
const [cmd, param] = command.split(/\s+/)
|
|
||||||
switch (cmd) {
|
|
||||||
case 'exit':
|
|
||||||
return
|
|
||||||
case 'show':
|
|
||||||
await tplg.show(param ? param.trim() : '')
|
|
||||||
break
|
|
||||||
case 'config':
|
|
||||||
fdn = await tplg.config(fdn)
|
|
||||||
break
|
|
||||||
case 'set':
|
|
||||||
await tplg.set()
|
|
||||||
break
|
|
||||||
case 'commit':
|
|
||||||
fdn = await tplg.commit(fdn.replace(/\((\w+)\)/g, ''))
|
|
||||||
break
|
|
||||||
case 'up':
|
|
||||||
fdn = commndUp(tplg, fdn)
|
|
||||||
break
|
|
||||||
case 'get':
|
|
||||||
tplg.get(fdn)
|
|
||||||
break
|
|
||||||
case 'check':
|
|
||||||
tplg.check(fdn.replace(/\((\w+)\)/g, ''))
|
|
||||||
break
|
|
||||||
case 'end':
|
|
||||||
tplg.end()
|
|
||||||
fdn = fdn.replace(/\((\w+)\)/g, '')
|
|
||||||
break
|
|
||||||
case 'home':
|
|
||||||
tplg.home()
|
|
||||||
fdn = fdn.split(',', 1)[0]
|
|
||||||
break
|
|
||||||
case 'description':
|
|
||||||
tplg.description()
|
|
||||||
break
|
|
||||||
case 'persistent':
|
|
||||||
tplg.persistent()
|
|
||||||
break
|
|
||||||
case 'fdn':
|
|
||||||
fdn = await tplg.fdn(fdn, param ? param.trim() : '')
|
|
||||||
break
|
|
||||||
case 'alarms':
|
|
||||||
await tplg.alarms(fdn)
|
|
||||||
break
|
|
||||||
case 'sync':
|
|
||||||
await tplg.sync(fdn)
|
|
||||||
break
|
|
||||||
|
|
||||||
default:
|
|
||||||
fdn = commandOther(tplg, fdn, command)
|
|
||||||
}
|
|
||||||
return fdn
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async function inputHandlerLoop(tplg) {
|
|
||||||
let prompt = await tplg.initialPrompt()
|
|
||||||
let fdn = prompt
|
|
||||||
let prefix = ''
|
|
||||||
while (true) {
|
|
||||||
try {
|
|
||||||
const input = await inquirer.prompt([
|
|
||||||
{
|
|
||||||
type: 'autocomplete',
|
|
||||||
name: 'command',
|
|
||||||
message: tplg.isConfig ? prompt.blue.underline : prompt.blue,
|
|
||||||
pageSize: 10,
|
|
||||||
prefix: prefix.gray,
|
|
||||||
suffix: tplg.isConfig ? '#'.blue : '>'.blue,
|
|
||||||
validate: isEmpty,
|
|
||||||
source: async (answers, input) => await tplg.next(input),
|
|
||||||
emptyText: prvn.help,
|
|
||||||
}
|
|
||||||
])
|
|
||||||
fdn = await handleCommand(tplg, fdn, input.command)
|
|
||||||
if (!fdn) break
|
|
||||||
({ prefix, prompt } = buildPrompt(fdn))
|
|
||||||
} catch (error) {
|
|
||||||
logError(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async function inputHandler() {
|
|
||||||
try {
|
|
||||||
await inputHandlerLoop(this)
|
|
||||||
} catch (error) {
|
|
||||||
logError(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = inputHandler
|
|
||||||
0
package.json
Normal file → Executable file
0
package.json
Normal file → Executable file
11
util/banner.js
Executable file
11
util/banner.js
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
function banner(params) {
|
||||||
|
console.log(`
|
||||||
|
If you see this, pls, send me this message:
|
||||||
|
${JSON.stringify(params, null, 2)}
|
||||||
|
If you see this, pls, send me this message:
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = banner
|
||||||
2
util/createNext.js
Normal file → Executable file
2
util/createNext.js
Normal file → Executable file
@@ -6,10 +6,10 @@ function createNext(filter) {
|
|||||||
const commands = this.commands.filter(cmd => cmd.toLowerCase().includes(filter.toLowerCase()))
|
const commands = this.commands.filter(cmd => cmd.toLowerCase().includes(filter.toLowerCase()))
|
||||||
const choices = this.choices.filter(choice => choice.toLowerCase().includes(filter.toLowerCase()))
|
const choices = this.choices.filter(choice => choice.toLowerCase().includes(filter.toLowerCase()))
|
||||||
return [
|
return [
|
||||||
|
...choices,
|
||||||
separator,
|
separator,
|
||||||
...commands.map(cmd => `[${cmd}]`),
|
...commands.map(cmd => `[${cmd}]`),
|
||||||
separator,
|
separator,
|
||||||
...choices,
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
util/eventTimeToString.js
Executable file
10
util/eventTimeToString.js
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
|
||||||
|
function eventTimeToString(eventTime) {
|
||||||
|
if (!eventTime) return ''
|
||||||
|
return new Date(eventTime).toISOString().slice(0, -1).split('T').join(' ')
|
||||||
|
// return `${eventDateTime.toLocaleDateString()} ${eventDateTime.toLocaleTimeString()}`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = eventTimeToString
|
||||||
26
util/logAlarm.js
Executable file
26
util/logAlarm.js
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
const chalk = require('chalk')
|
||||||
|
const eventTimeToString = require('./eventTimeToString')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const timeValues = [
|
||||||
|
'eventTime',
|
||||||
|
'insertTime',
|
||||||
|
'ceaseTime',
|
||||||
|
'ackTime',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
function logAlarm(alarmList, eventPoId) {
|
||||||
|
const alarm = alarmList.filter(item => item.eventPoIdAsLong === eventPoId)[0]
|
||||||
|
timeValues.forEach(value => alarm[value] = eventTimeToString(alarm[value]))
|
||||||
|
console.log(
|
||||||
|
JSON.stringify(alarm, null, 2)
|
||||||
|
.replace(/["(){}\[\]]/mg, '')
|
||||||
|
.replace(/,$/mg, '')
|
||||||
|
.replace(/^(\s{2}\w+):/mg, chalk.green('$1:'))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = logAlarm
|
||||||
84
util/logAttributeData.js
Executable file
84
util/logAttributeData.js
Executable file
@@ -0,0 +1,84 @@
|
|||||||
|
const chalk = require('chalk')
|
||||||
|
|
||||||
|
|
||||||
|
function logDefaultValue(value) {
|
||||||
|
return value ? ` default: ${value}` : ''
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function logAttribute(key, attribute, output) {
|
||||||
|
let attrName = key.replace(/([A-Z])/g, ' $1')
|
||||||
|
if (attribute !== undefined && attribute !== '') {
|
||||||
|
output.push(`${chalk.blue(attrName.toLocaleUpperCase())}
|
||||||
|
${attribute}
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function logConstraints(constraints, output) {
|
||||||
|
output.push(`${chalk.blue(Object.keys({constraints}).pop().toLocaleUpperCase())}`)
|
||||||
|
if (constraints.valueRangeConstraints) {
|
||||||
|
constraints.valueRangeConstraints.forEach(item => {
|
||||||
|
output.push(` ${chalk.yellow('Range')}: ${item.minValue}..${item.maxValue}`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
['nullable', 'validContentRegex', 'valueResolution'].forEach(key => {
|
||||||
|
if (Object.keys(constraints).includes(key)) {
|
||||||
|
output.push(` ${chalk.yellow(key.replace(/([A-Z])/g, ' $1').replace(/^([a-z])/g, (l) => l.toUpperCase()))}: ${constraints[key]}`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function logEnumeration(enumeration, output) {
|
||||||
|
output.push(`${chalk.blue(Object.keys({enumeration}).pop().toLocaleUpperCase())}
|
||||||
|
${chalk.cyan(enumeration.key)}
|
||||||
|
${enumeration.description}`)
|
||||||
|
enumeration.enumMembers.forEach(item => output.push(` ${chalk.yellow(item.key)} (${item.value}): -- ${chalk.gray(item.description)}`))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function logList(listReference, output) {
|
||||||
|
output.push(`${chalk.blue(Object.keys({listReference}).pop().toLocaleUpperCase())}
|
||||||
|
${listReference.type}`)
|
||||||
|
if (listReference.constraints){
|
||||||
|
logConstraints(listReference.constraints, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function logAttributeData(attributeData) {
|
||||||
|
const attributeDataKeys = [
|
||||||
|
'key',
|
||||||
|
'type',
|
||||||
|
'defaultValue',
|
||||||
|
'description',
|
||||||
|
'trafficDisturbances',
|
||||||
|
'unit',
|
||||||
|
'multiplicationFactor',
|
||||||
|
'immutable',
|
||||||
|
'precondition',
|
||||||
|
'dependencies',
|
||||||
|
'sideEffects',
|
||||||
|
'activeChoiceCase',
|
||||||
|
]
|
||||||
|
|
||||||
|
const output = [`
|
||||||
|
${chalk.yellow.bold(attributeData['key'])}: ${chalk.green(attributeData['type'])} ${logDefaultValue(attributeData['defaultValue'])}
|
||||||
|
`]
|
||||||
|
attributeDataKeys.slice(3).forEach((key) => logAttribute(key, attributeData[key], output))
|
||||||
|
if (attributeData.constraints) {
|
||||||
|
logConstraints(attributeData.constraints, output)
|
||||||
|
}
|
||||||
|
if (attributeData.enumeration) {
|
||||||
|
logEnumeration(attributeData.enumeration, output)
|
||||||
|
}
|
||||||
|
if (attributeData.listReference) {
|
||||||
|
logList(attributeData.listReference, output)
|
||||||
|
}
|
||||||
|
console.log(output.join('\n') + '\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = logAttributeData
|
||||||
34
util/logAttributes.js
Executable file
34
util/logAttributes.js
Executable file
@@ -0,0 +1,34 @@
|
|||||||
|
const chalk = require('chalk')
|
||||||
|
|
||||||
|
|
||||||
|
function transformAttributes(element) {
|
||||||
|
if (Array.isArray(element)) {
|
||||||
|
return element.map(item => transformAttributes(item))
|
||||||
|
}
|
||||||
|
if (Array.isArray(element.value)) {
|
||||||
|
return { [element.key]: transformAttributes(element.value) }
|
||||||
|
}
|
||||||
|
return element.key ? { [element.key]: element.value } : element
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function colorize(attributes) {
|
||||||
|
const sorted = attributes.sort ? attributes.sort((a, b) => a.key < b.key ? -1 : 1) : attributes
|
||||||
|
return JSON.stringify(transformAttributes(sorted), null, 1)
|
||||||
|
.replace(/["(){}\[\]]/mg, '')
|
||||||
|
.replace(/^\s*,*\n/mg, '')
|
||||||
|
.replace(/,$/mg, '')
|
||||||
|
.replace(/^(\s{2}\w+):/mg, chalk.green('$1:'))
|
||||||
|
.replace(/^(\s{4}\w+):/mg, chalk.yellow('$1:'))
|
||||||
|
.replace(/^(\s{5}\w+):/mg, chalk.cyan('$1:'))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function logAttributes(fdn, attributes) {
|
||||||
|
const output = `
|
||||||
|
${chalk.yellow.bold('FDN')}: ${chalk.bold(fdn)}
|
||||||
|
${colorize(attributes)}`
|
||||||
|
console.log(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = logAttributes
|
||||||
10
util/logCommit.js
Executable file
10
util/logCommit.js
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
const chalk = require('chalk')
|
||||||
|
|
||||||
|
|
||||||
|
function logCommit(commitResult) {
|
||||||
|
if (commitResult.title === 'Success') {
|
||||||
|
console.log(chalk.green(commitResult.title))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = logCommit
|
||||||
11
util/logDetails.js
Executable file
11
util/logDetails.js
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
const chalk = require('chalk')
|
||||||
|
|
||||||
|
|
||||||
|
function logDetails(networkDetails) {
|
||||||
|
const output = networkDetails.map(details => ` ${chalk.gray(details.key)}: ${details.value === 'UNSYNCHRONIZED' ? '⌛ ' + chalk.yellow(details.value): chalk.gray(details.value)}`)
|
||||||
|
console.log(`
|
||||||
|
${output.join('\n')}
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = logDetails
|
||||||
50
util/logError.js
Normal file → Executable file
50
util/logError.js
Normal file → Executable file
@@ -1,17 +1,8 @@
|
|||||||
const chalk = require('chalk')
|
const chalk = require('chalk')
|
||||||
|
|
||||||
function logError(err) {
|
function logError(err) {
|
||||||
if (err.response && err.response.data && err.response.data.errorTitle) {
|
try {
|
||||||
const {
|
if (!err.response) {
|
||||||
errorTitle = 'Error',
|
|
||||||
errorBody = 'No error body',
|
|
||||||
errorDetails = null
|
|
||||||
} = err.response.data
|
|
||||||
console.log(`
|
|
||||||
⚠️ ${chalk.bold.bgRed(errorTitle)}
|
|
||||||
${chalk.yellow(errorBody || '')}${errorDetails ? '\n' + errorDetails.toString() : ''}
|
|
||||||
`)
|
|
||||||
} else {
|
|
||||||
const {
|
const {
|
||||||
name = 'Error',
|
name = 'Error',
|
||||||
message = 'No error message',
|
message = 'No error message',
|
||||||
@@ -19,9 +10,42 @@ function logError(err) {
|
|||||||
} = err
|
} = err
|
||||||
console.log(`
|
console.log(`
|
||||||
⛔ ${chalk.bold.bgRed(name)}
|
⛔ ${chalk.bold.bgRed(name)}
|
||||||
${chalk.yellow(message)}
|
${chalk.yellow(message)}${chalk.dim(stack && process.env.NODE_ENV === 'development' ? '\n' + stack : '')}
|
||||||
${chalk.dim(stack && process.env.NODE_ENV === 'development' ? stack : '')}
|
|
||||||
`)
|
`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (err.response.data) {
|
||||||
|
const { data } = err.response
|
||||||
|
// other http error
|
||||||
|
let errorTitle = `${err.response.status}: ${err.response.statusText}`
|
||||||
|
let errorBody = data.code
|
||||||
|
let errorDetails = data.message
|
||||||
|
if (typeof data !== 'object') {
|
||||||
|
errorBody = data
|
||||||
|
}
|
||||||
|
if (data.errorCode) {
|
||||||
|
errorBody = `${data.errorCode}: ${data.userMessage.title}`
|
||||||
|
errorDetails = data.userMessage.body
|
||||||
|
}
|
||||||
|
// prvn error
|
||||||
|
if (data.errorTitle) {
|
||||||
|
errorTitle = data.errorTitle
|
||||||
|
errorBody = data.errorBody
|
||||||
|
errorDetails = data.errorDetails
|
||||||
|
}
|
||||||
|
// tplg error
|
||||||
|
if (data.title) {
|
||||||
|
errorTitle = `${data.errorCode}: ${data.title}`
|
||||||
|
errorBody = data.body
|
||||||
|
errorDetails = data.detail
|
||||||
|
}
|
||||||
|
console.log(`
|
||||||
|
⚠️ ${chalk.bold.bgRed(errorTitle)}
|
||||||
|
${chalk.yellow(errorBody)}${errorDetails ? '\n' + errorDetails.toString() : ''}
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
6
util/logNode.js
Normal file → Executable file
6
util/logNode.js
Normal file → Executable file
@@ -3,7 +3,7 @@ const chalk = require('chalk')
|
|||||||
|
|
||||||
function logNodeStatus(statusEntries, indent = 4) {
|
function logNodeStatus(statusEntries, indent = 4) {
|
||||||
if (!statusEntries) {
|
if (!statusEntries) {
|
||||||
throw new Error('No node status entries!')
|
throw new Error('No node status entries❗')
|
||||||
}
|
}
|
||||||
console.log('')
|
console.log('')
|
||||||
statusEntries.forEach(entry => {
|
statusEntries.forEach(entry => {
|
||||||
@@ -21,7 +21,7 @@ function logNodeStatus(statusEntries, indent = 4) {
|
|||||||
|
|
||||||
function logNodeProperties(attributes, attributeGroups, indent = 4) {
|
function logNodeProperties(attributes, attributeGroups, indent = 4) {
|
||||||
if (!attributeGroups) {
|
if (!attributeGroups) {
|
||||||
throw new Error('No node attribute groups!')
|
throw new Error('No node attribute groups❗')
|
||||||
}
|
}
|
||||||
console.log('')
|
console.log('')
|
||||||
logAttributes(attributes)
|
logAttributes(attributes)
|
||||||
@@ -37,7 +37,7 @@ function logNodeProperties(attributes, attributeGroups, indent = 4) {
|
|||||||
|
|
||||||
function logAttributes(attributes, indent = 4) {
|
function logAttributes(attributes, indent = 4) {
|
||||||
if (!attributes) {
|
if (!attributes) {
|
||||||
throw new Error('No node attributes!')
|
throw new Error('No node attributes❗')
|
||||||
}
|
}
|
||||||
attributes.forEach(attribute => {
|
attributes.forEach(attribute => {
|
||||||
const { name, value } = attribute
|
const { name, value } = attribute
|
||||||
|
|||||||
0
util/logProject.js
Normal file → Executable file
0
util/logProject.js
Normal file → Executable file
55
util/validation.js
Normal file → Executable file
55
util/validation.js
Normal file → Executable file
@@ -6,5 +6,58 @@ const isEmpty = input => (input === '' ? chalk.bgRed('Empty Inputs not Allowed')
|
|||||||
const isValidHardwareId = input => (input.match(/[A-HJ-NP-Z0-9]{13}/) ? true : chalk.bgRed(`The Ericsson Hardware Serial Number frame consists of 13 alphanumeric characters.
|
const isValidHardwareId = input => (input.match(/[A-HJ-NP-Z0-9]{13}/) ? true : chalk.bgRed(`The Ericsson Hardware Serial Number frame consists of 13 alphanumeric characters.
|
||||||
Character set is the letters A-Z with the exception of O and I, and digits 0-9.`))
|
Character set is the letters A-Z with the exception of O and I, and digits 0-9.`))
|
||||||
|
|
||||||
|
const isValidNumber = (input, constraints) => {
|
||||||
|
if (constraints) {
|
||||||
|
const test = input ? input : ''
|
||||||
|
if (!constraints.nullable && test === 'null') return chalk.red('Value Can\'t Be a null')
|
||||||
|
if (constraints.nullable && test === 'null') return true
|
||||||
|
if (!test.toString().match(/-?[0-9]+/)) return chalk.red('Input Is Not a Number')
|
||||||
|
const checkResult = checkValueRangeConstraints(+test, constraints)
|
||||||
|
if (checkResult) return checkResult
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = { isEmpty, isValidHardwareId }
|
const isValidString = (input, constraints) => {
|
||||||
|
if (constraints) {
|
||||||
|
const test = input ? input : ''
|
||||||
|
if (!constraints.nullable && test === 'null') return chalk.red('Value Can\'t Be a null')
|
||||||
|
if (constraints.nullable && test === 'null') return true
|
||||||
|
if (constraints.validContentRegex && !test.match(constraints.validContentRegex)) return chalk.red('Input Doesn\'t Match RegEx')
|
||||||
|
const checkResult = checkValueRangeConstraints(test.length, constraints)
|
||||||
|
if (checkResult) return checkResult
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkValueRangeConstraints = (value, constraints) => {
|
||||||
|
let min
|
||||||
|
let max
|
||||||
|
if (constraints.valueRangeConstraints) {
|
||||||
|
const inRange = constraints.valueRangeConstraints.some(item => {
|
||||||
|
min = item.minValue
|
||||||
|
max = item.maxValue
|
||||||
|
return min <= value && max >= value
|
||||||
|
})
|
||||||
|
errStrArr = constraints.valueRangeConstraints.map(item => `${item.minValue}..${item.maxValue}`)
|
||||||
|
if (!inRange) return chalk.red(`Input is Outside Allowed Range: ${errStrArr.join(', ')}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const isValidNodeName = (input) => {
|
||||||
|
if (input.match('[a-zA-Z0-9-_.\\/:$]+') || input === '') {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return chalk.red('Node Name is Invalid')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
isEmpty,
|
||||||
|
isValidHardwareId,
|
||||||
|
isValidNumber,
|
||||||
|
isValidString,
|
||||||
|
checkValueRangeConstraints,
|
||||||
|
isValidNodeName,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user