"""Command line tool to communicate with the NetBox API.""" from typing import Any, Dict, List import click import pandas as pd from gso.services.netbox_client import NetboxClient def convert_to_table(data: List[Dict[str, Any]], fields: List[str]) -> pd.DataFrame: if not data: raise ValueError("No data is available for your request") df = pd.DataFrame(data) if fields: df = df[fields] return df @click.group() def cli() -> None: pass @cli.group() def create() -> None: pass @create.command() @click.option("--fqdn", prompt="Enter device name", help="Device name") @click.option("--model", default="vmx", help="Device model") def device(fqdn: str, model: str) -> None: click.echo(f"Creating device: fqdn={fqdn}, model={model}") new_device = NetboxClient().create_device(fqdn, model) click.echo(new_device) @create.command() @click.option("--name", help="Interface name") @click.option("--type", default="10gbase-t", help="Interface type, default is 10GBASE-T") @click.option("--speed", default="1000", help="Interface speed , default is 1000") @click.option("--fqdn", help="Device where to create interface") def interface(name: str, type: str, speed: str, fqdn: str) -> None: click.echo(f"Creating interface: name={name}, speed={speed}, fqdn={fqdn}") new_interface = NetboxClient().create_interface(name, type, speed, fqdn) click.echo(new_interface) @create.command() @click.option("--name", help="Manufacturer name") @click.option("--slug", help="Short name for manufacturer") def manufacturer(name: str, slug: str) -> None: click.echo(f"Creating manufacturer: name={name}") manufacturer = NetboxClient().create_device_manufacturer(name, slug) click.echo(manufacturer) @create.command() @click.option("--manufacturer", help="Manufacturer for device") @click.option("--model", help="Model for device") @click.option("--slug", help="Short name for manufacturer") def device_type(manufacturer: str, model: str, slug: str) -> None: click.echo(f"Creating device type: manufacturer={manufacturer} model = {model}") device_type = NetboxClient().create_device_type(manufacturer, model, slug) click.echo(device_type) @create.command() @click.option("--name", help="Name for device role") @click.option("--slug", help="Short name for device role") def device_role(name: str, slug: str) -> None: click.echo(f"Creating device role: name={name}") device_role = NetboxClient().create_device_role(name, slug) click.echo(device_role) @create.command() @click.option("--name", help="Name for device site") @click.option("--slug", help="Short name for device site") def device_site(name: str, slug: str) -> None: click.echo(f"Creating device site: name={name}") device_site = NetboxClient().create_device_site(name, slug) click.echo(device_site) create.add_command(device) create.add_command(interface) create.add_command(manufacturer) create.add_command(device_type) create.add_command(device_role) create.add_command(device_site) # Define list commands here @cli.group() def list() -> None: pass @list.command() @click.option("--fqdn", help="Device name to list interfaces") @click.option("--speed", default="1000", help="Interface speed to list interfaces (default 1000=1G)") def interfaces(fqdn: str, speed: str) -> None: click.echo(f"Listing all interfaces for: device with fqdn={fqdn}, speed={speed}") interface_list = NetboxClient().get_interfaces_by_device(fqdn, speed) display_fields = ["name", "enabled", "mark_connected", "custom_fields", "lag", "speed"] iface_list = [] for iface in interface_list: iface_list.append(dict(iface)) table = convert_to_table(iface_list, display_fields) click.echo(table) @list.command() def devices() -> None: click.echo("Listing all devices:") device_list = NetboxClient().get_all_devices() display_fields = ["name", "device_type"] devices = [] for device in device_list: devices.append(dict(device)) table = convert_to_table(devices, display_fields) click.echo(table) list.add_command(interfaces) list.add_command(devices) # Define delete commands here @cli.group() def delete() -> None: pass @delete.command() # type: ignore[no-redef] @click.option("--fqdn", help="Name of device to delete") def device(fqdn: str) -> None: click.echo(f"Deleting device: device={fqdn}") NetboxClient().delete_device(fqdn) @delete.command() # type: ignore[no-redef] @click.option("--fqdn", help="Device name from where to get interface to delete") @click.option("--iface", help="Name of interface name to delete") def interface(fqdn: str, iface: str) -> None: click.echo(f"Deleting interface: device={fqdn}, interface name={iface}") NetboxClient().delete_interface(fqdn, iface) delete.add_command(device) delete.add_command(interface) # The action command @cli.group() def action() -> None: pass @action.command() @click.option("--fqdn", help="Device name from where to get interface to edit") @click.option("--iface", help="Interface name to edit") def reserve_interface(fqdn: str, iface: str) -> None: click.echo(f"Reserving interface: device ={fqdn}, interface name={iface}") reserved_iface = NetboxClient().reserve_interface(fqdn, iface) click.echo(reserved_iface) @action.command() @click.option("--fqdn", help="Device name from where to get interface to edit") @click.option("--iface", help="Interface name to edit") def free_interface(fqdn: str, iface: str) -> None: click.echo(f"Freeing interface: device={fqdn}, interface name={iface}") freed_iface = NetboxClient().free_interface(fqdn, iface) click.echo(freed_iface) @action.command() @click.option("--fqdn", help="Device name from where to get interface to edit") @click.option("--iface", help="Interface name to edit") def allocate_interface(fqdn: str, iface: str) -> None: click.echo(f"Allocating interface: device={fqdn}, interface name={iface}") allocated_iface = NetboxClient().allocate_interface(fqdn, iface) click.echo(allocated_iface) @action.command() @click.option("--fqdn", help="Device name from where to get interface to edit") @click.option("--iface", help="Interface name to edit") def deallocate_interface(fqdn: str, iface: str) -> None: click.echo(f"Deallocating interface: device={fqdn}, interface name={iface}") deallocated_iface = NetboxClient().free_interface(fqdn, iface) click.echo(deallocated_iface) @action.command() @click.option("--fqdn", help="Device name from where to get physical interface to attach LAG") @click.option("--lag", help="LAG name to attach physical interface to") @click.option("--iface", help="Interface name to attach to LAG") def attach_interface_to_lag(fqdn: str, lag: str, iface: str) -> None: click.echo(f"Attaching LAG to physical interface: device={fqdn}, LAG name={lag}, interface name={iface}") attached_iface = NetboxClient().attach_interface_to_lag(fqdn, lag, iface) click.echo(attached_iface) action.add_command(reserve_interface) action.add_command(free_interface) action.add_command(allocate_interface) action.add_command(deallocate_interface) action.add_command(attach_interface_to_lag) if __name__ == "__main__": cli()