n8n-nodes-netdevices
Version:
n8n node to interact with network devices
325 lines • 11.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.JuniperConnection = void 0;
const base_connection_1 = require("../base-connection");
class JuniperConnection extends base_connection_1.BaseConnection {
constructor(credentials) {
super(credentials);
this.inCliMode = false;
this.inConfigMode = false;
this.inShellMode = false;
}
async sessionPreparation() {
await this.createJuniperShellChannel();
if (this.fastMode) {
await this.setBasePrompt();
}
else {
await this.enterCliMode();
await Promise.all([
this.setTerminalWidth(),
this.disablePaging(),
]);
await this.setBasePrompt();
}
}
async createJuniperShellChannel() {
return new Promise((resolve, reject) => {
this.client.shell((err, channel) => {
if (err) {
reject(err);
return;
}
this.currentChannel = channel;
this.currentChannel.setEncoding(this.encoding);
const waitTime = this.fastMode ? 200 : 500;
setTimeout(() => {
resolve();
}, waitTime);
});
});
}
async enterCliMode() {
await this.writeChannel(this.returnChar);
let output = await this.readChannel(3000);
const mode = this.determineMode(output);
if (mode === 'shell') {
this.inShellMode = true;
this.inCliMode = false;
await this.writeChannel('cli' + this.newline);
output = await this.readChannel(3000);
if (output.includes('>') || output.includes('#')) {
this.inCliMode = true;
this.inShellMode = false;
}
}
else if (mode === 'cli') {
this.inCliMode = true;
this.inShellMode = false;
}
}
determineMode(data) {
if (data.match(/root@/) || data.match(/%/) || data.match(/\$/)) {
return 'shell';
}
if (data.includes('>') || data.includes('#')) {
return 'cli';
}
return 'cli';
}
async setTerminalWidth() {
try {
await this.writeChannel('set cli screen-width 511' + this.newline);
const output = await this.readChannel(2000);
if (!output.includes('Screen width set to')) {
await this.writeChannel('set cli screen-width 511' + this.newline);
await this.readChannel(2000);
}
}
catch (error) {
}
}
async disablePaging() {
try {
await this.writeChannel('set cli complete-on-space off' + this.newline);
await this.readChannel(2000);
await this.writeChannel('set cli screen-length 0' + this.newline);
await this.readChannel(2000);
}
catch (error) {
}
}
async setBasePrompt() {
await this.writeChannel(this.returnChar);
const output = await this.readChannel(3000);
const lines = output.trim().split('\n');
const lastLine = lines[lines.length - 1];
this.basePrompt = lastLine.replace(/[>#$%]\s*$/, '').trim();
this.enabledPrompt = this.basePrompt + '#';
this.configPrompt = this.basePrompt + '#';
}
async enterConfigMode() {
if (!this.inCliMode) {
await this.enterCliMode();
}
try {
await this.writeChannel('configure' + this.newline);
const output = await this.readChannel(3000);
if (output.includes('Entering configuration mode') || output.includes('[edit]')) {
this.inConfigMode = true;
}
else {
throw new Error('Failed to enter configuration mode');
}
}
catch (error) {
throw new Error(`Failed to enter configuration mode: ${error}`);
}
}
async exitConfigMode() {
if (!this.inConfigMode) {
return;
}
try {
await this.writeChannel('exit configuration-mode' + this.newline);
let output = await this.readChannel(3000);
if (output.includes('Exit with uncommitted changes')) {
await this.writeChannel('yes' + this.newline);
output = await this.readChannel(3000);
}
if (output.includes('>') && !output.includes('[edit]')) {
this.inConfigMode = false;
}
else {
throw new Error('Failed to exit configuration mode');
}
}
catch (error) {
throw new Error(`Failed to exit configuration mode: ${error}`);
}
}
async sendCommand(command) {
try {
if (!this.isConnected || !this.currentChannel) {
throw new Error('Not connected to device');
}
if (!this.fastMode) {
if (!this.inCliMode) {
await this.enterCliMode();
}
}
await this.writeChannel(command + this.newline);
const timeout = this.fastMode ? 5000 : 10000;
const output = await this.readUntilPrompt(undefined, timeout);
const cleanOutput = this.sanitizeOutput(output, command);
return {
command,
output: cleanOutput,
success: true
};
}
catch (error) {
return {
command,
output: '',
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
async sendConfig(configCommands) {
try {
if (!this.isConnected || !this.currentChannel) {
throw new Error('Not connected to device');
}
await this.enterConfigMode();
let allOutput = '';
for (const command of configCommands) {
await this.writeChannel(command + this.newline);
const output = await this.readChannel(3000);
allOutput += output;
if (output.includes('error:') || output.includes('syntax error')) {
throw new Error(`Configuration error on command "${command}": ${output}`);
}
}
await this.commitConfig();
await this.exitConfigMode();
const cleanOutput = this.sanitizeOutput(allOutput, configCommands.join('; '));
return {
command: configCommands.join('; '),
output: cleanOutput,
success: true
};
}
catch (error) {
if (this.inConfigMode) {
try {
await this.exitConfigMode();
}
catch (exitError) {
}
}
return {
command: configCommands.join('; '),
output: '',
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
async commitConfig(comment) {
try {
if (!this.inConfigMode) {
throw new Error('Not in configuration mode');
}
let commitCommand = 'commit';
if (comment) {
commitCommand += ` comment "${comment}"`;
}
await this.writeChannel(commitCommand + this.newline);
const output = await this.readChannel(10000);
if (output.includes('commit complete')) {
return {
command: commitCommand,
output: output,
success: true
};
}
else {
throw new Error('Commit failed');
}
}
catch (error) {
return {
command: 'commit',
output: '',
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
async getCurrentConfig() {
return await this.sendCommand('show configuration');
}
async saveConfig() {
return await this.sendCommand('show configuration | display set');
}
async rebootDevice() {
try {
await this.writeChannel('request system reboot' + this.newline);
let output = await this.readChannel(5000);
if (output.includes('Reboot the system?') || output.includes('[yes,no]')) {
await this.writeChannel('yes' + this.newline);
output += await this.readChannel(5000);
}
return {
command: 'request system reboot',
output: output,
success: true
};
}
catch (error) {
return {
command: 'request system reboot',
output: '',
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
sanitizeOutput(output, command) {
const escapedCommand = command.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
let cleanOutput = output.replace(new RegExp(escapedCommand, 'g'), '');
const escapedBasePrompt = this.basePrompt.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
cleanOutput = cleanOutput.replace(new RegExp(escapedBasePrompt + '[>#$%]', 'g'), '');
cleanOutput = cleanOutput.replace(/\[edit\]/g, '');
cleanOutput = cleanOutput.replace(/Entering configuration mode/g, '');
cleanOutput = cleanOutput.replace(/Exiting configuration mode/g, '');
cleanOutput = cleanOutput.replace(/commit complete/g, '');
cleanOutput = cleanOutput.replace(/Screen width set to \d+/g, '');
cleanOutput = cleanOutput.replace(/Disabling complete-on-space/g, '');
cleanOutput = cleanOutput.replace(/Screen length set to \d+/g, '');
cleanOutput = cleanOutput.replace(/^\s+|\s+$/g, '');
cleanOutput = cleanOutput.replace(/\r\n/g, '\n');
cleanOutput = cleanOutput.replace(/\r/g, '\n');
cleanOutput = cleanOutput.replace(/\n\s*\n/g, '\n');
return cleanOutput;
}
isInCliMode() {
return this.inCliMode;
}
isInConfigMode() {
return this.inConfigMode;
}
isInShellMode() {
return this.inShellMode;
}
async enterShellMode() {
if (this.inShellMode) {
return;
}
if (this.inCliMode) {
await this.writeChannel('start shell' + this.newline);
const output = await this.readChannel(3000);
if (output.includes('$') || output.includes('%')) {
this.inShellMode = true;
this.inCliMode = false;
}
}
}
async returnToCliMode() {
if (this.inCliMode) {
return;
}
if (this.inShellMode) {
await this.writeChannel('exit' + this.newline);
const output = await this.readChannel(3000);
if (output.includes('>') || output.includes('#')) {
this.inCliMode = true;
this.inShellMode = false;
}
}
}
}
exports.JuniperConnection = JuniperConnection;
//# sourceMappingURL=juniper-connection.js.map