feat(build): configure project tooling and update dependencies

- Replace placeholder deps with click, pygnmi, and rich for CLI functionality
- Add fabric-orch CLI entry point via project.scripts
- Configure hatchling as build backend with wheel/sdist targets
- Add ruff linter configuration for code quality
- Add dev dependency group with ruff
- Alphabetize yang module imports
This commit is contained in:
darnodo
2025-12-31 09:36:00 +01:00
parent 3e76eba46a
commit e041dab724
9 changed files with 1524 additions and 25 deletions

183
src/gnmi/README.md Normal file
View File

@@ -0,0 +1,183 @@
# gNMI Client Module
This module provides a high-level gNMI client wrapper for interacting with Arista devices using pygnmi.
## Features
- Connection management with context manager support
- Get capabilities (list supported YANG models)
- Get configuration and state data at any YANG path
- Set configuration with dry-run support
- Subscribe to path updates (on-change, sample modes)
- Error handling with meaningful exceptions
## Installation
Ensure you have the required dependencies:
```bash
uv add pygnmi click rich
```
## Usage
### Basic Connection
```python
from gnmi import GNMIClient
# Using context manager (recommended)
with GNMIClient(
host="172.16.0.50",
port=6030,
username="admin",
password="admin",
insecure=True
) as client:
# Use the client
caps = client.capabilities()
print(caps)
```
### Get Capabilities
```python
with GNMIClient(host="172.16.0.50", port=6030) as client:
# Get raw capabilities
caps = client.capabilities()
print(f"gNMI Version: {caps['gnmi_version']}")
# Get parsed models
models = client.get_models()
for model in models:
print(f" {model.name} ({model.organization}) v{model.version}")
```
### Get Data
```python
with GNMIClient(host="172.16.0.50", port=6030) as client:
# Get all data (config + state)
result = client.get("/interfaces/interface[name=Ethernet1]")
# Get config only
result = client.get(
"/interfaces/interface[name=Ethernet1]",
data_type="config"
)
# Get state only
result = client.get(
"/interfaces/interface[name=Ethernet1]/state",
data_type="state"
)
# Get multiple paths
result = client.get([
"/interfaces/interface[name=Ethernet1]/state",
"/interfaces/interface[name=Ethernet2]/state",
])
```
### Set Configuration
```python
with GNMIClient(host="172.16.0.50", port=6030) as client:
# Dry-run (default) - shows what would be set
result = client.set(
path="/interfaces/interface[name=Ethernet1]/config/description",
value="Uplink to Spine",
dry_run=True
)
# Actually apply the change
result = client.set(
path="/interfaces/interface[name=Ethernet1]/config/description",
value="Uplink to Spine",
dry_run=False
)
# Replace operation
result = client.set(
path="/interfaces/interface[name=Ethernet1]/config",
value={"description": "New config", "enabled": True},
operation="replace",
dry_run=False
)
# Delete operation
result = client.set(
path="/interfaces/interface[name=Ethernet1]/config/description",
value=None,
operation="delete",
dry_run=False
)
```
### Subscribe to Updates
```python
with GNMIClient(host="172.16.0.50", port=6030) as client:
# Subscribe to interface state changes
subscription = client.subscribe(
paths="/interfaces/interface/state/oper-status",
mode="stream",
stream_mode="on-change"
)
# Process updates
for update in subscription:
print(update)
```
## Error Handling
The module provides specific exceptions for different error types:
```python
from gnmi import GNMIClient, GNMIError, GNMIConnectionError, GNMIPathError
try:
with GNMIClient(host="172.16.0.50", port=6030) as client:
result = client.get("/invalid/path")
except GNMIConnectionError as e:
print(f"Connection failed: {e}")
except GNMIPathError as e:
print(f"Invalid path: {e}")
except GNMIError as e:
print(f"gNMI error: {e}")
```
## Environment Variables
The CLI supports these environment variables for defaults:
- `GNMI_TARGET` - Target device (host:port)
- `GNMI_USERNAME` - Username for authentication
- `GNMI_PASSWORD` - Password for authentication
## Path Format Notes
For Arista EOS, use native paths **without** module prefixes for subscriptions:
```python
# ✅ Correct - native path
"/interfaces/interface[name=Ethernet1]/state"
# ❌ Incorrect - with module prefix (may fail for subscriptions)
"/openconfig-interfaces:interfaces/interface[name=Ethernet1]/state"
```
## Validated Paths
These paths have been validated against Arista cEOS 4.35.0F:
| Category | Path | Notes |
|----------|------|-------|
| Interfaces | `/interfaces/interface[name=Ethernet1]/state` | Full state |
| BGP | `/network-instances/network-instance[name=default]/protocols/protocol[identifier=BGP][name=BGP]/bgp/neighbors/neighbor/state` | All neighbors |
| VXLAN | `/interfaces/interface[name=Vxlan1]/arista-vxlan/vlan-to-vnis` | VNI mappings |
| MLAG | `/arista/eos/mlag/config` | Config only |
| EVPN | `/arista/eos/evpn` | Config only |
See `docs/yang-paths.md` for complete path documentation.