@@ -1,45 +0,0 @@ -DICT_CONFIG = { - 'version': 1, - 'disable_existing_loggers': False, - 'formatters': { - 'json': { - '()': 'backend.logging_formatters.JsonFormatter', - 'datefmt': '%Y-%m-%dT%H:%M:%S%z', - }, - }, - 'handlers': { - 'default': { - 'class': 'logging.StreamHandler', - 'formatter': 'json', - 'level': 'INFO', - 'stream': 'ext://sys.stdout', - }, - }, - 'loggers': { - 'django': { - 'handlers': ['default'], - 'level': 'INFO', - 'propagate': False, - }, - # 'uvicorn': { - # 'handlers': ['default'], - # 'level': 'INFO', - # 'propagate': False, - # }, - 'gunicorn': { - 'handlers': ['default'], - 'level': 'INFO', - 'propagate': False, - }, - '': { - 'handlers': ['default'], - 'level': 'INFO', - 'propagate': False, - }, - '__main__': { - 'handlers': ['default'], - 'level': 'INFO', - 'propagate': False, - }, - }, -} @@ -1,21 +0,0 @@ -import json -import logging -from logging import Formatter - - -class JsonFormatter(Formatter): - def format(self, record: logging.LogRecord) -> str: - log_record = { - 'timestamp': self.formatTime(record, self.datefmt), - 'message': record.getMessage(), - 'level': record.levelname, - } - if record.exc_info: - log_record.update( - { - 'exception': self.formatException(record.exc_info), - 'func_name': record.funcName, - 'lineno': record.lineno, - } - ) - return json.dumps(log_record, ensure_ascii=False) @@ -5,18 +5,13 @@ import pyroscope from celery.schedules import crontab from environs import Env -from backend.logging import DICT_CONFIG - -logging.config.dictConfig(DICT_CONFIG) env = Env() env.read_env() - BASE_DIR = Path(__file__).resolve().parent.parent SECRET_KEY = env.str('SECRET_KEY') DEBUG = env.bool('DEBUG', False) - ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', []) CSRF_TRUSTED_ORIGINS = env.list('CSRF_TRUSTED_ORIGINS', []) CORS_ALLOWED_ORIGINS = env.list('CORS_ALLOWED_ORIGINS', []) @@ -28,7 +23,7 @@ MIDDLEWARE = [ 'django.middleware.locale.LocaleMiddleware', 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', - 'backend.middleware.IncomingRequestLoggingMiddleware', + 'lib.logging.middleware.IncomingRequestLoggingMiddleware', 'core.middleware.PyroscopeWrapper', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', @@ -36,7 +31,7 @@ MIDDLEWARE = [ 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'social_django.middleware.SocialAuthExceptionMiddleware', - 'backend.middleware.OutgoingResponseLoggingMiddleware', + 'lib.logging.middleware.OutgoingResponseLoggingMiddleware', ] CORE_APP = 'core.apps.CoreConfig' @@ -515,4 +510,4 @@ if CACHEOPS_REDIS: 'payments.*': {'ops': 'all', 'timeout': 60 * 60}, 'messages.*': {'ops': 'all', 'timeout': 60 * 60}, 'reports.*': {'ops': 'all', 'timeout': 60 * 60}, - } \ No newline at end of file + } @@ -64,8 +64,9 @@ urlpatterns = [ SpectacularAPIView.as_view(urlconf=['backend.public']), name='schema-public', ), + path('api/v1/public/', include('tools.public_api.urls')), path( - 'api/v1/public/', + 'api/v1/public-view/', SpectacularSwaggerView.as_view(url_name='schema-public'), ), path('api/v1/api/', api.urls), @@ -89,7 +89,8 @@ RELEASE=dev ENVIRONMENT=local LOG_LEVEL=debug -DOMAIN= +DOMAIN=localhost +PROVIDER=docker # DJANGO CHANNELS CHANNELS_HOST_MDB=channels-mdb @@ -1,6 +1,5 @@ .DEFAULT_GOAL=init -DEFAULT_VARS=CI_REGISTRY_IMAGE=air/backend/main TAG=latest ENV=.env DEBUG=true CMD=docker compose --project-name air -f docker-compose.yml -f docker-compose.local.yml UP=$(CMD) up @@ -13,7 +12,7 @@ create-default-network: docker network create infrastructure || true start: - $(DEFAULT_VARS) $(UP) --watch + $(UP) --watch init: copy-env create-default-network start @@ -23,12 +22,12 @@ remove-default-network: docker network rm infrastructure || true stop: - $(DEFAULT_VARS) $(DOWN) --remove-orphans + $(DOWN) --remove-orphans cleanup-volumes: remove-default-network - $(DEFAULT_VARS) $(DOWN) --remove-orphans -v + $(DOWN) --remove-orphans -v cleanup-images: remove-default-network - $(DEFAULT_VARS) $(DOWN) --remove-orphans && (docker rmi $(docker images -f "reference=air/backend/main" -q) || true) && yes | docker image prune + $(DOWN) --remove-orphans && (docker rmi $(docker images -f "reference=air/backend/main" -q) || true) && yes | docker image prune full-cleanup: cleanup-volumes cleanup-images @@ -14,7 +14,7 @@ services: volumes: - pgdata:/var/lib/postgresql/data env_file: - - $ENV + - ${ENV:-.env} ports: - "5432:5432" s3: @@ -23,23 +23,52 @@ services: volumes: - s3data:/data env_file: - - $ENV + - ${ENV:-.env} ports: - "9000:9000" - "9001:9001" proxy: - image: nginx:alpine + image: traefik:v3.2 restart: unless-stopped - command: - - /bin/sh - - -c - - echo 'server { listen 8000 default_server; location / { proxy_pass http://air-app-1:8000; proxy_set_header Host $$host; } }' > /etc/nginx/conf.d/default.conf - && nginx -g 'daemon off;' + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - proxy-cfg:/srv/traefik + command: | + --providers.${PROVIDER:-docker}.endpoint=unix:///var/run/docker.sock + --providers.${PROVIDER:-docker}.exposedByDefault=false + --providers.${PROVIDER:-docker}.network=infrastructure + --providers.file.directory=/srv/traefik + --entryPoints.web.address=:80 + --entryPoints.websecure.address=:443 + --entryPoints.web.forwardedHeaders.insecure + --entryPoints.websecure.forwardedHeaders.insecure + --certificatesresolvers.defaultresolver.acme.tlschallenge=false + --certificatesresolvers.defaultresolver.acme.caServer=none + --api=true + --api.dashboard=true + --api.insecure=true + --log.level=${LOG_LEVEL:-debug} env_file: - - $ENV + - ${ENV:-.env} ports: - - "8000:8000" + - "80:80" + - "8080:8080" depends_on: - - app + app: + condition: service_started + proxy-cfg-storage: + condition: service_completed_successfully networks: - - infrastructure \ No newline at end of file + - infrastructure + + proxy-cfg-storage: + image: alpine + command: + - /bin/sh + - -c + - "echo 'http: {\"middlewares\": {\"sts-header\": {\"headers\": {\"forceSTSHeader\": false, \"stspreload\": false, \"stsseconds\": 31536000}}, \"https-redirect\": {\"redirectscheme\": {\"scheme\": \"http\", \"permanent\": \"false\"}}, \"internal-allowlist\": {\"ipallowlist\": {\"sourcerange\": \"0.0.0.0/0\"}}, \"fallback\": {}}}' > /srv/traefik/general.yml" + volumes: + - proxy-cfg:/srv/traefik + +volumes: + proxy-cfg: {} \ No newline at end of file @@ -1,33 +1,33 @@ x-app-build: &app-build - image: $CI_REGISTRY_IMAGE:$TAG + image: ${CI_REGISTRY_IMAGE:-air/backend/main}:${TAG:-latest} build: context: . dockerfile: Dockerfile x-app-labels: &app-labels - traefik.enable=true - - traefik.$PROVIDER.network=infrastructure + - traefik.${PROVIDER:-docker}.network=infrastructure - - traefik.http.routers.backend-http.rule=Host(`$DOMAIN`) + - traefik.http.routers.backend-http.rule=Host(`${DOMAIN:-localhost}`) - traefik.http.routers.backend-http.entrypoints=web - traefik.http.routers.backend-http.tls=false - traefik.http.routers.backend-http.service=backend - traefik.http.routers.backend-http.middlewares=sts-header@file,https-redirect@file,internal-allowlist@file - - traefik.http.routers.backend-https.rule=Host(`$DOMAIN`) + - traefik.http.routers.backend-https.rule=Host(`${DOMAIN:-localhost}`) - traefik.http.routers.backend-https.entrypoints=websecure - traefik.http.routers.backend-https.service=backend - traefik.http.routers.backend-https.tls=true - traefik.http.routers.backend-https.tls.certresolver=defaultresolver - traefik.http.routers.backend-https.middlewares=internal-allowlist@file - - traefik.http.routers.backend-admin-http.rule=Host(`$DOMAIN`) && PathPrefix(`/djangoadmin`) + - traefik.http.routers.backend-admin-http.rule=Host(`${DOMAIN:-localhost}`) && PathPrefix(`/admin`) - traefik.http.routers.backend-admin-http.entrypoints=web - traefik.http.routers.backend-admin-http.tls=false - traefik.http.routers.backend-admin-http.service=backend - traefik.http.routers.backend-admin-http.middlewares=sts-header@file,https-redirect@file,internal-allowlist@file - - traefik.http.routers.backend-admin-https.rule=Host(`$DOMAIN`) && PathPrefix(`/djangoadmin`) + - traefik.http.routers.backend-admin-https.rule=Host(`${DOMAIN:-localhost}`) && PathPrefix(`/admin`) - traefik.http.routers.backend-admin-https.entrypoints=websecure - traefik.http.routers.backend-admin-https.service=backend - traefik.http.routers.backend-admin-https.tls=true @@ -38,9 +38,9 @@ x-app-labels: &app-labels x-static-server-labels: &static-server-labels - traefik.enable=true - - traefik.$PROVIDER.network=infrastructure + - traefik.${PROVIDER:-docker}.network=infrastructure - - traefik.http.routers.backend-static.rule=Host(`$DOMAIN`) && PathPrefix(`/static`) + - traefik.http.routers.backend-static.rule=Host(`${DOMAIN:-localhost}`) && PathPrefix(`/static`) - traefik.http.routers.backend-static.entrypoints=web,websecure - traefik.http.routers.backend-static.tls=true - traefik.http.routers.backend-static.tls.certresolver=defaultresolver @@ -57,7 +57,7 @@ services: - /bin/sh - -c - | - uvicorn backend.asgi:application --host 0.0.0.0 --ws wsproto --http httptools --lifespan off --log-level ${LOG_LEVEL:-info} $(case ${DEBUG} in ('true') echo '--reload' ;; esac) + uvicorn backend.asgi:application --host 0.0.0.0 --ws wsproto --http httptools --lifespan off --log-level ${LOG_LEVEL:-debug} $(case ${DEBUG:-true} in ('true') echo '--reload' ;; esac) deploy: replicas: 1 update_config: @@ -74,7 +74,7 @@ services: - node.role == worker labels: *app-labels env_file: - - $ENV + - ${ENV:-.env} depends_on: housekeeper: condition: service_completed_successfully @@ -100,13 +100,13 @@ services: python manage.py collectstatic --no-input python manage.py migrate python manage.py initialize_buckets - ([ '$DEBUG' = 'true' ] && python manage.py createsuperuser --no-input) || true + ([ '${DEBUG:-true}' = 'true' ] && python manage.py createsuperuser --no-input) || true env_file: - - $ENV + - ${ENV:-.env} celery: <<: *app-build - command: celery -A backend worker -l ${LOG_LEVEL:-info} --concurrency 8 + command: celery -A backend worker -l ${LOG_LEVEL:-debug} --concurrency 8 deploy: replicas: 1 update_config: @@ -122,7 +122,7 @@ services: constraints: - node.role == worker env_file: - - $ENV + - ${ENV:-.env} environment: - C_FORCE_ROOT=true develop: @@ -133,7 +133,7 @@ services: celery_beat: <<: *app-build - command: celery -A backend beat -l ${LOG_LEVEL:-info} + command: celery -A backend beat -l ${LOG_LEVEL:-debug} deploy: replicas: 1 update_config: @@ -149,7 +149,7 @@ services: constraints: - node.role == worker env_file: - - $ENV + - ${ENV:-.env} develop: watch: - path: ./ @@ -176,7 +176,7 @@ services: volumes: - static:/var/www/static env_file: - - $ENV + - ${ENV:-.env} cache-mdb: image: redis:alpine