From 847e55098b2fc3e0d91fcf771653c9ac53f6814c Mon Sep 17 00:00:00 2001 From: thatmattlove Date: Wed, 20 Mar 2024 00:57:11 -0400 Subject: [PATCH] update docs & examples --- .samples/Caddyfile | 14 + .samples/hyperglass-docker.service | 15 ++ .samples/hyperglass-manual.service | 13 + .samples/hyperglass.nginx | 49 ++++ .samples/sample_devices.yaml | 7 + docs/pages/configuration.mdx | 48 +++- docs/pages/configuration/_meta.json | 4 +- .../configuration/{reference => }/config.mdx | 0 .../{reference => }/config/_meta.json | 0 .../{reference => }/config/logging.mdx | 0 .../{reference => }/config/web-ui.mdx | 0 .../configuration/{reference => }/devices.mdx | 0 .../{reference => }/directives.mdx | 0 .../examples/basic-configuration.mdx | 21 +- docs/pages/configuration/reference/_meta.json | 5 - docs/pages/installation.mdx | 58 ++++ docs/pages/installation/_meta.json | 6 + docs/pages/installation/docker.mdx | 54 ++++ .../installation/environment-variables.mdx | 22 ++ docs/pages/installation/manual.mdx | 60 +++++ docs/pages/installation/reverse-proxy.mdx | 42 +++ docs/pages/platforms.mdx | 89 +++--- docs/platforms.json | 2 +- docs/theme.config.tsx | 253 +++++++++--------- hyperglass/defaults/directives/arista_eos.py | 19 +- hyperglass/defaults/directives/bird.py | 13 +- hyperglass/defaults/directives/cisco_ios.py | 13 +- hyperglass/defaults/directives/cisco_nxos.py | 13 +- hyperglass/defaults/directives/cisco_xr.py | 13 +- hyperglass/defaults/directives/frr.py | 13 +- hyperglass/defaults/directives/huawei.py | 13 +- hyperglass/defaults/directives/juniper.py | 19 +- hyperglass/defaults/directives/mikrotik.py | 13 +- hyperglass/defaults/directives/nokia_sros.py | 13 +- hyperglass/defaults/directives/openbgpd.py | 13 +- hyperglass/defaults/directives/tnsr.py | 13 +- hyperglass/defaults/directives/vyos.py | 13 +- hyperglass/util/docs.py | 57 +++- 38 files changed, 744 insertions(+), 256 deletions(-) create mode 100644 .samples/Caddyfile create mode 100644 .samples/hyperglass-docker.service create mode 100644 .samples/hyperglass-manual.service create mode 100644 .samples/hyperglass.nginx create mode 100644 .samples/sample_devices.yaml rename docs/pages/configuration/{reference => }/config.mdx (100%) rename docs/pages/configuration/{reference => }/config/_meta.json (100%) rename docs/pages/configuration/{reference => }/config/logging.mdx (100%) rename docs/pages/configuration/{reference => }/config/web-ui.mdx (100%) rename docs/pages/configuration/{reference => }/devices.mdx (100%) rename docs/pages/configuration/{reference => }/directives.mdx (100%) delete mode 100644 docs/pages/configuration/reference/_meta.json create mode 100644 docs/pages/installation/_meta.json create mode 100644 docs/pages/installation/docker.mdx create mode 100644 docs/pages/installation/environment-variables.mdx create mode 100644 docs/pages/installation/manual.mdx create mode 100644 docs/pages/installation/reverse-proxy.mdx diff --git a/.samples/Caddyfile b/.samples/Caddyfile new file mode 100644 index 00000000..2d75ebe5 --- /dev/null +++ b/.samples/Caddyfile @@ -0,0 +1,14 @@ +lg.example.com:443 { + tls person@example.com + file_server { + root /etc/hyperglass/static/ui + index /etc/hyperglass/static/ui/index.html + } + file_server /custom { + root /etc/hyperglass/static/custom + } + file_server /images { + root /etc/hyperglass/static/images + } + reverse_proxy localhost:8001 +} \ No newline at end of file diff --git a/.samples/hyperglass-docker.service b/.samples/hyperglass-docker.service new file mode 100644 index 00000000..3e8385a7 --- /dev/null +++ b/.samples/hyperglass-docker.service @@ -0,0 +1,15 @@ +[Unit] +Description=hyperglass +PartOf=docker.service +After=docker.service + +[Service] +Type=oneshot +RemainAfterExit=true +WorkingDirectory=/opt/hyperglass +EnvironmentFile=/etc/hyperglass/hyperglass.env +ExecStart=/usr/bin/docker compose up -d --remove-orphans +ExecStop=/usr/bin/docker compose down + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/.samples/hyperglass-manual.service b/.samples/hyperglass-manual.service new file mode 100644 index 00000000..7fa04dff --- /dev/null +++ b/.samples/hyperglass-manual.service @@ -0,0 +1,13 @@ +[Unit] +Description=hyperglass +After=network.target +Requires=redis-server + +[Service] +User=root +Group=root +EnvironmentFile=/etc/hyperglass/hyperglass.env +ExecStart=python3 -m hyperglass.console start + +[Install] +WantedBy=multi-user.target diff --git a/.samples/hyperglass.nginx b/.samples/hyperglass.nginx new file mode 100644 index 00000000..2fd3abd4 --- /dev/null +++ b/.samples/hyperglass.nginx @@ -0,0 +1,49 @@ +server { + listen 80; + listen [::]:80; + server_name lg.example.com; + return 301 https://$host$request_uri; +} +server { + listen [::]:443 ssl ipv6only=on; + listen 443 ssl; + ssl_certificate + ssl_certificate_key + + client_max_body_size 2M; + + server_name lg.example.com; + + root /etc/hyperglass/static; + + location / { + try_files $uri $uri/ /ui /ui/$uri =404; + index /ui/index.html; + } + + location /openapi.json { + try_files $uri @proxy_to_app; + } + + location /custom/ { + try_files $uri $uri/ /custom; + } + + location /images/ { + try_files $uri $uri/ /images; + } + + location /api { + try_files $uri @proxy_to_app; + } + + location @proxy_to_app { + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_redirect off; + proxy_pass http://[::1]:8001; + } + +} \ No newline at end of file diff --git a/.samples/sample_devices.yaml b/.samples/sample_devices.yaml new file mode 100644 index 00000000..5fe03c71 --- /dev/null +++ b/.samples/sample_devices.yaml @@ -0,0 +1,7 @@ +devices: + - name: Example Device + address: 127.0.0.1 + credential: + username: test + password: test + platform: juniper diff --git a/docs/pages/configuration.mdx b/docs/pages/configuration.mdx index 09d83bfd..58b95fc0 100644 --- a/docs/pages/configuration.mdx +++ b/docs/pages/configuration.mdx @@ -1,4 +1,24 @@ -import { Callout } from 'nextra-theme-docs'; +import { Code, Table, Td, Th, Tr } from "nextra/components"; +import { Callout } from "nextra-theme-docs"; +import platforms from "~/platforms.json"; +import { Supported } from "./platforms.mdx"; + +export const Platforms = () => ( +
    + {platforms.reduce((final, platform) => { + if (platform.native) { + const element = ( +
  • + + {platform.name} +
  • + ); + final = [...final, element]; + } + return final; + }, [])} +
+); Once you've gotten started with a basic configuration, you'll probably want to customize the look and feel of hyperglass by changing the logo or color scheme. Fortunately, there are _a lot_ ways to customize hyperglass. @@ -8,12 +28,12 @@ Once you've gotten started with a basic configuration, you'll probably want to c | :----------- | :------------------------------------------------------------------------- | | `config` | Application-wide configuration such as logging, web UI customization, etc. | | `devices` | Your devices and their associated configurations. | -| `directives` | Custom [directives](/configuration/directives-file-reference) (commands). | +| `directives` | Custom [directives](configuration/directives.mdx) (commands). | - **File Extensions**
- All the examples in the docs are provided in [YAML](https://yaml.org/) format, but [TOML](https://toml.io/), - JSON, and Python files are also supported. + **File Extensions**
+ All the examples in the docs are provided in [YAML](https://yaml.org/) format, but [TOML](https://toml.io/), + JSON, and Python files are also supported.
### Using a Python File @@ -55,3 +75,21 @@ main = { } } ``` + +## Built-in Directives + +hyperglass ships with predefined [directives](configuration/directives.mdx) for the following [platforms](platforms.mdx): + + + +All built in directives require that the following `attrs` be defined on each device using the directive: + +| Attribute | Value | +| :-------- | :-------------------------------------------------------- | +| `source4` | IPv4 address used to source Ping and Traceroute commands. | +| `source6` | IPv6 address used to source Ping and Traceroute commands. | + + + If you do not utilize IPv6 in your network, you'll need to create your own directive that only + has IPv4 commands. + diff --git a/docs/pages/configuration/_meta.json b/docs/pages/configuration/_meta.json index 3c9a1663..502e5131 100644 --- a/docs/pages/configuration/_meta.json +++ b/docs/pages/configuration/_meta.json @@ -1,4 +1,6 @@ { - "reference": "Reference", + "config": "Config File", + "devices": "Devices File", + "directives": "Directives File", "examples": "Examples" } diff --git a/docs/pages/configuration/reference/config.mdx b/docs/pages/configuration/config.mdx similarity index 100% rename from docs/pages/configuration/reference/config.mdx rename to docs/pages/configuration/config.mdx diff --git a/docs/pages/configuration/reference/config/_meta.json b/docs/pages/configuration/config/_meta.json similarity index 100% rename from docs/pages/configuration/reference/config/_meta.json rename to docs/pages/configuration/config/_meta.json diff --git a/docs/pages/configuration/reference/config/logging.mdx b/docs/pages/configuration/config/logging.mdx similarity index 100% rename from docs/pages/configuration/reference/config/logging.mdx rename to docs/pages/configuration/config/logging.mdx diff --git a/docs/pages/configuration/reference/config/web-ui.mdx b/docs/pages/configuration/config/web-ui.mdx similarity index 100% rename from docs/pages/configuration/reference/config/web-ui.mdx rename to docs/pages/configuration/config/web-ui.mdx diff --git a/docs/pages/configuration/reference/devices.mdx b/docs/pages/configuration/devices.mdx similarity index 100% rename from docs/pages/configuration/reference/devices.mdx rename to docs/pages/configuration/devices.mdx diff --git a/docs/pages/configuration/reference/directives.mdx b/docs/pages/configuration/directives.mdx similarity index 100% rename from docs/pages/configuration/reference/directives.mdx rename to docs/pages/configuration/directives.mdx diff --git a/docs/pages/configuration/examples/basic-configuration.mdx b/docs/pages/configuration/examples/basic-configuration.mdx index f2bc724e..a1913761 100644 --- a/docs/pages/configuration/examples/basic-configuration.mdx +++ b/docs/pages/configuration/examples/basic-configuration.mdx @@ -3,13 +3,13 @@ title: Basic Configuration description: Get started with a basic hyperglass configuration --- -import { Callout } from 'nextra-theme-docs'; +import { Callout } from "nextra-theme-docs"; To get started, hyperglass only needs to know about your devices. - **Devices** are your routers, switches, or whatever else you want to call the endpoints hyperglass - will query for information. + **Devices** are your routers, switches, or whatever else you want to call the endpoints + hyperglass will query for information. ## Simple Device Configuration @@ -18,12 +18,15 @@ Create a file called `devices.yaml` in the directory `/etc/hyperglass`. ```yaml filename="devices.yaml" devices: - - name: NYC Router 1 - address: - credential: - username: - password: - platform: cisco_ios + - name: NYC Router 1 + address: + credential: + username: + password: + platform: cisco_ios + attrs: + source4: + source6: ``` That's it! diff --git a/docs/pages/configuration/reference/_meta.json b/docs/pages/configuration/reference/_meta.json deleted file mode 100644 index 377c06b0..00000000 --- a/docs/pages/configuration/reference/_meta.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "config": "Config File", - "devices": "Devices File", - "directives": "Directives File" -} diff --git a/docs/pages/installation.mdx b/docs/pages/installation.mdx index c2888636..38814e3a 100644 --- a/docs/pages/installation.mdx +++ b/docs/pages/installation.mdx @@ -5,6 +5,64 @@ description: Installing hyperglass import { Callout, Tab, Tabs } from 'nextra-theme-docs'; +## Docker + +**Docker is the recommended method for running hyperglass.** + + +### 1. [Install Docker](https://docs.docker.com/engine/install/) + +### 2. Download hyperglass + +```shell copy +mkdir /etc/hyperglass +cd /opt +git clone https://github.com/thatmattlove/hyperglass/tree/v2.0.0 --depth=1 +``` + +### Quickstart (optional) + +Do this if you just want to see the hyperglass page working with a fake device. + +```shell copy +cp /opt/hyperglass/.samples/sample_devices.yaml /etc/hyperglass/devices.yaml +cd /opt/hyperglass +docker compose up +``` + +Navigate to http://localhost:8001 + +### 3. Setup Reverse Proxy + +[Caddy](https://caddyserver.com) is recommended, but any reverse proxy ([NGINX](https://www.nginx.com), [Apache2](https://httpd.apache.org)) will work. + +#### Caddy + +[**Install Caddy**](https://caddyserver.com/docs/install) + +```shell copy +cp /opt/hyperglass/.samples/Caddyfile /etc/caddy/Caddyfile +``` + +Change the `lg.example.com` and `person@example.com` values to match your hyperglass FQDN and email address (the email address is for automatic SSL certificate generation via Let's Encrypt). + + +If you prefer to use other Let's Encrypt validation methods or your own SSL certificate, modify your `/etc/hyperglass/Caddyfile` in accordance with the [Caddy docs](https://caddyserver.com/docs/caddyfile-tutorial). + + +Restart the Caddy service: `systemctl restart caddy{:shell}` + +#### NGINX + +```shell copy +cp /opt/hyperglass/.samples/hyperglass.nginx /etc/nginx/sites-available/hyperglass +ln -s /etc/nginx/sites-available/hyperglass /etc/nginx/sites-enabled/hyperglass +``` + +Change the `lg.example.com` value to match your hyperglass FQDN. + +Change the `` and `` values to match the path to your certificate and private key files. + ## Automatic installation If your system runs on: diff --git a/docs/pages/installation/_meta.json b/docs/pages/installation/_meta.json new file mode 100644 index 00000000..bf025c02 --- /dev/null +++ b/docs/pages/installation/_meta.json @@ -0,0 +1,6 @@ +{ + "docker": "Using Docker", + "manual": "Manual Installation", + "environment-variables": "Environment Variables", + "reverse-proxy": "Reverse Proxy" +} diff --git a/docs/pages/installation/docker.mdx b/docs/pages/installation/docker.mdx new file mode 100644 index 00000000..b0055335 --- /dev/null +++ b/docs/pages/installation/docker.mdx @@ -0,0 +1,54 @@ +--- +title: Using Docker +description: Installing hyperglass with Docker +--- + +import { Button } from "nextra/components"; +import { Callout } from "nextra-theme-docs"; + +## Docker + +**Docker is the recommended method for running hyperglass.** + +### 1. Install Docker + + + +### 2. Download hyperglass + +```shell copy +mkdir /etc/hyperglass +cd /opt +git clone https://github.com/thatmattlove/hyperglass/tree/v2.0.0 --depth=1 +``` + +### Optional: Quickstart + +Do this if you just want to see the hyperglass page working with a fake device. + +```shell copy +cp /opt/hyperglass/.samples/sample_devices.yaml /etc/hyperglass/devices.yaml +cd /opt/hyperglass +docker compose up +``` + +Navigate to http://localhost:8001 + +### 3. Create a `systemd` service + + + Before you create and start the hyperglass service, you may want to verify whether or not you + intend to change any [environment variables](environment-variables.mdx) and change them first. + + +```shell copy +cp /opt/hyperglass/.samples/hyperglass-docker.service /etc/hyperglass/hyperglass.service +ln -s /etc/hyperglass/hyperglass.service /etc/systemd/system/hyperglass.service +systemctl daemon-reload +systemctl enable hyperglass +systemctl start hyperglass +``` diff --git a/docs/pages/installation/environment-variables.mdx b/docs/pages/installation/environment-variables.mdx new file mode 100644 index 00000000..64d39157 --- /dev/null +++ b/docs/pages/installation/environment-variables.mdx @@ -0,0 +1,22 @@ +--- +title: Environment Variables +description: hyperglass environment variables +--- + +There are some configuration variables that must be supplied before hyperglass can start or read its configuration files. Most of the time, you should not need to modify these. + +Environment variables may be overridden at the command line, or by placing them in `${HYPERGLASS_APP_PATH}/hyperglass.env`. + +| Variable Name | Type | Default | Description | +| :-------------------------- | :------ | :---------------- | :----------------------------------------------------------------------------------------------------------------- | +| `HYPERGLASS_DEBUG` | boolean | `false` | Enable debug logging | +| `HYPERGLASS_DEV_MODE` | boolean | `false` | Enable developer mode. This should only be used if you are developing hyperglass under specific circumstances. | +| `HYPERGLASS_DISABLE_UI` | boolean | `false` | If set to `true`, the hyperglass UI is not built or served. The only way to access hyperglass is via REST API. | +| `HYPERGLASS_APP_PATH` | string | `/etc/hyperglass` | Directory where hyperglass configuration files and static web UI files are contained. | +| `HYPERGLASS_REDIS_HOST` | string | `localhost` | Host on which Redis is running. | +| `HYPERGLASS_REDIS_PASSWORD` | string | — | Redis password, if any. | +| `HYPERGLASS_REDIS_DB` | number | `1` | Redis database number. | +| `HYPERGLASS_REDIS_DSN` | string | — | Redis DSN. If supplied, overrides `HYPERGLASS_REDIS_HOST`, `HYPERGLASS_REDIS_DB`, and `HYPERGLASS_REDIS_PASSWORD`. | +| `HYPERGLASS_HOST` | string | `[::1]` | Address on which hyperglass listens for requests. | +| `HYPERGLASS_PORT` | number | `8001` | TCP port on which hyperglass listens for requests. | +| `HYPERGLASS_CA_CERT` | string | — | Path to CA certificate file for validating HTTPS certificates. If not supplied, system CAs are used. | diff --git a/docs/pages/installation/manual.mdx b/docs/pages/installation/manual.mdx new file mode 100644 index 00000000..99358cf4 --- /dev/null +++ b/docs/pages/installation/manual.mdx @@ -0,0 +1,60 @@ +--- +title: Manual Installation +description: Installing hyperglass manually +--- + +import { Callout } from 'nextra-theme-docs'; + +## Install Dependencies +To install hyperglass manually, you'll need to install the following dependencies: + +1. [Python 3.9, 3.10, 3.11, or 3.12](https://www.python.org/downloads/) +2. [NodeJS 18.17 or later](https://nodejs.org/en/download) +3. [PNPM 8 or later](https://pnpm.io/installation) +4. [Redis 7.2 or later](https://redis.io/download/) + + +Make sure the Redis server is started. + + +## Install hyperglass + +Once these dependencies are installed, install hyperglass via PyPI: + +```shell copy +pip3 install hyperglass +``` + +## Create app directory + + +If you plan on using a different directory, be sure to set the directory you wish to use in your [environment variables](environment-variables.mdx). + + +```shell copy +mkdir /etc/hyperglass +``` + +## Optional: Quickstart + +Do this if you just want to see the hyperglass page working with default settings and a fake device. + +```shell copy +curl -o /etc/hyperglass/devices.yaml https://github.com/thatmattlove/hyperglass/blob/v2.0.0/.samples/sample_devices.yaml +hyperglass start +``` + +## Create a `systemd` service + +```shell copy +curl -o /etc/hyperglass/hyperglass.service https://github.com/thatmattlove/hyperglass/blob/v2.0.0/.samples/hyperglass-manual.service +ln -s /etc/hyperglass/hyperglass.service /etc/systemd/system/hyperglass.service +systemctl daemon-reload +systemctl enable hyperglass +systemctl start hyperglass +``` + + +If you used a different app directory from the default `/etc/hyperglass`, change the `EnvironmentFile` value in the `hyperglass.service` file. + + diff --git a/docs/pages/installation/reverse-proxy.mdx b/docs/pages/installation/reverse-proxy.mdx new file mode 100644 index 00000000..48fe1732 --- /dev/null +++ b/docs/pages/installation/reverse-proxy.mdx @@ -0,0 +1,42 @@ +--- +title: Reverse Proxy +description: Setting up a reverse proxy for hyperglass +--- + +import { Button } from "nextra/components"; +import { Callout } from "nextra-theme-docs"; + +[Caddy](https://caddyserver.com) is recommended, but any reverse proxy ([NGINX](https://www.nginx.com), [Apache2](https://httpd.apache.org)) will work. + +## Caddy + + + +```shell copy +cp /opt/hyperglass/.samples/Caddyfile /etc/caddy/Caddyfile +``` + +Change the `lg.example.com` and `person@example.com` values to match your hyperglass FQDN and email address (the email address is for automatic SSL certificate generation via Let's Encrypt). + + + If you prefer to use other Let's Encrypt validation methods or your own SSL certificate, modify + your `/etc/hyperglass/Caddyfile` in accordance with the [Caddy + docs](https://caddyserver.com/docs/caddyfile-tutorial). + + +Restart the Caddy service: `systemctl restart caddy{:shell}` + +## NGINX + +```shell copy +cp /opt/hyperglass/.samples/hyperglass.nginx /etc/nginx/sites-available/hyperglass +ln -s /etc/nginx/sites-available/hyperglass /etc/nginx/sites-enabled/hyperglass +``` + +Change the `lg.example.com` value to match your hyperglass FQDN. + +Change the `` and `` values to match the path to your certificate and private key files. diff --git a/docs/pages/platforms.mdx b/docs/pages/platforms.mdx index 5f4a788f..0d63f89b 100644 --- a/docs/pages/platforms.mdx +++ b/docs/pages/platforms.mdx @@ -2,40 +2,57 @@ description: Platforms supported by hyperglass --- -import { Code, Table, Td, Th, Tr } from 'nextra/components'; -import { Callout } from 'nextra-theme-docs'; -import platforms from '~/platforms.json'; +import { Code, Table, Td, Th, Tr } from "nextra/components"; +import { Callout } from "nextra-theme-docs"; +import platforms from "~/platforms.json"; export const NotSupported = () => ( - - - - + + + + ); -export const Supported = () => ( - - - +export const Supported = (props) => ( + + + ); export const Platforms = () => ( - - - - - - - {platforms.map(([platform, native]) => ( - - - - - ))} - -
Platform KeysNatively Supported
- {platform} - {native ? : }
+ + + + + + + {platforms.map((spec) => ( + + + + + ))} + +
Platform KeysNatively Supported
+ {spec.keys.map((key) => ( + + {key} + + ))} + {spec.native ? : }
); hyperglass uses [Netmiko](https://github.com/ktbyers/netmiko) to interact with devices via SSH/telnet. [All platforms supported by Netmiko](https://github.com/ktbyers/netmiko/blob/develop/PLATFORMS.md) are supported by hyperglass. @@ -43,11 +60,11 @@ hyperglass uses [Netmiko](https://github.com/ktbyers/netmiko) to interact with d ## Netmiko Platforms - Just because Netmiko supports a given platform doesn't mean it will automatically work with - hyperglass. hyperglass has a limited number of built in directives (listed below). Any platforms - other than the ones listed below will require you to [add a custom - directive](/configuration/examples/add-your-own-command) for each command you wish to make - available. + Just because Netmiko supports a given platform doesn't mean it will automatically work with + hyperglass. hyperglass has a limited number of built in directives (listed below). Any platforms + other than the ones listed below will require you to [add a custom + directive](configuration/examples/add-your-own-command.mdx) for each command you wish to make + available.
@@ -56,8 +73,6 @@ hyperglass uses [Netmiko](https://github.com/ktbyers/netmiko) to interact with d ## Other Platforms -| Platform | Key | Natively Supported | -| :---------------- | :----- | :-------------------------------------------------------------------------: | -| FRRouting | `frr` | | -| BIRD | `bird` | | -| Any HTTP Endpoint | `http` | [See HTTP Device Docs](/configuration/reference/devices#http-configuration) | +| Platform | Key | Natively Supported | +| :---------------- | :----- | :------------------------------------------------------------------: | +| Any HTTP Endpoint | `http` | [See HTTP Device Docs](configuration/devices.mdx#http-configuration) | diff --git a/docs/platforms.json b/docs/platforms.json index deafcedb..43164abb 100644 --- a/docs/platforms.json +++ b/docs/platforms.json @@ -1 +1 @@ -[["a10", false], ["a10_ssh", false], ["accedian", false], ["accedian_ssh", false], ["adtran_os", false], ["adtran_os_ssh", false], ["alcatel_aos", false], ["alcatel_aos_ssh", false], ["alcatel_sros", false], ["alcatel_sros_ssh", false], ["allied_telesis_awplus", false], ["allied_telesis_awplus_ssh", false], ["apresia_aeos", false], ["apresia_aeos_ssh", false], ["arista_eos", true], ["arista_eos_ssh", false], ["aruba_os", false], ["aruba_os_ssh", false], ["aruba_osswitch", false], ["aruba_osswitch_ssh", false], ["aruba_procurve", false], ["aruba_procurve_ssh", false], ["avaya_ers", false], ["avaya_ers_ssh", false], ["avaya_vsp", false], ["avaya_vsp_ssh", false], ["broadcom_icos", false], ["broadcom_icos_ssh", false], ["brocade_fos", false], ["brocade_fos_ssh", false], ["brocade_fastiron", false], ["brocade_fastiron_ssh", false], ["brocade_netiron", false], ["brocade_netiron_ssh", false], ["brocade_nos", false], ["brocade_nos_ssh", false], ["brocade_vdx", false], ["brocade_vdx_ssh", false], ["brocade_vyos", false], ["brocade_vyos_ssh", false], ["checkpoint_gaia", false], ["checkpoint_gaia_ssh", false], ["calix_b6", false], ["calix_b6_ssh", false], ["cdot_cros", false], ["cdot_cros_ssh", false], ["centec_os", false], ["centec_os_ssh", false], ["ciena_saos", false], ["ciena_saos_ssh", false], ["cisco_asa", false], ["cisco_asa_ssh", false], ["cisco_ftd", false], ["cisco_ftd_ssh", false], ["cisco_ios", true], ["cisco_ios_ssh", false], ["cisco_nxos", true], ["cisco_nxos_ssh", false], ["cisco_s300", false], ["cisco_s300_ssh", false], ["cisco_tp", false], ["cisco_tp_ssh", false], ["cisco_wlc", false], ["cisco_wlc_ssh", false], ["cisco_xe", false], ["cisco_xe_ssh", false], ["cisco_xr", true], ["cisco_xr_ssh", false], ["cloudgenix_ion", false], ["cloudgenix_ion_ssh", false], ["coriant", false], ["coriant_ssh", false], ["dell_dnos9", false], ["dell_dnos9_ssh", false], ["dell_force10", false], ["dell_force10_ssh", false], ["dell_os6", false], ["dell_os6_ssh", false], ["dell_os9", false], ["dell_os9_ssh", false], ["dell_os10", false], ["dell_os10_ssh", false], ["dell_powerconnect", false], ["dell_powerconnect_ssh", false], ["dell_isilon", false], ["dell_isilon_ssh", false], ["dlink_ds", false], ["dlink_ds_ssh", false], ["endace", false], ["endace_ssh", false], ["eltex", false], ["eltex_ssh", false], ["eltex_esr", false], ["eltex_esr_ssh", false], ["enterasys", false], ["enterasys_ssh", false], ["ericsson_ipos", false], ["ericsson_ipos_ssh", false], ["extreme", false], ["extreme_ssh", false], ["extreme_ers", false], ["extreme_ers_ssh", false], ["extreme_exos", false], ["extreme_exos_ssh", false], ["extreme_netiron", false], ["extreme_netiron_ssh", false], ["extreme_nos", false], ["extreme_nos_ssh", false], ["extreme_slx", false], ["extreme_slx_ssh", false], ["extreme_vdx", false], ["extreme_vdx_ssh", false], ["extreme_vsp", false], ["extreme_vsp_ssh", false], ["extreme_wing", false], ["extreme_wing_ssh", false], ["f5_ltm", false], ["f5_ltm_ssh", false], ["f5_tmsh", false], ["f5_tmsh_ssh", false], ["f5_linux", false], ["f5_linux_ssh", false], ["flexvnf", false], ["flexvnf_ssh", false], ["fortinet", false], ["fortinet_ssh", false], ["generic", false], ["generic_ssh", false], ["generic_termserver", false], ["generic_termserver_ssh", false], ["hp_comware", false], ["hp_comware_ssh", false], ["hp_procurve", false], ["hp_procurve_ssh", false], ["huawei", true], ["huawei_ssh", false], ["huawei_smartax", false], ["huawei_smartax_ssh", false], ["huawei_olt", false], ["huawei_olt_ssh", false], ["huawei_vrpv8", false], ["huawei_vrpv8_ssh", false], ["ipinfusion_ocnos", false], ["ipinfusion_ocnos_ssh", false], ["juniper", true], ["juniper_ssh", false], ["juniper_junos", false], ["juniper_junos_ssh", false], ["juniper_screenos", false], ["juniper_screenos_ssh", false], ["keymile", false], ["keymile_ssh", false], ["keymile_nos", false], ["keymile_nos_ssh", false], ["linux", false], ["linux_ssh", false], ["mikrotik_routeros", false], ["mikrotik_routeros_ssh", false], ["mikrotik_switchos", false], ["mikrotik_switchos_ssh", false], ["mellanox", false], ["mellanox_ssh", false], ["mellanox_mlnxos", false], ["mellanox_mlnxos_ssh", false], ["mrv_lx", false], ["mrv_lx_ssh", false], ["mrv_optiswitch", false], ["mrv_optiswitch_ssh", false], ["netapp_cdot", false], ["netapp_cdot_ssh", false], ["netgear_prosafe", false], ["netgear_prosafe_ssh", false], ["netscaler", false], ["netscaler_ssh", false], ["nokia_sros", true], ["nokia_sros_ssh", false], ["oneaccess_oneos", false], ["oneaccess_oneos_ssh", false], ["ovs_linux", false], ["ovs_linux_ssh", false], ["paloalto_panos", false], ["paloalto_panos_ssh", false], ["pluribus", false], ["pluribus_ssh", false], ["quanta_mesh", false], ["quanta_mesh_ssh", false], ["rad_etx", false], ["rad_etx_ssh", false], ["raisecom_roap", false], ["raisecom_roap_ssh", false], ["ruckus_fastiron", false], ["ruckus_fastiron_ssh", false], ["ruijie_os", false], ["ruijie_os_ssh", false], ["sixwind_os", false], ["sixwind_os_ssh", false], ["sophos_sfos", false], ["sophos_sfos_ssh", false], ["supermicro_smis", false], ["supermicro_smis_ssh", false], ["tplink_jetstream", false], ["tplink_jetstream_ssh", false], ["ubiquiti_edge", false], ["ubiquiti_edge_ssh", false], ["ubiquiti_edgerouter", false], ["ubiquiti_edgerouter_ssh", false], ["ubiquiti_edgeswitch", false], ["ubiquiti_edgeswitch_ssh", false], ["ubiquiti_unifiswitch", false], ["ubiquiti_unifiswitch_ssh", false], ["vyatta_vyos", false], ["vyatta_vyos_ssh", false], ["vyos", true], ["vyos_ssh", false], ["watchguard_fireware", false], ["watchguard_fireware_ssh", false], ["zte_zxros", false], ["zte_zxros_ssh", false], ["yamaha", false], ["yamaha_ssh", false], ["adtran_os_telnet", false], ["apresia_aeos_telnet", false], ["arista_eos_telnet", false], ["aruba_procurve_telnet", false], ["brocade_fastiron_telnet", false], ["brocade_netiron_telnet", false], ["calix_b6_telnet", false], ["centec_os_telnet", false], ["ciena_saos_telnet", false], ["cisco_ios_telnet", false], ["cisco_xr_telnet", false], ["dell_dnos6_telnet", false], ["dell_powerconnect_telnet", false], ["dlink_ds_telnet", false], ["extreme_telnet", false], ["extreme_exos_telnet", false], ["extreme_netiron_telnet", false], ["generic_telnet", false], ["generic_termserver_telnet", false], ["hp_procurve_telnet", false], ["hp_comware_telnet", false], ["huawei_telnet", false], ["huawei_olt_telnet", false], ["ipinfusion_ocnos_telnet", false], ["juniper_junos_telnet", false], ["nokia_sros_telnet", false], ["oneaccess_oneos_telnet", false], ["paloalto_panos_telnet", false], ["rad_etx_telnet", false], ["raisecom_telnet", false], ["ruckus_fastiron_telnet", false], ["ruijie_os_telnet", false], ["supermicro_smis_telnet", false], ["tplink_jetstream_telnet", false], ["yamaha_telnet", false], ["zte_zxros_telnet", false], ["cisco_ios_serial", false], ["terminal_server", false], ["autodetect", false]] \ No newline at end of file +[{"name": "Arista EOS", "keys": ["arista_eos"], "native": true}, {"name": "BIRD", "keys": ["bird"], "native": true}, {"name": "Cisco IOS", "keys": ["cisco_ios"], "native": true}, {"name": "Cisco NX-OS", "keys": ["cisco_nxos"], "native": true}, {"name": "Cisco IOS-XR", "keys": ["cisco_xr"], "native": true}, {"name": "FRRouting", "keys": ["frr"], "native": true}, {"name": "Huawei VRP", "keys": ["huawei", "huawei_vrpv8"], "native": true}, {"name": "Juniper Junos", "keys": ["juniper", "juniper_junos"], "native": true}, {"name": "Mikrotik", "keys": ["mikrotik_routeros", "mikrotik_switchos"], "native": true}, {"name": "Nokia SR OS", "keys": ["nokia_sros"], "native": true}, {"name": "OpenBGPD", "keys": ["openbgpd"], "native": true}, {"name": "TNSR", "keys": ["tnsr"], "native": true}, {"name": "VyOS", "keys": ["vyos"], "native": true}, {"name": "", "keys": ["a10"], "native": false}, {"name": "", "keys": ["a10_ssh"], "native": false}, {"name": "", "keys": ["accedian"], "native": false}, {"name": "", "keys": ["accedian_ssh"], "native": false}, {"name": "", "keys": ["adtran_os"], "native": false}, {"name": "", "keys": ["adtran_os_ssh"], "native": false}, {"name": "", "keys": ["adtran_os_telnet"], "native": false}, {"name": "", "keys": ["alcatel_aos"], "native": false}, {"name": "", "keys": ["alcatel_aos_ssh"], "native": false}, {"name": "", "keys": ["alcatel_sros"], "native": false}, {"name": "", "keys": ["alcatel_sros_ssh"], "native": false}, {"name": "", "keys": ["allied_telesis_awplus"], "native": false}, {"name": "", "keys": ["allied_telesis_awplus_ssh"], "native": false}, {"name": "", "keys": ["apresia_aeos"], "native": false}, {"name": "", "keys": ["apresia_aeos_ssh"], "native": false}, {"name": "", "keys": ["apresia_aeos_telnet"], "native": false}, {"name": "", "keys": ["arista_eos_ssh"], "native": false}, {"name": "", "keys": ["arista_eos_telnet"], "native": false}, {"name": "", "keys": ["aruba_os"], "native": false}, {"name": "", "keys": ["aruba_os_ssh"], "native": false}, {"name": "", "keys": ["aruba_osswitch"], "native": false}, {"name": "", "keys": ["aruba_osswitch_ssh"], "native": false}, {"name": "", "keys": ["aruba_procurve"], "native": false}, {"name": "", "keys": ["aruba_procurve_ssh"], "native": false}, {"name": "", "keys": ["aruba_procurve_telnet"], "native": false}, {"name": "", "keys": ["audiocode_66"], "native": false}, {"name": "", "keys": ["audiocode_66_ssh"], "native": false}, {"name": "", "keys": ["audiocode_66_telnet"], "native": false}, {"name": "", "keys": ["audiocode_72"], "native": false}, {"name": "", "keys": ["audiocode_72_ssh"], "native": false}, {"name": "", "keys": ["audiocode_72_telnet"], "native": false}, {"name": "", "keys": ["audiocode_shell"], "native": false}, {"name": "", "keys": ["audiocode_shell_ssh"], "native": false}, {"name": "", "keys": ["audiocode_shell_telnet"], "native": false}, {"name": "", "keys": ["autodetect"], "native": false}, {"name": "", "keys": ["avaya_ers"], "native": false}, {"name": "", "keys": ["avaya_ers_ssh"], "native": false}, {"name": "", "keys": ["avaya_vsp"], "native": false}, {"name": "", "keys": ["avaya_vsp_ssh"], "native": false}, {"name": "", "keys": ["broadcom_icos"], "native": false}, {"name": "", "keys": ["broadcom_icos_ssh"], "native": false}, {"name": "", "keys": ["brocade_fastiron"], "native": false}, {"name": "", "keys": ["brocade_fastiron_ssh"], "native": false}, {"name": "", "keys": ["brocade_fastiron_telnet"], "native": false}, {"name": "", "keys": ["brocade_fos"], "native": false}, {"name": "", "keys": ["brocade_fos_ssh"], "native": false}, {"name": "", "keys": ["brocade_netiron"], "native": false}, {"name": "", "keys": ["brocade_netiron_ssh"], "native": false}, {"name": "", "keys": ["brocade_netiron_telnet"], "native": false}, {"name": "", "keys": ["brocade_nos"], "native": false}, {"name": "", "keys": ["brocade_nos_ssh"], "native": false}, {"name": "", "keys": ["brocade_vdx"], "native": false}, {"name": "", "keys": ["brocade_vdx_ssh"], "native": false}, {"name": "", "keys": ["brocade_vyos"], "native": false}, {"name": "", "keys": ["brocade_vyos_ssh"], "native": false}, {"name": "", "keys": ["calix_b6"], "native": false}, {"name": "", "keys": ["calix_b6_ssh"], "native": false}, {"name": "", "keys": ["calix_b6_telnet"], "native": false}, {"name": "", "keys": ["cdot_cros"], "native": false}, {"name": "", "keys": ["cdot_cros_ssh"], "native": false}, {"name": "", "keys": ["centec_os"], "native": false}, {"name": "", "keys": ["centec_os_ssh"], "native": false}, {"name": "", "keys": ["centec_os_telnet"], "native": false}, {"name": "", "keys": ["checkpoint_gaia"], "native": false}, {"name": "", "keys": ["checkpoint_gaia_ssh"], "native": false}, {"name": "", "keys": ["ciena_saos"], "native": false}, {"name": "", "keys": ["ciena_saos_ssh"], "native": false}, {"name": "", "keys": ["ciena_saos_telnet"], "native": false}, {"name": "", "keys": ["cisco_asa"], "native": false}, {"name": "", "keys": ["cisco_asa_ssh"], "native": false}, {"name": "", "keys": ["cisco_ftd"], "native": false}, {"name": "", "keys": ["cisco_ftd_ssh"], "native": false}, {"name": "", "keys": ["cisco_ios_serial"], "native": false}, {"name": "", "keys": ["cisco_ios_ssh"], "native": false}, {"name": "", "keys": ["cisco_ios_telnet"], "native": false}, {"name": "", "keys": ["cisco_nxos_ssh"], "native": false}, {"name": "", "keys": ["cisco_s300"], "native": false}, {"name": "", "keys": ["cisco_s300_ssh"], "native": false}, {"name": "", "keys": ["cisco_s300_telnet"], "native": false}, {"name": "", "keys": ["cisco_tp"], "native": false}, {"name": "", "keys": ["cisco_tp_ssh"], "native": false}, {"name": "", "keys": ["cisco_viptela"], "native": false}, {"name": "", "keys": ["cisco_viptela_ssh"], "native": false}, {"name": "", "keys": ["cisco_wlc"], "native": false}, {"name": "", "keys": ["cisco_wlc_ssh"], "native": false}, {"name": "", "keys": ["cisco_xe"], "native": false}, {"name": "", "keys": ["cisco_xe_ssh"], "native": false}, {"name": "", "keys": ["cisco_xr_ssh"], "native": false}, {"name": "", "keys": ["cisco_xr_telnet"], "native": false}, {"name": "", "keys": ["cloudgenix_ion"], "native": false}, {"name": "", "keys": ["cloudgenix_ion_ssh"], "native": false}, {"name": "", "keys": ["coriant"], "native": false}, {"name": "", "keys": ["coriant_ssh"], "native": false}, {"name": "", "keys": ["dell_dnos6_telnet"], "native": false}, {"name": "", "keys": ["dell_dnos9"], "native": false}, {"name": "", "keys": ["dell_dnos9_ssh"], "native": false}, {"name": "", "keys": ["dell_force10"], "native": false}, {"name": "", "keys": ["dell_force10_ssh"], "native": false}, {"name": "", "keys": ["dell_isilon"], "native": false}, {"name": "", "keys": ["dell_isilon_ssh"], "native": false}, {"name": "", "keys": ["dell_os10"], "native": false}, {"name": "", "keys": ["dell_os10_ssh"], "native": false}, {"name": "", "keys": ["dell_os6"], "native": false}, {"name": "", "keys": ["dell_os6_ssh"], "native": false}, {"name": "", "keys": ["dell_os9"], "native": false}, {"name": "", "keys": ["dell_os9_ssh"], "native": false}, {"name": "", "keys": ["dell_powerconnect"], "native": false}, {"name": "", "keys": ["dell_powerconnect_ssh"], "native": false}, {"name": "", "keys": ["dell_powerconnect_telnet"], "native": false}, {"name": "", "keys": ["dell_sonic"], "native": false}, {"name": "", "keys": ["dell_sonic_ssh"], "native": false}, {"name": "", "keys": ["dlink_ds"], "native": false}, {"name": "", "keys": ["dlink_ds_ssh"], "native": false}, {"name": "", "keys": ["dlink_ds_telnet"], "native": false}, {"name": "", "keys": ["eltex"], "native": false}, {"name": "", "keys": ["eltex_esr"], "native": false}, {"name": "", "keys": ["eltex_esr_ssh"], "native": false}, {"name": "", "keys": ["eltex_ssh"], "native": false}, {"name": "", "keys": ["endace"], "native": false}, {"name": "", "keys": ["endace_ssh"], "native": false}, {"name": "", "keys": ["enterasys"], "native": false}, {"name": "", "keys": ["enterasys_ssh"], "native": false}, {"name": "", "keys": ["ericsson_ipos"], "native": false}, {"name": "", "keys": ["ericsson_ipos_ssh"], "native": false}, {"name": "", "keys": ["extreme"], "native": false}, {"name": "", "keys": ["extreme_ers"], "native": false}, {"name": "", "keys": ["extreme_ers_ssh"], "native": false}, {"name": "", "keys": ["extreme_exos"], "native": false}, {"name": "", "keys": ["extreme_exos_ssh"], "native": false}, {"name": "", "keys": ["extreme_exos_telnet"], "native": false}, {"name": "", "keys": ["extreme_netiron"], "native": false}, {"name": "", "keys": ["extreme_netiron_ssh"], "native": false}, {"name": "", "keys": ["extreme_netiron_telnet"], "native": false}, {"name": "", "keys": ["extreme_nos"], "native": false}, {"name": "", "keys": ["extreme_nos_ssh"], "native": false}, {"name": "", "keys": ["extreme_slx"], "native": false}, {"name": "", "keys": ["extreme_slx_ssh"], "native": false}, {"name": "", "keys": ["extreme_ssh"], "native": false}, {"name": "", "keys": ["extreme_telnet"], "native": false}, {"name": "", "keys": ["extreme_tierra"], "native": false}, {"name": "", "keys": ["extreme_tierra_ssh"], "native": false}, {"name": "", "keys": ["extreme_vdx"], "native": false}, {"name": "", "keys": ["extreme_vdx_ssh"], "native": false}, {"name": "", "keys": ["extreme_vsp"], "native": false}, {"name": "", "keys": ["extreme_vsp_ssh"], "native": false}, {"name": "", "keys": ["extreme_wing"], "native": false}, {"name": "", "keys": ["extreme_wing_ssh"], "native": false}, {"name": "", "keys": ["f5_linux"], "native": false}, {"name": "", "keys": ["f5_linux_ssh"], "native": false}, {"name": "", "keys": ["f5_ltm"], "native": false}, {"name": "", "keys": ["f5_ltm_ssh"], "native": false}, {"name": "", "keys": ["f5_tmsh"], "native": false}, {"name": "", "keys": ["f5_tmsh_ssh"], "native": false}, {"name": "", "keys": ["flexvnf"], "native": false}, {"name": "", "keys": ["flexvnf_ssh"], "native": false}, {"name": "", "keys": ["fortinet"], "native": false}, {"name": "", "keys": ["fortinet_ssh"], "native": false}, {"name": "", "keys": ["generic"], "native": false}, {"name": "", "keys": ["generic_ssh"], "native": false}, {"name": "", "keys": ["generic_telnet"], "native": false}, {"name": "", "keys": ["generic_termserver"], "native": false}, {"name": "", "keys": ["generic_termserver_ssh"], "native": false}, {"name": "", "keys": ["generic_termserver_telnet"], "native": false}, {"name": "", "keys": ["hp_comware"], "native": false}, {"name": "", "keys": ["hp_comware_ssh"], "native": false}, {"name": "", "keys": ["hp_comware_telnet"], "native": false}, {"name": "", "keys": ["hp_procurve"], "native": false}, {"name": "", "keys": ["hp_procurve_ssh"], "native": false}, {"name": "", "keys": ["hp_procurve_telnet"], "native": false}, {"name": "", "keys": ["huawei_olt"], "native": false}, {"name": "", "keys": ["huawei_olt_ssh"], "native": false}, {"name": "", "keys": ["huawei_olt_telnet"], "native": false}, {"name": "", "keys": ["huawei_smartax"], "native": false}, {"name": "", "keys": ["huawei_smartax_ssh"], "native": false}, {"name": "", "keys": ["huawei_ssh"], "native": false}, {"name": "", "keys": ["huawei_telnet"], "native": false}, {"name": "", "keys": ["huawei_vrpv8_ssh"], "native": false}, {"name": "", "keys": ["ipinfusion_ocnos"], "native": false}, {"name": "", "keys": ["ipinfusion_ocnos_ssh"], "native": false}, {"name": "", "keys": ["ipinfusion_ocnos_telnet"], "native": false}, {"name": "", "keys": ["juniper_junos_ssh"], "native": false}, {"name": "", "keys": ["juniper_junos_telnet"], "native": false}, {"name": "", "keys": ["juniper_screenos"], "native": false}, {"name": "", "keys": ["juniper_screenos_ssh"], "native": false}, {"name": "", "keys": ["juniper_ssh"], "native": false}, {"name": "", "keys": ["keymile"], "native": false}, {"name": "", "keys": ["keymile_nos"], "native": false}, {"name": "", "keys": ["keymile_nos_ssh"], "native": false}, {"name": "", "keys": ["keymile_ssh"], "native": false}, {"name": "", "keys": ["linux"], "native": false}, {"name": "", "keys": ["linux_ssh"], "native": false}, {"name": "", "keys": ["mellanox"], "native": false}, {"name": "", "keys": ["mellanox_mlnxos"], "native": false}, {"name": "", "keys": ["mellanox_mlnxos_ssh"], "native": false}, {"name": "", "keys": ["mellanox_ssh"], "native": false}, {"name": "", "keys": ["mikrotik_routeros_ssh"], "native": false}, {"name": "", "keys": ["mikrotik_switchos_ssh"], "native": false}, {"name": "", "keys": ["mrv_lx"], "native": false}, {"name": "", "keys": ["mrv_lx_ssh"], "native": false}, {"name": "", "keys": ["mrv_optiswitch"], "native": false}, {"name": "", "keys": ["mrv_optiswitch_ssh"], "native": false}, {"name": "", "keys": ["netapp_cdot"], "native": false}, {"name": "", "keys": ["netapp_cdot_ssh"], "native": false}, {"name": "", "keys": ["netgear_prosafe"], "native": false}, {"name": "", "keys": ["netgear_prosafe_ssh"], "native": false}, {"name": "", "keys": ["netscaler"], "native": false}, {"name": "", "keys": ["netscaler_ssh"], "native": false}, {"name": "", "keys": ["nokia_srl"], "native": false}, {"name": "", "keys": ["nokia_srl_ssh"], "native": false}, {"name": "", "keys": ["nokia_sros_ssh"], "native": false}, {"name": "", "keys": ["nokia_sros_telnet"], "native": false}, {"name": "", "keys": ["oneaccess_oneos"], "native": false}, {"name": "", "keys": ["oneaccess_oneos_ssh"], "native": false}, {"name": "", "keys": ["oneaccess_oneos_telnet"], "native": false}, {"name": "", "keys": ["ovs_linux"], "native": false}, {"name": "", "keys": ["ovs_linux_ssh"], "native": false}, {"name": "", "keys": ["paloalto_panos"], "native": false}, {"name": "", "keys": ["paloalto_panos_ssh"], "native": false}, {"name": "", "keys": ["paloalto_panos_telnet"], "native": false}, {"name": "", "keys": ["pluribus"], "native": false}, {"name": "", "keys": ["pluribus_ssh"], "native": false}, {"name": "", "keys": ["quanta_mesh"], "native": false}, {"name": "", "keys": ["quanta_mesh_ssh"], "native": false}, {"name": "", "keys": ["rad_etx"], "native": false}, {"name": "", "keys": ["rad_etx_ssh"], "native": false}, {"name": "", "keys": ["rad_etx_telnet"], "native": false}, {"name": "", "keys": ["raisecom_roap"], "native": false}, {"name": "", "keys": ["raisecom_roap_ssh"], "native": false}, {"name": "", "keys": ["raisecom_telnet"], "native": false}, {"name": "", "keys": ["ruckus_fastiron"], "native": false}, {"name": "", "keys": ["ruckus_fastiron_ssh"], "native": false}, {"name": "", "keys": ["ruckus_fastiron_telnet"], "native": false}, {"name": "", "keys": ["ruijie_os"], "native": false}, {"name": "", "keys": ["ruijie_os_ssh"], "native": false}, {"name": "", "keys": ["ruijie_os_telnet"], "native": false}, {"name": "", "keys": ["sixwind_os"], "native": false}, {"name": "", "keys": ["sixwind_os_ssh"], "native": false}, {"name": "", "keys": ["sophos_sfos"], "native": false}, {"name": "", "keys": ["sophos_sfos_ssh"], "native": false}, {"name": "", "keys": ["supermicro_smis"], "native": false}, {"name": "", "keys": ["supermicro_smis_ssh"], "native": false}, {"name": "", "keys": ["supermicro_smis_telnet"], "native": false}, {"name": "", "keys": ["terminal_server"], "native": false}, {"name": "", "keys": ["tplink_jetstream"], "native": false}, {"name": "", "keys": ["tplink_jetstream_ssh"], "native": false}, {"name": "", "keys": ["tplink_jetstream_telnet"], "native": false}, {"name": "", "keys": ["ubiquiti_edge"], "native": false}, {"name": "", "keys": ["ubiquiti_edge_ssh"], "native": false}, {"name": "", "keys": ["ubiquiti_edgerouter"], "native": false}, {"name": "", "keys": ["ubiquiti_edgerouter_ssh"], "native": false}, {"name": "", "keys": ["ubiquiti_edgeswitch"], "native": false}, {"name": "", "keys": ["ubiquiti_edgeswitch_ssh"], "native": false}, {"name": "", "keys": ["ubiquiti_unifiswitch"], "native": false}, {"name": "", "keys": ["ubiquiti_unifiswitch_ssh"], "native": false}, {"name": "", "keys": ["vyatta_vyos"], "native": false}, {"name": "", "keys": ["vyatta_vyos_ssh"], "native": false}, {"name": "", "keys": ["vyos_ssh"], "native": false}, {"name": "", "keys": ["watchguard_fireware"], "native": false}, {"name": "", "keys": ["watchguard_fireware_ssh"], "native": false}, {"name": "", "keys": ["yamaha"], "native": false}, {"name": "", "keys": ["yamaha_ssh"], "native": false}, {"name": "", "keys": ["yamaha_telnet"], "native": false}, {"name": "", "keys": ["zte_zxros"], "native": false}, {"name": "", "keys": ["zte_zxros_ssh"], "native": false}, {"name": "", "keys": ["zte_zxros_telnet"], "native": false}, {"name": "", "keys": ["zyxel_os"], "native": false}, {"name": "", "keys": ["zyxel_os_ssh"], "native": false}] \ No newline at end of file diff --git a/docs/theme.config.tsx b/docs/theme.config.tsx index f02c0de9..20c9890e 100644 --- a/docs/theme.config.tsx +++ b/docs/theme.config.tsx @@ -1,130 +1,137 @@ -import styles from './global.module.css'; -import { useRouter } from 'next/router'; -import { useConfig, type DocsThemeConfig } from 'nextra-theme-docs'; -import faviconFormats from './favicon-formats'; +import { useRouter } from "next/router"; +import { type DocsThemeConfig, useConfig } from "nextra-theme-docs"; +import faviconFormats from "./favicon-formats"; +import styles from "./global.module.css"; -const NO_INDEX_FOLLOW = process.env.CF_PAGES_BRANCH !== 'main'; +const NO_INDEX_FOLLOW = process.env.CF_PAGES_BRANCH !== "main"; const config: DocsThemeConfig = { - logo: ( - - - - - - - - - - - - - - - - - - - - - - - - ), - - useNextSeoProps: () => { - const { asPath } = useRouter(); - const { frontMatter, title } = useConfig(); - return { - titleTemplate: '%s | hyperglass', - title: frontMatter.title || title, - openGraph: { - type: 'website', - url: `https://hyperglass.dev${asPath}`, - title: frontMatter.title || title, - description: frontMatter.description || 'hyperglass Documentation', - images: [ - { - url: 'https://hyperglass.dev/opengraph.jpg', - width: 1200, - height: 630, - alt: 'hyperglass', - }, - ], - }, - twitter: { handle: '@thatmattlove', site: '@thatmattlove', cardType: 'summary_large_image' }, - noindex: NO_INDEX_FOLLOW, - nofollow: NO_INDEX_FOLLOW, - additionalLinkTags: faviconFormats.map(fmt => { - const { image_format, dimensions, prefix, rel } = fmt; - const [w, h] = dimensions; - const href = `/img/${prefix}-${w}x${h}.${image_format}`; - return { rel: rel ?? '', href, type: `image/${image_format}` }; - }), - }; - }, - banner: { - dismissible: true, - text: '🎉 hyperglass 2.0 is here!', - }, - feedback: { content: null }, - footer: { text: `© ${new Date().getFullYear()} hyperglass` }, - chat: { - link: 'https://netdev.chat/', - icon: ( - - - + logo: ( + + + hyperglass + + + + + + + + + + + + + + + + + + + + + ), - }, - project: { - link: 'https://github.com/thatmattlove/hyperglass', - }, + + useNextSeoProps: () => { + const { asPath } = useRouter(); + const { frontMatter, title } = useConfig(); + return { + titleTemplate: "%s | hyperglass", + title: frontMatter.title || title, + openGraph: { + type: "website", + url: `https://hyperglass.dev${asPath}`, + title: frontMatter.title || title, + description: frontMatter.description || "hyperglass Documentation", + images: [ + { + url: "https://hyperglass.dev/opengraph.jpg", + width: 1200, + height: 630, + alt: "hyperglass", + }, + ], + }, + twitter: { + handle: "@thatmattlove", + site: "@thatmattlove", + cardType: "summary_large_image", + }, + noindex: NO_INDEX_FOLLOW, + nofollow: NO_INDEX_FOLLOW, + additionalLinkTags: faviconFormats.map((fmt) => { + const { image_format, dimensions, prefix, rel } = fmt; + const [w, h] = dimensions; + const href = `/img/${prefix}-${w}x${h}.${image_format}`; + return { rel: rel ?? "", href, type: `image/${image_format}` }; + }), + }; + }, + banner: { + dismissible: true, + // text: "🎉 hyperglass 2.0 is here!", + text: "😬 hyperglass 2.0 and its documentation is still in development!", + }, + feedback: { content: null }, + footer: { text: `© ${new Date().getFullYear()} hyperglass` }, + chat: { + link: "https://netdev.chat/", + icon: ( + + NetDev Chat + + + ), + }, + project: { + link: "https://github.com/thatmattlove/hyperglass", + }, }; export default config; diff --git a/hyperglass/defaults/directives/arista_eos.py b/hyperglass/defaults/directives/arista_eos.py index bf0acd5d..5d1bad7a 100644 --- a/hyperglass/defaults/directives/arista_eos.py +++ b/hyperglass/defaults/directives/arista_eos.py @@ -20,6 +20,9 @@ "AristaBGPCommunityTable", ) +NAME = "Arista EOS" +PLATFORMS = ["arista_eos"] + AristaBGPRoute = BuiltinDirective( id="__hyperglass_arista_eos_bgp_route__", name="BGP Route", @@ -37,7 +40,7 @@ ], field=Text(description="IP Address, Prefix, or Hostname"), table_output="__hyperglass_arista_eos_bgp_route_table__", - platforms=["arista_eos"], + platforms=PLATFORMS, ) AristaBGPASPath = BuiltinDirective( @@ -55,7 +58,7 @@ ], field=Text(description="AS Path Regular Expression"), table_output="__hyperglass_arista_eos_bgp_aspath_table__", - platforms=["arista_eos"], + platforms=PLATFORMS, ) AristaBGPCommunity = BuiltinDirective( @@ -73,7 +76,7 @@ ], field=Text(description="BGP Community String"), table_output="__hyperglass_arista_eos_bgp_community_table__", - platforms=["arista_eos"], + platforms=PLATFORMS, ) @@ -93,7 +96,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["arista_eos"], + platforms=PLATFORMS, ) AristaTraceroute = BuiltinDirective( @@ -112,7 +115,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["arista_eos"], + platforms=PLATFORMS, ) # Table Output Directives @@ -133,7 +136,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["arista_eos"], + platforms=PLATFORMS, ) AristaBGPASPathTable = BuiltinDirective( @@ -150,7 +153,7 @@ ) ], field=Text(description="AS Path Regular Expression"), - platforms=["arista_eos"], + platforms=PLATFORMS, ) AristaBGPCommunityTable = BuiltinDirective( @@ -167,5 +170,5 @@ ) ], field=Text(description="BGP Community String"), - platforms=["arista_eos"], + platforms=PLATFORMS, ) diff --git a/hyperglass/defaults/directives/bird.py b/hyperglass/defaults/directives/bird.py index 7531cbd0..14c97127 100644 --- a/hyperglass/defaults/directives/bird.py +++ b/hyperglass/defaults/directives/bird.py @@ -17,6 +17,9 @@ "BIRD_Traceroute", ) +NAME = "BIRD" +PLATFORMS = ["bird"] + BIRD_BGPRoute = BuiltinDirective( id="__hyperglass_bird_bgp_route__", name="BGP Route", @@ -33,7 +36,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["bird"], + platforms=PLATFORMS, ) BIRD_BGPASPath = BuiltinDirective( @@ -49,7 +52,7 @@ ) ], field=Text(description="AS Path Regular Expression"), - platforms=["bird"], + platforms=PLATFORMS, ) BIRD_BGPCommunity = BuiltinDirective( @@ -65,7 +68,7 @@ ) ], field=Text(description="BGP Community String"), - platforms=["bird"], + platforms=PLATFORMS, ) BIRD_Ping = BuiltinDirective( @@ -84,7 +87,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["bird"], + platforms=PLATFORMS, ) BIRD_Traceroute = BuiltinDirective( @@ -103,5 +106,5 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["bird"], + platforms=PLATFORMS, ) diff --git a/hyperglass/defaults/directives/cisco_ios.py b/hyperglass/defaults/directives/cisco_ios.py index e70821b6..f4327c92 100644 --- a/hyperglass/defaults/directives/cisco_ios.py +++ b/hyperglass/defaults/directives/cisco_ios.py @@ -17,6 +17,9 @@ "CiscoIOS_Traceroute", ) +NAME = "Cisco IOS" +PLATFORMS = ["cisco_ios"] + CiscoIOS_BGPRoute = BuiltinDirective( id="__hyperglass_cisco_ios_bgp_route__", name="BGP Route", @@ -33,7 +36,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["cisco_ios"], + platforms=PLATFORMS, ) CiscoIOS_BGPASPath = BuiltinDirective( @@ -50,7 +53,7 @@ ) ], field=Text(description="AS Path Regular Expression"), - platforms=["cisco_ios"], + platforms=PLATFORMS, ) CiscoIOS_BGPCommunity = BuiltinDirective( @@ -67,7 +70,7 @@ ) ], field=Text(description="BGP Community String"), - platforms=["cisco_ios"], + platforms=PLATFORMS, ) CiscoIOS_Ping = BuiltinDirective( @@ -86,7 +89,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["cisco_ios"], + platforms=PLATFORMS, ) CiscoIOS_Traceroute = BuiltinDirective( @@ -105,5 +108,5 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["cisco_ios"], + platforms=PLATFORMS, ) diff --git a/hyperglass/defaults/directives/cisco_nxos.py b/hyperglass/defaults/directives/cisco_nxos.py index 8c421c1e..1c7a8ea6 100644 --- a/hyperglass/defaults/directives/cisco_nxos.py +++ b/hyperglass/defaults/directives/cisco_nxos.py @@ -17,6 +17,9 @@ "CiscoNXOS_Traceroute", ) +NAME = "Cisco NX-OS" +PLATFORMS = ["cisco_nxos"] + CiscoNXOS_BGPRoute = BuiltinDirective( id="__hyperglass_cisco_nxos_bgp_route__", name="BGP Route", @@ -33,7 +36,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["cisco_nxos"], + platforms=PLATFORMS, ) CiscoNXOS_BGPASPath = BuiltinDirective( @@ -50,7 +53,7 @@ ) ], field=Text(description="AS Path Regular Expression"), - platforms=["cisco_nxos"], + platforms=PLATFORMS, ) CiscoNXOS_BGPCommunity = BuiltinDirective( @@ -67,7 +70,7 @@ ) ], field=Text(description="BGP Community String"), - platforms=["cisco_nxos"], + platforms=PLATFORMS, ) CiscoNXOS_Ping = BuiltinDirective( @@ -86,7 +89,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["cisco_nxos"], + platforms=PLATFORMS, ) CiscoNXOS_Traceroute = BuiltinDirective( @@ -105,5 +108,5 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["cisco_nxos"], + platforms=PLATFORMS, ) diff --git a/hyperglass/defaults/directives/cisco_xr.py b/hyperglass/defaults/directives/cisco_xr.py index 7f613b76..84501806 100644 --- a/hyperglass/defaults/directives/cisco_xr.py +++ b/hyperglass/defaults/directives/cisco_xr.py @@ -17,6 +17,9 @@ "CiscoXR_Traceroute", ) +NAME = "Cisco IOS-XR" +PLATFORMS = ["cisco_xr"] + CiscoXR_BGPRoute = BuiltinDirective( id="__hyperglass_cisco_xr_bgp_route__", name="BGP Route", @@ -33,7 +36,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["cisco_xr"], + platforms=PLATFORMS, ) CiscoXR_BGPASPath = BuiltinDirective( @@ -50,7 +53,7 @@ ) ], field=Text(description="AS Path Regular Expression"), - platforms=["cisco_xr"], + platforms=PLATFORMS, ) CiscoXR_BGPCommunity = BuiltinDirective( @@ -67,7 +70,7 @@ ) ], field=Text(description="BGP Community String"), - platforms=["cisco_xr"], + platforms=PLATFORMS, ) CiscoXR_Ping = BuiltinDirective( @@ -86,7 +89,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["cisco_xr"], + platforms=PLATFORMS, ) CiscoXR_Traceroute = BuiltinDirective( @@ -105,5 +108,5 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["cisco_xr"], + platforms=PLATFORMS, ) diff --git a/hyperglass/defaults/directives/frr.py b/hyperglass/defaults/directives/frr.py index 59224582..09e8f2d3 100644 --- a/hyperglass/defaults/directives/frr.py +++ b/hyperglass/defaults/directives/frr.py @@ -17,6 +17,9 @@ "FRRouting_Traceroute", ) +NAME = "FRRouting" +PLATFORMS = ["frr"] + FRRouting_BGPRoute = BuiltinDirective( id="__hyperglass_frr_bgp_route__", name="BGP Route", @@ -33,7 +36,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["frr"], + platforms=PLATFORMS, ) FRRouting_BGPASPath = BuiltinDirective( @@ -50,7 +53,7 @@ ) ], field=Text(description="AS Path Regular Expression"), - platforms=["frr"], + platforms=PLATFORMS, ) FRRouting_BGPCommunity = BuiltinDirective( @@ -67,7 +70,7 @@ ) ], field=Text(description="BGP Community String"), - platforms=["frr"], + platforms=PLATFORMS, ) FRRouting_Ping = BuiltinDirective( @@ -86,7 +89,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["frr"], + platforms=PLATFORMS, ) FRRouting_Traceroute = BuiltinDirective( @@ -105,5 +108,5 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["frr"], + platforms=PLATFORMS, ) diff --git a/hyperglass/defaults/directives/huawei.py b/hyperglass/defaults/directives/huawei.py index 1ab97a8f..b5175036 100644 --- a/hyperglass/defaults/directives/huawei.py +++ b/hyperglass/defaults/directives/huawei.py @@ -17,6 +17,9 @@ "Huawei_Traceroute", ) +NAME = "Huawei VRP" +PLATFORMS = ["huawei", "huawei_vrpv8"] + Huawei_BGPRoute = BuiltinDirective( id="__hyperglass_huawei_bgp_route__", name="BGP Route", @@ -33,7 +36,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["huawei"], + platforms=PLATFORMS, ) Huawei_BGPASPath = BuiltinDirective( @@ -50,7 +53,7 @@ ) ], field=Text(description="AS Path Regular Expression"), - platforms=["huawei"], + platforms=PLATFORMS, ) Huawei_BGPCommunity = BuiltinDirective( @@ -67,7 +70,7 @@ ) ], field=Text(description="BGP Community String"), - platforms=["huawei"], + platforms=PLATFORMS, ) Huawei_Ping = BuiltinDirective( @@ -86,7 +89,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["huawei"], + platforms=PLATFORMS, ) Huawei_Traceroute = BuiltinDirective( @@ -105,5 +108,5 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["huawei"], + platforms=PLATFORMS, ) diff --git a/hyperglass/defaults/directives/juniper.py b/hyperglass/defaults/directives/juniper.py index e568343a..8dca7046 100644 --- a/hyperglass/defaults/directives/juniper.py +++ b/hyperglass/defaults/directives/juniper.py @@ -20,6 +20,9 @@ "JuniperBGPCommunityTable", ) +NAME = "Juniper Junos" +PLATFORMS = ["juniper", "juniper_junos"] + JuniperBGPRoute = BuiltinDirective( id="__hyperglass_juniper_bgp_route__", name="BGP Route", @@ -37,7 +40,7 @@ ], field=Text(description="IP Address, Prefix, or Hostname"), table_output="__hyperglass_juniper_bgp_route_table__", - platforms=["juniper"], + platforms=PLATFORMS, ) JuniperBGPASPath = BuiltinDirective( @@ -55,7 +58,7 @@ ], field=Text(description="AS Path Regular Expression"), table_output="__hyperglass_juniper_bgp_aspath_table__", - platforms=["juniper"], + platforms=PLATFORMS, ) JuniperBGPCommunity = BuiltinDirective( @@ -73,7 +76,7 @@ ], field=Text(description="BGP Community String"), table_output="__hyperglass_juniper_bgp_community_table__", - platforms=["juniper"], + platforms=PLATFORMS, ) @@ -93,7 +96,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["juniper"], + platforms=PLATFORMS, ) JuniperTraceroute = BuiltinDirective( @@ -112,7 +115,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["juniper"], + platforms=PLATFORMS, ) # Table Output Directives @@ -133,7 +136,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["juniper"], + platforms=PLATFORMS, ) JuniperBGPASPathTable = BuiltinDirective( @@ -150,7 +153,7 @@ ) ], field=Text(description="AS Path Regular Expression"), - platforms=["juniper"], + platforms=PLATFORMS, ) JuniperBGPCommunityTable = BuiltinDirective( @@ -167,5 +170,5 @@ ) ], field=Text(description="BGP Community String"), - platforms=["juniper"], + platforms=PLATFORMS, ) diff --git a/hyperglass/defaults/directives/mikrotik.py b/hyperglass/defaults/directives/mikrotik.py index c65d2ae4..16c948a0 100644 --- a/hyperglass/defaults/directives/mikrotik.py +++ b/hyperglass/defaults/directives/mikrotik.py @@ -17,6 +17,9 @@ "Mikrotik_Traceroute", ) +NAME = "Mikrotik" +PLATFORMS = ["mikrotik_routeros", "mikrotik_switchos"] + Mikrotik_BGPRoute = BuiltinDirective( id="__hyperglass_mikrotik_bgp_route__", name="BGP Route", @@ -33,7 +36,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["mikrotik_routeros", "mikrotik_switchos"], + platforms=PLATFORMS, ) Mikrotik_BGPASPath = BuiltinDirective( @@ -50,7 +53,7 @@ ) ], field=Text(description="AS Path Regular Expression"), - platforms=["mikrotik_routeros", "mikrotik_switchos"], + platforms=PLATFORMS, ) Mikrotik_BGPCommunity = BuiltinDirective( @@ -67,7 +70,7 @@ ) ], field=Text(description="BGP Community String"), - platforms=["mikrotik_routeros", "mikrotik_switchos"], + platforms=PLATFORMS, ) Mikrotik_Ping = BuiltinDirective( @@ -86,7 +89,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["mikrotik_routeros", "mikrotik_switchos"], + platforms=PLATFORMS, ) Mikrotik_Traceroute = BuiltinDirective( @@ -105,5 +108,5 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["mikrotik_routeros", "mikrotik_switchos"], + platforms=PLATFORMS, ) diff --git a/hyperglass/defaults/directives/nokia_sros.py b/hyperglass/defaults/directives/nokia_sros.py index e013bae7..1e8ea5e3 100644 --- a/hyperglass/defaults/directives/nokia_sros.py +++ b/hyperglass/defaults/directives/nokia_sros.py @@ -17,6 +17,9 @@ "NokiaSROS_Traceroute", ) +NAME = "Nokia SR OS" +PLATFORMS = ["nokia_sros"] + NokiaSROS_BGPRoute = BuiltinDirective( id="__hyperglass_nokia_sros_bgp_route__", name="BGP Route", @@ -33,7 +36,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["nokia_sros"], + platforms=PLATFORMS, ) NokiaSROS_BGPASPath = BuiltinDirective( @@ -49,7 +52,7 @@ ) ], field=Text(description="AS Path Regular Expression"), - platforms=["nokia_sros"], + platforms=PLATFORMS, ) NokiaSROS_BGPCommunity = BuiltinDirective( @@ -65,7 +68,7 @@ ) ], field=Text(description="BGP Community String"), - platforms=["nokia_sros"], + platforms=PLATFORMS, ) NokiaSROS_Ping = BuiltinDirective( @@ -84,7 +87,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["nokia_sros"], + platforms=PLATFORMS, ) NokiaSROS_Traceroute = BuiltinDirective( @@ -103,5 +106,5 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["nokia_sros"], + platforms=PLATFORMS, ) diff --git a/hyperglass/defaults/directives/openbgpd.py b/hyperglass/defaults/directives/openbgpd.py index be448064..71e7077d 100644 --- a/hyperglass/defaults/directives/openbgpd.py +++ b/hyperglass/defaults/directives/openbgpd.py @@ -17,6 +17,9 @@ "OpenBGPD_Traceroute", ) +NAME = "OpenBGPD" +PLATFORMS = ["openbgpd"] + OpenBGPD_BGPRoute = BuiltinDirective( id="__hyperglass_openbgpd_bgp_route__", name="BGP Route", @@ -33,7 +36,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["openbgpd"], + platforms=PLATFORMS, ) OpenBGPD_BGPASPath = BuiltinDirective( @@ -50,7 +53,7 @@ ) ], field=Text(description="AS Path Regular Expression"), - platforms=["openbgpd"], + platforms=PLATFORMS, ) OpenBGPD_BGPCommunity = BuiltinDirective( @@ -67,7 +70,7 @@ ) ], field=Text(description="BGP Community String"), - platforms=["openbgpd"], + platforms=PLATFORMS, ) OpenBGPD_Ping = BuiltinDirective( @@ -86,7 +89,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["openbgpd"], + platforms=PLATFORMS, ) OpenBGPD_Traceroute = BuiltinDirective( @@ -105,5 +108,5 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["openbgpd"], + platforms=PLATFORMS, ) diff --git a/hyperglass/defaults/directives/tnsr.py b/hyperglass/defaults/directives/tnsr.py index ba81158a..cea46814 100644 --- a/hyperglass/defaults/directives/tnsr.py +++ b/hyperglass/defaults/directives/tnsr.py @@ -17,6 +17,9 @@ "TNSR_Traceroute", ) +NAME = "TNSR" +PLATFORMS = ["tnsr"] + TNSR_BGPRoute = BuiltinDirective( id="__hyperglass_tnsr_bgp_route__", name="BGP Route", @@ -33,7 +36,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["tnsr"], + platforms=PLATFORMS, ) TNSR_BGPASPath = BuiltinDirective( @@ -50,7 +53,7 @@ ) ], field=Text(description="AS Path Regular Expression"), - platforms=["tnsr"], + platforms=PLATFORMS, ) TNSR_BGPCommunity = BuiltinDirective( @@ -67,7 +70,7 @@ ) ], field=Text(description="BGP Community String"), - platforms=["tnsr"], + platforms=PLATFORMS, ) TNSR_Ping = BuiltinDirective( @@ -86,7 +89,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["tnsr"], + platforms=PLATFORMS, ) TNSR_Traceroute = BuiltinDirective( @@ -105,5 +108,5 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["tnsr"], + platforms=PLATFORMS, ) diff --git a/hyperglass/defaults/directives/vyos.py b/hyperglass/defaults/directives/vyos.py index 75a46683..fcfb4acd 100644 --- a/hyperglass/defaults/directives/vyos.py +++ b/hyperglass/defaults/directives/vyos.py @@ -17,6 +17,9 @@ "VyOS_Traceroute", ) +NAME = "VyOS" +PLATFORMS = ["vyos"] + VyOS_BGPRoute = BuiltinDirective( id="__hyperglass_vyos_bgp_route__", name="BGP Route", @@ -33,7 +36,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["vyos"], + platforms=PLATFORMS, ) VyOS_BGPASPath = BuiltinDirective( @@ -50,7 +53,7 @@ ) ], field=Text(description="AS Path Regular Expression"), - platforms=["vyos"], + platforms=PLATFORMS, ) VyOS_BGPCommunity = BuiltinDirective( @@ -67,7 +70,7 @@ ) ], field=Text(description="BGP Community String"), - platforms=["vyos"], + platforms=PLATFORMS, ) VyOS_Ping = BuiltinDirective( @@ -86,7 +89,7 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["vyos"], + platforms=PLATFORMS, ) VyOS_Traceroute = BuiltinDirective( @@ -105,5 +108,5 @@ ), ], field=Text(description="IP Address, Prefix, or Hostname"), - platforms=["vyos"], + platforms=PLATFORMS, ) diff --git a/hyperglass/util/docs.py b/hyperglass/util/docs.py index d2432439..1aa5336c 100644 --- a/hyperglass/util/docs.py +++ b/hyperglass/util/docs.py @@ -2,11 +2,37 @@ # Standard Library import json +import typing as t from pathlib import Path +from importlib.util import module_from_spec, spec_from_file_location + + +class PlatformSpec(t.TypedDict): + """Definition for each platform.""" + + name: str + keys: t.Tuple[str, ...] + native: bool + + +def get_directive_variable(path: Path, variable: str) -> t.Any: + """Read a variable from a directive file.""" + + name, _ = path.name.split(".") + spec = spec_from_file_location(name, location=path) + module = module_from_spec(spec) + spec.loader.exec_module(module) + + exports = tuple(getattr(module, e, None) for e in dir(module) if e == variable) + if len(exports) < 1: + raise RuntimeError(f"'{path!s} exists', but it is missing a variable named '{variable}'") + + value, *_ = exports + return value def create_platform_list() -> str: - """Create a list of platforms as a typescript file for use by the docs.""" + """Create a list of platforms as a JSON file for use by the docs.""" # Third Party from netmiko.ssh_dispatcher import CLASS_MAPPER # type: ignore @@ -17,11 +43,34 @@ def create_platform_list() -> str: builtin_directives = project_root / "hyperglass" / "defaults" / "directives" - names = [f.stem for f in builtin_directives.iterdir() if not f.name.startswith("_")] + platforms: t.Tuple[PlatformSpec] = () + + keys = [] + + for path in builtin_directives.iterdir(): + if not path.name.startswith("_"): + name = get_directive_variable(path, "NAME") + if not isinstance(name, str): + raise RuntimeError("'NAME' variable is missing or invalid in '{!s}'".format(path)) + _platforms = get_directive_variable(path, "PLATFORMS") + if not isinstance(_platforms, t.Tuple, t.List): + raise RuntimeError( + "'PLATFORMS' variable is missing or invalid in '{!s}'".format(path) + ) + spec: PlatformSpec = {"name": name, "keys": _platforms, "native": True} + platforms += (spec,) + keys = [*keys, *_platforms] + + for key in CLASS_MAPPER.keys(): + if key not in keys: + spec: PlatformSpec = {"name": "", "keys": (key,), "native": False} + platforms += (spec,) - platforms = [[p, p in names] for p in CLASS_MAPPER.keys()] + sorted_platforms = list(platforms) + sorted_platforms.sort(key=lambda x: x["keys"][0]) + sorted_platforms.sort(key=lambda x: not x["native"]) with file_.open("w+") as opened_file: - json.dump(platforms, opened_file) + json.dump(sorted_platforms, opened_file) return f"Wrote platforms to {file_!s}"