diff --git a/app/functions/utils.py b/app/functions/utils.py index 88ac041..ce58b7e 100644 --- a/app/functions/utils.py +++ b/app/functions/utils.py @@ -1,9 +1,10 @@ -import os, yaml, logging +import os, yaml, logging, requests from functools import wraps from netmiko import ConnectHandler, NetmikoTimeoutException, NetmikoAuthenticationException logger = logging.getLogger(__name__) + # Exception handler def exception_handler(func): @wraps(func) @@ -15,8 +16,10 @@ def exception_handler(func): return "An error occurred", 500 return wrapper + +# Load YAML configuration file @exception_handler -def load_yaml(filename): +def load_yaml(filename, key=None): if not filename.endswith('.yaml'): filename = f"{filename}.yaml" @@ -32,7 +35,13 @@ def load_yaml(filename): if data is None: logger.warning(f"Empty configuration file: {filename}") return {} + + # Return specific key if provided + if key: + return data.get(key, None) + return data + except yaml.YAMLError as e: logger.error(f"YAML parsing error in {filename}: {e}") return {} @@ -41,6 +50,21 @@ def load_yaml(filename): return {} +# Send data to a webhook URL +@exception_handler +def send_webhook(webhook_url, text_data): + headers = { + 'Content-Type': 'application/json' + } + payload = { + "text": text_data + } + + response = requests.post(webhook_url, json=payload, headers=headers) + response.raise_for_status() + + +# Establish connection to network device def establish_connection(device_config): try: return ConnectHandler(**device_config) @@ -48,6 +72,8 @@ def establish_connection(device_config): logger.error(f"Failed to establish connection to {device_config['host']}: {e}") raise + +# Execute command on network device def execute_command(device, command_format, target, ip_version): device_config = { 'device_type': device['type'], diff --git a/app/requirements.txt b/app/requirements.txt index 9e77704..e4d4d67 100644 --- a/app/requirements.txt +++ b/app/requirements.txt @@ -3,3 +3,4 @@ pyyaml==6.0.2 netmiko==4.5.0 werkzeug==3.1.3 gunicorn==23.0.0 +requests==2.32.3 \ No newline at end of file diff --git a/app/static/js/main.js b/app/static/js/main.js index 687fa40..b48dfdc 100644 --- a/app/static/js/main.js +++ b/app/static/js/main.js @@ -8,8 +8,9 @@ const app = Vue.createApp({ selectedIpVersion: 'IPv4', isLoading: false, commandResult: '', - devices: window.initialData?.devices ?? [], - commands: window.initialData?.commands ?? [], + devices: window.initialData?.devices ?? {}, + commands: window.initialData?.commands ?? {}, + currentDevice: null, currentCommand: null, showHelp: false, showTerms: false, @@ -23,15 +24,31 @@ const app = Vue.createApp({ }, watch: { + selectedDevice: { + handler(newVal) { + this.currentDevice = this.devices[newVal] || null; + if (!newVal) { + this.resetCommandState(); + } + }, + immediate: true + }, selectedCommand: { handler(newVal) { - this.currentCommand = this.commands.find(cmd => cmd.id === newVal); + this.currentCommand = this.commands[newVal] || null; }, immediate: true } }, computed: { + devicesList() { + return Object.entries(this.devices).map(([key, device]) => ({ + key, + ...device + })); + }, + showIpVersionSelector() { if (!this.targetIp) return true; @@ -82,15 +99,8 @@ const app = Vue.createApp({ document.documentElement.classList[this.isDark ? 'add' : 'remove']('dark'); }, - toggleDevice(device) { - const wasDeselected = this.selectedDevice === device; - this.selectedDevice = wasDeselected ? '' : device; - - if (wasDeselected) { - this.resetCommandState(); - } - - this.$nextTick(() => this.$forceUpdate()); + toggleDevice(deviceKey) { + this.selectedDevice = this.selectedDevice === deviceKey ? '' : deviceKey; }, resetCommandState() { diff --git a/app/templates/index.html b/app/templates/index.html index 5d798fe..cb8f2c1 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -6,11 +6,11 @@