netbox-toolkit-plugin 0.1.0__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_toolkit/__init__.py +30 -0
- netbox_toolkit/admin.py +16 -0
- netbox_toolkit/api/__init__.py +0 -0
- netbox_toolkit/api/mixins.py +54 -0
- netbox_toolkit/api/schemas.py +234 -0
- netbox_toolkit/api/serializers.py +158 -0
- netbox_toolkit/api/urls.py +10 -0
- netbox_toolkit/api/views/__init__.py +10 -0
- netbox_toolkit/api/views/command_logs.py +170 -0
- netbox_toolkit/api/views/commands.py +267 -0
- netbox_toolkit/config.py +159 -0
- netbox_toolkit/connectors/__init__.py +15 -0
- netbox_toolkit/connectors/base.py +97 -0
- netbox_toolkit/connectors/factory.py +301 -0
- netbox_toolkit/connectors/netmiko_connector.py +443 -0
- netbox_toolkit/connectors/scrapli_connector.py +486 -0
- netbox_toolkit/exceptions.py +36 -0
- netbox_toolkit/filtersets.py +85 -0
- netbox_toolkit/forms.py +31 -0
- netbox_toolkit/migrations/0001_initial.py +54 -0
- netbox_toolkit/migrations/0002_alter_command_options_alter_command_unique_together_and_more.py +66 -0
- netbox_toolkit/migrations/0003_permission_system_update.py +48 -0
- netbox_toolkit/migrations/0004_remove_django_permissions.py +77 -0
- netbox_toolkit/migrations/0005_alter_command_options_and_more.py +25 -0
- netbox_toolkit/migrations/0006_commandlog_parsed_data_commandlog_parsing_success_and_more.py +28 -0
- netbox_toolkit/migrations/0007_alter_commandlog_parsing_template.py +18 -0
- netbox_toolkit/migrations/__init__.py +0 -0
- netbox_toolkit/models.py +89 -0
- netbox_toolkit/navigation.py +30 -0
- netbox_toolkit/search.py +21 -0
- netbox_toolkit/services/__init__.py +7 -0
- netbox_toolkit/services/command_service.py +357 -0
- netbox_toolkit/services/device_service.py +87 -0
- netbox_toolkit/services/rate_limiting_service.py +228 -0
- netbox_toolkit/static/netbox_toolkit/css/toolkit.css +143 -0
- netbox_toolkit/static/netbox_toolkit/js/toolkit.js +657 -0
- netbox_toolkit/tables.py +37 -0
- netbox_toolkit/templates/netbox_toolkit/command.html +108 -0
- netbox_toolkit/templates/netbox_toolkit/command_edit.html +10 -0
- netbox_toolkit/templates/netbox_toolkit/command_list.html +12 -0
- netbox_toolkit/templates/netbox_toolkit/commandlog.html +170 -0
- netbox_toolkit/templates/netbox_toolkit/commandlog_list.html +4 -0
- netbox_toolkit/templates/netbox_toolkit/device_toolkit.html +536 -0
- netbox_toolkit/urls.py +22 -0
- netbox_toolkit/utils/__init__.py +1 -0
- netbox_toolkit/utils/connection.py +125 -0
- netbox_toolkit/utils/error_parser.py +428 -0
- netbox_toolkit/utils/logging.py +58 -0
- netbox_toolkit/utils/network.py +157 -0
- netbox_toolkit/views.py +385 -0
- netbox_toolkit_plugin-0.1.0.dist-info/METADATA +76 -0
- netbox_toolkit_plugin-0.1.0.dist-info/RECORD +56 -0
- netbox_toolkit_plugin-0.1.0.dist-info/WHEEL +5 -0
- netbox_toolkit_plugin-0.1.0.dist-info/entry_points.txt +2 -0
- netbox_toolkit_plugin-0.1.0.dist-info/licenses/LICENSE +200 -0
- netbox_toolkit_plugin-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,108 @@
|
|
1
|
+
{% extends 'generic/object.html' %}
|
2
|
+
{% load helpers %}
|
3
|
+
{% load static %}
|
4
|
+
|
5
|
+
{% block style %}
|
6
|
+
<link href="{% static 'netbox_toolkit/css/toolkit.css' %}" rel="stylesheet">
|
7
|
+
{% endblock %}
|
8
|
+
|
9
|
+
{% block buttons %}
|
10
|
+
{% if perms.netbox_toolkit.change_command %}
|
11
|
+
<a href="{% url 'plugins:netbox_toolkit:command_edit' pk=object.pk %}" class="btn btn-warning">
|
12
|
+
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
|
13
|
+
</a>
|
14
|
+
{% endif %}
|
15
|
+
{% if perms.netbox_toolkit.delete_command %}
|
16
|
+
<a href="{% url 'plugins:netbox_toolkit:command_delete' pk=object.pk %}" class="btn btn-danger">
|
17
|
+
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
|
18
|
+
</a>
|
19
|
+
{% endif %}
|
20
|
+
{% endblock %}
|
21
|
+
|
22
|
+
{% block content %}
|
23
|
+
<div class="row mb-3">
|
24
|
+
<div class="col col-md-6">
|
25
|
+
<div class="card">
|
26
|
+
<div class="card-header">
|
27
|
+
<h3 class="card-title">Command</h3>
|
28
|
+
</div>
|
29
|
+
<div class="card-body">
|
30
|
+
<table class="table table-hover attr-table">
|
31
|
+
<tr>
|
32
|
+
<th scope="row">Name</th>
|
33
|
+
<td>{{ object.name }}</td>
|
34
|
+
</tr>
|
35
|
+
<tr>
|
36
|
+
<th scope="row">Platform</th>
|
37
|
+
<td>{{ object.platform|linkify }}</td>
|
38
|
+
</tr>
|
39
|
+
<tr>
|
40
|
+
<th scope="row">Command Type</th>
|
41
|
+
<td>
|
42
|
+
{{ object.get_command_type_display }}
|
43
|
+
{% if can_execute %}
|
44
|
+
<span class="badge bg-success ms-2">
|
45
|
+
<i class="mdi mdi-check"></i> Executable
|
46
|
+
</span>
|
47
|
+
{% else %}
|
48
|
+
<span class="badge bg-secondary ms-2">
|
49
|
+
<i class="mdi mdi-lock"></i> No Execute Permission
|
50
|
+
</span>
|
51
|
+
{% endif %}
|
52
|
+
</td>
|
53
|
+
</tr>
|
54
|
+
<tr>
|
55
|
+
<th scope="row">Description</th>
|
56
|
+
<td>{{ object.description|placeholder }}</td>
|
57
|
+
</tr>
|
58
|
+
</table>
|
59
|
+
</div>
|
60
|
+
</div>
|
61
|
+
{% include 'inc/panels/custom_fields.html' %}
|
62
|
+
{% include 'inc/panels/tags.html' %}
|
63
|
+
</div>
|
64
|
+
<div class="col col-md-6">
|
65
|
+
<div class="card">
|
66
|
+
<div class="card-header">
|
67
|
+
<h3 class="card-title">Command Detail</h3>
|
68
|
+
</div>
|
69
|
+
<div class="card-body">
|
70
|
+
<pre>{{ object.command }}</pre>
|
71
|
+
</div>
|
72
|
+
</div>
|
73
|
+
</div>
|
74
|
+
</div>
|
75
|
+
<div class="row">
|
76
|
+
<div class="col col-md-12">
|
77
|
+
<div class="card">
|
78
|
+
<div class="card-header">
|
79
|
+
<h3 class="card-title">Recent Command Logs</h3>
|
80
|
+
</div>
|
81
|
+
<div class="card-body">
|
82
|
+
<table class="table table-hover table-headings">
|
83
|
+
<thead>
|
84
|
+
<tr>
|
85
|
+
<th>Device</th>
|
86
|
+
<th>Username</th>
|
87
|
+
<th>Execution Time</th>
|
88
|
+
</tr>
|
89
|
+
</thead>
|
90
|
+
<tbody>
|
91
|
+
{% for log in object.logs.all|slice:":5" %}
|
92
|
+
<tr>
|
93
|
+
<td>{{ log.device|linkify }}</td>
|
94
|
+
<td>{{ log.username }}</td>
|
95
|
+
<td>{{ log.execution_time }}</td>
|
96
|
+
</tr>
|
97
|
+
{% empty %}
|
98
|
+
<tr>
|
99
|
+
<td colspan="3" class="text-muted">No command executions recorded</td>
|
100
|
+
</tr>
|
101
|
+
{% endfor %}
|
102
|
+
</tbody>
|
103
|
+
</table>
|
104
|
+
</div>
|
105
|
+
</div>
|
106
|
+
</div>
|
107
|
+
</div>
|
108
|
+
{% endblock %}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
{% extends 'generic/object_list.html' %}
|
2
|
+
{% load helpers %}
|
3
|
+
|
4
|
+
{% block title %}Commands{% endblock %}
|
5
|
+
|
6
|
+
{% block buttons %}
|
7
|
+
{% if perms.netbox_toolkit.add_command %}
|
8
|
+
<a href="{% url 'plugins:netbox_toolkit:command_add' %}" class="btn btn-primary">
|
9
|
+
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add Command
|
10
|
+
</a>
|
11
|
+
{% endif %}
|
12
|
+
{% endblock %}
|
@@ -0,0 +1,170 @@
|
|
1
|
+
{% extends 'generic/object.html' %}
|
2
|
+
{% load helpers %}
|
3
|
+
{% load static %}
|
4
|
+
|
5
|
+
{% block style %}
|
6
|
+
<link href="{% static 'netbox_toolkit/css/toolkit.css' %}" rel="stylesheet">
|
7
|
+
{% endblock %}
|
8
|
+
|
9
|
+
{% block content %}
|
10
|
+
<div class="row mb-3">
|
11
|
+
<div class="col col-md-6">
|
12
|
+
<div class="card">
|
13
|
+
<div class="card-header">
|
14
|
+
<h3 class="card-title">Command Log</h3>
|
15
|
+
</div>
|
16
|
+
<div class="card-body">
|
17
|
+
<table class="table table-hover attr-table">
|
18
|
+
<tr>
|
19
|
+
<th scope="row">Command</th>
|
20
|
+
<td>{{ object.command|linkify }}</td>
|
21
|
+
</tr>
|
22
|
+
<tr>
|
23
|
+
<th scope="row">Device</th>
|
24
|
+
<td>{{ object.device|linkify }}</td>
|
25
|
+
</tr>
|
26
|
+
<tr>
|
27
|
+
<th scope="row">Username</th>
|
28
|
+
<td>{{ object.username }}</td>
|
29
|
+
</tr>
|
30
|
+
<tr>
|
31
|
+
<th scope="row">Execution Time</th>
|
32
|
+
<td>{{ object.execution_time }}</td>
|
33
|
+
</tr>
|
34
|
+
<tr>
|
35
|
+
<th scope="row">Status</th>
|
36
|
+
<td>
|
37
|
+
{% if object.success %}
|
38
|
+
<span class="badge bg-success">Success</span>
|
39
|
+
{% else %}
|
40
|
+
<span class="badge bg-danger">Failed</span>
|
41
|
+
{% endif %}
|
42
|
+
</td>
|
43
|
+
</tr>
|
44
|
+
{% if object.execution_duration %}
|
45
|
+
<tr>
|
46
|
+
<th scope="row">Duration</th>
|
47
|
+
<td>{{ object.execution_duration|floatformat:3 }}s</td>
|
48
|
+
</tr>
|
49
|
+
{% endif %}
|
50
|
+
{% if object.parsing_success %}
|
51
|
+
<tr>
|
52
|
+
<th scope="row">Parsing Status</th>
|
53
|
+
<td>
|
54
|
+
<span class="badge bg-success">
|
55
|
+
<i class="mdi mdi-check-circle me-1"></i>
|
56
|
+
Successfully Parsed
|
57
|
+
</span>
|
58
|
+
{% if object.parsing_template %}
|
59
|
+
<br><small class="text-muted">Template: {{ object.parsing_template }}</small>
|
60
|
+
{% endif %}
|
61
|
+
</td>
|
62
|
+
</tr>
|
63
|
+
{% elif object.parsed_data is not None %}
|
64
|
+
<tr>
|
65
|
+
<th scope="row">Parsing Status</th>
|
66
|
+
<td>
|
67
|
+
<span class="badge bg-warning">
|
68
|
+
<i class="mdi mdi-alert-circle me-1"></i>
|
69
|
+
Parsing Attempted
|
70
|
+
</span>
|
71
|
+
</td>
|
72
|
+
</tr>
|
73
|
+
{% endif %}
|
74
|
+
{% if not object.success and object.error_message %}
|
75
|
+
<tr>
|
76
|
+
<th scope="row">Error</th>
|
77
|
+
<td><code>{{ object.error_message }}</code></td>
|
78
|
+
</tr>
|
79
|
+
{% endif %}
|
80
|
+
</table>
|
81
|
+
</div>
|
82
|
+
</div>
|
83
|
+
</div>
|
84
|
+
</div>
|
85
|
+
<div class="row">
|
86
|
+
<div class="col col-md-12">
|
87
|
+
<div class="card">
|
88
|
+
<div class="card-header">
|
89
|
+
<h3 class="card-title">Command Output</h3>
|
90
|
+
</div>
|
91
|
+
<div class="card-body">
|
92
|
+
<pre>{{ object.output }}</pre>
|
93
|
+
</div>
|
94
|
+
</div>
|
95
|
+
</div>
|
96
|
+
</div>
|
97
|
+
|
98
|
+
{% if object.parsed_data %}
|
99
|
+
<div class="row mt-3">
|
100
|
+
<div class="col col-md-12">
|
101
|
+
<div class="card">
|
102
|
+
<div class="card-header">
|
103
|
+
<h3 class="card-title">
|
104
|
+
<i class="mdi mdi-table me-1"></i>
|
105
|
+
Parsed Data
|
106
|
+
</h3>
|
107
|
+
{% if object.parsing_template %}
|
108
|
+
<div class="card-subtitle">
|
109
|
+
<small class="text-muted">Template: {{ object.parsing_template }}</small>
|
110
|
+
</div>
|
111
|
+
{% endif %}
|
112
|
+
</div>
|
113
|
+
<div class="card-body">
|
114
|
+
{% if object.parsed_data|length > 0 %}
|
115
|
+
{% if object.parsed_data.0 %}
|
116
|
+
<!-- Table format for structured data -->
|
117
|
+
<div class="table-responsive">
|
118
|
+
<table class="table table-sm table-striped">
|
119
|
+
<thead>
|
120
|
+
<tr>
|
121
|
+
{% for key in object.parsed_data.0.keys %}
|
122
|
+
<th>{{ key|title }}</th>
|
123
|
+
{% endfor %}
|
124
|
+
</tr>
|
125
|
+
</thead>
|
126
|
+
<tbody>
|
127
|
+
{% for row in object.parsed_data %}
|
128
|
+
<tr>
|
129
|
+
{% for value in row.values %}
|
130
|
+
<td>{{ value }}</td>
|
131
|
+
{% endfor %}
|
132
|
+
</tr>
|
133
|
+
{% endfor %}
|
134
|
+
</tbody>
|
135
|
+
</table>
|
136
|
+
</div>
|
137
|
+
{% else %}
|
138
|
+
<!-- JSON format for other data types -->
|
139
|
+
<pre class="bg-light p-3 rounded">{{ object.parsed_data|pprint }}</pre>
|
140
|
+
{% endif %}
|
141
|
+
{% else %}
|
142
|
+
<div class="alert alert-info mb-0">
|
143
|
+
<i class="mdi mdi-information-outline me-1"></i>
|
144
|
+
No structured data found in the output.
|
145
|
+
</div>
|
146
|
+
{% endif %}
|
147
|
+
|
148
|
+
<!-- Copy parsed data button -->
|
149
|
+
{% if object.parsed_data|length > 0 %}
|
150
|
+
{{ object.parsed_data|json_script:"commandlog-parsed-data-json" }}
|
151
|
+
<div class="mt-3">
|
152
|
+
<div class="btn-list">
|
153
|
+
<button type="button" class="btn btn-sm btn-outline-primary copy-parsed-btn"
|
154
|
+
title="Copy parsed data as JSON">
|
155
|
+
<i class="mdi mdi-content-copy me-1"></i>Copy Parsed Data
|
156
|
+
</button>
|
157
|
+
</div>
|
158
|
+
</div>
|
159
|
+
{% endif %}
|
160
|
+
</div>
|
161
|
+
</div>
|
162
|
+
</div>
|
163
|
+
</div>
|
164
|
+
{% endif %}
|
165
|
+
{% endblock %}
|
166
|
+
|
167
|
+
{% block javascript %}
|
168
|
+
<!-- Load NetBox Toolkit consolidated JavaScript -->
|
169
|
+
<script src="{% static 'netbox_toolkit/js/toolkit.js' %}"></script>
|
170
|
+
{% endblock %}
|