Skip to content
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,32 @@ Hier Config is compatible with any NOS that utilizes a structured CLI syntax sim

The code documentation can be found at: [Hier Config documentation](https://hier-config.readthedocs.io/en/latest/).

Installation
============
## Highlights

- Predict the device state before deploying (`future()`) and generate accurate rollbacks that now preserve distinct structural commands—BGP neighbor descriptions, for example, no longer collapse when multiple peers share a common prefix.
- Build remediation workflows with deterministic diffs across Cisco-style and Junos-style configuration syntaxes.

## Installation

### PIP

Install from PyPi:

```shell
pip install hier-config
```

Quick Start
===========
## Quick Start

### Step 1: Import Required Classes

```python
from hier_config import WorkflowRemediation, get_hconfig, Platform
from hier_config.utils import read_text_from_file
```

### Step 2: Load Configurations

Load the running and intended configurations as strings:

```python
Expand All @@ -48,6 +54,7 @@ generated_config_text = read_text_from_file("./tests/fixtures/generated_config.c
```

### Step 3: Create HConfig Objects

Specify the device platform (e.g., `Platform.CISCO_IOS`):

```python
Expand All @@ -56,6 +63,7 @@ generated_config = get_hconfig(Platform.CISCO_IOS, generated_config_text)
```

### Step 4: Initialize WorkflowRemediation

Compare configurations and generate remediation steps:

```python
Expand Down
42 changes: 30 additions & 12 deletions docs/drivers.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ In Hier Config, the rules within a driver are organized into sections, each targ
---

### 1. Negation Rules

**Purpose**: Define how to negate commands or reset them to a default state.

- **Models**:
Expand All @@ -95,6 +96,7 @@ In Hier Config, the rules within a driver are organized into sections, each targ
---

### 2. Sectional Exiting

**Purpose**: Manage hierarchical configuration sections by defining commands for properly exiting each section.

- **Models**:
Expand All @@ -105,6 +107,7 @@ In Hier Config, the rules within a driver are organized into sections, each targ
---

### 3. Ordering

**Purpose**: Assign weights to commands to control the order of operations during configuration application.

- **Models**:
Expand All @@ -115,6 +118,7 @@ In Hier Config, the rules within a driver are organized into sections, each targ
---

### 4. Per-Line Substitutions

**Purpose**: Modify or clean up specific lines in the configuration.

- **Models**:
Expand All @@ -128,6 +132,7 @@ In Hier Config, the rules within a driver are organized into sections, each targ
---

### 5. Idempotent Commands

**Purpose**: Ensure commands are not repeated unnecessarily in the configuration.

- **Models**:
Expand All @@ -140,6 +145,7 @@ In Hier Config, the rules within a driver are organized into sections, each targ
---

### 6. Post-Processing Callbacks

**Purpose**: Apply additional transformations after initial configuration processing.

- **Implementation**:
Expand All @@ -148,6 +154,7 @@ In Hier Config, the rules within a driver are organized into sections, each targ
---

### 7. Tagging and Overwriting

**Purpose**: Apply tags to configuration lines or define overwriting behavior for specific sections.

- **Models**:
Expand All @@ -164,6 +171,7 @@ In Hier Config, the rules within a driver are organized into sections, each targ
---

### 8. Indentation Adjustments

**Purpose**: Define start and end points for adjusting indentation within configurations.

- **Models**:
Expand All @@ -174,6 +182,7 @@ In Hier Config, the rules within a driver are organized into sections, each targ
---

### 9. Match Rules

**Purpose**: Provide a flexible way to define conditions for matching configuration lines.

- **Models**:
Expand All @@ -187,6 +196,7 @@ In Hier Config, the rules within a driver are organized into sections, each targ
---

### 10. Instance Metadata

**Purpose**: Manage metadata for configuration instances, such as tags and comments.

- **Models**:
Expand All @@ -198,6 +208,7 @@ In Hier Config, the rules within a driver are organized into sections, each targ
---

### 11. Dumping Configuration

**Purpose**: Represent and handle the output of processed configuration lines.

- **Models**:
Expand Down Expand Up @@ -387,8 +398,8 @@ driver.rules.idempotent_commands.append(

#### Explanation

* **Dynamic Rule Extension:** You directly modify the driver.rules attributes to append new rules dynamically.
* **Flexibility:** This approach is useful when the driver is instantiated by external code, and subclassing is not feasible.
- **Dynamic Rule Extension:** You directly modify the driver.rules attributes to append new rules dynamically.
- **Flexibility:** This approach is useful when the driver is instantiated by external code, and subclassing is not feasible.

Both approaches allow you to extend the functionality of the Cisco IOS driver:

Expand All @@ -406,15 +417,17 @@ This guide walks you through the process of creating a custom driver using the `
The `HConfigDriverBase` class provides a foundation for defining driver-specific rules and behaviors. It encapsulates configuration rules and methods for handling idempotency, negation, and more. You will extend this class to create a new driver.

Key Components:

1. **`HConfigDriverRules`**: A collection of rules for handling configuration logic.
2. **Methods to Override**: Define custom behavior by overriding the `_instantiate_rules` method.
3. **Properties**: Adjust behavior for negation and declaration prefixes.
1. **Methods to Override**: Define custom behavior by overriding the `_instantiate_rules` method.
1. **Properties**: Adjust behavior for negation and declaration prefixes.

---

### Steps to Create a Custom Driver

#### Step 1: Subclass `HConfigDriverBase`

Begin by subclassing `HConfigDriverBase` to define a new driver.

```python
Expand Down Expand Up @@ -472,6 +485,7 @@ class CustomHConfigDriver(HConfigDriverBase):
```

#### Step 2: Customize Negation or Declaration Prefixes (Optional)

Override the `negation_prefix` or `declaration_prefix` properties to customize their behavior.

```python
Expand Down Expand Up @@ -547,7 +561,7 @@ workflow = WorkflowRemediation(running_config, generated_config)
### Key Methods in HConfigDriverBase

1. `idempotent_for`:
* Matches configurations against idempotent rules to prevent duplication.
- Matches configurations against idempotent rules to prevent duplication.

```python
def idempotent_for(
Expand All @@ -558,29 +572,30 @@ def idempotent_for(
...
```

2. `negate_with`:
* Provides a negation command based on rules.
1. `negate_with`:
- Provides a negation command based on rules.

```python
def negate_with(self, config: HConfigChild) -> Optional[str]:
...
```

3. `swap_negation`:
* Toggles the negation of a command.
1. `swap_negation`:
- Toggles the negation of a command.

```python
def swap_negation(self, child: HConfigChild) -> HConfigChild:
...
```

4. Properties:
* `negation_prefix`: Default is `"no "`.
* `declaration_prefix`: Default is `""`.
1. Properties:
- `negation_prefix`: Default is `"no "`.
- `declaration_prefix`: Default is `""`.

### Example Rule Definitions

#### Negation Rules

Define commands that require specific negation handling:

```python
Expand All @@ -593,6 +608,7 @@ negate_with=[
```

#### Sectional Exiting

Define how to exit specific configuration sections:

```python
Expand All @@ -608,6 +624,7 @@ sectional_exiting=[
```

#### Command Ordering

Set the execution order of specific commands:

```python
Expand All @@ -620,6 +637,7 @@ ordering=[
```

#### Per-Line Substitution

Clean up unwanted lines in the configuration:

```python
Expand Down
17 changes: 17 additions & 0 deletions docs/future-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ post_change_2_config = post_change_1_config.future(change_2_config)
change_2_rollback_config = post_change_2_config.config_to_get_to(post_change_1_config)
```


Currently, this algorithm does not account for:

- negate a numbered ACL when removing an item
Expand All @@ -35,6 +36,22 @@ Currently, this algorithm does not account for:
- idempotent_acl_check
- and likely others

## Structural Idempotency Matching

Starting in version 3.3.1, Hier Config derives a structural "idempotency key" from
each command’s lineage when evaluating [`IdempotentCommandsRule`](drivers.md).
This prevents unrelated lines that happen to share a prefix from being treated as
duplicates during `future()` predictions. For example, distinct BGP neighbor
descriptions such as `neighbor 2.2.2.2 description neighbor2` and
`neighbor 3.3.3.3 description neighbor3` now remain in the predicted future
configuration because their identities differ within the `neighbor` hierarchy.

> **Tip:** When creating driver rules, ensure your `MatchRule` definitions capture
> the structural parts of the command that should be unique (for instance, via
> regex capture groups or specific `startswith` clauses). This allows the
> idempotency engine to distinguish between commands that only vary by attributes
> such as IP address or description text.

```bash
>>> from hier_config import get_hconfig, Platform
>>> from hier_config.utils import read_text_from_file
Expand Down
Loading