netbox-atlassian 0.2.2__py3-none-any.whl → 0.2.4__py3-none-any.whl
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/__init__.py +75 -1
- netbox_atlassian/atlassian_client.py +32 -26
- netbox_atlassian/templates/netbox_atlassian/endpoint_tab.html +25 -0
- netbox_atlassian/urls.py +9 -0
- netbox_atlassian/views.py +150 -0
- {netbox_atlassian-0.2.2.dist-info → netbox_atlassian-0.2.4.dist-info}/METADATA +1 -1
- netbox_atlassian-0.2.4.dist-info/RECORD +15 -0
- netbox_atlassian-0.2.2.dist-info/RECORD +0 -14
- {netbox_atlassian-0.2.2.dist-info → netbox_atlassian-0.2.4.dist-info}/WHEEL +0 -0
- {netbox_atlassian-0.2.2.dist-info → netbox_atlassian-0.2.4.dist-info}/top_level.txt +0 -0
netbox_atlassian/__init__.py
CHANGED
|
@@ -5,9 +5,13 @@ Display Jira issues and Confluence pages related to devices in NetBox.
|
|
|
5
5
|
Searches by configurable fields (hostname, serial, role, etc.) with OR logic.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
import logging
|
|
9
|
+
|
|
8
10
|
from netbox.plugins import PluginConfig
|
|
9
11
|
|
|
10
|
-
__version__ = "0.2.
|
|
12
|
+
__version__ = "0.2.4"
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
11
15
|
|
|
12
16
|
|
|
13
17
|
class AtlassianConfig(PluginConfig):
|
|
@@ -53,6 +57,14 @@ class AtlassianConfig(PluginConfig):
|
|
|
53
57
|
{"name": "Role", "attribute": "role.name", "enabled": False},
|
|
54
58
|
{"name": "Primary IP", "attribute": "primary_ip4.address", "enabled": False},
|
|
55
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
|
+
],
|
|
56
68
|
# Jira search settings
|
|
57
69
|
"jira_max_results": 10,
|
|
58
70
|
"jira_projects": [], # Empty = search all projects
|
|
@@ -70,5 +82,67 @@ class AtlassianConfig(PluginConfig):
|
|
|
70
82
|
"device_types": [], # e.g., ["cisco", "juniper"]
|
|
71
83
|
}
|
|
72
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
|
+
|
|
73
147
|
|
|
74
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 %}
|
netbox_atlassian/urls.py
CHANGED
|
@@ -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
|
+
)
|
netbox_atlassian/views.py
CHANGED
|
@@ -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
|
+
)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
netbox_atlassian/__init__.py,sha256=vYAzVqKJPclCQITWPJQRRvs01oWyHUHDZvJ-wHuPsTM,5822
|
|
2
|
+
netbox_atlassian/atlassian_client.py,sha256=UEeAzcdr7Ob8tQQ4tIB1LaNmnv2dqbKjKdC2mwp8P7M,13771
|
|
3
|
+
netbox_atlassian/forms.py,sha256=b8MKsU3Ou-c0s7Cga_72m7E3UCCliZF-17woybN66dk,3385
|
|
4
|
+
netbox_atlassian/navigation.py,sha256=tpRgS8qESmxm5eEuCOd1UjEVXEDTMM12H4lEaZk1BRw,497
|
|
5
|
+
netbox_atlassian/urls.py,sha256=K5KCzgvWgYy801yUwf9XHiBdE4gHJoGFtFOZCzoGAJM,1009
|
|
6
|
+
netbox_atlassian/views.py,sha256=JYAp949EqzrUhPyNZ-G3bMXRqPYTt6QXP1cVmZadDE8,17372
|
|
7
|
+
netbox_atlassian/templates/netbox_atlassian/device_tab.html,sha256=yYNhzZHvVSFGa3liRYiHL0KosJv1offXS5v7L0vVGm0,677
|
|
8
|
+
netbox_atlassian/templates/netbox_atlassian/endpoint_tab.html,sha256=wi9hdRlsoLZ2by4wb8NO7XPv8VuTnkF4OTU9xhCteKA,866
|
|
9
|
+
netbox_atlassian/templates/netbox_atlassian/settings.html,sha256=bmiIzzJ6m1vwT5AOcOrdJ7uD3V31GbKUpT4M6TIP3wE,11709
|
|
10
|
+
netbox_atlassian/templates/netbox_atlassian/tab_content.html,sha256=vLH1glj16Pb_JarGJ9LP7FF1ijAt8B-MyZ-FlzITOjI,9473
|
|
11
|
+
netbox_atlassian/templates/netbox_atlassian/vm_tab.html,sha256=NG2Rk019tRLZtVLbrYmq8vakLyt-Gzj3WhGjxjfyn9Q,691
|
|
12
|
+
netbox_atlassian-0.2.4.dist-info/METADATA,sha256=qVwIj9mYzW9FQ9xrDiNxj70gtyejyq0XAUTi1dc_Ut8,6881
|
|
13
|
+
netbox_atlassian-0.2.4.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
14
|
+
netbox_atlassian-0.2.4.dist-info/top_level.txt,sha256=VaKVLTW0o2SE7896PzRTWUaEeYt8CWsryBXI6Ij4ECg,17
|
|
15
|
+
netbox_atlassian-0.2.4.dist-info/RECORD,,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
netbox_atlassian/__init__.py,sha256=cCI1AqClDapNesA6g-eoEvmXKGoqweNZFiODqrnQ7eE,2835
|
|
2
|
-
netbox_atlassian/atlassian_client.py,sha256=NaCwsHOx5kB9bz_g6rtfbjXFsE3J3KdrVY-wewAUIzg,13567
|
|
3
|
-
netbox_atlassian/forms.py,sha256=b8MKsU3Ou-c0s7Cga_72m7E3UCCliZF-17woybN66dk,3385
|
|
4
|
-
netbox_atlassian/navigation.py,sha256=tpRgS8qESmxm5eEuCOd1UjEVXEDTMM12H4lEaZk1BRw,497
|
|
5
|
-
netbox_atlassian/urls.py,sha256=3eLcwzSE6kG-9iDnrgxp6hFmbgRuUYRm196MIieuSF0,700
|
|
6
|
-
netbox_atlassian/views.py,sha256=3-5snH3vIGVFdY-Ejdb1oDXJHcwgkZ4re_KueYLKVkE,12068
|
|
7
|
-
netbox_atlassian/templates/netbox_atlassian/device_tab.html,sha256=yYNhzZHvVSFGa3liRYiHL0KosJv1offXS5v7L0vVGm0,677
|
|
8
|
-
netbox_atlassian/templates/netbox_atlassian/settings.html,sha256=bmiIzzJ6m1vwT5AOcOrdJ7uD3V31GbKUpT4M6TIP3wE,11709
|
|
9
|
-
netbox_atlassian/templates/netbox_atlassian/tab_content.html,sha256=vLH1glj16Pb_JarGJ9LP7FF1ijAt8B-MyZ-FlzITOjI,9473
|
|
10
|
-
netbox_atlassian/templates/netbox_atlassian/vm_tab.html,sha256=NG2Rk019tRLZtVLbrYmq8vakLyt-Gzj3WhGjxjfyn9Q,691
|
|
11
|
-
netbox_atlassian-0.2.2.dist-info/METADATA,sha256=Us88eAq8_jYfZY7YJ30R_na7jppaX8JJia76Rlr3shs,6881
|
|
12
|
-
netbox_atlassian-0.2.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
13
|
-
netbox_atlassian-0.2.2.dist-info/top_level.txt,sha256=VaKVLTW0o2SE7896PzRTWUaEeYt8CWsryBXI6Ij4ECg,17
|
|
14
|
-
netbox_atlassian-0.2.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|