Closes #4324: Add CSV import view for services

This commit is contained in:
Jeremy Stretch 2020-03-06 16:33:43 -05:00
parent 2a5bf2a222
commit 9fa5004a35
7 changed files with 53 additions and 4 deletions

View File

@ -3,6 +3,7 @@
## Enhancements ## Enhancements
* [#4323](https://github.com/netbox-community/netbox/issues/4323) - Add bulk edit view for power panels * [#4323](https://github.com/netbox-community/netbox/issues/4323) - Add bulk edit view for power panels
* [#4324](https://github.com/netbox-community/netbox/issues/4324) - Add CSV import view for services
--- ---

View File

@ -1382,6 +1382,37 @@ class ServiceFilterForm(BootstrapMixin, CustomFieldFilterForm):
tag = TagFilterField(model) tag = TagFilterField(model)
class ServiceCSVForm(CustomFieldModelCSVForm):
device = FlexibleModelChoiceField(
queryset=Device.objects.all(),
required=False,
to_field_name='name',
help_text='Name or ID of device',
error_messages={
'invalid_choice': 'Device not found.',
}
)
virtual_machine = FlexibleModelChoiceField(
queryset=VirtualMachine.objects.all(),
required=False,
to_field_name='name',
help_text='Name or ID of virtual machine',
error_messages={
'invalid_choice': 'Virtual machine not found.',
}
)
protocol = CSVChoiceField(
choices=ServiceProtocolChoices,
help_text='IP protocol'
)
class Meta:
model = Service
fields = Service.csv_headers
help_texts = {
}
class ServiceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm): class ServiceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
pk = forms.ModelMultipleChoiceField( pk = forms.ModelMultipleChoiceField(
queryset=Service.objects.all(), queryset=Service.objects.all(),

View File

@ -1027,7 +1027,7 @@ class Service(ChangeLoggedModel, CustomFieldModel):
tags = TaggableManager(through=TaggedItem) tags = TaggableManager(through=TaggedItem)
csv_headers = ['device', 'virtual_machine', 'name', 'protocol', 'description'] csv_headers = ['device', 'virtual_machine', 'name', 'protocol', 'port', 'description']
class Meta: class Meta:
ordering = ('protocol', 'port', 'pk') # (protocol, port) may be non-unique ordering = ('protocol', 'port', 'pk') # (protocol, port) may be non-unique

View File

@ -334,9 +334,6 @@ class VLANTestCase(ViewTestCases.PrimaryObjectViewTestCase):
class ServiceTestCase(ViewTestCases.PrimaryObjectViewTestCase): class ServiceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = Service model = Service
# Disable inapplicable tests
test_import_objects = None
# TODO: Resolve URL for Service creation # TODO: Resolve URL for Service creation
test_create_object = None test_create_object = None
@ -366,6 +363,13 @@ class ServiceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
'tags': 'Alpha,Bravo,Charlie', 'tags': 'Alpha,Bravo,Charlie',
} }
cls.csv_data = (
"device,name,protocol,port,description",
"Device 1,Service 1,TCP,1,First service",
"Device 1,Service 2,TCP,2,Second service",
"Device 1,Service 3,UDP,3,Third service",
)
cls.bulk_edit_data = { cls.bulk_edit_data = {
'protocol': ServiceProtocolChoices.PROTOCOL_UDP, 'protocol': ServiceProtocolChoices.PROTOCOL_UDP,
'port': 888, 'port': 888,

View File

@ -94,6 +94,7 @@ urlpatterns = [
# Services # Services
path('services/', views.ServiceListView.as_view(), name='service_list'), path('services/', views.ServiceListView.as_view(), name='service_list'),
path('services/import/', views.ServiceBulkImportView.as_view(), name='service_import'),
path('services/edit/', views.ServiceBulkEditView.as_view(), name='service_bulk_edit'), path('services/edit/', views.ServiceBulkEditView.as_view(), name='service_bulk_edit'),
path('services/delete/', views.ServiceBulkDeleteView.as_view(), name='service_bulk_delete'), path('services/delete/', views.ServiceBulkDeleteView.as_view(), name='service_bulk_delete'),
path('services/<int:pk>/', views.ServiceView.as_view(), name='service'), path('services/<int:pk>/', views.ServiceView.as_view(), name='service'),

View File

@ -1015,6 +1015,13 @@ class ServiceCreateView(PermissionRequiredMixin, ObjectEditView):
return service.parent.get_absolute_url() return service.parent.get_absolute_url()
class ServiceBulkImportView(PermissionRequiredMixin, BulkImportView):
permission_required = 'ipam.add_service'
model_form = forms.ServiceCSVForm
table = tables.ServiceTable
default_return_url = 'ipam:service_list'
class ServiceEditView(ServiceCreateView): class ServiceEditView(ServiceCreateView):
permission_required = 'ipam.change_service' permission_required = 'ipam.change_service'

View File

@ -338,6 +338,11 @@
<li class="divider"></li> <li class="divider"></li>
<li class="dropdown-header">Services</li> <li class="dropdown-header">Services</li>
<li{% if not perms.ipam.view_service %} class="disabled"{% endif %}> <li{% if not perms.ipam.view_service %} class="disabled"{% endif %}>
{% if perms.ipam.add_vservice %}
<div class="buttons pull-right">
<a href="{% url 'ipam:service_import' %}" class="btn btn-xs btn-info" title="Import"><i class="fa fa-download"></i></a>
</div>
{% endif %}
<a href="{% url 'ipam:service_list' %}">Services</a> <a href="{% url 'ipam:service_list' %}">Services</a>
</li> </li>
</ul> </ul>