An open API service indexing awesome lists of open source software.

https://github.com/netascode/go-netconf

A simple, fluent Go client library for interacting with network devices using the NETCONF protocol (RFC 6241).
https://github.com/netascode/go-netconf

golang netconf

Last synced: 8 months ago
JSON representation

A simple, fluent Go client library for interacting with network devices using the NETCONF protocol (RFC 6241).

Awesome Lists containing this project

README

          

go-netconf


GoDoc
Go Report Card
CI
codecov
License

A simple, fluent Go client library for interacting with network devices using the NETCONF protocol (RFC 6241).

## Features

- **Simple API**: Fluent, chainable API design
- **XML Manipulation**: Path-based XML operations using [xmldot](https://github.com/netascode/xmldot) (like gjson/sjson for JSON)
- **Complete NETCONF Support**: All standard operations (Get, GetConfig, EditConfig, Lock, Commit, etc.)
- **Robust Transport**: Built on [scrapligo](https://github.com/scrapli/scrapligo) for reliable SSH connectivity and NETCONF protocol handling
- **Automatic Retry**: Built-in retry logic with exponential backoff for transient errors
- **Thread-Safe**: Concurrent read operations with synchronized write operations
- **Capability Discovery**: Automatic capability negotiation and checking
- **Transaction Support**: Full candidate datastore workflow support
- **Structured Logging**: Configurable logging with automatic sensitive data redaction

## Installation

```bash
go get github.com/netascode/go-netconf
```

## Requirements

- Go 1.24 or later
- Network device with NETCONF support

## Quick Start

```go
package main

import (
"context"
"fmt"
"log"

"github.com/netascode/go-netconf"
)

func main() {
// Create client
client, err := netconf.NewClient(
"192.168.1.1",
netconf.Username("admin"),
netconf.Password("secret"),
netconf.Port(830),
)
if err != nil {
log.Fatal(err)
}
defer client.Close()

// Get configuration with filter
ctx := context.Background()
filter := netconf.SubtreeFilter("")
res, err := client.GetConfig(ctx, "running", filter)
if err != nil {
log.Fatal(err)
}

// Parse response using xmldot
ifName := res.Res.Get("data.interfaces.interface.name").String()
fmt.Println("Interface:", ifName)
}
```

## Usage

### Client Creation

```go
client, err := netconf.NewClient(
"192.168.1.1",
netconf.Username("admin"),
netconf.Password("secret"),
netconf.Port(830),
netconf.MaxRetries(5),
netconf.OperationTimeout(120*time.Second),
)
```

### Get Configuration

```go
ctx := context.Background()

// Get with filter
filter := netconf.SubtreeFilter("")
res, err := client.GetConfig(ctx, "running", filter)

// Get with XPath filter
filter := netconf.XPathFilter("/interfaces/interface[name='GigabitEthernet1']")
res, err := client.Get(ctx, filter)

// Get without filter (all data)
res, err := client.GetConfig(ctx, "running", netconf.NoFilter())
```

### Edit Configuration

```go
ctx := context.Background()

// Build configuration using Body builder
config := netconf.Body{}.
Set("interfaces.interface.name", "GigabitEthernet1").
Set("interfaces.interface.description", "WAN Interface").
Set("interfaces.interface.enabled", true).String()

// Apply configuration
res, err := client.EditConfig(ctx, "candidate", config,
netconf.DefaultOperation("merge"),
netconf.TestOption("test-then-set"),
)
```

### Transaction Workflow

```go
ctx := context.Background()

// Lock candidate datastore
if _, err := client.Lock(ctx, "candidate"); err != nil {
log.Fatal(err)
}
defer client.Unlock(ctx, "candidate")

// Edit configuration
config := netconf.Body{}.
Set("system.hostname", "router1").String()
_, err = client.EditConfig(ctx, "candidate", config)
if err != nil {
client.Discard(ctx)
log.Fatal(err)
}

// Commit changes
if _, err := client.Commit(ctx); err != nil {
log.Fatal(err)
}
```

### Error Handling

The library automatically retries transient errors (lock conflicts, resource exhaustion, transport failures) with exponential backoff:

```go
client, err := netconf.NewClient(
"192.168.1.1",
netconf.Username("admin"),
netconf.Password("secret"),
netconf.MaxRetries(10), // Maximum retry attempts
netconf.BackoffMinDelay(1*time.Second), // Minimum 1 second delay
netconf.BackoffMaxDelay(60*time.Second), // Maximum 60 second delay
netconf.BackoffDelayFactor(1.2), // Exponential factor
)
```

### Capability Checking

```go
// Check if server supports candidate datastore
if client.ServerHasCapability("urn:ietf:params:netconf:capability:candidate:1.0") {
ctx := context.Background()
// Use candidate datastore
client.Lock(ctx, "candidate")
// ...
}

// Get all server capabilities
caps := client.ServerCapabilities()
for _, cap := range caps {
fmt.Println(cap)
}
```

### Custom RPC Operations

```go
ctx := context.Background()
rpc := `

full

`
res, err := client.RPC(ctx, rpc)
```

## Supported Operations

| Operation | Description |
|-----------|-------------|
| Get | Retrieve configuration and state data |
| GetConfig | Retrieve configuration from datastore |
| EditConfig | Modify configuration |
| CopyConfig | Copy configuration between datastores |
| DeleteConfig | Delete configuration datastore |
| Lock | Lock datastore |
| Unlock | Unlock datastore |
| Commit | Commit candidate to running |
| Discard | Discard candidate changes |
| Validate | Validate configuration (requires `:validate` capability) |
| RPC | Send custom RPC operations |

## Documentation

- [GoDoc](https://pkg.go.dev/github.com/netascode/go-netconf)
- [RFC 6241 - NETCONF Protocol](https://tools.ietf.org/html/rfc6241)
- [RFC 6242 - NETCONF over SSH](https://tools.ietf.org/html/rfc6242)

## Examples

See the [examples](examples/) directory for library usage examples:

- **basic** - Client creation, GetConfig, EditConfig, response parsing
- **candidate** - Lock/Unlock, Validate, Commit/Discard workflows
- **concurrent** - Thread-safe concurrent operations
- **custom-rpc** - Custom RPC operations with RPC() method
- **filters** - SubtreeFilter, XPathFilter, NoFilter APIs
- **logging** - Logger configuration and log levels

## Testing

```bash
# Run tests
make test

# Run tests with coverage
make coverage

# Run linters
make lint

# Run all checks
make verify
```

## Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

## Acknowledgments

This library is built on top of [scrapligo](https://github.com/scrapli/scrapligo) for the NETCONF transport layer. Scrapligo provides robust SSH connectivity and NETCONF protocol handling, allowing go-netconf to focus on providing a simple, idiomatic Go API.

## License

Mozilla Public License Version 2.0 - see [LICENSE](LICENSE) for details.