diff --git a/.pylintrc b/.pylintrc index 4e2d6a9..6ef3977 100644 --- a/.pylintrc +++ b/.pylintrc @@ -1,5 +1,5 @@ [MASTER] -ignore=migrations +ignore=migrations,tests [MESSAGES CONTROL] disable=no-member,too-few-public-methods,too-many-ancestors, duplicate-code \ No newline at end of file diff --git a/netopsio/core/__init__.py b/netopsio/core/__init__.py new file mode 100644 index 0000000..239c127 --- /dev/null +++ b/netopsio/core/__init__.py @@ -0,0 +1 @@ +"""Netops.io core app.""" diff --git a/netopsio/core/admin.py b/netopsio/core/admin.py new file mode 100644 index 0000000..651dfe9 --- /dev/null +++ b/netopsio/core/admin.py @@ -0,0 +1,14 @@ +"""Register core models in admin panel.""" + +from django.contrib import admin + +from core.models import RequestLog + + +class RequestLogAdmin(admin.ModelAdmin): + """Request Log Admin Site Fields.""" + + list_display = ("ip", "app", "date") + + +admin.site.register(RequestLog, RequestLogAdmin) diff --git a/netopsio/core/api/__init__.py b/netopsio/core/api/__init__.py new file mode 100644 index 0000000..6f6fd31 --- /dev/null +++ b/netopsio/core/api/__init__.py @@ -0,0 +1 @@ +"""Core application API.""" diff --git a/netopsio/home/serializers.py b/netopsio/core/api/serializers.py similarity index 56% rename from netopsio/home/serializers.py rename to netopsio/core/api/serializers.py index 25a62dc..8fb9a6a 100644 --- a/netopsio/home/serializers.py +++ b/netopsio/core/api/serializers.py @@ -1,6 +1,8 @@ -"""Home App and Worker Serializers.""" -from rest_framework import serializers +"""Core App and Worker Serializers.""" from django_celery_results.models import TaskResult +from rest_framework import serializers + +from core import models class TaskResultSerializer(serializers.HyperlinkedModelSerializer): @@ -24,3 +26,19 @@ class Meta: "date_done", "url", ] + + +class TaskSerializer(serializers.Serializer): # pylint: disable=abstract-method + """Ping Serializer.""" + + task_id = serializers.CharField(max_length=512) + + +class RequestLogSerializer(serializers.ModelSerializer): + """RequestLog Serializer.""" + + class Meta: + """RequestLog Serializer Meta.""" + + model = models.RequestLog + fields = ["id", "date", "task_id", "ip", "app", "result", "url"] diff --git a/netopsio/core/api/urls.py b/netopsio/core/api/urls.py new file mode 100644 index 0000000..b573ef8 --- /dev/null +++ b/netopsio/core/api/urls.py @@ -0,0 +1,12 @@ +"""Netops.io core api urls.""" + +from rest_framework.routers import DefaultRouter + +from core.api import views + +router = DefaultRouter() +router.register(r"tasks", views.TaskResultViewSet) +router.register(r"request-logs", views.RequestLogViewSet, basename="requestlog") +router.register(r"ping", views.PingViewSet, basename="ping") +router.register(r"traceroute", views.TraceRouteViewSet, basename="traceroute") +router.register(r"nmap", views.NmapViewSet, basename="nmap") diff --git a/netopsio/core/api/views.py b/netopsio/core/api/views.py new file mode 100644 index 0000000..facb2c5 --- /dev/null +++ b/netopsio/core/api/views.py @@ -0,0 +1,92 @@ +"""Netops.io core api views.""" + +from django_celery_results.models import TaskResult +from drf_yasg import openapi +from drf_yasg.utils import swagger_auto_schema +from rest_framework import viewsets +from rest_framework.response import Response + +from core import models, tasks +from core.api import serializers +from netopsio.utilities import get_ip_address + + +class TaskResultViewSet(viewsets.ReadOnlyModelViewSet): + """Rest API View for 'list' and 'retrieving' TaskResult actions.""" + + queryset = TaskResult.objects.all() + serializer_class = serializers.TaskResultSerializer + lookup_field = "task_id" + + +class RequestLogViewSet(viewsets.ReadOnlyModelViewSet): + """Rest API View for 'list' and 'retrieving' RequestLog actions.""" + + queryset = models.RequestLog.objects.all() + serializer_class = serializers.RequestLogSerializer + + +class PingViewSet(viewsets.ViewSet): + """Ping Viewset.""" + + @swagger_auto_schema( + request_body=openapi.Schema( + type=openapi.TYPE_OBJECT, + properties={ + "host": openapi.Schema( + type=openapi.TYPE_STRING, description="Host to ping." + ), + }, + ) + ) # pylint: disable=no-self-use + def create(self, request, host=None): + """Ping a host.""" + host = get_ip_address(request) + task = tasks.ping.delay(host=host) + data = models.TaskModel(task_id=task.task_id) + serializer = serializers.TaskSerializer(data, context={"request": request}) + return Response(serializer.data) + + +class TraceRouteViewSet(viewsets.ViewSet): + """TraceRoute Viewset.""" + + @swagger_auto_schema( + request_body=openapi.Schema( + type=openapi.TYPE_OBJECT, + properties={ + "host": openapi.Schema( + type=openapi.TYPE_STRING, description="Host to traceroute." + ), + }, + ) + ) # pylint: disable=no-self-use + def create(self, request, host=None): + """Traceroute a host.""" + host = get_ip_address(request) + task = tasks.traceroute.delay(host=host) + data = models.TaskModel(task_id=task.task_id) + serializer = serializers.TaskSerializer(data, context={"request": request}) + return Response(serializer.data) + + +class NmapViewSet(viewsets.ViewSet): + """Nmap Viewset.""" + + @swagger_auto_schema( + request_body=openapi.Schema( + type=openapi.TYPE_OBJECT, + properties={ + "host": openapi.Schema( + type=openapi.TYPE_STRING, description="Host to ping." + ), + }, + ) + ) # pylint: disable=no-self-use + def create(self, request, host=None): + """Nmap a host.""" + host = get_ip_address(request) + task = tasks.nmap.delay(host=host) + data = models.TaskModel(task_id=task.task_id) + serializer = serializers.TaskSerializer(data, context={"request": request}) + return Response(serializer.data) diff --git a/netopsio/home/apps.py b/netopsio/core/apps.py similarity index 63% rename from netopsio/home/apps.py rename to netopsio/core/apps.py index 4191065..cfd1f99 100644 --- a/netopsio/home/apps.py +++ b/netopsio/core/apps.py @@ -3,7 +3,7 @@ from django.apps import AppConfig -class HomeConfig(AppConfig): - "Home app config." +class CoreConfig(AppConfig): + "Core app config." default_auto_field = "django.db.models.BigAutoField" - name = "home" + name = "core" diff --git a/netopsio/traceroute/migrations/0001_initial.py b/netopsio/core/migrations/0001_add_request_log.py similarity index 84% rename from netopsio/traceroute/migrations/0001_initial.py rename to netopsio/core/migrations/0001_add_request_log.py index a9eadbf..53d7bbe 100644 --- a/netopsio/traceroute/migrations/0001_initial.py +++ b/netopsio/core/migrations/0001_add_request_log.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.10 on 2022-07-11 00:25 +# Generated by Django 3.2.10 on 2022-07-18 02:40 from django.db import migrations, models @@ -11,7 +11,7 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name="TraceRouteRequest", + name="RequestLog", fields=[ ( "id", @@ -26,6 +26,7 @@ class Migration(migrations.Migration): ("task_id", models.UUIDField(null=True, unique=True)), ("ip", models.CharField(max_length=255)), ("result", models.TextField()), + ("app", models.CharField(max_length=255)), ], ), ] diff --git a/netopsio/home/__init__.py b/netopsio/core/migrations/__init__.py similarity index 100% rename from netopsio/home/__init__.py rename to netopsio/core/migrations/__init__.py diff --git a/netopsio/nmap/models.py b/netopsio/core/models.py similarity index 64% rename from netopsio/nmap/models.py rename to netopsio/core/models.py index 078189e..1583cbd 100644 --- a/netopsio/nmap/models.py +++ b/netopsio/core/models.py @@ -1,19 +1,20 @@ -"""Nmap App Models.""" +"""Netops.io core app models.""" from django.db import models -class NmapRequest(models.Model): - """Nmap Requests Logging Model.""" +class RequestLog(models.Model): + """Request Logging Model.""" date = models.DateTimeField(auto_now_add=True) task_id = models.UUIDField(unique=True, null=True) ip = models.CharField(max_length=255) result = models.TextField() + app = models.CharField(max_length=255) -class Nmap: - """Nmap Model.""" +class TaskModel: + """Task Model.""" def __init__(self, task_id: str): """Initialize the model.""" diff --git a/netopsio/core/tasks.py b/netopsio/core/tasks.py new file mode 100644 index 0000000..2832dd0 --- /dev/null +++ b/netopsio/core/tasks.py @@ -0,0 +1,35 @@ +"""Celery Background Tasks""" +import subprocess + +from celery import shared_task + +from core.models import RequestLog + + +@shared_task +def ping(host: str, count: int = 2) -> str: + """Ping host worker.""" + task = subprocess.run( + ["ping", f"-c {count}", host], capture_output=True, check=True + ) + data = RequestLog(ip=host, result=task.stdout.decode("utf-8"), app="ping") + data.save() + return task.stdout.decode("utf-8") + + +@shared_task +def traceroute(host: str) -> str: + """Traceroute host worker.""" + task = subprocess.run(["traceroute", host], capture_output=True, check=True) + data = RequestLog(ip=host, result=task.stdout.decode("utf-8"), app="traceroute") + data.save() + return task.stdout.decode("utf-8") + + +@shared_task +def nmap(host: str) -> str: + """Nmap host worker.""" + task = subprocess.run(["nmap", "-v", "-A", host], capture_output=True, check=True) + data = RequestLog(ip=host, result=task.stdout.decode("utf-8"), app="nmap") + data.save() + return task.stdout.decode("utf-8") diff --git a/netopsio/home/templates/home/base.html b/netopsio/core/templates/core/base.html similarity index 100% rename from netopsio/home/templates/home/base.html rename to netopsio/core/templates/core/base.html diff --git a/netopsio/nmap/templates/nmap/base.html b/netopsio/core/templates/core/task.html similarity index 96% rename from netopsio/nmap/templates/nmap/base.html rename to netopsio/core/templates/core/task.html index 0a4b88c..3de707f 100644 --- a/netopsio/nmap/templates/nmap/base.html +++ b/netopsio/core/templates/core/task.html @@ -14,4 +14,4 @@ -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/netopsio/home/templates/home/task_details.html b/netopsio/core/templates/core/task_details.html similarity index 100% rename from netopsio/home/templates/home/task_details.html rename to netopsio/core/templates/core/task_details.html diff --git a/netopsio/home/templates/home/tasks.html b/netopsio/core/templates/core/tasks.html similarity index 100% rename from netopsio/home/templates/home/tasks.html rename to netopsio/core/templates/core/tasks.html diff --git a/netopsio/core/tests/__init__.py b/netopsio/core/tests/__init__.py new file mode 100644 index 0000000..67ad1ef --- /dev/null +++ b/netopsio/core/tests/__init__.py @@ -0,0 +1 @@ +"""Core tests.""" diff --git a/netopsio/core/tests/test_api.py b/netopsio/core/tests/test_api.py new file mode 100644 index 0000000..19ae06d --- /dev/null +++ b/netopsio/core/tests/test_api.py @@ -0,0 +1,43 @@ +"""Core api tests.""" +from django.test import TestCase +from rest_framework.test import APIRequestFactory + +from core.api import views + + +class CoreApiTestCase(TestCase): + def setUp(self): + self.factory = APIRequestFactory() + self.ping = views.PingViewSet() + self.traceroute = views.TraceRouteViewSet() + self.nmap = views.NmapViewSet() + self.host = {"host": "localhost"} + self.content_type = {"Content-type": "application/json"} + return super().setUp() + + def test_ping_api(self): + request = self.factory.post( + "/api/v1/ping/", + self.host, + content_type=self.content_type, + ) + response = self.ping.create(request) + self.assertEqual(response.status_code, 200) + + def test_traceroute_api(self): + request = self.factory.post( + "/api/v1/traceroute/", + self.host, + content_type=self.content_type, + ) + response = self.traceroute.create(request) + self.assertEqual(response.status_code, 200) + + def test_nmap_api(self): + request = self.factory.post( + "/api/v1/nmap/", + self.host, + content_type=self.content_type, + ) + response = self.nmap.create(request) + self.assertEqual(response.status_code, 200) diff --git a/netopsio/core/tests/test_models.py b/netopsio/core/tests/test_models.py new file mode 100644 index 0000000..e0bf350 --- /dev/null +++ b/netopsio/core/tests/test_models.py @@ -0,0 +1,18 @@ +"Core app tests." +from django.test import TestCase + +from core.models import RequestLog + + +class RequestLogTestCase(TestCase): + """RequestLog TestCases.""" + + def setUp(self): + """Setup tests.""" + RequestLog.objects.create(ip="1.1.1.1", result="OK", app="ping") + return super().setUp() + + def test_requestlog_models(self): + """Test RequestLog models.""" + req = RequestLog.objects.get(ip="1.1.1.1") + self.assertEqual(req.ip, "1.1.1.1") diff --git a/netopsio/core/tests/test_tasks.py b/netopsio/core/tests/test_tasks.py new file mode 100644 index 0000000..48af040 --- /dev/null +++ b/netopsio/core/tests/test_tasks.py @@ -0,0 +1,23 @@ +"""Core tasks tests.""" + + +from django.test import TestCase + +from core import tasks + + +class TasksTestCase(TestCase): + def setUp(self): + self.host = "localhost" + + def test_ping_task(self): + ping = tasks.ping.delay(host=self.host) + self.assertIn(ping.status, ("PENDING", "STARTED", "SUCCESS")) + + def test_traceroute_task(self): + traceroute = tasks.ping.delay(host=self.host) + self.assertIn(traceroute.status, ("PENDING", "STARTED", "SUCCESS")) + + def test_nmap_task(self): + nmap = tasks.nmap.delay(host=self.host) + self.assertIn(nmap.status, ("PENDING", "STARTED", "SUCCESS")) diff --git a/netopsio/core/tests/test_views.py b/netopsio/core/tests/test_views.py new file mode 100644 index 0000000..613729d --- /dev/null +++ b/netopsio/core/tests/test_views.py @@ -0,0 +1,12 @@ +"Core app tests." +from django.test import TestCase + + +class CoreViewsTest(TestCase): + """Test the Core App views.""" + + def test_index_view(self): + """Test the core page.""" + response = self.client.get("/") + self.assertTemplateUsed(response, "core/base.html") + self.assertEqual(response.status_code, 200) diff --git a/netopsio/core/urls.py b/netopsio/core/urls.py new file mode 100644 index 0000000..6f24fa1 --- /dev/null +++ b/netopsio/core/urls.py @@ -0,0 +1,13 @@ +"Core app urls." +from django.urls import path + +from core import views + +urlpatterns = [ + path("", views.index, name="core-index"), + path("tasks/", views.tasks_view, name="tasks"), + path("tasks//", views.task_details, name="task-details"), + path("ping/", views.ping, name="ping"), + path("traceroute/", views.traceroute, name="traceroute"), + path("nmap/", views.nmap, name="nmap"), +] diff --git a/netopsio/core/views.py b/netopsio/core/views.py new file mode 100644 index 0000000..580f50f --- /dev/null +++ b/netopsio/core/views.py @@ -0,0 +1,59 @@ +"Core app views." +from django.http import HttpResponse +from django.shortcuts import get_object_or_404 +from django.template import loader +from django_celery_results.models import TaskResult + +from core import tasks +from netopsio.utilities import get_ip_address + + +def index(request): + """Render Core Page.""" + template = loader.get_template("core/base.html") + context = {"title": "Home"} + return HttpResponse(template.render(context, request)) + + +def tasks_view(request): + """Render Task Results.""" + task_results = TaskResult.objects.all() + template = loader.get_template("core/tasks.html") + context = {"title": "Task Results", "results": task_results} + return HttpResponse(template.render(context, request)) + + +def task_details(request, task_id): + """Render Task Detail Results.""" + job = get_object_or_404(TaskResult, task_id=task_id) + result = "\n".join(job.result.strip('"').split("\\n")) + template = loader.get_template("core/task_details.html") + context = {"title": "Task Details", "job": job, "result": result} + return HttpResponse(template.render(context, request)) + + +def ping(request): + """Ping view.""" + host = get_ip_address(request) + task = tasks.ping.delay(host=host) + template = loader.get_template("core/task.html") + context = {"host": host, "status": task.status, "id": task, "title": "Ping"} + return HttpResponse(template.render(context, request)) + + +def traceroute(request): + """TraceRoute view.""" + host = get_ip_address(request) + task = tasks.traceroute.delay(host=host) + template = loader.get_template("core/task.html") + context = {"host": host, "status": task.status, "id": task, "title": "Traceroute"} + return HttpResponse(template.render(context, request)) + + +def nmap(request): + """Nmap view.""" + host = get_ip_address(request) + task = tasks.nmap.delay(host=host) + template = loader.get_template("core/task.html") + context = {"host": host, "status": task.status, "id": task, "title": "Nmap"} + return HttpResponse(template.render(context, request)) diff --git a/netopsio/home/admin.py b/netopsio/home/admin.py deleted file mode 100644 index 4185d36..0000000 --- a/netopsio/home/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -# from django.contrib import admin - -# Register your models here. diff --git a/netopsio/home/models.py b/netopsio/home/models.py deleted file mode 100644 index 0b4331b..0000000 --- a/netopsio/home/models.py +++ /dev/null @@ -1,3 +0,0 @@ -# from django.db import models - -# Create your models here. diff --git a/netopsio/home/tests.py b/netopsio/home/tests.py deleted file mode 100644 index 39e7e2d..0000000 --- a/netopsio/home/tests.py +++ /dev/null @@ -1,12 +0,0 @@ -"Home app tests." -from django.test import TestCase - - -class HomeViewsTest(TestCase): - """Test the Home App views.""" - - def test_index_view(self): - """Test the home page.""" - response = self.client.get("/") - self.assertTemplateUsed(response, "home/base.html") - self.assertEqual(response.status_code, 200) diff --git a/netopsio/home/urls.py b/netopsio/home/urls.py deleted file mode 100644 index 4dd612f..0000000 --- a/netopsio/home/urls.py +++ /dev/null @@ -1,10 +0,0 @@ -"Home app urls." -from django.urls import path -from . import views - -app_name = "" # pylint: disable=invalid-name -urlpatterns = [ - path("", views.index, name="home-index"), - path("tasks/", views.tasks, name="tasks"), - path("tasks//", views.task_details, name="task-details"), -] diff --git a/netopsio/home/views.py b/netopsio/home/views.py deleted file mode 100644 index 6897405..0000000 --- a/netopsio/home/views.py +++ /dev/null @@ -1,39 +0,0 @@ -"Home app views." -from django.http import HttpResponse -from django.template import loader -from django.shortcuts import get_object_or_404 -from django_celery_results.models import TaskResult -from rest_framework import viewsets -from home.serializers import TaskResultSerializer - - -def index(request): - """Render Home Page.""" - template = loader.get_template("home/base.html") - context = {"title": "Home"} - return HttpResponse(template.render(context, request)) - - -def tasks(request): - """Render Task Results.""" - task_results = TaskResult.objects.all() - template = loader.get_template("home/tasks.html") - context = {"title": "Task Results", "results": task_results} - return HttpResponse(template.render(context, request)) - - -def task_details(request, task_id): - """Render Task Detail Results.""" - job = get_object_or_404(TaskResult, task_id=task_id) - result = "\n".join(job.result.strip('"').split("\\n")) - template = loader.get_template("home/task_details.html") - context = {"title": "Task Details", "job": job, "result": result} - return HttpResponse(template.render(context, request)) - - -class TaskResultViewSet(viewsets.ReadOnlyModelViewSet): - """Rest API View for 'list' and 'retrieving' TaskResult actions.""" - - queryset = TaskResult.objects.all() - serializer_class = TaskResultSerializer - lookup_field = "task_id" diff --git a/netopsio/netopsio/__init__.py b/netopsio/netopsio/__init__.py index 50bf77f..890a790 100644 --- a/netopsio/netopsio/__init__.py +++ b/netopsio/netopsio/__init__.py @@ -1,4 +1,5 @@ """Netops.io Project Base.""" + from .celery import app as celery_app __all__ = ("celery_app",) diff --git a/netopsio/netopsio/celery.py b/netopsio/netopsio/celery.py index 2428b8a..5c4be3a 100644 --- a/netopsio/netopsio/celery.py +++ b/netopsio/netopsio/celery.py @@ -4,7 +4,6 @@ from celery import Celery - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "netopsio.settings") app = Celery( diff --git a/netopsio/netopsio/settings.py b/netopsio/netopsio/settings.py index ae6f826..b670711 100644 --- a/netopsio/netopsio/settings.py +++ b/netopsio/netopsio/settings.py @@ -10,8 +10,8 @@ https://docs.djangoproject.com/en/3.2/ref/settings/ """ -from pathlib import Path import os +from pathlib import Path # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent @@ -41,10 +41,7 @@ "rest_framework", "drf_yasg", "django_celery_results", - "home", - "ping", - "traceroute", - "nmap", + "core", ] MIDDLEWARE = [ diff --git a/netopsio/home/migrations/__init__.py b/netopsio/netopsio/tests/__init__.py similarity index 100% rename from netopsio/home/migrations/__init__.py rename to netopsio/netopsio/tests/__init__.py diff --git a/netopsio/netopsio/tests/test_utilities.py b/netopsio/netopsio/tests/test_utilities.py new file mode 100644 index 0000000..d515497 --- /dev/null +++ b/netopsio/netopsio/tests/test_utilities.py @@ -0,0 +1,20 @@ +"""Test netopsio utilities.""" +from django.test import RequestFactory, TestCase + +from netopsio import utilities + + +class UtilitiesTestCase(TestCase): + """Test Utilities.""" + + def setUp(self): + """Setup tests.""" + self.request = RequestFactory() + + def test_get_ip_address(self): + """Test get_ip_address.""" + response = self.request.get("/") + self.assertEqual(utilities.get_ip_address(response), "127.0.0.1") + + response.META["HTTP_X_FORWARDED_FOR"] = response.META["REMOTE_ADDR"] + self.assertEqual(utilities.get_ip_address(response), "127.0.0.1") diff --git a/netopsio/netopsio/urls.py b/netopsio/netopsio/urls.py index f759ae3..bd107a3 100644 --- a/netopsio/netopsio/urls.py +++ b/netopsio/netopsio/urls.py @@ -15,25 +15,11 @@ """ from django.contrib import admin from django.urls import include, path, re_path -from rest_framework.routers import DefaultRouter -from rest_framework import permissions -from drf_yasg.views import get_schema_view from drf_yasg import openapi -from home.views import TaskResultViewSet -from ping.views import PingRequestViewSet, PingViewSet -from traceroute.views import TraceRouteRequestViewSet, TraceRouteViewSet -from nmap.views import NmapRequestViewSet, NmapViewSet - - -router = DefaultRouter() -router.register(r"tasks", TaskResultViewSet) -router.register(r"ping-logs", PingRequestViewSet) -router.register(r"ping", PingViewSet, basename="ping") -router.register(r"traceroute-logs", TraceRouteRequestViewSet) -router.register(r"traceroute", TraceRouteViewSet, basename="traceroute") -router.register(r"nmap-logs", NmapRequestViewSet) -router.register(r"nmap", NmapViewSet, basename="nmap") +from drf_yasg.views import get_schema_view +from rest_framework import permissions +from core.api.urls import router schema_view = get_schema_view( # pylint: disable=invalid-name openapi.Info( @@ -48,12 +34,9 @@ urlpatterns = [ - path("", include("home.urls"), name="home"), - path("ping/", include("ping.urls"), name="ping"), - path("traceroute/", include("traceroute.urls"), name="traceroute"), - path("nmap/", include("nmap.urls"), name="nmap"), + path("", include("core.urls"), name="core"), path("admin/", admin.site.urls, name="admin"), - path("api/v1/", include(router.urls), name="admin-v1"), + path("api/v1/", include(router.urls), name="api-v1"), re_path( r"^api/docs/(?P\.json|\.yaml)$", schema_view.without_ui(cache_timeout=0), diff --git a/netopsio/nmap/__init__.py b/netopsio/nmap/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/netopsio/nmap/admin.py b/netopsio/nmap/admin.py deleted file mode 100644 index f45858d..0000000 --- a/netopsio/nmap/admin.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Register Nmap Models in Admin Pandel.""" - -from django.contrib import admin -from nmap.models import NmapRequest - - -class NmapAdmin(admin.ModelAdmin): - """Nmap Admin Site Fields.""" - - list_display = ("ip", "date") - - -admin.site.register(NmapRequest, NmapAdmin) diff --git a/netopsio/nmap/apps.py b/netopsio/nmap/apps.py deleted file mode 100644 index e470ba9..0000000 --- a/netopsio/nmap/apps.py +++ /dev/null @@ -1,8 +0,0 @@ -# pylint: skip-file - -from django.apps import AppConfig - - -class PingConfig(AppConfig): - default_auto_field = "django.db.models.BigAutoField" - name = "nmap" diff --git a/netopsio/nmap/migrations/0001_initial.py b/netopsio/nmap/migrations/0001_initial.py deleted file mode 100644 index 03d6c1e..0000000 --- a/netopsio/nmap/migrations/0001_initial.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 3.2.10 on 2022-07-11 01:55 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [] - - operations = [ - migrations.CreateModel( - name="NmapRequest", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("date", models.DateTimeField(auto_now_add=True)), - ("task_id", models.UUIDField(null=True, unique=True)), - ("ip", models.CharField(max_length=255)), - ("result", models.TextField()), - ], - ), - ] diff --git a/netopsio/nmap/migrations/__init__.py b/netopsio/nmap/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/netopsio/nmap/serializers.py b/netopsio/nmap/serializers.py deleted file mode 100644 index 7a8fda2..0000000 --- a/netopsio/nmap/serializers.py +++ /dev/null @@ -1,20 +0,0 @@ -"""Nmap App serializers.""" - -from rest_framework import serializers -from nmap.models import NmapRequest - - -class NmapRequestSerializer(serializers.ModelSerializer): - """NmapRequest Serializer.""" - - class Meta: - """NmapRequest Serializer Meta.""" - - model = NmapRequest - fields = ["id", "date", "task_id", "ip", "result", "url"] - - -class NmapSerializer(serializers.Serializer): # pylint: disable=abstract-method - """Nmap Serializer.""" - - task_id = serializers.CharField(max_length=512) diff --git a/netopsio/nmap/tasks.py b/netopsio/nmap/tasks.py deleted file mode 100644 index da7e298..0000000 --- a/netopsio/nmap/tasks.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Celery Background Tasks""" -import subprocess -from celery import shared_task -from nmap.models import NmapRequest - - -@shared_task -def nmap(host: str) -> str: - """Nmap host worker.""" - task = subprocess.run(["nmap", "-v", "-A", host], capture_output=True, check=True) - data = NmapRequest(ip=host, result=task.stdout.decode("utf-8")) - data.save() - return task.stdout.decode("utf-8") diff --git a/netopsio/nmap/tests.py b/netopsio/nmap/tests.py deleted file mode 100644 index 277625c..0000000 --- a/netopsio/nmap/tests.py +++ /dev/null @@ -1,16 +0,0 @@ -"""Nmap App Tests.""" -from django.test import TestCase -from nmap.models import NmapRequest - - -class TestNmap(TestCase): - """Nmap App TestCases.""" - - def setUp(self): - """Setup tests.""" - NmapRequest.objects.create(ip="1.1.1.1", result="OK") - - def test_nmap_models(self): - """Test Nmap App models.""" - req = NmapRequest.objects.get(ip="1.1.1.1") - self.assertEqual(req.ip, "1.1.1.1") diff --git a/netopsio/nmap/urls.py b/netopsio/nmap/urls.py deleted file mode 100644 index 2944ca9..0000000 --- a/netopsio/nmap/urls.py +++ /dev/null @@ -1,7 +0,0 @@ -"Ping app urls." -from django.urls import path -from nmap import views - -urlpatterns = [ - path("", views.index, name="nmap-index"), -] diff --git a/netopsio/nmap/views.py b/netopsio/nmap/views.py deleted file mode 100644 index bd07785..0000000 --- a/netopsio/nmap/views.py +++ /dev/null @@ -1,49 +0,0 @@ -"""Ping app views.""" -from django.http import HttpResponse -from django.template import loader -from nmap.tasks import nmap -from nmap.models import NmapRequest, Nmap -from nmap.serializers import NmapRequestSerializer, NmapSerializer -from rest_framework import viewsets -from rest_framework.response import Response -from drf_yasg import openapi -from drf_yasg.utils import swagger_auto_schema -from netopsio.utilities import get_ip_address - - -def index(request): - """Nmap app index view.""" - host = get_ip_address(request) - task = nmap.delay(host=host) - template = loader.get_template("nmap/base.html") - context = {"host": host, "status": task.status, "id": task, "title": "Nmap"} - return HttpResponse(template.render(context, request)) - - -class NmapRequestViewSet(viewsets.ReadOnlyModelViewSet): - """Rest API View for 'list' and 'retrieving' NmapRequest actions.""" - - queryset = NmapRequest.objects.all() - serializer_class = NmapRequestSerializer - - -class NmapViewSet(viewsets.ViewSet): - """Nmap Viewset.""" - - @swagger_auto_schema( - request_body=openapi.Schema( - type=openapi.TYPE_OBJECT, - properties={ - "host": openapi.Schema( - type=openapi.TYPE_STRING, description="Host to ping." - ), - }, - ) - ) # pylint: disable=no-self-use - def create(self, request, host=None): - """Nmap a host.""" - host = get_ip_address(request) - task = nmap.delay(host=host) - data = Nmap(task_id=task.task_id) - serializer = NmapSerializer(data, context={"request": request}) - return Response(serializer.data) diff --git a/netopsio/ping/__init__.py b/netopsio/ping/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/netopsio/ping/admin.py b/netopsio/ping/admin.py deleted file mode 100644 index 0552e2d..0000000 --- a/netopsio/ping/admin.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Register Ping Models in Admin Pandel.""" - -from django.contrib import admin -from ping.models import PingRequest - - -class PingAdmin(admin.ModelAdmin): - """Ping Admin Site Fields.""" - - list_display = ("ip", "date") - - -admin.site.register(PingRequest, PingAdmin) diff --git a/netopsio/ping/apps.py b/netopsio/ping/apps.py deleted file mode 100644 index 69b3aa6..0000000 --- a/netopsio/ping/apps.py +++ /dev/null @@ -1,8 +0,0 @@ -# pylint: skip-file - -from django.apps import AppConfig - - -class PingConfig(AppConfig): - default_auto_field = "django.db.models.BigAutoField" - name = "ping" diff --git a/netopsio/ping/migrations/0001_initial.py b/netopsio/ping/migrations/0001_initial.py deleted file mode 100644 index 9f69123..0000000 --- a/netopsio/ping/migrations/0001_initial.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 3.2.10 on 2021-12-22 14:23 -# pylint: skip-file - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [] - - operations = [ - migrations.CreateModel( - name="PingRequest", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("date", models.DateTimeField(auto_now_add=True)), - ("task_id", models.UUIDField(null=True, unique=True)), - ("ip", models.CharField(max_length=255)), - ("result", models.TextField()), - ], - ), - ] diff --git a/netopsio/ping/migrations/__init__.py b/netopsio/ping/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/netopsio/ping/models.py b/netopsio/ping/models.py deleted file mode 100644 index 2a3546c..0000000 --- a/netopsio/ping/models.py +++ /dev/null @@ -1,20 +0,0 @@ -"""Ping App Models.""" - -from django.db import models - - -class PingRequest(models.Model): - """Ping Requests Logging Model.""" - - date = models.DateTimeField(auto_now_add=True) - task_id = models.UUIDField(unique=True, null=True) - ip = models.CharField(max_length=255) - result = models.TextField() - - -class Ping: - """Ping Model.""" - - def __init__(self, task_id: str): - """Initialize the model.""" - self.task_id = task_id diff --git a/netopsio/ping/serializers.py b/netopsio/ping/serializers.py deleted file mode 100644 index 569eda3..0000000 --- a/netopsio/ping/serializers.py +++ /dev/null @@ -1,20 +0,0 @@ -"""Ping App serializers.""" - -from rest_framework import serializers -from ping.models import PingRequest - - -class PingRequestSerializer(serializers.ModelSerializer): - """PingRequest Serializer.""" - - class Meta: - """PingRequest Serializer Meta.""" - - model = PingRequest - fields = ["id", "date", "task_id", "ip", "result", "url"] - - -class PingSerializer(serializers.Serializer): # pylint: disable=abstract-method - """Ping Serializer.""" - - task_id = serializers.CharField(max_length=512) diff --git a/netopsio/ping/tasks.py b/netopsio/ping/tasks.py deleted file mode 100644 index 21d3af4..0000000 --- a/netopsio/ping/tasks.py +++ /dev/null @@ -1,15 +0,0 @@ -"""Celery Background Tasks""" -import subprocess -from celery import shared_task -from ping.models import PingRequest - - -@shared_task -def ping(host: str, count: int = 2) -> str: - """Ping host worker.""" - task = subprocess.run( - ["ping", f"-c {count}", host], capture_output=True, check=True - ) - data = PingRequest(ip=host, result=task.stdout.decode("utf-8")) - data.save() - return task.stdout.decode("utf-8") diff --git a/netopsio/ping/templates/ping/base.html b/netopsio/ping/templates/ping/base.html deleted file mode 100644 index 0a4b88c..0000000 --- a/netopsio/ping/templates/ping/base.html +++ /dev/null @@ -1,17 +0,0 @@ -{% extends "base.html" %} -{% block content %} -
- - - - - - - - - - - -
StatusHost
{{ status }}{{ host }}
-
-{% endblock %} diff --git a/netopsio/ping/tests.py b/netopsio/ping/tests.py deleted file mode 100644 index 6048401..0000000 --- a/netopsio/ping/tests.py +++ /dev/null @@ -1,16 +0,0 @@ -"""Ping App Tests.""" -from django.test import TestCase -from ping.models import PingRequest - - -class TestPing(TestCase): - """Ping App TestCases.""" - - def setUp(self): - """Setup tests.""" - PingRequest.objects.create(ip="1.1.1.1", result="OK") - - def test_ping_models(self): - """Test Ping App models.""" - req = PingRequest.objects.get(ip="1.1.1.1") - self.assertEqual(req.ip, "1.1.1.1") diff --git a/netopsio/ping/urls.py b/netopsio/ping/urls.py deleted file mode 100644 index 65bc607..0000000 --- a/netopsio/ping/urls.py +++ /dev/null @@ -1,7 +0,0 @@ -"Ping app urls." -from django.urls import path -from ping import views - -urlpatterns = [ - path("", views.index, name="ping-index"), -] diff --git a/netopsio/ping/views.py b/netopsio/ping/views.py deleted file mode 100644 index f610384..0000000 --- a/netopsio/ping/views.py +++ /dev/null @@ -1,49 +0,0 @@ -"""Ping app views.""" -from django.http import HttpResponse -from django.template import loader -from ping.tasks import ping -from ping.models import PingRequest, Ping -from ping.serializers import PingRequestSerializer, PingSerializer -from rest_framework import viewsets -from rest_framework.response import Response -from drf_yasg import openapi -from drf_yasg.utils import swagger_auto_schema -from netopsio.utilities import get_ip_address - - -def index(request): - """Ping app index view.""" - host = get_ip_address(request) - task = ping.delay(host=host) - template = loader.get_template("ping/base.html") - context = {"host": host, "status": task.status, "id": task, "title": "Ping"} - return HttpResponse(template.render(context, request)) - - -class PingRequestViewSet(viewsets.ReadOnlyModelViewSet): - """Rest API View for 'list' and 'retrieving' PingRequest actions.""" - - queryset = PingRequest.objects.all() - serializer_class = PingRequestSerializer - - -class PingViewSet(viewsets.ViewSet): - """Ping Viewset.""" - - @swagger_auto_schema( - request_body=openapi.Schema( - type=openapi.TYPE_OBJECT, - properties={ - "host": openapi.Schema( - type=openapi.TYPE_STRING, description="Host to ping." - ), - }, - ) - ) # pylint: disable=no-self-use - def create(self, request, host=None): - """Ping a host.""" - host = get_ip_address(request) - task = ping.delay(host=host) - data = Ping(task_id=task.task_id) - serializer = PingSerializer(data, context={"request": request}) - return Response(serializer.data) diff --git a/netopsio/traceroute/__init__.py b/netopsio/traceroute/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/netopsio/traceroute/admin.py b/netopsio/traceroute/admin.py deleted file mode 100644 index 66e95d8..0000000 --- a/netopsio/traceroute/admin.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Register Ping Models in Admin Pandel.""" - -from django.contrib import admin -from traceroute.models import TraceRouteRequest - - -class TraceRouteAdmin(admin.ModelAdmin): - """TraceRoute Admin Site Fields.""" - - list_display = ("ip", "date") - - -admin.site.register(TraceRouteRequest, TraceRouteAdmin) diff --git a/netopsio/traceroute/apps.py b/netopsio/traceroute/apps.py deleted file mode 100644 index 99b760d..0000000 --- a/netopsio/traceroute/apps.py +++ /dev/null @@ -1,8 +0,0 @@ -# pylint: skip-file - -from django.apps import AppConfig - - -class TraceRouteConfig(AppConfig): - default_auto_field = "django.db.models.BigAutoField" - name = "traceroute" diff --git a/netopsio/traceroute/migrations/__init__.py b/netopsio/traceroute/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/netopsio/traceroute/models.py b/netopsio/traceroute/models.py deleted file mode 100644 index 7caa112..0000000 --- a/netopsio/traceroute/models.py +++ /dev/null @@ -1,20 +0,0 @@ -"""Ping App Models.""" - -from django.db import models - - -class TraceRouteRequest(models.Model): - """TraceRoute Requests Logging Model.""" - - date = models.DateTimeField(auto_now_add=True) - task_id = models.UUIDField(unique=True, null=True) - ip = models.CharField(max_length=255) - result = models.TextField() - - -class TraceRoute: - """TraceRoute Model.""" - - def __init__(self, task_id: str): - """Initialize the model.""" - self.task_id = task_id diff --git a/netopsio/traceroute/serializers.py b/netopsio/traceroute/serializers.py deleted file mode 100644 index 803a05c..0000000 --- a/netopsio/traceroute/serializers.py +++ /dev/null @@ -1,20 +0,0 @@ -"""TraceRoute App serializers.""" - -from rest_framework import serializers -from traceroute.models import TraceRouteRequest - - -class TraceRouteRequestSerializer(serializers.ModelSerializer): - """TraceRouteRequest Serializer.""" - - class Meta: - """TraceRouteRequest Serializer Meta.""" - - model = TraceRouteRequest - fields = ["id", "date", "task_id", "ip", "result", "url"] - - -class TraceRouteSerializer(serializers.Serializer): # pylint: disable=abstract-method - """TraceRoute Serializer.""" - - task_id = serializers.CharField(max_length=512) diff --git a/netopsio/traceroute/tasks.py b/netopsio/traceroute/tasks.py deleted file mode 100644 index b8ca11f..0000000 --- a/netopsio/traceroute/tasks.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Celery Background Tasks""" -import subprocess -from celery import shared_task -from traceroute.models import TraceRouteRequest - - -@shared_task -def traceroute(host: str) -> str: - """Traceroute host worker.""" - task = subprocess.run(["traceroute", host], capture_output=True, check=True) - data = TraceRouteRequest(ip=host, result=task.stdout.decode("utf-8")) - data.save() - return task.stdout.decode("utf-8") diff --git a/netopsio/traceroute/templates/traceroute/base.html b/netopsio/traceroute/templates/traceroute/base.html deleted file mode 100644 index 0a4b88c..0000000 --- a/netopsio/traceroute/templates/traceroute/base.html +++ /dev/null @@ -1,17 +0,0 @@ -{% extends "base.html" %} -{% block content %} -
- - - - - - - - - - - -
StatusHost
{{ status }}{{ host }}
-
-{% endblock %} diff --git a/netopsio/traceroute/tests.py b/netopsio/traceroute/tests.py deleted file mode 100644 index b406298..0000000 --- a/netopsio/traceroute/tests.py +++ /dev/null @@ -1,16 +0,0 @@ -"""Ping App Tests.""" -from django.test import TestCase -from traceroute.models import TraceRouteRequest - - -class TestTraceRoute(TestCase): - """TraceRoute App TestCases.""" - - def setUp(self): - """Setup tests.""" - TraceRouteRequest.objects.create(ip="1.1.1.1", result="OK") - - def test_traceroute_models(self): - """Test TraceRoute App models.""" - req = TraceRouteRequest.objects.get(ip="1.1.1.1") - self.assertEqual(req.ip, "1.1.1.1") diff --git a/netopsio/traceroute/urls.py b/netopsio/traceroute/urls.py deleted file mode 100644 index 94215c4..0000000 --- a/netopsio/traceroute/urls.py +++ /dev/null @@ -1,7 +0,0 @@ -"Ping app urls." -from django.urls import path -from traceroute import views - -urlpatterns = [ - path("", views.index, name="traceroute-index"), -] diff --git a/netopsio/traceroute/views.py b/netopsio/traceroute/views.py deleted file mode 100644 index 91d90b1..0000000 --- a/netopsio/traceroute/views.py +++ /dev/null @@ -1,49 +0,0 @@ -"""Ping app views.""" -from django.http import HttpResponse -from django.template import loader -from traceroute.tasks import traceroute -from traceroute.models import TraceRouteRequest, TraceRoute -from traceroute.serializers import TraceRouteRequestSerializer, TraceRouteSerializer -from rest_framework import viewsets -from rest_framework.response import Response -from drf_yasg import openapi -from drf_yasg.utils import swagger_auto_schema -from netopsio.utilities import get_ip_address - - -def index(request): - """TraceRoute app index view.""" - host = get_ip_address(request) - task = traceroute.delay(host=host) - template = loader.get_template("traceroute/base.html") - context = {"host": host, "status": task.status, "id": task, "title": "Traceroute"} - return HttpResponse(template.render(context, request)) - - -class TraceRouteRequestViewSet(viewsets.ReadOnlyModelViewSet): - """Rest API View for 'list' and 'retrieving' TraceRouteRequest actions.""" - - queryset = TraceRouteRequest.objects.all() - serializer_class = TraceRouteRequestSerializer - - -class TraceRouteViewSet(viewsets.ViewSet): - """TraceRoute Viewset.""" - - @swagger_auto_schema( - request_body=openapi.Schema( - type=openapi.TYPE_OBJECT, - properties={ - "host": openapi.Schema( - type=openapi.TYPE_STRING, description="Host to traceroute." - ), - }, - ) - ) # pylint: disable=no-self-use - def create(self, request, host=None): - """Traceroute a host.""" - host = get_ip_address(request) - task = traceroute.delay(host=host) - data = TraceRoute(task_id=task.task_id) - serializer = TraceRouteSerializer(data, context={"request": request}) - return Response(serializer.data) diff --git a/pyproject.toml b/pyproject.toml index 901234b..9c600ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "netops.io" -version = "0.3.1" +version = "0.3.2" description = "netops.io web application and rest framework" authors = ["James Williams "] license = "Apache" diff --git a/tasks.py b/tasks.py index 6488539..d0e1bf9 100644 --- a/tasks.py +++ b/tasks.py @@ -1,10 +1,10 @@ """Invoke Linting Task Automation.""" import os + from invoke import Collection from invoke import task as invoke_task - namespace = Collection("netopsio") namespace.configure( { @@ -63,6 +63,12 @@ def docker_compose(context, command, **kwargs): # Linting Tasks +@task +def isort(context): + """Execute Python isort.""" + context.run("isort .") + + @task def black(context): """Execute Python Black.""" @@ -78,12 +84,13 @@ def pylint(context): @task def flake8(context): """Execute Python Flake8.""" - context.run("flake8 netopsio/* --ignore=E501") + context.run("flake8 netopsio/* --ignore=E501 --exclude=*/tests/*") @task def linting(context): """Execute Linting Tasks.""" + isort(context) black(context) pylint(context) flake8(context) @@ -95,8 +102,11 @@ def linting(context): @task def coverage(context, container="app", percent=80): """Execute Coverage Test.""" + omit = ["netopsio/asgi.py", "netopsio/wsgi.py", "*/tests*", "manage.py"] coverage_cmd = "coverage run --source '.' manage.py test" - coverage_report = f"coverage report --fail-under={percent} -m" + coverage_report = ( + f"coverage report --fail-under={percent} -m --omit={','.join(omit)}" + ) docker_compose(context, f"exec {container} {coverage_cmd}", pty=True) docker_compose(context, f"exec {container} {coverage_report}", pty=True)