Metadata-Version: 2.4
Name: netdrift
Version: 0.1.0
Summary: Compare NetBox intended state against live Cisco device config
Author: Mason Williams
License: MIT
Keywords: netbox,cisco,network,automation,drift,config
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: System :: Networking
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.31
Requires-Dist: netmiko>=4.3
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Dynamic: license-file

# netdrift

Compare what NetBox *says* your network looks like against what your Cisco
devices are *actually* running.

```
  DRIFT REPORT: lab-sw1
  --------------------------------------------------------------------
  INTERFACE               FIELD         NETBOX        DEVICE
  --------------------------------------------------------------------
  GigabitEthernet1/0/1    trunk vlans   absent        +[60, 70, 80, 90, 100]
  GigabitEthernet1/0/2    access vlan   10            20
  GigabitEthernet1/0/2    voice vlan    None          200
  GigabitEthernet1/0/3    admin state   enabled       shutdown
  GigabitEthernet1/0/9    undocumented  -             on device only

  5 difference(s) found.
```

Somebody SSH'd in at 3am, fixed something, and never updated NetBox. That
port is now carrying VLANs nobody documented. `netdrift` finds it.

## Install

```bash
pip install netdrift
```

## Usage

Against a live NetBox and a live device:

```bash
netdrift --netbox-url https://netbox.example.com \
         --netbox-token $NETBOX_TOKEN \
         --device sw1 --host 10.0.0.1 \
         --username admin --password secret
```

Against a saved config file (no SSH):

```bash
netdrift --netbox-url https://netbox.example.com \
         --netbox-token $NETBOX_TOKEN \
         --device sw1 --config-file sw1-running-config.txt
```

Many devices in one run:

```bash
netdrift --netbox-url https://netbox.example.com \
         --netbox-token $NETBOX_TOKEN \
         --devices devices.txt \
         --username admin --password secret
```

`devices.txt` is one device per line — name, then either an IP to SSH to
or a saved config file:

```
core-sw1     10.0.0.1
core-sw2     10.0.0.2
edge-sw1     saved/edge-sw1.txt
```

JSON works too. Each device gets its own report, followed by a summary.
A device that's unreachable is reported and skipped, not fatal.

Trying it out with no NetBox at all:

```bash
netdrift --mock-netbox mock_netbox.json --device lab-sw1 \
         --config-file messy_config.txt
```

Exit codes: `0` clean, `1` drift found, `2` one or more devices
couldn't be checked. Drops straight into CI or a cron job.

## What it checks

| Field | Compared |
|---|---|
| Interface mode | access vs trunk (NetBox `tagged` normalized to `trunk`) |
| Access VLAN | untagged VLAN assignment |
| Trunk VLANs | allowed lists, including `add` continuation lines and ranges |
| Voice VLAN | `switchport voice vlan` |
| Admin state | `shutdown` / `no shutdown` |
| Missing ports | in NetBox, absent on device |
| Undocumented ports | on device, absent from NetBox |

SVIs, port-channels, sub-interfaces and loopbacks are hidden by default
since NetBox often doesn't model them. Pass `--show-logical` to see them.

Pasted terminal sessions (with `switch(config-if)#` prompts) are detected
and stripped automatically, so a copied CLI transcript works as input too.

## What it does not do (yet)

- IOS / IOS-XE and basic NX-OS. IOS-XR is not implemented.
- Read-only. It reports drift; it will never push config.
- No scheduling, history, or alerting.

## Flags

```
--netbox-url URL        NetBox base URL
--netbox-token TOKEN    NetBox API token
--mock-netbox FILE      JSON file instead of a live NetBox
--device NAME           single device name as it appears in NetBox
--devices FILE          inventory file: check many devices in one run
--host IP               device address for SSH
--username / --password SSH credentials
--config-file FILE      parse a saved running-config instead of SSH
--show-logical          include SVIs/port-channels in undocumented list
--dry-run               show NetBox intended state only
```

## Development

```bash
pip install -r requirements.txt
python -m pytest test_netdrift.py -v
```

29 tests cover the parser and the diff engine. Please add one with any
bug report — a config snippet that parses wrong is the most useful issue
you can file.

## Contributing

Bug reports with a sanitized config snippet are very welcome. **Please
scrub hostnames, IPs, keys and passwords before pasting anything.**

## License

MIT
