Skip to content

Commit 37b3f77

Browse files
authored
Merge pull request #11 from jtdub/ping
Ping App
2 parents 911c083 + 2e6dd99 commit 37b3f77

33 files changed

+1067
-214
lines changed

.github/workflows/linting.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
- uses: actions/checkout@v2
1414
- uses: hadolint/[email protected]
1515
with:
16-
dockerfile: Dockerfile
16+
dockerfile: development/Dockerfile
1717
black:
1818
runs-on: ubuntu-latest
1919
strategy:
@@ -30,7 +30,7 @@ jobs:
3030
uses: "networktocode/gh-action-setup-poetry-environment@v2"
3131
- name: "Linting: Black"
3232
run: |
33-
poetry run black --diff netopsio/
33+
poetry run invoke black
3434
pylint:
3535
runs-on: ubuntu-latest
3636
strategy:
@@ -47,7 +47,7 @@ jobs:
4747
uses: "networktocode/gh-action-setup-poetry-environment@v2"
4848
- name: "Linting: PyLint"
4949
run: |
50-
poetry run pylint netopsio/netopsio/ netopsio/home/
50+
poetry run invoke pylint
5151
flake8:
5252
runs-on: ubuntu-latest
5353
strategy:
@@ -64,4 +64,4 @@ jobs:
6464
uses: "networktocode/gh-action-setup-poetry-environment@v2"
6565
- name: "Linting: Flake8"
6666
run: |
67-
poetry run flake8 netopsio/ --ignore E501
67+
poetry run invoke flake8

.github/workflows/unit-tests.yaml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
strategy:
1313
fail-fast: true
1414
matrix:
15-
python-version: ["3.8", "3.9", "3.10"]
15+
python-version: ["3.10"]
1616
steps:
1717
- uses: actions/checkout@v2
1818
- name: Set up Python ${{ matrix.python-version }}
@@ -23,4 +23,8 @@ jobs:
2323
uses: "networktocode/gh-action-setup-poetry-environment@v2"
2424
- name: Execute Unit Tests
2525
run: |
26-
cd netopsio; poetry run ./manage.py test; cd -
26+
poetry run invoke build
27+
poetry run invoke start
28+
sleep 20
29+
poetry run invoke migrate
30+
poetry run invoke unittest

.pylintrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[MESSAGES CONTROL]
2+
disable=no-member
Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
FROM python:3.10-slim-bullseye
22

3-
WORKDIR /opt/netopsio
4-
53
ENV PATH="${PATH}:/root/.local/bin"
64

75
EXPOSE 8000
86

9-
COPY netopsio /opt/netopsio
7+
WORKDIR /opt/netopsio
8+
9+
VOLUME /opt/netopsio
1010

1111
COPY pyproject.toml .
1212

1313
COPY poetry.lock .
1414

1515
# hadolint ignore=DL3008
1616
RUN apt-get update && \
17-
apt-get install -y --no-install-recommends nmap iputils-ping traceroute curl && \
17+
apt-get install -y --no-install-recommends nmap iputils-ping traceroute curl mariadb-client libmariadb-dev gcc && \
1818
apt-get autoremove -y && \
1919
apt-get clean all && \
2020
rm -rf /var/lib/apt/lists/*
@@ -28,5 +28,3 @@ RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/inst
2828
RUN poetry config virtualenvs.create false && \
2929
poetry config installer.parallel false && \
3030
poetry install
31-
32-
CMD ["./manage.py", "runserver", "0.0.0.0:8000", "--insecure"]

development/creds.env

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# NETOPSIOS Settings
2+
NETOPSIO_DB_NAME = "netopsio"
3+
NETOPSIO_DB_USER = "root"
4+
NETOPSIO_DB_PASS = "superduper"
5+
NETOPSIO_DB_HOST = "db"
6+
NETOPSIO_BROKER_URL = "redis://redis:6379/0"
7+
8+
# Database Settings
9+
MARIADB_DATABASE = "netopsio"
10+
MARIADB_ROOT_PASSWORD = "superduper"
11+
12+
# Redis Settings
13+
REDIS_HOST = "redis"

development/docker-compose.yaml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
version: "3.9"
2+
services:
3+
db:
4+
image: "mariadb:latest"
5+
env_file: "creds.env"
6+
redis:
7+
image: "redis:latest"
8+
proxy:
9+
image: "haproxy:latest"
10+
volumes:
11+
- ./haproxy:/usr/local/etc/haproxy
12+
ports:
13+
- "80:80"
14+
links:
15+
- "app"
16+
worker:
17+
build:
18+
context: ../
19+
dockerfile: ./development/Dockerfile
20+
env_file: "creds.env"
21+
volumes:
22+
- ../netopsio:/opt/netopsio
23+
depends_on:
24+
- "db"
25+
- "redis"
26+
links:
27+
- "db"
28+
- "redis"
29+
command: ["celery", "-A", "netopsio", "worker", "-l", "INFO"]
30+
app:
31+
build:
32+
context: ../
33+
dockerfile: ./development/Dockerfile
34+
env_file: "creds.env"
35+
ports:
36+
- "8000:8000"
37+
volumes:
38+
- ../netopsio:/opt/netopsio
39+
depends_on:
40+
- "db"
41+
links:
42+
- "db"
43+
- "worker"
44+
restart: "always"
45+
command: ["./scripts/delay-start.sh", "./manage.py", "runserver", "0.0.0.0:8000", "--insecure"]

development/haproxy/haproxy.cfg

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
defaults
2+
timeout connect 10s
3+
timeout client 30s
4+
timeout server 30s
5+
log global
6+
mode http
7+
option httplog
8+
maxconn 3000
9+
10+
frontend http_server
11+
bind 0.0.0.0:80
12+
default_backend app_server
13+
14+
backend app_server
15+
balance roundrobin
16+
option forwardfor
17+
server app1 app:8000
Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,4 @@
1-
<!doctype html>
2-
<html lang="en">
3-
<head>
4-
<meta charset="utf-8">
5-
<meta name="viewport" content="width=device-width, initial-scale=1">
6-
7-
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
8-
9-
<title>NetOps.io</title>
10-
</head>
11-
<body>
12-
<h1>NetOps.io</h1>
13-
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-U1DAWAznBHeqEIlVSCgzq+c9gqGAJn5c/t99JyeKa9xxaYpSvHU5awsuZVVFIhvj" crossorigin="anonymous"></script>
14-
</body>
15-
</html>
1+
{% extends "base.html" %}
2+
{% block content %}
3+
<div class="container">{{ title }}</div>
4+
{% endblock %}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{% extends "base.html" %}
2+
{% block content %}
3+
<div class="container">
4+
<div class="mb-3">
5+
<label for="statusArea" class="form-label"><h3>Job Status</h3></label>
6+
<input type="input" class="form-control" id="statusArea" placeholder="{{ job.status }}">
7+
</div>
8+
<div class="mb-3">
9+
<label for="resultTextArea" class="form-label"><h3>{{ title }}</h3></label>
10+
<textarea class="form-control" id="resultTextArea" rows="5">{{ job.result }}</textarea>
11+
</div>
12+
</div>
13+
{% endblock %}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{% extends "base.html" %}
2+
{% block content %}
3+
<div class="container">
4+
<table class="table">
5+
<thead>
6+
<th scope="col">ID</th>
7+
<th scope="col">Task Name</th>
8+
<th scope="col">Task Status</th>
9+
<th scope="col">Keyword Arguments</th>
10+
</thead>
11+
<tbody>
12+
{% for task in results %}
13+
<tr>
14+
<th scope="row"><a href="/results/{{ task.task_id }}">{{ task.task_id }}</a></th>
15+
<td>{{ task.task_name }}</td>
16+
<td>{{ task.status }}</td>
17+
<td>{{ task.task_kwargs }}</td>
18+
</tr>
19+
{% endfor %}
20+
</tbody>
21+
</table>
22+
</div>
23+
{% endblock %}

netopsio/home/urls.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,7 @@
44

55
app_name = "" # pylint: disable=invalid-name
66
urlpatterns = [
7-
path("", views.index, name="index"),
7+
path("", views.index, name="home_index"),
8+
path("results/", views.results, name="home_results"),
9+
path("results/<str:task_id>/", views.result_details, name="results_details"),
810
]

netopsio/home/views.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,28 @@
11
"Home app views."
22
from django.http import HttpResponse
33
from django.template import loader
4+
from django.shortcuts import get_object_or_404
5+
from django_celery_results.models import TaskResult
46

57

68
def index(request):
79
"""Render Home Page."""
810
template = loader.get_template("home/base.html")
9-
context = {}
11+
context = {"title": "Home"}
12+
return HttpResponse(template.render(context, request))
13+
14+
15+
def results(request):
16+
"""Render Task Results."""
17+
task_results = TaskResult.objects.all()
18+
template = loader.get_template("home/results.html")
19+
context = {"title": "Task Results", "results": task_results}
20+
return HttpResponse(template.render(context, request))
21+
22+
23+
def result_details(request, task_id):
24+
"""Render Task Detail Results."""
25+
job = get_object_or_404(TaskResult, task_id=task_id)
26+
template = loader.get_template("home/result_details.html")
27+
context = {"title": "Task Result Details", "job": job}
1028
return HttpResponse(template.render(context, request))

netopsio/manage.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#!/usr/bin/env python
2+
# pylint: skip-file
3+
24
"""Django's command-line utility for administrative tasks."""
35
import os
46
import sys

netopsio/netopsio/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
"""Netops.io Project Base."""
2+
from .celery import app as celery_app
3+
4+
__all__ = ("celery_app",)

netopsio/netopsio/celery.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""Celery Jobs Initialization"""
2+
3+
import os
4+
5+
from celery import Celery
6+
7+
8+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "netopsio.settings")
9+
10+
app = Celery(
11+
"netopsio",
12+
broker=f"{os.getenv('NETOPSIO_BROKER_URL')}",
13+
)
14+
app.config_from_object("django.conf:settings", namespace="CELERY")
15+
app.autodiscover_tasks()
16+
17+
18+
@app.task(bind=True)
19+
def debug_task(self):
20+
"""Celery Debug Task"""
21+
print(f"Request: {self.request!r}")

netopsio/netopsio/settings.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"""
1212

1313
from pathlib import Path
14+
import os
1415

1516
# Build paths inside the project like this: BASE_DIR / 'subdir'.
1617
BASE_DIR = Path(__file__).resolve().parent.parent
@@ -37,7 +38,9 @@
3738
"django.contrib.sessions",
3839
"django.contrib.messages",
3940
"django.contrib.staticfiles",
41+
"django_celery_results",
4042
"home",
43+
"ping",
4144
]
4245

4346
MIDDLEWARE = [
@@ -55,7 +58,7 @@
5558
TEMPLATES = [
5659
{
5760
"BACKEND": "django.template.backends.django.DjangoTemplates",
58-
"DIRS": [],
61+
"DIRS": ["./templates"],
5962
"APP_DIRS": True,
6063
"OPTIONS": {
6164
"context_processors": [
@@ -76,12 +79,17 @@
7679

7780
DATABASES = {
7881
"default": {
79-
"ENGINE": "django.db.backends.sqlite3",
80-
"NAME": BASE_DIR / "db.sqlite3",
82+
"ENGINE": "django.db.backends.mysql",
83+
"NAME": os.getenv("NETOPSIO_DB_NAME"),
84+
"USER": os.getenv("NETOPSIO_DB_USER"),
85+
"PASSWORD": os.getenv("NETOPSIO_DB_PASS"),
86+
"HOST": os.getenv("NETOPSIO_DB_HOST"),
87+
"OPTIONS": {
88+
"init_command": "SET default_storage_engine=INNODB",
89+
},
8190
}
8291
}
8392

84-
8593
# Password validation
8694
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
8795

@@ -124,3 +132,12 @@
124132
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
125133

126134
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
135+
136+
# Celery Options
137+
CELERY_TIMEZONE = "US/Central"
138+
139+
CELERY_TASK_TRACK_STARTED = True
140+
141+
CELERY_TASK_TIME_LIMIT = 30 * 60
142+
143+
CELERY_RESULT_BACKEND = "django-db"

netopsio/netopsio/urls.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from django.urls import include, path
1818

1919
urlpatterns = [
20-
path("", include("home.urls")),
20+
path("", include("home.urls"), name="home"),
21+
path("ping/", include("ping.urls"), name="ping"),
2122
path("admin/", admin.site.urls),
2223
]

netopsio/ping/__init__.py

Whitespace-only changes.

netopsio/ping/admin.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""Register Ping Models in Admin Pandel."""
2+
3+
from django.contrib import admin
4+
from ping.models import PingRequest
5+
6+
7+
class PingAdmin(admin.ModelAdmin):
8+
"""Ping Admin Site Fields."""
9+
10+
list_display = ("ip", "date")
11+
12+
13+
admin.site.register(PingRequest, PingAdmin)

netopsio/ping/apps.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# pylint: skip-file
2+
3+
from django.apps import AppConfig
4+
5+
6+
class PingConfig(AppConfig):
7+
default_auto_field = "django.db.models.BigAutoField"
8+
name = "ping"

0 commit comments

Comments
 (0)