Skip to content

Commit d2a91f6

Browse files
committed
Merge remote-tracking branch 'origin/dev' into housekeeping/cleanup
# Conflicts: # netbox_acls/templates/netbox_acls/accesslist.html
2 parents eb89726 + f2eba68 commit d2a91f6

File tree

7 files changed

+196
-110
lines changed

7 files changed

+196
-110
lines changed

netbox_acls/forms/models.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@
1414
DynamicModelChoiceField,
1515
DynamicModelMultipleChoiceField,
1616
)
17-
from virtualization.models import VirtualMachine, VMInterface
17+
from virtualization.models import (
18+
Cluster,
19+
ClusterGroup,
20+
ClusterType,
21+
VirtualMachine,
22+
VMInterface,
23+
)
1824

1925
from ..choices import ACLTypeChoices
2026
from ..models import (
@@ -60,6 +66,7 @@ class AccessListForm(NetBoxModelForm):
6066
Requires a device, a name, a type, and a default_action.
6167
"""
6268

69+
# Device selector
6370
region = DynamicModelChoiceField(
6471
queryset=Region.objects.all(),
6572
required=False,
@@ -86,16 +93,48 @@ class AccessListForm(NetBoxModelForm):
8693
"site_id": "$site",
8794
},
8895
)
96+
97+
# Virtual Chassis selector
8998
virtual_chassis = DynamicModelChoiceField(
9099
queryset=VirtualChassis.objects.all(),
91100
required=False,
92101
label="Virtual Chassis",
93102
)
103+
104+
# Virtual Machine selector
105+
cluster_type = DynamicModelChoiceField(
106+
queryset=ClusterType.objects.all(),
107+
required=False,
108+
)
109+
110+
cluster_group = DynamicModelChoiceField(
111+
queryset=ClusterGroup.objects.all(),
112+
required=False,
113+
query_params={
114+
"type_id": "$cluster_type",
115+
},
116+
)
117+
118+
cluster = DynamicModelChoiceField(
119+
queryset=Cluster.objects.all(),
120+
required=False,
121+
query_params={
122+
"type_id": "$cluster_type",
123+
"group_id": "$cluster_group",
124+
},
125+
)
126+
94127
virtual_machine = DynamicModelChoiceField(
95128
queryset=VirtualMachine.objects.all(),
96129
required=False,
97130
label="Virtual Machine",
131+
query_params={
132+
"cluster_type_id": "$cluster_type",
133+
"cluster_group_id": "$cluster_group",
134+
"cluster_id": "$cluster",
135+
},
98136
)
137+
99138
comments = CommentField()
100139

101140
class Meta:
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Generated by Django 4.0.8 on 2023-01-21 09:00
2+
3+
import django.core.validators
4+
from django.db import migrations, models
5+
import django.db.models.deletion
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('contenttypes', '0002_remove_content_type_name'),
12+
('netbox_acls', '0001_initial'),
13+
]
14+
15+
operations = [
16+
migrations.AlterModelOptions(
17+
name='accesslist',
18+
options={'ordering': ['assigned_object_type', 'assigned_object_id', 'name'], 'verbose_name': 'Access List', 'verbose_name_plural': 'Access Lists'},
19+
),
20+
migrations.AlterModelOptions(
21+
name='aclextendedrule',
22+
options={'ordering': ['access_list', 'index'], 'verbose_name': 'ACL Extended Rule', 'verbose_name_plural': 'ACL Extended Rules'},
23+
),
24+
migrations.AlterModelOptions(
25+
name='aclinterfaceassignment',
26+
options={'ordering': ['assigned_object_type', 'assigned_object_id', 'access_list', 'direction'], 'verbose_name': 'ACL Interface Assignment', 'verbose_name_plural': 'ACL Interface Assignments'},
27+
),
28+
migrations.AlterModelOptions(
29+
name='aclstandardrule',
30+
options={'ordering': ['access_list', 'index'], 'verbose_name': 'ACL Standard Rule', 'verbose_name_plural': 'ACL Standard Rules'},
31+
),
32+
migrations.AlterField(
33+
model_name='accesslist',
34+
name='assigned_object_id',
35+
field=models.PositiveBigIntegerField(),
36+
),
37+
migrations.AlterField(
38+
model_name='accesslist',
39+
name='assigned_object_type',
40+
field=models.ForeignKey(limit_choices_to=models.Q(models.Q(models.Q(('app_label', 'dcim'), ('model', 'device')), models.Q(('app_label', 'dcim'), ('model', 'virtualchassis')), models.Q(('app_label', 'virtualization'), ('model', 'virtualmachine')), _connector='OR')), on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype'),
41+
),
42+
migrations.AlterField(
43+
model_name='accesslist',
44+
name='name',
45+
field=models.CharField(max_length=500, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z,-,_]*$', 'Only alphanumeric, hyphens, and underscores characters are allowed.')]),
46+
),
47+
migrations.AlterField(
48+
model_name='accesslist',
49+
name='type',
50+
field=models.CharField(max_length=30),
51+
),
52+
migrations.AlterField(
53+
model_name='aclextendedrule',
54+
name='access_list',
55+
field=models.ForeignKey(limit_choices_to={'type': 'extended'}, on_delete=django.db.models.deletion.CASCADE, related_name='aclextendedrules', to='netbox_acls.accesslist'),
56+
),
57+
migrations.AlterField(
58+
model_name='aclextendedrule',
59+
name='remark',
60+
field=models.CharField(blank=True, default='', max_length=500),
61+
preserve_default=False,
62+
),
63+
migrations.AlterField(
64+
model_name='aclinterfaceassignment',
65+
name='access_list',
66+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='netbox_acls.accesslist'),
67+
),
68+
migrations.AlterField(
69+
model_name='aclinterfaceassignment',
70+
name='assigned_object_id',
71+
field=models.PositiveBigIntegerField(),
72+
),
73+
migrations.AlterField(
74+
model_name='aclinterfaceassignment',
75+
name='assigned_object_type',
76+
field=models.ForeignKey(limit_choices_to=models.Q(models.Q(models.Q(('app_label', 'dcim'), ('model', 'interface')), models.Q(('app_label', 'virtualization'), ('model', 'vminterface')), _connector='OR')), on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype'),
77+
),
78+
migrations.AlterField(
79+
model_name='aclinterfaceassignment',
80+
name='direction',
81+
field=models.CharField(max_length=30),
82+
),
83+
migrations.AlterField(
84+
model_name='aclstandardrule',
85+
name='access_list',
86+
field=models.ForeignKey(limit_choices_to={'type': 'standard'}, on_delete=django.db.models.deletion.CASCADE, related_name='aclstandardrules', to='netbox_acls.accesslist'),
87+
),
88+
migrations.AlterField(
89+
model_name='aclstandardrule',
90+
name='remark',
91+
field=models.CharField(blank=True, default='', max_length=500),
92+
preserve_default=False,
93+
),
94+
]

netbox_acls/models/access_list_rules.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ class ACLRule(NetBoxModel):
5252
verbose_name="Source Prefix",
5353
)
5454

55+
clone_fields = ("access_list", "action", "source_prefix")
56+
5557
def __str__(self):
5658
return f"{self.access_list}: Rule {self.index}"
5759

netbox_acls/models/access_lists.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ class AccessList(NetBoxModel):
5959
blank=True,
6060
)
6161

62+
clone_fields = (
63+
"type",
64+
"default_action",
65+
)
66+
6267
class Meta:
6368
unique_together = ["assigned_object_type", "assigned_object_id", "name"]
6469
ordering = ["assigned_object_type", "assigned_object_id", "name"]
@@ -113,6 +118,8 @@ class ACLInterfaceAssignment(NetBoxModel):
113118
blank=True,
114119
)
115120

121+
clone_fields = ("access_list", "direction")
122+
116123
class Meta:
117124
unique_together = [
118125
"assigned_object_type",
Lines changed: 50 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,63 @@
11
{% extends 'generic/object.html' %}
22
{% load render_table from django_tables2 %}
33

4-
{% block breadcrumbs %}
5-
<li class="breadcrumb-item"><a href="{% url 'plugins:netbox_acls:accesslist_list' %}">Access Lists</a></li>
6-
{% endblock %}
7-
{% block controls %}
8-
<div class="pull-right noprint">
4+
{% block extra_controls %}
95
{% if perms.netbox_acls.change_policy %}
10-
{% if object.type == 'extended' %}
11-
<a href="{% url 'plugins:netbox_acls:aclextendedrule_add' %}?access_list={{ object.pk }}" class="btn btn-success">
12-
{% elif object.type == 'standard' %}
13-
<a href="{% url 'plugins:netbox_acls:aclstandardrule_add' %}?access_list={{ object.pk }}" class="btn btn-success">
14-
{% endif %}
15-
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Rule
16-
</a>
17-
<a href="{% url 'plugins:netbox_acls:accesslist_edit' pk=object.pk %}" class="btn btn-warning">
18-
<span class="mdi mdi-pencil" aria-hidden="true"></span> Edit
19-
</a>
20-
{% endif %}
21-
{% if perms.netbox_acls.delete_policy %}
22-
<a href="{% url 'plugins:netbox_acls:accesslist_delete' pk=object.pk %}" class="btn btn-danger">
23-
<span class="mdi mdi-trash-can-outline" aria-hidden="true"></span> Delete
6+
{% if object.type == 'extended' %}
7+
<a href="{% url 'plugins:netbox_acls:aclextendedrule_add' %}?access_list={{ object.pk }}" class="btn btn-sm btn-primary">
8+
{% elif object.type == 'standard' %}
9+
<a href="{% url 'plugins:netbox_acls:aclstandardrule_add' %}?access_list={{ object.pk }}" class="btn btn-sm btn-primary">
10+
{% endif %}
11+
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Rule
2412
</a>
2513
{% endif %}
26-
</div>
27-
{% endblock controls %}
28-
{% block tabs %}
29-
<ul class="nav nav-tabs px-3">
30-
{% block tab_items %}
31-
<li class="nav-item" role="presentation">
32-
<a class="nav-link{% if not active_tab %} active{% endif %}" href="{{ object.get_absolute_url }}">{{ object|meta:"verbose_name"|bettertitle }}</a>
33-
</li>
34-
{% endblock tab_items %}
35-
{% if perms.extras.view_objectchange %}
36-
<li role="presentation" class="nav-item">
37-
<a href="{% url 'plugins:netbox_acls:accesslist_changelog' pk=object.pk %}" class="nav-link{% if active_tab == 'changelog'%} active{% endif %}">Change Log</a>
38-
</li>
39-
{% endif %}
40-
</ul>
41-
{% endblock tabs %}
14+
{% endblock extra_controls %}
4215

4316
{% block content %}
44-
<div class="row mb-3">
45-
<div class="col col-md-6">
46-
<div class="card">
47-
<h5 class="card-header">Access List</h5>
48-
<div class="card-body">
49-
<table class="table table-hover attr-table">
50-
<tr>
51-
<th scope="row">Type</th>
52-
<td>{{ object.get_type_display }}</td>
53-
</tr>
54-
<tr>
55-
<th scope="row">Default Action</th>
56-
<td>{% badge object.get_default_action_display bg_color=object.get_default_action_color %}</td>
57-
</tr>
58-
<tr>
59-
<th scope="row">Rules</th>
60-
{% if object.type == 'standard' %}
61-
<td>{{ object.aclstandardrules.count|placeholder }}</td>
62-
{% elif object.type == 'extended' %}
63-
<td>{{ object.aclextendedrules.count|placeholder }}</td>
64-
{% endif %}
65-
</tr>
66-
<tr>
67-
<th scope="row">Assigned Host</th>
68-
<td>{{ object.assigned_object|linkify }}</td>
69-
</tr>
70-
</table>
17+
<div class="row mb-3">
18+
<div class="col col-md-6">
19+
<div class="card">
20+
<h5 class="card-header">Access List</h5>
21+
<div class="card-body">
22+
<table class="table table-hover attr-table">
23+
<tr>
24+
<th scope="row">Type</th>
25+
<td>{{ object.get_type_display }}</td>
26+
</tr>
27+
<tr>
28+
<th scope="row">Default Action</th>
29+
<td>{% badge object.get_default_action_display bg_color=object.get_default_action_color %}</td>
30+
</tr>
31+
<tr>
32+
<th scope="row">Rules</th>
33+
{% if object.type == 'standard' %}
34+
<td>{{ object.aclstandardrules.count|placeholder }}</td>
35+
{% elif object.type == 'extended' %}
36+
<td>{{ object.aclextendedrules.count|placeholder }}</td>
37+
{% endif %}
38+
</tr>
39+
<tr>
40+
<th scope="row">Assigned Host</th>
41+
<td>{{ object.assigned_object|linkify }}</td>
42+
</tr>
43+
</table>
44+
</div>
45+
</div>
46+
{% include 'inc/panels/custom_fields.html' %}
47+
</div>
48+
<div class="col col-md-6">
49+
{% include 'inc/panels/tags.html' %}
50+
{% include 'inc/panels/comments.html' %}
7151
</div>
72-
</div>
73-
{% include 'inc/panels/custom_fields.html' %}
74-
</div>
75-
<div class="col col-md-6">
76-
{% include 'inc/panels/tags.html' %}
77-
{% include 'inc/panels/comments.html' %}
7852
</div>
79-
</div>
80-
<div class="row">
81-
<div class="col col-md-12">
82-
<div class="card">
83-
<h5 class="card-header">{{ object.get_type_display }} Rules</h5>
84-
<div class="card-body table-responsive">
85-
{% render_table rules_table %}
53+
<div class="row">
54+
<div class="col col-md-12">
55+
<div class="card">
56+
<h5 class="card-header">{{ object.get_type_display }} Rules</h5>
57+
<div class="card-body table-responsive">
58+
{% render_table rules_table %}
59+
</div>
60+
</div>
8661
</div>
87-
</div>
8862
</div>
89-
</div>
9063
{% endblock content %}

netbox_acls/templates/netbox_acls/accesslist_edit.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ <h4>Host Assignment</h4>
6767
{% render_field form.virtual_chassis %}
6868
</div>
6969
<div class="tab-pane{% if form.initial.virtual_machine %} active{% endif %}" id="virtualmachine">
70+
{% render_field form.cluster_type %}
71+
{% render_field form.cluster_group %}
72+
{% render_field form.cluster %}
7073
{% render_field form.virtual_machine %}
7174
</div>
7275
</div>

netbox_acls/templates/netbox_acls/aclinterfaceassignment.html

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,6 @@
11
{% extends 'generic/object.html' %}
22
{% load render_table from django_tables2 %}
33

4-
{% block breadcrumbs %}
5-
<li class="breadcrumb-item"><a href="{% url 'plugins:netbox_acls:aclinterfaceassignment_list' %}">ACL Interface Assignments</a></li>
6-
{% endblock %}
7-
{% block controls %}
8-
<div class="pull-right noprint">
9-
{% if perms.netbox_acls.change_policy %}
10-
<a href="{% url 'plugins:netbox_acls:aclinterfaceassignment_edit' pk=object.pk %}" class="btn btn-warning">
11-
<span class="mdi mdi-pencil" aria-hidden="true"></span> Edit
12-
</a>
13-
{% endif %}
14-
{% if perms.netbox_acls.delete_policy %}
15-
<a href="{% url 'plugins:netbox_acls:aclinterfaceassignment_delete' pk=object.pk %}" class="btn btn-danger">
16-
<span class="mdi mdi-trash-can-outline" aria-hidden="true"></span> Delete
17-
</a>
18-
{% endif %}
19-
</div>
20-
{% endblock controls %}
21-
{% block tabs %}
22-
<ul class="nav nav-tabs px-3">
23-
{% block tab_items %}
24-
<li class="nav-item" role="presentation">
25-
<a class="nav-link{% if not active_tab %} active{% endif %}" href="{{ object.get_absolute_url }}">{{ object|meta:"verbose_name"|bettertitle }}</a>
26-
</li>
27-
{% endblock tab_items %}
28-
{% if perms.extras.view_objectchange %}
29-
<li role="presentation" class="nav-item">
30-
<a href="{% url 'plugins:netbox_acls:aclinterfaceassignment_changelog' pk=object.pk %}" class="nav-link{% if active_tab == 'changelog'%} active{% endif %}">Change Log</a>
31-
</li>
32-
{% endif %}
33-
</ul>
34-
{% endblock tabs %}
35-
364
{% block content %}
375
<div class="row mb-3">
386
<div class="col col-md-6">

0 commit comments

Comments
 (0)