From 78ab2ca3cf7079285648a3b9bf15948cc0aee2fe Mon Sep 17 00:00:00 2001 From: Berry den Hartog <38954346+berrydenhartog@users.noreply.github.com> Date: Mon, 6 May 2024 13:55:45 +0000 Subject: [PATCH] Add database --- .devcontainer/devcontainer.json | 3 ++- .env | 19 +++++++++++++------ .gitattributes | 2 ++ .vscode/tasks.json | 8 ++++---- compose.yml | 28 +++++++++++++++++++++++----- database/init-user-db.sh | 9 +++++++++ pyproject.toml | 4 ++-- tad/alembic/env.py | 10 +++++----- tad/core/config.py | 27 ++++++++++++--------------- 9 files changed, 72 insertions(+), 38 deletions(-) create mode 100644 .gitattributes create mode 100755 database/init-user-db.sh diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index b610aff08..57ea9c788 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -8,8 +8,9 @@ }, "remoteUser": "root", "features": { - "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {} + "ghcr.io/devcontainers/features/docker-in-docker:2": {} }, + "forwardPorts": [8000,8080], "postCreateCommand": ".devcontainer/postCreateCommand.sh", "customizations": { "vscode": { diff --git a/.env b/.env index eaead6b70..8d2b9d10a 100644 --- a/.env +++ b/.env @@ -3,15 +3,22 @@ DOMAIN=localhost # Environment: local, staging, production ENVIRONMENT=local - PROJECT_NAME="TAD" -# Backend +# TAD backend BACKEND_CORS_ORIGINS="http://localhost,https://localhost,http://127.0.0.1,https://127.0.0.1" -SECRET_KEY=changethisa - +SECRET_KEY=changethis SQLALCHEMY_SCHEME="postgresql+psycopg" +APP_DATABASE_USER=tad +APP_DATABASE_DB=tad +APP_DATABASE_PASSWORD=changethis + +# Postgres database +POSTGRES_SERVER=db POSTGRES_PORT=5432 -POSTGRES_DB=app +POSTGRES_DB=postgres POSTGRES_USER=postgres -POSTGRES_PASSWORD=changethisa +POSTGRES_PASSWORD=changethis + +# Database viewer +PGADMIN_DEFAULT_PASSWORD=changethis diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..efdba8764 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +* text=auto +*.sh text eol=lf diff --git a/.vscode/tasks.json b/.vscode/tasks.json index aaf2eb83b..087db6b76 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -5,7 +5,7 @@ "label": "PyRight", "detail": "typecheck code.", "type": "shell", - "command": "pyright", + "command": "poetry run pyright", "group": "test", "presentation": { "reveal": "always", @@ -17,7 +17,7 @@ "label": "Ruff", "detail": "format and lint code.", "type": "shell", - "command": "ruff format && ruff check", + "command": "poetry run ruff format && poetry run ruff check", "group": "test", "presentation": { "reveal": "always", @@ -29,7 +29,7 @@ "label": "Code Coverage", "detail": "Generate code coverage report.", "type": "shell", - "command": "coverage report --fail-under 95", + "command": "poetry run coverage report", "group": "test", "presentation": { "reveal": "always", @@ -41,7 +41,7 @@ "label": "PyTest", "detail": "test all code", "type": "shell", - "command": "coverage run -m pytest ./tad/tests", + "command": "poetry run coverage run -m pytest", "group": { "kind": "test", "isDefault": true diff --git a/compose.yml b/compose.yml index d17e16ae5..5b49484df 100644 --- a/compose.yml +++ b/compose.yml @@ -10,23 +10,41 @@ services: condition: service_healthy env_file: - .env + environment: + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?Variable not set} ports: - 8000:8000 db: - image: postgres:12 + image: postgres:16 restart: unless-stopped volumes: - app-db-data:/var/lib/postgresql/data/pgdata + - ./database/:/docker-entrypoint-initdb.d/:cached env_file: - .env environment: - PGDATA=/var/lib/postgresql/data/pgdata - - POSTGRES_PASSWORD=${POSTGRES_PASSWORD?Variable not set} - - POSTGRES_USER=${POSTGRES_USER?Variable not set} - - POSTGRES_DB=${POSTGRES_DB?Variable not set} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?Variable not set} + - SECRET_KEY=${SECRET_KEY:?Variable not set} healthcheck: - test: ["CMD-SHELL", "pg_isready", "-d", "tad"] + test: ["CMD-SHELL", "pg_isready", "-d", "tad", "-U", "postgres"] + start_period: 10s + + + db-admin: + image: dpage/pgadmin4:8.6 + restart: unless-stopped + ports: + - 8080:8080 + environment: + - PGADMIN_DEFAULT_EMAIL=${PGADMIN_DEFAULT_EMAIL:-berry.hartog@minbzk.nl} + - PGADMIN_DEFAULT_PASSWORD=${PGADMIN_DEFAULT_PASSWORD:?Variable not set} + - PGADMIN_LISTEN_PORT=${PGADMIN_LISTEN_PORT:-8080} + depends_on: + db: + condition: service_healthy + #TODO(berry): Traefik diff --git a/database/init-user-db.sh b/database/init-user-db.sh new file mode 100755 index 000000000..b13ccff2f --- /dev/null +++ b/database/init-user-db.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e + +# todo(berry): make user and database variables +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE USER tad WITH PASSWORD 'changethis'; + CREATE DATABASE tad; + GRANT ALL PRIVILEGES ON DATABASE tad TO tad; +EOSQL diff --git a/pyproject.toml b/pyproject.toml index f6d91ad9e..9ee2e753e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,7 +73,7 @@ reportMissingTypeStubs = true [tool.coverage.run] branch = true -command_line = "-m pytest ./tad/tests" +command_line = "-m pytest" [tool.coverage.report] fail_under = 95 @@ -85,5 +85,5 @@ title = "tad" [tool.pytest.ini_options] testpaths = [ - "tests" + "tad/tests" ] diff --git a/tad/alembic/env.py b/tad/alembic/env.py index cb802bc9d..29f967bbe 100644 --- a/tad/alembic/env.py +++ b/tad/alembic/env.py @@ -22,11 +22,11 @@ def get_url(): file = os.getenv("SQLITE_FILE", "./database") return f"{scheme}://{file}" - user = os.getenv("POSTGRES_USER", "postgres") - password = os.getenv("POSTGRES_PASSWORD", "") - server = os.getenv("POSTGRES_SERVER", "db") - port = os.getenv("POSTGRES_PORT", "5432") - db = os.getenv("POSTGRES_DB", "tad") + user = os.getenv("APP_DATABASE_USER", "postgres") + password = os.getenv("APP_DATABASE_PASSWORD", "") + server = os.getenv("APP_DATABASE_SERVER", "db") + port = os.getenv("APP_DATABASE_PORT", "5432") + db = os.getenv("APP_DATABASE_DB", "tad") return f"{scheme}://{user}:{password}@{server}:{port}/{db}" diff --git a/tad/core/config.py b/tad/core/config.py index f5c0f608b..dc562c7d7 100644 --- a/tad/core/config.py +++ b/tad/core/config.py @@ -40,16 +40,13 @@ def server_host(self) -> str: PROJECT_NAME: str = "TAD" - if ENVIRONMENT == "local": - SQLALCHEMY_SCHEME: str = "sqlite" - else: - SQLALCHEMY_SCHEME: str = "postgresql+psycopg" + SQLALCHEMY_SCHEME: str = "sqlite" - POSTGRES_SERVER: str = "db" - POSTGRES_PORT: int = 5432 - POSTGRES_USER: str = "postgres" - POSTGRES_PASSWORD: str - POSTGRES_DB: str = "tad" + APP_DATABASE_SERVER: str = "db" + APP_DATABASE_PORT: int = 5432 + APP_DATABASE_USER: str = "tad" + APP_DATABASE_PASSWORD: str + APP_DATABASE_DB: str = "tad" SQLITE_FILE: str = "./database" @@ -62,11 +59,11 @@ def SQLALCHEMY_DATABASE_URI(self) -> str: return str( MultiHostUrl.build( scheme=self.SQLALCHEMY_SCHEME, - username=self.POSTGRES_USER, - password=self.POSTGRES_PASSWORD, - host=self.POSTGRES_SERVER, - port=self.POSTGRES_PORT, - path=self.POSTGRES_DB, + username=self.APP_DATABASE_USER, + password=self.APP_DATABASE_PASSWORD, + host=self.APP_DATABASE_SERVER, + port=self.APP_DATABASE_PORT, + path=self.APP_DATABASE_DB, ) ) @@ -83,7 +80,7 @@ def _check_default_secret(self, var_name: str, value: str | None) -> None: @model_validator(mode="after") def _enforce_non_default_secrets(self) -> Self: self._check_default_secret("SECRET_KEY", self.SECRET_KEY) - self._check_default_secret("POSTGRES_PASSWORD", self.POSTGRES_PASSWORD) + self._check_default_secret("APP_DATABASE_PASSWORD", self.APP_DATABASE_PASSWORD) return self