nornir-rs 0.1.1

A Rust library and CLI that incorporates feature favorites from some of the best network automation tools.
Documentation

Nornir-rs & KoRE CLI

A network automation stack written in Rust

Crates.io Docs.rs License: MIT Pipeline Status

Overview

KoRE re-imagines the classic network automation toolchain (Nornir, Netmiko, Ansible, Jinja2, TextFSM) with modern Rust ergonomics. It delivers:

  • Declarative inventories with layered defaults, host/group vars, and secrets providers.
  • Async transports (SSH, NETCONF, HTTP, local runners) with connection pooling and profile-aware prompt handling.
  • Jinja2/MiniJinja templates for config generation plus first-class REST helpers and TextFSM parsing.
  • Ansible-vault compatible secrets and a CLI (kore) that mirrors the library API so you can embed workflows or drive them interactively.

Documentation Map

Quick Start

  1. Clone & build
    git clone https://gitlab.com/kolbash_pub/kore.git
    cd kore
    cargo build
    
  2. Bootstrap a workspace
    cargo run -- init
    # creates inventory/{hosts,groups,defaults}.yaml, kore.yaml, logs/
    
  3. List hosts
    cargo run -- list --filter platform=cisco_ios
    
  4. Render & push configs
    cargo run -- run ssh --command "show version"
    cargo run -- run j2 --template templates/core.j2 --output rendered/core.txt
    cargo run -- run pipeline pipelines/ospf.yaml
    

Once comfortable with the CLI, embed the same workflows via the nornir-rs crate and builder APIs.

Installation

KoRE is a Cargo project—any modern Rust toolchain works.

  • Install the CLI:
    cargo install --git https://gitlab.com/kolbash_pub/kore.git
    # or locally
    cargo install --path .
    
  • Manual build:
    cargo build --release
    install -m 0755 target/release/kore ~/.local/bin/
    
  • Ad-hoc runs (no install):
    cargo run -- <subcommand> [flags]
    

Configuration (kore.yaml)

The CLI searches for kore.yaml in this order:

  1. ./kore.yaml
  2. $HOME/.kore.yaml
  3. $KORE_CONFIG
  4. /etc/kore/kore.yaml

It controls transports, vault defaults, parsers, rendering paths, etc. See docs/CLI_USAGE.md for every field plus examples.

Inventory & Variables

The init command generates the canonical Nornir-style layout:

  • inventory/hosts.yaml – device entries (hostname, port, platform, metadata).
  • inventory/groups.yaml – shared parameters for groups.
  • inventory/defaults.yaml – global defaults merged last.

KoRE also supports remote inventory plugins wired through kore.yaml:

  • simple – load YAML/JSON/TOML files from disk (the default init layout).
  • http – fetch a serialized inventory document from any REST endpoint.
  • nautobot – call Nautobot’s REST API, paginate automatically, and build hosts for both devices and virtual machines (including custom fields, tags, and role/site/cluster groups).
  • netbox – query NetBox’s REST API (devices and virtual machines), flatten custom fields/tags, and optionally merge SimpleInventory-style groups/defaults.

Example Nautobot configuration:

inventory:
  plugin: nautobot
  options:
    url: https://nautobot.local/api/
    token: ${NAUTOBOT_TOKEN}
    include_virtual_machines: true
    flatten_custom_fields: true
    device_query:
      - name: status
        value: active
    virtual_machine_query:
      - name: tenant
        value: lab

Layer Ansible-style vars by pointing kore.yaml (or CLI flags) at inventory/group_vars and inventory/host_vars. Merge strategies (override or deep) mirror Nornir. Details live in docs/INVENTORY_SCHEMA.md.

Example NetBox configuration:

inventory:
  plugin: netbox
  options:
    nb_url: https://netbox.local
    nb_token: ${NETBOX_TOKEN}
    include_virtual_machines: true
    flatten_custom_fields: true
    device_query:
      - name: role
        value: edge
    group_file: inventory/groups.yaml
    defaults_file: inventory/defaults.yaml

NetBox API tokens can be provided in either legacy (Token abc…) or application (Bearer nbt_…) form; KoRE detects the prefix automatically, so you can paste the exact token string from NetBox.

Every static file—inventory YAML/TOML/JSON, kore.yaml, pipelines—supports ${…} interpolation. Reference environment variables, vault secrets, or other inventory data. Syntax and namespaces are documented in docs/INTERPOLATION.md.

Logging & Diagnostics

All commands expose consistent logging flags:

  • -v / -vv / -vvv raise verbosity to info/debug/trace.
  • -q/--quiet restricts output to warnings (ideal for scripting).
  • --log-level <level> explicitly sets the tracer level.
  • --log-file <path> mirrors stderr logs to a file.

For TextFSM troubleshooting, use the bundled debugger (see below) to step through template states without rerunning live commands.

Running Tasks

SSH

kore run ssh … reuses the inventory’s transport settings (or CLI overrides) with session pooling, fast CLI profiles, and optional TextFSM parsing.

cargo run -- run \
  --runner-timeout-ms 8000 \
  -f groups=core \
  ssh \
  --command "show version" \
  --command "show ip interface brief" \
  --use-textfsm --textfsm-dir templates/textfsm

Enable TextFSM globally via parsers.use_textfsm in kore.yaml or per command with --use-textfsm. Override template detection using --textfsm-command when the executed CLI differs from the canonical template name. Full flag reference: docs/CLI_USAGE.md#ssh.

NETCONF

Run NETCONF RPCs, <get-config>, <edit-config>, and raw payloads over SSH or any registered transport:

cargo run -- run \
  -f name=agg-sw \
  netconf --get \
  --xpath "/if:interfaces-state/interface" \
  --xpath-ns "if=urn:ietf:params:xml:ns:yang:ietf-interfaces" \
  --pretty \
  --output configs/interfaces.xml

Additional subcommands (--get-config, --edit-config, --rpc) support locking, commit confirm, pretty-printing, and per-host output paths. See docs/CLI_USAGE.md#netconf.

HTTP / RESTCONF

Use inventory-defined HTTP transports (RESTCONF, Arista eAPI, custom REST servers) and override headers, auth type, request bodies, and output paths on the CLI. ${host.*} and ${data.*} placeholders expand inside URLs, headers, and JSON payloads, so multi-host REST tasks stay declarative.

Template Rendering

MiniJinja renders Jinja2-compatible templates with the layered inventory data. Without explicit output flags each host renders to configs/<host>/<template>.config (configurable via kore.yaml, --output, --output-root, --output-pattern).

cargo run -- run j2 \
  --template templates/core.j2 \
  --vars vars/site.yaml \
  --group-vars inventory/group_vars \
  --host-vars inventory/host_vars \
  --vars-merge override \
  --trim-blocks \
  --lstrip-blocks \
  --output-root rendered \
  --output-pattern '${host.name}/${template.stem}.txt'

--debug-vars prints the fully merged context to stdout so you can inspect the data the template sees. Full render options are documented in docs/CLI_USAGE.md.

Pipelines

Pipelines package multiple tasks (render, push, verify, archive) into a single YAML/TOML/JSON file with the same semantics as the CLI flags. Each spec describes host selectors, vars, and ordered tasks:

- name: ospf-template
  hosts:
    names: [core1-rt, core2-rt]
    filters: [ "site: nyc" ]
  vars:
    template_dir: templates
  tasks:
    - name: Render
      j2:
        templates:
          - ${template_dir}/interfaces.j2
          - ${template_dir}/ospf.j2
        output-dir: configs
    - name: Push configuration
      ssh:
        config_files:
          - configs/${host.name}/interfaces.config
          - configs/${host.name}/ospf.config
        save_config: true
    - name: Archive
      local:
        commands:
          - tar -czf backups/${host.name}.tar.gz configs/${host.name}

Invoke with cargo run -- run pipeline pipelines/ospf.yaml. Pipelines share the same interpolation engine, vault flags, and logging behavior as the CLI. More examples live in docs/CLI_USAGE.md.

Secrets & Vault

kore vault mirrors Ansible-vault, supporting create/view/edit, encrypt/decrypt, --vault-id, and --ask-vault-password. Files encrypted by KoRE can be read by ansible-vault and vice versa. Configure default IDs/password sources inside kore.yaml:

vault:
  ids:
    - default@env:KORE_VAULT_PASS
    - prod@file:~/.config/kore/prod.vault

Inventories, vars, secrets providers, and pipeline files all understand vault payloads. Use kore test secrets --provider <name> --ref key[#field] to verify provider lookups before wiring them into inventories. Details: docs/SECRETS_VAULT.md.

TextFSM Debugger

Need to troubleshoot a template? The bundled debugger replays raw command output through TextFSM, logging every state/regex so you can see why a rule matched (or failed):

cargo run --bin textfsm-debug -- \
  --platform cisco_ios \
  --command "show ip interface" \
  --input tmp/show_ip_interface.raw \
  --textfsm-dir $NTC_TEMPLATES_DIR \
  --records --json > tmp/show_ip_interface_debug.json

For normal runs, --json (or --json-only) emits newline-delimited JSON for each command with template metadata and parsed records.

Shell Completions

Generate completion scripts for your preferred shell:

cargo run -- completions zsh --output ~/.config/kore/korerc
echo 'source ~/.config/kore/korerc' >> ~/.zshrc

Feedback & Contributions

Issues and merge requests are welcome—especially around new transports, collections, or docs. Spin up a test lab, kick the tires, and let me know what would make KoRE even better for your workflow. Happy automating!