Skip to content

Commit

Permalink
Merge pull request #4 from napalm-automation/develop
Browse files Browse the repository at this point in the history
Release 1.0.0
  • Loading branch information
ogenstad committed Feb 2, 2019
2 parents de10217 + e82b108 commit 3041445
Show file tree
Hide file tree
Showing 30 changed files with 771 additions and 1 deletion.
67 changes: 67 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]

# C extensions
*.so

# Distribution / packaging
.Python
env/
bin/
build/
develop-eggs/
dist/
eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml

# Translations
*.mo

# Mr Developer
.mr.developer.cfg
.project
.pydevproject

# Rope
.ropeproject

# Django stuff:
*.log
*.pot

# Sphinx documentation
docs/_build/
docs/_static/

.idea
.DS_Store

env
*.swp

test/unit/test_devices.py

report.json
tags
.pytest_cache/

33 changes: 33 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
sudo: required

language: python
python:
- 2.7
- 3.6
- 3.6

matrix:
include:
- python: 3.6
env: TOXENV=black
- python: 3.6
env: TOXENV=pylama

install:
- pip install tox tox-travis coveralls

script:
- tox

deploy:
provider: pypi
user: ogenstad
password:
secure: N1fnrXFMsJ4+uc5hNwSQv4tw7/BNV8Fd/IjTvIbxVocloDAwf7+mnwB6CTj2WrN3B9/2BLWtZj20tcxp7qD6zugWJt4RqnnqCjHAGq2qu2p3SqtHYJ1tCnoJzaNrnrj1Oklyi58dlIR5qv5495Ig+2ghOfg/lRELfZUjuDHoQv7e6E9olGtuDpQ7sqLW4emU/9+gdm6ebE7+V9nuHQA2JGpQcDpqvhbzokCkrn96Xfmvorw9g1fCR6Me0AcsbcMYuCbJJbPJ6iWEdc60PyetT7l68DFDtIIEev91exPUWDYiSQhLDREOoDtCaDyVwJPM4ZHPOgyDveKu02//CMBJMkmYwbm+SapJ9F7JOrQLORKlerTmpRg+pm2ZpzkUb13F545z1CNP+r0+GGWSuci+ALdG3stiFdLf7RF/xxZ5RzYNWyFw6yFt+yEMDHJbkv3yGRNjNK6pNLPlvAmmz76BINplk4NeKz0REffvnEF56MxjqUFr4WA6ieCGF00F+ECifW53cv38h7rP3DPmYSgY4YDAtXTblwkzMYCz8U0Ob4vJgIsPs6YpVN3/tCNI/21rdvYiSpP0wgKQvPt67KuFeVInaHTARjUK3/XZfd/qGNgkrl+TSWAvVvQlhkZTUlJqBvnt23PHnvy3qu5KiBwlu5l+hSUERNiqgBaA8cwd4nA=
distributions: "sdist bdist_wheel"
on:
tags: true
branch: master

after_success:
- coveralls
9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM python:3.6

COPY . /napalm-inspector

RUN pip install /napalm-inspector

ENV FLASK_APP napalm_inspector

ENTRYPOINT flask run --host=0.0.0.0
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include requirements*
graft napalm_inspector/static
graft napalm_inspector/templates
16 changes: 16 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
CONTAINER_NAME := "napalm-inspector"


.PHONY: docker
docker:
docker build . --tag napalm-inspector:latest


.PHONY: start
start: stop
docker run -it --name $(CONTAINER_NAME) -p 5000:5000 napalm-inspector:latest


.PHONY: stop
stop:
@docker rm $(CONTAINER_NAME) -f || exit 0
37 changes: 36 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,36 @@
# napalm-inspector
[![Build Status](https://travis-ci.org/napalm-automation/napalm-inspector.svg?branch=develop)](https://travis-ci.org/napalm-automation/napalm-inspector)
[![Coverage Status](https://coveralls.io/repos/github/napalm-automation/napalm-inspector/badge.svg?branch=develop)](https://coveralls.io/github/napalm-automation/napalm-inspector?branch=develop)

NAPALM-Inspector
================

The NAPALM Inspector is a web application aimed to help with troubleshooting the getters in NAPALM. If you have found a bug in one of the getters you can use this tool as an easy way to help the developers figure out what's going on.

Once the application is up and running visit [http://127.0.0.1:5000](http://127.0.0.1:5000) and choose the platform and getter you want to test. You will be asked to provide the information your network devices, i.e. when the application will ask you for the output from a command like `show version` then you just paste the output into the form and move on from there.

Installation
============

```bash
pip install napalm-inspector
export FLASK_APP=napalm_inspector
flask run
```

Running from Docker
===================

```bash
git clone https://github.com/napalm-automation/napalm-inspector
cd napalm-inspector
make docker
make start
```

Press Control+C to end the application when done.

Once you are done you can remove the container

```bash
make stop
```
15 changes: 15 additions & 0 deletions napalm_inspector/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from flask import Flask


def create_app():
app = Flask(__name__)

from napalm_inspector.errors import bp as errors_bp

app.register_blueprint(errors_bp)

from napalm_inspector.main import bp as main_bp

app.register_blueprint(main_bp)

return app
34 changes: 34 additions & 0 deletions napalm_inspector/drivers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from builtins import super
from napalm_inspector.exceptions import MissingData
from napalm.ios import IOSDriver
from napalm.nxos_ssh import NXOSSSHDriver
import re


class DummyDevice:

def __init__(self, data):
self.data = data

def send_command(self, command):
label = re.sub(r"[\[\]\*\^\+\s\|]", "_", command)
if label not in self.data:
raise MissingData(command)

return self.data[label]


class OfflineIOSDriver(IOSDriver):

def __init__(self, data):
super().__init__("127.0.0.1", "", "")
self.device = DummyDevice(data)


class OfflineNXOSSSHDriver(NXOSSSHDriver):

def __init__(self, data):
self.device = DummyDevice(data)


test_drivers = {"ios": OfflineIOSDriver, "nxos_ssh": OfflineNXOSSSHDriver}
5 changes: 5 additions & 0 deletions napalm_inspector/errors/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from flask import Blueprint

bp = Blueprint("errors", __name__)

from napalm_inspector.errors import handlers # noqa
7 changes: 7 additions & 0 deletions napalm_inspector/errors/handlers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from flask import render_template
from . import bp


@bp.app_errorhandler(404)
def not_found_error(error):
return render_template("404.html"), 404
8 changes: 8 additions & 0 deletions napalm_inspector/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import re


class MissingData(Exception):

def __init__(self, request):
self.request = request
self.request_id = re.sub(r"[\[\]\*\^\+\s\|]", "_", request)
5 changes: 5 additions & 0 deletions napalm_inspector/main/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from flask import Blueprint

bp = Blueprint("main", __name__)

from napalm_inspector.main import routes # noqa
74 changes: 74 additions & 0 deletions napalm_inspector/main/routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from napalm_inspector.exceptions import MissingData
from napalm_inspector.main import bp
from napalm_inspector.drivers import test_drivers
from flask import render_template, request
import json
import traceback


@bp.route("/")
def index():
"""Main page."""
return render_template("index.html")


@bp.route("/test-getters/")
def getters():
drivers = list(test_drivers.keys())
return render_template("test_getter_platforms.html", drivers=drivers)


@bp.route("/test-getters/<platform>/")
def platform(platform):
"""Main page."""

driver = test_drivers[platform]

napalm_getters = [g for g in dir(driver) if g.startswith("get_")]
return render_template("platform.html", platform=platform, getters=napalm_getters)


@bp.route("/test-getters/<platform>/<getter>", methods=["GET", "POST"])
def getter(platform, getter):
"""Getter test."""
tb = None
exception = None
data = None
missing_command = None
missing_command_id = None
input_data = {}
form_data = []
if request.method == "POST":
for entry in request.form:
input_data[entry] = request.form[entry].replace("\r\n", "\n")
command = {}
command["id"] = entry
command["data"] = request.form[entry]
form_data.append(command)

driver = test_drivers[platform]
dev = driver(input_data)

func = getattr(dev, getter)
try:
data = func()
data = json.dumps(data, indent=4, sort_keys=True)

except MissingData as e:
missing_command = e.request
missing_command_id = e.request_id
except Exception as e:
tb = traceback.format_exc()
exception = e

return render_template(
"getter.html",
getter=getter,
data=data,
traceback=tb,
exception=exception,
form_data=form_data,
missing_command=missing_command,
missing_command_id=missing_command_id,
platform=platform,
)
Binary file added napalm_inspector/static/favicon-default.ico
Binary file not shown.
Binary file added napalm_inspector/static/logo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions napalm_inspector/static/napalm.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
body {
padding-top: 8rem;
}

.napalm-center {
padding: 3rem 1.5rem;
text-align: center;
}


11 changes: 11 additions & 0 deletions napalm_inspector/templates/404.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% extends "base.html" %}


{% block content %}
<div class="napalm-center">
<h1>404</h1>
<p>Not even close, that page doesn't exist</p>
</div>

{% endblock %}

0 comments on commit 3041445

Please sign in to comment.