Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,13 @@ Users from the populate script all have password `pennlabs`.
- a. Navigate to `/frontend`
- b. `yarn cypress open`
- c. Click on `question.spec.ts`

### Emulating the production server
This will, as best as possible, emulate the production configuration described in `/k8s/main.ts`.

1. Open a command prompt to `/backend`
2. Run `docker compose --profile proddev up`
3. Connect via `http://127.0.0.1:8000`
4. To turn it off, use `CTRL+C` and then `docker compose --profile proddev down`

Note this will reuse the postgres database stored in `/backend/postgres`. You may reset this database by turinging off the docker containers and deleting `/backend/postgres`
1 change: 1 addition & 0 deletions backend/.dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ LICENSE
**/__pycache__/
tests/
postgres/
.venv
22 changes: 19 additions & 3 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
FROM pennlabs/django-base:b269ea1613686b1ac6370154debbb741b012de1a-3.11
ARG DEPENDENCY_MANAGER="uv"

LABEL maintainer="Penn Labs"

# Install uv
COPY --from=ghcr.io/astral-sh/uv@sha256:2381d6aa60c326b71fd40023f921a0a3b8f91b14d5db6b90402e65a635053709 /uv /uvx /bin/

# Copy project dependencies
COPY Pipfile* /app/
COPY Pipfile* pyproject.toml uv.lock /app/

# Install dependencies using uv or pipenv depending on DEPENDENCY_MANAGER arg
RUN if [ "$DEPENDENCY_MANAGER" = "uv" ]; then \
uv sync --frozen --no-dev --no-install-project --python $(which python); \
mv /app/.venv/bin/uwsgi /usr/local/bin/uwsgi; \
mv /app/.venv/bin/gunicorn /usr/local/bin/gunicorn; \
else \
pipenv install --system; \
fi

# Make installed binaries available for POSIX compliant scripts
ENV PATH="/app/.venv/bin:$PATH"

# Install project dependencies
RUN pipenv install --system
# Patch for scripts that use a hard-coded path to python (django-run, asgi-run)
ENV PYTHONPATH="/app/.venv/lib/python3.11/site-packages/:$PYTHONPATH"

# Copy project files
COPY . /app/
Expand Down
54 changes: 54 additions & 0 deletions backend/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,57 @@ services:
image: redis:4.0
ports:
- "6379:6379"
# api, dashboard, and admin requests for proddev
proddev-backend-wsgi:
depends_on:
- db
- redis
profiles:
- proddev
build:
context: .
dockerfile: Dockerfile
ports:
- "8001:80"
environment:
- DATABASE_URL=postgres://postgres:postgres@db:5432/postgres
- DJANGO_SETTINGS_MODULE=officehoursqueue.settings.proddev
command: sh -c "python manage.py migrate && { DJANGO_SUPERUSER_PASSWORD=root python manage.py createsuperuser --no-input --username root --email root@pennlabs.org; /usr/local/bin/django-run; }"
# Web socket requests for proddev
proddev-backend-asgi:
depends_on:
- db
- redis
profiles:
- proddev
build:
context: .
dockerfile: Dockerfile
ports:
- "8002:80"
environment:
- DATABASE_URL=postgres://postgres:postgres@db:5432/postgres
- DJANGO_SETTINGS_MODULE=officehoursqueue.settings.proddev
command: sh -c "python manage.py migrate && { DJANGO_SUPERUSER_PASSWORD=root python manage.py createsuperuser --no-input --username root --email root@pennlabs.org; /usr/local/bin/asgi-run; }"
# frontend for proddev
proddev-frontend:
profiles:
- proddev
build:
context: ../frontend
dockerfile: ../frontend/Dockerfile
ports:
- "8003:80"
# Reverse proxy for routing requests to the various proddev servers based on the path
nginx:
image: nginx:latest
depends_on:
- proddev-backend-wsgi
- proddev-backend-asgi
- proddev-frontend
profiles:
- proddev
ports:
- "8000:80"
volumes:
- ./nginx-proddev.conf:/etc/nginx/nginx.conf:ro
38 changes: 38 additions & 0 deletions backend/nginx-proddev.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Reverse proxy configuration for emulating what will actually be run in production as described in /k8s/main.ts

events { }

http {
server {
listen 80;

# Frontend is served unless overridden by other locations
location / {
proxy_pass http://proddev-frontend:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

# The wsgi backend is used on routes starting with '/api', '/admin', or '/assets'
location ~ ^/(api|admin|assets) {
proxy_pass http://proddev-backend-wsgi:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

# The asgi backend is used for websocket requests on routes starting with '/api/ws'
location /api/ws {
proxy_pass http://proddev-backend-asgi:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

# For web sockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
}
20 changes: 20 additions & 0 deletions backend/officehoursqueue/settings/proddev.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Django config based off of production config, but with minor changes to ensure it works on dev machines

from officehoursqueue.settings.production import *
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats the reason for adding this new proddev.py

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a basis for the django settings for proddev. It is based off of the production settings, but with some changes so it still actually works in the development environment. For example, unless ALLOWED_HOSTS is changed, it will return a 400 error on every request.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe it's possible to override Django settings with just environment variables without changing settings files.


import officehoursqueue.settings.base as base

# No https on dev machines
SECURE_PROXY_SSL_HEADER = ()

# Prevents request rejection on dev machines
ALLOWED_HOSTS = ["*"]

# Use local login instead of UPenn's
PLATFORM_ACCOUNTS = base.PLATFORM_ACCOUNTS

# Allow http callback for DLA
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"

# Use the console for email in development
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
58 changes: 58 additions & 0 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,60 @@
[project]
name = ""
version = "0.0.1"
requires-python = "==3.11.4"
dependencies = [
"dj-database-url==2.2.0",
"djangorestframework==3.15.2",
"psycopg2-binary==2.9.6",
"uvloop==0.17.0",
"sentry-sdk",
"django==5.0.3",
"django-cors-headers==4.4.0",
"pyyaml==6.0.2",
"uritemplate==4.1.1",
"uwsgi==2.0.27",
"django-labs-accounts==0.7.1",
"django-phonenumber-field[phonenumbers]==8.0.0",
"drf-nested-routers==0.94.1",
"django-email-tools==0.1.1",
"twilio==9.3.3",
"djangorestframework-camel-case==1.4.2",
"django-filter==24.3",
"celery==5.4.0",
"redis==5.1.1",
"django-auto-prefetching==0.2.12",
"django-rest-live==0.7.0",
"channels==3.0.5",
"channels-redis==4.2.0",
"uvicorn[standard]==0.31.0",
"gunicorn==23.0.0",
"django-schedules-ohq==0.10.1.4",
"typing-extensions==4.12.2",
"drf-excel==2.4.1",
"pytz==2024.2",
"inflection==0.5.1",
]

[tool.black]
line-length = 100

[dependency-groups]
dev = [
"black==22.3.0",
"unittest-xml-reporting==3.2.0",
"flake8==7.1.1",
"flake8-absolute-import==1.0.0.2",
"flake8-isort==6.1.1",
"flake8-quotes==3.4.0",
"django-debug-toolbar==4.4.6",
"django-extensions==3.2.3",
"parameterized==0.9.0",
"tblib==3.0.0",
]

[tool.uv]
package = false

[[tool.uv.index]]
name = "pypi"
url = "https://pypi.org/simple"
Loading
Loading