Skip to content

Commit

Permalink
Bumping to v0.3.0 (#30)
Browse files Browse the repository at this point in the history
* Adding lgtm badges

* Refreshing README

* Adding tox

* Refreshing API documentation

* Making pydantic dep more flexible

* Adding extra classifier

* Modifying the nodes_inventory method

* Modifying the nodes_inventory method tests

* Refactoring the Node.create to use the Template endpoint of the API

* Fixing some extra kwargs not needed

* Updating docs and fixing github link

* Bumping to verion 0.3.0
  • Loading branch information
davidban77 authored Sep 11, 2019
1 parent e648447 commit c2ca1fe
Show file tree
Hide file tree
Showing 17 changed files with 823 additions and 578 deletions.
17 changes: 12 additions & 5 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,12 @@ jobs:
- checkout
- restore_cache:
keys:
- deps-{{ checksum "poetry.lock" }}
# - deps-{{ checksum "poetry.lock" }}
- deps-clear
- run:
name: Install Dependencies
command: |
poetry install
- save_cache:
key: deps-{{ checksum "poetry.lock" }}
paths:
- /home/circleci/.cache/pypoetry/virtualenvs
- run:
name: Run flake8
command: |
Expand All @@ -37,6 +34,16 @@ jobs:
name: Run black formatting check
command: |
poetry run black --diff --check .
- run:
name: Run tox
command: |
poetry run tox
- save_cache:
# key: deps-{{ checksum "poetry.lock" }}
key: deps-clear
paths:
- /home/circleci/.cache/pypoetry/virtualenvs
- /home/circleci/.cache/.tox
- run:
name: Running tests
command: |
Expand Down
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@ docs-generate:

docs-show:
cd docs; mkdocs serve

test:
poetry run flake8 .
poetry run black --diff --check .
poetry run tox
poetry run pytest --cov-report=xml --cov=gns3fy tests/
158 changes: 89 additions & 69 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
[![Circle CI](https://circleci.com/gh/davidban77/gns3fy/tree/develop.svg?style=shield&circle-token=:circle-token)](https://circleci.com/gh/davidban77/gns3fy/tree/develop)[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)[![codecov](https://img.shields.io/codecov/c/github/davidban77/gns3fy)](https://codecov.io/gh/davidban77/gns3fy)
[![Circle CI](https://circleci.com/gh/davidban77/gns3fy/tree/develop.svg?style=shield&circle-token=:circle-token)](https://circleci.com/gh/davidban77/gns3fy/tree/develop)[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)[![codecov](https://img.shields.io/codecov/c/github/davidban77/gns3fy)](https://codecov.io/gh/davidban77/gns3fy)[![Total alerts](https://img.shields.io/lgtm/alerts/g/davidban77/gns3fy.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/davidban77/gns3fy/alerts/)[![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/davidban77/gns3fy.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/davidban77/gns3fy/context:python)


# gns3fy
Python wrapper around [GNS3 Server API](http://api.gns3.net/en/2.2/index.html).

Its main objective is to interact with the GNS3 server in a programatic way, so it can be integrated with the likes of Ansible, docker and scripts.
Its main objective is to interact with the GNS3 server in a programatic way, so it can be integrated with the likes of Ansible, docker and scripts. Ideal for network CI/CD pipeline tooling.

## Documentation

Check out the [Documentation](https://davidban77.github.io/gns3fy/) to explore use cases, and the API Reference
Check out the [Documentation](https://davidban77.github.io/gns3fy/) to explore use cases and the API Reference

## Install

Expand All @@ -26,38 +27,54 @@ You can start the library and use the `Gns3Connector` object and the `Project` o
For example:

```python
import gns3fy
>>> import gns3fy
>>> from tabulate import tabulate

# Define the server object to establish the connection
gns3_server = gns3fy.Gns3Connector("http://<server address>:3080")
>>> gns3_server = gns3fy.Gns3Connector("http://<server address>:3080")

# Show the available projects on the server
>>> print(
tabulate(
gns3_server.projects_summary(is_print=False),
headers=["Project Name", "Project ID", "Total Nodes", "Total Links", "Status"],
)
)
"""
Project Name Project ID Total Nodes Total Links Status
-------------- ------------------------------------ ------------- ------------- --------
test2 c9dc56bf-37b9-453b-8f95-2845ce8908e3 10 9 opened
API_TEST 4b21dfb3-675a-4efa-8613-2f7fb32e76fe 6 4 opened
mpls-bgpv2 f5de5917-0ac5-4850-82b1-1d7e3c777fa1 30 40 closed
"""

# Define the lab you want to load and assign the server connector
lab = gns3fy.Project(name="API_TEST", connector=gns3_server)
>>> lab = gns3fy.Project(name="API_TEST", connector=gns3_server)

# Retrieve its information and display
lab.get()

print(lab)
# Project(project_id='4b21dfb3-675a-4efa-8613-2f7fb32e76fe', name='API_TEST', status='opened', ...
>>> lab.get()
>>> print(lab)
"Project(project_id='4b21dfb3-675a-4efa-8613-2f7fb32e76fe', name='API_TEST', status='opened', ...)"

# Access the project attributes
print(f"Name: {lab.name} -- Status: {lab.status} -- Is auto_closed?: {lab.auto_close}")
# Name: API_TEST -- Status: closed -- Is auto_closed?: False
>>> print(f"Name: {lab.name} -- Status: {lab.status} -- Is auto_closed?: {lab.auto_close}")
"Name: API_TEST -- Status: closed -- Is auto_closed?: False"

# Open the project
lab.open()
print(lab.status)
# opened
>>> lab.open()
>>> lab.status
opened

# Verify the stats
print(lab.stats)
# {'drawings': 0, 'links': 4, 'nodes': 6, 'snapshots': 0}
>>> lab.stats
{'drawings': 0, 'links': 4, 'nodes': 6, 'snapshots': 0}

# List the names and status of all the nodes in the project
for node in lab.nodes:
print(f"Node: {node.name} -- Node Type: {node.node_type} -- Status: {node.status}")
# Node: Ethernetswitch-1 -- Node Type: ethernet_switch -- Status: started
# ...
>>> for node in lab.nodes:
... print(f"Node: {node.name} -- Node Type: {node.node_type} -- Status: {node.status}")

"Node: Ethernetswitch-1 -- Node Type: ethernet_switch -- Status: started"
...
```

Take a look at the API documentation for complete information about the attributes retrieved.
Expand All @@ -67,70 +84,73 @@ Take a look at the API documentation for complete information about the attribut
You have access to the `Node` and `Link` objects as well, this gives you the ability to start, stop, suspend the individual element in a GNS3 project.

```python
from gns3fy import Node, Link, Gns3Connector
>>> from gns3fy import Node, Link, Gns3Connector

PROJECT_ID = "<some project id>"
server = Gns3Connector("http://<server address>:3080")
>>> PROJECT_ID = "<some project id>"
>>> server = Gns3Connector("http://<server address>:3080")

alpine1 = Node(project_id=PROJECT_ID, name="alpine-1", connector=server)
>>> alpine1 = Node(project_id=PROJECT_ID, name="alpine-1", connector=server)

alpine1.get()
print(alpine1)
# Node(name='alpine-1', node_type='docker', node_directory= ...
>>> alpine1.get()
>>> print(alpine1)
"Node(name='alpine-1', node_type='docker', node_directory= ...)"

# And you can access the attributes the same way as the project
print(f"Name: {alpine1.name} -- Status: {alpine1.status} -- Console: {alpine1.console}")
# Name: alpine-1 -- Status: started -- Console: 5005
>>> print(f"Name: {alpine1.name} -- Status: {alpine1.status} -- Console: {alpine1.console}")
"Name: alpine-1 -- Status: started -- Console: 5005"

# Stop the node and start (you can just restart it as well)
alpine1.stop()
print(alpine1.status)
# stopped
>>> alpine1.stop()
>>> alpine1.status
stopped

alpine1.start()
print(alpine1.status)
# started
>>> alpine1.start()
>>> alpine1.status
started

# You can also see the Link objects assigned to this node
print(alpine1.links)
# [Link(link_id='4d9f1235-7fd1-466b-ad26-0b4b08beb778', link_type='ethernet', ....
>>> alpine1.links
[Link(link_id='4d9f1235-7fd1-466b-ad26-0b4b08beb778', link_type='ethernet', ...)]

# And in the same way you can interact with a Link object
link1 = alpine1.links[0]
print(f"Link Type: {link1.link_type} -- Capturing?: {link1.capturing} -- Endpoints: {link1.nodes}")
# Link Type: ethernet -- Capturing?: False -- Endpoints: [{'adapter_number': 2, ...
>>> link1 = alpine1.links[0]
>>> print(f"Link Type: {link1.link_type} -- Capturing?: {link1.capturing} -- Endpoints: {link1.nodes}")
"Link Type: ethernet -- Capturing?: False -- Endpoints: [{'adapter_number': 2, ...}]"
```

### Bonus
### Useful functions

You also have some commodity methods like the `nodes_summary` and `links_summary`, that if used with a library like `tabulate` you can see the following:

```python
...
from tabulate import tabulate

nodes_summary = lab.nodes_summary(is_print=False)

print(
tabulate(nodes_summary, headers=["Node", "Status", "Console Port", "ID"])
)
# Node Status Console Port ID
# ---------------- -------- -------------- ------------------------------------
# Ethernetswitch-1 started 5000 da28e1c0-9465-4f7c-b42c-49b2f4e1c64d
# IOU1 started 5001 de23a89a-aa1f-446a-a950-31d4bf98653c
# IOU2 started 5002 0d10d697-ef8d-40af-a4f3-fafe71f5458b
# vEOS-4.21.5F-1 started 5003 8283b923-df0e-4bc1-8199-be6fea40f500
# alpine-1 started 5005 ef503c45-e998-499d-88fc-2765614b313e
# Cloud-1 started cde85a31-c97f-4551-9596-a3ed12c08498

links_summary = lab.links_summary(is_print=False)
print(
tabulate(links_summary, headers=["Node A", "Port A", "Node B", "Port B"])
)
# Node A Port A Node B Port B
# -------------- ----------- ---------------- -----------
# IOU1 Ethernet1/0 IOU2 Ethernet1/0
# vEOS-4.21.5F-1 Management1 Ethernetswitch-1 Ethernet0
# vEOS-4.21.5F-1 Ethernet1 alpine-1 eth0
# Cloud-1 eth1 Ethernetswitch-1 Ethernet7

>>> from tabulate import tabulate

>>> nodes_summary = lab.nodes_summary(is_print=False)

>>> print(
... tabulate(nodes_summary, headers=["Node", "Status", "Console Port", "ID"])
... )
"""
Node Status Console Port ID
---------------- -------- -------------- ------------------------------------
Ethernetswitch-1 started 5000 da28e1c0-9465-4f7c-b42c-49b2f4e1c64d
IOU1 started 5001 de23a89a-aa1f-446a-a950-31d4bf98653c
IOU2 started 5002 0d10d697-ef8d-40af-a4f3-fafe71f5458b
vEOS-4.21.5F-1 started 5003 8283b923-df0e-4bc1-8199-be6fea40f500
alpine-1 started 5005 ef503c45-e998-499d-88fc-2765614b313e
Cloud-1 started cde85a31-c97f-4551-9596-a3ed12c08498
"""
>>> links_summary = lab.links_summary(is_print=False)
>>> print(
... tabulate(links_summary, headers=["Node A", "Port A", "Node B", "Port B"])
... )
"""
Node A Port A Node B Port B
-------------- ----------- ---------------- -----------
IOU1 Ethernet1/0 IOU2 Ethernet1/0
vEOS-4.21.5F-1 Management1 Ethernetswitch-1 Ethernet0
vEOS-4.21.5F-1 Ethernet1 alpine-1 eth0
Cloud-1 eth1 Ethernetswitch-1 Ethernet7
"""
```
17 changes: 16 additions & 1 deletion docs/content/about/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Upgrading

```
pip install -U gns3fy
```

# Releases

## 0.3.0

**Enhacement:**

- `tox` for pipeline testing. https://github.com/davidban77/gns3fy/pull/15
- `projects_summary` and `templates_summary` methods for `Gns3Connector`. https://github.com/davidban77/gns3fy/pull/17
- Improved `nodes_inventory` method. https://github.com/davidban77/gns3fy/pull/23
- Refactor of `Node` creation, basically changed the API endpoint from Node to Template. https://github.com/davidban77/gns3fy/pull/27

## 0.2.0

**New features:**
Expand All @@ -16,7 +31,7 @@

## 0.1.1

**Enhancement**
**Enhancement:**
- Adding `Gns3Connector` method `get_version`

## 0.1.0
Expand Down
Loading

0 comments on commit c2ca1fe

Please sign in to comment.