netbox-atlassian 0.2.2__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/PKG-INFO +1 -1
- netbox_atlassian-0.2.4/netbox_atlassian/__init__.py +148 -0
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/netbox_atlassian/atlassian_client.py +32 -26
- netbox_atlassian-0.2.4/netbox_atlassian/templates/netbox_atlassian/endpoint_tab.html +25 -0
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/netbox_atlassian/urls.py +9 -0
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/netbox_atlassian/views.py +150 -0
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/netbox_atlassian.egg-info/PKG-INFO +1 -1
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/netbox_atlassian.egg-info/SOURCES.txt +1 -0
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/pyproject.toml +1 -1
- netbox_atlassian-0.2.2/netbox_atlassian/__init__.py +0 -74
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/README.md +0 -0
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/netbox_atlassian/forms.py +0 -0
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/netbox_atlassian/navigation.py +0 -0
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/netbox_atlassian/templates/netbox_atlassian/device_tab.html +0 -0
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/netbox_atlassian/templates/netbox_atlassian/settings.html +0 -0
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/netbox_atlassian/templates/netbox_atlassian/tab_content.html +0 -0
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/netbox_atlassian/templates/netbox_atlassian/vm_tab.html +0 -0
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/netbox_atlassian.egg-info/dependency_links.txt +0 -0
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/netbox_atlassian.egg-info/requires.txt +0 -0
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/netbox_atlassian.egg-info/top_level.txt +0 -0
- {netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/setup.cfg +0 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"""
|
|
2
|
+
NetBox Atlassian Plugin
|
|
3
|
+
|
|
4
|
+
Display Jira issues and Confluence pages related to devices in NetBox.
|
|
5
|
+
Searches by configurable fields (hostname, serial, role, etc.) with OR logic.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
|
|
10
|
+
from netbox.plugins import PluginConfig
|
|
11
|
+
|
|
12
|
+
__version__ = "0.2.4"
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AtlassianConfig(PluginConfig):
|
|
18
|
+
"""Plugin configuration for NetBox Atlassian integration."""
|
|
19
|
+
|
|
20
|
+
name = "netbox_atlassian"
|
|
21
|
+
verbose_name = "Atlassian"
|
|
22
|
+
description = "Display Jira issues and Confluence pages related to devices"
|
|
23
|
+
version = __version__
|
|
24
|
+
author = "sieteunoseis"
|
|
25
|
+
author_email = "sieteunoseis@github.com"
|
|
26
|
+
base_url = "atlassian"
|
|
27
|
+
min_version = "4.0.0"
|
|
28
|
+
|
|
29
|
+
# Required settings - plugin won't load without these
|
|
30
|
+
required_settings = []
|
|
31
|
+
|
|
32
|
+
# Default configuration values
|
|
33
|
+
default_settings = {
|
|
34
|
+
# Jira settings (on-prem)
|
|
35
|
+
"jira_url": "", # e.g., "https://jira.example.com"
|
|
36
|
+
"jira_username": "",
|
|
37
|
+
"jira_password": "", # or API token
|
|
38
|
+
"jira_token": "", # Personal Access Token (PAT) - preferred for on-prem
|
|
39
|
+
"jira_verify_ssl": True,
|
|
40
|
+
# Confluence settings (on-prem)
|
|
41
|
+
"confluence_url": "", # e.g., "https://confluence.example.com"
|
|
42
|
+
"confluence_username": "",
|
|
43
|
+
"confluence_password": "", # or API token
|
|
44
|
+
"confluence_token": "", # Personal Access Token (PAT) - preferred for on-prem
|
|
45
|
+
"confluence_verify_ssl": True,
|
|
46
|
+
# Cloud settings (for future use)
|
|
47
|
+
"use_cloud": False,
|
|
48
|
+
"cloud_api_token": "",
|
|
49
|
+
"cloud_email": "",
|
|
50
|
+
# Search configuration
|
|
51
|
+
# Fields to search - values are device attribute paths
|
|
52
|
+
# Searches use OR logic - matches any field
|
|
53
|
+
"search_fields": [
|
|
54
|
+
{"name": "Hostname", "attribute": "name", "enabled": True},
|
|
55
|
+
{"name": "Serial", "attribute": "serial", "enabled": True},
|
|
56
|
+
{"name": "Asset Tag", "attribute": "asset_tag", "enabled": False},
|
|
57
|
+
{"name": "Role", "attribute": "role.name", "enabled": False},
|
|
58
|
+
{"name": "Primary IP", "attribute": "primary_ip4.address", "enabled": False},
|
|
59
|
+
],
|
|
60
|
+
# Endpoint search fields (for netbox-endpoints plugin)
|
|
61
|
+
# Searches use OR logic - matches any field
|
|
62
|
+
"endpoint_search_fields": [
|
|
63
|
+
{"name": "Name", "attribute": "name", "enabled": True},
|
|
64
|
+
{"name": "MAC Address", "attribute": "mac_address", "enabled": True},
|
|
65
|
+
{"name": "Serial", "attribute": "serial", "enabled": True},
|
|
66
|
+
{"name": "Asset Tag", "attribute": "asset_tag", "enabled": False},
|
|
67
|
+
],
|
|
68
|
+
# Jira search settings
|
|
69
|
+
"jira_max_results": 10,
|
|
70
|
+
"jira_projects": [], # Empty = search all projects
|
|
71
|
+
"jira_issue_types": [], # Empty = all types
|
|
72
|
+
# Confluence search settings
|
|
73
|
+
"confluence_max_results": 10,
|
|
74
|
+
"confluence_spaces": [], # Empty = search all spaces
|
|
75
|
+
# General settings
|
|
76
|
+
"timeout": 30,
|
|
77
|
+
"cache_timeout": 300, # Cache results for 5 minutes
|
|
78
|
+
# Enable legacy SSL renegotiation for older servers (required for OHSU wiki)
|
|
79
|
+
"enable_legacy_ssl": False,
|
|
80
|
+
# Device type filtering (like catalyst-center)
|
|
81
|
+
# Empty list = show tab for all devices
|
|
82
|
+
"device_types": [], # e.g., ["cisco", "juniper"]
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
def ready(self):
|
|
86
|
+
"""Register endpoint view if netbox_endpoints is available."""
|
|
87
|
+
super().ready()
|
|
88
|
+
self._register_endpoint_views()
|
|
89
|
+
|
|
90
|
+
def _register_endpoint_views(self):
|
|
91
|
+
"""Register Atlassian tab for Endpoints if plugin is installed."""
|
|
92
|
+
import sys
|
|
93
|
+
|
|
94
|
+
# Quick check if netbox_endpoints is available
|
|
95
|
+
if "netbox_endpoints" not in sys.modules:
|
|
96
|
+
try:
|
|
97
|
+
import importlib.util
|
|
98
|
+
|
|
99
|
+
if importlib.util.find_spec("netbox_endpoints") is None:
|
|
100
|
+
logger.debug("netbox_endpoints not installed, skipping endpoint view registration")
|
|
101
|
+
return
|
|
102
|
+
except Exception:
|
|
103
|
+
logger.debug("netbox_endpoints not available, skipping endpoint view registration")
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
try:
|
|
107
|
+
from django.shortcuts import render
|
|
108
|
+
from netbox.views import generic
|
|
109
|
+
from netbox_endpoints.models import Endpoint
|
|
110
|
+
from utilities.views import ViewTab, register_model_view
|
|
111
|
+
|
|
112
|
+
from .views import should_show_atlassian_tab_endpoint
|
|
113
|
+
|
|
114
|
+
@register_model_view(Endpoint, name="atlassian", path="atlassian")
|
|
115
|
+
class EndpointAtlassianView(generic.ObjectView):
|
|
116
|
+
"""Display Jira issues and Confluence pages for an Endpoint."""
|
|
117
|
+
|
|
118
|
+
queryset = Endpoint.objects.all()
|
|
119
|
+
template_name = "netbox_atlassian/endpoint_tab.html"
|
|
120
|
+
|
|
121
|
+
tab = ViewTab(
|
|
122
|
+
label="Atlassian",
|
|
123
|
+
weight=9100,
|
|
124
|
+
permission="netbox_endpoints.view_endpoint",
|
|
125
|
+
hide_if_empty=False,
|
|
126
|
+
visible=should_show_atlassian_tab_endpoint,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
def get(self, request, pk):
|
|
130
|
+
endpoint = Endpoint.objects.get(pk=pk)
|
|
131
|
+
return render(
|
|
132
|
+
request,
|
|
133
|
+
self.template_name,
|
|
134
|
+
{
|
|
135
|
+
"object": endpoint,
|
|
136
|
+
"tab": self.tab,
|
|
137
|
+
"loading": True,
|
|
138
|
+
},
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
logger.info("Registered Atlassian tab for Endpoint model")
|
|
142
|
+
except ImportError:
|
|
143
|
+
logger.debug("netbox_endpoints not installed, skipping endpoint view registration")
|
|
144
|
+
except Exception as e:
|
|
145
|
+
logger.warning(f"Could not register endpoint views: {e}")
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
config = AtlassianConfig
|
|
@@ -219,22 +219,26 @@ class AtlassianClient:
|
|
|
219
219
|
issues = []
|
|
220
220
|
for issue in result.get("issues", []):
|
|
221
221
|
fields = issue.get("fields", {})
|
|
222
|
-
issues.append(
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
222
|
+
issues.append(
|
|
223
|
+
{
|
|
224
|
+
"key": issue.get("key"),
|
|
225
|
+
"summary": fields.get("summary", ""),
|
|
226
|
+
"status": fields.get("status", {}).get("name", ""),
|
|
227
|
+
"status_category": fields.get("status", {}).get("statusCategory", {}).get("key", ""),
|
|
228
|
+
"type": fields.get("issuetype", {}).get("name", ""),
|
|
229
|
+
"type_icon": fields.get("issuetype", {}).get("iconUrl", ""),
|
|
230
|
+
"priority": fields.get("priority", {}).get("name", "") if fields.get("priority") else "",
|
|
231
|
+
"priority_icon": fields.get("priority", {}).get("iconUrl", "") if fields.get("priority") else "",
|
|
232
|
+
"assignee": (
|
|
233
|
+
fields.get("assignee", {}).get("displayName", "") if fields.get("assignee") else "Unassigned"
|
|
234
|
+
),
|
|
235
|
+
"created": fields.get("created", ""),
|
|
236
|
+
"updated": fields.get("updated", ""),
|
|
237
|
+
"project": fields.get("project", {}).get("name", ""),
|
|
238
|
+
"project_key": fields.get("project", {}).get("key", ""),
|
|
239
|
+
"url": f"{self.jira_url}/browse/{issue.get('key')}",
|
|
240
|
+
}
|
|
241
|
+
)
|
|
238
242
|
|
|
239
243
|
response = {
|
|
240
244
|
"issues": issues,
|
|
@@ -308,16 +312,18 @@ class AtlassianClient:
|
|
|
308
312
|
ancestors = page.get("ancestors", [])
|
|
309
313
|
breadcrumb = " > ".join([a.get("title", "") for a in ancestors])
|
|
310
314
|
|
|
311
|
-
pages.append(
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
315
|
+
pages.append(
|
|
316
|
+
{
|
|
317
|
+
"id": page.get("id"),
|
|
318
|
+
"title": page.get("title", ""),
|
|
319
|
+
"space_key": space.get("key", ""),
|
|
320
|
+
"space_name": space.get("name", ""),
|
|
321
|
+
"last_modified": version.get("when", ""),
|
|
322
|
+
"last_modified_by": version.get("by", {}).get("displayName", ""),
|
|
323
|
+
"breadcrumb": breadcrumb,
|
|
324
|
+
"url": f"{self.confluence_url}{page.get('_links', {}).get('webui', '')}",
|
|
325
|
+
}
|
|
326
|
+
)
|
|
321
327
|
|
|
322
328
|
response = {
|
|
323
329
|
"pages": pages,
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{% extends 'netbox_endpoints/endpoint.html' %}
|
|
2
|
+
{% load helpers %}
|
|
3
|
+
|
|
4
|
+
{% block content %}
|
|
5
|
+
{% if loading %}
|
|
6
|
+
<div id="atlassian-content"
|
|
7
|
+
hx-get="{% url 'plugins:netbox_atlassian:endpoint_content' pk=object.pk %}"
|
|
8
|
+
hx-trigger="load"
|
|
9
|
+
hx-swap="innerHTML">
|
|
10
|
+
<div class="d-flex justify-content-center align-items-center py-5">
|
|
11
|
+
<div class="text-center">
|
|
12
|
+
<div class="spinner-border text-primary mb-3" role="status" style="width: 3rem; height: 3rem;">
|
|
13
|
+
<span class="visually-hidden">Loading...</span>
|
|
14
|
+
</div>
|
|
15
|
+
<p class="text-muted mb-0">Loading Atlassian data...</p>
|
|
16
|
+
<p class="text-muted small">Searching Jira and Confluence</p>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
{% elif error %}
|
|
21
|
+
<div class="alert alert-warning">
|
|
22
|
+
<i class="mdi mdi-alert"></i> {{ error }}
|
|
23
|
+
</div>
|
|
24
|
+
{% endif %}
|
|
25
|
+
{% endblock %}
|
|
@@ -5,6 +5,7 @@ URL patterns for NetBox Atlassian Plugin
|
|
|
5
5
|
from django.urls import path
|
|
6
6
|
|
|
7
7
|
from .views import (
|
|
8
|
+
ENDPOINTS_PLUGIN_INSTALLED,
|
|
8
9
|
AtlassianSettingsView,
|
|
9
10
|
DeviceAtlassianContentView,
|
|
10
11
|
TestConfluenceConnectionView,
|
|
@@ -19,3 +20,11 @@ urlpatterns = [
|
|
|
19
20
|
path("device/<int:pk>/content/", DeviceAtlassianContentView.as_view(), name="device_content"),
|
|
20
21
|
path("vm/<int:pk>/content/", VMAtlassianContentView.as_view(), name="vm_content"),
|
|
21
22
|
]
|
|
23
|
+
|
|
24
|
+
# Add endpoint URLs if netbox_endpoints is installed
|
|
25
|
+
if ENDPOINTS_PLUGIN_INSTALLED:
|
|
26
|
+
from .views import EndpointAtlassianContentView
|
|
27
|
+
|
|
28
|
+
urlpatterns.append(
|
|
29
|
+
path("endpoint/<int:pk>/content/", EndpointAtlassianContentView.as_view(), name="endpoint_content"),
|
|
30
|
+
)
|
|
@@ -22,6 +22,14 @@ from virtualization.models import VirtualMachine
|
|
|
22
22
|
from .atlassian_client import get_client
|
|
23
23
|
from .forms import AtlassianSettingsForm
|
|
24
24
|
|
|
25
|
+
# Check if netbox_endpoints plugin is installed
|
|
26
|
+
try:
|
|
27
|
+
from netbox_endpoints.models import Endpoint
|
|
28
|
+
|
|
29
|
+
ENDPOINTS_PLUGIN_INSTALLED = True
|
|
30
|
+
except ImportError:
|
|
31
|
+
ENDPOINTS_PLUGIN_INSTALLED = False
|
|
32
|
+
|
|
25
33
|
|
|
26
34
|
def get_device_attribute(device, attribute_path: str):
|
|
27
35
|
"""
|
|
@@ -354,3 +362,145 @@ class TestConfluenceConnectionView(View):
|
|
|
354
362
|
if success:
|
|
355
363
|
return JsonResponse({"success": True, "message": message})
|
|
356
364
|
return JsonResponse({"success": False, "error": message}, status=400)
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
# Endpoint-specific functions for netbox_endpoints plugin
|
|
368
|
+
def get_endpoint_attribute(endpoint, attribute_path: str):
|
|
369
|
+
"""
|
|
370
|
+
Get an endpoint attribute by dot-separated path.
|
|
371
|
+
|
|
372
|
+
Args:
|
|
373
|
+
endpoint: Endpoint instance
|
|
374
|
+
attribute_path: Dot-separated attribute path (e.g., "name", "mac_address")
|
|
375
|
+
|
|
376
|
+
Returns:
|
|
377
|
+
Attribute value or None if not found
|
|
378
|
+
"""
|
|
379
|
+
try:
|
|
380
|
+
value = endpoint
|
|
381
|
+
for part in attribute_path.split("."):
|
|
382
|
+
value = getattr(value, part, None)
|
|
383
|
+
if value is None:
|
|
384
|
+
return None
|
|
385
|
+
# Convert to string for IP addresses and MAC
|
|
386
|
+
if hasattr(value, "ip"):
|
|
387
|
+
return str(value.ip)
|
|
388
|
+
return str(value) if value else None
|
|
389
|
+
except Exception:
|
|
390
|
+
return None
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def get_endpoint_search_terms(endpoint) -> list[str]:
|
|
394
|
+
"""
|
|
395
|
+
Get search terms from endpoint based on configured endpoint_search_fields.
|
|
396
|
+
|
|
397
|
+
Returns list of non-empty values from enabled search fields.
|
|
398
|
+
"""
|
|
399
|
+
config = settings.PLUGINS_CONFIG.get("netbox_atlassian", {})
|
|
400
|
+
search_fields = config.get(
|
|
401
|
+
"endpoint_search_fields",
|
|
402
|
+
[
|
|
403
|
+
{"name": "Name", "attribute": "name", "enabled": True},
|
|
404
|
+
{"name": "MAC Address", "attribute": "mac_address", "enabled": True},
|
|
405
|
+
{"name": "Serial", "attribute": "serial", "enabled": True},
|
|
406
|
+
],
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
terms = []
|
|
410
|
+
for field in search_fields:
|
|
411
|
+
if not field.get("enabled", True):
|
|
412
|
+
continue
|
|
413
|
+
|
|
414
|
+
attribute = field.get("attribute", "")
|
|
415
|
+
if not attribute:
|
|
416
|
+
continue
|
|
417
|
+
|
|
418
|
+
value = get_endpoint_attribute(endpoint, attribute)
|
|
419
|
+
if value and value.strip():
|
|
420
|
+
# Split comma-separated values
|
|
421
|
+
if "," in value:
|
|
422
|
+
for part in value.split(","):
|
|
423
|
+
part = part.strip()
|
|
424
|
+
if part and part not in terms:
|
|
425
|
+
terms.append(part)
|
|
426
|
+
else:
|
|
427
|
+
if value.strip() not in terms:
|
|
428
|
+
terms.append(value.strip())
|
|
429
|
+
|
|
430
|
+
return terms
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
def should_show_atlassian_tab_endpoint(endpoint) -> bool:
|
|
434
|
+
"""
|
|
435
|
+
Determine if the Atlassian tab should be visible for this endpoint.
|
|
436
|
+
|
|
437
|
+
Shows tab if endpoint has at least one searchable field value.
|
|
438
|
+
"""
|
|
439
|
+
if not ENDPOINTS_PLUGIN_INSTALLED:
|
|
440
|
+
return False
|
|
441
|
+
|
|
442
|
+
terms = get_endpoint_search_terms(endpoint)
|
|
443
|
+
return len(terms) > 0
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
# Endpoint views - only available if netbox_endpoints is installed
|
|
447
|
+
if ENDPOINTS_PLUGIN_INSTALLED:
|
|
448
|
+
|
|
449
|
+
class EndpointAtlassianContentView(LoginRequiredMixin, PermissionRequiredMixin, View):
|
|
450
|
+
"""HTMX endpoint that returns Atlassian content for Endpoint async loading."""
|
|
451
|
+
|
|
452
|
+
permission_required = "netbox_endpoints.view_endpoint"
|
|
453
|
+
|
|
454
|
+
def get(self, request, pk):
|
|
455
|
+
"""Fetch Atlassian data and return HTML content."""
|
|
456
|
+
endpoint = Endpoint.objects.get(pk=pk)
|
|
457
|
+
|
|
458
|
+
config = settings.PLUGINS_CONFIG.get("netbox_atlassian", {})
|
|
459
|
+
client = get_client()
|
|
460
|
+
|
|
461
|
+
# Get search terms from endpoint
|
|
462
|
+
search_terms = get_endpoint_search_terms(endpoint)
|
|
463
|
+
|
|
464
|
+
# Get configured search fields for display
|
|
465
|
+
search_fields = config.get(
|
|
466
|
+
"endpoint_search_fields",
|
|
467
|
+
[
|
|
468
|
+
{"name": "Name", "attribute": "name", "enabled": True},
|
|
469
|
+
{"name": "MAC Address", "attribute": "mac_address", "enabled": True},
|
|
470
|
+
{"name": "Serial", "attribute": "serial", "enabled": True},
|
|
471
|
+
],
|
|
472
|
+
)
|
|
473
|
+
enabled_fields = [f for f in search_fields if f.get("enabled", True)]
|
|
474
|
+
|
|
475
|
+
# Search Jira and Confluence
|
|
476
|
+
jira_results = {"issues": [], "total": 0, "error": None}
|
|
477
|
+
confluence_results = {"pages": [], "total": 0, "error": None}
|
|
478
|
+
|
|
479
|
+
if search_terms:
|
|
480
|
+
jira_max = config.get("jira_max_results", 10)
|
|
481
|
+
confluence_max = config.get("confluence_max_results", 10)
|
|
482
|
+
|
|
483
|
+
jira_results = client.search_jira(search_terms, max_results=jira_max)
|
|
484
|
+
confluence_results = client.search_confluence(search_terms, max_results=confluence_max)
|
|
485
|
+
|
|
486
|
+
# Get URLs for external links
|
|
487
|
+
jira_url = config.get("jira_url", "").rstrip("/")
|
|
488
|
+
confluence_url = config.get("confluence_url", "").rstrip("/")
|
|
489
|
+
|
|
490
|
+
return HttpResponse(
|
|
491
|
+
render_to_string(
|
|
492
|
+
"netbox_atlassian/tab_content.html",
|
|
493
|
+
{
|
|
494
|
+
"object": endpoint,
|
|
495
|
+
"search_terms": search_terms,
|
|
496
|
+
"enabled_fields": enabled_fields,
|
|
497
|
+
"jira_results": jira_results,
|
|
498
|
+
"confluence_results": confluence_results,
|
|
499
|
+
"jira_url": jira_url,
|
|
500
|
+
"confluence_url": confluence_url,
|
|
501
|
+
"jira_configured": bool(jira_url),
|
|
502
|
+
"confluence_configured": bool(confluence_url),
|
|
503
|
+
},
|
|
504
|
+
request=request,
|
|
505
|
+
)
|
|
506
|
+
)
|
|
@@ -12,6 +12,7 @@ netbox_atlassian.egg-info/dependency_links.txt
|
|
|
12
12
|
netbox_atlassian.egg-info/requires.txt
|
|
13
13
|
netbox_atlassian.egg-info/top_level.txt
|
|
14
14
|
netbox_atlassian/templates/netbox_atlassian/device_tab.html
|
|
15
|
+
netbox_atlassian/templates/netbox_atlassian/endpoint_tab.html
|
|
15
16
|
netbox_atlassian/templates/netbox_atlassian/settings.html
|
|
16
17
|
netbox_atlassian/templates/netbox_atlassian/tab_content.html
|
|
17
18
|
netbox_atlassian/templates/netbox_atlassian/vm_tab.html
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "netbox-atlassian"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.4"
|
|
8
8
|
description = "NetBox plugin to display Jira issues and Confluence pages related to devices"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "Apache-2.0"}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
NetBox Atlassian Plugin
|
|
3
|
-
|
|
4
|
-
Display Jira issues and Confluence pages related to devices in NetBox.
|
|
5
|
-
Searches by configurable fields (hostname, serial, role, etc.) with OR logic.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from netbox.plugins import PluginConfig
|
|
9
|
-
|
|
10
|
-
__version__ = "0.2.2"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class AtlassianConfig(PluginConfig):
|
|
14
|
-
"""Plugin configuration for NetBox Atlassian integration."""
|
|
15
|
-
|
|
16
|
-
name = "netbox_atlassian"
|
|
17
|
-
verbose_name = "Atlassian"
|
|
18
|
-
description = "Display Jira issues and Confluence pages related to devices"
|
|
19
|
-
version = __version__
|
|
20
|
-
author = "sieteunoseis"
|
|
21
|
-
author_email = "sieteunoseis@github.com"
|
|
22
|
-
base_url = "atlassian"
|
|
23
|
-
min_version = "4.0.0"
|
|
24
|
-
|
|
25
|
-
# Required settings - plugin won't load without these
|
|
26
|
-
required_settings = []
|
|
27
|
-
|
|
28
|
-
# Default configuration values
|
|
29
|
-
default_settings = {
|
|
30
|
-
# Jira settings (on-prem)
|
|
31
|
-
"jira_url": "", # e.g., "https://jira.example.com"
|
|
32
|
-
"jira_username": "",
|
|
33
|
-
"jira_password": "", # or API token
|
|
34
|
-
"jira_token": "", # Personal Access Token (PAT) - preferred for on-prem
|
|
35
|
-
"jira_verify_ssl": True,
|
|
36
|
-
# Confluence settings (on-prem)
|
|
37
|
-
"confluence_url": "", # e.g., "https://confluence.example.com"
|
|
38
|
-
"confluence_username": "",
|
|
39
|
-
"confluence_password": "", # or API token
|
|
40
|
-
"confluence_token": "", # Personal Access Token (PAT) - preferred for on-prem
|
|
41
|
-
"confluence_verify_ssl": True,
|
|
42
|
-
# Cloud settings (for future use)
|
|
43
|
-
"use_cloud": False,
|
|
44
|
-
"cloud_api_token": "",
|
|
45
|
-
"cloud_email": "",
|
|
46
|
-
# Search configuration
|
|
47
|
-
# Fields to search - values are device attribute paths
|
|
48
|
-
# Searches use OR logic - matches any field
|
|
49
|
-
"search_fields": [
|
|
50
|
-
{"name": "Hostname", "attribute": "name", "enabled": True},
|
|
51
|
-
{"name": "Serial", "attribute": "serial", "enabled": True},
|
|
52
|
-
{"name": "Asset Tag", "attribute": "asset_tag", "enabled": False},
|
|
53
|
-
{"name": "Role", "attribute": "role.name", "enabled": False},
|
|
54
|
-
{"name": "Primary IP", "attribute": "primary_ip4.address", "enabled": False},
|
|
55
|
-
],
|
|
56
|
-
# Jira search settings
|
|
57
|
-
"jira_max_results": 10,
|
|
58
|
-
"jira_projects": [], # Empty = search all projects
|
|
59
|
-
"jira_issue_types": [], # Empty = all types
|
|
60
|
-
# Confluence search settings
|
|
61
|
-
"confluence_max_results": 10,
|
|
62
|
-
"confluence_spaces": [], # Empty = search all spaces
|
|
63
|
-
# General settings
|
|
64
|
-
"timeout": 30,
|
|
65
|
-
"cache_timeout": 300, # Cache results for 5 minutes
|
|
66
|
-
# Enable legacy SSL renegotiation for older servers (required for OHSU wiki)
|
|
67
|
-
"enable_legacy_ssl": False,
|
|
68
|
-
# Device type filtering (like catalyst-center)
|
|
69
|
-
# Empty list = show tab for all devices
|
|
70
|
-
"device_types": [], # e.g., ["cisco", "juniper"]
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
config = AtlassianConfig
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_atlassian-0.2.2 → netbox_atlassian-0.2.4}/netbox_atlassian.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|