Compare commits

..
10 Commits
Author SHA1 Message Date
Mattijs Vanhaverbeke 31a8c756e2 package info 2022-08-03 14:07:51 +02:00
Mattijs Vanhaverbeke ce39c98396 bump version 2022-08-03 12:07:58 +02:00
mattieserver faf156a6b2 133 enhancement bubbletext (#136)
* added extra fields to popup

* open new tab with device info
2022-08-03 11:46:37 +02:00
mattieserver 1b36b9e7df added extra check (#135) 2022-08-03 10:59:02 +02:00
mattieserver 652a44437e Create SECURITY.md 2022-07-29 09:33:15 +02:00
mattieserver 76141e70ce update gh actions 2022-06-30 22:47:55 +02:00
mattieserver 76b4f6ac9a Create docker-publish.yml 2022-06-30 22:40:18 +02:00
mattieserver 953d7480af add dockerfile (#130) 2022-06-30 22:39:18 +02:00
Mattijs Vanhaverbeke f323278f00 bump version 2022-06-30 22:22:47 +02:00
mattieserver 56a6f22bf6 added site to device tooltip (#128) 2022-06-30 22:18:35 +02:00
12 changed files with 160 additions and 16 deletions
+93
View File
@@ -0,0 +1,93 @@
name: Docker
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
on:
schedule:
- cron: '35 10 * * *'
push:
branches: [ "master" ]
# Publish semver tags as releases.
tags: [ 'v*.*.*' ]
pull_request:
branches: [ "master" ]
env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Install the cosign tool except on PR
# https://github.com/sigstore/cosign-installer
- name: Install cosign
if: github.event_name != 'pull_request'
uses: sigstore/cosign-installer@7e0881f8fe90b25e305bbf0309761e9314607e25
with:
cosign-release: 'v1.9.0'
# Workaround: https://github.com/docker/build-push-action/issues/461
- name: Setup Docker buildx
uses: docker/setup-buildx-action@79abd3f86f79a9d68a23c75a09a9a85889262adf
# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@ac9327eae2b366085ac7f6a2d02df8aa8ead720a
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# Sign the resulting Docker image digest except on PRs.
# This will only write to the public Rekor transparency log when the Docker
# repository is public to avoid leaking data. If you would like to publish
# transparency data even for private images, pass --force to cosign below.
# https://github.com/sigstore/cosign
- name: Sign the published Docker image
if: ${{ github.event_name != 'pull_request' }}
env:
COSIGN_EXPERIMENTAL: "true"
# This step uses the identity token to provision an ephemeral certificate
# against the sigstore community Fulcio instance.
run: cosign sign ${{ steps.meta.outputs.tags }}@${{ steps.build-and-push.outputs.digest }}
+11 -11
View File
@@ -5,7 +5,7 @@ name: Upload Python Package
on:
release:
types: [created]
types: [published]
jobs:
deploy:
@@ -13,19 +13,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v1
uses: actions/setup-python@v3
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Build and publish
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
python setup.py sdist bdist_wheel
twine upload dist/*
pip install build
- name: Build package
run: python -m build
- name: Publish package
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
+4
View File
@@ -0,0 +1,4 @@
FROM netboxcommunity/netbox:latest
COPY ./docker/plugin_requirements.txt /
RUN /opt/netbox/venv/bin/pip install --no-warn-script-location -r /plugin_requirements.txt
+13
View File
@@ -0,0 +1,13 @@
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| > 2.0 | :white_check_mark: |
| < 2.0 | :x: |
## Reporting a Vulnerability
Please create an issue when you encounter a Security issue.
+1
View File
@@ -0,0 +1 @@
netbox-topology-views
+1 -1
View File
@@ -4,7 +4,7 @@ class TopologyViewsConfig(PluginConfig):
name = 'netbox_topology_views'
verbose_name = 'Topology views'
description = 'An plugin to render topology maps'
version = '2.0.0'
version = '2.0.2'
author = 'Mattijs Vanhaverbeke'
author_email = 'author@example.com'
base_url = 'netbox_topology_views'
@@ -1 +1 @@
var graph=null,container=null,downloadButton=null,MIME_TYPE="image/png",canvas=null,csrftoken=null,nodes=new vis.DataSet,edges=new vis.DataSet,options={interaction:{hover:!0,hoverConnectedEdges:!0,multiselect:!1},nodes:{shape:"image",brokenImage:"../../static/netbox_topology_views/img/role-unknown.png",size:35,font:{multi:"md",face:"helvetica"}},edges:{length:100,width:2,font:{face:"helvetica"},shadow:{enabled:!0}},physics:{solver:"forceAtlas2Based"}},selected_regions=[],selected_sites=[],coord_save_checkbox=null,htmlElement=null;function getCookie(e){var t=null;if(document.cookie&&""!==document.cookie)for(var o=document.cookie.split(";"),n=0;n<o.length;n++){var d=o[n].trim();if(d.substring(0,e.length+1)===e+"="){t=decodeURIComponent(d.substring(e.length+1));break}}return t}function htmlTitle(e){return(container=document.createElement("div")).innerHTML=e,container}function addEdge(e){e.title=htmlTitle(e.title),edges.add(e)}function addNode(e){e.title=htmlTitle(e.title),nodes.add(e)}function iniPlotboxIndex(){document.addEventListener("DOMContentLoaded",function(){csrftoken=getCookie("csrftoken"),container=document.getElementById("visgraph"),htmlElement=document.getElementsByTagName("html")[0],downloadButton=document.getElementById("btnDownloadImage"),handleLoadData(),btnFullView=document.getElementById("btnFullView"),coord_save_checkbox=document.getElementById("id_save_coords")},!1)}function performGraphDownload(){var e=document.createElement("a"),t=canvas.toDataURL(MIME_TYPE);e.href=t,e.download="topology",document.body.appendChild(e),e.click(),document.body.removeChild(e)}function handleLoadData(){null!==topology_data&&("dark"==htmlElement.dataset.netboxColorMode&&(options.nodes.font.color="#fff"),graph=null,nodes=new vis.DataSet,edges=new vis.DataSet,graph=new vis.Network(container,{nodes:nodes,edges:edges},options),topology_data.edges.forEach(addEdge),topology_data.nodes.forEach(addNode),graph.fit(),canvas=document.getElementById("visgraph").getElementsByTagName("canvas")[0],downloadButton.onclick=function(e){return performGraphDownload(),!1},graph.on("dragEnd",function(e){if(dragged=this.getPositions(e.nodes),coord_save_checkbox.checked&&0!==Object.keys(dragged).length)for(dragged_device in dragged){var t=dragged_device,o=new XMLHttpRequest;o.open("PATCH","/api/plugins/netbox_topology_views/save-coords/save_coords/"),o.setRequestHeader("X-CSRFToken",csrftoken),o.setRequestHeader("Accept","application/json"),o.setRequestHeader("Content-Type","application/json"),o.onreadystatechange=function(){4===o.readyState&&(console.log(o.status),console.log(o.responseText))};var n=JSON.stringify({node_id:t,x:dragged[t].x,y:dragged[t].y});o.send(n)}}))}
var graph=null,container=null,downloadButton=null,MIME_TYPE="image/png",canvas=null,csrftoken=null,nodes=new vis.DataSet,edges=new vis.DataSet,options={interaction:{hover:!0,hoverConnectedEdges:!0,multiselect:!1},nodes:{shape:"image",brokenImage:"../../static/netbox_topology_views/img/role-unknown.png",size:35,font:{multi:"md",face:"helvetica"}},edges:{length:100,width:2,font:{face:"helvetica"},shadow:{enabled:!0}},physics:{solver:"forceAtlas2Based"}},selected_regions=[],selected_sites=[],coord_save_checkbox=null,htmlElement=null;function getCookie(e){var o=null;if(document.cookie&&""!==document.cookie)for(var t=document.cookie.split(";"),n=0;n<t.length;n++){var d=t[n].trim();if(d.substring(0,e.length+1)===e+"="){o=decodeURIComponent(d.substring(e.length+1));break}}return o}function htmlTitle(e){return(container=document.createElement("div")).innerHTML=e,container}function addEdge(e){e.title=htmlTitle(e.title),edges.add(e)}function addNode(e){e.title=htmlTitle(e.title),nodes.add(e)}function iniPlotboxIndex(){document.addEventListener("DOMContentLoaded",function(){csrftoken=getCookie("csrftoken"),container=document.getElementById("visgraph"),htmlElement=document.getElementsByTagName("html")[0],downloadButton=document.getElementById("btnDownloadImage"),handleLoadData(),btnFullView=document.getElementById("btnFullView"),coord_save_checkbox=document.getElementById("id_save_coords")},!1)}function performGraphDownload(){var e=document.createElement("a"),o=canvas.toDataURL(MIME_TYPE);e.href=o,e.download="topology",document.body.appendChild(e),e.click(),document.body.removeChild(e)}function handleLoadData(){null!==topology_data&&("dark"==htmlElement.dataset.netboxColorMode&&(options.nodes.font.color="#fff"),graph=null,nodes=new vis.DataSet,edges=new vis.DataSet,graph=new vis.Network(container,{nodes:nodes,edges:edges},options),topology_data.edges.forEach(addEdge),topology_data.nodes.forEach(addNode),graph.fit(),canvas=document.getElementById("visgraph").getElementsByTagName("canvas")[0],downloadButton.onclick=function(e){return performGraphDownload(),!1},graph.on("dragEnd",function(e){if(dragged=this.getPositions(e.nodes),coord_save_checkbox.checked&&0!==Object.keys(dragged).length)for(dragged_device in dragged){var o=dragged_device,t=new XMLHttpRequest;t.open("PATCH","/api/plugins/netbox_topology_views/save-coords/save_coords/"),t.setRequestHeader("X-CSRFToken",csrftoken),t.setRequestHeader("Accept","application/json"),t.setRequestHeader("Content-Type","application/json"),t.onreadystatechange=function(){4===t.readyState&&(console.log(t.status),console.log(t.responseText))};var n=JSON.stringify({node_id:o,x:dragged[o].x,y:dragged[o].y});t.send(n)}}),graph.on("doubleClick",function(e){for(selected_device in console.log(e.nodes),selected_devices=e.nodes,selected_devices)console.log(selected_device),console.log(selected_devices[selected_device]),url="/dcim/devices/"+selected_devices[selected_device]+"/",console.log(url),window.open(url,"_blank")}))}
@@ -147,5 +147,15 @@ function handleLoadData() {
}
}
});
graph.on("doubleClick", function (params) {
console.log(params.nodes);
selected_devices = params.nodes;
for (selected_device in selected_devices) {
url = "/dcim/devices/" + selected_devices[selected_device] + "/";
window.open(url, "_blank");
}
});
}
}
+16
View File
@@ -31,6 +31,17 @@ def create_node(device):
node_content += "<tr><th>Serial: </th><td>" + device.serial + "</td></tr>"
if device.primary_ip is not None:
node_content += "<tr><th>IP Address: </th><td>" + str(device.primary_ip.address) + "</td></tr>"
if device.site is not None:
node_content += "<tr><th>Site: </th><td>" + device.site.name + "</td></tr>"
if device.location is not None:
node_content += "<tr><th>Location: </th><td>" + device.location.name + "</td></tr>"
if device.rack is not None:
node_content += "<tr><th>Rack: </th><td>" + device.rack.name + "</td></tr>"
if device.position is not None:
if device.face is not None:
node_content += "<tr><th>Position: </th><td> {} ({}) </td></tr>".format(device.position, device.face)
else:
node_content += "<tr><th>Position: </th><td>" + device.position + "</td></tr>"
dev_title = "<table> %s </table>" % (node_content)
@@ -125,6 +136,11 @@ def get_topology_data(queryset, hide_unconnected, intermediate_dev_role_ids, end
if path_destination is not None and path_destination.provider_network is None:
# ProviderNetwork not supported at the moment
# $path_destination.cable would be none : there is no cable between a CircuitTermination and ProviderNetwork
if not hasattr(link.termination_b, 'device'):
#CircuitTermination B Missing Device
continue
origin_device = link.termination_b.device
destination_device = path_destination.cable.termination_b.device
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "netbox_topology_views",
"version": "2.0.0",
"version": "2.0.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
+1 -1
View File
@@ -1,7 +1,7 @@
{
"private": true,
"name": "netbox_topology_views",
"version": "2.0.0",
"version": "2.0.2",
"scripts": {
"resources": "gulp build",
"resources_dev": "gulp build_dev"
+8 -1
View File
@@ -1,16 +1,23 @@
from setuptools import setup, find_packages
from os import path
top_level_directory = path.abspath(path.dirname(__file__))
with open(path.join(top_level_directory, 'README.md'), encoding='utf-8') as file:
long_description = file.read()
setup(
name='netbox-topology-views',
version='2.0.0',
version='2.0.2',
description='An NetBox plugin to create Topology maps',
long_description=long_description,
long_description_content_type='text/markdown',
url='https://github.com/mattieserver/netbox-topology-views',
author='Mattijs Vanhaverbeke',
license='Apache 2.0',
install_requires=[],
packages=find_packages(),
include_package_data=True,
keywords=['netbox-plugin'],
classifiers=[
'Programming Language :: Python',
'Programming Language :: Python :: 3',