network-device
network-device is a dependency-free Rust core for two distinct ways to
express network configuration:
- Operational eDSL: typed imperative operations executed immediately by a selected device driver.
- Desired state: declarative resource values planned and applied by an infrastructure-as-code (IaC) backend.
The crate contains neutral domain values, standard operation/resource types, and open extension contracts. It contains no protocol clients, vendor payload or path abstraction, persistence, Terraform/Pulumi dependencies, or runtime.
Operational eDSL
Implement Driver and Execute<Operation> for each supported operation. The
operation types are owned by the caller and consumed exactly once. The eDSL
composes these operations with statically typed then; it executes in order,
stops at the first error, and returns the last operation's output.
use ;
use Infallible;
use Future;
;
async
Connecting and authenticating a driver
Implement DriverConnector in the protocol/provider integration crate. The
connector defines its own target, authentication, driver, and connection error
types, and consumes the authentication value while constructing an
authenticated driver. It does not retrieve credentials.
An external integration can use its existing CredentialProvider (for
example, oss-providers::CredentialProvider) to resolve a
CredentialMaterial, convert that material to the selected connector's
Authentication type, and then call connect:
let credential = credential_provider.credential.await?;
let authentication = try_from?;
let driver = connector.connect.await?;
operation.run.await?;
This keeps secret retrieval, leases, and renewal in the external credential
integration while keeping protocol-specific authentication in the provider.
network-device itself has no dependency on oss-providers, Vault, or any
credential backend. The associated types and returned driver use static
dispatch; the connector contract adds no Box, trait object, or shared-state
wrapper.
Sequential composition is static and has no boxing or dynamic dispatch:
operation
.then
.run
.await?;
Each downstream crate can define its own operation and implement
Execute<CustomOperation> for a driver it owns, or implement a standard
operation for its own driver. New operation kinds do not require changes to
this crate.
Desired State and IaC
Desired-state resources are not imperative commands. For example,
InterfaceConfiguration describes a target configuration, while
SetInterfaceState asks a driver to perform an operation now. Both can use
the same neutral values such as InterfaceName and AdministrativeState.
IacBackend<Resource> is generic over the resource type, not a closed enum.
Each backend chooses its own plan and apply result types and implements only
the resource types it supports:
use ;
use Infallible;
use Future;
;
async
Potential implementation crates include network-device-nxapi,
network-device-netconf, network-device-terraform,
network-device-opentofu, and network-device-pulumi. Those names describe
future integrations only; this crate implements none of them. Terraform and
Pulumi have different semantics, so the shared IaC contract deliberately
stops at generic plan and apply operations with backend-specific result
types.
Base Types
InterfaceNamerejects empty names and control characters but preserves vendor-specific spelling.IpPrefixvalidates IPv4 and IPv6 prefix lengths.StaticRoutevalidates that its destination and next hop use the same IP family.- Standard operations:
SetInterfaceState,SetInterfaceDescription,EnsureStaticRoute, andRemoveStaticRoute. - Standard desired resources:
InterfaceConfigurationandStaticRouteConfiguration.
These are shared semantic types, not a claim that every device protocol maps them to identical native paths or payloads.