Skip to main content

jnprsr is a Parser for Juniper Configuration Files

Project description

jnprsr

PyPI Version

jnprsr ('ʤunəpɑrsər) is a Parser for Juniper configuration files.

It is based around a Lexer and Parser built using ANTLR4 (https://www.antlr.org/). The formal grammar used in our project was initially created by the batfish (https://github.com/batfish/batfish) project.

Our tool allows to generate an Abstract Syntax Tree (AST) from a given Juniper configuration file. This AST can then be processed further. Currently, we provide the following functions:

  • Pretty-Printing
  • Configuration Merge
  • Sub-Tree Selection

The AST generated by our implementation uses a data-type provided by the anytree (https://github.com/c0fec0de/anytree) library. You can easily process the AST generated by our implementation and use it in our own tools.

We have presented jnprsr at the DENOG Meetup 2025-01 in Frankfurt:

IMAGE ALT TEXT HERE

Slides

Please note: This is currently still a beta release. This product comes with absolutely no warranty. It is neither supported nor endorsed in any way by Juniper Networks Inc. We assume no liability for any undesired or incorrect behavior you might experience with this software. If you break your network using jnprsr, it is your responsibility and you should be ashamed of yourself for not testing your software properly.

Installation

You can install jnprsr using pip:

pip install jnprsr

You can also install directly from Git:

pip install git+https://github.com/markusju/jnprsr.git

TL;DR - What you can do with jnprsr

Pretty-Printing

It allows you to transform a configuration file looking like this

interfaces { et-0/0/0 {description "More Bandwidth!"; unit 0 {family inet{address 192.0.2.1/24;}}}}

into this

interfaces {
    et-0/0/0 {
        description "More Bandwidth!";
        unit 0 {
            family inet {
                address 192.0.2.1/24;
            }
        }
    }
}

Configuration Merge

Suppose you have this snippet

interfaces {
    et-0/0/0 {
        description "Skynet NNI";
    }
}

and this target configuration

interfaces {
    et-0/0/0 {
        unit 0 {
            family inet {
                address 192.0.2.1/24;
            } 
        }
    }
}

using jnprsr you can perform a > load merge operation on the target configuration with the snippet to generate this:

interfaces {
    et-0/0/0 {
        description "Skynet NNI";
        unit 0 {
            family inet {
                address 192.0.2.1/24;
            } 
        }
    }
}

Sub-Tree Selection

Let's say you have this configuration file:

protocols {
    bgp {
        group SKYNET-PEER {
            type external;
            peer-as 1337;
            neighbor 1.2.3.4;
        }
        group EVILCORP-PEER {
            type external;
            peer-as 1338;
            neighbor 1.2.3.5;
        }
        group UMBRELLACORP-PEER {
            type external;
            peer-as 1339;
            neighbor 1.2.3.6;
        }
    }
}

and you want to access the sub-tree of the SKYNET-PEER BGP peer-group.

Using jnprsr you can easily perform the equivalent of > show configuration protocols bgp group SKYNET-PEER:

protocols {
    bgp {
        group SKYNET-PEER {
            type external;
            peer-as 1337;
            neighbor 1.2.3.4;
        }
    }
}

Other Stuff

Since jnprsr creates an anytree object, you can easily work with the parsed configuration data. Some things you could do include, but are not limited to:

  • Validation and/or Verification: Does a certain configuration element or sub-tree exist?
  • Comparison: Comparing two given configurations, what nodes are different?
  • Editing: Create, Remove, Change a given configuration and generate textual output from the changed tree again.

Getting Started

On the shell

jnprsr currently comes with 3 commands that you can use on your shell:

  • jnprsr-pretty
  • jnprsr-subtree
  • jnprsr-merge

jnprsr-pretty

is a pretty printer. You can supply a Juniper Configuration file and it will pretty print the received configuration. Meaning that the configuration is returned with the proper indentation and spacing. You can use the script interactively. Simply call it and then paste the configuration. You can end your input on an empty new line with CTRL+D or by typing !END.

$ jnprsr-pretty
[Type CTRL+D or '!END' at a new line to end input]
interfaces { et-0/0/0 {description "More Bandwidth!"; unit 0 {family inet{address 192.0.2.1/24;}}}}
interfaces {
    et-0/0/0 {
        description "More Bandwidth!";
        unit 0 {
            family inet {
                address 192.0.2.1/24;
            }
        }
    }
}

Alternatively you can also simply pipe your messed up config at the script to make it pretty. In this case you do not need to end the input. Note that we are using the -s flag in this example. This silences any additional output, so that you can process the output more easily.

$ cat what-a-mess.txt | jnprsr-pretty -s
interfaces {
    et-0/0/0 {
        description "More Bandwidth!";
        unit 0 {
            family inet {
                address 192.0.2.1/24;
            }
        }
    }
}

jnprsr-subtree

is an interactive CLI allowing you to navigate a configuration (almost) as if you are working on a real device. Once you have loaded the configuration from a file, you can use the auto-completion function using the <TAB> key. You can navigate to a suggestion using the arrow keys. This script can be helpful when navigating large configuration files.

GIF showing the interactive use of jnprsr-subtree

jnprsr-merge

allow you to merge a given configuration onto another configuration. It behaves like a load merge operation on an existing configuration.

$ cat test1.txt
system {
    host-name "test";
}
$ cat test2.txt
system {
    name-server {
        10.4.3.222;
    }
}
$ jnprsr-merge test1.txt test2.txt
system {
    host-name "test";
    name-server {
        10.4.3.222;
    }
}

In your python script

You can easily use jnprsr in your own scripts. For this you will almost always start with the get_ast() function. It will parse a given string and return an object of the type JuniperASTNode. This datatype inherits properties from the anytree NodeMixin type. So you can work with this object the same way you would work with an anytree tree. For ease of use we have created some helper functions that allow

import jnprsr

config = "system { host-name "test"; }"
ast = jnprsr.get_ast(config)

For ease of use we have created some Juniper Configuration specific helper functions:

  • render_config_from_ast(ast: JuniperASTNode) -> str
    • This will return a textual representation of the AST, meaning it will converted back into configuration text.
  • render_ascii_tree_from_ast(ast: JuniperASTNode) -> str
    • This will return an ascii tree representing the AST, because why not? :)
  • render_dict_from_ast(ast: JuniperASTNode) -> dict
    • This will return a dictionary from a given configuration file.
  • merge(ast1, ast2) -> JuniperASTNode
    • This will merge ast2 onto ast1
  • get_sub_tree(ast: JuniperASTNode, path: str) -> JuniperASTNode
    • This will return the subtree at specified path, for example 'interfaces et-0/0/0'

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jnprsr-0.1.2.tar.gz (30.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jnprsr-0.1.2-py3-none-any.whl (27.7 kB view details)

Uploaded Python 3

File details

Details for the file jnprsr-0.1.2.tar.gz.

File metadata

  • Download URL: jnprsr-0.1.2.tar.gz
  • Upload date:
  • Size: 30.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for jnprsr-0.1.2.tar.gz
Algorithm Hash digest
SHA256 800ead1d4b15162f6d712c1d4cb6bd5fe9baf63ed3b820eb0a0b9398f4e31c5f
MD5 882e3f8adb861007d72bc2a9cfd3f973
BLAKE2b-256 574c0503f80d1f3ac4607833c0cfc133318c2eec9b013f201fd6c6738fba3529

See more details on using hashes here.

Provenance

The following attestation bundles were made for jnprsr-0.1.2.tar.gz:

Publisher: publish.yml on markusju/jnprsr

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file jnprsr-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: jnprsr-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 27.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for jnprsr-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 71ff59c4856841c87a0585ee3391dbc3905a87045b2fc456b7b716d38206fd8c
MD5 2e078a295f4bcfeeb8bb169b25171c46
BLAKE2b-256 b6177126d78962dd1bdb6695819f6562adcde6e9c24ad42a36d4f741a03ddb6e

See more details on using hashes here.

Provenance

The following attestation bundles were made for jnprsr-0.1.2-py3-none-any.whl:

Publisher: publish.yml on markusju/jnprsr

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page