Skip to content
Open
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
16 changes: 16 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.git
.gitignore
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
.pytest_cache/
.mypy_cache/
htmlcov/
dist/
build/
staticfiles/
ksdb/static/tmp/
test

24 changes: 24 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
FROM python:3.7-slim-bullseye

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Python 3.7 is nearing end-of-life. Any chance this can run on a newer Python?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

no addressed yet

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@yuliujpl let's postpone this for now; in retrospect I'm thinking maybe we should just file this under a separate issue like "Modernize KSDB" and instead narrow the focus on making KSDB work in a Dockerized environment


ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1

WORKDIR /app

COPY requirements-docker.txt /app/requirements-docker.txt
RUN apt-get update \
&& apt-get install -y --no-install-recommends build-essential ca-certificates \
&& pip install --no-cache-dir --upgrade pip setuptools wheel \
&& pip install --no-cache-dir -r /app/requirements-docker.txt \
&& apt-get purge -y --auto-remove build-essential \
&& rm -rf /var/lib/apt/lists/*

COPY . /app
COPY docker/entrypoint.sh /usr/local/bin/ksdb-entrypoint
COPY docker/init.sh /usr/local/bin/ksdb-init
RUN chmod +x /usr/local/bin/ksdb-entrypoint /usr/local/bin/ksdb-init

EXPOSE 8000

ENTRYPOINT ["/usr/local/bin/ksdb-entrypoint"]
CMD ["gunicorn", "sitemain.wsgi_docker:application", "--bind", "0.0.0.0:8000", "--workers", "2"]
Comment thread
nutjob4life marked this conversation as resolved.
58 changes: 31 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ Knowledge System DB: The goal of this system is to maintain generalized project

# DEPENDENCIES

```
sudo yum install postgresql-server postgresql-devel gcc openldap-devel openssl openssl-devel
python3:
curl -O https://www.python.org/ftp/python/3.5.0/Python-3.5.0.tgz
Expand All @@ -16,13 +15,10 @@ python3:
pip3:
curl -O https://bootstrap.pypa.io/get-pip.py
sudo python3 get-pip.py
```

# SETUP POSTGRES

## setup postgres

```
# setup postgres
sudo service postgresql initdb
sudo chkconfig postgresql on
sudo service postgresql start
Expand All @@ -32,53 +28,38 @@ pip3:
create database ksdb;
alter user edrn password 'edrn';
GRANT ALL ON database ksdb TO edrn;
```

## insert tables

```
# insert tables
ctrl^D once to exit out of database
sudo service postgresql restart
export PGPASSWORD=edrn
psql -U edrn -h 127.0.0.1 -d ksdb -a -f conf/createtables.sql
```

# SETUP KSDB

## Make sure to create a virtual environment

```
# Make sure to create a virtual environment
sudo pip install setuptools --upgrade
sudo pip install -r conf/dependencies.cfg
```

## Configure KSDB

```
# Configure KSDB
modify sitemain/settings.py to update DATABASES parameter. Make sure you updated 'name' to ksdb, 'user' to edrn, 'password' to edrn, and host to localhost.
*You can use support/set_settings.py to automatically apply a local settings file to the template settings file. The script will write a settings.py in the same directory as the template settings file:
**Example: python support/set_settings.py ~/KSDB/settings.tumor.py sitemain/settings.py.in
python manage.py migrate auth
python manage.py migrate
python manage.py createsuperuser (create the user you will be using to login)
```

## Running the project

```

# Running the project
To run this project:

#ingest knowledge objects from CancerDataExpo into database
python manage.py ingestorgans
python manage.py ingestpublications
python manage.py ingestpersons
```

## Run the server

```
# Run the server
python manage.py runserver 0.0.0.0:8000
```

You can now visit the following URLS:

Expand All @@ -89,6 +70,29 @@ You can now visit the following URLS:

Run the test suite:

```
python manage.py test ksdb


# Docker deployment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is fabulous. I tested it out and it works like a charm!


For the containerized setup, use the single wrapper script from the project root:

```bash
./deploy.sh
```

Useful variants:

```bash
./deploy.sh fresh
./deploy.sh status
./deploy.sh logs
./deploy.sh down
```

Notes:

- `./deploy.sh` builds the image, starts Postgres and Django, loads the schema, preloads supported KSDB data, and exposes the app on `http://localhost:8000/`
- `./deploy.sh fresh` also deletes the Docker volume and rebuilds the database from scratch
- One-time database initialization runs in a separate Compose `init` service before the web service starts
- The default login is `admin` / `admin` unless you override the compose environment variables
60 changes: 60 additions & 0 deletions deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/bin/sh
set -eu

SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
cd "${SCRIPT_DIR}"

ACTION="${1:-up}"

print_summary() {
port="${KSDB_PORT:-8000}"
user="${DJANGO_SUPERUSER_USERNAME:-admin}"
password="${DJANGO_SUPERUSER_PASSWORD:-admin}"

cat <<EOF
KSDB is available at: http://localhost:${port}/
Default login: ${user} / ${password}
EOF
}

case "${ACTION}" in
up)
docker compose up --build -d
print_summary
;;
fresh)
docker compose down -v --remove-orphans
docker compose up --build -d
print_summary
;;
down)
docker compose down --remove-orphans
;;
restart)
docker compose up --build -d
;;
logs)
docker compose logs -f web
;;
ps|status)
docker compose ps
;;
help|-h|--help)
cat <<'EOF'
Usage: ./deploy.sh [up|fresh|down|restart|logs|status]

Commands:
up Build and start KSDB in the background.
fresh Recreate KSDB from scratch, including a fresh database volume.
down Stop the stack.
restart Rebuild and restart the stack without deleting data.
logs Follow the web container logs.
status Show container status.
EOF
;;
*)
echo "Unknown action: ${ACTION}" >&2
echo "Run ./deploy.sh --help for usage." >&2
exit 1
;;
esac
1 change: 1 addition & 0 deletions django_datatables_view/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

81 changes: 81 additions & 0 deletions django_datatables_view/base_datatable_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from django.core.exceptions import FieldError
from django.http import JsonResponse
from django.views.generic.base import View


class BaseDatatableView(View):
model = None
columns = []
order_columns = []
max_display_length = 100

def get_initial_queryset(self):
return self.model.objects.all()

def filter_queryset(self, queryset):
return queryset

def render_column(self, row, column):
return getattr(row, column)

def ordering(self, queryset):
column_index = self.request.GET.get("order[0][column]")
direction = self.request.GET.get("order[0][dir]", "asc")

if column_index is None:
return queryset

try:
order_column = self.order_columns[int(column_index)]
except (IndexError, TypeError, ValueError):
return queryset

if not order_column or order_column == "Select":
return queryset

prefix = "-" if direction == "desc" else ""
try:
return queryset.order_by(prefix + order_column)
except FieldError:
return queryset

def paging(self, queryset):
try:
start = int(self.request.GET.get("start", 0))
except (TypeError, ValueError):
start = 0

try:
length = int(self.request.GET.get("length", 10))
except (TypeError, ValueError):
length = 10

if length < 0:
length = self.max_display_length
length = min(length, self.max_display_length)

return queryset[start:start + length]

def prepare_results(self, queryset):
data = []
for row in queryset:
data.append([self.render_column(row, column) for column in self.columns])
return data

def get(self, request, *args, **kwargs):
queryset = self.get_initial_queryset()
records_total = queryset.count()

filtered_queryset = self.filter_queryset(queryset)
records_filtered = filtered_queryset.count()
ordered_queryset = self.ordering(filtered_queryset)
page_queryset = self.paging(ordered_queryset)

return JsonResponse(
{
"draw": int(request.GET.get("draw", 1)),
"recordsTotal": records_total,
"recordsFiltered": records_filtered,
"data": self.prepare_results(page_queryset),
}
)
80 changes: 80 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
services:
db:
image: postgres:14
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB:-ksdb}
POSTGRES_USER: ${POSTGRES_USER:-ksdb}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-ksdb}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./conf/createtables.sql:/schema/createtables.sql:ro
- ./docker/postgres-init/10-load-schema.sh:/docker-entrypoint-initdb.d/10-load-schema.sh:ro
- ./docker/postgres-init/20-schema-fixes.sql:/docker-entrypoint-initdb.d/20-schema-fixes.sql:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 5s
timeout: 5s
retries: 20
start_period: 5s

init:
build:
context: .
dockerfile: Dockerfile
restart: "no"
depends_on:
db:
condition: service_healthy
environment:
DJANGO_SETTINGS_MODULE: sitemain.settings_docker
DATABASE_NAME: ${POSTGRES_DB:-ksdb}
DATABASE_USER: ${POSTGRES_USER:-ksdb}
DATABASE_PASSWORD: ${POSTGRES_PASSWORD:-ksdb}
DATABASE_HOST: db
DATABASE_PORT: 5432
DJANGO_DEBUG: ${DJANGO_DEBUG:-1}
DJANGO_SECRET_KEY: ${DJANGO_SECRET_KEY:-ksdb-local-dev-secret-key}
DJANGO_ALLOWED_HOSTS: ${DJANGO_ALLOWED_HOSTS:-*}
RDF_URL: ${RDF_URL:-http://localhost:8000/}
MCL_URL: ${MCL_URL:-http://localhost:8000/}
DJANGO_SUPERUSER_USERNAME: ${DJANGO_SUPERUSER_USERNAME:-admin}
DJANGO_SUPERUSER_EMAIL: ${DJANGO_SUPERUSER_EMAIL:-admin@example.com}
DJANGO_SUPERUSER_PASSWORD: ${DJANGO_SUPERUSER_PASSWORD:-admin}
KSDB_PRELOAD_DATA: ${KSDB_PRELOAD_DATA:-1}
volumes:
- staticfiles:/app/staticfiles
command: ["/usr/local/bin/ksdb-init"]

web:
build:
context: .
dockerfile: Dockerfile
restart: unless-stopped
depends_on:
init:
condition: service_completed_successfully
environment:
DJANGO_SETTINGS_MODULE: sitemain.settings_docker
DATABASE_NAME: ${POSTGRES_DB:-ksdb}
DATABASE_USER: ${POSTGRES_USER:-ksdb}
DATABASE_PASSWORD: ${POSTGRES_PASSWORD:-ksdb}
DATABASE_HOST: db
DATABASE_PORT: 5432
DJANGO_DEBUG: ${DJANGO_DEBUG:-1}
DJANGO_SECRET_KEY: ${DJANGO_SECRET_KEY:-ksdb-local-dev-secret-key}
DJANGO_ALLOWED_HOSTS: ${DJANGO_ALLOWED_HOSTS:-*}
RDF_URL: ${RDF_URL:-http://localhost:8000/}
MCL_URL: ${MCL_URL:-http://localhost:8000/}
DJANGO_SUPERUSER_USERNAME: ${DJANGO_SUPERUSER_USERNAME:-admin}
DJANGO_SUPERUSER_EMAIL: ${DJANGO_SUPERUSER_EMAIL:-admin@example.com}
DJANGO_SUPERUSER_PASSWORD: ${DJANGO_SUPERUSER_PASSWORD:-admin}
KSDB_PRELOAD_DATA: ${KSDB_PRELOAD_DATA:-1}
volumes:
- staticfiles:/app/staticfiles
ports:
- "${KSDB_PORT:-8000}:8000"

volumes:
postgres_data:
staticfiles:
7 changes: 7 additions & 0 deletions docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh
set -eu

cp /app/sitemain/settings_docker.py /app/sitemain/settings.py
cp /app/sitemain/wsgi_docker.py /app/sitemain/wsgi.py

exec "$@"
Loading